mirror of https://github.com/VLSIDA/OpenRAM.git
Changes for test generation and simulation
This commit is contained in:
parent
89c7d50bd1
commit
bbf2cd2913
|
|
@ -787,13 +787,15 @@ class layout():
|
|||
end=bot_pos)
|
||||
|
||||
|
||||
def connect_col_pins(self, layer, pins, name=None, full=False):
|
||||
def connect_col_pins(self, layer, pins, name=None, full=False, round=False, directions="pref"):
|
||||
"""
|
||||
Connects top/bot columns that are aligned.
|
||||
"""
|
||||
bins = {}
|
||||
for pin in pins:
|
||||
x = pin.cx()
|
||||
if round:
|
||||
x = round_to_grid(x)
|
||||
try:
|
||||
bins[x].append(pin)
|
||||
except KeyError:
|
||||
|
|
@ -819,7 +821,8 @@ class layout():
|
|||
self.add_via_stack_center(from_layer=pin.layer,
|
||||
to_layer=layer,
|
||||
offset=pin.center(),
|
||||
min_area=True)
|
||||
min_area=True,
|
||||
directions=directions)
|
||||
|
||||
if name:
|
||||
self.add_layout_pin_segment_center(text=name,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class pinv_dec(pinv):
|
|||
Other stuff is the same (netlist, sizes, etc.)
|
||||
"""
|
||||
|
||||
def __init__(self, name, size=1, beta=parameter["beta"], height=None, add_wells=True):
|
||||
def __init__(self, name, size=1, beta=parameter["beta"], height=None, add_wells=True, flip_io=False):
|
||||
|
||||
debug.info(2,
|
||||
"creating pinv_dec structure {0} with size of {1}".format(name,
|
||||
|
|
@ -37,7 +37,7 @@ class pinv_dec(pinv):
|
|||
self.supply_layer = "m1"
|
||||
else:
|
||||
self.supply_layer = "m2"
|
||||
|
||||
self.flip_io=flip_io
|
||||
super().__init__(name, size, beta, self.cell_height, add_wells)
|
||||
|
||||
def determine_tx_mults(self):
|
||||
|
|
@ -76,9 +76,14 @@ class pinv_dec(pinv):
|
|||
pmos_gate_pos = pmos_gate_pin.lc()
|
||||
self.add_path("poly", [nmos_gate_pos, pmos_gate_pos])
|
||||
|
||||
|
||||
# Center is completely symmetric.
|
||||
contact_width = self.poly_contact.width
|
||||
contact_offset = nmos_gate_pin.lc() \
|
||||
if self.flip_io:
|
||||
contact_offset = pmos_gate_pin.rc() \
|
||||
+ vector(self.poly_extend_active + 0.6 * contact_width, 0)
|
||||
else:
|
||||
contact_offset = nmos_gate_pin.lc() \
|
||||
- vector(self.poly_extend_active + 0.5 * contact_width, 0)
|
||||
via = self.add_via_stack_center(from_layer="poly",
|
||||
to_layer=self.route_layer,
|
||||
|
|
@ -107,8 +112,11 @@ class pinv_dec(pinv):
|
|||
height=self.height - ll.y + 0.5 * self.pwell_contact.height + self.well_enclose_active)
|
||||
|
||||
if "nwell" in layer:
|
||||
ll = (self.pmos_inst.ll() - vector(2 * [self.well_enclose_active])).scale(1, 0)
|
||||
ur = self.pmos_inst.ur() + vector(2 * [self.well_enclose_active])
|
||||
poly_offset = 0
|
||||
if self.flip_io:
|
||||
poly_offset = 1.2 * self.poly_contact.width
|
||||
ll = (self.pmos_inst.ll() - vector(2 * [self.well_enclose_active])).scale(1, 0) - vector(0, poly_offset)
|
||||
ur = self.pmos_inst.ur() + vector(2 * [self.well_enclose_active + poly_offset])
|
||||
self.add_rect(layer="nwell",
|
||||
offset=ll,
|
||||
width=ur.x - ll.x,
|
||||
|
|
|
|||
|
|
@ -1,39 +0,0 @@
|
|||
|
||||
|
||||
from openram.base import design
|
||||
from openram.base import vector
|
||||
from openram.sram_factory import factory
|
||||
|
||||
class rom_array_gnd_tap(design):
|
||||
|
||||
def __init__(self, name, length, cell_name=None, prop=None):
|
||||
super().__init__(name, cell_name, prop)
|
||||
self.length = length
|
||||
self.create_layout()
|
||||
|
||||
def create_layout(self):
|
||||
|
||||
self.add_cell()
|
||||
self.add_boundary()
|
||||
self.place_gnd_rail()
|
||||
|
||||
|
||||
def add_boundary(self):
|
||||
self.height = self.dummy.height
|
||||
self.width = self.dummy.width
|
||||
super().add_boundary()
|
||||
|
||||
def add_cell(self):
|
||||
self.dummy = factory.create(module_type="rom_dummy_cell")
|
||||
|
||||
def place_gnd_rail(self):
|
||||
rail_start = vector(-self.dummy.width / 2 ,0)
|
||||
rail_end = vector(self.dummy.width * self.length, 0)
|
||||
|
||||
self.add_layout_pin_rect_ends( name="gnd",
|
||||
layer="m1",
|
||||
start=rail_start,
|
||||
end=rail_end)
|
||||
|
||||
|
||||
|
||||
|
|
@ -58,16 +58,17 @@ class rom_base_array(bitcell_base_array):
|
|||
self.place_precharge()
|
||||
self.place_wordline_contacts()
|
||||
self.place_bitline_contacts()
|
||||
self.add_boundary()
|
||||
self.route_precharge()
|
||||
self.add_boundary()
|
||||
|
||||
self.place_rails()
|
||||
self.connect_taps()
|
||||
|
||||
|
||||
|
||||
|
||||
def add_boundary(self):
|
||||
ll = self.find_lowest_coords()
|
||||
bottom_offset = - self.zero_cell.nmos.end_to_contact + self.precharge_inst.offset.y
|
||||
m1_offset = self.m1_width
|
||||
self.translate_all(vector(0, ll.y + 0.5 * m1_offset))
|
||||
ur = self.find_highest_coords()
|
||||
|
|
@ -209,7 +210,7 @@ class rom_base_array(bitcell_base_array):
|
|||
|
||||
prechrg_pins.append("precharge")
|
||||
prechrg_pins.append("vdd")
|
||||
self.precharge_inst = self.add_inst(name="decode_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)
|
||||
|
||||
|
||||
|
|
@ -390,6 +391,9 @@ class rom_base_array(bitcell_base_array):
|
|||
|
||||
self.add_path(layer="m1", coordinates=[start, mid1, mid2, end])
|
||||
|
||||
self.add_layout_pin_rect_center(text="precharge_r", layer="m1", offset=mid1)
|
||||
|
||||
|
||||
|
||||
def connect_taps(self):
|
||||
array_pins = [self.tap_list[i].get_pin("poly_tap") for i in range(len(self.tap_list))]
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ class rom_base_bank(design):
|
|||
def __init__(self, strap_spacing=0, data_file=None, name="", word_size=2):
|
||||
super().__init__(name=name)
|
||||
self.word_size = word_size * 8
|
||||
self.read_binary(word_size=word_size, data_file=data_file)
|
||||
self.read_binary(word_size=word_size, data_file=data_file, scramble_bits=True, endian="little")
|
||||
|
||||
self.num_outputs = self.rows
|
||||
self.num_inputs = ceil(log(self.rows, 2))
|
||||
|
|
@ -48,7 +48,7 @@ class rom_base_bank(design):
|
|||
sets the row and column size based on the size of binary input, tries to keep array as square as possible,
|
||||
"""
|
||||
|
||||
def read_binary(self, data_file, word_size=2, endian="big"):
|
||||
def read_binary(self, data_file, word_size=2, endian="big", scramble_bits=False):
|
||||
# Read data as hexidecimal text file
|
||||
hex_file = open(data_file, 'r')
|
||||
hex_data = hex_file.read()
|
||||
|
|
@ -72,25 +72,56 @@ class rom_base_bank(design):
|
|||
|
||||
bits_per_row = self.words_per_row * word_size * 8
|
||||
|
||||
self.cols = bits_per_row
|
||||
self.rows = int(num_words / (self.words_per_row))
|
||||
chunked_data = []
|
||||
|
||||
for i in range(0, len(bin_data), bits_per_row):
|
||||
word = bin_data[i:i + bits_per_row]
|
||||
if len(word) < bits_per_row:
|
||||
word = [0] * (bits_per_row - len(word)) + word
|
||||
chunked_data.append(word)
|
||||
|
||||
if endian == "big":
|
||||
chunked_data.reverse()
|
||||
|
||||
row_data = bin_data[i:i + bits_per_row]
|
||||
if len(row_data) < bits_per_row:
|
||||
row_data = [0] * (bits_per_row - len(row_data)) + row_data
|
||||
chunked_data.append(row_data)
|
||||
|
||||
|
||||
# if endian == "big":
|
||||
|
||||
|
||||
self.data = chunked_data
|
||||
self.cols = bits_per_row
|
||||
self.rows = int(num_words / (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))
|
||||
if scramble_bits:
|
||||
scrambled_chunked = []
|
||||
|
||||
for row_data in chunked_data:
|
||||
scambled_data = []
|
||||
for bit in range(self.word_size):
|
||||
for word in range(self.words_per_row):
|
||||
scambled_data.append(row_data[bit + word * self.word_size])
|
||||
scrambled_chunked.append(scambled_data)
|
||||
self.data = scrambled_chunked
|
||||
|
||||
|
||||
|
||||
# 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))
|
||||
# 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):
|
||||
self.add_modules()
|
||||
self.add_pins()
|
||||
|
|
@ -147,6 +178,20 @@ class rom_base_bank(design):
|
|||
def add_modules(self):
|
||||
|
||||
print("Creating bank modules")
|
||||
# TODO: provide technology-specific calculation of these parameters
|
||||
# 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
|
||||
addr_control_buffer_effort = 4
|
||||
# a single min sized nmos makes up 1/4 of the input capacitance of a min sized inverter
|
||||
bitcell_effort = 0.25
|
||||
|
||||
# Takes into account inverter sizing
|
||||
wordline_effort = bitcell_effort * 0.5
|
||||
|
||||
# a single min sized pmos plus a single min sized nmos have approximately half the gate capacitance of a min inverter
|
||||
# an additional 0.2 accounts for the long wire capacitance and add delay to gaurentee the read timing
|
||||
precharge_cell_effort = 0.5 + 0.2
|
||||
|
||||
self.array = factory.create(module_type="rom_base_array",
|
||||
cols=self.cols,
|
||||
rows=self.rows,
|
||||
|
|
@ -163,7 +208,7 @@ class rom_base_bank(design):
|
|||
num_outputs=self.rows,
|
||||
strap_spacing=self.strap_spacing,
|
||||
route_layer=self.route_layer,
|
||||
cols=self.cols)
|
||||
fanout=(self.cols)*wordline_effort )
|
||||
|
||||
|
||||
self.column_mux = factory.create(module_type="rom_column_mux_array",
|
||||
|
|
@ -178,18 +223,27 @@ class rom_base_bank(design):
|
|||
num_outputs=self.words_per_row,
|
||||
strap_spacing=self.strap_spacing,
|
||||
route_layer=self.route_layer,
|
||||
cols=1,
|
||||
fanout=2,
|
||||
invert_outputs=True )
|
||||
|
||||
self.control_logic = factory.create(module_type="rom_control_logic",
|
||||
num_outputs=(self.rows + self.cols + self.words_per_row) * 0.5,
|
||||
clk_fanout=(self.col_bits + self.row_bits) * 2,
|
||||
num_outputs=(self.cols + self.words_per_row * precharge_cell_effort) \
|
||||
+ (addr_control_buffer_effort * self.col_bits),
|
||||
clk_fanout=(self.row_bits * addr_control_buffer_effort) + (precharge_cell_effort * self.rows),
|
||||
height=self.column_decode.height )
|
||||
|
||||
self.output_buffer = factory.create(module_type="rom_wordline_driver_array",
|
||||
self.bitline_inv = factory.create(module_type="rom_wordline_driver_array",
|
||||
module_name="rom_bitline_inverter",
|
||||
rows=self.cols,
|
||||
fanout=4,
|
||||
invert_outputs=True,
|
||||
tap_spacing=0,
|
||||
flip_io=True)
|
||||
self.output_inv = factory.create(module_type="rom_wordline_driver_array",
|
||||
module_name="rom_output_buffer",
|
||||
rows=self.word_size,
|
||||
cols=4)
|
||||
fanout=4,
|
||||
invert_outputs=True)
|
||||
|
||||
|
||||
def create_instances(self):
|
||||
|
|
@ -206,18 +260,21 @@ class rom_base_bank(design):
|
|||
|
||||
select_lines = ["word_sel_{}".format(word) for word in range(self.words_per_row)]
|
||||
|
||||
bitline_bar = ["bl_b_{}".format(bl) for bl in range(self.cols)]
|
||||
pre_buf_outputs = ["rom_out_prebuf_{}".format(bit) for bit in range(self.word_size)]
|
||||
outputs = ["rom_out_{}".format(bl) for bl in range(self.word_size)]
|
||||
|
||||
|
||||
array_pins = bitlines + wordlines + prechrg + vdd + gnd
|
||||
|
||||
row_decode_pins = addr_msb + wordlines + prechrg + clk + vdd + gnd
|
||||
col_decode_pins = addr_lsb + select_lines + prechrg + clk + vdd + gnd
|
||||
row_decode_pins = addr_msb + wordlines + clk + clk + vdd + gnd
|
||||
col_decode_pins = addr_lsb + select_lines + prechrg + prechrg + vdd + gnd
|
||||
|
||||
col_mux_pins = bitlines + select_lines + pre_buf_outputs + gnd
|
||||
col_mux_pins = bitline_bar + select_lines + pre_buf_outputs + gnd
|
||||
|
||||
output_buffer_pins = pre_buf_outputs + outputs + vdd + gnd
|
||||
bitline_inv_pins = bitlines + bitline_bar + vdd + gnd
|
||||
|
||||
output_buf_pins = pre_buf_outputs + outputs + vdd + gnd
|
||||
|
||||
self.array_inst = self.add_inst(name="rom_bit_array", mod=self.array)
|
||||
self.connect_inst(array_pins)
|
||||
|
|
@ -234,14 +291,19 @@ class rom_base_bank(design):
|
|||
self.col_decode_inst = self.add_inst(name="rom_column_decoder", mod=self.column_decode)
|
||||
self.connect_inst(col_decode_pins)
|
||||
|
||||
self.output_buf_inst = self.add_inst(name="rom_output_buffer", mod=self.output_buffer)
|
||||
self.connect_inst(output_buffer_pins)
|
||||
self.bitline_inv_inst = self.add_inst(name="rom_bitline_inverter", mod=self.bitline_inv)
|
||||
self.connect_inst(bitline_inv_pins)
|
||||
|
||||
self.output_inv_inst = self.add_inst(name="rom_output_inverter", mod=self.output_inv)
|
||||
self.connect_inst(output_buf_pins)
|
||||
|
||||
|
||||
|
||||
|
||||
def place_instances(self):
|
||||
self.place_row_decoder()
|
||||
self.place_data_array()
|
||||
self.place_bitline_inverter()
|
||||
self.place_col_mux()
|
||||
self.place_col_decoder()
|
||||
self.place_control_logic()
|
||||
|
|
@ -249,7 +311,7 @@ class rom_base_bank(design):
|
|||
|
||||
|
||||
def place_row_decoder(self):
|
||||
self.decode_offset = vector(0, self.control_inst.height - self.decode_array.control_array.height)
|
||||
self.decode_offset = vector(0, self.control_inst.height )
|
||||
self.decode_inst.place(offset=self.decode_offset)
|
||||
|
||||
def place_data_array(self):
|
||||
|
|
@ -263,11 +325,18 @@ class rom_base_bank(design):
|
|||
array_align = self.decode_inst.get_pin("wl_0").cy() - self.array_inst.get_pin("wl_0_0").cy()
|
||||
self.array_inst.place(offset=(self.array_offset + vector(0, array_align)))
|
||||
|
||||
def place_bitline_inverter(self):
|
||||
self.bitline_inv_inst.place(offset=[0,0], rotate=90)
|
||||
inv_y_offset = self.array_inst.by() - self.bitline_inv_inst.width - 2 * self.m1_pitch
|
||||
|
||||
inv_x_offset = self.array_inst.get_pin("bl_0_0").cx() - self.bitline_inv_inst.get_pin("out_0").cx()
|
||||
self.inv_offset = vector(inv_x_offset, inv_y_offset)
|
||||
self.bitline_inv_inst.place(offset=self.inv_offset, rotate=90)
|
||||
|
||||
def place_control_logic(self):
|
||||
|
||||
|
||||
self.control_offset = vector(self.control_inst.width + self.decode_array.control_array.width + 2 * (self.route_layer_pitch + self.route_layer_width), self.col_decode_inst.by() + self.control_logic.height)
|
||||
self.control_inst.place(offset=self.control_offset, mirror="XY")
|
||||
self.control_offset = vector(self.col_decode_inst.lx() - self.control_inst.width - 3 * self.m1_pitch, self.decode_inst.by() - self.control_logic.height - self.m1_pitch)
|
||||
self.control_inst.place(offset=self.control_offset)
|
||||
|
||||
def place_col_decoder(self):
|
||||
col_decode_y = self.mux_inst.get_pin("sel_0").cy() - self.col_decode_inst.get_pin("wl_0").cy()
|
||||
|
|
@ -275,28 +344,18 @@ class rom_base_bank(design):
|
|||
self.col_decode_inst.place(offset=self.col_decode_offset)
|
||||
|
||||
def place_col_mux(self):
|
||||
mux_y_offset = self.array_inst.by() - self.mux_inst.height - 5 * self.route_layer_pitch
|
||||
mux_y_offset = self.bitline_inv_inst.by() - self.mux_inst.height - 5 * self.route_layer_pitch
|
||||
|
||||
mux_x_offset = self.array_inst.get_pin("bl_0_0").cx() - self.mux_inst.get_pin("bl_0").cx()
|
||||
mux_x_offset = self.bitline_inv_inst.get_pin("out_0").cx() - self.mux_inst.get_pin("bl_0").cx()
|
||||
self.mux_offset = vector(mux_x_offset, mux_y_offset)
|
||||
self.mux_inst.place(offset=self.mux_offset)
|
||||
|
||||
def place_output_buffer(self):
|
||||
output_x = self.col_decode_inst.rx() + self.output_buf_inst.height
|
||||
output_y = self.col_decode_inst.by() + self.output_buf_inst.width
|
||||
self.output_buf_offset = vector(output_x, output_y)
|
||||
self.output_buf_inst.place(offset=self.output_buf_offset, rotate=270)
|
||||
output_x = self.col_decode_inst.rx() + self.output_inv_inst.height
|
||||
output_y = self.mux_inst.by() - self.word_size * self.m1_pitch
|
||||
self.output_inv_offset = vector(output_x, output_y)
|
||||
self.output_inv_inst.place(offset=self.output_inv_offset, rotate=270)
|
||||
|
||||
# def create_wl_bus(self):
|
||||
# bus_x = self.decode_inst.width + ( drc["minwidth_{}".format(self.bus_layer)] + 1.5 * drc["{0}_to_{0}".format(self.bus_layer)] )
|
||||
# bus_y = self.array_inst.by() + self.bus_layer_pitch + self.bus_layer_width
|
||||
# self.wl_interconnects = []
|
||||
|
||||
# for wl in range(self.rows):
|
||||
# self.wl_interconnects.append("wl_interconnect_{}".format(wl))
|
||||
|
||||
# self.wl_bus = self.create_vertical_bus(self.bus_layer, vector(bus_x, bus_y), self.wl_interconnects, self.decode_inst.uy() - self.array_inst.by() )
|
||||
|
||||
def route_decode_outputs(self):
|
||||
# for the row decoder
|
||||
route_pins = [self.array_inst.get_pin("wl_0_{}".format(wl)) for wl in range(self.rows)]
|
||||
|
|
@ -325,88 +384,105 @@ class rom_base_bank(design):
|
|||
start = vector(wl_bus_wire.cx(), end.y)
|
||||
|
||||
self.add_segment_center(self.interconnect_layer, start, end)
|
||||
self.add_via_stack_center(start, self.route_layer, self.interconnect_layer )
|
||||
|
||||
|
||||
def route_precharge(self):
|
||||
|
||||
prechrg_control = self.control_inst.get_pin("prechrg")
|
||||
row_decode_prechrg = self.decode_inst.get_pin("precharge")
|
||||
col_decode_prechrg = self.col_decode_inst.get_pin("precharge")
|
||||
|
||||
col_decode_prechrg = self.col_decode_inst.get_pin("precharge_r")
|
||||
col_decode_clk = self.col_decode_inst.get_pin("clk")
|
||||
array_prechrg = self.array_inst.get_pin("precharge")
|
||||
|
||||
|
||||
# Route precharge signal to the row decoder
|
||||
end = vector(row_decode_prechrg.cx() - 0.5 * self.interconnect_layer_width, prechrg_control.cy())
|
||||
# end = vector(row_decode_prechrg.cx() - 0.5 * self.interconnect_layer_width, prechrg_control.cy())
|
||||
|
||||
self.add_segment_center(self.interconnect_layer, prechrg_control.center(), end)
|
||||
# self.add_segment_center(self.interconnect_layer, prechrg_control.center(), end)
|
||||
|
||||
start = end + vector(0.5 * self.interconnect_layer_width, 0)
|
||||
self.add_segment_center(self.interconnect_layer, start, row_decode_prechrg.center())
|
||||
# start = end + vector(0.5 * self.interconnect_layer_width, 0)
|
||||
# self.add_segment_center(self.interconnect_layer, start, row_decode_prechrg.center())
|
||||
|
||||
self.add_via_stack_center(from_layer=self.route_stack[0],
|
||||
to_layer=prechrg_control.layer,
|
||||
offset=prechrg_control.center())
|
||||
|
||||
# Route precharge to col decoder
|
||||
start = row_decode_prechrg.center() - vector(0, self.route_layer_pitch + 2 * self.route_layer_width)
|
||||
mid = vector(col_decode_prechrg.cx(), start.y)
|
||||
end = vector(col_decode_prechrg.cx(), 0.5 * (self.col_decode_inst.uy() + mid.y) )
|
||||
self.add_path(self.route_stack[0], [start, mid, end])
|
||||
start = prechrg_control.center()
|
||||
mid1 = vector(self.control_inst.rx(), prechrg_control.cy())
|
||||
mid2 = vector(self.control_inst.rx(), col_decode_prechrg.cy())
|
||||
end = col_decode_prechrg.center()
|
||||
self.add_path(self.route_stack[0], [start, mid1, mid2, end])
|
||||
|
||||
self.add_via_stack_center(from_layer=self.route_stack[0],
|
||||
to_layer=col_decode_prechrg.layer,
|
||||
offset=end)
|
||||
self.add_segment_center(col_decode_prechrg.layer, end, col_decode_prechrg.center())
|
||||
|
||||
start = mid1
|
||||
mid1 = vector(self.control_inst.rx(), start.y)
|
||||
mid2 = vector(mid1.x, col_decode_clk.cy())
|
||||
end = col_decode_clk.center()
|
||||
self.add_path(self.route_stack[0], [start, mid1, mid2, end])
|
||||
|
||||
# self.add_segment_center(col_decode_prechrg.layer, end, col_decode_prechrg.center())
|
||||
|
||||
# Route precharge to main array
|
||||
end = vector(col_decode_prechrg.cx(), array_prechrg.cy())
|
||||
self.add_segment_center(self.route_stack[0], array_prechrg.center(), end)
|
||||
# end = vector(col_decode_prechrg.cx(), array_prechrg.cy())
|
||||
mid = vector(col_decode_prechrg.cx(), array_prechrg.cy() )
|
||||
self.add_path(self.route_stack[0], [array_prechrg.center(), mid, col_decode_prechrg.center()])
|
||||
|
||||
|
||||
def route_clock(self):
|
||||
clk_out = self.control_inst.get_pin("clk_out")
|
||||
row_decode_clk = self.decode_inst.get_pin("clk")
|
||||
col_decode_clk = self.col_decode_inst.get_pin("clk")
|
||||
|
||||
self.add_via_stack_center(from_layer=self.route_stack[2],
|
||||
to_layer=clk_out.layer,
|
||||
offset=clk_out.center())
|
||||
|
||||
# Route clock to row decoder
|
||||
end = row_decode_clk.rc() + vector( 2 * self.route_layer_pitch + self.route_layer_width, 0)
|
||||
self.add_path(self.route_stack[2], [clk_out.center(), end])
|
||||
mid = vector(self.control_inst.rx() + self.m1_pitch, clk_out.cy())
|
||||
|
||||
addr_control_clk = row_decode_clk.rc() + vector( 2 * self.route_layer_pitch + self.route_layer_width, 0)
|
||||
row_decode_prechrg = self.decode_inst.get_pin("precharge")
|
||||
|
||||
self.add_path(self.route_stack[2], [clk_out.center(), mid, addr_control_clk, row_decode_prechrg.center()])
|
||||
|
||||
self.add_via_stack_center(from_layer=self.route_stack[2],
|
||||
to_layer=row_decode_clk.layer,
|
||||
offset=end)
|
||||
offset=addr_control_clk)
|
||||
|
||||
self.add_segment_center(row_decode_clk.layer, end, row_decode_clk.rc())
|
||||
self.add_segment_center(row_decode_clk.layer, addr_control_clk, row_decode_clk.rc())
|
||||
|
||||
# Route clock to column decoder
|
||||
end = col_decode_clk.lc() - vector( 2 * self.route_layer_pitch + self.route_layer_width, 0)
|
||||
self.add_path(self.route_stack[2], [clk_out.center(), end])
|
||||
# end = col_decode_clk.lc() - vector( 2 * self.route_layer_pitch + self.route_layer_width, 0)
|
||||
# self.add_path(self.route_stack[2], [clk_out.center(), end])
|
||||
|
||||
self.add_via_stack_center(from_layer=self.route_stack[2],
|
||||
to_layer=row_decode_clk.layer,
|
||||
offset=end)
|
||||
# self.add_via_stack_center(from_layer=self.route_stack[2],
|
||||
# to_layer=row_decode_clk.layer,
|
||||
# offset=end)
|
||||
|
||||
self.add_segment_center(col_decode_clk.layer, end, col_decode_clk.lc())
|
||||
# self.add_segment_center(col_decode_clk.layer, end, col_decode_clk.lc())
|
||||
|
||||
|
||||
|
||||
|
||||
def route_array_outputs(self):
|
||||
for i in range(self.cols):
|
||||
bl_out = self.array_inst.get_pin("bl_0_{}".format(i)).center()
|
||||
array_out_pins = [self.array_inst.get_pin("bl_0_{}".format(bl)) for bl in range(self.cols)]
|
||||
inv_in_pins = [self.bitline_inv_inst.get_pin("in_{}".format(bl)) for bl in range(self.cols)]
|
||||
inv_out_pins = [self.bitline_inv_inst.get_pin("out_{}".format(bl)) for bl in range(self.cols)]
|
||||
mux_pins = [self.mux_inst.get_pin("bl_{}".format(bl)) for bl in range(self.cols)]
|
||||
|
||||
self.connect_col_pins(self.interconnect_layer, array_out_pins + inv_in_pins, round=True, directions="nonpref")
|
||||
self.connect_col_pins(self.interconnect_layer, inv_out_pins + mux_pins, round=True, directions="nonpref")
|
||||
|
||||
|
||||
bl_mux = self.mux_inst.get_pin("bl_{}".format(i)).center()
|
||||
|
||||
self.add_path(self.array.bitline_layer, [bl_out, bl_mux])
|
||||
|
||||
|
||||
def route_output_buffers(self):
|
||||
mux = self.mux_inst
|
||||
buf = self.output_buf_inst
|
||||
buf = self.output_inv_inst
|
||||
route_nets = [ [mux.get_pin("bl_out_{}".format(bit)), buf.get_pin("in_{}".format(bit))] for bit in range(self.word_size)]
|
||||
|
||||
channel_ll = vector( route_nets[0][0].cx(), route_nets[0][1].cy() + self.m1_pitch * 3)
|
||||
|
|
@ -429,7 +505,7 @@ class rom_base_bank(design):
|
|||
self.copy_layout_pin(self.control_inst, "clk_in", "clk")
|
||||
|
||||
for i in range(self.word_size):
|
||||
self.copy_layout_pin(self.output_buf_inst, "out_{}".format(i), "rom_out_{}".format(i))
|
||||
self.copy_layout_pin(self.output_inv_inst, "out_{}".format(i), "rom_out_{}".format(i))
|
||||
for lsb in range(self.col_bits):
|
||||
name = "addr_{}".format(lsb)
|
||||
self.copy_layout_pin(self.col_decode_inst, "A{}".format(lsb), name)
|
||||
|
|
@ -448,27 +524,7 @@ class rom_base_bank(design):
|
|||
if not inst.mod.name.__contains__("contact"):
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
self.copy_layout_pin(inst, "gnd")
|
||||
# gnd_start = vector(self.array_inst.get_pins("gnd")[0].cx(),0)
|
||||
|
||||
# decode_gnd = self.decode_inst.get_pin("gnd")
|
||||
# decode_vdd = self.decode_inst.get_pin("vdd")
|
||||
# array_vdd = self.array_inst.get_pin("vdd")
|
||||
|
||||
# # self.add_segment_center("m1", gnd_start, decode_gnd.center())
|
||||
|
||||
|
||||
# self.add_power_pin("gnd", decode_vdd.center())
|
||||
# self.add_power_pin("vdd", decode_gnd.center())
|
||||
|
||||
# vdd_start = vector(array_vdd.lx() + 0.5 * self.via1_space, array_vdd.cy())
|
||||
# end = vector(decode_vdd.lx(), vdd_start.y)
|
||||
|
||||
# self.add_segment_center(self.interconnect_layer, vdd_start, end)
|
||||
# self.add_via_stack_center(vdd_start, "m1", self.interconnect_layer)
|
||||
|
||||
# vdd_start = vector(decode_vdd.cx(), vdd_start.y)
|
||||
|
||||
# self.add_segment_center(self.interconnect_layer, vdd_start, decode_vdd.center())
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ class rom_control_logic(design):
|
|||
if self.height is not None:
|
||||
|
||||
self.driver_height = 0.5 * self.height
|
||||
self.gate_height = 0.25 * self.height
|
||||
self.gate_height = 0.5 * self.height
|
||||
else:
|
||||
self.gate_height = 20 * self.m1_pitch
|
||||
self.driver_height = self.gate_height
|
||||
|
|
@ -51,16 +51,18 @@ class rom_control_logic(design):
|
|||
self.route_insts()
|
||||
|
||||
def add_modules(self):
|
||||
|
||||
self.buf_mod = factory.create(module_type="pinvbuf",
|
||||
module_name="rom_control_logic_pinv",
|
||||
self.buf_mod = factory.create(module_type="pdriver",
|
||||
module_name="rom_clock_driver",
|
||||
height=self.gate_height,
|
||||
route_in_cell=True )
|
||||
fanout=self.clk_fanout + 2,
|
||||
add_wells=True,
|
||||
)
|
||||
self.nand_mod = factory.create(module_type="pnand2",
|
||||
module_name="rom_control_nand",
|
||||
height=self.gate_height,
|
||||
add_wells=False)
|
||||
self.driver_mod = factory.create(module_type="pdriver",
|
||||
module_name="rom_precharge_driver",
|
||||
inverting=True,
|
||||
fanout=self.output_size,
|
||||
height=self.driver_height,
|
||||
|
|
@ -77,34 +79,36 @@ class rom_control_logic(design):
|
|||
|
||||
def create_instances(self):
|
||||
|
||||
self.buf_inst = self.add_inst(name="clk_invbuf", mod=self.buf_mod)
|
||||
self.connect_inst(["clk_in", "clk_bar", "clk_out", "vdd", "gnd"])
|
||||
self.buf_inst = self.add_inst(name="clk_driver", mod=self.buf_mod)
|
||||
self.connect_inst(["clk_in", "clk_out", "vdd", "gnd"])
|
||||
|
||||
self.nand_inst = self.add_inst(name="control_nand", mod=self.nand_mod)
|
||||
self.connect_inst(["CS", "clk_out", "pre_drive", "vdd", "gnd"])
|
||||
|
||||
self.driver_inst = self.add_inst(name="driver_inst", mod=self.driver_mod)
|
||||
self.driver_inst = self.add_inst(name="precharge_driver", mod=self.driver_mod)
|
||||
self.connect_inst(["pre_drive", "prechrg", "vdd", "gnd"])
|
||||
|
||||
|
||||
def place_instances(self):
|
||||
buf_correction = drc["minwidth_{}".format(self.route_stack[0])] * 0.5
|
||||
# nand_y = self.buf_inst.get_pin("vdd").cy() - self.nand_inst.get_pin("vdd").cy()
|
||||
self.nand_inst.place(offset=[0, self.nand_inst.height + self.buf_mod.inv2.height + buf_correction], mirror="MX")
|
||||
self.driver_inst.place(offset=[0, self.buf_inst.height + buf_correction])
|
||||
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")
|
||||
|
||||
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")
|
||||
|
||||
|
||||
def route_insts(self):
|
||||
|
||||
route_width = drc["minwidth_{}".format(self.route_stack[2])]
|
||||
self.copy_layout_pin(self.buf_inst, "A", "clk_in")
|
||||
self.copy_layout_pin(self.buf_inst, "Zb", "clkb_out")
|
||||
self.copy_layout_pin(self.buf_inst, "Z", "clk_out")
|
||||
self.copy_layout_pin(self.driver_inst, "Z", "prechrg")
|
||||
self.copy_layout_pin(self.nand_inst, "A", "CS")
|
||||
self.copy_layout_pin(self.buf_inst, "gnd")
|
||||
self.copy_layout_pin(self.driver_inst, "vdd")
|
||||
self.copy_layout_pin(self.buf_inst, "vdd")
|
||||
# self.copy_layout_pin(self.buf_inst, "vdd")
|
||||
|
||||
clk = self.buf_inst.get_pin("Z")
|
||||
|
||||
|
|
@ -114,7 +118,7 @@ class rom_control_logic(design):
|
|||
# Connect buffered clock bar to nand input
|
||||
|
||||
mid = vector(clk.lx() - route_width - 2 * self.m1_space)
|
||||
self.add_path(self.route_stack[2], [clk.center(), mid, nand_B.center()])
|
||||
self.add_path(self.route_stack[2], [clk.center(), nand_B.center()])
|
||||
|
||||
self.add_via_stack_center(from_layer=clk.layer,
|
||||
to_layer=self.route_stack[2],
|
||||
|
|
@ -126,15 +130,17 @@ class rom_control_logic(design):
|
|||
|
||||
# Connect nand output to precharge driver
|
||||
nand_Z = self.nand_inst.get_pin("Z")
|
||||
nand_output = vector(nand_Z.cx(), nand_B.cy() + 3 * route_width)
|
||||
|
||||
driver_A = self.driver_inst.get_pin("A")
|
||||
self.add_path(self.route_stack[2], [nand_output, driver_A.center()])
|
||||
|
||||
mid = vector(driver_A.cx(), driver_A.cy() - 4 * route_width)
|
||||
|
||||
self.add_path(self.route_stack[2], [nand_Z.center(), mid, driver_A.center()])
|
||||
|
||||
|
||||
self.add_via_stack_center(from_layer=nand_Z.layer,
|
||||
to_layer=self.route_stack[2],
|
||||
offset=nand_output)
|
||||
offset=nand_Z.center())
|
||||
|
||||
self.add_via_stack_center(from_layer=driver_A.layer,
|
||||
to_layer=self.route_stack[2],
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from openram.tech import drc
|
|||
|
||||
|
||||
class rom_decoder(design):
|
||||
def __init__(self, num_outputs, cols, 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):
|
||||
|
||||
# word lines/ rows / inputs in the base array become the address lines / cols / inputs in the decoder
|
||||
# bit lines / cols / outputs in the base array become the word lines / rows / outputs in the decoder
|
||||
|
|
@ -33,7 +33,7 @@ class rom_decoder(design):
|
|||
self.route_layer = route_layer
|
||||
self.output_layer = output_layer
|
||||
self.inv_route_layer = "m2"
|
||||
self.cols=cols
|
||||
self.fanout=fanout
|
||||
self.invert_outputs=invert_outputs
|
||||
self.create_netlist()
|
||||
|
||||
|
|
@ -57,6 +57,17 @@ class rom_decoder(design):
|
|||
self.connect_inputs()
|
||||
self.route_supplies()
|
||||
self.add_boundary()
|
||||
|
||||
def add_boundary(self):
|
||||
ll = self.find_lowest_coords()
|
||||
m1_offset = self.m1_width
|
||||
self.translate_all(vector(0, ll.y))
|
||||
ur = self.find_highest_coords()
|
||||
|
||||
ur = vector(ur.x, ur.y)
|
||||
super().add_boundary(ll, ur)
|
||||
self.width = ur.x
|
||||
self.height = ur.y
|
||||
|
||||
def setup_layout_constants(self):
|
||||
self.inv_route_width = drc["minwidth_{}".format(self.inv_route_layer)]
|
||||
|
|
@ -114,7 +125,7 @@ class rom_decoder(design):
|
|||
|
||||
self.wordline_buf = factory.create(module_type="rom_wordline_driver_array", module_name="{}_wordline_buffer".format(self.name),
|
||||
rows=self.num_outputs,
|
||||
cols=ceil(self.cols * 0.5),
|
||||
fanout=ceil(self.fanout),
|
||||
invert_outputs=self.invert_outputs,
|
||||
tap_spacing=self.strap_spacing)
|
||||
|
||||
|
|
@ -224,7 +235,7 @@ class rom_decoder(design):
|
|||
def connect_inputs(self):
|
||||
|
||||
self.copy_layout_pin(self.array_inst, "precharge")
|
||||
|
||||
self.copy_layout_pin(self.array_inst, "precharge_r")
|
||||
for i in range(self.num_inputs):
|
||||
wl = (self.num_inputs - i) * 2 - 1
|
||||
wl_bar = wl - 1
|
||||
|
|
|
|||
|
|
@ -19,16 +19,16 @@ class rom_wordline_driver_array(design):
|
|||
Creates a Wordline Buffer/Inverter array
|
||||
"""
|
||||
|
||||
def __init__(self, name, rows, cols, invert_outputs=False, tap_spacing=4):
|
||||
def __init__(self, name, rows, fanout, invert_outputs=False, tap_spacing=4, flip_io=False):
|
||||
design.__init__(self, name)
|
||||
debug.info(1, "Creating {0}".format(self.name))
|
||||
self.add_comment("rows: {0} cols: {1}".format(rows, cols))
|
||||
self.add_comment("rows: {0} Buffer size of: {1}".format(rows, fanout))
|
||||
|
||||
self.rows = rows
|
||||
self.cols = cols
|
||||
self.fanout = fanout
|
||||
self.invert_outputs=invert_outputs
|
||||
self.tap_spacing = tap_spacing
|
||||
|
||||
self.flip_io = flip_io
|
||||
if OPTS.tech_name == "sky130":
|
||||
self.supply_layer = "m1"
|
||||
else:
|
||||
|
|
@ -51,7 +51,8 @@ class rom_wordline_driver_array(design):
|
|||
self.place_drivers()
|
||||
self.route_layout()
|
||||
self.route_supplies()
|
||||
self.place_taps()
|
||||
if self.tap_spacing != 0:
|
||||
self.place_taps()
|
||||
self.add_boundary()
|
||||
|
||||
def add_pins(self):
|
||||
|
|
@ -70,13 +71,14 @@ class rom_wordline_driver_array(design):
|
|||
|
||||
if self.invert_outputs:
|
||||
self.wl_driver = factory.create(module_type="pinv_dec",
|
||||
size=self.cols,
|
||||
size=self.fanout,
|
||||
height=b.height,
|
||||
add_wells=False)
|
||||
add_wells=False,
|
||||
flip_io=self.flip_io)
|
||||
|
||||
else:
|
||||
self.wl_driver = factory.create(module_type="pbuf_dec",
|
||||
size=self.cols,
|
||||
size=self.fanout,
|
||||
height=b.height,
|
||||
add_wells=False)
|
||||
|
||||
|
|
@ -108,7 +110,7 @@ class rom_wordline_driver_array(design):
|
|||
def place_drivers(self):
|
||||
y_offset = 0
|
||||
for row in range(self.rows):
|
||||
if row % self.tap_spacing == 0:
|
||||
if self.tap_spacing != 0 and row % self.tap_spacing == 0:
|
||||
y_offset += self.tap.pitch_offset
|
||||
offset = [0, y_offset]
|
||||
|
||||
|
|
@ -123,20 +125,34 @@ class rom_wordline_driver_array(design):
|
|||
""" Route all of the signals """
|
||||
route_width = drc["minwidth_{}".format(self.route_layer)]
|
||||
for row in range(self.rows):
|
||||
inst = self.wld_inst[row]
|
||||
if self.flip_io:
|
||||
row_num = self.rows - row - 1
|
||||
else:
|
||||
row_num = row
|
||||
inst = self.wld_inst[row_num]
|
||||
self.copy_layout_pin(inst, "vdd")
|
||||
self.copy_layout_pin(inst, "gnd")
|
||||
|
||||
self.copy_layout_pin(inst, "A", "in_{0}".format(row))
|
||||
|
||||
out_pin = inst.get_pin("Z")
|
||||
# output each WL on the right
|
||||
wl_offset = inst.get_pin("Z").rc() - vector( 0.5 * route_width, 0)
|
||||
if self.flip_io:
|
||||
wl_offset = out_pin.lc() - vector(1.6 * route_width, 0)
|
||||
|
||||
else:
|
||||
wl_offset = out_pin.rc() - vector( 0.5 * route_width, 0)
|
||||
|
||||
|
||||
end = vector(wl_offset.x, \
|
||||
self.get_pin("in_{}".format(row)).cy() + 0.5 * route_width)
|
||||
self.add_segment_center(layer=self.route_layer,
|
||||
start=wl_offset,
|
||||
end=end)
|
||||
if self.flip_io:
|
||||
self.add_segment_center(layer=self.route_layer,
|
||||
start=out_pin.lc(),
|
||||
end=vector(wl_offset.x - 0.5 * route_width, out_pin.cy()))
|
||||
|
||||
self.add_layout_pin_rect_center(text="out_{}".format(row), layer=self.route_layer, offset=end - vector(0, 0.5 * route_width))
|
||||
|
||||
|
|
|
|||
|
|
@ -24,8 +24,11 @@ class rom_bank_test(openram_test):
|
|||
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)
|
||||
|
||||
print('wriitng file')
|
||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||
self.local_check(a)
|
||||
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
#
|
||||
import unittest
|
||||
from testutils import *
|
||||
import sys, os
|
||||
|
||||
import openram
|
||||
from openram import OPTS
|
||||
from openram.sram_factory import factory
|
||||
from openram import debug
|
||||
|
||||
|
||||
class rom_bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
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)
|
||||
print('wriitng file')
|
||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||
self.local_check(a)
|
||||
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
#
|
||||
import unittest
|
||||
from testutils import *
|
||||
import sys, os
|
||||
|
||||
import openram
|
||||
from openram import OPTS
|
||||
from openram.sram_factory import factory
|
||||
from openram import debug
|
||||
|
||||
|
||||
class rom_bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
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)
|
||||
print('wriitng file')
|
||||
a.sp_write(OPTS.openram_temp + 'simulation_file.sp')
|
||||
self.local_check(a)
|
||||
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
# 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.
|
||||
#
|
||||
import unittest
|
||||
from testutils import *
|
||||
import sys, os
|
||||
|
||||
import openram
|
||||
from openram import OPTS
|
||||
from openram.sram_factory import factory
|
||||
from openram import debug
|
||||
|
||||
|
||||
class rom_bank_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
openram.init_openram(config_file, is_unit_test=True)
|
||||
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)
|
||||
print('wriitng file')
|
||||
a.sp_write(OPTS.openram_temp + 'simulation_file_8kB.sp')
|
||||
self.local_check(a)
|
||||
|
||||
|
||||
openram.end_openram()
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = openram.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
Loading…
Reference in New Issue