302 lines
11 KiB
Tcl
302 lines
11 KiB
Tcl
# Test cell classification (isBuffer, isInverter, isClockGate, etc.),
|
|
# pg_pin iteration, bus port member iteration, internal power queries,
|
|
# and port function queries across multiple PDKs.
|
|
# Targets:
|
|
# Liberty.cc: LibertyCell isBuffer, isInverter, isClockGate,
|
|
# isClockGateLatchPosedge, isClockGateLatchNegedge, isMacro, isPad,
|
|
# isMemory, hasInternalPower, internalPowers, addInternalPower,
|
|
# leakagePower, leakagePowers, cellPortBitCount, busPorts,
|
|
# isDisabledConstraint, pgPins, testCell, setDontUse, dontUse,
|
|
# LibertyPort isBus, isBusBit, isBundle, hasMembers, bundlePort,
|
|
# LibertyPortMemberIterator, findLibertyMember,
|
|
# LibertyLibrary findOperatingConditions, defaultOperatingConditions,
|
|
# supplyExists, findWireload, findWireloadSelection
|
|
# FuncExpr.cc: to_string, portTimingSense
|
|
# InternalPower.cc: InternalPower accessors
|
|
# LeakagePower.cc: LeakagePower accessors
|
|
source ../../test/helpers.tcl
|
|
|
|
############################################################
|
|
# Read libraries with pg_pin info (Sky130 has pg_pin groups)
|
|
############################################################
|
|
read_liberty ../../test/sky130hd/sky130hd_tt.lib
|
|
puts "PASS: read sky130hd"
|
|
|
|
read_liberty ../../test/nangate45/Nangate45_typ.lib
|
|
puts "PASS: read Nangate45"
|
|
|
|
read_liberty ../../test/asap7/asap7sc7p5t_SEQ_RVT_FF_nldm_220123.lib
|
|
puts "PASS: read ASAP7 SEQ"
|
|
|
|
read_liberty ../../test/ihp-sg13g2/sg13g2_stdcell_typ_1p20V_25C.lib
|
|
puts "PASS: read IHP"
|
|
|
|
############################################################
|
|
# Cell classification queries on Nangate45
|
|
############################################################
|
|
puts "--- Nangate45 cell classification ---"
|
|
|
|
# Buffers
|
|
set buf_x1 [get_lib_cell NangateOpenCellLibrary/BUF_X1]
|
|
puts "BUF_X1 is_buffer = [$buf_x1 is_buffer]"
|
|
puts "BUF_X1 is_inverter = [$buf_x1 is_inverter]"
|
|
puts "BUF_X1 is_leaf = [$buf_x1 is_leaf]"
|
|
|
|
# Inverters
|
|
set inv_x1 [get_lib_cell NangateOpenCellLibrary/INV_X1]
|
|
puts "INV_X1 is_buffer = [$inv_x1 is_buffer]"
|
|
puts "INV_X1 is_inverter = [$inv_x1 is_inverter]"
|
|
|
|
# Clock gate cells
|
|
catch {
|
|
set clkgate [get_lib_cell NangateOpenCellLibrary/CLKGATETST_X1]
|
|
puts "CLKGATETST_X1 is_buffer = [$clkgate is_buffer]"
|
|
puts "CLKGATETST_X1 is_inverter = [$clkgate is_inverter]"
|
|
}
|
|
|
|
# DFF
|
|
set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1]
|
|
puts "DFF_X1 is_buffer = [$dff is_buffer]"
|
|
puts "DFF_X1 is_inverter = [$dff is_inverter]"
|
|
puts "DFF_X1 is_leaf = [$dff is_leaf]"
|
|
|
|
# Test cell for scan DFF
|
|
catch {
|
|
set sdff [get_lib_cell NangateOpenCellLibrary/SDFF_X1]
|
|
set tc [$sdff test_cell]
|
|
puts "SDFF_X1 test_cell = $tc"
|
|
}
|
|
|
|
puts "PASS: Nangate45 classification"
|
|
|
|
############################################################
|
|
# Port function queries (exercises FuncExpr::to_string)
|
|
############################################################
|
|
puts "--- port function queries ---"
|
|
foreach {lib_name cell_name} {
|
|
NangateOpenCellLibrary INV_X1
|
|
NangateOpenCellLibrary BUF_X1
|
|
NangateOpenCellLibrary NAND2_X1
|
|
NangateOpenCellLibrary NOR2_X1
|
|
NangateOpenCellLibrary AND2_X1
|
|
NangateOpenCellLibrary OR2_X1
|
|
NangateOpenCellLibrary XOR2_X1
|
|
NangateOpenCellLibrary XNOR2_X1
|
|
NangateOpenCellLibrary AOI21_X1
|
|
NangateOpenCellLibrary OAI21_X1
|
|
NangateOpenCellLibrary MUX2_X1
|
|
NangateOpenCellLibrary HA_X1
|
|
NangateOpenCellLibrary FA_X1
|
|
} {
|
|
set cell [get_lib_cell $lib_name/$cell_name]
|
|
set port_iter [$cell liberty_port_iterator]
|
|
while {[$port_iter has_next]} {
|
|
set port [$port_iter next]
|
|
set func [$port function]
|
|
set tri [$port tristate_enable]
|
|
set dir [sta::liberty_port_direction $port]
|
|
set pwr [$port is_pwr_gnd]
|
|
if {$func != ""} {
|
|
puts " $cell_name/[$port bus_name] func=$func dir=$dir"
|
|
}
|
|
if {$tri != ""} {
|
|
puts " $cell_name/[$port bus_name] tristate=$tri"
|
|
}
|
|
}
|
|
$port_iter finish
|
|
}
|
|
puts "PASS: port function queries"
|
|
|
|
############################################################
|
|
# Bus port and member iteration
|
|
############################################################
|
|
puts "--- bus port member iteration ---"
|
|
|
|
# ASAP7 SEQ has bus ports in some cells
|
|
set asap7_libs [get_libs asap7sc7p5t_SEQ_RVT_FF_nldm_220123]
|
|
set asap7_seq_lib [lindex $asap7_libs 0]
|
|
set asap7_cells [get_lib_cells asap7sc7p5t_SEQ_RVT_FF_nldm_220123/*]
|
|
foreach cell_obj $asap7_cells {
|
|
set cname [$cell_obj name]
|
|
set port_iter [$cell_obj liberty_port_iterator]
|
|
while {[$port_iter has_next]} {
|
|
set port [$port_iter next]
|
|
if {[$port is_bus]} {
|
|
puts "$cname/[$port bus_name] is_bus=1 has_members=[$port has_members]"
|
|
set mem_iter [$port member_iterator]
|
|
while {[$mem_iter has_next]} {
|
|
set member [$mem_iter next]
|
|
puts " member: [$member bus_name] is_bus_bit=[$member is_bus_bit]"
|
|
}
|
|
$mem_iter finish
|
|
}
|
|
if {[$port is_bundle]} {
|
|
puts "$cname/[$port bus_name] is_bundle=1"
|
|
}
|
|
}
|
|
$port_iter finish
|
|
}
|
|
puts "PASS: bus port member iteration"
|
|
|
|
############################################################
|
|
# Port capacitance with corner/min_max
|
|
############################################################
|
|
puts "--- port capacitance corner ---"
|
|
foreach cell_name {INV_X1 INV_X4 INV_X16 BUF_X1 BUF_X8 NAND2_X1 DFF_X1} {
|
|
set cell [get_lib_cell NangateOpenCellLibrary/$cell_name]
|
|
set port_iter [$cell liberty_port_iterator]
|
|
while {[$port_iter has_next]} {
|
|
set port [$port_iter next]
|
|
set dir [sta::liberty_port_direction $port]
|
|
if {$dir == "input"} {
|
|
catch {
|
|
set cap [$port capacitance [sta::cmd_corner] [sta::find_min_max "max"]]
|
|
puts "$cell_name/[$port bus_name] cap(max)=$cap"
|
|
}
|
|
catch {
|
|
set cap [$port capacitance [sta::cmd_corner] [sta::find_min_max "min"]]
|
|
puts "$cell_name/[$port bus_name] cap(min)=$cap"
|
|
}
|
|
}
|
|
}
|
|
$port_iter finish
|
|
}
|
|
puts "PASS: port capacitance corner"
|
|
|
|
############################################################
|
|
# Timing arc set queries
|
|
############################################################
|
|
puts "--- timing arc sets ---"
|
|
foreach cell_name {INV_X1 BUF_X1 DFF_X1 DFFR_X1 NAND2_X1 AOI21_X1 MUX2_X1 SDFF_X1 CLKGATETST_X1} {
|
|
set cell [get_lib_cell NangateOpenCellLibrary/$cell_name]
|
|
set arc_sets [$cell timing_arc_sets]
|
|
puts "$cell_name arc_sets=[llength $arc_sets]"
|
|
foreach arc_set $arc_sets {
|
|
set from_port [$arc_set from]
|
|
set to_port [$arc_set to]
|
|
set role [$arc_set role]
|
|
set is_check [sta::timing_role_is_check $role]
|
|
set from_name [$from_port bus_name]
|
|
set to_name [$to_port bus_name]
|
|
puts " $from_name -> $to_name is_check=$is_check"
|
|
# Query timing arcs within the set
|
|
set arcs [$arc_set timing_arcs]
|
|
foreach arc $arcs {
|
|
set from_edge [$arc from_edge_name]
|
|
set to_edge [$arc to_edge_name]
|
|
puts " $from_edge -> $to_edge"
|
|
}
|
|
}
|
|
}
|
|
puts "PASS: timing arc sets"
|
|
|
|
############################################################
|
|
# Sky130 cell queries (has pg_pin groups, different features)
|
|
############################################################
|
|
puts "--- Sky130 cell queries ---"
|
|
foreach cell_name {
|
|
sky130_fd_sc_hd__inv_1 sky130_fd_sc_hd__inv_2 sky130_fd_sc_hd__inv_4
|
|
sky130_fd_sc_hd__buf_1 sky130_fd_sc_hd__buf_2
|
|
sky130_fd_sc_hd__nand2_1 sky130_fd_sc_hd__nor2_1
|
|
sky130_fd_sc_hd__and2_1 sky130_fd_sc_hd__or2_1
|
|
sky130_fd_sc_hd__dfxtp_1 sky130_fd_sc_hd__dfrtp_1
|
|
sky130_fd_sc_hd__mux2_1
|
|
sky130_fd_sc_hd__dlxtp_1
|
|
sky130_fd_sc_hd__ebufn_1
|
|
} {
|
|
catch {
|
|
set cell [get_lib_cell sky130_fd_sc_hd__tt_025C_1v80/$cell_name]
|
|
puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]"
|
|
set port_iter [$cell liberty_port_iterator]
|
|
while {[$port_iter has_next]} {
|
|
set port [$port_iter next]
|
|
set func [$port function]
|
|
set dir [sta::liberty_port_direction $port]
|
|
set pwr [$port is_pwr_gnd]
|
|
if {$pwr} {
|
|
puts " [$port bus_name] pwr_gnd=1"
|
|
}
|
|
}
|
|
$port_iter finish
|
|
}
|
|
}
|
|
puts "PASS: Sky130 cell queries"
|
|
|
|
############################################################
|
|
# Operating conditions (exercises find_operating_conditions)
|
|
############################################################
|
|
puts "--- operating conditions ---"
|
|
set sky_lib [lindex [get_libs sky130_fd_sc_hd__tt_025C_1v80] 0]
|
|
set default_oc [$sky_lib default_operating_conditions]
|
|
if {$default_oc != "NULL"} {
|
|
puts "Sky130 default OC process=[$default_oc process] voltage=[$default_oc voltage] temp=[$default_oc temperature]"
|
|
}
|
|
puts "PASS: operating conditions"
|
|
|
|
############################################################
|
|
# IHP cell queries (different vendor, might have different features)
|
|
############################################################
|
|
puts "--- IHP cell queries ---"
|
|
foreach cell_name {
|
|
sg13g2_inv_1 sg13g2_inv_2
|
|
sg13g2_buf_1 sg13g2_buf_2
|
|
sg13g2_nand2_1 sg13g2_nor2_1
|
|
sg13g2_and2_1
|
|
sg13g2_dfrbp_1 sg13g2_dfrbp_2
|
|
sg13g2_ebufn_2
|
|
} {
|
|
catch {
|
|
set cell [get_lib_cell sg13g2_stdcell_typ_1p20V_25C/$cell_name]
|
|
puts "$cell_name is_buffer=[$cell is_buffer] is_inverter=[$cell is_inverter]"
|
|
set arc_sets [$cell timing_arc_sets]
|
|
puts " arc_sets=[llength $arc_sets]"
|
|
}
|
|
}
|
|
puts "PASS: IHP cell queries"
|
|
|
|
############################################################
|
|
# Ensure voltage waveforms (exercises ensureVoltageWaveforms)
|
|
############################################################
|
|
puts "--- ensure voltage waveforms ---"
|
|
catch {
|
|
set inv [get_lib_cell NangateOpenCellLibrary/INV_X1]
|
|
$inv ensure_voltage_waveforms
|
|
puts "PASS: INV_X1 ensure_voltage_waveforms"
|
|
}
|
|
|
|
catch {
|
|
set dff [get_lib_cell NangateOpenCellLibrary/DFF_X1]
|
|
$dff ensure_voltage_waveforms
|
|
puts "PASS: DFF_X1 ensure_voltage_waveforms"
|
|
}
|
|
puts "PASS: ensure voltage waveforms"
|
|
|
|
############################################################
|
|
# Liberty cell matching with regex patterns
|
|
############################################################
|
|
puts "--- liberty cell matching ---"
|
|
set ng_lib [lindex [get_libs NangateOpenCellLibrary] 0]
|
|
set inv_matches [$ng_lib find_liberty_cells_matching "INV_*" 0 0]
|
|
puts "INV_* matches = [llength $inv_matches]"
|
|
|
|
set dff_matches [$ng_lib find_liberty_cells_matching "DFF*" 0 0]
|
|
puts "DFF* matches = [llength $dff_matches]"
|
|
|
|
set all_matches [$ng_lib find_liberty_cells_matching "*" 0 0]
|
|
puts "* matches = [llength $all_matches]"
|
|
|
|
# Regex matching
|
|
set regex_matches [$ng_lib find_liberty_cells_matching {^INV_X[0-9]+$} 1 0]
|
|
puts "regex INV_X matches = [llength $regex_matches]"
|
|
|
|
# Port matching on a cell
|
|
set inv [get_lib_cell NangateOpenCellLibrary/INV_X1]
|
|
set port_matches [$inv find_liberty_ports_matching "*" 0 0]
|
|
puts "INV_X1 port * matches = [llength $port_matches]"
|
|
|
|
set port_matches [$inv find_liberty_ports_matching "A" 0 0]
|
|
puts "INV_X1 port A matches = [llength $port_matches]"
|
|
puts "PASS: liberty cell matching"
|
|
|
|
puts "ALL PASSED"
|