from typing import List, Dict, Any, Tuple, Union
[docs]
def general_routing_load_generate(spice_filename: str, tile_sb_on: List[int], tile_sb_partial: List[int], tile_sb_off: List[int], tile_cb_on: List[int], tile_cb_partial: List[int], tile_cb_off: List[int], gen_r_wire: Dict[str, Any], sb_mux: Any) -> List[str]:
""" Generates a routing wire load SPICE deck """
# Open SPICE file for appending
spice_file = open(spice_filename, 'a')
###############################################################
## ROUTING WIRE LOAD
###############################################################
# Get gen routing wire information
wire_length = gen_r_wire["len"]
wire_id = gen_r_wire["id"]
# param string suffixes
p_str_suffix = f"_wire_uid{wire_id}"
routing_wire_load_pstr = f"wire_gen_routing{p_str_suffix}"
wire_sb_load_on_pstr = f"wire_sb_load_on{p_str_suffix}"
wire_sb_load_partial_pstr = f"wire_sb_load_partial{p_str_suffix}"
wire_sb_load_off_pstr = f"wire_sb_load_off{p_str_suffix}"
# for ease defining subckt names here
sb_mux_on_str = f"{sb_mux.name}_on"
sb_mux_partial_str = f"{sb_mux.name}_partial"
sb_mux_off_str = f"{sb_mux.name}_off"
# Not using a seperate cb mux for each wire type
wire_cb_load_on_pstr = f"wire_cb_load_on{p_str_suffix}"
wire_cb_load_partial_pstr = f"wire_cb_load_partial{p_str_suffix}"
wire_cb_load_off_pstr = f"wire_cb_load_off{p_str_suffix}"
subckt_cb_mux_on_str = f"cb_mux_on"
subckt_cb_mux_partial_str = f"cb_mux_partial"
subckt_cb_mux_off_str = f"cb_mux_off"
# wire load sbckt name
routing_wire_load_subckt_str = f"routing_wire_load{p_str_suffix}"
# First we write the individual tile loads
# Tiles are generated such that if you drive a wire from the left you get
# driver -> tile 4 -> tile 3 -> tile 2 -> tile 1 (driver) -> tile 4 -> etc.
for i in range(wire_length):
spice_file.write("******************************************************************************************\n")
spice_file.write("* Routing wire load tile " + str(i+1) + "\n")
spice_file.write("******************************************************************************************\n")
# If this is Tile 1, we need to add a nodes to which we can connect the ON sb_mux and cb_mux so that we can measure power.
if i == 0:
spice_file.write(f".SUBCKT routing_wire_load_tile_{i+1}{p_str_suffix} n_in n_out n_cb_out n_gate n_gate_n n_vdd n_gnd n_vdd_sb_mux_on n_vdd_cb_mux_on\n")
else:
spice_file.write(f".SUBCKT routing_wire_load_tile_{i+1}{p_str_suffix} n_in n_out n_cb_out n_gate n_gate_n n_vdd n_gnd\n")
spice_file.write(f"Xwire_gen_routing_1 n_in n_1_1 wire Rw='{routing_wire_load_pstr}_res/" + str(2*wire_length) + f"' Cw='{routing_wire_load_pstr}_cap/" + str(2*wire_length) + "'\n\n")
# SWITCH BLOCK LOAD
# Write the ON switch block loads
for sb_on in range(tile_sb_on[i]):
# Tile 1 is terminated by a on SB, if this is tile 1 and sb_on 1, we ignore it because we put that one at the end.
if i == 0:
if sb_on != 0:
spice_file.write("Xwire_sb_load_on_" + str(sb_on+1) + " n_1_1 n_1_sb_on_" + str(sb_on+1) + f" wire Rw={wire_sb_load_on_pstr}_res Cw={wire_sb_load_on_pstr}_cap\n")
spice_file.write("Xsb_load_on_" + str(sb_on+1) + " n_1_sb_on_" + str(sb_on+1) + " n_sb_mux_on_" + str(sb_on+1) + f"_hang n_gate n_gate_n n_vdd n_gnd {sb_mux_on_str}\n\n")
else:
spice_file.write("Xwire_sb_load_on_" + str(sb_on+1) + " n_1_1 n_1_sb_on_" + str(sb_on+1) + f" wire Rw={wire_sb_load_on_pstr}_res Cw={wire_sb_load_on_pstr}_cap\n")
spice_file.write("Xsb_load_on_" + str(sb_on+1) + " n_1_sb_on_" + str(sb_on+1) + " n_sb_mux_on_" + str(sb_on+1) + f"_hang n_gate n_gate_n n_vdd n_gnd {sb_mux_on_str}\n\n")
# Write partially on switch block loads
for sb_partial in range(tile_sb_partial[i]):
spice_file.write("Xwire_sb_load_partial_" + str(sb_partial+1) + " n_1_1 n_1_sb_partial_" + str(sb_partial+1) + f" wire Rw={wire_sb_load_partial_pstr}_res Cw={wire_sb_load_partial_pstr}_cap\n")
spice_file.write("Xsb_load_partial_" + str(sb_partial+1) + " n_1_sb_partial_" + str(sb_partial+1) + f" n_gate n_gate_n n_vdd n_gnd {sb_mux_partial_str}\n\n")
# Write off switch block loads
for sb_off in range(tile_sb_off[i]):
spice_file.write("Xwire_sb_load_off_" + str(sb_off+1) + " n_1_1 n_1_sb_off_" + str(sb_off+1) + f" wire Rw={wire_sb_load_off_pstr}_res Cw={wire_sb_load_off_pstr}_cap\n")
spice_file.write("Xsb_load_off_" + str(sb_off+1) + " n_1_sb_off_" + str(sb_off+1) + f" n_gate n_gate_n n_vdd n_gnd {sb_mux_off_str}\n\n")
# CONNECTION BLOCK LOAD
# Write the ON connection block load
for cb_on in range(tile_cb_on[i]):
# If this is tile 1, we need to connect the connection block to the n_cb_out net
if i == 0:
# We only connect one of them, so the first one in this case.
# This cb_mux is connected to a different power rail so that we can measure power.
if cb_on == 0:
spice_file.write("Xwire_cb_load_on_" + str(cb_on+1) + " n_1_1 n_1_cb_on_" + str(cb_on+1) + f" wire Rw={wire_cb_load_on_pstr}_res Cw={wire_cb_load_on_pstr}_cap\n")
spice_file.write("Xcb_load_on_" + str(cb_on+1) + " n_1_cb_on_" + str(cb_on+1) + f" n_cb_out n_gate n_gate_n n_vdd_cb_mux_on n_gnd {subckt_cb_mux_on_str}\n\n")
else:
spice_file.write("Xwire_cb_load_on_" + str(cb_on+1) + " n_1_1 n_1_cb_on_" + str(cb_on+1) + f" wire Rw={wire_cb_load_on_pstr}_res Cw={wire_cb_load_on_pstr}_cap\n")
spice_file.write("Xcb_load_on_" + str(cb_on+1) + " n_1_cb_on_" + str(cb_on+1) + " n_cb_mux_on_" + str(cb_on+1) + f"_hang n_gate n_gate_n n_vdd n_gnd {subckt_cb_mux_on_str}\n\n")
# Write partially on connection block loads
for cb_partial in range(tile_cb_partial[i]):
spice_file.write("Xwire_cb_load_partial_" + str(cb_partial+1) + " n_1_1 n_1_cb_partial_" + str(cb_partial+1) + f" wire Rw={wire_cb_load_partial_pstr}_res Cw={wire_cb_load_partial_pstr}_cap\n")
spice_file.write("Xcb_load_partial_" + str(cb_partial+1) + " n_1_cb_partial_" + str(cb_partial+1) + f" n_gate n_gate_n n_vdd n_gnd {subckt_cb_mux_partial_str}\n\n")
# Write off connection block loads
for cb_off in range(tile_cb_off[i]):
spice_file.write("Xwire_cb_load_off_" + str(cb_off+1) + " n_1_1 n_1_cb_off_" + str(cb_off+1) + f" wire Rw={wire_cb_load_off_pstr}_res Cw={wire_cb_load_off_pstr}_cap\n")
spice_file.write("Xcb_load_off_" + str(cb_off+1) + " n_1_cb_off_" + str(cb_off+1) + f" n_gate n_gate_n n_vdd n_gnd {subckt_cb_mux_off_str}\n\n")
# Tile 1 is terminated by a on switch block, other tiles just connect the wire to the output
# Tile 1's sb_mux is connected to a different power rail so that we can measure dynamic power.
if i == 0:
spice_file.write(f"Xwire_gen_routing_2 n_1_1 n_1_2 wire Rw='{routing_wire_load_pstr}_res/" + str(2*wire_length) + f"' Cw='{routing_wire_load_pstr}_cap/" + str(2*wire_length) + "'\n")
spice_file.write(f"Xsb_mux_on_out n_1_2 n_out n_gate n_gate_n n_vdd_sb_mux_on n_gnd {sb_mux_on_str}\n")
else:
spice_file.write(f"Xwire_gen_routing_2 n_1_1 n_out wire Rw='{routing_wire_load_pstr}_res/" + str(2*wire_length) + f"' Cw='{routing_wire_load_pstr}_cap/" + str(2*wire_length) + "'\n")
spice_file.write(".ENDS\n\n\n")
# Now write a subcircuit for the complete routing wire
spice_file.write("******************************************************************************************\n")
spice_file.write("* Routing wire load tile " + str(i+1) + "\n")
spice_file.write("******************************************************************************************\n")
# spice_file.write(".SUBCKT routing_wire_load n_in n_out n_cb_out n_gate n_gate_n n_vdd n_gnd n_vdd_sb_mux_on n_vdd_cb_mux_on\n")
spice_file.write(f".SUBCKT {routing_wire_load_subckt_str} n_in n_out n_cb_out n_gate n_gate_n n_vdd n_gnd n_vdd_sb_mux_on n_vdd_cb_mux_on\n")
# Iterate through tiles backwards
in_node = "n_in"
for tile in range(wire_length,1,-1):
out_node = "n_" + str(tile)
spice_file.write("Xrouting_wire_load_tile_" + str(tile) + " " + in_node + " " + out_node + " n_hang_" + str(tile) + f" n_gate n_gate_n n_vdd n_gnd routing_wire_load_tile_{tile}{p_str_suffix}\n")
in_node = out_node
# Write tile 1
spice_file.write("Xrouting_wire_load_tile_1 " + in_node + f" n_out n_cb_out n_gate n_gate_n n_vdd n_gnd n_vdd_sb_mux_on n_vdd_cb_mux_on routing_wire_load_tile_1{p_str_suffix}\n")
spice_file.write(".ENDS\n\n\n")
spice_file.close()
# Create a list of all wires used in this subcircuit
wire_names_list = []
wire_names_list.append(routing_wire_load_pstr)
wire_names_list.append(wire_sb_load_on_pstr)
wire_names_list.append(wire_sb_load_partial_pstr)
wire_names_list.append(wire_sb_load_off_pstr)
wire_names_list.append(wire_cb_load_on_pstr)
wire_names_list.append(wire_cb_load_partial_pstr)
wire_names_list.append(wire_cb_load_off_pstr)
return wire_names_list
[docs]
def local_routing_load_generate(spice_filename, num_on, num_partial, num_off):
""" """
# The first thing we want to figure out is the interval between each on load and each partially on load
# Number of partially on muxes between each on mux
interval_partial = int(num_partial/num_on)
# Number of off muxes between each partially on mux
interval_off = int(num_off/num_partial)
# Open SPICE file for appending
spice_file = open(spice_filename, 'a')
spice_file.write("******************************************************************************************\n")
spice_file.write("* Local routing wire load\n")
spice_file.write("******************************************************************************************\n")
spice_file.write(".SUBCKT local_routing_wire_load n_in n_out n_gate n_gate_n n_vdd n_gnd n_vdd_local_mux_on\n")
num_total = int(num_on + num_partial + num_off)
interval_counter_partial = 0
interval_counter_off = 0
on_counter = 0
partial_counter = 0
off_counter = 0
# Initialize nodes
current_node = "n_in"
next_node = "n_1"
# Write SPICE file while keeping correct intervals between partial and on muxes
for i in range(num_total):
if interval_counter_partial == interval_partial and on_counter < num_on:
# Add an on mux
interval_counter_partial = 0
on_counter = on_counter + 1
if on_counter == num_on:
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_local_routing_res/" + str(num_total) + "' Cw='wire_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_on_" + str(on_counter) + " " + next_node + " n_out n_gate n_gate_n n_vdd_local_mux_on n_gnd local_mux_on\n")
else:
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_local_routing_res/" + str(num_total) + "' Cw='wire_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_on_" + str(on_counter) + " " + next_node + " n_hang_" + str(on_counter) + " n_gate n_gate_n n_vdd n_gnd local_mux_on\n")
else:
if interval_counter_off == interval_off and partial_counter < num_partial:
# Add a partially on mux
interval_counter_off = 0
interval_counter_partial = interval_counter_partial + 1
partial_counter = partial_counter + 1
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_local_routing_res/" + str(num_total) + "' Cw='wire_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_partial_" + str(partial_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd local_mux_partial\n")
else:
# Add an off mux
interval_counter_off = interval_counter_off + 1
off_counter = off_counter + 1
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_local_routing_res/" + str(num_total) + "' Cw='wire_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_off_" + str(off_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd local_mux_off\n")
# Update current and next nodes
current_node = next_node
next_node = "n_" + str(i+2)
spice_file.write(".ENDS\n\n\n")
spice_file.close()
# Create a list of all wires used in this subcircuit
wire_names_list = []
wire_names_list.append("wire_local_routing")
return wire_names_list
[docs]
def hb_local_routing_load_generate(spice_filename, num_on, num_partial, num_off, hb_name, mux_name):
""" """
# The first thing we want to figure out is the interval between each on load and each partially on load
# Number of partially on muxes between each on mux
interval_partial = int(num_partial/num_on)
# Number of off muxes between each partially on mux
interval_off = int(num_off/num_partial)
# Open SPICE file for appending
spice_file = open(spice_filename, 'a')
spice_file.write("******************************************************************************************\n")
spice_file.write("* Local routing wire load\n")
spice_file.write("******************************************************************************************\n")
spice_file.write(".SUBCKT "+hb_name+" n_in n_out n_gate n_gate_n n_vdd n_gnd n_vdd_local_mux_on\n")
num_total = num_on + num_partial + num_off
interval_counter_partial = 0
interval_counter_off = 0
on_counter = 0
partial_counter = 0
off_counter = 0
# Initialize nodes
current_node = "n_in"
next_node = "n_1"
# Write SPICE file while keeping correct intervals between partial and on muxes
for i in range(num_total):
if interval_counter_partial == interval_partial and on_counter < num_on:
# Add an on mux
interval_counter_partial = 0
on_counter = on_counter + 1
if on_counter == num_on:
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_"+hb_name+"_res/" + str(num_total) + "' Cw='wire_"+hb_name+"_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_on_" + str(on_counter) + " " + next_node + " n_out n_gate n_gate_n n_vdd_local_mux_on n_gnd "+mux_name+"_on\n")
else:
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_"+hb_name+"_res/" + str(num_total) + "' Cw='wire_"+hb_name+"_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_on_" + str(on_counter) + " " + next_node + " n_hang_" + str(on_counter) + " n_gate n_gate_n n_vdd n_gnd "+mux_name+"_on\n")
else:
if interval_counter_off == interval_off and partial_counter < num_partial:
# Add a partially on mux
interval_counter_off = 0
interval_counter_partial = interval_counter_partial + 1
partial_counter = partial_counter + 1
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_"+hb_name+"_res/" + str(num_total) + "' Cw='wire_"+hb_name+"_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_partial_" + str(partial_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd "+mux_name+"_partial\n")
else:
# Add an off mux
interval_counter_off = interval_counter_off + 1
off_counter = off_counter + 1
spice_file.write("Xwire_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_"+hb_name+"_res/" + str(num_total) + "' Cw='wire_"+hb_name+"_cap/" + str(num_total) + "'\n")
spice_file.write("Xlocal_mux_off_" + str(off_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd "+mux_name+"_off\n")
# Update current and next nodes
current_node = next_node
next_node = "n_" + str(i+2)
spice_file.write(".ENDS\n\n\n")
spice_file.close()
# Create a list of all wires used in this subcircuit
wire_names_list = []
wire_names_list.append("wire_"+hb_name+"local_routing")
return wire_names_list
[docs]
def RAM_local_routing_load_generate(spice_filename, num_on, num_partial, num_off):
""" """
# The first thing we want to figure out is the interval between each on load and each partially on load
# Number of partially on muxes between each on mux
interval_partial = int(num_partial/num_on)
# Number of off muxes between each partially on mux
interval_off = int(num_off/num_partial)
# Open SPICE file for appending
spice_file = open(spice_filename, 'a')
spice_file.write("******************************************************************************************\n")
spice_file.write("* RAM local routing wire load\n")
spice_file.write("******************************************************************************************\n")
spice_file.write(".SUBCKT RAM_local_routing_wire_load n_in n_out n_gate n_gate_n n_vdd n_gnd n_vdd_RAM_local_mux_on\n")
num_total = num_on + num_partial + num_off
interval_counter_partial = 0
interval_counter_off = 0
on_counter = 0
partial_counter = 0
off_counter = 0
# Initialize nodes
current_node = "n_in"
next_node = "n_1"
# Write SPICE file while keeping correct intervals between partial and on muxes
for i in range(num_total):
if interval_counter_partial == interval_partial and on_counter < num_on:
# Add an on mux
interval_counter_partial = 0
on_counter = on_counter + 1
if on_counter == num_on:
spice_file.write("Xwire_RAM_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_RAM_local_routing_res/" + str(num_total) + "' Cw='wire_RAM_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("XRAM_local_mux_on_" + str(on_counter) + " " + next_node + " n_out n_gate n_gate_n n_vdd_RAM_local_mux_on n_gnd RAM_local_mux_on\n")
else:
spice_file.write("Xwire_RAM_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_RAM_local_routing_res/" + str(num_total) + "' Cw='wire_RAM_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("XRAM_local_mux_on_" + str(on_counter) + " " + next_node + " n_hang_" + str(on_counter) + " n_gate n_gate_n n_vdd n_gnd RAM_local_mux_on\n")
else:
if interval_counter_off == interval_off and partial_counter < num_partial:
# Add a partially on mux
interval_counter_off = 0
interval_counter_partial = interval_counter_partial + 1
partial_counter = partial_counter + 1
spice_file.write("Xwire_RAM_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_RAM_local_routing_res/" + str(num_total) + "' Cw='wire_RAM_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("XRAM_local_mux_partial_" + str(partial_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd RAM_local_mux_partial\n")
else:
# Add an off mux
interval_counter_off = interval_counter_off + 1
off_counter = off_counter + 1
spice_file.write("Xwire_RAM_local_routing_" + str(i+1) + " " + current_node + " " + next_node + " wire Rw='wire_RAM_local_routing_res/" + str(num_total) + "' Cw='wire_RAM_local_routing_cap/" + str(num_total) + "'\n")
spice_file.write("XRAM_local_mux_off_" + str(off_counter) + " " + next_node + " n_gate n_gate_n n_vdd n_gnd RAM_local_mux_off\n")
# Update current and next nodes
current_node = next_node
next_node = "n_" + str(i+2)
spice_file.write(".ENDS\n\n\n")
spice_file.close()
# Create a list of all wires used in this subcircuit
wire_names_list = []
wire_names_list.append("wire_RAM_local_routing")
return wire_names_list
# def generate_ble_outputs(spice_filename, num_local_out, num_gen_out, gen_r_wire: dict):
# """ Create the BLE outputs block. Contains 'num_local_out' local outputs and 'num_gen_out' general outputs. """
# #TODO: The order of the wires is weird in this netlist, have a look at it later.
# # Total number of BLE outputs
# total_outputs = num_local_out + num_gen_out
# subckt_local_ble_output_name = f"local_ble_output_wire_uid{gen_r_wire['id']}"
# subckt_general_ble_output_name = f"general_ble_output_wire_uid{gen_r_wire['id']}"
# wire_gen_ble_outputs = f"wire_ble_outputs_wire_uid{gen_r_wire['id']}"
# # Open SPICE file for appending
# spice_file = open(spice_filename, 'a')
# spice_file.write("******************************************************************************************\n")
# spice_file.write("* BLE outputs\n")
# spice_file.write("******************************************************************************************\n")
# spice_file.write(".SUBCKT ble_outputs n_1_" + str(int((total_outputs + 1)/2)+1) + " n_local_out n_general_out n_gate n_gate_n n_vdd n_gnd n_vdd_local_output_on n_vdd_general_output_on\n")
# # Create the BLE output bar
# current_node = 2
# for i in range(num_local_out):
# #if it is the first 2:1 local ble feedback mux then attach the n_local_out signal to its output else assign a random signal to it
# if i == 0:
# spice_file.write("Xlocal_ble_output_" + str(i+1) + " n_1_" + str(current_node) + f" n_local_out n_gate n_gate_n n_vdd_local_output_on n_gnd {subckt_local_ble_output_name}\n")
# else:
# spice_file.write("Xlocal_ble_output_" + str(i+1) + " n_1_" + str(current_node) + " n_hang_" + str(current_node) + f" n_gate n_gate_n n_vdd n_gnd {subckt_local_ble_output_name}\n")
# spice_file.write("Xwire_ble_outputs_" + str(i+1) + " n_1_" + str(current_node) + " n_1_" + str(current_node + 1) + " wire Rw='wire_ble_outputs_res/" + str(total_outputs-1) + "' Cw='wire_ble_outputs_cap/" + str(total_outputs-1) + "'\n")
# current_node = current_node + 1
# for i in range(num_gen_out):
# #if it is the first 2:1 general ble output mux then attach the n_general_out signal to its output else assign a random signal to it
# if i == 0:
# spice_file.write("Xgeneral_ble_output_" + str(i+1) + " n_1_" + str(current_node) + f" n_general_out n_gate n_gate_n n_vdd_general_output_on n_gnd {subckt_general_ble_output_name}\n")
# else:
# spice_file.write("Xgeneral_ble_output_" + str(i+1) + " n_1_" + str(current_node) + f" n_hang_" + str(current_node) + f" n_gate n_gate_n n_vdd n_gnd {subckt_general_ble_output_name}\n")
# # Only add wire if this is not the last ble output.
# if (i+1) != num_gen_out:
# spice_file.write("Xwire_ble_outputs_" + str(num_local_out+i+1) + " n_1_" + str(current_node) + " n_1_" + str(current_node + 1) + " wire Rw='wire_ble_outputs_res/" + str(total_outputs-1) + "' Cw='wire_ble_outputs_cap/" + str(total_outputs-1) + "'\n")
# current_node = current_node + 1
# spice_file.write(".ENDS\n\n\n")
# spice_file.close()
# # Create a list of all wires used in this subcircuit
# wire_names_list = []
# wire_names_list.append(wire_gen_ble_outputs)
# return wire_names_list
# def generate_lut_output_load(spice_filename, num_local_out, num_gen_out):
# """ Create the LUT output load subcircuit. It consists of a FF which
# has the register select mux at its input and all BLE outputs which
# include the output routing mux (Or) and the output feedback mux (Ofb) """
# # Total number of BLE outputs
# total_outputs = num_local_out + num_gen_out
# # Open SPICE file for appending
# spice_file = open(spice_filename, 'a')
# spice_file.write("******************************************************************************************\n")
# spice_file.write("* LUT output load\n")
# spice_file.write("******************************************************************************************\n")
# spice_file.write(".SUBCKT lut_output_load n_in n_local_out n_general_out n_gate n_gate_n n_vdd n_gnd n_vdd_local_output_on n_vdd_general_output_on\n")
# spice_file.write("Xwire_lut_output_load_1 n_in n_1_1 wire Rw='wire_lut_output_load_1_res' Cw='wire_lut_output_load_1_cap'\n")
# spice_file.write("Xff n_1_1 n_hang1 n_gate n_gate_n n_vdd n_gnd n_gnd n_vdd n_gnd n_vdd n_vdd n_gnd ff\n")
# spice_file.write("Xwire_lut_output_load_2 n_1_1 n_1_2 wire Rw='wire_lut_output_load_2_res' Cw='wire_lut_output_load_2_cap'\n")
# spice_file.write("Xble_outputs n_1_2 n_local_out n_general_out n_gate n_gate_n n_vdd n_gnd n_vdd_local_output_on n_vdd_general_output_on ble_outputs\n")
# spice_file.write(".ENDS\n\n\n")
# spice_file.close()
# # Create a list of all wires used in this subcircuit
# wire_names_list = []
# wire_names_list.append("wire_lut_output_load_1")
# wire_names_list.append("wire_lut_output_load_2")
# return wire_names_list
# def generate_local_ble_output_load(spice_filename):
# # Open SPICE file for appending
# spice_file = open(spice_filename, 'a')
# spice_file.write("******************************************************************************************\n")
# spice_file.write("* Local BLE output load\n")
# spice_file.write("******************************************************************************************\n")
# spice_file.write(".SUBCKT local_ble_output_load n_in n_gate n_gate_n n_vdd n_gnd\n")
# spice_file.write("Xwire_local_ble_output_feedback n_in n_1_1 wire Rw='wire_local_ble_output_feedback_res' Cw='wire_local_ble_output_feedback_cap'\n")
# spice_file.write("Xlocal_routing_wire_load_1 n_1_1 n_1_2 n_gate n_gate_n n_vdd n_gnd n_vdd local_routing_wire_load\n")
# spice_file.write("Xlut_a_driver_1 n_1_2 n_hang1 vsram vsram_n n_hang2 n_hang3 n_vdd n_gnd lut_a_driver\n\n")
# spice_file.write(".ENDS\n\n\n")
# spice_file.close()
# # Create a list of all wires used in this subcircuit
# wire_names_list = []
# wire_names_list.append("wire_local_ble_output_feedback")
# return wire_names_list
# def generate_general_ble_output_load(spice_filename: str, num_sb_mux_off: int, num_sb_mux_partial: int, num_sb_mux_on: int, gen_r_wire: dict):
# """ Create the cluster output load SPICE deck. We assume 2-level muxes. The load is distributed as
# off, then partial, then on.
# Inputs are SPICE file, number of SB muxes that are off, then partially on, then on.
# Returns wire names used in this SPICE circuit."""
# # Get gen routing wire information
# wire_length = gen_r_wire["len"]
# wire_id = gen_r_wire["id"]
# # for ease defining subckt names here
# p_str = f"_L{wire_length}_uid{wire_id}"
# sb_mux_name = f"sb_mux{p_str}"
# sb_mux_on_str = f"{sb_mux_name}_on"
# sb_mux_partial_str = f"{sb_mux_name}_partial"
# sb_mux_off_str = f"{sb_mux_name}_off"
# # Total number of sb muxes connected to this logic cluster output
# sb_mux_total = num_sb_mux_off + num_sb_mux_partial + num_sb_mux_on
# # Open SPICE file for appending
# spice_file = open(spice_filename, 'a')
# # Define the parameters for wire RCs, these will be returned from this function
# # Commenting out while testing to see if the multi sb mux itself is working, dont want to have to change LUT stuff
# wire_general_ble_output_pstr = f"wire_general_ble_output_L{wire_length}_uid{wire_id}"
# #wire_general_ble_output_pstr = f"wire_general_ble_output"
# spice_file.write("******************************************************************************************\n")
# spice_file.write("* General BLE output load\n")
# spice_file.write("******************************************************************************************\n")
# # For multi wire change to --> general_ble_output_load_L{gen_routing_wire_length}
# spice_file.write(f".SUBCKT general_ble_output_load_L{wire_length}_uid{wire_id} n_1_1 n_out n_gate n_gate_n n_vdd n_gnd\n")
# current_node = "n_1_1"
# next_node = "n_1_2"
# for i in range(num_sb_mux_off):
# spice_file.write("Xwire_general_ble_output_" + str(i+1) + " " + current_node + " " + next_node + f" wire Rw='{wire_general_ble_output_pstr}_res/" + str(sb_mux_total) + f"' Cw='{wire_general_ble_output_pstr}_cap/" + str(sb_mux_total) + "'\n")
# spice_file.write("Xsb_mux_off_" + str(i+1) + " " + next_node + f" n_gate n_gate_n n_vdd n_gnd {sb_mux_off_str}\n")
# current_node = next_node
# next_node = "n_1_" + str(i+3)
# for i in range(num_sb_mux_partial):
# spice_file.write("Xwire_general_ble_output_" + str(i+num_sb_mux_off+1) + " " + current_node + " " + next_node + f" wire Rw='{wire_general_ble_output_pstr}_res/" + str(sb_mux_total) + f"' Cw='{wire_general_ble_output_pstr}_cap/" + str(sb_mux_total) + "'\n")
# spice_file.write("Xsb_mux_partial_" + str(i+1) + " " + next_node + f" n_gate n_gate_n n_vdd n_gnd {sb_mux_partial_str}\n")
# current_node = next_node
# next_node = "n_1_" + str(i+num_sb_mux_off+3)
# for i in range(num_sb_mux_on):
# # The last 'on' sb_mux needs to have special node names to be able to connect it to the output and also for measurements.
# if i == (num_sb_mux_on-1):
# spice_file.write(f"Xwire_general_ble_output_" + str(i+num_sb_mux_off+num_sb_mux_partial+1) + " " + current_node + " n_meas_point"
# + f" wire Rw='{wire_general_ble_output_pstr}_res/" + str(sb_mux_total) + f"' Cw='{wire_general_ble_output_pstr}_cap/" + str(sb_mux_total) + "'\n")
# spice_file.write("Xsb_mux_on_" + str(i+1) + f" n_meas_point n_out n_gate n_gate_n n_vdd n_gnd {sb_mux_on_str}\n")
# else:
# spice_file.write("Xwire_general_ble_output_" + str(i+num_sb_mux_off+num_sb_mux_partial+1) + " " + current_node + " " + next_node
# + f" wire Rw='{wire_general_ble_output_pstr}_res/" + str(sb_mux_total) + f"' Cw='{wire_general_ble_output_pstr}_cap/" + str(sb_mux_total) + "'\n")
# spice_file.write("Xsb_mux_on_" + str(i+1) + " " + next_node + " n_hang_" + str(i) + f" n_gate n_gate_n n_vdd n_gnd {sb_mux_on_str}\n")
# current_node = next_node
# next_node = "n_1_" + str(i+num_sb_mux_off+num_sb_mux_partial+3)
# spice_file.write(".ENDS\n\n\n")
# spice_file.close()
# # Create a list of all wires used in this subcircuit
# wire_names_list = []
# wire_names_list.append(wire_general_ble_output_pstr)
# return wire_names_list