mirror of https://github.com/VLSIDA/OpenRAM.git
remove references to bank_sel
This commit is contained in:
parent
242d90f543
commit
1a23d156c0
|
|
@ -1,313 +0,0 @@
|
||||||
# See LICENSE for licensing information.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
|
||||||
# All rights reserved.
|
|
||||||
#
|
|
||||||
from tech import drc
|
|
||||||
from base import design
|
|
||||||
from base import vector
|
|
||||||
from pgates import pinv
|
|
||||||
from pgates import pnand2
|
|
||||||
from pgates import pnor2
|
|
||||||
from sram_factory import factory
|
|
||||||
from globals import OPTS
|
|
||||||
|
|
||||||
class bank_select(design):
|
|
||||||
"""Create a bank select signal that is combined with an array of
|
|
||||||
NOR+INV gates to gate the control signals in case of multiple
|
|
||||||
banks are created in upper level SRAM module
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, name="bank_select", port="rw"):
|
|
||||||
super().__init__(name)
|
|
||||||
|
|
||||||
self.port = port
|
|
||||||
|
|
||||||
self.create_netlist()
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
self.create_layout()
|
|
||||||
|
|
||||||
def create_netlist(self):
|
|
||||||
self.add_pins()
|
|
||||||
self.add_modules()
|
|
||||||
self.create_instances()
|
|
||||||
|
|
||||||
def create_layout(self):
|
|
||||||
self.calculate_module_offsets()
|
|
||||||
self.place_instances()
|
|
||||||
self.route_instances()
|
|
||||||
|
|
||||||
self.height = max([x.uy() for x in self.inv_inst]) + self.m1_width
|
|
||||||
self.width = max([x.rx() for x in self.inv_inst])
|
|
||||||
|
|
||||||
self.add_boundary()
|
|
||||||
self.DRC_LVS()
|
|
||||||
|
|
||||||
def add_pins(self):
|
|
||||||
|
|
||||||
# Number of control lines in the bus
|
|
||||||
if self.port == "rw":
|
|
||||||
self.num_control_lines = 4
|
|
||||||
else:
|
|
||||||
self.num_control_lines = 3
|
|
||||||
# The order of the control signals on the control bus:
|
|
||||||
# FIXME: Update for multiport (these names are not right)
|
|
||||||
self.input_control_signals = ["clk_buf", "clk_buf_bar"]
|
|
||||||
if (self.port == "rw") or (self.port == "w"):
|
|
||||||
self.input_control_signals.append("w_en")
|
|
||||||
if (self.port == "rw") or (self.port == "r"):
|
|
||||||
self.input_control_signals.append("s_en")
|
|
||||||
# These will be outputs of the gaters if this is multibank
|
|
||||||
self.control_signals = ["gated_" + str for str in self.input_control_signals]
|
|
||||||
|
|
||||||
self.add_pin_list(self.input_control_signals, "INPUT")
|
|
||||||
self.add_pin("bank_sel")
|
|
||||||
self.add_pin_list(self.control_signals, "OUTPUT")
|
|
||||||
self.add_pin("vdd", "POWER")
|
|
||||||
self.add_pin("gnd", "GROUND")
|
|
||||||
|
|
||||||
def add_modules(self):
|
|
||||||
""" Create modules for later instantiation """
|
|
||||||
self.dff = factory.create(module_type="dff")
|
|
||||||
height = self.dff.height + drc("poly_to_active")
|
|
||||||
|
|
||||||
# 1x Inverter
|
|
||||||
self.inv_sel = factory.create(module_type="pinv", height=height)
|
|
||||||
|
|
||||||
# 4x Inverter
|
|
||||||
self.inv4x = factory.create(module_type="pinv", height=height, size=4)
|
|
||||||
|
|
||||||
self.nor2 = factory.create(module_type="pnor2", height=height)
|
|
||||||
|
|
||||||
self.inv4x_nor = factory.create(module_type="pinv", height=height, size=4)
|
|
||||||
|
|
||||||
self.nand2 = factory.create(module_type="pnand2", height=height)
|
|
||||||
|
|
||||||
def calculate_module_offsets(self):
|
|
||||||
|
|
||||||
self.xoffset_nand = self.inv4x.width + 3 * self.m2_pitch + drc("pwell_to_nwell")
|
|
||||||
self.xoffset_nor = self.inv4x.width + 3 * self.m2_pitch + drc("pwell_to_nwell")
|
|
||||||
self.xoffset_bank_sel_inv = 0
|
|
||||||
self.xoffset_inputs = 0
|
|
||||||
self.yoffset_maxpoint = self.num_control_lines * self.inv4x.height
|
|
||||||
|
|
||||||
def create_instances(self):
|
|
||||||
|
|
||||||
self.bank_sel_inv=self.add_inst(name="bank_sel_inv",
|
|
||||||
mod=self.inv_sel)
|
|
||||||
self.connect_inst(["bank_sel", "bank_sel_bar", "vdd", "gnd"])
|
|
||||||
|
|
||||||
self.logic_inst = []
|
|
||||||
self.inv_inst = []
|
|
||||||
for i in range(self.num_control_lines):
|
|
||||||
input_name = self.input_control_signals[i]
|
|
||||||
gated_name = self.control_signals[i]
|
|
||||||
name_nand = "nand_{}".format(input_name)
|
|
||||||
name_nor = "nor_{}".format(input_name)
|
|
||||||
name_inv = "inv_{}".format(input_name)
|
|
||||||
|
|
||||||
# These require OR (nor2+inv) gates since they are active low.
|
|
||||||
# (writes occur on clk low)
|
|
||||||
if input_name in ("clk_buf"):
|
|
||||||
|
|
||||||
self.logic_inst.append(self.add_inst(name=name_nor,
|
|
||||||
mod=self.nor2))
|
|
||||||
self.connect_inst([input_name,
|
|
||||||
"bank_sel_bar",
|
|
||||||
gated_name + "_temp_bar",
|
|
||||||
"vdd",
|
|
||||||
"gnd"])
|
|
||||||
|
|
||||||
# They all get inverters on the output
|
|
||||||
self.inv_inst.append(self.add_inst(name=name_inv,
|
|
||||||
mod=self.inv4x_nor))
|
|
||||||
self.connect_inst([gated_name + "_temp_bar",
|
|
||||||
gated_name,
|
|
||||||
"vdd",
|
|
||||||
"gnd"])
|
|
||||||
|
|
||||||
# the rest are AND (nand2+inv) gates
|
|
||||||
else:
|
|
||||||
self.logic_inst.append(self.add_inst(name=name_nand,
|
|
||||||
mod=self.nand2))
|
|
||||||
self.connect_inst([input_name,
|
|
||||||
"bank_sel",
|
|
||||||
gated_name + "_temp_bar",
|
|
||||||
"vdd",
|
|
||||||
"gnd"])
|
|
||||||
|
|
||||||
# They all get inverters on the output
|
|
||||||
self.inv_inst.append(self.add_inst(name=name_inv,
|
|
||||||
mod=self.inv4x))
|
|
||||||
self.connect_inst([gated_name + "_temp_bar",
|
|
||||||
gated_name,
|
|
||||||
"vdd",
|
|
||||||
"gnd"])
|
|
||||||
|
|
||||||
def place_instances(self):
|
|
||||||
|
|
||||||
# bank select inverter
|
|
||||||
self.bank_select_inv_position = vector(self.xoffset_bank_sel_inv, 0)
|
|
||||||
|
|
||||||
# bank select inverter (must be made unique if more than one OR)
|
|
||||||
self.bank_sel_inv.place(vector(self.xoffset_bank_sel_inv, 0))
|
|
||||||
|
|
||||||
for i in range(self.num_control_lines):
|
|
||||||
|
|
||||||
logic_inst = self.logic_inst[i]
|
|
||||||
inv_inst = self.inv_inst[i]
|
|
||||||
|
|
||||||
input_name = self.input_control_signals[i]
|
|
||||||
|
|
||||||
if i == 0:
|
|
||||||
y_offset = 0
|
|
||||||
else:
|
|
||||||
y_offset = self.inv4x_nor.height + self.inv4x.height * (i - 1)
|
|
||||||
|
|
||||||
if i % 2:
|
|
||||||
y_offset += self.inv4x.height
|
|
||||||
mirror = "MX"
|
|
||||||
else:
|
|
||||||
mirror = ""
|
|
||||||
|
|
||||||
# These require OR (nor2+inv) gates since they are active low.
|
|
||||||
# (writes occur on clk low)
|
|
||||||
if input_name in ("clk_buf"):
|
|
||||||
|
|
||||||
logic_inst.place(offset=[self.xoffset_nor, y_offset],
|
|
||||||
mirror=mirror)
|
|
||||||
|
|
||||||
# the rest are AND (nand2+inv) gates
|
|
||||||
else:
|
|
||||||
logic_inst.place(offset=[self.xoffset_nand, y_offset],
|
|
||||||
mirror=mirror)
|
|
||||||
|
|
||||||
# They all get inverters on the output
|
|
||||||
inv_inst.place(offset=[logic_inst.rx(), y_offset],
|
|
||||||
mirror=mirror)
|
|
||||||
|
|
||||||
def route_instances(self):
|
|
||||||
|
|
||||||
# bank_sel is vertical wire
|
|
||||||
bank_sel_inv_pin = self.bank_sel_inv.get_pin("A")
|
|
||||||
xoffset_bank_sel = bank_sel_inv_pin.lx()
|
|
||||||
bank_sel_line_pos = vector(xoffset_bank_sel, 0)
|
|
||||||
bank_sel_line_end = vector(xoffset_bank_sel, self.yoffset_maxpoint)
|
|
||||||
self.add_path("m2", [bank_sel_line_pos, bank_sel_line_end])
|
|
||||||
self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=bank_sel_inv_pin.center())
|
|
||||||
|
|
||||||
# Route the pin to the left edge as well
|
|
||||||
bank_sel_pin_pos=vector(0, 0)
|
|
||||||
bank_sel_pin_end=vector(bank_sel_line_pos.x, bank_sel_pin_pos.y)
|
|
||||||
self.add_layout_pin_segment_center(text="bank_sel",
|
|
||||||
layer="m3",
|
|
||||||
start=bank_sel_pin_pos,
|
|
||||||
end=bank_sel_pin_end)
|
|
||||||
self.add_via_center(layers=self.m2_stack,
|
|
||||||
offset=bank_sel_pin_end,
|
|
||||||
directions=("H", "H"))
|
|
||||||
|
|
||||||
# bank_sel_bar is vertical wire
|
|
||||||
bank_sel_bar_pin = self.bank_sel_inv.get_pin("Z")
|
|
||||||
xoffset_bank_sel_bar = bank_sel_bar_pin.rx()
|
|
||||||
self.add_label_pin(text="bank_sel_bar",
|
|
||||||
layer="m2",
|
|
||||||
offset=vector(xoffset_bank_sel_bar, 0),
|
|
||||||
height=self.inv4x.height)
|
|
||||||
self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=bank_sel_bar_pin.rc())
|
|
||||||
|
|
||||||
for i in range(self.num_control_lines):
|
|
||||||
|
|
||||||
logic_inst = self.logic_inst[i]
|
|
||||||
inv_inst = self.inv_inst[i]
|
|
||||||
|
|
||||||
input_name = self.input_control_signals[i]
|
|
||||||
gated_name = self.control_signals[i]
|
|
||||||
if input_name in ("clk_buf"):
|
|
||||||
xoffset_bank_signal = xoffset_bank_sel_bar
|
|
||||||
else:
|
|
||||||
xoffset_bank_signal = xoffset_bank_sel
|
|
||||||
|
|
||||||
# Connect the logic output to inverter input
|
|
||||||
out_pin = logic_inst.get_pin("Z")
|
|
||||||
out_pos = out_pin.center()
|
|
||||||
in_pin = inv_inst.get_pin("A")
|
|
||||||
in_pos = in_pin.center()
|
|
||||||
mid1_pos = vector(0.5 * (out_pos.x + in_pos.x), out_pos.y)
|
|
||||||
mid2_pos = vector(0.5 * (out_pos.x + in_pos.x), in_pos.y)
|
|
||||||
self.add_path("m1", [out_pos, mid1_pos, mid2_pos, in_pos])
|
|
||||||
|
|
||||||
# Connect the logic B input to bank_sel / bank_sel_bar
|
|
||||||
logic_pin = logic_inst.get_pin("B")
|
|
||||||
logic_pos = logic_pin.center()
|
|
||||||
input_pos = vector(xoffset_bank_signal, logic_pos.y)
|
|
||||||
self.add_path("m3", [logic_pos, input_pos])
|
|
||||||
self.add_via_center(self.m2_stack,
|
|
||||||
input_pos)
|
|
||||||
self.add_via_stack_center(from_layer=logic_pin.layer,
|
|
||||||
to_layer="m3",
|
|
||||||
offset=logic_pos)
|
|
||||||
|
|
||||||
# Connect the logic A input to the input pin
|
|
||||||
logic_pin = logic_inst.get_pin("A")
|
|
||||||
logic_pos = logic_pin.center()
|
|
||||||
input_pos = vector(0, logic_pos.y)
|
|
||||||
self.add_via_stack_center(from_layer=logic_pin.layer,
|
|
||||||
to_layer="m3",
|
|
||||||
offset=logic_pos)
|
|
||||||
self.add_layout_pin_segment_center(text=input_name,
|
|
||||||
layer="m3",
|
|
||||||
start=input_pos,
|
|
||||||
end=logic_pos)
|
|
||||||
|
|
||||||
# Add output pins
|
|
||||||
out_pin = inv_inst.get_pin("Z")
|
|
||||||
self.add_layout_pin(text=gated_name,
|
|
||||||
layer=out_pin.layer,
|
|
||||||
offset=out_pin.ll(),
|
|
||||||
width=inv_inst.rx() - out_pin.lx(),
|
|
||||||
height=out_pin.height())
|
|
||||||
|
|
||||||
# Find the x offsets for where the vias/pins should be placed
|
|
||||||
a_xoffset = self.logic_inst[0].lx()
|
|
||||||
b_xoffset = self.inv_inst[0].lx()
|
|
||||||
for num in range(self.num_control_lines):
|
|
||||||
# Route both supplies
|
|
||||||
for n in ["vdd", "gnd"]:
|
|
||||||
supply_pin = self.inv_inst[num].get_pin(n)
|
|
||||||
supply_offset = supply_pin.ll().scale(0, 1)
|
|
||||||
self.add_rect(layer="m1",
|
|
||||||
offset=supply_offset,
|
|
||||||
width=self.width)
|
|
||||||
|
|
||||||
# Add pins in two locations
|
|
||||||
for xoffset in [a_xoffset, b_xoffset]:
|
|
||||||
pin_pos = vector(xoffset, supply_pin.cy())
|
|
||||||
self.add_via_center(layers=self.m1_stack,
|
|
||||||
offset=pin_pos,
|
|
||||||
directions=("H", "H"))
|
|
||||||
self.add_via_center(layers=self.m2_stack,
|
|
||||||
offset=pin_pos,
|
|
||||||
directions=("H", "H"))
|
|
||||||
self.add_layout_pin_rect_center(text=n,
|
|
||||||
layer="m3",
|
|
||||||
offset=pin_pos)
|
|
||||||
|
|
||||||
# Add vdd/gnd supply rails
|
|
||||||
gnd_pin = self.inv_inst[num].get_pin("gnd")
|
|
||||||
left_gnd_pos = vector(0, gnd_pin.cy())
|
|
||||||
self.add_layout_pin_segment_center(text="gnd",
|
|
||||||
layer="m1",
|
|
||||||
start=left_gnd_pos,
|
|
||||||
end=gnd_pin.rc())
|
|
||||||
|
|
||||||
vdd_pin = self.inv_inst[num].get_pin("vdd")
|
|
||||||
left_vdd_pos = vector(0, vdd_pin.cy())
|
|
||||||
self.add_layout_pin_segment_center(text="vdd",
|
|
||||||
layer="m1",
|
|
||||||
start=left_vdd_pos,
|
|
||||||
end=vdd_pin.rc())
|
|
||||||
|
|
@ -426,13 +426,6 @@ class sram_1bank(design, verilog, lef):
|
||||||
names=self.addr_bus_names,
|
names=self.addr_bus_names,
|
||||||
length=self.addr_bus_height))
|
length=self.addr_bus_height))
|
||||||
|
|
||||||
self.bank_sel_bus_names = ["bank_sel{0}_{1}".format(port, i) for i in range(1)]#range(self.num_banks)]
|
|
||||||
self.vert_control_bus_positions.update(self.create_vertical_pin_bus(layer="m2",
|
|
||||||
pitch=self.m2_pitch,
|
|
||||||
offset=self.bank_sel_bus_offset,
|
|
||||||
names=self.bank_sel_bus_names,
|
|
||||||
length=self.vertical_bus_height))
|
|
||||||
|
|
||||||
# Horizontal data bus
|
# Horizontal data bus
|
||||||
self.data_bus_names = ["DATA{0}[{1}]".format(port, i) for i in range(self.word_size)]
|
self.data_bus_names = ["DATA{0}[{1}]".format(port, i) for i in range(self.word_size)]
|
||||||
self.data_bus_positions = self.create_horizontal_pin_bus(layer="m3",
|
self.data_bus_positions = self.create_horizontal_pin_bus(layer="m3",
|
||||||
|
|
@ -462,16 +455,6 @@ class sram_1bank(design, verilog, lef):
|
||||||
names=self.control_bus_names[port],
|
names=self.control_bus_names[port],
|
||||||
length=self.control_bus_width))
|
length=self.control_bus_width))
|
||||||
|
|
||||||
def add_multi_bank_modules(self):
|
|
||||||
""" Create the multibank address flops and bank decoder """
|
|
||||||
from dff_buf_array import dff_buf_array
|
|
||||||
self.msb_address = dff_buf_array(name="msb_address",
|
|
||||||
rows=1,
|
|
||||||
columns=self.num_banks / 2)
|
|
||||||
|
|
||||||
if self.num_banks>2:
|
|
||||||
self.msb_decoder = self.bank.decoder.pre2_4
|
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
self.bitcell = factory.create(module_type=OPTS.bitcell)
|
self.bitcell = factory.create(module_type=OPTS.bitcell)
|
||||||
self.dff = factory.create(module_type="dff")
|
self.dff = factory.create(module_type="dff")
|
||||||
|
|
@ -542,9 +525,6 @@ class sram_1bank(design, verilog, lef):
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
for bit in range(self.bank_addr_size):
|
for bit in range(self.bank_addr_size):
|
||||||
temp.append("a{0}_{1}".format(port, bit))
|
temp.append("a{0}_{1}".format(port, bit))
|
||||||
# if(self.num_banks > 1):
|
|
||||||
# for port in self.all_ports:
|
|
||||||
# temp.append("bank_sel{0}_{1}".format(port, bank_num))
|
|
||||||
for port in self.read_ports:
|
for port in self.read_ports:
|
||||||
temp.append("s_en{0}".format(port))
|
temp.append("s_en{0}".format(port))
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue