mirror of https://github.com/VLSIDA/OpenRAM.git
PEP8 Formatting
This commit is contained in:
parent
7adeef6c9e
commit
9c1f0657dd
|
|
@ -17,9 +17,9 @@ from globals import OPTS
|
|||
class bank(design.design):
|
||||
"""
|
||||
Dynamically generated a single bank including bitcell array,
|
||||
hierarchical_decoder, precharge, (optional column_mux and column decoder),
|
||||
hierarchical_decoder, precharge, (optional column_mux and column decoder),
|
||||
write driver and sense amplifiers.
|
||||
This can create up to two ports in any combination: rw, w, r.
|
||||
This can create up to two ports in any combination: rw, w, r.
|
||||
"""
|
||||
|
||||
def __init__(self, sram_config, name=""):
|
||||
|
|
@ -27,15 +27,15 @@ class bank(design.design):
|
|||
self.sram_config = sram_config
|
||||
sram_config.set_local_config(self)
|
||||
if self.write_size:
|
||||
self.num_wmasks = int(self.word_size/self.write_size)
|
||||
self.num_wmasks = int(self.word_size / self.write_size)
|
||||
else:
|
||||
self.num_wmasks = 0
|
||||
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(self.word_size, self.num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,self.num_words))
|
||||
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(self.word_size,
|
||||
self.num_words))
|
||||
|
||||
# The local control signals are gated when we have bank select logic,
|
||||
# so this prefix will be added to all of the input signals to create
|
||||
|
|
@ -47,18 +47,17 @@ class bank(design.design):
|
|||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
debug.check(len(self.all_ports)<=2,"Bank layout cannot handle more than two ports.")
|
||||
debug.check(len(self.all_ports)<=2,
|
||||
"Bank layout cannot handle more than two ports.")
|
||||
self.create_layout()
|
||||
self.add_boundary()
|
||||
|
||||
|
||||
def create_netlist(self):
|
||||
|
||||
self.compute_sizes()
|
||||
self.add_modules()
|
||||
self.add_pins() # Must create the replica bitcell array first
|
||||
self.create_instances()
|
||||
|
||||
|
||||
def create_layout(self):
|
||||
self.place_instances()
|
||||
|
|
@ -66,35 +65,34 @@ class bank(design.design):
|
|||
self.route_layout()
|
||||
|
||||
# Can remove the following, but it helps for debug!
|
||||
#self.add_lvs_correspondence_points()
|
||||
# self.add_lvs_correspondence_points()
|
||||
|
||||
# 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_ul = self.bitcell_array_inst.ul()
|
||||
|
||||
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
""" Adding pins for Bank module"""
|
||||
for port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
self.add_pin("dout{0}_{1}".format(port,bit),"OUTPUT")
|
||||
self.add_pin("dout{0}_{1}".format(port, bit), "OUTPUT")
|
||||
for port in self.all_ports:
|
||||
self.add_pin(self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port]),"OUTPUT")
|
||||
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):
|
||||
self.add_pin("din{0}_{1}".format(port,bit),"INPUT")
|
||||
self.add_pin("din{0}_{1}".format(port,bit), "INPUT")
|
||||
for port in self.all_ports:
|
||||
for bit in range(self.addr_size):
|
||||
self.add_pin("addr{0}_{1}".format(port,bit),"INPUT")
|
||||
self.add_pin("addr{0}_{1}".format(port,bit), "INPUT")
|
||||
|
||||
# For more than one bank, we have a bank select and name
|
||||
# the signals gated_*.
|
||||
if self.num_banks > 1:
|
||||
for port in self.all_ports:
|
||||
self.add_pin("bank_sel{}".format(port),"INPUT")
|
||||
self.add_pin("bank_sel{}".format(port), "INPUT")
|
||||
for port in self.read_ports:
|
||||
self.add_pin("s_en{0}".format(port), "INPUT")
|
||||
for port in self.all_ports:
|
||||
|
|
@ -102,12 +100,11 @@ class bank(design.design):
|
|||
for port in self.write_ports:
|
||||
self.add_pin("w_en{0}".format(port), "INPUT")
|
||||
for bit in range(self.num_wmasks):
|
||||
self.add_pin("bank_wmask{0}_{1}".format(port,bit),"INPUT")
|
||||
self.add_pin("bank_wmask{0}_{1}".format(port, bit), "INPUT")
|
||||
for port in self.all_ports:
|
||||
self.add_pin("wl_en{0}".format(port), "INPUT")
|
||||
self.add_pin("vdd","POWER")
|
||||
self.add_pin("gnd","GROUND")
|
||||
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def route_layout(self):
|
||||
""" Create routing amoung the modules """
|
||||
|
|
@ -124,7 +121,7 @@ class bank(design.design):
|
|||
|
||||
self.route_supplies()
|
||||
|
||||
def route_rbl(self,port):
|
||||
def route_rbl(self, port):
|
||||
""" Route the rbl_bl and rbl_wl """
|
||||
|
||||
bl_pin_name = self.bitcell_array.get_rbl_bl_name(self.port_rbl_map[port])
|
||||
|
|
@ -135,8 +132,6 @@ class bank(design.design):
|
|||
height=bl_pin.height(),
|
||||
width=bl_pin.width())
|
||||
|
||||
|
||||
|
||||
def route_bitlines(self, port):
|
||||
""" Route the bitlines depending on the port type rw, w, or r. """
|
||||
|
||||
|
|
@ -146,7 +141,6 @@ class bank(design.design):
|
|||
self.route_port_data_out(port)
|
||||
self.route_port_data_to_bitcell_array(port)
|
||||
|
||||
|
||||
def create_instances(self):
|
||||
""" Create the instances of the netlist. """
|
||||
|
||||
|
|
@ -161,19 +155,18 @@ class bank(design.design):
|
|||
Compute the empty instance offsets for port0 and port1 (if needed)
|
||||
"""
|
||||
|
||||
self.port_data_offsets = [None]*len(self.all_ports)
|
||||
self.port_address_offsets = [None]*len(self.all_ports)
|
||||
|
||||
self.column_decoder_offsets = [None]*len(self.all_ports)
|
||||
self.bank_select_offsets = [None]*len(self.all_ports)
|
||||
self.port_data_offsets = [None] * len(self.all_ports)
|
||||
self.port_address_offsets = [None] * len(self.all_ports)
|
||||
|
||||
self.column_decoder_offsets = [None] * len(self.all_ports)
|
||||
self.bank_select_offsets = [None] * len(self.all_ports)
|
||||
|
||||
# The center point for these cells are the upper-right corner of
|
||||
# the bitcell array.
|
||||
# The port address decoder/driver logic is placed on the right and mirrored on Y-axis.
|
||||
# The port data write/sense/precharge/mux is placed on the top and mirrored on the X-axis.
|
||||
self.bitcell_array_top = self.bitcell_array.height
|
||||
self.bitcell_array_right = self.bitcell_array.width
|
||||
self.bitcell_array_top = self.bitcell_array.height
|
||||
self.bitcell_array_right = self.bitcell_array.width
|
||||
|
||||
# These are the offsets of the main array (excluding dummy and replica rows/cols)
|
||||
self.main_bitcell_array_top = self.bitcell_array.bitcell_array_inst.uy()
|
||||
|
|
@ -185,7 +178,6 @@ class bank(design.design):
|
|||
self.compute_instance_port0_offsets()
|
||||
if len(self.all_ports)==2:
|
||||
self.compute_instance_port1_offsets()
|
||||
|
||||
|
||||
def compute_instance_port0_offsets(self):
|
||||
"""
|
||||
|
|
@ -196,29 +188,30 @@ class bank(design.design):
|
|||
|
||||
# UPPER RIGHT QUADRANT
|
||||
# Bitcell array is placed at (0,0)
|
||||
self.bitcell_array_offset = vector(0,0)
|
||||
self.bitcell_array_offset = vector(0, 0)
|
||||
|
||||
# LOWER RIGHT QUADRANT
|
||||
# Below the bitcell array
|
||||
self.port_data_offsets[port] = vector(self.main_bitcell_array_left - self.bitcell_array.cell.width,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
|
||||
x_offset = self.m2_gap + self.port_address.width
|
||||
self.port_address_offsets[port] = vector(-x_offset,self.main_bitcell_array_bottom)
|
||||
x_offset = self.m2_gap + self.port_address.width
|
||||
self.port_address_offsets[port] = vector(-x_offset,
|
||||
self.main_bitcell_array_bottom)
|
||||
|
||||
# LOWER LEFT QUADRANT
|
||||
# Place the col decoder left aligned with wordline driver
|
||||
# Place the col decoder left aligned with wordline driver
|
||||
# This is also placed so that it's supply rails do not align with the SRAM-level
|
||||
# control logic to allow control signals to easily pass over in M3
|
||||
# by placing 1/2 a cell pitch down
|
||||
x_offset = self.central_bus_width[port] + self.port_address.wordline_driver.width
|
||||
if self.col_addr_size > 0:
|
||||
x_offset += self.column_decoder.width + self.col_addr_bus_width
|
||||
y_offset = 0.5*self.dff.height + self.column_decoder.height
|
||||
y_offset = 0.5 * self.dff.height + self.column_decoder.height
|
||||
else:
|
||||
y_offset = 0
|
||||
self.column_decoder_offsets[port] = vector(-x_offset,-y_offset)
|
||||
self.column_decoder_offsets[port] = vector(-x_offset, -y_offset)
|
||||
|
||||
# Bank select gets placed below the column decoder (x_offset doesn't change)
|
||||
if self.col_addr_size > 0:
|
||||
|
|
@ -227,7 +220,7 @@ class bank(design.design):
|
|||
y_offset = self.port_address_offsets[port].y
|
||||
if self.num_banks > 1:
|
||||
y_offset += self.bank_select.height + drc("well_to_well")
|
||||
self.bank_select_offsets[port] = vector(-x_offset,-y_offset)
|
||||
self.bank_select_offsets[port] = vector(-x_offset, -y_offset)
|
||||
|
||||
def compute_instance_port1_offsets(self):
|
||||
"""
|
||||
|
|
@ -246,18 +239,19 @@ class bank(design.design):
|
|||
# LOWER RIGHT QUADRANT
|
||||
# To the left of the bitcell array
|
||||
x_offset = self.bitcell_array_right + self.port_address.width + self.m2_gap
|
||||
self.port_address_offsets[port] = vector(x_offset,self.main_bitcell_array_bottom)
|
||||
self.port_address_offsets[port] = vector(x_offset,
|
||||
self.main_bitcell_array_bottom)
|
||||
|
||||
# UPPER RIGHT QUADRANT
|
||||
# Place the col decoder right aligned with wordline driver
|
||||
# Place the col decoder right aligned with wordline driver
|
||||
# Above the bitcell array with a well spacing
|
||||
x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width
|
||||
x_offset = self.bitcell_array_right + self.central_bus_width[port] + self.port_address.wordline_driver.width
|
||||
if self.col_addr_size > 0:
|
||||
x_offset += self.column_decoder.width + self.col_addr_bus_width
|
||||
y_offset = self.bitcell_array_top + 0.5*self.dff.height + self.column_decoder.height
|
||||
y_offset = self.bitcell_array_top + 0.5 * self.dff.height + self.column_decoder.height
|
||||
else:
|
||||
y_offset = self.bitcell_array_top
|
||||
self.column_decoder_offsets[port] = vector(x_offset,y_offset)
|
||||
self.column_decoder_offsets[port] = vector(x_offset, y_offset)
|
||||
|
||||
# Bank select gets placed above the column decoder (x_offset doesn't change)
|
||||
if self.col_addr_size > 0:
|
||||
|
|
@ -265,7 +259,7 @@ class bank(design.design):
|
|||
self.port_data[port].column_mux_offset.y + self.port_data[port].column_mux_array.height)
|
||||
else:
|
||||
y_offset = self.port_address_offsets[port].y
|
||||
self.bank_select_offsets[port] = vector(x_offset,y_offset)
|
||||
self.bank_select_offsets[port] = vector(x_offset, y_offset)
|
||||
|
||||
def place_instances(self):
|
||||
""" Place the instances. """
|
||||
|
|
@ -281,19 +275,20 @@ class bank(design.design):
|
|||
self.place_column_decoder(self.column_decoder_offsets)
|
||||
self.place_bank_select(self.bank_select_offsets)
|
||||
|
||||
|
||||
def compute_sizes(self):
|
||||
""" Computes the required sizes to create the bank """
|
||||
|
||||
self.num_cols = int(self.words_per_row*self.word_size)
|
||||
self.num_cols = int(self.words_per_row * self.word_size)
|
||||
self.num_rows = int(self.num_words / self.words_per_row)
|
||||
|
||||
self.row_addr_size = int(log(self.num_rows, 2))
|
||||
self.col_addr_size = int(log(self.words_per_row, 2))
|
||||
self.addr_size = self.col_addr_size + self.row_addr_size
|
||||
|
||||
debug.check(self.num_rows*self.num_cols==self.word_size*self.num_words,"Invalid bank sizes.")
|
||||
debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,"Invalid address break down.")
|
||||
debug.check(self.num_rows * self.num_cols==self.word_size * self.num_words,
|
||||
"Invalid bank sizes.")
|
||||
debug.check(self.addr_size==self.col_addr_size + self.row_addr_size,
|
||||
"Invalid address break down.")
|
||||
|
||||
# The order of the control signals on the control bus:
|
||||
self.input_control_signals = []
|
||||
|
|
@ -312,13 +307,13 @@ class bank(design.design):
|
|||
self.num_control_lines = [len(x) for x in self.input_control_signals]
|
||||
|
||||
# The width of this bus is needed to place other modules (e.g. decoder) for each port
|
||||
self.central_bus_width = [self.m2_pitch*x + self.m2_width for x in self.num_control_lines]
|
||||
self.central_bus_width = [self.m2_pitch * x + self.m2_width for x in self.num_control_lines]
|
||||
|
||||
# These will be outputs of the gaters if this is multibank, if not, normal signals.
|
||||
self.control_signals = []
|
||||
for port in self.all_ports:
|
||||
if self.num_banks > 1:
|
||||
self.control_signals.append(["gated_"+str for str in self.input_control_signals[port]])
|
||||
self.control_signals.append(["gated_" + str for str in self.input_control_signals[port]])
|
||||
else:
|
||||
self.control_signals.append(self.input_control_signals[port])
|
||||
|
||||
|
|
@ -326,19 +321,18 @@ class bank(design.design):
|
|||
if self.col_addr_size>0:
|
||||
self.num_col_addr_lines = 2**self.col_addr_size
|
||||
else:
|
||||
self.num_col_addr_lines = 0
|
||||
self.col_addr_bus_width = self.m2_pitch*self.num_col_addr_lines
|
||||
self.num_col_addr_lines = 0
|
||||
self.col_addr_bus_width = self.m2_pitch * self.num_col_addr_lines
|
||||
|
||||
# A space for wells or jogging m2
|
||||
self.m2_gap = max(2*drc("pwell_to_nwell") + drc("nwell_enclose_active"),
|
||||
3*self.m2_pitch)
|
||||
|
||||
self.m2_gap = max(2 * drc("pwell_to_nwell") + drc("nwell_enclose_active"),
|
||||
3 * self.m2_pitch)
|
||||
|
||||
def add_modules(self):
|
||||
""" Add all the modules using the class loader """
|
||||
|
||||
# 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.br_names = self.bitcell.get_all_br_names()
|
||||
self.wl_names = self.bitcell.get_all_wl_names()
|
||||
|
|
@ -352,13 +346,11 @@ class bank(design.design):
|
|||
self.port_data.append(temp_pre)
|
||||
self.add_mod(self.port_data[port])
|
||||
|
||||
|
||||
self.port_address = factory.create(module_type="port_address",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.port_address)
|
||||
|
||||
|
||||
self.port_rbl_map = self.all_ports
|
||||
self.num_rbl = len(self.all_ports)
|
||||
|
||||
|
|
@ -370,22 +362,20 @@ class bank(design.design):
|
|||
bitcell_ports=self.all_ports)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
|
||||
if(self.num_banks > 1):
|
||||
self.bank_select = factory.create(module_type="bank_select")
|
||||
self.add_mod(self.bank_select)
|
||||
|
||||
|
||||
def create_bitcell_array(self):
|
||||
""" Creating Bitcell Array """
|
||||
|
||||
self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array",
|
||||
self.bitcell_array_inst=self.add_inst(name="replica_bitcell_array",
|
||||
mod=self.bitcell_array)
|
||||
|
||||
temp = []
|
||||
for col in range(self.num_cols):
|
||||
for bitline in self.bitline_names:
|
||||
temp.append("{0}_{1}".format(bitline,col))
|
||||
temp.append("{0}_{1}".format(bitline, col))
|
||||
for rbl in range(self.num_rbl):
|
||||
rbl_bl_name=self.bitcell_array.get_rbl_bl_name(rbl)
|
||||
temp.append(rbl_bl_name)
|
||||
|
|
@ -393,23 +383,21 @@ class bank(design.design):
|
|||
temp.append(rbl_br_name)
|
||||
for row in range(self.num_rows):
|
||||
for wordline in self.wl_names:
|
||||
temp.append("{0}_{1}".format(wordline,row))
|
||||
temp.append("{0}_{1}".format(wordline, row))
|
||||
for port in self.all_ports:
|
||||
temp.append("wl_en{0}".format(port))
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def place_bitcell_array(self, offset):
|
||||
""" Placing Bitcell Array """
|
||||
self.bitcell_array_inst.place(offset)
|
||||
|
||||
|
||||
def create_port_data(self):
|
||||
""" Creating Port Data """
|
||||
|
||||
self.port_data_inst = [None]*len(self.all_ports)
|
||||
self.port_data_inst = [None] * len(self.all_ports)
|
||||
for port in self.all_ports:
|
||||
self.port_data_inst[port]=self.add_inst(name="port_data{}".format(port),
|
||||
mod=self.port_data[port])
|
||||
|
|
@ -419,17 +407,17 @@ class bank(design.design):
|
|||
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))
|
||||
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))
|
||||
if port in self.read_ports:
|
||||
for bit in range(self.word_size):
|
||||
temp.append("dout{0}_{1}".format(port,bit))
|
||||
temp.append("dout{0}_{1}".format(port, bit))
|
||||
if port in self.write_ports:
|
||||
for bit in range(self.word_size):
|
||||
temp.append("din{0}_{1}".format(port,bit))
|
||||
temp.append("din{0}_{1}".format(port, bit))
|
||||
# Will be empty if no col addr lines
|
||||
sel_names = ["sel{0}_{1}".format(port,x) for x in range(self.num_col_addr_lines)]
|
||||
sel_names = ["sel{0}_{1}".format(port, x) for x in range(self.num_col_addr_lines)]
|
||||
temp.extend(sel_names)
|
||||
if port in self.read_ports:
|
||||
temp.append("s_en{0}".format(port))
|
||||
|
|
@ -438,17 +426,16 @@ class bank(design.design):
|
|||
temp.append("w_en{0}".format(port))
|
||||
for bit in range(self.num_wmasks):
|
||||
temp.append("bank_wmask{0}_{1}".format(port, bit))
|
||||
temp.extend(["vdd","gnd"])
|
||||
temp.extend(["vdd", "gnd"])
|
||||
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def place_port_data(self, offsets):
|
||||
""" Placing Port Data """
|
||||
|
||||
for port in self.all_ports:
|
||||
# Top one is unflipped, bottom is flipped along X direction
|
||||
if port%2 == 1:
|
||||
if port % 2 == 1:
|
||||
mirror = "R0"
|
||||
else:
|
||||
mirror = "MX"
|
||||
|
|
@ -457,42 +444,40 @@ class bank(design.design):
|
|||
def create_port_address(self):
|
||||
""" Create the hierarchical row decoder """
|
||||
|
||||
self.port_address_inst = [None]*len(self.all_ports)
|
||||
self.port_address_inst = [None] * len(self.all_ports)
|
||||
for port in self.all_ports:
|
||||
self.port_address_inst[port] = self.add_inst(name="port_address{}".format(port),
|
||||
self.port_address_inst[port] = self.add_inst(name="port_address{}".format(port),
|
||||
mod=self.port_address)
|
||||
|
||||
temp = []
|
||||
for bit in range(self.row_addr_size):
|
||||
temp.append("addr{0}_{1}".format(port,bit+self.col_addr_size))
|
||||
temp.append("addr{0}_{1}".format(port, bit + self.col_addr_size))
|
||||
temp.append("wl_en{0}".format(port))
|
||||
for row in range(self.num_rows):
|
||||
temp.append("{0}_{1}".format(self.wl_names[port],row))
|
||||
temp.append("{0}_{1}".format(self.wl_names[port], row))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def place_port_address(self, offsets):
|
||||
""" Place the hierarchical row decoder """
|
||||
|
||||
debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place row decoder array.")
|
||||
|
||||
# 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 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.
|
||||
|
||||
for port in self.all_ports:
|
||||
if port%2:
|
||||
if port % 2:
|
||||
mirror = "MY"
|
||||
else:
|
||||
mirror = "R0"
|
||||
self.port_address_inst[port].place(offset=offsets[port], mirror=mirror)
|
||||
|
||||
|
||||
def create_column_decoder(self):
|
||||
"""
|
||||
"""
|
||||
Create a 2:4 or 3:8 column address decoder.
|
||||
"""
|
||||
|
||||
|
|
@ -510,40 +495,38 @@ class bank(design.design):
|
|||
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=self.dff.height)
|
||||
else:
|
||||
# No error checking before?
|
||||
debug.error("Invalid column decoder?",-1)
|
||||
debug.error("Invalid column decoder?", -1)
|
||||
self.add_mod(self.column_decoder)
|
||||
|
||||
self.column_decoder_inst = [None]*len(self.all_ports)
|
||||
self.column_decoder_inst = [None] * len(self.all_ports)
|
||||
for port in self.all_ports:
|
||||
self.column_decoder_inst[port] = self.add_inst(name="col_address_decoder{}".format(port),
|
||||
self.column_decoder_inst[port] = self.add_inst(name="col_address_decoder{}".format(port),
|
||||
mod=self.column_decoder)
|
||||
|
||||
temp = []
|
||||
for bit in range(self.col_addr_size):
|
||||
temp.append("addr{0}_{1}".format(port,bit))
|
||||
temp.append("addr{0}_{1}".format(port, bit))
|
||||
for bit in range(self.num_col_addr_lines):
|
||||
temp.append("sel{0}_{1}".format(port,bit))
|
||||
temp.append("sel{0}_{1}".format(port, bit))
|
||||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def place_column_decoder(self, offsets):
|
||||
"""
|
||||
"""
|
||||
Place a 2:4 or 3:8 column address decoder.
|
||||
"""
|
||||
if self.col_addr_size == 0:
|
||||
return
|
||||
|
||||
debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place column decoder.")
|
||||
debug.check(len(offsets)>=len(self.all_ports),
|
||||
"Insufficient offsets to place column decoder.")
|
||||
|
||||
for port in self.all_ports:
|
||||
if port%2 == 1:
|
||||
if port % 2 == 1:
|
||||
mirror = "XY"
|
||||
else:
|
||||
mirror = "R0"
|
||||
self.column_decoder_inst[port].place(offset=offsets[port], mirror=mirror)
|
||||
|
||||
|
||||
|
||||
def create_bank_select(self):
|
||||
""" Create the bank select logic. """
|
||||
|
|
@ -551,7 +534,7 @@ class bank(design.design):
|
|||
if not self.num_banks > 1:
|
||||
return
|
||||
|
||||
self.bank_select_inst = [None]*len(self.all_ports)
|
||||
self.bank_select_inst = [None] * len(self.all_ports)
|
||||
for port in self.all_ports:
|
||||
self.bank_select_inst[port] = self.add_inst(name="bank_select{}".format(port),
|
||||
mod=self.bank_select)
|
||||
|
|
@ -563,24 +546,23 @@ class bank(design.design):
|
|||
temp.extend(["vdd", "gnd"])
|
||||
self.connect_inst(temp)
|
||||
|
||||
|
||||
def place_bank_select(self, offsets):
|
||||
""" Place the bank select logic. """
|
||||
|
||||
if not self.num_banks > 1:
|
||||
return
|
||||
|
||||
debug.check(len(offsets)>=len(self.all_ports), "Insufficient offsets to place bank select logic.")
|
||||
debug.check(len(offsets)>=len(self.all_ports),
|
||||
"Insufficient offsets to place bank select logic.")
|
||||
|
||||
for port in self.all_ports:
|
||||
self.bank_select_inst[port].place(offsets[port])
|
||||
|
||||
|
||||
def route_supplies(self):
|
||||
""" Propagate all vdd/gnd pins up to this level for all modules """
|
||||
for inst in self.insts:
|
||||
self.copy_power_pins(inst,"vdd")
|
||||
self.copy_power_pins(inst,"gnd")
|
||||
self.copy_power_pins(inst, "vdd")
|
||||
self.copy_power_pins(inst, "gnd")
|
||||
|
||||
def route_bank_select(self, port):
|
||||
""" Route the bank select logic. """
|
||||
|
|
@ -595,7 +577,7 @@ class bank(design.design):
|
|||
bank_sel_signals = ["clk_buf", "s_en", "p_en_bar", "bank_sel"]
|
||||
gated_bank_sel_signals = ["gated_clk_buf", "gated_s_en", "gated_p_en_bar"]
|
||||
|
||||
copy_control_signals = self.input_control_signals[port]+["bank_sel{}".format(port)]
|
||||
copy_control_signals = self.input_control_signals[port] + ["bank_sel{}".format(port)]
|
||||
for signal in range(len(copy_control_signals)):
|
||||
self.copy_layout_pin(self.bank_select_inst[port], bank_sel_signals[signal], copy_control_signals[signal])
|
||||
|
||||
|
|
@ -604,25 +586,24 @@ class bank(design.design):
|
|||
out_pos = self.bank_select_inst[port].get_pin(gated_bank_sel_signals[signal]).rc()
|
||||
name = self.control_signals[port][signal]
|
||||
bus_pos = vector(self.bus_xoffset[port][name].x, out_pos.y)
|
||||
self.add_path("m3",[out_pos, bus_pos])
|
||||
self.add_path("m3", [out_pos, bus_pos])
|
||||
self.add_via_center(layers=self.m2_stack,
|
||||
offset=bus_pos)
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=out_pos)
|
||||
self.add_via_center(layers=self.m2_stack,
|
||||
offset=out_pos)
|
||||
|
||||
|
||||
def setup_routing_constraints(self):
|
||||
"""
|
||||
"""
|
||||
After the modules are instantiated, find the dimensions for the
|
||||
control bus, power ring, etc.
|
||||
control bus, power ring, etc.
|
||||
"""
|
||||
|
||||
self.max_y_offset = max([x.uy() for x in self.insts]) + 3*self.m1_width
|
||||
self.max_y_offset = max([x.uy() for x in self.insts]) + 3 * self.m1_width
|
||||
self.min_y_offset = min([x.by() for x in self.insts])
|
||||
|
||||
self.max_x_offset = max([x.rx() for x in self.insts]) + 3*self.m1_width
|
||||
self.max_x_offset = max([x.rx() for x in self.insts]) + 3 * self.m1_width
|
||||
self.min_x_offset = min([x.lx() for x in self.insts])
|
||||
|
||||
# # Create the core bbox for the power rings
|
||||
|
|
@ -632,7 +613,6 @@ class bank(design.design):
|
|||
|
||||
self.height = ur.y - ll.y
|
||||
self.width = ur.x - ll.x
|
||||
|
||||
|
||||
def route_central_bus(self):
|
||||
""" Create the address, supply, and control signal central bus lines. """
|
||||
|
|
@ -640,13 +620,13 @@ class bank(design.design):
|
|||
# Overall central bus width. It includes all the column mux lines,
|
||||
# and control lines.
|
||||
|
||||
self.bus_xoffset = [None]*len(self.all_ports)
|
||||
self.bus_xoffset = [None] * len(self.all_ports)
|
||||
# Port 0
|
||||
# The bank is at (0,0), so this is to the left of the y-axis.
|
||||
# 2 pitches on the right for vias/jogs to access the inputs
|
||||
# 2 pitches on the right for vias/jogs to access the inputs
|
||||
control_bus_offset = vector(-self.m2_pitch * self.num_control_lines[0] - self.m2_pitch, self.min_y_offset)
|
||||
# The control bus is routed up to two pitches below the bitcell array
|
||||
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2*self.m1_pitch
|
||||
control_bus_length = self.main_bitcell_array_bottom - self.min_y_offset - 2 * self.m1_pitch
|
||||
self.bus_xoffset[0] = self.create_bus(layer="m2",
|
||||
pitch=self.m2_pitch,
|
||||
offset=control_bus_offset,
|
||||
|
|
@ -658,7 +638,7 @@ class bank(design.design):
|
|||
# Port 1
|
||||
if len(self.all_ports)==2:
|
||||
# The other control bus is routed up to two pitches above the bitcell array
|
||||
control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2*self.m1_pitch
|
||||
control_bus_length = self.max_y_offset - self.main_bitcell_array_top - 2 * self.m1_pitch
|
||||
control_bus_offset = vector(self.bitcell_array_right + self.m2_pitch,
|
||||
self.max_y_offset - control_bus_length)
|
||||
# The bus for the right port is reversed so that the rbl_wl is closest to the array
|
||||
|
|
@ -669,7 +649,6 @@ class bank(design.design):
|
|||
length=control_bus_length,
|
||||
vertical=True,
|
||||
make_pins=(self.num_banks==1))
|
||||
|
||||
|
||||
def route_port_data_to_bitcell_array(self, port):
|
||||
""" Routing of BL and BR between port data and bitcell array """
|
||||
|
|
@ -677,11 +656,11 @@ class bank(design.design):
|
|||
# Connect the regular bitlines
|
||||
inst2 = self.port_data_inst[port]
|
||||
inst1 = self.bitcell_array_inst
|
||||
inst1_bl_name = self.bl_names[port]+"_{}"
|
||||
inst1_br_name = self.br_names[port]+"_{}"
|
||||
inst1_bl_name = self.bl_names[port] + "_{}"
|
||||
inst1_br_name = self.br_names[port] + "_{}"
|
||||
|
||||
inst2_bl_name = inst2.mod.get_bl_names()+"_{}"
|
||||
inst2_br_name = inst2.mod.get_br_names()+"_{}"
|
||||
inst2_bl_name = inst2.mod.get_bl_names() + "_{}"
|
||||
inst2_br_name = inst2.mod.get_br_names() + "_{}"
|
||||
|
||||
self.connect_bitlines(inst1=inst1, inst2=inst2, num_bits=self.num_cols,
|
||||
inst1_bl_name=inst1_bl_name, inst1_br_name=inst1_br_name,
|
||||
|
|
@ -693,20 +672,17 @@ class bank(design.design):
|
|||
self.connect_bitline(inst1, inst2, rbl_bl_name, "rbl_bl")
|
||||
self.connect_bitline(inst1, inst2, rbl_br_name, "rbl_br")
|
||||
|
||||
|
||||
|
||||
def route_port_data_out(self, port):
|
||||
""" Add pins for the port data out """
|
||||
|
||||
for bit in range(self.word_size):
|
||||
data_pin = self.port_data_inst[port].get_pin("dout_{0}".format(bit))
|
||||
self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port,bit),
|
||||
layer=data_pin.layer,
|
||||
self.add_layout_pin_rect_center(text="dout{0}_{1}".format(port, bit),
|
||||
layer=data_pin.layer,
|
||||
offset=data_pin.center(),
|
||||
height=data_pin.height(),
|
||||
width=data_pin.width())
|
||||
|
||||
|
||||
def route_port_address_in(self, port):
|
||||
""" Routes the row decoder inputs and supplies """
|
||||
|
||||
|
|
@ -714,17 +690,15 @@ class bank(design.design):
|
|||
for row in range(self.row_addr_size):
|
||||
addr_idx = row + self.col_addr_size
|
||||
decoder_name = "addr_{}".format(row)
|
||||
addr_name = "addr{0}_{1}".format(port,addr_idx)
|
||||
addr_name = "addr{0}_{1}".format(port, addr_idx)
|
||||
self.copy_layout_pin(self.port_address_inst[port], decoder_name, addr_name)
|
||||
|
||||
|
||||
|
||||
def route_port_data_in(self, port):
|
||||
""" Connecting port data in """
|
||||
|
||||
for row in range(self.word_size):
|
||||
data_name = "din_{}".format(row)
|
||||
din_name = "din{0}_{1}".format(port,row)
|
||||
din_name = "din{0}_{1}".format(port, row)
|
||||
self.copy_layout_pin(self.port_data_inst[port], data_name, din_name)
|
||||
|
||||
if self.word_size:
|
||||
|
|
@ -732,8 +706,6 @@ class bank(design.design):
|
|||
wmask_name = "bank_wmask_{}".format(row)
|
||||
bank_wmask_name = "bank_wmask{0}_{1}".format(port, row)
|
||||
self.copy_layout_pin(self.port_data_inst[port], wmask_name, bank_wmask_name)
|
||||
|
||||
|
||||
|
||||
def channel_route_bitlines(self, inst1, inst2, num_bits,
|
||||
inst1_bl_name="bl_{}", inst1_br_name="br_{}",
|
||||
|
|
@ -751,19 +723,18 @@ class bank(design.design):
|
|||
(bottom_inst, bottom_bl_name, bottom_br_name) = (inst2, inst2_bl_name, inst2_br_name)
|
||||
(top_inst, top_bl_name, top_br_name) = (inst1, inst1_bl_name, inst1_br_name)
|
||||
|
||||
|
||||
# Channel route each mux separately since we don't minimize the number
|
||||
# of tracks in teh channel router yet. If we did, we could route all the bits at once!
|
||||
offset = bottom_inst.ul() + vector(0,self.m1_pitch)
|
||||
offset = bottom_inst.ul() + vector(0, self.m1_pitch)
|
||||
for bit in range(num_bits):
|
||||
bottom_names = [bottom_inst.get_pin(bottom_bl_name.format(bit)), bottom_inst.get_pin(bottom_br_name.format(bit))]
|
||||
top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))]
|
||||
top_names = [top_inst.get_pin(top_bl_name.format(bit)), top_inst.get_pin(top_br_name.format(bit))]
|
||||
route_map = list(zip(bottom_names, top_names))
|
||||
self.create_horizontal_channel_route(route_map, offset, self.m1_stack)
|
||||
|
||||
def connect_bitline(self, inst1, inst2, inst1_name, inst2_name):
|
||||
"""
|
||||
Connect two pins of two modules.
|
||||
Connect two pins of two modules.
|
||||
This assumes that they have sufficient space to create a jog
|
||||
in the middle between the two modules (if needed).
|
||||
"""
|
||||
|
|
@ -784,11 +755,13 @@ class bank(design.design):
|
|||
bottom_loc = bottom_pin.uc()
|
||||
top_loc = top_pin.bc()
|
||||
|
||||
yoffset = 0.5*(top_loc.y+bottom_loc.y)
|
||||
self.add_path(top_pin.layer,[bottom_loc, vector(bottom_loc.x,yoffset),
|
||||
vector(top_loc.x,yoffset), top_loc])
|
||||
yoffset = 0.5 * (top_loc.y + bottom_loc.y)
|
||||
self.add_path(top_pin.layer,
|
||||
[bottom_loc,
|
||||
vector(bottom_loc.x, yoffset),
|
||||
vector(top_loc.x, yoffset),
|
||||
top_loc])
|
||||
|
||||
|
||||
def connect_bitlines(self, inst1, inst2, num_bits,
|
||||
inst1_bl_name, inst1_br_name,
|
||||
inst2_bl_name, inst2_br_name):
|
||||
|
|
@ -799,14 +772,13 @@ class bank(design.design):
|
|||
for col in range(num_bits):
|
||||
self.connect_bitline(inst1, inst2, inst1_bl_name.format(col), inst2_bl_name.format(col))
|
||||
self.connect_bitline(inst1, inst2, inst1_br_name.format(col), inst2_br_name.format(col))
|
||||
|
||||
|
||||
def route_port_address(self, port):
|
||||
""" Connect Wordline driver to bitcell array wordline """
|
||||
|
||||
self.route_port_address_in(port)
|
||||
|
||||
if port%2:
|
||||
if port % 2:
|
||||
self.route_port_address_right(port)
|
||||
else:
|
||||
self.route_port_address_left(port)
|
||||
|
|
@ -817,21 +789,20 @@ class bank(design.design):
|
|||
for row in range(self.num_rows):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pos = self.port_address_inst[port].get_pin("wl_{}".format(row)).rc()
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).lc()
|
||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].rx() + 0.5*self.bitcell_array_inst.lx(),0)
|
||||
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0.5,1)
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port] + "_{}".format(row)).lc()
|
||||
mid1 = driver_wl_pos.scale(0, 1) + vector(0.5 * self.port_address_inst[port].rx() + 0.5 * self.bitcell_array_inst.lx(), 0)
|
||||
mid2 = mid1.scale(1, 0) + bitcell_wl_pos.scale(0.5, 1)
|
||||
self.add_path("m1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
|
||||
def route_port_address_right(self, port):
|
||||
""" Connecting Wordline driver output to Bitcell WL connection """
|
||||
|
||||
for row in range(self.num_rows):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pos = self.port_address_inst[port].get_pin("wl_{}".format(row)).lc()
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port]+"_{}".format(row)).rc()
|
||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.port_address_inst[port].lx() + 0.5*self.bitcell_array_inst.rx(),0)
|
||||
mid2 = mid1.scale(1,0)+bitcell_wl_pos.scale(0,1)
|
||||
bitcell_wl_pos = self.bitcell_array_inst.get_pin(self.wl_names[port] + "_{}".format(row)).rc()
|
||||
mid1 = driver_wl_pos.scale(0, 1) + vector(0.5 * self.port_address_inst[port].lx() + 0.5 * self.bitcell_array_inst.rx(), 0)
|
||||
mid2 = mid1.scale(1, 0) + bitcell_wl_pos.scale(0, 1)
|
||||
self.add_path("m1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
def route_column_address_lines(self, port):
|
||||
|
|
@ -845,7 +816,7 @@ class bank(design.design):
|
|||
decode_names = ["Zb", "Z"]
|
||||
|
||||
# The Address LSB
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], "A", "addr{}_0".format(port))
|
||||
|
||||
elif self.col_addr_size > 1:
|
||||
decode_names = []
|
||||
|
|
@ -854,11 +825,11 @@ class bank(design.design):
|
|||
|
||||
for i in range(self.col_addr_size):
|
||||
decoder_name = "in_{}".format(i)
|
||||
addr_name = "addr{0}_{1}".format(port,i)
|
||||
addr_name = "addr{0}_{1}".format(port, i)
|
||||
self.copy_layout_pin(self.column_decoder_inst[port], decoder_name, addr_name)
|
||||
|
||||
if port%2:
|
||||
offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines*self.m2_pitch, 0)
|
||||
if port % 2:
|
||||
offset = self.column_decoder_inst[port].ll() - vector(self.num_col_addr_lines * self.m2_pitch, 0)
|
||||
else:
|
||||
offset = self.column_decoder_inst[port].lr() + vector(self.m2_pitch, 0)
|
||||
|
||||
|
|
@ -871,7 +842,8 @@ class bank(design.design):
|
|||
self.create_vertical_channel_route(route_map, offset, self.m1_stack)
|
||||
|
||||
def add_lvs_correspondence_points(self):
|
||||
""" This adds some points for easier debugging if LVS goes wrong.
|
||||
"""
|
||||
This adds some points for easier debugging if LVS goes wrong.
|
||||
These should probably be turned off by default though, since extraction
|
||||
will show these as ports in the extracted netlist.
|
||||
"""
|
||||
|
|
@ -880,7 +852,7 @@ class bank(design.design):
|
|||
wl_name = "wl_{}".format(i)
|
||||
wl_pin = self.bitcell_array_inst.get_pin(wl_name)
|
||||
self.add_label(text=wl_name,
|
||||
layer="m1",
|
||||
layer="m1",
|
||||
offset=wl_pin.center())
|
||||
|
||||
# Add the bitline names
|
||||
|
|
@ -890,35 +862,35 @@ class bank(design.design):
|
|||
bl_pin = self.bitcell_array_inst.get_pin(bl_name)
|
||||
br_pin = self.bitcell_array_inst.get_pin(br_name)
|
||||
self.add_label(text=bl_name,
|
||||
layer="m2",
|
||||
layer="m2",
|
||||
offset=bl_pin.center())
|
||||
self.add_label(text=br_name,
|
||||
layer="m2",
|
||||
layer="m2",
|
||||
offset=br_pin.center())
|
||||
|
||||
# # Add the data output names to the sense amp output
|
||||
# # Add the data output names to the sense amp output
|
||||
# for i in range(self.word_size):
|
||||
# data_name = "data_{}".format(i)
|
||||
# data_pin = self.sense_amp_array_inst.get_pin(data_name)
|
||||
# self.add_label(text="sa_out_{}".format(i),
|
||||
# layer="m2",
|
||||
# layer="m2",
|
||||
# offset=data_pin.center())
|
||||
|
||||
# Add labels on the decoder
|
||||
for port in self.write_ports:
|
||||
for i in range(self.word_size):
|
||||
data_name = "dec_out_{}".format(i)
|
||||
pin_name = "in_{}".format(i)
|
||||
pin_name = "in_{}".format(i)
|
||||
data_pin = self.wordline_driver_inst[port].get_pin(pin_name)
|
||||
self.add_label(text=data_name,
|
||||
layer="m1",
|
||||
layer="m1",
|
||||
offset=data_pin.center())
|
||||
|
||||
def route_control_lines(self, port):
|
||||
""" Route the control lines of the entire bank """
|
||||
|
||||
# Make a list of tuples that we will connect.
|
||||
# From control signal to the module pin
|
||||
# From control signal to the module pin
|
||||
# Connection from the central bus to the main control block crosses
|
||||
# pre-decoder and this connection is in metal3
|
||||
connection = []
|
||||
|
|
@ -943,58 +915,59 @@ class bank(design.design):
|
|||
|
||||
for (control_signal, pin_pos) in connection:
|
||||
control_mid_pos = self.bus_xoffset[port][control_signal]
|
||||
control_pos = vector(self.bus_xoffset[port][control_signal].x ,pin_pos.y)
|
||||
control_pos = vector(self.bus_xoffset[port][control_signal].x, pin_pos.y)
|
||||
self.add_wire(self.m1_stack, [control_mid_pos, control_pos, pin_pos])
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=control_pos)
|
||||
|
||||
|
||||
# clk to wordline_driver
|
||||
control_signal = self.prefix+"wl_en{}".format(port)
|
||||
if port%2:
|
||||
control_signal = self.prefix + "wl_en{}".format(port)
|
||||
if port % 2:
|
||||
pin_pos = self.port_address_inst[port].get_pin("wl_en").uc()
|
||||
mid_pos = pin_pos + vector(0,2*self.m2_gap) # to route down to the top of the bus
|
||||
mid_pos = pin_pos + vector(0, 2 * self.m2_gap) # to route down to the top of the bus
|
||||
else:
|
||||
pin_pos = self.port_address_inst[port].get_pin("wl_en").bc()
|
||||
mid_pos = pin_pos - vector(0,2*self.m2_gap) # to route down to the top of the bus
|
||||
mid_pos = pin_pos - vector(0, 2 * self.m2_gap) # to route down to the top of the bus
|
||||
control_x_offset = self.bus_xoffset[port][control_signal].x
|
||||
control_pos = vector(control_x_offset, mid_pos.y)
|
||||
self.add_wire(self.m1_stack,[pin_pos, mid_pos, control_pos])
|
||||
self.add_wire(self.m1_stack, [pin_pos, mid_pos, control_pos])
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
offset=control_pos)
|
||||
|
||||
def determine_wordline_stage_efforts(self, external_cout, inp_is_rise=True):
|
||||
"""Get the all the stage efforts for each stage in the path within the bank clk_buf to a wordline"""
|
||||
#Decoder is assumed to have settled before the negative edge of the clock. Delay model relies on this assumption
|
||||
# Decoder is assumed to have settled before the negative edge of the clock.
|
||||
# Delay model relies on this assumption
|
||||
stage_effort_list = []
|
||||
wordline_cout = self.bitcell_array.get_wordline_cin() + external_cout
|
||||
stage_effort_list += self.port_address.wordline_driver.determine_wordline_stage_efforts(wordline_cout,inp_is_rise)
|
||||
stage_effort_list += self.port_address.wordline_driver.determine_wordline_stage_efforts(wordline_cout,
|
||||
inp_is_rise)
|
||||
|
||||
return stage_effort_list
|
||||
|
||||
def get_wl_en_cin(self):
|
||||
"""Get the relative capacitance of all the clk connections in the bank"""
|
||||
#wl_en only used in the wordline driver.
|
||||
# wl_en only used in the wordline driver.
|
||||
return self.port_address.wordline_driver.get_wl_en_cin()
|
||||
|
||||
def get_w_en_cin(self):
|
||||
"""Get the relative capacitance of all the clk connections in the bank"""
|
||||
#wl_en only used in the wordline driver.
|
||||
port = self.write_ports[0]
|
||||
# wl_en only used in the wordline driver.
|
||||
port = self.write_ports[0]
|
||||
return self.port_data[port].write_driver.get_w_en_cin()
|
||||
|
||||
def get_clk_bar_cin(self):
|
||||
"""Get the relative capacitance of all the clk_bar connections in the bank"""
|
||||
#Current bank only uses clock bar (clk_buf_bar) as an enable for the precharge array.
|
||||
# Current bank only uses clock bar (clk_buf_bar) as an enable for the precharge array.
|
||||
|
||||
#Precharges are the all the same in Mulitport, one is picked
|
||||
# Precharges are the all the same in Mulitport, one is picked
|
||||
port = self.read_ports[0]
|
||||
return self.port_data[port].precharge_array.get_en_cin()
|
||||
|
||||
def get_sen_cin(self):
|
||||
"""Get the relative capacitance of all the sense amp enable connections in the bank"""
|
||||
#Current bank only uses sen as an enable for the sense amps.
|
||||
port = self.read_ports[0]
|
||||
# Current bank only uses sen as an enable for the sense amps.
|
||||
port = self.read_ports[0]
|
||||
return self.port_data[port].sense_amp_array.get_en_cin()
|
||||
|
||||
def graph_exclude_precharge(self):
|
||||
|
|
@ -1005,5 +978,7 @@ class bank(design.design):
|
|||
|
||||
def get_cell_name(self, inst_name, row, col):
|
||||
"""Gets the spice name of the target bitcell."""
|
||||
return self.bitcell_array_inst.mod.get_cell_name(inst_name+'.x'+self.bitcell_array_inst.name, row, col)
|
||||
return self.bitcell_array_inst.mod.get_cell_name(inst_name + '.x' + self.bitcell_array_inst.name,
|
||||
row,
|
||||
col)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue