mirror of https://github.com/VLSIDA/OpenRAM.git
New control logic, netlist only working
This commit is contained in:
parent
275891084b
commit
d36f14b408
|
|
@ -82,7 +82,7 @@ class bank(design.design):
|
|||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT")
|
||||
for port in self.read_ports:
|
||||
for port in self.all_ports:
|
||||
self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT")
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
|
|
@ -128,14 +128,13 @@ class bank(design.design):
|
|||
def route_rbl(self,port):
|
||||
""" Route the rbl_bl and rbl_wl """
|
||||
|
||||
if self.port_data[port].has_rbl():
|
||||
bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
bl_pin = self.bitcell_array_inst.get_pin(bl_pin_name)
|
||||
self.add_layout_pin(text="rbl_bl{0}".format(port),
|
||||
layer=bl_pin.layer,
|
||||
offset=bl_pin.ll(),
|
||||
height=bl_pin.height(),
|
||||
width=bl_pin.width())
|
||||
bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
bl_pin = self.bitcell_array_inst.get_pin(bl_pin_name)
|
||||
self.add_layout_pin(text="rbl_bl{0}".format(port),
|
||||
layer=bl_pin.layer,
|
||||
offset=bl_pin.ll(),
|
||||
height=bl_pin.height(),
|
||||
width=bl_pin.width())
|
||||
|
||||
|
||||
|
||||
|
|
@ -202,10 +201,7 @@ class bank(design.design):
|
|||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# Below the bitcell array
|
||||
if self.port_data[port].has_rbl():
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0)
|
||||
else:
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left,0)
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,0)
|
||||
|
||||
# UPPER LEFT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
|
|
@ -364,36 +360,15 @@ class bank(design.design):
|
|||
self.add_mod(self.port_address)
|
||||
|
||||
|
||||
# The number of replica lines depends on the port configuration
|
||||
rbl_counts = [self.read_ports.count(p) for p in self.all_ports]
|
||||
self.num_rbl = sum(rbl_counts)
|
||||
|
||||
# The replica array indices always start at 0, so this will map them to
|
||||
# the correct SRAM port
|
||||
# (e.g. if port 0 is w, then port 1 will use RBL 0 in replica bitcell array
|
||||
# because write ports don't use an RBL)
|
||||
self.port_rbl_map = {}
|
||||
index = 0
|
||||
for (i,num) in enumerate(rbl_counts):
|
||||
if num>0:
|
||||
self.port_rbl_map[i]=index
|
||||
index += 1
|
||||
if len(rbl_counts)<2:
|
||||
rbl_counts.append(0)
|
||||
|
||||
|
||||
# Which bitcell port should be used in the RBL
|
||||
# For now (since only 2 ports), if port 0 is not a read port, skip it in the RBLs
|
||||
bitcell_ports=list(range(len(self.read_ports)))
|
||||
if 0 not in self.read_ports:
|
||||
bitcell_ports = [x+1 for x in bitcell_ports]
|
||||
self.port_rbl_map = self.all_ports
|
||||
self.num_rbl = len(self.all_ports)
|
||||
|
||||
self.bitcell_array = factory.create(module_type="replica_bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows,
|
||||
left_rbl=rbl_counts[0],
|
||||
right_rbl=rbl_counts[1],
|
||||
bitcell_ports=bitcell_ports)
|
||||
left_rbl=1,
|
||||
right_rbl=1 if len(self.all_ports)>1 else 0,
|
||||
bitcell_ports=self.all_ports)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
|
||||
|
|
@ -421,8 +396,7 @@ class bank(design.design):
|
|||
for wordline in self.wl_names:
|
||||
temp.append("{0}_{1}".format(wordline,row))
|
||||
for port in self.all_ports:
|
||||
if self.port_data[port].has_rbl():
|
||||
temp.append("wl_en{0}".format(port))
|
||||
temp.append("wl_en{0}".format(port))
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
|
@ -442,11 +416,10 @@ class bank(design.design):
|
|||
mod=self.port_data[port])
|
||||
|
||||
temp = []
|
||||
if self.port_data[port].has_rbl():
|
||||
rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port])
|
||||
temp.append(rbl_bl_name)
|
||||
temp.append(rbl_br_name)
|
||||
rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port])
|
||||
temp.append(rbl_bl_name)
|
||||
temp.append(rbl_br_name)
|
||||
for col in range(self.num_cols):
|
||||
temp.append("{0}_{1}".format(self.bl_names[port],col))
|
||||
temp.append("{0}_{1}".format(self.br_names[port],col))
|
||||
|
|
@ -710,11 +683,10 @@ class bank(design.design):
|
|||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name)
|
||||
|
||||
# Connect the replica bitlines
|
||||
if self.port_data[port].has_rbl():
|
||||
rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port])
|
||||
self.connect_bitline(inst1, inst2, rbl_bl_name, "rbl_bl")
|
||||
self.connect_bitline(inst1, inst2, rbl_br_name, "rbl_br")
|
||||
rbl_bl_name=self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
rbl_br_name=self.bitcell_array.get_rbl_br_name(self.port_rbl_map[port])
|
||||
self.connect_bitline(inst1, inst2, rbl_bl_name, "rbl_bl")
|
||||
self.connect_bitline(inst1, inst2, rbl_br_name, "rbl_br")
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -125,10 +125,10 @@ class control_logic(design.design):
|
|||
self.add_mod(self.wl_en_driver)
|
||||
|
||||
# w_en drives every write driver
|
||||
self.wen_and2 = factory.create(module_type="pand2",
|
||||
self.wen_and = factory.create(module_type="pand3",
|
||||
size=self.word_size+8,
|
||||
height=dff_height)
|
||||
self.add_mod(self.wen_and2)
|
||||
self.add_mod(self.wen_and)
|
||||
|
||||
# s_en drives every sense amp
|
||||
self.sen_and2 = factory.create(module_type="pand2",
|
||||
|
|
@ -147,11 +147,13 @@ class control_logic(design.design):
|
|||
# prepended 3 inverter stages to guarantee it is slower and odd polarity
|
||||
self.p_en_bar_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.num_cols,
|
||||
neg_polarity=True,
|
||||
height=dff_height)
|
||||
self.add_mod(self.p_en_bar_driver)
|
||||
|
||||
|
||||
self.nand2 = factory.create(module_type="pnand2",
|
||||
height=dff_height)
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
# if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
# from importlib import reload
|
||||
|
|
@ -330,12 +332,9 @@ class control_logic(design.design):
|
|||
if self.port_type == "rw":
|
||||
self.input_list = ["csb", "web"]
|
||||
self.rbl_list = ["rbl_bl"]
|
||||
elif self.port_type == "r":
|
||||
self.input_list = ["csb"]
|
||||
self.rbl_list = ["rbl_bl"]
|
||||
else:
|
||||
self.input_list = ["csb"]
|
||||
self.rbl_list = []
|
||||
self.rbl_list = ["rbl_bl"]
|
||||
|
||||
if self.port_type == "rw":
|
||||
self.dff_output_list = ["cs_bar", "cs", "we_bar", "we"]
|
||||
|
|
@ -385,7 +384,7 @@ class control_logic(design.design):
|
|||
self.create_wen_row()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.create_sen_row()
|
||||
self.create_delay()
|
||||
self.create_delay()
|
||||
self.create_pen_row()
|
||||
|
||||
|
||||
|
|
@ -422,9 +421,9 @@ class control_logic(design.design):
|
|||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.place_sen_row(row)
|
||||
row += 1
|
||||
self.place_delay(row)
|
||||
height = self.delay_inst.uy()
|
||||
control_center_y = self.delay_inst.by()
|
||||
self.place_delay(row)
|
||||
height = self.delay_inst.uy()
|
||||
control_center_y = self.delay_inst.by()
|
||||
|
||||
# This offset is used for placement of the control logic in the SRAM level.
|
||||
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), control_center_y)
|
||||
|
|
@ -446,6 +445,7 @@ class control_logic(design.design):
|
|||
self.route_wen()
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
self.route_sen()
|
||||
self.route_delay()
|
||||
self.route_pen()
|
||||
self.route_clk_buf()
|
||||
self.route_gated_clk_bar()
|
||||
|
|
@ -457,7 +457,7 @@ class control_logic(design.design):
|
|||
""" Create the replica bitline """
|
||||
self.delay_inst=self.add_inst(name="delay_chain",
|
||||
mod=self.delay_chain)
|
||||
self.connect_inst(["rbl_bl", "pre_s_en", "vdd", "gnd"])
|
||||
self.connect_inst(["rbl_bl", "rbl_bl_delay", "vdd", "gnd"])
|
||||
|
||||
def place_delay(self,row):
|
||||
""" Place the replica bitline """
|
||||
|
|
@ -468,6 +468,11 @@ class control_logic(design.design):
|
|||
offset = vector(self.delay_chain.width, y_off)
|
||||
self.delay_inst.place(offset, mirror="MY")
|
||||
|
||||
def route_delay(self):
|
||||
|
||||
# Input from RBL goes to the delay line for futher delay
|
||||
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
|
||||
|
||||
|
||||
def create_clk_buf_row(self):
|
||||
""" Create the multistage and gated clock buffer """
|
||||
|
|
@ -604,10 +609,14 @@ class control_logic(design.design):
|
|||
self.connect_output(self.wl_en_inst, "Z", "wl_en")
|
||||
|
||||
def create_pen_row(self):
|
||||
# input: gated_clk_bar, output: p_en_bar
|
||||
self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar",
|
||||
self.p_en_bar_inst=self.add_inst(name="nand_p_en_bar",
|
||||
mod=self.nand2)
|
||||
self.connect_inst(["gated_clk_buf", "rbl_bl_delay", "p_en_bar_unbuf", "vdd", "gnd"])
|
||||
|
||||
self.p_en_bar_inst=self.add_inst(name="buf_p_en_bar",
|
||||
mod=self.p_en_bar_driver)
|
||||
self.connect_inst(["gated_clk_buf", "p_en_bar", "vdd", "gnd"])
|
||||
self.connect_inst(["p_en_bar_unbuf", "p_en_bar", "vdd", "gnd"])
|
||||
|
||||
|
||||
|
||||
def place_pen_row(self,row):
|
||||
|
|
@ -633,7 +642,7 @@ class control_logic(design.design):
|
|||
# GATE FOR S_EN
|
||||
self.s_en_gate_inst = self.add_inst(name="buf_s_en_and",
|
||||
mod=self.sen_and2)
|
||||
self.connect_inst(["pre_s_en", input_name, "s_en", "vdd", "gnd"])
|
||||
self.connect_inst(["rbl_bl_delay", input_name, "s_en", "vdd", "gnd"])
|
||||
|
||||
|
||||
def place_sen_row(self,row):
|
||||
|
|
@ -667,12 +676,13 @@ class control_logic(design.design):
|
|||
|
||||
self.connect_output(self.s_en_gate_inst, "Z", "s_en")
|
||||
|
||||
# Input from RBL goes to the delay line for futher delay
|
||||
self.copy_layout_pin(self.delay_inst, "in", "rbl_bl")
|
||||
|
||||
|
||||
|
||||
def create_wen_row(self):
|
||||
|
||||
self.rbl_bl_delay_inv_inst = self.add_inst(name="rbl_bl_delay_inv",
|
||||
mod=self.inv)
|
||||
self.connect_inst(["rbl_bl_delay", "rbl_bl_delay_bar", "vdd", "gnd"])
|
||||
|
||||
# input: we (or cs) output: w_en
|
||||
if self.port_type == "rw":
|
||||
input_name = "we"
|
||||
|
|
@ -682,8 +692,8 @@ class control_logic(design.design):
|
|||
|
||||
# GATE THE W_EN
|
||||
self.w_en_gate_inst = self.add_inst(name="w_en_and",
|
||||
mod=self.wen_and2)
|
||||
self.connect_inst([input_name, "gated_clk_bar", "w_en", "vdd", "gnd"])
|
||||
mod=self.wen_and)
|
||||
self.connect_inst([input_name, "rbl_bl_delay_bar", "gated_clk_bar", "w_en", "vdd", "gnd"])
|
||||
|
||||
|
||||
def place_wen_row(self,row):
|
||||
|
|
|
|||
|
|
@ -82,9 +82,8 @@ class port_data(design.design):
|
|||
def add_pins(self):
|
||||
""" Adding pins for port address module"""
|
||||
|
||||
if self.has_rbl():
|
||||
self.add_pin("rbl_bl","INOUT")
|
||||
self.add_pin("rbl_br","INOUT")
|
||||
self.add_pin("rbl_bl","INOUT")
|
||||
self.add_pin("rbl_br","INOUT")
|
||||
for bit in range(self.num_cols):
|
||||
self.add_pin("{0}_{1}".format(self.bl_names[self.port], bit),"INOUT")
|
||||
self.add_pin("{0}_{1}".format(self.br_names[self.port], bit),"INOUT")
|
||||
|
|
@ -150,30 +149,18 @@ class port_data(design.design):
|
|||
|
||||
def add_modules(self):
|
||||
|
||||
if self.port in self.read_ports:
|
||||
# Extra column +1 is for RBL
|
||||
# Precharge will be shifted left if needed
|
||||
self.precharge_array = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols + 1,
|
||||
bitcell_bl=self.bl_names[self.port],
|
||||
bitcell_br=self.br_names[self.port])
|
||||
self.add_mod(self.precharge_array)
|
||||
# Extra column +1 is for RBL
|
||||
# Precharge will be shifted left if needed
|
||||
self.precharge_array = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols + 1,
|
||||
bitcell_bl=self.bl_names[self.port],
|
||||
bitcell_br=self.br_names[self.port])
|
||||
self.add_mod(self.precharge_array)
|
||||
|
||||
self.sense_amp_array = factory.create(module_type="sense_amp_array",
|
||||
word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.add_mod(self.sense_amp_array)
|
||||
else:
|
||||
# Precharge is needed when we have a column mux or for byte writes
|
||||
# to prevent corruption of half-selected cells, so just always add it
|
||||
# This is a little power inefficient for write ports without a column mux,
|
||||
# but it is simpler.
|
||||
self.precharge_array = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols,
|
||||
bitcell_bl=self.bl_names[self.port],
|
||||
bitcell_br=self.br_names[self.port])
|
||||
self.add_mod(self.precharge_array)
|
||||
self.sense_amp_array = None
|
||||
self.sense_amp_array = factory.create(module_type="sense_amp_array",
|
||||
word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.add_mod(self.sense_amp_array)
|
||||
|
||||
|
||||
if self.col_addr_size > 0:
|
||||
|
|
@ -238,14 +225,14 @@ class port_data(design.design):
|
|||
|
||||
temp = []
|
||||
# Use left BLs for RBL
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
for bit in range(self.num_cols):
|
||||
temp.append(self.bl_names[self.port]+"_{0}".format(bit))
|
||||
temp.append(self.br_names[self.port]+"_{0}".format(bit))
|
||||
# Use right BLs for RBL
|
||||
if self.has_rbl() and self.port==1:
|
||||
if self.port==1:
|
||||
temp.append("rbl_bl")
|
||||
temp.append("rbl_br")
|
||||
temp.extend(["p_en_bar", "vdd"])
|
||||
|
|
@ -368,7 +355,7 @@ class port_data(design.design):
|
|||
vertical_port_order.append(self.write_driver_array_inst)
|
||||
|
||||
# Add one column for the the RBL
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
x_offset = self.bitcell.width
|
||||
else:
|
||||
x_offset = 0
|
||||
|
|
@ -438,7 +425,7 @@ class port_data(design.design):
|
|||
|
||||
inst1 = self.column_mux_array_inst
|
||||
inst2 = self.precharge_array_inst
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
self.connect_bitlines(inst1, inst2, self.num_cols, inst2_start_bit=1)
|
||||
else:
|
||||
self.connect_bitlines(inst1, inst2, self.num_cols)
|
||||
|
|
@ -460,7 +447,7 @@ class port_data(design.design):
|
|||
inst1 = self.precharge_array_inst
|
||||
inst1_bl_name = "bl_{}"
|
||||
inst1_br_name = "br_{}"
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
start_bit=1
|
||||
else:
|
||||
start_bit=0
|
||||
|
|
@ -484,7 +471,7 @@ class port_data(design.design):
|
|||
inst1 = self.precharge_array_inst
|
||||
inst1_bl_name = "bl_{}"
|
||||
inst1_br_name = "br_{}"
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
start_bit=1
|
||||
else:
|
||||
start_bit=0
|
||||
|
|
@ -507,11 +494,11 @@ class port_data(design.design):
|
|||
""" Add the bitline pins for the given port """
|
||||
|
||||
# Connect one bitline to the RBL and offset the indices for the other BLs
|
||||
if self.has_rbl() and self.port==0:
|
||||
if self.port==0:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_0", "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_0", "rbl_br")
|
||||
bit_offset=1
|
||||
elif self.has_rbl() and self.port==1:
|
||||
elif self.port==1:
|
||||
self.copy_layout_pin(self.precharge_array_inst, "bl_{}".format(self.num_cols), "rbl_bl")
|
||||
self.copy_layout_pin(self.precharge_array_inst, "br_{}".format(self.num_cols), "rbl_br")
|
||||
bit_offset=0
|
||||
|
|
@ -603,5 +590,3 @@ class port_data(design.design):
|
|||
if self.precharge_array_inst:
|
||||
self.graph_inst_exclude.add(self.precharge_array_inst)
|
||||
|
||||
def has_rbl(self):
|
||||
return self.port in self.read_ports
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ class replica_bitcell_array(design.design):
|
|||
self.right_rbl = right_rbl
|
||||
self.bitcell_ports = bitcell_ports
|
||||
|
||||
debug.check(left_rbl+right_rbl==len(self.read_ports),"Invalid number of RBLs for port configuration.")
|
||||
debug.check(left_rbl+right_rbl==len(self.all_ports),"Invalid number of RBLs for port configuration.")
|
||||
debug.check(left_rbl+right_rbl==len(self.bitcell_ports),"Bitcell ports must match total RBLs.")
|
||||
|
||||
# Two dummy rows/cols plus replica for each port
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ class sram_base(design, verilog, lef):
|
|||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
temp.append("DOUT{0}[{1}]".format(port,bit))
|
||||
for port in self.read_ports:
|
||||
for port in self.all_ports:
|
||||
temp.append("rbl_bl{0}".format(port))
|
||||
for port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
|
|
@ -499,9 +499,7 @@ class sram_base(design, verilog, lef):
|
|||
if port in self.readwrite_ports:
|
||||
temp.append("web{}".format(port))
|
||||
temp.append("clk{}".format(port))
|
||||
|
||||
if port in self.read_ports:
|
||||
temp.append("rbl_bl{}".format(port))
|
||||
temp.append("rbl_bl{}".format(port))
|
||||
|
||||
# Ouputs
|
||||
if port in self.read_ports:
|
||||
|
|
|
|||
Loading…
Reference in New Issue