mirror of https://github.com/VLSIDA/OpenRAM.git
PEP8 cleanup. Un-hard-code bitcell layers. Remove dead variable.
This commit is contained in:
parent
18c8ad265e
commit
b32c123dab
|
|
@ -51,23 +51,21 @@ class simulation():
|
|||
self.load = tech.spice["dff_in_cap"] * 4
|
||||
|
||||
self.v_high = self.vdd_voltage - tech.spice["nom_threshold"]
|
||||
self.v_low = tech.spice["nom_threshold"]
|
||||
self.v_low = tech.spice["nom_threshold"]
|
||||
self.gnd_voltage = 0
|
||||
|
||||
def create_signal_names(self):
|
||||
self.addr_name = "a"
|
||||
self.din_name = "din"
|
||||
self.dout_name = "dout"
|
||||
self.pins = self.gen_pin_names(port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||
port_info=(len(self.all_ports),self.write_ports,self.read_ports),
|
||||
self.pins = self.gen_pin_names(port_signal_names=(self.addr_name, self.din_name, self.dout_name),
|
||||
port_info=(len(self.all_ports), self.write_ports, self.read_ports),
|
||||
abits=self.addr_size,
|
||||
dbits=self.word_size + self.num_spare_cols)
|
||||
debug.check(len(self.sram.pins) == len(self.pins),
|
||||
"Number of pins generated for characterization \
|
||||
do not match pins of SRAM\nsram.pins = {0}\npin_names = {1}".format(self.sram.pins,
|
||||
self.pins))
|
||||
#This is TODO once multiport control has been finalized.
|
||||
#self.control_name = "CSB"
|
||||
self.pins))
|
||||
|
||||
def set_stimulus_variables(self):
|
||||
# Clock signals
|
||||
|
|
@ -96,7 +94,7 @@ class simulation():
|
|||
|
||||
def add_control_one_port(self, port, op):
|
||||
"""Appends control signals for operation to a given port"""
|
||||
#Determine values to write to port
|
||||
# Determine values to write to port
|
||||
web_val = 1
|
||||
csb_val = 1
|
||||
if op == "read":
|
||||
|
|
@ -406,7 +404,9 @@ class simulation():
|
|||
return pin_names
|
||||
|
||||
def add_graph_exclusions(self):
|
||||
"""Exclude portions of SRAM from timing graph which are not relevant"""
|
||||
"""
|
||||
Exclude portions of SRAM from timing graph which are not relevant
|
||||
"""
|
||||
|
||||
# other initializations can only be done during analysis when a bit has been selected
|
||||
# for testing.
|
||||
|
|
@ -417,7 +417,9 @@ class simulation():
|
|||
self.sram.bank.bitcell_array.graph_exclude_replica_col_bits()
|
||||
|
||||
def set_internal_spice_names(self):
|
||||
"""Sets important names for characterization such as Sense amp enable and internal bit nets."""
|
||||
"""
|
||||
Sets important names for characterization such as Sense amp enable and internal bit nets.
|
||||
"""
|
||||
|
||||
port = self.read_ports[0]
|
||||
if not OPTS.use_pex:
|
||||
|
|
@ -458,11 +460,10 @@ class simulation():
|
|||
|
||||
self.sen_name = self.get_sen_name(self.graph.all_paths)
|
||||
debug.info(2, "s_en name = {}".format(self.sen_name))
|
||||
|
||||
|
||||
self.bl_name = "bl{0}_{1}".format(port, OPTS.word_size - 1)
|
||||
self.br_name = "br{0}_{1}".format(port, OPTS.word_size - 1)
|
||||
debug.info(2, "bl name={}, br name={}".format(self.bl_name, self.br_name))
|
||||
debug.info(2, "bl name={}, br name={}".format(self.bl_name, self.br_name))
|
||||
|
||||
def get_sen_name(self, paths, assumed_port=None):
|
||||
"""
|
||||
|
|
@ -481,7 +482,9 @@ class simulation():
|
|||
return sen_name
|
||||
|
||||
def create_graph(self):
|
||||
"""Creates timing graph to generate the timing paths for the SRAM output."""
|
||||
"""
|
||||
Creates timing graph to generate the timing paths for the SRAM output.
|
||||
"""
|
||||
|
||||
self.sram.clear_exclude_bits() # Removes previous bit exclusions
|
||||
self.sram.graph_exclude_bits(self.wordline_row, self.bitline_column)
|
||||
|
|
@ -492,7 +495,9 @@ class simulation():
|
|||
self.sram.build_graph(self.graph, self.sram_instance_name, self.pins)
|
||||
|
||||
def get_bl_name_search_exclusions(self):
|
||||
"""Gets the mods as a set which should be excluded while searching for name."""
|
||||
"""
|
||||
Gets the mods as a set which should be excluded while searching for name.
|
||||
"""
|
||||
|
||||
# Exclude the RBL as it contains bitcells which are not in the main bitcell array
|
||||
# so it makes the search awkward
|
||||
|
|
@ -519,7 +524,9 @@ class simulation():
|
|||
return path_net_name
|
||||
|
||||
def get_bl_name(self, paths, port):
|
||||
"""Gets the signal name associated with the bitlines in the bank."""
|
||||
"""
|
||||
Gets the signal name associated with the bitlines in the bank.
|
||||
"""
|
||||
|
||||
cell_mod = factory.create(module_type=OPTS.bitcell)
|
||||
cell_bl = cell_mod.get_bl_name(port)
|
||||
|
|
|
|||
|
|
@ -67,7 +67,7 @@ class sram():
|
|||
"""Dump config file with all options.
|
||||
Include defaults and anything changed by input config."""
|
||||
f = open(name, "w")
|
||||
var_dict = dict((name, getattr(OPTS, name)) for name in dir(OPTS) if not name.startswith('__') and not callable(getattr(OPTS, name)))
|
||||
var_dict = dict((name, getattr(OPTS, name)) for name in dir(OPTS) if not name.startswith('__') and not callable(getattr(OPTS, name)))
|
||||
for var_name, var_value in var_dict.items():
|
||||
if isinstance(var_value, str):
|
||||
f.write(str(var_name) + " = " + "\"" + str(var_value) + "\"\n")
|
||||
|
|
@ -156,4 +156,4 @@ class sram():
|
|||
oname = OPTS.output_path + OPTS.output_name + "_extended.py"
|
||||
debug.print_raw("Extended Config: Writing to {0}".format(oname))
|
||||
self.extended_config_write(oname)
|
||||
print_time("Extended Config", datetime.datetime.now(), start_time)
|
||||
print_time("Extended Config", datetime.datetime.now(), start_time)
|
||||
|
|
|
|||
|
|
@ -15,9 +15,6 @@ from design import design
|
|||
from verilog import verilog
|
||||
from lef import lef
|
||||
from sram_factory import factory
|
||||
from tech import drc
|
||||
import numpy as np
|
||||
import logical_effort
|
||||
|
||||
|
||||
class sram_base(design, verilog, lef):
|
||||
|
|
@ -43,9 +40,6 @@ class sram_base(design, verilog, lef):
|
|||
if not self.num_spare_cols:
|
||||
self.num_spare_cols = 0
|
||||
|
||||
# For logical effort delay calculations.
|
||||
self.all_mods_except_control_done = False
|
||||
|
||||
def add_pins(self):
|
||||
""" Add pins for entire SRAM. """
|
||||
|
||||
|
|
@ -87,14 +81,16 @@ class sram_base(design, verilog, lef):
|
|||
for bit in range(self.word_size + self.num_spare_cols):
|
||||
self.add_pin("dout{0}[{1}]".format(port, bit), "OUTPUT")
|
||||
|
||||
self.add_pin("vdd","POWER")
|
||||
self.add_pin("gnd","GROUND")
|
||||
self.add_pin("vdd", "POWER")
|
||||
self.add_pin("gnd", "GROUND")
|
||||
|
||||
def add_global_pex_labels(self):
|
||||
"""
|
||||
Add pex labels at the sram level for spice analysis
|
||||
"""
|
||||
|
||||
|
||||
|
||||
# add pex labels for bitcells
|
||||
for bank_num in range(len(self.bank_insts)):
|
||||
bank = self.bank_insts[bank_num]
|
||||
|
|
@ -111,47 +107,62 @@ class sram_base(design, verilog, lef):
|
|||
bl = []
|
||||
br = []
|
||||
|
||||
storage_layer_name = "m1"
|
||||
bitline_layer_name = "m2"
|
||||
storage_layer_name = self.bitcell.get_pin("Q").layer
|
||||
bitline_layer_name = self.bitcell.get_pin("bl").layer
|
||||
|
||||
for cell in range(len(bank_offset)):
|
||||
Q = [bank_offset[cell][0] + Q_offset[cell][0], bank_offset[cell][1] + Q_offset[cell][1]]
|
||||
Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0], bank_offset[cell][1] + Q_bar_offset[cell][1]]
|
||||
Q = [bank_offset[cell][0] + Q_offset[cell][0],
|
||||
bank_offset[cell][1] + Q_offset[cell][1]]
|
||||
Q_bar = [bank_offset[cell][0] + Q_bar_offset[cell][0],
|
||||
bank_offset[cell][1] + Q_bar_offset[cell][1]]
|
||||
OPTS.words_per_row = self.words_per_row
|
||||
self.add_layout_pin_rect_center("bitcell_Q_b{}_r{}_c{}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.num_words))) , storage_layer_name, Q)
|
||||
self.add_layout_pin_rect_center("bitcell_Q_bar_b{}_r{}_c{}".format(bank_num, int(cell % (OPTS.num_words / self.words_per_row)), int(cell / (OPTS.num_words))), storage_layer_name, Q_bar)
|
||||
row = int(cell % (OPTS.num_words / self.words_per_row))
|
||||
col = int(cell / (OPTS.num_words))
|
||||
self.add_layout_pin_rect_center("bitcell_Q_b{}_r{}_c{}".format(bank_num,
|
||||
row,
|
||||
col),
|
||||
storage_layer_name,
|
||||
Q)
|
||||
self.add_layout_pin_rect_center("bitcell_Q_bar_b{}_r{}_c{}".format(bank_num,
|
||||
row,
|
||||
col),
|
||||
storage_layer_name,
|
||||
Q_bar)
|
||||
|
||||
for cell in range(len(bl_offsets)):
|
||||
col = bl_meta[cell][0][2]
|
||||
for bitline in range(len(bl_offsets[cell])):
|
||||
bitline_location = [float(bank_offset[cell][0]) + bl_offsets[cell][bitline][0], float(bank_offset[cell][1]) + bl_offsets[cell][bitline][1]]
|
||||
bitline_location = [float(bank_offset[cell][0]) + bl_offsets[cell][bitline][0],
|
||||
float(bank_offset[cell][1]) + bl_offsets[cell][bitline][1]]
|
||||
bl.append([bitline_location, bl_meta[cell][bitline][3], col])
|
||||
|
||||
for cell in range(len(br_offsets)):
|
||||
col = br_meta[cell][0][2]
|
||||
for bitline in range(len(br_offsets[cell])):
|
||||
bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0], float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]]
|
||||
br.append([bitline_location, br_meta[cell][bitline][3], col])
|
||||
bitline_location = [float(bank_offset[cell][0]) + br_offsets[cell][bitline][0],
|
||||
float(bank_offset[cell][1]) + br_offsets[cell][bitline][1]]
|
||||
br.append([bitline_location, br_meta[cell][bitline][3], col])
|
||||
|
||||
for i in range(len(bl)):
|
||||
self.add_layout_pin_rect_center("bl{0}_{1}".format(bl[i][1], bl[i][2]), bitline_layer_name, bl[i][0])
|
||||
self.add_layout_pin_rect_center("bl{0}_{1}".format(bl[i][1], bl[i][2]),
|
||||
bitline_layer_name, bl[i][0])
|
||||
|
||||
for i in range(len(br)):
|
||||
self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]), bitline_layer_name, br[i][0])
|
||||
self.add_layout_pin_rect_center("br{0}_{1}".format(br[i][1], br[i][2]),
|
||||
bitline_layer_name, br[i][0])
|
||||
|
||||
# add pex labels for control logic
|
||||
for i in range (len(self.control_logic_insts)):
|
||||
for i in range(len(self.control_logic_insts)):
|
||||
instance = self.control_logic_insts[i]
|
||||
control_logic_offset = instance.offset
|
||||
for output in instance.mod.output_list:
|
||||
pin = instance.mod.get_pin(output)
|
||||
pin.transform([0,0], instance.mirror, instance.rotate)
|
||||
offset = [control_logic_offset[0] + pin.center()[0], control_logic_offset[1] + pin.center()[1]]
|
||||
self.add_layout_pin_rect_center("{0}{1}".format(pin.name,i), storage_layer_name, offset)
|
||||
|
||||
|
||||
|
||||
|
||||
pin.transform([0, 0], instance.mirror, instance.rotate)
|
||||
offset = [control_logic_offset[0] + pin.center()[0],
|
||||
control_logic_offset[1] + pin.center()[1]]
|
||||
self.add_layout_pin_rect_center("{0}{1}".format(pin.name, i),
|
||||
storage_layer_name,
|
||||
offset)
|
||||
|
||||
def create_netlist(self):
|
||||
""" Netlist creation """
|
||||
|
|
@ -370,10 +381,6 @@ class sram_base(design, verilog, lef):
|
|||
|
||||
self.bank_count = 0
|
||||
|
||||
# The control logic can resize itself based on the other modules.
|
||||
# Requires all other modules added before control logic.
|
||||
self.all_mods_except_control_done = True
|
||||
|
||||
c = reload(__import__(OPTS.control_logic))
|
||||
self.mod_control_logic = getattr(c, OPTS.control_logic)
|
||||
|
||||
|
|
@ -619,6 +626,7 @@ class sram_base(design, verilog, lef):
|
|||
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
|
||||
sp.write("**************************************************\n")
|
||||
# This causes unit test mismatch
|
||||
|
||||
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
|
||||
# sp.write("* User: {0}\n".format(getpass.getuser()))
|
||||
# sp.write(".global {0} {1}\n".format(spice["vdd_name"],
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ Run regression tests/pex test on an extracted pinv to ensure pex functionality
|
|||
with HSPICE.
|
||||
"""
|
||||
import unittest
|
||||
from testutils import header,openram_test
|
||||
import sys,os
|
||||
from testutils import header, openram_test
|
||||
import sys, os
|
||||
sys.path.append(os.path.join(sys.path[0],".."))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
|
|
@ -35,43 +35,43 @@ class hspice_pex_pinv_test(openram_test):
|
|||
|
||||
# generate the pinv
|
||||
prev_purge_value = OPTS.purge_temp
|
||||
OPTS.purge_temp = False # force set purge to false to save the sp file
|
||||
# force set purge to false to save the sp file
|
||||
OPTS.purge_temp = False
|
||||
debug.info(2, "Checking 1x size inverter")
|
||||
tx = pinv.pinv(name="pinv", size=1)
|
||||
tempgds = "{0}{1}.gds".format(OPTS.openram_temp,tx.name)
|
||||
tempgds = "{0}{1}.gds".format(OPTS.openram_temp, tx.name)
|
||||
tx.gds_write(tempgds)
|
||||
tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name)
|
||||
tempsp = "{0}{1}.sp".format(OPTS.openram_temp, tx.name)
|
||||
tx.sp_write(tempsp)
|
||||
|
||||
# make sure that the library simulation is successful\
|
||||
sp_delay = self.simulate_delay(test_module = tempsp,
|
||||
top_level_name = tx.name)
|
||||
if sp_delay is "Failed":
|
||||
# make sure that the library simulation is successful
|
||||
sp_delay = self.simulate_delay(test_module=tempsp,
|
||||
top_level_name=tx.name)
|
||||
if sp_delay == "Failed":
|
||||
self.fail('Library Spice module did not behave as expected')
|
||||
|
||||
# now generate its pex file
|
||||
pex_file = self.run_pex(tx)
|
||||
OPTS.purge_temp = prev_purge_value # restore the old purge value
|
||||
OPTS.purge_temp = prev_purge_value # restore the old purge value
|
||||
# generate simulation for pex, make sure the simulation is successful
|
||||
pex_delay = self.simulate_delay(test_module = pex_file,
|
||||
top_level_name = tx.name)
|
||||
pex_delay = self.simulate_delay(test_module=pex_file,
|
||||
top_level_name=tx.name)
|
||||
# make sure the extracted spice simulated
|
||||
if pex_delay is "Failed":
|
||||
if pex_delay == "Failed":
|
||||
self.fail('Pex file did not behave as expected')
|
||||
|
||||
# if pex data is bigger than original spice file then result is ok
|
||||
# However this may not always be true depending on the netlist provided
|
||||
# comment out for now
|
||||
#debug.info(2,"pex_delay: {0}".format(pex_delay))
|
||||
#debug.info(2,"sp_delay: {0}".format(sp_delay))
|
||||
# debug.info(2,"pex_delay: {0}".format(pex_delay))
|
||||
# debug.info(2,"sp_delay: {0}".format(sp_delay))
|
||||
|
||||
#assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\
|
||||
#.format(pex_delay,sp_delay)
|
||||
# assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\
|
||||
# .format(pex_delay,sp_delay)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
def simulate_delay(self, test_module, top_level_name):
|
||||
from characterizer import charutils
|
||||
from charutils import parse_spice_list
|
||||
# setup simulation
|
||||
sim_file = OPTS.openram_temp + "stim.sp"
|
||||
|
|
@ -87,43 +87,43 @@ class hspice_pex_pinv_test(openram_test):
|
|||
from characterizer import measurements, stimuli
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
sim_file = open(sim_file, "w")
|
||||
simulation = stimuli(sim_file,corner)
|
||||
simulation = stimuli(sim_file, corner)
|
||||
|
||||
# library files
|
||||
simulation.write_include(cir_file)
|
||||
|
||||
# supply voltages
|
||||
simulation.gen_constant(sig_name ="vdd",
|
||||
v_val = tech.spice["nom_supply_voltage"])
|
||||
simulation.gen_constant(sig_name = "gnd",
|
||||
v_val = "0v")
|
||||
simulation.gen_constant(sig_name="vdd",
|
||||
v_val=tech.spice["nom_supply_voltage"])
|
||||
simulation.gen_constant(sig_name="gnd",
|
||||
v_val="0v")
|
||||
|
||||
run_time = tech.spice["feasible_period"] * 4
|
||||
# input voltage
|
||||
clk_period = tech.spice["feasible_period"]
|
||||
simulation.gen_pwl(sig_name ="input",
|
||||
clk_times = [clk_period,clk_period],
|
||||
data_values = [1,0],
|
||||
period = clk_period,
|
||||
slew = 0.001*tech.spice["feasible_period"],
|
||||
setup = 0)
|
||||
simulation.gen_pwl(sig_name="input",
|
||||
clk_times=[clk_period, clk_period],
|
||||
data_values=[1, 0],
|
||||
period=clk_period,
|
||||
slew=0.001 * tech.spice["feasible_period"],
|
||||
setup=0)
|
||||
|
||||
# instantiation of simulated pinv
|
||||
simulation.inst_model(pins = ["input", "output", "vdd", "gnd"],
|
||||
model_name = top_module_name)
|
||||
simulation.inst_model(pins=["input", "output", "vdd", "gnd"],
|
||||
model_name=top_module_name)
|
||||
|
||||
# delay measurement
|
||||
delay_measure = measurements.delay_measure(measure_name = "pinv_delay",
|
||||
trig_name = "input",
|
||||
targ_name = "output",
|
||||
trig_dir_str = "FALL",
|
||||
targ_dir_str = "RISE",
|
||||
has_port = False)
|
||||
delay_measure = measurements.delay_measure(measure_name="pinv_delay",
|
||||
trig_name="input",
|
||||
targ_name="output",
|
||||
trig_dir_str="FALL",
|
||||
targ_dir_str="RISE",
|
||||
has_port=False)
|
||||
trig_td = trag_td = 0.01 * run_time
|
||||
rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"]
|
||||
rest_info = trig_td, trag_td, tech.spice["nom_supply_voltage"]
|
||||
delay_measure.write_measure(simulation, rest_info)
|
||||
|
||||
simulation.write_control(end_time = run_time)
|
||||
simulation.write_control(end_time=run_time)
|
||||
sim_file.close()
|
||||
return simulation
|
||||
|
||||
|
|
|
|||
|
|
@ -34,43 +34,43 @@ class ngspice_pex_pinv_test(openram_test):
|
|||
|
||||
# generate the pinv module
|
||||
prev_purge_value = OPTS.purge_temp
|
||||
OPTS.purge_temp = False # force set purge to false to save the sp file
|
||||
OPTS.purge_temp = False # force set purge to false to save the sp file
|
||||
debug.info(2, "Checking 1x size inverter")
|
||||
tx = pinv.pinv(name="pinv", size=1)
|
||||
tempgds = "{0}{1}.gds".format(OPTS.openram_temp,tx.name)
|
||||
tempgds = "{0}{1}.gds".format(OPTS.openram_temp, tx.name)
|
||||
tx.gds_write(tempgds)
|
||||
tempsp = "{0}{1}.sp".format(OPTS.openram_temp,tx.name)
|
||||
tempsp = "{0}{1}.sp".format(OPTS.openram_temp, tx.name)
|
||||
tx.sp_write(tempsp)
|
||||
|
||||
# make sure that the library simulation is successful
|
||||
sp_delay = self.simulate_delay(test_module = tempsp,
|
||||
top_level_name = tx.name)
|
||||
if sp_delay is "Failed":
|
||||
sp_delay = self.simulate_delay(test_module=tempsp,
|
||||
top_level_name=tx.name)
|
||||
if sp_delay == "Failed":
|
||||
self.fail('Library Spice module did not behave as expected')
|
||||
|
||||
# now generate its pex file
|
||||
pex_file = self.run_pex(tx)
|
||||
OPTS.purge_temp = prev_purge_value # restore the old purge value
|
||||
# restore the old purge value
|
||||
OPTS.purge_temp = prev_purge_value
|
||||
# generate simulation for pex, make sure the simulation is successful
|
||||
pex_delay = self.simulate_delay(test_module = pex_file,
|
||||
top_level_name = tx.name)
|
||||
pex_delay = self.simulate_delay(test_module=pex_file,
|
||||
top_level_name=tx.name)
|
||||
# make sure the extracted spice simulated
|
||||
if pex_delay is "Failed":
|
||||
if pex_delay == "Failed":
|
||||
self.fail('Pex file did not behave as expected')
|
||||
|
||||
# if pex data is bigger than original spice file then result is ok
|
||||
# However this may not always be true depending on the netlist provided
|
||||
# comment out for now
|
||||
#debug.info(2,"pex_delay: {0}".format(pex_delay))
|
||||
#debug.info(2,"sp_delay: {0}".format(sp_delay))
|
||||
# debug.info(2,"pex_delay: {0}".format(pex_delay))
|
||||
# debug.info(2,"sp_delay: {0}".format(sp_delay))
|
||||
|
||||
#assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\
|
||||
#.format(pex_delay,sp_delay)
|
||||
# assert pex_delay > sp_delay, "pex delay {0} is smaller than sp_delay {1}"\
|
||||
# .format(pex_delay,sp_delay)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
def simulate_delay(self, test_module, top_level_name):
|
||||
from characterizer import charutils
|
||||
from charutils import parse_spice_list
|
||||
# setup simulation
|
||||
sim_file = OPTS.openram_temp + "stim.sp"
|
||||
|
|
@ -86,47 +86,46 @@ class ngspice_pex_pinv_test(openram_test):
|
|||
from characterizer import measurements, stimuli
|
||||
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||
sim_file = open(sim_file, "w")
|
||||
simulation = stimuli(sim_file,corner)
|
||||
simulation = stimuli(sim_file, corner)
|
||||
|
||||
# library files
|
||||
simulation.write_include(cir_file)
|
||||
|
||||
# supply voltages
|
||||
simulation.gen_constant(sig_name ="vdd",
|
||||
v_val = tech.spice["nom_supply_voltage"])
|
||||
simulation.gen_constant(sig_name="vdd",
|
||||
v_val=tech.spice["nom_supply_voltage"])
|
||||
# The scn4m_subm and ngspice combination will have a gnd source error:
|
||||
# "Fatal error: instance vgnd is a shorted VSRC"
|
||||
# However, remove gnd power for all techa pass for this test
|
||||
# simulation.gen_constant(sig_name = "gnd",
|
||||
# v_val = "0v")
|
||||
|
||||
|
||||
run_time = tech.spice["feasible_period"] * 4
|
||||
# input voltage
|
||||
clk_period = tech.spice["feasible_period"]
|
||||
simulation.gen_pwl(sig_name ="input",
|
||||
clk_times = [clk_period,clk_period],
|
||||
data_values = [1,0],
|
||||
period = clk_period,
|
||||
slew = 0.001*tech.spice["feasible_period"],
|
||||
setup = 0)
|
||||
simulation.gen_pwl(sig_name="input",
|
||||
clk_times=[clk_period, clk_period],
|
||||
data_values=[1, 0],
|
||||
period=clk_period,
|
||||
slew=0.001 * tech.spice["feasible_period"],
|
||||
setup=0)
|
||||
|
||||
# instantiation of simulated pinv
|
||||
simulation.inst_model(pins = ["input", "output", "vdd", "gnd"],
|
||||
model_name = top_module_name)
|
||||
simulation.inst_model(pins=["input", "output", "vdd", "gnd"],
|
||||
model_name=top_module_name)
|
||||
|
||||
# delay measurement
|
||||
delay_measure = measurements.delay_measure(measure_name = "pinv_delay",
|
||||
trig_name = "input",
|
||||
targ_name = "output",
|
||||
trig_dir_str = "FALL",
|
||||
targ_dir_str = "RISE",
|
||||
has_port = False)
|
||||
delay_measure = measurements.delay_measure(measure_name="pinv_delay",
|
||||
trig_name="input",
|
||||
targ_name="output",
|
||||
trig_dir_str="FALL",
|
||||
targ_dir_str="RISE",
|
||||
has_port=False)
|
||||
trig_td = trag_td = 0.01 * run_time
|
||||
rest_info = trig_td,trag_td,tech.spice["nom_supply_voltage"]
|
||||
rest_info = trig_td, trag_td, tech.spice["nom_supply_voltage"]
|
||||
delay_measure.write_measure(simulation, rest_info)
|
||||
|
||||
simulation.write_control(end_time = run_time)
|
||||
simulation.write_control(end_time=run_time)
|
||||
sim_file.close()
|
||||
return simulation
|
||||
|
||||
|
|
|
|||
|
|
@ -1,319 +0,0 @@
|
|||
#!/usr/bin/env python3
|
||||
# See LICENSE for licensing information.
|
||||
#
|
||||
# Copyright (c) 2016-2019 Regents of the University of California and The Board
|
||||
# of Regents for the Oklahoma Agricultural and Mechanical College
|
||||
# (acting for and on behalf of Oklahoma State University)
|
||||
# All rights reserved.
|
||||
#
|
||||
import unittest
|
||||
from testutils import *
|
||||
import sys,os
|
||||
sys.path.append(os.getenv("OPENRAM_HOME"))
|
||||
import globals
|
||||
from globals import OPTS
|
||||
from sram_factory import factory
|
||||
import debug
|
||||
|
||||
@unittest.skip("SKIPPING 26_pex_test")
|
||||
class sram_func_test(openram_test):
|
||||
|
||||
def runTest(self):
|
||||
config_file = "{}/tests/configs/config".format(os.getenv("OPENRAM_HOME"))
|
||||
globals.init_openram(config_file)
|
||||
|
||||
OPTS.use_pex = True
|
||||
|
||||
# This is a hack to reload the characterizer __init__ with the spice version
|
||||
from importlib import reload
|
||||
import characterizer
|
||||
reload(characterizer)
|
||||
from characterizer import setup_hold
|
||||
if not OPTS.spice_exe:
|
||||
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||
|
||||
self.func_test(bank_num=1)
|
||||
self.func_test(bank_num=2)
|
||||
self.func_test(bank_num=4)
|
||||
|
||||
globals.end_openram()
|
||||
|
||||
def func_test(self, bank_num):
|
||||
|
||||
import sram
|
||||
import tech
|
||||
|
||||
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
|
||||
s = sram.sram(word_size=OPTS.word_size,
|
||||
num_words=OPTS.num_words,
|
||||
num_banks=OPTS.num_banks,
|
||||
name="test_sram1")
|
||||
|
||||
tempspice = OPTS.openram_temp + "temp.sp"
|
||||
tempgds = OPTS.openram_temp + "temp.gds"
|
||||
|
||||
s.sp_write(tempspice)
|
||||
s.gds_write(tempgds)
|
||||
|
||||
self.assertFalse(verify.run_drc(s.name, tempgds))
|
||||
self.assertFalse(verify.run_lvs(s.name, tempgds, tempspice))
|
||||
self.assertFalse(verify.run_pex(s.name, tempgds,
|
||||
tempspice, output=OPTS.openram_temp + "temp_pex.sp"))
|
||||
|
||||
import sp_file
|
||||
stimulus_file = OPTS.openram_temp + "stimulus.sp"
|
||||
a_stimulus = sp_file.sp_file(stimulus_file)
|
||||
self.write_stimulus(a_stimulus)
|
||||
|
||||
simulator_file = OPTS.openram_temp + "simulator.sp"
|
||||
a_simulator = sp_file.sp_file(simulator_file)
|
||||
self.write_simulator(a_simulator)
|
||||
|
||||
result_file = OPTS.openram_temp + "result"
|
||||
|
||||
import os
|
||||
|
||||
if OPTS.spice_name == "hspice":
|
||||
cmd = "hspice -mt 2 -i {0} > {1} ".format(
|
||||
simulator_file, result_file)
|
||||
else:
|
||||
cmd = "ngspice -b -i {0} > {1} ".format(
|
||||
simulator_file, result_file)
|
||||
os.system(cmd)
|
||||
|
||||
import re
|
||||
sp_result = open(result_file, "r")
|
||||
contents = sp_result.read()
|
||||
key = "vr1"
|
||||
val = re.search(
|
||||
r"{0}(\s*)=(\s*)(\d*(.).*)(\s*)(from)".format(key), contents)
|
||||
val = val.group(3)
|
||||
value1 = float(self.convert_voltage_unit(val))
|
||||
|
||||
key = "vr2"
|
||||
val = re.search(
|
||||
r"{0}(\s*)=(\s*)(\d*(.).*)(\s*)(from)".format(key), contents)
|
||||
val = val.group(3)
|
||||
value2 = float(self.convert_voltage_unit(val))
|
||||
|
||||
self.assertTrue(round(value1) > 0.5 * tech.spice["supply_voltage"])
|
||||
self.assertTrue(round(value2) < 0.5 * tech.spice["supply_voltage"])
|
||||
|
||||
|
||||
|
||||
def convert_voltage_unit(self, string):
|
||||
newstring = ""
|
||||
for letter in string:
|
||||
if letter == "m":
|
||||
letter = "10e-3"
|
||||
elif letter == "u":
|
||||
letter = "10e-6"
|
||||
else:
|
||||
letter = letter
|
||||
newstring = str(newstring) + str(letter)
|
||||
return newstring
|
||||
|
||||
def convert_time_unit(self, string):
|
||||
newstring = ""
|
||||
for letter in string:
|
||||
if letter == "f":
|
||||
letter = "10e-15"
|
||||
elif letter == "p":
|
||||
letter = "10e-12"
|
||||
elif letter == "n":
|
||||
letter = "10e-9"
|
||||
elif letter == "u":
|
||||
letter = "10e-6"
|
||||
elif letter == "m":
|
||||
letter = "10e-3"
|
||||
else:
|
||||
letter = letter
|
||||
newstring = str(newstring) + str(letter)
|
||||
return newstring
|
||||
|
||||
def write_simulator(self, sim_file):
|
||||
sim_file.write("\n")
|
||||
import tech
|
||||
time_step = tech.spice["clock_period"]
|
||||
for model in tech.spice["fet_models"]:
|
||||
sim_file.write(".inc " + str(model) + "\n")
|
||||
sim_file.write(".inc stimulus.sp\n")
|
||||
sim_file.write(".inc temp_pex.sp\n")
|
||||
sim_file.write(".options post runlvl=6\n")
|
||||
sim_file.write("\n")
|
||||
|
||||
sim_file.write(
|
||||
"Xsource DATA[0] ADDR[0] ADDR[1] ADDR[2] ADDR[3] CSb WEb WEb_inv OEb clk vdd vss source\n")
|
||||
sim_file.write(
|
||||
"Xsram DATA[0] ADDR[0] ADDR[1] ADDR[2] ADDR[3] CSb WEb OEb clk vdd vss test_sram1\n")
|
||||
sim_file.write("\n")
|
||||
|
||||
sim_file.write(".MEASURE TRAN vr1 AVG V(DATA[0]) FROM ={0}ns TO ={1}ns\n".format(
|
||||
4.5 * tech.spice["clock_period"], 5 * tech.spice["clock_period"]))
|
||||
sim_file.write(".MEASURE TRAN vr2 AVG V(DATA[0]) FROM ={0}ns TO ={1}ns\n".format(
|
||||
9.5 * tech.spice["clock_period"], 10 * tech.spice["clock_period"]))
|
||||
sim_file.write("\n")
|
||||
|
||||
if OPTS.spice_name in ["hspice","xa"]:
|
||||
sim_file.write(".probe v(x*.*)\n")
|
||||
sim_file.write(".tran 0.1ns {0}ns\n".format(
|
||||
10 * tech.spice["clock_period"]))
|
||||
sim_file.write(".end\n")
|
||||
else:
|
||||
sim_file.write(
|
||||
".meas tran DELAY1.0 TRIG v(clk) VAL=0.5 RISE=6 TARG v(DATA[0]) VAL=0.5 TD=0.5n RISE=1\n")
|
||||
sim_file.write(".tran 0.1ns {0}ns\n".format(
|
||||
10 * tech.spice["clock_period"]))
|
||||
sim_file.write(".control\n")
|
||||
sim_file.write("run\n")
|
||||
#sim_file.write("plot CSb WEb OEb \n")
|
||||
#sim_file.write("plot clk DATA0 \n")
|
||||
sim_file.write("quit\n")
|
||||
sim_file.write(".endc\n")
|
||||
sim_file.write(".end\n")
|
||||
sim_file.file.close()
|
||||
|
||||
def write_stimulus(self, sti_file):
|
||||
import tech
|
||||
import sp_file
|
||||
sti_file.write(
|
||||
".subckt source DATA[0] ADDR[0] ADDR[1] ADDR[2] ADDR[3] CSb WEb WEb_inv OEb clk vdd vss\n")
|
||||
|
||||
time_step = tech.spice["clock_period"]
|
||||
|
||||
clk = sp_file.PWL(name="clk", port=["clk", "0"])
|
||||
for i in range(0, 11):
|
||||
clk.write_pulse(i * time_step, time_step, "UP")
|
||||
clk.write_to_sp(sti_file)
|
||||
|
||||
WEB_inv = sp_file.PWL(name="WEb_inv", port=["WEb_inv", "0"])
|
||||
WEB = sp_file.PWL(name="WEB", port=["WEb", "0"])
|
||||
OEb = sp_file.PWL(name="OEb", port=["OEb", "0"])
|
||||
CSb = sp_file.PWL(name="CSb", port=["CSb", "0"])
|
||||
|
||||
# write
|
||||
CSb.write_pulse(0.75 * time_step, time_step, "DN")
|
||||
WEB.write_pulse(0.75 * time_step, time_step, "DN")
|
||||
WEB_inv.write_pulse(0.75 * time_step, time_step, "UP")
|
||||
CSb.write_pulse(1.75 * time_step, time_step, "DN")
|
||||
WEB.write_pulse(1.75 * time_step, time_step, "DN")
|
||||
WEB_inv.write_pulse(1.75 * time_step, time_step, "UP")
|
||||
|
||||
# read
|
||||
OEb.write_pulse(3.75 * time_step, time_step, "DN")
|
||||
CSb.write_pulse(3.75 * time_step, time_step, "DN")
|
||||
|
||||
# write
|
||||
CSb.write_pulse(5.75 * time_step, time_step, "DN")
|
||||
WEB.write_pulse(5.75 * time_step, time_step, "DN")
|
||||
WEB_inv.write_pulse(5.75 * time_step, time_step, "UP")
|
||||
CSb.write_pulse(6.75 * time_step, time_step, "DN")
|
||||
WEB.write_pulse(6.75 * time_step, time_step, "DN")
|
||||
WEB_inv.write_pulse(6.75 * time_step, time_step, "UP")
|
||||
|
||||
# read
|
||||
OEb.write_pulse(8.75 * time_step, time_step, "DN")
|
||||
CSb.write_pulse(8.75 * time_step, time_step, "DN")
|
||||
|
||||
CSb.write_to_sp(sti_file)
|
||||
WEB.write_to_sp(sti_file)
|
||||
WEB_inv.write_to_sp(sti_file)
|
||||
OEb.write_to_sp(sti_file)
|
||||
|
||||
sti_file.write("VA[0] A[0] 0 PWL(0n {0} {1}n {0} {2}n 0 {3}n 0 {4}n {0})\n".format(tech.spice["supply_voltage"], 8.875 * tech.spice[
|
||||
"clock_period"], 13.875 * tech.spice["clock_period"], 14.5 * tech.spice["clock_period"], 14.501 * tech.spice["clock_period"]))
|
||||
sti_file.write("VA[1] A[1] 0 PWL(0n {0} {1}n {0} {2}n 0 {3}n 0 {4}n {0})\n".format(tech.spice["supply_voltage"], 8.875 * tech.spice[
|
||||
"clock_period"], 13.875 * tech.spice["clock_period"], 14.5 * tech.spice["clock_period"], 14.501 * tech.spice["clock_period"]))
|
||||
sti_file.write("VA[2] A[2] 0 PWL(0n {0} {1}n {0} {2}n 0 {3}n 0 {4}n {0})\n".format(tech.spice["supply_voltage"], 8.875 * tech.spice[
|
||||
"clock_period"], 13.875 * tech.spice["clock_period"], 14.5 * tech.spice["clock_period"], 14.501 * tech.spice["clock_period"]))
|
||||
sti_file.write("VA[3] A[3] 0 PWL(0n {0} {1}n {0} {2}n 0 {3}n 0 {4}n {0})\n".format(tech.spice["supply_voltage"], 8.875 * tech.spice[
|
||||
"clock_period"], 13.875 * tech.spice["clock_period"], 14.5 * tech.spice["clock_period"], 14.501 * tech.spice["clock_period"]))
|
||||
|
||||
sti_file.write(
|
||||
"xA[0]_buff A[0] ADDR[0]_inv ADDR[0] vdd vss test_buf\n")
|
||||
sti_file.write(
|
||||
"xA[1]_buff A[1] ADDR[1]_inv ADDR[1] vdd vss test_buf\n")
|
||||
sti_file.write(
|
||||
"xA[2]_buff A[2] ADDR[2]_inv ADDR[2] vdd vss test_buf\n")
|
||||
sti_file.write(
|
||||
"xA[3]_buff A[3] ADDR[3]_inv ADDR[3] vdd vss test_buf\n")
|
||||
|
||||
VD_0 = sp_file.PWL(name="VD[0]", port=["D[0]", "0"])
|
||||
VD_0.write_pulse(0, 5 * time_step, "S1")
|
||||
VD_0.write_pulse(5 * time_step, 5 * time_step, "S0")
|
||||
VD_0.write_to_sp(sti_file)
|
||||
|
||||
sti_file.write(
|
||||
"xD[0]_buff D[0] DATA[0]_inv DATA[0]s vdd vss test_buf\n")
|
||||
sti_file.write(
|
||||
"xD[0]_gate DATA[0]s WEb WEb_inv DATA[0] vdd vss tran_gate\n")
|
||||
sti_file.write("mp[0]_gate_vdd vdd write_v DATA[0] vdd " + str(tech.spice["pmos"]) +
|
||||
" w=" + str(2 * tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write("mn[0]_gate_vss vss write_g DATA[0] vss " + str(tech.spice["nmos"]) +
|
||||
" w=" + str(tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
|
||||
Vwrite_v = sp_file.PWL(name="write_v", port=["write_vs", "0"])
|
||||
Vwrite_v.write_pulse(0, 0.5 * time_step, "S1")
|
||||
Vwrite_v.write_pulse(7.5 * time_step, time_step, "DN")
|
||||
Vwrite_v.write_to_sp(sti_file)
|
||||
sti_file.write(
|
||||
"xwrite_v write_vs write_v_inv write_v vdd vss test_buf\n")
|
||||
|
||||
Vwrite_g = sp_file.PWL(name="write_g", port=["write_gs", "0"])
|
||||
Vwrite_g.write_pulse(0, 0.5 * time_step, "S0")
|
||||
Vwrite_g.write_pulse(3 * time_step, time_step, "UP")
|
||||
Vwrite_g.write_to_sp(sti_file)
|
||||
sti_file.write(
|
||||
"xwrite_g write_gs write_g_inv write_g vdd vss test_buf\n")
|
||||
|
||||
sti_file.write("Vdd vdd 0 DC " +
|
||||
str(tech.spice["supply_voltage"]) + "\n")
|
||||
sti_file.write("Vvss vss 0 DC 0\n")
|
||||
sti_file.write(".ENDS source\n")
|
||||
sti_file.write("\n")
|
||||
|
||||
sti_file.write(".SUBCKT tran_gate in gate gate_inv out vdd vss\n")
|
||||
sti_file.write("mp0 in gate out vdd " + str(tech.spice["pmos"]) +
|
||||
" w=" + str(2 * tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write("mn0 in gate_inv out vss " + str(tech.spice["nmos"]) +
|
||||
" w=" + str(tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write(".ENDS tran_gate\n")
|
||||
sti_file.write("\n")
|
||||
|
||||
sti_file.write(".SUBCKT test_buf in out_inv out_buf vdd vss\n")
|
||||
sti_file.write("mpinv1 out_inv in vdd vdd " + str(tech.spice["pmos"]) +
|
||||
" w=" + str(2 * tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write("mninv1 out_inv in vss vss " + str(tech.spice["nmos"]) +
|
||||
" w=" + str(tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write("mpinv2 out_buf out_inv vdd vdd " + str(tech.spice["pmos"]) +
|
||||
" w=" + str(2 * tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write("mninv2 out_buf out_inv vss vss " + str(tech.spice["nmos"]) +
|
||||
" w=" + str(tech.parameter["min_tx_size"]) + "u" +
|
||||
" l=" + str(tech.drc["minlength_channel"]) + "u" +
|
||||
"\n")
|
||||
sti_file.write(".ENDS test_buf\n")
|
||||
sti_file.write("\n")
|
||||
|
||||
sti_file.file.close()
|
||||
|
||||
|
||||
# run the test from the command line
|
||||
if __name__ == "__main__":
|
||||
(OPTS, args) = globals.parse_args()
|
||||
del sys.argv[1:]
|
||||
header(__file__, OPTS.tech_name)
|
||||
unittest.main(testRunner=debugTestRunner())
|
||||
|
|
@ -295,11 +295,8 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False):
|
|||
|
||||
global num_pex_runs
|
||||
num_pex_runs += 1
|
||||
#debug.warning("PEX using magic not implemented.")
|
||||
#return 1
|
||||
os.chdir(OPTS.openram_temp)
|
||||
|
||||
from tech import drc
|
||||
if output == None:
|
||||
output = name + ".pex.netlist"
|
||||
|
||||
|
|
@ -312,17 +309,11 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False):
|
|||
# pex_fix did run the pex using a script while dev orignial method
|
||||
# use batch mode.
|
||||
# the dev old code using batch mode does not run and is split into functions
|
||||
#pex_runset = write_batch_pex_rule(gds_name,name,sp_name,output)
|
||||
pex_runset = write_script_pex_rule(gds_name,name,output)
|
||||
pex_runset = write_script_pex_rule(gds_name, name, output)
|
||||
|
||||
errfile = "{0}{1}.pex.err".format(OPTS.openram_temp, name)
|
||||
outfile = "{0}{1}.pex.out".format(OPTS.openram_temp, name)
|
||||
|
||||
# bash mode command from dev branch
|
||||
#batch_cmd = "{0} -gui -pex {1}pex_runset -batch 2> {2} 1> {3}".format(OPTS.pex_exe,
|
||||
# OPTS.openram_temp,
|
||||
# errfile,
|
||||
# outfile)
|
||||
script_cmd = "{0} 2> {1} 1> {2}".format(pex_runset,
|
||||
errfile,
|
||||
outfile)
|
||||
|
|
@ -334,8 +325,8 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False):
|
|||
pex_nelist = open(output, 'r')
|
||||
s = pex_nelist.read()
|
||||
pex_nelist.close()
|
||||
s = s.replace('pfet','p')
|
||||
s = s.replace('nfet','n')
|
||||
s = s.replace('pfet', 'p')
|
||||
s = s.replace('nfet', 'n')
|
||||
f = open(output, 'w')
|
||||
f.write(s)
|
||||
f.close()
|
||||
|
|
@ -345,12 +336,13 @@ def run_pex(name, gds_name, sp_name, output=None, final_verification=False):
|
|||
results = f.readlines()
|
||||
f.close()
|
||||
out_errors = find_error(results)
|
||||
debug.check(os.path.isfile(output),"Couldn't find PEX extracted output.")
|
||||
debug.check(os.path.isfile(output), "Couldn't find PEX extracted output.")
|
||||
|
||||
correct_port(name,output,sp_name)
|
||||
correct_port(name, output, sp_name)
|
||||
return out_errors
|
||||
|
||||
def write_batch_pex_rule(gds_name,name,sp_name,output):
|
||||
|
||||
def write_batch_pex_rule(gds_name, name, sp_name, output):
|
||||
"""
|
||||
The dev branch old batch mode runset
|
||||
2. magic can perform extraction with the following:
|
||||
|
|
@ -394,7 +386,8 @@ def write_batch_pex_rule(gds_name,name,sp_name,output):
|
|||
f.close()
|
||||
return file
|
||||
|
||||
def write_script_pex_rule(gds_name,cell_name,output):
|
||||
|
||||
def write_script_pex_rule(gds_name, cell_name, output):
|
||||
global OPTS
|
||||
run_file = OPTS.openram_temp + "run_pex.sh"
|
||||
f = open(run_file, "w")
|
||||
|
|
@ -412,23 +405,24 @@ def write_script_pex_rule(gds_name,cell_name,output):
|
|||
pre = "#"
|
||||
else:
|
||||
pre = ""
|
||||
f.write(pre+"extract\n".format(cell_name))
|
||||
f.write(pre+"ext2spice hierarchy off\n")
|
||||
f.write(pre+"ext2spice format ngspice\n")
|
||||
f.write(pre+"ext2spice renumber off\n")
|
||||
f.write(pre+"ext2spice scale off\n")
|
||||
f.write(pre+"ext2spice blackbox on\n")
|
||||
f.write(pre+"ext2spice subcircuit top on\n")
|
||||
f.write(pre+"ext2spice global off\n")
|
||||
f.write(pre+"ext2spice {}\n".format(cell_name))
|
||||
f.write(pre + "extract\n")
|
||||
f.write(pre + "ext2spice hierarchy off\n")
|
||||
f.write(pre + "ext2spice format ngspice\n")
|
||||
f.write(pre + "ext2spice renumber off\n")
|
||||
f.write(pre + "ext2spice scale off\n")
|
||||
f.write(pre + "ext2spice blackbox on\n")
|
||||
f.write(pre + "ext2spice subcircuit top on\n")
|
||||
f.write(pre + "ext2spice global off\n")
|
||||
f.write(pre + "ext2spice {}\n".format(cell_name))
|
||||
f.write("quit -noprompt\n")
|
||||
f.write("eof\n")
|
||||
f.write("mv {0}.spice {1}\n".format(cell_name,output))
|
||||
f.write("mv {0}.spice {1}\n".format(cell_name, output))
|
||||
|
||||
f.close()
|
||||
os.system("chmod u+x {}".format(run_file))
|
||||
return run_file
|
||||
|
||||
|
||||
def find_error(results):
|
||||
# Errors begin with "ERROR:"
|
||||
test = re.compile("ERROR:")
|
||||
|
|
@ -438,6 +432,7 @@ def find_error(results):
|
|||
out_errors = len(stdouterrors)
|
||||
return out_errors
|
||||
|
||||
|
||||
def correct_port(name, output_file_name, ref_file_name):
|
||||
pex_file = open(output_file_name, "r")
|
||||
contents = pex_file.read()
|
||||
|
|
@ -456,9 +451,9 @@ def correct_port(name, output_file_name, ref_file_name):
|
|||
for bank in range(OPTS.num_banks):
|
||||
for bank in range(OPTS.num_banks):
|
||||
row = int(OPTS.num_words / OPTS.words_per_row) - 1
|
||||
col = int(OPTS.word_size * OPTS.words_per_row) - 1
|
||||
bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank,row,col)
|
||||
bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank,row,col)
|
||||
col = int(OPTS.word_size * OPTS.words_per_row) - 1
|
||||
bitcell_list += "bitcell_Q_b{0}_r{1}_c{2} ".format(bank, row, col)
|
||||
bitcell_list += "bitcell_Q_bar_b{0}_r{1}_c{2} ".format(bank, row, col)
|
||||
for col in range(OPTS.word_size * OPTS.words_per_row):
|
||||
for port in range(OPTS.num_r_ports + OPTS.num_w_ports + OPTS.num_rw_ports):
|
||||
bitcell_list += "bl{0}_{1} ".format(bank, col)
|
||||
|
|
@ -484,13 +479,18 @@ def correct_port(name, output_file_name, ref_file_name):
|
|||
# write the new pex file with info in the memory
|
||||
output_file = open(output_file_name, "w")
|
||||
output_file.write(part1)
|
||||
output_file.write(circuit_title+'\n')
|
||||
output_file.write(circuit_title + '\n')
|
||||
output_file.write(part2)
|
||||
output_file.close()
|
||||
|
||||
|
||||
def print_drc_stats():
|
||||
debug.info(1,"DRC runs: {0}".format(num_drc_runs))
|
||||
debug.info(1, "DRC runs: {0}".format(num_drc_runs))
|
||||
|
||||
|
||||
def print_lvs_stats():
|
||||
debug.info(1,"LVS runs: {0}".format(num_lvs_runs))
|
||||
debug.info(1, "LVS runs: {0}".format(num_lvs_runs))
|
||||
|
||||
|
||||
def print_pex_stats():
|
||||
debug.info(1,"PEX runs: {0}".format(num_pex_runs))
|
||||
debug.info(1, "PEX runs: {0}".format(num_pex_runs))
|
||||
|
|
|
|||
Loading…
Reference in New Issue