liberty pin names with brackets and .'s
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
84271b26da
commit
5d45a07e34
|
|
@ -1093,4 +1093,7 @@ private:
|
|||
LibertyCell *cell_;
|
||||
};
|
||||
|
||||
const char *
|
||||
portLibertyToSta(const char *port_name);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -140,10 +140,14 @@ stringAppend(char *&str1,
|
|||
str1 += strlen(str2);
|
||||
}
|
||||
|
||||
void
|
||||
stringDeleteCheck(const char *str);
|
||||
|
||||
// Delete for strings allocated with new char[].
|
||||
inline void
|
||||
stringDelete(const char *str)
|
||||
{
|
||||
stringDeleteCheck(str);
|
||||
delete [] str;
|
||||
}
|
||||
|
||||
|
|
@ -177,6 +181,8 @@ void
|
|||
initTmpStrings();
|
||||
void
|
||||
deleteTmpStrings();
|
||||
bool
|
||||
isTmpString(const char *str);
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -18,11 +18,6 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
const char *
|
||||
staToVerilog(const char *sta_name,
|
||||
const char escape);
|
||||
const char *
|
||||
verilogToSta(const char *verilog_name);
|
||||
const char *
|
||||
instanceVerilogName(const char *sta_name,
|
||||
const char escape);
|
||||
|
|
@ -33,4 +28,13 @@ const char *
|
|||
portVerilogName(const char *sta_name,
|
||||
const char escape);
|
||||
|
||||
const char *
|
||||
moduleVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
instanceVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
netVerilogToSta(const char *sta_name);
|
||||
const char *
|
||||
portVerilogToSta(const char *sta_name);
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -2499,6 +2499,26 @@ LibertyPort::setReceiverModel(ReceiverModelPtr receiver_model)
|
|||
receiver_model_ = receiver_model;
|
||||
}
|
||||
|
||||
const char *
|
||||
portLibertyToSta(const char *port_name)
|
||||
{
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
size_t name_length = strlen(port_name);
|
||||
char *sta_name = makeTmpString(name_length * 2);
|
||||
//char *sta_name = new char[name_length * 2];//makeTmpString(name_length * 2);
|
||||
char *p = sta_name;
|
||||
for (size_t i = 0; i < name_length; i++) {
|
||||
char ch = port_name[i];
|
||||
if (ch == bus_brkt_left
|
||||
|| ch == bus_brkt_right)
|
||||
*p++ = '\\';
|
||||
*p++ = ch;
|
||||
}
|
||||
*p++ = '\0';
|
||||
return sta_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
LibertyPortSeq
|
||||
|
|
|
|||
|
|
@ -39,25 +39,28 @@ LibertyBuilder::makeCell(LibertyLibrary *library,
|
|||
|
||||
LibertyPort *
|
||||
LibertyBuilder::makePort(LibertyCell *cell,
|
||||
const char *name)
|
||||
const char *port_name)
|
||||
{
|
||||
LibertyPort *port = new LibertyPort(cell, name, false, nullptr, -1, -1, false, nullptr);
|
||||
const char *sta_name = portLibertyToSta(port_name);
|
||||
LibertyPort *port = new LibertyPort(cell, sta_name, false, nullptr,
|
||||
-1, -1, false, nullptr);
|
||||
cell->addPort(port);
|
||||
return port;
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
LibertyBuilder::makeBusPort(LibertyCell *cell,
|
||||
const char *name,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl)
|
||||
{
|
||||
LibertyPort *port = new LibertyPort(cell, name, true, bus_dcl,
|
||||
string sta_name = portLibertyToSta(bus_name);
|
||||
LibertyPort *port = new LibertyPort(cell, sta_name.c_str(), true, bus_dcl,
|
||||
from_index, to_index,
|
||||
false, new ConcretePortSeq);
|
||||
cell->addPort(port);
|
||||
makeBusPortBits(cell->library(), cell, port, name, from_index, to_index);
|
||||
makeBusPortBits(cell->library(), cell, port, sta_name.c_str(), from_index, to_index);
|
||||
return port;
|
||||
}
|
||||
|
||||
|
|
@ -65,17 +68,17 @@ void
|
|||
LibertyBuilder::makeBusPortBits(ConcreteLibrary *library,
|
||||
LibertyCell *cell,
|
||||
ConcretePort *bus_port,
|
||||
const char *name,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index)
|
||||
{
|
||||
if (from_index < to_index) {
|
||||
for (int index = from_index; index <= to_index; index++)
|
||||
makeBusPortBit(library, cell, bus_port, name, index);
|
||||
makeBusPortBit(library, cell, bus_port, bus_name, index);
|
||||
}
|
||||
else {
|
||||
for (int index = from_index; index >= to_index; index--)
|
||||
makeBusPortBit(library, cell, bus_port, name, index);
|
||||
makeBusPortBit(library, cell, bus_port, bus_name, index);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ public:
|
|||
virtual LibertyPort *makePort(LibertyCell *cell,
|
||||
const char *name);
|
||||
virtual LibertyPort *makeBusPort(LibertyCell *cell,
|
||||
const char *name,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index,
|
||||
BusDcl *bus_dcl);
|
||||
|
|
@ -83,7 +83,7 @@ protected:
|
|||
void makeBusPortBits(ConcreteLibrary *library,
|
||||
LibertyCell *cell,
|
||||
ConcretePort *bus_port,
|
||||
const char *name,
|
||||
const char *bus_name,
|
||||
int from_index,
|
||||
int to_index);
|
||||
// Bus port bit (internal to makeBusPortBits).
|
||||
|
|
@ -93,7 +93,7 @@ protected:
|
|||
void makeBusPortBit(ConcreteLibrary *library,
|
||||
LibertyCell *cell,
|
||||
ConcretePort *bus_port,
|
||||
const char *name,
|
||||
const char *bus_name,
|
||||
int index);
|
||||
virtual TimingArcSet *makeTimingArcSet(LibertyCell *cell,
|
||||
LibertyPort *from,
|
||||
|
|
|
|||
|
|
@ -67,16 +67,20 @@ LibExprParser::~LibExprParser()
|
|||
stringDelete(token_);
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
libertyReaderFindPort(LibertyCell *cell,
|
||||
const char *port_name);
|
||||
|
||||
FuncExpr *
|
||||
LibExprParser::makeFuncExprPort(const char *port_name)
|
||||
{
|
||||
LibertyPort *port = cell_->findLibertyPort(port_name);
|
||||
FuncExpr *expr = nullptr;
|
||||
LibertyPort *port = libertyReaderFindPort(cell_, port_name);
|
||||
if (port)
|
||||
expr = FuncExpr::makePort(port);
|
||||
else
|
||||
report_->error(7, "%s references unknown port %s.",
|
||||
error_msg_, port_name);
|
||||
report_->warn(7, "%s references unknown port %s.",
|
||||
error_msg_, port_name);
|
||||
stringDelete(port_name);
|
||||
return expr;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ libertyExprFlushBuffer()
|
|||
|
||||
%x ESCAPED_STRING
|
||||
|
||||
PORT [A-Za-z_]([A-Za-z0-9_\[\]])*
|
||||
PORT [A-Za-z_]([A-Za-z0-9_\.\[\]])*
|
||||
OP "'"|"!"|"^"|"*"|"&"|"+"|"|"|1|0
|
||||
PAREN "("|")"
|
||||
BLANK [ \t\r]
|
||||
|
|
|
|||
|
|
@ -2852,9 +2852,9 @@ LibertyReader::beginPin(LibertyGroup *group)
|
|||
while (param_iter.hasNext()) {
|
||||
LibertyAttrValue *param = param_iter.next();
|
||||
if (param->isString()) {
|
||||
const char *name = param->stringValue();
|
||||
debugPrint(debug_, "liberty", 1, " port %s", name);
|
||||
PortNameBitIterator port_iter(cell_, name, this, group->line());
|
||||
const char *port_name = param->stringValue();
|
||||
debugPrint(debug_, "liberty", 1, " port %s", port_name);
|
||||
PortNameBitIterator port_iter(cell_, port_name, this, group->line());
|
||||
while (port_iter.hasNext()) {
|
||||
LibertyPort *port = port_iter.next();
|
||||
ports_->push_back(port);
|
||||
|
|
@ -2885,8 +2885,6 @@ LibertyReader::beginPin(LibertyGroup *group)
|
|||
}
|
||||
else {
|
||||
ports_ = new LibertyPortSeq;
|
||||
char brkt_left = library_->busBrktLeft();
|
||||
char brkt_right = library_->busBrktRight();
|
||||
// Multiple port names can share group def.
|
||||
LibertyAttrValueIterator param_iter(group->params());
|
||||
while (param_iter.hasNext()) {
|
||||
|
|
@ -2894,10 +2892,6 @@ LibertyReader::beginPin(LibertyGroup *group)
|
|||
if (param->isString()) {
|
||||
const char *name = param->stringValue();
|
||||
debugPrint(debug_, "liberty", 1, " port %s", name);
|
||||
if (isBusName(name, brkt_left, brkt_right, escape_))
|
||||
// Pins not inside a bus group with bus names are not really
|
||||
// busses, so escape the brackets.
|
||||
name = escapeChars(name, brkt_left, brkt_right, escape_);
|
||||
LibertyPort *port = builder_->makePort(cell_, name);
|
||||
ports_->push_back(port);
|
||||
}
|
||||
|
|
@ -3101,21 +3095,29 @@ LibertyReader::findPort(const char *port_name)
|
|||
return findPort(cell_, port_name);
|
||||
}
|
||||
|
||||
// Also used by LibExprParser::makeFuncExprPort.
|
||||
LibertyPort *
|
||||
libertyReaderFindPort(LibertyCell *cell,
|
||||
const char *port_name)
|
||||
{
|
||||
LibertyPort *port = cell->findLibertyPort(port_name);
|
||||
if (port == nullptr) {
|
||||
const LibertyLibrary *library = cell->libertyLibrary();
|
||||
char brkt_left = library->busBrktLeft();
|
||||
char brkt_right = library->busBrktRight();
|
||||
const char escape = '\\';
|
||||
// Pins at top level with bus names have escaped brackets.
|
||||
port_name = escapeChars(port_name, brkt_left, brkt_right, escape);
|
||||
port = cell->findLibertyPort(port_name);
|
||||
}
|
||||
return port;
|
||||
}
|
||||
|
||||
LibertyPort *
|
||||
LibertyReader::findPort(LibertyCell *cell,
|
||||
const char *port_name)
|
||||
{
|
||||
LibertyPort *port = cell->findLibertyPort(port_name);
|
||||
if (port == nullptr) {
|
||||
char brkt_left = library_->busBrktLeft();
|
||||
char brkt_right = library_->busBrktRight();
|
||||
if (isBusName(port_name, brkt_left, brkt_right, escape_)) {
|
||||
// Pins at top level with bus names have escaped brackets.
|
||||
port_name = escapeChars(port_name, brkt_left, brkt_right, escape_);
|
||||
port = cell->findLibertyPort(port_name);
|
||||
}
|
||||
}
|
||||
return port;
|
||||
return libertyReaderFindPort(cell, port_name);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -3795,7 +3797,10 @@ LibertyReader::endTiming(LibertyGroup *group)
|
|||
model->setScaleFactorType(type);
|
||||
}
|
||||
}
|
||||
if (timing_->relatedPortNames() == nullptr)
|
||||
TimingType timing_type = timing_->attrs()->timingType();
|
||||
if (timing_->relatedPortNames() == nullptr
|
||||
&& !(timing_type == TimingType::min_clock_tree_path
|
||||
|| timing_type == TimingType::max_clock_tree_path))
|
||||
libWarn(170, group, "timing group missing related_pin/related_bus_pin.");
|
||||
}
|
||||
timing_ = nullptr;
|
||||
|
|
@ -5548,7 +5553,7 @@ PortNameBitIterator::PortNameBitIterator(LibertyCell *cell,
|
|||
void
|
||||
PortNameBitIterator::init(const char *port_name)
|
||||
{
|
||||
LibertyPort *port = visitor_->findPort(cell_, port_name);
|
||||
LibertyPort *port = visitor_->findPort(port_name);
|
||||
if (port) {
|
||||
if (port->isBus())
|
||||
bit_iterator_ = new LibertyPortMemberIterator(port);
|
||||
|
|
@ -5564,7 +5569,7 @@ PortNameBitIterator::init(const char *port_name)
|
|||
parseBusRange(port_name, library->busBrktLeft(), library->busBrktRight(),
|
||||
'\\', bus_name, from, to);
|
||||
if (bus_name) {
|
||||
port = visitor_->findPort(cell_, port_name);
|
||||
port = visitor_->findPort(port_name);
|
||||
if (port) {
|
||||
if (port->isBus()) {
|
||||
if (port->busIndexInRange(from)
|
||||
|
|
@ -5656,7 +5661,7 @@ PortNameBitIterator::findRangeBusNameNext()
|
|||
library->busBrktLeft(),
|
||||
range_bit_,
|
||||
library->busBrktRight());
|
||||
range_name_next_ = visitor_->findPort(cell_, bus_bit_name);
|
||||
range_name_next_ = visitor_->findPort(bus_bit_name);
|
||||
if (range_name_next_) {
|
||||
if (range_from_ > range_to_)
|
||||
range_bit_--;
|
||||
|
|
|
|||
|
|
@ -1118,7 +1118,7 @@ SdcNetwork::visitMatches(const Instance *parent,
|
|||
*p = '\0';
|
||||
PatternMatch matcher(inst_path, pattern);
|
||||
InstanceSeq matches;
|
||||
findChildrenMatching(parent, &matcher, matches);
|
||||
network_->findChildrenMatching(parent, &matcher, matches);
|
||||
if (has_brkts && matches.empty()) {
|
||||
// Look for matches after escaping brackets.
|
||||
const PatternMatch escaped_brkts(escapeBrackets(inst_path, this),
|
||||
|
|
|
|||
|
|
@ -23,6 +23,20 @@
|
|||
|
||||
namespace sta {
|
||||
|
||||
static const char *
|
||||
staToVerilog(const char *sta_name,
|
||||
const char escape);
|
||||
static const char *
|
||||
staToVerilog2(const char *sta_name,
|
||||
const char escape);
|
||||
static const char *
|
||||
verilogToSta(const char *verilog_name);
|
||||
static inline void
|
||||
vstringAppend(char *&str,
|
||||
char *&str_end,
|
||||
char *&insert,
|
||||
char ch);
|
||||
|
||||
const char *
|
||||
instanceVerilogName(const char *sta_name,
|
||||
const char escape)
|
||||
|
|
@ -45,41 +59,64 @@ netVerilogName(const char *sta_name,
|
|||
return vname;
|
||||
}
|
||||
else
|
||||
return staToVerilog(sta_name, escape);
|
||||
return staToVerilog2(sta_name, escape);
|
||||
}
|
||||
|
||||
const char *
|
||||
portVerilogName(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
return staToVerilog(sta_name, escape);
|
||||
return staToVerilog2(sta_name, escape);
|
||||
}
|
||||
|
||||
// Append ch to str at insert. Resize str if necessary.
|
||||
static inline void
|
||||
vstringAppend(char *&str,
|
||||
char *&str_end,
|
||||
char *&insert,
|
||||
char ch)
|
||||
{
|
||||
if (insert == str_end) {
|
||||
size_t length = str_end - str;
|
||||
size_t length2 = length * 2;
|
||||
char *new_str = makeTmpString(length2);
|
||||
strncpy(new_str, str, length);
|
||||
str = new_str;
|
||||
str_end = &str[length2];
|
||||
insert = &str[length];
|
||||
}
|
||||
*insert++ = ch;
|
||||
}
|
||||
|
||||
const char *
|
||||
static const char *
|
||||
staToVerilog(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
const char bus_brkt_left = '[';
|
||||
const char bus_brkt_right = ']';
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
size_t verilog_name_length = strlen(sta_name) + 3;
|
||||
char *verilog_name = makeTmpString(verilog_name_length);
|
||||
char *verilog_name_end = &verilog_name[verilog_name_length];
|
||||
char *v = verilog_name;
|
||||
// Assume the name has to be escaped and start copying while scanning.
|
||||
bool escaped = false;
|
||||
*v++ = '\\';
|
||||
for (const char *s = sta_name; *s ; s++) {
|
||||
char ch = s[0];
|
||||
if (ch == escape) {
|
||||
char next_ch = s[1];
|
||||
if (next_ch == escape) {
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
vstringAppend(verilog_name, verilog_name_end, v, next_ch);
|
||||
s++;
|
||||
}
|
||||
else
|
||||
// Skip escape.
|
||||
escaped = true;
|
||||
}
|
||||
else {
|
||||
if ((!(isalnum(ch) || ch == '_')))
|
||||
escaped = true;
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ch);
|
||||
}
|
||||
}
|
||||
if (escaped) {
|
||||
// Add a terminating space.
|
||||
vstringAppend(verilog_name, verilog_name_end, v, ' ');
|
||||
vstringAppend(verilog_name, verilog_name_end, v, '\0');
|
||||
return verilog_name;
|
||||
}
|
||||
else
|
||||
return sta_name;
|
||||
}
|
||||
|
||||
static const char *
|
||||
staToVerilog2(const char *sta_name,
|
||||
const char escape)
|
||||
{
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
// Leave room for leading escape and trailing space if the name
|
||||
// needs to be escaped.
|
||||
size_t verilog_name_length = strlen(sta_name) + 3;
|
||||
|
|
@ -120,30 +157,60 @@ staToVerilog(const char *sta_name,
|
|||
return sta_name;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
const char *
|
||||
moduleVerilogToSta(const char *module_name)
|
||||
{
|
||||
return verilogToSta(module_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
instanceVerilogToSta(const char *inst_name)
|
||||
{
|
||||
return verilogToSta(inst_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
netVerilogToSta(const char *net_name)
|
||||
{
|
||||
return verilogToSta(net_name);
|
||||
}
|
||||
|
||||
const char *
|
||||
portVerilogToSta(const char *port_name)
|
||||
{
|
||||
return verilogToSta(port_name);
|
||||
}
|
||||
|
||||
static const char *
|
||||
verilogToSta(const char *verilog_name)
|
||||
{
|
||||
if (verilog_name[0] == '\\') {
|
||||
const char divider = '/';
|
||||
const char escape = '\\';
|
||||
const char bus_brkt_left = '[';
|
||||
const char bus_brkt_right = ']';
|
||||
size_t sta_name_length = strlen(verilog_name) + 1;
|
||||
if (verilog_name && verilog_name[0] == '\\') {
|
||||
constexpr char divider = '/';
|
||||
constexpr char escape = '\\';
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
|
||||
// Ignore leading '\'.
|
||||
verilog_name = &verilog_name[1];
|
||||
size_t verilog_name_length = strlen(verilog_name);
|
||||
if (verilog_name[verilog_name_length - 1] == ' ')
|
||||
verilog_name_length--;
|
||||
// +1 for \0, +2 for escaping brackets.
|
||||
size_t sta_name_length = verilog_name_length + 1;
|
||||
char *sta_name = makeTmpString(sta_name_length);
|
||||
char *sta_name_end = &sta_name[sta_name_length];
|
||||
char *s = sta_name;
|
||||
for (const char *v = &verilog_name[1]; *v ; v++) {
|
||||
char ch = *v;
|
||||
if (ch == divider
|
||||
|| ch == bus_brkt_left
|
||||
|| ch == bus_brkt_right
|
||||
|| ch == escape)
|
||||
// Escape dividers, bus brackets and escapes.
|
||||
for (size_t i = 0; i < verilog_name_length; i++) {
|
||||
char ch = verilog_name[i];
|
||||
if (ch == bus_brkt_left
|
||||
|| ch == bus_brkt_right
|
||||
|| ch == divider
|
||||
|| ch == escape)
|
||||
// Escape bus brackets, dividers and escapes.
|
||||
vstringAppend(sta_name, sta_name_end, s, escape);
|
||||
vstringAppend(sta_name, sta_name_end, s, ch);
|
||||
// Don't include the last character, which is always a space.
|
||||
if (v[2] == '\0')
|
||||
break;
|
||||
}
|
||||
vstringAppend(sta_name, sta_name_end, s, '\0');
|
||||
return sta_name;
|
||||
|
|
@ -152,4 +219,23 @@ verilogToSta(const char *verilog_name)
|
|||
return verilog_name;
|
||||
}
|
||||
|
||||
// Append ch to str at insert. Resize str if necessary.
|
||||
static inline void
|
||||
vstringAppend(char *&str,
|
||||
char *&str_end,
|
||||
char *&insert,
|
||||
char ch)
|
||||
{
|
||||
if (insert == str_end) {
|
||||
size_t length = str_end - str;
|
||||
size_t length2 = length * 2;
|
||||
char *new_str = makeTmpString(length2);
|
||||
strncpy(new_str, str, length);
|
||||
str = new_str;
|
||||
str_end = &str[length2];
|
||||
insert = &str[length];
|
||||
}
|
||||
*insert++ = ch;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
|
|
@ -22,8 +22,10 @@
|
|||
namespace sta {
|
||||
|
||||
char *
|
||||
spefToSta(const char *token, char spef_divider,
|
||||
char path_divider, char path_escape)
|
||||
spefToSta(const char *token,
|
||||
char spef_divider,
|
||||
char path_divider,
|
||||
char path_escape)
|
||||
{
|
||||
const char spef_escape = '\\';
|
||||
char *trans_token = new char[strlen(token) + 1];
|
||||
|
|
@ -63,8 +65,10 @@ spefToSta(const char *token, char spef_divider,
|
|||
}
|
||||
|
||||
char *
|
||||
staToSpef(const char *token, char spef_divider,
|
||||
char path_divider, char path_escape)
|
||||
staToSpef(const char *token,
|
||||
char spef_divider,
|
||||
char path_divider,
|
||||
char path_escape)
|
||||
{
|
||||
const char spef_escape = '\\';
|
||||
char *trans_token = new char[strlen(token) + 1];
|
||||
|
|
|
|||
|
|
@ -131,11 +131,7 @@ ReadVcdActivities::setVarActivity(VcdVar *var,
|
|||
string &var_name,
|
||||
const VcdValues &var_values)
|
||||
{
|
||||
// var names include the leading \ but not the trailing space so add it.
|
||||
if (var_name[0] == '\\')
|
||||
var_name += ' ';
|
||||
const char *sta_name = verilogToSta(var_name.c_str());
|
||||
|
||||
const char *sta_name = netVerilogToSta(var_name.c_str());
|
||||
if (var->width() == 1)
|
||||
setVarActivity(sta_name, var_values, 0);
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -85,11 +85,16 @@ EOL \r?\n
|
|||
|
||||
"//"[^\n]*{EOL} { sta::sdf_reader->incrLine(); }
|
||||
|
||||
("-"|"+")?([0-9]*)("."[0-9]+)?([eE]("-"|"+")?[0-9]+)? {
|
||||
("-"|"+")?([0-9]*)("."[0-9]+)([eE]("-"|"+")?[0-9]+)? {
|
||||
SdfParse_lval.number = static_cast<float>(atof(yytext));
|
||||
return NUMBER;
|
||||
return FNUMBER;
|
||||
}
|
||||
|
||||
"+"?[0-9]+ {
|
||||
SdfParse_lval.integer = atoi(yytext);
|
||||
return DNUMBER;
|
||||
}
|
||||
|
||||
":"|"{"|"}"|"["|"]"|","|"*"|";"|"="|"-"|"+"|"|"|"("|")"|{HCHAR} {
|
||||
return ((int) yytext[0]);
|
||||
}
|
||||
|
|
@ -178,15 +183,10 @@ COND {
|
|||
<COND_EXPR>. { sdf_token += yytext[0]; }
|
||||
|
||||
{ID} {
|
||||
SdfParse_lval.string = sta::stringCopy(sta::sdf_reader->unescaped(yytext));
|
||||
SdfParse_lval.string = sta::stringCopy(yytext);
|
||||
return ID;
|
||||
}
|
||||
|
||||
{ID}({HCHAR}{ID})* {
|
||||
SdfParse_lval.string = sta::stringCopy(sta::sdf_reader->unescaped(yytext));
|
||||
return PATH;
|
||||
}
|
||||
|
||||
{EOL} { sta::sdf_reader->incrLine(); }
|
||||
|
||||
{BLANK} { /* Ignore blanks. */ }
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ int SdfLex_lex();
|
|||
// use yacc generated parser errors
|
||||
#define YYERROR_VERBOSE
|
||||
|
||||
#define YYDEBUG 1
|
||||
|
||||
%}
|
||||
|
||||
// expected shift/reduce conflicts
|
||||
|
|
@ -32,9 +34,10 @@ int SdfLex_lex();
|
|||
|
||||
%union {
|
||||
char character;
|
||||
char *string;
|
||||
const char *string;
|
||||
float number;
|
||||
float *number_ptr;
|
||||
int integer;
|
||||
sta::SdfTriple *triple;
|
||||
sta::SdfTripleSeq *delval_list;
|
||||
sta::SdfPortSpec *port_spec;
|
||||
|
|
@ -48,13 +51,14 @@ int SdfLex_lex();
|
|||
%token IOPATH TIMINGCHECK
|
||||
%token SETUP HOLD SETUPHOLD RECOVERY REMOVAL RECREM WIDTH PERIOD SKEW NOCHANGE
|
||||
%token POSEDGE NEGEDGE COND CONDELSE
|
||||
%token QSTRING ID PATH NUMBER EXPR_OPEN_IOPATH EXPR_OPEN EXPR_ID_CLOSE
|
||||
%token QSTRING ID FNUMBER DNUMBER EXPR_OPEN_IOPATH EXPR_OPEN EXPR_ID_CLOSE
|
||||
|
||||
%type <number> NUMBER
|
||||
%type <number> FNUMBER NUMBER
|
||||
%type <integer> DNUMBER
|
||||
%type <number_ptr> number_opt
|
||||
%type <triple> value triple
|
||||
%type <delval_list> delval_list
|
||||
%type <string> QSTRING ID PATH path port_instance
|
||||
%type <string> QSTRING ID path port port_instance
|
||||
%type <string> EXPR_OPEN_IOPATH EXPR_OPEN EXPR_ID_CLOSE
|
||||
%type <port_spec> port_spec port_tchk
|
||||
%type <transition> port_transition
|
||||
|
|
@ -159,7 +163,9 @@ del_defs:
|
|||
|
||||
path:
|
||||
ID
|
||||
| PATH
|
||||
{ $$ = sta::sdf_reader->unescaped($1); }
|
||||
| path hchar ID
|
||||
{ $$ = sta::sdf_reader->makePath($1, sta::sdf_reader->unescaped($3)); }
|
||||
;
|
||||
|
||||
del_def:
|
||||
|
|
@ -218,7 +224,6 @@ tchk_def:
|
|||
{ sta::sdf_reader->timingCheckSetupHold($4, $5, $6, $7);
|
||||
sta::sdf_reader->setInTimingCheck(false);
|
||||
}
|
||||
//| '(' SETUPHOLD port_spec port_spec value value scond? ccond? ')'
|
||||
| '(' RECOVERY { sta::sdf_reader->setInTimingCheck(true); }
|
||||
port_tchk port_tchk value ')'
|
||||
{ sta::sdf_reader->timingCheck(sta::TimingRole::recovery(),$4,$5,$6);
|
||||
|
|
@ -234,7 +239,6 @@ tchk_def:
|
|||
{ sta::sdf_reader->timingCheckRecRem($4, $5, $6, $7);
|
||||
sta::sdf_reader->setInTimingCheck(false);
|
||||
}
|
||||
//| '(' RECREM port_spec port_spec value value scond? ccond? ')'
|
||||
| '(' SKEW { sta::sdf_reader->setInTimingCheck(true); }
|
||||
port_tchk port_tchk value ')'
|
||||
// Sdf skew clk/ref are reversed from liberty.
|
||||
|
|
@ -258,15 +262,23 @@ tchk_def:
|
|||
}
|
||||
;
|
||||
|
||||
port_instance:
|
||||
port:
|
||||
ID
|
||||
| PATH
|
||||
{ $$ = sta::sdf_reader->unescaped($1); }
|
||||
| ID '[' DNUMBER ']'
|
||||
{ $$ = sta::stringPrint("%s[%d]", sta::sdf_reader->unescaped($1), $3); }
|
||||
;
|
||||
|
||||
port_instance:
|
||||
port
|
||||
| path hchar port
|
||||
{ $$ = sta::sdf_reader->makePath($1, $3); }
|
||||
;
|
||||
|
||||
port_spec:
|
||||
ID
|
||||
port_instance
|
||||
{ $$=sta::sdf_reader->makePortSpec(sta::Transition::riseFall(),$1,NULL); }
|
||||
| '(' port_transition ID ')'
|
||||
| '(' port_transition port_instance ')'
|
||||
{ $$ = sta::sdf_reader->makePortSpec($2, $3, NULL); }
|
||||
;
|
||||
|
||||
|
|
@ -279,8 +291,8 @@ port_tchk:
|
|||
port_spec
|
||||
| '(' COND EXPR_ID_CLOSE
|
||||
{ $$ = sta::sdf_reader->makeCondPortSpec($3); }
|
||||
| '(' COND EXPR_OPEN port_transition ID ')' ')'
|
||||
{ $$ = sta::sdf_reader->makePortSpec($4, $5, $3); }
|
||||
| '(' COND EXPR_OPEN port_transition port_instance ')' ')'
|
||||
{ $$ = sta::sdf_reader->makePortSpec($4, $5, $3); sta::stringDelete($3); }
|
||||
;
|
||||
|
||||
value:
|
||||
|
|
@ -313,4 +325,12 @@ triple:
|
|||
}
|
||||
;
|
||||
|
||||
NUMBER:
|
||||
FNUMBER
|
||||
| DNUMBER
|
||||
{ $$ = static_cast<float>($1); }
|
||||
| '-' DNUMBER
|
||||
{ $$ = static_cast<float>(-$2); }
|
||||
;
|
||||
|
||||
%%
|
||||
|
|
|
|||
291
sdf/SdfReader.cc
291
sdf/SdfReader.cc
|
|
@ -20,6 +20,7 @@
|
|||
#include <ctype.h>
|
||||
|
||||
#include "Error.hh"
|
||||
#include "Debug.hh"
|
||||
#include "Report.hh"
|
||||
#include "MinMax.hh"
|
||||
#include "TimingArc.hh"
|
||||
|
|
@ -33,6 +34,7 @@
|
|||
|
||||
extern int
|
||||
SdfParse_parse();
|
||||
extern int SdfParse_debug;
|
||||
|
||||
namespace sta {
|
||||
|
||||
|
|
@ -55,13 +57,8 @@ class SdfPortSpec
|
|||
public:
|
||||
SdfPortSpec(Transition *tr,
|
||||
const char *port,
|
||||
const char *cond = nullptr) :
|
||||
tr_(tr), port_(port), cond_(cond) {}
|
||||
~SdfPortSpec()
|
||||
{
|
||||
stringDelete(port_);
|
||||
stringDelete(cond_);
|
||||
}
|
||||
const char *cond);
|
||||
~SdfPortSpec();
|
||||
const char *port() const { return port_; }
|
||||
Transition *transition() const { return tr_; }
|
||||
const char *cond() const { return cond_; }
|
||||
|
|
@ -140,6 +137,7 @@ SdfReader::read()
|
|||
{
|
||||
// Use zlib to uncompress gzip'd files automagically.
|
||||
stream_ = gzopen(filename_, "rb");
|
||||
//::SdfParse_debug = 1;
|
||||
if (stream_) {
|
||||
// yyparse returns 0 on success.
|
||||
bool success = (::SdfParse_parse() == 0);
|
||||
|
|
@ -212,8 +210,6 @@ SdfReader::interconnect(const char *from_pin_name,
|
|||
sdfWarn(186, "pin %s not found.", to_pin_name);
|
||||
}
|
||||
}
|
||||
stringDelete(from_pin_name);
|
||||
stringDelete(to_pin_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -238,7 +234,6 @@ SdfReader::port(const char *to_pin_name,
|
|||
}
|
||||
}
|
||||
}
|
||||
stringDelete(to_pin_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -314,7 +309,6 @@ SdfReader::setInstance(const char *instance_name)
|
|||
cell_name_);
|
||||
}
|
||||
}
|
||||
stringDelete(instance_name);
|
||||
}
|
||||
else
|
||||
instance_ = nullptr;
|
||||
|
|
@ -345,12 +339,8 @@ SdfReader::iopath(SdfPortSpec *from_edge,
|
|||
if (instance_) {
|
||||
const char *from_port_name = from_edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *from_port = network_->findPort(cell, from_port_name);
|
||||
Port *to_port = network_->findPort(cell, to_port_name);
|
||||
if (from_port == nullptr)
|
||||
portNotFound(from_port_name);
|
||||
if (to_port == nullptr)
|
||||
portNotFound(to_port_name);
|
||||
Port *from_port = findPort(cell, from_port_name);
|
||||
Port *to_port = findPort(cell, to_port_name);
|
||||
if (from_port && to_port) {
|
||||
Pin *from_pin = network_->findPin(instance_, from_port_name);
|
||||
Pin *to_pin = network_->findPin(instance_, to_port_name);
|
||||
|
|
@ -410,17 +400,33 @@ SdfReader::iopath(SdfPortSpec *from_edge,
|
|||
}
|
||||
}
|
||||
deletePortSpec(from_edge);
|
||||
stringDelete(to_port_name);
|
||||
deleteTripleSeq(triples);
|
||||
if (cond)
|
||||
stringDelete(cond);
|
||||
stringDelete(cond);
|
||||
}
|
||||
|
||||
Port *
|
||||
SdfReader::findPort(const Cell *cell,
|
||||
const char *port_name)
|
||||
{
|
||||
Port *port = network_->findPort(cell, port_name);
|
||||
if (port == nullptr)
|
||||
sdfWarn(194, "instance %s port %s not found.",
|
||||
network_->pathName(instance_),
|
||||
port_name);
|
||||
return port;
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheck(TimingRole *role, SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge, SdfTriple *triple)
|
||||
{
|
||||
timingCheck1(role, data_edge, clk_edge, triple, true);
|
||||
const char *data_port_name = data_edge->port();
|
||||
const char *clk_port_name = clk_edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *data_port = findPort(cell, data_port_name);
|
||||
Port *clk_port = findPort(cell, clk_port_name);
|
||||
if (data_port && clk_port)
|
||||
timingCheck1(role, data_port, data_edge, clk_port, clk_edge, triple);
|
||||
deletePortSpec(data_edge);
|
||||
deletePortSpec(clk_edge);
|
||||
deleteTriple(triple);
|
||||
|
|
@ -428,64 +434,54 @@ SdfReader::timingCheck(TimingRole *role, SdfPortSpec *data_edge,
|
|||
|
||||
void
|
||||
SdfReader::timingCheck1(TimingRole *role,
|
||||
Port *data_port,
|
||||
SdfPortSpec *data_edge,
|
||||
Port *clk_port,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *triple,
|
||||
bool warn)
|
||||
SdfTriple *triple)
|
||||
{
|
||||
// Ignore non-incremental annotations in incremental only mode.
|
||||
if (!(is_incremental_only_ && !in_incremental_)
|
||||
&& instance_) {
|
||||
const char *data_port_name = data_edge->port();
|
||||
const char *clk_port_name = clk_edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *data_port = network_->findPort(cell, data_port_name);
|
||||
Port *clk_port = network_->findPort(cell, clk_port_name);
|
||||
if (data_port == nullptr && warn)
|
||||
portNotFound(data_port_name);
|
||||
if (clk_port == nullptr && warn)
|
||||
portNotFound(clk_port_name);
|
||||
if (data_port && clk_port) {
|
||||
Pin *data_pin = network_->findPin(instance_, data_port_name);
|
||||
Pin *clk_pin = network_->findPin(instance_, clk_port_name);
|
||||
if (data_pin && clk_pin) {
|
||||
// Hack: always use triple max value for check.
|
||||
float **values = triple->values();
|
||||
float *value_min = values[triple_min_index_];
|
||||
float *value_max = values[triple_max_index_];
|
||||
if (value_min && value_max) {
|
||||
switch (analysis_type_) {
|
||||
case AnalysisType::single:
|
||||
break;
|
||||
case AnalysisType::bc_wc:
|
||||
if (role->genericRole() == TimingRole::setup())
|
||||
*value_min = *value_max;
|
||||
else
|
||||
*value_max = *value_min;
|
||||
break;
|
||||
case AnalysisType::ocv:
|
||||
Pin *data_pin = network_->findPin(instance_, data_port);
|
||||
Pin *clk_pin = network_->findPin(instance_, clk_port);
|
||||
if (data_pin && clk_pin) {
|
||||
// Hack: always use triple max value for check.
|
||||
float **values = triple->values();
|
||||
float *value_min = values[triple_min_index_];
|
||||
float *value_max = values[triple_max_index_];
|
||||
if (value_min && value_max) {
|
||||
switch (analysis_type_) {
|
||||
case AnalysisType::single:
|
||||
break;
|
||||
case AnalysisType::bc_wc:
|
||||
if (role->genericRole() == TimingRole::setup())
|
||||
*value_min = *value_max;
|
||||
break;
|
||||
}
|
||||
else
|
||||
*value_max = *value_min;
|
||||
break;
|
||||
case AnalysisType::ocv:
|
||||
*value_min = *value_max;
|
||||
break;
|
||||
}
|
||||
bool matched = annotateCheckEdges(data_pin, data_edge,
|
||||
clk_pin, clk_edge, role,
|
||||
triple, false);
|
||||
// Liberty setup/hold checks on preset/clear pins can be translated
|
||||
// into recovery/removal checks, so be flexible about matching.
|
||||
if (!matched)
|
||||
matched = annotateCheckEdges(data_pin, data_edge,
|
||||
clk_pin, clk_edge, role,
|
||||
triple, true);
|
||||
if (!matched
|
||||
// Only warn when non-null values are present.
|
||||
&& triple->hasValue())
|
||||
sdfWarn(192, "cell %s %s -> %s %s check not found.",
|
||||
network_->cellName(instance_),
|
||||
data_port_name,
|
||||
clk_port_name,
|
||||
role->asString());
|
||||
}
|
||||
bool matched = annotateCheckEdges(data_pin, data_edge,
|
||||
clk_pin, clk_edge, role,
|
||||
triple, false);
|
||||
// Liberty setup/hold checks on preset/clear pins can be translated
|
||||
// into recovery/removal checks, so be flexible about matching.
|
||||
if (!matched)
|
||||
matched = annotateCheckEdges(data_pin, data_edge,
|
||||
clk_pin, clk_edge, role,
|
||||
triple, true);
|
||||
if (!matched
|
||||
// Only warn when non-null values are present.
|
||||
&& triple->hasValue())
|
||||
sdfWarn(192, "cell %s %s -> %s %s check not found.",
|
||||
network_->cellName(instance_),
|
||||
network_->name(data_port),
|
||||
network_->name(clk_port),
|
||||
role->asString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -545,10 +541,8 @@ SdfReader::timingCheckWidth(SdfPortSpec *edge,
|
|||
&& instance_) {
|
||||
const char *port_name = edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *port = network_->findPort(cell, port_name);
|
||||
if (port == nullptr)
|
||||
portNotFound(port_name);
|
||||
else {
|
||||
Port *port = findPort(cell, port_name);
|
||||
if (port) {
|
||||
Pin *pin = network_->findPin(instance_, port_name);
|
||||
if (pin) {
|
||||
const RiseFall *rf = edge->transition()->asRiseFall();
|
||||
|
|
@ -574,6 +568,49 @@ SdfReader::timingCheckWidth(SdfPortSpec *edge,
|
|||
deleteTriple(triple);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckSetupHold(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *setup_triple,
|
||||
SdfTriple *hold_triple)
|
||||
{
|
||||
timingCheckSetupHold1(data_edge, clk_edge, setup_triple, hold_triple,
|
||||
TimingRole::setup(), TimingRole::hold());
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckRecRem(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *rec_triple,
|
||||
SdfTriple *rem_triple)
|
||||
{
|
||||
timingCheckSetupHold1(data_edge, clk_edge, rec_triple, rem_triple,
|
||||
TimingRole::recovery(), TimingRole::removal());
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckSetupHold1(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *setup_triple,
|
||||
SdfTriple *hold_triple,
|
||||
TimingRole *setup_role,
|
||||
TimingRole *hold_role)
|
||||
{
|
||||
const char *data_port_name = data_edge->port();
|
||||
const char *clk_port_name = clk_edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *data_port = findPort(cell, data_port_name);
|
||||
Port *clk_port = findPort(cell, clk_port_name);
|
||||
if (data_port && clk_port) {
|
||||
timingCheck1(setup_role, data_port, data_edge, clk_port, clk_edge, setup_triple);
|
||||
timingCheck1(hold_role, data_port, data_edge, clk_port, clk_edge, hold_triple);
|
||||
}
|
||||
deletePortSpec(data_edge);
|
||||
deletePortSpec(clk_edge);
|
||||
deleteTriple(setup_triple);
|
||||
deleteTriple(hold_triple);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckPeriod(SdfPortSpec *edge,
|
||||
SdfTriple *triple)
|
||||
|
|
@ -583,10 +620,8 @@ SdfReader::timingCheckPeriod(SdfPortSpec *edge,
|
|||
&& instance_) {
|
||||
const char *port_name = edge->port();
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *port = network_->findPort(cell, port_name);
|
||||
if (port == nullptr)
|
||||
portNotFound(port_name);
|
||||
else {
|
||||
Port *port = findPort(cell, port_name);
|
||||
if (port) {
|
||||
// Edge specifier is ignored for period checks.
|
||||
Pin *pin = network_->findPin(instance_, port_name);
|
||||
if (pin) {
|
||||
|
|
@ -610,34 +645,6 @@ SdfReader::timingCheckPeriod(SdfPortSpec *edge,
|
|||
deleteTriple(triple);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckSetupHold(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *setup_triple,
|
||||
SdfTriple *hold_triple)
|
||||
{
|
||||
timingCheck1(TimingRole::setup(), data_edge, clk_edge, setup_triple, true);
|
||||
timingCheck1(TimingRole::hold(), data_edge, clk_edge, hold_triple, false);
|
||||
deletePortSpec(data_edge);
|
||||
deletePortSpec(clk_edge);
|
||||
deleteTriple(setup_triple);
|
||||
deleteTriple(hold_triple);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckRecRem(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *rec_triple,
|
||||
SdfTriple *rem_triple)
|
||||
{
|
||||
timingCheck1(TimingRole::recovery(), data_edge, clk_edge, rec_triple, true);
|
||||
timingCheck1(TimingRole::removal(), data_edge, clk_edge, rem_triple, false);
|
||||
deletePortSpec(data_edge);
|
||||
deletePortSpec(clk_edge);
|
||||
deleteTriple(rec_triple);
|
||||
deleteTriple(rem_triple);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::timingCheckNochange(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
|
|
@ -675,15 +682,12 @@ SdfReader::device(const char *to_port_name,
|
|||
if (!(is_incremental_only_ && !in_incremental_)
|
||||
&& instance_) {
|
||||
Cell *cell = network_->cell(instance_);
|
||||
Port *to_port = network_->findPort(cell, to_port_name);
|
||||
if (to_port == nullptr)
|
||||
portNotFound(to_port_name);
|
||||
else {
|
||||
Port *to_port = findPort(cell, to_port_name);
|
||||
if (to_port) {
|
||||
Pin *to_pin = network_->findPin(instance_, to_port_name);
|
||||
setDevicePinDelays(to_pin, triples);
|
||||
}
|
||||
}
|
||||
stringDelete(to_port_name);
|
||||
deleteTripleSeq(triples);
|
||||
}
|
||||
|
||||
|
|
@ -822,7 +826,7 @@ SdfReader::makePortSpec(Transition *tr,
|
|||
}
|
||||
|
||||
SdfPortSpec *
|
||||
SdfReader::makeCondPortSpec(char *cond_port)
|
||||
SdfReader::makeCondPortSpec(const char *cond_port)
|
||||
{
|
||||
// Search from end to find port name because condition may contain spaces.
|
||||
string cond_port1(cond_port);
|
||||
|
|
@ -834,12 +838,13 @@ SdfReader::makeCondPortSpec(char *cond_port)
|
|||
if (cond_end != cond_port1.npos) {
|
||||
string cond1 = cond_port1.substr(0, cond_end + 1);
|
||||
SdfPortSpec *port_spec = makePortSpec(Transition::riseFall(),
|
||||
stringCopy(port1.c_str()),
|
||||
stringCopy(cond1.c_str()));
|
||||
port1.c_str(),
|
||||
cond1.c_str());
|
||||
stringDelete(cond_port);
|
||||
return port_spec;
|
||||
}
|
||||
}
|
||||
stringDelete(cond_port);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
|
@ -916,14 +921,14 @@ SdfReader::unescaped(const char *token)
|
|||
char path_divider = network_->pathDivider();
|
||||
char *unescaped = makeTmpString(strlen(token) + 1);
|
||||
char *u = unescaped;
|
||||
for (const char *s = token; *s ; s++) {
|
||||
char ch = *s;
|
||||
size_t token_length = strlen(token);
|
||||
|
||||
for (size_t i = 0; i < token_length; i++) {
|
||||
char ch = token[i];
|
||||
if (ch == escape_) {
|
||||
char next_ch = s[1];
|
||||
|
||||
char next_ch = token[i + 1];
|
||||
if (next_ch == divider_) {
|
||||
// Escaped divider.
|
||||
// Escaped divider.
|
||||
// Translate sdf escape to network escape.
|
||||
*u++ = path_escape;
|
||||
// Translate sdf divider to network divider.
|
||||
|
|
@ -938,21 +943,32 @@ SdfReader::unescaped(const char *token)
|
|||
*u++ = next_ch;
|
||||
}
|
||||
else
|
||||
// Escaped non-divider/bracket character.
|
||||
*u++ = next_ch;
|
||||
s++;
|
||||
// Escaped non-divider character.
|
||||
*u++ = next_ch;
|
||||
i++;
|
||||
}
|
||||
else if (ch == divider_)
|
||||
// Translate sdf divider to network divider.
|
||||
*u++ = path_divider;
|
||||
else
|
||||
// Just the normal noises.
|
||||
*u++ = ch;
|
||||
}
|
||||
*u = '\0';
|
||||
debugPrint(debug_, "sdf_name", 1, "token %s -> %s", token, unescaped);
|
||||
stringDelete(token);
|
||||
return unescaped;
|
||||
}
|
||||
|
||||
// Translate sdf divider to network divider.
|
||||
char *
|
||||
SdfReader::makePath(const char *head,
|
||||
const char *tail)
|
||||
{
|
||||
char *path = stringPrintTmp("%s%c%s",
|
||||
head,
|
||||
network_->pathDivider(),
|
||||
tail);
|
||||
return path;
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::incrLine()
|
||||
{
|
||||
|
|
@ -989,14 +1005,6 @@ SdfReader::notSupported(const char *feature)
|
|||
sdfError(193, "%s not supported.", feature);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::portNotFound(const char *port_name)
|
||||
{
|
||||
sdfWarn(194, "instance %s port %s not found.",
|
||||
network_->pathName(instance_),
|
||||
port_name);
|
||||
}
|
||||
|
||||
void
|
||||
SdfReader::sdfWarn(int id,
|
||||
const char *fmt, ...)
|
||||
|
|
@ -1044,6 +1052,23 @@ SdfReader::findInstance(const char *name)
|
|||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
SdfPortSpec::SdfPortSpec(Transition *tr,
|
||||
const char *port,
|
||||
const char *cond) :
|
||||
tr_(tr),
|
||||
port_(stringCopy(port)),
|
||||
cond_(stringCopy(cond))
|
||||
{
|
||||
}
|
||||
|
||||
SdfPortSpec::~SdfPortSpec()
|
||||
{
|
||||
stringDelete(port_);
|
||||
stringDelete(cond_);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
SdfTriple::SdfTriple(float *min,
|
||||
float *typ,
|
||||
float *max)
|
||||
|
|
|
|||
|
|
@ -108,6 +108,12 @@ public:
|
|||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *rec_triple,
|
||||
SdfTriple *rem_triple);
|
||||
void timingCheckSetupHold1(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *setup_triple,
|
||||
SdfTriple *hold_triple,
|
||||
TimingRole *setup_role,
|
||||
TimingRole *hold_role);
|
||||
void timingCheckNochange(SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *before_triple,
|
||||
|
|
@ -129,8 +135,10 @@ public:
|
|||
SdfPortSpec *makePortSpec(Transition *tr,
|
||||
const char *port,
|
||||
const char *cond);
|
||||
SdfPortSpec *makeCondPortSpec(char *cond_port);
|
||||
const char *unescaped(const char *s);
|
||||
SdfPortSpec *makeCondPortSpec(const char *cond_port);
|
||||
const char *unescaped(const char *token);
|
||||
char *makePath(const char *head,
|
||||
const char *tail);
|
||||
// Parser state used to control lexer for COND handling.
|
||||
bool inTimingCheck() { return in_timing_check_; }
|
||||
void setInTimingCheck(bool in);
|
||||
|
|
@ -169,10 +177,11 @@ private:
|
|||
bool condMatch(const char *sdf_cond,
|
||||
const char *lib_cond);
|
||||
void timingCheck1(TimingRole *role,
|
||||
SdfPortSpec *data_edge,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *triple,
|
||||
bool warn);
|
||||
Port *data_port,
|
||||
SdfPortSpec *data_edge,
|
||||
Port *clk_port,
|
||||
SdfPortSpec *clk_edge,
|
||||
SdfTriple *triple);
|
||||
bool annotateCheckEdges(Pin *data_pin,
|
||||
SdfPortSpec *data_edge,
|
||||
Pin *clk_pin,
|
||||
|
|
@ -181,7 +190,6 @@ private:
|
|||
SdfTriple *triple,
|
||||
bool match_generic);
|
||||
void deletePortSpec(SdfPortSpec *edge);
|
||||
void portNotFound(const char *port_name);
|
||||
Pin *findPin(const char *name);
|
||||
Instance *findInstance(const char *name);
|
||||
void setEdgeDelays(Edge *edge,
|
||||
|
|
@ -189,6 +197,8 @@ private:
|
|||
const char *sdf_cmd);
|
||||
void setDevicePinDelays(Pin *to_pin,
|
||||
SdfTripleSeq *triples);
|
||||
Port *findPort(const Cell *cell,
|
||||
const char *port_name);
|
||||
|
||||
const char *filename_;
|
||||
const char *path_;
|
||||
|
|
|
|||
|
|
@ -792,23 +792,33 @@ char *
|
|||
SdfWriter::sdfPortName(const Pin *pin)
|
||||
{
|
||||
const char *name = network_->portName(pin);
|
||||
char *sdf_name = makeTmpString(strlen(name) * 2 + 1);
|
||||
const char *p = name;
|
||||
size_t name_length = strlen(name);
|
||||
char *sdf_name = makeTmpString(name_length * 2 + 1);
|
||||
char *s = sdf_name;
|
||||
while (*p) {
|
||||
char ch = *p;
|
||||
|
||||
constexpr char bus_brkt_left = '[';
|
||||
constexpr char bus_brkt_right = ']';
|
||||
size_t bus_index = name_length;
|
||||
if (name_length >= 4
|
||||
&& name[name_length - 1] == bus_brkt_right) {
|
||||
const char *left = strrchr(name, bus_brkt_left);
|
||||
if (left)
|
||||
bus_index = left - name;
|
||||
}
|
||||
for (size_t i = 0; i < name_length; i++) {
|
||||
char ch = name[i];
|
||||
if (ch == network_escape_) {
|
||||
// Copy escape and escaped char.
|
||||
*s++ = sdf_escape_;
|
||||
*s++ = *++p;
|
||||
*s++ = name[++i];
|
||||
}
|
||||
else {
|
||||
if (!(isalnum(ch) || ch == '_' || ch == '[' || ch == ']'))
|
||||
if (!(isalnum(ch) || ch == '_')
|
||||
&& !(i >= bus_index && (ch == bus_brkt_right || ch == bus_brkt_left)))
|
||||
// Insert escape.
|
||||
*s++ = sdf_escape_;
|
||||
*s++ = ch;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
*s = '\0';
|
||||
return sdf_name;
|
||||
|
|
|
|||
|
|
@ -209,7 +209,7 @@ makeTmpString(size_t length)
|
|||
size_t tmp_length = tmp_string_lengths_[tmp_string_next_];
|
||||
if (tmp_length < length) {
|
||||
// String isn't long enough. Make a new one.
|
||||
stringDelete(tmp_str);
|
||||
delete [] tmp_str;
|
||||
tmp_str = new char[length];
|
||||
tmp_strings_[tmp_string_next_] = tmp_str;
|
||||
tmp_string_lengths_[tmp_string_next_] = length;
|
||||
|
|
@ -218,6 +218,27 @@ makeTmpString(size_t length)
|
|||
return tmp_str;
|
||||
}
|
||||
|
||||
void
|
||||
stringDeleteCheck(const char *str)
|
||||
{
|
||||
if (isTmpString(str)) {
|
||||
printf("Critical error: stringDelete for tmp string.");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
isTmpString(const char *str)
|
||||
{
|
||||
if (tmp_strings_) {
|
||||
for (int i = 0; i < tmp_string_count_; i++) {
|
||||
if (str == tmp_strings_[i])
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ wire { return WIRE; }
|
|||
wor { return WOR; }
|
||||
|
||||
{ID_TOKEN}("."{ID_TOKEN})* {
|
||||
VerilogParse_lval.string = sta::stringCopy(sta::verilogToSta(VerilogLex_text));
|
||||
VerilogParse_lval.string = sta::stringCopy(VerilogLex_text);
|
||||
return ID;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -36,9 +36,6 @@ namespace sta {
|
|||
VerilogReader *verilog_reader;
|
||||
static const char *unconnected_net_name = reinterpret_cast<const char*>(1);
|
||||
|
||||
static const char *
|
||||
verilogBusBitName(const char *bus_name,
|
||||
int index);
|
||||
static const char *
|
||||
verilogBusBitNameTmp(const char *bus_name,
|
||||
int index);
|
||||
|
|
@ -253,28 +250,30 @@ VerilogReader::module(Cell *cell)
|
|||
}
|
||||
|
||||
void
|
||||
VerilogReader::makeModule(const char *name,
|
||||
VerilogReader::makeModule(const char *module_vname,
|
||||
VerilogNetSeq *ports,
|
||||
VerilogStmtSeq *stmts,
|
||||
int line)
|
||||
{
|
||||
Cell *cell = network_->findCell(library_, name);
|
||||
const char *module_name = moduleVerilogToSta(module_vname);
|
||||
Cell *cell = network_->findCell(library_, module_name);
|
||||
if (cell) {
|
||||
VerilogModule *module = module_map_[cell];
|
||||
delete module;
|
||||
module_map_.erase(cell);
|
||||
network_->deleteCell(cell);
|
||||
}
|
||||
VerilogModule *module = new VerilogModule(name, ports, stmts,
|
||||
VerilogModule *module = new VerilogModule(module_name, ports, stmts,
|
||||
filename_, line, this);
|
||||
cell = network_->makeCell(library_, name, false, filename_);
|
||||
cell = network_->makeCell(library_, module_name, false, filename_);
|
||||
module_map_[cell] = module;
|
||||
makeCellPorts(cell, module, ports);
|
||||
module_count_++;
|
||||
stringDelete(module_vname);
|
||||
}
|
||||
|
||||
void
|
||||
VerilogReader::makeModule(const char *name,
|
||||
VerilogReader::makeModule(const char *module_name,
|
||||
VerilogStmtSeq *port_dcls,
|
||||
VerilogStmtSeq *stmts,
|
||||
int line)
|
||||
|
|
@ -285,8 +284,7 @@ VerilogReader::makeModule(const char *name,
|
|||
if (dcl->isDeclaration()) {
|
||||
VerilogDcl *dcl1 = dynamic_cast<VerilogDcl*>(dcl);
|
||||
for (VerilogDclArg *arg : *dcl1->args()) {
|
||||
const char *port_name = stringCopy(arg->netName());
|
||||
VerilogNetNamed *port = new VerilogNetScalar(port_name);
|
||||
VerilogNetNamed *port = new VerilogNetScalar(arg->netName());
|
||||
ports->push_back(port);
|
||||
}
|
||||
// Add the port declarations to the statements.
|
||||
|
|
@ -294,7 +292,7 @@ VerilogReader::makeModule(const char *name,
|
|||
}
|
||||
}
|
||||
delete port_dcls;
|
||||
makeModule(name, ports, stmts, line);
|
||||
makeModule(module_name, ports, stmts, line);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
@ -456,10 +454,13 @@ VerilogReader::makeDclBus(PortDirection *dir,
|
|||
}
|
||||
|
||||
VerilogDclArg *
|
||||
VerilogReader::makeDclArg(const char *net_name)
|
||||
VerilogReader::makeDclArg(const char *net_vname)
|
||||
{
|
||||
dcl_arg_count_++;
|
||||
return new VerilogDclArg(net_name);
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogDclArg *dcl =new VerilogDclArg(net_name);
|
||||
stringDelete(net_vname);
|
||||
return dcl;
|
||||
}
|
||||
|
||||
VerilogDclArg *
|
||||
|
|
@ -470,14 +471,18 @@ VerilogReader::makeDclArg(VerilogAssign *assign)
|
|||
}
|
||||
|
||||
VerilogNetPartSelect *
|
||||
VerilogReader::makeNetPartSelect(const char *name,
|
||||
VerilogReader::makeNetPartSelect(const char *net_vname,
|
||||
int from_index,
|
||||
int to_index)
|
||||
{
|
||||
net_part_select_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_bus_names_ += strlen(name) + 1;
|
||||
return new VerilogNetPartSelect(name, from_index, to_index);
|
||||
net_bus_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPartSelect *select = new VerilogNetPartSelect(net_name, from_index,
|
||||
to_index);
|
||||
stringDelete(net_vname);
|
||||
return select;
|
||||
}
|
||||
|
||||
VerilogNetConstant *
|
||||
|
|
@ -488,22 +493,28 @@ VerilogReader::makeNetConstant(const char *constant)
|
|||
}
|
||||
|
||||
VerilogNetScalar *
|
||||
VerilogReader::makeNetScalar(const char *name)
|
||||
VerilogReader::makeNetScalar(const char *net_vname)
|
||||
{
|
||||
net_scalar_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_scalar_names_ += strlen(name) + 1;
|
||||
return new VerilogNetScalar(name);
|
||||
net_scalar_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetScalar *scalar = new VerilogNetScalar(net_name);
|
||||
stringDelete(net_vname);
|
||||
return scalar;
|
||||
}
|
||||
|
||||
VerilogNetBitSelect *
|
||||
VerilogReader::makeNetBitSelect(const char *name,
|
||||
VerilogReader::makeNetBitSelect(const char *net_vname,
|
||||
int index)
|
||||
{
|
||||
net_bit_select_count_++;
|
||||
if (report_stmt_stats_)
|
||||
net_bus_names_ += strlen(name) + 1;
|
||||
return new VerilogNetBitSelect(name, index);
|
||||
net_bus_names_ += strlen(net_vname) + 1;
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetBitSelect *select = new VerilogNetBitSelect(net_name, index);
|
||||
stringDelete(net_vname);
|
||||
return select;
|
||||
}
|
||||
|
||||
VerilogAssign *
|
||||
|
|
@ -516,11 +527,13 @@ VerilogReader::makeAssign(VerilogNet *lhs,
|
|||
}
|
||||
|
||||
VerilogInst *
|
||||
VerilogReader::makeModuleInst(const char *module_name,
|
||||
const char *inst_name,
|
||||
VerilogReader::makeModuleInst(const char *module_vname,
|
||||
const char *inst_vname,
|
||||
VerilogNetSeq *pins,
|
||||
const int line)
|
||||
{
|
||||
const char *module_name = moduleVerilogToSta(module_vname);
|
||||
const char *inst_name = instanceVerilogToSta(inst_vname);
|
||||
Cell *cell = network_->findAnyCell(module_name);
|
||||
LibertyCell *liberty_cell = nullptr;
|
||||
if (cell)
|
||||
|
|
@ -558,13 +571,14 @@ VerilogReader::makeModuleInst(const char *module_name,
|
|||
}
|
||||
VerilogInst *inst = new VerilogLibertyInst(liberty_cell, inst_name,
|
||||
net_names, line);
|
||||
stringDelete(module_name);
|
||||
delete pins;
|
||||
if (report_stmt_stats_) {
|
||||
inst_names_ += strlen(inst_name) + 1;
|
||||
inst_lib_count_++;
|
||||
inst_lib_net_arrays_ += port_count;
|
||||
}
|
||||
stringDelete(module_vname);
|
||||
stringDelete(inst_vname);
|
||||
return inst;
|
||||
}
|
||||
else {
|
||||
|
|
@ -574,6 +588,8 @@ VerilogReader::makeModuleInst(const char *module_name,
|
|||
inst_names_ += strlen(inst_name) + 1;
|
||||
inst_mod_count_++;
|
||||
}
|
||||
stringDelete(module_vname);
|
||||
stringDelete(inst_vname);
|
||||
return inst;
|
||||
}
|
||||
}
|
||||
|
|
@ -603,60 +619,79 @@ VerilogReader::hasScalarNamedPortRefs(LibertyCell *liberty_cell,
|
|||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefScalarNet(const char *port_name,
|
||||
const char *net_name)
|
||||
VerilogReader::makeNetNamedPortRefScalarNet(const char *port_vname,
|
||||
const char *net_vname)
|
||||
{
|
||||
net_port_ref_scalar_net_count_++;
|
||||
if (report_stmt_stats_) {
|
||||
if (net_name)
|
||||
net_scalar_names_ += strlen(net_name) + 1;
|
||||
port_names_ += strlen(port_name) + 1;
|
||||
if (net_vname)
|
||||
net_scalar_names_ += strlen(net_vname) + 1;
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
}
|
||||
return new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
const char *net_name = netVerilogToSta(net_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
stringDelete(port_vname);
|
||||
stringDelete(net_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefBitSelect(const char *port_name,
|
||||
const char *bus_name,
|
||||
VerilogReader::makeNetNamedPortRefBitSelect(const char *port_vname,
|
||||
const char *bus_vname,
|
||||
int index)
|
||||
{
|
||||
net_port_ref_scalar_net_count_++;
|
||||
const char *net_name = verilogBusBitName(bus_name, index);
|
||||
const char *bus_name = portVerilogToSta(bus_vname);
|
||||
const char *net_name = verilogBusBitNameTmp(bus_name, index);
|
||||
if (report_stmt_stats_) {
|
||||
net_scalar_names_ += strlen(net_name) + 1;
|
||||
port_names_ += strlen(port_name) + 1;
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
}
|
||||
stringDelete(bus_name);
|
||||
return new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalarNet(port_name, net_name);
|
||||
stringDelete(port_vname);
|
||||
stringDelete(bus_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefScalar(const char *port_name,
|
||||
VerilogReader::makeNetNamedPortRefScalar(const char *port_vname,
|
||||
VerilogNet *net)
|
||||
{
|
||||
net_port_ref_scalar_count_++;
|
||||
if (report_stmt_stats_)
|
||||
port_names_ += strlen(port_name) + 1;
|
||||
return new VerilogNetPortRefScalar(port_name, net);
|
||||
port_names_ += strlen(port_vname) + 1;
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefScalar(port_name, net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefBit(const char *port_name,
|
||||
VerilogReader::makeNetNamedPortRefBit(const char *port_vname,
|
||||
int index,
|
||||
VerilogNet *net)
|
||||
{
|
||||
net_port_ref_bit_count_++;
|
||||
return new VerilogNetPortRefBit(port_name, index, net);
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefBit(port_name, index, net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetPortRef *
|
||||
VerilogReader::makeNetNamedPortRefPart(const char *port_name,
|
||||
VerilogReader::makeNetNamedPortRefPart(const char *port_vname,
|
||||
int from_index,
|
||||
int to_index,
|
||||
VerilogNet *net)
|
||||
{
|
||||
net_port_ref_part_count_++;
|
||||
return new VerilogNetPortRefPart(port_name, from_index, to_index, net);
|
||||
const char *port_name = portVerilogToSta(port_vname);
|
||||
VerilogNetPortRef *ref = new VerilogNetPortRefPart(port_name, from_index,
|
||||
to_index, net);
|
||||
stringDelete(port_vname);
|
||||
return ref;
|
||||
}
|
||||
|
||||
VerilogNetConcat *
|
||||
|
|
@ -769,7 +804,7 @@ VerilogModule::VerilogModule(const char *name,
|
|||
int line,
|
||||
VerilogReader *reader) :
|
||||
VerilogStmt(line),
|
||||
name_(name),
|
||||
name_(stringCopy(name)),
|
||||
filename_(filename),
|
||||
ports_(ports),
|
||||
stmts_(stmts)
|
||||
|
|
@ -879,9 +914,9 @@ VerilogStmt::VerilogStmt(int line) :
|
|||
}
|
||||
|
||||
VerilogInst::VerilogInst(const char *inst_name,
|
||||
const int line) :
|
||||
const int line) :
|
||||
VerilogStmt(line),
|
||||
inst_name_(inst_name)
|
||||
inst_name_(stringCopy(inst_name))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -902,7 +937,7 @@ VerilogModuleInst::VerilogModuleInst(const char *module_name,
|
|||
VerilogNetSeq *pins,
|
||||
int line) :
|
||||
VerilogInst(inst_name, line),
|
||||
module_name_(module_name),
|
||||
module_name_(stringCopy(module_name)),
|
||||
pins_(pins)
|
||||
{
|
||||
}
|
||||
|
|
@ -1020,7 +1055,7 @@ VerilogDclBus::size() const
|
|||
}
|
||||
|
||||
VerilogDclArg::VerilogDclArg(const char *net_name) :
|
||||
net_name_(net_name),
|
||||
net_name_(stringCopy(net_name)),
|
||||
assign_(nullptr)
|
||||
{
|
||||
}
|
||||
|
|
@ -1156,13 +1191,6 @@ verilogBusBitNameTmp(const char *bus_name,
|
|||
return stringPrintTmp("%s[%d]", bus_name, index);
|
||||
}
|
||||
|
||||
static const char *
|
||||
verilogBusBitName(const char *bus_name,
|
||||
int index)
|
||||
{
|
||||
return stringPrint("%s[%d]", bus_name, index);
|
||||
}
|
||||
|
||||
class VerilogConstantNetNameIterator : public VerilogNetNameIterator
|
||||
{
|
||||
public:
|
||||
|
|
@ -1265,7 +1293,7 @@ VerilogNetConcatNameIterator::next()
|
|||
|
||||
VerilogNetNamed::VerilogNetNamed(const char *name) :
|
||||
VerilogNet(),
|
||||
name_(name)
|
||||
name_(stringCopy(name))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1277,6 +1305,7 @@ VerilogNetNamed::~VerilogNetNamed()
|
|||
void
|
||||
VerilogNetNamed::setName(const char *name)
|
||||
{
|
||||
stringDelete(name_);
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
|
|
@ -1554,11 +1583,10 @@ VerilogNetPortRef::VerilogNetPortRef(const char *name) :
|
|||
{
|
||||
}
|
||||
|
||||
VerilogNetPortRefScalarNet::
|
||||
VerilogNetPortRefScalarNet(const char *name,
|
||||
const char *net_name) :
|
||||
VerilogNetPortRefScalarNet::VerilogNetPortRefScalarNet(const char *name,
|
||||
const char *net_name) :
|
||||
VerilogNetPortRef(name),
|
||||
net_name_(net_name)
|
||||
net_name_(stringCopy(net_name))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue