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 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) design.design.__init__(self, name)
debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols)) debug.info(1, "Creating {0} {1} x {2}".format(self.name, rows, cols))
self.add_comment("rows: {0} cols: {1}".format(rows, cols)) self.add_comment("rows: {0} cols: {1}".format(rows, cols))
self.column_size = cols self.column_size = cols
self.row_size = rows self.row_size = rows
self.column_offset = column_offset
def add_pins(self): def add_pins(self):
row_list = self.cell.get_all_wl_names() 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): for pin in inst.get_pins(pin_name):
self.add_power_pin(name=pin_name, loc=pin.center(), vertical=True, start_layer=pin.layer) 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): def place_array(self, name_template, row_offset=0):
@ -92,16 +110,22 @@ class bitcell_base_array(design.design):
xoffset = 0.0 xoffset = 0.0
for col in range(self.column_size): for col in range(self.column_size):
yoffset = 0.0 yoffset = 0.0
tempx, dir_y = self._adjust_x_offset(xoffset, col, self.column_offset)
for row in range(self.row_size): for row in range(self.row_size):
name = name_template.format(row, col) name = name_template.format(row, col)
if cell_properties.bitcell.mirror.x and (row + row_offset) % 2: tempy, dir_x = self._adjust_y_offset(yoffset, row, row_offset)
tempy = yoffset + self.cell.height
if dir_x and dir_y:
dir_key = "XY"
elif dir_x:
dir_key = "MX" dir_key = "MX"
elif dir_y:
dir_key = "MY"
else: else:
tempy = yoffset
dir_key = "" dir_key = ""
self.cell_inst[row,col].place(offset=[xoffset, tempy], self.cell_inst[row,col].place(offset=[tempx, tempy],
mirror=dir_key) mirror=dir_key)
yoffset += self.cell.height yoffset += self.cell.height
xoffset += self.cell.width xoffset += self.cell.width

View File

@ -20,8 +20,8 @@ class bitcell_array(bitcell_base_array):
and word line is connected by abutment. and word line is connected by abutment.
Connects the word lines and bit lines. Connects the word lines and bit lines.
""" """
def __init__(self, cols, rows, name): def __init__(self, cols, rows, name, column_offset=0):
super().__init__(cols, rows, name) super().__init__(cols, rows, name, column_offset)
self.create_netlist() self.create_netlist()
if not OPTS.netlist_only: 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. Generate a dummy row/column for the replica array.
""" """
def __init__(self, cols, rows, mirror=0, name=""): def __init__(self, cols, rows, column_offset=0, mirror=0, name=""):
super().__init__(cols, rows, name) super().__init__(cols, rows, name, column_offset)
self.mirror = mirror self.mirror = mirror
self.create_netlist() self.create_netlist()

View File

@ -86,6 +86,7 @@ class replica_bitcell_array(design.design):
# Bitcell array # Bitcell array
self.bitcell_array = factory.create(module_type="bitcell_array", self.bitcell_array = factory.create(module_type="bitcell_array",
column_offset=1 + self.left_rbl,
cols=self.column_size, cols=self.column_size,
rows=self.row_size) rows=self.row_size)
self.add_mod(self.bitcell_array) 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): for bit in range(self.left_rbl+self.right_rbl):
if bit<self.left_rbl: if bit<self.left_rbl:
replica_bit = bit+1 replica_bit = bit+1
# dummy column
column_offset = 1
else: else:
replica_bit = bit+self.row_size+1 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", self.replica_columns[bit] = factory.create(module_type="replica_column",
rows=self.row_size, rows=self.row_size,
left_rbl=self.left_rbl, left_rbl=self.left_rbl,
right_rbl=self.right_rbl, right_rbl=self.right_rbl,
column_offset=column_offset,
replica_bit=replica_bit) replica_bit=replica_bit)
self.add_mod(self.replica_columns[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", self.dummy_row = factory.create(module_type="dummy_array",
cols=self.column_size, cols=self.column_size,
rows=1, rows=1,
# dummy column + left replica column
column_offset=1 + self.left_rbl,
mirror=0) mirror=0)
self.add_mod(self.dummy_row) self.add_mod(self.dummy_row)
# Dummy col (mirror starting at first if odd replica+dummy rows) # Dummy col (mirror starting at first if odd replica+dummy rows)
self.dummy_col = factory.create(module_type="dummy_array", self.dummy_col_left = factory.create(module_type="dummy_array",
cols=1, cols=1,
rows=self.row_size + self.extra_rows, column_offset=0,
mirror=(self.left_rbl+1)%2) rows=self.row_size + self.extra_rows,
self.add_mod(self.dummy_col) 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): def add_pins(self):
@ -236,10 +256,10 @@ class replica_bitcell_array(design.design):
# Left/right Dummy columns # Left/right Dummy columns
self.dummy_col_left_inst=self.add_inst(name="dummy_col_left", 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.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", 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) 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. 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) design.design.__init__(self, name)
self.rows = rows self.rows = rows
@ -29,6 +30,7 @@ class replica_column(design.design):
self.replica_bit = replica_bit self.replica_bit = replica_bit
# left, right, regular rows plus top/bottom dummy cells # left, right, regular rows plus top/bottom dummy cells
self.total_size = self.left_rbl+rows+self.right_rbl+2 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!=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, 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 # 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 # so that we will start with mirroring rather than not mirroring
rbl_offset = (self.left_rbl+1)%2 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): for row in range(self.total_size):
dir_x = False
name = "bit_r{0}_{1}".format(row,"rbl") 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: 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" dir_key = "MX"
elif dir_y:
dir_key = "MY"
else: else:
dir_key = "R0" dir_key = ""
self.cell_inst[row].place(offset=offset, self.cell_inst[row].place(offset=offset,
mirror=dir_key) mirror=dir_key)