diff --git a/.gitignore b/.gitignore index e5e79e9a..2013c841 100644 --- a/.gitignore +++ b/.gitignore @@ -6,9 +6,12 @@ TAGS .#* .~lock.*\.*# .DS_Store +.vscode +.idea Makefile gmon.out +cmake-build-debug build pvt diff --git a/include/sta/ConcreteLibrary.hh b/include/sta/ConcreteLibrary.hh index 5909b81e..bacd91a0 100644 --- a/include/sta/ConcreteLibrary.hh +++ b/include/sta/ConcreteLibrary.hh @@ -38,6 +38,7 @@ class LibertyCell; class LibertyPort; typedef Map ConcreteCellMap; +typedef Map AttributeMap; typedef Vector ConcretePortSeq; typedef Map ConcretePortMap; typedef ConcreteCellMap::ConstIterator ConcreteLibraryCellIterator; @@ -105,6 +106,9 @@ public: ConcreteCellPortBitIterator *portBitIterator() const; bool isLeaf() const { return is_leaf_; } void setIsLeaf(bool is_leaf); + void setAttribute(const string &key, + const string &value); + string getAttribute(const string &key) const; // Cell acts as port factory. ConcretePort *makePort(const char *name); @@ -158,6 +162,7 @@ protected: // Port bit count (expanded buses). int port_bit_count_; bool is_leaf_; + AttributeMap attribute_map_; private: friend class ConcreteLibrary; diff --git a/include/sta/ConcreteNetwork.hh b/include/sta/ConcreteNetwork.hh index 99728c9c..06528214 100644 --- a/include/sta/ConcreteNetwork.hh +++ b/include/sta/ConcreteNetwork.hh @@ -38,6 +38,7 @@ class ConcreteBindingTbl; class ConcreteLibertyLibraryIterator; typedef Vector ConcreteLibrarySeq; +typedef Map AttributeMap; typedef Map ConcreteLibraryMap; typedef ConcreteLibrarySeq::ConstIterator ConcreteLibraryIterator; typedef MapsetIsLeaf(is_leaf); } +void +ConcreteNetwork::setAttribute(Cell *cell, + const string &key, + const string &value) +{ + ConcreteCell *ccell = reinterpret_cast(cell); + ccell->setAttribute(key, value); +} + Library * ConcreteNetwork::library(const Cell *cell) const { @@ -597,6 +606,14 @@ ConcreteNetwork::filename(const Cell *cell) return ccell->filename(); } +string +ConcreteNetwork::getAttribute(const Cell *cell, + const string &key) const +{ + const ConcreteCell *ccell = reinterpret_cast(cell); + return ccell->getAttribute(key); +} + Port * ConcreteNetwork::findPort(const Cell *cell, const char *name) const @@ -921,6 +938,14 @@ ConcreteNetwork::id(const Instance *instance) const return inst->id(); } +string +ConcreteNetwork::getAttribute(const Instance *inst, + const string &key) const +{ + const ConcreteInstance *cinst = reinterpret_cast(inst); + return cinst->getAttribute(key); +} + Cell * ConcreteNetwork::cell(const Instance *instance) const { @@ -1325,6 +1350,15 @@ ConcreteNetwork::connect(Instance *inst, return connect(inst, reinterpret_cast(port), net); } +void +ConcreteNetwork::setAttribute(Instance *inst, + const string &key, + const string &value) +{ + ConcreteInstance *cinst = reinterpret_cast(inst); + cinst->setAttribute(key, value); +} + Pin * ConcreteNetwork::connect(Instance *inst, Port *port, @@ -1648,6 +1682,22 @@ ConcreteInstance::childIterator() const return new ConcreteInstanceChildIterator(children_); } +void +ConcreteInstance::setAttribute(const string &key, + const string &value) +{ + attribute_map_.insert(key, value); +} + +string +ConcreteInstance::getAttribute(const string &key) const +{ + if (attribute_map_.hasKey(key)) { + return attribute_map_.findKey(key); + } + return ""; +} + void ConcreteInstance::addChild(ConcreteInstance *child) { diff --git a/network/SdcNetwork.cc b/network/SdcNetwork.cc index e5eb36bb..0973ed0c 100644 --- a/network/SdcNetwork.cc +++ b/network/SdcNetwork.cc @@ -122,6 +122,13 @@ NetworkNameAdapter::id(const Cell *cell) const return network_->id(cell); } +string +NetworkNameAdapter::getAttribute(const Cell *cell, + const string &key) const +{ + return network_->getAttribute(cell, key); +} + Library * NetworkNameAdapter::library(const Cell *cell) const { @@ -327,6 +334,13 @@ NetworkNameAdapter::cell(const Instance *instance) const return network_->cell(instance); } +string +NetworkNameAdapter::getAttribute(const Instance *inst, + const string &key) const +{ + return network_->getAttribute(inst, key); +} + Instance * NetworkNameAdapter::parent(const Instance *instance) const { diff --git a/tcl/StaTcl.i b/tcl/StaTcl.i index 39d4ec55..4eef9c66 100644 --- a/tcl/StaTcl.i +++ b/tcl/StaTcl.i @@ -4180,11 +4180,13 @@ void finish() { delete self; } } // LibertyLibraryIterator methods %extend Cell { +const char *name() { return cmdNetwork()->name(self); } Library *library() { return cmdNetwork()->library(self); } LibertyCell *liberty_cell() { return cmdNetwork()->libertyCell(self); } bool is_leaf() { return cmdNetwork()->isLeaf(self); } CellPortIterator * port_iterator() { return cmdNetwork()->portIterator(self); } +string get_attribute(const char *key) { return cmdNetwork()->getAttribute(self, key); } Port * find_port(const char *name) @@ -4409,6 +4411,7 @@ find_pin(const char *name) { return cmdLinkedNetwork()->findPin(self, name); } +string get_attribute(const char *key) { return cmdNetwork()->getAttribute(self, key); } } // Instance methods %extend InstanceChildIterator { diff --git a/test/attribute_parsing.ok b/test/attribute_parsing.ok new file mode 100644 index 00000000..96fae92c --- /dev/null +++ b/test/attribute_parsing.ok @@ -0,0 +1,2 @@ +top_instance:"counter" attribute "src" = synthesis/tests/counter.v:16.1-32.10 +instance: _1415_ attribute "src" = synthesis/tests/counter.v:22.3-28.6 diff --git a/test/attribute_parsing.tcl b/test/attribute_parsing.tcl new file mode 100644 index 00000000..e771c6d2 --- /dev/null +++ b/test/attribute_parsing.tcl @@ -0,0 +1,14 @@ +read_liberty ../examples/sky130hd_tt.lib +read_verilog attribute_parsing.v +link_design counter +create_clock -name clk [get_ports clk] -period 50 + +set instance [sta::top_instance] +set cell [$instance cell] +set cell_name [$cell name] +set src_location [$cell get_attribute "src"] +puts "top_instance:\"$cell_name\" attribute \"src\" = $src_location" + +set instance_name "_1415_" +set instance_src_location [[sta::find_instance $instance_name] get_attribute "src"] +puts "instance: $instance_name attribute \"src\" = $instance_src_location" \ No newline at end of file diff --git a/test/attribute_parsing.v b/test/attribute_parsing.v new file mode 100644 index 00000000..bb353e19 --- /dev/null +++ b/test/attribute_parsing.v @@ -0,0 +1,21 @@ +/* Generated by Yosys 0.8+ */ + +(* hdlname = "\\counter" *) +(* top = 1 *) +(* src = "synthesis/tests/counter.v:16.1-32.10" *) +module counter(clk, reset, in, out); + (* src = "synthesis/tests/counter.v:17.14-17.17" *) + input clk; + (* src = "synthesis/tests/counter.v:19.18-19.21" *) + output out; + (* src = "synthesis/tests/counter.v:18.14-18.19" *) + input reset; + input in; + (* src = "synthesis/tests/counter.v:22.3-28.6" *) + sky130_fd_sc_hd__dfrtp_1 _1415_ ( + .CLK(clk), + .D(in), + .Q(out), + .RESET_B(reset) + ); +endmodule diff --git a/test/regression_vars.tcl b/test/regression_vars.tcl index 8509e04a..f6a9ad8c 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -122,6 +122,7 @@ record_example_tests { } record_sta_tests { + attribute_parsing } define_test_group fast [group_tests all] diff --git a/verilog/VerilogLex.ll b/verilog/VerilogLex.ll index 42880540..60dd6109 100644 --- a/verilog/VerilogLex.ll +++ b/verilog/VerilogLex.ll @@ -41,7 +41,6 @@ verilogFlushBuffer() %option never-interactive %x COMMENT -%x ATTRIBUTE %x QSTRING SIGN "+"|"-" @@ -77,21 +76,6 @@ ID_TOKEN {ID_ESCAPED_TOKEN}|{ID_ALPHA_TOKEN} } } -"(*" { BEGIN ATTRIBUTE; } -{ -. - -{EOL} { sta::verilog_reader->incrLine(); } - -"*)" { BEGIN INITIAL; } - -<> { - VerilogParse_error("unterminated attribute"); - BEGIN(INITIAL); - yyterminate(); - } -} - {SIGN}?{UNSIGNED_NUMBER}?"'"[bB][01_xz]+ { VerilogParse_lval.constant = sta::stringCopy(VerilogLex_text); return CONSTANT; @@ -121,6 +105,8 @@ ID_TOKEN {ID_ESCAPED_TOKEN}|{ID_ALPHA_TOKEN} return ((int) VerilogLex_text[0]); } +"(*" { return ATTRIBUTE_OPEN; } +"*)" { return ATTRIBUTE_CLOSED; } assign { return ASSIGN; } endmodule { return ENDMODULE; } inout { return INOUT; } diff --git a/verilog/VerilogParse.yy b/verilog/VerilogParse.yy index b12f3cef..e70b74e8 100644 --- a/verilog/VerilogParse.yy +++ b/verilog/VerilogParse.yy @@ -17,6 +17,8 @@ // along with this program. If not, see . #include +#include +#include #include "PortDirection.hh" #include "verilog/VerilogReaderPvt.hh" @@ -33,6 +35,7 @@ int VerilogLex_lex(); int ival; const char *string; const char *constant; + const char *attribute_spec_value; sta::VerilogModule *module; sta::VerilogStmt *stmt; sta::VerilogStmtSeq *stmt_seq; @@ -44,10 +47,15 @@ int VerilogLex_lex(); sta::VerilogNet *net; sta::VerilogNetBitSelect *net_bit; sta::VerilogNetSeq *nets; + sta::VerilogAttributeEntry *attribute_entry; + sta::VerilogAttributeEntrySeq *attribute_seq; + sta::VerilogAttributeStmt *attribute_stmt; + sta::VerilogAttributeStmtSeq *attribute_stmt_seq; } %token INT CONSTANT ID STRING MODULE ENDMODULE ASSIGN PARAMETER DEFPARAM %token WIRE WAND WOR TRI INPUT OUTPUT INOUT SUPPLY1 SUPPLY0 REG +%token ATTRIBUTE_OPEN ATTRIBUTE_CLOSED %left '-' '+' %left '*' '/' @@ -55,8 +63,10 @@ int VerilogLex_lex(); %type ID STRING %type WIRE WAND WOR TRI INPUT OUTPUT INOUT SUPPLY1 SUPPLY0 +%type ATTRIBUTE_OPEN ATTRIBUTE_CLOSED %type INT parameter_exprs parameter_expr module_begin %type CONSTANT +%type attr_spec_value %type dcl_type port_dcl_type %type stmt declaration instance parameter parameter_dcls parameter_dcl %type defparam param_values param_value port_dcl @@ -69,6 +79,10 @@ int VerilogLex_lex(); %type inst_named_pin net_named net_expr_concat %type port_list port_refs inst_ordered_pins %type inst_named_pins net_exprs inst_pins +%type attr_spec +%type attr_specs +%type attribute_instance +%type attribute_instance_seq %start file @@ -92,14 +106,14 @@ module_begin: ; module: - module_begin ID ';' stmts ENDMODULE - { sta::verilog_reader->makeModule($2, new sta::VerilogNetSeq,$4,$1);} -| module_begin ID '(' ')' ';' stmts ENDMODULE - { sta::verilog_reader->makeModule($2, new sta::VerilogNetSeq,$6,$1);} -| module_begin ID '(' port_list ')' ';' stmts ENDMODULE - { sta::verilog_reader->makeModule($2, $4, $7, $1); } -| module_begin ID '(' port_dcls ')' ';' stmts ENDMODULE - { sta::verilog_reader->makeModule($2, $4, $7, $1); } + attribute_instance_seq module_begin ID ';' stmts ENDMODULE + { sta::verilog_reader->makeModule($3, new sta::VerilogNetSeq, $5, $1, $2);} +| attribute_instance_seq module_begin ID '(' ')' ';' stmts ENDMODULE + { sta::verilog_reader->makeModule($3, new sta::VerilogNetSeq, $7, $1, $2);} +| attribute_instance_seq module_begin ID '(' port_list ')' ';' stmts ENDMODULE + { sta::verilog_reader->makeModule($3, $5, $8, $1, $2); } +| attribute_instance_seq module_begin ID '(' port_dcls ')' ';' stmts ENDMODULE + { sta::verilog_reader->makeModule($3, $5, $8, $1, $2); } ; port_list: @@ -157,11 +171,12 @@ port_dcls: ; port_dcl: - port_dcl_type { $$ = sta::verilog_reader->line(); } dcl_arg - { $$ = sta::verilog_reader->makeDcl($1, $3, $2); } -| port_dcl_type { $$ = sta::verilog_reader->line(); } - '[' INT ':' INT ']' dcl_arg - { $$ = sta::verilog_reader->makeDclBus($1, $4, $6, $8, $2); } + attribute_instance_seq port_dcl_type + { $$ = sta::verilog_reader->line(); } dcl_arg + { $$ = sta::verilog_reader->makeDcl($2, $4, $1, $3); } +| attribute_instance_seq port_dcl_type + { $$ = sta::verilog_reader->line(); } '[' INT ':' INT ']' dcl_arg + { $$ = sta::verilog_reader->makeDclBus($2, $5, $7, $9, $1, $3); } ; port_dcl_type: @@ -282,11 +297,11 @@ param_value: ; declaration: - dcl_type { $$ = sta::verilog_reader->line(); } dcl_args ';' - { $$ = sta::verilog_reader->makeDcl($1, $3, $2); } -| dcl_type { $$ = sta::verilog_reader->line(); } + attribute_instance_seq dcl_type { $$ = sta::verilog_reader->line(); } dcl_args ';' + { $$ = sta::verilog_reader->makeDcl($2, $4, $1, $3); } +| attribute_instance_seq dcl_type { $$ = sta::verilog_reader->line(); } '[' INT ':' INT ']' dcl_args ';' - { $$ = sta::verilog_reader->makeDclBus($1, $4, $6, $8, $2); } + { $$ = sta::verilog_reader->makeDclBus($2, $5, $7, $9, $1,$3); } ; dcl_type: @@ -344,11 +359,11 @@ net_assign_lhs: ; instance: - ID { $$ = sta::verilog_reader->line(); } ID '(' inst_pins ')' ';' - { $$ = sta::verilog_reader->makeModuleInst($1, $3, $5, $2); } -| ID { $$ = sta::verilog_reader->line(); } parameter_values + attribute_instance_seq ID { $$ = sta::verilog_reader->line(); } ID '(' inst_pins ')' ';' + { $$ = sta::verilog_reader->makeModuleInst($2, $4, $6, $1, $3); } +| attribute_instance_seq ID { $$ = sta::verilog_reader->line(); } parameter_values ID '(' inst_pins ')' ';' - { $$ = sta::verilog_reader->makeModuleInst($1, $4, $6, $2); } + { $$ = sta::verilog_reader->makeModuleInst($2, $5, $7, $1, $3); } ; parameter_values: @@ -467,4 +482,41 @@ net_expr: | net_expr_concat ; +attribute_instance_seq: + // empty + { $$ = new sta::VerilogAttributeStmtSeq; } +| attribute_instance_seq attribute_instance + { if ($2) $1->push_back($2); } + ; + +attribute_instance: + ATTRIBUTE_OPEN attr_specs ATTRIBUTE_CLOSED + { $$ = new sta::VerilogAttributeStmt($2); } + ; + +attr_specs: + attr_spec + { $$ = new sta::VerilogAttributeEntrySeq; + $$->push_back($1); + } +| attr_spec ',' attr_spec + { $$->push_back($3); } + ; + +attr_spec: + ID + { $$ = new sta::VerilogAttributeEntry($1, "1"); } +| ID '=' attr_spec_value + { $$ = new sta::VerilogAttributeEntry($1, $3); } + ; + +attr_spec_value: + CONSTANT + { $$ = $1; } +| STRING + { $$ = $1; } +| INT + { $$ = sta::stringCopy(std::to_string($1).c_str()); } + ; + %% diff --git a/verilog/VerilogReader.cc b/verilog/VerilogReader.cc index fdfa1288..0b7c7fcc 100644 --- a/verilog/VerilogReader.cc +++ b/verilog/VerilogReader.cc @@ -26,6 +26,7 @@ #include "PortDirection.hh" #include "Network.hh" #include "VerilogNamespace.hh" +#include "StringUtil.hh" #include "verilog/VerilogReaderPvt.hh" extern int @@ -253,6 +254,7 @@ void VerilogReader::makeModule(const char *module_vname, VerilogNetSeq *ports, VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, int line) { string module_name = moduleVerilogToSta(module_vname); @@ -263,10 +265,17 @@ VerilogReader::makeModule(const char *module_vname, module_map_.erase(cell); network_->deleteCell(cell); } - VerilogModule *module = new VerilogModule(module_name.c_str(), - ports, stmts, - filename_, line, this); + + VerilogModule *module = new VerilogModule(module_name.c_str(), ports, stmts, + attribute_stmts, filename_, line, this); cell = network_->makeCell(library_, module_name.c_str(), false, filename_); + + for (VerilogAttributeStmt *stmt : *attribute_stmts) { + for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) { + network_->setAttribute(cell, entry->key(), entry->value()); + } + } + module_map_[cell] = module; makeCellPorts(cell, module, ports); module_count_++; @@ -277,6 +286,7 @@ void VerilogReader::makeModule(const char *module_name, VerilogStmtSeq *port_dcls, VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, int line) { VerilogNetSeq *ports = new VerilogNetSeq; @@ -293,7 +303,7 @@ VerilogReader::makeModule(const char *module_name, } } delete port_dcls; - makeModule(module_name, ports, stmts, line); + makeModule(module_name, ports, stmts, attribute_stmts, line); } void @@ -392,6 +402,7 @@ VerilogReader::checkModuleDcls(VerilogModule *module, VerilogDcl * VerilogReader::makeDcl(PortDirection *dir, VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, int line) { if (dir->isInternal()) { @@ -411,24 +422,25 @@ VerilogReader::makeDcl(PortDirection *dir, delete args; if (assign_args) { dcl_count_++; - return new VerilogDcl(dir, assign_args, line); + return new VerilogDcl(dir, assign_args, attribute_stmts, line); } else return nullptr; } else { dcl_count_++; - return new VerilogDcl(dir, args, line); + return new VerilogDcl(dir, args, attribute_stmts, line); } } VerilogDcl * VerilogReader::makeDcl(PortDirection *dir, VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, int line) { dcl_count_++; - return new VerilogDcl(dir, arg, line); + return new VerilogDcl(dir, arg, attribute_stmts, line); } VerilogDclBus * @@ -436,10 +448,12 @@ VerilogReader::makeDclBus(PortDirection *dir, int from_index, int to_index, VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, int line) { dcl_bus_count_++; - return new VerilogDclBus(dir, from_index, to_index, arg, line); + return new VerilogDclBus(dir, from_index, to_index, arg, attribute_stmts, + line); } VerilogDclBus * @@ -447,10 +461,12 @@ VerilogReader::makeDclBus(PortDirection *dir, int from_index, int to_index, VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, int line) { dcl_bus_count_++; - return new VerilogDclBus(dir, from_index, to_index, args, line); + return new VerilogDclBus(dir, from_index, to_index, args, attribute_stmts, + line); } VerilogDclArg * @@ -529,9 +545,10 @@ VerilogReader::makeAssign(VerilogNet *lhs, VerilogInst * VerilogReader::makeModuleInst(const char *module_vname, - const char *inst_vname, - VerilogNetSeq *pins, - const int line) + const char *inst_vname, + VerilogNetSeq *pins, + VerilogAttributeStmtSeq* attribute_stmts, + const int line) { string module_name = moduleVerilogToSta(module_vname); string inst_name = instanceVerilogToSta(inst_vname); @@ -571,7 +588,7 @@ VerilogReader::makeModuleInst(const char *module_vname, net_port_ref_scalar_net_count_--; } VerilogInst *inst = new VerilogLibertyInst(liberty_cell, inst_name.c_str(), - net_names, line); + net_names, attribute_stmts, line); delete pins; if (report_stmt_stats_) { inst_names_ += inst_name.size() + 1; @@ -585,7 +602,9 @@ VerilogReader::makeModuleInst(const char *module_vname, else { VerilogInst *inst = new VerilogModuleInst(module_name.c_str(), inst_name.c_str(), - pins, line); + pins, + attribute_stmts, + line); if (report_stmt_stats_) { inst_module_names_ += module_name.size() + 1; inst_names_ += inst_name.size() + 1; @@ -817,16 +836,18 @@ VerilogReader::netVerilogName(const char *net_name) //////////////////////////////////////////////////////////////// VerilogModule::VerilogModule(const char *name, - VerilogNetSeq *ports, - VerilogStmtSeq *stmts, - const char *filename, - int line, - VerilogReader *reader) : + VerilogNetSeq *ports, + VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, + const char *filename, + int line, + VerilogReader *reader) : VerilogStmt(line), name_(stringCopy(name)), filename_(filename), ports_(ports), - stmts_(stmts) + stmts_(stmts), + attribute_stmts_(attribute_stmts) { parseStmts(reader); } @@ -837,6 +858,8 @@ VerilogModule::~VerilogModule() delete ports_; stmts_->deleteContents(); delete stmts_; + attribute_stmts_->deleteContents(); + delete attribute_stmts_; stringDelete(name_); } @@ -936,15 +959,19 @@ VerilogStmt::VerilogStmt(int line) : } VerilogInst::VerilogInst(const char *inst_name, + VerilogAttributeStmtSeq* attribute_stmts, const int line) : VerilogStmt(line), - inst_name_(stringCopy(inst_name)) + inst_name_(stringCopy(inst_name)), + attribute_stmts_(attribute_stmts) { } VerilogInst::~VerilogInst() { stringDelete(inst_name_); + attribute_stmts_->deleteContents(); + delete attribute_stmts_; } void @@ -955,10 +982,11 @@ VerilogInst::setInstanceName(const char *inst_name) } VerilogModuleInst::VerilogModuleInst(const char *module_name, - const char *inst_name, - VerilogNetSeq *pins, - int line) : - VerilogInst(inst_name, line), + const char *inst_name, + VerilogNetSeq *pins, + VerilogAttributeStmtSeq* attribute_stmts, + int line) : + VerilogInst(inst_name, attribute_stmts, line), module_name_(stringCopy(module_name)), pins_(pins) { @@ -990,10 +1018,11 @@ VerilogModuleInst::namedPins() } VerilogLibertyInst::VerilogLibertyInst(LibertyCell *cell, - const char *inst_name, - const char **net_names, - const int line) : - VerilogInst(inst_name, line), + const char *inst_name, + const char **net_names, + VerilogAttributeStmtSeq* attribute_stmts, + const int line) : + VerilogInst(inst_name, attribute_stmts, line), cell_(cell), net_names_(net_names) { @@ -1012,28 +1041,34 @@ VerilogLibertyInst::~VerilogLibertyInst() } VerilogDcl::VerilogDcl(PortDirection *dir, - VerilogDclArgSeq *args, - int line) : + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, + int line) : VerilogStmt(line), dir_(dir), - args_(args) + args_(args), + attribute_stmts_(attribute_stmts) { } VerilogDcl::VerilogDcl(PortDirection *dir, - VerilogDclArg *arg, - int line) : + VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, + int line) : VerilogStmt(line), dir_(dir) { args_ = new VerilogDclArgSeq; args_->push_back(arg); + attribute_stmts_ = attribute_stmts; } VerilogDcl::~VerilogDcl() { args_->deleteContents(); delete args_; + attribute_stmts_->deleteContents(); + delete attribute_stmts_; } void @@ -1049,22 +1084,24 @@ VerilogDcl::portName() } VerilogDclBus::VerilogDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArgSeq *args, - int line) : - VerilogDcl(dir, args, line), + int from_index, + int to_index, + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, + int line) : + VerilogDcl(dir, args, attribute_stmts, line), from_index_(from_index), to_index_(to_index) { } VerilogDclBus::VerilogDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArg *arg, - int line) : - VerilogDcl(dir, arg, line), + int from_index, + int to_index, + VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, + int line) : + VerilogDcl(dir, arg, attribute_stmts, line), from_index_(from_index), to_index_(to_index) { @@ -1702,6 +1739,45 @@ VerilogNetPortRefPart::name() const return name_; } +VerilogAttributeEntry::VerilogAttributeEntry(std::string key, + std::string value) : + key_(key), + value_(value) +{ +} + + +std::string +VerilogAttributeEntry::key() +{ + return key_; +} + +std::string +VerilogAttributeEntry::value() +{ + return value_; +} + +VerilogAttributeStmt::VerilogAttributeStmt( + VerilogAttributeEntrySeq* attribute_sequence): + attribute_sequence_(attribute_sequence) +{ +} + +VerilogAttributeStmt::~VerilogAttributeStmt() +{ + attribute_sequence_->deleteContents(); + delete attribute_sequence_; +} + +VerilogAttributeEntrySeq* +VerilogAttributeStmt::attribute_sequence() +{ + return attribute_sequence_; +} + + //////////////////////////////////////////////////////////////// // // Link verilog network @@ -1859,6 +1935,13 @@ VerilogReader::makeModuleInstNetwork(VerilogModuleInst *mod_inst, cell = network_->cell(lib_cell); Instance *inst = network_->makeInstance(cell, mod_inst->instanceName(), parent); + VerilogAttributeStmtSeq *attribute_stmts = mod_inst->attribute_stmts(); + for (VerilogAttributeStmt *stmt : *attribute_stmts) { + for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) { + network_->setAttribute(inst, entry->key(), entry->value()); + } + } + if (lib_cell) { // Make all pins so timing arcs are built. LibertyCellPortBitIterator port_iter(lib_cell); @@ -2044,6 +2127,12 @@ VerilogReader::makeLibertyInst(VerilogLibertyInst *lib_inst, Cell *cell = reinterpret_cast(lib_cell); Instance *inst = network_->makeInstance(cell, lib_inst->instanceName(), parent); + VerilogAttributeStmtSeq *attribute_stmts = lib_inst->attribute_stmts(); + for (VerilogAttributeStmt *stmt : *attribute_stmts) { + for (VerilogAttributeEntry *entry : *stmt->attribute_sequence()) { + network_->setAttribute(inst, entry->key(), entry->value()); + } + } const char **net_names = lib_inst->netNames(); LibertyCellPortBitIterator port_iter(lib_cell); while (port_iter.hasNext()) { @@ -2205,7 +2294,7 @@ VerilogBindingTbl::find(const char *name, NetworkReader *network) } void -VerilogBindingTbl::bind(const char *name, +VerilogBindingTbl::bind(const char *name, Net *net) { map_[name] = net; diff --git a/verilog/VerilogReaderPvt.hh b/verilog/VerilogReaderPvt.hh index eb6afa09..ea9f857c 100644 --- a/verilog/VerilogReaderPvt.hh +++ b/verilog/VerilogReaderPvt.hh @@ -37,6 +37,8 @@ using std::set; class Debug; class Report; +class VerilogAttributeEntry; +class VerilogAttributeStmt; class VerilogReader; class VerilogStmt; class VerilogNet; @@ -60,6 +62,8 @@ class VerilogNetPortRef; class VerilogError; class LibertyCell; +typedef Vector VerilogAttributeStmtSeq; +typedef Vector VerilogAttributeEntrySeq; typedef Vector VerilogNetSeq; typedef Vector VerilogStmtSeq; typedef Map VerilogDclMap; @@ -87,35 +91,42 @@ public: int &result, size_t max_size); void makeModule(const char *module_name, - VerilogNetSeq *ports, - VerilogStmtSeq *stmts, - int line); + VerilogNetSeq *ports, + VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, + int line); void makeModule(const char *module_name, - VerilogStmtSeq *port_dcls, - VerilogStmtSeq *stmts, - int line); + VerilogStmtSeq *port_dcls, + VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, + int line); VerilogDcl *makeDcl(PortDirection *dir, - VerilogDclArgSeq *args, - int line); + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, + int line); VerilogDcl *makeDcl(PortDirection *dir, - VerilogDclArg *arg, - int line); + VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, + int line); VerilogDclArg *makeDclArg(const char *net_name); VerilogDclArg*makeDclArg(VerilogAssign *assign); VerilogDclBus *makeDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArg *arg, - int line); + int from_index, + int to_index, + VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, + int line); VerilogDclBus *makeDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArgSeq *args, - int line); + int from_index, + int to_index, + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, + int line); VerilogInst *makeModuleInst(const char *module_name, - const char *inst_name, - VerilogNetSeq *pins, - const int line); + const char *inst_name, + VerilogNetSeq *pins, + VerilogAttributeStmtSeq* attribute_stmts, + const int line); VerilogAssign *makeAssign(VerilogNet *lhs, VerilogNet *rhs, int line); @@ -326,14 +337,16 @@ class VerilogModule : public VerilogStmt { public: VerilogModule(const char *name, - VerilogNetSeq *ports, - VerilogStmtSeq *stmts, - const char *filename, - int line, - VerilogReader *reader); + VerilogNetSeq *ports, + VerilogStmtSeq *stmts, + VerilogAttributeStmtSeq *attribute_stmts, + const char *filename, + int line, + VerilogReader *reader); virtual ~VerilogModule(); const char *name() { return name_; } const char *filename() { return filename_; } + VerilogAttributeStmtSeq *attribute_stmts() { return attribute_stmts_; } VerilogNetSeq *ports() { return ports_; } VerilogDcl *declaration(const char *net_name); VerilogStmtSeq *stmts() { return stmts_; } @@ -352,17 +365,20 @@ private: VerilogNetSeq *ports_; VerilogStmtSeq *stmts_; VerilogDclMap dcl_map_; + VerilogAttributeStmtSeq *attribute_stmts_; }; class VerilogDcl : public VerilogStmt { public: VerilogDcl(PortDirection *dir, - VerilogDclArgSeq *args, - int line); + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq *attribute_stmts, + int line); VerilogDcl(PortDirection *dir, - VerilogDclArg *arg, - int line); + VerilogDclArg *arg, + VerilogAttributeStmtSeq *attribute_stmts, + int line); virtual ~VerilogDcl(); const char *portName(); virtual bool isBus() const { return false; } @@ -376,21 +392,24 @@ public: private: PortDirection *dir_; VerilogDclArgSeq *args_; + VerilogAttributeStmtSeq *attribute_stmts_; }; class VerilogDclBus : public VerilogDcl { public: VerilogDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArgSeq *args, - int line); + int from_index, + int to_index, + VerilogDclArgSeq *args, + VerilogAttributeStmtSeq* attribute_stmts, + int line); VerilogDclBus(PortDirection *dir, - int from_index, - int to_index, - VerilogDclArg *arg, - int line); + int from_index, + int to_index, + VerilogDclArg *arg, + VerilogAttributeStmtSeq* attribute_stmts, + int line); virtual bool isBus() const { return true; } int fromIndex() const { return from_index_; } int toIndex() const { return to_index_; } @@ -437,23 +456,27 @@ class VerilogInst : public VerilogStmt { public: VerilogInst(const char *inst_name, - const int line); + VerilogAttributeStmtSeq* attribute_stmts, + const int line); virtual ~VerilogInst(); virtual bool isInstance() const { return true; } const char *instanceName() const { return inst_name_; } + VerilogAttributeStmtSeq *attribute_stmts() const { return attribute_stmts_; } void setInstanceName(const char *inst_name); private: const char *inst_name_; + VerilogAttributeStmtSeq* attribute_stmts_; }; class VerilogModuleInst : public VerilogInst { public: VerilogModuleInst(const char *module_name, - const char *inst_name, - VerilogNetSeq *pins, - const int line); + const char *inst_name, + VerilogNetSeq *pins, + VerilogAttributeStmtSeq* attribute_stmts, + const int line); virtual ~VerilogModuleInst(); virtual bool isModuleInst() const { return true; } const char *moduleName() const { return module_name_; } @@ -473,9 +496,10 @@ class VerilogLibertyInst : public VerilogInst { public: VerilogLibertyInst(LibertyCell *cell, - const char *inst_name, - const char **net_names, - const int line); + const char *inst_name, + const char **net_names, + VerilogAttributeStmtSeq* attribute_stmts, + const int line); virtual ~VerilogLibertyInst(); virtual bool isLibertyInst() const { return true; } LibertyCell *cell() const { return cell_; } @@ -691,4 +715,29 @@ class VerilogNetNameIterator : public Iterator { }; +class VerilogAttributeStmt +{ +public: + VerilogAttributeStmt(VerilogAttributeEntrySeq *attribute_sequence); + VerilogAttributeEntrySeq *attribute_sequence(); + virtual ~VerilogAttributeStmt(); + +private: + VerilogAttributeEntrySeq *attribute_sequence_; +}; + +class VerilogAttributeEntry +{ +public: + VerilogAttributeEntry(std::string key, + std::string value); + virtual std::string key(); + virtual std::string value(); + virtual ~VerilogAttributeEntry() = default; + +private: + std::string key_; + std::string value_; +}; + } // namespace