Changed routing to allow for 2 write port with write mask.

This commit is contained in:
jsowash 2019-09-03 14:43:03 -07:00
parent 01bdea23ae
commit dd67490823
4 changed files with 67 additions and 47 deletions

View File

@ -74,7 +74,9 @@ class bank(design.design):
# Remember the bank center for further placement # Remember the bank center for further placement
self.bank_array_ll = self.offset_all_coordinates().scale(-1,-1) self.bank_array_ll = self.offset_all_coordinates().scale(-1,-1)
self.bank_array_ur = self.bitcell_array_inst.ur() self.bank_array_ur = self.bitcell_array_inst.ur()
self.bank_array_ul = self.bitcell_array_inst.ul()
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):

View File

@ -22,11 +22,11 @@ class port_data(design.design):
sram_config.set_local_config(self) sram_config.set_local_config(self)
self.port = port self.port = port
if self.write_size: if self.write_size is not None:
self.num_wmasks = int(self.word_size/self.write_size) self.num_wmasks = int(self.word_size/self.write_size)
else: else:
self.num_wmasks = 0 self.num_wmasks = 0
if name == "": if name == "":
name = "port_data_{0}".format(self.port) name = "port_data_{0}".format(self.port)
design.design.__init__(self, name) design.design.__init__(self, name)
@ -58,7 +58,7 @@ class port_data(design.design):
if self.write_driver_array: if self.write_driver_array:
self.create_write_driver_array() self.create_write_driver_array()
if self.write_size: if self.write_size is not None:
self.create_write_mask_and_array() self.create_write_mask_and_array()
else: else:
self.write_mask_and_array_inst = None self.write_mask_and_array_inst = None
@ -70,9 +70,9 @@ class port_data(design.design):
self.create_column_mux_array() self.create_column_mux_array()
else: else:
self.column_mux_array_inst = None self.column_mux_array_inst = None
def create_layout(self): def create_layout(self):
self.compute_instance_offsets() self.compute_instance_offsets()
self.place_instances() self.place_instances()
@ -81,7 +81,7 @@ class port_data(design.design):
def add_pins(self): def add_pins(self):
""" Adding pins for port address module""" """ Adding pins for port address module"""
self.add_pin("rbl_bl","INOUT") self.add_pin("rbl_bl","INOUT")
self.add_pin("rbl_br","INOUT") self.add_pin("rbl_br","INOUT")
for bit in range(self.num_cols): for bit in range(self.num_cols):
@ -107,7 +107,7 @@ class port_data(design.design):
self.add_pin("vdd","POWER") self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND") self.add_pin("gnd","GROUND")
def route_layout(self): def route_layout(self):
""" Create routing among the modules """ """ Create routing among the modules """
self.route_data_lines() self.route_data_lines()
@ -118,15 +118,15 @@ class port_data(design.design):
""" Add the pins """ """ Add the pins """
self.route_bitline_pins() self.route_bitline_pins()
self.route_control_pins() self.route_control_pins()
def route_data_lines(self): def route_data_lines(self):
""" Route the bitlines depending on the port type rw, w, or r. """ """ Route the bitlines depending on the port type rw, w, or r. """
if self.port in self.readwrite_ports: if self.port in self.readwrite_ports:
# (write_mask_and ->) write_driver -> sense_amp -> (column_mux ->) precharge -> bitcell_array # (write_mask_and ->) write_driver -> sense_amp -> (column_mux ->) precharge -> bitcell_array
self.route_write_mask_and_array_in(self.port) self.route_write_mask_and_array_in(self.port)
self.route_write_mask_and_array_to_write_driver(self.port) self.route_write_mask_and_array_to_write_driver(self.port)
self.route_write_driver_in(self.port) self.route_write_driver_in(self.port)
self.route_sense_amp_out(self.port) self.route_sense_amp_out(self.port)
self.route_write_driver_to_sense_amp(self.port) self.route_write_driver_to_sense_amp(self.port)
self.route_sense_amp_to_column_mux_or_precharge_array(self.port) self.route_sense_amp_to_column_mux_or_precharge_array(self.port)
@ -142,15 +142,15 @@ class port_data(design.design):
self.route_write_mask_and_array_to_write_driver(self.port) self.route_write_mask_and_array_to_write_driver(self.port)
self.route_write_driver_in(self.port) self.route_write_driver_in(self.port)
self.route_write_driver_to_column_mux_or_precharge_array(self.port) self.route_write_driver_to_column_mux_or_precharge_array(self.port)
self.route_column_mux_to_precharge_array(self.port) self.route_column_mux_to_precharge_array(self.port)
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 """
for inst in self.insts: for inst in self.insts:
self.copy_power_pins(inst,"vdd") self.copy_power_pins(inst,"vdd")
self.copy_power_pins(inst,"gnd") self.copy_power_pins(inst,"gnd")
def add_modules(self): def add_modules(self):
# Extra column +1 is for RBL # Extra column +1 is for RBL
@ -163,23 +163,23 @@ class port_data(design.design):
if self.port in self.read_ports: if self.port in self.read_ports:
self.sense_amp_array = factory.create(module_type="sense_amp_array", self.sense_amp_array = factory.create(module_type="sense_amp_array",
word_size=self.word_size, word_size=self.word_size,
words_per_row=self.words_per_row) words_per_row=self.words_per_row)
self.add_mod(self.sense_amp_array) self.add_mod(self.sense_amp_array)
else: else:
self.sense_amp_array = None self.sense_amp_array = None
if self.col_addr_size > 0: if self.col_addr_size > 0:
self.column_mux_array = factory.create(module_type="column_mux_array", self.column_mux_array = factory.create(module_type="column_mux_array",
columns=self.num_cols, columns=self.num_cols,
word_size=self.word_size, word_size=self.word_size,
bitcell_bl=self.bl_names[self.port], bitcell_bl=self.bl_names[self.port],
bitcell_br=self.br_names[self.port]) bitcell_br=self.br_names[self.port])
self.add_mod(self.column_mux_array) self.add_mod(self.column_mux_array)
else: else:
self.column_mux_array = None self.column_mux_array = None
if self.port in self.write_ports: if self.port in self.write_ports:
self.write_driver_array = factory.create(module_type="write_driver_array", self.write_driver_array = factory.create(module_type="write_driver_array",
@ -187,11 +187,12 @@ class port_data(design.design):
word_size=self.word_size, word_size=self.word_size,
write_size=self.write_size) write_size=self.write_size)
self.add_mod(self.write_driver_array) self.add_mod(self.write_driver_array)
if self.write_size: if self.write_size is not None:
self.write_mask_and_array = factory.create(module_type="write_mask_and_array", self.write_mask_and_array = factory.create(module_type="write_mask_and_array",
columns=self.num_cols, columns=self.num_cols,
word_size=self.word_size, word_size=self.word_size,
write_size=self.write_size) write_size=self.write_size,
port = self.port)
self.add_mod(self.write_mask_and_array) self.add_mod(self.write_mask_and_array)
else: else:
self.write_mask_and_array = None self.write_mask_and_array = None
@ -207,8 +208,8 @@ class port_data(design.design):
if self.col_addr_size>0: if self.col_addr_size>0:
self.num_col_addr_lines = 2**self.col_addr_size self.num_col_addr_lines = 2**self.col_addr_size
else: else:
self.num_col_addr_lines = 0 self.num_col_addr_lines = 0
# A space for wells or jogging m2 between modules # A space for wells or jogging m2 between modules
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"), self.m2_gap = max(2*drc("pwell_to_nwell") + drc("well_enclosure_active"),
@ -216,7 +217,7 @@ class port_data(design.design):
# create arrays of bitline and bitline_bar names for read, write, or all ports # create arrays of bitline and bitline_bar names for read, write, or all ports
self.bitcell = factory.create(module_type="bitcell") self.bitcell = factory.create(module_type="bitcell")
self.bl_names = self.bitcell.get_all_bl_names() self.bl_names = self.bitcell.get_all_bl_names()
self.br_names = self.bitcell.get_all_br_names() self.br_names = self.bitcell.get_all_br_names()
self.wl_names = self.bitcell.get_all_wl_names() self.wl_names = self.bitcell.get_all_wl_names()
@ -226,7 +227,7 @@ class port_data(design.design):
if not self.precharge_array: if not self.precharge_array:
self.precharge_array_inst = None self.precharge_array_inst = None
return return
self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port), self.precharge_array_inst = self.add_inst(name="precharge_array{}".format(self.port),
mod=self.precharge_array) mod=self.precharge_array)
@ -245,16 +246,16 @@ class port_data(design.design):
temp.extend(["p_en_bar", "vdd"]) temp.extend(["p_en_bar", "vdd"])
self.connect_inst(temp) self.connect_inst(temp)
def place_precharge_array(self, offset): def place_precharge_array(self, offset):
""" Placing Precharge """ """ Placing Precharge """
self.precharge_array_inst.place(offset=offset, mirror="MX") self.precharge_array_inst.place(offset=offset, mirror="MX")
def create_column_mux_array(self): def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """ """ Creating Column Mux when words_per_row > 1 . """
self.column_mux_array_inst = self.add_inst(name="column_mux_array{}".format(self.port), self.column_mux_array_inst = self.add_inst(name="column_mux_array{}".format(self.port),
mod=self.column_mux_array) mod=self.column_mux_array)
@ -270,15 +271,15 @@ class port_data(design.design):
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
def place_column_mux_array(self, offset): def place_column_mux_array(self, offset):
""" Placing Column Mux when words_per_row > 1 . """ """ Placing Column Mux when words_per_row > 1 . """
if self.col_addr_size == 0: if self.col_addr_size == 0:
return return
self.column_mux_array_inst.place(offset=offset, mirror="MX") self.column_mux_array_inst.place(offset=offset, mirror="MX")
def create_sense_amp_array(self): def create_sense_amp_array(self):
""" Creating Sense amp """ """ Creating Sense amp """
self.sense_amp_array_inst = self.add_inst(name="sense_amp_array{}".format(self.port), self.sense_amp_array_inst = self.add_inst(name="sense_amp_array{}".format(self.port),
@ -293,11 +294,11 @@ class port_data(design.design):
else: else:
temp.append(self.bl_names[self.port]+"_out_{0}".format(bit)) temp.append(self.bl_names[self.port]+"_out_{0}".format(bit))
temp.append(self.br_names[self.port]+"_out_{0}".format(bit)) temp.append(self.br_names[self.port]+"_out_{0}".format(bit))
temp.extend(["s_en", "vdd", "gnd"]) temp.extend(["s_en", "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def place_sense_amp_array(self, offset): def place_sense_amp_array(self, offset):
""" Placing Sense amp """ """ Placing Sense amp """
self.sense_amp_array_inst.place(offset=offset, mirror="MX") self.sense_amp_array_inst.place(offset=offset, mirror="MX")
@ -320,7 +321,7 @@ class port_data(design.design):
temp.append(self.bl_names[self.port] + "_out_{0}".format(bit)) temp.append(self.bl_names[self.port] + "_out_{0}".format(bit))
temp.append(self.br_names[self.port] + "_out_{0}".format(bit)) temp.append(self.br_names[self.port] + "_out_{0}".format(bit))
if self.write_size: if self.write_size is not None:
for i in range(self.num_wmasks): for i in range(self.num_wmasks):
temp.append("wdriver_sel_{}".format(i)) temp.append("wdriver_sel_{}".format(i))
else: else:

View File

@ -20,7 +20,7 @@ class write_mask_and_array(design.design):
The write mask AND array goes between the write driver array and the sense amp array. The write mask AND array goes between the write driver array and the sense amp array.
""" """
def __init__(self, name, columns, word_size, write_size): def __init__(self, name, columns, word_size, write_size, port):
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {0}".format(self.name)) debug.info(1, "Creating {0}".format(self.name))
self.add_comment("columns: {0}".format(columns)) self.add_comment("columns: {0}".format(columns))
@ -30,6 +30,7 @@ class write_mask_and_array(design.design):
self.columns = columns self.columns = columns
self.word_size = word_size self.word_size = word_size
self.write_size = write_size self.write_size = write_size
self.port = port
self.words_per_row = int(columns / word_size) self.words_per_row = int(columns / word_size)
self.num_wmasks = int(word_size / write_size) self.num_wmasks = int(word_size / write_size)
@ -106,13 +107,24 @@ class write_mask_and_array(design.design):
self.nand2 = factory.create(module_type="pnand2") self.nand2 = factory.create(module_type="pnand2")
supply_pin=self.nand2.get_pin("vdd") supply_pin=self.nand2.get_pin("vdd")
# Create the enable pin that connects all write mask AND array's B pins # Create the enable pin that connects all write mask AND array's B pins
beg_en_pin = self.and2_insts[0].get_pin("B") beg_en_pin = self.and2_insts[0].get_pin("B")
end_en_pin = self.and2_insts[self.num_wmasks-1].get_pin("B") end_en_pin = self.and2_insts[self.num_wmasks-1].get_pin("B")
self.add_layout_pin(text="en", if self.port == 0:
layer="metal3", self.add_layout_pin(text="en",
offset=beg_en_pin.bc(), layer="metal3",
width = end_en_pin.cx() - beg_en_pin.cx()) offset=beg_en_pin.bc(),
width=end_en_pin.cx() - beg_en_pin.cx())
else:
en_to_edge = self.and2.width - beg_en_pin.cx()
self.add_layout_pin(text="en",
layer="metal3",
offset=beg_en_pin.bc(),
width=end_en_pin.cx() - beg_en_pin.cx() + en_to_edge)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=vector(end_en_pin.cx() + en_to_edge, end_en_pin.cy()))
for i in range(self.num_wmasks): for i in range(self.num_wmasks):
# Copy remaining layout pins # Copy remaining layout pins

View File

@ -138,7 +138,7 @@ class sram_1bank(sram_base):
if port in self.write_ports: if port in self.write_ports:
if self.write_size: if self.write_size:
# Add the write mask flops below the write mask AND array. # Add the write mask flops below the write mask AND array.
wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.data_dff_insts[port].width, wmask_pos[port] = vector(self.bank.bank_array_ur.x - self.wmask_dff_insts[port].width,
self.bank.height + max_gap_size_wmask + self.dff.height) self.bank.height + max_gap_size_wmask + self.dff.height)
self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX") self.wmask_dff_insts[port].place(wmask_pos[port], mirror="MX")
@ -355,11 +355,16 @@ class sram_1bank(sram_base):
""" Connect the output of the data flops to the write driver """ """ Connect the output of the data flops to the write driver """
# This is where the channel will start (y-dimension at least) # This is where the channel will start (y-dimension at least)
for port in self.write_ports: for port in self.write_ports:
if port%2: if self.write_size:
offset = self.data_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch) if port % 2:
offset = self.data_dff_insts[port].ll() - vector(0, (self.word_size + 2)*self.m3_pitch)
else:
offset = self.data_dff_insts[port].ul() + vector(0, 2 * self.m3_pitch)
else: else:
offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch) if port%2:
offset = self.data_dff_insts[port].ll() - vector(0, (self.word_size+2)*self.m1_pitch)
else:
offset = self.data_dff_insts[port].ul() + vector(0, 2*self.m1_pitch)
dff_names = ["dout_{}".format(x) for x in range(self.word_size)] dff_names = ["dout_{}".format(x) for x in range(self.word_size)]
dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names] dff_pins = [self.data_dff_insts[port].get_pin(x) for x in dff_names]
@ -399,7 +404,7 @@ class sram_1bank(sram_base):
# This is where the channel will start (y-dimension at least) # This is where the channel will start (y-dimension at least)
for port in self.write_ports: for port in self.write_ports:
if port % 2: if port % 2:
offset = self.wmask_dff_insts[port].ll() - vector(0, (self.word_size + 2) * self.m1_pitch) offset = self.wmask_dff_insts[port].ll() - vector(0, (self.num_wmasks+2) * self.m1_pitch)
else: else:
offset = self.wmask_dff_insts[port].ul() + vector(0, 2 * self.m1_pitch) offset = self.wmask_dff_insts[port].ul() + vector(0, 2 * self.m1_pitch)