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):
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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."""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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))
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue