Skip to content

Commit

Permalink
Merge pull request #6501 from jeffng-or/tcl-unit-tests
Browse files Browse the repository at this point in the history
Tcl versions of Python unit tests
  • Loading branch information
maliberty authored Jan 11, 2025
2 parents 2e35fb1 + d777881 commit 8a2b35f
Show file tree
Hide file tree
Showing 14 changed files with 1,249 additions and 43 deletions.
5 changes: 4 additions & 1 deletion src/odb/src/swig/common/odb.i
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ using namespace odb;
%typemap(out) (uint) = (int);
%typemap(out) (uint64) = (long);
%typemap(out) (int64_t) = (long);
%apply int* OUTPUT {int* x, int* y};
%apply int* OUTPUT {int* x, int* y, int& ext};

%ignore odb::dbTechLayerAntennaRule::pwl_pair;
%ignore odb::dbTechLayerAntennaRule::getDiffPAR() const;
Expand Down Expand Up @@ -88,6 +88,8 @@ using namespace odb;
%include "dbhelpers.i"
%include "dbdiff.i"

%rename(getPoint_ext) odb::dbWireDecoder::getPoint(int& x, int& y, int& ext) const;

%include "odb/dbViaParams.h"
%include "odb/dbWireCodec.h"
%include "odb/dbBlockCallBackObj.h"
Expand All @@ -98,3 +100,4 @@ using namespace odb;
%include "odb/wOrder.h"

std::string generateMacroPlacementString(odb::dbBlock* block);

1 change: 1 addition & 0 deletions src/odb/test/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ or_integration_tests(
test_iterm
test_module
test_net
test_wire_codec
)

# Skipped
Expand Down
211 changes: 211 additions & 0 deletions src/odb/test/helper.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
# Converted from helper.py

proc createSimpleDB {{use_default_db 0}} {
if {$use_default_db} {
set db [ord::get_db]
} else {
set db [odb::dbDatabase_create]
}
set tech [odb::dbTech_create $db "simple_tech"]
set L1 [odb::dbTechLayer_create $tech "L1" "ROUTING"]
set lib [odb::dbLib_create $db "lib" $tech "/"]
set chip [odb::dbChip_create $db]
set and2 [createMaster2X1 $lib "and2" 1000 1000 "a" "b" "o"]
set or2 [createMaster2X1 $lib "or2" 500 500 "a" "b" "o"]
return [list $db $lib]
}

proc createMultiLayerDB {} {
set db [odb::dbDatabase_create]
set tech [odb::dbTech_create $db "multi_tech"]

set m1 [odb::dbTechLayer_create $tech "M1" "ROUTING"]
$m1 setWidth 2000
set m2 [odb::dbTechLayer_create $tech "M2" "ROUTING"]
$m2 setWidth 2000
set m3 [odb::dbTechLayer_create $tech "M3" "ROUTING"]
$m3 setWidth 2000

set v12 [odb::dbTechVia_create $tech "VIA12"]
odb::dbBox_create $v12 $m1 0 0 2000 2000
odb::dbBox_create $v12 $m2 0 0 2000 2000

set v23 [odb::dbTechVia_create $tech "VIA23"]
odb::dbBox_create $v23 $m2 0 0 2000 2000
odb::dbBox_create $v23 $m3 0 0 2000 2000

return [list $db $tech $m1 $m2 $m3 $v12 $v23]
}

# logical expr OUT = (IN1&IN2)
#
# (n1) +-----
# IN1--------|a \ (n3)
# (n2) | (i1)o|-----------OUT
# IN2--------|b /
# +-----
proc create1LevelBlock {db lib parent} {
set blockName "1LevelBlock"
set block [odb::dbBlock_create $parent $blockName [$lib getTech] ","]
# Creating Master and2 and instance inst
set and2 [$lib findMaster "and2"]
set inst [odb::dbInst_create $block $and2 "inst"]
# creating our nets
set n1 [odb::dbNet_create $block "n1"]
set n2 [odb::dbNet_create $block "n2"]
set n3 [odb::dbNet_create $block "n3"]
set IN1 [odb::dbBTerm_create $n1 "IN1"]
$IN1 setIoType "INPUT"
set IN2 [odb::dbBTerm_create $n2 "IN2"]
$IN2 setIoType "INPUT"
set OUT [odb::dbBTerm_create $n3 "OUT"]
$OUT setIoType "OUTPUT"
# connecting nets
set a [$inst findITerm "a"]
$a connect $n1
set b [$inst findITerm "b"]
$b connect $n2
set o [$inst findITerm "o"]
$o connect $n3
return $block
}


# logical expr OUT = (IN1&IN2) | (IN3&IN4)
# (n1) +-----
# IN1--------|a \ (n5)
# (n2) | (i1)o|-----------+
# IN2--------|b / | +-------
# +----- +--------\a \ (n7)
# ) (i3)o|---------------OUT
# (n3) +----- +--------/b /
# IN3--------|a \ (n6) | +-------
# (n4) | (i2)o|-----------+
# IN4--------|b /
# +-----
proc create2LevelBlock { db lib parent } {
set blockName "2LevelBlock"
set block [odb::dbBlock_create $parent $blockName [$lib getTech] ","]

set and2 [$lib findMaster "and2"]
set or2 [$lib findMaster "or2"]
# creating instances
set i1 [odb::dbInst_create $block $and2 "i1"]
set i2 [odb::dbInst_create $block $and2 "i2"]
set i3 [odb::dbInst_create $block $or2 "i3"]
# creating nets and block terms
set n1 [odb::dbNet_create $block "n1"]
set n2 [odb::dbNet_create $block "n2"]
set n3 [odb::dbNet_create $block "n3"]
set n4 [odb::dbNet_create $block "n4"]
set n5 [odb::dbNet_create $block "n5"]
set n6 [odb::dbNet_create $block "n6"]
set n7 [odb::dbNet_create $block "n7"]

set IN1 [odb::dbBTerm_create $n1 "IN1"]
$IN1 setIoType "INPUT"
set IN2 [odb::dbBTerm_create $n2 "IN2"]
$IN2 setIoType "INPUT"
set IN3 [odb::dbBTerm_create $n3 "IN3"]
$IN3 setIoType "INPUT"
set IN4 [odb::dbBTerm_create $n4 "IN4"]
$IN4 setIoType "INPUT"
set OUT [odb::dbBTerm_create $n7 "OUT"]
$OUT setIoType "OUTPUT"
# connecting $nets
set i1_a [$i1 findITerm "a"]
$i1_a connect $n1
set i1_b [$i1 findITerm "b"]
$i1_b connect $n2
set i1_o [$i1 findITerm "o"]
$i1_o connect $n5

set i2_a [$i2 findITerm "a"]
$i2_a connect $n3
set i2_b [$i2 findITerm "b"]
$i2_b connect $n4
set i2_o [$i2 findITerm "o"]
$i2_o connect $n6

set i3_a [$i3 findITerm "a"]
$i3_a connect $n5
set i3_b [$i3 findITerm "b"]
$i3_b connect $n6
set i3_o [$i3 findITerm "o"]
$i3_o connect $n7

set P1 [odb::dbBPin_create $IN1]
set P2 [odb::dbBPin_create $IN2]
set P3 [odb::dbBPin_create $IN3]
set P4 [odb::dbBPin_create $IN4]
set P5 [odb::dbBPin_create $OUT]

return $block
}

# +-----
# |in1 \
# out|
# |in2 /
# +-----
proc createMaster2X1 {lib name width height in1 in2 out} {
set master [odb::dbMaster_create $lib $name]
$master setWidth $width
$master setHeight $height
$master setType "CORE"
odb::dbMTerm_create $master $in1 "INPUT"
odb::dbMTerm_create $master $in2 "INPUT"
odb::dbMTerm_create $master $out "OUTPUT"
$master setFrozen
return $master
}

proc createMaster3X1 {lib name width height in1 in2 in3 out} {
set master [odb::dbMaster_create $lib $name]
$master setWidth $width
$master setHeight $height
$master setType "CORE"
odb::dbMTerm_create $master $in1 "INPUT"
odb::dbMTerm_create $master $in2 "INPUT"
odb::dbMTerm_create $master $in3 "INPUT"
odb::dbMTerm_create $master $out "OUTPUT"
$master setFrozen
return $master
}

#
# Assertion helper
#
proc assert { condition { message "assertion failed" } } {
# Try to evaluate the condition as an expression.
# This will work for numeric comparisons (e.g., $x == 5)
if {![catch {uplevel 1 expr $condition}]} {
# If the expression evaluates successfully and returns false, raise an error
if {![uplevel 1 expr $condition]} {
error $message
}
} else {
# If the condition involves string comparison, use string equal or eq.
if {[string equal $condition ""]} {
error $message
}
}
}

#
# List comparison helper, since struct::list isn't available
# returns true if two lists are the same
#
proc lequal {l1 l2} {
foreach elem $l1 {
if { $elem ni $l2 } {
return false
}
}
foreach elem $l2 {
if { $elem ni $l1 } {
return false
}
}
return true
}
156 changes: 156 additions & 0 deletions src/odb/test/test_block.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
#package require control
#control::control assert enabled 1
#
# Converted from test_block.py
# TclTest isn't available so just calling tests sequentially
#
source "helper.tcl"

proc placeInst {inst x y} {
$inst setLocation $x $y
$inst setPlacementStatus "PLACED"
}

proc placeBPin {bpin layer x1 y1 x2 y2} {
odb::dbBox_create $bpin $layer $x1 $y1 $x2 $y2
$bpin setPlacementStatus "PLACED"
}

# Set up data
proc setUp {} {
lassign [createSimpleDB] db lib
set parentBlock [odb::dbBlock_create [$db getChip] "Parent"]
set block [create2LevelBlock $db $lib $parentBlock]
$block setCornerCount 4
set extcornerblock [$block createExtCornerBlock 1]
odb::dbTechNonDefaultRule_create $block "non_default_1"
set parentRegion [odb::dbRegion_create $block "parentRegion"]
return [list $db $lib $block $parentBlock]
}

proc tearDown {db} {
odb::dbDatabase_destroy $db
}

proc test_find {} {
lassign [setUp] db lib block parentBlock
# bterm
assert {[[$block findBTerm "IN1"] getName] == "IN1"}
assert {[$block findBTerm "in1"] == "NULL"}
# child
assert {[[$parentBlock findChild "2LevelBlock"] getName] == "2LevelBlock"}
assert {[$parentBlock findChild "1LevelBlock"] == "NULL"}
# inst
assert {[[$block findInst "i3"] getName] == "i3"}
assert {[$parentBlock findInst "i3"] == "NULL"}
# net
assert {[[$block findNet "n2"] getName] == "n2"}
assert {[$block findNet "a"] == "NULL"}
# iterm
set iterm [$block findITerm "i1o"]
assert {[[$iterm getInst] getName] == "i1"}
assert {[[$iterm getMTerm] getName] == "o"}
assert {[$block findITerm "i1\o"] == "NULL"}
# extcornerblock
assert {[[$block findExtCornerBlock 1] getName] == "extCornerBlock__1"}
assert {[$block findExtCornerBlock 0] == "NULL"}
# nondefaultrule
assert {[[$block findNonDefaultRule "non_default_1"] getName] == "non_default_1"}
assert {[$block findNonDefaultRule "non_default_2"] == "NULL"}
# region
assert {[[$block findRegion "parentRegion"] getName] == "parentRegion"}
tearDown $db
}

proc check_box_rect {block min_x min_y max_x max_y} {
set box [$block getBBox]
assert {[$box xMin] == $min_x} [format "bbox xMin doesn't match: %d %d" [$box xMin] $min_x]
assert {[$box xMax] == $max_x} [format "bbox xMax doesn't match: %d %d" [$box xMax] $max_x]
assert {[$box yMin] == $min_y} [format "bbox yMin doesn't match: %d %d" [$box yMin] $min_y]
assert {[$box yMax] == $max_y} [format "bbox yMax doesn't match: %d %d" [$box yMax] $max_y]
}

proc block_placement {block lib test_num flag} {
if {($flag && $test_num == 1) || (!$flag && $test_num >= 1)} {
if {$flag} {
puts "here"
}
placeInst [$block findInst "i1"] 0 3000
placeInst [$block findInst "i2"] -1000 0
placeInst [$block findInst "i3"] 2000 -1000
}
if {($flag && $test_num == 2) || (!$flag && $test_num >= 2)} {
placeBPin [lindex [[$block findBTerm "OUT"] getBPins] 0] \
[[$lib getTech] findLayer "L1"] 2500 -1000 2550 -950
}
if {($flag && $test_num == 3) || (!$flag && $test_num >= 3)} {
odb::dbObstruction_create $block [[$lib getTech] findLayer "L1"] \
-1500 0 -1580 50
}
if {($flag && $test_num == 4) || (!$flag && $test_num >= 4)} {
set n_s [odb::dbNet_create $block "n_s"]
set swire [odb::dbSWire_create $n_s "NONE"]
odb::dbSBox_create $swire [[$lib getTech] findLayer "L1"] \
0 4000 100 4100 "NONE"
}
if {($flag && $test_num == 5) || (!$flag && $test_num >= 5)} {
# TODO ADD WIRE
}
}

proc test_bbox0 {} {
lassign [setUp] db lib block parentBlock
set box [$block getBBox]
check_box_rect $block 0 0 0 0
tearDown $db
}

proc test_bbox1 {} {
lassign [setUp] db lib block parentBlock
set box [$block getBBox]
block_placement $block $lib 1 false
check_box_rect $block -1000 -1000 2500 4000
tearDown $db
}

proc test_bbox2 {} {
lassign [setUp] db lib block parentBlock
set box [$block getBBox]
block_placement $block $lib 2 false
check_box_rect $block -1000 -1000 2550 4000
tearDown $db
}

proc test_bbox3 {} {
lassign [setUp] db lib block parentBlock
# block_placement $block 2 false
# set box [$block getBBox]
# block_placement $block 3 true
set layer [[$lib getTech] findLayer "L1"]
placeInst [$block findInst "i1"] 0 3000
placeInst [$block findInst "i2"] -1000 0
placeInst [$block findInst "i3"] 2000 -1000
placeBPin [lindex [[$block findBTerm "OUT"] getBPins] 0] \
$layer 2500 -1000 2550 -950
set box [$block getBBox]
odb::dbObstruction_create $block $layer -1500 0 -1580 50
check_box_rect $block -1580 -1000 2550 4000
tearDown $db
}

proc test_bbox4 {} {
lassign [setUp] db lib block parentBlock
set box [$block getBBox]
block_placement $block $lib 4 false
check_box_rect $block -1580 -1000 2550 4100
tearDown $db
}

test_find
test_bbox0
test_bbox1
test_bbox2
test_bbox3
test_bbox4
puts "pass"
exit 0
Loading

0 comments on commit 8a2b35f

Please sign in to comment.