I’ve been using ADE-XL to run corner simulations lately. I like that it lets me set up a specification for simulations (AKA a scoreboard) and then runs through different corners. And it supports distributed or parallel computing.
But getting things like corner definitions in there is difficult. You’d have to hand-enter them. Luckily, Cadence allows you to load these definitions from a CSV file or an XML format they call SDB.
The CSV file is pretty useless. The reason is that each corner entry is another column in the file, not another row. This is the transpose of the way everyone else does CSV files—where a row is another record, and the columns are the fields in that record.
But, with some use of Python’s etree XML capabilities, you can get the SDB file to work pretty easily.
Here’s a sample script that takes a sample SDB file (which you can export from ADE-XL) and then adds multiple corners.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import xml.etree.ElementTree as ET import itertools import os.path tree = ET.parse('adexl-sample-corners.sdb') root = tree.getroot() corners = root.find('active').find('corners') vdds = [3.0, 3.3, 3.5] temps = [-40, 25, 85] model_comb = itertools.product(['slowNMOS', 'fastNMOS'], ['slowPMOS', 'fastPMOS'], ['lowResistor', 'highResistor']) model_corners = [''.join(k) for k in model_comb] all_combs_keys = ['modelsection:/path/to/modelfile.scs', 'var:VDD', 'var:temperature'] all_combs = itertools.product(model_corners, vdds, temps) corner_list = [ dict( (all_combs_keys[i], v) for i,v in enumerate(c) ) for c in all_combs ] for i,corner in enumerate(corner_list): if 'corner name' in corner: c_name = c['corner name'] else: c_name = 'C{0}'.format(i) c = ET.SubElement(corners, 'corner', enabled="1") c.text = c_name print(c.text) for k,v in corner.iteritems(): if k.startswith('modelsection'): modelfile = k.split(':')[1] models = c.find('models') if not models: models = ET.SubElement(c, 'models') mm = ET.SubElement(models, 'model', enabled="1") mm.text = os.path.split(modelfile)[-1] mt = ET.SubElement(mm, 'modeltest') mt.text = 'All' mb = ET.SubElement(mm, 'modelblock') mb.text = 'Global' mf = ET.SubElement(mm, 'modelfile') mf.text = modelfile ms = ET.SubElement(mm, 'modelsection') ms.text = v if k.startswith('var'): var_name = k.split(':')[1] vars = c.find('vars') if not vars: vars = ET.SubElement(c, 'vars') var = ET.SubElement(vars, 'var') var.text = var_name val = ET.SubElement(var, 'value') val.text = str(v) tree.write('generated.sdb') |
The first section makes all the different corner combinations of process, voltage and temperature. As a small tangent, I also constructed all the process corners themselves (slow/fast NMOS, slow/fast PMOS, etc).