mirror of https://github.com/VLSIDA/OpenRAM.git
Add draft of assura DRC/LVS
This commit is contained in:
parent
37edd7cac6
commit
658f794b12
|
|
@ -0,0 +1,170 @@
|
|||
"""
|
||||
This is a DRC/LVS interface for Assura. It implements completely
|
||||
independently two functions: run_drc and run_lvs, that perform these
|
||||
functions in batch mode and will return true/false if the result
|
||||
passes. All of the setup (the rules, temp dirs, etc.) should be
|
||||
contained in this file. Replacing with another DRC/LVS tool involves
|
||||
rewriting this code to work properly. Porting to a new technology in
|
||||
Assura means pointing the code to the proper DRC and LVS rule files.
|
||||
|
||||
LVS Notes:
|
||||
|
||||
For some processes the FET models are sub-circuits. Meaning, the
|
||||
first letter of their SPICE instantiation begins with 'X' not 'M'.
|
||||
The former confuses Assura, however, so to get these sub-circuit models
|
||||
to LVS properly, an empty sub-circuit must be inserted into the
|
||||
LVS SPICE netlist. The sub-circuits are pointed to using the
|
||||
drc["lvs_subcircuits"] variable, and additional options must be
|
||||
inserted in the runset.
|
||||
"""
|
||||
|
||||
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import debug
|
||||
import globals
|
||||
|
||||
|
||||
def run_drc(name, gds_name):
|
||||
"""Run DRC check on a given top-level name which is
|
||||
implemented in gds_name."""
|
||||
OPTS = globals.get_opts()
|
||||
|
||||
from tech import drc
|
||||
|
||||
drc_rules = drc["drc_rules"]
|
||||
drc_runset = OPTS.openram_temp + name + ".rsf"
|
||||
drc_log_file = "%s%s.log" % (OPTS.openram_temp, name)
|
||||
|
||||
# write the runset file
|
||||
# the runset file contains all the options to run Assura
|
||||
# different processes may require different options
|
||||
f = open(drc_runset, "w")
|
||||
f.write("avParameters(\n")
|
||||
f.write(" ?flagDotShapes t\n")
|
||||
f.write(" ?flagMalformed t\n")
|
||||
f.write(" ?flagPathNonManhattanSeg all\n")
|
||||
f.write(" ?flagPathShortSegments endOnlySmart\n")
|
||||
f.write(" ?maintain45 nil\n")
|
||||
f.write(" ?combineNearCollinearEdges nil\n")
|
||||
f.write(")\n")
|
||||
f.write("\n")
|
||||
f.write("avParameters(\n")
|
||||
f.write(" ?inputLayout ( \"gds2\" \"%s\" )\n" % (gds_name))
|
||||
f.write(" ?cellName \"%s\"\n" % (name))
|
||||
f.write(" ?workingDirectory \"%s\"\n" % (OPTS.openram_temp))
|
||||
f.write(" ?rulesFile \"%s\"\n" % (drc_rules))
|
||||
f.write(" ?set ( \"GridCheck\" )\n")
|
||||
f.write(" ?avrpt t\n")
|
||||
f.write(")\n")
|
||||
f.close()
|
||||
|
||||
# run drc
|
||||
cwd = os.getcwd()
|
||||
os.chdir(OPTS.openram_temp)
|
||||
cmd = "assura {0} 2> {1} 1> {2}".format(drc_runset, drc_log_file, drc_log_file)
|
||||
debug.info(1, cmd)
|
||||
os.system(cmd)
|
||||
os.chdir(cwd)
|
||||
|
||||
# count and report errors
|
||||
errors = 0
|
||||
try:
|
||||
f = open(OPTS.openram_temp+name+".err", "r")
|
||||
except:
|
||||
debug.error("Unable to retrieve DRC results file.",1)
|
||||
results = f.readlines()
|
||||
f.close()
|
||||
for line in results:
|
||||
if re.match("Rule No.", line):
|
||||
if re.search("# INFO:", line) == None:
|
||||
errors = errors + 1
|
||||
debug.info(1, line)
|
||||
|
||||
if errors > 0:
|
||||
debug.error("Errors: %d" % (errors))
|
||||
|
||||
return errors
|
||||
|
||||
|
||||
def run_lvs(name, gds_name, sp_name):
|
||||
"""Run LVS check on a given top-level name which is
|
||||
implemented in gds_name and sp_name. """
|
||||
OPTS = globals.get_opts()
|
||||
|
||||
from tech import drc
|
||||
|
||||
lvs_rules = drc["lvs_rules"]
|
||||
lvs_runset = OPTS.openram_temp + name + ".rsf"
|
||||
lvs_compare = drc["lvs_compare"]
|
||||
lvs_bindings = drc["lvs_bindings"]
|
||||
lvs_log_file = "{0}{1}.log".format(OPTS.openram_temp, name)
|
||||
# Needed when FET models are sub-circuits
|
||||
if drc.has_key("lvs_subcircuits"):
|
||||
lvs_sub_file = drc["lvs_subcircuits"]
|
||||
else:
|
||||
lvs_sub_file = ""
|
||||
|
||||
# write the runset file
|
||||
# the runset file contains all the options to run Assura
|
||||
# different processes may require different options
|
||||
f = open(lvs_runset, "w")
|
||||
f.write("avParameters(\n")
|
||||
f.write(" ?inputLayout ( \"gds2\" \"{}\" )\n".format(gds_name))
|
||||
f.write(" ?cellName \"{}\"\n".format(name))
|
||||
f.write(" ?workingDirectory \"{}\"\n".format(OPTS.openram_temp))
|
||||
f.write(" ?rulesFile \"{}\"\n".format(lvs_rules))
|
||||
f.write(" ?autoGrid nil\n")
|
||||
f.write(" ?avrpt t\n")
|
||||
# The below options vary greatly between processes and cell-types
|
||||
f.write(" ?set (\"NO_SUBC_IN_GRLOGIC\")\n")
|
||||
f.write(")\n")
|
||||
f.write("\n")
|
||||
c = open(lvs_compare, "r")
|
||||
lines = c.read()
|
||||
c.close
|
||||
f.write(lines)
|
||||
f.write("\n")
|
||||
f.write("avCompareRules(\n")
|
||||
f.write(" schematic(\n")
|
||||
# Needed when FET models are sub-circuits
|
||||
if os.path.isfile(lvs_sub_file):
|
||||
f.write(" genericDevice(emptySubckt)\n")
|
||||
f.write(" netlist( spice \"{}\" )\n".format(lvs_sub_file))
|
||||
f.write(" netlist( spice \"{}\" )\n".format(sp_name))
|
||||
f.write(" )\n")
|
||||
f.write(" layout(\n")
|
||||
# Separate gnd shapes are sometimes not connected by metal, so this connects by name
|
||||
# The use of this option is not recommended for final DRC
|
||||
f.write(" joinNets( root \"gnd\" \"gnd*\" ) \n")
|
||||
f.write(" )\n")
|
||||
f.write(" bindingFile( \"{}\" )\n".format(lvs_bindings))
|
||||
f.write(")\n")
|
||||
f.write("\n")
|
||||
f.write("avLVS()\n")
|
||||
f.close()
|
||||
|
||||
# run lvs
|
||||
cwd = os.getcwd()
|
||||
os.chdir(OPTS.openram_temp)
|
||||
cmd = "assura {0} 2> {1} 1> {2}".format(lvs_runset, lvs_log_file, lvs_log_file)
|
||||
debug.info(1, cmd)
|
||||
os.system(cmd)
|
||||
os.chdir(cwd)
|
||||
|
||||
errors = 0
|
||||
try:
|
||||
f = open(OPTS.openram_temp+name+".csm", "r")
|
||||
except:
|
||||
debug.error("Unable to retrieve LVS results file.",1)
|
||||
results = f.readlines()
|
||||
f.close()
|
||||
for line in results:
|
||||
if re.search("errors", line):
|
||||
errors = errors + 1
|
||||
debug.info(1, line)
|
||||
elif re.search("Schematic and Layout", line):
|
||||
debug.info(1, line)
|
||||
|
||||
return errors
|
||||
|
|
@ -116,8 +116,8 @@ def init_openram(config_file):
|
|||
set_spice()
|
||||
|
||||
global OPTS
|
||||
OPTS.drc_exe = get_tool("DRC",["calibre","magic"])
|
||||
OPTS.lvs_exe = get_tool("LVS",["calibre","netgen"])
|
||||
OPTS.drc_exe = get_tool("DRC",["calibre","assura","magic"])
|
||||
OPTS.lvs_exe = get_tool("LVS",["calibre","assura","netgen"])
|
||||
OPTS.pex_exe = get_tool("PEX",["calibre","magic"])
|
||||
#set_drc()
|
||||
#set_lvs()
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ if OPTS.drc_exe == None:
|
|||
pass
|
||||
elif "calibre" in OPTS.drc_exe:
|
||||
from calibre import run_drc
|
||||
elif "assura" in OPTS.drc_exe:
|
||||
from assura import run_drc
|
||||
elif "magic" in OPTS.drc_exe:
|
||||
from magic import run_drc
|
||||
else:
|
||||
|
|
@ -25,6 +27,8 @@ if OPTS.lvs_exe == None:
|
|||
pass
|
||||
elif "calibre" in OPTS.lvs_exe:
|
||||
from calibre import run_lvs
|
||||
elif "assura" in OPTS.lvs_exe:
|
||||
from assura import run_lvs
|
||||
elif "netgen" in OPTS.lvs_exe:
|
||||
from magic import run_lvs
|
||||
else:
|
||||
|
|
|
|||
Loading…
Reference in New Issue