Skip to content

Commit 01f6610

Browse files
committed
util: Update and enhance correlateRC
Use `6_final.odb` guides as the basis for correlation. Make changes to the `6_net_rc.csv` format: * include information about the layer stack * include via count * include net classification (signal/clock) Change the method of obtaining the ground truth resistance from STA parasitic network. Include vias in correlation. Signed-off-by: Martin Povišer <[email protected]>
1 parent 9c1f98e commit 01f6610

File tree

3 files changed

+148
-104
lines changed

3 files changed

+148
-104
lines changed

flow/util/correlateRC.py

Lines changed: 103 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,10 @@
55
# Use ORFS 'make write_net_rc' to write cap files.
66

77
import os
8-
from sys import exit
8+
from sys import exit, stderr
99
from collections import defaultdict
1010

11+
import traceback
1112
import collections
1213
import argparse
1314
import re
@@ -81,39 +82,55 @@ def makeDict():
8182

8283
data = makeDict()
8384

85+
stack = []
86+
stack_line = None
87+
88+
# indices of relevant layers (routable layers or via layers)
89+
active_layers = set()
90+
8491
# Parse the cap CSV file generated by compare_rc_script.tcl
8592
for rc_file in args.rc_file:
8693
design = rc_file
8794
print("reading", design)
8895
with open(rc_file) as f:
8996
nonGrtNets = 0
9097
for line in f:
98+
if line.startswith("# stack: "):
99+
if stack_line is not None and stack_line != line:
100+
print(f"layer stack inconsistent", file=stderr)
101+
exit(1)
102+
elif stack_line is None:
103+
for layer in line.removeprefix("# stack: ").strip().split(" "):
104+
name = layer.removesuffix("(routing)")
105+
is_routing = layer.endswith("(routing)")
106+
stack.append((name, is_routing))
107+
continue
108+
91109
tokens = line.strip().split(",")
92110
netName = tokens[0]
93-
gpl_res = float(tokens[1])
94-
gpl_cap = float(tokens[2])
95-
grt_res = float(tokens[3])
96-
grt_cap = float(tokens[4])
97-
rcx_res = float(tokens[5])
98-
rcx_cap = float(tokens[6])
99-
100-
data[design][netName]["gpl_res"] = gpl_res
101-
data[design][netName]["gpl_cap"] = gpl_cap
102-
data[design][netName]["grt_res"] = grt_res
103-
data[design][netName]["grt_cap"] = grt_cap
104-
data[design][netName]["rcx_res"] = rcx_res
105-
data[design][netName]["rcx_cap"] = rcx_cap
106-
107-
layer_lengths = []
108-
layer_names = []
109-
wire_length = 0.0
110-
for i in range(7, len(tokens), 2):
111-
layer_names.append(tokens[i])
112-
layer_length = float(tokens[i + 1])
113-
layer_lengths.append(layer_length)
114-
wire_length += layer_length
111+
112+
data[design][netName] = {
113+
"type": tokens[1],
114+
"gpl_res": float(tokens[2]),
115+
"gpl_cap": float(tokens[3]),
116+
"grt_res": float(tokens[4]),
117+
"grt_cap": float(tokens[5]),
118+
"rcx_res": float(tokens[6]),
119+
"rcx_cap": float(tokens[7]),
120+
}
121+
122+
layer_lengths = [float(tok) for tok in tokens[8:]]
123+
for i, length in enumerate(layer_lengths):
124+
if length > 0:
125+
active_layers.add(i)
126+
115127
data[design][netName]["layer_lengths"] = layer_lengths
116-
data[design][netName]["wire_length"] = wire_length
128+
data[design][netName]["wire_length"] = sum(
129+
length
130+
for i, length in enumerate(layer_lengths)
131+
# ignore contribution from via layers
132+
if stack[i][1]
133+
)
117134

118135
################################################################
119136

@@ -210,8 +227,7 @@ def makeDict():
210227
for net in data[design]:
211228
rcx_res = data[design][net]["rcx_res"]
212229
if rcx_res > 0:
213-
layer_lengths = data[design][net]["layer_lengths"]
214-
x.append(layer_lengths)
230+
x.append(data[design][net]["layer_lengths"])
215231
y.append(rcx_res)
216232

217233
x = np.array(x)
@@ -229,8 +245,8 @@ def makeDict():
229245
y = []
230246
for design in data:
231247
for net in data[design]:
232-
layer_lengths = data[design][net]["layer_lengths"]
233-
x.append(layer_lengths)
248+
lengths = data[design][net]["layer_lengths"]
249+
x.append([length for length, layer in zip(lengths, stack) if layer[1]])
234250
y.append(data[design][net]["rcx_cap"])
235251

236252
x = np.array(x)
@@ -241,48 +257,72 @@ def makeDict():
241257
print("Capacitance coefficient of determination: {:.4f}".format(r_sq))
242258

243259
print("Updated layer resistance {}/um capacitance {}/um".format(res_unit, cap_unit))
244-
for layer, res_coeff, cap_coeff in zip(layer_names, res_model.coef_, cap_model.coef_):
245-
if res_coeff > 0.0 or cap_coeff > 0.0:
260+
routable_layer_no = 0
261+
for i, layer, res_coeff in zip(range(len(stack)), stack, res_model.coef_):
262+
if not layer[1] or i not in active_layers:
263+
# skip non-routable and non-active layers
264+
continue
265+
cap_coeff = cap_model.coef_[routable_layer_no]
266+
print(
267+
"set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format(
268+
layer[0], res_coeff / res_scale, cap_coeff / cap_scale
269+
)
270+
)
271+
routable_layer_no += 1
272+
273+
for i, layer, res_coeff in zip(range(len(stack)), stack, res_model.coef_):
274+
if layer[1] or i not in active_layers:
275+
# skip routable and non-active layers
276+
continue
277+
if res_coeff != 0.0:
246278
print(
247-
"set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format(
248-
layer, res_coeff / res_scale, cap_coeff / cap_scale
279+
"set_layer_rc -via {} -resistance {:.5E}".format(
280+
layer[0], res_coeff / res_scale
249281
)
250282
)
251283

252284
################################################################
253285

254-
x = []
255-
y = []
256-
for design in data:
257-
for net in data[design]:
258-
wire_res = data[design][net]["rcx_res"]
259-
wire_length = data[design][net]["wire_length"]
260-
if wire_res != 0.0:
261-
x.append([wire_length])
262-
y.append(wire_res)
263-
264-
x = np.array(x)
265-
y = np.array(y)
266-
267-
wire_res_model = LinearRegression(fit_intercept=False).fit(x, y)
268-
wire_res = wire_res_model.coef_[0]
269286

270-
x = []
271-
y = []
272-
for design in data:
273-
for net in data[design]:
274-
wire_length = data[design][net]["wire_length"]
275-
x.append([wire_length])
276-
y.append(data[design][net]["rcx_cap"])
287+
def generic_rc_fit(type_sieve):
288+
x = []
289+
y = []
290+
for design in data:
291+
for net in data[design]:
292+
net_type = data[design][net]["type"]
293+
wire_res = data[design][net]["rcx_res"]
294+
wire_length = data[design][net]["wire_length"]
295+
if net_type in type_sieve and wire_res != 0.0:
296+
x.append([wire_length])
297+
y.append(wire_res)
298+
x = np.array(x)
299+
y = np.array(y)
300+
wire_res_model = LinearRegression(fit_intercept=False).fit(x, y)
301+
wire_res = wire_res_model.coef_[0]
302+
303+
x = []
304+
y = []
305+
for design in data:
306+
for net in data[design]:
307+
net_type = data[design][net]["type"]
308+
if net_type in type_sieve:
309+
wire_length = data[design][net]["wire_length"]
310+
wire_cap = data[design][net]["rcx_cap"]
311+
x.append([wire_length])
312+
y.append(wire_cap)
313+
x = np.array(x)
314+
y = np.array(y)
315+
wire_cap_model = LinearRegression(fit_intercept=False).fit(x, y)
316+
wire_cap = wire_cap_model.coef_[0]
317+
318+
return "-resistance {:.5E} -capacitance {:.5E}".format(
319+
wire_res / res_scale, wire_cap / cap_scale
320+
)
277321

278-
x = np.array(x)
279-
y = np.array(y)
280322

281-
wire_cap_model = LinearRegression(fit_intercept=False).fit(x, y)
282-
wire_cap = wire_cap_model.coef_[0]
323+
print("# Combined fit:")
324+
print("set_wire_rc " + generic_rc_fit(["signal", "clock"]))
283325

284-
print(
285-
"set_wire_rc -resistance {:.5E} -capacitance {:.5E}".format(
286-
wire_res / res_scale, wire_cap / cap_scale
287-
)
288-
)
326+
print("# Split signal/clock fit:")
327+
print("set_wire_rc -signal " + generic_rc_fit(["signal"]))
328+
print("set_wire_rc -clock " + generic_rc_fit(["clock"]))

flow/util/write_net_rc.tcl

Lines changed: 43 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,25 +37,52 @@ proc write_rc_csv { filename } {
3737
upvar 1 grt rc_var2
3838
upvar 1 rcx rc_var3
3939

40-
set max_layer_name $::env(MAX_ROUTING_LAYER)
41-
set max_layer [[[ord::get_db_tech] findLayer $max_layer_name] getRoutingLevel]
42-
set min_layer_name $::env(MIN_ROUTING_LAYER)
43-
set min_layer [[[ord::get_db_tech] findLayer $min_layer_name] getRoutingLevel]
40+
set tech [ord::get_db_tech]
4441
set stream [open $filename "w"]
42+
43+
puts -nonewline $stream "# stack:"
44+
foreach layer [[ord::get_db_tech] getLayers] {
45+
set routing [expr [$layer getRoutingLevel] != 0]
46+
set is_routing([$layer getNumber]) $routing
47+
puts -nonewline $stream " [$layer getName]"
48+
if $routing {
49+
puts -nonewline $stream "(routing)"
50+
}
51+
}
52+
puts $stream ""
53+
54+
set use_drt_data [env_var_exists_and_non_empty CORRELATE_DRT_WIRELENGTH]
55+
4556
foreach net [get_nets *] {
46-
set net_name [get_full_name $net]
47-
lassign $rc_var1($net_name) wire_res1 wire_cap1
48-
lassign $rc_var2($net_name) wire_res2 wire_cap2
49-
lassign $rc_var3($net_name) wire_res3 wire_cap3
50-
puts -nonewline $stream "[get_full_name $net],[format %.3e $wire_res1],[format %.3e $wire_cap1],[format %.3e $wire_res2],[format %.3e $wire_cap2],[format %.3e $wire_res3],[format %.3e $wire_cap3]"
5157
set db_net [sta::sta_to_db_net $net]
52-
set layer_lengths [grt::route_layer_lengths $db_net]
53-
for {set layer $min_layer} {$layer <= $max_layer} {incr layer} {
54-
set layer_name [[[ord::get_db_tech] findRoutingLayer $layer] getName]
55-
set length [lindex $layer_lengths $layer]
56-
puts -nonewline $stream ",$layer_name,[ord::dbu_to_microns $length]"
58+
set type [$db_net getSigType]
59+
if {([string equal $type "CLOCK"] || [string equal $type "SIGNAL"]) &&
60+
(!$use_drt_data || [$db_net getWire] ne "NULL")} {
61+
set net_name [get_full_name $net]
62+
lassign $rc_var1($net_name) wire_res1 wire_cap1
63+
lassign $rc_var2($net_name) wire_res2 wire_cap2
64+
lassign $rc_var3($net_name) wire_res3 wire_cap3
65+
puts -nonewline $stream "[get_full_name $net],[expr {[string equal $type "CLOCK"] ? "clock" : "signal"}],"
66+
puts -nonewline $stream "[format %.3e $wire_res1],[format %.3e $wire_cap1],[format %.3e $wire_res2],[format %.3e $wire_cap2],[format %.3e $wire_res3],[format %.3e $wire_cap3]"
67+
set db_net [sta::sta_to_db_net $net]
68+
69+
if $use_drt_data {
70+
set layer_lengths [drt::route_layer_lengths [$db_net getWire]]
71+
} else {
72+
set layer_lengths [grt::route_layer_lengths $db_net]
73+
}
74+
75+
for {set layer 0} {$layer < [$tech getLayerCount]} {incr layer} {
76+
set length [lindex $layer_lengths $layer]
77+
if $is_routing($layer) {
78+
puts -nonewline $stream ",[ord::dbu_to_microns $length]"
79+
} else {
80+
puts -nonewline $stream ",$length"
81+
}
82+
}
83+
84+
puts $stream ""
5785
}
58-
puts $stream ""
5986
}
6087
close $stream
6188
}
@@ -73,19 +100,7 @@ proc record_wire_rc { var_name } {
73100

74101
# Only works or makes sense for 2 pin nets.
75102
proc net_wire_res { net } {
76-
set pins [get_pins -of_object $net]
77-
if { [llength $pins] == 2 } {
78-
lassign $pins pin1 pin2
79-
if { [$pin1 is_driver] } {
80-
set drvr $pin1
81-
} else {
82-
set drvr $pin2
83-
}
84-
lassign [sta::find_pi_elmore $drvr rise max] c2 rpi c1
85-
return $rpi
86-
} else {
87-
return 0.0
88-
}
103+
return [rsz::sum_parasitic_network_resist $net]
89104
}
90105

91106
proc net_wire_cap { net } {

flow/util/write_net_rc_script.tcl

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,15 @@
11
source $::env(SCRIPTS_DIR)/load.tcl
2-
# Note 6_final.def has wires that prevent global routing.
3-
load_design 4_1_cts.odb 4_cts.sdc
2+
load_design 6_final.odb 6_final.sdc
43

54
source $::env(UTILS_DIR)/write_net_rc.tcl
65

76
estimate_parasitics -placement
87
record_wire_rc gpl
98

10-
if {[env_var_exists_and_non_empty FASTROUTE_TCL]} {
11-
source $env(FASTROUTE_TCL)
12-
} else {
13-
set_global_routing_layer_adjustment $env(MIN_ROUTING_LAYER)-$env(MAX_ROUTING_LAYER) 0.5
14-
set_routing_layers -signal $env(MIN_ROUTING_LAYER)-$env(MAX_ROUTING_LAYER)
15-
set_macro_extension 2
16-
}
17-
18-
global_route -congestion_iterations 100
19-
209
estimate_parasitics -global_routing
2110
record_wire_rc grt
2211

23-
read_spef -quiet -reduce_to pi_elmore $::env(RESULTS_DIR)/6_final.spef
12+
read_spef $::env(RESULTS_DIR)/6_final.spef
2413
record_wire_rc rcx
2514

2615
#compare_wire_rc 50 grt rcx

0 commit comments

Comments
 (0)