mirror of https://github.com/VLSIDA/OpenRAM.git
Merge remote-tracking branch 'bkoppelmann/bit-sym' into dev
This commit is contained in:
commit
3147b99ce0
|
|
@ -0,0 +1,131 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2019 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import debug
|
||||
import design
|
||||
from tech import cell_properties
|
||||
|
||||
class bitcell_base_array(design.design):
|
||||
"""
|
||||
Abstract base class for bitcell-arrays -- bitcell, dummy
|
||||
"""
|
||||
def __init__(self, cols, rows, name, column_offset):
|
||||
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
|
||||
self.column_offset = column_offset
|
||||
|
||||
def add_pins(self):
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
self.add_pin(cell_column+"_{0}".format(col), "INOUT")
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
self.add_pin(cell_row+"_{0}".format(row), "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def get_bitcell_pins(self, col, row):
|
||||
""" Creates a list of connections in the bitcell,
|
||||
indexed by column and row, for instance use in bitcell_array """
|
||||
|
||||
bitcell_pins = []
|
||||
|
||||
pin_names = self.cell.get_all_bitline_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(col))
|
||||
pin_names = self.cell.get_all_wl_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(row))
|
||||
bitcell_pins.append("vdd")
|
||||
bitcell_pins.append("gnd")
|
||||
|
||||
return bitcell_pins
|
||||
|
||||
def add_layout_pins(self):
|
||||
""" Add the layout pins """
|
||||
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
|
||||
self.add_layout_pin(text=cell_column+"_{0}".format(col),
|
||||
layer=bl_pin.layer,
|
||||
offset=bl_pin.ll().scale(1,0),
|
||||
width=bl_pin.width(),
|
||||
height=self.height)
|
||||
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
|
||||
self.add_layout_pin(text=cell_row+"_{0}".format(row),
|
||||
layer=wl_pin.layer,
|
||||
offset=wl_pin.ll().scale(0,1),
|
||||
width=self.width,
|
||||
height=wl_pin.height())
|
||||
|
||||
# For every second row and column, add a via for gnd and vdd
|
||||
for row in range(self.row_size):
|
||||
for col in range(self.column_size):
|
||||
inst = self.cell_inst[row,col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
def _adjust_x_offset(self, xoffset, col, col_offset):
|
||||
tempx = xoffset
|
||||
dir_y = False
|
||||
# If we mirror the current cell on the y axis adjust the x position
|
||||
if cell_properties.bitcell.mirror.y and (col + col_offset) % 2:
|
||||
tempx = xoffset + self.cell.width
|
||||
dir_y = True
|
||||
return (tempx, dir_y)
|
||||
|
||||
def _adjust_y_offset(self, yoffset, row, row_offset):
|
||||
tempy = yoffset
|
||||
dir_x = False
|
||||
# If we mirror the current cell on the x axis adjust the y position
|
||||
if cell_properties.bitcell.mirror.x and (row + row_offset) % 2:
|
||||
tempy = yoffset + self.cell.height
|
||||
dir_x = True
|
||||
return (tempy, dir_x)
|
||||
|
||||
|
||||
def place_array(self, name_template, row_offset=0):
|
||||
# We increase it by a well enclosure so the precharges don't overlap our wells
|
||||
self.height = self.row_size*self.cell.height
|
||||
self.width = self.column_size*self.cell.width
|
||||
|
||||
xoffset = 0.0
|
||||
for col in range(self.column_size):
|
||||
yoffset = 0.0
|
||||
tempx, dir_y = self._adjust_x_offset(xoffset, col, self.column_offset)
|
||||
|
||||
for row in range(self.row_size):
|
||||
name = name_template.format(row, col)
|
||||
tempy, dir_x = self._adjust_y_offset(yoffset, row, row_offset)
|
||||
|
||||
if dir_x and dir_y:
|
||||
dir_key = "XY"
|
||||
elif dir_x:
|
||||
dir_key = "MX"
|
||||
elif dir_y:
|
||||
dir_key = "MY"
|
||||
else:
|
||||
dir_key = ""
|
||||
|
||||
self.cell_inst[row,col].place(offset=[tempx, tempy],
|
||||
mirror=dir_key)
|
||||
yoffset += self.cell.height
|
||||
xoffset += self.cell.width
|
||||
|
|
@ -7,25 +7,21 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
from base_array import bitcell_base_array
|
||||
from tech import drc, spice
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
import logical_effort
|
||||
|
||||
class bitcell_array(design.design):
|
||||
class bitcell_array(bitcell_base_array):
|
||||
"""
|
||||
Creates a rows x cols array of memory cells. Assumes bit-lines
|
||||
and word line is connected by abutment.
|
||||
Connects the word lines and bit lines.
|
||||
"""
|
||||
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
|
||||
def __init__(self, cols, rows, name, column_offset=0):
|
||||
super().__init__(cols, rows, name, column_offset)
|
||||
|
||||
self.create_netlist()
|
||||
if not OPTS.netlist_only:
|
||||
|
|
@ -44,27 +40,7 @@ class bitcell_array(design.design):
|
|||
|
||||
def create_layout(self):
|
||||
|
||||
# We increase it by a well enclosure so the precharges don't overlap our wells
|
||||
self.height = self.row_size*self.cell.height
|
||||
self.width = self.column_size*self.cell.width
|
||||
|
||||
xoffset = 0.0
|
||||
for col in range(self.column_size):
|
||||
yoffset = 0.0
|
||||
for row in range(self.row_size):
|
||||
name = "bit_r{0}_c{1}".format(row, col)
|
||||
|
||||
if row % 2:
|
||||
tempy = yoffset + self.cell.height
|
||||
dir_key = "MX"
|
||||
else:
|
||||
tempy = yoffset
|
||||
dir_key = ""
|
||||
|
||||
self.cell_inst[row,col].place(offset=[xoffset, tempy],
|
||||
mirror=dir_key)
|
||||
yoffset += self.cell.height
|
||||
xoffset += self.cell.width
|
||||
self.place_array("bit_r{0}_c{1}")
|
||||
|
||||
self.add_layout_pins()
|
||||
|
||||
|
|
@ -72,41 +48,13 @@ class bitcell_array(design.design):
|
|||
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
self.add_pin(cell_column+"_{0}".format(col), "INOUT")
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
self.add_pin(cell_row+"_{0}".format(row), "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
self.cell = factory.create(module_type="bitcell")
|
||||
self.add_mod(self.cell)
|
||||
|
||||
def get_bitcell_pins(self, col, row):
|
||||
""" Creates a list of connections in the bitcell,
|
||||
indexed by column and row, for instance use in bitcell_array """
|
||||
|
||||
bitcell_pins = []
|
||||
|
||||
pin_names = self.cell.get_all_bitline_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(col))
|
||||
pin_names = self.cell.get_all_wl_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(row))
|
||||
bitcell_pins.append("vdd")
|
||||
bitcell_pins.append("gnd")
|
||||
|
||||
return bitcell_pins
|
||||
|
||||
|
||||
def create_instances(self):
|
||||
""" Create the module instances used in this design """
|
||||
self.cell_inst = {}
|
||||
|
|
@ -117,37 +65,6 @@ class bitcell_array(design.design):
|
|||
mod=self.cell)
|
||||
self.connect_inst(self.get_bitcell_pins(col, row))
|
||||
|
||||
def add_layout_pins(self):
|
||||
""" Add the layout pins """
|
||||
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
|
||||
self.add_layout_pin(text=cell_column+"_{0}".format(col),
|
||||
layer=bl_pin.layer,
|
||||
offset=bl_pin.ll().scale(1,0),
|
||||
width=bl_pin.width(),
|
||||
height=self.height)
|
||||
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
|
||||
self.add_layout_pin(text=cell_row+"_{0}".format(row),
|
||||
layer=wl_pin.layer,
|
||||
offset=wl_pin.ll().scale(0,1),
|
||||
width=self.width,
|
||||
height=wl_pin.height())
|
||||
|
||||
# For every second row and column, add a via for gnd and vdd
|
||||
for row in range(self.row_size):
|
||||
for col in range(self.column_size):
|
||||
inst = self.cell_inst[row,col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
def analytical_power(self, corner, load):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2020 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
|
||||
class _MirrorAxis:
|
||||
def __init__(self, x, y):
|
||||
self.x = x
|
||||
self.y = y
|
||||
|
||||
class _Bitcell:
|
||||
def __init__(self, mirror):
|
||||
self.mirror = mirror
|
||||
|
||||
class CellProperties():
|
||||
"""
|
||||
TODO
|
||||
"""
|
||||
def __init__(self):
|
||||
self.names = {}
|
||||
self._bitcell = _Bitcell(_MirrorAxis(True, False))
|
||||
|
||||
@property
|
||||
def bitcell(self):
|
||||
return self._bitcell
|
||||
|
|
@ -5,23 +5,19 @@
|
|||
#
|
||||
import debug
|
||||
import design
|
||||
from base_array import bitcell_base_array
|
||||
from tech import drc
|
||||
import contact
|
||||
from sram_factory import factory
|
||||
from vector import vector
|
||||
from globals import OPTS
|
||||
|
||||
class dummy_array(design.design):
|
||||
class dummy_array(bitcell_base_array):
|
||||
"""
|
||||
Generate a dummy row/column for the replica array.
|
||||
"""
|
||||
def __init__(self, cols, rows, mirror=0, 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
|
||||
def __init__(self, cols, rows, column_offset=0, mirror=0, name=""):
|
||||
super().__init__(cols, rows, name, column_offset)
|
||||
self.mirror = mirror
|
||||
|
||||
self.create_netlist()
|
||||
|
|
@ -37,27 +33,7 @@ class dummy_array(design.design):
|
|||
|
||||
def create_layout(self):
|
||||
|
||||
# We increase it by a well enclosure so the precharges don't overlap our wells
|
||||
self.height = self.row_size*self.dummy_cell.height
|
||||
self.width = self.column_size*self.dummy_cell.width
|
||||
|
||||
xoffset = 0.0
|
||||
for col in range(self.column_size):
|
||||
yoffset = 0.0
|
||||
for row in range(self.row_size):
|
||||
name = "dummy_r{0}_c{1}".format(row, col)
|
||||
|
||||
if (row+self.mirror) % 2:
|
||||
tempy = yoffset + self.dummy_cell.height
|
||||
dir_key = "MX"
|
||||
else:
|
||||
tempy = yoffset
|
||||
dir_key = ""
|
||||
|
||||
self.cell_inst[row,col].place(offset=[xoffset, tempy],
|
||||
mirror=dir_key)
|
||||
yoffset += self.dummy_cell.height
|
||||
xoffset += self.dummy_cell.width
|
||||
self.place_array("dummy_r{0}_c{1}", self.mirror)
|
||||
|
||||
self.add_layout_pins()
|
||||
|
||||
|
|
@ -65,18 +41,6 @@ class dummy_array(design.design):
|
|||
|
||||
self.DRC_LVS()
|
||||
|
||||
def add_pins(self):
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
self.add_pin(cell_column+"_{0}".format(col), "INOUT")
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
self.add_pin(cell_row+"_{0}".format(row), "INPUT")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_modules(self):
|
||||
""" Add the modules used in this design """
|
||||
self.dummy_cell = factory.create(module_type="dummy_bitcell")
|
||||
|
|
@ -84,23 +48,6 @@ class dummy_array(design.design):
|
|||
|
||||
self.cell = factory.create(module_type="bitcell")
|
||||
|
||||
def get_bitcell_pins(self, col, row):
|
||||
""" Creates a list of connections in the bitcell,
|
||||
indexed by column and row, for instance use in bitcell_array """
|
||||
|
||||
bitcell_pins = []
|
||||
|
||||
pin_names = self.cell.get_all_bitline_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(col))
|
||||
pin_names = self.cell.get_all_wl_names()
|
||||
for pin in pin_names:
|
||||
bitcell_pins.append(pin+"_{0}".format(row))
|
||||
bitcell_pins.append("vdd")
|
||||
bitcell_pins.append("gnd")
|
||||
|
||||
return bitcell_pins
|
||||
|
||||
|
||||
def create_instances(self):
|
||||
""" Create the module instances used in this design """
|
||||
|
|
@ -111,39 +58,6 @@ class dummy_array(design.design):
|
|||
self.cell_inst[row,col]=self.add_inst(name=name,
|
||||
mod=self.dummy_cell)
|
||||
self.connect_inst(self.get_bitcell_pins(col, row))
|
||||
|
||||
def add_layout_pins(self):
|
||||
""" Add the layout pins """
|
||||
|
||||
row_list = self.cell.get_all_wl_names()
|
||||
column_list = self.cell.get_all_bitline_names()
|
||||
|
||||
for col in range(self.column_size):
|
||||
for cell_column in column_list:
|
||||
bl_pin = self.cell_inst[0,col].get_pin(cell_column)
|
||||
self.add_layout_pin(text=cell_column+"_{0}".format(col),
|
||||
layer="m2",
|
||||
offset=bl_pin.ll(),
|
||||
width=bl_pin.width(),
|
||||
height=self.height)
|
||||
|
||||
for row in range(self.row_size):
|
||||
for cell_row in row_list:
|
||||
wl_pin = self.cell_inst[row,0].get_pin(cell_row)
|
||||
self.add_layout_pin(text=cell_row+"_{0}".format(row),
|
||||
layer="m1",
|
||||
offset=wl_pin.ll(),
|
||||
width=self.width,
|
||||
height=wl_pin.height())
|
||||
|
||||
# For every second row and column, add a via for gnd and vdd
|
||||
for row in range(self.row_size):
|
||||
for col in range(self.column_size):
|
||||
inst = self.cell_inst[row,col]
|
||||
for pin_name in ["vdd", "gnd"]:
|
||||
for pin in inst.get_pins(pin_name):
|
||||
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer)
|
||||
|
||||
|
||||
def input_load(self):
|
||||
wl_wire = self.gen_wl_wire()
|
||||
|
|
|
|||
|
|
@ -107,9 +107,19 @@ class precharge_array(design.design):
|
|||
|
||||
def place_insts(self):
|
||||
""" Places precharge array by horizontally tiling the precharge cell"""
|
||||
from tech import cell_properties
|
||||
xoffset = 0
|
||||
for i in range(self.columns):
|
||||
offset = vector(self.pc_cell.width * i, 0)
|
||||
self.local_insts[i].place(offset)
|
||||
tempx = xoffset
|
||||
if cell_properties.bitcell.mirror.y and (i + 1) % 2:
|
||||
mirror = "MY"
|
||||
tempx = tempx + self.pc_cell.width
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
offset = vector(tempx, 0)
|
||||
self.local_insts[i].place(offset=offset, mirror=mirror)
|
||||
xoffset = xoffset + self.pc_cell.width
|
||||
|
||||
def get_en_cin(self):
|
||||
"""Get the relative capacitance of all the clk connections in the precharge array"""
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@ class replica_bitcell_array(design.design):
|
|||
|
||||
# Bitcell array
|
||||
self.bitcell_array = factory.create(module_type="bitcell_array",
|
||||
column_offset=1 + self.left_rbl,
|
||||
cols=self.column_size,
|
||||
rows=self.row_size)
|
||||
self.add_mod(self.bitcell_array)
|
||||
|
|
@ -95,12 +96,17 @@ class replica_bitcell_array(design.design):
|
|||
for bit in range(self.left_rbl+self.right_rbl):
|
||||
if bit<self.left_rbl:
|
||||
replica_bit = bit+1
|
||||
# dummy column
|
||||
column_offset = 1
|
||||
else:
|
||||
replica_bit = bit+self.row_size+1
|
||||
# dummy column + replica column + bitcell colums
|
||||
column_offset = 3 + self.row_size
|
||||
self.replica_columns[bit] = factory.create(module_type="replica_column",
|
||||
rows=self.row_size,
|
||||
left_rbl=self.left_rbl,
|
||||
right_rbl=self.right_rbl,
|
||||
column_offset=column_offset,
|
||||
replica_bit=replica_bit)
|
||||
self.add_mod(self.replica_columns[bit])
|
||||
|
||||
|
|
@ -108,16 +114,30 @@ class replica_bitcell_array(design.design):
|
|||
self.dummy_row = factory.create(module_type="dummy_array",
|
||||
cols=self.column_size,
|
||||
rows=1,
|
||||
# dummy column + left replica column
|
||||
column_offset=1 + self.left_rbl,
|
||||
mirror=0)
|
||||
self.add_mod(self.dummy_row)
|
||||
|
||||
# Dummy col (mirror starting at first if odd replica+dummy rows)
|
||||
self.dummy_col = factory.create(module_type="dummy_array",
|
||||
cols=1,
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.left_rbl+1)%2)
|
||||
self.add_mod(self.dummy_col)
|
||||
|
||||
self.dummy_col_left = factory.create(module_type="dummy_array",
|
||||
cols=1,
|
||||
column_offset=0,
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.left_rbl+1)%2)
|
||||
self.add_mod(self.dummy_col_left)
|
||||
|
||||
self.dummy_col_right = factory.create(module_type="dummy_array",
|
||||
cols=1,
|
||||
# dummy column
|
||||
# + left replica column
|
||||
# + bitcell columns
|
||||
# + right replica column
|
||||
column_offset=1 + self.left_rbl + self.column_size + self.right_rbl,
|
||||
rows=self.row_size + self.extra_rows,
|
||||
mirror=(self.left_rbl+1)%2)
|
||||
self.add_mod(self.dummy_col_right)
|
||||
|
||||
|
||||
|
||||
def add_pins(self):
|
||||
|
|
@ -236,10 +256,10 @@ class replica_bitcell_array(design.design):
|
|||
|
||||
# Left/right Dummy columns
|
||||
self.dummy_col_left_inst=self.add_inst(name="dummy_col_left",
|
||||
mod=self.dummy_col)
|
||||
mod=self.dummy_col_left)
|
||||
self.connect_inst([x+"_left" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies)
|
||||
self.dummy_col_right_inst=self.add_inst(name="dummy_col_right",
|
||||
mod=self.dummy_col)
|
||||
mod=self.dummy_col_right)
|
||||
self.connect_inst([x+"_right" for x in self.dummy_cell_bl_names] + self.dummy_col_wl_names + supplies)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,8 @@ class replica_column(design.design):
|
|||
replica cell.
|
||||
"""
|
||||
|
||||
def __init__(self, name, rows, left_rbl, right_rbl, replica_bit):
|
||||
def __init__(self, name, rows, left_rbl, right_rbl, replica_bit,
|
||||
column_offset=0):
|
||||
design.design.__init__(self, name)
|
||||
|
||||
self.rows = rows
|
||||
|
|
@ -29,6 +30,7 @@ class replica_column(design.design):
|
|||
self.replica_bit = replica_bit
|
||||
# left, right, regular rows plus top/bottom dummy cells
|
||||
self.total_size = self.left_rbl+rows+self.right_rbl+2
|
||||
self.column_offset = column_offset
|
||||
|
||||
debug.check(replica_bit!=0 and replica_bit!=rows,"Replica bit cannot be the dummy row.")
|
||||
debug.check(replica_bit<=left_rbl or replica_bit>=self.total_size-right_rbl-1,
|
||||
|
|
@ -92,18 +94,35 @@ class replica_column(design.design):
|
|||
self.connect_inst(self.get_bitcell_pins(0, row))
|
||||
|
||||
def place_instances(self):
|
||||
|
||||
from tech import cell_properties
|
||||
# Flip the mirrors if we have an odd number of replica+dummy rows at the bottom
|
||||
# so that we will start with mirroring rather than not mirroring
|
||||
rbl_offset = (self.left_rbl+1)%2
|
||||
|
||||
|
||||
# if our bitcells are mirrored on the y axis, check if we are in global
|
||||
# column that needs to be flipped.
|
||||
dir_y = False
|
||||
xoffset = 0
|
||||
if cell_properties.bitcell.mirror.y and self.column_offset % 2:
|
||||
dir_y = True
|
||||
xoffset = self.replica_cell.width
|
||||
|
||||
for row in range(self.total_size):
|
||||
dir_x = False
|
||||
name = "bit_r{0}_{1}".format(row,"rbl")
|
||||
offset = vector(0,self.cell.height*(row+(row+rbl_offset)%2))
|
||||
if (row+rbl_offset)%2:
|
||||
if cell_properties.bitcell.mirror.x and (row+rbl_offset)%2:
|
||||
dir_x = True
|
||||
|
||||
offset = vector(xoffset,self.cell.height*(row+(row+rbl_offset)%2))
|
||||
|
||||
if dir_x and dir_y:
|
||||
dir_key = "XY"
|
||||
elif dir_x:
|
||||
dir_key = "MX"
|
||||
elif dir_y:
|
||||
dir_key = "MY"
|
||||
else:
|
||||
dir_key = "R0"
|
||||
dir_key = ""
|
||||
|
||||
self.cell_inst[row].place(offset=offset,
|
||||
mirror=dir_key)
|
||||
|
|
|
|||
|
|
@ -84,14 +84,27 @@ class sense_amp_array(design.design):
|
|||
"en", "vdd", "gnd"])
|
||||
|
||||
def place_sense_amp_array(self):
|
||||
|
||||
from tech import cell_properties
|
||||
if self.bitcell.width > self.amp.width:
|
||||
amp_spacing = self.bitcell.width * self.words_per_row
|
||||
else:
|
||||
amp_spacing = self.amp.width * self.words_per_row
|
||||
|
||||
for i in range(0,self.word_size):
|
||||
amp_position = vector(amp_spacing * i, 0)
|
||||
self.local_insts[i].place(amp_position)
|
||||
xoffset = amp_spacing * i
|
||||
|
||||
# align the xoffset to the grid of bitcells. This way we
|
||||
# know when to do the mirroring.
|
||||
grid_x = int(xoffset / self.amp.width)
|
||||
|
||||
if cell_properties.bitcell.mirror.y and grid_x % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.amp.width
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
amp_position = vector(xoffset, 0)
|
||||
self.local_insts[i].place(offset=amp_position,mirror=mirror)
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
|
|
|||
|
|
@ -99,11 +99,19 @@ class single_level_column_mux_array(design.design):
|
|||
"gnd"])
|
||||
|
||||
def place_array(self):
|
||||
from tech import cell_properties
|
||||
# For every column, add a pass gate
|
||||
for col_num in range(self.columns):
|
||||
xoffset = col_num * self.mux.width
|
||||
if cell_properties.bitcell.mirror.y and col_num % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.mux.width
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
name = "XMUX{0}".format(col_num)
|
||||
x_off = vector(col_num * self.mux.width, self.route_height)
|
||||
self.mux_inst[col_num].place(x_off)
|
||||
offset = vector(xoffset, self.route_height)
|
||||
self.mux_inst[col_num].place(offset=offset, mirror=mirror)
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
|
@ -161,6 +169,7 @@ class single_level_column_mux_array(design.design):
|
|||
|
||||
def route_bitlines(self):
|
||||
""" Connect the output bit-lines to form the appropriate width mux """
|
||||
from tech import cell_properties
|
||||
for j in range(self.columns):
|
||||
bl_offset = self.mux_inst[j].get_pin("bl_out").bc()
|
||||
br_offset = self.mux_inst[j].get_pin("br_out").bc()
|
||||
|
|
@ -171,23 +180,38 @@ class single_level_column_mux_array(design.design):
|
|||
bl_out_offset_end = bl_out_offset + vector(0,self.route_height)
|
||||
br_out_offset_end = br_out_offset + vector(0,self.route_height)
|
||||
|
||||
if cell_properties.bitcell.mirror.y and j % 2:
|
||||
tmp_bl_out_end = br_out_offset_end
|
||||
tmp_br_out_end = bl_out_offset_end
|
||||
else:
|
||||
tmp_bl_out_end = bl_out_offset_end
|
||||
tmp_br_out_end = br_out_offset_end
|
||||
|
||||
if (j % self.words_per_row) == 0:
|
||||
# Create the metal1 to connect the n-way mux output from the pass gate
|
||||
# These will be located below the select lines. Yes, these are M2 width
|
||||
# to ensure vias are enclosed and M1 min width rules.
|
||||
width = self.m2_width + self.mux.width * (self.words_per_row - 1)
|
||||
self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width,0)])
|
||||
self.add_path("m1", [br_out_offset, br_out_offset+vector(width,0)])
|
||||
|
||||
if cell_properties.bitcell.mirror.y and (j % 2) == 0:
|
||||
bl = self.mux.get_pin("bl")
|
||||
br = self.mux.get_pin("br")
|
||||
dist = abs(bl.ll().x - br.ll().x)
|
||||
else:
|
||||
dist = 0
|
||||
|
||||
self.add_path("m1", [bl_out_offset, bl_out_offset+vector(width+dist,0)])
|
||||
self.add_path("m1", [br_out_offset, br_out_offset+vector(width-dist,0)])
|
||||
|
||||
# Extend the bitline output rails and gnd downward on the first bit of each n-way mux
|
||||
self.add_layout_pin_segment_center(text="bl_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="m2",
|
||||
start=bl_out_offset,
|
||||
end=bl_out_offset_end)
|
||||
end=tmp_bl_out_end)
|
||||
self.add_layout_pin_segment_center(text="br_out_{}".format(int(j/self.words_per_row)),
|
||||
layer="m2",
|
||||
start=br_out_offset,
|
||||
end=br_out_offset_end)
|
||||
end=tmp_br_out_end)
|
||||
|
||||
|
||||
# This via is on the right of the wire
|
||||
|
|
@ -200,8 +224,8 @@ class single_level_column_mux_array(design.design):
|
|||
|
||||
else:
|
||||
|
||||
self.add_path("m2", [ bl_out_offset, bl_out_offset_end])
|
||||
self.add_path("m2", [ br_out_offset, br_out_offset_end])
|
||||
self.add_path("m2", [ bl_out_offset, tmp_bl_out_end])
|
||||
self.add_path("m2", [ br_out_offset, tmp_br_out_end])
|
||||
|
||||
# This via is on the right of the wire
|
||||
self.add_via_center(layers=self.m1_stack,
|
||||
|
|
|
|||
|
|
@ -106,14 +106,23 @@ class write_driver_array(design.design):
|
|||
|
||||
|
||||
def place_write_array(self):
|
||||
from tech import cell_properties
|
||||
if self.bitcell.width > self.driver.width:
|
||||
self.driver_spacing = self.bitcell.width
|
||||
else:
|
||||
self.driver_spacing = self.driver.width
|
||||
for i in range(0,self.columns,self.words_per_row):
|
||||
index = int(i/self.words_per_row)
|
||||
base = vector(i * self.driver_spacing, 0)
|
||||
self.driver_insts[index].place(base)
|
||||
xoffset = i * self.driver_spacing
|
||||
|
||||
if cell_properties.bitcell.mirror.y and i % 2:
|
||||
mirror = "MY"
|
||||
xoffset = xoffset + self.driver.width
|
||||
else:
|
||||
mirror = ""
|
||||
|
||||
base = vector(xoffset, 0)
|
||||
self.driver_insts[index].place(offset=base, mirror=mirror)
|
||||
|
||||
|
||||
def add_layout_pins(self):
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import os
|
||||
from design_rules import *
|
||||
from module_type import *
|
||||
from custom_cell_properties import CellProperties
|
||||
|
||||
"""
|
||||
File containing the process technology parameters for FreePDK 45nm.
|
||||
|
|
@ -24,6 +25,12 @@ File containing the process technology parameters for FreePDK 45nm.
|
|||
# For example: tech_modules['contact'] = 'contact_freepdk45'
|
||||
tech_modules = ModuleType()
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = CellProperties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
###################################################
|
||||
# GDS file info
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import os
|
||||
from design_rules import *
|
||||
from module_type import *
|
||||
from custom_cell_properties import CellProperties
|
||||
|
||||
"""
|
||||
File containing the process technology parameters for SCMOS 3me, subm, 180nm.
|
||||
|
|
@ -12,6 +13,13 @@ File containing the process technology parameters for SCMOS 3me, subm, 180nm.
|
|||
# For example: tech_modules['contact'] = 'contact_scn3me'
|
||||
tech_modules = ModuleType()
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = CellProperties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
#GDS file info
|
||||
GDS={}
|
||||
# gds units
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
import os
|
||||
from design_rules import *
|
||||
from module_type import *
|
||||
from custom_cell_properties import CellProperties
|
||||
|
||||
"""
|
||||
File containing the process technology parameters for SCMOS 4m, 0.35um
|
||||
|
|
@ -24,6 +25,12 @@ File containing the process technology parameters for SCMOS 4m, 0.35um
|
|||
# For example: tech_modules['contact'] = 'contact_scn4m'
|
||||
tech_modules = ModuleType()
|
||||
|
||||
###################################################
|
||||
# Custom cell properties
|
||||
###################################################
|
||||
cell_properties = CellProperties()
|
||||
cell_properties.bitcell.mirror.x = True
|
||||
cell_properties.bitcell.mirror.y = False
|
||||
|
||||
###################################################
|
||||
# GDS file info
|
||||
|
|
|
|||
Loading…
Reference in New Issue