mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-08-29 01:24:39 +02:00
Merge branch 'laptop_checkpoint' into dev
This commit is contained in:
+25
-11
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 = ""
|
||||
|
||||
|
||||
Reference in New Issue
Block a user