Reimplement trim options (except on unit tests).

Allow trim netlist to be used for delay and functional simulation.
Each class implements a "trim_insts" set of instances that can be removed.
By default far left, right, top and bottom cells in the bitcell arrays are kept.

Use lvs option in sp_write

Fix lvs option in sram.
This commit is contained in:
mrg 2021-04-06 17:01:52 -07:00
parent 31d3e6cb26
commit d609e4ea04
30 changed files with 147 additions and 206 deletions

View File

@ -53,7 +53,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
elif (OPTS.inline_lvsdrc or force_check or final_verification): elif (OPTS.inline_lvsdrc or force_check or final_verification):
tempspice = "{}.sp".format(self.name) tempspice = "{}.sp".format(self.name)
self.lvs_write("{0}{1}".format(OPTS.openram_temp, tempspice)) self.sp_write("{0}{1}".format(OPTS.openram_temp, tempspice), lvs=True)
tempgds = "{}.gds".format(self.name) tempgds = "{}.gds".format(self.name)
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds)) self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
# Final verification option does not allow nets to be connected by label. # Final verification option does not allow nets to be connected by label.
@ -82,7 +82,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
return return
elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
tempspice = "{}.sp".format(self.name) tempspice = "{}.sp".format(self.name)
self.lvs_write("{0}{1}".format(OPTS.openram_temp, tempspice)) self.sp_write("{0}{1}".format(OPTS.openram_temp, tempspice), lvs=True)
tempgds = "{}.gds".format(self.cell_name) tempgds = "{}.gds".format(self.cell_name)
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds)) self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
num_errors = verify.run_drc(self.cell_name, tempgds, tempspice, final_verification=final_verification) num_errors = verify.run_drc(self.cell_name, tempgds, tempspice, final_verification=final_verification)
@ -102,7 +102,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
return return
elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
tempspice = "{}.sp".format(self.cell_name) tempspice = "{}.sp".format(self.cell_name)
self.lvs_write("{0}{1}".format(OPTS.openram_temp, tempspice)) self.sp_write("{0}{1}".format(OPTS.openram_temp, tempspice), lvs=True)
tempgds = "{}.gds".format(self.name) tempgds = "{}.gds".format(self.name)
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds)) self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification) num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)

View File

@ -63,6 +63,8 @@ class spice():
self.conns = [] self.conns = []
# If this is set, it will out output subckt or isntances of this (for row/col caps etc.) # If this is set, it will out output subckt or isntances of this (for row/col caps etc.)
self.no_instances = False self.no_instances = False
# If we are doing a trimmed netlist, these are the instance that will be filtered
self.trim_insts = set()
# Keep track of any comments to add the the spice # Keep track of any comments to add the the spice
try: try:
self.commments self.commments
@ -312,10 +314,11 @@ class spice():
return True return True
return False return False
def sp_write_file(self, sp, usedMODS, lvs_netlist=False): def sp_write_file(self, sp, usedMODS, lvs=False, trim=False):
""" """
Recursive spice subcircuit write; Recursive spice subcircuit write;
Writes the spice subcircuit from the library or the dynamically generated one Writes the spice subcircuit from the library or the dynamically generated one.
Trim netlist is intended ONLY for bitcell arrays.
""" """
if self.no_instances: if self.no_instances:
@ -328,7 +331,7 @@ class spice():
if self.contains(i, usedMODS): if self.contains(i, usedMODS):
continue continue
usedMODS.append(i) usedMODS.append(i)
i.sp_write_file(sp, usedMODS, lvs_netlist) i.sp_write_file(sp, usedMODS, lvs, trim)
if len(self.insts) == 0: if len(self.insts) == 0:
return return
@ -371,10 +374,16 @@ class spice():
# these are wires and paths # these are wires and paths
if self.conns[i] == []: if self.conns[i] == []:
continue continue
# Instance with no devices in it needs no subckt/instance # Instance with no devices in it needs no subckt/instance
if self.insts[i].mod.no_instances: if self.insts[i].mod.no_instances:
continue continue
if lvs_netlist and hasattr(self.insts[i].mod, "lvs_device"):
# If this is a trimmed netlist, skip it by adding comment char
if trim and self.insts[i].name in self.trim_insts:
sp.write("* ")
if lvs and hasattr(self.insts[i].mod, "lvs_device"):
sp.write(self.insts[i].mod.lvs_device.format(self.insts[i].name, sp.write(self.insts[i].mod.lvs_device.format(self.insts[i].name,
" ".join(self.conns[i]))) " ".join(self.conns[i])))
sp.write("\n") sp.write("\n")
@ -394,30 +403,20 @@ class spice():
# Including the file path makes the unit test fail for other users. # Including the file path makes the unit test fail for other users.
# if os.path.isfile(self.sp_file): # if os.path.isfile(self.sp_file):
# sp.write("\n* {0}\n".format(self.sp_file)) # sp.write("\n* {0}\n".format(self.sp_file))
if lvs_netlist and hasattr(self, "lvs"): if lvs and hasattr(self, "lvs"):
sp.write("\n".join(self.lvs)) sp.write("\n".join(self.lvs))
else: else:
sp.write("\n".join(self.spice)) sp.write("\n".join(self.spice))
sp.write("\n") sp.write("\n")
def sp_write(self, spname): def sp_write(self, spname, lvs=False, trim=False):
"""Writes the spice to files""" """Writes the spice to files"""
debug.info(3, "Writing to {0}".format(spname)) debug.info(3, "Writing to {0}".format(spname))
spfile = open(spname, 'w') spfile = open(spname, 'w')
spfile.write("*FIRST LINE IS A COMMENT\n") spfile.write("*FIRST LINE IS A COMMENT\n")
usedMODS = list() usedMODS = list()
self.sp_write_file(spfile, usedMODS) self.sp_write_file(spfile, usedMODS, lvs=lvs, trim=trim)
del usedMODS
spfile.close()
def lvs_write(self, spname):
"""Writes the lvs to files"""
debug.info(3, "Writing to {0}".format(spname))
spfile = open(spname, 'w')
spfile.write("*FIRST LINE IS A COMMENT\n")
usedMODS = list()
self.sp_write_file(spfile, usedMODS, True)
del usedMODS del usedMODS
spfile.close() spfile.close()

View File

@ -1100,14 +1100,8 @@ class delay(simulation):
# Set up to trim the netlist here if that is enabled # Set up to trim the netlist here if that is enabled
if OPTS.trim_netlist: if OPTS.trim_netlist:
self.trim_sp_file = "{}reduced.sp".format(OPTS.openram_temp) self.trim_sp_file = "{}trimmed.sp".format(OPTS.openram_temp)
self.trimsp=trim_spice(self.sp_file, self.trim_sp_file) self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True)
self.trimsp.set_configuration(self.num_banks,
self.num_rows,
self.num_cols,
self.word_size,
self.num_spare_rows)
self.trimsp.trim(self.probe_address, self.probe_data)
else: else:
# The non-reduced netlist file when it is disabled # The non-reduced netlist file when it is disabled
self.trim_sp_file = "{}sram.sp".format(OPTS.openram_temp) self.trim_sp_file = "{}sram.sp".format(OPTS.openram_temp)

View File

@ -21,13 +21,17 @@ class functional(simulation):
for successful SRAM operation. for successful SRAM operation.
""" """
def __init__(self, sram, spfile, corner=None, cycles=15, period=None, output_path=None): def __init__(self, sram, spfile=None, corner=None, cycles=15, period=None, output_path=None):
super().__init__(sram, spfile, corner) super().__init__(sram, spfile, corner)
# Seed the characterizer with a constant seed for unit tests # Seed the characterizer with a constant seed for unit tests
if OPTS.is_unit_test: if OPTS.is_unit_test:
random.seed(12345) random.seed(12345)
if not spfile:
# self.sp_file is assigned in base class
sram.sp_write(self.sp_file, trim=OPTS.trim_netlist)
if not corner: if not corner:
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
@ -46,7 +50,18 @@ class functional(simulation):
if not self.num_spare_cols: if not self.num_spare_cols:
self.num_spare_cols = 0 self.num_spare_cols = 0
if self.num_spare_cols > 0:
debug.error("Functional simulation not debugged with spare columns.")
# FIXME: we need to remember the correct value of the spare columns
self.max_value = 2 ** (self.word_size + self.num_spare_cols) - 1
# If trim is set, specify the valid addresses
self.valid_addresses = set()
self.max_address = 2**self.addr_size - 1 + (self.num_spare_rows * self.words_per_row)
if OPTS.trim_netlist:
for i in range(self.words_per_row):
self.valid_addresses.add(i)
self.valid_addresses.add(self.max_address - i)
self.probe_address, self.probe_data = '0' * self.addr_size, 0 self.probe_address, self.probe_data = '0' * self.addr_size, 0
self.set_corner(corner) self.set_corner(corner)
self.set_spice_constants() self.set_spice_constants()
@ -300,21 +315,16 @@ class functional(simulation):
def gen_data(self): def gen_data(self):
""" Generates a random word to write. """ """ Generates a random word to write. """
if not self.num_spare_cols: random_value = random.randint(0, self.max_value)
random_value = random.randint(0, (2 ** self.word_size) - 1)
else:
random_value1 = random.randint(0, (2 ** self.word_size) - 1)
random_value2 = random.randint(0, (2 ** self.num_spare_cols) - 1)
random_value = random_value1 + random_value2
data_bits = self.convert_to_bin(random_value, False) data_bits = self.convert_to_bin(random_value, False)
return data_bits return data_bits
def gen_addr(self): def gen_addr(self):
""" Generates a random address value to write to. """ """ Generates a random address value to write to. """
if self.num_spare_rows==0: if self.valid_addresses:
random_value = random.randint(0, (2 ** self.addr_size) - 1) random_value = random.sample(self.valid_addresses, 1)[0]
else: else:
random_value = random.randint(0, ((2 ** (self.addr_size - 1) - 1)) + (self.num_spare_rows * self.words_per_row)) random_value = random.randint(0, self.max_address)
addr_bits = self.convert_to_bin(random_value, True) addr_bits = self.convert_to_bin(random_value, True)
return addr_bits return addr_bits

View File

@ -5,9 +5,8 @@
# (acting for and on behalf of Oklahoma State University) # (acting for and on behalf of Oklahoma State University)
# All rights reserved. # All rights reserved.
# #
import os,sys,re import os
import debug import debug
import math
import datetime import datetime
from .setup_hold import * from .setup_hold import *
from .delay import * from .delay import *
@ -16,6 +15,7 @@ import tech
import numpy as np import numpy as np
from globals import OPTS from globals import OPTS
class lib: class lib:
""" lib file generation.""" """ lib file generation."""
@ -601,7 +601,6 @@ class lib:
from .elmore import elmore as model from .elmore import elmore as model
else: else:
debug.error("{} model not recognized. See options.py for available models.".format(OPTS.model_name)) debug.error("{} model not recognized. See options.py for available models.".format(OPTS.model_name))
import math
m = model(self.sram, self.sp_file, self.corner) m = model(self.sram, self.sp_file, self.corner)
char_results = m.get_lib_values(self.slews,self.loads) char_results = m.get_lib_values(self.slews,self.loads)
@ -834,4 +833,4 @@ class lib:
#FIXME: should be read_fall_power #FIXME: should be read_fall_power
datasheet.write("{0},{1},".format('write_fall_power_{}'.format(port), read0_power)) datasheet.write("{0},{1},".format('write_fall_power_{}'.format(port), read0_power))

View File

@ -27,7 +27,10 @@ class simulation():
self.num_spare_cols = 0 self.num_spare_cols = 0
else: else:
self.num_spare_cols = self.sram.num_spare_cols self.num_spare_cols = self.sram.num_spare_cols
self.sp_file = spfile if not spfile:
self.sp_file = OPTS.openram_temp + "sram.sp"
else:
self.sp_file = spfile
self.all_ports = self.sram.all_ports self.all_ports = self.sram.all_ports
self.readwrite_ports = self.sram.readwrite_ports self.readwrite_ports = self.sram.readwrite_ports

View File

@ -9,6 +9,7 @@ import debug
from math import log,ceil from math import log,ceil
import re import re
class trim_spice(): class trim_spice():
""" """
A utility to trim redundant parts of an SRAM spice netlist. A utility to trim redundant parts of an SRAM spice netlist.
@ -29,7 +30,6 @@ class trim_spice():
for i in range(len(self.spice)): for i in range(len(self.spice)):
self.spice[i] = self.spice[i].rstrip(" \n") self.spice[i] = self.spice[i].rstrip(" \n")
self.sp_buffer = self.spice self.sp_buffer = self.spice
def set_configuration(self, banks, rows, columns, word_size): def set_configuration(self, banks, rows, columns, word_size):
@ -46,21 +46,23 @@ class trim_spice():
self.col_addr_size = int(log(self.words_per_row, 2)) self.col_addr_size = int(log(self.words_per_row, 2))
self.bank_addr_size = self.col_addr_size + self.row_addr_size self.bank_addr_size = self.col_addr_size + self.row_addr_size
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2)) self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
def trim(self, address, data_bit): def trim(self, address, data_bit):
""" Reduce the spice netlist but KEEP the given bits at the """
address (and things that will add capacitive load!)""" Reduce the spice netlist but KEEP the given bits at the
address (and things that will add capacitive load!)
"""
# Always start fresh if we do multiple reductions # Always start fresh if we do multiple reductions
self.sp_buffer = self.spice self.sp_buffer = self.spice
# Split up the address and convert to an int # Split up the address and convert to an int
wl_address = int(address[self.col_addr_size:],2) wl_address = int(address[self.col_addr_size:], 2)
if self.col_addr_size>0: if self.col_addr_size > 0:
col_address = int(address[0:self.col_addr_size],2) col_address = int(address[0:self.col_addr_size], 2)
else: else:
col_address = 0 col_address = 0
# 1. Keep cells in the bitcell array based on WL and BL # 1. Keep cells in the bitcell array based on WL and BL
wl_name = "wl_{}".format(wl_address) wl_name = "wl_{}".format(wl_address)
bl_name = "bl_{}".format(int(self.words_per_row*data_bit + col_address)) bl_name = "bl_{}".format(int(self.words_per_row*data_bit + col_address))
@ -81,7 +83,6 @@ class trim_spice():
self.sp_buffer.insert(0, "* It should NOT be used for LVS!!") self.sp_buffer.insert(0, "* It should NOT be used for LVS!!")
self.sp_buffer.insert(0, "* WARNING: This is a TRIMMED NETLIST.") self.sp_buffer.insert(0, "* WARNING: This is a TRIMMED NETLIST.")
wl_regex = r"wl\d*_{}".format(wl_address) wl_regex = r"wl\d*_{}".format(wl_address)
bl_regex = r"bl\d*_{}".format(int(self.words_per_row*data_bit + col_address)) bl_regex = r"bl\d*_{}".format(int(self.words_per_row*data_bit + col_address))
self.remove_insts("bitcell_array",[wl_regex,bl_regex]) self.remove_insts("bitcell_array",[wl_regex,bl_regex])
@ -91,11 +92,11 @@ class trim_spice():
#self.remove_insts("sense_amp_array",[bl_regex]) #self.remove_insts("sense_amp_array",[bl_regex])
# 3. Keep column muxes basd on BL # 3. Keep column muxes basd on BL
self.remove_insts("column_mux_array",[bl_regex]) self.remove_insts("column_mux_array", [bl_regex])
# 4. Keep write driver based on DATA # 4. Keep write driver based on DATA
data_regex = r"data_{}".format(data_bit) data_regex = r"data_{}".format(data_bit)
self.remove_insts("write_driver_array",[data_regex]) self.remove_insts("write_driver_array", [data_regex])
# 5. Keep wordline driver based on WL # 5. Keep wordline driver based on WL
# Need to keep the gater too # Need to keep the gater too
@ -111,7 +112,6 @@ class trim_spice():
sp.write("\n".join(self.sp_buffer)) sp.write("\n".join(self.sp_buffer))
sp.close() sp.close()
def remove_insts(self, subckt_name, keep_inst_list): def remove_insts(self, subckt_name, keep_inst_list):
"""This will remove all of the instances in the list from the named """This will remove all of the instances in the list from the named
subckt that DO NOT contain a term in the list. It just does a subckt that DO NOT contain a term in the list. It just does a
@ -119,7 +119,7 @@ class trim_spice():
net connection, the instance name, anything.. net connection, the instance name, anything..
""" """
removed_insts = 0 removed_insts = 0
#Expects keep_inst_list are regex patterns. Compile them here. # Expects keep_inst_list are regex patterns. Compile them here.
compiled_patterns = [re.compile(pattern) for pattern in keep_inst_list] compiled_patterns = [re.compile(pattern) for pattern in keep_inst_list]
start_name = ".SUBCKT {}".format(subckt_name) start_name = ".SUBCKT {}".format(subckt_name)

View File

@ -64,7 +64,11 @@ class bitcell_array(bitcell_base_array):
self.cell_inst[row, col]=self.add_inst(name=name, self.cell_inst[row, col]=self.add_inst(name=name,
mod=self.cell) mod=self.cell)
self.connect_inst(self.get_bitcell_pins(row, col)) self.connect_inst(self.get_bitcell_pins(row, col))
# If it is a "core" cell, it could be trimmed for sim time
if col>0 and col<self.column_size-1 and row>0 and row<self.row_size-1:
self.trim_insts.add(name)
def analytical_power(self, corner, load): def analytical_power(self, corner, load):
"""Power of Bitcell array and bitline in nW.""" """Power of Bitcell array and bitline in nW."""

View File

@ -57,11 +57,8 @@ class sram():
if not OPTS.is_unit_test: if not OPTS.is_unit_test:
print_time("SRAM creation", datetime.datetime.now(), start_time) print_time("SRAM creation", datetime.datetime.now(), start_time)
def sp_write(self, name): def sp_write(self, name, lvs=False, trim=False):
self.s.sp_write(name) self.s.sp_write(name, lvs, trim)
def lvs_write(self, name):
self.s.lvs_write(name)
def lef_write(self, name): def lef_write(self, name):
self.s.lef_write(name) self.s.lef_write(name)

View File

@ -675,7 +675,7 @@ class sram_base(design, verilog, lef):
return insts return insts
def sp_write(self, sp_name, lvs_netlist=False): def sp_write(self, sp_name, lvs=False, trim=False):
# Write the entire spice of the object to the file # Write the entire spice of the object to the file
############################################################ ############################################################
# Spice circuit # Spice circuit
@ -688,6 +688,8 @@ class sram_base(design, verilog, lef):
sp.write("* Data bits: {}\n".format(self.word_size)) sp.write("* Data bits: {}\n".format(self.word_size))
sp.write("* Banks: {}\n".format(self.num_banks)) sp.write("* Banks: {}\n".format(self.num_banks))
sp.write("* Column mux: {}:1\n".format(self.words_per_row)) sp.write("* Column mux: {}:1\n".format(self.words_per_row))
sp.write("* Trimmed: {}\n".format(trim))
sp.write("* LVS: {}\n".format(lvs))
sp.write("**************************************************\n") sp.write("**************************************************\n")
# This causes unit test mismatch # This causes unit test mismatch
@ -696,13 +698,10 @@ class sram_base(design, verilog, lef):
# sp.write(".global {0} {1}\n".format(spice["vdd_name"], # sp.write(".global {0} {1}\n".format(spice["vdd_name"],
# spice["gnd_name"])) # spice["gnd_name"]))
usedMODS = list() usedMODS = list()
self.sp_write_file(sp, usedMODS, lvs_netlist=lvs_netlist) self.sp_write_file(sp, usedMODS, lvs=lvs, trim=trim)
del usedMODS del usedMODS
sp.close() sp.close()
def lvs_write(self, sp_name):
self.sp_write(sp_name, lvs_netlist=True)
def graph_exclude_bits(self, targ_row, targ_col): def graph_exclude_bits(self, targ_row, targ_col):
""" """
Excludes bits in column from being added to graph except target Excludes bits in column from being added to graph except target

View File

@ -30,19 +30,13 @@ class timing_sram_test(openram_test):
reload(characterizer) reload(characterizer)
from characterizer import delay from characterizer import delay
from sram_config import sram_config from sram_config import sram_config
c = sram_config(word_size=1, c = sram_config(word_size=4,
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
# c = sram_config(word_size=32,
# num_words=256,
# num_banks=1)
# c.words_per_row=2
c.recompute_sizes() c.recompute_sizes()
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
#import sys
#sys.exit(1)
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)
@ -61,34 +55,35 @@ class timing_sram_test(openram_test):
data.update(port_data[0]) data.update(port_data[0])
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'min_period': 0.898, golden_data = {'delay_hl': [0.23941909999999997],
'write1_power': [0.2659137999999999], 'delay_lh': [0.23941909999999997],
'disabled_write0_power': [0.1782495], 'disabled_read0_power': [0.18183159999999998],
'disabled_read0_power': [0.14490679999999997], 'disabled_read1_power': [0.1979447],
'write0_power': [0.3330119], 'disabled_write0_power': [0.2129604],
'disabled_write1_power': [0.1865223], 'disabled_write1_power': [0.23266849999999997],
'leakage_power': 0.0014532, 'leakage_power': 0.0019882,
'disabled_read1_power': [0.1627516], 'min_period': 0.938,
'slew_lh': [0.25367799999999996], 'read0_power': [0.4115467],
'slew_hl': [0.25367799999999996], 'read1_power': [0.41158859999999997],
'delay_lh': [0.23820930000000004], 'slew_hl': [0.2798571],
'delay_hl': [0.23820930000000004], 'slew_lh': [0.2798571],
'read1_power': [0.3005756], 'write0_power': [0.45873749999999996],
'read0_power': [0.3005888]} 'write1_power': [0.40716199999999997]}
elif OPTS.tech_name == "scn4m_subm": elif OPTS.tech_name == "scn4m_subm":
golden_data = {'leakage_power': 0.0006356576000000001, golden_data = {'delay_hl': [1.7652000000000003],
'write1_power': [11.292700000000002], 'delay_lh': [1.7652000000000003],
'read0_power': [12.98], 'disabled_read0_power': [8.2716],
'disabled_write1_power': [8.3707], 'disabled_read1_power': [9.5857],
'write0_power': [14.4447], 'delay_hl': [1.7445000000000002], 'disabled_write0_power': [9.9825],
'disabled_read0_power': [6.4325], 'disabled_write1_power': [10.598400000000002],
'slew_hl': [1.7437], 'leakage_power': 0.0006681718,
'disabled_write0_power': [8.1307], 'min_period': 6.562,
'slew_lh': [1.7437], 'read0_power': [18.6446],
'read1_power': [12.9869], 'read1_power': [18.5126],
'disabled_read1_power': [7.706], 'slew_hl': [1.9026],
'min_period': 6.25, 'slew_lh': [1.9026],
'delay_lh': [1.7445000000000002]} 'write0_power': [21.022600000000004],
'write1_power': [16.6377]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
# Check if no too many or too few results # Check if no too many or too few results

View File

@ -30,7 +30,7 @@ class timing_sram_test(openram_test):
reload(characterizer) reload(characterizer)
from characterizer import delay from characterizer import delay
from sram_config import sram_config from sram_config import sram_config
c = sram_config(word_size=1, c = sram_config(word_size=4,
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
@ -55,35 +55,35 @@ class timing_sram_test(openram_test):
data.update(port_data[0]) data.update(port_data[0])
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'slew_lh': [0.2592187], golden_data = {'delay_hl': [0.24671600000000002],
'slew_hl': [0.2592187], 'delay_lh': [0.24671600000000002],
'delay_lh': [0.2465583], 'disabled_read0_power': [0.1749204],
'disabled_write0_power': [0.1924678], 'disabled_read1_power': [0.1873704],
'disabled_read0_power': [0.152483], 'disabled_write0_power': [0.204619],
'write0_power': [0.3409064], 'disabled_write1_power': [0.2262653],
'disabled_read1_power': [0.1737818], 'leakage_power': 0.0021375310000000002,
'read0_power': [0.3096708], 'min_period': 0.977,
'read1_power': [0.3107916], 'read0_power': [0.3856875],
'delay_hl': [0.2465583], 'read1_power': [0.38856060000000003],
'write1_power': [0.26915849999999997], 'slew_hl': [0.2842019],
'leakage_power': 0.002044307, 'slew_lh': [0.2842019],
'min_period': 0.898, 'write0_power': [0.45274410000000004],
'disabled_write1_power': [0.201411]} 'write1_power': [0.38727789999999995]}
elif OPTS.tech_name == "scn4m_subm": elif OPTS.tech_name == "scn4m_subm":
golden_data = {'delay_hl': [1.8435739999999998], golden_data = {'delay_hl': [1.882508],
'delay_lh': [1.8435739999999998], 'delay_lh': [1.882508],
'disabled_read0_power': [5.917947], 'disabled_read0_power': [7.487227],
'disabled_read1_power': [7.154297], 'disabled_read1_power': [8.749013],
'disabled_write0_power': [7.696351], 'disabled_write0_power': [9.268901],
'disabled_write1_power': [7.999409000000001], 'disabled_write1_power': [9.962973],
'leakage_power': 0.004809726, 'leakage_power': 0.0046686359999999994,
'min_period': 6.875, 'min_period': 7.188,
'read0_power': [11.833079999999999], 'read0_power': [16.64011],
'read1_power': [11.99236], 'read1_power': [17.20825],
'slew_hl': [1.8668490000000002], 'slew_hl': [2.039655],
'slew_lh': [1.8668490000000002], 'slew_lh': [2.039655],
'write0_power': [13.287510000000001], 'write0_power': [19.31883],
'write1_power': [10.416369999999999]} 'write1_power': [15.297369999999999]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -23,7 +23,6 @@ class psram_1bank_2mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.replica_bitcell="replica_pbitcell" OPTS.replica_bitcell="replica_pbitcell"
@ -53,10 +52,7 @@ class psram_1bank_2mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class psram_1bank_4mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.replica_bitcell="replica_pbitcell" OPTS.replica_bitcell="replica_pbitcell"
@ -54,11 +53,8 @@ class psram_1bank_4mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp"
s.sp_write(tempspice)
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
f = functional(s.s, tempspice, corner) f = functional(s.s, corner=corner)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class psram_1bank_8mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.replica_bitcell="replica_pbitcell" OPTS.replica_bitcell="replica_pbitcell"
@ -54,10 +53,7 @@ class psram_1bank_8mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -23,7 +23,6 @@ class psram_1bank_nomux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.bitcell = "pbitcell" OPTS.bitcell = "pbitcell"
OPTS.replica_bitcell="replica_pbitcell" OPTS.replica_bitcell="replica_pbitcell"
@ -53,10 +52,7 @@ class psram_1bank_nomux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_1bank_2mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -43,10 +42,7 @@ class sram_1bank_2mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_1bank_2mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -44,10 +43,7 @@ class sram_1bank_2mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_1bank_2mux_sparecols_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -45,10 +44,7 @@ class sram_1bank_2mux_sparecols_func_test(openram_test):
c.num_spare_cols, c.num_spare_cols,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_1bank_4mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -43,10 +42,7 @@ class sram_1bank_4mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_1bank_8mux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -46,10 +45,7 @@ class sram_1bank_8mux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -23,7 +23,6 @@ class psram_1bank_nomux_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
OPTS.num_r_ports = 1 OPTS.num_r_ports = 1
@ -46,10 +45,7 @@ class psram_1bank_nomux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -42,10 +42,7 @@ class sram_1bank_nomux_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -43,10 +43,7 @@ class sram_1bank_nomux_sparecols_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -23,7 +23,6 @@ class sram_wmask_1w_1r_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
OPTS.num_r_ports = 1 OPTS.num_r_ports = 1
@ -49,10 +48,7 @@ class sram_wmask_1w_1r_func_test(openram_test):
c.write_size, c.write_size,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class sram_wmask_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload
@ -45,10 +44,7 @@ class sram_wmask_func_test(openram_test):
c.write_size, c.write_size,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp" f = functional(s.s)
s.sp_write(tempspice)
f = functional(s.s, tempspice)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -21,7 +21,6 @@ class lib_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
# This is a hack to reload the characterizer __init__ with the spice version # This is a hack to reload the characterizer __init__ with the spice version
from importlib import reload from importlib import reload

View File

@ -45,7 +45,7 @@ class sram_pex_test(openram_test):
tempspice = self.run_pex(s) tempspice = self.run_pex(s)
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
f = functional(s.s, tempspice, corner) f = functional(s.s, spfile=tempspice, corner=corner)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -24,7 +24,6 @@ class riscv_func_test(openram_test):
globals.init_openram(config_file) globals.init_openram(config_file)
OPTS.analytical_delay = False OPTS.analytical_delay = False
OPTS.netlist_only = True OPTS.netlist_only = True
OPTS.trim_netlist = False
OPTS.local_array_size = 16 OPTS.local_array_size = 16
OPTS.num_rw_ports = 1 OPTS.num_rw_ports = 1
OPTS.num_w_ports = 0 OPTS.num_w_ports = 0
@ -49,11 +48,8 @@ class riscv_func_test(openram_test):
c.words_per_row, c.words_per_row,
c.num_banks)) c.num_banks))
s = factory.create(module_type="sram", sram_config=c) s = factory.create(module_type="sram", sram_config=c)
tempspice = OPTS.openram_temp + "sram.sp"
s.sp_write(tempspice)
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0]) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
f = functional(s.s, tempspice, corner) f = functional(s.s, corner=corner)
(fail, error) = f.run() (fail, error) = f.run()
self.assertTrue(fail, error) self.assertTrue(fail, error)

View File

@ -63,7 +63,7 @@ class openram_test(unittest.TestCase):
tempspice = "{}.sp".format(a.name) tempspice = "{}.sp".format(a.name)
tempgds = "{}.gds".format(a.name) tempgds = "{}.gds".format(a.name)
a.lvs_write("{0}{1}".format(OPTS.openram_temp, tempspice)) a.sp_write("{0}{1}".format(OPTS.openram_temp, tempspice), lvs=True)
# cannot write gds in netlist_only mode # cannot write gds in netlist_only mode
if not OPTS.netlist_only: if not OPTS.netlist_only:
a.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds)) a.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))