Converted all modules to not run create_layout when netlist_only

mode is enabled.
This commit is contained in:
Matt Guthaus
2018-08-27 16:42:48 -07:00
parent 9f051df18d
commit 8664f7a0b8
27 changed files with 711 additions and 466 deletions
+20 -17
View File
@@ -56,7 +56,8 @@ class bank(design.design):
self.prefix=""
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
@@ -580,23 +581,25 @@ class bank(design.design):
def route_bank_select(self):
""" Route the bank select logic. """
for input_name in self.input_control_signals+["bank_sel"]:
self.copy_layout_pin(self.bank_select_inst, input_name)
for k in range(self.total_ports):
for input_name in self.input_control_signals+["bank_sel"]:
self.copy_layout_pin(self.bank_select_inst[k], input_name)
for gated_name in self.control_signals:
# Connect the inverter output to the central bus
out_pos = self.bank_select_inst[0].get_pin(gated_name).rc()
bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
self.add_path("metal3",[out_pos, bus_pos])
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=bus_pos,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=out_pos,
rotate=90)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=out_pos,
rotate=90)
for gated_name in self.control_signals:
# Connect the inverter output to the central bus
out_pos = self.bank_select_inst[k].get_pin(gated_name).rc()
bus_pos = vector(self.bus_xoffset[gated_name].x, out_pos.y)
self.add_path("metal3",[out_pos, bus_pos])
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=bus_pos,
rotate=90)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=out_pos,
rotate=90)
self.add_via_center(layers=("metal2", "via2", "metal3"),
offset=out_pos,
rotate=90)
def setup_routing_constraints(self):
+77 -40
View File
@@ -18,9 +18,29 @@ class bank_select(design.design):
def __init__(self, name="bank_select"):
design.design.__init__(self, name)
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_modules()
def create_layout(self):
self.calculate_module_offsets()
self.place_modules()
self.route_modules()
self.DRC_LVS()
def add_pins(self):
# Number of control lines in the bus
self.num_control_lines = 4
# The order of the control signals on the control bus:
# FIXME: Update for multiport (these names are not right)
self.input_control_signals = ["clk_buf", "clk_buf_bar", "w_en0", "s_en0"]
# These will be outputs of the gaters if this is multibank
self.control_signals = ["gated_"+str for str in self.input_control_signals]
@@ -31,14 +51,7 @@ class bank_select(design.design):
self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND")
self.create_modules()
self.calculate_module_offsets()
self.add_modules()
self.route_modules()
self.DRC_LVS()
def create_modules(self):
def add_modules(self):
""" Create modules for later instantiation """
# 1x Inverter
self.inv = pinv()
@@ -67,7 +80,52 @@ class bank_select(design.design):
self.height = self.yoffset_maxpoint + 2*self.m1_pitch
self.width = self.xoffset_inv + self.inv4x.width
def add_modules(self):
def create_modules(self):
self.bank_sel_inv=self.add_inst(name="bank_sel_inv",
mod=self.inv)
self.connect_inst(["bank_sel", "bank_sel_bar", "vdd", "gnd"])
self.logic_inst = []
self.inv_inst = []
for i in range(self.num_control_lines):
input_name = self.input_control_signals[i]
gated_name = self.control_signals[i]
name_nand = "nand_{}".format(input_name)
name_nor = "nor_{}".format(input_name)
name_inv = "inv_{}".format(input_name)
# These require OR (nor2+inv) gates since they are active low.
# (writes occur on clk low)
if input_name in ("clk_buf"):
self.logic_inst.append(self.add_inst(name=name_nor,
mod=self.nor2))
self.connect_inst([input_name,
"bank_sel_bar",
gated_name+"_temp_bar",
"vdd",
"gnd"])
# the rest are AND (nand2+inv) gates
else:
self.logic_inst.append(self.add_inst(name=name_nand,
mod=self.nand2))
self.connect_inst([input_name,
"bank_sel",
gated_name+"_temp_bar",
"vdd",
"gnd"])
# They all get inverters on the output
self.inv_inst.append(self.add_inst(name=name_inv,
mod=self.inv4x))
self.connect_inst([gated_name+"_temp_bar",
gated_name,
"vdd",
"gnd"])
def place_modules(self):
# bank select inverter
self.bank_select_inv_position = vector(self.xoffset_bank_sel_inv, 0)
@@ -78,8 +136,6 @@ class bank_select(design.design):
offset=[self.xoffset_bank_sel_inv, 0])
self.connect_inst(["bank_sel", "bank_sel_bar", "vdd", "gnd"])
self.logic_inst = []
self.inv_inst = []
for i in range(self.num_control_lines):
input_name = self.input_control_signals[i]
gated_name = self.control_signals[i]
@@ -98,40 +154,21 @@ class bank_select(design.design):
# (writes occur on clk low)
if input_name in ("clk_buf"):
self.logic_inst.append(self.add_inst(name=name_nor,
mod=self.nor2,
offset=[self.xoffset_nor, y_offset],
mirror=mirror))
self.connect_inst([input_name,
"bank_sel_bar",
gated_name+"_temp_bar",
"vdd",
"gnd"])
self.place_inst(name=name_nor,
offset=[self.xoffset_nor, y_offset],
mirror=mirror)
# the rest are AND (nand2+inv) gates
else:
self.logic_inst.append(self.add_inst(name=name_nand,
mod=self.nand2,
offset=[self.xoffset_nand, y_offset],
mirror=mirror))
bank_sel_signal = "bank_sel"
self.connect_inst([input_name,
"bank_sel",
gated_name+"_temp_bar",
"vdd",
"gnd"])
self.place_inst(name=name_nand,
offset=[self.xoffset_nand, y_offset],
mirror=mirror)
# They all get inverters on the output
self.inv_inst.append(self.add_inst(name=name_inv,
mod=self.inv4x,
offset=[self.xoffset_inv, y_offset],
mirror=mirror))
self.connect_inst([gated_name+"_temp_bar",
gated_name,
"vdd",
"gnd"])
self.place_inst(name=name_inv,
offset=[self.xoffset_inv, y_offset],
mirror=mirror)
def route_modules(self):
+24 -24
View File
@@ -32,25 +32,25 @@ class bitcell_array(design.design):
self.width = self.column_size*self.cell.width + self.m1_width
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
# We don't offset this because we need to align
# the replica bitcell in the control logic
#self.offset_all_coordinates()
def add_pins(self):
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
def create_netlist(self):
""" Create and connect the netlist """
self.add_pins()
self.cell_inst = {}
for col in range(self.column_size):
for cell_column in column_list:
self.add_pin(cell_column+"[{0}]".format(col))
for row in range(self.row_size):
for cell_row in row_list:
self.add_pin(cell_row+"[{0}]".format(row))
self.add_pin("vdd")
self.add_pin("gnd")
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.cell)
self.connect_inst(self.cell.list_bitcell_pins(col, row))
def create_layout(self):
xoffset = 0.0
@@ -75,18 +75,18 @@ class bitcell_array(design.design):
self.add_layout_pins()
self.DRC_LVS()
def create_netlist(self):
""" Create and connect the netlist """
self.add_pins()
self.cell_inst = {}
def add_pins(self):
row_list = self.cell.list_all_wl_names()
column_list = self.cell.list_all_bitline_names()
for col in range(self.column_size):
for row in range(self.row_size):
name = "bit_r{0}_c{1}".format(row, col)
self.cell_inst[row,col]=self.add_inst(name=name,
mod=self.cell)
self.connect_inst(self.cell.list_bitcell_pins(col, row))
for cell_column in column_list:
self.add_pin(cell_column+"[{0}]".format(col))
for row in range(self.row_size):
for cell_row in row_list:
self.add_pin(cell_row+"[{0}]".format(row))
self.add_pin("vdd")
self.add_pin("gnd")
def add_layout_pins(self):
+147 -107
View File
@@ -24,17 +24,26 @@ class control_logic(design.design):
debug.info(1, "Creating {}".format(self.name))
self.num_rows = num_rows
self.create_layout()
self.DRC_LVS()
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.setup_signal_busses()
self.add_pins()
self.add_modules()
self.create_modules()
def create_layout(self):
""" Create layout and route between modules """
self.setup_layout_offsets()
self.add_pins()
self.create_modules()
self.add_rails()
self.add_modules()
self.add_routing()
self.route_rails()
self.place_modules()
self.route_all()
self.add_lvs_correspondence_points()
self.DRC_LVS()
def add_pins(self):
@@ -46,8 +55,8 @@ class control_logic(design.design):
self.add_pin("vdd","POWER")
self.add_pin("gnd","GROUND")
def create_modules(self):
""" add all the required modules """
def add_modules(self):
""" Add all the required modules """
dff = dff_inv()
dff_height = dff.height
@@ -83,14 +92,8 @@ class control_logic(design.design):
self.add_mod(self.replica_bitline)
def setup_layout_offsets(self):
""" Setup layout offsets, determine the size of the busses etc """
# These aren't for instantiating, but we use them to get the dimensions
#self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height)
# Have the cell gap leave enough room to route an M2 wire.
# Some cells may have pwell/nwell spacing problems too when the wells are different heights.
#self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"])
def setup_signal_busses(self):
""" Setup bus names, determine the size of the busses etc """
# List of input control signals
self.input_list =["csb","web"]
@@ -104,7 +107,7 @@ class control_logic(design.design):
self.supply_list = ["vdd", "gnd"]
def add_rails(self):
def route_rails(self):
""" Add the input signal inverted tracks """
height = 4*self.inv1.height - self.m2_pitch
offset = vector(self.ctrl_dff_array.width,0)
@@ -112,7 +115,20 @@ class control_logic(design.design):
self.rail_offsets = self.create_vertical_bus("metal2", self.m2_pitch, offset, self.internal_bus_list, height)
def add_modules(self):
def create_modules(self):
""" Create all the modules """
self.create_dffs()
self.create_clk_row()
self.create_we_row()
# self.create_trien_row()
# self.create_trien_bar_row()
self.create_rbl_in_row()
self.create_sen_row()
self.create_rbl()
def place_modules(self):
""" Place all the modules """
# Keep track of all right-most instances to determine row boundary
# and add the vdd/gnd pins
@@ -120,20 +136,18 @@ class control_logic(design.design):
# Add the control flops on the left of the bus
self.add_dffs()
self.place_dffs()
# Add the logic on the right of the bus
self.add_clk_row(row=0) # clk is a double-high cell
self.add_we_row(row=2)
# self.add_trien_row(row=3)
# self.add_trien_bar_row(row=4)
self.add_rbl_in_row(row=3)
self.add_sen_row(row=4)
self.add_rbl(row=5)
self.place_clk_row(row=0) # clk is a double-high cell
self.place_we_row(row=2)
# self.place_trien_row(row=3)
# self.place_trien_bar_row(row=4)
self.place_rbl_in_row(row=3)
self.place_sen_row(row=4)
self.place_rbl(row=5)
self.add_lvs_correspondence_points()
# This offset is used for placement of the control logic in
# the SRAM level.
self.control_logic_center = vector(self.ctrl_dff_inst.rx(), self.rbl_inst.by())
@@ -142,9 +156,9 @@ class control_logic(design.design):
self.height = self.rbl_inst.uy() + self.m3_pitch
# Max of modules or logic rows
self.width = max(self.rbl_inst.rx(), max([inst.rx() for inst in self.row_end_inst])) + self.m2_pitch
def add_routing(self):
def route_all(self):
""" Routing between modules """
self.route_dffs()
#self.route_trien()
@@ -156,84 +170,98 @@ class control_logic(design.design):
self.route_supply()
def add_rbl(self,row):
""" Add the replica bitline """
def create_rbl(self):
""" Create the replica bitline """
self.rbl_inst=self.add_inst(name="replica_bitline",
mod=self.replica_bitline)
self.connect_inst(["rbl_in", "pre_s_en", "vdd", "gnd"])
def place_rbl(self,row):
""" Place the replica bitline """
y_off = row * self.inv1.height + 2*self.m1_pitch
# Add the RBL above the rows
# Add to the right of the control rows and routing channel
self.replica_bitline_offset = vector(0, y_off)
self.rbl_inst=self.add_inst(name="replica_bitline",
mod=self.replica_bitline,
offset=self.replica_bitline_offset)
self.connect_inst(["rbl_in", "pre_s_en", "vdd", "gnd"])
self.place_inst(name="replica_bitline",
offset=self.replica_bitline_offset)
def add_clk_row(self,row):
""" Add the multistage clock buffer below the control flops """
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
clkbuf_offset = vector(x_off,y_off)
def create_clk_row(self):
""" Create the multistage clock buffer """
self.clkbuf_inst = self.add_inst(name="clkbuf",
mod=self.clkbuf,
offset=clkbuf_offset)
mod=self.clkbuf)
self.connect_inst(["clk","clk_buf_bar","clk_buf","vdd","gnd"])
def place_clk_row(self,row):
""" Place the multistage clock buffer below the control flops """
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
clkbuf_offset = vector(x_off,y_off)
self.place_inst(name="clkbuf",
offset=clkbuf_offset)
self.row_end_inst.append(self.clkbuf_inst)
def add_rbl_in_row(self,row):
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
# input: clk_buf_bar,CS output: rbl_in_bar
self.rbl_in_bar_offset = vector(x_off, y_off)
def create_rbl_in_row(self):
self.rbl_in_bar_inst=self.add_inst(name="nand3_rbl_in_bar",
mod=self.nand2,
offset=self.rbl_in_bar_offset,
mirror=mirror)
mod=self.nand2)
self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"])
x_off += self.nand2.width
# input: rbl_in_bar, output: rbl_in
self.rbl_in_offset = vector(x_off, y_off)
self.rbl_in_inst=self.add_inst(name="inv_rbl_in",
mod=self.inv1,
offset=self.rbl_in_offset,
mirror=mirror)
mod=self.inv1)
self.connect_inst(["rbl_in_bar", "rbl_in", "vdd", "gnd"])
self.row_end_inst.append(self.rbl_in_inst)
def add_sen_row(self,row):
""" The sense enable buffer gets placed to the far right of the
row. """
def place_rbl_in_row(self,row):
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
self.rbl_in_bar_offset = vector(x_off, y_off)
self.place_inst(name="nand3_rbl_in_bar",
offset=self.rbl_in_bar_offset,
mirror=mirror)
x_off += self.nand2.width
self.rbl_in_offset = vector(x_off, y_off)
self.place_inst(name="inv_rbl_in",
offset=self.rbl_in_offset,
mirror=mirror)
self.row_end_inst.append(self.rbl_in_inst)
def create_sen_row(self):
""" Create the sense enable buffer. """
# input: pre_s_en, output: pre_s_en_bar
self.pre_s_en_bar_offset = vector(x_off, y_off)
self.pre_s_en_bar_inst=self.add_inst(name="inv_pre_s_en_bar",
mod=self.inv2,
offset=self.pre_s_en_bar_offset,
mirror=mirror)
mod=self.inv2)
self.connect_inst(["pre_s_en", "pre_s_en_bar", "vdd", "gnd"])
x_off += self.inv2.width
# BUFFER INVERTERS FOR S_EN
# input: input: pre_s_en_bar, output: s_en
self.s_en_offset = vector(x_off, y_off)
self.s_en_inst=self.add_inst(name="inv_s_en",
mod=self.inv8,
offset=self.s_en_offset,
mirror=mirror)
mod=self.inv8)
self.connect_inst(["pre_s_en_bar", "s_en0", "vdd", "gnd"])
def place_sen_row(self,row):
"""
The sense enable buffer gets placed to the far right of the
row.
"""
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
self.pre_s_en_bar_offset = vector(x_off, y_off)
self.place_inst(name="inv_pre_s_en_bar",
offset=self.pre_s_en_bar_offset,
mirror=mirror)
x_off += self.inv2.width
self.s_en_offset = vector(x_off, y_off)
self.place_inst(name="inv_s_en",
offset=self.s_en_offset,
mirror=mirror)
self.row_end_inst.append(self.s_en_inst)
@@ -256,14 +284,17 @@ class control_logic(design.design):
self.copy_layout_pin(self.ctrl_dff_inst, "din[1]", "web")
def add_dffs(self):
def create_dffs(self):
""" Add the three input DFFs (with inverters) """
self.ctrl_dff_inst=self.add_inst(name="ctrl_dffs",
mod=self.ctrl_dff_array,
offset=vector(0,0))
mod=self.ctrl_dff_array)
self.connect_inst(self.input_list + self.dff_output_list + ["clk_buf"] + self.supply_list)
def place_dffs(self):
""" Place the input DFFs (with inverters) """
self.place_inst(name="ctrl_dffs",
offset=vector(0,0))
def get_offset(self,row):
""" Compute the y-offset and mirroring """
@@ -276,48 +307,57 @@ class control_logic(design.design):
return (y_off,mirror)
def add_we_row(self,row):
def create_we_row(self):
# input: WE, CS output: w_en_bar
self.w_en_bar_inst=self.add_inst(name="nand3_w_en_bar",
mod=self.nand3)
self.connect_inst(["clk_buf_bar", "cs", "we", "w_en_bar", "vdd", "gnd"])
# input: w_en_bar, output: pre_w_en
self.pre_w_en_inst=self.add_inst(name="inv_pre_w_en",
mod=self.inv1)
self.connect_inst(["w_en_bar", "pre_w_en", "vdd", "gnd"])
# BUFFER INVERTERS FOR W_EN
self.pre_w_en_bar_inst=self.add_inst(name="inv_pre_w_en_bar",
mod=self.inv2)
self.connect_inst(["pre_w_en", "pre_w_en_bar", "vdd", "gnd"])
self.w_en_inst=self.add_inst(name="inv_w_en2",
mod=self.inv8)
self.connect_inst(["pre_w_en_bar", "w_en0", "vdd", "gnd"])
def place_we_row(self,row):
x_off = self.ctrl_dff_inst.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
# input: WE, CS output: w_en_bar
w_en_bar_offset = vector(x_off, y_off)
self.w_en_bar_inst=self.add_inst(name="nand3_w_en_bar",
mod=self.nand3,
offset=w_en_bar_offset,
mirror=mirror)
self.connect_inst(["clk_buf_bar", "cs", "we", "w_en_bar", "vdd", "gnd"])
self.place_inst(name="nand3_w_en_bar",
offset=w_en_bar_offset,
mirror=mirror)
x_off += self.nand3.width
# input: w_en_bar, output: pre_w_en
pre_w_en_offset = vector(x_off, y_off)
self.pre_w_en_inst=self.add_inst(name="inv_pre_w_en",
mod=self.inv1,
offset=pre_w_en_offset,
mirror=mirror)
self.connect_inst(["w_en_bar", "pre_w_en", "vdd", "gnd"])
self.place_inst(name="inv_pre_w_en",
offset=pre_w_en_offset,
mirror=mirror)
x_off += self.inv1.width
# BUFFER INVERTERS FOR W_EN
pre_w_en_bar_offset = vector(x_off, y_off)
self.pre_w_en_bar_inst=self.add_inst(name="inv_pre_w_en_bar",
mod=self.inv2,
offset=pre_w_en_bar_offset,
mirror=mirror)
self.connect_inst(["pre_w_en", "pre_w_en_bar", "vdd", "gnd"])
self.place_inst(name="inv_pre_w_en_bar",
offset=pre_w_en_bar_offset,
mirror=mirror)
x_off += self.inv2.width
w_en_offset = vector(x_off, y_off)
self.w_en_inst=self.add_inst(name="inv_w_en2",
mod=self.inv8,
offset=w_en_offset,
mirror=mirror)
self.connect_inst(["pre_w_en_bar", "w_en0", "vdd", "gnd"])
self.place_inst(name="inv_w_en2",
offset=w_en_offset,
mirror=mirror)
x_off += self.inv8.width
self.row_end_inst.append(self.w_en_inst)
def route_rbl_in(self):
""" Connect the logic for the rbl_in generation """
+47 -31
View File
@@ -24,14 +24,23 @@ class delay_chain(design.design):
# number of inverters including any fanout loads.
self.fanout_list = fanout_list
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_module()
self.add_inverters()
self.add_modules()
self.create_inverters()
def create_layout(self):
# Each stage is a a row
self.height = len(self.fanout_list)*self.inv.height
# The width is determined by the largest fanout plus the driver
self.width = (max(self.fanout_list)+1) * self.inv.width
self.place_inverters()
self.route_inverters()
self.add_layout_pins()
self.DRC_LVS()
@@ -43,40 +52,27 @@ class delay_chain(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def create_module(self):
""" Add the inverter logical module """
def add_modules(self):
from importlib import reload
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
self.inv = pinv(route_output=False)
self.add_mod(self.inv)
# Each stage is a a row
self.height = len(self.fanout_list)*self.inv.height
# The width is determined by the largest fanout plus the driver
self.width = (max(self.fanout_list)+1) * self.inv.width
def add_inverters(self):
""" Add the inverters and connect them based on the stage list """
def create_inverters(self):
""" Create the inverters and connect them based on the stage list """
self.driver_inst_list = []
self.rightest_load_inst = {}
self.load_inst_map = {}
for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list):
if stage_num % 2:
inv_mirror = "MX"
inv_offset = vector(0, (stage_num+1)* self.inv.height)
else:
inv_mirror = "R0"
inv_offset = vector(0, stage_num * self.inv.height)
# Add the inverter
cur_driver=self.add_inst(name="dinv{}".format(stage_num),
mod=self.inv,
offset=inv_offset,
mirror=inv_mirror)
mod=self.inv)
# keep track of the inverter instances so we can use them to get the pins
self.driver_inst_list.append(cur_driver)
# Hook up the driver
if stage_num+1==len(self.fanout_list):
stageout_name = "out"
@@ -91,11 +87,8 @@ class delay_chain(design.design):
# Now add the dummy loads to the right
self.load_inst_map[cur_driver]=[]
for i in range(fanout_size):
inv_offset += vector(self.inv.width,0)
cur_load=self.add_inst(name="dload_{0}_{1}".format(stage_num,i),
mod=self.inv,
offset=inv_offset,
mirror=inv_mirror)
mod=self.inv)
# Fanout stage is always driven by driver and output is disconnected
disconnect_name = "n_{0}_{1}".format(stage_num,i)
self.connect_inst([stageout_name, disconnect_name, "vdd", "gnd"])
@@ -105,6 +98,29 @@ class delay_chain(design.design):
else:
# Keep track of the last one so we can add the the wire later
self.rightest_load_inst[cur_driver]=cur_load
def place_inverters(self):
""" Place the inverters and connect them based on the stage list """
for stage_num,fanout_size in zip(range(len(self.fanout_list)),self.fanout_list):
if stage_num % 2:
inv_mirror = "MX"
inv_offset = vector(0, (stage_num+1)* self.inv.height)
else:
inv_mirror = "R0"
inv_offset = vector(0, stage_num * self.inv.height)
# Add the inverter
self.place_inst(name="dinv{}".format(stage_num),
offset=inv_offset,
mirror=inv_mirror)
# Now add the dummy loads to the right
for i in range(fanout_size):
inv_offset += vector(self.inv.width,0)
self.place_inst(name="dload_{0}_{1}".format(stage_num,i),
offset=inv_offset,
mirror=inv_mirror)
def add_route(self, pin1, pin2):
""" This guarantees that we route from the top to bottom row correctly. """
+12 -8
View File
@@ -20,21 +20,21 @@ class dff_buf_array(design.design):
name = "dff_buf_array_{0}x{1}".format(rows, columns)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.dff = dff_buf.dff_buf(inv1_size, inv2_size)
self.add_mod(self.dff)
self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height
self.inv1_size = inv1_size
self.inv2_size = inv2_size
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_dff()
self.create_dff_array()
def create_layout(self):
self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height
self.place_dff_array()
self.add_layout_pins()
self.DRC_LVS()
@@ -51,6 +51,10 @@ class dff_buf_array(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def add_dff(self):
self.dff = dff_buf.dff_buf(self.inv1_size, self.inv2_size)
self.add_mod(self.dff)
def create_dff_array(self):
self.dff_insts={}
for row in range(self.rows):
+35 -19
View File
@@ -18,31 +18,30 @@ class dff_inv(design.design):
name = "dff_inv_{0}".format(inv_size)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.inv_size = inv_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.
debug.check(inv_size>=2, "Inverter must be greater than two for rail spacing DRC rules.")
from importlib import reload
c = reload(__import__(OPTS.dff))
self.mod_dff = getattr(c, OPTS.dff)
self.dff = self.mod_dff("dff")
self.add_mod(self.dff)
self.inv1 = pinv(size=inv_size,height=self.dff.height)
self.add_mod(self.inv1)
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_modules()
def create_layout(self):
self.width = self.dff.width + self.inv1.width
self.height = self.dff.height
self.create_layout()
def create_layout(self):
self.add_pins()
self.add_insts()
self.place_modules()
self.add_wires()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
@@ -53,18 +52,35 @@ class dff_inv(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def add_insts(self):
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.add_mod(self.dff)
self.inv1 = pinv(size=self.inv_size,height=self.dff.height)
self.add_mod(self.inv1)
def create_modules(self):
# Add the DFF
self.dff_inst=self.add_inst(name="dff_inv_dff",
mod=self.dff,
offset=vector(0,0))
mod=self.dff)
self.connect_inst(["D", "Q", "clk", "vdd", "gnd"])
# Add INV1 to the right
self.inv1_inst=self.add_inst(name="dff_inv_inv1",
mod=self.inv1,
offset=vector(self.dff_inst.rx(),0))
mod=self.inv1)
self.connect_inst(["Q", "Qb", "vdd", "gnd"])
def place_modules(self):
# Place the DFF
self.place_inst(name="dff_inv_dff",
offset=vector(0,0))
# Place the INV1 to the right
self.place_inst(name="dff_inv_inv1",
offset=vector(self.dff_inst.rx(),0))
def add_wires(self):
+31 -17
View File
@@ -20,21 +20,29 @@ class dff_inv_array(design.design):
name = "dff_inv_array_{0}x{1}".format(rows, columns)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.inv_size = inv_size
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
self.dff = dff_inv.dff_inv(inv_size)
self.add_mod(self.dff)
def create_netlist(self):
self.add_pins()
self.add_dff()
self.create_dff_array()
def create_layout(self):
self.width = self.columns * self.dff.width
self.height = self.rows * self.dff.height
self.create_layout()
def create_layout(self):
self.add_pins()
self.create_dff_array()
self.place_dff_array()
self.add_layout_pins()
self.DRC_LVS()
def add_dff(self):
self.dff = dff_inv.dff_inv(self.inv_size)
self.add_mod(self.dff)
def add_pins(self):
for row in range(self.rows):
for col in range(self.columns):
@@ -52,16 +60,8 @@ class dff_inv_array(design.design):
for row in range(self.rows):
for col in range(self.columns):
name = "Xdff_r{0}_c{1}".format(row,col)
if (row % 2 == 0):
base = vector(col*self.dff.width,row*self.dff.height)
mirror = "R0"
else:
base = vector(col*self.dff.width,(row+1)*self.dff.height)
mirror = "MX"
self.dff_insts[row,col]=self.add_inst(name=name,
mod=self.dff,
offset=base,
mirror=mirror)
mod=self.dff)
self.connect_inst([self.get_din_name(row,col),
self.get_dout_name(row,col),
self.get_dout_bar_name(row,col),
@@ -69,6 +69,20 @@ class dff_inv_array(design.design):
"vdd",
"gnd"])
def place_dff_array(self):
for row in range(self.rows):
for col in range(self.columns):
name = "Xdff_r{0}_c{1}".format(row,col)
if (row % 2 == 0):
base = vector(col*self.dff.width,row*self.dff.height)
mirror = "R0"
else:
base = vector(col*self.dff.width,(row+1)*self.dff.height)
mirror = "MX"
self.place_inst(name=name,
offset=base,
mirror=mirror)
def get_din_name(self, row, col):
if self.columns == 1:
din_name = "din[{0}]".format(row)
+2 -1
View File
@@ -37,7 +37,8 @@ class hierarchical_decoder(design.design):
(self.no_of_pre2x4,self.no_of_pre3x8)=self.determine_predecodes(self.num_inputs)
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
+1 -1
View File
@@ -49,7 +49,7 @@ class hierarchical_predecode(design.design):
else:
debug.error("Invalid number of predecode inputs: {}".format(inputs),-1)
def setup_constraints(self):
def setup_layout_constraints(self):
self.height = self.number_of_outputs * self.nand.height
@@ -3,6 +3,7 @@ import debug
import design
from vector import vector
from hierarchical_predecode import hierarchical_predecode
from globals import OPTS
class hierarchical_predecode2x4(hierarchical_predecode):
"""
@@ -11,13 +12,13 @@ class hierarchical_predecode2x4(hierarchical_predecode):
def __init__(self):
hierarchical_predecode.__init__(self, 2)
self.add_pins()
self.create_modules()
self.setup_constraints()
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_modules()
self.create_input_inverters()
self.create_output_inverters()
connections =[["inbar[0]", "inbar[1]", "Z[0]", "vdd", "gnd"],
@@ -33,6 +34,7 @@ class hierarchical_predecode2x4(hierarchical_predecode):
3) a set of M2 rails for the vdd, gnd, inverted inputs, inputs
4) a set of NAND gates for inversion
"""
self.setup_layout_constraints()
self.route_rails()
self.place_input_inverters()
self.place_output_inverters()
@@ -3,6 +3,7 @@ import debug
import design
from vector import vector
from hierarchical_predecode import hierarchical_predecode
from globals import OPTS
class hierarchical_predecode3x8(hierarchical_predecode):
"""
@@ -11,13 +12,13 @@ class hierarchical_predecode3x8(hierarchical_predecode):
def __init__(self):
hierarchical_predecode.__init__(self, 3)
self.add_pins()
self.create_modules()
self.setup_constraints()
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_modules()
self.create_input_inverters()
self.create_output_inverters()
connections=[["inbar[0]", "inbar[1]", "inbar[2]", "Z[0]", "vdd", "gnd"],
@@ -38,6 +39,7 @@ class hierarchical_predecode3x8(hierarchical_predecode):
3) a set of M2 rails for the vdd, gnd, inverted inputs, inputs
4) a set of NAND gates for inversion
"""
self.setup_layout_constraints()
self.route_rails()
self.place_input_inverters()
self.place_output_inverters()
+6 -5
View File
@@ -3,7 +3,7 @@ import debug
from tech import drc
from vector import vector
from precharge import precharge
from globals import OPTS
class precharge_array(design.design):
"""
@@ -24,11 +24,9 @@ class precharge_array(design.design):
self.pc_cell = precharge(name="precharge", size=size, bitcell_bl=bitcell_bl, bitcell_br=bitcell_br)
self.add_mod(self.pc_cell)
self.width = self.columns * self.pc_cell.width
self.height = self.pc_cell.height
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def add_pins(self):
"""Adds pins for spice file"""
@@ -43,6 +41,9 @@ class precharge_array(design.design):
self.create_insts()
def create_layout(self):
self.width = self.columns * self.pc_cell.width
self.height = self.pc_cell.height
self.place_insts()
self.add_layout_pins()
self.DRC_LVS()
+45 -21
View File
@@ -24,16 +24,24 @@ class replica_bitline(design.design):
g = reload(__import__(OPTS.replica_bitcell))
self.mod_replica_bitcell = getattr(g, OPTS.replica_bitcell)
for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin)
self.bitcell_loads = bitcell_loads
self.delay_stages = delay_stages
self.delay_fanout = delay_fanout
self.create_modules()
self.calculate_module_offsets()
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin)
self.add_modules()
self.create_modules()
def create_layout(self):
self.calculate_module_offsets()
self.place_modules()
self.route()
self.offset_all_coordinates()
@@ -48,6 +56,7 @@ class replica_bitline(design.design):
self.DRC_LVS()
def calculate_module_offsets(self):
""" Calculate all the module offsets """
@@ -74,8 +83,8 @@ class replica_bitline(design.design):
def create_modules(self):
""" Create modules for later instantiation """
def add_modules(self):
""" Add the modules for later usage """
self.bitcell = self.replica_bitcell = self.mod_replica_bitcell()
self.add_mod(self.bitcell)
@@ -93,38 +102,53 @@ class replica_bitline(design.design):
self.access_tx = ptx(tx_type="pmos")
self.add_mod(self.access_tx)
def add_modules(self):
""" Add all of the module instances in the logical netlist """
def create_modules(self):
""" Create all of the module instances in the logical netlist """
# This is the threshold detect inverter on the output of the RBL
self.rbl_inv_inst=self.add_inst(name="rbl_inv",
mod=self.inv,
offset=self.rbl_inv_offset,
rotate=180)
mod=self.inv)
self.connect_inst(["bl[0]", "out", "vdd", "gnd"])
self.tx_inst=self.add_inst(name="rbl_access_tx",
mod=self.access_tx,
offset=self.access_tx_offset)
mod=self.access_tx)
# D, G, S, B
self.connect_inst(["vdd", "delayed_en", "bl[0]", "vdd"])
# add the well and poly contact
self.dc_inst=self.add_inst(name="delay_chain",
mod=self.delay_chain,
offset=self.delay_chain_offset)
mod=self.delay_chain)
self.connect_inst(["en", "delayed_en", "vdd", "gnd"])
self.rbc_inst=self.add_inst(name="bitcell",
mod=self.replica_bitcell,
offset=self.bitcell_offset,
mirror="MX")
mod=self.replica_bitcell)
self.connect_inst(["bl[0]", "br[0]", "delayed_en", "vdd", "gnd"])
self.rbl_inst=self.add_inst(name="load",
mod=self.rbl,
offset=self.rbl_offset)
mod=self.rbl)
self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.bitcell_loads + ["vdd", "gnd"])
def place_modules(self):
""" Add all of the module instances in the logical netlist """
# This is the threshold detect inverter on the output of the RBL
self.place_inst(name="rbl_inv",
offset=self.rbl_inv_offset,
rotate=180)
self.place_inst(name="rbl_access_tx",
offset=self.access_tx_offset)
self.place_inst(name="delay_chain",
offset=self.delay_chain_offset)
self.place_inst(name="bitcell",
offset=self.bitcell_offset,
mirror="MX")
self.place_inst(name="load",
offset=self.rbl_offset)
+13 -12
View File
@@ -21,10 +21,21 @@ class wordline_driver(design.design):
self.rows = rows
self.create_netlist()
self.create_layout()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_drivers()
def create_layout(self):
self.place_drivers()
self.route_layout()
self.route_vdd_gnd()
self.offset_all_coordinates()
self.DRC_LVS()
def add_pins(self):
# inputs to wordline_driver.
for i in range(self.rows):
@@ -36,16 +47,6 @@ class wordline_driver(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_drivers()
def create_layout(self):
self.place_drivers()
self.route_layout()
self.route_vdd_gnd()
def add_modules(self):
self.inv = pinv()