mirror of https://github.com/VLSIDA/OpenRAM.git
Skeleton code for indirect DRC/LVS/PEX tools.
This commit is contained in:
parent
29c5ab48f0
commit
3e0f39cd8e
|
|
@ -97,11 +97,13 @@ def run_drc(name, gds_name):
|
||||||
# run drc
|
# run drc
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(OPTS.openram_temp)
|
os.chdir(OPTS.openram_temp)
|
||||||
errfile = "%s%s.drc.err" % (OPTS.openram_temp, name)
|
errfile = "{0}{1}.drc.err".format(OPTS.openram_temp, name)
|
||||||
outfile = "%s%s.drc.out" % (OPTS.openram_temp, name)
|
outfile = "{0}{1}.drc.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
cmd = "{0} -gui -drc {1}drc_runset -batch 2> {2} 1> {3}".format(
|
cmd = "{0} -gui -drc {1}drc_runset -batch 2> {2} 1> {3}".format(OPTS.drc_exe,
|
||||||
OPTS.calibre_exe, OPTS.openram_temp, errfile, outfile)
|
OPTS.openram_temp,
|
||||||
|
errfile,
|
||||||
|
outfile)
|
||||||
debug.info(1, cmd)
|
debug.info(1, cmd)
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
@ -172,12 +174,14 @@ def run_lvs(name, gds_name, sp_name):
|
||||||
# run LVS
|
# run LVS
|
||||||
cwd = os.getcwd()
|
cwd = os.getcwd()
|
||||||
os.chdir(OPTS.openram_temp)
|
os.chdir(OPTS.openram_temp)
|
||||||
errfile = "%s%s.lvs.err" % (OPTS.openram_temp, name)
|
errfile = "{0}{1}.lvs.err".format(OPTS.openram_temp, name)
|
||||||
outfile = "%s%s.lvs.out" % (OPTS.openram_temp, name)
|
outfile = "{0}{1}.lvs.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
cmd = "calibre -gui -lvs %slvs_runset -batch 2> %s 1> %s" % (
|
cmd = "{0} -gui -lvs {1}lvs_runset -batch 2> {2} 1> {3}".format(OPTS.lvs_exe,
|
||||||
OPTS.openram_temp, errfile, outfile)
|
OPTS.openram_temp,
|
||||||
debug.info(2, cmd)
|
errfile,
|
||||||
|
outfile)
|
||||||
|
debug.info(1, cmd)
|
||||||
os.system(cmd)
|
os.system(cmd)
|
||||||
os.chdir(cwd)
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
|
@ -283,7 +287,7 @@ def run_pex(name, gds_name, sp_name, output=None):
|
||||||
errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name)
|
errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name)
|
||||||
outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name)
|
outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.calibre_exe,
|
cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe,
|
||||||
OPTS.openram_temp,
|
OPTS.openram_temp,
|
||||||
errfile,
|
errfile,
|
||||||
outfile)
|
outfile)
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import hierarchy_layout
|
import hierarchy_layout
|
||||||
import hierarchy_spice
|
import hierarchy_spice
|
||||||
import globals
|
import globals
|
||||||
import calibre
|
import verify
|
||||||
import debug
|
import debug
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
|
@ -56,8 +56,8 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
tempgds = OPTS.openram_temp + "/temp.gds"
|
tempgds = OPTS.openram_temp + "/temp.gds"
|
||||||
self.sp_write(tempspice)
|
self.sp_write(tempspice)
|
||||||
self.gds_write(tempgds)
|
self.gds_write(tempgds)
|
||||||
debug.check(calibre.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
|
debug.check(verify.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
|
||||||
debug.check(calibre.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
|
debug.check(verify.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
|
||||||
os.remove(tempspice)
|
os.remove(tempspice)
|
||||||
os.remove(tempgds)
|
os.remove(tempgds)
|
||||||
|
|
||||||
|
|
@ -66,7 +66,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
if OPTS.check_lvsdrc:
|
if OPTS.check_lvsdrc:
|
||||||
tempgds = OPTS.openram_temp + "/temp.gds"
|
tempgds = OPTS.openram_temp + "/temp.gds"
|
||||||
self.gds_write(tempgds)
|
self.gds_write(tempgds)
|
||||||
debug.check(calibre.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
|
debug.check(verify.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
|
||||||
os.remove(tempgds)
|
os.remove(tempgds)
|
||||||
|
|
||||||
def LVS(self):
|
def LVS(self):
|
||||||
|
|
@ -76,7 +76,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
tempgds = OPTS.openram_temp + "/temp.gds"
|
tempgds = OPTS.openram_temp + "/temp.gds"
|
||||||
self.sp_write(tempspice)
|
self.sp_write(tempspice)
|
||||||
self.gds_write(tempgds)
|
self.gds_write(tempgds)
|
||||||
debug.check(calibre.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
|
debug.check(verify.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
|
||||||
os.remove(tempspice)
|
os.remove(tempspice)
|
||||||
os.remove(tempgds)
|
os.remove(tempgds)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -115,7 +115,11 @@ def init_openram(config_file):
|
||||||
|
|
||||||
set_spice()
|
set_spice()
|
||||||
|
|
||||||
set_calibre()
|
set_drc()
|
||||||
|
|
||||||
|
set_lvs()
|
||||||
|
|
||||||
|
set_pex()
|
||||||
|
|
||||||
|
|
||||||
def read_config(config_file):
|
def read_config(config_file):
|
||||||
|
|
@ -154,29 +158,68 @@ def read_config(config_file):
|
||||||
debug.error("Unable to make output directory.",-1)
|
debug.error("Unable to make output directory.",-1)
|
||||||
|
|
||||||
|
|
||||||
|
def find_exe(check_exe):
|
||||||
|
""" Check if the binary exists in the path and return the full path. """
|
||||||
|
# Check if the preferred spice option exists in the path
|
||||||
|
for path in os.environ["PATH"].split(os.pathsep):
|
||||||
|
exe = os.path.join(path, check_exe)
|
||||||
|
# if it is found, then break and use first version
|
||||||
|
if is_exe(exe):
|
||||||
|
return exe
|
||||||
|
return None
|
||||||
|
|
||||||
def set_calibre():
|
|
||||||
debug.info(2,"Finding calibre...")
|
def set_drc():
|
||||||
|
debug.info(2,"Finding DRC tool...")
|
||||||
global OPTS
|
global OPTS
|
||||||
|
|
||||||
# check if calibre is installed, if so, we should be running LVS/DRC on
|
|
||||||
# everything.
|
|
||||||
if not OPTS.check_lvsdrc:
|
if not OPTS.check_lvsdrc:
|
||||||
# over-ride the check LVS/DRC option
|
debug.info(1,"LVS/DRC/PEX disabled.")
|
||||||
debug.info(0,"Over-riding LVS/DRC. Not performing LVS/DRC.")
|
return
|
||||||
else:
|
else:
|
||||||
# see if calibre is in the path (extend to other tools later)
|
import tech
|
||||||
for path in os.environ["PATH"].split(os.pathsep):
|
if tech.drc_version != "":
|
||||||
OPTS.calibre_exe = os.path.join(path, "calibre")
|
OPTS.drc_exe=find_exe(tech.drc_version)
|
||||||
# if it is found, do inline LVS/DRC
|
if OPTS.drc_exe==None:
|
||||||
if is_exe(OPTS.calibre_exe):
|
debug.warning("{0} not found. Unable to perform DRC.".format(tech.drc_version))
|
||||||
OPTS.check_lvsdrc = True
|
OPTS.check_lvsdrc = False
|
||||||
debug.info(1, "Using calibre: " + OPTS.calibre_exe)
|
else:
|
||||||
break
|
debug.info(1, "Using DRC: " + OPTS.drc_exe)
|
||||||
else:
|
|
||||||
# otherwise, give warning and procede
|
|
||||||
debug.warning("Calibre not found. Not performing LVS/DRC.")
|
def set_lvs():
|
||||||
OPTS.check_lvsdrc = False
|
debug.info(2,"Finding LVS tool...")
|
||||||
|
global OPTS
|
||||||
|
|
||||||
|
if not OPTS.check_lvsdrc:
|
||||||
|
debug.info(1,"LVS/DRC/PEX disabled.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
import tech
|
||||||
|
if tech.lvs_version != "":
|
||||||
|
OPTS.lvs_exe=find_exe(tech.lvs_version)
|
||||||
|
if OPTS.lvs_exe==None:
|
||||||
|
debug.warning("{0} not found. Unable to perform LVS.".format(tech.lvs_version))
|
||||||
|
OPTS.check_lvsdrc = False
|
||||||
|
else:
|
||||||
|
debug.info(1, "Using LVS: " + OPTS.lvs_exe)
|
||||||
|
|
||||||
|
def set_pex():
|
||||||
|
debug.info(2,"Finding PEX tool...")
|
||||||
|
global OPTS
|
||||||
|
|
||||||
|
if not OPTS.check_lvsdrc:
|
||||||
|
debug.info(1,"LVS/DRC/PEX disabled.")
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
import tech
|
||||||
|
if tech.pex_version != "":
|
||||||
|
OPTS.pex_exe=find_exe(tech.pex_version)
|
||||||
|
if OPTS.pex_exe==None:
|
||||||
|
debug.warning("{0} not found. Unable to perform PEX.".format(tech.pex_version))
|
||||||
|
OPTS.check_lvsdrc = False
|
||||||
|
else:
|
||||||
|
debug.info(1, "Using PEX: " + OPTS.pex_exe)
|
||||||
|
|
||||||
def end_openram():
|
def end_openram():
|
||||||
""" Clean up openram for a proper exit """
|
""" Clean up openram for a proper exit """
|
||||||
|
|
@ -234,16 +277,6 @@ def setup_paths():
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def find_spice(check_exe):
|
|
||||||
# Check if the preferred spice option exists in the path
|
|
||||||
for path in os.environ["PATH"].split(os.pathsep):
|
|
||||||
spice_exe = os.path.join(path, check_exe)
|
|
||||||
# if it is found, then break and use first version
|
|
||||||
if is_exe(spice_exe):
|
|
||||||
OPTS.spice_exe = spice_exe
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def set_spice():
|
def set_spice():
|
||||||
debug.info(2,"Finding spice...")
|
debug.info(2,"Finding spice...")
|
||||||
global OPTS
|
global OPTS
|
||||||
|
|
@ -252,13 +285,15 @@ def set_spice():
|
||||||
debug.info(1,"Using analytical delay models (no characterization)")
|
debug.info(1,"Using analytical delay models (no characterization)")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
spice_preferences = ["xa", "hspice", "ngspice", "ngspice.exe"]
|
|
||||||
if OPTS.spice_version != "":
|
if OPTS.spice_version != "":
|
||||||
if not find_spice(OPTS.spice_version):
|
OPTS.spice_exe=find_exe(OPTS.spice_version)
|
||||||
|
if OPTS.spice_exe==None:
|
||||||
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1)
|
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_version),1)
|
||||||
else:
|
else:
|
||||||
|
spice_preferences = ["xa", "hspice", "ngspice", "ngspice.exe"]
|
||||||
for spice_name in spice_preferences:
|
for spice_name in spice_preferences:
|
||||||
if find_spice(spice_name):
|
OPTS.spice_exe = find_exe(spice_name)
|
||||||
|
if OPTS.spice_exe!=None:
|
||||||
OPTS.spice_version=spice_name
|
OPTS.spice_version=spice_name
|
||||||
debug.info(1, "Using spice: " + OPTS.spice_exe)
|
debug.info(1, "Using spice: " + OPTS.spice_exe)
|
||||||
break
|
break
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,306 @@
|
||||||
|
"""
|
||||||
|
This is a DRC/LVS/PEX interface file for magic + netgen.
|
||||||
|
|
||||||
|
1. magic can perform drc with the following:
|
||||||
|
#!/bin/sh
|
||||||
|
magic -dnull -noconsole << EOF
|
||||||
|
tech load SCN3ME_SUBM.30
|
||||||
|
** import gds file
|
||||||
|
load $1.mag -force
|
||||||
|
drc count
|
||||||
|
drc why
|
||||||
|
quit -noprompt
|
||||||
|
EOF
|
||||||
|
|
||||||
|
2. magic can perform extraction with the following:
|
||||||
|
#!/bin/sh
|
||||||
|
rm -f $1.ext
|
||||||
|
rm -f $1.spice
|
||||||
|
magic -dnull -noconsole << EOF
|
||||||
|
tech load SCN3ME_SUBM.30
|
||||||
|
** import gds file
|
||||||
|
load $1.mag -force
|
||||||
|
extract
|
||||||
|
ext2spice scale off
|
||||||
|
ext2spice
|
||||||
|
quit -noprompt
|
||||||
|
EOF
|
||||||
|
|
||||||
|
3. netgen can perform LVS with:
|
||||||
|
#!/bin/sh
|
||||||
|
netgen -noconsole <<EOF
|
||||||
|
readnet $1.spice
|
||||||
|
readnet $1.sp
|
||||||
|
ignore class c
|
||||||
|
permute transistors
|
||||||
|
compare hierarchical $1.spice {$1.sp $1}
|
||||||
|
permute
|
||||||
|
run converge
|
||||||
|
EOF
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
import time
|
||||||
|
import debug
|
||||||
|
import globals
|
||||||
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
def run_drc(name, gds_name):
|
||||||
|
"""Run DRC check on a given top-level name which is
|
||||||
|
implemented in gds_name."""
|
||||||
|
|
||||||
|
debug.error("DRC using magic not implemented.",-1)
|
||||||
|
OPTS = globals.get_opts()
|
||||||
|
|
||||||
|
# the runset file contains all the options to run drc
|
||||||
|
from tech import drc
|
||||||
|
drc_rules = drc["drc_rules"]
|
||||||
|
|
||||||
|
drc_runset = {
|
||||||
|
'drcRulesFile': drc_rules,
|
||||||
|
'drcRunDir': OPTS.openram_temp,
|
||||||
|
'drcLayoutPaths': gds_name,
|
||||||
|
'drcLayoutPrimary': name,
|
||||||
|
'drcLayoutSystem': 'GDSII',
|
||||||
|
'drcResultsformat': 'ASCII',
|
||||||
|
'drcResultsFile': OPTS.openram_temp + name + ".drc.results",
|
||||||
|
'drcSummaryFile': OPTS.openram_temp + name + ".drc.summary",
|
||||||
|
'cmnFDILayerMapFile': drc["layer_map"],
|
||||||
|
'cmnFDIUseLayerMap': 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# write the runset file
|
||||||
|
f = open(OPTS.openram_temp + "drc_runset", "w")
|
||||||
|
for k in sorted(drc_runset.iterkeys()):
|
||||||
|
f.write("*%s: %s\n" % (k, drc_runset[k]))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# run drc
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(OPTS.openram_temp)
|
||||||
|
errfile = "{0}{1}.drc.err".format(OPTS.openram_temp, name)
|
||||||
|
outfile = "{0}{1}.drc.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
|
cmd = "{0} -gui -drc {1}drc_runset -batch 2> {2} 1> {3}".format(OPTS.drc_exe,
|
||||||
|
OPTS.openram_temp,
|
||||||
|
errfile,
|
||||||
|
outfile)
|
||||||
|
debug.info(1, cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
# check the result for these lines in the summary:
|
||||||
|
# TOTAL Original Layer Geometries: 106 (157)
|
||||||
|
# TOTAL DRC RuleChecks Executed: 156
|
||||||
|
# TOTAL DRC Results Generated: 0 (0)
|
||||||
|
try:
|
||||||
|
f = open(drc_runset['drcSummaryFile'], "r")
|
||||||
|
except:
|
||||||
|
debug.error("Unable to retrieve DRC results file. Is magic set up?",1)
|
||||||
|
results = f.readlines()
|
||||||
|
f.close()
|
||||||
|
# those lines should be the last 3
|
||||||
|
results = results[-3:]
|
||||||
|
geometries = int(re.split("\W+", results[0])[5])
|
||||||
|
rulechecks = int(re.split("\W+", results[1])[4])
|
||||||
|
errors = int(re.split("\W+", results[2])[5])
|
||||||
|
|
||||||
|
# always display this summary
|
||||||
|
if errors > 0:
|
||||||
|
debug.error("%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" %
|
||||||
|
(name, geometries, rulechecks, errors))
|
||||||
|
else:
|
||||||
|
debug.info(1, "%-25s\tGeometries: %d\tChecks: %d\tErrors: %d" %
|
||||||
|
(name, geometries, rulechecks, 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. """
|
||||||
|
|
||||||
|
debug.error("LVS using magic+netgen not implemented.",-1)
|
||||||
|
|
||||||
|
OPTS = globals.get_opts()
|
||||||
|
from tech import drc
|
||||||
|
lvs_rules = drc["lvs_rules"]
|
||||||
|
lvs_runset = {
|
||||||
|
'lvsRulesFile': lvs_rules,
|
||||||
|
'lvsRunDir': OPTS.openram_temp,
|
||||||
|
'lvsLayoutPaths': gds_name,
|
||||||
|
'lvsLayoutPrimary': name,
|
||||||
|
'lvsSourcePath': sp_name,
|
||||||
|
'lvsSourcePrimary': name,
|
||||||
|
'lvsSourceSystem': 'SPICE',
|
||||||
|
'lvsSpiceFile': OPTS.openram_temp + "extracted.sp",
|
||||||
|
'lvsPowerNames': 'vdd',
|
||||||
|
'lvsGroundNames': 'gnd',
|
||||||
|
'lvsIncludeSVRFCmds': 1,
|
||||||
|
'lvsSVRFCmds': '{VIRTUAL CONNECT NAME VDD? GND? ?}',
|
||||||
|
'lvsIgnorePorts': 1,
|
||||||
|
'lvsERCDatabase': OPTS.openram_temp + name + ".erc.results",
|
||||||
|
'lvsERCSummaryFile': OPTS.openram_temp + name + ".erc.summary",
|
||||||
|
'lvsReportFile': OPTS.openram_temp + name + ".lvs.report",
|
||||||
|
'lvsMaskDBFile': OPTS.openram_temp + name + ".maskdb",
|
||||||
|
'cmnFDILayerMapFile': drc["layer_map"],
|
||||||
|
'cmnFDIUseLayerMap': 1,
|
||||||
|
'cmnVConnectNames': 'vdd, gnd',
|
||||||
|
#'cmnVConnectNamesState' : 'ALL', #connects all nets with the same name
|
||||||
|
}
|
||||||
|
|
||||||
|
# write the runset file
|
||||||
|
f = open(OPTS.openram_temp + "lvs_runset", "w")
|
||||||
|
for k in sorted(lvs_runset.iterkeys()):
|
||||||
|
f.write("*%s: %s\n" % (k, lvs_runset[k]))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# run LVS
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(OPTS.openram_temp)
|
||||||
|
errfile = "{0}{1}.lvs.err".format(OPTS.openram_temp, name)
|
||||||
|
outfile = "{0}{1}.lvs.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
|
cmd = "{0} -gui -lvs {1}lvs_runset -batch 2> {2} 1> {3}".format(OPTS.lvs_exe,
|
||||||
|
OPTS.openram_temp,
|
||||||
|
errfile,
|
||||||
|
outfile)
|
||||||
|
debug.info(1, cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
# check the result for these lines in the summary:
|
||||||
|
f = open(lvs_runset['lvsReportFile'], "r")
|
||||||
|
results = f.readlines()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# NOT COMPARED
|
||||||
|
# CORRECT
|
||||||
|
# INCORRECT
|
||||||
|
test = re.compile("# CORRECT #")
|
||||||
|
correct = filter(test.search, results)
|
||||||
|
test = re.compile("NOT COMPARED")
|
||||||
|
notcompared = filter(test.search, results)
|
||||||
|
test = re.compile("# INCORRECT #")
|
||||||
|
incorrect = filter(test.search, results)
|
||||||
|
|
||||||
|
# Errors begin with "Error:"
|
||||||
|
test = re.compile("\s+Error:")
|
||||||
|
errors = filter(test.search, results)
|
||||||
|
for e in errors:
|
||||||
|
debug.error(e.strip("\n"))
|
||||||
|
|
||||||
|
summary_errors = len(notcompared) + len(incorrect) + len(errors)
|
||||||
|
|
||||||
|
# also check the extraction summary file
|
||||||
|
f = open(lvs_runset['lvsReportFile'] + ".ext", "r")
|
||||||
|
results = f.readlines()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
test = re.compile("ERROR:")
|
||||||
|
exterrors = filter(test.search, results)
|
||||||
|
for e in exterrors:
|
||||||
|
debug.error(e.strip("\n"))
|
||||||
|
|
||||||
|
test = re.compile("WARNING:")
|
||||||
|
extwarnings = filter(test.search, results)
|
||||||
|
for e in extwarnings:
|
||||||
|
debug.warning(e.strip("\n"))
|
||||||
|
|
||||||
|
# MRG - 9/26/17 - Change this to exclude warnings because of
|
||||||
|
# multiple labels on different pins in column mux.
|
||||||
|
ext_errors = len(exterrors)
|
||||||
|
ext_warnings = len(extwarnings)
|
||||||
|
|
||||||
|
# also check the output file
|
||||||
|
f = open(outfile, "r")
|
||||||
|
results = f.readlines()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# Errors begin with "ERROR:"
|
||||||
|
test = re.compile("ERROR:")
|
||||||
|
stdouterrors = filter(test.search, results)
|
||||||
|
for e in stdouterrors:
|
||||||
|
debug.error(e.strip("\n"))
|
||||||
|
|
||||||
|
out_errors = len(stdouterrors)
|
||||||
|
|
||||||
|
total_errors = summary_errors + out_errors + ext_errors
|
||||||
|
return total_errors
|
||||||
|
|
||||||
|
|
||||||
|
def run_pex(name, gds_name, sp_name, output=None):
|
||||||
|
"""Run pex on a given top-level name which is
|
||||||
|
implemented in gds_name and sp_name. """
|
||||||
|
|
||||||
|
debug.error("PEX using magic not implemented.",-1)
|
||||||
|
|
||||||
|
OPTS = globals.get_opts()
|
||||||
|
from tech import drc
|
||||||
|
if output == None:
|
||||||
|
output = name + ".pex.netlist"
|
||||||
|
|
||||||
|
# check if lvs report has been done
|
||||||
|
# if not run drc and lvs
|
||||||
|
if not os.path.isfile(name + ".lvs.report"):
|
||||||
|
run_drc(name, gds_name)
|
||||||
|
run_lvs(name, gds_name, sp_name)
|
||||||
|
|
||||||
|
pex_rules = drc["xrc_rules"]
|
||||||
|
pex_runset = {
|
||||||
|
'pexRulesFile': pex_rules,
|
||||||
|
'pexRunDir': OPTS.openram_temp,
|
||||||
|
'pexLayoutPaths': gds_name,
|
||||||
|
'pexLayoutPrimary': name,
|
||||||
|
#'pexSourcePath' : OPTS.openram_temp+"extracted.sp",
|
||||||
|
'pexSourcePath': sp_name,
|
||||||
|
'pexSourcePrimary': name,
|
||||||
|
'pexReportFile': name + ".lvs.report",
|
||||||
|
'pexPexNetlistFile': output,
|
||||||
|
'pexPexReportFile': name + ".pex.report",
|
||||||
|
'pexMaskDBFile': name + ".maskdb",
|
||||||
|
'cmnFDIDEFLayoutPath': name + ".def",
|
||||||
|
}
|
||||||
|
|
||||||
|
# write the runset file
|
||||||
|
f = open(OPTS.openram_temp + "pex_runset", "w")
|
||||||
|
for k in sorted(pex_runset.iterkeys()):
|
||||||
|
f.write("*{0}: {1}\n".format(k, pex_runset[k]))
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# run pex
|
||||||
|
cwd = os.getcwd()
|
||||||
|
os.chdir(OPTS.openram_temp)
|
||||||
|
errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name)
|
||||||
|
outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name)
|
||||||
|
|
||||||
|
cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe,
|
||||||
|
OPTS.openram_temp,
|
||||||
|
errfile,
|
||||||
|
outfile)
|
||||||
|
debug.info(2, cmd)
|
||||||
|
os.system(cmd)
|
||||||
|
os.chdir(cwd)
|
||||||
|
|
||||||
|
# also check the output file
|
||||||
|
f = open(outfile, "r")
|
||||||
|
results = f.readlines()
|
||||||
|
f.close()
|
||||||
|
|
||||||
|
# Errors begin with "ERROR:"
|
||||||
|
test = re.compile("ERROR:")
|
||||||
|
stdouterrors = filter(test.search, results)
|
||||||
|
for e in stdouterrors:
|
||||||
|
debug.error(e.strip("\n"))
|
||||||
|
|
||||||
|
out_errors = len(stdouterrors)
|
||||||
|
|
||||||
|
assert(os.path.isfile(output))
|
||||||
|
#correct_port(name, output, sp_name)
|
||||||
|
|
||||||
|
return out_errors
|
||||||
|
|
||||||
|
|
@ -36,7 +36,7 @@ class nand_3(design.design):
|
||||||
|
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
self.DRC_LVS()
|
#self.DRC_LVS()
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
""" add pics for this module """
|
""" add pics for this module """
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,6 @@ a Liberty (.lib) file for timing analysis/optimization
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = "Matthew Guthaus (mrg@ucsc.edu) and numerous others"
|
|
||||||
__version__ = "$Revision: 0.9 $"
|
|
||||||
__copyright__ = "Copyright (c) 2015 UCSC and OSU"
|
|
||||||
__license__ = "This is not currently licensed for use outside of UCSC's VLSI-DA and OSU's VLSI group."
|
|
||||||
|
|
||||||
|
|
||||||
import sys,os
|
import sys,os
|
||||||
import datetime
|
import datetime
|
||||||
import re
|
import re
|
||||||
|
|
@ -72,17 +66,18 @@ print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
|
||||||
print("Technology: {0}".format(OPTS.tech_name))
|
print("Technology: {0}".format(OPTS.tech_name))
|
||||||
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks))
|
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks))
|
||||||
|
|
||||||
|
if not OPTS.check_lvsdrc:
|
||||||
|
print("DRC/LVS/PEX checking is disabled.")
|
||||||
|
|
||||||
if OPTS.analytical_delay:
|
if OPTS.analytical_delay:
|
||||||
print("Using analytical delay models (no characterization)")
|
print("Using analytical delay models (no characterization)")
|
||||||
else:
|
else:
|
||||||
print("Performing simulation-based characterization with {}".format(OPTS.spice_version))
|
print("Performing simulation-based characterization with {}".format(OPTS.spice_version))
|
||||||
|
if OPTS.trim_netlist:
|
||||||
if OPTS.trim_netlist:
|
print("Trimming netlist to speed up characterization (sacrificing some accuracy).")
|
||||||
print("Trimming netlist to speed up characterization (sacrificing some accuracy).")
|
|
||||||
|
|
||||||
# only start importing modules after we have the config file
|
# only start importing modules after we have the config file
|
||||||
import calibre
|
import verify
|
||||||
import sram
|
import sram
|
||||||
|
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
@ -111,7 +106,7 @@ last_time=print_time("Spice writing", datetime.datetime.now(), last_time)
|
||||||
sram_file = spname
|
sram_file = spname
|
||||||
if OPTS.use_pex:
|
if OPTS.use_pex:
|
||||||
sram_file = OPTS.output_path + "temp_pex.sp"
|
sram_file = OPTS.output_path + "temp_pex.sp"
|
||||||
calibre.run_pex(s.name, gdsname, spname, output=sram_file)
|
verify.run_pex(s.name, gdsname, spname, output=sram_file)
|
||||||
|
|
||||||
# Characterize the design
|
# Characterize the design
|
||||||
import lib
|
import lib
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,10 @@ class options(optparse.Values):
|
||||||
spice_version = ""
|
spice_version = ""
|
||||||
# Should we print out the banner at startup
|
# Should we print out the banner at startup
|
||||||
print_banner = True
|
print_banner = True
|
||||||
# The Calibre executable being used which is derived from the user PATH.
|
# The DRC/LVS/PEX executable being used which is derived from the user PATH.
|
||||||
calibre_exe = ""
|
drc_exe = ""
|
||||||
|
lvs_exe = ""
|
||||||
|
pex_exe = ""
|
||||||
# The spice executable being used which is derived from the user PATH.
|
# The spice executable being used which is derived from the user PATH.
|
||||||
spice_exe = ""
|
spice_exe = ""
|
||||||
# Run with extracted parasitics
|
# Run with extracted parasitics
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
"""
|
||||||
|
This is a module that will import the correct DRC/LVS/PEX
|
||||||
|
module based on what tools are found. It is a layer of indirection
|
||||||
|
to enable multiple verification tool support.
|
||||||
|
|
||||||
|
Each DRC/LVS/PEX tool should implement the functions run_drc, run_lvs, and
|
||||||
|
run_pex, repsectively. If there is an error, they should abort and report the errors.
|
||||||
|
If not, OpenRAM will continue as if nothing happened!
|
||||||
|
"""
|
||||||
|
|
||||||
|
import debug
|
||||||
|
import tech
|
||||||
|
|
||||||
|
if tech.drc_version=="calibre":
|
||||||
|
from calibre import run_drc
|
||||||
|
elif tech.drc_version=="magic":
|
||||||
|
from magic import run_drc
|
||||||
|
else:
|
||||||
|
debug.warning("Did not find a supported DRC tool.")
|
||||||
|
|
||||||
|
if tech.lvs_version=="calibre":
|
||||||
|
from calibre import run_lvs
|
||||||
|
elif tech.lvs_version=="netgen":
|
||||||
|
from magic import run_lvs
|
||||||
|
else:
|
||||||
|
debug.warning("Did not find a supported LVS tool.")
|
||||||
|
|
||||||
|
|
||||||
|
if tech.pex_version=="calibre":
|
||||||
|
from calibre import run_pex
|
||||||
|
elif tech.pex_version=="magic":
|
||||||
|
from magic import run_pex
|
||||||
|
else:
|
||||||
|
debug.warning("Did not find a supported PEX tool.")
|
||||||
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
"""
|
"""
|
||||||
File containing the process technology parameters.
|
File containing the process technology parameters for FreePDK 45nm.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
info = {}
|
info = {}
|
||||||
|
|
@ -17,9 +17,13 @@ GDS["unit"] = (0.0005,1e-9)
|
||||||
# default label zoom
|
# default label zoom
|
||||||
GDS["zoom"] = 0.05
|
GDS["zoom"] = 0.05
|
||||||
|
|
||||||
#####################################################################################################
|
drc_version = "calibre"
|
||||||
##GDS Layer Map######################################################################################
|
lvs_version = "calibre"
|
||||||
#####################################################################################################
|
pex_version = "calibre"
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
##GDS Layer Map
|
||||||
|
###################################################
|
||||||
|
|
||||||
# create the GDS layer map
|
# create the GDS layer map
|
||||||
# FIXME: parse the gds layer map from the cadence map?
|
# FIXME: parse the gds layer map from the cadence map?
|
||||||
|
|
@ -56,13 +60,13 @@ layer["metal10"] = 29
|
||||||
layer["text"] = 239
|
layer["text"] = 239
|
||||||
layer["boundary"]= 239
|
layer["boundary"]= 239
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##END GDS Layer Map##################################################################################
|
##END GDS Layer Map
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##DRC/LVS Rules Setup################################################################################
|
##DRC/LVS Rules Setup
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#technology parameter
|
#technology parameter
|
||||||
parameter={}
|
parameter={}
|
||||||
|
|
@ -243,13 +247,13 @@ drc["metal10_to_metal10"] = 0.14
|
||||||
drc["metal10_extend_via9"] = 0
|
drc["metal10_extend_via9"] = 0
|
||||||
drc["metal10_enclosure_via9"] = 0
|
drc["metal10_enclosure_via9"] = 0
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##END DRC/LVS Rules##################################################################################
|
##END DRC/LVS Rules
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##Spice Simulation Parameters########################################################################
|
##Spice Simulation Parameters
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#spice info
|
#spice info
|
||||||
spice = {}
|
spice = {}
|
||||||
|
|
@ -298,3 +302,9 @@ spice["msflop_setup"] = 9 # DFF setup time in ps
|
||||||
spice["msflop_hold"] = 1 # DFF hold time in ps
|
spice["msflop_hold"] = 1 # DFF hold time in ps
|
||||||
spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps
|
spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps
|
||||||
spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load
|
spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
##END Spice Simulation Parameters
|
||||||
|
###################################################
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Class containing the process technology parameters.
|
File containing the process technology parameters for SCMOS 3me, subm, 180nm.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
info={}
|
info={}
|
||||||
info["name"]="scn3me_subm"
|
info["name"]="scn3me_subm"
|
||||||
info["body_tie_down"] = 0
|
info["body_tie_down"] = 0
|
||||||
|
|
@ -16,9 +17,14 @@ GDS["unit"]=(0.001,1e-6)
|
||||||
# default label zoom
|
# default label zoom
|
||||||
GDS["zoom"] = 0.5
|
GDS["zoom"] = 0.5
|
||||||
|
|
||||||
#####################################################################################################
|
drc_version = "magic"
|
||||||
##GDS Layer Map######################################################################################
|
lvs_version = "netgen"
|
||||||
#####################################################################################################
|
pex_version = "magic"
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
##GDS Layer Map
|
||||||
|
###################################################
|
||||||
|
|
||||||
# create the GDS layer map
|
# create the GDS layer map
|
||||||
layer={}
|
layer={}
|
||||||
|
|
@ -41,13 +47,13 @@ layer["metal3"] = 62
|
||||||
layer["text"] = 83
|
layer["text"] = 83
|
||||||
layer["boundary"] = 83
|
layer["boundary"] = 83
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##END GDS Layer Map##################################################################################
|
##END GDS Layer Map
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##DRC/LVS Rules Setup################################################################################
|
##DRC/LVS Rules Setup
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#technology parameter
|
#technology parameter
|
||||||
parameter={}
|
parameter={}
|
||||||
|
|
@ -163,13 +169,13 @@ drc["metal3_extend_via2"] = 0.6
|
||||||
drc["metal3_enclosure_via2"] = 0.6
|
drc["metal3_enclosure_via2"] = 0.6
|
||||||
drc["minarea_metal3"] = 0
|
drc["minarea_metal3"] = 0
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##END DRC/LVS Rules##################################################################################
|
##END DRC/LVS Rules
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
#####################################################################################################
|
###################################################
|
||||||
##Spice Simulation Parameters########################################################################
|
##Spice Simulation Parameters
|
||||||
#####################################################################################################
|
###################################################
|
||||||
|
|
||||||
# spice model info
|
# spice model info
|
||||||
spice={}
|
spice={}
|
||||||
|
|
@ -218,3 +224,7 @@ spice["msflop_hold"] = 1 # DFF hold time in ps
|
||||||
spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps
|
spice["msflop_delay"] = 20.5 # DFF Clk-to-q delay in ps
|
||||||
spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load
|
spice["msflop_slew"] = 13.1 # DFF output slew in ps w/ no load
|
||||||
|
|
||||||
|
|
||||||
|
###################################################
|
||||||
|
##END Spice Simulation Parameters
|
||||||
|
###################################################
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue