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
1415import numpy as np
1516from sklearn .linear_model import LinearRegression
1617import matplotlib .pyplot as plt
1718
19+ LAYER_HEADER_RE = re .compile ("^([^\\ (]+)\\ (([^\\ )]+)\\ )$" )
20+
1821# Parse and validate arguments
1922# =============================================================================
2023
@@ -81,39 +84,76 @@ def makeDict():
8184
8285data = makeDict ()
8386
87+ stack = []
88+ stack_line = None
89+
90+ # indices of relevant layers (routable layers or via layers)
91+ active_layers = set ()
92+
8493# Parse the cap CSV file generated by compare_rc_script.tcl
8594for rc_file in args .rc_file :
8695 design = rc_file
8796 print ("reading" , design )
8897 with open (rc_file ) as f :
8998 nonGrtNets = 0
9099 for line in f :
100+ if line .startswith ("# stack: " ):
101+ if stack_line is not None and stack_line != line :
102+ print (f"layer stack inconsistent" , file = stderr )
103+ exit (1 )
104+ elif stack_line is None :
105+ for layer in line .removeprefix ("# stack: " ).strip ().split (" " ):
106+ name = layer
107+ is_routing = False
108+ via_resist = 0.0
109+ if layer .endswith (")" ):
110+ # layer name has extra data
111+ match = LAYER_HEADER_RE .match (layer )
112+ assert match
113+ name = match .group (1 )
114+ if match .group (2 ) == "routing" :
115+ is_routing = True
116+ else :
117+ via_resist = float (match .group (2 ))
118+ stack .append ((name , is_routing , via_resist ))
119+ continue
120+
91121 tokens = line .strip ().split ("," )
92122 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
123+
124+ data [design ][netName ] = {
125+ "type" : tokens [1 ],
126+ "gpl_res" : float (tokens [2 ]),
127+ "gpl_cap" : float (tokens [3 ]),
128+ "grt_res" : float (tokens [4 ]),
129+ "grt_cap" : float (tokens [5 ]),
130+ "rcx_res" : float (tokens [6 ]),
131+ "rcx_cap" : float (tokens [7 ]),
132+ }
133+
134+ layer_lengths = [float (tok ) for tok in tokens [8 :]]
135+ for i , length in enumerate (layer_lengths ):
136+ if length > 0 :
137+ active_layers .add (i )
138+
115139 data [design ][netName ]["layer_lengths" ] = layer_lengths
116- data [design ][netName ]["wire_length" ] = wire_length
140+ data [design ][netName ]["routable_layer_lengths" ] = [
141+ length
142+ for i , length in enumerate (layer_lengths )
143+ # ignore non-routable layers
144+ if stack [i ][1 ]
145+ ]
146+ data [design ][netName ]["wire_length" ] = sum (
147+ length
148+ for i , length in enumerate (layer_lengths )
149+ # ignore non-routable layers
150+ if stack [i ][1 ]
151+ )
152+ data [design ][netName ]["grt_via_res" ] = sum (
153+ (length * stack [i ][2 ])
154+ for i , length in enumerate (layer_lengths )
155+ if not stack [i ][1 ]
156+ )
117157
118158################################################################
119159
@@ -210,16 +250,15 @@ def makeDict():
210250 for net in data [design ]:
211251 rcx_res = data [design ][net ]["rcx_res" ]
212252 if rcx_res > 0 :
213- layer_lengths = data [design ][net ]["layer_lengths" ]
214- x .append (layer_lengths )
215- y .append (rcx_res )
253+ x .append (data [design ][net ]["routable_layer_lengths" ])
254+ y .append (rcx_res - data [design ][net ]["grt_via_res" ])
216255
217256x = np .array (x )
218257y = np .array (y )
219258
220259res_model = LinearRegression (fit_intercept = False ).fit (x , y )
221260r_sq = res_model .score (x , y )
222- print ("Resistance coefficient of determination: {:.4f}" .format (r_sq ))
261+ print ("# Resistance coefficient of determination: {:.4f}" .format (r_sq ))
223262
224263################################################################
225264
@@ -229,60 +268,70 @@ def makeDict():
229268y = []
230269for design in data :
231270 for net in data [design ]:
232- layer_lengths = data [design ][net ]["layer_lengths" ]
233- x .append (layer_lengths )
271+ x .append (data [design ][net ]["routable_layer_lengths" ])
234272 y .append (data [design ][net ]["rcx_cap" ])
235273
236274x = np .array (x )
237275y = np .array (y )
238276
239277cap_model = LinearRegression (fit_intercept = False ).fit (x , y )
240278r_sq = cap_model .score (x , y )
241- print ("Capacitance coefficient of determination: {:.4f}" .format (r_sq ))
242-
243- 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 :
279+ print ("# Capacitance coefficient of determination: {:.4f}" .format (r_sq ))
280+ print ("# Updated layer resistance {}/um capacitance {}/um" .format (res_unit , cap_unit ))
281+
282+ routable_layers = [layer for layer in stack if layer [1 ]]
283+ for i , layer in enumerate (routable_layers ):
284+ res_coeff = res_model .coef_ [i ]
285+ cap_coeff = cap_model .coef_ [i ]
286+ if res_coeff != 0.0 or cap_coeff != 0.0 :
246287 print (
247288 "set_layer_rc -layer {} -resistance {:.5E} -capacitance {:.5E}" .format (
248- layer , res_coeff / res_scale , cap_coeff / cap_scale
289+ layer [ 0 ] , res_coeff / res_scale , cap_coeff / cap_scale
249290 )
250291 )
251292
252293################################################################
253294
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 ]
269295
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" ])
296+ def generic_rc_fit (type_sieve ):
297+ x = []
298+ y = []
299+ for design in data :
300+ for net in data [design ]:
301+ net_type = data [design ][net ]["type" ]
302+ wire_res = data [design ][net ]["rcx_res" ]
303+ wire_length = data [design ][net ]["wire_length" ]
304+ if net_type in type_sieve and wire_res != 0.0 :
305+ x .append ([wire_length ])
306+ y .append (wire_res )
307+ x = np .array (x )
308+ y = np .array (y )
309+ wire_res_model = LinearRegression (fit_intercept = False ).fit (x , y )
310+ wire_res = wire_res_model .coef_ [0 ]
311+
312+ x = []
313+ y = []
314+ for design in data :
315+ for net in data [design ]:
316+ net_type = data [design ][net ]["type" ]
317+ if net_type in type_sieve :
318+ wire_length = data [design ][net ]["wire_length" ]
319+ wire_cap = data [design ][net ]["rcx_cap" ]
320+ x .append ([wire_length ])
321+ y .append (wire_cap )
322+ x = np .array (x )
323+ y = np .array (y )
324+ wire_cap_model = LinearRegression (fit_intercept = False ).fit (x , y )
325+ wire_cap = wire_cap_model .coef_ [0 ]
326+
327+ return "-resistance {:.5E} -capacitance {:.5E}" .format (
328+ wire_res / res_scale , wire_cap / cap_scale
329+ )
277330
278- x = np .array (x )
279- y = np .array (y )
280331
281- wire_cap_model = LinearRegression ( fit_intercept = False ). fit ( x , y )
282- wire_cap = wire_cap_model . coef_ [ 0 ]
332+ print ( "# Combined fit:" )
333+ print ( "set_wire_rc " + generic_rc_fit ([ "signal" , "clock" ]))
283334
284- print (
285- "set_wire_rc -resistance {:.5E} -capacitance {:.5E}" .format (
286- wire_res / res_scale , wire_cap / cap_scale
287- )
288- )
335+ print ("# Split signal/clock fit:" )
336+ print ("set_wire_rc -signal " + generic_rc_fit (["signal" ]))
337+ print ("set_wire_rc -clock " + generic_rc_fit (["clock" ]))
0 commit comments