blob: 8efaae8749bc2f95cf68a88db3b9182a99dc6c9e [file] [log] [blame]
// *****************************************************************************
// *****************************************************************************
// Copyright 2012 - 2015, 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lex.h"
#include "lefiViaRule.hpp"
#include "lefiDebug.hpp"
BEGIN_LEFDEF_PARSER_NAMESPACE
// *****************************************************************************
// lefiViaRuleLayer
// *****************************************************************************
lefiViaRuleLayer::lefiViaRuleLayer()
: name_(NULL),
direction_(0),
overhang1_(0.0),
overhang2_(0.0),
hasWidth_(0),
hasResistance_(0),
hasOverhang_(0),
hasMetalOverhang_(0),
hasSpacing_(0),
hasRect_(0),
widthMin_(0.0),
widthMax_(0.0),
overhang_(0.0),
metalOverhang_(0.0),
resistance_(0.0),
spacingStepX_(0.0),
spacingStepY_(0.0),
xl_(0.0),
xh_(0.0),
yl_(0.0),
yh_(0.0)
{
Init();
}
void
lefiViaRuleLayer::Init()
{
name_ = 0;
overhang1_ = -1;
overhang2_ = -1;
}
void
lefiViaRuleLayer::clearLayerOverhang()
{
overhang1_ = -1;
overhang2_ = -1;
}
void
lefiViaRuleLayer::setName(const char *name)
{
int len = strlen(name) + 1;
if (name_)
lefFree(name_);
name_ = (char*) lefMalloc(len);
strcpy(name_, CASE(name));
direction_ = '\0';
// overhang1_ = -1; already reset in clearLayerOverhang
// overhang2_ = -1;
hasWidth_ = 0;
hasResistance_ = 0;
hasOverhang_ = 0;
hasMetalOverhang_ = 0;
hasSpacing_ = 0;
hasRect_ = 0;
}
void
lefiViaRuleLayer::Destroy()
{
if (name_)
lefFree(name_);
}
lefiViaRuleLayer::~lefiViaRuleLayer()
{
// Destroy will be called explicitly
// so do nothing here.
}
void
lefiViaRuleLayer::setHorizontal()
{
direction_ = 'H';
}
void
lefiViaRuleLayer::setVertical()
{
direction_ = 'V';
}
// 5.5
void
lefiViaRuleLayer::setEnclosure(double overhang1,
double overhang2)
{
overhang1_ = overhang1;
overhang2_ = overhang2;
}
void
lefiViaRuleLayer::setWidth(double minW,
double maxW)
{
hasWidth_ = 1;
widthMin_ = minW;
widthMax_ = maxW;
}
void
lefiViaRuleLayer::setOverhang(double d)
{
hasOverhang_ = 1;
overhang_ = d;
}
// 5.6
void
lefiViaRuleLayer::setOverhangToEnclosure(double d)
{
if ((overhang1_ != -1) && (overhang2_ != -1))
return; // both overhang1_ & overhang2_ are set
if (overhang1_ == -1)
overhang1_ = d; // set value to overhang1_
else
overhang2_ = d; // overhang1_ already set, set to overhang2_
return;
}
// 5.5
void
lefiViaRuleLayer::setMetalOverhang(double d)
{
hasMetalOverhang_ = 1;
metalOverhang_ = d;
}
void
lefiViaRuleLayer::setResistance(double d)
{
hasResistance_ = 1;
resistance_ = d;
}
void
lefiViaRuleLayer::setSpacing(double x,
double y)
{
hasSpacing_ = 1;
spacingStepX_ = x;
spacingStepY_ = y;
}
void
lefiViaRuleLayer::setRect(double xl,
double yl,
double xh,
double yh)
{
hasRect_ = 1;
xl_ = xl;
yl_ = yl;
xh_ = xh;
yh_ = yh;
}
int
lefiViaRuleLayer::hasRect() const
{
return hasRect_;
}
int
lefiViaRuleLayer::hasDirection() const
{
return direction_ ? 1 : 0;
}
// 5.5
int
lefiViaRuleLayer::hasEnclosure() const
{
return overhang1_ == -1 ? 0 : 1;
}
int
lefiViaRuleLayer::hasWidth() const
{
return hasWidth_;
}
int
lefiViaRuleLayer::hasResistance() const
{
return hasResistance_;
}
int
lefiViaRuleLayer::hasOverhang() const
{
return hasOverhang_;
}
int
lefiViaRuleLayer::hasMetalOverhang() const
{
return hasMetalOverhang_;
}
int
lefiViaRuleLayer::hasSpacing() const
{
return hasSpacing_;
}
char *
lefiViaRuleLayer::name() const
{
return name_;
}
int
lefiViaRuleLayer::isHorizontal() const
{
return direction_ == 'H' ? 1 : 0;
}
int
lefiViaRuleLayer::isVertical() const
{
return direction_ == 'V' ? 1 : 0;
}
// 5.5
double
lefiViaRuleLayer::enclosureOverhang1() const
{
return overhang1_;
}
// 5.5
double
lefiViaRuleLayer::enclosureOverhang2() const
{
return overhang2_;
}
double
lefiViaRuleLayer::widthMin() const
{
return widthMin_;
}
double
lefiViaRuleLayer::widthMax() const
{
return widthMax_;
}
double
lefiViaRuleLayer::overhang() const
{
return overhang_;
}
double
lefiViaRuleLayer::metalOverhang() const
{
return metalOverhang_;
}
double
lefiViaRuleLayer::resistance() const
{
return resistance_;
}
double
lefiViaRuleLayer::spacingStepX() const
{
return spacingStepX_;
}
double
lefiViaRuleLayer::spacingStepY() const
{
return spacingStepY_;
}
double
lefiViaRuleLayer::xl() const
{
return xl_;
}
double
lefiViaRuleLayer::yl() const
{
return yl_;
}
double
lefiViaRuleLayer::xh() const
{
return xh_;
}
double
lefiViaRuleLayer::yh() const
{
return yh_;
}
void
lefiViaRuleLayer::print(FILE *f) const
{
fprintf(f, " Layer %s", name_);
if (isHorizontal())
fprintf(f, " HORIZONTAL");
if (isVertical())
fprintf(f, " VERTICAL");
fprintf(f, "\n");
if (hasWidth())
fprintf(f, " WIDTH %g %g\n", widthMin(),
widthMax());
if (hasResistance())
fprintf(f, " RESISTANCE %g\n", resistance());
if (hasOverhang())
fprintf(f, " OVERHANG %g\n", overhang());
if (hasMetalOverhang())
fprintf(f, " METALOVERHANG %g\n",
metalOverhang());
if (hasSpacing())
fprintf(f, " SPACING %g %g\n",
spacingStepX(),
spacingStepY());
if (hasRect())
fprintf(f, " RECT %g,%g %g,%g\n",
xl(), yl(),
xh(), yh());
}
// *****************************************************************************
// lefiViaRule
// *****************************************************************************
lefiViaRule::lefiViaRule()
: name_(NULL),
nameSize_(0),
hasGenerate_(0),
hasDefault_(0),
numLayers_(0),
numVias_(0),
viasAllocated_(0),
vias_(NULL),
numProps_(0),
propsAllocated_(0),
names_(NULL),
values_(NULL),
dvalues_(NULL),
types_(NULL)
{
Init();
}
void
lefiViaRule::Init()
{
nameSize_ = 16;
name_ = (char*) lefMalloc(16);
viasAllocated_ = 2;
vias_ = (char**) lefMalloc(sizeof(char*) * 2);
layers_[0].Init();
layers_[1].Init();
layers_[2].Init();
numLayers_ = 0;
numVias_ = 0;
numProps_ = 0;
propsAllocated_ = 1;
names_ = (char**) lefMalloc(sizeof(char*));
values_ = (char**) lefMalloc(sizeof(char*));
dvalues_ = (double*) lefMalloc(sizeof(double));
types_ = (char*) lefMalloc(sizeof(char));
}
void
lefiViaRule::clear()
{
int i;
hasGenerate_ = 0;
hasDefault_ = 0;
for (i = 0; i < numProps_; i++) {
lefFree(names_[i]);
lefFree(values_[i]);
dvalues_[i] = 0;
}
numProps_ = 0;
numLayers_ = 0;
for (i = 0; i < numVias_; i++) {
lefFree(vias_[i]);
}
numVias_ = 0;
}
void
lefiViaRule::clearLayerOverhang()
{
layers_[0].clearLayerOverhang();
layers_[1].clearLayerOverhang();
}
void
lefiViaRule::setName(const char *name)
{
int len = strlen(name) + 1;
if (len > nameSize_) {
lefFree(name_);
name_ = (char*) lefMalloc(len);
nameSize_ = len;
}
strcpy(name_, CASE(name));
clear();
}
void
lefiViaRule::Destroy()
{
clear();
lefFree(name_);
lefFree((char*) (vias_));
lefFree((char*) (names_));
lefFree((char*) (values_));
lefFree((char*) (dvalues_));
lefFree((char*) (types_));
layers_[0].Destroy();
layers_[1].Destroy();
layers_[2].Destroy();
}
lefiViaRule::~lefiViaRule()
{
Destroy();
}
void
lefiViaRule::setGenerate()
{
hasGenerate_ = 1;
}
void
lefiViaRule::setDefault()
{
hasDefault_ = 1;
}
void
lefiViaRule::addViaName(const char *name)
{
// Add one of possibly many via names
int len = strlen(name) + 1;
if (numVias_ == viasAllocated_) {
int i;
char **nn;
if (viasAllocated_ == 0)
viasAllocated_ = 2;
else
viasAllocated_ *= 2;
nn = (char**) lefMalloc(sizeof(char*) * viasAllocated_);
for (i = 0; i < numVias_; i++)
nn[i] = vias_[i];
lefFree((char*) (vias_));
vias_ = nn;
}
vias_[numVias_] = (char*) lefMalloc(len);
strcpy(vias_[numVias_], CASE(name));
numVias_ += 1;
}
void
lefiViaRule::setRect(double xl,
double yl,
double xh,
double yh)
{
layers_[numLayers_ - 1].setRect(xl, yl, xh, yh);
}
void
lefiViaRule::setSpacing(double x,
double y)
{
layers_[numLayers_ - 1].setSpacing(x, y);
}
void
lefiViaRule::setWidth(double x,
double y)
{
layers_[numLayers_ - 1].setWidth(x, y);
}
void
lefiViaRule::setResistance(double d)
{
layers_[numLayers_ - 1].setResistance(d);
}
void
lefiViaRule::setOverhang(double d)
{
layers_[numLayers_ - 1].setOverhang(d);
}
// 5.6, try to set value to layers_[0] & layers_[1]
void
lefiViaRule::setOverhangToEnclosure(double d)
{
layers_[0].setOverhangToEnclosure(d);
layers_[1].setOverhangToEnclosure(d);
}
void
lefiViaRule::setMetalOverhang(double d)
{
layers_[numLayers_ - 1].setMetalOverhang(d);
}
void
lefiViaRule::setVertical()
{
layers_[numLayers_ - 1].setVertical();
}
void
lefiViaRule::setHorizontal()
{
layers_[numLayers_ - 1].setHorizontal();
}
void
lefiViaRule::setEnclosure(double overhang1,
double overhang2)
{
layers_[numLayers_ - 1].setEnclosure(overhang1,
overhang2);
}
void
lefiViaRule::setLayer(const char *name)
{
if (numLayers_ == 3) {
lefiError(0, 1430, "ERROR (LEFPARS-1430): too many via rule layers");
return;
}
// This routine sets and creates the active layer.
layers_[numLayers_].setName(name);
numLayers_ += 1;
}
int
lefiViaRule::hasGenerate() const
{
return hasGenerate_;
}
int
lefiViaRule::hasDefault() const
{
return hasDefault_;
}
int
lefiViaRule::numLayers() const
{
// There are 2 or 3 layers in a rule.
// numLayers() tells how many.
// If a third layer exists then it is the cut layer.
return numLayers_;
}
lefiViaRuleLayer *
lefiViaRule::layer(int index) const
{
if (index < 0 || index > 2)
return 0;
return (lefiViaRuleLayer*) &(layers_[index]);
}
char *
lefiViaRule::name() const
{
return name_;
}
void
lefiViaRule::print(FILE *f) const
{
int i;
fprintf(f, "VIA RULE %s", name());
if (hasGenerate())
fprintf(f, " GENERATE");
fprintf(f, "\n");
for (i = 0; i < numLayers(); i++) {
layers_[i].print(f);
}
for (i = 0; i < numVias(); i++) {
fprintf(f, " Via %s\n", viaName(i));
}
}
int
lefiViaRule::numVias() const
{
return numVias_;
}
char *
lefiViaRule::viaName(int index) const
{
if (index < 0 || index >= numVias_)
return 0;
return vias_[index];
}
int
lefiViaRule::numProps() const
{
return numProps_;
}
void
lefiViaRule::addProp(const char *name,
const char *value,
const char type)
{
int len = strlen(name) + 1;
if (numProps_ == propsAllocated_) {
int i;
int max;
int lim;
char **nn;
char **nv;
double *nd;
char *nt;
if (propsAllocated_ == 0)
propsAllocated_ = 1; // initialize propsAllocated_
max = propsAllocated_ *= 2;
lim = numProps_;
nn = (char**) lefMalloc(sizeof(char*) * max);
nv = (char**) lefMalloc(sizeof(char*) * max);
nd = (double*) lefMalloc(sizeof(double) * max);
nt = (char*) lefMalloc(sizeof(char) * max);
for (i = 0; i < lim; i++) {
nn[i] = names_[i];
nv[i] = values_[i];
nd[i] = dvalues_[i];
nt[i] = types_[i];
}
lefFree((char*) (names_));
lefFree((char*) (values_));
lefFree((char*) (dvalues_));
lefFree((char*) (types_));
names_ = nn;
values_ = nv;
dvalues_ = nd;
types_ = nt;
}
names_[numProps_] = (char*) lefMalloc(sizeof(char) * len);
strcpy(names_[numProps_], name);
len = strlen(value) + 1;
values_[numProps_] = (char*) lefMalloc(sizeof(char) * len);
strcpy(values_[numProps_], value);
dvalues_[numProps_] = 0;
types_[numProps_] = type;
numProps_ += 1;
}
void
lefiViaRule::addNumProp(const char *name,
const double d,
const char *value,
const char type)
{
int len = strlen(name) + 1;
if (numProps_ == propsAllocated_) {
int i;
int max;
int lim;
char **nn;
char **nv;
double *nd;
char *nt;
if (propsAllocated_ == 0)
propsAllocated_ = 1; // initialize propsAllocated_
max = propsAllocated_ *= 2;
lim = numProps_;
nn = (char**) lefMalloc(sizeof(char*) * max);
nv = (char**) lefMalloc(sizeof(char*) * max);
nd = (double*) lefMalloc(sizeof(double) * max);
nt = (char*) lefMalloc(sizeof(char) * max);
for (i = 0; i < lim; i++) {
nn[i] = names_[i];
nv[i] = values_[i];
nd[i] = dvalues_[i];
nt[i] = types_[i];
}
lefFree((char*) (names_));
lefFree((char*) (values_));
lefFree((char*) (dvalues_));
lefFree((char*) (types_));
names_ = nn;
values_ = nv;
dvalues_ = nd;
types_ = nt;
}
names_[numProps_] = (char*) lefMalloc(sizeof(char) * len);
strcpy(names_[numProps_], name);
len = strlen(value) + 1;
values_[numProps_] = (char*) lefMalloc(sizeof(char) * len);
strcpy(values_[numProps_], value);
dvalues_[numProps_] = d;
types_[numProps_] = type;
numProps_ += 1;
}
const char *
lefiViaRule::propName(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return names_[i];
}
const char *
lefiViaRule::propValue(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return values_[i];
}
double
lefiViaRule::propNumber(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return dvalues_[i];
}
const char
lefiViaRule::propType(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return types_[i];
}
int
lefiViaRule::propIsNumber(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return dvalues_[i] ? 1 : 0;
}
int
lefiViaRule::propIsString(int i) const
{
char msg[160];
if (i < 0 || i >= numProps_) {
sprintf(msg, "ERROR (LEFPARS-1431): The index number %d given for the VIARULE PROPERTY is invalid.\nValid index is from 0 to %d", i, numProps_);
lefiError(0, 1431, msg);
return 0;
}
return dvalues_[i] ? 0 : 1;
}
END_LEFDEF_PARSER_NAMESPACE