PEP8 cleanup. DRC/LVS returns errors.

This commit is contained in:
mrg 2020-04-02 09:47:39 -07:00
parent 0d6c84036d
commit 5349323acd
3 changed files with 75 additions and 56 deletions

View File

@ -29,39 +29,42 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
hierarchy_layout.layout.__init__(self, name)
self.init_graph_params()
def get_layout_pins(self,inst):
def get_layout_pins(self, inst):
""" Return a map of pin locations of the instance offset """
# find the instance
for i in self.insts:
if i.name == inst.name:
break
else:
debug.error("Couldn't find instance {0}".format(inst_name),-1)
debug.error("Couldn't find instance {0}".format(inst_name), -1)
inst_map = inst.mod.pin_map
return inst_map
def DRC_LVS(self, final_verification=False, top_level=False):
def DRC_LVS(self, final_verification=False, force_check=False):
"""Checks both DRC and LVS for a module"""
# Final verification option does not allow nets to be connected by label.
# Unit tests will check themselves.
if OPTS.is_unit_test:
if not force_check and OPTS.is_unit_test:
return ("skipped", "skipped")
if not OPTS.check_lvsdrc:
if not force_check and not OPTS.check_lvsdrc:
return ("skipped", "skipped")
# Do not run if disabled in options.
if (OPTS.inline_lvsdrc or top_level):
if (OPTS.inline_lvsdrc or force_check):
tempspice = "{0}/{1}.sp".format(OPTS.openram_temp,self.name)
tempgds = "{0}/{1}.gds".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)
self.sp_write(tempspice)
self.gds_write(tempgds)
num_drc_errors = verify.run_drc(self.name, tempgds, extract=True, final_verification=final_verification)
num_lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
debug.check(num_drc_errors == 0,"DRC failed for {0} with {1} error(s)".format(self.name,num_drc_errors))
debug.check(num_lvs_errors == 0,"LVS failed for {0} with {1} errors(s)".format(self.name,num_lvs_errors))
num_drc_errors = verify.run_drc(self.name, tempgds, extract=True, final_verification=final_verification)
num_lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
debug.check(num_drc_errors == 0,
"DRC failed for {0} with {1} error(s)".format(self.name,
num_drc_errors))
debug.check(num_lvs_errors == 0,
"LVS failed for {0} with {1} errors(s)".format(self.name,
num_lvs_errors))
os.remove(tempspice)
os.remove(tempgds)
@ -74,10 +77,12 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
# Do not run if disabled in options.
if (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.name)
self.gds_write(tempgds)
num_errors = verify.run_drc(self.name, tempgds, final_verification=final_verification)
debug.check(num_errors == 0,"DRC failed for {0} with {1} error(s)".format(self.name,num_error))
num_errors = verify.run_drc(self.name, tempgds, final_verification=final_verification)
debug.check(num_errors == 0,
"DRC failed for {0} with {1} error(s)".format(self.name,
num_errors))
os.remove(tempgds)
@ -91,12 +96,14 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
# Do not run if disabled in options.
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)
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.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,num_errors))
debug.check(num_errors == 0,
"LVS failed for {0} with {1} error(s)".format(self.name,
num_errors))
os.remove(tempspice)
os.remove(tempgds)
@ -106,40 +113,44 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
def init_graph_params(self):
"""Initializes parameters relevant to the graph creation"""
#Only initializes a set for checking instances which should not be added
# Only initializes a set for checking instances which should not be added
self.graph_inst_exclude = set()
def build_graph(self, graph, inst_name, port_nets):
def build_graph(self, graph, inst_name, port_nets):
"""Recursively create graph from instances in module."""
#Translate port names to external nets
# Translate port names to external nets
if len(port_nets) != len(self.pins):
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1)
port_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,
self.pins),
1)
port_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
debug.info(3, "Instance name={}".format(inst_name))
for subinst, conns in zip(self.insts, self.conns):
if subinst in self.graph_inst_exclude:
continue
subinst_name = inst_name+'.X'+subinst.name
subinst_name = inst_name + '.X' + subinst.name
subinst_ports = self.translate_nets(conns, port_dict, inst_name)
subinst.mod.build_graph(graph, subinst_name, subinst_ports)
def build_names(self, name_dict, inst_name, port_nets):
"""Collects all the nets and the parent inst of that net."""
#Translate port names to external nets
# Translate port names to external nets
if len(port_nets) != len(self.pins):
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1)
port_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,
self.pins),
1)
port_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
debug.info(3, "Instance name={}".format(inst_name))
for subinst, conns in zip(self.insts, self.conns):
subinst_name = inst_name+'.X'+subinst.name
subinst_name = inst_name + '.X' + subinst.name
subinst_ports = self.translate_nets(conns, port_dict, inst_name)
for si_port, conn in zip(subinst_ports, conns):
#Only add for first occurrence
# Only add for first occurrence
if si_port.lower() not in name_dict:
mod_info = {'mod':self, 'int_net':conn}
mod_info = {'mod': self, 'int_net': conn}
name_dict[si_port.lower()] = mod_info
subinst.mod.build_names(name_dict, subinst_name, subinst_ports)
subinst.mod.build_names(name_dict, subinst_name, subinst_ports)
def find_aliases(self, inst_name, port_nets, path_nets, alias, alias_mod, exclusion_set=None):
"""Given a list of nets, will compare the internal alias of a mod to determine
@ -159,17 +170,17 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
int_mod = self.name_dict[net]['mod']
if int_mod.is_net_alias(int_net, alias, alias_mod, exclusion_set):
aliases.append(net)
return aliases
return aliases
def is_net_alias(self, known_net, net_alias, mod, exclusion_set):
"""Checks if the alias_net in input mod is the same as the input net for this mod (self)."""
if self in exclusion_set:
return False
#Check ports of this mod
# Check ports of this mod
for pin in self.pins:
if self.is_net_alias_name_check(known_net, pin, net_alias, mod):
return True
#Check connections of all other subinsts
# Check connections of all other subinsts
mod_set = set()
for subinst, inst_conns in zip(self.insts, self.conns):
for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins):
@ -179,7 +190,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
if subinst.mod.is_net_alias(mod_pin, net_alias, mod, exclusion_set):
return True
mod_set.add(subinst.mod)
return False
return False
def is_net_alias_name_check(self, parent_net, child_net, alias_net, mod):
"""Utility function for checking single net alias."""
@ -188,8 +199,10 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
parent_net.lower() == alias_net.lower()
def get_mod_net(self, parent_net, child_inst, child_conns):
"""Given an instance and net, returns the internal net in the mod
corresponding to input net."""
"""
Given an instance and net, returns the internal net in the mod
corresponding to input net.
"""
for conn, pin in zip(child_conns, child_inst.mod.pins):
if parent_net.lower() == conn.lower():
return pin
@ -203,27 +216,27 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
converted_conns.append(port_dict[conn])
else:
converted_conns.append("{}.{}".format(inst_name, conn))
return converted_conns
return converted_conns
def add_graph_edges(self, graph, port_nets):
"""For every input, adds an edge to every output.
Only intended to be used for gates and other simple modules."""
#The final pin names will depend on the spice hierarchy, so
#they are passed as an input.
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)}
# The final pin names will depend on the spice hierarchy, so
# they are passed as an input.
pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
input_pins = self.get_inputs()
output_pins = self.get_outputs()
inout_pins = self.get_inouts()
for inp in input_pins+inout_pins:
for out in output_pins+inout_pins:
if inp != out: #do not add self loops
graph.add_edge(pin_dict[inp], pin_dict[out], self)
for inp in input_pins + inout_pins:
for out in output_pins + inout_pins:
if inp != out: # do not add self loops
graph.add_edge(pin_dict[inp], pin_dict[out], self)
def __str__(self):
""" override print function output """
pins = ",".join(self.pins)
insts = [" {}".format(x) for x in self.insts]
objs = [" {}".format(x) for x in self.objs]
objs = [" {}".format(x) for x in self.objs]
s = "********** design {0} **********".format(self.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))
@ -234,8 +247,8 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
""" override print function output """
text="( design: " + self.name + " pins=" + str(self.pins) + " " + str(self.width) + "x" + str(self.height) + " )\n"
for i in self.objs:
text+=str(i)+",\n"
text+=str(i) + ",\n"
for i in self.insts:
text+=str(i)+",\n"
text+=str(i) + ",\n"
return text

View File

@ -37,13 +37,19 @@ class hierarchical_decoder(design.design):
def find_decoder_height(self):
b = factory.create(module_type="bitcell")
cell_height = b.height
and3 = factory.create(module_type="pand3",
height=cell_height)
# Try to make a nand with a given height
# Default
return (b.height, 1)
cell_multiple = 1
while cell_multiple < 3:
cell_height = cell_multiple * b.height
and3 = factory.create(module_type="pand3",
height=cell_height)
(drc_errors, lvs_errors) = and3.DRC_LVS(force_check=True)
if drc_errors + lvs_errors == 0:
return (cell_height, cell_multiple)
cell_multiple += 1
else:
debug.error("Couldn't find a valid decoder height multiple.", -1)
def create_netlist(self):
self.add_modules()

View File

@ -121,7 +121,7 @@ class sram_base(design, verilog, lef):
start_time = datetime.datetime.now()
# We only enable final verification if we have routed the design
self.DRC_LVS(final_verification=OPTS.route_supplies, top_level=True)
self.DRC_LVS(final_verification=OPTS.route_supplies, roce_check=True)
if not OPTS.is_unit_test:
print_time("Verification", datetime.datetime.now(), start_time)