mirror of https://github.com/VLSIDA/OpenRAM.git
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:
parent
31d3e6cb26
commit
d609e4ea04
|
|
@ -53,7 +53,7 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
|
|||
elif (OPTS.inline_lvsdrc or force_check or final_verification):
|
||||
|
||||
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)
|
||||
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
|
||||
# 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
|
||||
elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
|
||||
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)
|
||||
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
|
||||
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
|
||||
elif (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
|
||||
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)
|
||||
self.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
|
||||
num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification=final_verification)
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ class spice():
|
|||
self.conns = []
|
||||
# If this is set, it will out output subckt or isntances of this (for row/col caps etc.)
|
||||
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
|
||||
try:
|
||||
self.commments
|
||||
|
|
@ -312,10 +314,11 @@ class spice():
|
|||
return True
|
||||
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;
|
||||
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:
|
||||
|
|
@ -328,7 +331,7 @@ class spice():
|
|||
if self.contains(i, usedMODS):
|
||||
continue
|
||||
usedMODS.append(i)
|
||||
i.sp_write_file(sp, usedMODS, lvs_netlist)
|
||||
i.sp_write_file(sp, usedMODS, lvs, trim)
|
||||
|
||||
if len(self.insts) == 0:
|
||||
return
|
||||
|
|
@ -371,10 +374,16 @@ class spice():
|
|||
# these are wires and paths
|
||||
if self.conns[i] == []:
|
||||
continue
|
||||
|
||||
# Instance with no devices in it needs no subckt/instance
|
||||
if self.insts[i].mod.no_instances:
|
||||
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,
|
||||
" ".join(self.conns[i])))
|
||||
sp.write("\n")
|
||||
|
|
@ -394,30 +403,20 @@ class spice():
|
|||
# Including the file path makes the unit test fail for other users.
|
||||
# if os.path.isfile(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))
|
||||
else:
|
||||
sp.write("\n".join(self.spice))
|
||||
|
||||
sp.write("\n")
|
||||
|
||||
def sp_write(self, spname):
|
||||
def sp_write(self, spname, lvs=False, trim=False):
|
||||
"""Writes the spice 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)
|
||||
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)
|
||||
self.sp_write_file(spfile, usedMODS, lvs=lvs, trim=trim)
|
||||
del usedMODS
|
||||
spfile.close()
|
||||
|
||||
|
|
|
|||
|
|
@ -1100,14 +1100,8 @@ class delay(simulation):
|
|||
|
||||
# Set up to trim the netlist here if that is enabled
|
||||
if OPTS.trim_netlist:
|
||||
self.trim_sp_file = "{}reduced.sp".format(OPTS.openram_temp)
|
||||
self.trimsp=trim_spice(self.sp_file, self.trim_sp_file)
|
||||
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)
|
||||
self.trim_sp_file = "{}trimmed.sp".format(OPTS.openram_temp)
|
||||
self.sram.sp_write(self.trim_sp_file, lvs=False, trim=True)
|
||||
else:
|
||||
# The non-reduced netlist file when it is disabled
|
||||
self.trim_sp_file = "{}sram.sp".format(OPTS.openram_temp)
|
||||
|
|
|
|||
|
|
@ -21,13 +21,17 @@ class functional(simulation):
|
|||
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)
|
||||
|
||||
# Seed the characterizer with a constant seed for unit tests
|
||||
if OPTS.is_unit_test:
|
||||
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:
|
||||
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:
|
||||
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.set_corner(corner)
|
||||
self.set_spice_constants()
|
||||
|
|
@ -300,21 +315,16 @@ class functional(simulation):
|
|||
|
||||
def gen_data(self):
|
||||
""" Generates a random word to write. """
|
||||
if not self.num_spare_cols:
|
||||
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
|
||||
random_value = random.randint(0, self.max_value)
|
||||
data_bits = self.convert_to_bin(random_value, False)
|
||||
return data_bits
|
||||
|
||||
def gen_addr(self):
|
||||
""" Generates a random address value to write to. """
|
||||
if self.num_spare_rows==0:
|
||||
random_value = random.randint(0, (2 ** self.addr_size) - 1)
|
||||
if self.valid_addresses:
|
||||
random_value = random.sample(self.valid_addresses, 1)[0]
|
||||
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)
|
||||
return addr_bits
|
||||
|
||||
|
|
|
|||
|
|
@ -5,9 +5,8 @@
|
|||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import os,sys,re
|
||||
import os
|
||||
import debug
|
||||
import math
|
||||
import datetime
|
||||
from .setup_hold import *
|
||||
from .delay import *
|
||||
|
|
@ -16,6 +15,7 @@ import tech
|
|||
import numpy as np
|
||||
from globals import OPTS
|
||||
|
||||
|
||||
class lib:
|
||||
""" lib file generation."""
|
||||
|
||||
|
|
@ -601,7 +601,6 @@ class lib:
|
|||
from .elmore import elmore as model
|
||||
else:
|
||||
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)
|
||||
char_results = m.get_lib_values(self.slews,self.loads)
|
||||
|
|
@ -834,4 +833,4 @@ class lib:
|
|||
#FIXME: should be read_fall_power
|
||||
datasheet.write("{0},{1},".format('write_fall_power_{}'.format(port), read0_power))
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,10 @@ class simulation():
|
|||
self.num_spare_cols = 0
|
||||
else:
|
||||
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.readwrite_ports = self.sram.readwrite_ports
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import debug
|
|||
from math import log,ceil
|
||||
import re
|
||||
|
||||
|
||||
class trim_spice():
|
||||
"""
|
||||
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)):
|
||||
self.spice[i] = self.spice[i].rstrip(" \n")
|
||||
|
||||
|
||||
self.sp_buffer = self.spice
|
||||
|
||||
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.bank_addr_size = self.col_addr_size + self.row_addr_size
|
||||
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
|
||||
|
||||
|
||||
|
||||
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
|
||||
self.sp_buffer = self.spice
|
||||
|
||||
# Split up the address and convert to an int
|
||||
wl_address = int(address[self.col_addr_size:],2)
|
||||
if self.col_addr_size>0:
|
||||
col_address = int(address[0:self.col_addr_size],2)
|
||||
wl_address = int(address[self.col_addr_size:], 2)
|
||||
if self.col_addr_size > 0:
|
||||
col_address = int(address[0:self.col_addr_size], 2)
|
||||
else:
|
||||
col_address = 0
|
||||
|
||||
# 1. Keep cells in the bitcell array based on WL and BL
|
||||
wl_name = "wl_{}".format(wl_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, "* WARNING: This is a TRIMMED NETLIST.")
|
||||
|
||||
|
||||
wl_regex = r"wl\d*_{}".format(wl_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])
|
||||
|
|
@ -91,11 +92,11 @@ class trim_spice():
|
|||
#self.remove_insts("sense_amp_array",[bl_regex])
|
||||
|
||||
# 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
|
||||
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
|
||||
# Need to keep the gater too
|
||||
|
|
@ -111,7 +112,6 @@ class trim_spice():
|
|||
sp.write("\n".join(self.sp_buffer))
|
||||
sp.close()
|
||||
|
||||
|
||||
def remove_insts(self, subckt_name, keep_inst_list):
|
||||
"""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
|
||||
|
|
@ -119,7 +119,7 @@ class trim_spice():
|
|||
net connection, the instance name, anything..
|
||||
"""
|
||||
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]
|
||||
|
||||
start_name = ".SUBCKT {}".format(subckt_name)
|
||||
|
|
|
|||
|
|
@ -64,7 +64,11 @@ class bitcell_array(bitcell_base_array):
|
|||
self.cell_inst[row, col]=self.add_inst(name=name,
|
||||
mod=self.cell)
|
||||
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):
|
||||
"""Power of Bitcell array and bitline in nW."""
|
||||
|
||||
|
|
|
|||
|
|
@ -57,11 +57,8 @@ class sram():
|
|||
if not OPTS.is_unit_test:
|
||||
print_time("SRAM creation", datetime.datetime.now(), start_time)
|
||||
|
||||
def sp_write(self, name):
|
||||
self.s.sp_write(name)
|
||||
|
||||
def lvs_write(self, name):
|
||||
self.s.lvs_write(name)
|
||||
def sp_write(self, name, lvs=False, trim=False):
|
||||
self.s.sp_write(name, lvs, trim)
|
||||
|
||||
def lef_write(self, name):
|
||||
self.s.lef_write(name)
|
||||
|
|
|
|||
|
|
@ -675,7 +675,7 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
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
|
||||
############################################################
|
||||
# Spice circuit
|
||||
|
|
@ -688,6 +688,8 @@ class sram_base(design, verilog, lef):
|
|||
sp.write("* Data bits: {}\n".format(self.word_size))
|
||||
sp.write("* Banks: {}\n".format(self.num_banks))
|
||||
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")
|
||||
# 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"],
|
||||
# spice["gnd_name"]))
|
||||
usedMODS = list()
|
||||
self.sp_write_file(sp, usedMODS, lvs_netlist=lvs_netlist)
|
||||
self.sp_write_file(sp, usedMODS, lvs=lvs, trim=trim)
|
||||
del usedMODS
|
||||
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):
|
||||
"""
|
||||
Excludes bits in column from being added to graph except target
|
||||
|
|
|
|||
|
|
@ -30,19 +30,13 @@ class timing_sram_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import delay
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=1,
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=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()
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
#import sys
|
||||
#sys.exit(1)
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
|
@ -61,34 +55,35 @@ class timing_sram_test(openram_test):
|
|||
data.update(port_data[0])
|
||||
|
||||
if OPTS.tech_name == "freepdk45":
|
||||
golden_data = {'min_period': 0.898,
|
||||
'write1_power': [0.2659137999999999],
|
||||
'disabled_write0_power': [0.1782495],
|
||||
'disabled_read0_power': [0.14490679999999997],
|
||||
'write0_power': [0.3330119],
|
||||
'disabled_write1_power': [0.1865223],
|
||||
'leakage_power': 0.0014532,
|
||||
'disabled_read1_power': [0.1627516],
|
||||
'slew_lh': [0.25367799999999996],
|
||||
'slew_hl': [0.25367799999999996],
|
||||
'delay_lh': [0.23820930000000004],
|
||||
'delay_hl': [0.23820930000000004],
|
||||
'read1_power': [0.3005756],
|
||||
'read0_power': [0.3005888]}
|
||||
golden_data = {'delay_hl': [0.23941909999999997],
|
||||
'delay_lh': [0.23941909999999997],
|
||||
'disabled_read0_power': [0.18183159999999998],
|
||||
'disabled_read1_power': [0.1979447],
|
||||
'disabled_write0_power': [0.2129604],
|
||||
'disabled_write1_power': [0.23266849999999997],
|
||||
'leakage_power': 0.0019882,
|
||||
'min_period': 0.938,
|
||||
'read0_power': [0.4115467],
|
||||
'read1_power': [0.41158859999999997],
|
||||
'slew_hl': [0.2798571],
|
||||
'slew_lh': [0.2798571],
|
||||
'write0_power': [0.45873749999999996],
|
||||
'write1_power': [0.40716199999999997]}
|
||||
elif OPTS.tech_name == "scn4m_subm":
|
||||
golden_data = {'leakage_power': 0.0006356576000000001,
|
||||
'write1_power': [11.292700000000002],
|
||||
'read0_power': [12.98],
|
||||
'disabled_write1_power': [8.3707],
|
||||
'write0_power': [14.4447], 'delay_hl': [1.7445000000000002],
|
||||
'disabled_read0_power': [6.4325],
|
||||
'slew_hl': [1.7437],
|
||||
'disabled_write0_power': [8.1307],
|
||||
'slew_lh': [1.7437],
|
||||
'read1_power': [12.9869],
|
||||
'disabled_read1_power': [7.706],
|
||||
'min_period': 6.25,
|
||||
'delay_lh': [1.7445000000000002]}
|
||||
golden_data = {'delay_hl': [1.7652000000000003],
|
||||
'delay_lh': [1.7652000000000003],
|
||||
'disabled_read0_power': [8.2716],
|
||||
'disabled_read1_power': [9.5857],
|
||||
'disabled_write0_power': [9.9825],
|
||||
'disabled_write1_power': [10.598400000000002],
|
||||
'leakage_power': 0.0006681718,
|
||||
'min_period': 6.562,
|
||||
'read0_power': [18.6446],
|
||||
'read1_power': [18.5126],
|
||||
'slew_hl': [1.9026],
|
||||
'slew_lh': [1.9026],
|
||||
'write0_power': [21.022600000000004],
|
||||
'write1_power': [16.6377]}
|
||||
else:
|
||||
self.assertTrue(False) # other techs fail
|
||||
# Check if no too many or too few results
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ class timing_sram_test(openram_test):
|
|||
reload(characterizer)
|
||||
from characterizer import delay
|
||||
from sram_config import sram_config
|
||||
c = sram_config(word_size=1,
|
||||
c = sram_config(word_size=4,
|
||||
num_words=16,
|
||||
num_banks=1)
|
||||
c.words_per_row=1
|
||||
|
|
@ -55,35 +55,35 @@ class timing_sram_test(openram_test):
|
|||
data.update(port_data[0])
|
||||
|
||||
if OPTS.tech_name == "freepdk45":
|
||||
golden_data = {'slew_lh': [0.2592187],
|
||||
'slew_hl': [0.2592187],
|
||||
'delay_lh': [0.2465583],
|
||||
'disabled_write0_power': [0.1924678],
|
||||
'disabled_read0_power': [0.152483],
|
||||
'write0_power': [0.3409064],
|
||||
'disabled_read1_power': [0.1737818],
|
||||
'read0_power': [0.3096708],
|
||||
'read1_power': [0.3107916],
|
||||
'delay_hl': [0.2465583],
|
||||
'write1_power': [0.26915849999999997],
|
||||
'leakage_power': 0.002044307,
|
||||
'min_period': 0.898,
|
||||
'disabled_write1_power': [0.201411]}
|
||||
golden_data = {'delay_hl': [0.24671600000000002],
|
||||
'delay_lh': [0.24671600000000002],
|
||||
'disabled_read0_power': [0.1749204],
|
||||
'disabled_read1_power': [0.1873704],
|
||||
'disabled_write0_power': [0.204619],
|
||||
'disabled_write1_power': [0.2262653],
|
||||
'leakage_power': 0.0021375310000000002,
|
||||
'min_period': 0.977,
|
||||
'read0_power': [0.3856875],
|
||||
'read1_power': [0.38856060000000003],
|
||||
'slew_hl': [0.2842019],
|
||||
'slew_lh': [0.2842019],
|
||||
'write0_power': [0.45274410000000004],
|
||||
'write1_power': [0.38727789999999995]}
|
||||
elif OPTS.tech_name == "scn4m_subm":
|
||||
golden_data = {'delay_hl': [1.8435739999999998],
|
||||
'delay_lh': [1.8435739999999998],
|
||||
'disabled_read0_power': [5.917947],
|
||||
'disabled_read1_power': [7.154297],
|
||||
'disabled_write0_power': [7.696351],
|
||||
'disabled_write1_power': [7.999409000000001],
|
||||
'leakage_power': 0.004809726,
|
||||
'min_period': 6.875,
|
||||
'read0_power': [11.833079999999999],
|
||||
'read1_power': [11.99236],
|
||||
'slew_hl': [1.8668490000000002],
|
||||
'slew_lh': [1.8668490000000002],
|
||||
'write0_power': [13.287510000000001],
|
||||
'write1_power': [10.416369999999999]}
|
||||
golden_data = {'delay_hl': [1.882508],
|
||||
'delay_lh': [1.882508],
|
||||
'disabled_read0_power': [7.487227],
|
||||
'disabled_read1_power': [8.749013],
|
||||
'disabled_write0_power': [9.268901],
|
||||
'disabled_write1_power': [9.962973],
|
||||
'leakage_power': 0.0046686359999999994,
|
||||
'min_period': 7.188,
|
||||
'read0_power': [16.64011],
|
||||
'read1_power': [17.20825],
|
||||
'slew_hl': [2.039655],
|
||||
'slew_lh': [2.039655],
|
||||
'write0_power': [19.31883],
|
||||
'write1_power': [15.297369999999999]}
|
||||
else:
|
||||
self.assertTrue(False) # other techs fail
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class psram_1bank_2mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell="replica_pbitcell"
|
||||
|
|
@ -53,10 +52,7 @@ class psram_1bank_2mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class psram_1bank_4mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell="replica_pbitcell"
|
||||
|
|
@ -54,11 +53,8 @@ class psram_1bank_4mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
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])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
f = functional(s.s, corner=corner)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class psram_1bank_8mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell="replica_pbitcell"
|
||||
|
|
@ -54,10 +53,7 @@ class psram_1bank_8mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
OPTS.bitcell = "pbitcell"
|
||||
OPTS.replica_bitcell="replica_pbitcell"
|
||||
|
|
@ -53,10 +52,7 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_1bank_2mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -43,10 +42,7 @@ class sram_1bank_2mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_1bank_2mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -44,10 +43,7 @@ class sram_1bank_2mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_1bank_2mux_sparecols_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -45,10 +44,7 @@ class sram_1bank_2mux_sparecols_func_test(openram_test):
|
|||
c.num_spare_cols,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_1bank_4mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -43,10 +42,7 @@ class sram_1bank_4mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_1bank_8mux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -46,10 +45,7 @@ class sram_1bank_8mux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 1
|
||||
|
|
@ -46,10 +45,7 @@ class psram_1bank_nomux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -42,10 +42,7 @@ class sram_1bank_nomux_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,7 @@ class sram_1bank_nomux_sparecols_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ class sram_wmask_1w_1r_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
OPTS.num_r_ports = 1
|
||||
|
|
@ -49,10 +48,7 @@ class sram_wmask_1w_1r_func_test(openram_test):
|
|||
c.write_size,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class sram_wmask_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
@ -45,10 +44,7 @@ class sram_wmask_func_test(openram_test):
|
|||
c.write_size,
|
||||
c.num_banks))
|
||||
s = factory.create(module_type="sram", sram_config=c)
|
||||
tempspice = OPTS.openram_temp + "sram.sp"
|
||||
s.sp_write(tempspice)
|
||||
|
||||
f = functional(s.s, tempspice)
|
||||
f = functional(s.s)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ class lib_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ class sram_pex_test(openram_test):
|
|||
tempspice = self.run_pex(s)
|
||||
|
||||
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()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ class riscv_func_test(openram_test):
|
|||
globals.init_openram(config_file)
|
||||
OPTS.analytical_delay = False
|
||||
OPTS.netlist_only = True
|
||||
OPTS.trim_netlist = False
|
||||
OPTS.local_array_size = 16
|
||||
OPTS.num_rw_ports = 1
|
||||
OPTS.num_w_ports = 0
|
||||
|
|
@ -49,11 +48,8 @@ class riscv_func_test(openram_test):
|
|||
c.words_per_row,
|
||||
c.num_banks))
|
||||
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])
|
||||
f = functional(s.s, tempspice, corner)
|
||||
f = functional(s.s, corner=corner)
|
||||
(fail, error) = f.run()
|
||||
self.assertTrue(fail, error)
|
||||
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ class openram_test(unittest.TestCase):
|
|||
tempspice = "{}.sp".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
|
||||
if not OPTS.netlist_only:
|
||||
a.gds_write("{0}{1}".format(OPTS.openram_temp, tempgds))
|
||||
|
|
|
|||
Loading…
Reference in New Issue