55# Use ORFS 'make write_net_rc' to write cap files.
66
77import os
8- from sys import exit
8+ from sys import exit , stderr
99from collections import defaultdict
1010
11+ import traceback
1112import collections
1213import argparse
1314import re
@@ -81,39 +82,55 @@ def makeDict():
8182
8283data = 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
8592for 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
217233x = np .array (x )
@@ -229,8 +245,8 @@ def makeDict():
229245y = []
230246for 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
236252x = np .array (x )
@@ -241,48 +257,72 @@ def makeDict():
241257print ("Capacitance coefficient of determination: {:.4f}" .format (r_sq ))
242258
243259print ("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" ]))
0 commit comments