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/CMakeLists.txt b/CMakeLists.txt index 5fe12ab8..6ab8e49f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,6 +30,8 @@ project(STA VERSION 2.5.0 option(USE_CUDD "Use CUDD BDD package") option(CUDD_DIR "CUDD BDD package directory") +option(USE_TCL_READLINE "Use TCL readliine package") +option(USE_SANITIZE "Compile with santize address enabled") # Turn on to debug compiler args. set(CMAKE_VERBOSE_MAKEFILE OFF) @@ -333,8 +335,6 @@ add_custom_command(OUTPUT ${STA_TCL_INIT} # Do not use REQUIRED because it also requires TK, which is not used by OpenSTA. find_package(TCL) -option(USE_TCL_READLINE "Use TCL readliine package") - set(TCL_READLINE 0) # check for tclReadline if (USE_TCL_READLINE) @@ -539,6 +539,12 @@ target_include_directories(OpenSTA # common to gcc/clang set(CXX_FLAGS -Wall -Wextra -pedantic -Wcast-qual -Wredundant-decls -Wformat-security) +if(USE_SANITIZE) + message(STATUS "Sanitize: ${USE_SANITIZE}") + set(CXX_FLAGS "${CXX_FLAGS};-fsanitize=address;-fno-omit-frame-pointer;-fno-common") + set(CMAKE_EXE_LINKER_FLAGS "-fsanitize=address") +endif() + target_compile_options(OpenSTA PRIVATE $<$:${CXX_FLAGS}> diff --git a/README.md b/README.md index 6d5b0dad..79405a52 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,7 @@ Use the following commands to checkout the git repository and build the OpenSTA library and excutable. ``` -git clone https://github.com/The-OpenROAD-Project/OpenSTA.git +git clone https://github.com/parallaxsw/OpenSTA.git cd OpenSTA mkdir build cd build diff --git a/dcalc/GraphDelayCalc.cc b/dcalc/GraphDelayCalc.cc index 87ccc66d..9d8f8435 100644 --- a/dcalc/GraphDelayCalc.cc +++ b/dcalc/GraphDelayCalc.cc @@ -1158,11 +1158,10 @@ GraphDelayCalc::loadCap(const Pin *drvr_pin, const DcalcAnalysisPt *dcalc_ap) const { const MinMax *min_max = dcalc_ap->constraintMinMax(); - float load_cap = 0.0; + float load_cap = min_max->initValue(); for (auto drvr_rf : RiseFall::range()) { float cap = loadCap(drvr_pin, drvr_rf, dcalc_ap); - if (min_max->compare(cap, load_cap)) - load_cap = cap; + load_cap = min_max->minMax(cap, load_cap); } arc_delay_calc_->finishDrvrPin(); return load_cap; 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..7c62a4f7 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 Map value2, Min value1 < value2. bool compare(float value1, float value2) const; @@ -74,12 +75,14 @@ private: MinMax(const char *name, int index, float init_value, + int init_value_int, bool (*compare)(float value1, float value2)); const char *name_; int index_; float init_value_; + int init_value_int_; bool (*compare_)(float value1, float value2); diff --git a/include/sta/Network.hh b/include/sta/Network.hh index 8a97dbc7..5f0f1e21 100644 --- a/include/sta/Network.hh +++ b/include/sta/Network.hh @@ -144,6 +144,9 @@ public: virtual Cell *cell(LibertyCell *cell) const = 0; // Filename may return null. virtual const char *filename(const Cell *cell) = 0; + // Attributes can be null + virtual string getAttribute(const Cell *cell, + const string &key) const = 0; // Name can be a simple, bundle, bus, or bus bit name. virtual Port *findPort(const Cell *cell, const char *name) const = 0; @@ -206,6 +209,8 @@ public: const PatternMatch *pattern) const; virtual InstanceSeq findInstancesHierMatching(const Instance *instance, const PatternMatch *pattern) const; + virtual string getAttribute(const Instance *inst, + const string &key) const = 0; // Hierarchical path name. virtual const char *pathName(const Instance *instance) const; bool pathNameLess(const Instance *inst1, @@ -544,6 +549,12 @@ public: const char *name) = 0; virtual void setIsLeaf(Cell *cell, bool is_leaf) = 0; + virtual void setAttribute(Cell *cell, + const string &key, + const string &value) = 0; + virtual void setAttribute(Instance *instance, + const string &key, + const string &value) = 0; virtual Port *makePort(Cell *cell, const char *name) = 0; virtual Port *makeBusPort(Cell *cell, diff --git a/include/sta/SdcNetwork.hh b/include/sta/SdcNetwork.hh index f2859f46..66c42026 100644 --- a/include/sta/SdcNetwork.hh +++ b/include/sta/SdcNetwork.hh @@ -45,6 +45,8 @@ public: const PatternMatch *pattern) const override; const char *name(const Cell *cell) const override; + string getAttribute(const Cell *cell, + const string &key) const override; ObjectId id(const Cell *cell) const override; Library *library(const Cell *cell) const override; LibertyCell *libertyCell(Cell *cell) const override; @@ -80,6 +82,8 @@ public: bool hasMembers(const Port *port) const override; ObjectId id(const Instance *instance) const override; + string getAttribute(const Instance *inst, + const string &key) const override; Instance *topInstance() const override; Cell *cell(const Instance *instance) const override; Instance *parent(const Instance *instance) const override; diff --git a/network/ConcreteLibrary.cc b/network/ConcreteLibrary.cc index 86627833..e6cceeef 100644 --- a/network/ConcreteLibrary.cc +++ b/network/ConcreteLibrary.cc @@ -268,6 +268,22 @@ ConcreteCell::setIsLeaf(bool is_leaf) is_leaf_ = is_leaf; } +void +ConcreteCell::setAttribute(const string &key, + const string &value) +{ + attribute_map_.insert(key, value); +} + +string +ConcreteCell::getAttribute(const string &key) const +{ + if (attribute_map_.hasKey(key)) { + return attribute_map_.findKey(key); + } + return ""; +} + ConcretePort * ConcreteCell::findPort(const char *name) const { diff --git a/network/ConcreteNetwork.cc b/network/ConcreteNetwork.cc index 24084ef5..c6c3cd00 100644 --- a/network/ConcreteNetwork.cc +++ b/network/ConcreteNetwork.cc @@ -557,6 +557,15 @@ ConcreteNetwork::setIsLeaf(Cell *cell, ccell->setIsLeaf(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/power/ReadVcdActivities.cc b/power/ReadVcdActivities.cc index 59a4c91a..396dab63 100644 --- a/power/ReadVcdActivities.cc +++ b/power/ReadVcdActivities.cc @@ -231,8 +231,7 @@ ReadVcdActivities::findVarActivity(const VcdValues &var_values, if (prev_value == '1') high_time += time_max - prev_time; duty = static_cast(high_time) / time_max; - activity = transition_count - / (time_max * vcd_.timeUnitScale() / clk_period_); + activity = transition_count / (time_max * vcd_.timeScale() / clk_period_); } void @@ -240,7 +239,7 @@ ReadVcdActivities::checkClkPeriod(const Pin *pin, double transition_count) { VcdTime time_max = vcd_.timeMax(); - double sim_period = time_max * vcd_.timeUnitScale() / (transition_count / 2.0); + double sim_period = time_max * vcd_.timeScale() / (transition_count / 2.0); ClockSet *clks = sdc_->findLeafPinClocks(pin); if (clks) { diff --git a/power/VcdReader.cc b/power/VcdReader.cc index b917f3e1..92fc981c 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -135,12 +135,14 @@ VcdReader::parseTimescale() vector tokens = readStmtTokens(); if (tokens.size() == 1) { size_t last; - vcd_->setTimeScale(std::stod(tokens[0], &last)); + double time_scale = std::stod(tokens[0], &last); setTimeUnit(tokens[0].substr(last)); + vcd_->setTimeScale(time_scale * vcd_->timeUnitScale()); } else if (tokens.size() == 2) { - vcd_->setTimeScale(std::stod(tokens[0])); setTimeUnit(tokens[1]); + double time_scale = std::stod(tokens[0]); + vcd_->setTimeScale(time_scale * vcd_->timeUnitScale()); } else report_->fileError(801, filename_, stmt_line_, "timescale syntax error."); diff --git a/search/Sta.cc b/search/Sta.cc index f6012128..f0c6500c 100644 --- a/search/Sta.cc +++ b/search/Sta.cc @@ -3705,7 +3705,7 @@ Sta::portExtCaps(const Port *port, bool fanout_exists = false; pin_cap = min_max->initValue(); wire_cap = min_max->initValue(); - fanout = min_max->initValue(); + fanout = min_max->initValueInt(); for (RiseFall *rf : RiseFall::range()) { float pin_cap1, wire_cap1; int fanout1; diff --git a/tcl/CmdUtil.tcl b/tcl/CmdUtil.tcl index 324b2ead..a265427d 100644 --- a/tcl/CmdUtil.tcl +++ b/tcl/CmdUtil.tcl @@ -140,26 +140,26 @@ proc set_cmd_units { args } { set_unit_values "distance" -distance "m" keys } -proc set_unit_values { unit key unit_name key_var } { +proc set_unit_values { unit key suffix key_var } { upvar 1 $key_var keys if { [info exists keys($key)] } { set value $keys($key) - if { [string equal -nocase $value $unit_name] } { - set_cmd_unit_scale $unit 1.0 - } else { - set prefix [string index $value 0] - set suffix [string range $value 1 end] - # unit includes "1" prefix - if { [string is digit $prefix] } { - set prefix [string index $value 1] - set suffix [string range $value 2 end] - } - if { [string equal -nocase $suffix $unit_name] } { - set scale [unit_prefix_scale $unit $prefix] - set_cmd_unit_scale $unit $scale + set suffix_length [string length $suffix] + set arg_suffix [string range $value end-[expr $suffix_length - 1] end] + if { [string match -nocase $arg_suffix $suffix] } { + set arg_prefix [string range $value 0 end-$suffix_length] + if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } { + #puts "$arg_prefix '$mult' '$prefix'" + if { $mult == "" } { + set mult 1 + } + set scale [unit_prefix_scale $unit $prefix ] + set_cmd_unit_scale $unit $scale } else { - sta_error 163 "unknown $unit unit '$suffix'." + sta_error 343 "unknown unit $unit prefix '${arg_prefix}'." } + } else { + sta_error 501 "incorrect unit suffix '$arg_suffix'." } if [info exists keys(-digits)] { set_cmd_unit_digits $unit $keys(-digits) diff --git a/tcl/Sdc.tcl b/tcl/Sdc.tcl index 4ce727b6..322d1e62 100644 --- a/tcl/Sdc.tcl +++ b/tcl/Sdc.tcl @@ -235,51 +235,44 @@ proc set_units { args } { check_unit "current" -current "A" keys check_unit "power" -power "W" keys check_unit "distance" -distance "m" keys - check_unit "power" -power "w" keys } -proc check_unit { unit key unit_name key_var } { +proc check_unit { unit key suffix key_var } { upvar 1 $key_var keys if { [info exists keys($key)] } { set value $keys($key) - if { [string equal -nocase $value $unit_name] } { - check_unit_scale $unit 1.0 - } else { - set prefix [string index $value 0] - set suffix [string range $value 1 end] - # unit includes "1" prefix - if { [string is digit $prefix] } { - set prefix [string index $value 1] - set suffix [string range $value 2 end] - } - if { [string equal -nocase $suffix $unit_name] } { - set scale [unit_prefix_scale $unit $prefix] - check_unit_scale $unit $scale + set suffix_length [string length $suffix] + set arg_suffix [string range $value end-[expr $suffix_length - 1] end] + if { [string match -nocase $arg_suffix $suffix] } { + set arg_prefix [string range $value 0 end-$suffix_length] + if { [regexp "^(10*)?(\[Mkmunpf\])?$" $arg_prefix ignore mult prefix] } { + #puts "$arg_prefix '$mult' '$prefix'" + if { $mult == "" } { + set mult 1 + } + set scale [unit_prefix_scale $unit $prefix ] + check_unit_scale $unit [expr $scale * $mult] } else { - sta_error 343 "unknown unit $unit '$suffix'." + sta_error 343 "unknown unit $unit prefix '${arg_prefix}'." } + } else { + sta_error 501 "incorrect unit suffix '$arg_suffix'." } } } proc unit_prefix_scale { unit prefix } { - if { [string equal $prefix "M"] } { - return 1E+6 - } elseif { [string equal $prefix "k"] } { - return 1E+3 - } elseif { [string equal $prefix "m"] } { - return 1E-3 - } elseif { [string equal $prefix "u"] } { - return 1E-6 - } elseif { [string equal $prefix "n"] } { - return 1E-9 - } elseif { [string equal $prefix "p"] } { - return 1E-12 - } elseif { [string equal $prefix "f"] } { - return 1E-15 - } else { - sta_error 344 "unknown $unit prefix '$prefix'." + switch -exact -- $prefix { + "M" { return 1E+6 } + "k" { return 1E+3 } + "" { return 1E+0 } + "m" { return 1E-3 } + "u" { return 1E-6 } + "n" { return 1E-9 } + "p" { return 1E-12 } + "f" { return 1E-15 } } + sta_error 344 "unknown $unit prefix '$prefix'." } proc check_unit_scale { unit scale } { 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/regression_vars.tcl b/test/regression_vars.tcl index 8509e04a..444cab71 100644 --- a/test/regression_vars.tcl +++ b/test/regression_vars.tcl @@ -122,6 +122,7 @@ record_example_tests { } record_sta_tests { + verilog_attribute } define_test_group fast [group_tests all] diff --git a/test/verilog_attribute.ok b/test/verilog_attribute.ok new file mode 100644 index 00000000..305bd5b2 --- /dev/null +++ b/test/verilog_attribute.ok @@ -0,0 +1,4 @@ +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 +instance: _1415_ attribute "attr1" = test_attr1 +instance: _1415_ attribute "attr2" = test_attr2 diff --git a/test/verilog_attribute.tcl b/test/verilog_attribute.tcl new file mode 100644 index 00000000..225a0187 --- /dev/null +++ b/test/verilog_attribute.tcl @@ -0,0 +1,18 @@ +read_liberty ../examples/sky130hd_tt.lib +read_verilog verilog_attribute.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"] +set instance_attr1 [[sta::find_instance $instance_name] get_attribute "attr1"] +set instance_attr2 [[sta::find_instance $instance_name] get_attribute "attr2"] +puts "instance: $instance_name attribute \"src\" = $instance_src_location" +puts "instance: $instance_name attribute \"attr1\" = $instance_attr1" +puts "instance: $instance_name attribute \"attr2\" = $instance_attr2" diff --git a/test/verilog_attribute.v b/test/verilog_attribute.v new file mode 100644 index 00000000..473c5e28 --- /dev/null +++ b/test/verilog_attribute.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", attr1 = "test_attr1", attr2 = "test_attr2" *) + sky130_fd_sc_hd__dfrtp_1 _1415_ ( + .CLK(clk), + .D(in), + .Q(out), + .RESET_B(reset) + ); +endmodule diff --git a/util/MinMax.cc b/util/MinMax.cc index 7631cf9c..5c7ed750 100644 --- a/util/MinMax.cc +++ b/util/MinMax.cc @@ -17,6 +17,7 @@ #include "MinMax.hh" #include +#include #include "StringUtil.hh" @@ -40,18 +41,20 @@ compareMax(float value1, //////////////////////////////////////////////////////////////// -MinMax MinMax::min_("min", 0, INF, compareMin); -MinMax MinMax::max_("max", 1, -INF, compareMax); +MinMax MinMax::min_("min", 0, INF, std::numeric_limits::max(), compareMin); +MinMax MinMax::max_("max", 1, -INF, std::numeric_limits::min(), compareMax); const std::array MinMax::range_{&min_, &max_}; const std::array MinMax::range_index_{min_.index(), max_.index()}; MinMax::MinMax(const char *name, int index, float init_value, + int init_value_int, bool (*compare)(float value1, float value2)) : name_(name), index_(index), init_value_(init_value), + init_value_int_(init_value_int), compare_(compare) { } 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..a7752bd6 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_specs ',' 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..dbb602ac 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