mirror of
https://github.com/VLSIDA/OpenRAM.git
synced 2026-09-07 11:21:14 +02:00
Fixed merge conflicts
This commit is contained in:
+47
-48
@@ -6,9 +6,7 @@ import math
|
||||
from math import log,sqrt,ceil
|
||||
import contact
|
||||
import pgates
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
|
||||
from globals import OPTS
|
||||
@@ -396,25 +394,14 @@ class bank(design.design):
|
||||
def add_modules(self):
|
||||
""" Add all the modules using the class loader """
|
||||
|
||||
mod_list = ["bitcell", "decoder", "wordline_driver",
|
||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
||||
"column_mux_array", "write_driver_array",
|
||||
"dff", "bank_select"]
|
||||
from importlib import reload
|
||||
for mod_name in mod_list:
|
||||
config_mod_name = getattr(OPTS, mod_name)
|
||||
class_file = reload(__import__(config_mod_name))
|
||||
mod_class = getattr(class_file , config_mod_name)
|
||||
setattr (self, "mod_"+mod_name, mod_class)
|
||||
|
||||
|
||||
|
||||
self.bitcell_array = self.mod_bitcell_array(cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.bitcell_array = factory.create(module_type="bitcell_array",
|
||||
cols=self.num_cols,
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
||||
# create arrays of bitline and bitline_bar names for read, write, or all ports
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
self.bl_names = self.bitcell.list_all_bl_names()
|
||||
self.br_names = self.bitcell.list_all_br_names()
|
||||
self.wl_names = self.bitcell.list_all_wl_names()
|
||||
@@ -423,7 +410,11 @@ class bank(design.design):
|
||||
self.precharge_array = []
|
||||
for port in self.all_ports:
|
||||
if port in self.read_ports:
|
||||
self.precharge_array.append(self.mod_precharge_array(columns=self.num_cols, bitcell_bl=self.bl_names[port], bitcell_br=self.br_names[port]))
|
||||
temp_pre = factory.create(module_type="precharge_array",
|
||||
columns=self.num_cols,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port])
|
||||
self.precharge_array.append(temp_pre)
|
||||
self.add_mod(self.precharge_array[port])
|
||||
else:
|
||||
self.precharge_array.append(None)
|
||||
@@ -431,32 +422,39 @@ class bank(design.design):
|
||||
if self.col_addr_size > 0:
|
||||
self.column_mux_array = []
|
||||
for port in self.all_ports:
|
||||
self.column_mux_array.append(self.mod_column_mux_array(columns=self.num_cols,
|
||||
word_size=self.word_size,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port]))
|
||||
temp_col = factory.create(module_type="column_mux_array",
|
||||
columns=self.num_cols,
|
||||
word_size=self.word_size,
|
||||
bitcell_bl=self.bl_names[port],
|
||||
bitcell_br=self.br_names[port])
|
||||
self.column_mux_array.append(temp_col)
|
||||
self.add_mod(self.column_mux_array[port])
|
||||
|
||||
|
||||
self.sense_amp_array = self.mod_sense_amp_array(word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.sense_amp_array = factory.create(module_type="sense_amp_array",
|
||||
word_size=self.word_size,
|
||||
words_per_row=self.words_per_row)
|
||||
self.add_mod(self.sense_amp_array)
|
||||
|
||||
self.write_driver_array = self.mod_write_driver_array(columns=self.num_cols,
|
||||
word_size=self.word_size)
|
||||
self.write_driver_array = factory.create(module_type="write_driver_array",
|
||||
columns=self.num_cols,
|
||||
word_size=self.word_size)
|
||||
self.add_mod(self.write_driver_array)
|
||||
|
||||
self.row_decoder = self.mod_decoder(rows=self.num_rows)
|
||||
self.row_decoder = factory.create(module_type="decoder",
|
||||
rows=self.num_rows)
|
||||
self.add_mod(self.row_decoder)
|
||||
|
||||
self.wordline_driver = self.mod_wordline_driver(rows=self.num_rows)
|
||||
self.wordline_driver = factory.create(module_type="wordline_driver",
|
||||
rows=self.num_rows,
|
||||
cols=self.num_cols)
|
||||
self.add_mod(self.wordline_driver)
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pinv")
|
||||
self.add_mod(self.inv)
|
||||
|
||||
if(self.num_banks > 1):
|
||||
self.bank_select = self.mod_bank_select()
|
||||
self.bank_select = factory.create(module_type="bank_select")
|
||||
self.add_mod(self.bank_select)
|
||||
|
||||
|
||||
@@ -693,18 +691,17 @@ class bank(design.design):
|
||||
"""
|
||||
Create a 2:4 or 3:8 column address decoder.
|
||||
"""
|
||||
|
||||
dff = factory.create(module_type="dff")
|
||||
|
||||
if self.col_addr_size == 0:
|
||||
return
|
||||
elif self.col_addr_size == 1:
|
||||
from pinvbuf import pinvbuf
|
||||
self.column_decoder = pinvbuf(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="pinvbuf", height=dff.height)
|
||||
elif self.col_addr_size == 2:
|
||||
from hierarchical_predecode2x4 import hierarchical_predecode2x4 as pre2x4
|
||||
self.column_decoder = pre2x4(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode2x4", height=dff.height)
|
||||
elif self.col_addr_size == 3:
|
||||
from hierarchical_predecode3x8 import hierarchical_predecode3x8 as pre3x8
|
||||
self.column_decoder = pre3x8(height=self.mod_dff.height)
|
||||
self.column_decoder = factory.create(module_type="hierarchical_predecode3x8", height=dff.height)
|
||||
else:
|
||||
# No error checking before?
|
||||
debug.error("Invalid column decoder?",-1)
|
||||
@@ -1071,8 +1068,8 @@ class bank(design.design):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pos = self.wordline_driver_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.5,1)+bitcell_wl_pos.scale(0.5,0)
|
||||
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.wordline_driver_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("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
|
||||
@@ -1090,8 +1087,8 @@ class bank(design.design):
|
||||
# The mid guarantees we exit the input cell to the right.
|
||||
driver_wl_pos = self.wordline_driver_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.5,1)+bitcell_wl_pos.scale(0.5,0)
|
||||
mid2 = driver_wl_pos.scale(0.5,0)+bitcell_wl_pos.scale(0.5,1)
|
||||
mid1 = driver_wl_pos.scale(0,1) + vector(0.5*self.wordline_driver_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("metal1", [driver_wl_pos, mid1, mid2, bitcell_wl_pos])
|
||||
|
||||
def route_column_address_lines(self, port):
|
||||
@@ -1257,20 +1254,22 @@ class bank(design.design):
|
||||
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.
|
||||
total_clk_cin = self.wordline_driver.get_wl_en_cin()
|
||||
return total_clk_cin
|
||||
|
||||
return self.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.
|
||||
return self.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.
|
||||
|
||||
#Precharges are the all the same in Mulitport, one is picked
|
||||
port = self.read_ports[0]
|
||||
total_clk_bar_cin = self.precharge_array[port].get_en_cin()
|
||||
return total_clk_bar_cin
|
||||
return self.precharge_array[port].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.
|
||||
total_sen_cin = self.sense_amp_array.get_en_cin()
|
||||
return total_sen_cin
|
||||
return self.sense_amp_array.get_en_cin()
|
||||
|
||||
@@ -7,6 +7,7 @@ from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class bank_select(design.design):
|
||||
@@ -62,28 +63,25 @@ class bank_select(design.design):
|
||||
|
||||
def add_modules(self):
|
||||
""" Create modules for later instantiation """
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
height = self.bitcell.height + drc("poly_to_active")
|
||||
|
||||
# 1x Inverter
|
||||
self.inv_sel = pinv(height=height)
|
||||
self.inv_sel = factory.create(module_type="pinv", height=height)
|
||||
self.add_mod(self.inv_sel)
|
||||
|
||||
# 4x Inverter
|
||||
self.inv = self.inv4x = pinv(4)
|
||||
self.inv4x = factory.create(module_type="pinv", height=height, size=4)
|
||||
self.add_mod(self.inv4x)
|
||||
|
||||
self.nor2 = pnor2(height=height)
|
||||
self.nor2 = factory.create(module_type="pnor2", height=height)
|
||||
self.add_mod(self.nor2)
|
||||
|
||||
self.inv4x_nor = pinv(size=4, height=height)
|
||||
self.inv4x_nor = factory.create(module_type="pinv", height=height, size=4)
|
||||
self.add_mod(self.inv4x_nor)
|
||||
|
||||
self.nand2 = pnand2()
|
||||
self.nand2 = factory.create(module_type="pnand2")
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
def calculate_module_offsets(self):
|
||||
@@ -94,7 +92,7 @@ class bank_select(design.design):
|
||||
self.xoffset_bank_sel_inv = 0
|
||||
self.xoffset_inputs = 0
|
||||
|
||||
self.yoffset_maxpoint = self.num_control_lines * self.inv.height
|
||||
self.yoffset_maxpoint = self.num_control_lines * self.inv4x.height
|
||||
# Include the M1 pitches for the supply rails and spacing
|
||||
self.height = self.yoffset_maxpoint + 2*self.m1_pitch
|
||||
self.width = self.xoffset_inv + self.inv4x.width
|
||||
@@ -170,10 +168,10 @@ class bank_select(design.design):
|
||||
if i == 0:
|
||||
y_offset = 0
|
||||
else:
|
||||
y_offset = self.inv4x_nor.height + self.inv.height * (i-1)
|
||||
y_offset = self.inv4x_nor.height + self.inv4x.height * (i-1)
|
||||
|
||||
if i%2:
|
||||
y_offset += self.inv.height
|
||||
y_offset += self.inv4x.height
|
||||
mirror = "MX"
|
||||
else:
|
||||
mirror = ""
|
||||
@@ -223,7 +221,7 @@ class bank_select(design.design):
|
||||
self.add_label_pin(text="bank_sel_bar",
|
||||
layer="metal2",
|
||||
offset=vector(xoffset_bank_sel_bar, 0),
|
||||
height=self.inv.height)
|
||||
height=self.inv4x.height)
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=bank_sel_bar_pin.rc())
|
||||
|
||||
|
||||
@@ -3,8 +3,7 @@ import design
|
||||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
unique_id = 1
|
||||
from sram_factory import factory
|
||||
|
||||
class bitcell_array(design.design):
|
||||
"""
|
||||
@@ -12,16 +11,10 @@ class bitcell_array(design.design):
|
||||
and word line is connected by abutment.
|
||||
Connects the word lines and bit lines.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, cols, rows, name=""):
|
||||
|
||||
if name == "":
|
||||
name = "bitcell_array_{0}x{1}_{2}".format(rows,cols,bitcell_array.unique_id)
|
||||
bitcell_array.unique_id += 1
|
||||
def __init__(self, cols, rows, name):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
|
||||
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
|
||||
|
||||
self.column_size = cols
|
||||
self.row_size = rows
|
||||
@@ -83,11 +76,7 @@ class bitcell_array(design.design):
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.cell = self.mod_bitcell()
|
||||
self.cell = factory.create(module_type="bitcell")
|
||||
self.add_mod(self.cell)
|
||||
|
||||
def create_instances(self):
|
||||
@@ -210,4 +199,4 @@ class bitcell_array(design.design):
|
||||
#A single wordline is connected to all the bitcells in a single row meaning the capacitance depends on the # of columns
|
||||
bitcell_wl_cin = self.cell.get_wl_cin()
|
||||
total_cin = bitcell_wl_cin * self.column_size
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
||||
@@ -3,13 +3,7 @@ import design
|
||||
from tech import drc, parameter
|
||||
import debug
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from pbuf import pbuf
|
||||
from pand2 import pand2
|
||||
from pnand2 import pnand2
|
||||
from pinvbuf import pinvbuf
|
||||
from dff_buf import dff_buf
|
||||
from dff_buf_array import dff_buf_array
|
||||
from sram_factory import factory
|
||||
import math
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
@@ -20,20 +14,26 @@ class control_logic(design.design):
|
||||
Dynamically generated Control logic for the total SRAM circuit.
|
||||
"""
|
||||
|
||||
def __init__(self, num_rows, words_per_row, sram=None, port_type="rw"):
|
||||
def __init__(self, num_rows, words_per_row, word_size, sram=None, port_type="rw"):
|
||||
""" Constructor """
|
||||
name = "control_logic_" + port_type
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(name))
|
||||
self.add_comment("num_rows: {0}".format(num_rows))
|
||||
self.add_comment("words_per_row: {0}".format(words_per_row))
|
||||
self.add_comment("word_size {0}".format(word_size))
|
||||
|
||||
self.sram=sram
|
||||
self.num_rows = num_rows
|
||||
self.words_per_row = words_per_row
|
||||
self.word_size = word_size
|
||||
self.port_type = port_type
|
||||
|
||||
self.num_cols = word_size*words_per_row
|
||||
self.num_words = num_rows * words_per_row
|
||||
|
||||
self.enable_delay_chain_resizing = False
|
||||
|
||||
#This is needed to resize the delay chain. Likely to be changed at some point.
|
||||
self.sram=sram
|
||||
#self.sram=None #disable re-sizing for debugging, FIXME: resizing is not working, needs to be adjusted for new control logic.
|
||||
self.wl_timing_tolerance = 1 #Determines how much larger the sen delay should be. Accounts for possible error in model.
|
||||
self.parasitic_inv_delay = parameter["min_inv_para_delay"] #Keeping 0 for now until further testing.
|
||||
@@ -75,38 +75,62 @@ class control_logic(design.design):
|
||||
def add_modules(self):
|
||||
""" Add all the required modules """
|
||||
|
||||
dff = dff_buf()
|
||||
dff = factory.create(module_type="dff_buf")
|
||||
dff_height = dff.height
|
||||
|
||||
self.ctrl_dff_array = dff_buf_array(rows=self.num_control_signals,columns=1)
|
||||
self.ctrl_dff_array = factory.create(module_type="dff_buf_array",
|
||||
rows=self.num_control_signals,
|
||||
columns=1)
|
||||
|
||||
self.add_mod(self.ctrl_dff_array)
|
||||
|
||||
self.and2 = pand2(size=4,height=dff_height)
|
||||
self.and2 = factory.create(module_type="pand2",
|
||||
size=4,
|
||||
height=dff_height)
|
||||
self.add_mod(self.and2)
|
||||
|
||||
# Special gates: inverters for buffering
|
||||
# Size the clock for the number of rows (fanout)
|
||||
clock_driver_size = max(1,int(self.num_rows/4))
|
||||
self.clkbuf = pbuf(size=clock_driver_size, height=dff_height)
|
||||
self.add_mod(self.clkbuf)
|
||||
|
||||
self.buf16 = pbuf(size=16, height=dff_height)
|
||||
self.add_mod(self.buf16)
|
||||
|
||||
self.buf8 = pbuf(size=8, height=dff_height)
|
||||
self.add_mod(self.buf8)
|
||||
# clk_buf drives a flop for every address and control bit
|
||||
# plus about 5 fanouts for the control logic
|
||||
# each flop internally has a FO 4 approximately
|
||||
clock_fanout = 4*(math.log(self.num_words,2) + math.log(self.words_per_row,2) \
|
||||
+ self.num_control_signals) + 5
|
||||
self.clk_buf_driver = factory.create(module_type="pdriver",
|
||||
fanout=clock_fanout,
|
||||
height=dff_height)
|
||||
|
||||
self.inv = self.inv1 = pinv(size=1, height=dff_height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
self.inv8 = pinv(size=8, height=dff_height)
|
||||
self.add_mod(self.inv8)
|
||||
|
||||
# self.inv2 = pinv(size=4, height=dff_height)
|
||||
# self.add_mod(self.inv2)
|
||||
#self.inv16 = pinv(size=16, height=dff_height)
|
||||
#self.add_mod(self.inv16)
|
||||
self.add_mod(self.clk_buf_driver)
|
||||
|
||||
# wl_en drives every row in the bank
|
||||
self.wl_en_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.num_rows,
|
||||
height=dff_height)
|
||||
self.add_mod(self.wl_en_driver)
|
||||
|
||||
# w_en drives every write driver
|
||||
self.w_en_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.word_size+8,
|
||||
height=dff_height)
|
||||
self.add_mod(self.w_en_driver)
|
||||
|
||||
# s_en drives every sense amp
|
||||
self.s_en_driver = factory.create(module_type="pdriver",
|
||||
fanout=self.word_size,
|
||||
height=dff_height)
|
||||
self.add_mod(self.s_en_driver)
|
||||
|
||||
# used to generate inverted signals with low fanout
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
size=1,
|
||||
height=dff_height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
# p_en_bar drives every column in the bicell array
|
||||
self.p_en_bar_driver = factory.create(module_type="pdriver",
|
||||
neg_polarity=True,
|
||||
fanout=self.num_cols,
|
||||
height=dff_height)
|
||||
self.add_mod(self.p_en_bar_driver)
|
||||
|
||||
if (self.port_type == "rw") or (self.port_type == "r"):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.replica_bitline))
|
||||
@@ -126,9 +150,9 @@ class control_logic(design.design):
|
||||
else: #Otherwise, use a heuristic and/or model based sizing.
|
||||
#First use a heuristic
|
||||
delay_stages_heuristic, delay_fanout_heuristic = self.get_heuristic_delay_chain_size()
|
||||
self.replica_bitline = replica_bitline([delay_fanout_heuristic]*delay_stages_heuristic,
|
||||
bitcell_loads,
|
||||
name="replica_bitline_"+self.port_type)
|
||||
self.replica_bitline = replica_bitline("replica_bitline_"+self.port_type,
|
||||
[delay_fanout_heuristic]*delay_stages_heuristic,
|
||||
bitcell_loads)
|
||||
if self.sram != None: #Calculate delays for potential re-sizing
|
||||
self.set_sen_wl_delays()
|
||||
#Resize if necessary, condition depends on resizing method
|
||||
@@ -412,8 +436,8 @@ class control_logic(design.design):
|
||||
|
||||
def create_clk_buf_row(self):
|
||||
""" Create the multistage and gated clock buffer """
|
||||
self.clkbuf_inst = self.add_inst(name="clkbuf",
|
||||
mod=self.clkbuf)
|
||||
self.clk_buf_inst = self.add_inst(name="clkbuf",
|
||||
mod=self.clk_buf_driver)
|
||||
self.connect_inst(["clk","clk_buf","vdd","gnd"])
|
||||
|
||||
def place_clk_buf_row(self,row):
|
||||
@@ -422,12 +446,12 @@ class control_logic(design.design):
|
||||
(y_off,mirror)=self.get_offset(row)
|
||||
|
||||
offset = vector(x_off,y_off)
|
||||
self.clkbuf_inst.place(offset, mirror)
|
||||
self.clk_buf_inst.place(offset, mirror)
|
||||
|
||||
self.row_end_inst.append(self.clkbuf_inst)
|
||||
self.row_end_inst.append(self.clk_buf_inst)
|
||||
|
||||
def route_clk_buf(self):
|
||||
clk_pin = self.clkbuf_inst.get_pin("A")
|
||||
clk_pin = self.clk_buf_inst.get_pin("A")
|
||||
clk_pos = clk_pin.center()
|
||||
self.add_layout_pin_segment_center(text="clk",
|
||||
layer="metal2",
|
||||
@@ -437,14 +461,17 @@ class control_logic(design.design):
|
||||
offset=clk_pos)
|
||||
|
||||
|
||||
clkbuf_map = zip(["Z"], ["clk_buf"])
|
||||
self.connect_vertical_bus(clkbuf_map, self.clkbuf_inst, self.rail_offsets, ("metal3", "via2", "metal2"))
|
||||
# Connect this at the bottom of the buffer
|
||||
out_pos = self.clk_buf_inst.get_pin("Z").center()
|
||||
mid1 = vector(out_pos.x,2*self.m2_pitch)
|
||||
mid2 = vector(self.rail_offsets["clk_buf"].x, mid1.y)
|
||||
bus_pos = self.rail_offsets["clk_buf"]
|
||||
self.add_wire(("metal3","via2","metal2"),[out_pos, mid1, mid2, bus_pos])
|
||||
# The pin is on M1, so we need another via as well
|
||||
self.add_via_center(layers=("metal1","via1","metal2"),
|
||||
offset=self.clkbuf_inst.get_pin("Z").center())
|
||||
|
||||
offset=self.clk_buf_inst.get_pin("Z").center())
|
||||
|
||||
self.connect_output(self.clkbuf_inst, "Z", "clk_buf")
|
||||
self.connect_output(self.clk_buf_inst, "Z", "clk_buf")
|
||||
|
||||
def create_gated_clk_bar_row(self):
|
||||
self.clk_bar_inst = self.add_inst(name="inv_clk_bar",
|
||||
@@ -523,7 +550,7 @@ class control_logic(design.design):
|
||||
def create_wlen_row(self):
|
||||
# input pre_p_en, output: wl_en
|
||||
self.wl_en_inst=self.add_inst(name="buf_wl_en",
|
||||
mod=self.buf16)
|
||||
mod=self.wl_en_driver)
|
||||
self.connect_inst(["gated_clk_bar", "wl_en", "vdd", "gnd"])
|
||||
|
||||
def place_wlen_row(self, row):
|
||||
@@ -593,7 +620,7 @@ class control_logic(design.design):
|
||||
|
||||
# input: pre_p_en, output: p_en_bar
|
||||
self.p_en_bar_inst=self.add_inst(name="inv_p_en_bar",
|
||||
mod=self.inv8)
|
||||
mod=self.p_en_bar_driver)
|
||||
self.connect_inst([input_name, "p_en_bar", "vdd", "gnd"])
|
||||
|
||||
|
||||
@@ -633,7 +660,7 @@ class control_logic(design.design):
|
||||
# BUFFER FOR S_EN
|
||||
# input: pre_s_en, output: s_en
|
||||
self.s_en_inst=self.add_inst(name="buf_s_en",
|
||||
mod=self.buf8)
|
||||
mod=self.s_en_driver)
|
||||
self.connect_inst(["pre_s_en", "s_en", "vdd", "gnd"])
|
||||
|
||||
def place_sen_row(self,row):
|
||||
@@ -670,7 +697,7 @@ class control_logic(design.design):
|
||||
|
||||
# BUFFER FOR W_EN
|
||||
self.w_en_inst = self.add_inst(name="buf_w_en_buf",
|
||||
mod=self.buf8)
|
||||
mod=self.w_en_driver)
|
||||
self.connect_inst([input_name, "w_en", "vdd", "gnd"])
|
||||
|
||||
|
||||
@@ -827,7 +854,7 @@ class control_logic(design.design):
|
||||
#Calculate the load on wl_en within the module and add it to external load
|
||||
external_cout = self.sram.get_wl_en_cin()
|
||||
#First stage is the clock buffer
|
||||
stage_effort_list += self.clkbuf.get_output_stage_efforts(external_cout, is_clk_bar_rise)
|
||||
stage_effort_list += self.clk_buf_driver.get_stage_efforts(external_cout, is_clk_bar_rise)
|
||||
last_stage_is_rise = stage_effort_list[-1].is_rise
|
||||
|
||||
#Then ask the sram for the other path delays (from the bank)
|
||||
@@ -858,21 +885,21 @@ class control_logic(design.design):
|
||||
#First stage, gated_clk_bar -(and2)-> rbl_in. Only for RW ports.
|
||||
if self.port_type == "rw":
|
||||
stage1_cout = self.replica_bitline.get_en_cin()
|
||||
stage_effort_list += self.and2.get_output_stage_efforts(stage1_cout, last_stage_rise)
|
||||
stage_effort_list += self.and2.get_stage_efforts(stage1_cout, last_stage_rise)
|
||||
last_stage_rise = stage_effort_list[-1].is_rise
|
||||
|
||||
#Replica bitline stage, rbl_in -(rbl)-> pre_s_en
|
||||
stage2_cout = self.buf8.get_cin()
|
||||
stage2_cout = self.s_en_driver.get_cin()
|
||||
stage_effort_list += self.replica_bitline.determine_sen_stage_efforts(stage2_cout, last_stage_rise)
|
||||
last_stage_rise = stage_effort_list[-1].is_rise
|
||||
|
||||
#buffer stage, pre_s_en -(buffer)-> s_en
|
||||
stage3_cout = self.sram.get_sen_cin()
|
||||
stage_effort_list += self.buf8.get_output_stage_efforts(stage3_cout, last_stage_rise)
|
||||
stage_effort_list += self.s_en_driver.get_stage_efforts(stage3_cout, last_stage_rise)
|
||||
last_stage_rise = stage_effort_list[-1].is_rise
|
||||
|
||||
return stage_effort_list
|
||||
|
||||
|
||||
def get_wl_sen_delays(self):
|
||||
"""Gets a list of the stages and delays in order of their path."""
|
||||
if self.sen_stage_efforts == None or self.wl_stage_efforts == None:
|
||||
@@ -880,4 +907,4 @@ class control_logic(design.design):
|
||||
wl_delays = logical_effort.calculate_delays(self.wl_stage_efforts, self.parasitic_inv_delay)
|
||||
sen_delays = logical_effort.calculate_delays(self.sen_stage_efforts, self.parasitic_inv_delay)
|
||||
return wl_delays, sen_delays
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import debug
|
||||
import design
|
||||
from tech import drc
|
||||
from pinv import pinv
|
||||
from contact import contact
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
|
||||
class delay_chain(design.design):
|
||||
"""
|
||||
@@ -13,14 +13,12 @@ class delay_chain(design.design):
|
||||
Usually, this will be constant, but it could have varied fanout.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, fanout_list, name="delay_chain"):
|
||||
def __init__(self, name, fanout_list):
|
||||
"""init function"""
|
||||
name = name+"_{}".format(delay_chain.unique_id)
|
||||
delay_chain.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
|
||||
debug.info(1, "creating delay chain {0}".format(str(fanout_list)))
|
||||
self.add_comment("fanouts: {0}".format(str(fanout_list)))
|
||||
|
||||
# Two fanouts are needed so that we can route the vdd/gnd connections
|
||||
for f in fanout_list:
|
||||
debug.check(f>=2,"Must have >=2 fanouts for each stage.")
|
||||
@@ -57,7 +55,7 @@ class delay_chain(design.design):
|
||||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
self.inv = pinv(route_output=False)
|
||||
self.inv = factory.create(module_type="pinv", route_output=False)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
def create_inverters(self):
|
||||
@@ -234,8 +232,8 @@ class delay_chain(design.design):
|
||||
stage_cout = self.inv.get_cin()*(stage_fanout+1)
|
||||
if len(stage_effort_list) == len(self.fanout_list)-1: #last stage
|
||||
stage_cout+=ext_delayed_en_cout
|
||||
stage = self.inv.get_effort_stage(stage_cout, last_stage_is_rise)
|
||||
stage = self.inv.get_stage_effort(stage_cout, last_stage_is_rise)
|
||||
stage_effort_list.append(stage)
|
||||
last_stage_is_rise = stage.is_rise
|
||||
|
||||
return stage_effort_list
|
||||
return stage_effort_list
|
||||
|
||||
@@ -3,6 +3,7 @@ import design
|
||||
from tech import drc
|
||||
from math import log
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class dff_array(design.design):
|
||||
@@ -11,7 +12,7 @@ class dff_array(design.design):
|
||||
Unlike the data flops, these are never spaced out.
|
||||
"""
|
||||
|
||||
def __init__(self, rows, columns, inv1_size=2, inv2_size=4, name=""):
|
||||
def __init__(self, rows, columns, name=""):
|
||||
self.rows = rows
|
||||
self.columns = columns
|
||||
|
||||
@@ -19,7 +20,8 @@ class dff_array(design.design):
|
||||
name = "dff_array_{0}x{1}".format(rows, columns)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0} rows={1} cols={2}".format(self.name, self.rows, self.columns))
|
||||
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, columns))
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
self.create_layout()
|
||||
@@ -38,10 +40,7 @@ class dff_array(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def add_pins(self):
|
||||
@@ -61,7 +60,7 @@ class dff_array(design.design):
|
||||
for col in range(self.columns):
|
||||
name = "dff_r{0}_c{1}".format(row,col)
|
||||
self.dff_insts[row,col]=self.add_inst(name=name,
|
||||
mod=self.dff)
|
||||
mod=self.dff)
|
||||
self.connect_inst([self.get_din_name(row,col),
|
||||
self.get_dout_name(row,col),
|
||||
"clk",
|
||||
@@ -162,4 +161,4 @@ class dff_array(design.design):
|
||||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
||||
@@ -4,7 +4,7 @@ from tech import drc,parameter
|
||||
from math import log
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from pinv import pinv
|
||||
from sram_factory import factory
|
||||
|
||||
class dff_buf(design.design):
|
||||
"""
|
||||
@@ -21,7 +21,8 @@ class dff_buf(design.design):
|
||||
dff_buf.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
|
||||
self.add_comment("inv1: {0} inv2: {1}".format(inv1_size, inv2_size))
|
||||
|
||||
# This is specifically for SCMOS where the DFF vdd/gnd rails are more than min width.
|
||||
# This causes a DRC in the pinv which assumes min width rails. This ensures the output
|
||||
# contact does not violate spacing to the rail in the NMOS.
|
||||
@@ -50,16 +51,17 @@ class dff_buf(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
self.inv1 = pinv(size=self.inv1_size,height=self.dff.height)
|
||||
self.inv1 = factory.create(module_type="pinv",
|
||||
size=self.inv1_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
self.inv2 = pinv(size=self.inv2_size,height=self.dff.height)
|
||||
self.inv2 = factory.create(module_type="pinv",
|
||||
size=self.inv2_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv2)
|
||||
|
||||
|
||||
@@ -182,4 +184,4 @@ class dff_buf(design.design):
|
||||
#This is a handmade cell so the value must be entered in the tech.py file or estimated.
|
||||
#Calculated in the tech file by summing the widths of all the gates and dividing by the minimum width.
|
||||
#FIXME: Dff changed in a past commit. The parameter need to be updated.
|
||||
return parameter["dff_clk_cin"]
|
||||
return parameter["dff_clk_cin"]
|
||||
|
||||
@@ -4,7 +4,7 @@ from tech import drc
|
||||
from math import log
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
import dff_buf
|
||||
from sram_factory import factory
|
||||
|
||||
class dff_buf_array(design.design):
|
||||
"""
|
||||
@@ -22,6 +22,9 @@ class dff_buf_array(design.design):
|
||||
dff_buf_array.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, columns))
|
||||
self.add_comment("inv1: {0} inv2: {1}".format(inv1_size, inv2_size))
|
||||
|
||||
self.inv1_size = inv1_size
|
||||
self.inv2_size = inv2_size
|
||||
|
||||
@@ -54,7 +57,9 @@ class dff_buf_array(design.design):
|
||||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = dff_buf.dff_buf(self.inv1_size, self.inv2_size)
|
||||
self.dff = factory.create(module_type="dff_buf",
|
||||
inv1_size=self.inv1_size,
|
||||
inv2_size=self.inv2_size)
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def create_dff_array(self):
|
||||
@@ -189,4 +194,4 @@ class dff_buf_array(design.design):
|
||||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
||||
@@ -20,6 +20,8 @@ class dff_inv(design.design):
|
||||
dff_inv.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.add_comment("inv: {0}".format(inv_size))
|
||||
|
||||
self.inv_size = inv_size
|
||||
|
||||
# This is specifically for SCMOS where the DFF vdd/gnd rails are more than min width.
|
||||
@@ -55,13 +57,12 @@ class dff_inv(design.design):
|
||||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.dff))
|
||||
self.mod_dff = getattr(c, OPTS.dff)
|
||||
self.dff = self.mod_dff("dff")
|
||||
self.dff = dff_inv.dff_inv(self.inv_size)
|
||||
self.add_mod(self.dff)
|
||||
|
||||
self.inv1 = pinv(size=self.inv_size,height=self.dff.height)
|
||||
self.inv1 = factory.create(module_type="pinv",
|
||||
size=self.inv_size,
|
||||
height=self.dff.height)
|
||||
self.add_mod(self.inv1)
|
||||
|
||||
def create_modules(self):
|
||||
@@ -152,4 +153,4 @@ class dff_inv(design.design):
|
||||
|
||||
def get_clk_cin(self):
|
||||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff"""
|
||||
return self.dff.get_clk_cin()
|
||||
return self.dff.get_clk_cin()
|
||||
|
||||
@@ -22,6 +22,9 @@ class dff_inv_array(design.design):
|
||||
dff_inv_array.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {}".format(self.name))
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, columns))
|
||||
self.add_comment("inv1: {0}".format(inv1_size))
|
||||
|
||||
self.inv_size = inv_size
|
||||
|
||||
self.create_netlist()
|
||||
@@ -42,7 +45,7 @@ class dff_inv_array(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.dff = dff_inv.dff_inv(self.inv_size)
|
||||
self.dff = factory.create(module_type="dff")
|
||||
self.add_mod(self.dff)
|
||||
|
||||
def add_pins(self):
|
||||
@@ -189,4 +192,4 @@ class dff_inv_array(design.design):
|
||||
"""Return the total capacitance (in relative units) that the clock is loaded by in the dff array"""
|
||||
dff_clk_cin = self.dff.get_clk_cin()
|
||||
total_cin = dff_clk_cin * self.rows * self.columns
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
||||
@@ -4,12 +4,8 @@ import design
|
||||
from math import log
|
||||
from math import sqrt
|
||||
import math
|
||||
import contact
|
||||
from pnand2 import pnand2
|
||||
from pnand3 import pnand3
|
||||
from pinv import pinv
|
||||
from hierarchical_predecode2x4 import hierarchical_predecode2x4 as pre2x4
|
||||
from hierarchical_predecode3x8 import hierarchical_predecode3x8 as pre3x8
|
||||
import contact
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
@@ -17,11 +13,8 @@ class hierarchical_decoder(design.design):
|
||||
"""
|
||||
Dynamically generated hierarchical decoder.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, rows, height=None):
|
||||
design.design.__init__(self, "hierarchical_decoder_{0}rows_{1}".format(rows,hierarchical_decoder.unique_id))
|
||||
hierarchical_decoder.unique_id += 1
|
||||
def __init__(self, name, rows, height=None):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.NAND_FORMAT = "DEC_NAND_{0}"
|
||||
self.INV_FORMAT = "DEC_INV_{0}"
|
||||
@@ -57,21 +50,26 @@ class hierarchical_decoder(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.inv = pinv(height=self.cell_height)
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.inv)
|
||||
self.nand2 = pnand2(height=self.cell_height)
|
||||
self.nand2 = factory.create(module_type="pnand2",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.nand2)
|
||||
self.nand3 = pnand3(height=self.cell_height)
|
||||
self.nand3 = factory.create(module_type="pnand3",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.nand3)
|
||||
|
||||
self.add_decoders()
|
||||
|
||||
def add_decoders(self):
|
||||
""" Create the decoders based on the number of pre-decodes """
|
||||
self.pre2_4 = pre2x4(height=self.cell_height)
|
||||
self.pre2_4 = factory.create(module_type="hierarchical_predecode2x4",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.pre2_4)
|
||||
|
||||
self.pre3_8 = pre3x8(height=self.cell_height)
|
||||
self.pre3_8 = factory.create(module_type="hierarchical_predecode3x8",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.pre3_8)
|
||||
|
||||
def determine_predecodes(self,num_inputs):
|
||||
|
||||
@@ -3,24 +3,19 @@ import design
|
||||
import math
|
||||
from tech import drc
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from pnand2 import pnand2
|
||||
from pnand3 import pnand3
|
||||
from sram_factory import factory
|
||||
|
||||
class hierarchical_predecode(design.design):
|
||||
"""
|
||||
Pre 2x4 and 3x8 decoder shared code.
|
||||
"""
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, input_number, height=None):
|
||||
def __init__(self, name, input_number, height=None):
|
||||
self.number_of_inputs = input_number
|
||||
self.cell_height = height
|
||||
self.number_of_outputs = int(math.pow(2, self.number_of_inputs))
|
||||
design.design.__init__(self, name="pre{0}x{1}_{2}".format(self.number_of_inputs,self.number_of_outputs,hierarchical_predecode.unique_id))
|
||||
hierarchical_predecode.unique_id += 1
|
||||
design.design.__init__(self, name)
|
||||
|
||||
def add_pins(self):
|
||||
for k in range(self.number_of_inputs):
|
||||
@@ -33,7 +28,8 @@ class hierarchical_predecode(design.design):
|
||||
def add_modules(self):
|
||||
""" Add the INV and NAND gate modules """
|
||||
|
||||
self.inv = pinv(height=self.cell_height)
|
||||
self.inv = factory.create(module_type="pinv",
|
||||
height=self.cell_height)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.add_nand(self.number_of_inputs)
|
||||
@@ -42,9 +38,11 @@ class hierarchical_predecode(design.design):
|
||||
def add_nand(self,inputs):
|
||||
""" Create the NAND for the predecode input stage """
|
||||
if inputs==2:
|
||||
self.nand = pnand2(height=self.cell_height)
|
||||
self.nand = factory.create(module_type="pnand2",
|
||||
height=self.cell_height)
|
||||
elif inputs==3:
|
||||
self.nand = pnand3(height=self.cell_height)
|
||||
self.nand = factory.create(module_type="pnand3",
|
||||
height=self.cell_height)
|
||||
else:
|
||||
debug.error("Invalid number of predecode inputs: {}".format(inputs),-1)
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ class hierarchical_predecode2x4(hierarchical_predecode):
|
||||
"""
|
||||
Pre 2x4 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, height=None):
|
||||
hierarchical_predecode.__init__(self, 2, height)
|
||||
def __init__(self, name, height=None):
|
||||
hierarchical_predecode.__init__(self, name, 2, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
||||
@@ -9,8 +9,8 @@ class hierarchical_predecode3x8(hierarchical_predecode):
|
||||
"""
|
||||
Pre 3x8 decoder used in hierarchical_decoder.
|
||||
"""
|
||||
def __init__(self, height=None):
|
||||
hierarchical_predecode.__init__(self, 3, height)
|
||||
def __init__(self, name, height=None):
|
||||
hierarchical_predecode.__init__(self, name, 3, height)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
||||
@@ -5,12 +5,8 @@ import design
|
||||
import math
|
||||
from math import log,sqrt,ceil
|
||||
import contact
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from pnor2 import pnor2
|
||||
from vector import vector
|
||||
from pinvbuf import pinvbuf
|
||||
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class multibank(design.design):
|
||||
@@ -21,21 +17,8 @@ class multibank(design.design):
|
||||
This module includes the tristate and bank select logic.
|
||||
"""
|
||||
|
||||
def __init__(self, word_size, num_words, words_per_row, num_banks=1, name=""):
|
||||
def __init__(self, name, word_size, num_words, words_per_row, num_banks=1):
|
||||
|
||||
mod_list = ["tri_gate", "bitcell", "decoder", "wordline_driver",
|
||||
"bitcell_array", "sense_amp_array", "precharge_array",
|
||||
"column_mux_array", "write_driver_array", "tri_gate_array",
|
||||
"dff", "bank_select"]
|
||||
from importlib import reload
|
||||
for mod_name in mod_list:
|
||||
config_mod_name = getattr(OPTS, mod_name)
|
||||
class_file = reload(__import__(config_mod_name))
|
||||
mod_class = getattr(class_file , config_mod_name)
|
||||
setattr (self, "mod_"+mod_name, mod_class)
|
||||
|
||||
if name == "":
|
||||
name = "bank_{0}_{1}".format(word_size, num_words)
|
||||
design.design.__init__(self, name)
|
||||
debug.info(2, "create sram of size {0} with {1} words".format(word_size,num_words))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import design
|
||||
import debug
|
||||
from tech import drc
|
||||
from vector import vector
|
||||
from precharge import precharge
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class precharge_array(design.design):
|
||||
@@ -11,14 +11,11 @@ class precharge_array(design.design):
|
||||
of bit line columns, height is the height of the bit-cell array.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, columns, size=1, bitcell_bl="bl", bitcell_br="br"):
|
||||
name = "precharge_array_{}".format(precharge_array.unique_id)
|
||||
precharge_array.unique_id += 1
|
||||
def __init__(self, name, columns, size=1, bitcell_bl="bl", bitcell_br="br"):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
|
||||
self.add_comment("cols: {0} size: {1} bl: {2} br: {3}".format(columns, size, bitcell_bl, bitcell_br))
|
||||
|
||||
self.columns = columns
|
||||
self.size = size
|
||||
self.bitcell_bl = bitcell_bl
|
||||
@@ -50,10 +47,12 @@ class precharge_array(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
self.pc_cell = precharge(name="precharge",
|
||||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
self.pc_cell = factory.create(module_type="precharge",
|
||||
size=self.size,
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
|
||||
|
||||
self.add_mod(self.pc_cell)
|
||||
|
||||
|
||||
@@ -107,4 +106,4 @@ class precharge_array(design.design):
|
||||
"""Get the relative capacitance of all the clk connections in the precharge array"""
|
||||
#Assume single port
|
||||
precharge_en_cin = self.pc_cell.get_en_cin()
|
||||
return precharge_en_cin*self.columns
|
||||
return precharge_en_cin*self.columns
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import debug
|
||||
import design
|
||||
from tech import drc
|
||||
from pinv import pinv
|
||||
import contact
|
||||
from bitcell_array import bitcell_array
|
||||
from ptx import ptx
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
@@ -15,7 +13,7 @@ class replica_bitline(design.design):
|
||||
line and rows is the height of the replica bit loads.
|
||||
"""
|
||||
|
||||
def __init__(self, delay_fanout_list, bitcell_loads, name="replica_bitline"):
|
||||
def __init__(self, name, delay_fanout_list, bitcell_loads):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.bitcell_loads = bitcell_loads
|
||||
@@ -78,29 +76,25 @@ class replica_bitline(design.design):
|
||||
def add_modules(self):
|
||||
""" Add the modules for later usage """
|
||||
|
||||
from importlib import reload
|
||||
#g = reload(__import__(OPTS.delay_chain))
|
||||
#self.mod_delay_chain = getattr(g, OPTS.delay_chain)
|
||||
|
||||
g = reload(__import__(OPTS.replica_bitcell))
|
||||
self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell)
|
||||
|
||||
self.bitcell = self.replica_bitcell = self.mod_replica_bitcell()
|
||||
self.add_mod(self.bitcell)
|
||||
self.replica_bitcell = factory.create(module_type="replica_bitcell")
|
||||
self.add_mod(self.replica_bitcell)
|
||||
|
||||
# This is the replica bitline load column that is the height of our array
|
||||
self.rbl = bitcell_array(cols=1, rows=self.bitcell_loads)
|
||||
self.rbl = factory.create(module_type="bitcell_array",
|
||||
cols=1,
|
||||
rows=self.bitcell_loads)
|
||||
self.add_mod(self.rbl)
|
||||
|
||||
# FIXME: The FO and depth of this should be tuned
|
||||
from delay_chain import delay_chain
|
||||
self.delay_chain = delay_chain(self.delay_fanout_list)
|
||||
self.delay_chain = factory.create(module_type="delay_chain",
|
||||
fanout_list=self.delay_fanout_list)
|
||||
self.add_mod(self.delay_chain)
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pinv")
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.access_tx = ptx(tx_type="pmos")
|
||||
self.access_tx = factory.create(module_type="ptx",
|
||||
tx_type="pmos")
|
||||
self.add_mod(self.access_tx)
|
||||
|
||||
def create_instances(self):
|
||||
@@ -132,7 +126,6 @@ class replica_bitline(design.design):
|
||||
temp.append("vdd")
|
||||
temp.append("gnd")
|
||||
self.connect_inst(temp)
|
||||
#self.connect_inst(["bl_0", "br_0", "delayed_en", "vdd", "gnd"])
|
||||
|
||||
self.rbl_inst=self.add_inst(name="load",
|
||||
mod=self.rbl)
|
||||
@@ -621,7 +614,7 @@ class replica_bitline(design.design):
|
||||
|
||||
#The delay chain triggers the enable on the replica bitline (rbl). This is used to track the bitline delay whereas this
|
||||
#model is intended to track every but that. Therefore, the next stage is the inverter after the rbl.
|
||||
stage2 = self.inv.get_effort_stage(ext_cout, last_stage_is_rise)
|
||||
stage2 = self.inv.get_stage_effort(ext_cout, last_stage_is_rise)
|
||||
stage_effort_list.append(stage2)
|
||||
|
||||
return stage_effort_list
|
||||
@@ -631,4 +624,4 @@ class replica_bitline(design.design):
|
||||
access_tx_cin = self.access_tx.get_cin()
|
||||
rbc_cin = self.replica_bitcell.get_wl_cin()
|
||||
return access_tx_cin + rbc_cin
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import design
|
||||
from tech import drc
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
import debug
|
||||
from globals import OPTS
|
||||
|
||||
@@ -10,9 +11,11 @@ class sense_amp_array(design.design):
|
||||
Dynamically generated sense amp array for all bitlines.
|
||||
"""
|
||||
|
||||
def __init__(self, word_size, words_per_row):
|
||||
design.design.__init__(self, "sense_amp_array")
|
||||
def __init__(self, name, word_size, words_per_row):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.add_comment("word_size {0}".format(word_size))
|
||||
self.add_comment("words_per_row: {0}".format(words_per_row))
|
||||
|
||||
self.word_size = word_size
|
||||
self.words_per_row = words_per_row
|
||||
@@ -51,17 +54,13 @@ class sense_amp_array(design.design):
|
||||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.sense_amp))
|
||||
self.mod_sense_amp = getattr(c, OPTS.sense_amp)
|
||||
self.amp = self.mod_sense_amp("sense_amp")
|
||||
self.amp = factory.create(module_type="sense_amp")
|
||||
|
||||
self.add_mod(self.amp)
|
||||
|
||||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
def create_sense_amp_array(self):
|
||||
self.local_insts = []
|
||||
@@ -143,4 +142,4 @@ class sense_amp_array(design.design):
|
||||
def get_en_cin(self):
|
||||
"""Get the relative capacitance of all the sense amp enable connections in the array"""
|
||||
sense_amp_en_cin = self.amp.get_en_cin()
|
||||
return sense_amp_en_cin * self.words_per_row
|
||||
return sense_amp_en_cin * self.words_per_row
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
from math import log
|
||||
import design
|
||||
from single_level_column_mux import single_level_column_mux
|
||||
import contact
|
||||
from tech import drc
|
||||
import debug
|
||||
import math
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class single_level_column_mux_array(design.design):
|
||||
@@ -14,13 +14,11 @@ class single_level_column_mux_array(design.design):
|
||||
Array of column mux to read the bitlines through the 6T.
|
||||
"""
|
||||
|
||||
unique_id = 1
|
||||
|
||||
def __init__(self, columns, word_size, bitcell_bl="bl", bitcell_br="br"):
|
||||
name="single_level_column_mux_array_{}".format(single_level_column_mux_array.unique_id)
|
||||
single_level_column_mux_array.unique_id += 1
|
||||
def __init__(self, name, columns, word_size, bitcell_bl="bl", bitcell_br="br"):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.add_comment("cols: {0} word_size: {1} bl: {2} br: {3}".format(columns, word_size, bitcell_bl, bitcell_br))
|
||||
|
||||
self.columns = columns
|
||||
self.word_size = word_size
|
||||
self.words_per_row = int(self.columns / self.word_size)
|
||||
@@ -61,7 +59,9 @@ class single_level_column_mux_array(design.design):
|
||||
|
||||
|
||||
def add_modules(self):
|
||||
self.mux = single_level_column_mux(bitcell_bl=self.bitcell_bl, bitcell_br=self.bitcell_br)
|
||||
self.mux = factory.create(module_type="single_level_column_mux",
|
||||
bitcell_bl=self.bitcell_bl,
|
||||
bitcell_br=self.bitcell_br)
|
||||
self.add_mod(self.mux)
|
||||
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@ import debug
|
||||
from tech import drc
|
||||
import design
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class tri_gate_array(design.design):
|
||||
@@ -36,10 +37,7 @@ class tri_gate_array(design.design):
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.tri_gate))
|
||||
self.mod_tri_gate = getattr(c, OPTS.tri_gate)
|
||||
self.tri = self.mod_tri_gate("tri_gate")
|
||||
self.tri = factory.create(module_type="tri_gate")
|
||||
self.add_mod(self.tri)
|
||||
|
||||
def add_pins(self):
|
||||
|
||||
@@ -5,9 +5,8 @@ import contact
|
||||
from math import log
|
||||
from math import sqrt
|
||||
import math
|
||||
from pinv import pinv
|
||||
from pnand2 import pnand2
|
||||
from vector import vector
|
||||
from sram_factory import factory
|
||||
from globals import OPTS
|
||||
|
||||
class wordline_driver(design.design):
|
||||
@@ -16,10 +15,13 @@ class wordline_driver(design.design):
|
||||
Generates the wordline-driver to drive the bitcell
|
||||
"""
|
||||
|
||||
def __init__(self, rows):
|
||||
design.design.__init__(self, "wordline_driver")
|
||||
|
||||
def __init__(self, name, rows, cols):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
|
||||
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
@@ -53,13 +55,16 @@ class wordline_driver(design.design):
|
||||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
|
||||
self.inv = pinv()
|
||||
self.inv = factory.create(module_type="pdriver",
|
||||
fanout=self.cols,
|
||||
neg_polarity=True)
|
||||
self.add_mod(self.inv)
|
||||
|
||||
self.inv_no_output = pinv(route_output=False)
|
||||
self.inv_no_output = factory.create(module_type="pinv",
|
||||
route_output=False)
|
||||
self.add_mod(self.inv_no_output)
|
||||
|
||||
self.nand2 = pnand2()
|
||||
self.nand2 = factory.create(module_type="pnand2")
|
||||
self.add_mod(self.nand2)
|
||||
|
||||
|
||||
@@ -224,12 +229,12 @@ class wordline_driver(design.design):
|
||||
stage_effort_list = []
|
||||
|
||||
stage1_cout = self.inv.get_cin()
|
||||
stage1 = self.nand2.get_effort_stage(stage1_cout, inp_is_rise)
|
||||
stage1 = self.nand2.get_stage_effort(stage1_cout, inp_is_rise)
|
||||
stage_effort_list.append(stage1)
|
||||
last_stage_is_rise = stage1.is_rise
|
||||
|
||||
stage2 = self.inv.get_effort_stage(external_cout, last_stage_is_rise)
|
||||
stage_effort_list.append(stage2)
|
||||
stage2 = self.inv.get_stage_efforts(external_cout, last_stage_is_rise)
|
||||
stage_effort_list.extend(stage2)
|
||||
|
||||
return stage_effort_list
|
||||
|
||||
@@ -237,4 +242,4 @@ class wordline_driver(design.design):
|
||||
"""Get the relative capacitance of all the enable connections in the bank"""
|
||||
#The enable is connected to a nand2 for every row.
|
||||
total_cin = self.nand2.get_cin() * self.rows
|
||||
return total_cin
|
||||
return total_cin
|
||||
|
||||
@@ -23,3 +23,8 @@ class write_driver(design.design):
|
||||
self.height = write_driver.height
|
||||
self.pin_map = write_driver.pin_map
|
||||
|
||||
|
||||
def get_w_en_cin(self):
|
||||
"""Get the relative capacitance of a single input"""
|
||||
# This is approximated from SCMOS. It has roughly 5 3x transistor gates.
|
||||
return 5*3
|
||||
|
||||
@@ -2,6 +2,7 @@ from math import log
|
||||
import design
|
||||
from tech import drc
|
||||
import debug
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
@@ -11,9 +12,11 @@ class write_driver_array(design.design):
|
||||
Dynamically generated write driver array of all bitlines.
|
||||
"""
|
||||
|
||||
def __init__(self, columns, word_size):
|
||||
design.design.__init__(self, "write_driver_array")
|
||||
def __init__(self, name, columns, word_size):
|
||||
design.design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.add_comment("columns: {0}".format(columns))
|
||||
self.add_comment("word_size {0}".format(word_size))
|
||||
|
||||
self.columns = columns
|
||||
self.word_size = word_size
|
||||
@@ -53,17 +56,12 @@ class write_driver_array(design.design):
|
||||
self.add_pin("gnd")
|
||||
|
||||
def add_modules(self):
|
||||
from importlib import reload
|
||||
c = reload(__import__(OPTS.write_driver))
|
||||
self.mod_write_driver = getattr(c, OPTS.write_driver)
|
||||
self.driver = self.mod_write_driver("write_driver")
|
||||
self.driver = factory.create(module_type="write_driver")
|
||||
self.add_mod(self.driver)
|
||||
|
||||
# This is just used for measurements,
|
||||
# so don't add the module
|
||||
c = reload(__import__(OPTS.bitcell))
|
||||
self.mod_bitcell = getattr(c, OPTS.bitcell)
|
||||
self.bitcell = self.mod_bitcell()
|
||||
self.bitcell = factory.create(module_type="bitcell")
|
||||
|
||||
def create_write_array(self):
|
||||
self.driver_insts = {}
|
||||
@@ -134,3 +132,7 @@ class write_driver_array(design.design):
|
||||
|
||||
|
||||
|
||||
def get_w_en_cin(self):
|
||||
"""Get the relative capacitance of all the enable connections in the bank"""
|
||||
#The enable is connected to a nand2 for every row.
|
||||
return self.driver.get_w_en_cin() * len(self.driver_insts)
|
||||
|
||||
Reference in New Issue
Block a user