mirror of https://github.com/VLSIDA/OpenRAM.git
Add optional lvs_lib netlists for LVS usage (sp_lib is for simulation)
This commit is contained in:
parent
8603d3edd6
commit
f358de78bb
|
|
@ -24,6 +24,14 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
|
||||||
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
|
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
|
||||||
self.sp_file = OPTS.openram_tech + "sp_lib/" + name + ".sp"
|
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
|
self.name = name
|
||||||
hierarchy_spice.spice.__init__(self, name)
|
hierarchy_spice.spice.__init__(self, name)
|
||||||
hierarchy_layout.layout.__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)
|
tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name)
|
||||||
tempgds = "{0}/{1}.gds".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)
|
self.gds_write(tempgds)
|
||||||
# Final verification option does not allow nets to be connected by label.
|
# 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)
|
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)):
|
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)
|
tempspice = "{0}/{1}.sp".format(OPTS.openram_temp, self.name)
|
||||||
tempgds = "{0}/{1}.gds".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)
|
self.gds_write(tempgds)
|
||||||
num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
|
num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
|
||||||
debug.check(num_errors == 0,
|
debug.check(num_errors == 0,
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ class spice():
|
||||||
# Keep track of any comments to add the the spice
|
# Keep track of any comments to add the the spice
|
||||||
try:
|
try:
|
||||||
self.commments
|
self.commments
|
||||||
except NameError:
|
except AttributeError:
|
||||||
self.comments = []
|
self.comments = []
|
||||||
|
|
||||||
self.sp_read()
|
self.sp_read()
|
||||||
|
|
@ -57,7 +57,7 @@ class spice():
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self.commments
|
self.commments
|
||||||
except NameError:
|
except AttributeError:
|
||||||
self.comments = []
|
self.comments = []
|
||||||
|
|
||||||
self.comments.append(comment)
|
self.comments.append(comment)
|
||||||
|
|
@ -210,6 +210,24 @@ class spice():
|
||||||
else:
|
else:
|
||||||
self.spice = []
|
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):
|
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."""
|
"""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.
|
# Remove spaces and lower case then add spaces.
|
||||||
|
|
@ -239,16 +257,18 @@ class spice():
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def sp_write_file(self, sp, usedMODS):
|
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"""
|
Recursive spice subcircuit write;
|
||||||
|
Writes the spice subcircuit from the library or the dynamically generated one
|
||||||
|
"""
|
||||||
if not self.spice:
|
if not self.spice:
|
||||||
# recursively write the modules
|
# recursively write the modules
|
||||||
for i in self.mods:
|
for i in self.mods:
|
||||||
if self.contains(i, usedMODS):
|
if self.contains(i, usedMODS):
|
||||||
continue
|
continue
|
||||||
usedMODS.append(i)
|
usedMODS.append(i)
|
||||||
i.sp_write_file(sp, usedMODS)
|
i.sp_write_file(sp, usedMODS, lvs_netlist)
|
||||||
|
|
||||||
if len(self.insts) == 0:
|
if len(self.insts) == 0:
|
||||||
return
|
return
|
||||||
|
|
@ -296,7 +316,10 @@ class spice():
|
||||||
# Including the file path makes the unit test fail for other users.
|
# Including the file path makes the unit test fail for other users.
|
||||||
# if os.path.isfile(self.sp_file):
|
# if os.path.isfile(self.sp_file):
|
||||||
# sp.write("\n* {0}\n".format(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")
|
sp.write("\n")
|
||||||
|
|
||||||
|
|
@ -310,6 +333,16 @@ class spice():
|
||||||
del usedMODS
|
del usedMODS
|
||||||
spfile.close()
|
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):
|
def analytical_delay(self, corner, slew, load=0.0):
|
||||||
"""Inform users undefined delay module while building new modules"""
|
"""Inform users undefined delay module while building new modules"""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -574,11 +574,11 @@ class sram_base(design, verilog, lef):
|
||||||
sp.write("* Data bits: {}\n".format(self.word_size))
|
sp.write("* Data bits: {}\n".format(self.word_size))
|
||||||
sp.write("* Banks: {}\n".format(self.num_banks))
|
sp.write("* Banks: {}\n".format(self.num_banks))
|
||||||
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
|
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
|
||||||
sp.write("**************************************************\n")
|
sp.write("**************************************************\n")
|
||||||
# This causes unit test mismatch
|
# This causes unit test mismatch
|
||||||
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
|
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
|
||||||
# sp.write("* User: {0}\n".format(getpass.getuser()))
|
# 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"]))
|
# spice["gnd_name"]))
|
||||||
usedMODS = list()
|
usedMODS = list()
|
||||||
self.sp_write_file(sp, usedMODS)
|
self.sp_write_file(sp, usedMODS)
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,9 @@ class library_lvs_test(openram_test):
|
||||||
|
|
||||||
def setup_files():
|
def setup_files():
|
||||||
gds_dir = OPTS.openram_tech + "/gds_lib"
|
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)
|
files = os.listdir(gds_dir)
|
||||||
nametest = re.compile("\.gds$", re.IGNORECASE)
|
nametest = re.compile("\.gds$", re.IGNORECASE)
|
||||||
gds_files = list(filter(nametest.search, files))
|
gds_files = list(filter(nametest.search, files))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue