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) hierarchy_layout.layout.__init__(self, name)
self.init_graph_params() 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 """ """ Return a map of pin locations of the instance offset """
# find the instance # find the instance
for i in self.insts: for i in self.insts:
if i.name == inst.name: if i.name == inst.name:
break break
else: 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 inst_map = inst.mod.pin_map
return inst_map return inst_map
def DRC_LVS(self, final_verification=False, force_check=False):
def DRC_LVS(self, final_verification=False, top_level=False):
"""Checks both DRC and LVS for a module""" """Checks both DRC and LVS for a module"""
# Final verification option does not allow nets to be connected by label. # Final verification option does not allow nets to be connected by label.
# Unit tests will check themselves. # Unit tests will check themselves.
if OPTS.is_unit_test: if not force_check and OPTS.is_unit_test:
return ("skipped", "skipped") return ("skipped", "skipped")
if not OPTS.check_lvsdrc: if not force_check and not OPTS.check_lvsdrc:
return ("skipped", "skipped") return ("skipped", "skipped")
# Do not run if disabled in options. # 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) 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.sp_write(tempspice)
self.gds_write(tempgds) self.gds_write(tempgds)
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)
num_lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, 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_drc_errors == 0,
debug.check(num_lvs_errors == 0,"LVS failed for {0} with {1} errors(s)".format(self.name,num_lvs_errors)) "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(tempspice)
os.remove(tempgds) os.remove(tempgds)
@ -74,10 +77,12 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
# Do not run if disabled in options. # Do not run if disabled in options.
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)):
tempgds = "{0}/{1}.gds".format(OPTS.openram_temp,self.name) tempgds = "{0}/{1}.gds".format(OPTS.openram_temp, self.name)
self.gds_write(tempgds) self.gds_write(tempgds)
num_errors = verify.run_drc(self.name, tempgds, final_verification=final_verification) 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)) debug.check(num_errors == 0,
"DRC failed for {0} with {1} error(s)".format(self.name,
num_errors))
os.remove(tempgds) os.remove(tempgds)
@ -91,12 +96,14 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
# Do not run if disabled in options. # Do not run if disabled in options.
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.sp_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,"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(tempspice)
os.remove(tempgds) os.remove(tempgds)
@ -106,38 +113,42 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
def init_graph_params(self): def init_graph_params(self):
"""Initializes parameters relevant to the graph creation""" """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() 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.""" """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): if len(port_nets) != len(self.pins):
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,
port_dict = {pin:port for pin,port in zip(self.pins, 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)) debug.info(3, "Instance name={}".format(inst_name))
for subinst, conns in zip(self.insts, self.conns): for subinst, conns in zip(self.insts, self.conns):
if subinst in self.graph_inst_exclude: if subinst in self.graph_inst_exclude:
continue 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_ports = self.translate_nets(conns, port_dict, inst_name)
subinst.mod.build_graph(graph, subinst_name, subinst_ports) subinst.mod.build_graph(graph, subinst_name, subinst_ports)
def build_names(self, name_dict, inst_name, port_nets): def build_names(self, name_dict, inst_name, port_nets):
"""Collects all the nets and the parent inst of that net.""" """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): if len(port_nets) != len(self.pins):
debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,self.pins),1) debug.error("Port length mismatch:\nExt nets={}, Ports={}".format(port_nets,
port_dict = {pin:port for pin,port in zip(self.pins, 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)) debug.info(3, "Instance name={}".format(inst_name))
for subinst, conns in zip(self.insts, self.conns): 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) subinst_ports = self.translate_nets(conns, port_dict, inst_name)
for si_port, conn in zip(subinst_ports, conns): 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: 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 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)
@ -165,11 +176,11 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""Checks if the alias_net in input mod is the same as the input net for this mod (self).""" """Checks if the alias_net in input mod is the same as the input net for this mod (self)."""
if self in exclusion_set: if self in exclusion_set:
return False return False
#Check ports of this mod # Check ports of this mod
for pin in self.pins: for pin in self.pins:
if self.is_net_alias_name_check(known_net, pin, net_alias, mod): if self.is_net_alias_name_check(known_net, pin, net_alias, mod):
return True return True
#Check connections of all other subinsts # Check connections of all other subinsts
mod_set = set() mod_set = set()
for subinst, inst_conns in zip(self.insts, self.conns): for subinst, inst_conns in zip(self.insts, self.conns):
for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins): for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins):
@ -188,8 +199,10 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
parent_net.lower() == alias_net.lower() parent_net.lower() == alias_net.lower()
def get_mod_net(self, parent_net, child_inst, child_conns): 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): for conn, pin in zip(child_conns, child_inst.mod.pins):
if parent_net.lower() == conn.lower(): if parent_net.lower() == conn.lower():
return pin return pin
@ -208,15 +221,15 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
def add_graph_edges(self, graph, port_nets): def add_graph_edges(self, graph, port_nets):
"""For every input, adds an edge to every output. """For every input, adds an edge to every output.
Only intended to be used for gates and other simple modules.""" Only intended to be used for gates and other simple modules."""
#The final pin names will depend on the spice hierarchy, so # The final pin names will depend on the spice hierarchy, so
#they are passed as an input. # they are passed as an input.
pin_dict = {pin:port for pin,port in zip(self.pins, port_nets)} pin_dict = {pin: port for pin, port in zip(self.pins, port_nets)}
input_pins = self.get_inputs() input_pins = self.get_inputs()
output_pins = self.get_outputs() output_pins = self.get_outputs()
inout_pins = self.get_inouts() inout_pins = self.get_inouts()
for inp in input_pins+inout_pins: for inp in input_pins + inout_pins:
for out in output_pins+inout_pins: for out in output_pins + inout_pins:
if inp != out: #do not add self loops if inp != out: # do not add self loops
graph.add_edge(pin_dict[inp], pin_dict[out], self) graph.add_edge(pin_dict[inp], pin_dict[out], self)
def __str__(self): def __str__(self):
@ -234,8 +247,8 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
""" override print function output """ """ override print function output """
text="( design: " + self.name + " pins=" + str(self.pins) + " " + str(self.width) + "x" + str(self.height) + " )\n" text="( design: " + self.name + " pins=" + str(self.pins) + " " + str(self.width) + "x" + str(self.height) + " )\n"
for i in self.objs: for i in self.objs:
text+=str(i)+",\n" text+=str(i) + ",\n"
for i in self.insts: for i in self.insts:
text+=str(i)+",\n" text+=str(i) + ",\n"
return text return text

View File

@ -37,14 +37,20 @@ class hierarchical_decoder(design.design):
def find_decoder_height(self): def find_decoder_height(self):
b = factory.create(module_type="bitcell") 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) 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): def create_netlist(self):
self.add_modules() self.add_modules()
self.setup_netlist_constants() self.setup_netlist_constants()

View File

@ -121,7 +121,7 @@ class sram_base(design, verilog, lef):
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
# We only enable final verification if we have routed the design # 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: if not OPTS.is_unit_test:
print_time("Verification", datetime.datetime.now(), start_time) print_time("Verification", datetime.datetime.now(), start_time)