Configured bitline directions into prot_data

This commit is contained in:
mrg 2020-04-20 14:23:40 -07:00
parent cbb67ad483
commit 7f65176908
3 changed files with 42 additions and 25 deletions

View File

@ -974,6 +974,7 @@ class layout():
def create_channel_route(self, netlist, def create_channel_route(self, netlist,
offset, offset,
layer_stack, layer_stack,
layer_dirs=None,
vertical=False): vertical=False):
""" """
The net list is a list of the nets. Each net is a list of pins The net list is a list of the nets. Each net is a list of pins
@ -1012,25 +1013,38 @@ class layout():
def vcg_pin_overlap(pin1, pin2, vertical, pitch): def vcg_pin_overlap(pin1, pin2, vertical, pitch):
""" Check for vertical or horizontal overlap of the two pins """ """ Check for vertical or horizontal overlap of the two pins """
# FIXME: If the pins are not in a row, this may break. # FIXME: If the pins are not in a row, this may break.
# However, a top pin shouldn't overlap another top pin, # However, a top pin shouldn't overlap another top pin,
# for example, so the # for example, so the
# extra comparison *shouldn't* matter. # extra comparison *shouldn't* matter.
# Pin 1 must be in the "BOTTOM" set # Pin 1 must be in the "BOTTOM" set
x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x-pin2.center().x)<pitch x_overlap = pin1.by() < pin2.by() and abs(pin1.center().x - pin2.center().x) < pitch
# Pin 1 must be in the "LEFT" set # Pin 1 must be in the "LEFT" set
y_overlap = pin1.lx() < pin2.lx() and abs(pin1.center().y-pin2.center().y)<pitch y_overlap = pin1.lx() < pin2.lx() and abs(pin1.center().y - pin2.center().y) < pitch
overlaps = (not vertical and x_overlap) or (vertical and y_overlap) overlaps = (not vertical and x_overlap) or (vertical and y_overlap)
return overlaps return overlaps
if self.get_preferred_direction(layer_stack[0]) == "V": if not layer_dirs:
self.vertical_layer = layer_stack[0] # Use the preferred layer directions
self.horizontal_layer = layer_stack[2] if self.get_preferred_direction(layer_stack[0]) == "V":
self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2]
else:
self.vertical_layer = layer_stack[2]
self.horizontal_layer = layer_stack[0]
else: else:
self.vertical_layer = layer_stack[2] # Use the layer directions specified to the router rather than
self.horizontal_layer = layer_stack[0] # the preferred directions
debug.check(layer_dirs[0] != layer_dirs[1], "Must have unique layer directions.")
if layer_dirs[0] == "V":
self.vertical_layer = layer_stack[0]
self.horizontal_layer = layer_stack[2]
else:
self.horizontal_layer = layer_stack[0]
self.vertical_layer = layer_stack[2]
layer_stuff = self.get_layer_pitch(self.vertical_layer) layer_stuff = self.get_layer_pitch(self.vertical_layer)
(self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff (self.vertical_pitch, self.vertical_width, self.vertical_space) = layer_stuff
@ -1113,17 +1127,17 @@ class layout():
self.horizontal_pitch) self.horizontal_pitch)
offset += vector(0, self.horizontal_pitch) offset += vector(0, self.horizontal_pitch)
def create_vertical_channel_route(self, netlist, offset, layer_stack): def create_vertical_channel_route(self, netlist, offset, layer_stack, layer_dirs):
""" """
Wrapper to create a vertical channel route Wrapper to create a vertical channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=True) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=True)
def create_horizontal_channel_route(self, netlist, offset, layer_stack): def create_horizontal_channel_route(self, netlist, offset, layer_stack, layer_dirs):
""" """
Wrapper to create a horizontal channel route Wrapper to create a horizontal channel route
""" """
self.create_channel_route(netlist, offset, layer_stack, vertical=False) self.create_channel_route(netlist, offset, layer_stack, layer_dirs, vertical=False)
def add_boundary(self, ll=vector(0, 0), ur=None): def add_boundary(self, ll=vector(0, 0), ur=None):
""" Add boundary for debugging dimensions """ """ Add boundary for debugging dimensions """

View File

@ -28,7 +28,6 @@ class bitcell_array(bitcell_base_array):
# the replica bitcell in the control logic # the replica bitcell in the control logic
# self.offset_all_coordinates() # self.offset_all_coordinates()
def create_netlist(self): def create_netlist(self):
""" Create and connect the netlist """ """ Create and connect the netlist """
self.add_modules() self.add_modules()
@ -56,22 +55,21 @@ class bitcell_array(bitcell_base_array):
for col in range(self.column_size): for col in range(self.column_size):
for row in range(self.row_size): for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col) name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.cell) mod=self.cell)
self.connect_inst(self.get_bitcell_pins(col, row)) self.connect_inst(self.get_bitcell_pins(col, row))
def analytical_power(self, corner, load): def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW.""" """Power of Bitcell array and bitline in nW."""
from tech import drc, parameter
# Dynamic Power from Bitline # Dynamic Power from Bitline
bl_wire = self.gen_bl_wire() bl_wire = self.gen_bl_wire()
cell_load = 2 * bl_wire.return_input_cap() cell_load = 2 * bl_wire.return_input_cap()
bl_swing = OPTS.rbl_delay_percentage bl_swing = OPTS.rbl_delay_percentage
freq = spice["default_event_frequency"] freq = spice["default_event_frequency"]
bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing) bitline_dynamic = self.calc_dynamic_power(corner, cell_load, freq, swing=bl_swing)
# Calculate the bitcell power which currently only includes leakage # Calculate the bitcell power which currently only includes leakage
cell_power = self.cell.analytical_power(corner, load) cell_power = self.cell.analytical_power(corner, load)
# Leakage power grows with entire array and bitlines. # Leakage power grows with entire array and bitlines.
@ -85,7 +83,7 @@ class bitcell_array(bitcell_base_array):
else: else:
width = self.width width = self.width
wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1")) wl_wire = self.generate_rc_net(int(self.column_size), width, drc("minwidth_m1"))
wl_wire.wire_c = 2*spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell wl_wire.wire_c = 2 * spice["min_tx_gate_c"] + wl_wire.wire_c # 2 access tx gate per cell
return wl_wire return wl_wire
def gen_bl_wire(self): def gen_bl_wire(self):
@ -94,26 +92,26 @@ class bitcell_array(bitcell_base_array):
else: else:
height = self.height height = self.height
bl_pos = 0 bl_pos = 0
bl_wire = self.generate_rc_net(int(self.row_size-bl_pos), height, drc("minwidth_m1")) bl_wire = self.generate_rc_net(int(self.row_size - bl_pos), height, drc("minwidth_m1"))
bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell bl_wire.wire_c =spice["min_tx_drain_c"] + bl_wire.wire_c # 1 access tx d/s per cell
return bl_wire return bl_wire
def get_wordline_cin(self): def get_wordline_cin(self):
"""Get the relative input capacitance from the wordline connections in all the bitcell""" """Get the relative input capacitance from the wordline connections in all the bitcell"""
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns # A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
bitcell_wl_cin = self.cell.get_wl_cin() bitcell_wl_cin = self.cell.get_wl_cin()
total_cin = bitcell_wl_cin * self.column_size total_cin = bitcell_wl_cin * self.column_size
return total_cin return total_cin
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
"""Excludes bits in column from being added to graph except target""" """Excludes bits in column from being added to graph except target"""
#Function is not robust with column mux configurations # Function is not robust with column mux configurations
for row in range(self.row_size): for row in range(self.row_size):
for col in range(self.column_size): for col in range(self.column_size):
if row == targ_row and col == targ_col: if row == targ_row and col == targ_col:
continue continue
self.graph_inst_exclude.add(self.cell_inst[row,col]) self.graph_inst_exclude.add(self.cell_inst[row, col])
def get_cell_name(self, inst_name, row, col): def get_cell_name(self, inst_name, row, col):
"""Gets the spice name of the target bitcell.""" """Gets the spice name of the target bitcell."""
return inst_name+'.x'+self.cell_inst[row,col].name, self.cell_inst[row,col] return inst_name + '.x' + self.cell_inst[row, col].name, self.cell_inst[row, col]

View File

@ -699,8 +699,13 @@ class port_data(design.design):
bottom_names = self._get_bitline_pins(bot_inst_group, bit) bottom_names = self._get_bitline_pins(bot_inst_group, bit)
top_names = self._get_bitline_pins(top_inst_group, bit) top_names = self._get_bitline_pins(top_inst_group, bit)
if bottom_names[0].layer == "m2":
bitline_dirs = ("H", "V")
elif bottom_names[0].layer == "m1":
bitline_dirs = ("V", "H")
route_map = list(zip(bottom_names, top_names)) route_map = list(zip(bottom_names, top_names))
self.create_horizontal_channel_route(route_map, offset, self.m1_stack) self.create_horizontal_channel_route(route_map, offset, self.m1_stack, bitline_dirs)
def connect_bitlines(self, inst1, inst2, num_bits, def connect_bitlines(self, inst1, inst2, num_bits,
inst1_bls_template="{inst}_{bit}", inst1_bls_template="{inst}_{bit}",