mirror of https://github.com/VLSIDA/OpenRAM.git
Altering control logic for read ports and write ports, by including only read or write specific circuitry. Altering replica bitline layout to support multiport
This commit is contained in:
parent
934959952b
commit
f1560375fc
|
|
@ -18,14 +18,18 @@ class control_logic(design.design):
|
||||||
Dynamically generated Control logic for the total SRAM circuit.
|
Dynamically generated Control logic for the total SRAM circuit.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, num_rows):
|
def __init__(self, num_rows, port="rw"):
|
||||||
""" Constructor """
|
""" Constructor """
|
||||||
design.design.__init__(self, "control_logic")
|
design.design.__init__(self, "control_logic")
|
||||||
debug.info(1, "Creating {}".format(self.name))
|
debug.info(1, "Creating {}".format(self.name))
|
||||||
|
|
||||||
self.num_rows = num_rows
|
self.num_rows = num_rows
|
||||||
self.total_write = OPTS.num_rw_ports + OPTS.num_w_ports
|
self.port = port
|
||||||
self.total_read = OPTS.num_rw_ports + OPTS.num_r_ports
|
|
||||||
|
if self.port == "r":
|
||||||
|
self.num_control_signals = 1
|
||||||
|
else:
|
||||||
|
self.num_control_signals = 2
|
||||||
|
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
if not OPTS.netlist_only:
|
if not OPTS.netlist_only:
|
||||||
|
|
@ -43,7 +47,7 @@ class control_logic(design.design):
|
||||||
self.place_modules()
|
self.place_modules()
|
||||||
self.route_all()
|
self.route_all()
|
||||||
|
|
||||||
self.add_lvs_correspondence_points()
|
#self.add_lvs_correspondence_points()
|
||||||
|
|
||||||
self.DRC_LVS()
|
self.DRC_LVS()
|
||||||
|
|
||||||
|
|
@ -63,7 +67,7 @@ class control_logic(design.design):
|
||||||
dff = dff_inv()
|
dff = dff_inv()
|
||||||
dff_height = dff.height
|
dff_height = dff.height
|
||||||
|
|
||||||
self.ctrl_dff_array = dff_inv_array(rows=1+self.total_write,columns=1)
|
self.ctrl_dff_array = dff_inv_array(rows=self.num_control_signals,columns=1)
|
||||||
self.add_mod(self.ctrl_dff_array)
|
self.add_mod(self.ctrl_dff_array)
|
||||||
|
|
||||||
self.nand2 = pnand2(height=dff_height)
|
self.nand2 = pnand2(height=dff_height)
|
||||||
|
|
@ -83,39 +87,47 @@ class control_logic(design.design):
|
||||||
self.inv8 = pinv(size=16, height=dff_height)
|
self.inv8 = pinv(size=16, height=dff_height)
|
||||||
self.add_mod(self.inv8)
|
self.add_mod(self.inv8)
|
||||||
|
|
||||||
from importlib import reload
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
c = reload(__import__(OPTS.replica_bitline))
|
from importlib import reload
|
||||||
replica_bitline = getattr(c, OPTS.replica_bitline)
|
c = reload(__import__(OPTS.replica_bitline))
|
||||||
# FIXME: These should be tuned according to the size!
|
replica_bitline = getattr(c, OPTS.replica_bitline)
|
||||||
delay_stages = 4 # Must be non-inverting
|
# FIXME: These should be tuned according to the size!
|
||||||
delay_fanout = 3 # This can be anything >=2
|
delay_stages = 4 # Must be non-inverting
|
||||||
bitcell_loads = int(math.ceil(self.num_rows / 5.0))
|
delay_fanout = 3 # This can be anything >=2
|
||||||
self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads)
|
bitcell_loads = int(math.ceil(self.num_rows / 5.0))
|
||||||
self.add_mod(self.replica_bitline)
|
self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads)
|
||||||
|
self.add_mod(self.replica_bitline)
|
||||||
|
|
||||||
|
|
||||||
def setup_signal_busses(self):
|
def setup_signal_busses(self):
|
||||||
""" Setup bus names, determine the size of the busses etc """
|
""" Setup bus names, determine the size of the busses etc """
|
||||||
|
|
||||||
# List of input control signals
|
# List of input control signals
|
||||||
self.input_list =["csb"]
|
if self.port == "r":
|
||||||
for port in range(self.total_write):
|
self.input_list =["csb"]
|
||||||
self.input_list.append("web{}".format(port))
|
else:
|
||||||
|
self.input_list =["csb", "web"]
|
||||||
|
|
||||||
self.dff_output_list =["cs_bar", "cs"]
|
if self.port == "r":
|
||||||
for port in range(self.total_write):
|
self.dff_output_list =["cs_bar", "cs"]
|
||||||
self.dff_output_list.append("we_bar{}".format(port))
|
else:
|
||||||
self.dff_output_list.append("we{}".format(port))
|
self.dff_output_list =["cs_bar", "cs", "we_bar", "we"]
|
||||||
|
|
||||||
# list of output control signals (for making a vertical bus)
|
# list of output control signals (for making a vertical bus)
|
||||||
self.internal_bus_list = ["clk_buf", "clk_buf_bar", "we", "cs"]
|
if self.port == "r":
|
||||||
|
self.internal_bus_list = ["clk_buf", "clk_buf_bar", "cs"]
|
||||||
|
else:
|
||||||
|
self.internal_bus_list = ["clk_buf", "clk_buf_bar", "we", "cs"]
|
||||||
# leave space for the bus plus one extra space
|
# leave space for the bus plus one extra space
|
||||||
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
|
self.internal_bus_width = (len(self.internal_bus_list)+1)*self.m2_pitch
|
||||||
|
|
||||||
# Outputs to the bank
|
# Outputs to the bank
|
||||||
self.output_list = ["s_en"]
|
if self.port == "r":
|
||||||
for port in range(self.total_write):
|
self.output_list = ["s_en"]
|
||||||
self.output_list.append("w_en{}".format(port))
|
elif self.port == "w":
|
||||||
|
self.output_list = ["w_en"]
|
||||||
|
else:
|
||||||
|
self.output_list = ["s_en", "w_en"]
|
||||||
self.output_list.append("clk_buf_bar")
|
self.output_list.append("clk_buf_bar")
|
||||||
self.output_list.append("clk_buf")
|
self.output_list.append("clk_buf")
|
||||||
|
|
||||||
|
|
@ -134,13 +146,12 @@ class control_logic(design.design):
|
||||||
""" Create all the modules """
|
""" Create all the modules """
|
||||||
self.create_dffs()
|
self.create_dffs()
|
||||||
self.create_clk_row()
|
self.create_clk_row()
|
||||||
self.create_we_row()
|
if (self.port == "rw") or (self.port == "w"):
|
||||||
# self.create_trien_row()
|
self.create_we_row()
|
||||||
# self.create_trien_bar_row()
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
self.create_rbl_in_row()
|
self.create_rbl_in_row()
|
||||||
self.create_sen_row()
|
self.create_sen_row()
|
||||||
self.create_rbl()
|
self.create_rbl()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_modules(self):
|
def place_modules(self):
|
||||||
|
|
@ -149,38 +160,44 @@ class control_logic(design.design):
|
||||||
# and add the vdd/gnd pins
|
# and add the vdd/gnd pins
|
||||||
self.row_end_inst = []
|
self.row_end_inst = []
|
||||||
|
|
||||||
|
|
||||||
# Add the control flops on the left of the bus
|
# Add the control flops on the left of the bus
|
||||||
self.place_dffs()
|
self.place_dffs()
|
||||||
|
|
||||||
|
row = 0
|
||||||
# Add the logic on the right of the bus
|
# Add the logic on the right of the bus
|
||||||
self.place_clk_row(row=0) # clk is a double-high cell
|
self.place_clk_row(row=row) # clk is a double-high cell
|
||||||
self.place_we_row(row=2)
|
row += 2
|
||||||
# self.place_trien_row(row=3)
|
if (self.port == "rw") or (self.port == "w"):
|
||||||
# self.place_trien_bar_row(row=4)
|
self.place_we_row(row=row)
|
||||||
self.place_rbl_in_row(row=3)
|
pre_height = self.w_en_inst.uy()
|
||||||
self.place_sen_row(row=4)
|
control_center_y = self.w_en_inst.by()
|
||||||
self.place_rbl(row=5)
|
row += 1
|
||||||
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
|
self.place_rbl_in_row(row=row)
|
||||||
|
self.place_sen_row(row=row+1)
|
||||||
|
self.place_rbl(row=row+2)
|
||||||
|
pre_height = self.rbl_inst.uy()
|
||||||
|
control_center_y = self.rbl_inst.by()
|
||||||
|
|
||||||
|
# This offset is used for placement of the control logic in the SRAM level.
|
||||||
# This offset is used for placement of the control logic in
|
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), control_center_y)
|
||||||
# the SRAM level.
|
|
||||||
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), self.rbl_inst.by())
|
|
||||||
|
|
||||||
# Extra pitch on top and right
|
# Extra pitch on top and right
|
||||||
self.height = self.rbl_inst.uy() + self.m3_pitch
|
self.height = pre_height + self.m3_pitch
|
||||||
# Max of modules or logic rows
|
# Max of modules or logic rows
|
||||||
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
|
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
|
||||||
|
else:
|
||||||
|
self.width = max([inst.rx() for inst in self.row_end_inst]) + self.m2_pitch
|
||||||
|
|
||||||
def route_all(self):
|
def route_all(self):
|
||||||
""" Routing between modules """
|
""" Routing between modules """
|
||||||
self.route_dffs()
|
self.route_dffs()
|
||||||
#self.route_trien()
|
if (self.port == "rw") or (self.port == "w"):
|
||||||
#self.route_trien_bar()
|
self.route_wen()
|
||||||
self.route_rbl_in()
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
self.route_wen()
|
self.route_rbl_in()
|
||||||
self.route_sen()
|
self.route_sen()
|
||||||
self.route_clk()
|
self.route_clk()
|
||||||
self.route_supply()
|
self.route_supply()
|
||||||
|
|
||||||
|
|
@ -217,7 +234,7 @@ class control_logic(design.design):
|
||||||
|
|
||||||
|
|
||||||
def create_rbl_in_row(self):
|
def create_rbl_in_row(self):
|
||||||
self.rbl_in_bar_inst=self.add_inst(name="nand3_rbl_in_bar",
|
self.rbl_in_bar_inst=self.add_inst(name="nand2_rbl_in_bar",
|
||||||
mod=self.nand2)
|
mod=self.nand2)
|
||||||
self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"])
|
self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"])
|
||||||
|
|
||||||
|
|
@ -277,7 +294,11 @@ class control_logic(design.design):
|
||||||
def route_dffs(self):
|
def route_dffs(self):
|
||||||
""" Route the input inverters """
|
""" Route the input inverters """
|
||||||
|
|
||||||
dff_out_map = zip(["dout_bar[{}]".format(i) for i in range(3)], ["cs", "we"])
|
if self.port == "r":
|
||||||
|
control_inputs = ["cs"]
|
||||||
|
else:
|
||||||
|
control_inputs = ["cs", "we"]
|
||||||
|
dff_out_map = zip(["dout_bar[{}]".format(i) for i in range(2*self.num_control_signals - 1)], control_inputs)
|
||||||
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets)
|
self.connect_vertical_bus(dff_out_map, self.ctrl_dff_inst, self.rail_offsets)
|
||||||
|
|
||||||
# Connect the clock rail to the other clock rail
|
# Connect the clock rail to the other clock rail
|
||||||
|
|
@ -290,7 +311,8 @@ class control_logic(design.design):
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst, "din[0]", "csb")
|
self.copy_layout_pin(self.ctrl_dff_inst, "din[0]", "csb")
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst, "din[1]", "web0")
|
if (self.port == "rw") or (self.port == "w"):
|
||||||
|
self.copy_layout_pin(self.ctrl_dff_inst, "din[1]", "web")
|
||||||
|
|
||||||
|
|
||||||
def create_dffs(self):
|
def create_dffs(self):
|
||||||
|
|
@ -317,31 +339,23 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def create_we_row(self):
|
def create_we_row(self):
|
||||||
# input: WE, CS output: w_en_bar
|
# input: WE, CS output: w_en_bar
|
||||||
self.w_en_bar_inst = []
|
self.w_en_bar_inst = self.add_inst(name="nand3_w_en_bar",
|
||||||
for port in range(self.total_write):
|
mod=self.nand3)
|
||||||
self.w_en_bar_inst.append(self.add_inst(name="nand3_w_en_bar{}".format(port),
|
self.connect_inst(["clk_buf_bar", "cs", "we", "w_en_bar", "vdd", "gnd"])
|
||||||
mod=self.nand3))
|
|
||||||
self.connect_inst(["clk_buf_bar", "cs", "we{}".format(port), "w_en_bar{}".format(port), "vdd", "gnd"])
|
|
||||||
|
|
||||||
# input: w_en_bar, output: pre_w_en
|
# input: w_en_bar, output: pre_w_en
|
||||||
self.pre_w_en_inst = []
|
self.pre_w_en_inst = self.add_inst(name="inv_pre_w_en",
|
||||||
for port in range(self.total_write):
|
mod=self.inv1)
|
||||||
self.pre_w_en_inst.append(self.add_inst(name="inv_pre_w_en{}".format(port),
|
self.connect_inst(["w_en_bar", "pre_w_en", "vdd", "gnd"])
|
||||||
mod=self.inv1))
|
|
||||||
self.connect_inst(["w_en_bar{}".format(port), "pre_w_en{}".format(port), "vdd", "gnd"])
|
|
||||||
|
|
||||||
# BUFFER INVERTERS FOR W_EN
|
# BUFFER INVERTERS FOR W_EN
|
||||||
self.pre_w_en_bar_inst = []
|
self.pre_w_en_bar_inst = self.add_inst(name="inv_pre_w_en_bar",
|
||||||
for port in range(self.total_write):
|
mod=self.inv2)
|
||||||
self.pre_w_en_bar_inst.append(self.add_inst(name="inv_pre_w_en_bar{}".format(port),
|
self.connect_inst(["pre_w_en", "pre_w_en_bar", "vdd", "gnd"])
|
||||||
mod=self.inv2))
|
|
||||||
self.connect_inst(["pre_w_en{}".format(port), "pre_w_en_bar{}".format(port), "vdd", "gnd"])
|
|
||||||
|
|
||||||
self.w_en_inst = []
|
self.w_en_inst = self.add_inst(name="inv_w_en2",
|
||||||
for port in range(self.total_write):
|
mod=self.inv8)
|
||||||
self.w_en_inst.append(self.add_inst(name="inv_w_en2_{}".format(port),
|
self.connect_inst(["pre_w_en_bar", "w_en", "vdd", "gnd"])
|
||||||
mod=self.inv8))
|
|
||||||
self.connect_inst(["pre_w_en_bar{}".format(port), "w_en{}".format(port), "vdd", "gnd"])
|
|
||||||
|
|
||||||
|
|
||||||
def place_we_row(self,row):
|
def place_we_row(self,row):
|
||||||
|
|
@ -349,26 +363,26 @@ class control_logic(design.design):
|
||||||
(y_off,mirror)=self.get_offset(row)
|
(y_off,mirror)=self.get_offset(row)
|
||||||
|
|
||||||
w_en_bar_offset = vector(x_off, y_off)
|
w_en_bar_offset = vector(x_off, y_off)
|
||||||
self.w_en_bar_inst[0].place(offset=w_en_bar_offset,
|
self.w_en_bar_inst.place(offset=w_en_bar_offset,
|
||||||
mirror=mirror)
|
mirror=mirror)
|
||||||
x_off += self.nand3.width
|
x_off += self.nand3.width
|
||||||
|
|
||||||
pre_w_en_offset = vector(x_off, y_off)
|
pre_w_en_offset = vector(x_off, y_off)
|
||||||
self.pre_w_en_inst[0].place(offset=pre_w_en_offset,
|
self.pre_w_en_inst.place(offset=pre_w_en_offset,
|
||||||
mirror=mirror)
|
mirror=mirror)
|
||||||
x_off += self.inv1.width
|
x_off += self.inv1.width
|
||||||
|
|
||||||
pre_w_en_bar_offset = vector(x_off, y_off)
|
pre_w_en_bar_offset = vector(x_off, y_off)
|
||||||
self.pre_w_en_bar_inst[0].place(offset=pre_w_en_bar_offset,
|
self.pre_w_en_bar_inst.place(offset=pre_w_en_bar_offset,
|
||||||
mirror=mirror)
|
mirror=mirror)
|
||||||
x_off += self.inv2.width
|
x_off += self.inv2.width
|
||||||
|
|
||||||
w_en_offset = vector(x_off, y_off)
|
w_en_offset = vector(x_off, y_off)
|
||||||
self.w_en_inst[0].place(offset=w_en_offset,
|
self.w_en_inst.place(offset=w_en_offset,
|
||||||
mirror=mirror)
|
mirror=mirror)
|
||||||
x_off += self.inv8.width
|
x_off += self.inv8.width
|
||||||
|
|
||||||
self.row_end_inst.append(self.w_en_inst[0])
|
self.row_end_inst.append(self.w_en_inst)
|
||||||
|
|
||||||
|
|
||||||
def route_rbl_in(self):
|
def route_rbl_in(self):
|
||||||
|
|
@ -446,19 +460,19 @@ class control_logic(design.design):
|
||||||
|
|
||||||
def route_wen(self):
|
def route_wen(self):
|
||||||
wen_map = zip(["A", "B", "C"], ["clk_buf_bar", "cs", "we"])
|
wen_map = zip(["A", "B", "C"], ["clk_buf_bar", "cs", "we"])
|
||||||
self.connect_vertical_bus(wen_map, self.w_en_bar_inst[0], self.rail_offsets)
|
self.connect_vertical_bus(wen_map, self.w_en_bar_inst, self.rail_offsets)
|
||||||
|
|
||||||
# Connect the NAND3 output to the inverter
|
# Connect the NAND3 output to the inverter
|
||||||
# The pins are assumed to extend all the way to the cell edge
|
# The pins are assumed to extend all the way to the cell edge
|
||||||
w_en_bar_pos = self.w_en_bar_inst[0].get_pin("Z").center()
|
w_en_bar_pos = self.w_en_bar_inst.get_pin("Z").center()
|
||||||
inv_in_pos = self.pre_w_en_inst[0].get_pin("A").center()
|
inv_in_pos = self.pre_w_en_inst.get_pin("A").center()
|
||||||
mid1 = vector(inv_in_pos.x,w_en_bar_pos.y)
|
mid1 = vector(inv_in_pos.x,w_en_bar_pos.y)
|
||||||
self.add_path("metal1",[w_en_bar_pos,mid1,inv_in_pos])
|
self.add_path("metal1",[w_en_bar_pos,mid1,inv_in_pos])
|
||||||
|
|
||||||
self.add_path("metal1",[self.pre_w_en_inst[0].get_pin("Z").center(), self.pre_w_en_bar_inst[0].get_pin("A").center()])
|
self.add_path("metal1",[self.pre_w_en_inst.get_pin("Z").center(), self.pre_w_en_bar_inst.get_pin("A").center()])
|
||||||
self.add_path("metal1",[self.pre_w_en_bar_inst[0].get_pin("Z").center(), self.w_en_inst[0].get_pin("A").center()])
|
self.add_path("metal1",[self.pre_w_en_bar_inst.get_pin("Z").center(), self.w_en_inst.get_pin("A").center()])
|
||||||
|
|
||||||
self.connect_output(self.w_en_inst[0], "Z", "w_en0")
|
self.connect_output(self.w_en_inst, "Z", "w_en")
|
||||||
|
|
||||||
def route_sen(self):
|
def route_sen(self):
|
||||||
rbl_out_pos = self.rbl_inst.get_pin("out").bc()
|
rbl_out_pos = self.rbl_inst.get_pin("out").bc()
|
||||||
|
|
@ -521,9 +535,9 @@ class control_logic(design.design):
|
||||||
self.add_power_pin("gnd", pin_loc)
|
self.add_power_pin("gnd", pin_loc)
|
||||||
self.add_path("metal1", [row_loc, pin_loc])
|
self.add_path("metal1", [row_loc, pin_loc])
|
||||||
|
|
||||||
|
if (self.port == "rw") or (self.port == "r"):
|
||||||
self.copy_layout_pin(self.rbl_inst,"gnd")
|
self.copy_layout_pin(self.rbl_inst,"gnd")
|
||||||
self.copy_layout_pin(self.rbl_inst,"vdd")
|
self.copy_layout_pin(self.rbl_inst,"vdd")
|
||||||
|
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst,"gnd")
|
self.copy_layout_pin(self.ctrl_dff_inst,"gnd")
|
||||||
self.copy_layout_pin(self.ctrl_dff_inst,"vdd")
|
self.copy_layout_pin(self.ctrl_dff_inst,"vdd")
|
||||||
|
|
|
||||||
|
|
@ -107,7 +107,7 @@ class replica_bitline(design.design):
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
""" Create all of the module instances in the logical netlist """
|
""" Create all of the module instances in the logical netlist """
|
||||||
|
|
||||||
total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
self.total_ports = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
||||||
|
|
||||||
# This is the threshold detect inverter on the output of the RBL
|
# This is the threshold detect inverter on the output of the RBL
|
||||||
self.rbl_inv_inst=self.add_inst(name="rbl_inv",
|
self.rbl_inv_inst=self.add_inst(name="rbl_inv",
|
||||||
|
|
@ -127,10 +127,10 @@ class replica_bitline(design.design):
|
||||||
self.rbc_inst=self.add_inst(name="bitcell",
|
self.rbc_inst=self.add_inst(name="bitcell",
|
||||||
mod=self.replica_bitcell)
|
mod=self.replica_bitcell)
|
||||||
temp = []
|
temp = []
|
||||||
for port in range(total_ports):
|
for port in range(self.total_ports):
|
||||||
temp.append("bl{}[0]".format(port))
|
temp.append("bl{}[0]".format(port))
|
||||||
temp.append("br{}[0]".format(port))
|
temp.append("br{}[0]".format(port))
|
||||||
for port in range(total_ports):
|
for port in range(self.total_ports):
|
||||||
temp.append("delayed_en")
|
temp.append("delayed_en")
|
||||||
temp.append("vdd")
|
temp.append("vdd")
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
|
|
@ -141,11 +141,11 @@ class replica_bitline(design.design):
|
||||||
mod=self.rbl)
|
mod=self.rbl)
|
||||||
|
|
||||||
temp = []
|
temp = []
|
||||||
for port in range(total_ports):
|
for port in range(self.total_ports):
|
||||||
temp.append("bl{}[0]".format(port))
|
temp.append("bl{}[0]".format(port))
|
||||||
temp.append("br{}[0]".format(port))
|
temp.append("br{}[0]".format(port))
|
||||||
for wl in range(self.bitcell_loads):
|
for wl in range(self.bitcell_loads):
|
||||||
for port in range(total_ports):
|
for port in range(self.total_ports):
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
temp.append("vdd")
|
temp.append("vdd")
|
||||||
temp.append("gnd")
|
temp.append("gnd")
|
||||||
|
|
@ -171,9 +171,6 @@ class replica_bitline(design.design):
|
||||||
self.rbl_inst.place(self.rbl_offset)
|
self.rbl_inst.place(self.rbl_offset)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route(self):
|
def route(self):
|
||||||
""" Connect all the signals together """
|
""" Connect all the signals together """
|
||||||
self.route_supplies()
|
self.route_supplies()
|
||||||
|
|
@ -202,6 +199,12 @@ class replica_bitline(design.design):
|
||||||
self.add_path("metal1", [pin_right, pin_extension1, pin_extension2])
|
self.add_path("metal1", [pin_right, pin_extension1, pin_extension2])
|
||||||
self.add_power_pin("gnd", pin_extension2)
|
self.add_power_pin("gnd", pin_extension2)
|
||||||
|
|
||||||
|
# for multiport, need to short wordlines to each other so they all connect to gnd
|
||||||
|
wl_last = self.wl_list[self.total_ports-1]+"[{}]".format(row)
|
||||||
|
pin_last = self.rbl_inst.get_pin(wl_last)
|
||||||
|
|
||||||
|
correct = vector(0.5*drc["minwidth_metal1"], 0)
|
||||||
|
self.add_path("metal1", [pin.rc()-correct, pin_last.rc()-correct])
|
||||||
|
|
||||||
def route_supplies(self):
|
def route_supplies(self):
|
||||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||||
|
|
@ -266,6 +269,15 @@ class replica_bitline(design.design):
|
||||||
#wl_mid2 = vector(xmid_point,wl_offset.y)
|
#wl_mid2 = vector(xmid_point,wl_offset.y)
|
||||||
self.add_path("metal1", [wl_offset, wl_mid1, wl_mid2, contact_offset])
|
self.add_path("metal1", [wl_offset, wl_mid1, wl_mid2, contact_offset])
|
||||||
|
|
||||||
|
# 4. Short wodlines if multiport
|
||||||
|
wl = self.wl_list[0]
|
||||||
|
wl_last = self.wl_list[self.total_ports-1]
|
||||||
|
pin = self.rbc_inst.get_pin(wl)
|
||||||
|
pin_last = self.rbc_inst.get_pin(wl_last)
|
||||||
|
|
||||||
|
correct = vector(0.5*drc["minwidth_metal1"], 0)
|
||||||
|
self.add_path("metal1", [pin.lc()+correct, pin_last.lc()+correct])
|
||||||
|
|
||||||
# DRAIN ROUTE
|
# DRAIN ROUTE
|
||||||
# Route the drain to the vdd rail
|
# Route the drain to the vdd rail
|
||||||
drain_offset = self.tx_inst.get_pin("D").center()
|
drain_offset = self.tx_inst.get_pin("D").center()
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,23 @@ class replica_bitline_test(openram_test):
|
||||||
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
|
stages=4
|
||||||
|
fanout=4
|
||||||
|
rows=13
|
||||||
|
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||||
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
|
stages=8
|
||||||
|
rows=100
|
||||||
|
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
|
||||||
|
a = replica_bitline.replica_bitline(stages,fanout,rows)
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
||||||
# instantiate a copy of the class to actually run the test
|
# instantiate a copy of the class to actually run the test
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,6 @@ class control_logic_test(openram_test):
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
# check control logic for multi-port
|
# check control logic for multi-port
|
||||||
# only layout for 1RW is supported at the moment
|
|
||||||
OPTS.bitcell = "pbitcell"
|
OPTS.bitcell = "pbitcell"
|
||||||
OPTS.replica_bitcell = "replica_pbitcell"
|
OPTS.replica_bitcell = "replica_pbitcell"
|
||||||
OPTS.num_rw_ports = 1
|
OPTS.num_rw_ports = 1
|
||||||
|
|
@ -35,6 +34,19 @@ class control_logic_test(openram_test):
|
||||||
a = control_logic.control_logic(num_rows=128)
|
a = control_logic.control_logic(num_rows=128)
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
# Check write-only and read-only control logic
|
||||||
|
OPTS.num_rw_ports = 1
|
||||||
|
OPTS.num_w_ports = 1
|
||||||
|
OPTS.num_r_ports = 1
|
||||||
|
|
||||||
|
debug.info(1, "Testing sample for control_logic for multiport, only write control logic")
|
||||||
|
a = control_logic.control_logic(num_rows=128, port="w")
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
|
debug.info(1, "Testing sample for control_logic for multiport, only read control logic")
|
||||||
|
a = control_logic.control_logic(num_rows=128, port="r")
|
||||||
|
self.local_check(a)
|
||||||
|
|
||||||
globals.end_openram()
|
globals.end_openram()
|
||||||
|
|
||||||
# instantiate a copdsay of the class to actually run the test
|
# instantiate a copdsay of the class to actually run the test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue