scmos passing with odd sizses again

This commit is contained in:
Jesse Cirimelli-Low 2023-07-27 18:39:18 -07:00
parent a6e07aa364
commit 8d8f243f99
3 changed files with 83 additions and 44 deletions

View File

@ -164,7 +164,7 @@ class instance(geometry):
An instance of an instance/module with a specified location and An instance of an instance/module with a specified location and
rotation rotation
""" """
def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0): def __init__(self, name, mod, offset=[0, 0], mirror="R0", rotate=0, is_bitcell=False):
"""Initializes an instance to represent a module""" """Initializes an instance to represent a module"""
super().__init__() super().__init__()
debug.check(mirror not in ["R90", "R180", "R270"], debug.check(mirror not in ["R90", "R180", "R270"],
@ -176,6 +176,7 @@ class instance(geometry):
self.rotate = rotate self.rotate = rotate
self.offset = vector(offset).snap_to_grid() self.offset = vector(offset).snap_to_grid()
self.mirror = mirror self.mirror = mirror
self.is_bitcell = is_bitcell
if OPTS.netlist_only: if OPTS.netlist_only:
self.width = 0 self.width = 0
self.height = 0 self.height = 0

View File

@ -12,6 +12,7 @@ from openram import OPTS
from .bitcell_base_array import bitcell_base_array from .bitcell_base_array import bitcell_base_array
from .pattern import pattern from .pattern import pattern
from openram.base import geometry, instance from openram.base import geometry, instance
from math import ceil
class bitcell_array(bitcell_base_array): class bitcell_array(bitcell_base_array):
""" """
@ -60,18 +61,11 @@ class bitcell_array(bitcell_base_array):
def create_instances(self): def create_instances(self):
self.cell_inst={} self.cell_inst={}
core_block = [[0 for x in range(2)] for y in range(2)] core_block = [[0 for x in range(2)] for y in range(2)]
core_block[0][0] = geometry.instance("core_0_0", mod=self.cell) core_block[0][0] = geometry.instance("core_0_0", mod=self.cell, is_bitcell=True)
core_block[0][1] = geometry.instance("core_1_0", mod=self.cell) core_block[0][1] = geometry.instance("core_1_0", mod=self.cell, is_bitcell=True)
core_block[1][0] = geometry.instance("core_0_1", mod=self.cell) core_block[1][0] = geometry.instance("core_0_1", mod=self.cell, is_bitcell=True)
core_block[1][1] = geometry.instance("core_1_1", mod=self.cell) core_block[1][1] = geometry.instance("core_1_1", mod=self.cell, is_bitcell=True)
num_core_x = self.row_size/len(core_block[0]) self.pattern = pattern(self, "bitcell_array", core_block, self.row_size, self.column_size)
num_core_y = self.column_size/len(core_block)
debug.check(num_core_x.is_integer(), "number of core blocks must be an integer")
debug.check(num_core_y.is_integer(), "number of core blocks must be an integer")
num_core_x = int(num_core_x)
num_core_y = int(num_core_y)
self.pattern = pattern(self, "bitcell_array", core_block, num_core_x, num_core_y)
self.pattern.connect_array() self.pattern.connect_array()
def analytical_power(self, corner, load): def analytical_power(self, corner, load):

View File

@ -4,6 +4,7 @@ from typing import List
from typing import Optional from typing import Optional
from openram.base import design from openram.base import design
from openram.globals import OPTS from openram.globals import OPTS
from math import ceil
class pattern(): class pattern():
""" """
This class is used to desribe the internals of a bitcell array. It describes This class is used to desribe the internals of a bitcell array. It describes
@ -15,8 +16,10 @@ class pattern():
parent_design: design, parent_design: design,
name:str, name:str,
core_block:block, core_block:block,
num_core_x:int, num_rows:int,
num_core_y:int, num_cols:int,
num_cores_x: Optional[int] = 0,
num_cores_y: Optional[int] = 0,
cores_per_x_block: int = 1, cores_per_x_block: int = 1,
cores_per_y_block: int = 1, cores_per_y_block: int = 1,
x_block: Optional[block] = None, x_block: Optional[block] = None,
@ -40,8 +43,15 @@ class pattern():
self.parent_design = parent_design self.parent_design = parent_design
self.name = name self.name = name
self.core_block = core_block self.core_block = core_block
self.num_core_x = num_core_x self.num_rows = num_rows
self.num_core_y = num_core_y self.num_cols = num_cols
self.num_cores_x = num_cores_x
self.num_cores_y = num_cores_y
if num_cores_x == 0:
self.num_cores_x = ceil(num_cols/len(core_block[0]))
if num_cores_y == 0:
self.num_cores_y = ceil(num_rows/len(core_block))
self.cores_per_x_block = cores_per_x_block self.cores_per_x_block = cores_per_x_block
self.cores_per_y_block = cores_per_y_block self.cores_per_y_block = cores_per_y_block
self.x_block = x_block self.x_block = x_block
@ -92,24 +102,39 @@ class pattern():
if(self.xy_block): if(self.xy_block):
debug.check(self.xy_block_height == self.x_block_height, "xy_block does not align with x_block") debug.check(self.xy_block_height == self.x_block_height, "xy_block does not align with x_block")
debug.check(self.xy_block_width == self.y_block_width, "xy_block does not align with y_block") debug.check(self.xy_block_width == self.y_block_width, "xy_block does not align with y_block")
def connect_block(self, block: block, col: int, row: int) -> None: def connect_block(self, block: block, col: int, row: int):
for dr in range(len(block)): for dr in range(len(block)):
for dc in range(len(block[0])): for dc in range(len(block[0])):
inst = block[dc][dr] if(self.bit_rows.count(self.num_rows) != self.num_cols and self.bit_cols.count(self.bit_cols) != self.num_rows):
self.parent_design.cell_inst[row + dr, col + dc] = self.parent_design.add_existing_inst(inst,"bit_r{}_c{}".format(row +dr, col+dc)) inst = block[dc][dr]
self.parent_design.connect_inst(self.parent_design.get_bitcell_pins(row+dr, col+dc)) if(len(self.bit_rows) <= col + dc):
self.bit_rows.append(0)
if(len(self.bit_cols) <= row + dr):
self.bit_cols.append(0)
if(self.bit_rows[col+dc] < self.num_cols and self.bit_cols[row+dr] < self.num_rows):
if(inst.is_bitcell):
self.bit_rows[col+dc] += 1
self.bit_cols[row+dr] += 1
self.parent_design.cell_inst[row + dr, col + dc] = self.parent_design.add_existing_inst(inst,"bit_r{}_c{}".format(row +dr, col+dc))
self.parent_design.connect_inst(self.parent_design.get_bitcell_pins(row+dr, col+dc))
def place_block(self, block: block, row: int, col: int, place_x: float, place_y: float) -> None: def connect_array(self) -> None:
x_offset = 0 self.bit_rows = []
y_offset = 0 self.bit_cols = []
for dr in range(len(block)): row = 0
for dc in range(len(block[0])): col = 0
inst = self.parent_design.cell_inst[row + dr, col +dc] for i in range(self.num_cores_y):
self.place_inst(inst, (place_x + x_offset, place_y + y_offset)) for j in range (self.num_cores_x):
x_offset += inst.width print("connecting {} {}".format(row,col))
x_offset = 0 self.connect_block(self.core_block, col, row)
y_offset += inst.height col += len(self.core_block[0])
col = 0
row += len(self.core_block)
print(self.bit_rows)
print(self.bit_cols)
print(self.parent_design.cell_inst)
def place_inst(self, inst, offset) -> None: def place_inst(self, inst, offset) -> None:
x = offset[0] x = offset[0]
@ -120,31 +145,50 @@ class pattern():
x += inst.width x += inst.width
inst.place((x, y), inst.mirror, inst.rotate) inst.place((x, y), inst.mirror, inst.rotate)
def connect_array(self) -> None:
row = 0
col = 0 def place_block(self, block: block, row: int, col: int, place_x: float, place_y: float) -> None:
for i in range(self.num_core_y): x_offset = 0
for j in range (self.num_core_x): y_offset = 0
print("connecting {} {}".format(row,col)) for dr in range(len(block)):
self.connect_block(self.core_block, col, row) for dc in range(len(block[0])):
col += len(self.core_block[0]) if(self.bit_rows.count(self.num_rows) != self.num_cols and self.bit_cols.count(self.bit_cols) != self.num_rows):
col = 0 if(len(self.bit_rows) <= col + dc):
row += len(self.core_block) self.bit_rows.append(0)
if(len(self.bit_cols) <= row + dr):
self.bit_cols.append(0)
if(self.bit_rows[col+dc] < self.num_cols and self.bit_cols[row+dr] < self.num_rows):
inst = self.parent_design.cell_inst[row + dr, col +dc]
if(inst.is_bitcell):
self.bit_rows[col+dc] += 1
self.bit_cols[row+dr] += 1
self.place_inst(inst, (place_x + x_offset, place_y + y_offset))
x_offset += inst.width
x_offset = 0
y_offset += inst.height
def place_array(self) -> None: def place_array(self) -> None:
self.bit_rows = []
self.bit_cols = []
row = 0 row = 0
col = 0 col = 0
place_x = 0 place_x = 0
place_y = 0 place_y = 0
for i in range(self.num_core_y): for i in range(self.num_cores_y):
col = 0 col = 0
place_x = 0 place_x = 0
for j in range (self.num_core_x): for j in range (self.num_cores_x):
print("placing {} {}".format(row,col)) print("placing {} {}".format(row,col))
self.place_block(self.core_block, row, col, place_x, place_y) self.place_block(self.core_block, row, col, place_x, place_y)
place_x += self.core_block_width place_x += self.core_block_width
col += len(self.core_block[0]) col += len(self.core_block[0])
if(self.bit_rows.count(self.num_rows) == self.num_cols and self.bit_cols.count(self.bit_cols) == self.num_rows):
print(self.bit_rows)
print(self.bit_cols)
return
row += len(self.core_block) row += len(self.core_block)
place_y += self.core_block_height place_y += self.core_block_height
self.parent_design.width = place_x self.parent_design.width = place_x