mirror of https://github.com/VLSIDA/OpenRAM.git
Update to space according to the bitcell array.
This commit is contained in:
parent
4482c63d6f
commit
e95ab66916
|
|
@ -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])
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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. """
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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 = ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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 """
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue