mirror of https://github.com/VLSIDA/OpenRAM.git
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:
parent
df9f351a91
commit
dd1afe0313
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue