Corrected density check script, and corrected the LI fill generation to meet the MR manufacturing requirements.
diff --git a/sky130/custom/scripts/check_density.py b/sky130/custom/scripts/check_density.py index 0df2423..f2e529c 100755 --- a/sky130/custom/scripts/check_density.py +++ b/sky130/custom/scripts/check_density.py
@@ -223,18 +223,7 @@ # Use signal to poll the process and generate any output as it arrives - fomfill = [] - polyfill = [] - lifill = [] - met1fill = [] - met2fill = [] - met3fill = [] - met4fill = [] - met5fill = [] - xtiles = 0 - ytiles = 0 - xfrac = 0.0 - yfrac = 0.0 + dlines = [] while mproc: status = mproc.poll() @@ -248,39 +237,8 @@ outlines = output[0] errlines = output[1] for line in outlines.splitlines(): + dlines.append(line) print(line) - dpair = line.split(':') - if len(dpair) == 2: - layer = dpair[0] - try: - density = float(dpair[1].strip()) - except: - continue - if layer == 'FOM': - fomfill.append(density) - elif layer == 'POLY': - polyfill.append(density) - elif layer == 'LI1': - lifill.append(density) - elif layer == 'MET1': - met1fill.append(density) - elif layer == 'MET2': - met2fill.append(density) - elif layer == 'MET3': - met3fill.append(density) - elif layer == 'MET4': - met4fill.append(density) - elif layer == 'MET5': - met5fill.append(density) - elif layer == 'XTILES': - xtiles = int(dpair[1].strip()) - elif layer == 'YTILES': - ytiles = int(dpair[1].strip()) - elif layer == 'XFRAC': - xfrac = float(dpair[1].strip()) - elif layer == 'YFRAC': - yfrac = float(dpair[1].strip()) - for line in errlines.splitlines(): print(line) print('Magic exited with status ' + str(status)) @@ -300,6 +258,7 @@ sresult = select.select([mproc.stdout, mproc.stderr], [], [], 0)[0] if mproc.stdout in sresult: outstring = mproc.stdout.readline().strip() + dlines.append(outstring) print(outstring) elif mproc.stderr in sresult: outstring = mproc.stderr.readline().strip() @@ -307,6 +266,56 @@ else: break + fomfill = [] + polyfill = [] + lifill = [] + met1fill = [] + met2fill = [] + met3fill = [] + met4fill = [] + met5fill = [] + xtiles = 0 + ytiles = 0 + xfrac = 0.0 + yfrac = 0.0 + + for line in dlines: + dpair = line.split(':') + if len(dpair) == 2: + layer = dpair[0] + try: + density = float(dpair[1].strip()) + except: + continue + if layer == 'FOM': + fomfill.append(density) + elif layer == 'POLY': + polyfill.append(density) + elif layer == 'LI1': + lifill.append(density) + elif layer == 'MET1': + met1fill.append(density) + elif layer == 'MET2': + met2fill.append(density) + elif layer == 'MET3': + met3fill.append(density) + elif layer == 'MET4': + met4fill.append(density) + elif layer == 'MET5': + met5fill.append(density) + elif layer == 'XTILES': + xtiles = int(dpair[1].strip()) + elif layer == 'YTILES': + ytiles = int(dpair[1].strip()) + elif layer == 'XFRAC': + xfrac = float(dpair[1].strip()) + elif layer == 'YFRAC': + yfrac = float(dpair[1].strip()) + + if ytiles == 0 or xtiles == 0: + print('Failed to read XTILES or YTILES from output.') + sys.exit(1) + total_tiles = (ytiles - 9) * (xtiles - 9) print('') @@ -337,10 +346,11 @@ base = xtiles * w + x fomaccum += sum(fomfill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(fomaccum / atotal)) - if fomaccum < 33.0: + fomaccum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(fomaccum)) + if fomaccum < 0.33: print('***Error: FOM Density < 33%') - elif fomaccum > 57.0: + elif fomaccum > 0.57: print('***Error: FOM Density > 57%') print('') @@ -361,7 +371,8 @@ base = xtiles * w + x polyaccum += sum(polyfill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(polyaccum / atotal)) + polyaccum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(polyaccum)) print('') print('LI Density:') @@ -381,10 +392,11 @@ base = xtiles * w + x liaccum += sum(lifill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(liaccum / atotal)) - if liaccum < 35.0: + liaccum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(liaccum)) + if liaccum < 0.35: print('***Error: LI Density < 35%') - elif liaccum > 70.0: + elif liaccum > 0.70: print('***Error: LI Density > 70%') print('') @@ -405,10 +417,11 @@ base = xtiles * w + x met1accum += sum(met1fill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met1accum / atotal)) - if met1accum < 35.0: + met1accum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met1accum)) + if met1accum < 0.35: print('***Error: MET1 Density < 35%') - elif met1accum > 70.0: + elif met1accum > 0.70: print('***Error: MET1 Density > 70%') print('') @@ -429,10 +442,11 @@ base = xtiles * w + x met2accum += sum(met2fill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met2accum / atotal)) - if met2accum < 35.0: + met2accum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met2accum)) + if met2accum < 0.35: print('***Error: MET2 Density < 35%') - elif met2accum > 70.0: + elif met2accum > 0.70: print('***Error: MET2 Density > 70%') print('') @@ -453,10 +467,11 @@ base = xtiles * w + x met3accum += sum(met3fill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met3accum / atotal)) - if met3accum < 35.0: + met3accum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met3accum)) + if met3accum < 0.35: print('***Error: MET3 Density < 35%') - elif met3accum > 70.0: + elif met3accum > 0.70: print('***Error: MET3 Density > 70%') print('') @@ -477,10 +492,11 @@ base = xtiles * w + x met4accum += sum(met4fill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met4accum / atotal)) - if met4accum < 35.0: + met4accum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met4accum)) + if met4accum < 0.35: print('***Error: MET4 Density < 35%') - elif met4accum > 70.0: + elif met4accum > 0.70: print('***Error: MET4 Density > 70%') print('') @@ -501,11 +517,77 @@ base = xtiles * w + x met5accum += sum(met5fill[base : base + 10]) - print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met5accum / atotal)) - if met5accum < 45.0: + met5accum /= atotal + print('Tile (' + str(x) + ', ' + str(y) + '): ' + str(met5accum)) + if met5accum < 0.45: print('***Error: MET5 Density < 45%') - elif met5accum > 86.0: - print('***Error: MET5 Density > 80%') + elif met5accum > 0.86: + print('***Error: MET5 Density > 86%') + + print('') + print('Whole-chip density results:') + + atotal = ((xtiles - 1.0) * (ytiles - 1.0)) + ((ytiles - 1.0) * xfrac) + ((xtiles - 1.0) * yfrac) + (xfrac * yfrac) + + fomaccum = sum(fomfill) / atotal + print('') + print('FOM Density: ' + str(fomaccum)) + if fomaccum < 0.33: + print('***Error: FOM Density < 33%') + elif fomaccum > 0.57: + print('***Error: FOM Density > 57%') + + polyaccum = sum(polyfill) / atotal + print('') + print('POLY Density: ' + str(polyaccum)) + + liaccum = sum(lifill) / atotal + print('') + print('LI Density: ' + str(liaccum)) + if liaccum < 0.35: + print('***Error: LI Density < 35%') + elif liaccum > 0.70: + print('***Error: LI Density > 70%') + + met1accum = sum(met1fill) / atotal + print('') + print('MET1 Density: ' + str(met1accum)) + if met1accum < 0.35: + print('***Error: MET1 Density < 35%') + elif met1accum > 0.70: + print('***Error: MET1 Density > 70%') + + met2accum = sum(met2fill) / atotal + print('') + print('MET2 Density: ' + str(met2accum)) + if met2accum < 0.35: + print('***Error: MET2 Density < 35%') + elif met2accum > 0.70: + print('***Error: MET2 Density > 70%') + + met3accum = sum(met3fill) / atotal + print('') + print('MET3 Density: ' + str(met3accum)) + if met3accum < 0.35: + print('***Error: MET3 Density < 35%') + elif met3accum > 0.70: + print('***Error: MET3 Density > 70%') + + met4accum = sum(met4fill) / atotal + print('') + print('MET4 Density: ' + str(met4accum)) + if met4accum < 0.35: + print('***Error: MET4 Density < 35%') + elif met4accum > 0.70: + print('***Error: MET4 Density > 70%') + + met5accum = sum(met5fill) / atotal + print('') + print('MET5 Density: ' + str(met5accum)) + if met5accum < 0.45: + print('***Error: MET5 Density < 45%') + elif met5accum > 0.86: + print('***Error: MET5 Density > 86%') if not keepmode: os.remove(magpath + '/check_density.tcl')
diff --git a/sky130/magic/sky130.tech b/sky130/magic/sky130.tech index ecfb831..0458e9e 100644 --- a/sky130/magic/sky130.tech +++ b/sky130/magic/sky130.tech
@@ -1908,37 +1908,43 @@ or polyfill_fine calma 28 28 -#--------------------------------------------------- +#--------------------------------------------------------- # LI fill -#--------------------------------------------------- +# Note requirement that LI fill may not overlap (non-fill) +# diff or poly. +#--------------------------------------------------------- templayer obstruct_li_coarse allli,allpad,obsli,lifill,fillblock,fillblock4 - grow 3000 + grow 2800 + or alldiff,allpoly + grow 200 templayer lifill_coarse topbox - # slots 0 2000 200 0 2000 200 700 0 - slots 0 2000 350 0 2000 350 700 0 + slots 0 3000 500 0 3000 500 700 0 and-not obstruct_li_coarse and topbox - shrink 995 - grow 995 + shrink 1495 + grow 1495 templayer obstruct_li_medium allli,allpad,obsli,lifill,fillblock,fillblock4 - grow 2800 + grow 2500 or lifill_coarse + grow 300 + or alldiff,allpoly grow 200 templayer lifill_medium topbox - slots 0 1000 200 0 1000 200 700 0 + slots 0 1500 500 0 1500 500 700 0 and-not obstruct_li_medium and topbox - shrink 495 - grow 495 + shrink 745 + grow 745 templayer obstruct_li_fine allli,allpad,obsli,lifill,fillblock,fillblock4 - grow 300 or lifill_coarse,lifill_medium + grow 300 + or alldiff,allpoly grow 200 templayer lifill_fine topbox - slots 0 580 200 0 580 200 700 0 + slots 0 580 500 0 580 500 700 0 and-not obstruct_li_fine and topbox shrink 285