mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-03 08:27:11 +02:00
Merge branch 'dev' into laptop_checkpoint
This commit is contained in:
+10
-18
@@ -329,13 +329,13 @@ class bank(design.design):
|
||||
self.input_control_signals = []
|
||||
port_num = 0
|
||||
for port in range(OPTS.num_rw_ports):
|
||||
self.input_control_signals.append(["s_en{}".format(port_num), "w_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)])
|
||||
self.input_control_signals.append(["p_en_bar{}".format(port_num), "s_en{}".format(port_num), "w_en{}".format(port_num)])
|
||||
port_num += 1
|
||||
for port in range(OPTS.num_w_ports):
|
||||
self.input_control_signals.append(["w_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)])
|
||||
self.input_control_signals.append(["p_en_bar{}".format(port_num), "w_en{}".format(port_num)])
|
||||
port_num += 1
|
||||
for port in range(OPTS.num_r_ports):
|
||||
self.input_control_signals.append(["s_en{}".format(port_num), "p_en_bar{}".format(port_num), "wl_en{}".format(port_num)])
|
||||
self.input_control_signals.append(["p_en_bar{}".format(port_num), "s_en{}".format(port_num)])
|
||||
port_num += 1
|
||||
|
||||
# Number of control lines in the bus for each port
|
||||
@@ -530,13 +530,16 @@ class bank(design.design):
|
||||
height=self.dff.height)
|
||||
elif self.col_addr_size == 2:
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode2x4",
|
||||
column_decoder=True,
|
||||
height=self.dff.height)
|
||||
|
||||
elif self.col_addr_size == 3:
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8",
|
||||
column_decoder=True,
|
||||
height=self.dff.height)
|
||||
elif self.col_addr_size == 4:
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode4x16",
|
||||
column_decoder=True,
|
||||
height=self.dff.height)
|
||||
else:
|
||||
# No error checking before?
|
||||
@@ -692,6 +695,8 @@ class bank(design.design):
|
||||
make_pins=(self.num_banks==1),
|
||||
pitch=self.m3_pitch)
|
||||
|
||||
self.copy_layout_pin(self.port_address_inst[0], "wl_en", self.prefix + "wl_en0")
|
||||
|
||||
# Port 1
|
||||
if len(self.all_ports)==2:
|
||||
# The other control bus is routed up to two pitches above the bitcell array
|
||||
@@ -707,6 +712,8 @@ class bank(design.design):
|
||||
make_pins=(self.num_banks==1),
|
||||
pitch=self.m3_pitch)
|
||||
|
||||
self.copy_layout_pin(self.port_address_inst[1], "wl_en", self.prefix + "wl_en1")
|
||||
|
||||
def route_port_data_to_bitcell_array(self, port):
|
||||
""" Routing of BL and BR between port data and bitcell array """
|
||||
|
||||
@@ -1055,21 +1062,6 @@ class bank(design.design):
|
||||
to_layer="m2",
|
||||
offset=control_pos)
|
||||
|
||||
# clk to wordline_driver
|
||||
control_signal = self.prefix + "wl_en{}".format(port)
|
||||
if port % 2:
|
||||
pin_pos = self.port_address_inst[port].get_pin("wl_en").uc()
|
||||
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()
|
||||
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])
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=control_pos)
|
||||
|
||||
def graph_exclude_precharge(self):
|
||||
"""
|
||||
|
||||
@@ -64,7 +64,11 @@ class bitcell_array(bitcell_base_array):
|
||||
self.cell_inst[row, col]=self.add_inst(name=name,
|
||||
mod=self.cell)
|
||||
self.connect_inst(self.get_bitcell_pins(row, col))
|
||||
|
||||
|
||||
# If it is a "core" cell, it could be trimmed for sim time
|
||||
if col>0 and col<self.column_size-1 and row>0 and row<self.row_size-1:
|
||||
self.trim_insts.add(name)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
|
||||
|
||||
@@ -333,21 +333,19 @@ class control_logic(design.design):
|
||||
row += 1
|
||||
self.place_gated_clk_buf_row(row)
|
||||
row += 1
|
||||
self.place_wlen_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.place_sen_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.place_wen_row(row)
|
||||
height = self.w_en_gate_inst.uy()
|
||||
control_center_y = self.w_en_gate_inst.uy()
|
||||
row += 1
|
||||
self.place_pen_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "w"):
|
||||
self.place_rbl_delay_row(row)
|
||||
row += 1
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.place_sen_row(row)
|
||||
row += 1
|
||||
self.place_wlen_row(row)
|
||||
row += 1
|
||||
self.place_delay(row)
|
||||
height = self.delay_inst.uy()
|
||||
control_center_y = self.delay_inst.by()
|
||||
|
||||
@@ -11,6 +11,7 @@ from sram_factory import factory
|
||||
from vector import vector
|
||||
import debug
|
||||
from numpy import cumsum
|
||||
from tech import layer_properties as layer_props
|
||||
|
||||
|
||||
class global_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
@@ -223,11 +224,20 @@ class global_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
new_name = "{0}_{1}".format(base_name, col + col_value)
|
||||
self.copy_layout_pin(inst, pin_name, new_name)
|
||||
|
||||
# Add the global word lines
|
||||
wl_layer = layer_props.global_bitcell_array.wordline_layer
|
||||
|
||||
for wl_name in self.local_mods[0].get_inputs():
|
||||
for local_inst in self.local_insts:
|
||||
wl_pin = local_inst.get_pin(wl_name)
|
||||
self.add_via_stack_center(from_layer=wl_pin.layer,
|
||||
to_layer=wl_layer,
|
||||
offset=wl_pin.center())
|
||||
|
||||
left_pin = self.local_insts[0].get_pin(wl_name)
|
||||
right_pin = self.local_insts[-1].get_pin(wl_name)
|
||||
self.add_layout_pin_segment_center(text=wl_name,
|
||||
layer=left_pin.layer,
|
||||
layer=wl_layer,
|
||||
start=left_pin.lc(),
|
||||
end=right_pin.rc())
|
||||
|
||||
|
||||
@@ -18,19 +18,17 @@ class hierarchical_predecode(design.design):
|
||||
"""
|
||||
Pre 2x4 and 3x8 and TBD 4x16 decoder shared code.
|
||||
"""
|
||||
def __init__(self, name, input_number, height=None):
|
||||
def __init__(self, name, input_number, column_decoder=False, height=None):
|
||||
self.number_of_inputs = input_number
|
||||
|
||||
b = factory.create(module_type=OPTS.bitcell)
|
||||
|
||||
if not height:
|
||||
self.cell_height = b.height
|
||||
self.column_decoder = False
|
||||
else:
|
||||
self.cell_height = height
|
||||
# If we are pitch matched to the bitcell, it's a predecoder
|
||||
# otherwise it's a column decoder (out of pgates)
|
||||
self.column_decoder = (height != b.height)
|
||||
|
||||
self.column_decoder = column_decoder
|
||||
|
||||
self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
|
||||
super().__init__(name)
|
||||
@@ -87,8 +85,14 @@ class hierarchical_predecode(design.design):
|
||||
|
||||
self.bus_layer = layer_props.hierarchical_predecode.bus_layer
|
||||
self.bus_directions = layer_props.hierarchical_predecode.bus_directions
|
||||
self.bus_pitch = getattr(self, self.bus_layer + "_pitch")
|
||||
self.bus_space = layer_props.hierarchical_predecode.bus_space_factor * getattr(self, self.bus_layer + "_space")
|
||||
if self.column_decoder:
|
||||
# Column decoders may be routed on M2/M3 if there's a write mask
|
||||
self.bus_pitch = self.m3_pitch
|
||||
self.bus_space = self.m3_space
|
||||
else:
|
||||
self.bus_pitch = getattr(self, self.bus_layer + "_pitch")
|
||||
self.bus_space = getattr(self, self.bus_layer + "_space")
|
||||
self.bus_space = layer_props.hierarchical_predecode.bus_space_factor * self.bus_space
|
||||
self.input_layer = layer_props.hierarchical_predecode.input_layer
|
||||
self.output_layer = layer_props.hierarchical_predecode.output_layer
|
||||
self.output_layer_pitch = getattr(self, self.output_layer + "_pitch")
|
||||
@@ -114,7 +118,8 @@ class hierarchical_predecode(design.design):
|
||||
self.input_rails = self.create_vertical_bus(layer=self.bus_layer,
|
||||
offset=offset,
|
||||
names=input_names,
|
||||
length=self.height - 2 * self.bus_pitch)
|
||||
length=self.height - 2 * self.bus_pitch,
|
||||
pitch=self.bus_pitch)
|
||||
|
||||
invert_names = ["Abar_{}".format(x) for x in range(self.number_of_inputs)]
|
||||
non_invert_names = ["A_{}".format(x) for x in range(self.number_of_inputs)]
|
||||
@@ -123,7 +128,8 @@ class hierarchical_predecode(design.design):
|
||||
self.decode_rails = self.create_vertical_bus(layer=self.bus_layer,
|
||||
offset=offset,
|
||||
names=decode_names,
|
||||
length=self.height - 2 * self.bus_pitch)
|
||||
length=self.height - 2 * self.bus_pitch,
|
||||
pitch=self.bus_pitch)
|
||||
|
||||
def create_input_inverters(self):
|
||||
""" Create the input inverters to invert input signals for the decode stage. """
|
||||
@@ -175,10 +181,12 @@ class hierarchical_predecode(design.design):
|
||||
mirror=mirror)
|
||||
|
||||
def route(self):
|
||||
|
||||
self.route_input_inverters()
|
||||
self.route_output_inverters()
|
||||
self.route_inputs_to_rails()
|
||||
self.route_and_to_rails()
|
||||
self.route_output_and()
|
||||
self.route_input_ands()
|
||||
self.route_output_ands()
|
||||
self.route_vdd_gnd()
|
||||
|
||||
def route_inputs_to_rails(self):
|
||||
@@ -210,7 +218,7 @@ class hierarchical_predecode(design.design):
|
||||
to_layer=self.bus_layer,
|
||||
offset=[self.decode_rails[a_pin].cx(), y_offset])
|
||||
|
||||
def route_output_and(self):
|
||||
def route_output_ands(self):
|
||||
"""
|
||||
Route all conections of the outputs and gates
|
||||
"""
|
||||
@@ -225,12 +233,40 @@ class hierarchical_predecode(design.design):
|
||||
|
||||
def route_input_inverters(self):
|
||||
"""
|
||||
Route all conections of the inputs inverters [Inputs, outputs, vdd, gnd]
|
||||
Route all conections of the inverter inputs
|
||||
"""
|
||||
for inv_num in range(self.number_of_inputs):
|
||||
in_pin = "in_{}".format(inv_num)
|
||||
|
||||
# route input
|
||||
pin = self.inv_inst[inv_num].get_pin("A")
|
||||
inv_in_pos = pin.center()
|
||||
in_pos = vector(self.input_rails[in_pin].cx(), inv_in_pos.y)
|
||||
self.add_path(self.input_layer, [in_pos, inv_in_pos])
|
||||
|
||||
# Inverter input pin
|
||||
self.add_via_stack_center(from_layer=pin.layer,
|
||||
to_layer=self.input_layer,
|
||||
offset=inv_in_pos)
|
||||
# Input rail pin position
|
||||
via=self.add_via_stack_center(from_layer=self.input_layer,
|
||||
to_layer=self.bus_layer,
|
||||
offset=in_pos,
|
||||
directions=self.bus_directions)
|
||||
|
||||
# Create the input pin at this location on the rail
|
||||
self.add_layout_pin_rect_center(text=in_pin,
|
||||
layer=self.bus_layer,
|
||||
offset=in_pos,
|
||||
height=via.mod.second_layer_height,
|
||||
width=via.mod.second_layer_width)
|
||||
|
||||
def route_output_inverters(self):
|
||||
"""
|
||||
Route all conections of the inverter outputs
|
||||
"""
|
||||
for inv_num in range(self.number_of_inputs):
|
||||
out_pin = "Abar_{}".format(inv_num)
|
||||
in_pin = "in_{}".format(inv_num)
|
||||
|
||||
inv_out_pin = self.inv_inst[inv_num].get_pin("Z")
|
||||
|
||||
# add output so that it is just below the vdd or gnd rail
|
||||
@@ -250,31 +286,11 @@ class hierarchical_predecode(design.design):
|
||||
offset=rail_pos,
|
||||
directions=self.bus_directions)
|
||||
|
||||
# route input
|
||||
pin = self.inv_inst[inv_num].get_pin("A")
|
||||
inv_in_pos = pin.center()
|
||||
in_pos = vector(self.input_rails[in_pin].cx(), inv_in_pos.y)
|
||||
self.add_path(self.input_layer, [in_pos, inv_in_pos])
|
||||
self.add_via_stack_center(from_layer=pin.layer,
|
||||
to_layer=self.input_layer,
|
||||
offset=inv_in_pos)
|
||||
via=self.add_via_stack_center(from_layer=self.input_layer,
|
||||
to_layer=self.bus_layer,
|
||||
offset=in_pos)
|
||||
# Create the input pin at this location on the rail
|
||||
self.add_layout_pin_rect_center(text=in_pin,
|
||||
layer=self.bus_layer,
|
||||
offset=in_pos,
|
||||
height=via.mod.second_layer_height,
|
||||
width=via.mod.second_layer_width)
|
||||
def route_input_ands(self):
|
||||
"""
|
||||
Route the different permutations of the NAND/AND decocer cells.
|
||||
"""
|
||||
|
||||
# This is a hack to fix via-to-via spacing issues, but it is currently
|
||||
# causing its own DRC problems.
|
||||
# if layer_props.hierarchical_predecode.vertical_supply:
|
||||
# below_rail = vector(self.decode_rails[out_pin].cx(), y_offset - (self.cell_height / 2))
|
||||
# self.add_path(self.bus_layer, [rail_pos, below_rail], width=self.li_width + self.m1_enclose_mcon * 2)
|
||||
|
||||
def route_and_to_rails(self):
|
||||
# This 2D array defines the connection mapping
|
||||
and_input_line_combination = self.get_and_input_line_combination()
|
||||
for k in range(self.number_of_outputs):
|
||||
|
||||
@@ -13,8 +13,8 @@ class hierarchical_predecode2x4(hierarchical_predecode):
|
||||
"""
|
||||
Pre 2x4 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, name, height=None):
|
||||
super().__init__( name, 2, height)
|
||||
def __init__(self, name, column_decoder=False, height=None):
|
||||
super().__init__(name, 2, column_decoder, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
||||
@@ -13,8 +13,8 @@ class hierarchical_predecode3x8(hierarchical_predecode):
|
||||
"""
|
||||
Pre 3x8 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, name, height=None):
|
||||
super().__init__(name, 3, height)
|
||||
def __init__(self, name, column_decoder=False, height=None):
|
||||
super().__init__(name, 3, column_decoder, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
||||
@@ -13,8 +13,8 @@ class hierarchical_predecode4x16(hierarchical_predecode):
|
||||
"""
|
||||
Pre 4x16 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, name, height=None):
|
||||
super().__init__(name, 4, height)
|
||||
def __init__(self, name, column_decoder=False, height=None):
|
||||
super().__init__(name, 4, column_decoder, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
||||
@@ -10,6 +10,7 @@ from globals import OPTS
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
import debug
|
||||
from tech import layer_properties as layer_props
|
||||
|
||||
|
||||
class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
@@ -190,6 +191,11 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
|
||||
def route(self):
|
||||
|
||||
global_wl_layer = layer_props.global_bitcell_array.wordline_layer
|
||||
global_wl_pitch = getattr(self, "{}_pitch".format(global_wl_layer))
|
||||
global_wl_pitch_factor = layer_props.global_bitcell_array.wordline_pitch_factor
|
||||
local_wl_layer = layer_props.local_bitcell_array.wordline_layer
|
||||
|
||||
# Route the global wordlines
|
||||
for port in self.all_ports:
|
||||
if port == 0:
|
||||
@@ -204,25 +210,33 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
in_pin = self.wl_insts[port].get_pin(in_pin_name)
|
||||
|
||||
y_offset = in_pin.cy()
|
||||
|
||||
if port == 0:
|
||||
y_offset -= 2 * self.m3_pitch
|
||||
y_offset -= global_wl_pitch_factor * global_wl_pitch
|
||||
else:
|
||||
y_offset += 2 * self.m3_pitch
|
||||
|
||||
self.add_layout_pin_segment_center(text=wl_name,
|
||||
layer="m3",
|
||||
start=vector(self.wl_insts[port].lx(), y_offset),
|
||||
end=vector(self.wl_insts[port].lx() + self.wl_array.width, y_offset))
|
||||
|
||||
y_offset += global_wl_pitch_factor * global_wl_pitch
|
||||
mid = vector(in_pin.cx(), y_offset)
|
||||
self.add_path("m2", [in_pin.center(), mid])
|
||||
|
||||
self.add_layout_pin_rect_center(text=wl_name,
|
||||
layer=global_wl_layer,
|
||||
offset=mid)
|
||||
|
||||
self.add_path(local_wl_layer, [in_pin.center(), mid])
|
||||
|
||||
# A short jog to the global line
|
||||
self.add_via_stack_center(from_layer=in_pin.layer,
|
||||
to_layer="m2",
|
||||
offset=in_pin.center())
|
||||
self.add_via_center(self.m2_stack,
|
||||
offset=mid)
|
||||
|
||||
to_layer=local_wl_layer,
|
||||
offset=in_pin.center(),
|
||||
min_area=True)
|
||||
self.add_path(local_wl_layer, [in_pin.center(), mid])
|
||||
self.add_via_stack_center(from_layer=local_wl_layer,
|
||||
to_layer=global_wl_layer,
|
||||
offset=mid,
|
||||
min_area=True)
|
||||
# Add the global WL pin
|
||||
self.add_layout_pin_rect_center(text=wl_name,
|
||||
layer=global_wl_layer,
|
||||
offset=mid)
|
||||
# Route the buffers
|
||||
for port in self.all_ports:
|
||||
driver_outputs = self.driver_wordline_outputs[port]
|
||||
@@ -239,7 +253,12 @@ class local_bitcell_array(bitcell_base_array.bitcell_base_array):
|
||||
out_loc = out_pin.lc()
|
||||
mid_loc = vector(self.wl_insts[port].lx() - 1.5 * self.m3_pitch, out_loc.y)
|
||||
in_loc = in_pin.rc()
|
||||
self.add_path(out_pin.layer, [out_loc, mid_loc, in_loc])
|
||||
|
||||
self.add_path(out_pin.layer, [out_loc, mid_loc])
|
||||
self.add_via_stack_center(from_layer=out_pin.layer,
|
||||
to_layer=in_pin.layer,
|
||||
offset=mid_loc)
|
||||
self.add_path(in_pin.layer, [mid_loc, in_loc])
|
||||
|
||||
def get_main_array_top(self):
|
||||
return self.bitcell_array_inst.by() + self.bitcell_array.get_main_array_top()
|
||||
|
||||
Reference in New Issue
Block a user