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,53 @@ 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+ # ignore via counts
130+ length for i , length in enumerate (layer_lengths ) if stack [i ][1 ]
131+ )
117132
118133################################################################
119134
@@ -210,8 +225,7 @@ def makeDict():
210225 for net in data [design ]:
211226 rcx_res = data [design ][net ]["rcx_res" ]
212227 if rcx_res > 0 :
213- layer_lengths = data [design ][net ]["layer_lengths" ]
214- x .append (layer_lengths )
228+ x .append (data [design ][net ]["layer_lengths" ])
215229 y .append (rcx_res )
216230
217231x = np .array (x )
@@ -229,8 +243,8 @@ def makeDict():
229243y = []
230244for design in data :
231245 for net in data [design ]:
232- layer_lengths = data [design ][net ]["layer_lengths" ]
233- x .append (layer_lengths )
246+ lengths = data [design ][net ]["layer_lengths" ]
247+ x .append ([ length for length , layer in zip ( lengths , stack ) if layer [ 1 ]] )
234248 y .append (data [design ][net ]["rcx_cap" ])
235249
236250x = np .array (x )
@@ -241,48 +255,72 @@ def makeDict():
241255print ("Capacitance coefficient of determination: {:.4f}" .format (r_sq ))
242256
243257print ("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 :
258+ routable_layer_no = 0
259+ for i , layer , res_coeff in zip (range (len (stack )), stack , res_model .coef_ ):
260+ if not layer [1 ] or i not in active_layers :
261+ # skip non-routable and non-active layers
262+ continue
263+ cap_coeff = cap_model .coef_ [routable_layer_no ]
264+ #if res_coeff > 0.0 or cap_coeff > 0.0:
265+ print (
266+ "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}" .format (
267+ layer [0 ], res_coeff / res_scale , cap_coeff / cap_scale
268+ )
269+ )
270+ routable_layer_no += 1
271+
272+ for i , layer , res_coeff in zip (range (len (stack )), stack , res_model .coef_ ):
273+ if layer [1 ] or i not in active_layers :
274+ # skip routable and non-active layers
275+ continue
276+ if res_coeff != 0.0 :
246277 print (
247- "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}" .format (
248- layer , res_coeff / res_scale , cap_coeff / cap_scale
278+ "set_layer_rc -via {} -resistance {:.5E}" .format (
279+ layer [ 0 ] , res_coeff / res_scale
249280 )
250281 )
251282
252283################################################################
253284
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 ]
269-
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" ])
285+ def generic_rc_fit (type_sieve ):
286+ x = []
287+ y = []
288+ for design in data :
289+ for net in data [design ]:
290+ net_type = data [design ][net ]["type" ]
291+ wire_res = data [design ][net ]["rcx_res" ]
292+ wire_length = data [design ][net ]["wire_length" ]
293+ if net_type in type_sieve and wire_res != 0.0 :
294+ x .append ([wire_length ])
295+ y .append (wire_res )
296+ x = np .array (x )
297+ y = np .array (y )
298+ wire_res_model = LinearRegression (fit_intercept = False ).fit (x , y )
299+ wire_res = wire_res_model .coef_ [0 ]
300+
301+ x = []
302+ y = []
303+ for design in data :
304+ for net in data [design ]:
305+ net_type = data [design ][net ]["type" ]
306+ if net_type in type_sieve :
307+ wire_length = data [design ][net ]["wire_length" ]
308+ wire_cap = data [design ][net ]["rcx_cap" ]
309+ x .append ([wire_length ])
310+ y .append (wire_cap )
311+ x = np .array (x )
312+ y = np .array (y )
313+ wire_cap_model = LinearRegression (fit_intercept = False ).fit (x , y )
314+ wire_cap = wire_cap_model .coef_ [0 ]
315+
316+ return "-resistance {:.5E} -capacitance {:.5E}" .format (
317+ wire_res / res_scale , wire_cap / cap_scale
318+ )
277319
278- x = np .array (x )
279- y = np .array (y )
280320
281- wire_cap_model = LinearRegression ( fit_intercept = False ). fit ( x , y )
282- wire_cap = wire_cap_model . coef_ [ 0 ]
321+ print ( "# Combined fit:" )
322+ print ( "set_wire_rc " + generic_rc_fit ([ "signal" , "clock" ]))
283323
284- print (
285- "set_wire_rc -resistance {:.5E} -capacitance {:.5E}" .format (
286- wire_res / res_scale , wire_cap / cap_scale
287- )
288- )
324+ print ("# Split signal/clock fit:" )
325+ print ("set_wire_rc -signal " + generic_rc_fit (["signal" ]))
326+ print ("set_wire_rc -clock " + generic_rc_fit (["clock" ]))
0 commit comments