Add netlist only mode to new pgates

This commit is contained in:
Matt Guthaus 2018-11-26 15:29:42 -08:00
parent 2eff166527
commit b440031855
4 changed files with 141 additions and 151 deletions

View File

@ -4,8 +4,9 @@ from tech import drc, parameter
import debug import debug
import contact import contact
from pinv import pinv from pinv import pinv
from pbuf import pbuf
from pand2 import pand2
from pnand2 import pnand2 from pnand2 import pnand2
from pnand3 import pnand3
from pinvbuf import pinvbuf from pinvbuf import pinvbuf
from dff_inv import dff_inv from dff_inv import dff_inv
from dff_inv_array import dff_inv_array from dff_inv_array import dff_inv_array
@ -71,22 +72,30 @@ class control_logic(design.design):
self.ctrl_dff_array = dff_inv_array(rows=self.num_control_signals,columns=1) self.ctrl_dff_array = dff_inv_array(rows=self.num_control_signals,columns=1)
self.add_mod(self.ctrl_dff_array) self.add_mod(self.ctrl_dff_array)
self.and2 = pand2(height=dff_height)
self.add_mod(self.and2)
self.nand2 = pnand2(height=dff_height) self.nand2 = pnand2(height=dff_height)
self.add_mod(self.nand2) self.add_mod(self.nand2)
self.nand3 = pnand3(height=dff_height)
self.add_mod(self.nand3)
# Special gates: inverters for buffering # Special gates: inverters for buffering
# Size the clock for the number of rows (fanout) # Size the clock for the number of rows (fanout)
clock_driver_size = max(1,int(self.num_rows/4)) clock_driver_size = max(1,int(self.num_rows/4))
self.clkbuf = pinvbuf(clock_driver_size,height=dff_height) self.clkbuf = pbuf(size=clock_driver_size, height=dff_height)
self.add_mod(self.clkbuf) self.add_mod(self.clkbuf)
self.inv = self.inv1 = pinv(size=1, height=dff_height)
self.add_mod(self.inv1) self.pbuf8 = pbuf(size=8, height=dff_height)
self.inv2 = pinv(size=4, height=dff_height) self.add_mod(self.pbuf8)
self.add_mod(self.inv2)
self.inv8 = pinv(size=16, height=dff_height) self.pbuf1 = pbuf(size=1, height=dff_height)
self.add_mod(self.inv8) self.add_mod(self.pbuf1)
# self.inv = self.inv1 = pinv(size=1, height=dff_height)
# self.add_mod(self.inv1)
# self.inv2 = pinv(size=4, height=dff_height)
# self.add_mod(self.inv2)
# self.inv8 = pinv(size=16, height=dff_height)
# self.add_mod(self.inv8)
if (self.port_type == "rw") or (self.port_type == "r"): if (self.port_type == "rw") or (self.port_type == "r"):
from importlib import reload from importlib import reload
@ -157,7 +166,7 @@ class control_logic(design.design):
def create_instances(self): def create_instances(self):
""" Create all the instances """ """ Create all the instances """
self.create_dffs() self.create_dffs()
self.create_clk_row() self.create_clk_rows()
if (self.port_type == "rw") or (self.port_type == "w"): if (self.port_type == "rw") or (self.port_type == "w"):
self.create_we_row() self.create_we_row()
if (self.port_type == "rw") or (self.port_type == "r"): if (self.port_type == "rw") or (self.port_type == "r"):
@ -177,8 +186,10 @@ class control_logic(design.design):
row = 0 row = 0
# Add the logic on the right of the bus # Add the logic on the right of the bus
self.place_clk_row(row=row) # clk is a double-high cell self.place_clkbuf_row(row=row)
row += 2 row += 1
self.place_gated_clk_row(row=row)
row += 1
if (self.port_type == "rw") or (self.port_type == "w"): if (self.port_type == "rw") or (self.port_type == "w"):
self.place_we_row(row=row) self.place_we_row(row=row)
height = self.w_en_inst.uy() height = self.w_en_inst.uy()
@ -219,11 +230,11 @@ class control_logic(design.design):
""" Create the replica bitline """ """ Create the replica bitline """
self.rbl_inst=self.add_inst(name="replica_bitline", self.rbl_inst=self.add_inst(name="replica_bitline",
mod=self.replica_bitline) mod=self.replica_bitline)
self.connect_inst(["rbl_in", "pre_s_en", "vdd", "gnd"]) self.connect_inst(["pre_p_en", "pre_s_en", "vdd", "gnd"])
def place_rbl(self,row): def place_rbl(self,row):
""" Place the replica bitline """ """ Place the replica bitline """
y_off = row * self.inv1.height + 2*self.m1_pitch y_off = row * self.nand2.height + 2*self.m1_pitch
# Add the RBL above the rows # Add the RBL above the rows
# Add to the right of the control rows and routing channel # Add to the right of the control rows and routing channel
@ -231,30 +242,38 @@ class control_logic(design.design):
self.rbl_inst.place(self.replica_bitline_offset) self.rbl_inst.place(self.replica_bitline_offset)
def create_clk_row(self): def create_clk_rows(self):
""" Create the multistage clock buffer """ """ Create the multistage and gated clock buffer """
self.clkbuf_inst = self.add_inst(name="clkbuf", self.clkbuf_inst = self.add_inst(name="clkbuf",
mod=self.clkbuf) mod=self.clkbuf)
self.connect_inst(["clk","clk_buf_bar","clk_buf","vdd","gnd"]) self.connect_inst(["clk","clk_buf","vdd","gnd"])
def place_clk_row(self,row): self.gated_clk_inst = self.add_inst(name="gated_clkbuf",
mod=self.pbuf1)
self.connect_inst(["cs","clk_buf","gated_clk","vdd","gnd"])
def place_clkbuf_row(self,row):
""" Place the multistage clock buffer below the control flops """ """ Place the multistage clock buffer below the control flops """
x_off = self.ctrl_dff_array.width + self.internal_bus_width x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row) (y_off,mirror)=self.get_offset(row)
clkbuf_offset = vector(x_off,y_off) offset = vector(x_off,y_off)
self.clkbuf_inst.place(clkbuf_offset) self.clkbuf_inst.place(offset)
self.row_end_inst.append(self.clkbuf_inst) self.row_end_inst.append(self.clkbuf_inst)
def place_gatedclk_row(self,row):
""" Place the gated clk logic below the control flops """
x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row)
offset = vector(x_off,y_off)
self.gated_clk_inst.place(offset)
self.row_end_inst.append(self.gated_clk_inst)
def create_rbl_in_row(self): def create_rbl_in_row(self):
self.rbl_in_bar_inst=self.add_inst(name="nand2_rbl_in_bar", # input: gated_clk, we_bar, output: pre_p_en
mod=self.nand2) self.pre_p_en_inst=self.add_inst(name="and2_pre_p_en",
self.connect_inst(["clk_buf_bar", "cs", "rbl_in_bar", "vdd", "gnd"]) mod=self.and2)
self.connect_inst(["gated_clk", "we_bar", "pre_p_en", "vdd", "gnd"])
# input: rbl_in_bar, output: rbl_in
self.rbl_in_inst=self.add_inst(name="inv_rbl_in",
mod=self.inv1)
self.connect_inst(["rbl_in_bar", "rbl_in", "vdd", "gnd"])
def place_rbl_in_row(self,row): def place_rbl_in_row(self,row):
@ -262,28 +281,20 @@ class control_logic(design.design):
(y_off,mirror)=self.get_offset(row) (y_off,mirror)=self.get_offset(row)
self.rbl_in_bar_offset = vector(x_off, y_off) self.pre_p_en_offset = vector(x_off, y_off)
self.rbl_in_bar_inst.place(offset=self.rbl_in_bar_offset, self.pre_p_en_inst.place(offset=self.pre_p_en_offset,
mirror=mirror) mirror=mirror)
x_off += self.nand2.width x_off += self.and2.width
self.rbl_in_offset = vector(x_off, y_off) self.row_end_inst.append(self.pre_p_en_inst)
self.rbl_in_inst.place(offset=self.rbl_in_offset,
mirror=mirror)
self.row_end_inst.append(self.rbl_in_inst)
def create_sen_row(self): def create_sen_row(self):
""" Create the sense enable buffer. """ """ Create the sense enable buffer. """
# input: pre_s_en, output: pre_s_en_bar # BUFFER FOR S_EN
self.pre_s_en_bar_inst=self.add_inst(name="inv_pre_s_en_bar", # input: pre_s_en, output: s_en
mod=self.inv2) self.s_en_inst=self.add_inst(name="buf_s_en",
self.connect_inst(["pre_s_en", "pre_s_en_bar", "vdd", "gnd"]) mod=self.pbuf8)
self.connect_inst(["pre_s_en", "s_en", "vdd", "gnd"])
# BUFFER INVERTERS FOR S_EN
# input: input: pre_s_en_bar, output: s_en
self.s_en_inst=self.add_inst(name="inv_s_en",
mod=self.inv8)
self.connect_inst(["pre_s_en_bar", "s_en", "vdd", "gnd"])
def place_sen_row(self,row): def place_sen_row(self,row):
""" """
@ -293,11 +304,6 @@ class control_logic(design.design):
x_off = self.ctrl_dff_array.width + self.internal_bus_width x_off = self.ctrl_dff_array.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row) (y_off,mirror)=self.get_offset(row)
self.pre_s_en_bar_offset = vector(x_off, y_off)
self.pre_s_en_bar_inst.place(offset=self.pre_s_en_bar_offset,
mirror=mirror)
x_off += self.inv2.width
self.s_en_offset = vector(x_off, y_off) self.s_en_offset = vector(x_off, y_off)
self.s_en_inst.place(offset=self.s_en_offset, self.s_en_inst.place(offset=self.s_en_offset,
mirror=mirror) mirror=mirror)
@ -341,9 +347,9 @@ class control_logic(design.design):
def get_offset(self,row): def get_offset(self,row):
""" Compute the y-offset and mirroring """ """ Compute the y-offset and mirroring """
y_off = row*self.inv1.height y_off = row*self.nand2.height
if row % 2: if row % 2:
y_off += self.inv1.height y_off += self.nand2.height
mirror="MX" mirror="MX"
else: else:
mirror="R0" mirror="R0"
@ -351,60 +357,36 @@ class control_logic(design.design):
return (y_off,mirror) return (y_off,mirror)
def create_we_row(self): def create_we_row(self):
# input: WE, CS output: w_en_bar # input: we, gated_clk output: pre_w_en
if self.port_type == "rw": if self.port_type == "rw":
nand_mod = self.nand3 self.pre_w_en_inst = self.add_inst(name="and_pre_w_en",
temp = ["clk_buf_bar", "cs", "we", "w_en_bar", "vdd", "gnd"] mod=self.pand2)
self.connect_inst(["we", "gated_clk", "pre_w_en", "vdd", "gnd"])
input_name = "pre_w_en"
else: else:
nand_mod = self.nand2 # No we signal is needed for write-only ports
temp = ["clk_buf_bar", "cs", "w_en_bar", "vdd", "gnd"] input_name = "gated_clk"
self.w_en_bar_inst = self.add_inst(name="nand3_w_en_bar", # BUFFER FOR W_EN
mod=nand_mod) self.w_en_inst = self.add_inst(name="w_en_buf",
self.connect_inst(temp) mod=self.pbuf8)
self.connect_inst([input_name, "w_en", "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_en", "vdd", "gnd"])
def place_we_row(self,row): def place_we_row(self,row):
x_off = self.ctrl_dff_inst.width + self.internal_bus_width x_off = self.ctrl_dff_inst.width + self.internal_bus_width
(y_off,mirror)=self.get_offset(row) (y_off,mirror)=self.get_offset(row)
w_en_bar_offset = vector(x_off, y_off)
self.w_en_bar_inst.place(offset=w_en_bar_offset,
mirror=mirror)
if self.port_type == "rw": if self.port_type == "rw":
x_off += self.nand3.width pre_w_en_offset = vector(x_off, y_off)
else: self.pre_w_en_inst.place(offset=pre_w_en_offset,
mirror=mirror)
x_off += self.nand2.width x_off += self.nand2.width
pre_w_en_offset = vector(x_off, y_off) w_en_offset = vector(x_off, y_off)
self.pre_w_en_inst.place(offset=pre_w_en_offset,
mirror=mirror)
x_off += self.inv1.width
pre_w_en_bar_offset = vector(x_off, y_off)
self.pre_w_en_bar_inst.place(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.place(offset=w_en_offset, self.w_en_inst.place(offset=w_en_offset,
mirror=mirror) mirror=mirror)
x_off += self.inv8.width
self.row_end_inst.append(self.w_en_inst) self.row_end_inst.append(self.w_en_inst)

View File

@ -17,38 +17,40 @@ class pand2(design.design):
unique_id = 1 unique_id = 1
def __init__(self, driver_size=4, height=bitcell.height, name=""): def __init__(self, size=1, height=bitcell.height, name=""):
stage_effort = 4
# FIXME: Change the number of stages to support high drives.
self.size = size
self.height = height
if name=="": if name=="":
name = "pand2_{0}_{1}".format(driver_size, pand2.unique_id) name = "pand2_{0}_{1}".format(size, pand2.unique_id)
pand2.unique_id += 1 pand2.unique_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name)) debug.info(1, "Creating {}".format(self.name))
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def create_netlist(self):
self.add_pins()
self.create_modules()
self.create_insts()
def create_modules(self):
# Shield the cap, but have at least a stage effort of 4 # Shield the cap, but have at least a stage effort of 4
self.nand = pnand2(height=height) self.nand = pnand2(height=self.height)
self.add_mod(self.nand) self.add_mod(self.nand)
self.inv = pinv(size=driver_size, height=height) self.inv = pinv(size=self.size, height=self.height)
self.add_mod(self.inv) self.add_mod(self.inv)
self.width = self.nand.width + self.inv.width
self.height = self.inv.height
self.create_layout()
#self.offset_all_coordinates()
self.DRC_LVS()
def create_layout(self): def create_layout(self):
self.add_pins() self.width = self.nand.width + self.inv.width
self.add_insts() self.place_insts()
self.add_wires() self.add_wires()
self.add_layout_pins() self.add_layout_pins()
@ -59,20 +61,21 @@ class pand2(design.design):
self.add_pin("vdd") self.add_pin("vdd")
self.add_pin("gnd") self.add_pin("gnd")
def add_insts(self): def create_insts(self):
# Add NAND to the right
self.nand_inst=self.add_inst(name="pand2_nand", self.nand_inst=self.add_inst(name="pand2_nand",
mod=self.nand, mod=self.nand)
offset=vector(0,0))
self.connect_inst(["A", "B", "zb_int", "vdd", "gnd"]) self.connect_inst(["A", "B", "zb_int", "vdd", "gnd"])
self.inv_inst=self.add_inst(name="pand2_inv",
mod=self.inv)
self.connect_inst(["zb_int", "Z", "vdd", "gnd"])
def place_insts(self):
# Add NAND to the right
self.nand_inst.place(offset=vector(0,0))
# Add INV to the right # Add INV to the right
self.inv_inst=self.add_inst(name="pand2_inv", self.inv_inst.place(offset=vector(self.nand_inst.rx(),0))
mod=self.inv,
offset=vector(self.nand_inst.rx(),0))
self.connect_inst(["zb_int", "Z", "vdd", "gnd"])
def add_wires(self): def add_wires(self):
# nand Z to inv A # nand Z to inv A

View File

@ -16,39 +16,33 @@ class pbuf(design.design):
unique_id = 1 unique_id = 1
def __init__(self, driver_size=4, height=bitcell.height, name=""): def __init__(self, size=4, height=bitcell.height, name=""):
stage_effort = 4 self.stage_effort = 4
self.size = size
self.width = 0
self.height = height
# FIXME: Change the number of stages to support high drives. # FIXME: Change the number of stages to support high drives.
if name=="": if name=="":
name = "pbuf_{0}_{1}".format(driver_size, pbuf.unique_id) name = "pbuf_{0}_{1}".format(self.size, pbuf.unique_id)
pbuf.unique_id += 1 pbuf.unique_id += 1
design.design.__init__(self, name) design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name)) debug.info(1, "Creating {}".format(self.name))
self.create_netlist()
# Shield the cap, but have at least a stage effort of 4 if not OPTS.netlist_only:
input_size = max(1,int(driver_size/stage_effort)) self.create_layout()
self.inv1 = pinv(size=input_size, height=height) # 1
self.add_mod(self.inv1)
self.inv2 = pinv(size=driver_size, height=height) # 2
self.add_mod(self.inv2)
self.width = self.inv1.width + self.inv2.width def create_netlist(self):
self.height = self.inv1.height self.add_pins()
self.create_modules()
self.create_layout() self.create_insts()
#self.offset_all_coordinates()
self.DRC_LVS()
def create_layout(self): def create_layout(self):
self.add_pins() self.width = self.inv1.width + self.inv2.width
self.add_insts() self.place_insts()
self.add_wires() self.add_wires()
self.add_layout_pins() self.add_layout_pins()
@ -58,19 +52,31 @@ class pbuf(design.design):
self.add_pin("vdd") self.add_pin("vdd")
self.add_pin("gnd") self.add_pin("gnd")
def add_insts(self): def create_modules(self):
# Add INV1 to the right # Shield the cap, but have at least a stage effort of 4
input_size = max(1,int(self.size/self.stage_effort))
self.inv1 = pinv(size=input_size, height=self.height)
self.add_mod(self.inv1)
self.inv2 = pinv(size=self.size, height=self.height)
self.add_mod(self.inv2)
def create_insts(self):
self.inv1_inst=self.add_inst(name="buf_inv1", self.inv1_inst=self.add_inst(name="buf_inv1",
mod=self.inv1, mod=self.inv1)
offset=vector(0,0))
self.connect_inst(["A", "zb_int", "vdd", "gnd"]) self.connect_inst(["A", "zb_int", "vdd", "gnd"])
# Add INV2 to the right
self.inv2_inst=self.add_inst(name="buf_inv2", self.inv2_inst=self.add_inst(name="buf_inv2",
mod=self.inv2, mod=self.inv2)
offset=vector(self.inv1_inst.rx(),0))
self.connect_inst(["zb_int", "Z", "vdd", "gnd"]) self.connect_inst(["zb_int", "Z", "vdd", "gnd"])
def place_insts(self):
# Add INV1 to the right
self.inv1_inst.place(vector(0,0))
# Add INV2 to the right
self.inv2_inst.place(vector(self.inv1_inst.rx(),0))
def add_wires(self): def add_wires(self):

View File

@ -33,7 +33,6 @@ class pnand2(pgate.pgate):
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: if not OPTS.netlist_only:
self.create_layout() self.create_layout()
#self.DRC_LVS()
def create_netlist(self): def create_netlist(self):