mirror of https://github.com/VLSIDA/OpenRAM.git
fix pin/net dictionary deepcopy-ing
This commit is contained in:
parent
09aa395174
commit
bfabe64f33
|
|
@ -292,19 +292,25 @@ class instance(geometry):
|
||||||
to both of their respective objects
|
to both of their respective objects
|
||||||
nets_list must be the same length as self.spice_pins
|
nets_list must be the same length as self.spice_pins
|
||||||
"""
|
"""
|
||||||
|
if len(nets_list) == 0 and len(self.spice_pins) == 0:
|
||||||
|
# this is the only valid case to skip the following debug check
|
||||||
|
# because this with no pins are often connected arbitrarily
|
||||||
|
self.connected = True
|
||||||
|
return
|
||||||
debug.check(not self.connected,
|
debug.check(not self.connected,
|
||||||
"instance {} has already been connected".format(self.name))
|
"instance {} has already been connected".format(self.name))
|
||||||
debug.check(len(self.spice_pins) == len(nets_list),
|
debug.check(len(self.spice_pins) == len(nets_list),
|
||||||
"must provide list of nets the same length as pin list\
|
"must provide list of nets the same length as pin list\
|
||||||
when connecting an instance")
|
when connecting an instance")
|
||||||
for i in range(len(self.spice_pins)):
|
for pin in self.spice_pins.values():
|
||||||
self.spice_pins[i].set_inst_net(nets_list[i])
|
net = nets_list.pop(0)
|
||||||
nets_list[i].connect_pin(self.spice_pins[i])
|
pin.set_inst_net(net)
|
||||||
|
net.connect_pin(pin)
|
||||||
self.connected = True
|
self.connected = True
|
||||||
|
|
||||||
def get_connections(self):
|
def get_connections(self):
|
||||||
conns = []
|
conns = []
|
||||||
for pin in self.spice_pins:
|
for pin in self.spice_pins.values():
|
||||||
conns.append(pin.inst_net.name)
|
conns.append(pin.inst_net.name)
|
||||||
return conns
|
return conns
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -629,7 +629,7 @@ class layout():
|
||||||
"""
|
"""
|
||||||
Return a pin list of all pins
|
Return a pin list of all pins
|
||||||
"""
|
"""
|
||||||
return self.pins
|
return list(self.pins)
|
||||||
|
|
||||||
def copy_layout_pin(self, instance, pin_name, new_name="", relative_offset=vector(0, 0)):
|
def copy_layout_pin(self, instance, pin_name, new_name="", relative_offset=vector(0, 0)):
|
||||||
"""
|
"""
|
||||||
|
|
@ -1523,6 +1523,7 @@ class layout():
|
||||||
""" Return the pin shapes as blockages for non-top-level blocks. """
|
""" Return the pin shapes as blockages for non-top-level blocks. """
|
||||||
# FIXME: We don't have a body contact in ptx, so just ignore it for now
|
# FIXME: We don't have a body contact in ptx, so just ignore it for now
|
||||||
import copy
|
import copy
|
||||||
|
# FIXME: this may not work now that self.pins is a dict as defined in hierarchy_spice
|
||||||
pin_names = copy.deepcopy(self.pins)
|
pin_names = copy.deepcopy(self.pins)
|
||||||
if self.name.startswith("pmos") or self.name.startswith("nmos"):
|
if self.name.startswith("pmos") or self.name.startswith("nmos"):
|
||||||
pin_names.remove("B")
|
pin_names.remove("B")
|
||||||
|
|
|
||||||
|
|
@ -90,13 +90,13 @@ class spice():
|
||||||
def add_pin(self, name, pin_type="INOUT"):
|
def add_pin(self, name, pin_type="INOUT"):
|
||||||
""" Adds a pin to the pins list. Default type is INOUT signal. """
|
""" Adds a pin to the pins list. Default type is INOUT signal. """
|
||||||
debug.check(name not in self.pins, "cannot add duplicate spice pin {}".format(name))
|
debug.check(name not in self.pins, "cannot add duplicate spice pin {}".format(name))
|
||||||
self.pins[name] = pin_spice(name, pin_type)
|
self.pins[name] = pin_spice(name, pin_type, self)
|
||||||
|
|
||||||
def add_pin_list(self, pin_list, pin_type="INOUT"):
|
def add_pin_list(self, pin_list, pin_type="INOUT"):
|
||||||
""" Adds a pin_list to the pins list """
|
""" Adds a pin_list to the pins list """
|
||||||
# The pin type list can be a single type for all pins
|
# The pin type list can be a single type for all pins
|
||||||
# or a list that is the same length as the pin list.
|
# or a list that is the same length as the pin list.
|
||||||
if type(pin_type) == str:
|
if isinstance(pin_type, str):
|
||||||
for pin in pin_list:
|
for pin in pin_list:
|
||||||
self.add_pin(pin, pin_type)
|
self.add_pin(pin, pin_type)
|
||||||
|
|
||||||
|
|
@ -124,7 +124,7 @@ class spice():
|
||||||
"{} spice subcircuit number of port types does not match number of pins\
|
"{} spice subcircuit number of port types does not match number of pins\
|
||||||
\n pin names={}\n port types={}".format(self.name, list(self.pins), type_list))
|
\n pin names={}\n port types={}".format(self.name, list(self.pins), type_list))
|
||||||
for pin, type in zip(self.pins.values(), type_list):
|
for pin, type in zip(self.pins.values(), type_list):
|
||||||
pin.set_pin_type(type)
|
pin.set_type(type)
|
||||||
|
|
||||||
def get_pin_type(self, name):
|
def get_pin_type(self, name):
|
||||||
""" Returns the type of the signal pin. """
|
""" Returns the type of the signal pin. """
|
||||||
|
|
@ -212,7 +212,7 @@ class spice():
|
||||||
for name in names_list:
|
for name in names_list:
|
||||||
# setdefault adds to the dict if it doesn't find the net in it already
|
# setdefault adds to the dict if it doesn't find the net in it already
|
||||||
# then it returns the net it found or created, a net_spice object
|
# then it returns the net it found or created, a net_spice object
|
||||||
net = self.nets.setdefault(name, net_spice(name))
|
net = self.nets.setdefault(name, net_spice(name, self))
|
||||||
nets.append(net)
|
nets.append(net)
|
||||||
return nets
|
return nets
|
||||||
|
|
||||||
|
|
@ -764,9 +764,10 @@ class pin_spice():
|
||||||
self.inst = inst
|
self.inst = inst
|
||||||
|
|
||||||
def set_inst_net(self, net):
|
def set_inst_net(self, net):
|
||||||
debug.check(self.inst_net is None,
|
if self.inst_net is not None:
|
||||||
"pin {} is already connected to net {} so it cannot also be connected to net {}\
|
debug.error("pin {} is already connected to net {}\
|
||||||
".format(self.name, self.inst_net.name, net.name))
|
so it cannot also be connected to net {}\
|
||||||
|
".format(self.name, self.inst_net.name, net.name), 1)
|
||||||
debug.check(isinstance(net, net_spice), "net must be a net_spice object")
|
debug.check(isinstance(net, net_spice), "net must be a net_spice object")
|
||||||
self.inst_net = net
|
self.inst_net = net
|
||||||
|
|
||||||
|
|
@ -789,6 +790,23 @@ class pin_spice():
|
||||||
"""
|
"""
|
||||||
return self._hash
|
return self._hash
|
||||||
|
|
||||||
|
def __deepcopy__(original, memo):
|
||||||
|
"""
|
||||||
|
This function is defined so that instances of modules can make deep
|
||||||
|
copies of their parent module's pins dictionary. It is only expected
|
||||||
|
to be called by the instance class __init__ function. Mod and mod_net
|
||||||
|
should not be deep copies but references to the existing mod and net
|
||||||
|
objects they refer to in the original. If inst is already defined this
|
||||||
|
function will throw an error because that means it was called on a pin
|
||||||
|
from an instance, which is not defined behavior.
|
||||||
|
"""
|
||||||
|
debug.check(original.inst is None,
|
||||||
|
"cannot make a deepcopy of a spice pin from an inst")
|
||||||
|
pin = pin_spice(original.name, original.type, original.mod)
|
||||||
|
if original.mod_net is not None:
|
||||||
|
pin.set_mod_net(original.mod_net)
|
||||||
|
return pin
|
||||||
|
|
||||||
|
|
||||||
class net_spice():
|
class net_spice():
|
||||||
"""
|
"""
|
||||||
|
|
@ -797,9 +815,10 @@ class net_spice():
|
||||||
inst is the instance this net is a part of, if any.
|
inst is the instance this net is a part of, if any.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, name):
|
def __init__(self, name, mod):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.pins = []
|
self.pins = []
|
||||||
|
self.mod = mod
|
||||||
self.inst = None
|
self.inst = None
|
||||||
|
|
||||||
# TODO: evaluate if this makes sense... and works
|
# TODO: evaluate if this makes sense... and works
|
||||||
|
|
@ -812,9 +831,12 @@ class net_spice():
|
||||||
else:
|
else:
|
||||||
self.pins.append(pin)
|
self.pins.append(pin)
|
||||||
|
|
||||||
|
def set_inst(self, inst):
|
||||||
|
self.inst = inst
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
""" override print function output """
|
""" override print function output """
|
||||||
return "(pin_name={} type={})".format(self.name, self.type)
|
return "(net_name={} type={})".format(self.name, self.type)
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
""" override repr function output """
|
""" override repr function output """
|
||||||
|
|
@ -830,3 +852,21 @@ class net_spice():
|
||||||
Provides a speedup if pin_spice is used as a key for dicts.
|
Provides a speedup if pin_spice is used as a key for dicts.
|
||||||
"""
|
"""
|
||||||
return self._hash
|
return self._hash
|
||||||
|
|
||||||
|
def __deepcopy__(original, memo):
|
||||||
|
"""
|
||||||
|
This function is defined so that instances of modules can make deep
|
||||||
|
copies of their parent module's nets dictionary. It is only expected
|
||||||
|
to be called by the instance class __init__ function. Mod and mod_net
|
||||||
|
should not be deep copies but references to the existing mod and net
|
||||||
|
objects they refer to in the original. If inst is already defined this
|
||||||
|
function will throw an error because that means it was called on a pin
|
||||||
|
from an instance, which is not defined behavior.
|
||||||
|
"""
|
||||||
|
debug.check(original.inst is None,
|
||||||
|
"cannot make a deepcopy of a spice net from an inst")
|
||||||
|
net = net_spice(original.name, original.mod)
|
||||||
|
if original.pins != []:
|
||||||
|
# TODO: honestly I'm not sure if this is right but we'll see...
|
||||||
|
net.pins = original.pins
|
||||||
|
return net
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue