Add optional lvs_lib netlists for LVS usage (sp_lib is for simulation)

This commit is contained in:
mrg 2020-04-03 13:39:54 -07:00
parent 8603d3edd6
commit f358de78bb
4 changed files with 55 additions and 12 deletions

View File

@ -24,6 +24,14 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
self.sp_file = OPTS.openram_tech + "sp_lib/" + name + ".sp"
# If we have a separate lvs directory, then all the lvs files
# should be in there (all or nothing!)
lvs_dir = OPTS.openram_tech + "lvs_lib/"
if os.path.exists(lvs_dir):
self.lvs_file = lvs_dir + name + ".sp"
else:
self.lvs_file = self.sp_file
self.name = name
hierarchy_spice.spice.__init__(self, name)
hierarchy_layout.layout.__init__(self, name)
@ -56,7 +64,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name)
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
self.sp_write(tempspice)
self.lvs_write(tempspice)
self.gds_write(tempgds)
# Final verification option does not allow nets to be connected by label.
num_drc_errors = verify.run_drc(self.name, tempgds, extract=True, final_verification=final_verification)
@ -114,7 +122,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name)
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
self.sp_write(tempspice)
self.lvs_write(tempspice)
self.gds_write(tempgds)
num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
debug.check(num_errors == 0,

View File

@ -43,7 +43,7 @@ class spice():
# Keep track of any comments to add the the spice
try:
self.commments
except NameError:
except AttributeError:
self.comments = []
self.sp_read()
@ -57,7 +57,7 @@ class spice():
try:
self.commments
except NameError:
except AttributeError:
self.comments = []
self.comments.append(comment)
@ -210,6 +210,24 @@ class spice():
else:
self.spice = []
# We don't define self.lvs and will use self.spice if dynamically created
# or they are the same file
if self.lvs_file!=self.sp_file and os.path.isfile(self.lvs_file):
debug.info(3, "opening {0}".format(self.lvs_file))
f = open(self.lvs_file)
self.lvs = f.readlines()
for i in range(len(self.lvs)):
self.lvs[i] = self.lvs[i].rstrip(" \n")
f.close()
# pins and subckt should be the same
# find the correct subckt line in the file
subckt = re.compile("^.subckt {}".format(self.name), re.IGNORECASE)
subckt_line = list(filter(subckt.search, self.lvs))[0]
# parses line into ports and remove subckt
lvs_pins = subckt_line.split(" ")[2:]
debug.check(lvs_pins == self.pins, "LVS and spice file pin mismatch.", -1)
def check_net_in_spice(self, net_name):
"""Checks if a net name exists in the current. Intended to be check nets in hand-made cells."""
# Remove spaces and lower case then add spaces.
@ -239,16 +257,18 @@ class spice():
return True
return False
def sp_write_file(self, sp, usedMODS):
""" Recursive spice subcircuit write;
Writes the spice subcircuit from the library or the dynamically generated one"""
def sp_write_file(self, sp, usedMODS, lvs_netlist=False):
"""
Recursive spice subcircuit write;
Writes the spice subcircuit from the library or the dynamically generated one
"""
if not self.spice:
# recursively write the modules
for i in self.mods:
if self.contains(i, usedMODS):
continue
usedMODS.append(i)
i.sp_write_file(sp, usedMODS)
i.sp_write_file(sp, usedMODS, lvs_netlist)
if len(self.insts) == 0:
return
@ -296,7 +316,10 @@ class spice():
# Including the file path makes the unit test fail for other users.
# if os.path.isfile(self.sp_file):
# sp.write("\n* {0}\n".format(self.sp_file))
sp.write("\n".join(self.spice))
if lvs_netlist:
sp.write("\n".join(self.lvs))
else:
sp.write("\n".join(self.spice))
sp.write("\n")
@ -310,6 +333,16 @@ class spice():
del usedMODS
spfile.close()
def lvs_write(self, spname):
"""Writes the lvs to files"""
debug.info(3, "Writing to {0}".format(spname))
spfile = open(spname, 'w')
spfile.write("*FIRST LINE IS A COMMENT\n")
usedMODS = list()
self.sp_write_file(spfile, usedMODS, True)
del usedMODS
spfile.close()
def analytical_delay(self, corner, slew, load=0.0):
"""Inform users undefined delay module while building new modules"""

View File

@ -574,11 +574,11 @@ class sram_base(design, verilog, lef):
sp.write("* Data bits: {}\n".format(self.word_size))
sp.write("* Banks: {}\n".format(self.num_banks))
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
sp.write("**************************************************\n")
sp.write("**************************************************\n")
# This causes unit test mismatch
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
# sp.write("* User: {0}\n".format(getpass.getuser()))
# sp.write(".global {0} {1}\n".format(spice["vdd_name"],
# sp.write(".global {0} {1}\n".format(spice["vdd_name"],
# spice["gnd_name"]))
usedMODS = list()
self.sp_write_file(sp, usedMODS)

View File

@ -45,7 +45,9 @@ class library_lvs_test(openram_test):
def setup_files():
gds_dir = OPTS.openram_tech + "/gds_lib"
sp_dir = OPTS.openram_tech + "/sp_lib"
sp_dir = OPTS.openram_tech + "/lvs_lib"
if not os.path.exists(sp_dir):
sp_dir = OPTS.openram_tech + "/sp_lib"
files = os.listdir(gds_dir)
nametest = re.compile("\.gds$", re.IGNORECASE)
gds_files = list(filter(nametest.search, files))