Update to space according to the bitcell array.

This commit is contained in:
mrg 2020-09-14 12:05:45 -07:00
parent 4482c63d6f
commit e95ab66916
10 changed files with 74 additions and 69 deletions

View File

@ -189,6 +189,8 @@ class bank(design.design):
self.main_bitcell_array_top = self.bitcell_array.get_main_array_top()
# Just past the dummy column
self.main_bitcell_array_left = self.bitcell_array.get_main_array_left()
# Just past the dummy column
self.main_bitcell_array_right = self.bitcell_array.get_main_array_right()
# Just past the dummy row and replica row
self.main_bitcell_array_bottom = self.bitcell_array.get_main_array_bottom()
@ -200,8 +202,10 @@ class bank(design.design):
"""
Return an array of the x offsets of all the regular bits
"""
return self.bitcell_array.get_column_offsets()
# Assumes bitcell_array is at 0,0
offsets = self.bitcell_array.get_column_offsets()
return offsets
def compute_instance_port0_offsets(self):
"""
Compute the instance offsets for port0 on the left/bottom of the bank.
@ -215,7 +219,7 @@ class bank(design.design):
# LOWER RIGHT QUADRANT
# Below the bitcell array
self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width, 0)
self.port_data_offsets[port] = vector(0, 0)
# UPPER LEFT QUADRANT
# To the left of the bitcell array above the predecoders and control logic
@ -259,7 +263,7 @@ class bank(design.design):
# UPPER LEFT QUADRANT
# Above the bitcell array
self.port_data_offsets[port] = vector(self.main_bitcell_array_left, self.bitcell_array_top)
self.port_data_offsets[port] = vector(0, self.bitcell_array_top)
# LOWER RIGHT QUADRANT
# To the right of the bitcell array
@ -392,11 +396,12 @@ class bank(design.design):
self.add_mod(self.bitcell_array)
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,
port=port,
bit_offsets=self.bitcell_array.get_column_offsets())
bit_offsets=self.bit_offsets)
self.port_data.append(temp_pre)
self.add_mod(self.port_data[port])
@ -916,7 +921,7 @@ class bank(design.design):
offset = self.column_decoder_inst[port].lr() + vector(pitch, 0)
decode_pins = [self.column_decoder_inst[port].get_pin(x) for x in decode_names]
sel_names = ["sel_{}".format(x) for x in range(self.num_col_addr_lines)]
column_mux_pins = [self.port_data_inst[port].get_pin(x) for x in sel_names]
@ -1043,10 +1048,12 @@ class bank(design.design):
control_signal = self.prefix + "wl_en{}".format(port)
if port % 2:
pin_pos = self.port_address_inst[port].get_pin("wl_en").uc()
mid_pos = pin_pos + vector(0, 2 * self.m2_gap) # to route down to the top of the bus
control_y_offset = self.bus_pins[port][control_signal].by()
mid_pos = vector(pin_pos.x, control_y_offset + self.m1_pitch)
else:
pin_pos = self.port_address_inst[port].get_pin("wl_en").bc()
mid_pos = pin_pos - vector(0, 2 * self.m2_gap) # to route down to the top of the bus
control_y_offset = self.bus_pins[port][control_signal].uy()
mid_pos = vector(pin_pos.x, control_y_offset - self.m1_pitch)
control_x_offset = self.bus_pins[port][control_signal].cx()
control_pos = vector(control_x_offset, mid_pos.y)
self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos])

View File

@ -211,4 +211,5 @@ class bitcell_base_array(design.design):
"""
Return an array of the x offsets of all the regular bits
"""
return [self.cell_inst[0, col].lx() for col in range(self.column_size)]
offsets = [self.cell_inst[0, col].lx() for col in range(self.column_size)]
return offsets

View File

@ -260,5 +260,5 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array):
"""
offsets = []
for inst in self.local_insts:
offsets.extend(inst.lx() + inst.mod.get_column_offsets())
offsets.extend(inst.lx() + x for x in inst.mod.get_column_offsets())
return offsets

View File

@ -260,5 +260,6 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
Return an array of the x offsets of all the regular bits
"""
# must add the offset of the instance
return [self.bitcell_array_inst.lx() + x for x in self.bitcell_array.get_column_offsets()]
offsets = [self.bitcell_array_inst.lx() + x for x in self.bitcell_array.get_column_offsets()]
return offsets

View File

@ -37,7 +37,7 @@ class port_data(design.design):
self.bit_offsets.append(i * bitcell.width)
else:
self.bit_offsets = bit_offsets
if name == "":
name = "port_data_{0}".format(self.port)
super().__init__(name)
@ -187,9 +187,19 @@ class port_data(design.design):
# Precharge will be shifted left if needed
# Column offset is set to port so extra column can be on left or right
# and mirroring happens correctly
# Used for names/dimensions only
self.cell = factory.create(module_type="bitcell")
if self.port == 0:
# Append an offset on the left
precharge_bit_offsets = [self.bit_offsets[0] - self.cell.width] + self.bit_offsets
else:
# Append an offset on the right
precharge_bit_offsets = self.bit_offsets + [self.bit_offsets[-1] + self.cell.width]
self.precharge_array = factory.create(module_type="precharge_array",
columns=self.num_cols + self.num_spare_cols + 1,
offsets=self.bit_offsets,
offsets=precharge_bit_offsets,
bitcell_bl=self.bl_names[self.port],
bitcell_br=self.br_names[self.port],
column_offset=self.port - 1)
@ -231,6 +241,7 @@ class port_data(design.design):
# RBLs don't get a write mask
self.write_mask_and_array = factory.create(module_type="write_mask_and_array",
columns=self.num_cols,
offsets=self.bit_offsets,
word_size=self.word_size,
write_size=self.write_size)
self.add_mod(self.write_mask_and_array)
@ -423,21 +434,15 @@ class port_data(design.design):
vertical_port_order.append(self.write_driver_array_inst)
vertical_port_order.append(self.write_mask_and_array_inst)
# Add one column for the the RBL
if self.port==0:
x_offset = self.bitcell.width
else:
x_offset = 0
vertical_port_offsets = 5 * [None]
self.width = x_offset
self.width = 0
self.height = 0
for i, p in enumerate(vertical_port_order):
if p == None:
continue
self.height += (p.height + self.m2_gap)
self.width = max(self.width, p.width)
vertical_port_offsets[i] = vector(x_offset, self.height)
vertical_port_offsets[i] = vector(0, self.height)
# Reversed order
self.write_mask_and_offset = vertical_port_offsets[4]
@ -445,9 +450,6 @@ class port_data(design.design):
self.sense_amp_offset = vertical_port_offsets[2]
self.column_mux_offset = vertical_port_offsets[1]
self.precharge_offset = vertical_port_offsets[0]
# Shift the precharge left if port 0
if self.precharge_offset and self.port == 0:
self.precharge_offset -= vector(x_offset, 0)
def place_instances(self):
""" Place the instances. """

View File

@ -118,7 +118,7 @@ class precharge_array(design.design):
# Default to single spaced columns
if not self.offsets:
self.offsets = [n * self.pc_cell.width for n in range(self.columns)]
for i, xoffset in enumerate(self.offsets):
if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2:
mirror = "MY"
@ -129,4 +129,5 @@ class precharge_array(design.design):
offset = vector(tempx, 0)
self.local_insts[i].place(offset=offset, mirror=mirror)
xoffset = xoffset + self.pc_cell.width

View File

@ -321,7 +321,8 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
# Array was at (0, 0) but move everything so it is at the lower left
# We move DOWN the number of left RBL even if we didn't add the column to this bitcell array
self.translate_all(self.bitcell_offset.scale(-1 - len(self.left_rbl), -1 - self.rbl[0]))
array_offset = self.bitcell_offset.scale(1 + len(self.left_rbl), 1 + self.rbl[0])
self.translate_all(array_offset.scale(-1, -1))
self.add_layout_pins()
@ -347,8 +348,8 @@ class replica_bitcell_array(bitcell_base_array.bitcell_base_array):
"""
Return an array of the x offsets of all the regular bits
"""
# This works because the instance of the module is placed at 0,0
return self.bitcell_array.get_column_offsets()
offsets = [x + self.bitcell_array_inst.lx() for x in self.bitcell_array.get_column_offsets()]
return offsets
def add_replica_columns(self):
""" Add replica columns on left and right of array """

View File

@ -6,12 +6,11 @@
# All rights reserved.
#
import design
from tech import drc
from vector import vector
from sram_factory import factory
import debug
from globals import OPTS
import logical_effort
from tech import cell_properties
class sense_amp_array(design.design):
@ -29,6 +28,7 @@ class sense_amp_array(design.design):
self.word_size = word_size
self.words_per_row = words_per_row
self.columns = word_size * words_per_row
self.offsets = offsets
if not num_spare_cols:
self.num_spare_cols = 0
@ -69,16 +69,15 @@ class sense_amp_array(design.design):
self.create_sense_amp_array()
def create_layout(self):
self.height = self.amp.height
if self.bitcell.width > self.amp.width:
self.width = self.bitcell.width * (self.word_size * self.words_per_row + self.num_spare_cols)
else:
self.width = self.amp.width * (self.word_size * self.words_per_row + self.num_spare_cols)
self.place_sense_amp_array()
self.height = self.amp.height
self.width = self.local_insts[-1].rx()
self.add_layout_pins()
self.route_rails()
self.add_boundary()
self.DRC_LVS()
@ -112,29 +111,32 @@ class sense_amp_array(design.design):
self.en_name, "vdd", "gnd"])
def place_sense_amp_array(self):
from tech import cell_properties
if self.bitcell.width > self.amp.width:
self.amp_spacing = self.bitcell.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)
for i in range(0, self.row_size, self.words_per_row):
index = int(i / self.words_per_row)
xoffset = i * self.bitcell.width
if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2:
for i, xoffset in enumerate(self.offsets[0:self.columns:self.words_per_row]):
if cell_properties.bitcell.mirror.y and (i * self.words_per_row + self.column_offset) % 2:
mirror = "MY"
xoffset = xoffset + self.amp.width
xoffset = xoffset + self.amp_spacing
else:
mirror = ""
amp_position = vector(xoffset, 0)
self.local_insts[index].place(offset=amp_position, mirror=mirror)
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 in range(0, self.num_spare_cols):
for i, xoffset in enumerate(self.offsets[self.columns:]):
index = self.word_size + i
xoffset = ((self.word_size * self.words_per_row) + i) * self.bitcell.width
if cell_properties.bitcell.mirror.y and (i + self.column_offset) % 2:
if cell_properties.bitcell.mirror.y and (index + self.column_offset) % 2:
mirror = "MY"
xoffset = xoffset + self.amp.width
xoffset = xoffset + self.amp_width
else:
mirror = ""

View File

@ -117,14 +117,12 @@ class single_level_column_mux_array(design.design):
"gnd"])
def place_array(self):
# Default to single spaced columns
if not self.offsets:
self.offsets = [n * self.mux.width for n in range(self.columns)]
# For every column, add a pass gate
for col_num, xoffset in enumerate(self.offsets[0:self.columns]):
xoffset = col_num * self.mux.width
if cell_properties.bitcell.mirror.y and (col_num + self.column_offset) % 2:
mirror = "MY"
xoffset = xoffset + self.mux.width
@ -168,7 +166,7 @@ class single_level_column_mux_array(design.design):
self.add_layout_pin(text="sel_{}".format(j),
layer=self.sel_layer,
offset=offset,
width=self.mux.width * self.columns)
width=self.mux_inst[-1].rx())
def add_vertical_poly_rail(self):
""" Connect the poly to the address rails """

View File

@ -68,17 +68,10 @@ class write_driver_array(design.design):
def create_layout(self):
if self.bitcell.width > self.driver.width:
self.width = (self.columns + self.num_spare_cols) * self.bitcell.width
self.width_regular_cols = self.columns * self.bitcell.width
self.single_col_width = self.bitcell.width
else:
self.width = (self.columns + self.num_spare_cols) * self.driver.width
self.width_regular_cols = self.columns * self.driver.width
self.single_col_width = self.driver.width
self.height = self.driver.height
self.place_write_array()
self.width = self.driver_insts[-1].rx()
self.width_regular_cols = self.driver_insts[-self.num_spare_cols].rx()
self.height = self.driver.height
self.add_layout_pins()
self.add_boundary()
self.DRC_LVS()
@ -109,14 +102,14 @@ class write_driver_array(design.design):
self.bitcell = factory.create(module_type="bitcell")
def create_write_array(self):
self.driver_insts = {}
self.driver_insts = []
w = 0
windex=0
for i in range(0, self.columns, self.words_per_row):
name = "write_driver{}".format(i)
index = int(i / self.words_per_row)
self.driver_insts[index]=self.add_inst(name=name,
mod=self.driver)
self.driver_insts.append(self.add_inst(name=name,
mod=self.driver))
if self.write_size:
self.connect_inst([self.data_name + "_{0}".format(index),
@ -148,8 +141,8 @@ class write_driver_array(design.design):
else:
offset = 1
name = "write_driver{}".format(self.columns + i)
self.driver_insts[index]=self.add_inst(name=name,
mod=self.driver)
self.driver_insts.append(self.add_inst(name=name,
mod=self.driver))
self.connect_inst([self.data_name + "_{0}".format(index),
self.get_bl_name() + "_{0}".format(index),
@ -178,7 +171,6 @@ class write_driver_array(design.design):
self.driver_insts[i].place(offset=base, mirror=mirror)
# place spare write drivers (if spare columns are specified)
for i, xoffset in enumerate(self.offsets[self.columns:]):
index = self.word_size + i