PR from mithro + other changable GDS file names

This commit is contained in:
mrg
2020-11-02 16:00:16 -08:00
parent 1caecf5a69
commit fa89b73ef8
38 changed files with 275 additions and 330 deletions
+1 -1
View File
@@ -34,7 +34,7 @@ class contact(hierarchy_design.hierarchy_design):
# This will ignore the name parameter since
# we can guarantee a unique name here
super().__init__(name)
super().__init__(name, name)
debug.info(4, "create contact object {0}".format(name))
self.add_comment("layers: {0}".format(layer_stack))
+4 -2
View File
@@ -20,8 +20,10 @@ class design(hierarchy_design):
"""
def __init__(self, name):
super().__init__(name)
def __init__(self, name, cell_name=None):
if not cell_name:
cell_name = name
super().__init__(name, cell_name)
self.setup_multiport_constants()
+3 -3
View File
@@ -227,7 +227,7 @@ class instance(geometry):
self.mod.gds_write_file(self.gds)
# now write an instance of my module/structure
new_layout.addInstance(self.gds,
self.mod.name,
self.mod.cell_name,
offsetInMicrons=self.offset,
mirror=self.mirror,
rotate=self.rotate)
@@ -402,11 +402,11 @@ class instance(geometry):
def __str__(self):
""" override print function output """
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")"
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.cell_name + " " + self.mirror + " R=" + str(self.rotate) + ")"
def __repr__(self):
""" override print function output """
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.name + " " + self.mirror + " R=" + str(self.rotate) + ")"
return "( inst: " + self.name + " @" + str(self.offset) + " mod=" + self.mod.cell_name + " " + self.mirror + " R=" + str(self.rotate) + ")"
class path(geometry):
+16 -15
View File
@@ -20,9 +20,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""
name_map = []
def __init__(self, name):
self.gds_file = OPTS.openram_tech + "gds_lib/" + name + ".gds"
self.sp_file = OPTS.openram_tech + "sp_lib/" + name + ".sp"
def __init__(self, name, cell_name):
self.gds_file = OPTS.openram_tech + "gds_lib/" + cell_name + ".gds"
self.sp_file = OPTS.openram_tech + "sp_lib/" + cell_name + ".sp"
# If we have a separate lvs directory, then all the lvs files
# should be in there (all or nothing!)
@@ -41,8 +41,9 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
self.lvs_errors = "skipped"
self.name = name
hierarchy_spice.spice.__init__(self, name)
hierarchy_layout.layout.__init__(self, name)
self.cell_name = cell_name
hierarchy_spice.spice.__init__(self, name, cell_name)
hierarchy_layout.layout.__init__(self, name, cell_name)
self.init_graph_params()
def get_layout_pins(self, inst):
@@ -76,17 +77,17 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
self.lvs_write(tempspice)
self.gds_write(tempgds)
# Final verification option does not allow nets to be connected by label.
self.drc_errors = verify.run_drc(self.name, tempgds, extract=True, final_verification=final_verification)
self.lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
self.drc_errors = verify.run_drc(self.cell_name, tempgds, extract=True, final_verification=final_verification)
self.lvs_errors = verify.run_lvs(self.cell_name, tempgds, tempspice, final_verification=final_verification)
# force_check is used to determine decoder height and other things, so we shouldn't fail
# if that flag is set
if OPTS.inline_lvsdrc and not force_check:
debug.check(self.drc_errors == 0,
"DRC failed for {0} with {1} error(s)".format(self.name,
"DRC failed for {0} with {1} error(s)".format(self.cell_name,
self.drc_errors))
debug.check(self.lvs_errors == 0,
"LVS failed for {0} with {1} errors(s)".format(self.name,
"LVS failed for {0} with {1} errors(s)".format(self.cell_name,
self.lvs_errors))
if OPTS.purge_temp:
@@ -104,11 +105,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
if OPTS.netlist_only:
return
elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.cell_name)
self.gds_write(tempgds)
num_errors = verify.run_drc(self.name, tempgds, final_verification=final_verification)
num_errors = verify.run_drc(self.cell_name, tempgds, final_verification=final_verification)
debug.check(num_errors == 0,
"DRC failed for {0} with {1} error(s)".format(self.name,
"DRC failed for {0} with {1} error(s)".format(self.cell_name,
num_errors))
if OPTS.purge_temp:
@@ -125,13 +126,13 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
if OPTS.netlist_only:
return
elif (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.cell_name)
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
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,
"LVS failed for {0} with {1} error(s)".format(self.name,
"LVS failed for {0} with {1} error(s)".format(self.cell_name,
num_errors))
if OPTS.purge_temp:
os.remove(tempspice)
@@ -217,7 +218,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
pins = ",".join(self.pins)
insts = [" {}".format(x) for x in self.insts]
objs = [" {}".format(x) for x in self.objs]
s = "********** design {0} **********".format(self.name)
s = "********** design {0} **********".format(self.cell_name)
s += "\n pins ({0})={1}\n".format(len(self.pins), pins)
s += "\n objs ({0})=\n{1}\n".format(len(self.objs), "\n".join(objs))
s += "\n insts ({0})=\n{1}\n".format(len(self.insts), "\n".join(insts))
+4 -3
View File
@@ -30,8 +30,9 @@ class layout():
layout/netlist and perform LVS/DRC.
"""
def __init__(self, name):
def __init__(self, name, cell_name):
self.name = name
self.cell_name = cell_name
self.width = None
self.height = None
self.bounding_box = None
@@ -214,7 +215,7 @@ class layout():
# Contacts are not really instances, so skip them
if "contact" not in mod.name:
# Check that the instance name is unique
debug.check(name not in self.inst_names, "Duplicate named instance in {0}: {1}".format(self.name, name))
debug.check(name not in self.inst_names, "Duplicate named instance in {0}: {1}".format(self.cell_name, name))
self.inst_names.add(name)
self.insts.append(geometry.instance(name, mod, offset, mirror, rotate))
@@ -315,7 +316,7 @@ class layout():
return any_pin
except Exception:
self.gds_write("missing_pin.gds")
debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.name), -1)
debug.error("No pin found with name {0} on {1}. Saved as missing_pin.gds.".format(text, self.cell_name), -1)
def get_pins(self, text):
"""
+11 -11
View File
@@ -10,6 +10,7 @@ import re
import os
import math
import tech
from pprint import pformat
from delay_data import delay_data
from wire_spice_model import wire_spice_model
from power_data import power_data
@@ -26,8 +27,9 @@ class spice():
Class consisting of a set of modules and instances of these modules
"""
def __init__(self, name):
def __init__(self, name, cell_name):
self.name = name
self.cell_name = cell_name
self.valid_signal_types = ["INOUT", "INPUT", "OUTPUT", "POWER", "GROUND"]
# Holds subckts/mods for this module
@@ -164,7 +166,6 @@ class spice():
num_pins = len(self.insts[-1].mod.pins)
num_args = len(args)
if (check and num_pins != num_args):
from pprint import pformat
if num_pins < num_args:
mod_pins = self.insts[-1].mod.pins + [""] * (num_args - num_pins)
arg_pins = args
@@ -181,7 +182,6 @@ class spice():
self.conns.append(args)
if check and (len(self.insts)!=len(self.conns)):
from pprint import pformat
insts_string=pformat(self.insts)
conns_string=pformat(self.conns)
@@ -214,7 +214,7 @@ class spice():
f.close()
# find the correct subckt line in the file
subckt = re.compile("^.subckt {}".format(self.name), re.IGNORECASE)
subckt = re.compile("^.subckt {}".format(self.cell_name), re.IGNORECASE)
subckt_line = list(filter(subckt.search, self.spice))[0]
# parses line into ports and remove subckt
self.pins = subckt_line.split(" ")[2:]
@@ -234,7 +234,7 @@ class spice():
# 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 = re.compile("^.subckt {}".format(self.cell_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:]
@@ -293,7 +293,7 @@ class spice():
return
# write out the first spice line (the subcircuit)
sp.write("\n.SUBCKT {0} {1}\n".format(self.name,
sp.write("\n.SUBCKT {0} {1}\n".format(self.cell_name,
" ".join(self.pins)))
for pin in self.pins:
@@ -304,7 +304,7 @@ class spice():
# every instance must have a set of connections, even if it is empty.
if len(self.insts) != len(self.conns):
debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.name,
debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.cell_name,
len(self.insts),
len(self.conns)))
debug.error("Instances: \n" + str(self.insts))
@@ -330,9 +330,9 @@ class spice():
else:
sp.write("X{0} {1} {2}\n".format(self.insts[i].name,
" ".join(self.conns[i]),
self.insts[i].mod.name))
self.insts[i].mod.cell_name))
sp.write(".ENDS {0}\n".format(self.name))
sp.write(".ENDS {0}\n".format(self.cell_name))
else:
# If spice is a hard module, output the spice file contents.
@@ -390,7 +390,7 @@ class spice():
.format(self.__class__.__name__))
debug.warning("Class {0} name {1}"
.format(self.__class__.__name__,
self.name))
self.cell_name))
return None
def get_cin(self):
@@ -408,7 +408,7 @@ class spice():
.format(self.__class__.__name__))
debug.warning("Class {0} name {1}"
.format(self.__class__.__name__,
self.name))
self.cell_name))
return 0
def cal_delay_with_rc(self, corner, r, c, slew, swing=0.5):
+2
View File
@@ -95,6 +95,7 @@ def _get_gds_reader(units, gds_filename):
_GDS_SIZE_CACHE = {}
def get_gds_size(name, gds_filename, units, lpp):
"""
Open a GDS file and return the size from either the
@@ -129,6 +130,7 @@ def get_libcell_size(name, units, lpp):
_GDS_PINS_CACHE = {}
def get_gds_pins(pin_names, name, gds_filename, units):
"""
Open a GDS file and find the pins in pin_names as text on a given layer.