Skip to content

Commit 8bfc980

Browse files
committed
util: Take via resistances for fixed in RC correlation
OR has single per-layer via resistance setting (`set_layer_rc -via`) which applies to both estimation and final parasitics extraction. Given this the via resistances must enter the RC fit as constants, not variables. Signed-off-by: Martin Povišer <[email protected]>
1 parent acc382a commit 8bfc980

File tree

2 files changed

+48
-33
lines changed

2 files changed

+48
-33
lines changed

flow/util/correlateRC.py

Lines changed: 41 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,11 @@
1616
from sklearn.linear_model import LinearRegression
1717
import matplotlib.pyplot as plt
1818

19+
LAYER_HEADER_RE = re.compile("^([^\\(]+)\\(([^\\)]+)\\)$")
20+
1921
# Parse and validate arguments
2022
# =============================================================================
2123

22-
2324
def parse_args():
2425
parser = argparse.ArgumentParser(
2526
description="Determines layer capacitance and resistance values for OpenROAD flow designs"
@@ -101,9 +102,19 @@ def makeDict():
101102
exit(1)
102103
elif stack_line is None:
103104
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))
105+
name = layer
106+
is_routing = False
107+
via_resist = 0.0
108+
if layer.endswith(")"):
109+
# layer name has extra data
110+
match = LAYER_HEADER_RE.match(layer)
111+
assert match
112+
name = match.group(1)
113+
if match.group(2) == "routing":
114+
is_routing = True
115+
else:
116+
via_resist = float(match.group(2))
117+
stack.append((name, is_routing, via_resist))
107118
continue
108119

109120
tokens = line.strip().split(",")
@@ -125,12 +136,23 @@ def makeDict():
125136
active_layers.add(i)
126137

127138
data[design][netName]["layer_lengths"] = layer_lengths
139+
data[design][netName]["routable_layer_lengths"] = [
140+
length
141+
for i, length in enumerate(layer_lengths)
142+
# ignore non-routable layers
143+
if stack[i][1]
144+
]
128145
data[design][netName]["wire_length"] = sum(
129146
length
130147
for i, length in enumerate(layer_lengths)
131-
# ignore contribution from via layers
148+
# ignore non-routable layers
132149
if stack[i][1]
133150
)
151+
data[design][netName]["grt_via_res"] = sum(
152+
(length * stack[i][2])
153+
for i, length in enumerate(layer_lengths)
154+
if not stack[i][1]
155+
)
134156

135157
################################################################
136158

@@ -227,15 +249,15 @@ def makeDict():
227249
for net in data[design]:
228250
rcx_res = data[design][net]["rcx_res"]
229251
if rcx_res > 0:
230-
x.append(data[design][net]["layer_lengths"])
231-
y.append(rcx_res)
252+
x.append(data[design][net]["routable_layer_lengths"])
253+
y.append(rcx_res - data[design][net]["grt_via_res"])
232254

233255
x = np.array(x)
234256
y = np.array(y)
235257

236258
res_model = LinearRegression(fit_intercept=False).fit(x, y)
237259
r_sq = res_model.score(x, y)
238-
print("Resistance coefficient of determination: {:.4f}".format(r_sq))
260+
print("# Resistance coefficient of determination: {:.4f}".format(r_sq))
239261

240262
################################################################
241263

@@ -245,39 +267,25 @@ def makeDict():
245267
y = []
246268
for design in data:
247269
for net in data[design]:
248-
lengths = data[design][net]["layer_lengths"]
249-
x.append([length for length, layer in zip(lengths, stack) if layer[1]])
270+
x.append(data[design][net]["routable_layer_lengths"])
250271
y.append(data[design][net]["rcx_cap"])
251272

252273
x = np.array(x)
253274
y = np.array(y)
254275

255276
cap_model = LinearRegression(fit_intercept=False).fit(x, y)
256277
r_sq = cap_model.score(x, y)
257-
print("Capacitance coefficient of determination: {:.4f}".format(r_sq))
258-
259-
print("Updated layer resistance {}/um capacitance {}/um".format(res_unit, cap_unit))
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:
278+
print("# Capacitance coefficient of determination: {:.4f}".format(r_sq))
279+
print("# Updated layer resistance {}/um capacitance {}/um".format(res_unit, cap_unit))
280+
281+
routable_layers = [layer for layer in stack if layer[1]]
282+
for i, layer in enumerate(routable_layers):
283+
res_coeff = res_model.coef_[i]
284+
cap_coeff = cap_model.coef_[i]
285+
if res_coeff != 0.0 or cap_coeff != 0.0:
278286
print(
279-
"set_layer_rc -via {} -resistance {:.5E}".format(
280-
layer[0], res_coeff / res_scale
287+
"set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}".format(
288+
layer[0], res_coeff / res_scale, cap_coeff / cap_scale
281289
)
282290
)
283291

flow/util/write_net_rc.tcl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,16 @@ proc write_rc_csv { filename } {
4444
foreach layer [[ord::get_db_tech] getLayers] {
4545
set routing [expr [$layer getRoutingLevel] != 0]
4646
set is_routing([$layer getNumber]) $routing
47+
set is_routing([$layer getNumber]) $routing
4748
puts -nonewline $stream " [$layer getName]"
4849
if $routing {
4950
puts -nonewline $stream "(routing)"
51+
} else {
52+
# insert via resistance information
53+
set via_resist [$layer getResistance]
54+
if { $via_resist != 0.0 } {
55+
puts -nonewline $stream "([format %.4e $via_resist])"
56+
}
5057
}
5158
}
5259
puts $stream ""

0 commit comments

Comments
 (0)