Merge branch 'laptop_checkpoint' into dev

This commit is contained in:
mrg
2021-06-04 15:22:37 -07:00
20 changed files with 210 additions and 73 deletions
+25 -11
View File
@@ -366,18 +366,13 @@ class bank(design.design):
# A space for wells or jogging m2
self.m2_gap = max(2 * drc("pwell_to_nwell") + drc("nwell_enclose_active"),
3 * self.m2_pitch)
3 * self.m2_pitch,
drc("nwell_to_nwell"))
def add_modules(self):
""" Add all the modules using the class loader """
self.port_address = []
for port in self.all_ports:
self.port_address.append(factory.create(module_type="port_address",
cols=self.num_cols + self.num_spare_cols,
rows=self.num_rows,
port=port))
self.add_mod(self.port_address[port])
local_array_size = OPTS.local_array_size
@@ -397,12 +392,26 @@ class bank(design.design):
cols=self.num_cols + self.num_spare_cols,
rows=self.num_rows)
self.add_mod(self.bitcell_array)
if self.num_spare_cols == 0:
self.num_spare_cols = (self.bitcell_array.column_size % (self.word_size *self.words_per_row))
self.port_address = []
for port in self.all_ports:
self.port_address.append(factory.create(module_type="port_address",
cols=self.bitcell_array.column_size,
rows=self.bitcell_array.row_size,
port=port))
self.add_mod(self.port_address[port])
self.port_data = []
self.bit_offsets = self.get_column_offsets()
for port in self.all_ports:
temp_pre = factory.create(module_type="port_data",
sram_config=self.sram_config,
dimension_override=True,
cols=self.bitcell_array.column_size - self.num_spare_cols,
rows=self.bitcell_array.row_size,
num_spare_cols=self.num_spare_cols,
port=port,
bit_offsets=self.bit_offsets)
self.port_data.append(temp_pre)
@@ -430,7 +439,9 @@ class bank(design.design):
temp.append("vdd")
temp.append("gnd")
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
temp.append('vpb')
temp.append('vnb')
self.connect_inst(temp)
def place_bitcell_array(self, offset):
@@ -489,7 +500,7 @@ class bank(design.design):
mod=self.port_address[port])
temp = []
for bit in range(self.row_addr_size):
for bit in range(ceil(log(self.bitcell_array.row_size, 2))):
temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size))
temp.append("wl_en{}".format(port))
wordline_names = self.bitcell_array.get_wordline_names(port)
@@ -614,6 +625,10 @@ class bank(design.design):
self.copy_power_pins(inst, "vdd", add_vias=False)
self.copy_power_pins(inst, "gnd", add_vias=False)
if 'vpb' in self.bitcell_array_inst.mod.pins and 'vnb' in self.bitcell_array_inst.mod.pins:
for pin_name, supply_name in zip(['vpb','vnb'],['vdd','gnd']):
self.copy_power_pins(self.bitcell_array_inst, pin_name, new_name=supply_name)
# If we use the pinvbuf as the decoder, we need to add power pins.
# Other decoders already have them.
if self.col_addr_size == 1:
@@ -1062,7 +1077,6 @@ class bank(design.design):
to_layer="m2",
offset=control_pos)
def graph_exclude_precharge(self):
"""
Precharge adds a loop between bitlines, can be excluded to reduce complexity
+47 -4
View File
@@ -12,6 +12,10 @@ from vector import vector
from sram_factory import factory
from globals import OPTS
from tech import layer_properties as layer_props
from tech import layer_indices
from tech import layer_stacks
from tech import preferred_directions
from tech import drc
class hierarchical_predecode(design.design):
@@ -29,7 +33,7 @@ class hierarchical_predecode(design.design):
self.cell_height = height
self.column_decoder = column_decoder
self.input_and_rail_pos = []
self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
super().__init__(name)
@@ -183,9 +187,9 @@ class hierarchical_predecode(design.design):
def route(self):
self.route_input_inverters()
self.route_output_inverters()
self.route_inputs_to_rails()
self.route_input_ands()
self.route_output_inverters()
self.route_inputs_to_rails()
self.route_output_ands()
self.route_vdd_gnd()
@@ -274,8 +278,46 @@ class hierarchical_predecode(design.design):
# pins in the and gates.
inv_out_pos = inv_out_pin.rc()
y_offset = (inv_num + 1) * self.inv.height - self.output_layer_pitch
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").rx(), 0)
rail_pos = vector(self.decode_rails[out_pin].cx(), y_offset)
# create via for dimensions
from_layer = self.output_layer
to_layer = self.bus_layer
cur_layer = from_layer
from_id = layer_indices[cur_layer]
to_id = layer_indices[to_layer]
if from_id < to_id: # grow the stack up
search_id = 0
next_id = 2
else: # grow the stack down
search_id = 2
next_id = 0
curr_stack = next(filter(lambda stack: stack[search_id] == cur_layer, layer_stacks), None)
via = factory.create(module_type="contact",
layer_stack=curr_stack,
dimensions=[1, 1],
directions=self.bus_directions)
overlapping_pin_space = drc["{0}_to_{0}".format(self.output_layer)]
total_buffer_space = (overlapping_pin_space + via.height)
#FIXME: compute rail locations instead of just guessing and nudging
while(True):
drc_error = 0
for and_input in self.input_and_rail_pos:
if and_input.x == rail_pos.x:
if (abs(y_offset - and_input.y) < total_buffer_space) and (abs(y_offset - and_input.y) > via.height):
drc_error = 1
if drc_error == 0:
break
else:
y_offset += drc["grid"]
rail_pos.y = y_offset
right_pos = inv_out_pos + vector(self.inv.width - self.inv.get_pin("Z").rx(), 0)
self.add_path(self.output_layer, [inv_out_pos, right_pos, vector(right_pos.x, y_offset), rail_pos])
self.add_via_stack_center(from_layer=inv_out_pin.layer,
@@ -316,6 +358,7 @@ class hierarchical_predecode(design.design):
to_layer=self.bus_layer,
offset=rail_pos,
directions=self.bus_directions)
self.input_and_rail_pos.append(rail_pos)
if gate_pin == "A":
direction = None
else:
+49 -21
View File
@@ -11,6 +11,7 @@ from sram_factory import factory
from collections import namedtuple
from vector import vector
from globals import OPTS
from tech import cell_properties
from tech import layer_properties as layer_props
@@ -20,26 +21,36 @@ class port_data(design.design):
Port 0 always has the RBL on the left while port 1 is on the right.
"""
def __init__(self, sram_config, port, bit_offsets=None, name=""):
def __init__(self, sram_config, port, num_spare_cols=None, bit_offsets=None, name="", rows=None, cols=None, dimension_override=False):
sram_config.set_local_config(self)
if dimension_override:
self.num_rows = rows
self.num_cols = cols
self.word_size = sram_config.word_size
self.port = port
if self.write_size is not None:
self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
else:
self.num_wmasks = 0
if self.num_spare_cols is None:
if num_spare_cols:
self.num_spare_cols = num_spare_cols
elif self.num_spare_cols is None:
self.num_spare_cols = 0
if not bit_offsets:
bitcell = factory.create(module_type=OPTS.bitcell)
if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = bitcell.width + strap.width
else:
precharge_width = bitcell.width
self.bit_offsets = []
for i in range(self.num_cols + self.num_spare_cols):
self.bit_offsets.append(i * bitcell.width)
self.bit_offsets.append(i * precharge_width)
else:
self.bit_offsets = bit_offsets
if name == "":
name = "port_data_{0}".format(self.port)
super().__init__(name)
@@ -117,7 +128,6 @@ class port_data(design.design):
for bit in range(self.num_spare_cols):
self.add_pin("sparebl_{0}".format(bit), "INOUT")
self.add_pin("sparebr_{0}".format(bit), "INOUT")
if self.port in self.read_ports:
for bit in range(self.word_size + self.num_spare_cols):
self.add_pin("dout_{}".format(bit), "OUTPUT")
@@ -191,14 +201,19 @@ class port_data(design.design):
# and mirroring happens correctly
# Used for names/dimensions only
self.cell = factory.create(module_type=OPTS.bitcell)
cell = factory.create(module_type=OPTS.bitcell)
if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = cell.width + strap.width
else:
precharge_width = cell.width
if self.port == 0:
# Append an offset on the left
precharge_bit_offsets = [self.bit_offsets[0] - self.cell.width] + self.bit_offsets
precharge_bit_offsets = [self.bit_offsets[0] - precharge_width] + self.bit_offsets
else:
# Append an offset on the right
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + self.cell.width]
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + precharge_width]
self.precharge_array = factory.create(module_type="precharge_array",
columns=self.num_cols + self.num_spare_cols + 1,
offsets=precharge_bit_offsets,
@@ -567,19 +582,32 @@ class port_data(design.design):
off = 1
else:
off = 0
if OPTS.num_ports > 1:
self.channel_route_bitlines(inst1=self.column_mux_array_inst,
inst1_bls_template="{inst}_out_{bit}",
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
self.channel_route_bitlines(inst1=self.column_mux_array_inst,
inst1_bls_template="{inst}_out_{bit}",
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
self.channel_route_bitlines(inst1=self.precharge_array_inst,
inst1_bls_template="{inst}_{bit}",
inst2=inst2,
num_bits=self.num_spare_cols,
inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size)
else:
self.connect_bitlines(inst1=self.column_mux_array_inst,
inst1_bls_template="{inst}_out_{bit}",
inst2=inst2,
num_bits=self.word_size,
inst1_start_bit=start_bit)
self.channel_route_bitlines(inst1=self.precharge_array_inst,
inst1_bls_template="{inst}_{bit}",
inst2=inst2,
num_bits=self.num_spare_cols,
inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size)
self.connect_bitlines(inst1=self.precharge_array_inst,
inst1_bls_template="{inst}_{bit}",
inst2=inst2,
num_bits=self.num_spare_cols,
inst1_start_bit=self.num_cols + off,
inst2_start_bit=self.word_size)
elif layer_props.port_data.channel_route_bitlines:
self.channel_route_bitlines(inst1=inst1,
+1 -1
View File
@@ -76,8 +76,8 @@ class precharge_array(design.design):
size=self.size,
bitcell_bl=self.bitcell_bl,
bitcell_br=self.bitcell_br)
self.add_mod(self.pc_cell)
self.cell = factory.create(module_type=OPTS.bitcell)
def add_layout_pins(self):
+1 -1
View File
@@ -6,7 +6,7 @@
import debug
from bitcell_base_array import bitcell_base_array
from tech import drc, spice
from tech import drc, spice, cell_properties
from vector import vector
from globals import OPTS
from sram_factory import factory
+12 -6
View File
@@ -8,6 +8,7 @@
import design
from vector import vector
from sram_factory import factory
from tech import cell_properties
import debug
from globals import OPTS
@@ -41,7 +42,6 @@ class sense_amp_array(design.design):
self.en_layer = "m3"
else:
self.en_layer = "m1"
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
@@ -109,15 +109,22 @@ class sense_amp_array(design.design):
self.en_name, "vdd", "gnd"])
def place_sense_amp_array(self):
if self.bitcell.width > self.amp.width:
self.amp_spacing = self.bitcell.width
cell = factory.create(module_type=OPTS.bitcell)
if(cell_properties.use_strap == True and OPTS.num_ports == 1):
strap = factory.create(module_type=cell_properties.strap_module, version=cell_properties.strap_version)
precharge_width = cell.width + strap.width
else:
precharge_width = cell.width
if precharge_width > self.amp.width:
self.amp_spacing = precharge_width
else:
self.amp_spacing = self.amp.width
if not self.offsets:
self.offsets = []
for i in range(self.num_cols + self.num_spare_cols):
self.offsets.append(i * self.bitcell.width)
self.offsets.append(i * self.amp_spacing)
for i, xoffset in enumerate(self.offsets[0:self.num_cols:self.words_per_row]):
if self.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
@@ -128,13 +135,12 @@ class sense_amp_array(design.design):
amp_position = vector(xoffset, 0)
self.local_insts[i].place(offset=amp_position, mirror=mirror)
# place spare sense amps (will share the same enable as regular sense amps)
for i, xoffset in enumerate(self.offsets[self.num_cols:]):
index = self.word_size + i
if self.bitcell.mirror.y and (index + self.column_offset) % 2:
mirror = "MY"
xoffset = xoffset + self.amp_width
xoffset = xoffset + self.amp_spacing
else:
mirror = ""