Finalized separation of netlist/layout creation.

This commit is contained in:
Matt Guthaus 2018-08-27 14:18:32 -07:00
parent 0daad338e4
commit 19d46f5954
16 changed files with 454 additions and 275 deletions

View File

@ -54,19 +54,22 @@ class bank(design.design):
self.prefix="gated_" self.prefix="gated_"
else: else:
self.prefix="" self.prefix=""
self.create_netlist()
self.create_layout()
def create_netlist(self):
self.compute_sizes() self.compute_sizes()
self.add_pins() self.add_pins()
self.create_modules()
self.add_modules() self.add_modules()
self.setup_layout_constraints() self.create_modules()
# FIXME: Move this to the add modules function def create_layout(self):
self.add_bank_select() self.place_modules()
self.setup_routing_constraints()
self.route_layout() self.route_layout()
# Can remove the following, but it helps for debug! # Can remove the following, but it helps for debug!
#self.add_lvs_correspondence_points() #self.add_lvs_correspondence_points()
@ -74,7 +77,7 @@ class bank(design.design):
self.bank_center=self.offset_all_coordinates().scale(-1,-1) self.bank_center=self.offset_all_coordinates().scale(-1,-1)
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):
""" Adding pins for Bank module""" """ Adding pins for Bank module"""
for k in range(self.total_read): for k in range(self.total_read):
@ -117,24 +120,46 @@ class bank(design.design):
self.route_vdd_gnd() self.route_vdd_gnd()
def add_modules(self): def create_modules(self):
""" Add modules. The order should not matter! """ """ Add modules. The order should not matter! """
# Above the bitcell array # Above the bitcell array
self.add_bitcell_array() self.create_bitcell_array()
self.add_precharge_array() self.create_precharge_array()
# Below the bitcell array # Below the bitcell array
self.add_column_mux_array() self.create_column_mux_array()
self.add_sense_amp_array() self.create_sense_amp_array()
self.add_write_driver_array() self.create_write_driver_array()
# To the left of the bitcell array # To the left of the bitcell array
self.add_row_decoder() self.create_row_decoder()
self.add_wordline_driver() self.create_wordline_driver()
self.add_column_decoder() self.create_column_decoder()
self.create_bank_select()
def place_modules(self):
""" Add modules. The order should not matter! """
# Above the bitcell array
self.place_bitcell_array()
self.place_precharge_array()
# Below the bitcell array
self.place_column_mux_array()
self.place_sense_amp_array()
self.place_write_driver_array()
# To the left of the bitcell array
self.place_row_decoder()
self.place_wordline_driver()
self.place_column_decoder()
self.place_bank_select()
def compute_sizes(self): def compute_sizes(self):
""" Computes the required sizes to create the bank """ """ Computes the required sizes to create the bank """
@ -178,7 +203,7 @@ class bank(design.design):
2*self.m2_pitch) 2*self.m2_pitch)
def create_modules(self): def add_modules(self):
""" Create all the modules using the class loader """ """ Create all the modules using the class loader """
self.bitcell = self.mod_bitcell() self.bitcell = self.mod_bitcell()
@ -199,9 +224,9 @@ class bank(design.design):
self.total_wl_list = self.bitcell.list_all_wl_names() self.total_wl_list = self.bitcell.list_all_wl_names()
self.total_bitline_list = self.bitcell.list_all_bitline_names() self.total_bitline_list = self.bitcell.list_all_bitline_names()
self.precharge_array = [None] * self.total_read self.precharge_array = []
for k in range(self.total_read): for k in range(self.total_read):
self.precharge_array[k] = self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[k], bitcell_br=self.read_br_list[k]) self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.read_bl_list[k], bitcell_br=self.read_br_list[k]))
self.add_mod(self.precharge_array[k]) self.add_mod(self.precharge_array[k])
if self.col_addr_size > 0: if self.col_addr_size > 0:
@ -232,12 +257,12 @@ class bank(design.design):
self.add_mod(self.bank_select) self.add_mod(self.bank_select)
def add_bitcell_array(self): def create_bitcell_array(self):
""" Adding Bitcell Array """ """ Creating Bitcell Array """
self.bitcell_array_inst=self.add_inst(name="bitcell_array", self.bitcell_array_inst=self.add_inst(name="bitcell_array",
mod=self.bitcell_array, mod=self.bitcell_array)
offset=vector(0,0))
temp = [] temp = []
for col in range(self.num_cols): for col in range(self.num_cols):
@ -250,19 +275,19 @@ class bank(design.design):
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
def place_bitcell_array(self):
""" Placing Bitcell Array """
self.place_inst(name="bitcell_array",
offset=vector(0,0))
def add_precharge_array(self):
""" Adding Precharge """
self.precharge_array_inst = [None] * self.total_read
def create_precharge_array(self):
""" Creating Precharge """
self.precharge_array_inst = []
for k in range(self.total_read): for k in range(self.total_read):
# The wells must be far enough apart self.precharge_array_inst.append(self.add_inst(name="precharge_array{}".format(k),
# The enclosure is for the well and the spacing is to the bitcell wells mod=self.precharge_array[k]))
y_offset = self.bitcell_array.height + self.m2_gap
self.precharge_array_inst[k]=self.add_inst(name="precharge_array{}".format(k),
mod=self.precharge_array[k],
offset=vector(0,y_offset))
temp = [] temp = []
for i in range(self.num_cols): for i in range(self.num_cols):
temp.append(self.read_bl_list[k]+"[{0}]".format(i)) temp.append(self.read_bl_list[k]+"[{0}]".format(i))
@ -270,22 +295,27 @@ class bank(design.design):
temp.extend([self.prefix+"clk_buf_bar", "vdd"]) temp.extend([self.prefix+"clk_buf_bar", "vdd"])
self.connect_inst(temp) self.connect_inst(temp)
def add_column_mux_array(self): def place_precharge_array(self):
""" Adding Column Mux when words_per_row > 1 . """ """ Placing Precharge """
if self.col_addr_size > 0: # FIXME: place for multiport
self.column_mux_height = self.column_mux_array.height + self.m2_gap for k in range(self.total_read):
else: # The wells must be far enough apart
self.column_mux_height = 0 # The enclosure is for the well and the spacing is to the bitcell wells
y_offset = self.bitcell_array.height + self.m2_gap
self.place_inst(name=self.precharge_array_inst[k].name,
offset=vector(0,y_offset))
def create_column_mux_array(self):
""" Creating Column Mux when words_per_row > 1 . """
if self.col_addr_size == 0:
return return
self.col_mux_array_inst = [None] * self.total_ports self.col_mux_array_inst = []
for k in range(self.total_ports): for k in range(self.total_ports):
y_offset = self.column_mux_height self.col_mux_array_inst.append(self.add_inst(name="column_mux_array{}".format(k),
self.col_mux_array_inst[k]=self.add_inst(name="column_mux_array{}".format(k), mod=self.column_mux_array))
mod=self.column_mux_array,
offset=vector(0,y_offset).scale(-1,-1))
temp = [] temp = []
for i in range(self.num_cols): for i in range(self.num_cols):
temp.append(self.total_bl_list[k]+"[{0}]".format(i)) temp.append(self.total_bl_list[k]+"[{0}]".format(i))
@ -298,16 +328,27 @@ class bank(design.design):
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
def add_sense_amp_array(self): def place_column_mux_array(self):
""" Adding Sense amp """ """ Placing Column Mux when words_per_row > 1 . """
if self.col_addr_size > 0:
self.column_mux_height = self.column_mux_array.height + self.m2_gap
else:
self.column_mux_height = 0
return
self.sense_amp_array_inst = [None] * self.total_read for k in range(self.total_ports):
y_offset = self.column_mux_height
self.place_inst(name=self.col_mux_array_inst[k].name,
offset=vector(0,y_offset).scale(-1,-1))
def create_sense_amp_array(self):
""" Creating Sense amp """
self.sense_amp_array_inst = []
for k in range(self.total_read): for k in range(self.total_read):
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap self.sense_amp_array_inst.append(self.add_inst(name="sense_amp_array{}".format(k),
self.sense_amp_array_inst[k]=self.add_inst(name="sense_amp_array{}".format(k), mod=self.sense_amp_array))
mod=self.sense_amp_array,
offset=vector(0,y_offset).scale(-1,-1))
temp = [] temp = []
for i in range(self.word_size): for i in range(self.word_size):
temp.append("dout{0}[{1}]".format(k,i)) temp.append("dout{0}[{1}]".format(k,i))
@ -321,17 +362,22 @@ class bank(design.design):
temp.extend([self.prefix+"s_en{0}".format(k), "vdd", "gnd"]) temp.extend([self.prefix+"s_en{0}".format(k), "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def add_write_driver_array(self): def place_sense_amp_array(self):
""" Adding Write Driver """ """ Placing Sense amp """
self.write_driver_array_inst = [None] * self.total_write # FIXME: place for multiport
for k in range(self.total_read):
y_offset = self.column_mux_height + self.sense_amp_array.height + self.m2_gap
self.place_inst(name=self.sense_amp_array_inst[k].name,
offset=vector(0,y_offset).scale(-1,-1))
def create_write_driver_array(self):
""" Creating Write Driver """
self.write_driver_array_inst = []
for k in range(self.total_write): for k in range(self.total_write):
y_offset = self.sense_amp_array.height + self.column_mux_height \ self.write_driver_array_inst.append(self.add_inst(name="write_driver_array{}".format(k),
+ self.m2_gap + self.write_driver_array.height mod=self.write_driver_array))
self.write_driver_array_inst[k]=self.add_inst(name="write_driver_array{}".format(k),
mod=self.write_driver_array,
offset=vector(0,y_offset).scale(-1,-1))
temp = [] temp = []
for i in range(self.word_size): for i in range(self.word_size):
@ -346,23 +392,25 @@ class bank(design.design):
temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"]) temp.extend([self.prefix+"w_en{0}".format(k), "vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def place_write_driver_array(self):
""" Placing Write Driver """
def add_row_decoder(self): # FIXME: place for multiport
""" Add the hierarchical row decoder """ for k in range(self.total_write):
y_offset = self.sense_amp_array.height + self.column_mux_height \
+ self.m2_gap + self.write_driver_array.height
self.place_inst(name=self.write_driver_array_inst[k].name,
offset=vector(0,y_offset).scale(-1,-1))
# The address and control bus will be in between decoder and the main memory array
# This bus will route address bits to the decoder input and column mux inputs.
# The wires are actually routed after we placed the stuff on both sides. def create_row_decoder(self):
# The predecoder is below the x-axis and the main decoder is above the x-axis """ Create the hierarchical row decoder """
# The address flop and decoder are aligned in the x coord.
self.row_decoder_inst = [None] * self.total_ports
self.row_decoder_inst = []
for k in range(self.total_ports): for k in range(self.total_ports):
x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width) self.row_decoder_inst.append(self.add_inst(name="row_decoder{}".format(k),
self.row_decoder_inst[k]=self.add_inst(name="row_decoder{}".format(k), mod=self.row_decoder))
mod=self.row_decoder,
offset=vector(x_offset,0))
temp = [] temp = []
for i in range(self.row_addr_size): for i in range(self.row_addr_size):
@ -372,17 +420,29 @@ class bank(design.design):
temp.extend(["vdd", "gnd"]) temp.extend(["vdd", "gnd"])
self.connect_inst(temp) self.connect_inst(temp)
def add_wordline_driver(self): def place_row_decoder(self):
""" Wordline Driver """ """ Place the hierarchical row decoder """
self.wordline_driver_inst = [None] * self.total_ports # The address and control bus will be in between decoder and the main memory array
# This bus will route address bits to the decoder input and column mux inputs.
# The wires are actually routed after we placed the stuff on both sides.
# The predecoder is below the x-axis and the main decoder is above the x-axis
# The address flop and decoder are aligned in the x coord.
# FIXME: place for multiport
for k in range(self.total_ports): for k in range(self.total_ports):
# The wordline driver is placed to the right of the main decoder width. x_offset = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
x_offset = -(self.central_bus_width + self.wordline_driver.width) + self.m2_pitch self.place_inst(name=self.row_decoder_inst[k].name,
self.wordline_driver_inst[k]=self.add_inst(name="wordline_driver{}".format(k), offset=vector(x_offset,0))
mod=self.wordline_driver,
offset=vector(x_offset,0))
def create_wordline_driver(self):
""" Create the Wordline Driver """
self.wordline_driver_inst = []
for k in range(self.total_ports):
self.wordline_driver_inst.append(self.add_inst(name="wordline_driver{}".format(k),
mod=self.wordline_driver))
temp = [] temp = []
for i in range(self.num_rows): for i in range(self.num_rows):
@ -394,35 +454,22 @@ class bank(design.design):
temp.append("gnd") temp.append("gnd")
self.connect_inst(temp) self.connect_inst(temp)
def place_wordline_driver(self):
""" Place the Wordline Driver """
# FIXME: place for multiport
for k in range(self.total_ports):
# The wordline driver is placed to the right of the main decoder width.
x_offset = -(self.central_bus_width + self.wordline_driver.width) + self.m2_pitch
self.place_inst(name=self.wordline_driver_inst[k].name,
offset=vector(x_offset,0))
def add_column_decoder_module(self): def create_column_decoder(self):
""" """
Create a 2:4 or 3:8 column address decoder. Create a 2:4 or 3:8 column address decoder.
""" """
self.col_decoder_inst = [None] * self.total_ports
for k in range(self.total_ports):
# Place the col decoder right aligned with row decoder
x_off = -(self.central_bus_width + self.wordline_driver.width + self.col_decoder.width)
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
self.col_decoder_inst[k]=self.add_inst(name="col_address_decoder{}".format(k),
mod=self.col_decoder,
offset=vector(x_off,y_off))
temp = []
for i in range(self.col_addr_size):
temp.append("addr{0}[{1}]".format(k,i))
for j in range(self.num_col_addr_lines):
temp.append("sel{0}[{1}]".format(k,j))
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
def add_column_decoder(self):
"""
Create a decoder to decode column select lines. This could be an inverter/buffer for 1:2,
2:4 decoder, or 3:8 decoder.
"""
if self.col_addr_size == 0: if self.col_addr_size == 0:
return return
elif self.col_addr_size == 1: elif self.col_addr_size == 1:
@ -435,51 +482,92 @@ class bank(design.design):
else: else:
# No error checking before? # No error checking before?
debug.error("Invalid column decoder?",-1) debug.error("Invalid column decoder?",-1)
self.col_decoder_inst = []
for k in range(self.total_ports):
self.col_decoder_inst.append(self.add_inst(name="col_address_decoder{}".format(k),
mod=self.col_decoder))
temp = []
for i in range(self.col_addr_size):
temp.append("addr{0}[{1}]".format(k,i))
for j in range(self.num_col_addr_lines):
temp.append("sel{0}[{1}]".format(k,j))
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
def place_column_decoder(self):
"""
Place a 2:4 or 3:8 column address decoder.
"""
if self.col_addr_size == 0:
return
self.add_column_decoder_module() # FIXME: place for multiport
for k in range(self.total_ports):
# Place the col decoder right aligned with row decoder
x_off = -(self.central_bus_width + self.wordline_driver.width + self.col_decoder.width)
y_off = -(self.col_decoder.height + 2*drc["well_to_well"])
self.place_inst(name=self.col_decoder_inst[k].name,
offset=vector(x_off,y_off))
def create_bank_select(self):
""" Create the bank select logic. """
def add_bank_select(self): if not self.num_banks > 1:
""" Instantiate the bank select logic. """ return
self.bank_select_inst = []
for k in range(self.total_ports):
self.bank_select_inst.append(self.add_inst(name="bank_select",
mod=self.bank_select))
temp = []
temp.extend(self.input_control_signals)
temp.append("bank_sel")
temp.extend(self.control_signals)
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
def place_bank_select(self):
""" Place the bank select logic. """
if not self.num_banks > 1: if not self.num_banks > 1:
return return
x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width) # FIXME: place for multiport
if self.col_addr_size > 0: for k in range(self.total_ports):
y_off = min(self.col_decoder_inst[0].by(), self.col_mux_array_inst[0].by()) x_off = -(self.row_decoder.width + self.central_bus_width + self.wordline_driver.width)
else: if self.col_addr_size > 0:
y_off = self.row_decoder_inst[0].by() y_off = min(self.col_decoder_inst[0].by(), self.col_mux_array_inst[0].by())
y_off -= (self.bank_select.height + drc["well_to_well"]) else:
self.bank_select_pos = vector(x_off,y_off) y_off = self.row_decoder_inst[0].by()
self.bank_select_inst = self.add_inst(name="bank_select", y_off -= (self.bank_select.height + drc["well_to_well"])
mod=self.bank_select, self.bank_select_pos = vector(x_off,y_off)
offset=self.bank_select_pos) self.place_inst(name=self.bank_select_inst[k].name,
offset=self.bank_select_pos)
temp = []
temp.extend(self.input_control_signals)
temp.append("bank_sel")
temp.extend(self.control_signals)
temp.extend(["vdd", "gnd"])
self.connect_inst(temp)
def route_vdd_gnd(self): def route_vdd_gnd(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 """
# These are the instances that every bank has # These are the instances that every bank has
top_instances = [self.bitcell_array_inst, top_instances = [self.bitcell_array_inst]
self.precharge_array_inst[0],
self.sense_amp_array_inst[0], for k in range(self.total_ports):
self.write_driver_array_inst[0], top_instances.extend([self.precharge_array_inst[k],
self.row_decoder_inst[0], self.sense_amp_array_inst[k],
self.wordline_driver_inst[0]] self.write_driver_array_inst[k],
# Add these if we use the part... self.row_decoder_inst[k],
if self.col_addr_size > 0: self.wordline_driver_inst[k]])
top_instances.append(self.col_decoder_inst[0]) # Add these if we use the part...
top_instances.append(self.col_mux_array_inst[0]) if self.col_addr_size > 0:
top_instances.append(self.col_decoder_inst[k])
top_instances.append(self.col_mux_array_inst[k])
if self.num_banks > 1: if self.num_banks > 1:
top_instances.append(self.bank_select_inst) top_instances.append(self.bank_select_inst[k])
for inst in top_instances: for inst in top_instances:
@ -497,7 +585,7 @@ class bank(design.design):
for gated_name in self.control_signals: for gated_name in self.control_signals:
# Connect the inverter output to the central bus # Connect the inverter output to the central bus
out_pos = self.bank_select_inst.get_pin(gated_name).rc() out_pos = self.bank_select_inst[0].get_pin(gated_name).rc()
bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y) bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
self.add_path("metal3",[out_pos, bus_pos]) self.add_path("metal3",[out_pos, bus_pos])
self.add_via_center(layers=("metal2", "via2", "metal3"), self.add_via_center(layers=("metal2", "via2", "metal3"),
@ -511,9 +599,11 @@ class bank(design.design):
rotate=90) rotate=90)
def setup_layout_constraints(self): def setup_routing_constraints(self):
""" After the modules are instantiated, find the dimensions for the """
control bus, power ring, etc. """ After the modules are instantiated, find the dimensions for the
control bus, power ring, etc.
"""
#The minimum point is either the bottom of the address flops, #The minimum point is either the bottom of the address flops,
#the column decoder (if there is one). #the column decoder (if there is one).
@ -535,10 +625,11 @@ class bank(design.design):
# The max point is always the top of the precharge bitlines # The max point is always the top of the precharge bitlines
# Add a vdd and gnd power rail above the array # Add a vdd and gnd power rail above the array
# FIXME: Update multiport
self.max_y_offset = self.precharge_array_inst[0].uy() + 3*self.m1_width self.max_y_offset = self.precharge_array_inst[0].uy() + 3*self.m1_width
self.max_x_offset = self.bitcell_array_inst.ur().x + 3*self.m1_width self.max_x_offset = self.bitcell_array_inst.ur().x + 3*self.m1_width
self.min_x_offset = self.row_decoder_inst[0].lx() self.min_x_offset = self.row_decoder_inst[0].lx()
# # Create the core bbox for the power rings # # Create the core bbox for the power rings
ur = vector(self.max_x_offset, self.max_y_offset) ur = vector(self.max_x_offset, self.max_y_offset)
ll = vector(self.min_x_offset, self.min_y_offset) ll = vector(self.min_x_offset, self.min_y_offset)
@ -570,7 +661,8 @@ class bank(design.design):
def route_precharge_to_bitcell_array(self): def route_precharge_to_bitcell_array(self):
""" Routing of BL and BR between pre-charge and bitcell array """ """ Routing of BL and BR between pre-charge and bitcell array """
# FIXME: Update for multiport
for k in range(self.total_read): for k in range(self.total_read):
for i in range(self.num_cols): for i in range(self.num_cols):
precharge_bl = self.precharge_array_inst[k].get_pin("bl[{}]".format(i)).bc() precharge_bl = self.precharge_array_inst[k].get_pin("bl[{}]".format(i)).bc()
@ -592,6 +684,7 @@ class bank(design.design):
if self.col_addr_size==0: if self.col_addr_size==0:
return return
# FIXME: Update for multiport
for k in range(self.total_ports): for k in range(self.total_ports):
for i in range(self.num_cols): for i in range(self.num_cols):
col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".format(i)).uc() col_mux_bl = self.col_mux_array_inst[k].get_pin("bl[{}]".format(i)).uc()
@ -665,22 +758,20 @@ class bank(design.design):
def route_wordline_driver(self): def route_wordline_driver(self):
""" Connecting Wordline driver output to Bitcell WL connection """ """ Connecting Wordline driver output to Bitcell WL connection """
for k in range(self.total_read): for i in range(self.num_rows):
# we don't care about bends after connecting to the input pin, so let the path code decide. # The pre/post is to access the pin from "outside" the cell to avoid DRCs
for i in range(self.num_rows): decoder_out_pos = self.row_decoder_inst[0].get_pin("decode[{}]".format(i)).rc()
# The pre/post is to access the pin from "outside" the cell to avoid DRCs driver_in_pos = self.wordline_driver_inst[0].get_pin("in[{}]".format(i)).lc()
decoder_out_pos = self.row_decoder_inst[k].get_pin("decode[{}]".format(i)).rc() mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0)
driver_in_pos = self.wordline_driver_inst[k].get_pin("in[{}]".format(i)).lc() mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
mid1 = decoder_out_pos.scale(0.5,1)+driver_in_pos.scale(0.5,0) self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
mid2 = decoder_out_pos.scale(0.5,0)+driver_in_pos.scale(0.5,1)
self.add_path("metal1", [decoder_out_pos, mid1, mid2, driver_in_pos])
# The mid guarantees we exit the input cell to the right. # The mid guarantees we exit the input cell to the right.
driver_wl_pos = self.wordline_driver_inst[k].get_pin("wl[{}]".format(i)).rc() driver_wl_pos = self.wordline_driver_inst[0].get_pin("wl[{}]".format(i)).rc()
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[k]+"[{}]".format(i)).lc() bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.total_wl_list[0]+"[{}]".format(i)).lc()
mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0) mid1 = driver_wl_pos.scale(0.5,1)+bitcell_wl_pos.scale(0.5,0)
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1) mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos]) self.add_path("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])

View File

@ -54,7 +54,9 @@ class hierarchical_decoder(design.design):
self.route_input_rails() self.route_input_rails()
self.route_predecode_rails() self.route_predecode_rails()
self.route_vdd_gnd() self.route_vdd_gnd()
self.offset_all_coordinates()
self.DRC_LVS()
def add_modules(self): def add_modules(self):
self.inv = pinv() self.inv = pinv()
self.add_mod(self.inv) self.add_mod(self.inv)

View File

@ -37,17 +37,17 @@ class hierarchical_predecode(design.design):
self.inv = pinv() self.inv = pinv()
self.add_mod(self.inv) self.add_mod(self.inv)
self.create_nand(self.number_of_inputs) self.add_nand(self.number_of_inputs)
self.add_mod(self.nand) self.add_mod(self.nand)
def create_nand(self,inputs): def add_nand(self,inputs):
""" Create the NAND for the predecode input stage """ """ Create the NAND for the predecode input stage """
if inputs==2: if inputs==2:
self.nand = pnand2() self.nand = pnand2()
elif inputs==3: elif inputs==3:
self.nand = pnand3() self.nand = pnand3()
else: else:
debug.error("Invalid number of predecode inputs.",-1) debug.error("Invalid number of predecode inputs: {}".format(inputs),-1)
def setup_constraints(self): def setup_constraints(self):

View File

@ -28,7 +28,7 @@ class hierarchical_predecode3x8(hierarchical_predecode):
["in[0]", "inbar[1]", "in[2]", "Z[5]", "vdd", "gnd"], ["in[0]", "inbar[1]", "in[2]", "Z[5]", "vdd", "gnd"],
["inbar[0]", "in[1]", "in[2]", "Z[6]", "vdd", "gnd"], ["inbar[0]", "in[1]", "in[2]", "Z[6]", "vdd", "gnd"],
["in[0]", "in[1]", "in[2]", "Z[7]", "vdd", "gnd"]] ["in[0]", "in[1]", "in[2]", "Z[7]", "vdd", "gnd"]]
self.create_nand(connections) self.create_nand_array(connections)
def create_layout(self): def create_layout(self):
""" """
@ -41,7 +41,7 @@ class hierarchical_predecode3x8(hierarchical_predecode):
self.route_rails() self.route_rails()
self.place_input_inverters() self.place_input_inverters()
self.place_output_inverters() self.place_output_inverters()
self.place_nand() self.place_nand_array()
self.route() self.route()
self.DRC_LVS() self.DRC_LVS()

View File

@ -28,9 +28,8 @@ class pbitcell(pgate.pgate):
self.num_write = num_write self.num_write = num_write
self.num_read = num_read self.num_read = num_read
self.add_pins() self.create_netlist()
self.create_layout() self.create_layout()
self.DRC_LVS()
pbitcell.width = self.width pbitcell.width = self.width
pbitcell.height = self.height pbitcell.height = self.height
@ -61,6 +60,9 @@ class pbitcell(pgate.pgate):
self.add_pin("gnd") self.add_pin("gnd")
def create_netlist(self):
self.add_pins()
def create_layout(self): def create_layout(self):
self.create_ptx() self.create_ptx()
self.calculate_spacing() self.calculate_spacing()
@ -75,6 +77,7 @@ class pbitcell(pgate.pgate):
self.add_read_ports() self.add_read_ports()
self.extend_well() self.extend_well()
self.offset_all_coordinates() self.offset_all_coordinates()
self.DRC_LVS()
def create_ptx(self): def create_ptx(self):

View File

@ -39,7 +39,8 @@ class pinv(pgate.pgate):
self.height = height # Maybe minimize height if not defined in future? self.height = height # Maybe minimize height if not defined in future?
self.route_output = False self.route_output = False
self.add_pins()
self.create_netlist()
self.create_layout() self.create_layout()
# for run-time, we won't check every transitor DRC/LVS independently # for run-time, we won't check every transitor DRC/LVS independently
@ -50,6 +51,10 @@ class pinv(pgate.pgate):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """
self.add_pin_list(["A", "Z", "vdd", "gnd"]) self.add_pin_list(["A", "Z", "vdd", "gnd"])
def create_netlist(self):
""" Calls all functions related to the generation of the netlist """
self.add_pins()
def create_layout(self): def create_layout(self):
""" Calls all functions related to the generation of the layout """ """ Calls all functions related to the generation of the layout """

View File

@ -19,47 +19,43 @@ class pinvbuf(design.design):
def __init__(self, driver_size=4, height=bitcell.height, name=""): def __init__(self, driver_size=4, height=bitcell.height, name=""):
stage_effort = 4 self.stage_effort = 4
self.row_height = height
# FIXME: Change the number of stages to support high drives. # FIXME: Change the number of stages to support high drives.
# stage effort of 4 or less # stage effort of 4 or less
# The pinvbuf has a FO of 2 for the first stage, so the second stage # The pinvbuf has a FO of 2 for the first stage, so the second stage
# should be sized "half" to prevent loading of the first stage # should be sized "half" to prevent loading of the first stage
predriver_size = max(int(driver_size/(stage_effort/2)),1) self.driver_size = driver_size
self.predriver_size = max(int(self.driver_size/(self.stage_effort/2)),1)
if name=="": if name=="":
name = "pinvbuf_{0}_{1}_{2}".format(predriver_size, driver_size, pinvbuf.unique_id) name = "pinvbuf_{0}_{1}_{2}".format(self.predriver_size, self.driver_size, pinvbuf.unique_id)
pinvbuf.unique_id += 1 pinvbuf.unique_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name)) debug.info(1, "Creating {}".format(self.name))
self.create_netlist()
# Shield the cap, but have at least a stage effort of 4 self.create_layout()
input_size = max(1,int(predriver_size/stage_effort))
self.inv = pinv(size=input_size, height=height)
self.add_mod(self.inv)
self.inv1 = pinv(size=predriver_size, height=height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=driver_size, height=height)
self.add_mod(self.inv2) def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_insts()
def create_layout(self):
self.width = 2*self.inv1.width + self.inv2.width self.width = 2*self.inv1.width + self.inv2.width
self.height = 2*self.inv1.height self.height = 2*self.inv1.height
self.create_layout() self.place_insts()
self.route_wires()
self.add_layout_pins()
self.offset_all_coordinates() self.offset_all_coordinates()
self.DRC_LVS() self.DRC_LVS()
def create_layout(self):
self.add_pins()
self.add_insts()
self.add_wires()
self.add_layout_pins()
def add_pins(self): def add_pins(self):
self.add_pin("A") self.add_pin("A")
@ -68,35 +64,58 @@ class pinvbuf(design.design):
self.add_pin("vdd") self.add_pin("vdd")
self.add_pin("gnd") self.add_pin("gnd")
def add_insts(self): def add_modules(self):
# Add INV1 to the right (capacitance shield)
# Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.predriver_size/self.stage_effort))
self.inv = pinv(size=input_size, height=self.row_height)
self.add_mod(self.inv)
self.inv1 = pinv(size=self.predriver_size, height=self.row_height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.driver_size, height=self.row_height)
self.add_mod(self.inv2)
def create_insts(self):
# Create INV1 (capacitance shield)
self.inv1_inst=self.add_inst(name="buf_inv1", self.inv1_inst=self.add_inst(name="buf_inv1",
mod=self.inv, mod=self.inv)
offset=vector(0,0))
self.connect_inst(["A", "zb_int", "vdd", "gnd"]) self.connect_inst(["A", "zb_int", "vdd", "gnd"])
# Add INV2 to the right
self.inv2_inst=self.add_inst(name="buf_inv2", self.inv2_inst=self.add_inst(name="buf_inv2",
mod=self.inv1, mod=self.inv1)
offset=vector(self.inv1_inst.rx(),0))
self.connect_inst(["zb_int", "z_int", "vdd", "gnd"]) self.connect_inst(["zb_int", "z_int", "vdd", "gnd"])
# Add INV3 to the right
self.inv3_inst=self.add_inst(name="buf_inv3", self.inv3_inst=self.add_inst(name="buf_inv3",
mod=self.inv2, mod=self.inv2)
offset=vector(self.inv2_inst.rx(),0))
self.connect_inst(["z_int", "Zb", "vdd", "gnd"]) self.connect_inst(["z_int", "Zb", "vdd", "gnd"])
# Add INV4 to the bottom
self.inv4_inst=self.add_inst(name="buf_inv4", self.inv4_inst=self.add_inst(name="buf_inv4",
mod=self.inv2, mod=self.inv2)
offset=vector(self.inv2_inst.rx(),2*self.inv2.height),
mirror = "MX")
self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) self.connect_inst(["zb_int", "Z", "vdd", "gnd"])
def place_insts(self):
# Add INV1 to the right (capacitance shield)
self.place_inst(name="buf_inv1",
offset=vector(0,0))
# Add INV2 to the right
self.place_inst(name="buf_inv2",
offset=vector(self.inv1_inst.rx(),0))
# Add INV3 to the right
self.place_inst(name="buf_inv3",
offset=vector(self.inv2_inst.rx(),0))
# Add INV4 to the bottom
self.place_inst(name="buf_inv4",
offset=vector(self.inv2_inst.rx(),2*self.inv2.height),
mirror = "MX")
def add_wires(self): def route_wires(self):
# inv1 Z to inv2 A # inv1 Z to inv2 A
z1_pin = self.inv1_inst.get_pin("Z") z1_pin = self.inv1_inst.get_pin("Z")
a2_pin = self.inv2_inst.get_pin("A") a2_pin = self.inv2_inst.get_pin("A")

View File

@ -35,7 +35,7 @@ class pnand2(pgate.pgate):
debug.check(size==1,"Size 1 pnand2 is only supported now.") debug.check(size==1,"Size 1 pnand2 is only supported now.")
self.tx_mults = 1 self.tx_mults = 1
self.add_pins() self.create_netlist()
self.create_layout() self.create_layout()
#self.DRC_LVS() #self.DRC_LVS()
@ -44,6 +44,10 @@ class pnand2(pgate.pgate):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """
self.add_pin_list(["A", "B", "Z", "vdd", "gnd"]) self.add_pin_list(["A", "B", "Z", "vdd", "gnd"])
def create_netlist(self):
self.add_pins()
def create_layout(self): def create_layout(self):
""" Calls all functions related to the generation of the layout """ """ Calls all functions related to the generation of the layout """

View File

@ -38,7 +38,7 @@ class pnand3(pgate.pgate):
debug.check(size==1,"Size 1 pnand3 is only supported now.") debug.check(size==1,"Size 1 pnand3 is only supported now.")
self.tx_mults = 1 self.tx_mults = 1
self.add_pins() self.create_netlist()
self.create_layout() self.create_layout()
#self.DRC_LVS() #self.DRC_LVS()
@ -47,6 +47,9 @@ class pnand3(pgate.pgate):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """
self.add_pin_list(["A", "B", "C", "Z", "vdd", "gnd"]) self.add_pin_list(["A", "B", "C", "Z", "vdd", "gnd"])
def create_netlist(self):
self.add_pins()
def create_layout(self): def create_layout(self):
""" Calls all functions related to the generation of the layout """ """ Calls all functions related to the generation of the layout """

View File

@ -36,7 +36,7 @@ class pnor2(pgate.pgate):
debug.check(size==1,"Size 1 pnor2 is only supported now.") debug.check(size==1,"Size 1 pnor2 is only supported now.")
self.tx_mults = 1 self.tx_mults = 1
self.add_pins() self.create_netlist()
self.create_layout() self.create_layout()
#self.DRC_LVS() #self.DRC_LVS()
@ -45,6 +45,9 @@ class pnor2(pgate.pgate):
""" Adds pins for spice netlist """ """ Adds pins for spice netlist """
self.add_pin_list(["A", "B", "Z", "vdd", "gnd"]) self.add_pin_list(["A", "B", "Z", "vdd", "gnd"])
def create_netlist(self):
self.add_pins()
def create_layout(self): def create_layout(self):
""" Calls all functions related to the generation of the layout """ """ Calls all functions related to the generation of the layout """

View File

@ -31,13 +31,15 @@ class precharge(pgate.pgate):
self.bitcell_bl = bitcell_bl self.bitcell_bl = bitcell_bl
self.bitcell_br = bitcell_br self.bitcell_br = bitcell_br
self.add_pins() self.create_netlist()
self.create_layout() self.create_layout()
self.DRC_LVS()
def add_pins(self): def add_pins(self):
self.add_pin_list(["bl", "br", "en", "vdd"]) self.add_pin_list(["bl", "br", "en", "vdd"])
def create_netlist(self):
self.add_pins()
def create_layout(self): def create_layout(self):
self.create_ptx() self.create_ptx()
self.add_ptx() self.add_ptx()
@ -47,6 +49,7 @@ class precharge(pgate.pgate):
self.add_vdd_rail() self.add_vdd_rail()
self.add_bitlines() self.add_bitlines()
self.connect_to_bitlines() self.connect_to_bitlines()
self.DRC_LVS()
def create_ptx(self): def create_ptx(self):
"""Initializes the upper and lower pmos""" """Initializes the upper and lower pmos"""

View File

@ -39,7 +39,7 @@ class ptx(design.design):
self.connect_poly = connect_poly self.connect_poly = connect_poly
self.num_contacts = num_contacts self.num_contacts = num_contacts
self.create_spice() self.create_netlist()
self.create_layout() self.create_layout()
self.translate_all(self.active_offset) self.translate_all(self.active_offset)
@ -57,7 +57,7 @@ class ptx(design.design):
self.add_poly() self.add_poly()
self.add_active_contacts() self.add_active_contacts()
def create_spice(self): def create_netlist(self):
self.add_pin_list(["D", "G", "S", "B"]) self.add_pin_list(["D", "G", "S", "B"])
# self.spice.append("\n.SUBCKT {0} {1}".format(self.name, # self.spice.append("\n.SUBCKT {0} {1}".format(self.name,

View File

@ -23,12 +23,15 @@ class single_level_column_mux(design.design):
self.bitcell = self.mod_bitcell() self.bitcell = self.mod_bitcell()
self.ptx_width = tx_size * drc["minwidth_tx"] self.ptx_width = tx_size * drc["minwidth_tx"]
self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"])
self.create_netlist()
self.create_layout() self.create_layout()
def create_layout(self): def create_netlist(self):
self.add_pin_list(["bl", "br", "bl_out", "br_out", "sel", "gnd"])
self.add_ptx() self.add_ptx()
def create_layout(self):
self.pin_height = 2*self.m2_width self.pin_height = 2*self.m2_width
self.width = self.bitcell.width self.width = self.bitcell.width
self.height = self.nmos_upper.uy() + self.pin_height self.height = self.nmos_upper.uy() + self.pin_height

View File

@ -37,9 +37,7 @@ class sram():
else: else:
debug.error("Invalid number of banks.",-1) debug.error("Invalid number of banks.",-1)
self.s.compute_sizes() self.s.create_netlist()
self.s.create_modules()
self.s.add_pins()
self.s.create_layout() self.s.create_layout()
# Can remove the following, but it helps for debug! # Can remove the following, but it helps for debug!

View File

@ -20,14 +20,38 @@ class sram_1bank(sram_base):
def __init__(self, word_size, num_words, name): def __init__(self, word_size, num_words, name):
sram_base.__init__(self, word_size, num_words, 1, name) sram_base.__init__(self, word_size, num_words, 1, name)
def add_modules(self): def create_netlist(self):
self.compute_sizes()
self.add_modules()
# Must run this after add modules to get control pin names
self.add_pins()
self.create_modules()
def create_modules(self):
""" """
This adds the moduels for a single bank SRAM with control This adds the modules for a single bank SRAM with control
logic.
"""
self.bank_inst = self.create_bank()
self.control_logic_inst = self.create_control_logic()
self.row_addr_dff_inst = self.create_row_addr_dff()
if self.col_addr_dff:
self.col_addr_dff_inst = self.create_col_addr_dff()
self.data_dff_inst = self.create_data_dff()
def place_modules(self):
"""
This places the modules for a single bank SRAM with control
logic. logic.
""" """
# No orientation or offset # No orientation or offset
self.bank_inst = self.add_bank(0, [0, 0], 1, 1) self.place_bank(self.bank_inst, [0, 0], 1, 1)
# The control logic is placed such that the vertical center (between the delay/RBL and # The control logic is placed such that the vertical center (between the delay/RBL and
# the actual control logic is aligned with the vertical center of the bank (between # the actual control logic is aligned with the vertical center of the bank (between
@ -36,12 +60,14 @@ class sram_1bank(sram_base):
# up to the row address DFFs. # up to the row address DFFs.
control_pos = vector(-self.control_logic.width - 2*self.m2_pitch, control_pos = vector(-self.control_logic.width - 2*self.m2_pitch,
self.bank.bank_center.y - self.control_logic.control_logic_center.y) self.bank.bank_center.y - self.control_logic.control_logic_center.y)
self.add_control_logic(position=control_pos) self.place_inst(name=self.control_logic_inst.name,
offset=control_pos)
# The row address bits are placed above the control logic aligned on the right. # The row address bits are placed above the control logic aligned on the right.
row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width, row_addr_pos = vector(self.control_logic_inst.rx() - self.row_addr_dff.width,
self.control_logic_inst.uy()) self.control_logic_inst.uy())
self.add_row_addr_dff(row_addr_pos) self.place_inst(name=self.row_addr_dff_inst.name,
offset=row_addr_pos)
# This is M2 pitch even though it is on M1 to help stem via spacings on the trunk # This is M2 pitch even though it is on M1 to help stem via spacings on the trunk
data_gap = -self.m2_pitch*(self.word_size+1) data_gap = -self.m2_pitch*(self.word_size+1)
@ -51,7 +77,8 @@ class sram_1bank(sram_base):
if self.col_addr_dff: if self.col_addr_dff:
col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width, col_addr_pos = vector(self.bank.bank_center.x - self.col_addr_dff.width - self.bank.central_bus_width,
data_gap - self.col_addr_dff.height) data_gap - self.col_addr_dff.height)
self.add_col_addr_dff(col_addr_pos) self.place_inst(name=self.col_addr_dff_inst.name,
offset=col_addr_pos)
# Add the data flops below the bank to the right of the center of bank: # Add the data flops below the bank to the right of the center of bank:
# This relies on the center point of the bank: # This relies on the center point of the bank:
@ -60,12 +87,13 @@ class sram_1bank(sram_base):
# sense amps. # sense amps.
data_pos = vector(self.bank.bank_center.x, data_pos = vector(self.bank.bank_center.x,
data_gap - self.data_dff.height) data_gap - self.data_dff.height)
self.add_data_dff(data_pos) self.place_inst(self.data_dff.name,
offset=data_pos)
# two supply rails are already included in the bank, so just 2 here. # two supply rails are already included in the bank, so just 2 here.
self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch self.width = self.bank.width + self.control_logic.width + 2*self.supply_rail_pitch
self.height = self.bank.height self.height = self.bank.height
def add_layout_pins(self): def add_layout_pins(self):
""" """
Add the top-level pins for a single bank SRAM with control. Add the top-level pins for a single bank SRAM with control.

View File

@ -32,6 +32,8 @@ class sram_base(design):
self.num_words = num_words self.num_words = num_words
self.num_banks = num_banks self.num_banks = num_banks
self.bank_insts = []
def compute_sizes(self): def compute_sizes(self):
""" Computes the organization of the memory using bitcell size by trying to make it square.""" """ Computes the organization of the memory using bitcell size by trying to make it square."""
@ -114,12 +116,17 @@ class sram_base(design):
self.add_pin("gnd","GROUND") self.add_pin("gnd","GROUND")
def create_netlist(self):
""" Netlist creation """
self.add_modules()
self.add_pins()
def create_layout(self): def create_layout(self):
""" Layout creation """ """ Layout creation """
self.add_modules() self.place_modules()
self.route() self.route()
self.add_lvs_correspondence_points() self.add_lvs_correspondence_points()
def compute_bus_sizes(self): def compute_bus_sizes(self):
""" Compute the independent bus widths shared between two and four bank SRAMs """ """ Compute the independent bus widths shared between two and four bank SRAMs """
@ -235,7 +242,7 @@ class sram_base(design):
self.copy_layout_pin(inst, "gnd") self.copy_layout_pin(inst, "gnd")
def create_multi_bank_modules(self): def add_multi_bank_modules(self):
""" Create the multibank address flops and bank decoder """ """ Create the multibank address flops and bank decoder """
from dff_buf_array import dff_buf_array from dff_buf_array import dff_buf_array
self.msb_address = dff_buf_array(name="msb_address", self.msb_address = dff_buf_array(name="msb_address",
@ -247,7 +254,7 @@ class sram_base(design):
self.msb_decoder = self.bank.decoder.pre2_4 self.msb_decoder = self.bank.decoder.pre2_4
self.add_mod(self.msb_decoder) self.add_mod(self.msb_decoder)
def create_modules(self): def add_modules(self):
""" Create all the modules that will be used """ """ Create all the modules that will be used """
from control_logic import control_logic from control_logic import control_logic
@ -280,7 +287,7 @@ class sram_base(design):
# Create bank decoder # Create bank decoder
if(self.num_banks > 1): if(self.num_banks > 1):
self.create_multi_bank_modules() self.add_multi_bank_modules()
self.bank_count = 0 self.bank_count = 0
@ -289,7 +296,28 @@ class sram_base(design):
def add_bank(self, bank_num, position, x_flip, y_flip): def create_bank(self):
""" Create a bank """
bank_num = len(self.bank_insts)
self.bank_insts.append(self.add_inst(name="bank{0}".format(bank_num),
mod=self.bank))
temp = []
for i in range(self.word_size):
temp.append("DOUT[{0}]".format(i))
for i in range(self.word_size):
temp.append("BANK_DIN[{0}]".format(i))
for i in range(self.bank_addr_size):
temp.append("A[{0}]".format(i))
if(self.num_banks > 1):
temp.append("bank_sel[{0}]".format(bank_num))
temp.extend(["s_en0", "w_en0", "clk_buf_bar","clk_buf" , "vdd", "gnd"])
self.connect_inst(temp)
return self.bank_insts[-1]
def place_bank(self, bank_inst, position, x_flip, y_flip):
""" Place a bank at the given position with orientations """ """ Place a bank at the given position with orientations """
# x_flip == 1 --> no flip in x_axis # x_flip == 1 --> no flip in x_axis
@ -313,32 +341,19 @@ class sram_base(design):
else: else:
bank_mirror = "R0" bank_mirror = "R0"
bank_inst=self.add_inst(name="bank{0}".format(bank_num), self.place_inst(name=bank_inst.name,
mod=self.bank, offset=position,
offset=position, mirror=bank_mirror,
mirror=bank_mirror, rotate=bank_rotation)
rotate=bank_rotation)
temp = []
for i in range(self.word_size):
temp.append("DOUT[{0}]".format(i))
for i in range(self.word_size):
temp.append("BANK_DIN[{0}]".format(i))
for i in range(self.bank_addr_size):
temp.append("A[{0}]".format(i))
if(self.num_banks > 1):
temp.append("bank_sel[{0}]".format(bank_num))
temp.extend(["s_en0", "w_en0", "clk_buf_bar","clk_buf" , "vdd", "gnd"])
self.connect_inst(temp)
return bank_inst return bank_inst
def add_row_addr_dff(self, position): def create_row_addr_dff(self):
""" Add and place all address flops for the main decoder """ """ Add all address flops for the main decoder """
self.row_addr_dff_inst = self.add_inst(name="row_address", inst = self.add_inst(name="row_address",
mod=self.row_addr_dff, mod=self.row_addr_dff)
offset=position)
# inputs, outputs/output/bar # inputs, outputs/output/bar
inputs = [] inputs = []
outputs = [] outputs = []
@ -347,13 +362,13 @@ class sram_base(design):
outputs.append("A[{}]".format(i+self.col_addr_size)) outputs.append("A[{}]".format(i+self.col_addr_size))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"]) self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst
def add_col_addr_dff(self, position): def create_col_addr_dff(self):
""" Add and place all address flops for the column decoder """ """ Add and place all address flops for the column decoder """
self.col_addr_dff_inst = self.add_inst(name="row_address", inst = self.add_inst(name="col_address",
mod=self.col_addr_dff, mod=self.col_addr_dff)
offset=position)
# inputs, outputs/output/bar # inputs, outputs/output/bar
inputs = [] inputs = []
outputs = [] outputs = []
@ -362,12 +377,13 @@ class sram_base(design):
outputs.append("A[{}]".format(i)) outputs.append("A[{}]".format(i))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"]) self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst
def add_data_dff(self, position):
def create_data_dff(self):
""" Add and place all data flops """ """ Add and place all data flops """
self.data_dff_inst = self.add_inst(name="data_dff", inst = self.add_inst(name="data_dff",
mod=self.data_dff, mod=self.data_dff)
offset=position)
# inputs, outputs/output/bar # inputs, outputs/output/bar
inputs = [] inputs = []
outputs = [] outputs = []
@ -376,15 +392,16 @@ class sram_base(design):
outputs.append("BANK_DIN[{}]".format(i)) outputs.append("BANK_DIN[{}]".format(i))
self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"]) self.connect_inst(inputs + outputs + ["clk_buf", "vdd", "gnd"])
return inst
def add_control_logic(self, position): def create_control_logic(self):
""" Add and place control logic """ """ Add and place control logic """
self.control_logic_inst=self.add_inst(name="control", inst = self.add_inst(name="control",
mod=self.control_logic, mod=self.control_logic)
offset=position)
self.connect_inst(self.control_logic_inputs + self.control_logic_outputs + ["vdd", "gnd"]) self.connect_inst(self.control_logic_inputs + self.control_logic_outputs + ["vdd", "gnd"])
return inst