mirror of https://github.com/VLSIDA/OpenRAM.git
PEP8 cleanup. DRC/LVS returns errors.
This commit is contained in:
parent
0d6c84036d
commit
5349323acd
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue