Merge pull request #72 from akashlevy/master

Add property-based filtering (`-filter` keyword arg) on all SDC `get_*` commands (+ DRY refactor)
This commit is contained in:
James Cherry 2024-08-13 12:23:56 -07:00 committed by GitHub
commit e8a6ebe512
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 708 additions and 586 deletions

Binary file not shown.

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1325,13 +1325,58 @@ filter_pins(const char *property,
return filter_objects<const Pin>(property, op, pattern, pins);
}
ClockSeq
filter_clocks(const char *property,
const char *op,
const char *pattern,
ClockSeq *clocks)
{
return filter_objects<Clock>(property, op, pattern, clocks);
}
LibertyCellSeq
filter_lib_cells(const char *property,
const char *op,
const char *pattern,
LibertyCellSeq *cells)
{
return filter_objects<LibertyCell>(property, op, pattern, cells);
}
LibertyPortSeq
filter_lib_pins(const char *property,
const char *op,
const char *pattern,
LibertyPortSeq *pins)
{
return filter_objects<LibertyPort>(property, op, pattern, pins);
}
LibertyLibrarySeq
filter_liberty_libraries(const char *property,
const char *op,
const char *pattern,
LibertyLibrarySeq *libs)
{
return filter_objects<LibertyLibrary>(property, op, pattern, libs);
}
NetSeq
filter_nets(const char *property,
const char *op,
const char *pattern,
NetSeq *nets)
{
return filter_objects<const Net>(property, op, pattern, nets);
}
EdgeSeq
filter_timing_arcs(const char *property,
const char *op,
const char *pattern,
EdgeSeq *edges)
{
return filter_objects<sta::Edge>(property, op, pattern, edges);
return filter_objects<Edge>(property, op, pattern, edges);
}
////////////////////////////////////////////////////////////////

View File

@ -406,6 +406,36 @@ proc current_design { {design ""} } {
################################################################
# Generic get_* filter.
proc filter_objs { filter objects filter_function object_type } {
set filter_regexp1 {@?([a-zA-Z_]+) *(==|!=|=~|!~) *([0-9a-zA-Z_\*]+)}
set filter_or_regexp "($filter_regexp1) *\\|\\| *($filter_regexp1)"
set filter_and_regexp "($filter_regexp1) *&& *($filter_regexp1)"
set filtered_objects {}
# Ignore sub-exprs in filter_regexp1 for expr2 match var.
if { [regexp $filter_or_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects1 [$filter_function $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects2 [$filter_function $attr_name $op $arg $objects]
set filtered_objects [concat $filtered_objects1 $filtered_objects2]
} elseif { [regexp $filter_and_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects [$filter_function $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects [$filter_function $attr_name $op $arg $filtered_objects]
} elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } {
set filtered_objects [$filter_function $attr_name $op $arg $objects]
} else {
sta_error 350 "unsupported $object_type -filter expression."
}
return $filtered_objects
}
################################################################
define_cmd_args "get_cells" \
{[-hierarchical] [-hsc separator] [-filter expr]\
[-regexp] [-nocase] [-quiet] [-of_objects objects] [patterns]}
@ -473,46 +503,19 @@ proc get_cells { args } {
}
}
if [info exists keys(-filter)] {
set insts [filter_insts1 $keys(-filter) $insts]
set insts [filter_objs $keys(-filter) $insts filter_insts "instance"]
}
return $insts
}
proc filter_insts1 { filter objects } {
variable filter_regexp1
variable filter_or_regexp
variable filter_and_regexp
set filtered_objects {}
# Ignore sub-exprs in filter_regexp1 for expr2 match var.
if { [regexp $filter_or_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects1 [filter_insts $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects2 [filter_insts $attr_name $op $arg $objects]
set filtered_objects [concat $filtered_objects1 $filtered_objects2]
} elseif { [regexp $filter_and_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects [filter_insts $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects [filter_insts $attr_name $op $arg $filtered_objects]
} elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } {
set filtered_objects [filter_insts $attr_name $op $arg $objects]
} else {
sta_error 350 "unsupported instance -filter expression."
}
return $filtered_objects
}
################################################################
define_cmd_args "get_clocks" {[-regexp] [-nocase] [-quiet] patterns}
define_cmd_args "get_clocks" {[-regexp] [-nocase] [-quiet] [-filter expr] patterns}
define_cmd_alias "get_clock" "get_clocks"
proc get_clocks { args } {
parse_key_args "get_clocks" args keys {} flags {-regexp -nocase -quiet}
parse_key_args "get_clocks" args keys {-filter} flags {-regexp -nocase -quiet}
check_argc_eq1 "get_clocks" $args
check_nocase_flag flags
@ -531,20 +534,23 @@ proc get_clocks { args } {
}
}
}
if [info exists keys(-filter)] {
set clocks [filter_objs $keys(-filter) $clocks filter_clocks "clock"]
}
return $clocks
}
################################################################
define_cmd_args "get_lib_cells" \
{[-hsc separator] [-regexp] [-nocase] [-quiet]\
{[-hsc separator] [-regexp] [-nocase] [-quiet] [-filter expr]\
[-of_objects objects] [patterns]}
define_cmd_alias "get_lib_cell" "get_lib_cells"
proc get_lib_cells { args } {
global hierarchy_separator
parse_key_args "get_lib_cells" args keys {-hsc -of_objects} \
parse_key_args "get_lib_cells" args keys {-hsc -of_objects -filter} \
flags {-regexp -nocase -quiet}
check_nocase_flag flags
@ -598,20 +604,23 @@ proc get_lib_cells { args } {
}
}
}
if [info exists keys(-filter)] {
set cells [filter_objs $keys(-filter) $cells filter_lib_cells "liberty cell"]
}
return $cells
}
################################################################
define_cmd_args "get_lib_pins" \
{[-hsc separator] [-regexp] [-nocase] [-quiet] patterns}
{[-hsc separator] [-regexp] [-nocase] [-quiet] [-filter expr] patterns}
define_cmd_alias "get_lib_pin" "get_lib_pins"
# "get_lib_ports" in sta terminology.
proc get_lib_pins { args } {
global hierarchy_separator
parse_key_args "get_lib_pins" args keys {-hsc} flags {-regexp -nocase -quiet}
parse_key_args "get_lib_pins" args keys {-hsc -filter} flags {-regexp -nocase -quiet}
check_argc_eq1 "get_lib_pins" $args
check_nocase_flag flags
@ -668,6 +677,9 @@ proc get_lib_pins { args } {
}
}
}
if [info exists keys(-filter)] {
set ports [filter_objs $keys(-filter) $ports filter_lib_pins "liberty port"]
}
return $ports
}
@ -680,12 +692,12 @@ proc check_nocase_flag { flags_var } {
################################################################
define_cmd_args "get_libs" {[-regexp] [-nocase] [-quiet] patterns}
define_cmd_args "get_libs" {[-regexp] [-nocase] [-quiet] [-filter expr] patterns}
define_cmd_alias "get_lib" "get_libs"
proc get_libs { args } {
parse_key_args "get_libs" args keys {} flags {-regexp -nocase -quiet}
parse_key_args "get_libs" args keys {-filter} flags {-regexp -nocase -quiet}
check_argc_eq1 "get_libs" $args
check_nocase_flag flags
@ -704,6 +716,9 @@ proc get_libs { args } {
}
}
}
if [info exists keys(-filter)] {
set libs [filter_objs $keys(-filter) $libs filter_liberty_libraries "liberty library"]
}
return $libs
}
@ -737,7 +752,7 @@ proc find_liberty_libraries_matching { pattern regexp nocase } {
################################################################
define_cmd_args "get_nets" \
{[-hierarchical] [-hsc separator] [-regexp] [-nocase] [-quiet]\
{[-hierarchical] [-hsc separator] [-regexp] [-nocase] [-quiet] [-filter expr]\
[-of_objects objects] [patterns]}
define_cmd_alias "get_net" "get_nets"
@ -745,7 +760,7 @@ define_cmd_alias "get_net" "get_nets"
proc get_nets { args } {
global hierarchy_separator
parse_key_args get_nets args keys {-hsc -of_objects} \
parse_key_args get_nets args keys {-hsc -of_objects -filter} \
flags {-hierarchical -regexp -nocase -quiet}
check_nocase_flag flags
@ -791,6 +806,9 @@ proc get_nets { args } {
}
}
}
if [info exists keys(-filter)] {
set nets [filter_objs $keys(-filter) $nets filter_nets "net"]
}
return $nets
}
@ -858,38 +876,11 @@ proc get_pins { args } {
}
}
if [info exists keys(-filter)] {
set pins [filter_pins1 $keys(-filter) $pins]
set pins [filter_objs $keys(-filter) $pins filter_pins "pin"]
}
return $pins
}
proc filter_pins1 { filter objects } {
variable filter_regexp1
variable filter_or_regexp
variable filter_and_regexp
set filtered_objects {}
# Ignore sub-exprs in filter_regexp1 for expr2 match var.
if { [regexp $filter_or_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects1 [filter_pins $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects2 [filter_pins $attr_name $op $arg $objects]
set filtered_objects [concat $filtered_objects1 $filtered_objects2]
} elseif { [regexp $filter_and_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects [filter_pins $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects [filter_pins $attr_name $op $arg $filtered_objects]
} elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } {
set filtered_objects [filter_pins $attr_name $op $arg $objects]
} else {
sta_error 364 "unsupported pin -filter expression."
}
return $filtered_objects
}
################################################################
define_cmd_args "get_ports" \
@ -930,42 +921,11 @@ proc get_ports { args } {
}
}
if [info exists keys(-filter)] {
set ports [filter_ports1 $keys(-filter) $ports]
set ports [filter_objs $keys(-filter) $ports filter_ports "port"]
}
return $ports
}
variable filter_regexp1 {@?([a-zA-Z_]+) *(==|!=|=~|!~) *([0-9a-zA-Z_\*]+)}
variable filter_or_regexp "($filter_regexp1) *\\|\\| *($filter_regexp1)"
variable filter_and_regexp "($filter_regexp1) *&& *($filter_regexp1)"
proc filter_ports1 { filter objects } {
variable filter_regexp1
variable filter_or_regexp
variable filter_and_regexp
set filtered_objects {}
# Ignore sub-exprs in filter_regexp1 for expr2 match var.
if { [regexp $filter_or_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects1 [filter_ports $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects2 [filter_ports $attr_name $op $arg $objects]
set filtered_objects [concat $filtered_objects1 $filtered_objects2]
} elseif { [regexp $filter_and_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects [filter_ports $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects [filter_ports $attr_name $op $arg $filtered_objects]
} elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } {
set filtered_objects [filter_ports $attr_name $op $arg $objects]
} else {
sta_error 367 "unsupported port -filter expression."
}
return $filtered_objects
}
################################################################
#
# Timing Constraints

View File

@ -171,7 +171,7 @@ proc get_timing_edges_cmd { cmd cmd_args } {
cmd_usage_error $cmd
}
if [info exists keys(-filter)] {
set arcs [filter_timing_arcs1 $keys(-filter) $arcs]
set arcs [filter_objs $keys(-filter) $arcs filter_timing_arcs "timing arc"]
}
return $arcs
}
@ -260,34 +260,6 @@ proc get_timing_arcs_to { to_pin_arg } {
return $edges
}
proc filter_timing_arcs1 { filter objects } {
variable filter_regexp1
variable filter_or_regexp
variable filter_and_regexp
set filtered_objects {}
# Ignore sub-exprs in filter_regexp1 for expr2 match var.
if { [regexp $filter_or_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects1 [filter_timing_arcs $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects2 [filter_timing_arcs $attr_name $op $arg $objects]
set filtered_objects [concat $filtered_objects1 $filtered_objects2]
} elseif { [regexp $filter_and_regexp $filter ignore expr1 \
ignore ignore ignore expr2] } {
regexp $filter_regexp1 $expr1 ignore attr_name op arg
set filtered_objects [filter_timing_arcs $attr_name $op $arg $objects]
regexp $filter_regexp1 $expr2 ignore attr_name op arg
set filtered_objects [filter_timing_arcs $attr_name $op \
$arg $filtered_objects]
} elseif { [regexp $filter_regexp1 $filter ignore attr_name op arg] } {
set filtered_objects [filter_timing_arcs $attr_name $op $arg $objects]
} else {
sta_error 541 "unsupported -filter expression."
}
return $filtered_objects
}
################################################################
define_cmd_args "report_clock_properties" {[clocks]}

View File

@ -520,6 +520,10 @@ using namespace sta;
seqTclList<CellSeq, Cell>($1, SWIGTYPE_p_Cell, interp);
}
%typemap(in) LibertyCellSeq* {
$1 = tclListSeqPtr<LibertyCell*>($input, SWIGTYPE_p_LibertyCell, interp);
}
%typemap(out) LibertyCellSeq * {
seqPtrTclList<LibertyCellSeq, LibertyCell>($1, SWIGTYPE_p_LibertyCell, interp);
}
@ -528,6 +532,10 @@ using namespace sta;
seqTclList<LibertyCellSeq, LibertyCell>($1, SWIGTYPE_p_LibertyCell, interp);
}
%typemap(in) LibertyPortSeq* {
$1 = tclListSeqPtr<LibertyPort*>($input, SWIGTYPE_p_LibertyPort, interp);
}
%typemap(out) LibertyPortSeq {
seqTclList<LibertyPortSeq, LibertyPort>($1, SWIGTYPE_p_LibertyPort, interp);
}
@ -746,6 +754,14 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(in) LibertyLibrarySeq* {
$1 = tclListSeqPtr<LibertyLibrary*>($input, SWIGTYPE_p_LibertyLibrary, interp);
}
%typemap(out) LibertyLibrarySeq {
seqTclList<LibertyLibrarySeq, LibertyLibrary>($1, SWIGTYPE_p_LibertyLibrary, interp);
}
%typemap(out) Pin* {
Tcl_Obj *obj = SWIG_NewInstanceObj($1, $1_descriptor, false);
Tcl_SetObjResult(interp, obj);
@ -755,7 +771,6 @@ using namespace sta;
seqPtrTclList<PinSeq, Pin>($1, SWIGTYPE_p_Pin, interp);
}
%typemap(out) PinSeq {
seqTclList<PinSeq, Pin>($1, SWIGTYPE_p_Pin, interp);
}
@ -765,6 +780,10 @@ using namespace sta;
Tcl_SetObjResult(interp, obj);
}
%typemap(in) NetSeq* {
$1 = tclListSeqPtr<const Net*>($input, SWIGTYPE_p_Net, interp);
}
%typemap(out) NetSeq* {
seqPtrTclList<NetSeq, Net>($1, SWIGTYPE_p_Net, interp);
}
@ -806,6 +825,10 @@ using namespace sta;
$1 = tclListSeq<const Clock*>($input, SWIGTYPE_p_Clock, interp);
}
%typemap(in) ClockSeq* {
$1 = tclListSeqPtr<Clock*>($input, SWIGTYPE_p_Clock, interp);
}
%typemap(out) ClockSeq* {
seqPtrTclList<ClockSeq, Clock>($1, SWIGTYPE_p_Clock, interp);
}

45
test/get_filter.ok Normal file
View File

@ -0,0 +1,45 @@
get_cells
u1
get_clocks
clk
get_clocks 2
vclk
get_lib_cells
asap7_small/BUFx2_ASAP7_75t_R
get_lib_cells 2
asap7_small/AND2x2_ASAP7_75t_R
asap7_small/BUFx2_ASAP7_75t_R
asap7_small/DFFHQx4_ASAP7_75t_R
get_lib_pins
A
get_lib_pins 2
Y
get_libs
asap7_small
get_nets
r1q
r2q
get_pins
r1/CLK
r1/D
r2/CLK
r2/D
r3/CLK
r3/D
u1/A
u2/A
u2/B
get_pins 2
r1/Q
r2/Q
r3/Q
u1/Y
u2/Y
get_ports
clk1
clk2
clk3
in1
in2
get_ports 2
out

34
test/get_filter.tcl Normal file
View File

@ -0,0 +1,34 @@
# Read in design and libraries
read_liberty asap7_small.lib.gz
read_verilog reg1_asap7.v
link_design top
create_clock -name clk -period 500 {clk1 clk2 clk3}
create_clock -name vclk -period 1000
# Test filters for each SDC command
puts "get_cells"
report_object_full_names [get_cells -filter liberty_cell==BUFx2_ASAP7_75t_R *]
puts "get_clocks"
report_object_full_names [get_clocks -filter is_virtual==0 *]
puts "get_clocks 2"
report_object_full_names [get_clocks -filter is_virtual==1 *]
puts "get_lib_cells"
report_object_full_names [get_lib_cells -filter is_buffer==1 *]
puts "get_lib_cells 2"
report_object_full_names [get_lib_cells -filter is_inverter==0 *]
puts "get_lib_pins"
report_object_full_names [get_lib_pins -filter direction==input BUFx2_ASAP7_75t_R/*]
puts "get_lib_pins 2"
report_object_full_names [get_lib_pins -filter direction==output BUFx2_ASAP7_75t_R/*]
puts "get_libs"
report_object_full_names [get_libs -filter name==asap7_small *]
puts "get_nets"
report_object_full_names [get_nets -filter name=~*q *]
puts "get_pins"
report_object_full_names [get_pins -filter direction==input *]
puts "get_pins 2"
report_object_full_names [get_pins -filter direction==output *]
puts "get_ports"
report_object_full_names [get_ports -filter direction==input *]
puts "get_ports 2"
report_object_full_names [get_ports -filter direction==output *]

View File

@ -125,6 +125,7 @@ record_sta_tests {
prima3
verilog_attribute
liberty_arcs_one2one
get_filter
}
define_test_group fast [group_tests all]