get connections from spice objects in instances

This commit is contained in:
Sam Crow 2023-07-18 10:50:50 -07:00
parent 8a441bc68b
commit 478c76c1ca
3 changed files with 46 additions and 32 deletions

View File

@ -176,6 +176,8 @@ class instance(geometry):
self.rotate = rotate self.rotate = rotate
self.offset = vector(offset).snap_to_grid() self.offset = vector(offset).snap_to_grid()
self.mirror = mirror self.mirror = mirror
# track if the instance's spice pin connections have been made
self.connected = False
# deepcopy because this instance needs to # deepcopy because this instance needs to
# change attributes in these spice objects # change attributes in these spice objects
@ -290,12 +292,21 @@ 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
""" """
debug.check(not self.connected,
"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 i in range(len(self.spice_pins)):
self.spice_pins[i].set_inst_net(nets_list[i]) self.spice_pins[i].set_inst_net(nets_list[i])
nets_list[i].connect_pin(self.spice_pins[i]) nets_list[i].connect_pin(self.spice_pins[i])
self.connected = True
def get_connections(self):
conns = []
for pin in self.spice_pins:
conns.append(pin.inst_net.name)
return conns
def calculate_transform(self, node): def calculate_transform(self, node):
#set up the rotation matrix #set up the rotation matrix

View File

@ -139,7 +139,7 @@ class hierarchy_design(spice, layout):
1) 1)
port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} port_dict = {pin: port for pin, port in zip(list(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.get_instance_connections()):
if subinst in self.graph_inst_exclude: if subinst in self.graph_inst_exclude:
continue continue
subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name
@ -157,7 +157,7 @@ class hierarchy_design(spice, layout):
1) 1)
port_dict = {pin: port for pin, port in zip(list(self.pins), port_nets)} port_dict = {pin: port for pin, port in zip(list(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.get_instance_connections()):
subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + subinst.name subinst_name = inst_name + "{}x".format(OPTS.hier_seperator) + 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):

View File

@ -209,8 +209,6 @@ class spice():
ordered_nets = self.create_nets(ordered_args) ordered_nets = self.create_nets(ordered_args)
self.insts[-1].connect_spice_pins(ordered_nets) self.insts[-1].connect_spice_pins(ordered_nets)
# TODO: replace functionality that checked if user forgot to connect an inst before connecting the next
def create_nets(self, names_list): def create_nets(self, names_list):
nets = [] nets = []
for name in names_list: for name in names_list:
@ -294,8 +292,6 @@ class spice():
return False return False
def sp_write_file(self, sp, usedMODS, lvs=False, trim=False): def sp_write_file(self, sp, usedMODS, lvs=False, trim=False):
# FIXME: this function refers to conns for connections but that no longer exists.
# it should be possible to just query the instances themselves for their connections.
""" """
Recursive spice subcircuit write; Recursive spice subcircuit write;
Writes the spice subcircuit from the library or the dynamically generated one. Writes the spice subcircuit from the library or the dynamically generated one.
@ -308,11 +304,11 @@ class spice():
# If spice isn't defined, we dynamically generate one. # If spice isn't defined, we dynamically generate one.
# recursively write the modules # recursively write the modules
for i in self.mods: for mod in self.mods:
if self.contains(i, usedMODS): if self.contains(mod, usedMODS):
continue continue
usedMODS.append(i) usedMODS.append(mod)
i.sp_write_file(sp, usedMODS, lvs, trim) mod.sp_write_file(sp, usedMODS, lvs, trim)
if len(self.insts) == 0: if len(self.insts) == 0:
return return
@ -331,43 +327,44 @@ class spice():
for line in self.comments: for line in self.comments:
sp.write("* {}\n".format(line)) sp.write("* {}\n".format(line))
# every instance must have a set of connections, even if it is empty. # every instance must be connected with the connect_inst function
if len(self.insts) != len(self.conns): # TODO: may run into empty pin lists edge case, not sure yet
debug.error("{0} : Not all instance pins ({1}) are connected ({2}).".format(self.cell_name, connected = True
len(self.insts), for inst in self.insts:
len(self.conns))) if inst.connected:
debug.error("Instances: \n" + str(self.insts)) continue
debug.error("-----") debug.error("Instance {} spice pins not connected".format(str(inst)))
debug.error("Connections: \n" + str(self.conns), 1) connected = False
debug.check(connected, "{0} : Not all instance spice pins are connected.".format(self.cell_name))
for i in range(len(self.insts)): for inst in self.insts:
# we don't need to output connections of empty instances. # we don't need to output connections of empty instances.
# these are wires and paths # these are wires and paths
if self.conns[i] == []: if len(inst.spice_pins) == 0:
continue continue
# Instance with no devices in it needs no subckt/instance # Instance with no devices in it needs no subckt/instance
if self.insts[i].mod.no_instances: if inst.mod.no_instances:
continue continue
# If this is a trimmed netlist, skip it by adding comment char # If this is a trimmed netlist, skip it by adding comment char
if trim and self.insts[i].name in self.trim_insts: if trim and inst.name in self.trim_insts:
sp.write("* ") sp.write("* ")
if lvs and hasattr(self.insts[i].mod, "lvs_device"): if lvs and hasattr(inst.mod, "lvs_device"):
sp.write(self.insts[i].mod.lvs_device.format(self.insts[i].name, sp.write(inst.mod.lvs_device.format(inst.name,
" ".join(self.conns[i]))) " ".join(inst.get_connections())))
sp.write("\n") sp.write("\n")
elif hasattr(self.insts[i].mod, "spice_device"): elif hasattr(inst.mod, "spice_device"):
sp.write(self.insts[i].mod.spice_device.format(self.insts[i].name, sp.write(inst.mod.spice_device.format(inst.name,
" ".join(self.conns[i]))) " ".join(inst.get_connections())))
sp.write("\n") sp.write("\n")
else: else:
wrapped_connections = "\n+ ".join(tr.wrap(" ".join(self.conns[i]))) wrapped_connections = "\n+ ".join(tr.wrap(" ".join(inst.get_connections())))
sp.write("X{0}\n+ {1}\n+ {2}\n".format(self.insts[i].name, sp.write("X{0}\n+ {1}\n+ {2}\n".format(inst.name,
wrapped_connections, wrapped_connections,
self.insts[i].mod.cell_name)) inst.mod.cell_name))
sp.write(".ENDS {0}\n".format(self.cell_name)) sp.write(".ENDS {0}\n".format(self.cell_name))
@ -696,6 +693,12 @@ class spice():
aliases.append(net) aliases.append(net)
return aliases return aliases
def get_instance_connections(self):
conns = []
for inst in self.instances:
conns.append(inst.get_connections())
return conns
def is_net_alias(self, known_net, net_alias, mod, exclusion_set): 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). Checks if the alias_net in input mod is the same as the input net for this mod (self).
@ -708,7 +711,7 @@ class spice():
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.get_instance_connections()):
for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins): for inst_conn, mod_pin in zip(inst_conns, subinst.mod.pins):
if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod): if self.is_net_alias_name_check(known_net, inst_conn, net_alias, mod):
return True return True