| // ***************************************************************************** |
| // ***************************************************************************** |
| // Copyright 2013 - 2016, Cadence Design Systems |
| // |
| // This file is part of the Cadence LEF/DEF Open Source |
| // Distribution, Product Version 5.8. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or |
| // implied. See the License for the specific language governing |
| // permissions and limitations under the License. |
| // |
| // For updates, support, or to become part of the LEF/DEF Community, |
| // check www.openeda.org for details. |
| // |
| // $Author: dell $ |
| // $Revision: #1 $ |
| // $Date: 2017/06/06 $ |
| // $State: $ |
| // ***************************************************************************** |
| // ***************************************************************************** |
| |
| #include <stdlib.h> |
| #include <string.h> |
| #include "defiPath.hpp" |
| #include "defiDebug.hpp" |
| #include "lex.h" |
| #include "defiUtil.hpp" |
| |
| BEGIN_LEFDEF_PARSER_NAMESPACE |
| |
| defiPath::defiPath(defrData *data) |
| : defData(data), |
| keys_(NULL), |
| data_(NULL), |
| pointer_(NULL), |
| numUsed_(0), |
| numAllocated_(0), |
| numX_(0), |
| numY_(0), |
| stepX_(0), |
| stepY_(0), |
| deltaX_(0), |
| deltaY_(0), |
| mask_(0) |
| {} |
| |
| |
| defiPath::defiPath(defiPath *defiPathRef) |
| { |
| *this = *defiPathRef; |
| |
| defiPathRef->pointer_ = NULL; |
| defiPathRef->keys_ = NULL; |
| defiPathRef->data_ = NULL; |
| } |
| |
| |
| defiPath::~defiPath() { |
| Destroy(); |
| } |
| |
| |
| void defiPath::Init() { |
| // Should do nothing in constructor case. |
| Destroy(); |
| |
| numUsed_ = 0; |
| numAllocated_ = 0; |
| pointer_ = new int; |
| *pointer_ = -1; |
| |
| numX_ = 0; |
| numY_ = 0; |
| stepX_ = 0; |
| stepY_ = 0; |
| deltaX_ = 0; |
| deltaY_ = 0; |
| mask_ = 0; |
| |
| bumpSize(16); |
| } |
| |
| |
| void defiPath::clear() { |
| int i; |
| |
| for (i = 0; i < numUsed_; i++) { |
| free(data_[i]); |
| data_[i] = NULL; |
| } |
| |
| numUsed_ = 0; |
| |
| delete pointer_; |
| pointer_ = NULL; |
| } |
| |
| |
| void defiPath::Destroy() { |
| |
| if (keys_) |
| free((char*)(keys_)); |
| keys_ = NULL; |
| if (data_) { |
| clear(); |
| free((char*)(data_)); |
| data_ = NULL; |
| } |
| } |
| |
| |
| void defiPath::reverseOrder() { |
| int one = 0; |
| int two = numUsed_ - 1; |
| int t; |
| void *tptr; |
| while (one < two) { |
| t = keys_[one]; |
| keys_[one] = keys_[two]; |
| keys_[two] = t; |
| tptr = data_[one]; |
| data_[one] = data_[two]; |
| data_[two] = tptr; |
| one++; |
| two--; |
| } |
| } |
| |
| |
| void defiPath::initTraverse() const { |
| *(pointer_) = -1; |
| } |
| |
| |
| void defiPath::initTraverseBackwards() const { |
| *(pointer_) = numUsed_; |
| } |
| |
| |
| int |
| defiPath::currentType() const |
| { |
| if (*(pointer_) >= 0 && *(pointer_) < numUsed_) { |
| switch (keys_[*(pointer_)]) { |
| case 'L': return DEFIPATH_LAYER; |
| case 'V': return DEFIPATH_VIA; |
| case 'W': return DEFIPATH_WIDTH; |
| case 'P': return DEFIPATH_POINT; |
| case 'F': return DEFIPATH_FLUSHPOINT; |
| case 'T': return DEFIPATH_TAPER; |
| case 'R': return DEFIPATH_TAPERRULE; |
| case 'S': return DEFIPATH_SHAPE; |
| case 'Y': return DEFIPATH_STYLE; |
| case 'O': return DEFIPATH_VIAROTATION; |
| case 'E': return DEFIPATH_RECT; |
| case 'D': return DEFIPATH_VIADATA; |
| case 'U': return DEFIPATH_VIRTUALPOINT; |
| case 'M': return DEFIPATH_MASK; |
| case 'C': return DEFIPATH_VIAMASK; |
| default : return DEFIPATH_DONE; |
| } |
| } |
| |
| return DEFIPATH_DONE; |
| } |
| |
| int defiPath::next() const |
| { |
| (*(pointer_))++; |
| |
| return currentType(); |
| } |
| |
| |
| int defiPath::prev() const{ |
| (*(pointer_))--; |
| |
| return currentType(); |
| } |
| |
| int defiPath::getTaper() const { |
| if (keys_[*(pointer_)] != 'T') return 0; |
| return 1; |
| } |
| |
| const char* defiPath::getTaperRule() const { |
| if (keys_[*(pointer_)] != 'R') return 0; |
| return (char*)(data_[*(pointer_)]); |
| } |
| |
| const char* defiPath::getLayer() const { |
| if (keys_[*(pointer_)] != 'L') return 0; |
| return (char*)(data_[*(pointer_)]); |
| } |
| |
| |
| const char* defiPath::getVia() const { |
| if (keys_[*(pointer_)] != 'V') return 0; |
| return (char*)(data_[*(pointer_)]); |
| } |
| |
| |
| const char* defiPath::getShape() const { |
| if (keys_[*(pointer_)] != 'S') return 0; |
| return (char*)(data_[*(pointer_)]); |
| } |
| |
| |
| int defiPath::getStyle() const { |
| int *style; |
| if (keys_[*(pointer_)] != 'Y') return 0; |
| style = (int*)(data_[*(pointer_)]); |
| return *style; |
| } |
| |
| |
| int defiPath::getWidth() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'W') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| return *wptr; |
| } |
| |
| int defiPath::getViaRotation() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'O') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| return *wptr; |
| } |
| |
| int defiPath::getMask() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'M') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| return *wptr; |
| } |
| |
| int defiPath::getViaBottomMask() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'C') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| |
| int viaMask = *wptr; |
| |
| return viaMask % 10; |
| } |
| |
| int defiPath::getViaCutMask() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'C') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| |
| int viaMask = *wptr; |
| |
| return viaMask / 10 % 10; |
| } |
| |
| int defiPath::getViaTopMask() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'C') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| |
| int viaMask = *wptr; |
| |
| return viaMask / 100; |
| } |
| |
| const char* defiPath::getViaRotationStr() const { |
| int *wptr; |
| if (keys_[*(pointer_)] != 'O') return 0; |
| wptr = (int*)(data_[*(pointer_)]); |
| return defiOrientStr(*wptr); |
| } |
| |
| void defiPath::getViaRect(int* deltaX1, int* deltaY1, int* deltaX2, int* deltaY2) const { |
| if (keys_[*(pointer_)] != 'E') return ; |
| *deltaX1 = ((struct defiViaRect*)(data_[*(pointer_)]))->deltaX1; |
| *deltaY1 = ((struct defiViaRect*)(data_[*(pointer_)]))->deltaY1; |
| *deltaX2 = ((struct defiViaRect*)(data_[*(pointer_)]))->deltaX2; |
| *deltaY2 = ((struct defiViaRect*)(data_[*(pointer_)]))->deltaY2; |
| } |
| |
| void defiPath::getViaData(int* numX, int* numY, int* stepX, int* stepY) const { |
| if (keys_[*(pointer_)] != 'D') return ; |
| *numX = ((struct defiViaData*)(data_[*(pointer_)]))->numX; |
| *numY = ((struct defiViaData*)(data_[*(pointer_)]))->numY; |
| *stepX = ((struct defiViaData*)(data_[*(pointer_)]))->stepX; |
| *stepY = ((struct defiViaData*)(data_[*(pointer_)]))->stepY; |
| } |
| |
| |
| void defiPath::getFlushPoint(int* x, int* y, int* ext) const { |
| if (keys_[*(pointer_)] != 'F') return ; |
| *x = ((struct defiPnt*)(data_[*(pointer_)]))->x; |
| *y = ((struct defiPnt*)(data_[*(pointer_)]))->y; |
| *ext = ((struct defiPnt*)(data_[*(pointer_)]))->ext; |
| } |
| |
| void defiPath::getVirtualPoint(int* x, int* y) const { |
| if (keys_[*(pointer_)] != 'U') return ; |
| *x = ((struct defiPnt*)(data_[*(pointer_)]))->x; |
| *y = ((struct defiPnt*)(data_[*(pointer_)]))->y; |
| } |
| |
| void defiPath::getPoint(int* x, int* y) const { |
| if (keys_[*(pointer_)] != 'P') return ; |
| *x = ((struct defiPnt*)(data_[*(pointer_)]))->x; |
| *y = ((struct defiPnt*)(data_[*(pointer_)]))->y; |
| } |
| |
| |
| void defiPath::addWidth(int w) { |
| int * wValue; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| wValue = (int*)malloc(sizeof(int)); |
| *wValue = w; |
| keys_[numUsed_] = 'W'; |
| data_[numUsed_] = wValue; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addVia(const char* l) { |
| int len = strlen(l)+1; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'V'; |
| data_[numUsed_] = malloc(len); |
| strcpy((char*)(data_[numUsed_]), defData->DEFCASE(l)); |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addViaRotation(int o) { |
| int * orient; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| orient = (int*)malloc(sizeof(int)); |
| *orient = o; |
| keys_[numUsed_] = 'O'; |
| data_[numUsed_] = orient; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addViaRect(int deltaX1, int deltaY1, int deltaX2, int deltaY2) { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'E'; // RECT |
| data_[numUsed_] = malloc(sizeof(struct defiViaRect)); |
| ((struct defiViaRect*)(data_[numUsed_]))->deltaX1 = deltaX1; |
| ((struct defiViaRect*)(data_[numUsed_]))->deltaY1 = deltaY1; |
| ((struct defiViaRect*)(data_[numUsed_]))->deltaX2 = deltaX2; |
| ((struct defiViaRect*)(data_[numUsed_]))->deltaY2 = deltaY2; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addViaData(int numX, int numY, int stepX, int stepY) { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'D'; |
| data_[numUsed_] = malloc(sizeof(struct defiViaData)); |
| ((struct defiViaData*)(data_[numUsed_]))->numX = numX; |
| ((struct defiViaData*)(data_[numUsed_]))->numY = numY; |
| ((struct defiViaData*)(data_[numUsed_]))->stepX = stepX; |
| ((struct defiViaData*)(data_[numUsed_]))->stepY = stepY; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addLayer(const char* l) { |
| int len = strlen(l)+1; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'L' ; |
| data_[numUsed_] = malloc(len); |
| strcpy((char*)(data_[numUsed_]), defData->DEFCASE(l)); |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addTaperRule(const char* l) { |
| int len = strlen(l)+1; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'R' ; |
| data_[numUsed_] = malloc(len); |
| strcpy((char*)(data_[numUsed_]), defData->DEFCASE(l)); |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addPoint(int x, int y) { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'P'; |
| data_[numUsed_] = malloc(sizeof(struct defiPnt)); |
| ((struct defiPnt*)(data_[numUsed_])) -> x = x; |
| ((struct defiPnt*)(data_[numUsed_])) -> y = y; |
| (numUsed_)++; |
| } |
| |
| void defiPath::addMask(int colorMask) { |
| int* mask; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| mask = (int*)malloc(sizeof(int)); |
| *mask = colorMask; |
| keys_[numUsed_] = 'M'; //Mask for points |
| data_[numUsed_] = mask; |
| (numUsed_)++; |
| } |
| |
| void defiPath::addViaMask(int colorMask) { |
| int* mask; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| mask = (int*)malloc(sizeof(int)); |
| *mask = colorMask; |
| keys_[numUsed_] = 'C'; //viaMask |
| data_[numUsed_] = mask; |
| (numUsed_)++; |
| } |
| |
| void defiPath::addFlushPoint(int x, int y, int ext) { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'F'; |
| data_[numUsed_] = malloc(sizeof(struct defiPnt)); |
| ((struct defiPnt*)(data_[numUsed_])) -> x = x; |
| ((struct defiPnt*)(data_[numUsed_])) -> y = y; |
| ((struct defiPnt*)(data_[numUsed_])) -> ext = ext; |
| (numUsed_)++; |
| } |
| |
| void defiPath::addVirtualPoint(int x, int y) { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'U'; |
| data_[numUsed_] = malloc(sizeof(struct defiPnt)); |
| ((struct defiPnt*)(data_[numUsed_])) -> x = x; |
| ((struct defiPnt*)(data_[numUsed_])) -> y = y; |
| (numUsed_)++; |
| } |
| |
| void defiPath::setTaper() { |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'T'; |
| data_[numUsed_] = 0; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::addShape(const char* l) { |
| int len = strlen(l)+1; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| keys_[numUsed_] = 'S' ; |
| data_[numUsed_] = malloc(len); |
| strcpy((char*)(data_[numUsed_]), defData->DEFCASE(l)); |
| (numUsed_)++; |
| } |
| |
| void defiPath::addStyle(int s) { |
| int *style; |
| if (numUsed_ == numAllocated_) |
| bumpSize(numAllocated_ * 2); |
| style = (int*)malloc(sizeof(int)); |
| *style = s; |
| keys_[numUsed_] = 'Y' ; |
| data_[numUsed_] = style; |
| (numUsed_)++; |
| } |
| |
| |
| void defiPath::print(FILE* fout) const { |
| int i; |
| int *wptr; |
| if (fout == 0) fout = stdout; |
| fprintf(fout, "Path:\n"); |
| for (i = 0; i < numUsed_; i++) { |
| if (keys_[i] == 'L') { |
| fprintf(fout, " layer %s\n", (char*)(data_[i])); |
| } else if (keys_[i] == 'R') { |
| fprintf(fout, " taperrule %s\n", data_[i] ? (char*)(data_[i]) : "" ); |
| } else if (keys_[i] == 'T') { |
| fprintf(fout, " taper %s\n", data_[i] ? (char*)(data_[i]) : "" ); |
| } else if (keys_[i] == 'S') { |
| fprintf(fout, " shape %s\n", data_[i] ? (char*)(data_[i]) : "" ); |
| } else if (keys_[i] == 'V') { |
| fprintf(fout, " via %s\n", data_[i] ? (char*)(data_[i]) : "" ); |
| } else if (keys_[i] == 'O') { |
| fprintf(fout, " via rotation %s\n", |
| data_[i] ? (char*)(data_[i]) : "" ); |
| } else if (keys_[i] == 'M') { |
| fprintf(fout, " mask %d\n", getMask() ); |
| } else if (keys_[i] == 'E') { |
| fprintf(fout, " rect %d,%d,%d,%d\n", |
| ((struct defiViaRect*)(data_[i]))->deltaX1, |
| ((struct defiViaRect*)(data_[i]))->deltaY1, |
| ((struct defiViaRect*)(data_[i]))->deltaX2, |
| ((struct defiViaRect*)(data_[i]))->deltaY2); |
| } else if (keys_[i] == 'W') { |
| wptr = (int*)(data_[i]); |
| fprintf(fout, " width %d\n", *wptr); |
| } else if (keys_[i] == 'P') { |
| fprintf(fout, " point %d,%d\n", |
| ((struct defiPnt*)(data_[i]))->x, |
| ((struct defiPnt*)(data_[i]))->y); |
| } else if (keys_[i] == 'F') { |
| fprintf(fout, " flushpoint %d,%d,%d\n", |
| ((struct defiPnt*)(data_[i]))->x, |
| ((struct defiPnt*)(data_[i]))->y, |
| ((struct defiPnt*)(data_[i]))->ext); |
| } else if (keys_[i] == 'U') { |
| fprintf(fout, " virtualpoint %d,%d\n", |
| ((struct defiPnt*)(data_[i]))->x, |
| ((struct defiPnt*)(data_[i]))->y); |
| } else if (keys_[i] == 'D') { |
| fprintf(fout, " DO %d BY %d STEP %d %d\n", |
| ((struct defiViaData*)(data_[i]))->numX, |
| ((struct defiViaData*)(data_[i]))->numY, |
| ((struct defiViaData*)(data_[i]))->stepX, |
| ((struct defiViaData*)(data_[i]))->stepY); |
| } else { |
| fprintf(fout, " ERROR\n"); |
| } |
| } |
| } |
| |
| |
| void defiPath::bumpSize(int size) { |
| int i; |
| int* newKeys = (int*)malloc(size * sizeof(int*)); |
| void** newData = (void**)malloc(size * sizeof(void*)); |
| |
| for (i = 0; i < numUsed_; i++) { |
| newKeys[i] = keys_[i]; |
| newData[i] = data_[i]; |
| } |
| |
| if (keys_) free((char*)(keys_)); |
| if (data_) free((char*)(data_)); |
| |
| keys_ = newKeys; |
| data_ = newData; |
| numAllocated_ = size; |
| } |
| |
| |
| END_LEFDEF_PARSER_NAMESPACE |
| |