Replacing replica_pbitcell module with a more effiecient verision. replica_pbitcell is now a wrapper for pbitcell in replica_bitcell mode.

This commit is contained in:
Michael Timothy Grimes 2018-09-13 16:53:24 -07:00
parent e0b9989d85
commit 5fd484ee5a
4 changed files with 119 additions and 1191 deletions

View File

@ -0,0 +1,82 @@
import debug
import design
from tech import drc, spice
from vector import vector
from globals import OPTS
from pbitcell import pbitcell
class replica_pbitcell(design.design):
"""
Creates a replica bitcell using pbitcell
"""
def __init__(self):
self.num_rw_ports = OPTS.num_rw_ports
self.num_w_ports = OPTS.num_w_ports
self.num_r_ports = OPTS.num_r_ports
self.total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports
design.design.__init__(self, "replica_pbitcell")
debug.info(1, "create a replica bitcell using pbitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports,
self.num_w_ports,
self.num_r_ports))
self.create_netlist()
self.create_layout()
def create_netlist(self):
self.add_pins()
self.add_modules()
self.create_modules()
def create_layout(self):
self.place_pbitcell()
self.route_rbc_connections()
self.DRC_LVS()
def add_pins(self):
for port in range(self.total_ports):
self.add_pin("bl{}".format(port))
self.add_pin("br{}".format(port))
for port in range(self.total_ports):
self.add_pin("wl{}".format(port))
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
self.prbc = pbitcell(replica_bitcell=True)
self.add_mod(self.prbc)
self.height = self.prbc.height
self.width = self.prbc.width
def create_modules(self):
self.prbc_inst = self.add_inst(name="pbitcell",
mod=self.prbc)
temp = []
for port in range(self.total_ports):
temp.append("bl{}".format(port))
temp.append("br{}".format(port))
for port in range(self.total_ports):
temp.append("wl{}".format(port))
temp.append("vdd")
temp.append("gnd")
self.connect_inst(temp)
def place_pbitcell(self):
offset = [0,0]
self.prbc_inst.place(offset=offset)
def route_rbc_connections(self):
for port in range(self.total_ports):
self.copy_layout_pin(self.prbc_inst, "bl{}".format(port))
self.copy_layout_pin(self.prbc_inst, "br{}".format(port))
for port in range(self.total_ports):
self.copy_layout_pin(self.prbc_inst, "wl{}".format(port))
self.copy_layout_pin(self.prbc_inst, "vdd")
self.copy_layout_pin(self.prbc_inst, "gnd")

View File

@ -12,14 +12,19 @@ class pbitcell(design.design):
with a variable number of read/write, write, and read ports
"""
def __init__(self):
def __init__(self, replica_bitcell=False):
self.num_rw_ports = OPTS.num_rw_ports
self.num_w_ports = OPTS.num_w_ports
self.num_r_ports = OPTS.num_r_ports
self.total_ports = self.num_rw_ports + self.num_w_ports + self.num_r_ports
name = "pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
self.replica_bitcell = replica_bitcell
if self.replica_bitcell:
name = "replica_pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
else:
name = "pbitcell_{0}RW_{1}W_{2}R".format(self.num_rw_ports, self.num_w_ports, self.num_r_ports)
# This is not a pgate because pgates depend on the bitcell height!
design.design.__init__(self, name)
debug.info(2, "create a multi-port bitcell with {0} rw ports, {1} w ports and {2} r ports".format(self.num_rw_ports,
@ -70,6 +75,9 @@ class pbitcell(design.design):
self.route_read_access()
self.extend_well()
if self.replica_bitcell:
self.route_rbc_short()
# in netlist_only mode, calling offset_all_coordinates will not be possible
# this function is not needed to calculate the dimensions of pbitcell in netlist_only mode though
if not OPTS.netlist_only:
@ -124,6 +132,11 @@ class pbitcell(design.design):
self.add_pin("vdd")
self.add_pin("gnd")
if self.replica_bitcell:
self.Q_bar = "vdd"
else:
self.Q_bar = "Q_bar"
def add_modules(self):
"""
@ -232,6 +245,10 @@ class pbitcell(design.design):
# calculation for row line tiling
self.rail_tile_height = drc["active_to_body_active"] + contact.well.width
if self.inverter_pmos_contact_extension > 0:
self.vdd_tile_height = self.inverter_pmos_contact_extension + drc["minwidth_metal1"] + contact.well.width
else:
self.vdd_tile_height = self.rail_tile_height
self.rowline_tile_height = drc["minwidth_metal1"] + contact.m1m2.width
# calculations related to inverter connections
@ -295,7 +312,7 @@ class pbitcell(design.design):
# topmost position = height of the inverter + height of vdd
self.topmost_ypos = self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height \
+ self.rail_tile_height
+ self.vdd_tile_height
# calculations for the cell dimensions
array_vdd_overlap = 0.5*contact.well.width
@ -312,20 +329,20 @@ class pbitcell(design.design):
# create active for nmos
self.inverter_nmos_left = self.add_inst(name="inverter_nmos_left",
mod=self.inverter_nmos)
self.connect_inst(["Q_bar", "Q", "gnd", "gnd"])
self.connect_inst([self.Q_bar, "Q", "gnd", "gnd"])
self.inverter_nmos_right = self.add_inst(name="inverter_nmos_right",
mod=self.inverter_nmos)
self.connect_inst(["gnd", "Q_bar", "Q", "gnd"])
self.connect_inst(["gnd", self.Q_bar, "Q", "gnd"])
# create active for pmos
self.inverter_pmos_left = self.add_inst(name="inverter_pmos_left",
mod=self.inverter_pmos)
self.connect_inst(["Q_bar", "Q", "vdd", "vdd"])
self.connect_inst([self.Q_bar, "Q", "vdd", "vdd"])
self.inverter_pmos_right = self.add_inst(name="inverter_pmos_right",
mod=self.inverter_pmos)
self.connect_inst(["vdd", "Q_bar", "Q", "vdd"])
self.connect_inst(["vdd", self.Q_bar, "Q", "vdd"])
def place_storage(self):
@ -395,7 +412,7 @@ class pbitcell(design.design):
height=contact.well.second_layer_width)
vdd_ypos = self.inverter_nmos.active_height + self.inverter_gap + self.inverter_pmos.active_height \
+ drc["active_to_body_active"]
+ self.vdd_tile_height - contact.well.second_layer_width
self.vdd_position = vector(self.leftmost_xpos, vdd_ypos)
self.vdd = self.add_layout_pin(text="vdd",
layer="metal1",
@ -442,7 +459,7 @@ class pbitcell(design.design):
self.readwrite_nmos_right[k] = self.add_inst(name="readwrite_nmos_right{}".format(k),
mod=self.readwrite_nmos)
self.connect_inst(["Q_bar", self.rw_wl_names[k], self.rw_br_names[k], "gnd"])
self.connect_inst([self.Q_bar, self.rw_wl_names[k], self.rw_br_names[k], "gnd"])
def place_readwrite_ports(self):
@ -646,7 +663,7 @@ class pbitcell(design.design):
self.write_nmos_right[k] = self.add_inst(name="write_nmos_right{}".format(k),
mod=self.write_nmos)
self.connect_inst(["Q_bar", self.w_wl_names[k], self.w_br_names[k], "gnd"])
self.connect_inst([self.Q_bar, self.w_wl_names[k], self.w_br_names[k], "gnd"])
def place_write_ports(self):
@ -849,7 +866,7 @@ class pbitcell(design.design):
# add read-access transistors
self.read_access_nmos_left[k] = self.add_inst(name="read_access_nmos_left{}".format(k),
mod=self.read_nmos)
self.connect_inst(["RA_to_R_left{}".format(k), "Q_bar", "gnd", "gnd"])
self.connect_inst(["RA_to_R_left{}".format(k), self.Q_bar, "gnd", "gnd"])
self.read_access_nmos_right[k] = self.add_inst(name="read_access_nmos_right{}".format(k),
mod=self.read_nmos)
@ -1218,4 +1235,11 @@ class pbitcell(design.design):
def list_write_br_names(self):
""" Creates a list of br pin names asscociated with write ports"""
br_pins = self.rw_br_names + self.w_br_names
return br_pins
return br_pins
def route_rbc_short(self):
""" route the short from Q_bar to gnd necessary for the replica bitcell """
Q_bar_pos = self.inverter_pmos_left.get_pin("D").uc()
vdd_pos = vector(Q_bar_pos.x, self.vdd_position.y)
self.add_path("metal1", [Q_bar_pos, vdd_pos])

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,6 @@ class replica_pbitcell_test(openram_test):
import replica_pbitcell
import tech
# check precharge in multi-port
OPTS.bitcell = "pbitcell"
OPTS.num_rw_ports = 1
OPTS.num_r_ports = 0