287 lines
9.3 KiB
Tcl
287 lines
9.3 KiB
Tcl
# Test cell pattern matching, net merging, bus port operations,
|
|
# and network modification with multiple libraries.
|
|
# Targets:
|
|
# Network.cc: findCellsMatching, findNetsMatching, findNetsHierMatching,
|
|
# findInstancesMatching, findInstancesHierMatching,
|
|
# pathNameCmp, pathNameLess, busIndexInRange
|
|
# ConcreteNetwork.cc: mergeInto (net merge), groupBusPorts,
|
|
# makeConcretePort, findPort, deletePinBefore,
|
|
# connect, disconnect, replaceCell, setAttribute, getAttribute
|
|
# SdcNetwork.cc: findCellsMatching, findNetsMatching delegation
|
|
|
|
source ../../test/helpers.tcl
|
|
|
|
############################################################
|
|
# Read libraries
|
|
############################################################
|
|
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
|
read_liberty ../../test/sky130hd/sky130hd_tt.lib
|
|
puts "PASS: read libraries"
|
|
|
|
############################################################
|
|
# Cell pattern matching on libraries
|
|
# Exercises: find_liberty_cells_matching with patterns
|
|
############################################################
|
|
puts "--- cell pattern matching ---"
|
|
|
|
set ng_lib [sta::find_liberty NangateOpenCellLibrary]
|
|
|
|
# Wildcard patterns
|
|
set inv_cells [$ng_lib find_liberty_cells_matching "INV_*" 0 0]
|
|
puts "INV_* matches: [llength $inv_cells]"
|
|
|
|
set buf_cells [$ng_lib find_liberty_cells_matching "BUF_*" 0 0]
|
|
puts "BUF_* matches: [llength $buf_cells]"
|
|
|
|
set dff_cells [$ng_lib find_liberty_cells_matching "DFF*" 0 0]
|
|
puts "DFF* matches: [llength $dff_cells]"
|
|
|
|
set nand_cells [$ng_lib find_liberty_cells_matching "NAND*" 0 0]
|
|
puts "NAND* matches: [llength $nand_cells]"
|
|
|
|
set nor_cells [$ng_lib find_liberty_cells_matching "NOR*" 0 0]
|
|
puts "NOR* matches: [llength $nor_cells]"
|
|
|
|
set aoi_cells [$ng_lib find_liberty_cells_matching "AOI*" 0 0]
|
|
puts "AOI* matches: [llength $aoi_cells]"
|
|
|
|
set oai_cells [$ng_lib find_liberty_cells_matching "OAI*" 0 0]
|
|
puts "OAI* matches: [llength $oai_cells]"
|
|
|
|
# All cells
|
|
set all_cells [$ng_lib find_liberty_cells_matching "*" 0 0]
|
|
puts "all cells: [llength $all_cells]"
|
|
|
|
# Regexp patterns
|
|
set re_inv [$ng_lib find_liberty_cells_matching {^INV_X[0-9]+$} 1 0]
|
|
puts "regexp INV_X#: [llength $re_inv]"
|
|
|
|
set re_buf [$ng_lib find_liberty_cells_matching {^BUF_X[0-9]+$} 1 0]
|
|
puts "regexp BUF_X#: [llength $re_buf]"
|
|
|
|
set re_dff [$ng_lib find_liberty_cells_matching {^DFF[RS]*_X[12]$} 1 0]
|
|
puts "regexp DFF(R|S|RS)_X(1|2): [llength $re_dff]"
|
|
|
|
# Nocase patterns
|
|
set nc_nand [$ng_lib find_liberty_cells_matching "nand*" 0 1]
|
|
puts "nocase nand*: [llength $nc_nand]"
|
|
|
|
set nc_buf [$ng_lib find_liberty_cells_matching "buf_*" 0 1]
|
|
puts "nocase buf_*: [llength $nc_buf]"
|
|
|
|
puts "PASS: Nangate cell pattern matching"
|
|
|
|
# Sky130 pattern matching
|
|
set sky_lib [sta::find_liberty sky130_fd_sc_hd__tt_025C_1v80]
|
|
|
|
set sky_inv [$sky_lib find_liberty_cells_matching "*inv*" 0 0]
|
|
puts "sky inv* matches: [llength $sky_inv]"
|
|
|
|
set sky_buf [$sky_lib find_liberty_cells_matching "*buf*" 0 0]
|
|
puts "sky buf* matches: [llength $sky_buf]"
|
|
|
|
set sky_dff [$sky_lib find_liberty_cells_matching "*dfxtp*" 0 0]
|
|
puts "sky dfxtp* matches: [llength $sky_dff]"
|
|
|
|
set sky_scan [$sky_lib find_liberty_cells_matching "*sdf*" 0 0]
|
|
puts "sky sdf* matches: [llength $sky_scan]"
|
|
|
|
set sky_latch [$sky_lib find_liberty_cells_matching "*dlx*" 0 0]
|
|
puts "sky dlx* matches: [llength $sky_latch]"
|
|
|
|
set sky_clkgate [$sky_lib find_liberty_cells_matching "*dlclkp*" 0 0]
|
|
puts "sky dlclkp* matches: [llength $sky_clkgate]"
|
|
|
|
set sky_lvlshift [$sky_lib find_liberty_cells_matching "*lsbuf*" 0 0]
|
|
puts "sky lsbuf* matches: [llength $sky_lvlshift]"
|
|
|
|
set sky_all [$sky_lib find_liberty_cells_matching "*" 0 0]
|
|
puts "sky all cells: [llength $sky_all]"
|
|
|
|
puts "PASS: Sky130 cell pattern matching"
|
|
|
|
############################################################
|
|
# Port matching on cells
|
|
# Exercises: find_liberty_ports_matching
|
|
############################################################
|
|
puts "--- port pattern matching ---"
|
|
|
|
set dff_cell [get_lib_cell NangateOpenCellLibrary/DFF_X1]
|
|
set dff_ports [$dff_cell find_liberty_ports_matching "*" 0 0]
|
|
puts "DFF_X1 all ports: [llength $dff_ports]"
|
|
|
|
set dff_q_ports [$dff_cell find_liberty_ports_matching "Q*" 0 0]
|
|
puts "DFF_X1 Q* ports: [llength $dff_q_ports]"
|
|
|
|
set dffr_cell [get_lib_cell NangateOpenCellLibrary/DFFR_X1]
|
|
set dffr_ports [$dffr_cell find_liberty_ports_matching "*" 0 0]
|
|
puts "DFFR_X1 all ports: [llength $dffr_ports]"
|
|
|
|
set dffrs_cell [get_lib_cell NangateOpenCellLibrary/DFFRS_X1]
|
|
set dffrs_ports [$dffrs_cell find_liberty_ports_matching "*" 0 0]
|
|
puts "DFFRS_X1 all ports: [llength $dffrs_ports]"
|
|
|
|
# Pattern for S* (SN port on some cells)
|
|
set dffrs_s [$dffrs_cell find_liberty_ports_matching "S*" 0 0]
|
|
puts "DFFRS_X1 S* ports: [llength $dffrs_s]"
|
|
|
|
set dffrs_r [$dffrs_cell find_liberty_ports_matching "R*" 0 0]
|
|
puts "DFFRS_X1 R* ports: [llength $dffrs_r]"
|
|
|
|
puts "PASS: port pattern matching"
|
|
|
|
############################################################
|
|
# Load a design and exercise network-level pattern matching
|
|
############################################################
|
|
read_verilog network_test1.v
|
|
link_design network_test1
|
|
|
|
create_clock -name clk -period 10 [get_ports clk]
|
|
set_input_delay -clock clk 0 [get_ports in1]
|
|
set_input_delay -clock clk 0 [get_ports in2]
|
|
set_output_delay -clock clk 0 [get_ports out1]
|
|
set_input_transition 0.1 [all_inputs]
|
|
report_checks
|
|
puts "PASS: design setup"
|
|
|
|
############################################################
|
|
# Instance pattern matching
|
|
############################################################
|
|
puts "--- instance pattern matching ---"
|
|
|
|
set all_insts [get_cells *]
|
|
puts "all cells: [llength $all_insts]"
|
|
|
|
set buf_insts [get_cells buf*]
|
|
puts "buf* cells: [llength $buf_insts]"
|
|
|
|
set reg_insts [get_cells reg*]
|
|
puts "reg* cells: [llength $reg_insts]"
|
|
|
|
set and_insts [get_cells and*]
|
|
puts "and* cells: [llength $and_insts]"
|
|
|
|
set inv_insts [get_cells inv*]
|
|
puts "inv* cells: [llength $inv_insts]"
|
|
|
|
set or_insts [get_cells or*]
|
|
puts "or* cells: [llength $or_insts]"
|
|
|
|
set n_insts [get_cells n*]
|
|
puts "n* cells: [llength $n_insts]"
|
|
|
|
puts "PASS: instance pattern matching"
|
|
|
|
############################################################
|
|
# Net pattern matching
|
|
############################################################
|
|
puts "--- net pattern matching ---"
|
|
|
|
set all_nets [get_nets *]
|
|
puts "all nets: [llength $all_nets]"
|
|
|
|
set n_nets [get_nets n*]
|
|
puts "n* nets: [llength $n_nets]"
|
|
|
|
puts "PASS: net pattern matching"
|
|
|
|
############################################################
|
|
# Create instances and exercise net merging
|
|
# Exercises: mergeInto in ConcreteNetwork
|
|
############################################################
|
|
puts "--- net merge operations ---"
|
|
|
|
# Create two instances connected to different nets, then merge
|
|
set inst_a [make_instance merge_buf_a NangateOpenCellLibrary/BUF_X1]
|
|
set inst_b [make_instance merge_buf_b NangateOpenCellLibrary/BUF_X1]
|
|
make_net merge_net_1
|
|
make_net merge_net_2
|
|
|
|
catch {connect_pin merge_net_1 merge_buf_a/Z}
|
|
catch {connect_pin merge_net_2 merge_buf_b/A}
|
|
|
|
# Verify both nets exist
|
|
catch {
|
|
set mn1 [get_nets merge_net_1]
|
|
set mn2 [get_nets merge_net_2]
|
|
puts "merge_net_1 exists, merge_net_2 exists"
|
|
}
|
|
|
|
# Now do a cell replacement to exercise mergeInto path
|
|
# Replace buf_a with BUF_X2
|
|
replace_cell merge_buf_a NangateOpenCellLibrary/BUF_X2
|
|
set ref [get_property [get_cells merge_buf_a] ref_name]
|
|
puts "merge_buf_a -> BUF_X2: ref=$ref"
|
|
|
|
# Replace merge_buf_b with different sizes
|
|
replace_cell merge_buf_b NangateOpenCellLibrary/BUF_X4
|
|
set ref [get_property [get_cells merge_buf_b] ref_name]
|
|
puts "merge_buf_b -> BUF_X4: ref=$ref"
|
|
|
|
replace_cell merge_buf_b NangateOpenCellLibrary/INV_X1
|
|
set ref [get_property [get_cells merge_buf_b] ref_name]
|
|
puts "merge_buf_b -> INV_X1: ref=$ref"
|
|
|
|
# Disconnect and clean up
|
|
catch {disconnect_pin merge_net_1 merge_buf_a/Z}
|
|
catch {disconnect_pin merge_net_2 merge_buf_b/A}
|
|
catch {delete_instance merge_buf_a}
|
|
catch {delete_instance merge_buf_b}
|
|
catch {delete_net merge_net_1}
|
|
catch {delete_net merge_net_2}
|
|
puts "PASS: net merge / replace cleanup"
|
|
|
|
############################################################
|
|
# Exercise multiple cell creation and connection patterns
|
|
############################################################
|
|
puts "--- multi-cell connection patterns ---"
|
|
|
|
# Create a chain of buffers
|
|
set chain_nets {}
|
|
set chain_insts {}
|
|
for {set i 0} {$i < 8} {incr i} {
|
|
set iname "chain_buf_$i"
|
|
make_instance $iname NangateOpenCellLibrary/BUF_X1
|
|
lappend chain_insts $iname
|
|
|
|
if {$i > 0} {
|
|
set nname "chain_net_$i"
|
|
make_net $nname
|
|
lappend chain_nets $nname
|
|
catch {connect_pin $nname chain_buf_[expr {$i-1}]/Z}
|
|
catch {connect_pin $nname chain_buf_$i/A}
|
|
}
|
|
}
|
|
puts "PASS: created buffer chain"
|
|
|
|
# Report some nets in the chain
|
|
foreach nname [lrange $chain_nets 0 2] {
|
|
catch {report_net $nname}
|
|
}
|
|
puts "PASS: report chain nets"
|
|
|
|
# Replace cells in chain
|
|
for {set i 0} {$i < 8} {incr i} {
|
|
set sizes {BUF_X1 BUF_X2 BUF_X4}
|
|
set size_idx [expr {$i % 3}]
|
|
replace_cell chain_buf_$i NangateOpenCellLibrary/[lindex $sizes $size_idx]
|
|
}
|
|
puts "PASS: replace chain cells"
|
|
|
|
# Clean up chain
|
|
foreach nname $chain_nets {
|
|
foreach iname $chain_insts {
|
|
catch {disconnect_pin $nname $iname/A}
|
|
catch {disconnect_pin $nname $iname/Z}
|
|
}
|
|
}
|
|
foreach iname $chain_insts {catch {delete_instance $iname}}
|
|
foreach nname $chain_nets {catch {delete_net $nname}}
|
|
puts "PASS: cleanup chain"
|
|
|
|
# Final timing check
|
|
report_checks
|
|
puts "PASS: final timing check"
|
|
|
|
puts "ALL PASSED"
|