Merge branch 'dev' of https://github.com/VLSIDA/PrivateRAM into multiport

This commit is contained in:
Michael Timothy Grimes 2018-10-25 00:36:46 -07:00
commit 40450ac0f5
42 changed files with 1179 additions and 807 deletions

View File

@ -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

View File

@ -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

View File

@ -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 *

View File

@ -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

View File

@ -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()

View File

@ -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")

View File

@ -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":

View File

@ -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")

View File

@ -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))

View File

@ -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))]

View File

@ -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"]

View File

@ -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

View File

@ -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

View File

@ -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"),

View 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

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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()

View File

@ -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):

View File

@ -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()

View File

@ -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){
} }
} }
} }
} }
} }

View File

@ -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){
} }
} }
} }
} }
} }

View File

@ -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){
} }
} }
} }
} }
} }

View File

@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
} }
} }
} }
} }
} }

View File

@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
} }
} }
} }
} }
} }

View File

@ -314,5 +314,6 @@ cell (sram_2_16_1_scn3me_subm){
} }
} }
} }
} }
} }

View File

@ -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");
} }
} }
} }
} }
} }

View File

@ -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){
} }
} }
} }
} }
} }

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 >>

View File

@ -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