Bitcell arrays: Allow mirroring on the y axis

this allows for bitcells that need to be mirrored on the y axis, like
thin cells. However, the portdata elements also need to be mirrored on
the y axis. Otherwise the router will fail horribly when connecting
bitlines.

Signed-off-by: Bastian Koppelmann <kbastian@mail.uni-paderborn.de>
This commit is contained in:
Bastian Koppelmann 2020-01-27 17:17:06 +01:00
parent df9f351a91
commit dd1afe0313
5 changed files with 84 additions and 21 deletions

View File

@ -13,13 +13,14 @@ class bitcell_base_array(design.design):
"""
Abstract base class for bitcell-arrays -- bitcell, dummy
"""
def __init__(self, cols, rows, name):
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()
@ -82,6 +83,23 @@ class bitcell_base_array(design.design):
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):
@ -92,16 +110,22 @@ class bitcell_base_array(design.design):
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)
if cell_properties.bitcell.mirror.x and (row + row_offset) % 2:
tempy = yoffset + self.cell.height
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:
tempy = yoffset
dir_key = ""
self.cell_inst[row,col].place(offset=[xoffset, tempy],
self.cell_inst[row,col].place(offset=[tempx, tempy],
mirror=dir_key)
yoffset += self.cell.height
xoffset += self.cell.width

View File

@ -20,8 +20,8 @@ class bitcell_array(bitcell_base_array):
and word line is connected by abutment.
Connects the word lines and bit lines.
"""
def __init__(self, cols, rows, name):
super().__init__(cols, rows, name)
def __init__(self, cols, rows, name, column_offset=0):
super().__init__(cols, rows, name, column_offset)
self.create_netlist()
if not OPTS.netlist_only:

View File

@ -16,8 +16,8 @@ class dummy_array(bitcell_base_array):
"""
Generate a dummy row/column for the replica array.
"""
def __init__(self, cols, rows, mirror=0, name=""):
super().__init__(cols, rows, name)
def __init__(self, cols, rows, column_offset=0, mirror=0, name=""):
super().__init__(cols, rows, name, column_offset)
self.mirror = mirror
self.create_netlist()

View File

@ -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)

View File

@ -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,
@ -96,14 +98,31 @@ class replica_column(design.design):
# 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 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)