{"id":999,"date":"2014-12-11T14:38:12","date_gmt":"2014-12-11T20:38:12","guid":{"rendered":"https:\/\/www.circuitdesign.info\/blog\/?p=999"},"modified":"2025-01-14T18:13:19","modified_gmt":"2025-01-15T00:13:19","slug":"generating-corners-for-ade-xl-with-python","status":"publish","type":"post","link":"https:\/\/www.circuitdesign.info\/blog\/2014\/12\/generating-corners-for-ade-xl-with-python\/","title":{"rendered":"Generating Corners for ADE-XL with Python"},"content":{"rendered":"\n<p>I&#8217;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.<\/p>\n\n\n\n<p>But getting things like corner definitions in there is difficult. You&#8217;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.<\/p>\n\n\n\n<p>The CSV file is pretty useless. The reason is that each corner entry is another <em>column<\/em> in the file, not another row. This is the transpose of the way everyone else does CSV files\u2014where a row is another record, and the columns are the fields in that record.<\/p>\n\n\n\n<p>But, with some use of Python&#8217;s etree XML capabilities, you can get the SDB file to work pretty easily.<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>Here&#8217;s a sample script that takes a sample SDB file (which you can export from ADE-XL) and then adds multiple corners.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import xml.etree.ElementTree as ET\nimport itertools\nimport os.path\n\ntree = ET.parse('adexl-sample-corners.sdb')\nroot = tree.getroot()\ncorners = root.find('active').find('corners')\n\nvdds = &#91;3.0, 3.3, 3.5]\ntemps = &#91;-40, 25, 85]\n\nmodel_comb = itertools.product(&#91;'slowNMOS', 'fastNMOS'], &#91;'slowPMOS', 'fastPMOS'], &#91;'lowResistor', 'highResistor'])\n\nmodel_corners = &#91;''.join(k) for k in model_comb]\nall_combs_keys = &#91;'modelsection:\/path\/to\/modelfile.scs', 'var:VDD', 'var:temperature']\nall_combs = itertools.product(model_corners, vdds, temps)\ncorner_list = &#91; dict( (all_combs_keys&#91;i], v) for i,v in enumerate(c) ) for c in all_combs ]\n\nfor i,corner in enumerate(corner_list):\n  if 'corner name' in corner:\n    c_name = c&#91;'corner name']\n  else:\n    c_name = 'C{0}'.format(i)\n  c = ET.SubElement(corners, 'corner', enabled=\"1\")\n  c.text = c_name\n  print(c.text)\n\nfor k,v in corner.iteritems():\n  if k.startswith('modelsection'):\n    modelfile = k.split(':')&#91;1]\n    models = c.find('models')\n  if not models:\n    models = ET.SubElement(c, 'models')\n    mm = ET.SubElement(models, 'model', enabled=\"1\")\n    mm.text = os.path.split(modelfile)&#91;-1]\n    mt = ET.SubElement(mm, 'modeltest')\n    mt.text = 'All'\n  mb = ET.SubElement(mm, 'modelblock')\n  mb.text = 'Global'\n  mf = ET.SubElement(mm, 'modelfile')\n  mf.text = modelfile\n  ms = ET.SubElement(mm, 'modelsection')\n  ms.text = v\n  if k.startswith('var'):\n    var_name = k.split(':')&#91;1]\n    vars = c.find('vars')\n    if not vars:\n      vars = ET.SubElement(c, 'vars')\n      var = ET.SubElement(vars, 'var')\n      var.text = var_name\n    val = ET.SubElement(var, 'value')\n  val.text = str(v)\n\ntree.write('generated.sdb')<\/code><\/pre>\n\n\n\n<p>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).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;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&#8217;d have to hand-enter them. Luckily, Cadence allows [&hellip;]<\/p>\n","protected":false},"author":4,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3],"tags":[177,180,33,178,181,179],"class_list":["post-999","post","type-post","status-publish","format-standard","hentry","category-analog-pro","tag-ade-xl","tag-automation","tag-cadence","tag-python","tag-regression","tag-scripting"],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/poCEy-g7","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/posts\/999","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/users\/4"}],"replies":[{"embeddable":true,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/comments?post=999"}],"version-history":[{"count":11,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/posts\/999\/revisions"}],"predecessor-version":[{"id":1252,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/posts\/999\/revisions\/1252"}],"wp:attachment":[{"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/media?parent=999"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/categories?post=999"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.circuitdesign.info\/blog\/wp-json\/wp\/v2\/tags?post=999"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}