mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport
This commit is contained in:
commit
40450ac0f5
|
|
@ -3,6 +3,7 @@ import gdsMill
|
||||||
import tech
|
import tech
|
||||||
import math
|
import math
|
||||||
import globals
|
import globals
|
||||||
|
import debug
|
||||||
from vector import vector
|
from vector import vector
|
||||||
from pin_layout import pin_layout
|
from pin_layout import pin_layout
|
||||||
|
|
||||||
|
|
@ -65,6 +66,7 @@ def get_gds_size(name, gds_filename, units, layer):
|
||||||
Open a GDS file and return the size from either the
|
Open a GDS file and return the size from either the
|
||||||
bounding box or a border layer.
|
bounding box or a border layer.
|
||||||
"""
|
"""
|
||||||
|
debug.info(2,"Creating VLSI layout for {}".format(name))
|
||||||
cell_vlsi = gdsMill.VlsiLayout(units=units)
|
cell_vlsi = gdsMill.VlsiLayout(units=units)
|
||||||
reader = gdsMill.Gds2reader(cell_vlsi)
|
reader = gdsMill.Gds2reader(cell_vlsi)
|
||||||
reader.loadFromFile(gds_filename)
|
reader.loadFromFile(gds_filename)
|
||||||
|
|
@ -72,6 +74,7 @@ def get_gds_size(name, gds_filename, units, layer):
|
||||||
cell = {}
|
cell = {}
|
||||||
measure_result = cell_vlsi.getLayoutBorder(layer)
|
measure_result = cell_vlsi.getLayoutBorder(layer)
|
||||||
if measure_result == None:
|
if measure_result == None:
|
||||||
|
debug.info(2,"Layout border failed. Trying to measure size for {}".format(name))
|
||||||
measure_result = cell_vlsi.measureSize(name)
|
measure_result = cell_vlsi.measureSize(name)
|
||||||
# returns width,height
|
# returns width,height
|
||||||
return measure_result
|
return measure_result
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
import design
|
||||||
|
import debug
|
||||||
|
import utils
|
||||||
|
from tech import GDS,layer
|
||||||
|
|
||||||
|
class bitcell_1rw_1r(design.design):
|
||||||
|
"""
|
||||||
|
A single bit cell (6T, 8T, etc.) This module implements the
|
||||||
|
single memory cell used in the design. It is a hand-made cell, so
|
||||||
|
the layout and netlist should be available in the technology
|
||||||
|
library.
|
||||||
|
"""
|
||||||
|
|
||||||
|
pin_names = ["bl0", "br0", "bl1", "br1", "wl0", "wl1", "vdd", "gnd"]
|
||||||
|
(width,height) = utils.get_libcell_size("cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||||
|
pin_map = utils.get_libcell_pins(pin_names, "cell_1rw_1r", GDS["unit"], layer["boundary"])
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
design.design.__init__(self, "cell_1rw_1r")
|
||||||
|
debug.info(2, "Create bitcell with 1RW and 1R Port")
|
||||||
|
|
||||||
|
self.width = bitcell.width
|
||||||
|
self.height = bitcell.height
|
||||||
|
self.pin_map = bitcell.pin_map
|
||||||
|
|
||||||
|
def analytical_delay(self, slew, load=0, swing = 0.5):
|
||||||
|
# delay of bit cell is not like a driver(from WL)
|
||||||
|
# so the slew used should be 0
|
||||||
|
# it should not be slew dependent?
|
||||||
|
# because the value is there
|
||||||
|
# the delay is only over half transsmission gate
|
||||||
|
from tech import spice
|
||||||
|
r = spice["min_tx_r"]*3
|
||||||
|
c_para = spice["min_tx_drain_c"]
|
||||||
|
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = swing)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def list_bitcell_pins(self, col, row):
|
||||||
|
""" Creates a list of connections in the bitcell, indexed by column and row, for instance use in bitcell_array """
|
||||||
|
bitcell_pins = ["bl0[{0}]".format(col),
|
||||||
|
"br0[{0}]".format(col),
|
||||||
|
"bl1[{0}]".format(col),
|
||||||
|
"br1[{0}]".format(col),
|
||||||
|
"wl0[{0}]".format(row),
|
||||||
|
"wl1[{0}]".format(row),
|
||||||
|
"vdd",
|
||||||
|
"gnd"]
|
||||||
|
return bitcell_pins
|
||||||
|
|
||||||
|
def list_all_wl_names(self):
|
||||||
|
""" Creates a list of all wordline pin names """
|
||||||
|
row_pins = ["wl0", "wl1"]
|
||||||
|
return row_pins
|
||||||
|
|
||||||
|
def list_all_bitline_names(self):
|
||||||
|
""" Creates a list of all bitline pin names (both bl and br) """
|
||||||
|
column_pins = ["bl0", "br0", "bl1", "br1"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_all_bl_names(self):
|
||||||
|
""" Creates a list of all bl pins names """
|
||||||
|
column_pins = ["bl0", "bl1"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_all_br_names(self):
|
||||||
|
""" Creates a list of all br pins names """
|
||||||
|
column_pins = ["br0", "br1"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_read_bl_names(self):
|
||||||
|
""" Creates a list of bl pin names associated with read ports """
|
||||||
|
column_pins = ["bl0", "bl1"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_read_br_names(self):
|
||||||
|
""" Creates a list of br pin names associated with read ports """
|
||||||
|
column_pins = ["br0", "br1"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_write_bl_names(self):
|
||||||
|
""" Creates a list of bl pin names associated with write ports """
|
||||||
|
column_pins = ["bl0"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def list_write_br_names(self):
|
||||||
|
""" Creates a list of br pin names asscociated with write ports"""
|
||||||
|
column_pins = ["br0"]
|
||||||
|
return column_pins
|
||||||
|
|
||||||
|
def analytical_power(self, proc, vdd, temp, load):
|
||||||
|
"""Bitcell power in nW. Only characterizes leakage."""
|
||||||
|
from tech import spice
|
||||||
|
leakage = spice["bitcell_leakage"]
|
||||||
|
dynamic = 0 #temporary
|
||||||
|
total_power = self.return_power(dynamic, leakage)
|
||||||
|
return total_power
|
||||||
|
|
||||||
|
|
@ -6,6 +6,7 @@ from .lib import *
|
||||||
from .delay import *
|
from .delay import *
|
||||||
from .setup_hold import *
|
from .setup_hold import *
|
||||||
from .functional import *
|
from .functional import *
|
||||||
|
from .worst_case import *
|
||||||
from .simulation import *
|
from .simulation import *
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -7,8 +7,9 @@ from .trim_spice import *
|
||||||
from .charutils import *
|
from .charutils import *
|
||||||
import utils
|
import utils
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
|
from .simulation import simulation
|
||||||
|
|
||||||
class delay():
|
class delay(simulation):
|
||||||
"""Functions to measure the delay and power of an SRAM at a given address and
|
"""Functions to measure the delay and power of an SRAM at a given address and
|
||||||
data bit.
|
data bit.
|
||||||
|
|
||||||
|
|
@ -26,27 +27,14 @@ class delay():
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, sram, spfile, corner):
|
def __init__(self, sram, spfile, corner):
|
||||||
self.sram = sram
|
simulation.__init__(self, sram, spfile, corner)
|
||||||
self.name = sram.name
|
|
||||||
self.word_size = self.sram.word_size
|
|
||||||
self.addr_size = self.sram.addr_size
|
|
||||||
self.num_cols = self.sram.num_cols
|
|
||||||
self.num_rows = self.sram.num_rows
|
|
||||||
self.num_banks = self.sram.num_banks
|
|
||||||
self.sp_file = spfile
|
|
||||||
|
|
||||||
self.total_ports = self.sram.total_ports
|
|
||||||
self.total_write = self.sram.total_write
|
|
||||||
self.total_read = self.sram.total_read
|
|
||||||
self.read_index = self.sram.read_index
|
|
||||||
self.write_index = self.sram.write_index
|
|
||||||
self.port_id = self.sram.port_id
|
|
||||||
|
|
||||||
# These are the member variables for a simulation
|
# These are the member variables for a simulation
|
||||||
|
self.targ_read_ports = []
|
||||||
|
self.targ_write_ports = []
|
||||||
self.period = 0
|
self.period = 0
|
||||||
self.set_load_slew(0,0)
|
self.set_load_slew(0,0)
|
||||||
self.set_corner(corner)
|
self.set_corner(corner)
|
||||||
self.create_port_names()
|
|
||||||
self.create_signal_names()
|
self.create_signal_names()
|
||||||
|
|
||||||
#Create global measure names. Should maybe be an input at some point.
|
#Create global measure names. Should maybe be an input at some point.
|
||||||
|
|
@ -66,34 +54,6 @@ class delay():
|
||||||
#This is TODO once multiport control has been finalized.
|
#This is TODO once multiport control has been finalized.
|
||||||
#self.control_name = "CSB"
|
#self.control_name = "CSB"
|
||||||
|
|
||||||
def create_port_names(self):
|
|
||||||
"""Generates the port names to be used in characterization and sets default simulation target ports"""
|
|
||||||
self.write_ports = []
|
|
||||||
self.read_ports = []
|
|
||||||
self.total_port_num = OPTS.num_rw_ports + OPTS.num_w_ports + OPTS.num_r_ports
|
|
||||||
|
|
||||||
#save a member variable to avoid accessing global. readwrite ports have different control signals.
|
|
||||||
self.readwrite_port_num = OPTS.num_rw_ports
|
|
||||||
|
|
||||||
#Generate the port names. readwrite ports are required to be added first for this to work.
|
|
||||||
for readwrite_port_num in range(OPTS.num_rw_ports):
|
|
||||||
self.read_ports.append(readwrite_port_num)
|
|
||||||
self.write_ports.append(readwrite_port_num)
|
|
||||||
#This placement is intentional. It makes indexing input data easier. See self.data_values
|
|
||||||
for write_port_num in range(OPTS.num_rw_ports, OPTS.num_rw_ports+OPTS.num_w_ports):
|
|
||||||
self.write_ports.append(write_port_num)
|
|
||||||
for read_port_num in range(OPTS.num_rw_ports+OPTS.num_w_ports, OPTS.num_rw_ports+OPTS.num_w_ports+OPTS.num_r_ports):
|
|
||||||
self.read_ports.append(read_port_num)
|
|
||||||
|
|
||||||
#Set the default target ports for simulation. Default is all the ports.
|
|
||||||
self.targ_read_ports = self.read_ports
|
|
||||||
self.targ_write_ports = self.write_ports
|
|
||||||
|
|
||||||
def set_corner(self,corner):
|
|
||||||
""" Set the corner values """
|
|
||||||
self.corner = corner
|
|
||||||
(self.process, self.vdd_voltage, self.temperature) = corner
|
|
||||||
|
|
||||||
def set_load_slew(self,load,slew):
|
def set_load_slew(self,load,slew):
|
||||||
""" Set the load and slew """
|
""" Set the load and slew """
|
||||||
self.load = load
|
self.load = load
|
||||||
|
|
@ -113,9 +73,9 @@ class delay():
|
||||||
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
debug.error("Given probe_data is not an integer to specify a data bit",1)
|
||||||
|
|
||||||
#Adding port options here which the characterizer cannot handle. Some may be added later like ROM
|
#Adding port options here which the characterizer cannot handle. Some may be added later like ROM
|
||||||
if len(self.read_ports) == 0:
|
if len(self.read_index) == 0:
|
||||||
debug.error("Characterizer does not currently support SRAMs without read ports.",1)
|
debug.error("Characterizer does not currently support SRAMs without read ports.",1)
|
||||||
if len(self.write_ports) == 0:
|
if len(self.write_index) == 0:
|
||||||
debug.error("Characterizer does not currently support SRAMs without write ports.",1)
|
debug.error("Characterizer does not currently support SRAMs without write ports.",1)
|
||||||
|
|
||||||
def write_generic_stimulus(self):
|
def write_generic_stimulus(self):
|
||||||
|
|
@ -129,12 +89,12 @@ class delay():
|
||||||
self.sf.write("\n* Instantiation of the SRAM\n")
|
self.sf.write("\n* Instantiation of the SRAM\n")
|
||||||
self.stim.inst_sram(sram=self.sram,
|
self.stim.inst_sram(sram=self.sram,
|
||||||
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
port_signal_names=(self.addr_name,self.din_name,self.dout_name),
|
||||||
port_info=(self.total_port_num,self.write_ports,self.read_ports),
|
port_info=(self.total_ports,self.write_index,self.read_index),
|
||||||
abits=self.addr_size,
|
abits=self.addr_size,
|
||||||
dbits=self.word_size,
|
dbits=self.word_size,
|
||||||
sram_name=self.name)
|
sram_name=self.name)
|
||||||
self.sf.write("\n* SRAM output loads\n")
|
self.sf.write("\n* SRAM output loads\n")
|
||||||
for port in self.read_ports:
|
for port in self.read_index:
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port,i,self.dout_name,self.load))
|
self.sf.write("CD{0}{1} {2}{0}_{1} 0 {3}f\n".format(port,i,self.dout_name,self.load))
|
||||||
|
|
||||||
|
|
@ -172,7 +132,7 @@ class delay():
|
||||||
self.gen_control()
|
self.gen_control()
|
||||||
|
|
||||||
self.sf.write("\n* Generation of Port clock signal\n")
|
self.sf.write("\n* Generation of Port clock signal\n")
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
self.stim.gen_pulse(sig_name="CLK{0}".format(port),
|
self.stim.gen_pulse(sig_name="CLK{0}".format(port),
|
||||||
v1=0,
|
v1=0,
|
||||||
v2=self.vdd_voltage,
|
v2=self.vdd_voltage,
|
||||||
|
|
@ -195,9 +155,6 @@ class delay():
|
||||||
"""
|
"""
|
||||||
self.check_arguments()
|
self.check_arguments()
|
||||||
|
|
||||||
# obtains list of time-points for each rising clk edge
|
|
||||||
#self.create_test_cycles()
|
|
||||||
|
|
||||||
# creates and opens stimulus file for writing
|
# creates and opens stimulus file for writing
|
||||||
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
|
||||||
self.sf = open(temp_stim, "w")
|
self.sf = open(temp_stim, "w")
|
||||||
|
|
@ -214,24 +171,24 @@ class delay():
|
||||||
|
|
||||||
# generate data and addr signals
|
# generate data and addr signals
|
||||||
self.sf.write("\n* Generation of data and address signals\n")
|
self.sf.write("\n* Generation of data and address signals\n")
|
||||||
for write_port in self.write_ports:
|
for write_port in self.write_index:
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
self.stim.gen_constant(sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i),
|
self.stim.gen_constant(sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i),
|
||||||
v_val=0)
|
v_val=0)
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
for i in range(self.addr_size):
|
for i in range(self.addr_size):
|
||||||
self.stim.gen_constant(sig_name="{0}{1}_{2}".format(self.addr_name,port, i),
|
self.stim.gen_constant(sig_name="{0}{1}_{2}".format(self.addr_name,port, i),
|
||||||
v_val=0)
|
v_val=0)
|
||||||
|
|
||||||
# generate control signals
|
# generate control signals
|
||||||
self.sf.write("\n* Generation of control signals\n")
|
self.sf.write("\n* Generation of control signals\n")
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
self.stim.gen_constant(sig_name="CSB{0}".format(port), v_val=self.vdd_voltage)
|
self.stim.gen_constant(sig_name="CSB{0}".format(port), v_val=self.vdd_voltage)
|
||||||
if port in self.write_ports and port in self.read_ports:
|
if port in self.write_index and port in self.read_index:
|
||||||
self.stim.gen_constant(sig_name="WEB{0}".format(port), v_val=self.vdd_voltage)
|
self.stim.gen_constant(sig_name="WEB{0}".format(port), v_val=self.vdd_voltage)
|
||||||
|
|
||||||
self.sf.write("\n* Generation of global clock signal\n")
|
self.sf.write("\n* Generation of global clock signal\n")
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
self.stim.gen_constant(sig_name="CLK{0}".format(port), v_val=0)
|
self.stim.gen_constant(sig_name="CLK{0}".format(port), v_val=0)
|
||||||
|
|
||||||
self.write_power_measures()
|
self.write_power_measures()
|
||||||
|
|
@ -257,10 +214,10 @@ class delay():
|
||||||
trig_name = trig_clk_name
|
trig_name = trig_clk_name
|
||||||
if 'lh' in delay_name:
|
if 'lh' in delay_name:
|
||||||
targ_dir="RISE"
|
targ_dir="RISE"
|
||||||
trig_td = targ_td = self.cycle_times[self.measure_cycles["read1_{0}".format(port)]]
|
trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read1"]]
|
||||||
else:
|
else:
|
||||||
targ_dir="FALL"
|
targ_dir="FALL"
|
||||||
trig_td = targ_td = self.cycle_times[self.measure_cycles["read0_{0}".format(port)]]
|
trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read0"]]
|
||||||
|
|
||||||
elif 'slew' in delay_name:
|
elif 'slew' in delay_name:
|
||||||
trig_name = targ_name
|
trig_name = targ_name
|
||||||
|
|
@ -268,12 +225,12 @@ class delay():
|
||||||
trig_val = trig_slew_low
|
trig_val = trig_slew_low
|
||||||
targ_val = targ_slew_high
|
targ_val = targ_slew_high
|
||||||
targ_dir = trig_dir = "RISE"
|
targ_dir = trig_dir = "RISE"
|
||||||
trig_td = targ_td = self.cycle_times[self.measure_cycles["read1_{0}".format(port)]]
|
trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read1"]]
|
||||||
else:
|
else:
|
||||||
trig_val = targ_slew_high
|
trig_val = targ_slew_high
|
||||||
targ_val = trig_slew_low
|
targ_val = trig_slew_low
|
||||||
targ_dir = trig_dir = "FALL"
|
targ_dir = trig_dir = "FALL"
|
||||||
trig_td = targ_td = self.cycle_times[self.measure_cycles["read0_{0}".format(port)]]
|
trig_td = targ_td = self.cycle_times[self.measure_cycles[port]["read0"]]
|
||||||
else:
|
else:
|
||||||
debug.error(1, "Measure command {0} not recognized".format(delay_name))
|
debug.error(1, "Measure command {0} not recognized".format(delay_name))
|
||||||
return (meas_name,trig_name,targ_name,trig_val,targ_val,trig_dir,targ_dir,trig_td,targ_td)
|
return (meas_name,trig_name,targ_name,trig_val,targ_val,trig_dir,targ_dir,trig_td,targ_td)
|
||||||
|
|
@ -294,11 +251,11 @@ class delay():
|
||||||
#Different naming schemes are used for the measure cycle dict and measurement names.
|
#Different naming schemes are used for the measure cycle dict and measurement names.
|
||||||
#TODO: make them the same so they can be indexed the same.
|
#TODO: make them the same so they can be indexed the same.
|
||||||
if '1' in pname:
|
if '1' in pname:
|
||||||
t_initial = self.cycle_times[self.measure_cycles["read1_{0}".format(port)]]
|
t_initial = self.cycle_times[self.measure_cycles[port]["read1"]]
|
||||||
t_final = self.cycle_times[self.measure_cycles["read1_{0}".format(port)]+1]
|
t_final = self.cycle_times[self.measure_cycles[port]["read1"]+1]
|
||||||
elif '0' in pname:
|
elif '0' in pname:
|
||||||
t_initial = self.cycle_times[self.measure_cycles["read0_{0}".format(port)]]
|
t_initial = self.cycle_times[self.measure_cycles[port]["read0"]]
|
||||||
t_final = self.cycle_times[self.measure_cycles["read0_{0}".format(port)]+1]
|
t_final = self.cycle_times[self.measure_cycles[port]["read0"]+1]
|
||||||
self.stim.gen_meas_power(meas_name="{0}{1}".format(pname, port),
|
self.stim.gen_meas_power(meas_name="{0}{1}".format(pname, port),
|
||||||
t_initial=t_initial,
|
t_initial=t_initial,
|
||||||
t_final=t_final)
|
t_final=t_final)
|
||||||
|
|
@ -311,11 +268,11 @@ class delay():
|
||||||
for pname in self.power_meas_names:
|
for pname in self.power_meas_names:
|
||||||
if "write" not in pname:
|
if "write" not in pname:
|
||||||
continue
|
continue
|
||||||
t_initial = self.cycle_times[self.measure_cycles["write0_{0}".format(port)]]
|
t_initial = self.cycle_times[self.measure_cycles[port]["write0"]]
|
||||||
t_final = self.cycle_times[self.measure_cycles["write0_{0}".format(port)]+1]
|
t_final = self.cycle_times[self.measure_cycles[port]["write0"]+1]
|
||||||
if '1' in pname:
|
if '1' in pname:
|
||||||
t_initial = self.cycle_times[self.measure_cycles["write1_{0}".format(port)]]
|
t_initial = self.cycle_times[self.measure_cycles[port]["write1"]]
|
||||||
t_final = self.cycle_times[self.measure_cycles["write1_{0}".format(port)]+1]
|
t_final = self.cycle_times[self.measure_cycles[port]["write1"]+1]
|
||||||
|
|
||||||
self.stim.gen_meas_power(meas_name="{0}{1}".format(pname, port),
|
self.stim.gen_meas_power(meas_name="{0}{1}".format(pname, port),
|
||||||
t_initial=t_initial,
|
t_initial=t_initial,
|
||||||
|
|
@ -360,10 +317,9 @@ class delay():
|
||||||
double the period until we find a valid period to use as a
|
double the period until we find a valid period to use as a
|
||||||
starting point.
|
starting point.
|
||||||
"""
|
"""
|
||||||
debug.check(port in self.read_ports, "Characterizer requires a read port to determine a period.")
|
debug.check(port in self.read_index, "Characterizer requires a read port to determine a period.")
|
||||||
|
|
||||||
feasible_period = float(tech.spice["feasible_period"])
|
feasible_period = float(tech.spice["feasible_period"])
|
||||||
#feasible_period = float(2.5)#What happens if feasible starting point is wrong?
|
|
||||||
time_out = 9
|
time_out = 9
|
||||||
while True:
|
while True:
|
||||||
time_out -= 1
|
time_out -= 1
|
||||||
|
|
@ -406,19 +362,18 @@ class delay():
|
||||||
Loops through all read ports determining the feasible period and collecting
|
Loops through all read ports determining the feasible period and collecting
|
||||||
delay information from each port.
|
delay information from each port.
|
||||||
"""
|
"""
|
||||||
feasible_delays = [{} for i in range(self.total_port_num)]
|
feasible_delays = [{} for i in range(self.total_ports)]
|
||||||
self.period = float(tech.spice["feasible_period"])
|
|
||||||
|
|
||||||
#Get initial feasible delays from first port
|
#Get initial feasible delays from first port
|
||||||
feasible_delays[self.read_ports[0]] = self.find_feasible_period_one_port(self.read_ports[0])
|
feasible_delays[self.read_index[0]] = self.find_feasible_period_one_port(self.read_index[0])
|
||||||
previous_period = self.period
|
previous_period = self.period
|
||||||
|
|
||||||
|
|
||||||
#Loops through all the ports checks if the feasible period works. Everything restarts it if does not.
|
#Loops through all the ports checks if the feasible period works. Everything restarts it if does not.
|
||||||
#Write ports do not produce delays which is why they are not included here.
|
#Write ports do not produce delays which is why they are not included here.
|
||||||
i = 1
|
i = 1
|
||||||
while i < len(self.read_ports):
|
while i < len(self.read_index):
|
||||||
port = self.read_ports[i]
|
port = self.read_index[i]
|
||||||
#Only extract port values from the specified port, not the entire results.
|
#Only extract port values from the specified port, not the entire results.
|
||||||
feasible_delays[port].update(self.find_feasible_period_one_port(port))
|
feasible_delays[port].update(self.find_feasible_period_one_port(port))
|
||||||
#Function sets the period. Restart the entire process if period changes to collect accurate delays
|
#Function sets the period. Restart the entire process if period changes to collect accurate delays
|
||||||
|
|
@ -461,7 +416,7 @@ class delay():
|
||||||
#Sanity Check
|
#Sanity Check
|
||||||
debug.check(self.period > 0, "Target simulation period non-positive")
|
debug.check(self.period > 0, "Target simulation period non-positive")
|
||||||
|
|
||||||
result = [{} for i in range(self.total_port_num)]
|
result = [{} for i in range(self.total_ports)]
|
||||||
# Checking from not data_value to data_value
|
# Checking from not data_value to data_value
|
||||||
self.write_delay_stimulus()
|
self.write_delay_stimulus()
|
||||||
|
|
||||||
|
|
@ -563,7 +518,7 @@ class delay():
|
||||||
|
|
||||||
#Find the minimum period for all ports. Start at one port and perform binary search then use that delay as a starting position.
|
#Find the minimum period for all ports. Start at one port and perform binary search then use that delay as a starting position.
|
||||||
#For testing purposes, only checks read ports.
|
#For testing purposes, only checks read ports.
|
||||||
for port in self.read_ports:
|
for port in self.read_index:
|
||||||
target_period = self.find_min_period_one_port(feasible_delays, port, lb_period, ub_period, target_period)
|
target_period = self.find_min_period_one_port(feasible_delays, port, lb_period, ub_period, target_period)
|
||||||
#The min period of one port becomes the new lower bound. Reset the upper_bound.
|
#The min period of one port becomes the new lower bound. Reset the upper_bound.
|
||||||
lb_period = target_period
|
lb_period = target_period
|
||||||
|
|
@ -728,8 +683,8 @@ class delay():
|
||||||
"""Simulate all specified output loads and input slews pairs of all ports"""
|
"""Simulate all specified output loads and input slews pairs of all ports"""
|
||||||
measure_data = self.get_empty_measure_data_dict()
|
measure_data = self.get_empty_measure_data_dict()
|
||||||
#Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways.
|
#Set the target simulation ports to all available ports. This make sims slower but failed sims exit anyways.
|
||||||
self.targ_read_ports = self.read_ports
|
self.targ_read_ports = self.read_index
|
||||||
self.targ_write_ports = self.write_ports
|
self.targ_write_ports = self.write_index
|
||||||
for slew in slews:
|
for slew in slews:
|
||||||
for load in loads:
|
for load in loads:
|
||||||
self.set_load_slew(load,slew)
|
self.set_load_slew(load,slew)
|
||||||
|
|
@ -738,7 +693,7 @@ class delay():
|
||||||
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load))
|
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load))
|
||||||
debug.info(1, "Simulation Passed: Port {0} slew={1} load={2}".format("All", self.slew,self.load))
|
debug.info(1, "Simulation Passed: Port {0} slew={1} load={2}".format("All", self.slew,self.load))
|
||||||
#The results has a dict for every port but dicts can be empty (e.g. ports were not targeted).
|
#The results has a dict for every port but dicts can be empty (e.g. ports were not targeted).
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
for mname,value in delay_results[port].items():
|
for mname,value in delay_results[port].items():
|
||||||
if "power" in mname:
|
if "power" in mname:
|
||||||
# Subtract partial array leakage and add full array leakage for the power measures
|
# Subtract partial array leakage and add full array leakage for the power measures
|
||||||
|
|
@ -746,119 +701,8 @@ class delay():
|
||||||
else:
|
else:
|
||||||
measure_data[port][mname].append(value)
|
measure_data[port][mname].append(value)
|
||||||
return measure_data
|
return measure_data
|
||||||
|
|
||||||
def add_data(self, data, port):
|
|
||||||
""" Add the array of data values """
|
|
||||||
debug.check(len(data)==self.word_size, "Invalid data word size.")
|
|
||||||
debug.check(port < len(self.data_values), "Port number cannot index data values.")
|
|
||||||
index = 0
|
|
||||||
for c in data:
|
|
||||||
if c=="0":
|
|
||||||
self.data_values[port][index].append(0)
|
|
||||||
elif c=="1":
|
|
||||||
self.data_values[port][index].append(1)
|
|
||||||
else:
|
|
||||||
debug.error("Non-binary data string",1)
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
def add_address(self, address, port):
|
|
||||||
""" Add the array of address values """
|
|
||||||
debug.check(len(address)==self.addr_size, "Invalid address size.")
|
|
||||||
index = 0
|
|
||||||
for c in address:
|
|
||||||
if c=="0":
|
|
||||||
self.addr_values[port][index].append(0)
|
|
||||||
elif c=="1":
|
|
||||||
self.addr_values[port][index].append(1)
|
|
||||||
else:
|
|
||||||
debug.error("Non-binary address string",1)
|
|
||||||
index += 1
|
|
||||||
|
|
||||||
def add_noop_one_port(self, address, data, port):
|
|
||||||
""" Add the control values for a noop to a single port. """
|
|
||||||
#This is to be used as a helper function for the other add functions. Cycle and comments are omitted.
|
|
||||||
self.add_control_one_port(port, "noop")
|
|
||||||
if port in self.write_ports:
|
|
||||||
self.add_data(data,port)
|
|
||||||
self.add_address(address, port)
|
|
||||||
|
|
||||||
def add_noop_all_ports(self, comment, address, data):
|
|
||||||
""" Add the control values for a noop to all ports. """
|
|
||||||
self.add_comment("All", comment)
|
|
||||||
self.cycle_times.append(self.t_current)
|
|
||||||
self.t_current += self.period
|
|
||||||
|
|
||||||
for port in range(self.total_port_num):
|
|
||||||
self.add_noop_one_port(address, data, port)
|
|
||||||
|
|
||||||
|
|
||||||
def add_read(self, comment, address, data, port):
|
|
||||||
""" Add the control values for a read cycle. """
|
|
||||||
debug.check(port in self.read_ports, "Cannot add read cycle to a write port.")
|
|
||||||
self.add_comment(port, comment)
|
|
||||||
self.cycle_times.append(self.t_current)
|
|
||||||
self.t_current += self.period
|
|
||||||
self.add_control_one_port(port, "read")
|
|
||||||
|
|
||||||
#If the port is also a readwrite then add data.
|
|
||||||
if port in self.write_ports:
|
|
||||||
self.add_data(data,port)
|
|
||||||
self.add_address(address, port)
|
|
||||||
|
|
||||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
|
||||||
noop_data = "0"*self.word_size
|
|
||||||
#Add noops to all other ports.
|
|
||||||
for unselected_port in range(self.total_port_num):
|
|
||||||
if unselected_port != port:
|
|
||||||
self.add_noop_one_port(address, noop_data, unselected_port)
|
|
||||||
|
|
||||||
def add_write(self, comment, address, data, port):
|
|
||||||
""" Add the control values for a write cycle. """
|
|
||||||
debug.check(port in self.write_ports, "Cannot add read cycle to a read port.")
|
|
||||||
self.add_comment(port, comment)
|
|
||||||
self.cycle_times.append(self.t_current)
|
|
||||||
self.t_current += self.period
|
|
||||||
|
|
||||||
self.add_control_one_port(port, "write")
|
|
||||||
self.add_data(data,port)
|
|
||||||
self.add_address(address,port)
|
|
||||||
|
|
||||||
#This value is hard coded here. Possibly change to member variable or set in add_noop_one_port
|
|
||||||
noop_data = "0"*self.word_size
|
|
||||||
#Add noops to all other ports.
|
|
||||||
for unselected_port in range(self.total_port_num):
|
|
||||||
if unselected_port != port:
|
|
||||||
self.add_noop_one_port(address, noop_data, unselected_port)
|
|
||||||
|
|
||||||
def add_control_one_port(self, port, op):
|
|
||||||
"""Appends control signals for operation to a given port"""
|
|
||||||
#Determine values to write to port
|
|
||||||
web_val = 1
|
|
||||||
csb_val = 1
|
|
||||||
if op == "read":
|
|
||||||
csb_val = 0
|
|
||||||
elif op == "write":
|
|
||||||
csb_val = 0
|
|
||||||
web_val = 0
|
|
||||||
elif op != "noop":
|
|
||||||
debug.error("Could not add control signals for port {0}. Command {1} not recognized".format(port,op),1)
|
|
||||||
|
|
||||||
#Append the values depending on the type of port
|
|
||||||
self.csb_values[port].append(csb_val)
|
|
||||||
#If port is in both lists, add rw control signal. Condition indicates its a RW port.
|
|
||||||
if port in self.write_ports and port in self.read_ports:
|
|
||||||
self.web_values[port].append(web_val)
|
|
||||||
|
|
||||||
def add_comment(self, port, comment):
|
|
||||||
"""Add comment to list to be printed in stimulus file"""
|
|
||||||
#Clean up time before appending. Make spacing dynamic as well.
|
|
||||||
time = "{0:.2f} ns:".format(self.t_current)
|
|
||||||
time_spacing = len(time)+6
|
|
||||||
self.cycle_comments.append("Cycle {0:<6d} Port {1:<6} {2:<{3}}: {4}".format(len(self.cycle_times),
|
|
||||||
port,
|
|
||||||
time,
|
|
||||||
time_spacing,
|
|
||||||
comment))
|
|
||||||
def gen_test_cycles_one_port(self, read_port, write_port):
|
def gen_test_cycles_one_port(self, read_port, write_port):
|
||||||
"""Intended but not implemented: Returns a list of key time-points [ns] of the waveform (each rising edge)
|
"""Intended but not implemented: Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||||
of the cycles to do a timing evaluation of a single port. Current: Values overwritten for multiple calls"""
|
of the cycles to do a timing evaluation of a single port. Current: Values overwritten for multiple calls"""
|
||||||
|
|
@ -886,8 +730,7 @@ class delay():
|
||||||
|
|
||||||
self.add_write("W data 0 address 11..11 to write value",
|
self.add_write("W data 0 address 11..11 to write value",
|
||||||
self.probe_address,data_zeros,write_port)
|
self.probe_address,data_zeros,write_port)
|
||||||
self.measure_cycles["write0_{0}".format(write_port)] = len(self.cycle_times)-1
|
self.measure_cycles[write_port]["write0"] = len(self.cycle_times)-1
|
||||||
#self.write0_cycle=len(self.cycle_times)-1 # Remember for power measure
|
|
||||||
|
|
||||||
# This also ensures we will have a H->L transition on the next read
|
# This also ensures we will have a H->L transition on the next read
|
||||||
self.add_read("R data 1 address 00..00 to set DOUT caps",
|
self.add_read("R data 1 address 00..00 to set DOUT caps",
|
||||||
|
|
@ -895,18 +738,14 @@ class delay():
|
||||||
|
|
||||||
self.add_read("R data 0 address 11..11 to check W0 worked",
|
self.add_read("R data 0 address 11..11 to check W0 worked",
|
||||||
self.probe_address,data_zeros,read_port)
|
self.probe_address,data_zeros,read_port)
|
||||||
self.measure_cycles["read0_{0}".format(read_port)] = len(self.cycle_times)-1
|
self.measure_cycles[read_port]["read0"] = len(self.cycle_times)-1
|
||||||
#self.read0_cycle=len(self.cycle_times)-1 # Remember for power measure
|
|
||||||
|
|
||||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)",
|
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle)",
|
||||||
inverse_address,data_zeros)
|
inverse_address,data_zeros)
|
||||||
#Does not seem like is is used anywhere commenting out for now.
|
|
||||||
#self.idle_cycle=len(self.cycle_times)-1 # Remember for power measure
|
|
||||||
|
|
||||||
self.add_write("W data 1 address 11..11 to write value",
|
self.add_write("W data 1 address 11..11 to write value",
|
||||||
self.probe_address,data_ones,write_port)
|
self.probe_address,data_ones,write_port)
|
||||||
self.measure_cycles["write1_{0}".format(write_port)] = len(self.cycle_times)-1
|
self.measure_cycles[write_port]["write1"] = len(self.cycle_times)-1
|
||||||
#self.write1_cycle=len(self.cycle_times)-1 # Remember for power measure
|
|
||||||
|
|
||||||
self.add_write("W data 0 address 00..00 to clear DIN caps",
|
self.add_write("W data 0 address 00..00 to clear DIN caps",
|
||||||
inverse_address,data_zeros,write_port)
|
inverse_address,data_zeros,write_port)
|
||||||
|
|
@ -917,19 +756,22 @@ class delay():
|
||||||
|
|
||||||
self.add_read("R data 1 address 11..11 to check W1 worked",
|
self.add_read("R data 1 address 11..11 to check W1 worked",
|
||||||
self.probe_address,data_zeros,read_port)
|
self.probe_address,data_zeros,read_port)
|
||||||
self.measure_cycles["read1_{0}".format(read_port)] = len(self.cycle_times)-1
|
self.measure_cycles[read_port]["read1"] = len(self.cycle_times)-1
|
||||||
#self.read1_cycle=len(self.cycle_times)-1 # Remember for power measure
|
|
||||||
|
|
||||||
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))",
|
self.add_noop_all_ports("Idle cycle (if read takes >1 cycle))",
|
||||||
self.probe_address,data_zeros)
|
self.probe_address,data_zeros)
|
||||||
|
|
||||||
def get_available_port(self,get_read_port):
|
def get_available_port(self,get_read_port):
|
||||||
"""Returns the first accessible read or write port. """
|
"""Returns the first accessible read or write port. """
|
||||||
if get_read_port and len(self.read_ports) > 0:
|
if get_read_port and len(self.read_index) > 0:
|
||||||
return self.read_ports[0]
|
return self.read_index[0]
|
||||||
elif not get_read_port and len(self.write_ports) > 0:
|
elif not get_read_port and len(self.write_index) > 0:
|
||||||
return self.write_ports[0]
|
return self.write_index[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def set_stimulus_variables(self):
|
||||||
|
simulation.set_stimulus_variables(self)
|
||||||
|
self.measure_cycles = [{} for port in range(self.total_ports)]
|
||||||
|
|
||||||
def create_test_cycles(self):
|
def create_test_cycles(self):
|
||||||
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
"""Returns a list of key time-points [ns] of the waveform (each rising edge)
|
||||||
|
|
@ -937,35 +779,16 @@ class delay():
|
||||||
and does not need a rising edge."""
|
and does not need a rising edge."""
|
||||||
#Using this requires setting at least one port to target for simulation.
|
#Using this requires setting at least one port to target for simulation.
|
||||||
if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0:
|
if len(self.targ_write_ports) == 0 and len(self.targ_read_ports) == 0:
|
||||||
debug.error("No ports selected for characterization.",1)
|
debug.error("No port selected for characterization.",1)
|
||||||
|
self.set_stimulus_variables()
|
||||||
# Start at time 0
|
|
||||||
self.t_current = 0
|
|
||||||
|
|
||||||
# Cycle times (positive edge) with comment
|
|
||||||
self.cycle_comments = []
|
|
||||||
self.cycle_times = []
|
|
||||||
self.measure_cycles = {}
|
|
||||||
|
|
||||||
# Control signals for ports. These are not the final signals and will likely be changed later.
|
|
||||||
#web is the enable for write ports. Dicts used for simplicity as ports are not necessarily incremental.
|
|
||||||
self.web_values = {port:[] for port in self.write_ports}
|
|
||||||
#csb acts as an enable for the read ports.
|
|
||||||
self.csb_values = {port:[] for port in range(self.total_port_num)}
|
|
||||||
|
|
||||||
# Address and data values for each address/data bit. A 3d list of size #ports x bits x cycles.
|
|
||||||
self.data_values=[[[] for bit in range(self.word_size)] for port in range(len(self.write_ports))]
|
|
||||||
self.addr_values=[[[] for bit in range(self.addr_size)] for port in range(self.total_port_num)]
|
|
||||||
|
|
||||||
#Get any available read/write port in case only a single write or read ports is being characterized.
|
#Get any available read/write port in case only a single write or read ports is being characterized.
|
||||||
cur_read_port = self.get_available_port(get_read_port=True)
|
cur_read_port = self.get_available_port(get_read_port=True)
|
||||||
cur_write_port = self.get_available_port(get_read_port=False)
|
cur_write_port = self.get_available_port(get_read_port=False)
|
||||||
|
|
||||||
#These checks should be superceded by check_arguments which should have been called earlier, so this is a double check.
|
|
||||||
debug.check(cur_read_port != None, "Characterizer requires at least 1 read port")
|
debug.check(cur_read_port != None, "Characterizer requires at least 1 read port")
|
||||||
debug.check(cur_write_port != None, "Characterizer requires at least 1 write port")
|
debug.check(cur_write_port != None, "Characterizer requires at least 1 write port")
|
||||||
|
|
||||||
#Characterizing the remaining target ports. Not the final design.
|
#Create test cycles for specified target ports.
|
||||||
write_pos = 0
|
write_pos = 0
|
||||||
read_pos = 0
|
read_pos = 0
|
||||||
while True:
|
while True:
|
||||||
|
|
@ -997,7 +820,7 @@ class delay():
|
||||||
for slew in slews:
|
for slew in slews:
|
||||||
for load in loads:
|
for load in loads:
|
||||||
self.set_load_slew(load,slew)
|
self.set_load_slew(load,slew)
|
||||||
bank_delay = sram.analytical_delay(self.slew,self.load)
|
bank_delay = sram.analytical_delay(self.vdd_voltage, self.slew,self.load)
|
||||||
# Convert from ps to ns
|
# Convert from ps to ns
|
||||||
delay_lh.append(bank_delay.delay/1e3)
|
delay_lh.append(bank_delay.delay/1e3)
|
||||||
delay_hl.append(bank_delay.delay/1e3)
|
delay_hl.append(bank_delay.delay/1e3)
|
||||||
|
|
@ -1026,7 +849,7 @@ class delay():
|
||||||
|
|
||||||
def gen_data(self):
|
def gen_data(self):
|
||||||
""" Generates the PWL data inputs for a simulation timing test. """
|
""" Generates the PWL data inputs for a simulation timing test. """
|
||||||
for write_port in self.write_ports:
|
for write_port in self.write_index:
|
||||||
for i in range(self.word_size):
|
for i in range(self.word_size):
|
||||||
sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i)
|
sig_name="{0}{1}_{2} ".format(self.din_name,write_port, i)
|
||||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[write_port][i], self.period, self.slew, 0.05)
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.data_values[write_port][i], self.period, self.slew, 0.05)
|
||||||
|
|
@ -1036,16 +859,16 @@ class delay():
|
||||||
Generates the address inputs for a simulation timing test.
|
Generates the address inputs for a simulation timing test.
|
||||||
This alternates between all 1's and all 0's for the address.
|
This alternates between all 1's and all 0's for the address.
|
||||||
"""
|
"""
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
for i in range(self.addr_size):
|
for i in range(self.addr_size):
|
||||||
sig_name = "{0}{1}_{2}".format(self.addr_name,port,i)
|
sig_name = "{0}{1}_{2}".format(self.addr_name,port,i)
|
||||||
self.stim.gen_pwl(sig_name, self.cycle_times, self.addr_values[port][i], self.period, self.slew, 0.05)
|
self.stim.gen_pwl(sig_name, self.cycle_times, self.addr_values[port][i], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
def gen_control(self):
|
def gen_control(self):
|
||||||
""" Generates the control signals """
|
""" Generates the control signals """
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_ports):
|
||||||
self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05)
|
self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05)
|
||||||
if port in self.read_ports and port in self.write_ports:
|
if port in self.read_index and port in self.write_index:
|
||||||
self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05)
|
self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1053,5 +876,5 @@ class delay():
|
||||||
"""Make a dict of lists for each type of delay and power measurement to append results to"""
|
"""Make a dict of lists for each type of delay and power measurement to append results to"""
|
||||||
measure_names = self.delay_meas_names + self.power_meas_names
|
measure_names = self.delay_meas_names + self.power_meas_names
|
||||||
#Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists.
|
#Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists.
|
||||||
measure_data = [{mname:[] for mname in measure_names} for i in range(self.total_port_num)]
|
measure_data = [{mname:[] for mname in measure_names} for i in range(self.total_ports)]
|
||||||
return measure_data
|
return measure_data
|
||||||
|
|
|
||||||
|
|
@ -266,7 +266,7 @@ class functional(simulation):
|
||||||
t_intital=t_intital,
|
t_intital=t_intital,
|
||||||
t_final=t_final)
|
t_final=t_final)
|
||||||
|
|
||||||
self.stim.write_control(self.cycle_times[-1] + self.period)
|
self.stim.write_control(self.cycle_times[-1] + self.period, runlvl=1)
|
||||||
self.sf.close()
|
self.sf.close()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,8 @@ class lib:
|
||||||
self.sram = sram
|
self.sram = sram
|
||||||
self.sp_file = sp_file
|
self.sp_file = sp_file
|
||||||
self.use_model = use_model
|
self.use_model = use_model
|
||||||
self.gen_port_names() #copy and paste from delay.py, names are not final will likely be changed later.
|
#self.gen_port_names() #copy and paste from delay.py, names are not final will likely be changed later.
|
||||||
|
self.set_port_indices()
|
||||||
|
|
||||||
self.prepare_tables()
|
self.prepare_tables()
|
||||||
|
|
||||||
|
|
@ -25,7 +26,10 @@ class lib:
|
||||||
|
|
||||||
self.characterize_corners()
|
self.characterize_corners()
|
||||||
|
|
||||||
|
def set_port_indices(self):
|
||||||
|
self.total_port_num = self.sram.total_ports
|
||||||
|
self.read_ports = self.sram.read_index
|
||||||
|
self.write_ports = self.sram.write_index
|
||||||
|
|
||||||
def gen_port_names(self):
|
def gen_port_names(self):
|
||||||
"""Generates the port names to be written to the lib file"""
|
"""Generates the port names to be written to the lib file"""
|
||||||
|
|
@ -108,21 +112,21 @@ class lib:
|
||||||
|
|
||||||
self.write_header()
|
self.write_header()
|
||||||
|
|
||||||
#Loop over all readwrite ports. This is debugging. Will change later.
|
#Loop over all ports.
|
||||||
for port in range(self.total_port_num):
|
for port in range(self.total_port_num):
|
||||||
#set the read and write port as inputs.
|
#set the read and write port as inputs.
|
||||||
self.write_data_bus(port)
|
self.write_data_bus(port)
|
||||||
self.write_addr_bus(port)
|
self.write_addr_bus(port)
|
||||||
self.write_control_pins(port) #need to split this into sram and port control signals
|
self.write_control_pins(port) #need to split this into sram and port control signals
|
||||||
|
self.write_clk_timing_power(port)
|
||||||
self.write_clk_timing_power()
|
|
||||||
|
|
||||||
self.write_footer()
|
self.write_footer()
|
||||||
|
|
||||||
|
|
||||||
def write_footer(self):
|
def write_footer(self):
|
||||||
""" Write the footer """
|
""" Write the footer """
|
||||||
self.lib.write("}\n")
|
self.lib.write(" }\n") #Closing brace for the cell
|
||||||
|
self.lib.write("}\n") #Closing brace for the library
|
||||||
|
|
||||||
def write_header(self):
|
def write_header(self):
|
||||||
""" Write the header information """
|
""" Write the header information """
|
||||||
|
|
@ -151,7 +155,7 @@ class lib:
|
||||||
self.lib.write(" dont_touch : true;\n")
|
self.lib.write(" dont_touch : true;\n")
|
||||||
self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
|
self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
|
||||||
|
|
||||||
#Build string of all control signals. This is subject to change once control signals finalized.
|
#Build string of all control signals.
|
||||||
control_str = 'CSb0' #assume at least 1 port
|
control_str = 'CSb0' #assume at least 1 port
|
||||||
for i in range(1, self.total_port_num):
|
for i in range(1, self.total_port_num):
|
||||||
control_str += ' & CSb{0}'.format(i)
|
control_str += ' & CSb{0}'.format(i)
|
||||||
|
|
@ -296,12 +300,12 @@ class lib:
|
||||||
self.lib.write(" }\n\n")
|
self.lib.write(" }\n\n")
|
||||||
|
|
||||||
|
|
||||||
def write_FF_setuphold(self):
|
def write_FF_setuphold(self, port):
|
||||||
""" Adds Setup and Hold timing results"""
|
""" Adds Setup and Hold timing results"""
|
||||||
|
|
||||||
self.lib.write(" timing(){ \n")
|
self.lib.write(" timing(){ \n")
|
||||||
self.lib.write(" timing_type : setup_rising; \n")
|
self.lib.write(" timing_type : setup_rising; \n")
|
||||||
self.lib.write(" related_pin : \"clk\"; \n")
|
self.lib.write(" related_pin : \"clk{0}\"; \n".format(port))
|
||||||
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
|
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
|
||||||
rounded_values = list(map(round_time,self.times["setup_times_LH"]))
|
rounded_values = list(map(round_time,self.times["setup_times_LH"]))
|
||||||
self.write_values(rounded_values,len(self.slews)," ")
|
self.write_values(rounded_values,len(self.slews)," ")
|
||||||
|
|
@ -313,7 +317,7 @@ class lib:
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" timing(){ \n")
|
self.lib.write(" timing(){ \n")
|
||||||
self.lib.write(" timing_type : hold_rising; \n")
|
self.lib.write(" timing_type : hold_rising; \n")
|
||||||
self.lib.write(" related_pin : \"clk\"; \n")
|
self.lib.write(" related_pin : \"clk{0}\"; \n".format(port))
|
||||||
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
|
self.lib.write(" rise_constraint(CONSTRAINT_TABLE) {\n")
|
||||||
rounded_values = list(map(round_time,self.times["hold_times_LH"]))
|
rounded_values = list(map(round_time,self.times["hold_times_LH"]))
|
||||||
self.write_values(rounded_values,len(self.slews)," ")
|
self.write_values(rounded_values,len(self.slews)," ")
|
||||||
|
|
@ -339,10 +343,9 @@ class lib:
|
||||||
|
|
||||||
|
|
||||||
self.lib.write(" pin(DOUT{1}[{0}:0]){{\n".format(self.sram.word_size - 1, read_port))
|
self.lib.write(" pin(DOUT{1}[{0}:0]){{\n".format(self.sram.word_size - 1, read_port))
|
||||||
self.write_FF_setuphold()
|
|
||||||
self.lib.write(" timing(){ \n")
|
self.lib.write(" timing(){ \n")
|
||||||
self.lib.write(" timing_sense : non_unate; \n")
|
self.lib.write(" timing_sense : non_unate; \n")
|
||||||
self.lib.write(" related_pin : \"clk\"; \n")
|
self.lib.write(" related_pin : \"clk{0}\"; \n".format(read_port))
|
||||||
self.lib.write(" timing_type : rising_edge; \n")
|
self.lib.write(" timing_type : rising_edge; \n")
|
||||||
self.lib.write(" cell_rise(CELL_TABLE) {\n")
|
self.lib.write(" cell_rise(CELL_TABLE) {\n")
|
||||||
self.write_values(self.char_port_results[read_port]["delay_lh"],len(self.loads)," ")
|
self.write_values(self.char_port_results[read_port]["delay_lh"],len(self.loads)," ")
|
||||||
|
|
@ -361,7 +364,7 @@ class lib:
|
||||||
self.lib.write(" }\n\n") # bus
|
self.lib.write(" }\n\n") # bus
|
||||||
|
|
||||||
def write_data_bus_input(self, write_port):
|
def write_data_bus_input(self, write_port):
|
||||||
""" Adds data bus timing results."""
|
""" Adds DIN data bus timing results."""
|
||||||
|
|
||||||
self.lib.write(" bus(DIN{0}){{\n".format(write_port))
|
self.lib.write(" bus(DIN{0}){{\n".format(write_port))
|
||||||
self.lib.write(" bus_type : DATA; \n")
|
self.lib.write(" bus_type : DATA; \n")
|
||||||
|
|
@ -370,9 +373,12 @@ class lib:
|
||||||
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
||||||
self.lib.write(" memory_write(){ \n")
|
self.lib.write(" memory_write(){ \n")
|
||||||
self.lib.write(" address : ADDR{0}; \n".format(write_port))
|
self.lib.write(" address : ADDR{0}; \n".format(write_port))
|
||||||
self.lib.write(" clocked_on : clk; \n")
|
self.lib.write(" clocked_on : clk{0}; \n".format(write_port))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" pin(DIN{1}[{0}:0]){{\n".format(self.sram.word_size - 1, write_port))
|
||||||
|
self.write_FF_setuphold(write_port)
|
||||||
|
self.lib.write(" }\n") # pin
|
||||||
|
self.lib.write(" }\n") #bus
|
||||||
|
|
||||||
def write_data_bus(self, port):
|
def write_data_bus(self, port):
|
||||||
""" Adds data bus timing results."""
|
""" Adds data bus timing results."""
|
||||||
|
|
@ -392,7 +398,7 @@ class lib:
|
||||||
self.lib.write(" pin(ADDR{1}[{0}:0])".format(self.sram.addr_size - 1, port))
|
self.lib.write(" pin(ADDR{1}[{0}:0])".format(self.sram.addr_size - 1, port))
|
||||||
self.lib.write("{\n")
|
self.lib.write("{\n")
|
||||||
|
|
||||||
self.write_FF_setuphold()
|
self.write_FF_setuphold(port)
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n\n")
|
self.lib.write(" }\n\n")
|
||||||
|
|
||||||
|
|
@ -409,28 +415,25 @@ class lib:
|
||||||
self.lib.write("{\n")
|
self.lib.write("{\n")
|
||||||
self.lib.write(" direction : input; \n")
|
self.lib.write(" direction : input; \n")
|
||||||
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
||||||
self.write_FF_setuphold()
|
self.write_FF_setuphold(port)
|
||||||
self.lib.write(" }\n\n")
|
self.lib.write(" }\n\n")
|
||||||
|
|
||||||
def write_clk_timing_power(self):
|
def write_clk_timing_power(self, port):
|
||||||
""" Adds clk pin timing results."""
|
""" Adds clk pin timing results."""
|
||||||
|
|
||||||
self.lib.write(" pin(clk){\n")
|
self.lib.write(" pin(clk{0}){{\n".format(port))
|
||||||
self.lib.write(" clock : true;\n")
|
self.lib.write(" clock : true;\n")
|
||||||
self.lib.write(" direction : input; \n")
|
self.lib.write(" direction : input; \n")
|
||||||
# FIXME: This depends on the clock buffer size in the control logic
|
# FIXME: This depends on the clock buffer size in the control logic
|
||||||
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
|
||||||
|
|
||||||
#Add power values for the ports. lib generated with this is not syntactically correct. TODO once
|
self.add_clk_control_power(port)
|
||||||
#top level is done.
|
|
||||||
for port in range(self.total_port_num):
|
|
||||||
self.add_clk_control_power(port)
|
|
||||||
|
|
||||||
min_pulse_width = round_time(self.char_sram_results["min_period"])/2.0
|
min_pulse_width = round_time(self.char_sram_results["min_period"])/2.0
|
||||||
min_period = round_time(self.char_sram_results["min_period"])
|
min_period = round_time(self.char_sram_results["min_period"])
|
||||||
self.lib.write(" timing(){ \n")
|
self.lib.write(" timing(){ \n")
|
||||||
self.lib.write(" timing_type :\"min_pulse_width\"; \n")
|
self.lib.write(" timing_type :\"min_pulse_width\"; \n")
|
||||||
self.lib.write(" related_pin : clk; \n")
|
self.lib.write(" related_pin : clk{0}; \n".format(port))
|
||||||
self.lib.write(" rise_constraint(scalar) {\n")
|
self.lib.write(" rise_constraint(scalar) {\n")
|
||||||
self.lib.write(" values(\"{0}\"); \n".format(min_pulse_width))
|
self.lib.write(" values(\"{0}\"); \n".format(min_pulse_width))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
@ -440,7 +443,7 @@ class lib:
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" timing(){ \n")
|
self.lib.write(" timing(){ \n")
|
||||||
self.lib.write(" timing_type :\"minimum_period\"; \n")
|
self.lib.write(" timing_type :\"minimum_period\"; \n")
|
||||||
self.lib.write(" related_pin : clk; \n")
|
self.lib.write(" related_pin : clk{0}; \n".format(port))
|
||||||
self.lib.write(" rise_constraint(scalar) {\n")
|
self.lib.write(" rise_constraint(scalar) {\n")
|
||||||
self.lib.write(" values(\"{0}\"); \n".format(min_period))
|
self.lib.write(" values(\"{0}\"); \n".format(min_period))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
@ -448,8 +451,7 @@ class lib:
|
||||||
self.lib.write(" values(\"{0}\"); \n".format(min_period))
|
self.lib.write(" values(\"{0}\"); \n".format(min_period))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n\n")
|
||||||
self.lib.write(" }\n")
|
|
||||||
|
|
||||||
def add_clk_control_power(self, port):
|
def add_clk_control_power(self, port):
|
||||||
"""Writes powers under the clock pin group for a specified port"""
|
"""Writes powers under the clock pin group for a specified port"""
|
||||||
|
|
@ -461,7 +463,7 @@ class lib:
|
||||||
web_name = " & !WEb{0}".format(port)
|
web_name = " & !WEb{0}".format(port)
|
||||||
avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"])
|
avg_write_power = np.mean(self.char_port_results[port]["write1_power"] + self.char_port_results[port]["write0_power"])
|
||||||
self.lib.write(" internal_power(){\n")
|
self.lib.write(" internal_power(){\n")
|
||||||
self.lib.write(" when : \"!CSb{0} & clk{1}\"; \n".format(port, web_name))
|
self.lib.write(" when : \"!CSb{0} & clk{0}{1}\"; \n".format(port, web_name))
|
||||||
self.lib.write(" rise_power(scalar){\n")
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
|
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
@ -475,7 +477,7 @@ class lib:
|
||||||
web_name = " & WEb{0}".format(port)
|
web_name = " & WEb{0}".format(port)
|
||||||
avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"])
|
avg_read_power = np.mean(self.char_port_results[port]["read1_power"] + self.char_port_results[port]["read0_power"])
|
||||||
self.lib.write(" internal_power(){\n")
|
self.lib.write(" internal_power(){\n")
|
||||||
self.lib.write(" when : \"!CSb{0} & !clk{1}\"; \n".format(port, web_name))
|
self.lib.write(" when : \"!CSb{0} & !clk{0}{1}\"; \n".format(port, web_name))
|
||||||
self.lib.write(" rise_power(scalar){\n")
|
self.lib.write(" rise_power(scalar){\n")
|
||||||
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
|
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
|
||||||
self.lib.write(" }\n")
|
self.lib.write(" }\n")
|
||||||
|
|
|
||||||
|
|
@ -58,6 +58,7 @@ class simulation():
|
||||||
|
|
||||||
# For generating comments in SPICE stimulus
|
# For generating comments in SPICE stimulus
|
||||||
self.cycle_comments = []
|
self.cycle_comments = []
|
||||||
|
self.fn_cycle_comments = []
|
||||||
|
|
||||||
def add_control_one_port(self, port, op):
|
def add_control_one_port(self, port, op):
|
||||||
"""Appends control signals for operation to a given port"""
|
"""Appends control signals for operation to a given port"""
|
||||||
|
|
@ -81,7 +82,6 @@ class simulation():
|
||||||
def add_data(self, data, port):
|
def add_data(self, data, port):
|
||||||
""" Add the array of data values """
|
""" Add the array of data values """
|
||||||
debug.check(len(data)==self.word_size, "Invalid data word size.")
|
debug.check(len(data)==self.word_size, "Invalid data word size.")
|
||||||
#debug.check(port < len(self.data_values), "Port number cannot index data values.")
|
|
||||||
|
|
||||||
bit = self.word_size - 1
|
bit = self.word_size - 1
|
||||||
for c in data:
|
for c in data:
|
||||||
|
|
@ -111,8 +111,10 @@ class simulation():
|
||||||
""" Add the control values for a write cycle. """
|
""" Add the control values for a write cycle. """
|
||||||
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
||||||
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
|
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
|
||||||
debug.info(1, comment)
|
debug.info(2, comment)
|
||||||
self.cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
|
self.append_cycle_comment(port, comment)
|
||||||
|
|
||||||
self.cycle_times.append(self.t_current)
|
self.cycle_times.append(self.t_current)
|
||||||
self.t_current += self.period
|
self.t_current += self.period
|
||||||
|
|
@ -132,9 +134,11 @@ class simulation():
|
||||||
""" Add the control values for a read cycle. """
|
""" Add the control values for a read cycle. """
|
||||||
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
||||||
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
|
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
|
||||||
debug.info(1, comment)
|
debug.info(2, comment)
|
||||||
self.cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
|
self.append_cycle_comment(port, comment)
|
||||||
|
|
||||||
self.cycle_times.append(self.t_current)
|
self.cycle_times.append(self.t_current)
|
||||||
self.t_current += self.period
|
self.t_current += self.period
|
||||||
self.add_control_one_port(port, "read")
|
self.add_control_one_port(port, "read")
|
||||||
|
|
@ -154,9 +158,11 @@ class simulation():
|
||||||
def add_noop_all_ports(self, address, data):
|
def add_noop_all_ports(self, address, data):
|
||||||
""" Add the control values for a noop to all ports. """
|
""" Add the control values for a noop to all ports. """
|
||||||
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current)
|
comment = self.gen_cycle_comment("noop", "0"*self.word_size, "0"*self.addr_size, 0, self.t_current)
|
||||||
debug.info(1, comment)
|
debug.info(2, comment)
|
||||||
self.cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
|
self.append_cycle_comment("All", comment)
|
||||||
|
|
||||||
self.cycle_times.append(self.t_current)
|
self.cycle_times.append(self.t_current)
|
||||||
self.t_current += self.period
|
self.t_current += self.period
|
||||||
|
|
||||||
|
|
@ -167,8 +173,8 @@ class simulation():
|
||||||
""" Add the control values for a write cycle. Does not increment the period. """
|
""" Add the control values for a write cycle. Does not increment the period. """
|
||||||
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
debug.check(port in self.write_index, "Cannot add write cycle to a read port. Port {0}, Write Ports {1}".format(port, self.write_index))
|
||||||
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
|
comment = self.gen_cycle_comment("write", data, address, port, self.t_current)
|
||||||
debug.info(1, comment)
|
debug.info(2, comment)
|
||||||
self.cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
self.add_control_one_port(port, "write")
|
self.add_control_one_port(port, "write")
|
||||||
self.add_data(data,port)
|
self.add_data(data,port)
|
||||||
|
|
@ -178,8 +184,8 @@ class simulation():
|
||||||
""" Add the control values for a read cycle. Does not increment the period. """
|
""" Add the control values for a read cycle. Does not increment the period. """
|
||||||
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
debug.check(port in self.read_index, "Cannot add read cycle to a write port. Port {0}, Read Ports {1}".format(port, self.read_index))
|
||||||
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
|
comment = self.gen_cycle_comment("read", dout_data, address, port, self.t_current)
|
||||||
debug.info(1, comment)
|
debug.info(2, comment)
|
||||||
self.cycle_comments.append(comment)
|
self.fn_cycle_comments.append(comment)
|
||||||
|
|
||||||
self.add_control_one_port(port, "read")
|
self.add_control_one_port(port, "read")
|
||||||
#If the port is also a readwrite then add data.
|
#If the port is also a readwrite then add data.
|
||||||
|
|
@ -193,6 +199,17 @@ class simulation():
|
||||||
if port in self.write_index:
|
if port in self.write_index:
|
||||||
self.add_data(data,port)
|
self.add_data(data,port)
|
||||||
self.add_address(address, port)
|
self.add_address(address, port)
|
||||||
|
|
||||||
|
def append_cycle_comment(self, port, comment):
|
||||||
|
"""Add comment to list to be printed in stimulus file"""
|
||||||
|
#Clean up time before appending. Make spacing dynamic as well.
|
||||||
|
time = "{0:.2f} ns:".format(self.t_current)
|
||||||
|
time_spacing = len(time)+6
|
||||||
|
self.cycle_comments.append("Cycle {0:<6d} Port {1:<6} {2:<{3}}: {4}".format(len(self.cycle_times),
|
||||||
|
port,
|
||||||
|
time,
|
||||||
|
time_spacing,
|
||||||
|
comment))
|
||||||
|
|
||||||
def gen_cycle_comment(self, op, word, addr, port, t_current):
|
def gen_cycle_comment(self, op, word, addr, port, t_current):
|
||||||
if op == "noop":
|
if op == "noop":
|
||||||
|
|
|
||||||
|
|
@ -232,8 +232,19 @@ class stimuli():
|
||||||
measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t_intital, t_final)
|
measure_string=".meas tran {0} AVG v({1}) FROM={2}n TO={3}n\n\n".format(meas_name, dout, t_intital, t_final)
|
||||||
self.sf.write(measure_string)
|
self.sf.write(measure_string)
|
||||||
|
|
||||||
def write_control(self, end_time):
|
def write_control(self, end_time, runlvl=4):
|
||||||
""" Write the control cards to run and end the simulation """
|
""" Write the control cards to run and end the simulation """
|
||||||
|
|
||||||
|
# These are guesses...
|
||||||
|
if runlvl==1:
|
||||||
|
reltol = 0.02 # 2%
|
||||||
|
elif runlvl==2:
|
||||||
|
reltol = 0.01 # 1%
|
||||||
|
elif runlvl==3:
|
||||||
|
reltol = 0.005 # 0.5%
|
||||||
|
else:
|
||||||
|
reltol = 0.001 # 0.1%
|
||||||
|
|
||||||
# UIC is needed for ngspice to converge
|
# UIC is needed for ngspice to converge
|
||||||
self.sf.write(".TRAN 5p {0}n UIC\n".format(end_time))
|
self.sf.write(".TRAN 5p {0}n UIC\n".format(end_time))
|
||||||
if OPTS.spice_name == "ngspice":
|
if OPTS.spice_name == "ngspice":
|
||||||
|
|
@ -241,9 +252,9 @@ class stimuli():
|
||||||
# which is more accurate, but slower than the default trapezoid method
|
# which is more accurate, but slower than the default trapezoid method
|
||||||
# Do not remove this or it may not converge due to some "pa_00" nodes
|
# Do not remove this or it may not converge due to some "pa_00" nodes
|
||||||
# unless you figure out what these are.
|
# unless you figure out what these are.
|
||||||
self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE method=gear TEMP={}\n".format(self.temperature))
|
self.sf.write(".OPTIONS POST=1 RELTOL={0} PROBE method=gear TEMP={1}\n".format(reltol,self.temperature))
|
||||||
else:
|
else:
|
||||||
self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE TEMP={}\n".format(self.temperature))
|
self.sf.write(".OPTIONS POST=1 RUNLVL={0} PROBE TEMP={1}\n".format(runlvl,self.temperature))
|
||||||
|
|
||||||
# create plots for all signals
|
# create plots for all signals
|
||||||
self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n")
|
self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n")
|
||||||
|
|
|
||||||
|
|
@ -111,6 +111,7 @@ class trim_spice():
|
||||||
match of the line with a term so you can search for a single
|
match of the line with a term so you can search for a single
|
||||||
net connection, the instance name, anything..
|
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]
|
compiled_patterns = [re.compile(pattern) for pattern in keep_inst_list]
|
||||||
|
|
||||||
|
|
@ -127,11 +128,14 @@ class trim_spice():
|
||||||
new_buffer.append(line)
|
new_buffer.append(line)
|
||||||
in_subckt=False
|
in_subckt=False
|
||||||
elif in_subckt:
|
elif in_subckt:
|
||||||
|
removed_insts += 1
|
||||||
for pattern in compiled_patterns:
|
for pattern in compiled_patterns:
|
||||||
if pattern.search(line) != None:
|
if pattern.search(line) != None:
|
||||||
new_buffer.append(line)
|
new_buffer.append(line)
|
||||||
|
removed_insts -= 1
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
new_buffer.append(line)
|
new_buffer.append(line)
|
||||||
|
|
||||||
self.sp_buffer = new_buffer
|
self.sp_buffer = new_buffer
|
||||||
|
debug.info(2, "Removed {} instances from {} subcircuit.".format(removed_insts, subckt_name))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
import sys,re,shutil
|
||||||
|
import debug
|
||||||
|
import tech
|
||||||
|
import math
|
||||||
|
from .stimuli import *
|
||||||
|
from .trim_spice import *
|
||||||
|
from .charutils import *
|
||||||
|
import utils
|
||||||
|
from globals import OPTS
|
||||||
|
from .delay import delay
|
||||||
|
|
||||||
|
class worst_case(delay):
|
||||||
|
"""Functions to test for the worst case delay in a target SRAM
|
||||||
|
|
||||||
|
The current worst case determines a feasible period for the SRAM then tests
|
||||||
|
several bits and record the delay and differences between the bits.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, sram, spfile, corner):
|
||||||
|
delay.__init__(self,sram,spfile,corner)
|
||||||
|
|
||||||
|
|
||||||
|
def analyze(self,probe_address, probe_data, slews, loads):
|
||||||
|
"""
|
||||||
|
Main function to test the delays of different bits.
|
||||||
|
"""
|
||||||
|
debug.check(OPTS.num_rw_ports < 2 and OPTS.num_w_ports < 1 and OPTS.num_r_ports < 1 ,
|
||||||
|
"Bit testing does not currently support multiport.")
|
||||||
|
#Dict to hold all characterization values
|
||||||
|
char_sram_data = {}
|
||||||
|
|
||||||
|
self.set_probe(probe_address, probe_data)
|
||||||
|
#self.prepare_netlist()
|
||||||
|
|
||||||
|
self.load=max(loads)
|
||||||
|
self.slew=max(slews)
|
||||||
|
|
||||||
|
# 1) Find a feasible period and it's corresponding delays using the trimmed array.
|
||||||
|
feasible_delays = self.find_feasible_period()
|
||||||
|
|
||||||
|
# 2) Find the delays of several bits
|
||||||
|
test_bits = self.get_test_bits()
|
||||||
|
bit_delays = self.simulate_for_bit_delays(test_bits)
|
||||||
|
|
||||||
|
for i in range(len(test_bits)):
|
||||||
|
debug.info(1, "Bit tested: addr {0[0]} data_pos {0[1]}\n Values {1}".format(test_bits[i], bit_delays[i]))
|
||||||
|
|
||||||
|
def simulate_for_bit_delays(self, test_bits):
|
||||||
|
"""Simulates the delay of the sram of over several bits."""
|
||||||
|
bit_delays = [{} for i in range(len(test_bits))]
|
||||||
|
|
||||||
|
#Assumes a bitcell with only 1 rw port. (6t, port 0)
|
||||||
|
port = 0
|
||||||
|
self.targ_read_ports = [self.read_ports[port]]
|
||||||
|
self.targ_write_ports = [self.write_ports[port]]
|
||||||
|
|
||||||
|
for i in range(len(test_bits)):
|
||||||
|
(bit_addr, bit_data) = test_bits[i]
|
||||||
|
self.set_probe(bit_addr, bit_data)
|
||||||
|
debug.info(1,"Delay bit test: period {}, addr {}, data_pos {}".format(self.period, bit_addr, bit_data))
|
||||||
|
(success, results)=self.run_delay_simulation()
|
||||||
|
debug.check(success, "Bit Test Failed: period {}, addr {}, data_pos {}".format(self.period, bit_addr, bit_data))
|
||||||
|
bit_delays[i] = results[port]
|
||||||
|
|
||||||
|
return bit_delays
|
||||||
|
|
||||||
|
|
||||||
|
def get_test_bits(self):
|
||||||
|
"""Statically determines address and bit values to test"""
|
||||||
|
#First and last address, first middle, and last bit. Last bit is repeated twice with different data position.
|
||||||
|
bit_addrs = ["0"*self.addr_size, "0"+"1"*(self.addr_size-1), "1"*self.addr_size, "1"*self.addr_size]
|
||||||
|
data_positions = [0, (self.word_size-1)//2, 0, self.word_size-1]
|
||||||
|
#Return them in a tuple form
|
||||||
|
return [(bit_addrs[i], data_positions[i]) for i in range(len(bit_addrs))]
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
word_size = 2
|
word_size = 2
|
||||||
num_words = 16
|
num_words = 16
|
||||||
num_banks = 1
|
|
||||||
|
|
||||||
tech_name = "freepdk45"
|
tech_name = "freepdk45"
|
||||||
process_corners = ["TT"]
|
process_corners = ["TT"]
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
word_size = 2
|
word_size = 2
|
||||||
num_words = 16
|
num_words = 16
|
||||||
num_banks = 1
|
|
||||||
|
|
||||||
tech_name = "scn4m_subm"
|
tech_name = "scn4m_subm"
|
||||||
process_corners = ["TT"]
|
process_corners = ["TT"]
|
||||||
|
|
@ -9,3 +8,11 @@ temperatures = [ 25 ]
|
||||||
|
|
||||||
output_path = "temp"
|
output_path = "temp"
|
||||||
output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name)
|
output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name)
|
||||||
|
|
||||||
|
#Setting for multiport
|
||||||
|
netlist_only = True
|
||||||
|
bitcell = "pbitcell"
|
||||||
|
replica_bitcell="replica_pbitcell"
|
||||||
|
num_rw_ports = 1
|
||||||
|
num_r_ports = 1
|
||||||
|
num_w_ports = 1
|
||||||
|
|
@ -155,10 +155,10 @@ class VlsiLayout:
|
||||||
def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None,
|
def traverseTheHierarchy(self, startingStructureName=None, delegateFunction = None,
|
||||||
transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)):
|
transformPath = [], rotateAngle = 0, transFlags = [0,0,0], coordinates = (0,0)):
|
||||||
#since this is a recursive function, must deal with the default
|
#since this is a recursive function, must deal with the default
|
||||||
#parameters explicitly
|
#parameters explicitly
|
||||||
if startingStructureName == None:
|
if startingStructureName == None:
|
||||||
startingStructureName = self.rootStructureName
|
startingStructureName = self.rootStructureName
|
||||||
|
|
||||||
#set up the rotation matrix
|
#set up the rotation matrix
|
||||||
if(rotateAngle == None or rotateAngle == ""):
|
if(rotateAngle == None or rotateAngle == ""):
|
||||||
angle = 0
|
angle = 0
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ def parse_args():
|
||||||
global OPTS
|
global OPTS
|
||||||
|
|
||||||
option_list = {
|
option_list = {
|
||||||
optparse.make_option("-b", "--backannotated", action="store_true", dest="run_pex",
|
optparse.make_option("-b", "--backannotated", action="store_true", dest="use_pex",
|
||||||
help="Back annotate simulation"),
|
help="Back annotate simulation"),
|
||||||
optparse.make_option("-o", "--output", dest="output_name",
|
optparse.make_option("-o", "--output", dest="output_name",
|
||||||
help="Base output file name(s) prefix", metavar="FILE"),
|
help="Base output file name(s) prefix", metavar="FILE"),
|
||||||
|
|
|
||||||
|
|
@ -925,7 +925,7 @@ class bank(design.design):
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
|
|
||||||
def analytical_delay(self, slew, load):
|
def analytical_delay(self, vdd, slew, load):
|
||||||
""" return analytical delay of the bank"""
|
""" return analytical delay of the bank"""
|
||||||
decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load())
|
decoder_delay = self.row_decoder.analytical_delay(slew, self.wordline_driver.input_load())
|
||||||
|
|
||||||
|
|
@ -933,10 +933,17 @@ class bank(design.design):
|
||||||
|
|
||||||
bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew)
|
bitcell_array_delay = self.bitcell_array.analytical_delay(word_driver_delay.slew)
|
||||||
|
|
||||||
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(bitcell_array_delay.slew,
|
if self.words_per_row > 1:
|
||||||
|
port = 0 #Analytical delay only supports single port
|
||||||
|
column_mux_delay = self.column_mux_array[port].analytical_delay(vdd, bitcell_array_delay.slew,
|
||||||
|
self.sense_amp_array.input_load())
|
||||||
|
else:
|
||||||
|
column_mux_delay = self.return_delay(delay = 0.0, slew=word_driver_delay.slew)
|
||||||
|
|
||||||
|
bl_t_data_out_delay = self.sense_amp_array.analytical_delay(column_mux_delay.slew,
|
||||||
self.bitcell_array.output_load())
|
self.bitcell_array.output_load())
|
||||||
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
# output load of bitcell_array is set to be only small part of bl for sense amp.
|
||||||
|
|
||||||
result = decoder_delay + word_driver_delay + bitcell_array_delay + bl_t_data_out_delay
|
result = decoder_delay + word_driver_delay + bitcell_array_delay + column_mux_delay + bl_t_data_out_delay
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,11 @@ class sense_amp(design.design):
|
||||||
self.height = sense_amp.height
|
self.height = sense_amp.height
|
||||||
self.pin_map = sense_amp.pin_map
|
self.pin_map = sense_amp.pin_map
|
||||||
|
|
||||||
|
def input_load(self):
|
||||||
|
#Input load for the bitlines which are connected to the source/drain of a TX. Not the selects.
|
||||||
|
bitline_pmos_size = 8 #FIXME: This should be set somewhere and referenced. Probably in tech file.
|
||||||
|
return spice["min_tx_drain_c"]*(bitline_pmos_size/parameter["min_tx_size"])#ff
|
||||||
|
|
||||||
def analytical_delay(self, slew, load=0.0):
|
def analytical_delay(self, slew, load=0.0):
|
||||||
from tech import spice
|
from tech import spice
|
||||||
r = spice["min_tx_r"]/(10)
|
r = spice["min_tx_r"]/(10)
|
||||||
|
|
|
||||||
|
|
@ -134,6 +134,9 @@ class sense_amp_array(design.design):
|
||||||
width=self.width,
|
width=self.width,
|
||||||
height=drc("minwidth_metal1"))
|
height=drc("minwidth_metal1"))
|
||||||
|
|
||||||
|
def input_load(self):
|
||||||
|
return self.amp.input_load()
|
||||||
|
|
||||||
def analytical_delay(self, slew, load=0.0):
|
def analytical_delay(self, slew, load=0.0):
|
||||||
return self.amp.analytical_delay(slew=slew, load=load)
|
return self.amp.analytical_delay(slew=slew, load=load)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -217,5 +217,13 @@ class single_level_column_mux_array(design.design):
|
||||||
offset= br_out_offset,
|
offset= br_out_offset,
|
||||||
rotate=90)
|
rotate=90)
|
||||||
|
|
||||||
|
def analytical_delay(self, vdd, slew, load=0.0):
|
||||||
|
from tech import spice
|
||||||
|
r = spice["min_tx_r"]/(self.mux.ptx_width/parameter["min_tx_size"])
|
||||||
|
#Drains of mux transistors make up capacitance.
|
||||||
|
c_para = spice["min_tx_drain_c"]*(self.mux.ptx_width/parameter["min_tx_size"])*self.words_per_row#ff
|
||||||
|
volt_swing = spice["v_threshold_typical"]/vdd
|
||||||
|
|
||||||
|
result = self.cal_delay_with_rc(r = r, c = c_para+load, slew = slew, swing = volt_swing)
|
||||||
|
return self.return_delay(result.delay, result.slew)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,21 @@ class sram():
|
||||||
def save(self):
|
def save(self):
|
||||||
""" Save all the output files while reporting time to do it as well. """
|
""" Save all the output files while reporting time to do it as well. """
|
||||||
|
|
||||||
|
if not OPTS.netlist_only:
|
||||||
|
# Write the layout
|
||||||
|
start_time = datetime.datetime.now()
|
||||||
|
gdsname = OPTS.output_path + self.s.name + ".gds"
|
||||||
|
print("GDS: Writing to {0}".format(gdsname))
|
||||||
|
self.s.gds_write(gdsname)
|
||||||
|
print_time("GDS", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
|
# Create a LEF physical model
|
||||||
|
start_time = datetime.datetime.now()
|
||||||
|
lefname = OPTS.output_path + self.s.name + ".lef"
|
||||||
|
print("LEF: Writing to {0}".format(lefname))
|
||||||
|
self.s.lef_write(lefname)
|
||||||
|
print_time("LEF", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
# Save the spice file
|
# Save the spice file
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
spname = OPTS.output_path + self.s.name + ".sp"
|
spname = OPTS.output_path + self.s.name + ".sp"
|
||||||
|
|
@ -70,6 +85,7 @@ class sram():
|
||||||
|
|
||||||
# Save the extracted spice file
|
# Save the extracted spice file
|
||||||
if OPTS.use_pex:
|
if OPTS.use_pex:
|
||||||
|
import verify
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
# Output the extracted design if requested
|
# Output the extracted design if requested
|
||||||
sp_file = OPTS.output_path + "temp_pex.sp"
|
sp_file = OPTS.output_path + "temp_pex.sp"
|
||||||
|
|
@ -92,21 +108,6 @@ class sram():
|
||||||
print("Trimming netlist to speed up characterization.")
|
print("Trimming netlist to speed up characterization.")
|
||||||
lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file)
|
lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file)
|
||||||
print_time("Characterization", datetime.datetime.now(), start_time)
|
print_time("Characterization", datetime.datetime.now(), start_time)
|
||||||
|
|
||||||
if not OPTS.netlist_only:
|
|
||||||
# Write the layout
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
gdsname = OPTS.output_path + self.s.name + ".gds"
|
|
||||||
print("GDS: Writing to {0}".format(gdsname))
|
|
||||||
self.s.gds_write(gdsname)
|
|
||||||
print_time("GDS", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Create a LEF physical model
|
|
||||||
start_time = datetime.datetime.now()
|
|
||||||
lefname = OPTS.output_path + self.s.name + ".lef"
|
|
||||||
print("LEF: Writing to {0}".format(lefname))
|
|
||||||
self.s.lef_write(lefname)
|
|
||||||
print_time("LEF", datetime.datetime.now(), start_time)
|
|
||||||
|
|
||||||
# Write the datasheet
|
# Write the datasheet
|
||||||
start_time = datetime.datetime.now()
|
start_time = datetime.datetime.now()
|
||||||
|
|
|
||||||
|
|
@ -451,8 +451,8 @@ class sram_base(design):
|
||||||
sp.close()
|
sp.close()
|
||||||
|
|
||||||
|
|
||||||
def analytical_delay(self,slew,load):
|
def analytical_delay(self, vdd, slew,load):
|
||||||
""" LH and HL are the same in analytical model. """
|
""" LH and HL are the same in analytical model. """
|
||||||
return self.bank.analytical_delay(slew,load)
|
return self.bank.analytical_delay(vdd,slew,load)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ class sram_config:
|
||||||
# Estimate the number of rows given the tentative words per row
|
# Estimate the number of rows given the tentative words per row
|
||||||
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
|
||||||
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
|
||||||
|
|
||||||
# Fix the number of columns and rows
|
# Fix the number of columns and rows
|
||||||
self.num_cols = int(self.words_per_row*self.word_size)
|
self.num_cols = int(self.words_per_row*self.word_size)
|
||||||
self.num_rows = int(self.num_words_per_bank/self.words_per_row)
|
self.num_rows = int(self.num_words_per_bank/self.words_per_row)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Run regresion tests on a parameterized bitcell
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from testutils import header,openram_test
|
||||||
|
import sys,os
|
||||||
|
sys.path.append(os.path.join(sys.path[0],".."))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
import debug
|
||||||
|
|
||||||
|
OPTS = globals.OPTS
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 04_bitcell_1rw_1r_test")
|
||||||
|
class bitcell_1rw_1r_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
OPTS.bitcell = "bitcell_1rw_1r"
|
||||||
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
|
from bitcell import bitcell
|
||||||
|
from bitcell_1rw_1r import bitcell_1rw_1r
|
||||||
|
import tech
|
||||||
|
OPTS.num_rw_ports=1
|
||||||
|
OPTS.num_w_ports=0
|
||||||
|
OPTS.num_r_ports=1
|
||||||
|
debug.info(2, "Bitcell with 1 read/write and 1 read port")
|
||||||
|
#tx = bitcell_1rw_1r()
|
||||||
|
tx = bitcell()
|
||||||
|
self.local_check(tx)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# instantiate a copy of the class to actually run the test
|
||||||
|
if __name__ == "__main__":
|
||||||
|
(OPTS, args) = globals.parse_args()
|
||||||
|
del sys.argv[1:]
|
||||||
|
header(__file__, OPTS.tech_name)
|
||||||
|
unittest.main()
|
||||||
|
|
@ -11,7 +11,7 @@ import globals
|
||||||
from globals import OPTS
|
from globals import OPTS
|
||||||
import debug
|
import debug
|
||||||
|
|
||||||
@unittest.skip("SKIPPING 22_sram_pex_test")
|
@unittest.skip("SKIPPING 26_pex_test")
|
||||||
class sram_func_test(openram_test):
|
class sram_func_test(openram_test):
|
||||||
|
|
||||||
def runTest(self):
|
def runTest(self):
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,80 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Run a regression test on various srams
|
||||||
|
"""
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
from testutils import header,openram_test
|
||||||
|
import sys,os
|
||||||
|
sys.path.append(os.path.join(sys.path[0],".."))
|
||||||
|
import globals
|
||||||
|
from globals import OPTS
|
||||||
|
import debug
|
||||||
|
|
||||||
|
@unittest.skip("SKIPPING 27_worst_case_delay_test")
|
||||||
|
class worst_case_timing_sram_test(openram_test):
|
||||||
|
|
||||||
|
def runTest(self):
|
||||||
|
OPTS.tech_name = "freepdk45"
|
||||||
|
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
|
||||||
|
OPTS.spice_name="hspice"
|
||||||
|
OPTS.analytical_delay = False
|
||||||
|
OPTS.trim_netlist = False
|
||||||
|
OPTS.check_lvsdrc = 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 worst_case
|
||||||
|
if not OPTS.spice_exe:
|
||||||
|
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
|
||||||
|
|
||||||
|
word_size, num_words, num_banks = 2, 16, 1
|
||||||
|
from sram import sram
|
||||||
|
from sram_config import sram_config
|
||||||
|
c = sram_config(word_size=word_size,
|
||||||
|
num_words=num_words,
|
||||||
|
num_banks=num_banks)
|
||||||
|
c.words_per_row=1
|
||||||
|
#c.compute_sizes()
|
||||||
|
debug.info(1, "Testing the timing different bitecells inside a {}bit, {} words SRAM with {} bank".format(
|
||||||
|
word_size, num_words, num_banks))
|
||||||
|
s = sram(c, name="sram1")
|
||||||
|
|
||||||
|
sp_netlist_file = OPTS.openram_temp + "temp.sp"
|
||||||
|
s.sp_write(sp_netlist_file)
|
||||||
|
|
||||||
|
if OPTS.use_pex:
|
||||||
|
gdsname = OPTS.output_path + s.name + ".gds"
|
||||||
|
s.gds_write(gdsname)
|
||||||
|
|
||||||
|
import verify
|
||||||
|
reload(verify)
|
||||||
|
# Output the extracted design if requested
|
||||||
|
sp_pex_file = OPTS.output_path + s.name + "_pex.sp"
|
||||||
|
verify.run_pex(s.name, gdsname, sp_netlist_file, output=sp_pex_file)
|
||||||
|
sp_sim_file = sp_pex_file
|
||||||
|
debug.info(1, "Performing spice simulations with backannotated spice file.")
|
||||||
|
else:
|
||||||
|
sp_sim_file = sp_netlist_file
|
||||||
|
debug.info(1, "Performing spice simulations with spice netlist.")
|
||||||
|
|
||||||
|
corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
|
||||||
|
wc = worst_case(s.s, sp_sim_file, corner)
|
||||||
|
import tech
|
||||||
|
loads = [tech.spice["msflop_in_cap"]*4]
|
||||||
|
slews = [tech.spice["rise_time"]*2]
|
||||||
|
probe_address = "1" * s.s.addr_size
|
||||||
|
probe_data = s.s.word_size - 1
|
||||||
|
wc.analyze(probe_address, probe_data, slews, loads)
|
||||||
|
|
||||||
|
globals.end_openram()
|
||||||
|
|
||||||
|
# instantiate a copdsay of the class to actually run the test
|
||||||
|
if __name__ == "__main__":
|
||||||
|
(OPTS, args) = globals.parse_args()
|
||||||
|
del sys.argv[1:]
|
||||||
|
header(__file__, OPTS.tech_name)
|
||||||
|
unittest.main()
|
||||||
|
|
@ -78,214 +78,216 @@ cell (sram_2_16_1_freepdk45){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 948.52275;
|
area : 977.4951374999999;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
value : 0.0021292;
|
value : 0.0011164579999999999;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN){
|
bus(DIN0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
|
}
|
||||||
|
pin(DIN0[1:0]){
|
||||||
|
timing(){
|
||||||
|
timing_type : setup_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.033, 0.033, 0.039",\
|
||||||
|
"0.033, 0.033, 0.039",\
|
||||||
|
"0.033, 0.033, 0.039");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.027, 0.027, 0.033",\
|
||||||
|
"0.027, 0.027, 0.033",\
|
||||||
|
"0.027, 0.027, 0.033");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timing(){
|
||||||
|
timing_type : hold_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.01, -0.016, -0.022",\
|
||||||
|
"-0.01, -0.016, -0.022",\
|
||||||
|
"-0.01, -0.016, -0.022");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.016, -0.016, -0.016",\
|
||||||
|
"-0.016, -0.016, -0.016",\
|
||||||
|
"-0.016, -0.016, -0.016");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus(DOUT){
|
bus(DOUT0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : output;
|
direction : output;
|
||||||
max_capacitance : 1.6728;
|
max_capacitance : 1.6728;
|
||||||
min_capacitance : 0.052275;
|
min_capacitance : 0.052275;
|
||||||
memory_read(){
|
memory_read(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
}
|
|
||||||
pin(DOUT[1:0]){
|
|
||||||
timing(){
|
|
||||||
timing_type : setup_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.015, 0.027",\
|
|
||||||
"0.009, 0.015, 0.027",\
|
|
||||||
"0.009, 0.015, 0.027");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.015",\
|
|
||||||
"0.009, 0.009, 0.015",\
|
|
||||||
"0.009, 0.009, 0.015");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
|
||||||
timing_type : hold_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.002, 0.002, -0.004",\
|
|
||||||
"0.002, 0.002, -0.004",\
|
|
||||||
"0.002, 0.002, -0.004");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("-0.004, -0.004, -0.016",\
|
|
||||||
"-0.004, -0.004, -0.016",\
|
|
||||||
"-0.004, -0.004, -0.016");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("0.229, 0.23, 0.234",\
|
values("0.235, 0.235, 0.239",\
|
||||||
"0.23, 0.23, 0.234",\
|
"0.235, 0.236, 0.24",\
|
||||||
"0.236, 0.236, 0.24");
|
"0.241, 0.242, 0.246");
|
||||||
}
|
}
|
||||||
cell_fall(CELL_TABLE) {
|
cell_fall(CELL_TABLE) {
|
||||||
values("2.555, 2.556, 2.568",\
|
values("2.583, 2.585, 2.612",\
|
||||||
"2.555, 2.557, 2.569",\
|
"2.584, 2.585, 2.613",\
|
||||||
"2.562, 2.563, 2.575");
|
"2.59, 2.592, 2.62");
|
||||||
}
|
}
|
||||||
rise_transition(CELL_TABLE) {
|
rise_transition(CELL_TABLE) {
|
||||||
values("0.02, 0.021, 0.028",\
|
values("0.022, 0.022, 0.03",\
|
||||||
"0.02, 0.021, 0.028",\
|
"0.022, 0.023, 0.03",\
|
||||||
"0.02, 0.021, 0.028");
|
"0.022, 0.022, 0.03");
|
||||||
}
|
}
|
||||||
fall_transition(CELL_TABLE) {
|
fall_transition(CELL_TABLE) {
|
||||||
values("0.111, 0.112, 0.115",\
|
values("0.078, 0.079, 0.083",\
|
||||||
"0.111, 0.111, 0.115",\
|
"0.078, 0.079, 0.083",\
|
||||||
"0.111, 0.111, 0.116");
|
"0.079, 0.079, 0.083");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bus(ADDR){
|
bus(ADDR0){
|
||||||
bus_type : ADDR;
|
bus_type : ADDR;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
max_transition : 0.04;
|
max_transition : 0.04;
|
||||||
pin(ADDR[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(CSb){
|
pin(CSb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(WEb){
|
pin(WEb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & clk & !WEb";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.027431397222222223");
|
values("0.03599689694444445");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.027431397222222223");
|
values("0.03599689694444445");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & !clk & WEb";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.026240397222222222");
|
values("0.029906643888888886");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.026240397222222222");
|
values("0.029906643888888886");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0");
|
values("0");
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +297,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("2.422");
|
values("2.422");
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +307,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("4.844");
|
values("4.844");
|
||||||
}
|
}
|
||||||
|
|
@ -314,5 +316,6 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,96 +78,98 @@ cell (sram_2_16_1_freepdk45){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 948.52275;
|
area : 977.4951374999999;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
value : 0.000168;
|
value : 0.000179;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN){
|
bus(DIN0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
|
}
|
||||||
|
pin(DIN0[1:0]){
|
||||||
|
timing(){
|
||||||
|
timing_type : setup_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.009, 0.009, 0.009",\
|
||||||
|
"0.009, 0.009, 0.009",\
|
||||||
|
"0.009, 0.009, 0.009");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.009, 0.009, 0.009",\
|
||||||
|
"0.009, 0.009, 0.009",\
|
||||||
|
"0.009, 0.009, 0.009");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timing(){
|
||||||
|
timing_type : hold_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.001, 0.001, 0.001",\
|
||||||
|
"0.001, 0.001, 0.001",\
|
||||||
|
"0.001, 0.001, 0.001");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.001, 0.001, 0.001",\
|
||||||
|
"0.001, 0.001, 0.001",\
|
||||||
|
"0.001, 0.001, 0.001");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus(DOUT){
|
bus(DOUT0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : output;
|
direction : output;
|
||||||
max_capacitance : 1.6728;
|
max_capacitance : 1.6728;
|
||||||
min_capacitance : 0.052275;
|
min_capacitance : 0.052275;
|
||||||
memory_read(){
|
memory_read(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
}
|
|
||||||
pin(DOUT[1:0]){
|
|
||||||
timing(){
|
|
||||||
timing_type : setup_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
|
||||||
timing_type : hold_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("0.103, 0.104, 0.113",\
|
values("0.098, 0.098, 0.098",\
|
||||||
"0.103, 0.104, 0.113",\
|
"0.098, 0.098, 0.098",\
|
||||||
"0.103, 0.104, 0.113");
|
"0.098, 0.098, 0.098");
|
||||||
}
|
}
|
||||||
cell_fall(CELL_TABLE) {
|
cell_fall(CELL_TABLE) {
|
||||||
values("0.103, 0.104, 0.113",\
|
values("0.098, 0.098, 0.098",\
|
||||||
"0.103, 0.104, 0.113",\
|
"0.098, 0.098, 0.098",\
|
||||||
"0.103, 0.104, 0.113");
|
"0.098, 0.098, 0.098");
|
||||||
}
|
}
|
||||||
rise_transition(CELL_TABLE) {
|
rise_transition(CELL_TABLE) {
|
||||||
values("0.006, 0.007, 0.018",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.006, 0.007, 0.018",\
|
"0.001, 0.001, 0.001",\
|
||||||
"0.006, 0.007, 0.018");
|
"0.001, 0.001, 0.001");
|
||||||
}
|
}
|
||||||
fall_transition(CELL_TABLE) {
|
fall_transition(CELL_TABLE) {
|
||||||
values("0.006, 0.007, 0.018",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.006, 0.007, 0.018",\
|
"0.001, 0.001, 0.001",\
|
||||||
"0.006, 0.007, 0.018");
|
"0.001, 0.001, 0.001");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bus(ADDR){
|
bus(ADDR0){
|
||||||
bus_type : ADDR;
|
bus_type : ADDR;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
max_transition : 0.04;
|
max_transition : 0.04;
|
||||||
pin(ADDR[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -181,7 +183,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -196,12 +198,12 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(CSb){
|
pin(CSb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -215,7 +217,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -229,12 +231,12 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(WEb){
|
pin(WEb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -248,7 +250,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -262,30 +264,30 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & clk & !WEb";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.0739870044551111");
|
values("0.0747594982142222");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.0739870044551111");
|
values("0.0747594982142222");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & !clk & WEb";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.0739870044551111");
|
values("0.0747594982142222");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.0739870044551111");
|
values("0.0747594982142222");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0");
|
values("0");
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +297,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0.0");
|
values("0.0");
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +307,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0");
|
values("0");
|
||||||
}
|
}
|
||||||
|
|
@ -314,5 +316,6 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,214 +78,216 @@ cell (sram_2_16_1_freepdk45){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 948.52275;
|
area : 977.4951374999999;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
value : 0.0021292;
|
value : 0.0011164579999999999;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN){
|
bus(DIN0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
|
}
|
||||||
|
pin(DIN0[1:0]){
|
||||||
|
timing(){
|
||||||
|
timing_type : setup_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.033, 0.033, 0.039",\
|
||||||
|
"0.033, 0.033, 0.039",\
|
||||||
|
"0.033, 0.033, 0.039");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.027, 0.027, 0.033",\
|
||||||
|
"0.027, 0.027, 0.033",\
|
||||||
|
"0.027, 0.027, 0.033");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timing(){
|
||||||
|
timing_type : hold_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.01, -0.016, -0.022",\
|
||||||
|
"-0.01, -0.016, -0.022",\
|
||||||
|
"-0.01, -0.016, -0.022");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.016, -0.016, -0.016",\
|
||||||
|
"-0.016, -0.016, -0.016",\
|
||||||
|
"-0.016, -0.016, -0.016");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus(DOUT){
|
bus(DOUT0){
|
||||||
bus_type : DATA;
|
bus_type : DATA;
|
||||||
direction : output;
|
direction : output;
|
||||||
max_capacitance : 1.6728;
|
max_capacitance : 1.6728;
|
||||||
min_capacitance : 0.052275;
|
min_capacitance : 0.052275;
|
||||||
memory_read(){
|
memory_read(){
|
||||||
address : ADDR;
|
address : ADDR0;
|
||||||
}
|
|
||||||
pin(DOUT[1:0]){
|
|
||||||
timing(){
|
|
||||||
timing_type : setup_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.015, 0.027",\
|
|
||||||
"0.009, 0.015, 0.027",\
|
|
||||||
"0.009, 0.015, 0.027");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.015",\
|
|
||||||
"0.009, 0.009, 0.015",\
|
|
||||||
"0.009, 0.009, 0.015");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
|
||||||
timing_type : hold_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.002, 0.002, -0.004",\
|
|
||||||
"0.002, 0.002, -0.004",\
|
|
||||||
"0.002, 0.002, -0.004");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("-0.004, -0.004, -0.016",\
|
|
||||||
"-0.004, -0.004, -0.016",\
|
|
||||||
"-0.004, -0.004, -0.016");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("0.227, 0.227, 0.231",\
|
values("0.233, 0.233, 0.237",\
|
||||||
"0.227, 0.228, 0.232",\
|
"0.233, 0.234, 0.237",\
|
||||||
"0.233, 0.234, 0.238");
|
"0.239, 0.24, 0.244");
|
||||||
}
|
}
|
||||||
cell_fall(CELL_TABLE) {
|
cell_fall(CELL_TABLE) {
|
||||||
values("2.555, 2.557, 2.569",\
|
values("2.584, 2.585, 2.611",\
|
||||||
"2.556, 2.557, 2.569",\
|
"2.584, 2.585, 2.612",\
|
||||||
"2.562, 2.563, 2.576");
|
"2.591, 2.592, 2.618");
|
||||||
}
|
}
|
||||||
rise_transition(CELL_TABLE) {
|
rise_transition(CELL_TABLE) {
|
||||||
values("0.02, 0.021, 0.028",\
|
values("0.022, 0.022, 0.03",\
|
||||||
"0.02, 0.021, 0.028",\
|
"0.022, 0.023, 0.03",\
|
||||||
"0.02, 0.021, 0.028");
|
"0.022, 0.023, 0.03");
|
||||||
}
|
}
|
||||||
fall_transition(CELL_TABLE) {
|
fall_transition(CELL_TABLE) {
|
||||||
values("0.11, 0.11, 0.114",\
|
values("0.076, 0.077, 0.082",\
|
||||||
"0.109, 0.11, 0.113",\
|
"0.077, 0.077, 0.082",\
|
||||||
"0.11, 0.11, 0.114");
|
"0.077, 0.077, 0.082");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bus(ADDR){
|
bus(ADDR0){
|
||||||
bus_type : ADDR;
|
bus_type : ADDR;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
max_transition : 0.04;
|
max_transition : 0.04;
|
||||||
pin(ADDR[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(CSb){
|
pin(CSb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(WEb){
|
pin(WEb0){
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.015, 0.027",\
|
values("0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027",\
|
"0.033, 0.033, 0.039",\
|
||||||
"0.009, 0.015, 0.027");
|
"0.033, 0.033, 0.039");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.015",\
|
values("0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015",\
|
"0.027, 0.027, 0.033",\
|
||||||
"0.009, 0.009, 0.015");
|
"0.027, 0.027, 0.033");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.002, 0.002, -0.004",\
|
values("-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004",\
|
"-0.01, -0.016, -0.022",\
|
||||||
"0.002, 0.002, -0.004");
|
"-0.01, -0.016, -0.022");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.004, -0.004, -0.016",\
|
values("-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016",\
|
"-0.016, -0.016, -0.016",\
|
||||||
"-0.004, -0.004, -0.016");
|
"-0.016, -0.016, -0.016");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 0.2091;
|
capacitance : 0.2091;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & clk & !WEb";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.025181683333333333");
|
values("0.03334771594444444");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.025181683333333333");
|
values("0.03334771594444444");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb & !clk & WEb";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0.024945991666666667");
|
values("0.028457026222222223");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("0.024945991666666667");
|
values("0.028457026222222223");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "CSb";
|
when : "CSb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("0");
|
values("0");
|
||||||
}
|
}
|
||||||
|
|
@ -295,7 +297,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("2.422");
|
values("2.422");
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +307,7 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("4.844");
|
values("4.844");
|
||||||
}
|
}
|
||||||
|
|
@ -314,5 +316,6 @@ cell (sram_2_16_1_freepdk45){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 60176.520000000004;
|
area : 60774.3;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb0";
|
when : "CSb0";
|
||||||
value : 0.000175;
|
value : 0.0009813788999999999;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN0){
|
bus(DIN0){
|
||||||
|
|
@ -91,7 +91,37 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR0;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
|
}
|
||||||
|
pin(DIN0[1:0]){
|
||||||
|
timing(){
|
||||||
|
timing_type : setup_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.167, 0.167, 0.228",\
|
||||||
|
"0.167, 0.167, 0.228",\
|
||||||
|
"0.167, 0.167, 0.228");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.131, 0.125, 0.137",\
|
||||||
|
"0.131, 0.125, 0.137",\
|
||||||
|
"0.131, 0.125, 0.137");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timing(){
|
||||||
|
timing_type : hold_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.065, -0.071, -0.114",\
|
||||||
|
"-0.065, -0.071, -0.114",\
|
||||||
|
"-0.065, -0.071, -0.114");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.089, -0.089, -0.089",\
|
||||||
|
"-0.089, -0.089, -0.089",\
|
||||||
|
"-0.089, -0.089, -0.089");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus(DOUT0){
|
bus(DOUT0){
|
||||||
|
|
@ -103,57 +133,29 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
address : ADDR0;
|
address : ADDR0;
|
||||||
}
|
}
|
||||||
pin(DOUT0[1:0]){
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
|
||||||
timing_type : setup_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009",\
|
|
||||||
"0.009, 0.009, 0.009");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
|
||||||
timing_type : hold_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001",\
|
|
||||||
"0.001, 0.001, 0.001");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("0.268, 0.268, 0.268",\
|
values("1.556, 1.576, 1.751",\
|
||||||
"0.268, 0.268, 0.268",\
|
"1.559, 1.579, 1.754",\
|
||||||
"0.268, 0.268, 0.268");
|
"1.624, 1.643, 1.819");
|
||||||
}
|
}
|
||||||
cell_fall(CELL_TABLE) {
|
cell_fall(CELL_TABLE) {
|
||||||
values("0.268, 0.268, 0.268",\
|
values("3.445, 3.504, 3.926",\
|
||||||
"0.268, 0.268, 0.268",\
|
"3.448, 3.507, 3.93",\
|
||||||
"0.268, 0.268, 0.268");
|
"3.49, 3.549, 3.972");
|
||||||
}
|
}
|
||||||
rise_transition(CELL_TABLE) {
|
rise_transition(CELL_TABLE) {
|
||||||
values("0.004, 0.004, 0.004",\
|
values("0.13, 0.169, 0.574",\
|
||||||
"0.004, 0.004, 0.004",\
|
"0.13, 0.169, 0.574",\
|
||||||
"0.004, 0.004, 0.004");
|
"0.13, 0.169, 0.574");
|
||||||
}
|
}
|
||||||
fall_transition(CELL_TABLE) {
|
fall_transition(CELL_TABLE) {
|
||||||
values("0.004, 0.004, 0.004",\
|
values("0.467, 0.49, 0.959",\
|
||||||
"0.004, 0.004, 0.004",\
|
"0.467, 0.49, 0.959",\
|
||||||
"0.004, 0.004, 0.004");
|
"0.47, 0.493, 0.96");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,30 +169,30 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
pin(ADDR0[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -201,30 +203,30 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,54 +236,54 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.009, 0.009, 0.009");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"0.001, 0.001, 0.001");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & clk & !WEb0";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("11.3007276371");
|
values("9.972790277777777");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("11.3007276371");
|
values("9.972790277777777");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & !clk & WEb0";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("11.3007276371");
|
values("8.899322499999998");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("11.3007276371");
|
values("8.899322499999998");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
|
|
@ -295,24 +297,25 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0.0");
|
values("2.344");
|
||||||
}
|
}
|
||||||
fall_constraint(scalar) {
|
fall_constraint(scalar) {
|
||||||
values("0.0");
|
values("2.344");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0");
|
values("4.688");
|
||||||
}
|
}
|
||||||
fall_constraint(scalar) {
|
fall_constraint(scalar) {
|
||||||
values("0");
|
values("4.688");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 60176.520000000004;
|
area : 60774.3;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb0";
|
when : "CSb0";
|
||||||
value : 0.000175;
|
value : 0.000179;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN0){
|
bus(DIN0){
|
||||||
|
|
@ -91,21 +91,12 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR0;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
}
|
}
|
||||||
}
|
pin(DIN0[1:0]){
|
||||||
bus(DOUT0){
|
|
||||||
bus_type : DATA;
|
|
||||||
direction : output;
|
|
||||||
max_capacitance : 78.5936;
|
|
||||||
min_capacitance : 2.45605;
|
|
||||||
memory_read(){
|
|
||||||
address : ADDR0;
|
|
||||||
}
|
|
||||||
pin(DOUT0[1:0]){
|
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -119,7 +110,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -131,9 +122,20 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
"0.001, 0.001, 0.001");
|
"0.001, 0.001, 0.001");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bus(DOUT0){
|
||||||
|
bus_type : DATA;
|
||||||
|
direction : output;
|
||||||
|
max_capacitance : 78.5936;
|
||||||
|
min_capacitance : 2.45605;
|
||||||
|
memory_read(){
|
||||||
|
address : ADDR0;
|
||||||
|
}
|
||||||
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("0.268, 0.268, 0.268",\
|
values("0.268, 0.268, 0.268",\
|
||||||
|
|
@ -167,7 +169,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
pin(ADDR0[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -181,7 +183,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -201,7 +203,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -215,7 +217,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -234,7 +236,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.009, 0.009, 0.009",\
|
values("0.009, 0.009, 0.009",\
|
||||||
"0.009, 0.009, 0.009",\
|
"0.009, 0.009, 0.009",\
|
||||||
|
|
@ -248,7 +250,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.001, 0.001, 0.001",\
|
values("0.001, 0.001, 0.001",\
|
||||||
"0.001, 0.001, 0.001",\
|
"0.001, 0.001, 0.001",\
|
||||||
|
|
@ -262,26 +264,26 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & clk & !WEb0";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("11.3007276371");
|
values("11.3049604371");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("11.3007276371");
|
values("11.3049604371");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & !clk & WEb0";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("11.3007276371");
|
values("11.3049604371");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("11.3007276371");
|
values("11.3049604371");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
|
|
@ -295,7 +297,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0.0");
|
values("0.0");
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +307,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("0");
|
values("0");
|
||||||
}
|
}
|
||||||
|
|
@ -314,5 +316,6 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,11 +78,11 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
dont_use : true;
|
dont_use : true;
|
||||||
map_only : true;
|
map_only : true;
|
||||||
dont_touch : true;
|
dont_touch : true;
|
||||||
area : 60176.520000000004;
|
area : 60774.3;
|
||||||
|
|
||||||
leakage_power () {
|
leakage_power () {
|
||||||
when : "CSb0";
|
when : "CSb0";
|
||||||
value : 0.025716199999999998;
|
value : 0.0009813788999999999;
|
||||||
}
|
}
|
||||||
cell_leakage_power : 0;
|
cell_leakage_power : 0;
|
||||||
bus(DIN0){
|
bus(DIN0){
|
||||||
|
|
@ -91,7 +91,37 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
memory_write(){
|
memory_write(){
|
||||||
address : ADDR0;
|
address : ADDR0;
|
||||||
clocked_on : clk;
|
clocked_on : clk0;
|
||||||
|
}
|
||||||
|
pin(DIN0[1:0]){
|
||||||
|
timing(){
|
||||||
|
timing_type : setup_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.167, 0.167, 0.228",\
|
||||||
|
"0.167, 0.167, 0.228",\
|
||||||
|
"0.167, 0.167, 0.228");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("0.131, 0.125, 0.137",\
|
||||||
|
"0.131, 0.125, 0.137",\
|
||||||
|
"0.131, 0.125, 0.137");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
timing(){
|
||||||
|
timing_type : hold_rising;
|
||||||
|
related_pin : "clk0";
|
||||||
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.065, -0.071, -0.114",\
|
||||||
|
"-0.065, -0.071, -0.114",\
|
||||||
|
"-0.065, -0.071, -0.114");
|
||||||
|
}
|
||||||
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
|
values("-0.089, -0.089, -0.089",\
|
||||||
|
"-0.089, -0.089, -0.089",\
|
||||||
|
"-0.089, -0.089, -0.089");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
bus(DOUT0){
|
bus(DOUT0){
|
||||||
|
|
@ -103,57 +133,29 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
address : ADDR0;
|
address : ADDR0;
|
||||||
}
|
}
|
||||||
pin(DOUT0[1:0]){
|
pin(DOUT0[1:0]){
|
||||||
timing(){
|
|
||||||
timing_type : setup_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.179, 0.173, 0.228",\
|
|
||||||
"0.179, 0.173, 0.228",\
|
|
||||||
"0.179, 0.173, 0.228");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("0.125, 0.125, 0.143",\
|
|
||||||
"0.125, 0.125, 0.143",\
|
|
||||||
"0.125, 0.125, 0.143");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
|
||||||
timing_type : hold_rising;
|
|
||||||
related_pin : "clk";
|
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("-0.065, -0.071, -0.114",\
|
|
||||||
"-0.065, -0.071, -0.114",\
|
|
||||||
"-0.065, -0.071, -0.114");
|
|
||||||
}
|
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
|
||||||
values("-0.089, -0.089, -0.095",\
|
|
||||||
"-0.089, -0.089, -0.095",\
|
|
||||||
"-0.089, -0.089, -0.095");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
timing(){
|
timing(){
|
||||||
timing_sense : non_unate;
|
timing_sense : non_unate;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
timing_type : rising_edge;
|
timing_type : rising_edge;
|
||||||
cell_rise(CELL_TABLE) {
|
cell_rise(CELL_TABLE) {
|
||||||
values("1.277, 1.297, 1.475",\
|
values("1.542, 1.562, 1.738",\
|
||||||
"1.28, 1.3, 1.479",\
|
"1.545, 1.565, 1.741",\
|
||||||
"1.347, 1.367, 1.545");
|
"1.609, 1.629, 1.805");
|
||||||
}
|
}
|
||||||
cell_fall(CELL_TABLE) {
|
cell_fall(CELL_TABLE) {
|
||||||
values("3.217, 3.281, 3.71",\
|
values("3.446, 3.505, 3.924",\
|
||||||
"3.22, 3.285, 3.714",\
|
"3.45, 3.508, 3.927",\
|
||||||
"3.261, 3.325, 3.75");
|
"3.491, 3.55, 3.97");
|
||||||
}
|
}
|
||||||
rise_transition(CELL_TABLE) {
|
rise_transition(CELL_TABLE) {
|
||||||
values("0.122, 0.164, 0.579",\
|
values("0.129, 0.169, 0.573",\
|
||||||
"0.122, 0.164, 0.578",\
|
"0.129, 0.169, 0.573",\
|
||||||
"0.122, 0.164, 0.58");
|
"0.129, 0.169, 0.573");
|
||||||
}
|
}
|
||||||
fall_transition(CELL_TABLE) {
|
fall_transition(CELL_TABLE) {
|
||||||
values("0.363, 0.396, 0.958",\
|
values("0.457, 0.481, 0.956",\
|
||||||
"0.363, 0.396, 0.957",\
|
"0.457, 0.481, 0.956",\
|
||||||
"0.366, 0.399, 0.951");
|
"0.459, 0.483, 0.957");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -167,30 +169,30 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
pin(ADDR0[3:0]){
|
pin(ADDR0[3:0]){
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.179, 0.173, 0.228",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.125, 0.125, 0.143",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.065, -0.071, -0.114",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.089, -0.089, -0.095",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -201,30 +203,30 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.179, 0.173, 0.228",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.125, 0.125, 0.143",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.065, -0.071, -0.114",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.089, -0.089, -0.095",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -234,54 +236,54 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : setup_rising;
|
timing_type : setup_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.179, 0.173, 0.228",\
|
values("0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228",\
|
"0.167, 0.167, 0.228",\
|
||||||
"0.179, 0.173, 0.228");
|
"0.167, 0.167, 0.228");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("0.125, 0.125, 0.143",\
|
values("0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143",\
|
"0.131, 0.125, 0.137",\
|
||||||
"0.125, 0.125, 0.143");
|
"0.131, 0.125, 0.137");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type : hold_rising;
|
timing_type : hold_rising;
|
||||||
related_pin : "clk";
|
related_pin : "clk0";
|
||||||
rise_constraint(CONSTRAINT_TABLE) {
|
rise_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.065, -0.071, -0.114",\
|
values("-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114",\
|
"-0.065, -0.071, -0.114",\
|
||||||
"-0.065, -0.071, -0.114");
|
"-0.065, -0.071, -0.114");
|
||||||
}
|
}
|
||||||
fall_constraint(CONSTRAINT_TABLE) {
|
fall_constraint(CONSTRAINT_TABLE) {
|
||||||
values("-0.089, -0.089, -0.095",\
|
values("-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095",\
|
"-0.089, -0.089, -0.089",\
|
||||||
"-0.089, -0.089, -0.095");
|
"-0.089, -0.089, -0.089");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pin(clk){
|
pin(clk0){
|
||||||
clock : true;
|
clock : true;
|
||||||
direction : input;
|
direction : input;
|
||||||
capacitance : 9.8242;
|
capacitance : 9.8242;
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & clk & !WEb0";
|
when : "!CSb0 & clk0 & !WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("9.141838916666668");
|
values("9.602821763527778");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("9.141838916666668");
|
values("9.602821763527778");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
when : "!CSb0 & !clk & WEb0";
|
when : "!CSb0 & !clk0 & WEb0";
|
||||||
rise_power(scalar){
|
rise_power(scalar){
|
||||||
values("8.304491694444444");
|
values("8.647938152416664");
|
||||||
}
|
}
|
||||||
fall_power(scalar){
|
fall_power(scalar){
|
||||||
values("8.304491694444444");
|
values("8.647938152416664");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
internal_power(){
|
internal_power(){
|
||||||
|
|
@ -295,7 +297,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"min_pulse_width";
|
timing_type :"min_pulse_width";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("2.344");
|
values("2.344");
|
||||||
}
|
}
|
||||||
|
|
@ -305,7 +307,7 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
timing(){
|
timing(){
|
||||||
timing_type :"minimum_period";
|
timing_type :"minimum_period";
|
||||||
related_pin : clk;
|
related_pin : clk0;
|
||||||
rise_constraint(scalar) {
|
rise_constraint(scalar) {
|
||||||
values("4.688");
|
values("4.688");
|
||||||
}
|
}
|
||||||
|
|
@ -314,5 +316,6 @@ cell (sram_2_16_1_scn4m_subm){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
.SUBCKT cell_1rw_1r bl0 br0 bl1 br1 wl0 wl1 vdd gnd
|
||||||
|
MM9 RA_to_R_right wl1 br1 gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM8 RA_to_R_right Q gnd gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM7 RA_to_R_left Q_bar gnd gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM6 RA_to_R_left wl1 bl1 gnd NMOS_VTG W=180.0n L=50n m=1
|
||||||
|
MM5 Q wl0 bl0 gnd NMOS_VTG W=135.00n L=50n m=1
|
||||||
|
MM4 Q_bar wl0 br0 gnd NMOS_VTG W=135.00n L=50n m=1
|
||||||
|
MM1 Q Q_bar gnd gnd NMOS_VTG W=270.0n L=50n m=1
|
||||||
|
MM0 Q_bar Q gnd gnd NMOS_VTG W=270.0n L=50n m=1
|
||||||
|
MM3 Q Q_bar vdd vdd PMOS_VTG W=90n L=50n m=1
|
||||||
|
MM2 Q_bar Q vdd vdd PMOS_VTG W=90n L=50n m=1
|
||||||
|
.ENDS
|
||||||
|
|
||||||
|
|
@ -295,6 +295,7 @@ spice["channel"] = drc["minlength_channel"]
|
||||||
spice["clk"] = "clk"
|
spice["clk"] = "clk"
|
||||||
|
|
||||||
# analytical delay parameters
|
# analytical delay parameters
|
||||||
|
spice["v_threshold_typical"] = 0.4 # Typical Threshold voltage in Volts
|
||||||
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
||||||
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
||||||
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
||||||
|
|
|
||||||
|
|
@ -240,6 +240,7 @@ spice["clk"] = "clk"
|
||||||
|
|
||||||
# analytical delay parameters
|
# analytical delay parameters
|
||||||
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45.
|
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45.
|
||||||
|
spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts
|
||||||
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
||||||
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
||||||
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,146 @@
|
||||||
|
magic
|
||||||
|
tech scmos
|
||||||
|
timestamp 1539900829
|
||||||
|
<< nwell >>
|
||||||
|
rect -18 -1 32 26
|
||||||
|
<< pwell >>
|
||||||
|
rect -18 -51 32 -6
|
||||||
|
<< ntransistor >>
|
||||||
|
rect -6 -18 -4 -12
|
||||||
|
rect 2 -24 4 -12
|
||||||
|
rect 10 -24 12 -12
|
||||||
|
rect 18 -18 20 -12
|
||||||
|
rect -6 -36 -4 -28
|
||||||
|
rect 2 -36 4 -28
|
||||||
|
rect 10 -36 12 -28
|
||||||
|
rect 18 -36 20 -28
|
||||||
|
<< ptransistor >>
|
||||||
|
rect 2 5 4 9
|
||||||
|
rect 10 5 12 9
|
||||||
|
<< ndiffusion >>
|
||||||
|
rect -11 -14 -6 -12
|
||||||
|
rect -7 -18 -6 -14
|
||||||
|
rect -4 -18 -3 -12
|
||||||
|
rect 1 -20 2 -12
|
||||||
|
rect -3 -24 2 -20
|
||||||
|
rect 4 -24 5 -12
|
||||||
|
rect 9 -24 10 -12
|
||||||
|
rect 12 -20 13 -12
|
||||||
|
rect 17 -18 18 -12
|
||||||
|
rect 20 -14 25 -12
|
||||||
|
rect 20 -18 21 -14
|
||||||
|
rect 12 -24 17 -20
|
||||||
|
rect -11 -30 -6 -28
|
||||||
|
rect -7 -34 -6 -30
|
||||||
|
rect -11 -36 -6 -34
|
||||||
|
rect -4 -36 2 -28
|
||||||
|
rect 4 -36 5 -28
|
||||||
|
rect 9 -36 10 -28
|
||||||
|
rect 12 -36 18 -28
|
||||||
|
rect 20 -30 25 -28
|
||||||
|
rect 20 -34 21 -30
|
||||||
|
rect 20 -36 25 -34
|
||||||
|
<< pdiffusion >>
|
||||||
|
rect 1 5 2 9
|
||||||
|
rect 4 5 5 9
|
||||||
|
rect 9 5 10 9
|
||||||
|
rect 12 5 13 9
|
||||||
|
<< ndcontact >>
|
||||||
|
rect -11 -18 -7 -14
|
||||||
|
rect -3 -20 1 -12
|
||||||
|
rect 5 -24 9 -12
|
||||||
|
rect 13 -20 17 -12
|
||||||
|
rect 21 -18 25 -14
|
||||||
|
rect -11 -34 -7 -30
|
||||||
|
rect 5 -36 9 -28
|
||||||
|
rect 21 -34 25 -30
|
||||||
|
<< pdcontact >>
|
||||||
|
rect -3 5 1 9
|
||||||
|
rect 5 5 9 9
|
||||||
|
rect 13 5 17 9
|
||||||
|
<< psubstratepcontact >>
|
||||||
|
rect 5 -44 9 -40
|
||||||
|
<< nsubstratencontact >>
|
||||||
|
rect 5 19 9 23
|
||||||
|
<< polysilicon >>
|
||||||
|
rect 2 9 4 11
|
||||||
|
rect 10 9 12 11
|
||||||
|
rect 2 -5 4 5
|
||||||
|
rect 10 2 12 5
|
||||||
|
rect 11 -2 12 2
|
||||||
|
rect -6 -12 -4 -7
|
||||||
|
rect 2 -9 3 -5
|
||||||
|
rect 2 -12 4 -9
|
||||||
|
rect 10 -12 12 -2
|
||||||
|
rect 18 -12 20 -7
|
||||||
|
rect -6 -20 -4 -18
|
||||||
|
rect 18 -20 20 -18
|
||||||
|
rect -6 -28 -4 -27
|
||||||
|
rect 2 -28 4 -24
|
||||||
|
rect 10 -28 12 -24
|
||||||
|
rect 18 -28 20 -27
|
||||||
|
rect -6 -38 -4 -36
|
||||||
|
rect 2 -38 4 -36
|
||||||
|
rect 10 -38 12 -36
|
||||||
|
rect 18 -38 20 -36
|
||||||
|
<< polycontact >>
|
||||||
|
rect 7 -2 11 2
|
||||||
|
rect -10 -11 -6 -7
|
||||||
|
rect 3 -9 7 -5
|
||||||
|
rect 20 -11 24 -7
|
||||||
|
rect -8 -27 -4 -23
|
||||||
|
rect 18 -27 22 -23
|
||||||
|
<< metal1 >>
|
||||||
|
rect -18 19 5 23
|
||||||
|
rect 9 19 32 23
|
||||||
|
rect -18 12 32 16
|
||||||
|
rect -10 -7 -6 12
|
||||||
|
rect -3 2 0 5
|
||||||
|
rect -3 -2 7 2
|
||||||
|
rect -3 -12 0 -2
|
||||||
|
rect 14 -5 17 5
|
||||||
|
rect 7 -9 17 -5
|
||||||
|
rect 14 -12 17 -9
|
||||||
|
rect 20 -7 24 12
|
||||||
|
rect -14 -18 -11 -14
|
||||||
|
rect 25 -18 28 -14
|
||||||
|
rect 5 -28 9 -24
|
||||||
|
rect 5 -40 9 -36
|
||||||
|
rect -17 -44 5 -40
|
||||||
|
rect 9 -44 31 -40
|
||||||
|
rect -17 -51 -4 -47
|
||||||
|
rect 0 -51 14 -47
|
||||||
|
rect 18 -51 31 -47
|
||||||
|
<< m2contact >>
|
||||||
|
rect 5 19 9 23
|
||||||
|
rect 5 5 9 9
|
||||||
|
rect -18 -18 -14 -14
|
||||||
|
rect -4 -27 0 -23
|
||||||
|
rect 28 -18 32 -14
|
||||||
|
rect 14 -27 18 -23
|
||||||
|
rect -11 -34 -7 -30
|
||||||
|
rect 21 -34 25 -30
|
||||||
|
rect -4 -51 0 -47
|
||||||
|
rect 14 -51 18 -47
|
||||||
|
<< metal2 >>
|
||||||
|
rect -18 -14 -14 23
|
||||||
|
rect -18 -51 -14 -18
|
||||||
|
rect -11 -30 -7 23
|
||||||
|
rect 5 9 9 19
|
||||||
|
rect -11 -51 -7 -34
|
||||||
|
rect -4 -47 0 -27
|
||||||
|
rect 14 -47 18 -27
|
||||||
|
rect 21 -30 25 23
|
||||||
|
rect 21 -51 25 -34
|
||||||
|
rect 28 -14 32 23
|
||||||
|
rect 28 -51 32 -18
|
||||||
|
<< labels >>
|
||||||
|
rlabel metal1 7 -49 7 -49 1 wl1
|
||||||
|
rlabel psubstratepcontact 7 -42 7 -42 1 gnd
|
||||||
|
rlabel m2contact 7 21 7 21 5 vdd
|
||||||
|
rlabel metal1 -1 14 -1 14 1 wl0
|
||||||
|
rlabel metal2 -16 -46 -16 -46 2 bl0
|
||||||
|
rlabel metal2 -9 -46 -9 -46 1 bl1
|
||||||
|
rlabel metal2 23 -46 23 -46 1 br1
|
||||||
|
rlabel metal2 30 -46 30 -46 8 br0
|
||||||
|
<< end >>
|
||||||
|
|
@ -261,6 +261,7 @@ spice["clk"] = "clk"
|
||||||
|
|
||||||
# analytical delay parameters
|
# analytical delay parameters
|
||||||
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45.
|
# FIXME: These need to be updated for SCMOS, they are copied from FreePDK45.
|
||||||
|
spice["v_threshold_typical"] = 1.3 # Typical Threshold voltage in Volts
|
||||||
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
spice["wire_unit_r"] = 0.075 # Unit wire resistance in ohms/square
|
||||||
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
spice["wire_unit_c"] = 0.64 # Unit wire capacitance ff/um^2
|
||||||
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
spice["min_tx_r"] = 9250.0 # Minimum transistor on resistance in ohms
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue