Merge branch 'dev' into laptop_checkpoint

This commit is contained in:
Jesse Cirimelli-Low
2021-04-23 22:50:23 -07:00
70 changed files with 1097 additions and 490 deletions
+10 -18
View File
@@ -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):
"""
+5 -1
View File
@@ -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."""
+5 -7
View File
@@ -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 -1
View File
@@ -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())
+55 -39
View File
@@ -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:
+34 -15
View File
@@ -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()