diff --git a/include/sta/FilterObjects.hh b/include/sta/FilterObjects.hh index bbabd4b0..7420b450 100644 --- a/include/sta/FilterObjects.hh +++ b/include/sta/FilterObjects.hh @@ -40,67 +40,56 @@ class Report; PortSeq filterPorts(std::string_view filter_expression, PortSeq *objects, - bool bool_props_as_int, Sta *sta); InstanceSeq filterInstances(std::string_view filter_expression, InstanceSeq *objects, - bool bool_props_as_int, Sta *sta); PinSeq filterPins(std::string_view filter_expression, PinSeq *objects, - bool bool_props_as_int, Sta *sta); NetSeq filterNets(std::string_view filter_expression, NetSeq *objects, - bool bool_props_as_int, Sta *sta); ClockSeq filterClocks(std::string_view filter_expression, ClockSeq *objects, - bool bool_props_as_int, Sta *sta); LibertyCellSeq filterLibCells(std::string_view filter_expression, LibertyCellSeq *objects, - bool bool_props_as_int, Sta *sta); LibertyPortSeq filterLibPins(std::string_view filter_expression, LibertyPortSeq *objects, - bool bool_props_as_int, Sta *sta); LibertyLibrarySeq filterLibertyLibraries(std::string_view filter_expression, LibertyLibrarySeq *objects, - bool bool_props_as_int, Sta *sta); EdgeSeq filterTimingArcs(std::string_view filter_expression, EdgeSeq *objects, - bool bool_props_as_int, Sta *sta); PathEndSeq filterPathEnds(std::string_view filter_expression, PathEndSeq *objects, - bool bool_props_as_int, Sta *sta); // For FilterExpr unit tests. StringSeq filterExprToPostfix(std::string_view expr, - bool bool_props_as_int, Report *report); } // namespace diff --git a/sdc/FilterObjects.cc b/sdc/FilterObjects.cc index 2e18473e..6e263037 100644 --- a/sdc/FilterObjects.cc +++ b/sdc/FilterObjects.cc @@ -73,9 +73,9 @@ public: FilterExpr(std::string_view expression, Report *report); - std::vector> postfix(bool bool_props_as_int); + std::vector> postfix(); private: - std::vector> lex(bool bool_props_as_int); + std::vector> lex(); std::vector> shuntingYard(std::vector> &infix); std::string raw_; @@ -106,20 +106,21 @@ FilterExpr::FilterExpr(std::string_view expression, } std::vector> -FilterExpr::postfix(bool bool_props_as_int) +FilterExpr::postfix() { - auto infix = lex(bool_props_as_int); + auto infix = lex(); return shuntingYard(infix); } std::vector> -FilterExpr::lex(bool bool_props_as_int) +FilterExpr::lex() { std::vector> token_regexes = { {std::regex("^\\s+"), Token::Kind::skip}, {std::regex("^defined\\(([a-zA-Z_]+)\\)"), Token::Kind::defined}, {std::regex("^undefined\\(([a-zA-Z_]+)\\)"), Token::Kind::undefined}, - {std::regex("^@?([a-zA-Z_]+) *((==|!=|=~|!~) *([0-9a-zA-Z_\\/$\\[\\]*?]+))?"), Token::Kind::predicate}, + {std::regex("^@?([a-zA-Z_]+) *((==|!=|=~|!~) *([0-9a-zA-Z_\\/$\\[\\]*?.]+))?"), + Token::Kind::predicate}, {std::regex("^(&&)"), Token::Kind::op_and}, {std::regex("^(\\|\\|)"), Token::Kind::op_or}, {std::regex("^(!)"), Token::Kind::op_inv}, @@ -139,9 +140,9 @@ FilterExpr::lex(bool bool_props_as_int) std::string property = token_match[1].str(); // The default operation on a predicate if an op and arg are - // omitted is 'arg == 1' / 'arg == true'. + // omitted is 'prop == 1 || true'. std::string op = "=="; - std::string arg = (bool_props_as_int ? "1" : "true"); + std::string arg = "1"; if (token_match[2].length() != 0) { op = token_match[3].str(); @@ -250,13 +251,18 @@ filterObjects(const char *property, bool not_pattern_match = stringEq(op, "!~"); for (T *object : all) { PropertyValue value = properties.getProperty(object, property); - std::string prop_str = value.to_string(network); - const char *prop = prop_str.c_str(); - if (prop && - ((exact_match && stringEq(prop, pattern)) - || (not_match && !stringEq(prop, pattern)) - || (pattern_match && patternMatch(pattern, prop)) - || (not_pattern_match && !patternMatch(pattern, prop)))) + std::string prop = value.to_string(network); + if (value.type() == PropertyValue::Type::bool_) { + // Canonicalize bool true/false to 1/0. + if (stringEqual(pattern, "true")) + pattern = "1"; + else if (stringEqual(pattern, "false")) + pattern = "0"; + } + if ((exact_match && stringEq(prop.c_str(), pattern)) + || (not_match && !stringEq(prop.c_str(), pattern)) + || (pattern_match && patternMatch(pattern, prop)) + || (not_pattern_match && !patternMatch(pattern, prop))) filtered_objects.insert(object); } return filtered_objects; @@ -265,7 +271,6 @@ filterObjects(const char *property, template std::vector filterObjects(std::string_view filter_expression, std::vector *objects, - bool bool_props_as_int, Sta *sta) { Report *report = sta->report(); @@ -278,7 +283,7 @@ filterObjects(std::string_view filter_expression, all.insert(object); FilterExpr filter(filter_expression, report); - auto postfix = filter.postfix(bool_props_as_int); + auto postfix = filter.postfix(); std::stack> eval_stack; for (auto &token : postfix) { if (token->kind == FilterExpr::Token::Kind::op_or) { @@ -405,100 +410,89 @@ filterObjects(std::string_view filter_expression, PortSeq filterPorts(std::string_view filter_expression, PortSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } InstanceSeq filterInstances(std::string_view filter_expression, InstanceSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } PinSeq filterPins(std::string_view filter_expression, PinSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } NetSeq filterNets(std::string_view filter_expression, NetSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } ClockSeq filterClocks(std::string_view filter_expression, ClockSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } LibertyCellSeq filterLibCells(std::string_view filter_expression, LibertyCellSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } LibertyPortSeq filterLibPins(std::string_view filter_expression, LibertyPortSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } LibertyLibrarySeq filterLibertyLibraries(std::string_view filter_expression, LibertyLibrarySeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } EdgeSeq filterTimingArcs(std::string_view filter_expression, EdgeSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } PathEndSeq filterPathEnds(std::string_view filter_expression, PathEndSeq *objects, - bool bool_props_as_int, Sta *sta) { - return filterObjects(filter_expression, objects, bool_props_as_int, sta); + return filterObjects(filter_expression, objects, sta); } StringSeq filterExprToPostfix(std::string_view expr, - bool bool_props_as_int, Report *report) { FilterExpr filter(expr, report); - auto postfix = filter.postfix(bool_props_as_int); + auto postfix = filter.postfix(); StringSeq result; for (auto &token : postfix) result.push_back(token->text); diff --git a/sdc/Sdc.i b/sdc/Sdc.i index eccd234e..60107704 100644 --- a/sdc/Sdc.i +++ b/sdc/Sdc.i @@ -1493,101 +1493,90 @@ find_register_output_pins(ClockSet *clks, PortSeq filter_ports(const char *filter_expression, - PortSeq *ports, - bool bool_props_as_int) + PortSeq *ports) { sta::Sta *sta = Sta::sta(); - return filterPorts(filter_expression, ports, bool_props_as_int, sta); + return filterPorts(filter_expression, ports, sta); } InstanceSeq filter_insts(const char *filter_expression, - InstanceSeq *insts, - bool bool_props_as_int) + InstanceSeq *insts) { sta::Sta *sta = Sta::sta(); - return filterInstances(filter_expression, insts, bool_props_as_int, sta); + return filterInstances(filter_expression, insts, sta); } PinSeq filter_pins(const char *filter_expression, - PinSeq *pins, - bool bool_props_as_int) + PinSeq *pins) { sta::Sta *sta = Sta::sta(); - return filterPins(filter_expression, pins, bool_props_as_int, sta); + return filterPins(filter_expression, pins, sta); } NetSeq filter_nets(const char *filter_expression, - NetSeq *nets, - bool bool_props_as_int) + NetSeq *nets) { sta::Sta *sta = Sta::sta(); - return filterNets(filter_expression, nets, bool_props_as_int, sta); + return filterNets(filter_expression, nets, sta); } ClockSeq filter_clocks(const char *filter_expression, - ClockSeq *clocks, - bool bool_props_as_int) + ClockSeq *clocks) { sta::Sta *sta = Sta::sta(); - return filterClocks(filter_expression, clocks, bool_props_as_int, sta); + return filterClocks(filter_expression, clocks, sta); } LibertyCellSeq filter_lib_cells(const char *filter_expression, - LibertyCellSeq *cells, - bool bool_props_as_int) + LibertyCellSeq *cells) { sta::Sta *sta = Sta::sta(); - return filterLibCells(filter_expression, cells, bool_props_as_int, sta); + return filterLibCells(filter_expression, cells, sta); } LibertyPortSeq filter_lib_pins(const char *filter_expression, - LibertyPortSeq *pins, - bool bool_props_as_int) + LibertyPortSeq *pins) { sta::Sta *sta = Sta::sta(); - return filterLibPins(filter_expression, pins, bool_props_as_int, sta); + return filterLibPins(filter_expression, pins, sta); } LibertyLibrarySeq filter_liberty_libraries(const char *filter_expression, - LibertyLibrarySeq *libs, - bool bool_props_as_int) + LibertyLibrarySeq *libs) { sta::Sta *sta = Sta::sta(); - return filterLibertyLibraries(filter_expression, libs, bool_props_as_int, sta); + return filterLibertyLibraries(filter_expression, libs, sta); } EdgeSeq filter_timing_arcs(const char *filter_expression, - EdgeSeq *edges, - bool bool_props_as_int) + EdgeSeq *edges) { sta::Sta *sta = Sta::sta(); - return filterTimingArcs(filter_expression, edges, bool_props_as_int, sta); + return filterTimingArcs(filter_expression, edges, sta); } PathEndSeq filter_path_ends(const char *filter_expression, - PathEndSeq *path_ends, - bool bool_props_as_int) + PathEndSeq *path_ends) { sta::Sta *sta = Sta::sta(); - return filterPathEnds(filter_expression, path_ends, bool_props_as_int, sta); + return filterPathEnds(filter_expression, path_ends, sta); } // For FilterExpr unit tests. StringSeq -filter_expr_to_postfix(const char* expr, - bool bool_props_as_int) +filter_expr_to_postfix(const char* expr) { Report *report = Sta::sta()->report(); - return filterExprToPostfix(expr, bool_props_as_int, report); + return filterExprToPostfix(expr, report); } //////////////////////////////////////////////////////////////// diff --git a/sdc/Sdc.tcl b/sdc/Sdc.tcl index dd5374cd..d8e5aef1 100644 --- a/sdc/Sdc.tcl +++ b/sdc/Sdc.tcl @@ -393,7 +393,7 @@ proc get_cells { args } { } } if [info exists keys(-filter)] { - set insts [filter_insts $keys(-filter) $insts 1] + set insts [filter_insts $keys(-filter) $insts] } return $insts } @@ -436,7 +436,7 @@ proc get_clocks { args } { } } if [info exists keys(-filter)] { - set clocks [filter_clocks $keys(-filter) $clocks 1] + set clocks [filter_clocks $keys(-filter) $clocks] } return $clocks } @@ -517,7 +517,7 @@ proc get_lib_cells { args } { } } if [info exists keys(-filter)] { - set cells [filter_lib_cells $keys(-filter) $cells 1] + set cells [filter_lib_cells $keys(-filter) $cells] } return $cells } @@ -621,7 +621,7 @@ proc get_lib_pins { args } { } } if [info exists keys(-filter)] { - set ports [filter_lib_pins $keys(-filter) $ports 1] + set ports [filter_lib_pins $keys(-filter) $ports] } return $ports } @@ -671,7 +671,7 @@ proc get_libs { args } { } } if [info exists keys(-filter)] { - set libs [filter_liberty_libraries $keys(-filter) $libs 1] + set libs [filter_liberty_libraries $keys(-filter) $libs] } return $libs } @@ -772,7 +772,7 @@ proc get_nets { args } { } } if [info exists keys(-filter)] { - set nets [filter_nets $keys(-filter) $nets 1] + set nets [filter_nets $keys(-filter) $nets] } return $nets } @@ -863,7 +863,7 @@ proc get_pins { args } { } } if [info exists keys(-filter)] { - set pins [filter_pins $keys(-filter) $pins 1] + set pins [filter_pins $keys(-filter) $pins] } return $pins } @@ -919,7 +919,7 @@ proc get_ports { args } { } } if [info exists keys(-filter)] { - set ports [filter_ports $keys(-filter) $ports 1] + set ports [filter_ports $keys(-filter) $ports] } return $ports } diff --git a/search/Property.cc b/search/Property.cc index cdb0c088..067298d7 100644 --- a/search/Property.cc +++ b/search/Property.cc @@ -564,7 +564,7 @@ PropertyValue::to_string(const Network *network) const case Type::float_: return unit_->asString(float_, 6); case Type::bool_: - // true/false would be better but these are TCL true/false values. + // These are TCL true/false values. if (bool_) return "1"; else diff --git a/tcl/Sta.tcl b/tcl/Sta.tcl index f6daed10..8796df34 100644 --- a/tcl/Sta.tcl +++ b/tcl/Sta.tcl @@ -300,7 +300,7 @@ proc get_timing_edges_cmd { cmd cmd_args } { cmd_usage_error $cmd } if [info exists keys(-filter)] { - set arcs [filter_timing_arcs $keys(-filter) $arcs 1] + set arcs [filter_timing_arcs $keys(-filter) $arcs] } return $arcs } diff --git a/test/asap7_small.lib.gz b/test/asap7_small.lib.gz index 3c47419f..f0381ded 100644 Binary files a/test/asap7_small.lib.gz and b/test/asap7_small.lib.gz differ diff --git a/test/get_filter.ok b/test/get_filter.ok index 8bd8c18a..1f0402ec 100644 --- a/test/get_filter.ok +++ b/test/get_filter.ok @@ -1,24 +1,11 @@ [get_cells -filter liberty_cell==BUFx2_ASAP7_75t_R *] u1 -[get_clocks -filter is_virtual==0 *] -clk -[get_clocks -filter is_virtual==1 *] -vclk [get_clocks -filter is_virtual *] vclk -[get_clocks -filter is_virtual&&is_generated *] -[get_clocks -filter is_virtual&&is_generated==0 *] -vclk -[get_clocks -filter is_virtual||is_generated *] -vclk -[get_clocks -filter is_virtual==0||is_generated *] -clk -[get_lib_cells -filter is_buffer==1 *] +[get_lib_cells -filter is_buffer *] asap7_small/BUFx2_ASAP7_75t_R -[get_lib_cells -filter is_inverter==0 *] -asap7_small/AND2x2_ASAP7_75t_R -asap7_small/BUFx2_ASAP7_75t_R -asap7_small/DFFHQx4_ASAP7_75t_R +[get_lib_cells -filter is_inverter *] +asap7_small/INVx2_ASAP7_75t_R [get_lib_pins -filter direction==input BUFx2_ASAP7_75t_R/*] A [get_lib_pins -filter direction==output BUFx2_ASAP7_75t_R/*] @@ -54,9 +41,22 @@ in2 out [get_cells -filter {name ~= *r1*} *] Error: 2600 -filter parsing failed at '~= *r1*'. +direction == input && name =~ clk* clk1 clk2 clk3 +(direction == input) && (name =~ clk*)" clk1 clk2 clk3 +[get_clocks -filter is_virtual||is_generated *] +vclk +[get_clocks -filter is_virtual==0 *] +clk +[get_clocks -filter is_virtual==false *] +clk +[get_clocks -filter is_virtual==1 *] +vclk +[get_clocks -filter is_virtual==true *] +vclk +{direction == input} {name =~ clk*} {is_clock == 1} && && diff --git a/test/get_filter.tcl b/test/get_filter.tcl index d6009a89..b373e944 100644 --- a/test/get_filter.tcl +++ b/test/get_filter.tcl @@ -5,29 +5,16 @@ link_design top create_clock -name clk -period 500 {clk1 clk2 clk3} create_clock -name vclk -period 1000 -# Test filters for each SDC get_* command. puts {[get_cells -filter liberty_cell==BUFx2_ASAP7_75t_R *]} report_object_full_names [get_cells -filter liberty_cell==BUFx2_ASAP7_75t_R *] -puts {[get_clocks -filter is_virtual==0 *]} -report_object_full_names [get_clocks -filter is_virtual==0 *] -puts {[get_clocks -filter is_virtual==1 *]} -report_object_full_names [get_clocks -filter is_virtual==1 *] puts {[get_clocks -filter is_virtual *]} report_object_full_names [get_clocks -filter is_virtual *] -puts {[get_clocks -filter is_virtual&&is_generated *]} -report_object_full_names [get_clocks -filter is_virtual&&is_generated *] -puts {[get_clocks -filter is_virtual&&is_generated==0 *]} -report_object_full_names [get_clocks -filter is_virtual&&is_generated==0 *] -puts {[get_clocks -filter is_virtual||is_generated *]} -report_object_full_names [get_clocks -filter is_virtual||is_generated *] -puts {[get_clocks -filter is_virtual==0||is_generated *]} -report_object_full_names [get_clocks -filter is_virtual==0||is_generated *] -puts {[get_lib_cells -filter is_buffer==1 *]} -report_object_full_names [get_lib_cells -filter is_buffer==1 *] -puts {[get_lib_cells -filter is_inverter==0 *]} -report_object_full_names [get_lib_cells -filter is_inverter==0 *] +puts {[get_lib_cells -filter is_buffer *]} +report_object_full_names [get_lib_cells -filter is_buffer *] +puts {[get_lib_cells -filter is_inverter *]} +report_object_full_names [get_lib_cells -filter is_inverter *] puts {[get_lib_pins -filter direction==input BUFx2_ASAP7_75t_R/*]} report_object_full_names [get_lib_pins -filter direction==input BUFx2_ASAP7_75t_R/*] @@ -55,9 +42,32 @@ puts {[get_cells -filter {name ~= *r1*} *]} catch {get_cells -filter {name ~= *r1*} *} result puts $result -# AND pattern match expr +# AND expr +puts {direction == input && name =~ clk*} report_object_names [get_ports -filter "direction == input && name =~ clk*" *] # parens around sub-exprs +puts {(direction == input) && (name =~ clk*)"} report_object_names [get_ports -filter "(direction == input) && (name =~ clk*)" *] -sta::filter_expr_to_postfix "direction == input && name =~ clk* && is_clock" 1 +# OR expr +puts {[get_clocks -filter is_virtual||is_generated *]} +report_object_full_names [get_clocks -filter is_virtual||is_generated *] + + +# unary==0 / unary==false +puts {[get_clocks -filter is_virtual==0 *]} +report_object_full_names [get_clocks -filter is_virtual==0 *] +puts {[get_clocks -filter is_virtual==false *]} +report_object_full_names [get_clocks -filter is_virtual==false *] + +# unary==1 / unary==true +puts {[get_clocks -filter is_virtual==1 *]} +report_object_full_names [get_clocks -filter is_virtual==1 *] +puts {[get_clocks -filter is_virtual==true *]} +report_object_full_names [get_clocks -filter is_virtual==true *] + +# glob pattern with . (literal dot, no match symantics) +report_object_full_names [get_cells -filter {name =~ .1} *] + +puts [sta::filter_expr_to_postfix "direction == input && name =~ clk* && is_clock"] + diff --git a/test/get_lib_pins_of_objects.ok b/test/get_lib_pins_of_objects.ok index 8c8489b9..850bfc85 100644 --- a/test/get_lib_pins_of_objects.ok +++ b/test/get_lib_pins_of_objects.ok @@ -5,6 +5,7 @@ Y [get_lib_pins -of_objects [get_lib_cells *]] A A +A B CLK D @@ -13,3 +14,4 @@ IQN Q Y Y +Y diff --git a/test/get_noargs.ok b/test/get_noargs.ok index b952fdaa..4da70ba1 100644 --- a/test/get_noargs.ok +++ b/test/get_noargs.ok @@ -11,9 +11,11 @@ vclk asap7_small/AND2x2_ASAP7_75t_R asap7_small/BUFx2_ASAP7_75t_R asap7_small/DFFHQx4_ASAP7_75t_R +asap7_small/INVx2_ASAP7_75t_R [get_lib_pins] A A +A B CLK D @@ -22,6 +24,7 @@ IQN Q Y Y +Y [get_libs] asap7_small [get_nets] diff --git a/test/get_objrefs.ok b/test/get_objrefs.ok index 5430faff..08593630 100644 --- a/test/get_objrefs.ok +++ b/test/get_objrefs.ok @@ -9,9 +9,11 @@ vclk asap7_small/AND2x2_ASAP7_75t_R asap7_small/BUFx2_ASAP7_75t_R asap7_small/DFFHQx4_ASAP7_75t_R +asap7_small/INVx2_ASAP7_75t_R [get_lib_pins [get_lib_pins]] A A +A B CLK D @@ -20,6 +22,7 @@ IQN Q Y Y +Y [get_libs [get_libs]] asap7_small [get_nets [get_nets]]