New control logic, netlist only working

This commit is contained in:
Matt Guthaus 2019-08-07 17:14:33 -07:00
parent 275891084b
commit d36f14b408
5 changed files with 82 additions and 117 deletions

View File

@ -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")

View File

@ -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",
@ -141,17 +141,19 @@ class control_logic(design.design):
size=1,
height=dff_height)
self.add_mod(self.inv)
# p_en_bar drives every column in the bitcell array
# but it is sized the same as the wl_en driver with
# 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):

View File

@ -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)
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
# 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)
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

View File

@ -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

View File

@ -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: