mirror of https://github.com/VLSIDA/OpenRAM.git
code cleanup and updated copyright
This commit is contained in:
parent
ab955f0da8
commit
79efff9ca6
|
|
@ -1,11 +1,10 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
from openram.base import design
|
from openram.base import design
|
||||||
from openram.sram_factory import factory
|
from openram.sram_factory import factory
|
||||||
from openram.base import vector
|
from openram.base import vector
|
||||||
|
|
@ -80,7 +79,6 @@ class rom_address_control_array(design):
|
||||||
for col in range(self.cols):
|
for col in range(self.cols):
|
||||||
|
|
||||||
name = "Xaddr_buf_{0}".format(col)
|
name = "Xaddr_buf_{0}".format(col)
|
||||||
|
|
||||||
addr_buf = self.add_inst(name=name, mod=self.addr_control)
|
addr_buf = self.add_inst(name=name, mod=self.addr_control)
|
||||||
|
|
||||||
A_in = "A{0}_in".format(col)
|
A_in = "A{0}_in".format(col)
|
||||||
|
|
@ -99,24 +97,16 @@ class rom_address_control_array(design):
|
||||||
|
|
||||||
self.buf_insts[col].place(offset=base, mirror="MY")
|
self.buf_insts[col].place(offset=base, mirror="MY")
|
||||||
|
|
||||||
|
|
||||||
def copy_pins(self):
|
def copy_pins(self):
|
||||||
for i in range(self.cols):
|
for i in range(self.cols):
|
||||||
self.copy_layout_pin(self.buf_insts[i], "A_out", "A{0}_out".format(i))
|
self.copy_layout_pin(self.buf_insts[i], "A_out", "A{0}_out".format(i))
|
||||||
self.copy_layout_pin(self.buf_insts[i], "Abar_out", "Abar{0}_out".format(i))
|
self.copy_layout_pin(self.buf_insts[i], "Abar_out", "Abar{0}_out".format(i))
|
||||||
self.copy_layout_pin(self.buf_insts[i], "A_in", "A{0}_in".format(i))
|
self.copy_layout_pin(self.buf_insts[i], "A_in", "A{0}_in".format(i))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_clk(self):
|
def route_clk(self):
|
||||||
self.route_horizontal_pins("clk", insts=self.buf_insts, layer=self.route_layer)
|
self.route_horizontal_pins("clk", insts=self.buf_insts, layer=self.route_layer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_sources(self):
|
def route_sources(self):
|
||||||
|
|
||||||
self.route_horizontal_pins("vdd", insts=self.buf_insts, layer=self.route_layer)
|
self.route_horizontal_pins("vdd", insts=self.buf_insts, layer=self.route_layer)
|
||||||
self.route_horizontal_pins("gnd", insts=self.buf_insts, layer=self.route_layer)
|
self.route_horizontal_pins("gnd", insts=self.buf_insts, layer=self.route_layer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -22,10 +22,7 @@ class rom_address_control_buf(design):
|
||||||
|
|
||||||
self.route_layer = route_layer
|
self.route_layer = route_layer
|
||||||
self.add_wells = add_wells
|
self.add_wells = add_wells
|
||||||
|
|
||||||
self.size = size
|
self.size = size
|
||||||
|
|
||||||
|
|
||||||
if "li" in layer:
|
if "li" in layer:
|
||||||
self.inv_layer = "li"
|
self.inv_layer = "li"
|
||||||
else:
|
else:
|
||||||
|
|
@ -39,7 +36,6 @@ class rom_address_control_buf(design):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
self.create_instances()
|
self.create_instances()
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
self.width = self.cell.height * 2
|
self.width = self.cell.height * 2
|
||||||
self.height = self.inv.width + 2 * self.nand.width
|
self.height = self.inv.width + 2 * self.nand.width
|
||||||
|
|
@ -50,10 +46,8 @@ class rom_address_control_buf(design):
|
||||||
self.route_sources()
|
self.route_sources()
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
|
|
||||||
|
|
||||||
def create_modules(self):
|
def create_modules(self):
|
||||||
|
|
||||||
|
|
||||||
# self.inv1_mod = factory.create(module_type="pinv", module_name="inv_array_end_mod", height=self.inv_size, add_wells=False)
|
# self.inv1_mod = factory.create(module_type="pinv", module_name="inv_array_end_mod", height=self.inv_size, add_wells=False)
|
||||||
self.inv = factory.create(module_type="pinv_dec", module_name="inv_array_mod", add_wells=False, size=self.size)
|
self.inv = factory.create(module_type="pinv_dec", module_name="inv_array_mod", add_wells=False, size=self.size)
|
||||||
# self.end_inv = factory.create(module_type="pinv", module_name="inv_array_end_mod", size=self.size, add_wells=True)
|
# self.end_inv = factory.create(module_type="pinv", module_name="inv_array_end_mod", size=self.size, add_wells=True)
|
||||||
|
|
@ -95,24 +89,15 @@ class rom_address_control_buf(design):
|
||||||
inst_Z = "Abar_out"
|
inst_Z = "Abar_out"
|
||||||
self.connect_inst([inst_A, inst_B, inst_Z, "vdd", "gnd"])
|
self.connect_inst([inst_A, inst_B, inst_Z, "vdd", "gnd"])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def setup_layout_constants(self):
|
def setup_layout_constants(self):
|
||||||
self.route_width = drc["minwidth_{}".format(self.route_layer)]
|
self.route_width = drc["minwidth_{}".format(self.route_layer)]
|
||||||
self.interconnect_width = drc["minwidth_{}".format(self.inv_layer)]
|
self.interconnect_width = drc["minwidth_{}".format(self.inv_layer)]
|
||||||
|
|
||||||
def place_instances(self):
|
def place_instances(self):
|
||||||
|
|
||||||
|
|
||||||
self.inv_inst.place(offset=vector(self.inv_inst.height,0), rotate=90)
|
self.inv_inst.place(offset=vector(self.inv_inst.height,0), rotate=90)
|
||||||
self.addr_nand.place(offset=vector(self.addr_nand.height , self.inv_inst.width + self.route_width ), rotate=90)
|
self.addr_nand.place(offset=vector(self.addr_nand.height , self.inv_inst.width + self.route_width ), rotate=90)
|
||||||
|
|
||||||
self.addr_bar_nand.place(offset=vector( self.addr_bar_nand.height, self.addr_nand.width + self.inv_inst.width + self.route_width), rotate=90)
|
self.addr_bar_nand.place(offset=vector( self.addr_bar_nand.height, self.addr_nand.width + self.inv_inst.width + self.route_width), rotate=90)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_gates(self):
|
def route_gates(self):
|
||||||
clk1_pin = self.addr_nand.get_pin("A")
|
clk1_pin = self.addr_nand.get_pin("A")
|
||||||
clk2_pin = self.addr_bar_nand.get_pin("A")
|
clk2_pin = self.addr_bar_nand.get_pin("A")
|
||||||
|
|
@ -171,9 +156,6 @@ class rom_address_control_buf(design):
|
||||||
self.add_segment_center(self.inv_layer, Abar_int_out.center(), end)
|
self.add_segment_center(self.inv_layer, Abar_int_out.center(), end)
|
||||||
self.copy_layout_pin(self.inv_inst, "A", "A_in")
|
self.copy_layout_pin(self.inv_inst, "A", "A_in")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_sources(self):
|
def route_sources(self):
|
||||||
|
|
||||||
self.copy_layout_pin(self.addr_nand, "vdd")
|
self.copy_layout_pin(self.addr_nand, "vdd")
|
||||||
|
|
@ -210,5 +192,3 @@ class rom_address_control_buf(design):
|
||||||
self.add_via_stack_center(offset=contact_pos,
|
self.add_via_stack_center(offset=contact_pos,
|
||||||
from_layer=self.active_stack[2],
|
from_layer=self.active_stack[2],
|
||||||
to_layer=self.route_layer)
|
to_layer=self.route_layer)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -29,8 +29,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.data_col_size = self.column_size
|
self.data_col_size = self.column_size
|
||||||
self.tap_spacing = tap_spacing
|
self.tap_spacing = tap_spacing
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if strap_spacing != 0:
|
if strap_spacing != 0:
|
||||||
self.array_col_size = self.column_size + math.ceil(self.column_size / strap_spacing)
|
self.array_col_size = self.column_size + math.ceil(self.column_size / strap_spacing)
|
||||||
else:
|
else:
|
||||||
|
|
@ -40,7 +38,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.create_netlist()
|
self.create_netlist()
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
|
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_modules()
|
self.add_modules()
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -48,7 +45,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.create_cell_instances()
|
self.create_cell_instances()
|
||||||
self.create_precharge_inst()
|
self.create_precharge_inst()
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
self.create_layout_constants()
|
self.create_layout_constants()
|
||||||
self.place_array()
|
self.place_array()
|
||||||
|
|
@ -64,21 +60,16 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.place_rails()
|
self.place_rails()
|
||||||
self.connect_taps()
|
self.connect_taps()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_boundary(self):
|
def add_boundary(self):
|
||||||
ll = self.find_lowest_coords()
|
ll = self.find_lowest_coords()
|
||||||
m1_offset = self.m1_width
|
m1_offset = self.m1_width
|
||||||
self.translate_all(vector(0, ll.y + 0.5 * m1_offset))
|
self.translate_all(vector(0, ll.y + 0.5 * m1_offset))
|
||||||
ur = self.find_highest_coords()
|
ur = self.find_highest_coords()
|
||||||
|
|
||||||
ur = vector(ur.x, ur.y - self.m1_width)
|
ur = vector(ur.x, ur.y - self.m1_width)
|
||||||
super().add_boundary(vector(0, 0), ur)
|
super().add_boundary(vector(0, 0), ur)
|
||||||
self.width = ur.x
|
self.width = ur.x
|
||||||
self.height = ur.y
|
self.height = ur.y
|
||||||
|
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
|
|
||||||
self.zero_cell = factory.create(module_name="rom_base_zero_cell",
|
self.zero_cell = factory.create(module_name="rom_base_zero_cell",
|
||||||
|
|
@ -102,13 +93,10 @@ class rom_base_array(bitcell_base_array):
|
||||||
strap_layer=self.wordline_layer,
|
strap_layer=self.wordline_layer,
|
||||||
tap_direction=self.tap_direction)
|
tap_direction=self.tap_direction)
|
||||||
|
|
||||||
|
|
||||||
def create_layout_constants(self):
|
def create_layout_constants(self):
|
||||||
self.route_width = drc("minwidth_" + self.bitline_layer)
|
self.route_width = drc("minwidth_" + self.bitline_layer)
|
||||||
|
|
||||||
self.route_pitch = drc("{0}_to_{0}".format(self.bitline_layer))
|
self.route_pitch = drc("{0}_to_{0}".format(self.bitline_layer))
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
for bl_name in self.get_bitline_names():
|
for bl_name in self.get_bitline_names():
|
||||||
self.add_pin(bl_name, "OUTPUT")
|
self.add_pin(bl_name, "OUTPUT")
|
||||||
|
|
@ -123,7 +111,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.tap_list = []
|
self.tap_list = []
|
||||||
self.cell_inst = {}
|
self.cell_inst = {}
|
||||||
self.cell_list = []
|
self.cell_list = []
|
||||||
|
|
||||||
self.current_row = 0
|
self.current_row = 0
|
||||||
#list of current bitline interconnect nets, starts as the same as the bitline list and is updated when new insts of cells are added
|
#list of current bitline interconnect nets, starts as the same as the bitline list and is updated when new insts of cells are added
|
||||||
self.int_bl_list = self.bitline_names[0].copy()
|
self.int_bl_list = self.bitline_names[0].copy()
|
||||||
|
|
@ -133,21 +120,17 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
# for each new strap placed, offset the column index refrenced to get correct bit in the data array
|
# for each new strap placed, offset the column index refrenced to get correct bit in the data array
|
||||||
# cols are bit lines
|
# cols are bit lines
|
||||||
|
|
||||||
for col in range(self.column_size):
|
for col in range(self.column_size):
|
||||||
|
|
||||||
if col % self.strap_spacing == 0:
|
if col % self.strap_spacing == 0:
|
||||||
self.create_poly_tap(row, col)
|
self.create_poly_tap(row, col)
|
||||||
|
|
||||||
|
|
||||||
new_inst = self.create_cell(row, col)
|
new_inst = self.create_cell(row, col)
|
||||||
|
|
||||||
self.cell_inst[row, col] = new_inst
|
self.cell_inst[row, col] = new_inst
|
||||||
|
|
||||||
row_list.append(new_inst)
|
row_list.append(new_inst)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
name = "tap_r{0}_c{1}".format(row, self.array_col_size)
|
name = "tap_r{0}_c{1}".format(row, self.array_col_size)
|
||||||
new_tap = self.add_inst(name=name, mod=self.poly_tap)
|
new_tap = self.add_inst(name=name, mod=self.poly_tap)
|
||||||
self.tap_inst[row, self.column_size] = new_tap
|
self.tap_inst[row, self.column_size] = new_tap
|
||||||
|
|
@ -156,10 +139,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
self.cell_list.append(row_list)
|
self.cell_list.append(row_list)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_poly_tap(self, row, col):
|
def create_poly_tap(self, row, col):
|
||||||
name = "tap_r{0}_c{1}".format(row, col)
|
name = "tap_r{0}_c{1}".format(row, col)
|
||||||
new_tap = self.add_inst(name=name, mod=self.poly_tap)
|
new_tap = self.add_inst(name=name, mod=self.poly_tap)
|
||||||
|
|
@ -167,7 +146,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
self.tap_list.append(new_tap)
|
self.tap_list.append(new_tap)
|
||||||
self.connect_inst([])
|
self.connect_inst([])
|
||||||
|
|
||||||
|
|
||||||
def create_cell(self, row, col):
|
def create_cell(self, row, col):
|
||||||
name = "bit_r{0}_c{1}".format(row, col)
|
name = "bit_r{0}_c{1}".format(row, col)
|
||||||
|
|
||||||
|
|
@ -182,7 +160,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
if self.data[row][col] == 1:
|
if self.data[row][col] == 1:
|
||||||
self.int_bl_list[col] = "bl_int_{0}_{1}".format(row, col)
|
self.int_bl_list[col] = "bl_int_{0}_{1}".format(row, col)
|
||||||
|
|
||||||
bl_h = self.int_bl_list[col]
|
bl_h = self.int_bl_list[col]
|
||||||
# Final row of dummy nmos that contains only 1s, acts to prevent shorting bl to ground when precharging
|
# Final row of dummy nmos that contains only 1s, acts to prevent shorting bl to ground when precharging
|
||||||
|
|
||||||
|
|
@ -198,23 +175,14 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
return new_inst
|
return new_inst
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_precharge_inst(self):
|
def create_precharge_inst(self):
|
||||||
prechrg_pins = self.bitline_names[0].copy()
|
prechrg_pins = self.bitline_names[0].copy()
|
||||||
|
|
||||||
# for bl in range(self.column_size):
|
|
||||||
# # if the internal bl was never updated there are no active cells in the bitline, so it should route straight to ground"
|
|
||||||
# if self.int_bl_list[bl] == prechrg_pins[bl]:
|
|
||||||
# prechrg_pins[bl] = "gnd"
|
|
||||||
|
|
||||||
prechrg_pins.append("precharge")
|
prechrg_pins.append("precharge")
|
||||||
prechrg_pins.append("vdd")
|
prechrg_pins.append("vdd")
|
||||||
self.precharge_inst = self.add_inst(name="bitcell_array_precharge", mod=self.precharge_array)
|
self.precharge_inst = self.add_inst(name="bitcell_array_precharge", mod=self.precharge_array)
|
||||||
self.connect_inst(prechrg_pins)
|
self.connect_inst(prechrg_pins)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_all_bitline_names(self):
|
def create_all_bitline_names(self):
|
||||||
for col in range(self.column_size):
|
for col in range(self.column_size):
|
||||||
for port in self.all_ports:
|
for port in self.all_ports:
|
||||||
|
|
@ -222,25 +190,18 @@ class rom_base_array(bitcell_base_array):
|
||||||
# Make a flat list too
|
# Make a flat list too
|
||||||
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
|
self.all_bitline_names = [x for sl in zip(*self.bitline_names) for x in sl]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_rails(self):
|
def place_rails(self):
|
||||||
via_width = drc("m2_enclose_via1") * 0.5 + drc("minwidth_via1")
|
via_width = drc("m2_enclose_via1") * 0.5 + drc("minwidth_via1")
|
||||||
pitch = drc["{0}_to_{0}".format(self.wordline_layer)]
|
pitch = drc["{0}_to_{0}".format(self.wordline_layer)]
|
||||||
|
|
||||||
for i in range(self.column_size):
|
for i in range(self.column_size):
|
||||||
drain = self.cell_list[self.row_size][i].get_pin("D")
|
drain = self.cell_list[self.row_size][i].get_pin("D")
|
||||||
|
|
||||||
gnd_pos = drain.center() + vector(0, pitch + via_width + self.route_pitch)
|
gnd_pos = drain.center() + vector(0, pitch + via_width + self.route_pitch)
|
||||||
self.add_layout_pin_rect_center(text="gnd", layer=self.bitline_layer, offset=gnd_pos)
|
self.add_layout_pin_rect_center(text="gnd", layer=self.bitline_layer, offset=gnd_pos)
|
||||||
self.route_horizontal_pins("gnd", insts=[self], yside="cy")
|
self.route_horizontal_pins("gnd", insts=[self], yside="cy")
|
||||||
|
|
||||||
|
|
||||||
self.copy_layout_pin(self.precharge_inst, "vdd")
|
self.copy_layout_pin(self.precharge_inst, "vdd")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_array(self):
|
def place_array(self):
|
||||||
self.cell_pos = {}
|
self.cell_pos = {}
|
||||||
self.strap_pos = {}
|
self.strap_pos = {}
|
||||||
|
|
@ -268,13 +229,9 @@ class rom_base_array(bitcell_base_array):
|
||||||
cell_x += self.zero_cell.width
|
cell_x += self.zero_cell.width
|
||||||
# self.add_label("debug", "li", self.cell_pos[row, col])
|
# self.add_label("debug", "li", self.cell_pos[row, col])
|
||||||
|
|
||||||
|
|
||||||
self.strap_pos[row, self.column_size] = vector(cell_x, cell_y)
|
self.strap_pos[row, self.column_size] = vector(cell_x, cell_y)
|
||||||
self.tap_inst[row, self.column_size].place(self.strap_pos[row, self.column_size])
|
self.tap_inst[row, self.column_size].place(self.strap_pos[row, self.column_size])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_pitch_offsets(self):
|
def route_pitch_offsets(self):
|
||||||
|
|
||||||
for row in range(0 , self.row_size, self.tap_spacing):
|
for row in range(0 , self.row_size, self.tap_spacing):
|
||||||
|
|
@ -289,11 +246,8 @@ class rom_base_array(bitcell_base_array):
|
||||||
start = vector(drain.cx(), source.cy())
|
start = vector(drain.cx(), source.cy())
|
||||||
end = drain.center()
|
end = drain.center()
|
||||||
self.add_segment_center(self.bitline_layer, start, end)
|
self.add_segment_center(self.bitline_layer, start, end)
|
||||||
|
|
||||||
self.place_well_tap(row, col)
|
self.place_well_tap(row, col)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_well_tap(self, row, col):
|
def place_well_tap(self, row, col):
|
||||||
cell = self.cell_inst[row, col]
|
cell = self.cell_inst[row, col]
|
||||||
source = cell.get_pin("S")
|
source = cell.get_pin("S")
|
||||||
|
|
@ -309,9 +263,7 @@ class rom_base_array(bitcell_base_array):
|
||||||
else:
|
else:
|
||||||
tap_y = source.cy() - self.contact_width - 2 * self.active_enclose_contact - self.active_space
|
tap_y = source.cy() - self.contact_width - 2 * self.active_enclose_contact - self.active_space
|
||||||
|
|
||||||
|
|
||||||
tap_pos = vector(tap_x, tap_y)
|
tap_pos = vector(tap_x, tap_y)
|
||||||
|
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.add_via_center(layers=self.active_stack,
|
||||||
offset=tap_pos,
|
offset=tap_pos,
|
||||||
implant_type="p",
|
implant_type="p",
|
||||||
|
|
@ -322,27 +274,17 @@ class rom_base_array(bitcell_base_array):
|
||||||
to_layer=self.wordline_layer)
|
to_layer=self.wordline_layer)
|
||||||
self.add_layout_pin_rect_center("gnd", self.wordline_layer, tap_pos)
|
self.add_layout_pin_rect_center("gnd", self.wordline_layer, tap_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_precharge(self):
|
def place_precharge(self):
|
||||||
|
|
||||||
self.precharge_offset = vector(0, - self.precharge_inst.height - self.zero_cell.nmos.end_to_contact - 2 * drc["nwell_enclose_active"] - 3 * self.m1_pitch)
|
self.precharge_offset = vector(0, - self.precharge_inst.height - self.zero_cell.nmos.end_to_contact - 2 * drc["nwell_enclose_active"] - 3 * self.m1_pitch)
|
||||||
|
|
||||||
self.precharge_inst.place(offset=self.precharge_offset)
|
self.precharge_inst.place(offset=self.precharge_offset)
|
||||||
|
|
||||||
self.copy_layout_pin(self.precharge_inst, "vdd")
|
self.copy_layout_pin(self.precharge_inst, "vdd")
|
||||||
self.copy_layout_pin(self.precharge_inst, "gate", "precharge")
|
self.copy_layout_pin(self.precharge_inst, "gate", "precharge")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_wordline_contacts(self):
|
def place_wordline_contacts(self):
|
||||||
|
|
||||||
for wl in range(self.row_size):
|
for wl in range(self.row_size):
|
||||||
|
|
||||||
self.copy_layout_pin(self.tap_inst[wl, 0], "poly_tap", self.wordline_names[0][wl])
|
self.copy_layout_pin(self.tap_inst[wl, 0], "poly_tap", self.wordline_names[0][wl])
|
||||||
# self.add_via_stack_center(poly_via.center(), "m1", self.output_layer)
|
|
||||||
|
|
||||||
# self.create_horizontal_pin_bus(self.route_layer, offset=corrected_offset, names=self.wordline_names[0], pitch=self.zero_cell.height, length=None)
|
|
||||||
|
|
||||||
def place_bitline_contacts(self):
|
def place_bitline_contacts(self):
|
||||||
|
|
||||||
|
|
@ -364,8 +306,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(self.bitline_names[0][bl], self.bitline_layer, output_pos )
|
self.add_layout_pin_rect_center(self.bitline_names[0][bl], self.bitline_layer, output_pos )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def route_precharge(self):
|
def route_precharge(self):
|
||||||
for bl in range(self.column_size):
|
for bl in range(self.column_size):
|
||||||
bl_pin = self.cell_list[0][bl].get_pin("S")
|
bl_pin = self.cell_list[0][bl].get_pin("S")
|
||||||
|
|
@ -393,8 +333,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="precharge_r", layer="m1", offset=mid1)
|
self.add_layout_pin_rect_center(text="precharge_r", layer="m1", offset=mid1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def connect_taps(self):
|
def connect_taps(self):
|
||||||
array_pins = [self.tap_list[i].get_pin("poly_tap") for i in range(len(self.tap_list))]
|
array_pins = [self.tap_list[i].get_pin("poly_tap") for i in range(len(self.tap_list))]
|
||||||
|
|
||||||
|
|
@ -404,8 +342,6 @@ class rom_base_array(bitcell_base_array):
|
||||||
if self.tap_direction == "col":
|
if self.tap_direction == "col":
|
||||||
self.route_vertical_pins("active_tap", insts=self.tap_list, layer=self.supply_stack[0], full_width=False)
|
self.route_vertical_pins("active_tap", insts=self.tap_list, layer=self.supply_stack[0], full_width=False)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def get_next_cell_in_bl(self, row_start, col):
|
def get_next_cell_in_bl(self, row_start, col):
|
||||||
for row in range(row_start + 1, self.row_size):
|
for row in range(row_start + 1, self.row_size):
|
||||||
if self.data[row][col] == 1:
|
if self.data[row][col] == 1:
|
||||||
|
|
@ -422,5 +358,3 @@ class rom_base_array(bitcell_base_array):
|
||||||
"""create a new net name for a bitline interconnect"""
|
"""create a new net name for a bitline interconnect"""
|
||||||
self.current_row = row
|
self.current_row = row
|
||||||
return "bli_{0}_{1}".format(row, col)
|
return "bli_{0}_{1}".format(row, col)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,10 @@
|
||||||
|
# See LICENSE for licensing information.
|
||||||
|
#
|
||||||
|
# Copyright (c) 2016-2023 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.
|
||||||
|
#
|
||||||
|
|
||||||
from math import ceil, log, sqrt
|
from math import ceil, log, sqrt
|
||||||
from openram.base import vector
|
from openram.base import vector
|
||||||
|
|
@ -103,24 +110,7 @@ class rom_base_bank(design):
|
||||||
# self.data.reverse()
|
# self.data.reverse()
|
||||||
|
|
||||||
debug.info(1, "Read rom binary: length {0} bytes, {1} words, set number of cols to {2}, rows to {3}, with {4} words per row".format(data_size, num_words, self.cols, self.rows, self.words_per_row))
|
debug.info(1, "Read rom binary: length {0} bytes, {1} words, set number of cols to {2}, rows to {3}, with {4} words per row".format(data_size, num_words, self.cols, self.rows, self.words_per_row))
|
||||||
# self.print_data(chunked_data)
|
|
||||||
# print("Scrambled")
|
|
||||||
# self.print_data(scrambled_chunked)
|
|
||||||
|
|
||||||
# self.print_word(self.data, 0, 0)
|
|
||||||
# self.print_word(self.data, 0, 1)
|
|
||||||
# self.print_word(self.data, 0, 2)
|
|
||||||
# self.print_word(self.data, 0, 3)
|
|
||||||
# print("hex: {0}, binary: {1}, chunked: {2}".format(hex_data, bin_data, chunked_data))
|
|
||||||
|
|
||||||
def print_data(self, data_array):
|
|
||||||
for row in range(len(data_array)):
|
|
||||||
print(data_array[row])
|
|
||||||
|
|
||||||
def print_word(self, data_array, bl, word):
|
|
||||||
for bit in range(self.word_size):
|
|
||||||
print(data_array[bl][word + self.words_per_row * bit], end =" ")
|
|
||||||
print("")
|
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_modules()
|
self.add_modules()
|
||||||
|
|
@ -129,18 +119,13 @@ class rom_base_bank(design):
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
print("Creating ROM bank instances")
|
|
||||||
self.create_instances()
|
self.create_instances()
|
||||||
print("Placing ROM bank instances")
|
|
||||||
self.place_instances()
|
self.place_instances()
|
||||||
|
|
||||||
print("Routing decoders to array")
|
|
||||||
self.route_decode_outputs()
|
self.route_decode_outputs()
|
||||||
|
|
||||||
print("Routing precharge signal")
|
|
||||||
self.route_precharge()
|
self.route_precharge()
|
||||||
|
|
||||||
print("Routing clock signal")
|
|
||||||
self.route_clock()
|
self.route_clock()
|
||||||
self.route_array_outputs()
|
self.route_array_outputs()
|
||||||
self.place_top_level_pins()
|
self.place_top_level_pins()
|
||||||
|
|
@ -177,7 +162,6 @@ class rom_base_bank(design):
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
|
|
||||||
print("Creating bank modules")
|
|
||||||
# TODO: provide technology-specific calculation of these parameters
|
# TODO: provide technology-specific calculation of these parameters
|
||||||
# in sky130 the address control buffer is composed of 2 size 2 NAND gates,
|
# in sky130 the address control buffer is composed of 2 size 2 NAND gates,
|
||||||
# with a beta of 3, each of these gates has gate capacitance of 2 min sized inverters, therefor a load of 4
|
# with a beta of 3, each of these gates has gate capacitance of 2 min sized inverters, therefor a load of 4
|
||||||
|
|
@ -487,16 +471,7 @@ class rom_base_bank(design):
|
||||||
|
|
||||||
channel_ll = vector( route_nets[0][0].cx(), route_nets[0][1].cy() + self.m1_pitch * 3)
|
channel_ll = vector( route_nets[0][0].cx(), route_nets[0][1].cy() + self.m1_pitch * 3)
|
||||||
self.create_horizontal_channel_route(netlist=route_nets, offset=channel_ll, layer_stack=self.m1_stack)
|
self.create_horizontal_channel_route(netlist=route_nets, offset=channel_ll, layer_stack=self.m1_stack)
|
||||||
# for bit in range(self.word_size):
|
|
||||||
# mux_pin = self.mux_inst.get_pin("bl_out_{}".format(bit))
|
|
||||||
# buf_pin = self.output_buf_inst.get_pin("in_{}".format(bit))
|
|
||||||
# mux_out = vector(mux_pin.cx(), mux_pin.by())
|
|
||||||
# buf_in = buf_pin.center()
|
|
||||||
|
|
||||||
# mid1 = vector(mux_out.x, buf_in.y + bit * self.m2_pitch)
|
|
||||||
# mid2 = vector(buf_in.x, mid1.y)
|
|
||||||
# print("start: {0}, mid: {1}, stop: {2}".format(mux_out, mid1, buf_in))
|
|
||||||
# self.add_path(layer="m2", coordinates=[mux_out, mid1, mid2, buf_in])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -524,12 +499,3 @@ class rom_base_bank(design):
|
||||||
if not inst.mod.name.__contains__("contact"):
|
if not inst.mod.name.__contains__("contact"):
|
||||||
self.copy_layout_pin(inst, "vdd")
|
self.copy_layout_pin(inst, "vdd")
|
||||||
self.copy_layout_pin(inst, "gnd")
|
self.copy_layout_pin(inst, "gnd")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -80,7 +80,7 @@ class rom_base_cell(design):
|
||||||
# height = self.base_width - min(self.cell_diffusion_offset, 0) - min(self.poly_active_offset, 0) - min(self.poly_tap_offset, 0)
|
# height = self.base_width - min(self.cell_diffusion_offset, 0) - min(self.poly_active_offset, 0) - min(self.poly_tap_offset, 0)
|
||||||
|
|
||||||
# make the cells square so the pitch of wordlines will match bitlines
|
# make the cells square so the pitch of wordlines will match bitlines
|
||||||
# print("height: {0} width: {1}".format(height, width))
|
|
||||||
if width > height:
|
if width > height:
|
||||||
self.width = width
|
self.width = width
|
||||||
self.height = width
|
self.height = width
|
||||||
|
|
@ -151,22 +151,3 @@ class rom_base_cell(design):
|
||||||
def short_gate(self):
|
def short_gate(self):
|
||||||
|
|
||||||
self.add_segment_center(self.bitline_layer, self.get_pin("D").center(), self.get_pin("S").center())
|
self.add_segment_center(self.bitline_layer, self.get_pin("D").center(), self.get_pin("S").center())
|
||||||
|
|
||||||
# def place_tap(self):
|
|
||||||
|
|
||||||
# tap_x = self.poly_contact.width * 0.5
|
|
||||||
# tap_y = self.via.uy() + drc["{0}_to_{0}".format(self.strap_layer)] * 2
|
|
||||||
|
|
||||||
# contact_pos = vector(tap_x, tap_y)
|
|
||||||
# self.add_via_center(layers=self.active_stack,
|
|
||||||
# offset=contact_pos,
|
|
||||||
# implant_type="p",
|
|
||||||
# well_type="p")
|
|
||||||
# self.add_power_pin(name="gnd",
|
|
||||||
# loc=contact_pos,
|
|
||||||
# start_layer=self.active_stack[2])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -208,10 +208,3 @@ class rom_column_mux(pgate):
|
||||||
self.add_layout_pin_rect_center(text="gnd",
|
self.add_layout_pin_rect_center(text="gnd",
|
||||||
layer=self.supply_stack[0],
|
layer=self.supply_stack[0],
|
||||||
offset=active_pos)
|
offset=active_pos)
|
||||||
|
|
||||||
# Add well enclosure over all the tx and contact
|
|
||||||
# if "pwell" in layer:
|
|
||||||
# self.add_rect(layer="pwell",
|
|
||||||
# offset=vector(0, 0),
|
|
||||||
# width=rbc_width,
|
|
||||||
# height=self.height)
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -28,7 +28,6 @@ class rom_control_logic(design):
|
||||||
|
|
||||||
self.clk_fanout = clk_fanout
|
self.clk_fanout = clk_fanout
|
||||||
|
|
||||||
|
|
||||||
if "li" in layer:
|
if "li" in layer:
|
||||||
self.route_stack = self.li_stack
|
self.route_stack = self.li_stack
|
||||||
else:
|
else:
|
||||||
|
|
@ -38,7 +37,6 @@ class rom_control_logic(design):
|
||||||
self.create_layout()
|
self.create_layout()
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
|
|
||||||
|
|
||||||
def create_netlist(self):
|
def create_netlist(self):
|
||||||
self.add_modules()
|
self.add_modules()
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
|
|
@ -68,7 +66,6 @@ class rom_control_logic(design):
|
||||||
height=self.driver_height,
|
height=self.driver_height,
|
||||||
add_wells=True)
|
add_wells=True)
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
self.add_pin("clk_in", "INPUT")
|
self.add_pin("clk_in", "INPUT")
|
||||||
self.add_pin("CS", "INPUT")
|
self.add_pin("CS", "INPUT")
|
||||||
|
|
@ -90,15 +87,12 @@ class rom_control_logic(design):
|
||||||
|
|
||||||
|
|
||||||
def place_instances(self):
|
def place_instances(self):
|
||||||
# nand_y = self.buf_inst.get_pin("vdd").cy() - self.nand_inst.get_pin("vdd").cy()
|
|
||||||
self.nand_inst.place(offset=[self.buf_inst.width, 0])
|
self.nand_inst.place(offset=[self.buf_inst.width, 0])
|
||||||
self.driver_inst.place(offset=[0, self.buf_inst.height + self.driver_inst.height], mirror="MX")
|
self.driver_inst.place(offset=[0, self.buf_inst.height + self.driver_inst.height], mirror="MX")
|
||||||
|
|
||||||
offset = self.driver_inst.get_pin("vdd").cy() - self.nand_inst.get_pin("vdd").cy()
|
offset = self.driver_inst.get_pin("vdd").cy() - self.nand_inst.get_pin("vdd").cy()
|
||||||
print("offset: {}".format(offset))
|
|
||||||
self.driver_inst.place(offset=[0, self.buf_inst.height + self.driver_inst.height - offset], mirror="MX")
|
self.driver_inst.place(offset=[0, self.buf_inst.height + self.driver_inst.height - offset], mirror="MX")
|
||||||
|
|
||||||
|
|
||||||
def route_insts(self):
|
def route_insts(self):
|
||||||
|
|
||||||
route_width = drc["minwidth_{}".format(self.route_stack[2])]
|
route_width = drc["minwidth_{}".format(self.route_stack[2])]
|
||||||
|
|
@ -137,7 +131,6 @@ class rom_control_logic(design):
|
||||||
|
|
||||||
self.add_path(self.route_stack[2], [nand_Z.center(), mid, driver_A.center()])
|
self.add_path(self.route_stack[2], [nand_Z.center(), mid, driver_A.center()])
|
||||||
|
|
||||||
|
|
||||||
self.add_via_stack_center(from_layer=nand_Z.layer,
|
self.add_via_stack_center(from_layer=nand_Z.layer,
|
||||||
to_layer=self.route_stack[2],
|
to_layer=self.route_stack[2],
|
||||||
offset=nand_Z.center())
|
offset=nand_Z.center())
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -11,8 +11,6 @@ from openram.base import vector, design
|
||||||
from openram import OPTS
|
from openram import OPTS
|
||||||
from openram.tech import drc
|
from openram.tech import drc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class rom_decoder(design):
|
class rom_decoder(design):
|
||||||
def __init__(self, num_outputs, fanout, strap_spacing, name="", route_layer="m1", output_layer="m1", invert_outputs=False):
|
def __init__(self, num_outputs, fanout, strap_spacing, name="", route_layer="m1", output_layer="m1", invert_outputs=False):
|
||||||
|
|
||||||
|
|
@ -24,8 +22,6 @@ class rom_decoder(design):
|
||||||
self.num_inputs = ceil(log(num_outputs, 2))
|
self.num_inputs = ceil(log(num_outputs, 2))
|
||||||
self.create_decode_map()
|
self.create_decode_map()
|
||||||
|
|
||||||
# for i in range(2 * self.num_inputs): print(self.decode_map[i])
|
|
||||||
|
|
||||||
super().__init__(name)
|
super().__init__(name)
|
||||||
|
|
||||||
b = factory.create(module_type=OPTS.bitcell)
|
b = factory.create(module_type=OPTS.bitcell)
|
||||||
|
|
@ -46,7 +42,6 @@ class rom_decoder(design):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
self.create_instances()
|
self.create_instances()
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
self.setup_layout_constants()
|
self.setup_layout_constants()
|
||||||
self.place_array()
|
self.place_array()
|
||||||
|
|
@ -93,18 +88,14 @@ class rom_decoder(design):
|
||||||
bin_digit = int(addr[addr_idx])
|
bin_digit = int(addr[addr_idx])
|
||||||
|
|
||||||
col_array.append(bin_digit)
|
col_array.append(bin_digit)
|
||||||
# print("addr {0}, at indx {1}, digit {2}".format(addr, addr_idx, bin_digit))
|
|
||||||
|
|
||||||
if bin_digit == 0 : inv_col_array.append(1)
|
if bin_digit == 0 : inv_col_array.append(1)
|
||||||
else : inv_col_array.append(0)
|
else : inv_col_array.append(0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
self.decode_map.append(col_array)
|
self.decode_map.append(col_array)
|
||||||
self.decode_map.append(inv_col_array)
|
self.decode_map.append(inv_col_array)
|
||||||
self.decode_map.reverse()
|
self.decode_map.reverse()
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
for i in range(self.num_inputs):
|
for i in range(self.num_inputs):
|
||||||
self.add_pin("A{0}".format(i), "INPUT")
|
self.add_pin("A{0}".format(i), "INPUT")
|
||||||
|
|
@ -116,20 +107,17 @@ class rom_decoder(design):
|
||||||
self.add_pin("vdd", "POWER")
|
self.add_pin("vdd", "POWER")
|
||||||
self.add_pin("gnd", "GROUND")
|
self.add_pin("gnd", "GROUND")
|
||||||
|
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
|
|
||||||
self.control_array = factory.create(module_type="rom_address_control_array",
|
self.control_array = factory.create(module_type="rom_address_control_array",
|
||||||
cols=self.num_inputs)
|
cols=self.num_inputs)
|
||||||
|
|
||||||
|
|
||||||
self.wordline_buf = factory.create(module_type="rom_wordline_driver_array", module_name="{}_wordline_buffer".format(self.name),
|
self.wordline_buf = factory.create(module_type="rom_wordline_driver_array", module_name="{}_wordline_buffer".format(self.name),
|
||||||
rows=self.num_outputs,
|
rows=self.num_outputs,
|
||||||
fanout=ceil(self.fanout),
|
fanout=ceil(self.fanout),
|
||||||
invert_outputs=self.invert_outputs,
|
invert_outputs=self.invert_outputs,
|
||||||
tap_spacing=self.strap_spacing)
|
tap_spacing=self.strap_spacing)
|
||||||
|
|
||||||
|
|
||||||
self.array_mod = factory.create(module_type="rom_base_array",
|
self.array_mod = factory.create(module_type="rom_base_array",
|
||||||
module_name="{}_array".format(self.name),
|
module_name="{}_array".format(self.name),
|
||||||
cols=self.num_outputs,
|
cols=self.num_outputs,
|
||||||
|
|
@ -139,14 +127,12 @@ class rom_decoder(design):
|
||||||
bitline_layer=self.output_layer,
|
bitline_layer=self.output_layer,
|
||||||
tap_direction="col")
|
tap_direction="col")
|
||||||
|
|
||||||
|
|
||||||
def create_instances(self):
|
def create_instances(self):
|
||||||
|
|
||||||
self.create_array_inst()
|
self.create_array_inst()
|
||||||
self.create_input_buffer()
|
self.create_input_buffer()
|
||||||
self.create_wordline_buffer()
|
self.create_wordline_buffer()
|
||||||
|
|
||||||
|
|
||||||
def create_input_buffer(self):
|
def create_input_buffer(self):
|
||||||
name = "pre_control_array"
|
name = "pre_control_array"
|
||||||
self.buf_inst = self.add_inst(name=name, mod=self.control_array)
|
self.buf_inst = self.add_inst(name=name, mod=self.control_array)
|
||||||
|
|
@ -166,7 +152,6 @@ class rom_decoder(design):
|
||||||
control_pins.append("gnd")
|
control_pins.append("gnd")
|
||||||
self.connect_inst(control_pins)
|
self.connect_inst(control_pins)
|
||||||
|
|
||||||
|
|
||||||
def create_array_inst(self):
|
def create_array_inst(self):
|
||||||
self.array_inst = self.add_inst(name="decode_array_inst", mod=self.array_mod)
|
self.array_inst = self.add_inst(name="decode_array_inst", mod=self.array_mod)
|
||||||
|
|
||||||
|
|
@ -192,8 +177,6 @@ class rom_decoder(design):
|
||||||
pwr_pins = ["vdd", "gnd"]
|
pwr_pins = ["vdd", "gnd"]
|
||||||
self.connect_inst(in_pins + out_pins + pwr_pins)
|
self.connect_inst(in_pins + out_pins + pwr_pins)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_input_buffer(self):
|
def place_input_buffer(self):
|
||||||
wl = self.array_mod.row_size - 1
|
wl = self.array_mod.row_size - 1
|
||||||
align = self.array_inst.get_pin(self.array_mod.wordline_names[0][wl]).cx() - self.buf_inst.get_pin("A0_out").cx()
|
align = self.array_inst.get_pin(self.array_mod.wordline_names[0][wl]).cx() - self.buf_inst.get_pin("A0_out").cx()
|
||||||
|
|
@ -202,8 +185,6 @@ class rom_decoder(design):
|
||||||
|
|
||||||
self.copy_layout_pin(self.buf_inst, "clk")
|
self.copy_layout_pin(self.buf_inst, "clk")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_array(self):
|
def place_array(self):
|
||||||
offset = vector(self.array_mod.height, self.control_array.height + self.m1_width + self.poly_contact.width)
|
offset = vector(self.array_mod.height, self.control_array.height + self.m1_width + self.poly_contact.width)
|
||||||
self.array_inst.place(offset, rotate=90)
|
self.array_inst.place(offset, rotate=90)
|
||||||
|
|
@ -231,7 +212,6 @@ class rom_decoder(design):
|
||||||
route_pins = array_pins + driver_pins
|
route_pins = array_pins + driver_pins
|
||||||
self.connect_row_pins(self.output_layer, route_pins, round=True)
|
self.connect_row_pins(self.output_layer, route_pins, round=True)
|
||||||
|
|
||||||
|
|
||||||
def connect_inputs(self):
|
def connect_inputs(self):
|
||||||
|
|
||||||
self.copy_layout_pin(self.array_inst, "precharge")
|
self.copy_layout_pin(self.array_inst, "precharge")
|
||||||
|
|
@ -264,27 +244,3 @@ class rom_decoder(design):
|
||||||
self.copy_layout_pin(self.array_inst, "gnd")
|
self.copy_layout_pin(self.array_inst, "gnd")
|
||||||
self.copy_layout_pin(self.wordline_buf_inst, "gnd")
|
self.copy_layout_pin(self.wordline_buf_inst, "gnd")
|
||||||
self.copy_layout_pin(self.buf_inst, "gnd")
|
self.copy_layout_pin(self.buf_inst, "gnd")
|
||||||
|
|
||||||
# Extend nwells to connect with eachother
|
|
||||||
# self.extend_wells()
|
|
||||||
|
|
||||||
|
|
||||||
def extend_wells(self):
|
|
||||||
precharge_well_rx = self.array_inst.get_pins("vdd")[0].cx() + 0.5 * self.nwell_width
|
|
||||||
precharge_well_lx = precharge_well_rx - self.array_mod.precharge_array.height - 0.5 * self.nwell_width - self.array_mod.precharge_array.well_offset
|
|
||||||
|
|
||||||
|
|
||||||
offset = vector(precharge_well_rx ,self.array_inst.by())
|
|
||||||
|
|
||||||
self.add_label(text="well_right", layer="nwell", offset=offset)
|
|
||||||
offset = vector(precharge_well_lx ,self.array_inst.by())
|
|
||||||
self.add_label(text="well_left", layer="nwell", offset=offset)
|
|
||||||
vdd_pins=self.buf_inst.get_pins("vdd").copy()
|
|
||||||
print(vdd_pins)
|
|
||||||
well_by = vdd_pins[0].cy()
|
|
||||||
# well_ll = vector(precharge_well_lx, well_by)
|
|
||||||
well_ll = vector(self.buf_inst.rx(), well_by)
|
|
||||||
# self.add_rect(layer="nwell", offset=well_ll, height = self.array_inst.by() - well_by, width=precharge_well_rx - self.buf_inst.rx())
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,87 +0,0 @@
|
||||||
# See LICENSE for licensing information.
|
|
||||||
#
|
|
||||||
# Copyright (c) 2016-2021 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.
|
|
||||||
#
|
|
||||||
|
|
||||||
from openram.base import design
|
|
||||||
from openram.base import vector
|
|
||||||
from openram import OPTS
|
|
||||||
from openram.sram_factory import factory
|
|
||||||
from openram.tech import drc
|
|
||||||
|
|
||||||
|
|
||||||
class rom_dummy_cell(design):
|
|
||||||
|
|
||||||
def __init__(self, name="", cell_name=None, add_source_contact=False, add_drain_contact=False, route_layer="m1"):
|
|
||||||
super().__init__(name, cell_name)
|
|
||||||
self.route_layer = route_layer
|
|
||||||
self.add_source_contact="li"
|
|
||||||
self.add_drain_contact="li"
|
|
||||||
self.create_netlist()
|
|
||||||
self.create_layout()
|
|
||||||
|
|
||||||
def create_netlist(self):
|
|
||||||
#creates nmos for layout dimensions
|
|
||||||
self.add_nmos()
|
|
||||||
|
|
||||||
#set height and width such that the cell will tile perfectly by only ofsetting in the array by its width and height
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
|
||||||
|
|
||||||
|
|
||||||
self.setup_drc_offsets()
|
|
||||||
|
|
||||||
self.add_boundary()
|
|
||||||
self.add_poly()
|
|
||||||
self.add_metal()
|
|
||||||
#self.add_label("0,0", self.route_layer)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_poly(self):
|
|
||||||
|
|
||||||
poly_x = 0.5 * (self.nmos.poly_height + self.poly_extend_active_spacing)
|
|
||||||
# 0.5 * self.nmos.contact_width + self.contact_to_gate
|
|
||||||
|
|
||||||
self.poly = self.add_rect_center("poly", vector(poly_x, self.base_width * 0.5), 2 * poly_x, self.poly_width)
|
|
||||||
|
|
||||||
def add_metal(self):
|
|
||||||
|
|
||||||
if self.route_layer == "li":
|
|
||||||
via = "mcon"
|
|
||||||
else:
|
|
||||||
via = "via{}".format(self.route_layer[len(self.route_layer) - 1])
|
|
||||||
wire_y = self.height + drc["minwidth_{}".format(via)] * 0.5
|
|
||||||
wire_x = 0.5 * (self.width - self.poly_extend_active_spacing)
|
|
||||||
|
|
||||||
wire_start = vector( wire_x, 0)
|
|
||||||
wire_end = vector(wire_x, wire_y)
|
|
||||||
|
|
||||||
# if self.route_layer == 'm1':
|
|
||||||
|
|
||||||
# if self.drain_contact:
|
|
||||||
# self.add_via_center(self.li_stack, [wire_x, wire_y])
|
|
||||||
# if self.source_contact:
|
|
||||||
# self.add_via_center(self.li_stack, [self.width, wire_y])
|
|
||||||
|
|
||||||
self.add_path(self.route_layer, [wire_start, wire_end])
|
|
||||||
|
|
||||||
# drain_x = 0
|
|
||||||
# drain_y = 0.5 * (self.width)
|
|
||||||
source_x = 0.5 * (self.width - self.poly_extend_active_spacing)
|
|
||||||
source_y = 0
|
|
||||||
source_pos = vector(source_x, source_y)
|
|
||||||
self.add_layout_pin_rect_center("S", self.route_layer, source_pos)
|
|
||||||
|
|
||||||
drain_pos = vector(source_x, self.height)
|
|
||||||
self.add_layout_pin_rect_center("D", self.route_layer, drain_pos)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
#
|
#
|
||||||
|
|
||||||
from openram.base import design
|
from openram.base import design
|
||||||
from openram.base import vector
|
from openram.base import vector
|
||||||
from openram import OPTS
|
from openram import OPTS
|
||||||
|
|
@ -27,11 +26,6 @@ class rom_poly_tap(design):
|
||||||
#for layout constants
|
#for layout constants
|
||||||
self.dummy = factory.create(module_type="rom_base_cell")
|
self.dummy = factory.create(module_type="rom_base_cell")
|
||||||
|
|
||||||
# if self.tx_type == "nmos":
|
|
||||||
# self.dummy = factory.create(module_type="rom_base_cell")
|
|
||||||
# else:
|
|
||||||
# self.dummy = factory.create(module_type="rom_precharge_cell")
|
|
||||||
|
|
||||||
self.pmos = factory.create(module_type="ptx", tx_type="pmos")
|
self.pmos = factory.create(module_type="ptx", tx_type="pmos")
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
|
|
@ -42,11 +36,6 @@ class rom_poly_tap(design):
|
||||||
self.place_active_tap()
|
self.place_active_tap()
|
||||||
self.extend_poly()
|
self.extend_poly()
|
||||||
|
|
||||||
|
|
||||||
# if self.length != 0:
|
|
||||||
# self.place_strap()
|
|
||||||
|
|
||||||
|
|
||||||
def add_boundary(self):
|
def add_boundary(self):
|
||||||
contact_width = self.poly_contact.width
|
contact_width = self.poly_contact.width
|
||||||
|
|
||||||
|
|
@ -86,15 +75,6 @@ class rom_poly_tap(design):
|
||||||
offset=self.contact_offset)
|
offset=self.contact_offset)
|
||||||
self.add_layout_pin_rect_center("poly_tap", self.strap_layer, self.contact_offset)
|
self.add_layout_pin_rect_center("poly_tap", self.strap_layer, self.contact_offset)
|
||||||
|
|
||||||
|
|
||||||
# def place_strap(self):
|
|
||||||
|
|
||||||
# strap_start = vector(self.via.lx() , self.via.cy())
|
|
||||||
|
|
||||||
# strap_end = vector( self.dummy.width * (self.length + 1), self.via.cy())
|
|
||||||
|
|
||||||
# self.strap = self.add_path(self.strap_layer, (strap_start, strap_end))
|
|
||||||
|
|
||||||
def extend_poly(self):
|
def extend_poly(self):
|
||||||
y_offset = 0
|
y_offset = 0
|
||||||
if self.tx_type == "pmos":
|
if self.tx_type == "pmos":
|
||||||
|
|
@ -104,8 +84,6 @@ class rom_poly_tap(design):
|
||||||
self.add_segment_center("poly", start, vector(self.via.cx() + self.pitch_offset, self.via.cy() + y_offset))
|
self.add_segment_center("poly", start, vector(self.via.cx() + self.pitch_offset, self.via.cy() + y_offset))
|
||||||
self.add_segment_center("poly", start, vector(0, self.via.cy() + y_offset))
|
self.add_segment_center("poly", start, vector(0, self.via.cy() + y_offset))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def place_active_tap(self):
|
def place_active_tap(self):
|
||||||
gap = self.poly_extend_active - 0.5 * ( self.active_contact.height - self.poly_contact.width )
|
gap = self.poly_extend_active - 0.5 * ( self.active_contact.height - self.poly_contact.width )
|
||||||
offset = self.active_space - gap
|
offset = self.active_space - gap
|
||||||
|
|
@ -114,7 +92,6 @@ class rom_poly_tap(design):
|
||||||
tap_y = self.via.cy() + self.dummy.width * 0.5
|
tap_y = self.via.cy() + self.dummy.width * 0.5
|
||||||
contact_pos = vector(tap_x, tap_y)
|
contact_pos = vector(tap_x, tap_y)
|
||||||
|
|
||||||
|
|
||||||
# edge of the next nmos
|
# edge of the next nmos
|
||||||
active_edge = self.dummy.width - self.dummy.cell_inst.height - self.poly_extend_active
|
active_edge = self.dummy.width - self.dummy.cell_inst.height - self.poly_extend_active
|
||||||
|
|
||||||
|
|
@ -123,7 +100,6 @@ class rom_poly_tap(design):
|
||||||
self.pitch_offset += (self.active_space * 2) - (tap_edge - active_edge) + self.contact_x_offset
|
self.pitch_offset += (self.active_space * 2) - (tap_edge - active_edge) + self.contact_x_offset
|
||||||
|
|
||||||
if self.tx_type == "nmos":
|
if self.tx_type == "nmos":
|
||||||
|
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.add_via_center(layers=self.active_stack,
|
||||||
offset=contact_pos,
|
offset=contact_pos,
|
||||||
implant_type="p",
|
implant_type="p",
|
||||||
|
|
@ -133,5 +109,3 @@ class rom_poly_tap(design):
|
||||||
loc=contact_pos,
|
loc=contact_pos,
|
||||||
start_layer=self.active_stack[2])
|
start_layer=self.active_stack[2])
|
||||||
self.add_layout_pin_rect_center("active_tap", self.supply_stack[0], contact_pos)
|
self.add_layout_pin_rect_center("active_tap", self.supply_stack[0], contact_pos)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -13,8 +13,6 @@ from openram.sram_factory import factory
|
||||||
from openram.base import vector
|
from openram.base import vector
|
||||||
from openram.tech import layer, drc
|
from openram.tech import layer, drc
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class rom_precharge_array(design):
|
class rom_precharge_array(design):
|
||||||
"""
|
"""
|
||||||
An array of inverters to create the inverted address lines for the rom decoder
|
An array of inverters to create the inverted address lines for the rom decoder
|
||||||
|
|
@ -55,8 +53,6 @@ class rom_precharge_array(design):
|
||||||
self.add_pins()
|
self.add_pins()
|
||||||
self.create_instances()
|
self.create_instances()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
self.width = self.cols * self.pmos.width
|
self.width = self.cols * self.pmos.width
|
||||||
self.height = self.pmos.width
|
self.height = self.pmos.width
|
||||||
|
|
@ -68,7 +64,6 @@ class rom_precharge_array(design):
|
||||||
self.add_boundary()
|
self.add_boundary()
|
||||||
self.extend_well()
|
self.extend_well()
|
||||||
|
|
||||||
|
|
||||||
def add_boundary(self):
|
def add_boundary(self):
|
||||||
# self.translate_all(self.well_ll)
|
# self.translate_all(self.well_ll)
|
||||||
ur = self.find_highest_coords()
|
ur = self.find_highest_coords()
|
||||||
|
|
@ -93,7 +88,6 @@ class rom_precharge_array(design):
|
||||||
self.add_pin("gate", "INPUT")
|
self.add_pin("gate", "INPUT")
|
||||||
self.add_pin("vdd", "POWER")
|
self.add_pin("vdd", "POWER")
|
||||||
|
|
||||||
|
|
||||||
def create_instances(self):
|
def create_instances(self):
|
||||||
self.array_insts = []
|
self.array_insts = []
|
||||||
self.pmos_insts = []
|
self.pmos_insts = []
|
||||||
|
|
@ -106,8 +100,6 @@ class rom_precharge_array(design):
|
||||||
self.create_poly_tap(col)
|
self.create_poly_tap(col)
|
||||||
self.create_precharge_tx(col)
|
self.create_precharge_tx(col)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_precharge_tx(self, col):
|
def create_precharge_tx(self, col):
|
||||||
name = "pmos_c{0}".format(col)
|
name = "pmos_c{0}".format(col)
|
||||||
pmos = self.add_inst(name=name, mod=self.pmos)
|
pmos = self.add_inst(name=name, mod=self.pmos)
|
||||||
|
|
@ -141,20 +133,12 @@ class rom_precharge_array(design):
|
||||||
if self.tap_direction == "col":
|
if self.tap_direction == "col":
|
||||||
cell_x += self.poly_tap.pitch_offset
|
cell_x += self.poly_tap.pitch_offset
|
||||||
|
|
||||||
|
|
||||||
# if col % self.strap_spacing == 0 :
|
|
||||||
# self.tap_insts[strap_num].place(vector(cell_x, cell_y))
|
|
||||||
# self.add_label("debug", "li", vector(cell_x, cell_y))
|
|
||||||
# cell_x += self.poly_tap.width
|
|
||||||
|
|
||||||
self.pmos_insts[col].place(vector(cell_x, cell_y))
|
self.pmos_insts[col].place(vector(cell_x, cell_y))
|
||||||
self.add_label("debug", "li", vector(cell_x, cell_y))
|
self.add_label("debug", "li", vector(cell_x, cell_y))
|
||||||
cell_x += self.pmos.width
|
cell_x += self.pmos.width
|
||||||
print(self.tap_insts)
|
|
||||||
|
|
||||||
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
self.tap_insts[strap_num].place(vector(cell_x, cell_y + self.poly_tap.height))
|
||||||
|
|
||||||
|
|
||||||
def create_layout_pins(self):
|
def create_layout_pins(self):
|
||||||
self.copy_layout_pin(self.tap_insts[0], "poly_tap", "gate")
|
self.copy_layout_pin(self.tap_insts[0], "poly_tap", "gate")
|
||||||
self.copy_layout_pin(self.tap_insts[-1], "poly_tap", "precharge_r")
|
self.copy_layout_pin(self.tap_insts[-1], "poly_tap", "precharge_r")
|
||||||
|
|
@ -163,16 +147,12 @@ class rom_precharge_array(design):
|
||||||
bl = "pre_bl{0}_out".format(col)
|
bl = "pre_bl{0}_out".format(col)
|
||||||
self.add_layout_pin_rect_center(bl, self.route_layer, source_pin.center())
|
self.add_layout_pin_rect_center(bl, self.route_layer, source_pin.center())
|
||||||
|
|
||||||
|
|
||||||
def route_supply(self):
|
def route_supply(self):
|
||||||
|
|
||||||
# self.vdd = self.add_layout_pin_segment_center("vdd", self.supply_layer, start, end)
|
# self.vdd = self.add_layout_pin_segment_center("vdd", self.supply_layer, start, end)
|
||||||
# vdd = [self.pmos_insts[i].get_pin("vdd") for i in range(self.cols)]routeroute_horizon_horizon
|
# vdd = [self.pmos_insts[i].get_pin("vdd") for i in range(self.cols)]routeroute_horizon_horizon
|
||||||
self.route_horizontal_pins("vdd", insts=self.pmos_insts, layer=self.strap_layer)
|
self.route_horizontal_pins("vdd", insts=self.pmos_insts, layer=self.strap_layer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def connect_taps(self):
|
def connect_taps(self):
|
||||||
array_pins = [self.tap_insts[i].get_pin("poly_tap") for i in range(len(self.tap_insts))]
|
array_pins = [self.tap_insts[i].get_pin("poly_tap") for i in range(len(self.tap_insts))]
|
||||||
|
|
||||||
|
|
@ -183,12 +163,8 @@ class rom_precharge_array(design):
|
||||||
start = vector(tap_pin.cx(), tap_pin.by())
|
start = vector(tap_pin.cx(), tap_pin.by())
|
||||||
end = vector(start.x, tap.mod.get_pin("poly_tap").cy())
|
end = vector(start.x, tap.mod.get_pin("poly_tap").cy())
|
||||||
self.add_segment_center(layer="poly", start=start, end=end)
|
self.add_segment_center(layer="poly", start=start, end=end)
|
||||||
print(end)
|
|
||||||
offset_start = vector(end.x - self.poly_tap.width + self.poly_extend_active, end.y)
|
offset_start = vector(end.x - self.poly_tap.width + self.poly_extend_active, end.y)
|
||||||
offset_end = end + vector(0.5*self.poly_width, 0)
|
offset_end = end + vector(0.5*self.poly_width, 0)
|
||||||
print(self.poly_tap.width)
|
|
||||||
print(end)
|
|
||||||
print(offset_start)
|
|
||||||
self.add_segment_center(layer="poly", start=offset_start, end=offset_end)
|
self.add_segment_center(layer="poly", start=offset_start, end=offset_end)
|
||||||
|
|
||||||
def extend_well(self):
|
def extend_well(self):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -13,23 +13,18 @@ from openram import OPTS
|
||||||
from openram.sram_factory import factory
|
from openram.sram_factory import factory
|
||||||
from openram.tech import drc
|
from openram.tech import drc
|
||||||
|
|
||||||
|
|
||||||
class rom_precharge_cell(rom_base_cell):
|
class rom_precharge_cell(rom_base_cell):
|
||||||
|
|
||||||
def __init__(self, name="", route_layer="m1", supply_layer="li"):
|
def __init__(self, name="", route_layer="m1", supply_layer="li"):
|
||||||
self.supply_layer = supply_layer
|
self.supply_layer = supply_layer
|
||||||
super().__init__(name=name, bitline_layer=route_layer)
|
super().__init__(name=name, bitline_layer=route_layer)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_layout(self):
|
def create_layout(self):
|
||||||
super().create_layout()
|
super().create_layout()
|
||||||
|
|
||||||
self.place_tap()
|
self.place_tap()
|
||||||
self.extend_well()
|
self.extend_well()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def add_modules(self):
|
def add_modules(self):
|
||||||
width = pgate.nearest_bin("pmos", drc["minwidth_tx"])
|
width = pgate.nearest_bin("pmos", drc["minwidth_tx"])
|
||||||
self.pmos = factory.create(module_type="ptx",
|
self.pmos = factory.create(module_type="ptx",
|
||||||
|
|
@ -46,7 +41,6 @@ class rom_precharge_cell(rom_base_cell):
|
||||||
)
|
)
|
||||||
self.connect_inst(["bitline", "gate", "vdd", "vdd"])
|
self.connect_inst(["bitline", "gate", "vdd", "vdd"])
|
||||||
|
|
||||||
|
|
||||||
def add_pins(self):
|
def add_pins(self):
|
||||||
pin_list = ["vdd", "gate", "bitline"]
|
pin_list = ["vdd", "gate", "bitline"]
|
||||||
dir_list = ["POWER", "INPUT", "OUTPUT"]
|
dir_list = ["POWER", "INPUT", "OUTPUT"]
|
||||||
|
|
@ -66,7 +60,6 @@ class rom_precharge_cell(rom_base_cell):
|
||||||
#so that the poly taps are far enough apart
|
#so that the poly taps are far enough apart
|
||||||
self.poly_tap_offset = (self.base_width - self.poly_contact.width - self.poly_active_offset) - drc("poly_to_poly")
|
self.poly_tap_offset = (self.base_width - self.poly_contact.width - self.poly_active_offset) - drc("poly_to_poly")
|
||||||
|
|
||||||
|
|
||||||
def extend_well(self):
|
def extend_well(self):
|
||||||
|
|
||||||
well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width
|
well_y = self.get_pin("vdd").cy() - 0.5 * self.nwell_width
|
||||||
|
|
@ -75,7 +68,6 @@ class rom_precharge_cell(rom_base_cell):
|
||||||
height = self.get_pin("D").cy() + 0.5 * self.nwell_width - well_y
|
height = self.get_pin("D").cy() + 0.5 * self.nwell_width - well_y
|
||||||
self.add_rect("nwell", well_ll, self.width , height)
|
self.add_rect("nwell", well_ll, self.width , height)
|
||||||
|
|
||||||
|
|
||||||
def place_tap(self):
|
def place_tap(self):
|
||||||
source = self.cell_inst.get_pin("S")
|
source = self.cell_inst.get_pin("S")
|
||||||
|
|
||||||
|
|
@ -99,5 +91,6 @@ class rom_precharge_cell(rom_base_cell):
|
||||||
self.add_path(self.supply_layer, [self.get_pin("vdd").center(), pos, self.get_pin("S").center()])
|
self.add_path(self.supply_layer, [self.get_pin("vdd").center(), pos, self.get_pin("S").center()])
|
||||||
|
|
||||||
self.remove_layout_pin("S")
|
self.remove_layout_pin("S")
|
||||||
|
|
||||||
def place_bitline(self):
|
def place_bitline(self):
|
||||||
pass
|
pass
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -13,7 +13,6 @@ from openram.tech import layer
|
||||||
from openram.tech import layer_properties as layer_props
|
from openram.tech import layer_properties as layer_props
|
||||||
from openram import OPTS
|
from openram import OPTS
|
||||||
|
|
||||||
|
|
||||||
class rom_wordline_driver_array(design):
|
class rom_wordline_driver_array(design):
|
||||||
"""
|
"""
|
||||||
Creates a Wordline Buffer/Inverter array
|
Creates a Wordline Buffer/Inverter array
|
||||||
|
|
@ -82,7 +81,6 @@ class rom_wordline_driver_array(design):
|
||||||
height=b.height,
|
height=b.height,
|
||||||
add_wells=False)
|
add_wells=False)
|
||||||
|
|
||||||
|
|
||||||
def route_supplies(self):
|
def route_supplies(self):
|
||||||
"""
|
"""
|
||||||
Add a pin for each row of vdd/gnd which
|
Add a pin for each row of vdd/gnd which
|
||||||
|
|
@ -117,7 +115,6 @@ class rom_wordline_driver_array(design):
|
||||||
self.wld_inst[row].place(offset=offset)
|
self.wld_inst[row].place(offset=offset)
|
||||||
y_offset += self.wld_inst[row].height
|
y_offset += self.wld_inst[row].height
|
||||||
|
|
||||||
|
|
||||||
self.width = self.wl_driver.width
|
self.width = self.wl_driver.width
|
||||||
self.height = self.wl_driver.height * self.rows
|
self.height = self.wl_driver.height * self.rows
|
||||||
|
|
||||||
|
|
@ -143,7 +140,6 @@ class rom_wordline_driver_array(design):
|
||||||
else:
|
else:
|
||||||
wl_offset = out_pin.rc() - vector( 0.5 * route_width, 0)
|
wl_offset = out_pin.rc() - vector( 0.5 * route_width, 0)
|
||||||
|
|
||||||
|
|
||||||
end = vector(wl_offset.x, \
|
end = vector(wl_offset.x, \
|
||||||
self.get_pin("in_{}".format(row)).cy() + 0.5 * route_width)
|
self.get_pin("in_{}".format(row)).cy() + 0.5 * route_width)
|
||||||
self.add_segment_center(layer=self.route_layer,
|
self.add_segment_center(layer=self.route_layer,
|
||||||
|
|
@ -156,7 +152,6 @@ class rom_wordline_driver_array(design):
|
||||||
|
|
||||||
self.add_layout_pin_rect_center(text="out_{}".format(row), layer=self.route_layer, offset=end - vector(0, 0.5 * route_width))
|
self.add_layout_pin_rect_center(text="out_{}".format(row), layer=self.route_layer, offset=end - vector(0, 0.5 * route_width))
|
||||||
|
|
||||||
|
|
||||||
def place_taps(self):
|
def place_taps(self):
|
||||||
|
|
||||||
for wl in range(0 , self.rows, self.tap_spacing):
|
for wl in range(0 , self.rows, self.tap_spacing):
|
||||||
|
|
@ -182,7 +177,6 @@ class rom_wordline_driver_array(design):
|
||||||
contact_pos = vector( gnd_pin2.cx(), left_edge)
|
contact_pos = vector( gnd_pin2.cx(), left_edge)
|
||||||
self.place_tap(contact_pos, "p")
|
self.place_tap(contact_pos, "p")
|
||||||
|
|
||||||
|
|
||||||
def place_tap(self, offset, well_type):
|
def place_tap(self, offset, well_type):
|
||||||
self.add_via_center(layers=self.active_stack,
|
self.add_via_center(layers=self.active_stack,
|
||||||
offset=offset,
|
offset=offset,
|
||||||
|
|
@ -197,4 +191,3 @@ class rom_wordline_driver_array(design):
|
||||||
else:
|
else:
|
||||||
pin = "vdd"
|
pin = "vdd"
|
||||||
self.add_layout_pin_rect_center(text=pin, layer=self.supply_layer, offset=offset)
|
self.add_layout_pin_rect_center(text=pin, layer=self.supply_layer, offset=offset)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -24,11 +24,9 @@ class rom_bank_test(openram_test):
|
||||||
debug.info(1, "Testing 1kB rom cell")
|
debug.info(1, "Testing 1kB rom cell")
|
||||||
|
|
||||||
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_1kB", word_size=1)
|
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_1kB", word_size=1)
|
||||||
print('wriitng file')
|
|
||||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
|
|
||||||
# run the test from the command line
|
# run the test from the command line
|
||||||
|
|
|
||||||
|
|
@ -24,11 +24,9 @@ class rom_bank_test(openram_test):
|
||||||
debug.info(1, "Testing 2kB rom cell")
|
debug.info(1, "Testing 2kB rom cell")
|
||||||
|
|
||||||
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_2kB", word_size=1)
|
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_2kB", word_size=1)
|
||||||
print('wriitng file')
|
|
||||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
|
|
||||||
# run the test from the command line
|
# run the test from the command line
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -24,11 +24,9 @@ class rom_bank_test(openram_test):
|
||||||
debug.info(1, "Testing 4kB rom cell")
|
debug.info(1, "Testing 4kB rom cell")
|
||||||
|
|
||||||
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_4kB", word_size=2)
|
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_4kB", word_size=2)
|
||||||
print('wriitng file')
|
|
||||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
|
|
||||||
# run the test from the command line
|
# run the test from the command line
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -24,7 +24,6 @@ class rom_bank_test(openram_test):
|
||||||
debug.info(1, "Testing 8kB rom cell")
|
debug.info(1, "Testing 8kB rom cell")
|
||||||
|
|
||||||
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_8kB", word_size=2)
|
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_8kB", word_size=2)
|
||||||
print('wriitng file')
|
|
||||||
a.sp_write(OPTS.openram_temp + 'simulation_file_8kB.sp')
|
a.sp_write(OPTS.openram_temp + 'simulation_file_8kB.sp')
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
@ -26,7 +26,6 @@ class rom_bank_test(openram_test):
|
||||||
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_64B", word_size=1)
|
a = factory.create(module_type="rom_base_bank", strap_spacing = 8, data_file="/openram/technology/rom_data_64B", word_size=1)
|
||||||
|
|
||||||
self.local_check(a)
|
self.local_check(a)
|
||||||
print('wriitng file')
|
|
||||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||||
openram.end_openram()
|
openram.end_openram()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2021 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# See LICENSE for licensing information.
|
# See LICENSE for licensing information.
|
||||||
#
|
#
|
||||||
# Copyright (c) 2016-2022 Regents of the University of California and The Board
|
# Copyright (c) 2016-2023 Regents of the University of California and The Board
|
||||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||||
# (acting for and on behalf of Oklahoma State University)
|
# (acting for and on behalf of Oklahoma State University)
|
||||||
# All rights reserved.
|
# All rights reserved.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue