Merge branch 'master' of https://github.com/mguthaus/OpenRAM into multiport

This commit is contained in:
Michael Timothy Grimes 2018-02-28 04:29:38 -08:00
commit bf7d846e5f
262 changed files with 4310516 additions and 4391 deletions

1
.gitattributes vendored Normal file
View File

@ -0,0 +1 @@
*.sp linguist-vendored

5
.gitignore vendored
View File

@ -1,4 +1,7 @@
.DS_Store .DS_Store
*~ *~
*.pyc *.pyc
*.log *.aux
*.out
*.toc
*.synctex.gz

View File

@ -96,15 +96,14 @@ the tests on your contributions before they will be accepted.
git pull upstream dev git pull upstream dev
``` ```
9. Merge the changes from dev into your branch 9. Frequently rebase your branch to keep track of current changes in dev.
``` ```
git merge dev git fetch upstream
git rebase origin/dev
``` ```
10. After you are done, rebase your branch to minimize the number of commits if you
had a lot. I prefer a single commit that you contribute. After this, 10. After a final rebase and your code is working, push your branch to YOUR repository:
push your branch to YOUR repository:
``` ```
git rebase dev
git push -u origin useful-branch-name git push -u origin useful-branch-name
``` ```
Remember origin is your copy on github and useful-branch-name is the Remember origin is your copy on github and useful-branch-name is the

View File

@ -27,7 +27,7 @@ def parse_output(filename, key):
if val != None: if val != None:
debug.info(4, "Key = " + key + " Val = " + val.group(1)) debug.info(4, "Key = " + key + " Val = " + val.group(1))
return val.group(1) return convert_to_float(val.group(1))
else: else:
return "Failed" return "Failed"

View File

@ -1,29 +1,54 @@
import sys import sys,re,shutil
import re
import debug import debug
import tech import tech
import math import math
import stimuli import stimuli
from trim_spice import trim_spice
import charutils as ch import charutils as ch
import utils import utils
from globals import OPTS from globals import OPTS
class delay(): class delay():
""" """Functions to measure the delay and power of an SRAM at a given address and
Functions to measure the delay of an SRAM at a given address and
data bit. data bit.
In general, this will perform the following actions:
1) Trim the netlist to remove unnecessary logic.
2) Find a feasible clock period using max load/slew on the trimmed netlist.
3) Characterize all loads/slews and consider fail when delay is greater than 5% of feasible delay using trimmed netlist.
4) Measure the leakage during the last cycle of the trimmed netlist when there is no operation.
5) Measure the leakage of the whole netlist (untrimmed) in each corner.
6) Subtract the trimmed leakage and add the untrimmed leakage to the power.
Netlist trimming can be removed by setting OPTS.trim_netlist to
False, but this is VERY slow.
""" """
def __init__(self,sram,spfile): def __init__(self, sram, spfile, corner):
self.sram = sram
self.name = sram.name self.name = sram.name
self.num_words = sram.num_words self.word_size = self.sram.word_size
self.word_size = sram.word_size self.addr_size = self.sram.addr_size
self.addr_size = sram.addr_size self.num_cols = self.sram.num_cols
self.sram_sp_file = spfile self.num_rows = self.sram.num_rows
self.num_banks = self.sram.num_banks
self.sp_file = spfile
self.vdd = tech.spice["supply_voltage"] # These are the member variables for a simulation
self.gnd = tech.spice["gnd_voltage"] self.period = 0
self.set_load_slew(0,0)
self.set_corner(corner)
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):
""" Set the load and slew """
self.load = load
self.slew = slew
def check_arguments(self): def check_arguments(self):
"""Checks if arguments given for write_stimulus() meets requirements""" """Checks if arguments given for write_stimulus() meets requirements"""
@ -38,8 +63,29 @@ class delay():
if not isinstance(self.probe_data, int) or self.probe_data>self.word_size or self.probe_data<0: if not isinstance(self.probe_data, int) or self.probe_data>self.word_size or self.probe_data<0:
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)
def write_generic_stimulus(self):
""" Create the instance, supplies, loads, and access transistors. """
def write_stimulus(self, period, load, slew): # add vdd/gnd statements
self.sf.write("\n* Global Power Supplies\n")
self.stim.write_supply()
# instantiate the sram
self.sf.write("\n* Instantiation of the SRAM\n")
self.stim.inst_sram(abits=self.addr_size,
dbits=self.word_size,
sram_name=self.name)
self.sf.write("\n* SRAM output loads\n")
for i in range(self.word_size):
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,self.load))
# add access transistors for data-bus
self.sf.write("\n* Transmission Gates for data-bus and control signals\n")
self.stim.inst_accesstx(dbits=self.word_size)
def write_delay_stimulus(self):
""" Creates a stimulus file for simulations to probe a bitcell at a given clock period. """ Creates a stimulus file for simulations to probe a bitcell at a given clock period.
Address and bit were previously set with set_probe(). Address and bit were previously set with set_probe().
Input slew (in ns) and output capacitive load (in fF) are required for charaterization. Input slew (in ns) and output capacitive load (in fF) are required for charaterization.
@ -47,79 +93,108 @@ class delay():
self.check_arguments() self.check_arguments()
# obtains list of time-points for each rising clk edge # obtains list of time-points for each rising clk edge
self.obtain_cycle_times(period) self.obtain_cycle_times()
# 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")
self.sf.write("* Stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(period,load,slew)) self.sf.write("* Delay stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(self.period,
self.load,
self.slew))
self.stim = stimuli.stimuli(self.sf, self.corner)
# include files in stimulus file # include files in stimulus file
model_list = tech.spice["fet_models"] + [self.sram_sp_file] self.stim.write_include(self.trim_sp_file)
stimuli.write_include(stim_file=self.sf, models=model_list)
# add vdd/gnd statements self.write_generic_stimulus()
self.sf.write("\n* Global Power Supplies\n")
stimuli.write_supply(self.sf)
# instantiate the sram
self.sf.write("\n* Instantiation of the SRAM\n")
stimuli.inst_sram(stim_file=self.sf,
abits=self.addr_size,
dbits=self.word_size,
sram_name=self.name)
self.sf.write("\n* SRAM output loads\n")
for i in range(self.word_size):
self.sf.write("CD{0} d[{0}] 0 {1}f\n".format(i,load))
# add access transistors for data-bus
self.sf.write("\n* Transmission Gates for data-bus and control signals\n")
stimuli.inst_accesstx(stim_file=self.sf, dbits=self.word_size)
# 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 i in range(self.word_size): for i in range(self.word_size):
if i == self.probe_data: if i == self.probe_data:
self.gen_data(clk_times=self.cycle_times, self.gen_data(clk_times=self.cycle_times,
sig_name="data[{0}]".format(i), sig_name="data[{0}]".format(i))
period=period,
slew=slew)
else: else:
stimuli.gen_constant(stim_file=self.sf, self.stim.gen_constant(sig_name="d[{0}]".format(i),
sig_name="d[{0}]".format(i), v_val=0)
v_val=self.gnd)
self.gen_addr(clk_times=self.cycle_times, self.gen_addr(clk_times=self.cycle_times,
addr=self.probe_address, addr=self.probe_address)
period=period,
slew=slew)
# generate control signals # generate control signals
self.sf.write("\n* Generation of control signals\n") self.sf.write("\n* Generation of control signals\n")
self.gen_csb(self.cycle_times, period, slew) self.gen_csb(self.cycle_times)
self.gen_web(self.cycle_times, period, slew) self.gen_web(self.cycle_times)
self.gen_oeb(self.cycle_times, period, slew) self.gen_oeb(self.cycle_times)
self.sf.write("\n* Generation of global clock signal\n") self.sf.write("\n* Generation of global clock signal\n")
stimuli.gen_pulse(stim_file=self.sf, self.stim.gen_pulse(sig_name="CLK",
sig_name="CLK", v1=0,
v1=self.gnd, v2=self.vdd_voltage,
v2=self.vdd, offset=self.period,
offset=period, period=self.period,
period=period, t_rise=self.slew,
t_rise=slew, t_fall=self.slew)
t_fall=slew)
self.write_measures(period) self.write_delay_measures()
# run until the end of the cycle time # run until the end of the cycle time
stimuli.write_control(self.sf,self.cycle_times[-1] + period) self.stim.write_control(self.cycle_times[-1] + self.period)
self.sf.close() self.sf.close()
def write_measures(self,period):
def write_power_stimulus(self, trim):
""" Creates a stimulus file to measure leakage power only.
This works on the *untrimmed netlist*.
"""
self.check_arguments()
# obtains list of time-points for each rising clk edge
self.obtain_cycle_times()
# creates and opens stimulus file for writing
temp_stim = "{0}/stim.sp".format(OPTS.openram_temp)
self.sf = open(temp_stim, "w")
self.sf.write("* Power stimulus for period of {0}n\n\n".format(self.period))
self.stim = stimuli.stimuli(self.sf, self.corner)
# include UNTRIMMED files in stimulus file
if trim:
self.stim.write_include(self.trim_sp_file)
else:
self.stim.write_include(self.sim_sp_file)
self.write_generic_stimulus()
# generate data and addr signals
self.sf.write("\n* Generation of data and address signals\n")
for i in range(self.word_size):
self.stim.gen_constant(sig_name="d[{0}]".format(i),
v_val=0)
for i in range(self.addr_size):
self.stim.gen_constant(sig_name="A[{0}]".format(i),
v_val=0)
# generate control signals
self.sf.write("\n* Generation of control signals\n")
self.stim.gen_constant(sig_name="CSb", v_val=self.vdd_voltage)
self.stim.gen_constant(sig_name="WEb", v_val=self.vdd_voltage)
self.stim.gen_constant(sig_name="OEb", v_val=self.vdd_voltage)
self.sf.write("\n* Generation of global clock signal\n")
self.stim.gen_constant(sig_name="CLK", v_val=0)
self.write_power_measures()
# run until the end of the cycle time
self.stim.write_control(2*self.period)
self.sf.close()
def write_delay_measures(self):
""" """
Write the measure statements to quantify the delay and power results. Write the measure statements to quantify the delay and power results.
""" """
@ -134,11 +209,10 @@ class delay():
# Trigger on the clk of the appropriate cycle # Trigger on the clk of the appropriate cycle
trig_name = "clk" trig_name = "clk"
targ_name = "{0}".format("d[{0}]".format(self.probe_data)) targ_name = "{0}".format("d[{0}]".format(self.probe_data))
trig_val = targ_val = 0.5 * self.vdd trig_val = targ_val = 0.5 * self.vdd_voltage
# Delay the target to measure after the negative edge # Delay the target to measure after the negative edge
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="DELAY_HL",
meas_name="DELAY0",
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -146,10 +220,9 @@ class delay():
trig_dir="FALL", trig_dir="FALL",
targ_dir="FALL", targ_dir="FALL",
trig_td=self.cycle_times[self.read0_cycle], trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]+0.5*period) targ_td=self.cycle_times[self.read0_cycle]+0.5*self.period)
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="DELAY_LH",
meas_name="DELAY1",
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -157,60 +230,69 @@ class delay():
trig_dir="FALL", trig_dir="FALL",
targ_dir="RISE", targ_dir="RISE",
trig_td=self.cycle_times[self.read1_cycle], trig_td=self.cycle_times[self.read1_cycle],
targ_td=self.cycle_times[self.read1_cycle]+0.5*period) targ_td=self.cycle_times[self.read1_cycle]+0.5*self.period)
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="SLEW_HL",
meas_name="SLEW0",
trig_name=targ_name, trig_name=targ_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=0.9*self.vdd, trig_val=0.9*self.vdd_voltage,
targ_val=0.1*self.vdd, targ_val=0.1*self.vdd_voltage,
trig_dir="FALL", trig_dir="FALL",
targ_dir="FALL", targ_dir="FALL",
trig_td=self.cycle_times[self.read0_cycle], trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]+0.5*period) targ_td=self.cycle_times[self.read0_cycle]+0.5*self.period)
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="SLEW_LH",
meas_name="SLEW1",
trig_name=targ_name, trig_name=targ_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=0.1*self.vdd, trig_val=0.1*self.vdd_voltage,
targ_val=0.9*self.vdd, targ_val=0.9*self.vdd_voltage,
trig_dir="RISE", trig_dir="RISE",
targ_dir="RISE", targ_dir="RISE",
trig_td=self.cycle_times[self.read1_cycle], trig_td=self.cycle_times[self.read1_cycle],
targ_td=self.cycle_times[self.read1_cycle]+0.5*period) targ_td=self.cycle_times[self.read1_cycle]+0.5*self.period)
# add measure statements for power # add measure statements for power
t_initial = self.cycle_times[self.write0_cycle] t_initial = self.cycle_times[self.write0_cycle]
t_final = self.cycle_times[self.write0_cycle+1] t_final = self.cycle_times[self.write0_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf, self.stim.gen_meas_power(meas_name="WRITE0_POWER",
meas_name="WRITE0_POWER",
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.write1_cycle] t_initial = self.cycle_times[self.write1_cycle]
t_final = self.cycle_times[self.write1_cycle+1] t_final = self.cycle_times[self.write1_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf, self.stim.gen_meas_power(meas_name="WRITE1_POWER",
meas_name="WRITE1_POWER",
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.read0_cycle] t_initial = self.cycle_times[self.read0_cycle]
t_final = self.cycle_times[self.read0_cycle+1] t_final = self.cycle_times[self.read0_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf, self.stim.gen_meas_power(meas_name="READ0_POWER",
meas_name="READ0_POWER",
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
t_initial = self.cycle_times[self.read1_cycle] t_initial = self.cycle_times[self.read1_cycle]
t_final = self.cycle_times[self.read1_cycle+1] t_final = self.cycle_times[self.read1_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf, self.stim.gen_meas_power(meas_name="READ1_POWER",
meas_name="READ1_POWER",
t_initial=t_initial, t_initial=t_initial,
t_final=t_final) t_final=t_final)
def find_feasible_period(self, load, slew):
def write_power_measures(self):
"""
Write the measure statements to quantify the leakage power only.
"""
self.sf.write("\n* Measure statements for idle leakage power\n")
# add measure statements for power
t_initial = self.period
t_final = 2*self.period
self.stim.gen_meas_power(meas_name="leakage_power",
t_initial=t_initial,
t_final=t_final)
def find_feasible_period(self):
""" """
Uses an initial period and finds a feasible period before we Uses an initial period and finds a feasible period before we
run the binary search algorithm to find min period. We check if run the binary search algorithm to find min period. We check if
@ -219,7 +301,7 @@ class delay():
starting point. starting point.
""" """
feasible_period = tech.spice["feasible_period"] feasible_period = float(tech.spice["feasible_period"])
time_out = 8 time_out = 8
while True: while True:
debug.info(1, "Trying feasible period: {0}ns".format(feasible_period)) debug.info(1, "Trying feasible period: {0}ns".format(feasible_period))
@ -227,81 +309,134 @@ class delay():
if (time_out <= 0): if (time_out <= 0):
debug.error("Timed out, could not find a feasible period.",2) debug.error("Timed out, could not find a feasible period.",2)
self.period = feasible_period
(success, feasible_delay1, feasible_slew1, feasible_delay0, feasible_slew0)=self.run_simulation(feasible_period,load,slew) (success, results)=self.run_delay_simulation()
if not success: if not success:
feasible_period = 2 * feasible_period feasible_period = 2 * feasible_period
continue continue
feasible_delay_lh = results["delay_lh"]
feasible_slew_lh = results["slew_lh"]
feasible_delay_hl = results["delay_hl"]
feasible_slew_hl = results["slew_hl"]
debug.info(1, "Found feasible_period: {0}ns feasible_delay1/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period, debug.info(1, "Found feasible_period: {0}ns feasible_delay {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,
feasible_delay1, feasible_delay_lh,
feasible_delay0, feasible_delay_hl,
feasible_slew1, feasible_slew_lh,
feasible_slew0)) feasible_slew_hl))
return (feasible_period, feasible_delay1, feasible_delay0) self.period = feasible_period
return (feasible_delay_lh, feasible_delay_hl)
def run_simulation(self, period, load, slew): def run_delay_simulation(self):
""" """
This tries to simulate a period and checks if the result This tries to simulate a period and checks if the result works. If
works. If so, it returns True and the delays and slews. so, it returns True and the delays, slews, and powers. It
works on the trimmed netlist by default, so powers do not
include leakage of all cells.
""" """
# Checking from not data_value to data_value # Checking from not data_value to data_value
self.write_stimulus(period, load, slew) self.write_delay_stimulus()
stimuli.run_sim() self.stim.run_sim()
delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0")) delay_hl = ch.parse_output("timing", "delay_hl")
delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1")) delay_lh = ch.parse_output("timing", "delay_lh")
slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0")) slew_hl = ch.parse_output("timing", "slew_hl")
slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1")) slew_lh = ch.parse_output("timing", "slew_lh")
delays = (delay_hl, delay_lh, slew_hl, slew_lh)
read0_power=ch.parse_output("timing", "read0_power")
write0_power=ch.parse_output("timing", "write0_power")
read1_power=ch.parse_output("timing", "read1_power")
write1_power=ch.parse_output("timing", "write1_power")
if not self.check_valid_delays(delays):
return (False,{})
# if it failed or the read was longer than a period
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float:
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
load,
slew,
delay0,
delay1,
slew0,
slew1))
return (False,0,0,0,0)
# Scale delays to ns (they previously could have not been floats)
delay0 *= 1e9
delay1 *= 1e9
slew0 *= 1e9
slew1 *= 1e9
if delay0>period or delay1>period or slew0>period or slew1>period:
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
load,
slew,
delay0,
delay1,
slew0,
slew1))
return (False,0,0,0,0)
else:
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay0={3}n delay1={4}ns slew0={5}n slew1={6}n".format(period,
load,
slew,
delay0,
delay1,
slew0,
slew1))
# For debug, you sometimes want to inspect each simulation. # For debug, you sometimes want to inspect each simulation.
#key=raw_input("press return to continue") #key=raw_input("press return to continue")
# Scale results to ns and mw, respectively
result = { "delay_hl" : delay_hl*1e9,
"delay_lh" : delay_lh*1e9,
"slew_hl" : slew_hl*1e9,
"slew_lh" : slew_lh*1e9,
"read0_power" : read0_power*1e3,
"read1_power" : read1_power*1e3,
"write0_power" : write0_power*1e3,
"write1_power" : write1_power*1e3}
# The delay is from the negative edge for our SRAM # The delay is from the negative edge for our SRAM
return (True,delay1,slew1,delay0,slew0) return (True,result)
def run_power_simulation(self):
"""
This simulates a disabled SRAM to get the leakage power when it is off.
def find_min_period(self,feasible_period, load, slew, feasible_delay1, feasible_delay0): """
self.write_power_stimulus(trim=False)
self.stim.run_sim()
leakage_power=ch.parse_output("timing", "leakage_power")
debug.check(leakage_power!="Failed","Could not measure leakage power.")
self.write_power_stimulus(trim=True)
self.stim.run_sim()
trim_leakage_power=ch.parse_output("timing", "leakage_power")
debug.check(trim_leakage_power!="Failed","Could not measure leakage power.")
# For debug, you sometimes want to inspect each simulation.
#key=raw_input("press return to continue")
return (leakage_power*1e3, trim_leakage_power*1e3)
def check_valid_delays(self, (delay_hl, delay_lh, slew_hl, slew_lh)):
""" Check if the measurements are defined and if they are valid. """
# if it failed or the read was longer than a period
if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
debug.info(2,"Failed simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
self.load,
self.slew,
delay_hl,
delay_lh,
slew_hl,
slew_lh))
return False
# Scale delays to ns (they previously could have not been floats)
delay_hl *= 1e9
delay_lh *= 1e9
slew_hl *= 1e9
slew_lh *= 1e9
if delay_hl>self.period or delay_lh>self.period or slew_hl>self.period or slew_lh>self.period:
debug.info(2,"UNsuccessful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
self.load,
self.slew,
delay_hl,
delay_lh,
slew_hl,
slew_lh))
return False
else:
debug.info(2,"Successful simulation: period {0} load {1} slew {2}, delay_hl={3}n delay_lh={4}ns slew_hl={5}n slew_lh={6}n".format(self.period,
self.load,
self.slew,
delay_hl,
delay_lh,
slew_hl,
slew_lh))
return True
def find_min_period(self, feasible_delay_lh, feasible_delay_hl):
""" """
Searches for the smallest period with output delays being within 5% of Searches for the smallest period with output delays being within 5% of
long period. long period.
""" """
previous_period = ub_period = feasible_period previous_period = ub_period = self.period
lb_period = 0.0 lb_period = 0.0
# Binary search algorithm to find the min period (max frequency) of design # Binary search algorithm to find the min period (max frequency) of design
@ -312,11 +447,12 @@ class delay():
debug.error("Timed out, could not converge on minimum period.",2) debug.error("Timed out, could not converge on minimum period.",2)
target_period = 0.5 * (ub_period + lb_period) target_period = 0.5 * (ub_period + lb_period)
self.period = target_period
debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period, debug.info(1, "MinPeriod Search: {0}ns (ub: {1} lb: {2})".format(target_period,
ub_period, ub_period,
lb_period)) lb_period))
if self.try_period(target_period, load, slew, feasible_delay1, feasible_delay0): if self.try_period(feasible_delay_lh, feasible_delay_hl):
ub_period = target_period ub_period = target_period
else: else:
lb_period = target_period lb_period = target_period
@ -326,54 +462,54 @@ class delay():
return ub_period return ub_period
def try_period(self, period, load, slew, feasible_delay1, feasible_delay0): def try_period(self, feasible_delay_lh, feasible_delay_hl):
""" """
This tries to simulate a period and checks if the result This tries to simulate a period and checks if the result
works. If it does and the delay is within 5% still, it returns True. works. If it does and the delay is within 5% still, it returns True.
""" """
# Checking from not data_value to data_value # Checking from not data_value to data_value
self.write_stimulus(period,load,slew) self.write_delay_stimulus()
stimuli.run_sim() self.stim.run_sim()
delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0")) delay_hl = ch.parse_output("timing", "delay_hl")
delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1")) delay_lh = ch.parse_output("timing", "delay_lh")
slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0")) slew_hl = ch.parse_output("timing", "slew_hl")
slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1")) slew_lh = ch.parse_output("timing", "slew_lh")
# if it failed or the read was longer than a period # if it failed or the read was longer than a period
if type(delay0)!=float or type(delay1)!=float or type(slew1)!=float or type(slew0)!=float: if type(delay_hl)!=float or type(delay_lh)!=float or type(slew_lh)!=float or type(slew_hl)!=float:
debug.info(2,"Invalid measures: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, debug.info(2,"Invalid measures: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
delay0, delay_hl,
delay1, delay_lh,
slew0, slew_hl,
slew1)) slew_lh))
return False return False
delay0 *= 1e9 delay_hl *= 1e9
delay1 *= 1e9 delay_lh *= 1e9
slew0 *= 1e9 slew_hl *= 1e9
slew1 *= 1e9 slew_lh *= 1e9
if delay0>period or delay1>period or slew0>period or slew1>period: if delay_hl>self.period or delay_lh>self.period or slew_hl>self.period or slew_lh>self.period:
debug.info(2,"Too long delay/slew: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, debug.info(2,"Too long delay/slew: Period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
delay0, delay_hl,
delay1, delay_lh,
slew0, slew_hl,
slew1)) slew_lh))
return False return False
else: else:
if not ch.relative_compare(delay1,feasible_delay1,error_tolerance=0.05): if not ch.relative_compare(delay_lh,feasible_delay_lh,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay1,feasible_delay1)) debug.info(2,"Delay too big {0} vs {1}".format(delay_lh,feasible_delay_lh))
return False return False
elif not ch.relative_compare(delay0,feasible_delay0,error_tolerance=0.05): elif not ch.relative_compare(delay_hl,feasible_delay_hl,error_tolerance=0.05):
debug.info(2,"Delay too big {0} vs {1}".format(delay0,feasible_delay0)) debug.info(2,"Delay too big {0} vs {1}".format(delay_hl,feasible_delay_hl))
return False return False
#key=raw_input("press return to continue") #key=raw_input("press return to continue")
debug.info(2,"Successful period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, debug.info(2,"Successful period {0}, delay_hl={1}ns, delay_lh={2}ns slew_hl={3}ns slew_lh={4}ns".format(self.period,
delay0, delay_hl,
delay1, delay_lh,
slew0, slew_hl,
slew1)) slew_lh))
return True return True
def set_probe(self,probe_address, probe_data): def set_probe(self,probe_address, probe_data):
@ -382,12 +518,35 @@ class delay():
self.probe_address = probe_address self.probe_address = probe_address
self.probe_data = probe_data self.probe_data = probe_data
self.prepare_netlist()
def prepare_netlist(self):
""" Prepare a trimmed netlist and regular netlist. """
# Set up to trim the netlist here if that is enabled
if OPTS.trim_netlist:
self.trim_sp_file = "{}reduced.sp".format(OPTS.openram_temp)
self.trimsp=trim_spice(self.sp_file, self.trim_sp_file)
self.trimsp.set_configuration(self.num_banks,
self.num_rows,
self.num_cols,
self.word_size)
self.trimsp.trim(self.probe_address,self.probe_data)
else:
# The non-reduced netlist file when it is disabled
self.trim_sp_file = "{}sram.sp".format(OPTS.openram_temp)
# The non-reduced netlist file for power simulation
self.sim_sp_file = "{}sram.sp".format(OPTS.openram_temp)
# Make a copy in temp for debugging
shutil.copy(self.sp_file, self.sim_sp_file)
def analyze(self,probe_address, probe_data, slews, loads): def analyze(self,probe_address, probe_data, slews, loads):
"""main function to calculate the min period for a low_to_high """
transistion and a high_to_low transistion returns a dictionary Main function to characterize an SRAM for a table. Computes both delay and power characterization.
that contains all both the min period and associated delays
Dictionary Keys: min_period1, delay1, min_period0, delay0
""" """
self.set_probe(probe_address, probe_data) self.set_probe(probe_address, probe_data)
@ -395,58 +554,62 @@ class delay():
# This is for debugging a full simulation # This is for debugging a full simulation
# debug.info(0,"Debug simulation running...") # debug.info(0,"Debug simulation running...")
# target_period=50.0 # target_period=50.0
# feasible_delay1=0.059083183 # feasible_delay_lh=0.059083183
# feasible_delay0=0.17953789 # feasible_delay_hl=0.17953789
# load=1.6728 # load=1.6728
# slew=0.04 # slew=0.04
# self.try_period(target_period, load, slew, feasible_delay1, feasible_delay0) # self.try_period(target_period, feasible_delay_lh, feasible_delay_hl)
# sys.exit(1) # sys.exit(1)
(feasible_period, feasible_delay1, feasible_delay0) = self.find_feasible_period(max(loads), max(slews)) # 1) Find a feasible period and it's corresponding delays using the trimmed array.
debug.check(feasible_delay1>0,"Negative delay may not be possible") self.load=max(loads)
debug.check(feasible_delay0>0,"Negative delay may not be possible") self.slew=max(slews)
(feasible_delay_lh, feasible_delay_hl) = self.find_feasible_period()
debug.check(feasible_delay_lh>0,"Negative delay may not be possible")
debug.check(feasible_delay_hl>0,"Negative delay may not be possible")
# The power variables are just scalars. These use the final feasible period simulation # 2) Measure the delay, slew and power for all slew/load pairs.
# which should have worked. # Make a list for each type of measurement to append results to
read0_power=ch.convert_to_float(ch.parse_output("timing", "read0_power")) char_data = {}
write0_power=ch.convert_to_float(ch.parse_output("timing", "write0_power")) for m in ["delay_lh", "delay_hl", "slew_lh", "slew_hl", "read0_power",
read1_power=ch.convert_to_float(ch.parse_output("timing", "read1_power")) "read1_power", "write0_power", "write1_power", "leakage_power"]:
write1_power=ch.convert_to_float(ch.parse_output("timing", "write1_power")) char_data[m]=[]
# 2a) Find the leakage power of the trimmmed and UNtrimmed arrays.
(full_array_leakage, trim_array_leakage)=self.run_power_simulation()
char_data["leakage_power"]=full_array_leakage
LH_delay = []
HL_delay = []
LH_slew = []
HL_slew = []
for slew in slews: for slew in slews:
for load in loads: for load in loads:
(success, delay1, slew1, delay0, slew0) = self.run_simulation(feasible_period, load, slew) self.set_load_slew(load,slew)
debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(slew,load)) # 2c) Find the delay, dynamic power, and leakage power of the trimmed array.
LH_delay.append(delay1) (success, delay_results) = self.run_delay_simulation()
HL_delay.append(delay0) debug.check(success,"Couldn't run a simulation. slew={0} load={1}\n".format(self.slew,self.load))
LH_slew.append(slew1) for k,v in delay_results.items():
HL_slew.append(slew0) if "power" in k:
# Subtract partial array leakage and add full array leakage for the power measures
char_data[k].append(v - trim_array_leakage + full_array_leakage)
else:
char_data[k].append(v)
# finds the minimum period without degrading the delays by X%
min_period = self.find_min_period(feasible_period, max(loads), max(slews), feasible_delay1, feasible_delay0)
# 3) Finds the minimum period without degrading the delays by X%
self.set_load_slew(max(loads),max(slews))
min_period = self.find_min_period(feasible_delay_lh, feasible_delay_hl)
debug.check(type(min_period)==float,"Couldn't find minimum period.") debug.check(type(min_period)==float,"Couldn't find minimum period.")
debug.info(1, "Min Period: {0}n with a delay of {1} / {2}".format(min_period, feasible_delay1, feasible_delay0)) debug.info(1, "Min Period: {0}n with a delay of {1} / {2}".format(min_period, feasible_delay_lh, feasible_delay_hl))
# 4) Pack up the final measurements
char_data["min_period"] = ch.round_time(min_period)
return char_data
data = {"min_period": ch.round_time(min_period),
"delay1": LH_delay,
"delay0": HL_delay,
"slew1": LH_slew,
"slew0": HL_slew,
"read0_power": read0_power*1e3,
"read1_power": read1_power*1e3,
"write0_power": write0_power*1e3,
"write1_power": write1_power*1e3
}
return data
def obtain_cycle_times(self, period): def obtain_cycle_times(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)
of the cycles to do a timing evaluation. The last time is the end of the simulation of the cycles to do a timing evaluation. The last time is the end of the simulation
and does not need a rising edge.""" and does not need a rising edge."""
@ -461,7 +624,7 @@ class delay():
t_current, t_current,
msg)) msg))
self.cycle_times.append(t_current) self.cycle_times.append(t_current)
t_current += period t_current += self.period
# One period # One period
msg = "W data 1 address 11..11 to initialize cell" msg = "W data 1 address 11..11 to initialize cell"
@ -469,7 +632,7 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "W data 0 address 11..11 (to ensure a write of value works)" msg = "W data 0 address 11..11 (to ensure a write of value works)"
@ -478,7 +641,7 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "W data 1 address 00..00 (to clear bus caps)" msg = "W data 1 address 00..00 (to clear bus caps)"
@ -486,7 +649,7 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "R data 0 address 11..11 to check W0 worked" msg = "R data 0 address 11..11 to check W0 worked"
@ -495,15 +658,16 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "Idle cycle" msg = "Idle cycle (Read addr 00..00)"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
self.cycle_times.append(t_current) self.cycle_times.append(t_current)
t_current += period self.idle_cycle=len(self.cycle_times)-1
t_current += self.period
# One period # One period
msg = "W data 1 address 11..11 (to ensure a write of value worked)" msg = "W data 1 address 11..11 (to ensure a write of value worked)"
@ -512,7 +676,7 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "W data 0 address 00..00 (to clear bus caps)" msg = "W data 0 address 00..00 (to clear bus caps)"
@ -520,7 +684,7 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "R data 1 address 11..11 to check W1 worked" msg = "R data 1 address 11..11 to check W1 worked"
@ -529,55 +693,57 @@ class delay():
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
t_current += period t_current += self.period
# One period # One period
msg = "Idle cycle" msg = "Idle cycle (Read addr 11..11)"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1, self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current, t_current,
msg)) msg))
self.cycle_times.append(t_current) self.cycle_times.append(t_current)
t_current += period t_current += self.period
def analytical_model(self,sram, slews, loads): def analytical_delay(self,sram, slews, loads):
""" Just return the analytical model results for the SRAM. """ Just return the analytical model results for the SRAM.
""" """
LH_delay = [] delay_lh = []
HL_delay = [] delay_hl = []
LH_slew = [] slew_lh = []
HL_slew = [] slew_hl = []
for slew in slews: for slew in slews:
for load in loads: for load in loads:
bank_delay = sram.analytical_delay(slew,load) self.set_load_slew(load,slew)
bank_delay = sram.analytical_delay(self.slew,self.load)
# Convert from ps to ns # Convert from ps to ns
LH_delay.append(bank_delay.delay/1e3) delay_lh.append(bank_delay.delay/1e3)
HL_delay.append(bank_delay.delay/1e3) delay_hl.append(bank_delay.delay/1e3)
LH_slew.append(bank_delay.slew/1e3) slew_lh.append(bank_delay.slew/1e3)
HL_slew.append(bank_delay.slew/1e3) slew_hl.append(bank_delay.slew/1e3)
data = {"min_period": 0, data = {"min_period": 0,
"delay1": LH_delay, "delay_lh": delay_lh,
"delay0": HL_delay, "delay_hl": delay_hl,
"slew1": LH_slew, "slew_lh": slew_lh,
"slew0": HL_slew, "slew_hl": slew_hl,
"read0_power": 0, "read0_power": 0,
"read1_power": 0, "read1_power": 0,
"write0_power": 0, "write0_power": 0,
"write1_power": 0 "write1_power": 0,
"leakage_power": 0
} }
return data return data
def gen_data(self, clk_times, sig_name, period, slew): def gen_data(self, clk_times, sig_name):
""" Generates the PWL data inputs for a simulation timing test. """ """ Generates the PWL data inputs for a simulation timing test. """
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP # values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# we are asserting the opposite value on the other side of the tx gate during # we are asserting the opposite value on the other side of the tx gate during
# the read to be "worst case". Otherwise, it can actually assist the read. # the read to be "worst case". Otherwise, it can actually assist the read.
values = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0 ] values = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0 ]
stimuli.gen_pwl(self.sf, sig_name, clk_times, values, period, slew, 0.05) self.stim.gen_pwl(sig_name, clk_times, values, self.period, self.slew, 0.05)
def gen_addr(self, clk_times, addr, period, slew): def gen_addr(self, clk_times, addr):
""" """
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.
@ -589,34 +755,34 @@ class delay():
for i in range(len(addr)): for i in range(len(addr)):
sig_name = "A[{0}]".format(i) sig_name = "A[{0}]".format(i)
if addr[i]=="1": if addr[i]=="1":
stimuli.gen_pwl(self.sf, sig_name, clk_times, ones_values, period, slew, 0.05) self.stim.gen_pwl(sig_name, clk_times, ones_values, self.period, self.slew, 0.05)
else: else:
stimuli.gen_pwl(self.sf, sig_name, clk_times, zero_values, period, slew, 0.05) self.stim.gen_pwl(sig_name, clk_times, zero_values, self.period, self.slew, 0.05)
def gen_csb(self, clk_times, period, slew): def gen_csb(self, clk_times):
""" Generates the PWL CSb signal """ """ Generates the PWL CSb signal """
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP # values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep CSb asserted in NOP for measuring >1 period # Keep CSb asserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0] values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
stimuli.gen_pwl(self.sf, "csb", clk_times, values, period, slew, 0.05) self.stim.gen_pwl("csb", clk_times, values, self.period, self.slew, 0.05)
def gen_web(self, clk_times, period, slew): def gen_web(self, clk_times):
""" Generates the PWL WEb signal """ """ Generates the PWL WEb signal """
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP # values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep WEb deasserted in NOP for measuring >1 period # Keep WEb deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1] values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
stimuli.gen_pwl(self.sf, "web", clk_times, values, period, slew, 0.05) self.stim.gen_pwl("web", clk_times, values, self.period, self.slew, 0.05)
# Keep acc_en deasserted in NOP for measuring >1 period # Keep acc_en deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1] values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
stimuli.gen_pwl(self.sf, "acc_en", clk_times, values, period, slew, 0) self.stim.gen_pwl("acc_en", clk_times, values, self.period, self.slew, 0)
values = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0] values = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
stimuli.gen_pwl(self.sf, "acc_en_inv", clk_times, values, period, slew, 0) self.stim.gen_pwl("acc_en_inv", clk_times, values, self.period, self.slew, 0)
def gen_oeb(self, clk_times, period, slew): def gen_oeb(self, clk_times):
""" Generates the PWL WEb signal """ """ Generates the PWL WEb signal """
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP # values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
# Keep OEb asserted in NOP for measuring >1 period # Keep OEb asserted in NOP for measuring >1 period
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0] values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
stimuli.gen_pwl(self.sf, "oeb", clk_times, values, period, slew, 0.05) self.stim.gen_pwl("oeb", clk_times, values, self.period, self.slew, 0.05)

View File

@ -1,4 +1,4 @@
import os,sys,re,shutil import os,sys,re
import debug import debug
import math import math
import setup_hold import setup_hold
@ -6,40 +6,31 @@ import delay
import charutils as ch import charutils as ch
import tech import tech
import numpy as np import numpy as np
from trim_spice import trim_spice
from globals import OPTS from globals import OPTS
class lib: class lib:
""" lib file generation.""" """ lib file generation."""
def __init__(self, libname, sram, spfile, use_model=OPTS.analytical_delay): def __init__(self, out_dir, sram, sp_file, use_model=OPTS.analytical_delay):
self.out_dir = out_dir
self.sram = sram self.sram = sram
self.sp_file = spfile self.sp_file = sp_file
self.use_model = use_model self.use_model = use_model
self.name = sram.name
self.num_words = sram.num_words
self.word_size = sram.word_size
self.addr_size = sram.addr_size
# Set up to trim the netlist here if that is enabled self.prepare_tables()
if OPTS.trim_netlist:
self.sim_sp_file = "{}reduced.sp".format(OPTS.openram_temp)
self.trimsp=trim_spice(self.sp_file, self.sim_sp_file)
self.trimsp.set_configuration(self.sram.num_banks,
self.sram.num_rows,
self.sram.num_cols,
self.sram.word_size)
else:
# Else, use the non-reduced netlist file for simulation
self.sim_sp_file = "{}sram.sp".format(OPTS.openram_temp)
# Make a copy in temp for debugging
shutil.copy(self.sp_file, self.sim_sp_file)
self.create_corners()
self.characterize_corners()
def prepare_tables(self):
""" Determine the load/slews if they aren't specified in the config file. """
# These are the parameters to determine the table sizes # These are the parameters to determine the table sizes
#self.load_scales = np.array([0.1, 0.25, 0.5, 1, 2, 4, 8]) #self.load_scales = np.array([0.1, 0.25, 0.5, 1, 2, 4, 8])
self.load_scales = np.array([0.25, 1, 8]) self.load_scales = np.array([0.25, 1, 8])
#self.load_scales = np.array([0.25, 1]) #self.load_scales = np.array([0.25, 1])
self.load = tech.spice["FF_in_cap"] self.load = tech.spice["dff_in_cap"]
self.loads = self.load_scales*self.load self.loads = self.load_scales*self.load
debug.info(1,"Loads: {0}".format(self.loads)) debug.info(1,"Loads: {0}".format(self.loads))
@ -50,8 +41,47 @@ class lib:
self.slews = self.slew_scales*self.slew self.slews = self.slew_scales*self.slew
debug.info(1,"Slews: {0}".format(self.slews)) debug.info(1,"Slews: {0}".format(self.slews))
debug.info(1,"Writing to {0}".format(libname))
self.lib = open(libname, "w") def create_corners(self):
""" Create corners for characterization. """
# Get the corners from the options file
self.temperatures = OPTS.temperatures
self.supply_voltages = OPTS.supply_voltages
self.process_corners = OPTS.process_corners
# Enumerate all possible corners
self.corners = []
self.lib_files = []
for proc in self.process_corners:
for temp in self.temperatures:
for volt in self.supply_voltages:
self.corner_name = "{0}_{1}_{2}V_{3}C".format(self.sram.name,
proc,
volt,
temp)
self.corner_name = self.corner_name.replace(".","p") # Remove decimals
lib_name = self.out_dir+"{}.lib".format(self.corner_name)
# A corner is a tuple of PVT
self.corners.append((proc, volt, temp))
self.lib_files.append(lib_name)
def characterize_corners(self):
""" Characterize the list of corners. """
for (self.corner,lib_name) in zip(self.corners,self.lib_files):
debug.info(1,"Corner: " + str(self.corner))
(self.process, self.voltage, self.temperature) = self.corner
self.lib = open(lib_name, "w")
debug.info(1,"Writing to {0}".format(lib_name))
self.characterize()
self.lib.close()
def characterize(self):
""" Characterize the current corner. """
self.compute_delay()
self.compute_setup_hold()
self.write_header() self.write_header()
@ -63,11 +93,16 @@ class lib:
self.write_clk() self.write_clk()
self.lib.close() self.write_footer()
def write_footer(self):
""" Write the footer """
self.lib.write("}\n")
def write_header(self): def write_header(self):
""" Write the header information """ """ Write the header information """
self.lib.write("library ({0}_lib)".format(self.name)) self.lib.write("library ({0}_lib)".format(self.corner_name))
self.lib.write("{\n") self.lib.write("{\n")
self.lib.write(" delay_model : \"table_lookup\";\n") self.lib.write(" delay_model : \"table_lookup\";\n")
@ -75,22 +110,29 @@ class lib:
self.write_defaults() self.write_defaults()
self.write_LUT_templates() self.write_LUT_templates()
self.lib.write(" default_operating_conditions : TT; \n") self.lib.write(" default_operating_conditions : OC; \n")
self.write_bus() self.write_bus()
self.lib.write("cell ({0})".format(self.name)) self.lib.write("cell ({0})".format(self.sram.name))
self.lib.write("{\n") self.lib.write("{\n")
self.lib.write(" memory(){ \n") self.lib.write(" memory(){ \n")
self.lib.write(" type : ram;\n") self.lib.write(" type : ram;\n")
self.lib.write(" address_width : {0};\n".format(self.addr_size)) self.lib.write(" address_width : {};\n".format(self.sram.addr_size))
self.lib.write(" word_width : {0};\n".format(self.word_size)) self.lib.write(" word_width : {};\n".format(self.sram.word_size))
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" interface_timing : true;\n") self.lib.write(" interface_timing : true;\n")
self.lib.write(" dont_use : true;\n") self.lib.write(" dont_use : true;\n")
self.lib.write(" map_only : true;\n") self.lib.write(" map_only : true;\n")
self.lib.write(" dont_touch : true;\n") self.lib.write(" dont_touch : true;\n")
self.lib.write(" area : {0};\n\n".format(self.sram.width * self.sram.height)) self.lib.write(" area : {};\n\n".format(self.sram.width * self.sram.height))
# Leakage is included in dynamic when macro is enabled
self.lib.write(" leakage_power () {\n")
self.lib.write(" when : \"CSb\";\n")
self.lib.write(" value : {};\n".format(self.char_results["leakage_power"]))
self.lib.write(" }\n")
self.lib.write(" cell_leakage_power : {};\n".format(0))
def write_units(self): def write_units(self):
@ -103,9 +145,10 @@ class lib:
self.lib.write(" capacitive_load_unit(1 ,fF) ;\n") self.lib.write(" capacitive_load_unit(1 ,fF) ;\n")
self.lib.write(" leakage_power_unit : \"1mW\" ;\n") self.lib.write(" leakage_power_unit : \"1mW\" ;\n")
self.lib.write(" pulling_resistance_unit :\"1kohm\" ;\n") self.lib.write(" pulling_resistance_unit :\"1kohm\" ;\n")
self.lib.write(" operating_conditions(TT){\n") self.lib.write(" operating_conditions(OC){\n")
self.lib.write(" voltage : {0} ;\n".format(tech.spice["supply_voltage"])) self.lib.write(" process : {} ;\n".format(1.0)) # How to use TT, FF, SS?
self.lib.write(" temperature : 25.000 ;\n") self.lib.write(" voltage : {} ;\n".format(self.voltage))
self.lib.write(" temperature : {};\n".format(self.temperature))
self.lib.write(" }\n\n") self.lib.write(" }\n\n")
def write_defaults(self): def write_defaults(self):
@ -120,6 +163,10 @@ class lib:
self.lib.write(" slew_lower_threshold_pct_rise : 10.0 ;\n") self.lib.write(" slew_lower_threshold_pct_rise : 10.0 ;\n")
self.lib.write(" slew_upper_threshold_pct_rise : 90.0 ;\n\n") self.lib.write(" slew_upper_threshold_pct_rise : 90.0 ;\n\n")
self.lib.write(" nom_voltage : {};\n".format(tech.spice["nom_supply_voltage"]))
self.lib.write(" nom_temperature : {};\n".format(tech.spice["nom_temperature"]))
self.lib.write(" nom_process : {};\n".format(1.0))
self.lib.write(" default_cell_leakage_power : 0.0 ;\n") self.lib.write(" default_cell_leakage_power : 0.0 ;\n")
self.lib.write(" default_leakage_power_density : 0.0 ;\n") self.lib.write(" default_leakage_power_density : 0.0 ;\n")
self.lib.write(" default_input_pin_cap : 1.0 ;\n") self.lib.write(" default_input_pin_cap : 1.0 ;\n")
@ -206,25 +253,23 @@ class lib:
self.lib.write(" type (DATA){\n") self.lib.write(" type (DATA){\n")
self.lib.write(" base_type : array;\n") self.lib.write(" base_type : array;\n")
self.lib.write(" data_type : bit;\n") self.lib.write(" data_type : bit;\n")
self.lib.write(" bit_width : {0};\n".format(self.word_size)) self.lib.write(" bit_width : {0};\n".format(self.sram.word_size))
self.lib.write(" bit_from : 0;\n") self.lib.write(" bit_from : 0;\n")
self.lib.write(" bit_to : {0};\n".format(self.word_size - 1)) self.lib.write(" bit_to : {0};\n".format(self.sram.word_size - 1))
self.lib.write(" }\n\n") self.lib.write(" }\n\n")
self.lib.write(" type (ADDR){\n") self.lib.write(" type (ADDR){\n")
self.lib.write(" base_type : array;\n") self.lib.write(" base_type : array;\n")
self.lib.write(" data_type : bit;\n") self.lib.write(" data_type : bit;\n")
self.lib.write(" bit_width : {0};\n".format(self.addr_size)) self.lib.write(" bit_width : {0};\n".format(self.sram.addr_size))
self.lib.write(" bit_from : 0;\n") self.lib.write(" bit_from : 0;\n")
self.lib.write(" bit_to : {0};\n".format(self.addr_size - 1)) self.lib.write(" bit_to : {0};\n".format(self.sram.addr_size - 1))
self.lib.write(" }\n\n") self.lib.write(" }\n\n")
def write_FF_setuphold(self): def write_FF_setuphold(self):
""" Adds Setup and Hold timing results""" """ Adds Setup and Hold timing results"""
self.compute_setup_hold()
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\"; \n")
@ -255,12 +300,12 @@ class lib:
def write_data_bus(self): def write_data_bus(self):
""" Adds data bus timing results.""" """ Adds data bus timing results."""
self.compute_delay()
self.lib.write(" bus(DATA){\n") self.lib.write(" bus(DATA){\n")
self.lib.write(" bus_type : DATA; \n") self.lib.write(" bus_type : DATA; \n")
self.lib.write(" direction : inout; \n") self.lib.write(" direction : inout; \n")
self.lib.write(" max_capacitance : {0}; \n".format(8*tech.spice["FF_in_cap"])) # This is conservative, but limit to range that we characterized.
self.lib.write(" max_capacitance : {0}; \n".format(max(self.loads)))
self.lib.write(" min_capacitance : {0}; \n".format(min(self.loads)))
self.lib.write(" three_state : \"!OEb & !clk\"; \n") self.lib.write(" three_state : \"!OEb & !clk\"; \n")
self.lib.write(" memory_write(){ \n") self.lib.write(" memory_write(){ \n")
self.lib.write(" address : ADDR; \n") self.lib.write(" address : ADDR; \n")
@ -269,53 +314,29 @@ class lib:
self.lib.write(" memory_read(){ \n") self.lib.write(" memory_read(){ \n")
self.lib.write(" address : ADDR; \n") self.lib.write(" address : ADDR; \n")
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" pin(DATA[{0}:0])".format(self.word_size - 1))
self.lib.write("{\n")
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"OEb & !clk\"; \n")
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(self.delay["write1_power"]))
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(self.delay["write0_power"]))
self.lib.write(" }\n")
self.lib.write(" }\n")
self.lib.write(" pin(DATA[{0}:0]){{\n".format(self.sram.word_size - 1))
self.write_FF_setuphold() self.write_FF_setuphold()
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"!OEb & !clk\"; \n")
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(self.delay["read1_power"]))
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(self.delay["read0_power"]))
self.lib.write(" }\n")
self.lib.write(" }\n")
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\"; \n")
self.lib.write(" timing_type : falling_edge; \n") self.lib.write(" timing_type : falling_edge; \n")
self.lib.write(" cell_rise(CELL_TABLE) {\n") self.lib.write(" cell_rise(CELL_TABLE) {\n")
rounded_values = map(ch.round_time,self.delay["delay1"]) self.write_values(self.char_results["delay_lh"],len(self.loads)," ")
self.write_values(rounded_values,len(self.loads)," ") self.lib.write(" }\n") # rise delay
self.lib.write(" }\n")
self.lib.write(" cell_fall(CELL_TABLE) {\n") self.lib.write(" cell_fall(CELL_TABLE) {\n")
rounded_values = map(ch.round_time,self.delay["delay0"]) self.write_values(self.char_results["delay_hl"],len(self.loads)," ")
self.write_values(rounded_values,len(self.loads)," ") self.lib.write(" }\n") # fall delay
self.lib.write(" }\n")
self.lib.write(" rise_transition(CELL_TABLE) {\n") self.lib.write(" rise_transition(CELL_TABLE) {\n")
rounded_values = map(ch.round_time,self.delay["slew1"]) self.write_values(self.char_results["slew_lh"],len(self.loads)," ")
self.write_values(rounded_values,len(self.loads)," ") self.lib.write(" }\n") # rise trans
self.lib.write(" }\n")
self.lib.write(" fall_transition(CELL_TABLE) {\n") self.lib.write(" fall_transition(CELL_TABLE) {\n")
rounded_values = map(ch.round_time,self.delay["slew0"]) self.write_values(self.char_results["slew_hl"],len(self.loads)," ")
self.write_values(rounded_values,len(self.loads)," ") self.lib.write(" }\n") # fall trans
self.lib.write(" }\n") self.lib.write(" }\n") # timing
self.lib.write(" }\n") self.lib.write(" }\n") # pin
self.lib.write(" }\n") self.lib.write(" }\n\n") # bus
self.lib.write(" }\n\n")
def write_addr_bus(self): def write_addr_bus(self):
@ -324,10 +345,9 @@ class lib:
self.lib.write(" bus(ADDR){\n") self.lib.write(" bus(ADDR){\n")
self.lib.write(" bus_type : ADDR; \n") self.lib.write(" bus_type : ADDR; \n")
self.lib.write(" direction : input; \n") self.lib.write(" direction : input; \n")
self.lib.write(" capacitance : {0}; \n".format(tech.spice["FF_in_cap"])) self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
self.lib.write(" max_transition : {0};\n".format(self.slews[-1])) self.lib.write(" max_transition : {0};\n".format(self.slews[-1]))
self.lib.write(" fanout_load : 1.000000;\n") self.lib.write(" pin(ADDR[{0}:0])".format(self.sram.addr_size - 1))
self.lib.write(" pin(ADDR[{0}:0])".format(self.addr_size - 1))
self.lib.write("{\n") self.lib.write("{\n")
self.write_FF_setuphold() self.write_FF_setuphold()
@ -343,7 +363,7 @@ class lib:
self.lib.write(" pin({0})".format(i)) self.lib.write(" pin({0})".format(i))
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["FF_in_cap"])) self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
self.write_FF_setuphold() self.write_FF_setuphold()
self.lib.write(" }\n\n") self.lib.write(" }\n\n")
@ -351,14 +371,50 @@ class lib:
def write_clk(self): def write_clk(self):
""" Adds clk pin timing results.""" """ Adds clk pin timing results."""
self.compute_delay()
self.lib.write(" pin(clk){\n") self.lib.write(" pin(clk){\n")
self.lib.write(" clock : true;\n") self.lib.write(" clock : true;\n")
self.lib.write(" direction : input; \n") self.lib.write(" direction : input; \n")
self.lib.write(" capacitance : {0}; \n".format(tech.spice["FF_in_cap"])) # This should actually be a min inverter cap, but ok...
min_pulse_width = ch.round_time(self.delay["min_period"])/2.0 self.lib.write(" capacitance : {0}; \n".format(tech.spice["dff_in_cap"]))
min_period = ch.round_time(self.delay["min_period"])
# Find the average power of 1 and 0 bits for writes and reads over all loads/slews
# Could make it a table, but this is fine for now.
avg_write_power = np.mean(self.char_results["write1_power"] + self.char_results["write0_power"])
avg_read_power = np.mean(self.char_results["read1_power"] + self.char_results["read0_power"])
# Equally divide read/write power between first and second half of clock period
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"!CSb & clk & !WEb\"; \n")
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_write_power/2.0))
self.lib.write(" }\n")
self.lib.write(" }\n")
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"!CSb & !clk & WEb\"; \n")
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"{0}\");\n".format(avg_read_power/2.0))
self.lib.write(" }\n")
self.lib.write(" }\n")
# Have 0 internal power when disabled, this will be represented as leakage power.
self.lib.write(" internal_power(){\n")
self.lib.write(" when : \"CSb\"; \n")
self.lib.write(" rise_power(scalar){\n")
self.lib.write(" values(\"0\");\n")
self.lib.write(" }\n")
self.lib.write(" fall_power(scalar){\n")
self.lib.write(" values(\"0\");\n")
self.lib.write(" }\n")
self.lib.write(" }\n")
min_pulse_width = ch.round_time(self.char_results["min_period"])/2.0
min_period = ch.round_time(self.char_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; \n")
@ -381,23 +437,20 @@ class lib:
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write(" }\n") self.lib.write(" }\n")
self.lib.write("}\n")
def compute_delay(self): def compute_delay(self):
""" Do the analysis if we haven't characterized the SRAM yet """ """ Do the analysis if we haven't characterized the SRAM yet """
try: try:
self.d self.d
except AttributeError: except AttributeError:
self.d = delay.delay(self.sram, self.sim_sp_file) self.d = delay.delay(self.sram, self.sp_file, self.corner)
if self.use_model: if self.use_model:
self.delay = self.d.analytical_model(self.sram,self.slews,self.loads) self.char_results = self.d.analytical_delay(self.sram,self.slews,self.loads)
else: else:
probe_address = "1" * self.addr_size probe_address = "1" * self.sram.addr_size
probe_data = self.word_size - 1 probe_data = self.sram.word_size - 1
# We must trim based on a specific address and data bit self.char_results = self.d.analyze(probe_address, probe_data, self.slews, self.loads)
if OPTS.trim_netlist:
self.trimsp.trim(probe_address,probe_data)
self.delay = self.d.analyze(probe_address, probe_data, self.slews, self.loads)
def compute_setup_hold(self): def compute_setup_hold(self):
""" Do the analysis if we haven't characterized a FF yet """ """ Do the analysis if we haven't characterized a FF yet """
@ -405,9 +458,9 @@ class lib:
try: try:
self.sh self.sh
except AttributeError: except AttributeError:
self.sh = setup_hold.setup_hold() self.sh = setup_hold.setup_hold(self.corner)
if self.use_model: if self.use_model:
self.times = self.sh.analytical_model(self.slews,self.loads) self.times = self.sh.analytical_setuphold(self.slews,self.loads)
else: else:
self.times = self.sh.analyze(self.slews,self.slews) self.times = self.sh.analyze(self.slews,self.slews)

View File

@ -13,19 +13,24 @@ class setup_hold():
(Bisection Methodology) (Bisection Methodology)
""" """
def __init__(self): def __init__(self, corner):
# This must match the spice model order # This must match the spice model order
self.pins = ["data", "dout", "dout_bar", "clk", "vdd", "gnd"] self.pins = ["data", "dout", "dout_bar", "clk", "vdd", "gnd"]
self.model_name = "ms_flop" self.model_name = "ms_flop"
self.model_location = OPTS.openram_tech + "sp_lib/ms_flop.sp" self.model_location = OPTS.openram_tech + "sp_lib/ms_flop.sp"
self.period = tech.spice["feasible_period"] self.period = tech.spice["feasible_period"]
self.vdd = tech.spice["supply_voltage"]
self.gnd = tech.spice["gnd_voltage"]
debug.info(2,"Feasible period from technology file: {0} ".format(self.period)) debug.info(2,"Feasible period from technology file: {0} ".format(self.period))
self.set_corner(corner)
def set_corner(self,corner):
""" Set the corner values """
self.corner = corner
(self.process, self.vdd_voltage, self.temperature) = corner
self.gnd_voltage = 0
def write_stimulus(self, mode, target_time, correct_value): def write_stimulus(self, mode, target_time, correct_value):
"""Creates a stimulus file for SRAM setup/hold time calculation""" """Creates a stimulus file for SRAM setup/hold time calculation"""
@ -33,13 +38,13 @@ class setup_hold():
# creates and opens the stimulus file for writing # creates and opens the stimulus file for writing
temp_stim = OPTS.openram_temp + "stim.sp" temp_stim = OPTS.openram_temp + "stim.sp"
self.sf = open(temp_stim, "w") self.sf = open(temp_stim, "w")
self.stim = stimuli.stimuli(self.sf, self.corner)
self.write_header(correct_value) self.write_header(correct_value)
# instantiate the master-slave d-flip-flop # instantiate the master-slave d-flip-flop
self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n") self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n")
stimuli.inst_model(stim_file=self.sf, self.stim.inst_model(pins=self.pins,
pins=self.pins,
model_name=self.model_name) model_name=self.model_name)
self.write_data(mode=mode, self.write_data(mode=mode,
@ -52,7 +57,7 @@ class setup_hold():
correct_value=correct_value) correct_value=correct_value)
stimuli.write_control(self.sf,4*self.period) self.stim.write_control(4*self.period)
self.sf.close() self.sf.close()
@ -61,13 +66,11 @@ class setup_hold():
self.sf.write("\n* Stimulus for setup/hold: data {0} period {1}n\n".format(correct_value, self.period)) self.sf.write("\n* Stimulus for setup/hold: data {0} period {1}n\n".format(correct_value, self.period))
# include files in stimulus file # include files in stimulus file
self.model_list = tech.spice["fet_models"] + [self.model_location] self.stim.write_include(self.model_location)
stimuli.write_include(stim_file=self.sf,
models=self.model_list)
# add vdd/gnd statements # add vdd/gnd statements
self.sf.write("\n* Global Power Supplies\n") self.sf.write("\n* Global Power Supplies\n")
stimuli.write_supply(self.sf) self.stim.write_supply()
def write_data(self, mode, target_time, correct_value): def write_data(self, mode, target_time, correct_value):
@ -77,7 +80,7 @@ class setup_hold():
""" """
self.sf.write("\n* Generation of the data and clk signals\n") self.sf.write("\n* Generation of the data and clk signals\n")
incorrect_value = stimuli.get_inverse_value(correct_value) incorrect_value = self.stim.get_inverse_value(correct_value)
if mode=="HOLD": if mode=="HOLD":
init_value = incorrect_value init_value = incorrect_value
start_value = correct_value start_value = correct_value
@ -87,8 +90,7 @@ class setup_hold():
start_value = incorrect_value start_value = incorrect_value
end_value = correct_value end_value = correct_value
stimuli.gen_pwl(stim_file=self.sf, self.stim.gen_pwl(sig_name="data",
sig_name="data",
clk_times=[0, self.period, target_time], clk_times=[0, self.period, target_time],
data_values=[init_value, start_value, end_value], data_values=[init_value, start_value, end_value],
period=target_time, period=target_time,
@ -99,8 +101,7 @@ class setup_hold():
""" Create the clock signal for setup/hold analysis. First period initializes the FF """ Create the clock signal for setup/hold analysis. First period initializes the FF
while the second is used for characterization.""" while the second is used for characterization."""
stimuli.gen_pwl(stim_file=self.sf, self.stim.gen_pwl(sig_name="clk",
sig_name="clk",
# initial clk edge is right after the 0 time to initialize a flop # initial clk edge is right after the 0 time to initialize a flop
# without using .IC on an internal node. # without using .IC on an internal node.
# Return input to value after one period. # Return input to value after one period.
@ -135,10 +136,9 @@ class setup_hold():
self.sf.write("\n* Measure statements for pass/fail verification\n") self.sf.write("\n* Measure statements for pass/fail verification\n")
trig_name = "clk" trig_name = "clk"
targ_name = "dout" targ_name = "dout"
trig_val = targ_val = 0.5 * self.vdd trig_val = targ_val = 0.5 * self.vdd_voltage
# Start triggers right before the clock edge at 2*period # Start triggers right before the clock edge at 2*period
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="clk2q_delay",
meas_name="clk2q_delay",
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -151,8 +151,7 @@ class setup_hold():
targ_name = "data" targ_name = "data"
# Start triggers right after initialize value is returned to normal # Start triggers right after initialize value is returned to normal
# at one period # at one period
stimuli.gen_meas_delay(stim_file=self.sf, self.stim.gen_meas_delay(meas_name="setup_hold_time",
meas_name="setup_hold_time",
trig_name=trig_name, trig_name=trig_name,
targ_name=targ_name, targ_name=targ_name,
trig_val=trig_val, trig_val=trig_val,
@ -186,7 +185,7 @@ class setup_hold():
self.write_stimulus(mode=mode, self.write_stimulus(mode=mode,
target_time=feasible_bound, target_time=feasible_bound,
correct_value=correct_value) correct_value=correct_value)
stimuli.run_sim() self.stim.run_sim()
ideal_clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay")) ideal_clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time")) setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time"))
debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time)) debug.info(2,"*** {0} CHECK: {1} Ideal Clk-to-Q: {2} Setup/Hold: {3}".format(mode, correct_value,ideal_clk_to_q,setuphold_time))
@ -219,7 +218,7 @@ class setup_hold():
feasible_bound)) feasible_bound))
stimuli.run_sim() self.stim.run_sim()
clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay")) clk_to_q = ch.convert_to_float(ch.parse_output("timing", "clk2q_delay"))
setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time")) setuphold_time = ch.convert_to_float(ch.parse_output("timing", "setup_hold_time"))
if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float: if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float:
@ -300,7 +299,7 @@ class setup_hold():
} }
return times return times
def analytical_model(self,related_slews, constrained_slews): def analytical_setuphold(self,related_slews, constrained_slews):
""" Just return the fixed setup/hold times from the technology. """ Just return the fixed setup/hold times from the technology.
""" """
LH_setup = [] LH_setup = []

View File

@ -12,121 +12,130 @@ import sys
import numpy as np import numpy as np
from globals import OPTS from globals import OPTS
vdd_voltage = tech.spice["supply_voltage"]
gnd_voltage = tech.spice["gnd_voltage"]
vdd_name = tech.spice["vdd_name"]
gnd_name = tech.spice["gnd_name"]
pmos_name = tech.spice["pmos_name"]
nmos_name = tech.spice["nmos_name"]
tx_width = tech.spice["minwidth_tx"]
tx_length = tech.spice["channel"]
def inst_sram(stim_file, abits, dbits, sram_name): class stimuli():
""" Class for providing stimuli functions """
def __init__(self, stim_file, corner):
self.vdd_name = tech.spice["vdd_name"]
self.gnd_name = tech.spice["gnd_name"]
self.pmos_name = tech.spice["pmos"]
self.nmos_name = tech.spice["nmos"]
self.tx_width = tech.spice["minwidth_tx"]
self.tx_length = tech.spice["channel"]
self.sf = stim_file
(self.process, self.voltage, self.temperature) = corner
self.device_models = tech.spice["fet_models"][self.process]
def inst_sram(self, abits, dbits, sram_name):
""" Function to instatiate an SRAM subckt. """ """ Function to instatiate an SRAM subckt. """
stim_file.write("Xsram ") self.sf.write("Xsram ")
for i in range(dbits): for i in range(dbits):
stim_file.write("D[{0}] ".format(i)) self.sf.write("D[{0}] ".format(i))
for i in range(abits): for i in range(abits):
stim_file.write("A[{0}] ".format(i)) self.sf.write("A[{0}] ".format(i))
for i in tech.spice["control_signals"]: for i in tech.spice["control_signals"]:
stim_file.write("{0} ".format(i)) self.sf.write("{0} ".format(i))
stim_file.write("{0} ".format(tech.spice["clk"])) self.sf.write("{0} ".format(tech.spice["clk"]))
stim_file.write("{0} {1} ".format(vdd_name, gnd_name)) self.sf.write("{0} {1} ".format(self.vdd_name, self.gnd_name))
stim_file.write("{0}\n".format(sram_name)) self.sf.write("{0}\n".format(sram_name))
def inst_model(stim_file, pins, model_name): def inst_model(self, pins, model_name):
""" Function to instantiate a generic model with a set of pins """ """ Function to instantiate a generic model with a set of pins """
stim_file.write("X{0} ".format(model_name)) self.sf.write("X{0} ".format(model_name))
for pin in pins: for pin in pins:
stim_file.write("{0} ".format(pin)) self.sf.write("{0} ".format(pin))
stim_file.write("{0}\n".format(model_name)) self.sf.write("{0}\n".format(model_name))
def create_inverter(stim_file, size=1, beta=2.5): def create_inverter(self, size=1, beta=2.5):
""" Generates inverter for the top level signals (only for sim purposes) """ """ Generates inverter for the top level signals (only for sim purposes) """
stim_file.write(".SUBCKT test_inv in out {0} {1}\n".format(vdd_name, gnd_name)) self.sf.write(".SUBCKT test_inv in out {0} {1}\n".format(self.vdd_name, self.gnd_name))
stim_file.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name, self.sf.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
pmos_name, self.pmos_name,
beta * size * tx_width, beta * size * self.tx_width,
tx_length)) self.tx_length))
stim_file.write("mninv out in {0} {0} {1} w={2}u l={3}u\n".format(gnd_name, self.sf.write("mninv out in {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
nmos_name, self.nmos_name,
size * tx_width, size * self.tx_width,
tx_length)) self.tx_length))
stim_file.write(".ENDS test_inv\n") self.sf.write(".ENDS test_inv\n")
def create_buffer(stim_file, buffer_name, size=[1,3], beta=2.5): def create_buffer(self, buffer_name, size=[1,3], beta=2.5):
""" """
Generates buffer for top level signals (only for sim Generates buffer for top level signals (only for sim
purposes). Size is pair for PMOS, NMOS width multiple. purposes). Size is pair for PMOS, NMOS width multiple.
""" """
stim_file.write(".SUBCKT test_{2} in out {0} {1}\n".format(vdd_name, self.sf.write(".SUBCKT test_{2} in out {0} {1}\n".format(self.vdd_name,
gnd_name, self.gnd_name,
buffer_name)) buffer_name))
stim_file.write("mpinv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name, self.sf.write("mpinv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
pmos_name, self.pmos_name,
beta * size[0] * tx_width, beta * size[0] * self.tx_width,
tx_length)) self.tx_length))
stim_file.write("mninv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(gnd_name, self.sf.write("mninv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
nmos_name, self.nmos_name,
size[0] * tx_width, size[0] * self.tx_width,
tx_length)) self.tx_length))
stim_file.write("mpinv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(vdd_name, self.sf.write("mpinv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
pmos_name, self.pmos_name,
beta * size[1] * tx_width, beta * size[1] * self.tx_width,
tx_length)) self.tx_length))
stim_file.write("mninv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(gnd_name, self.sf.write("mninv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
nmos_name, self.nmos_name,
size[1] * tx_width, size[1] * self.tx_width,
tx_length)) self.tx_length))
stim_file.write(".ENDS test_{0}\n\n".format(buffer_name)) self.sf.write(".ENDS test_{0}\n\n".format(buffer_name))
def inst_buffer(stim_file, buffer_name, signal_list): def inst_buffer(self, buffer_name, signal_list):
""" Adds buffers to each top level signal that is in signal_list (only for sim purposes) """ """ Adds buffers to each top level signal that is in signal_list (only for sim purposes) """
for signal in signal_list: for signal in signal_list:
stim_file.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal, self.sf.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal,
"test"+vdd_name, "test"+self.vdd_name,
"test"+gnd_name, "test"+self.gnd_name,
buffer_name)) buffer_name))
def inst_inverter(stim_file, signal_list): def inst_inverter(self, signal_list):
""" Adds inv for each signal that needs its inverted version (only for sim purposes) """ """ Adds inv for each signal that needs its inverted version (only for sim purposes) """
for signal in signal_list: for signal in signal_list:
stim_file.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal, self.sf.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal,
"test"+vdd_name, "test"+self.vdd_name,
"test"+gnd_name)) "test"+self.gnd_name))
def inst_accesstx(stim_file, dbits): def inst_accesstx(self, dbits):
""" Adds transmission gate for inputs to data-bus (only for sim purposes) """ """ Adds transmission gate for inputs to data-bus (only for sim purposes) """
stim_file.write("* Tx Pin-list: Drain Gate Source Body\n") self.sf.write("* Tx Pin-list: Drain Gate Source Body\n")
for i in range(dbits): for i in range(dbits):
pmos_access_string="mp{0} DATA[{0}] acc_en D[{0}] {1} {2} w={3}u l={4}u\n" pmos_access_string="mp{0} DATA[{0}] acc_en D[{0}] {1} {2} w={3}u l={4}u\n"
stim_file.write(pmos_access_string.format(i, self.sf.write(pmos_access_string.format(i,
"test"+vdd_name, "test"+self.vdd_name,
pmos_name, self.pmos_name,
2 * tx_width, 2 * self.tx_width,
tx_length)) self.tx_length))
nmos_access_string="mn{0} DATA[{0}] acc_en_inv D[{0}] {1} {2} w={3}u l={4}u\n" nmos_access_string="mn{0} DATA[{0}] acc_en_inv D[{0}] {1} {2} w={3}u l={4}u\n"
stim_file.write(nmos_access_string.format(i, self.sf.write(nmos_access_string.format(i,
"test"+gnd_name, "test"+self.gnd_name,
nmos_name, self.nmos_name,
2 * tx_width, 2 * self.tx_width,
tx_length)) self.tx_length))
def gen_pulse(stim_file, sig_name, v1=gnd_voltage, v2=vdd_voltage, offset=0, period=1, t_rise=0, t_fall=0): def gen_pulse(self, sig_name, v1, v2, offset, period, t_rise, t_fall):
""" """
Generates a periodic signal with 50% duty cycle and slew rates. Period is measured Generates a periodic signal with 50% duty cycle and slew rates. Period is measured
from 50% to 50%. from 50% to 50%.
""" """
stim_file.write("* PULSE: period={0}\n".format(period)) self.sf.write("* PULSE: period={0}\n".format(period))
pulse_string="V{0} {0} 0 PULSE ({1} {2} {3}n {4}n {5}n {6}n {7}n)\n" pulse_string="V{0} {0} 0 PULSE ({1} {2} {3}n {4}n {5}n {6}n {7}n)\n"
stim_file.write(pulse_string.format(sig_name, self.sf.write(pulse_string.format(sig_name,
v1, v1,
v2, v2,
offset, offset,
@ -136,7 +145,7 @@ def gen_pulse(stim_file, sig_name, v1=gnd_voltage, v2=vdd_voltage, offset=0, per
period)) period))
def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup): def gen_pwl(self, sig_name, clk_times, data_values, period, slew, setup):
""" """
Generate a PWL stimulus given a signal name and data values at each period. Generate a PWL stimulus given a signal name and data values at each period.
Automatically creates slews and ensures each data occurs a setup before the clock Automatically creates slews and ensures each data occurs a setup before the clock
@ -148,30 +157,30 @@ def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
# shift signal times earlier for setup time # shift signal times earlier for setup time
times = np.array(clk_times) - setup*period times = np.array(clk_times) - setup*period
values = np.array(data_values) * vdd_voltage values = np.array(data_values) * self.voltage
half_slew = 0.5 * slew half_slew = 0.5 * slew
stim_file.write("* (time, data): {}\n".format(zip(clk_times, data_values))) self.sf.write("* (time, data): {}\n".format(zip(clk_times, data_values)))
stim_file.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0])) self.sf.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
for i in range(1,len(times)): for i in range(1,len(times)):
stim_file.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew, self.sf.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
values[i-1], values[i-1],
times[i]+half_slew, times[i]+half_slew,
values[i])) values[i]))
stim_file.write(")\n") self.sf.write(")\n")
def gen_constant(stim_file, sig_name, v_val): def gen_constant(self, sig_name, v_val):
""" Generates a constant signal with reference voltage and the voltage value """ """ Generates a constant signal with reference voltage and the voltage value """
stim_file.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val)) self.sf.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val))
def get_inverse_voltage(value): def get_inverse_voltage(self, value):
if value > 0.5*vdd_voltage: if value > 0.5*self.voltage:
return gnd_voltage return 0
elif value <= 0.5*vdd_voltage: elif value <= 0.5*self.voltage:
return vdd_voltage return self.voltage
else: else:
debug.error("Invalid value to get an inverse of: {0}".format(value)) debug.error("Invalid value to get an inverse of: {0}".format(value))
def get_inverse_value(value): def get_inverse_value(self, value):
if value > 0.5: if value > 0.5:
return 0 return 0
elif value <= 0.5: elif value <= 0.5:
@ -180,10 +189,10 @@ def get_inverse_value(value):
debug.error("Invalid value to get an inverse of: {0}".format(value)) debug.error("Invalid value to get an inverse of: {0}".format(value))
def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td): def gen_meas_delay(self, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, trig_td, targ_td):
""" Creates the .meas statement for the measurement of delay """ """ Creates the .meas statement for the measurement of delay """
measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n" measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={4}n TARG v({5}) VAL={6} {7}=1 TD={8}n\n\n"
stim_file.write(measure_string.format(meas_name, self.sf.write(measure_string.format(meas_name,
trig_name, trig_name,
trig_val, trig_val,
trig_dir, trig_dir,
@ -193,65 +202,67 @@ def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_va
targ_dir, targ_dir,
targ_td)) targ_td))
def gen_meas_power(stim_file, meas_name, t_initial, t_final): def gen_meas_power(self, meas_name, t_initial, t_final):
""" Creates the .meas statement for the measurement of avg power """ """ Creates the .meas statement for the measurement of avg power """
# power mea cmd is different in different spice: # power mea cmd is different in different spice:
if OPTS.spice_name == "hspice": if OPTS.spice_name == "hspice":
power_exp = "power" power_exp = "power"
else: else:
power_exp = "par('(-1*v(" + str(vdd_name) + ")*I(v" + str(vdd_name) + "))')" power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')"
stim_file.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name, self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name,
power_exp, power_exp,
t_initial, t_initial,
t_final)) t_final))
def write_control(stim_file, end_time): def write_control(self, end_time):
""" Write the control cards to run and end the simulation """ """ Write the control cards to run and end the simulation """
# UIC is needed for ngspice to converge # UIC is needed for ngspice to converge
stim_file.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":
# ngspice sometimes has convergence problems if not using gear method # ngspice sometimes has convergence problems if not using gear method
# 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.
stim_file.write(".OPTIONS POST=1 RUNLVL=4 PROBE method=gear\n") self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE method=gear TEMP={}\n".format(self.temperature))
else: else:
stim_file.write(".OPTIONS POST=1 RUNLVL=4 PROBE\n") self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE TEMP={}\n".format(self.temperature))
# create plots for all signals # create plots for all signals
stim_file.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")
if OPTS.debug_level>0: if OPTS.debug_level>0:
if OPTS.spice_name in ["hspice","xa"]: if OPTS.spice_name in ["hspice","xa"]:
stim_file.write(".probe V(*)\n") self.sf.write(".probe V(*)\n")
else: else:
stim_file.write(".plot V(*)\n") self.sf.write(".plot V(*)\n")
else: else:
stim_file.write("*.probe V(*)\n") self.sf.write("*.probe V(*)\n")
stim_file.write("*.plot V(*)\n") self.sf.write("*.plot V(*)\n")
# end the stimulus file # end the stimulus file
stim_file.write(".end\n\n") self.sf.write(".end\n\n")
def write_include(stim_file, models): def write_include(self, circuit):
"""Writes include statements, inputs are lists of model files""" """Writes include statements, inputs are lists of model files"""
for item in list(models): includes = self.device_models + [circuit]
self.sf.write("* {} process corner\n".format(self.process))
for item in list(includes):
if os.path.isfile(item): if os.path.isfile(item):
stim_file.write(".include \"{0}\"\n".format(item)) self.sf.write(".include \"{0}\"\n".format(item))
else: else:
debug.error("Could not find spice model: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item)) debug.error("Could not find spice model: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item))
def write_supply(stim_file): def write_supply(self):
""" Writes supply voltage statements """ """ Writes supply voltage statements """
stim_file.write("V{0} {0} 0.0 {1}\n".format(vdd_name, vdd_voltage)) self.sf.write("V{0} {0} 0.0 {1}\n".format(self.vdd_name, self.voltage))
stim_file.write("V{0} {0} 0.0 {1}\n".format(gnd_name, gnd_voltage)) self.sf.write("V{0} {0} 0.0 {1}\n".format(self.gnd_name, 0))
# This is for the test power supply # This is for the test power supply
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+vdd_name, vdd_voltage)) self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.vdd_name, self.voltage))
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+gnd_name, gnd_voltage)) self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.gnd_name, 0))
def run_sim(): def run_sim(self):
""" Run hspice in batch mode and output rawfile to parse. """ """ Run hspice in batch mode and output rawfile to parse. """
temp_stim = "{0}stim.sp".format(OPTS.openram_temp) temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
import datetime import datetime
@ -275,6 +286,7 @@ def run_sim():
OPTS.openram_temp) OPTS.openram_temp)
valid_retcode=0 valid_retcode=0
else: else:
# ngspice 27+ supports threading with "set num_threads=4" in the stimulus file or a .spiceinit
cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe, cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe,
temp_stim, temp_stim,
OPTS.openram_temp) OPTS.openram_temp)

View File

@ -1,8 +1,11 @@
word_size = 2 word_size = 2
num_words = 128 num_words = 16
num_banks = 1 num_banks = 1
tech_name = "freepdk45" tech_name = "freepdk45"
process_corners = ["TT"]
supply_voltages = [1.0]
temperatures = [25]
output_path = "temp" output_path = "temp"
output_name = "sram_2_16_1_freepdk45" output_name = "sram_2_16_1_freepdk45"

View File

@ -3,6 +3,10 @@ num_words = 16
num_banks = 1 num_banks = 1
tech_name = "scn3me_subm" tech_name = "scn3me_subm"
process_corners = ["TT"]
supply_voltages = [ 5.0 ]
temperatures = [ 25 ]
output_path = "temp" output_path = "temp"
output_name = "sram_2_16_1_scn3me_subm" output_name = "sram_2_16_1_scn3me_subm"

View File

@ -772,29 +772,36 @@ class VlsiLayout:
return boundaries return boundaries
def getPinInStructure(self,coordinates,layer,Structure): def getPinInStructure(self,coordinates,layer,structure):
""" """
Go through all the shapes in a structure and return the list of shapes Go through all the shapes in a structure and return the list of shapes
that the label coordinates are inside. that the label coordinates are inside.
""" """
StructureName=Structure[0]
StructureOrigin=[Structure[1][0],Structure[1][1]] # check if this is a rectangle
StructureuVector=[Structure[2][0],Structure[2][1],Structure[2][2]] structureName=structure[0]
StructurevVector=[Structure[3][0],Structure[3][1],Structure[3][2]] structureOrigin=[structure[1][0],structure[1][1]]
structureuVector=[structure[2][0],structure[2][1],structure[2][2]]
structurevVector=[structure[3][0],structure[3][1],structure[3][2]]
boundaries = [] boundaries = []
for boundary in self.structures[str(StructureName)].boundaries: for boundary in self.structures[str(structureName)].boundaries:
# Pin enclosures only work on rectangular pins so ignore any non rectangle
# This may report not finding pins, but the user should fix this by adding a rectangle.
if len(boundary.coordinates)!=5:
continue
if layer==boundary.drawingLayer: if layer==boundary.drawingLayer:
left_bottom=boundary.coordinates[0] left_bottom=boundary.coordinates[0]
right_top=boundary.coordinates[2] right_top=boundary.coordinates[2]
MetalBoundary=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]] # Rectangle is [leftx, bottomy, rightx, topy].
MetalBoundary=self.transformRectangle(MetalBoundary,StructureuVector,StructurevVector) boundaryRect=[left_bottom[0],left_bottom[1],right_top[0],right_top[1]]
MetalBoundary=[MetalBoundary[0]+StructureOrigin[0],MetalBoundary[1]+StructureOrigin[1], boundaryRect=self.transformRectangle(boundaryRect,structureuVector,structurevVector)
MetalBoundary[2]+StructureOrigin[0],MetalBoundary[3]+StructureOrigin[1]] boundaryRect=[boundaryRect[0]+structureOrigin[0],boundaryRect[1]+structureOrigin[1],
boundaryRect[2]+structureOrigin[0],boundaryRect[3]+structureOrigin[1]]
if self.labelInRectangle(coordinates,MetalBoundary): if self.labelInRectangle(coordinates,boundaryRect):
boundaries.append(MetalBoundary) boundaries.append(boundaryRect)
return boundaries return boundaries
@ -829,7 +836,7 @@ class VlsiLayout:
def labelInRectangle(self,coordinate,rectangle): def labelInRectangle(self,coordinate,rectangle):
""" """
Checks if a coordinate is within a given rectangle. Checks if a coordinate is within a given rectangle. Rectangle is [leftx, bottomy, rightx, topy].
""" """
coordinate_In_Rectangle_x_range=(coordinate[0]>=int(rectangle[0]))&(coordinate[0]<=int(rectangle[2])) coordinate_In_Rectangle_x_range=(coordinate[0]>=int(rectangle[0]))&(coordinate[0]<=int(rectangle[2]))
coordinate_In_Rectangle_y_range=(coordinate[1]>=int(rectangle[1]))&(coordinate[1]<=int(rectangle[3])) coordinate_In_Rectangle_y_range=(coordinate[1]>=int(rectangle[1]))&(coordinate[1]<=int(rectangle[3]))

86
compiler/gen_stimulus.py Executable file
View File

@ -0,0 +1,86 @@
#!/usr/bin/env python2.7
"""
This script will generate a stimulus file for a given period, load, and slew input
for the given dimension SRAM. It is useful for debugging after an SRAM has been
created without re-running the entire process. Right now, it assumes the nominal
corner, but should probably be extended.
"""
import sys,os
import datetime
import re
import importlib
from globals import *
(OPTS, args) = parse_args()
# Override the usage
USAGE = "Usage: {} [options] <config file> <period in ns> <load in fF> <slew in ns>\nUse -h for help.\n".format(__file__)
# Check that we are left with a single configuration file as argument.
if len(args) != 4:
print(USAGE)
sys.exit(2)
# We need to get the:
# config file
config_file = args[0]
# period
period = float(args[1])
# load
load = float(args[2])
# slew
slew = float(args[3])
# These depend on arguments, so don't load them until now.
import debug
init_openram(config_file=config_file, is_unit_test=False)
OPTS.check_lvsdrc = False
# Put the temp output in the output path since it is what we want to generate!
old_openram_temp = OPTS.openram_temp
OPTS.openram_temp = OPTS.output_path
import sram
class fake_sram(sram.sram):
""" This is an SRAM that doesn't actually create itself, just computes
the sizes. """
def __init__(self, word_size, num_words, num_banks, name):
self.name = name
self.word_size = word_size
self.num_words = num_words
self.num_banks = num_banks
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
self.bitcell = self.mod_bitcell()
# to get the row, col, etc.
self.compute_sizes()
sram = fake_sram(OPTS.word_size, OPTS.num_words, OPTS.num_banks, OPTS.output_name)
sp_file = OPTS.output_path+OPTS.output_name + ".sp"
from characterizer import delay
import tech
# Set up the delay and set to the nominal corner
d = delay.delay(sram, sp_file, ("TT", tech.spice["nom_supply_voltage"], tech.spice["nom_temperature"]))
# Set the period
d.period = period
# Set the load of outputs and slew of inputs
d.set_load_slew(load,slew)
# Set the probe address/bit
probe_address = "1" * sram.addr_size
probe_data = sram.word_size - 1
d.set_probe(probe_address, probe_data)
d.write_delay_stimulus()
# Output info about this run
report_status()
print("Output files are:\n{0}stim.sp\n{0}sram.sp\n{0}reduced.sp".format(OPTS.output_path))
OPTS.openram_temp = old_openram_temp
# Delete temp files, remove the dir, etc.
end_openram()

View File

@ -16,12 +16,6 @@ USAGE = "Usage: openram.py [options] <config file>\nUse -h for help.\n"
# Anonymous object that will be the options # Anonymous object that will be the options
OPTS = options.options() OPTS = options.options()
# check that we are not using version 3 and at least 2.7
major_python_version = sys.version_info.major
minor_python_version = sys.version_info.minor
if not (major_python_version == 2 and minor_python_version >= 7):
debug.error("Python 2.7 is required.",-1)
def parse_args(): def parse_args():
""" Parse the optional arguments for OpenRAM """ """ Parse the optional arguments for OpenRAM """
@ -36,8 +30,6 @@ def parse_args():
help="Output file(s) location"), help="Output file(s) location"),
optparse.make_option("-n", "--nocheck", action="store_false", optparse.make_option("-n", "--nocheck", action="store_false",
help="Disable inline LVS/DRC checks", dest="check_lvsdrc"), help="Disable inline LVS/DRC checks", dest="check_lvsdrc"),
optparse.make_option("-q", "--quiet", action="store_false", dest="print_banner",
help="Don\'t display banner"),
optparse.make_option("-v", "--verbose", action="count", dest="debug_level", optparse.make_option("-v", "--verbose", action="count", dest="debug_level",
help="Increase the verbosity level"), help="Increase the verbosity level"),
optparse.make_option("-t", "--tech", dest="tech_name", optparse.make_option("-t", "--tech", dest="tech_name",
@ -72,7 +64,7 @@ def parse_args():
def print_banner(): def print_banner():
""" Conditionally print the banner to stdout """ """ Conditionally print the banner to stdout """
global OPTS global OPTS
if not OPTS.print_banner: if OPTS.is_unit_test:
return return
print("|==============================================================================|") print("|==============================================================================|")
@ -85,22 +77,41 @@ def print_banner():
print("|=========" + "VLSI Computer Architecture Research Group".center(60) + "=========|") print("|=========" + "VLSI Computer Architecture Research Group".center(60) + "=========|")
print("|=========" + "Oklahoma State University ECE Department".center(60) + "=========|") print("|=========" + "Oklahoma State University ECE Department".center(60) + "=========|")
print("|=========" + " ".center(60) + "=========|") print("|=========" + " ".center(60) + "=========|")
print("|=========" + OPTS.openram_temp.center(60) + "=========|") user_info = "Usage help: openram-user-group@ucsc.edu"
print("|=========" + user_info.center(60) + "=========|")
dev_info = "Development help: openram-dev-group@ucsc.edu"
print("|=========" + dev_info.center(60) + "=========|")
temp_info = "Temp dir: {}".format(OPTS.openram_temp)
print("|=========" + temp_info.center(60) + "=========|")
print("|==============================================================================|") print("|==============================================================================|")
def init_openram(config_file): def check_versions():
""" Run some checks of required software versions. """
# check that we are not using version 3 and at least 2.7
major_python_version = sys.version_info.major
minor_python_version = sys.version_info.minor
if not (major_python_version == 2 and minor_python_version >= 7):
debug.error("Python 2.7 is required.",-1)
# FIXME: Check versions of other tools here??
# or, this could be done in each module (e.g. verify, characterizer, etc.)
def init_openram(config_file, is_unit_test=True):
"""Initialize the technology, paths, simulators, etc.""" """Initialize the technology, paths, simulators, etc."""
check_versions()
debug.info(1,"Initializing OpenRAM...") debug.info(1,"Initializing OpenRAM...")
setup_paths() setup_paths()
read_config(config_file) read_config(config_file, is_unit_test)
import_tech() import_tech()
def get_tool(tool_type, preferences): def get_tool(tool_type, preferences):
""" """
Find which tool we have from a list of preferences and return the Find which tool we have from a list of preferences and return the
@ -120,7 +131,7 @@ def get_tool(tool_type, preferences):
def read_config(config_file): def read_config(config_file, is_unit_test=True):
""" """
Read the configuration file that defines a few parameters. The Read the configuration file that defines a few parameters. The
config file is just a Python file that defines some config config file is just a Python file that defines some config
@ -156,8 +167,20 @@ def read_config(config_file):
if not OPTS.output_path.endswith('/'): if not OPTS.output_path.endswith('/'):
OPTS.output_path += "/" OPTS.output_path += "/"
if not OPTS.output_path.startswith('/'):
OPTS.output_path = os.getcwd() + "/" + OPTS.output_path
debug.info(1, "Output saved in " + OPTS.output_path) debug.info(1, "Output saved in " + OPTS.output_path)
OPTS.is_unit_test=is_unit_test
# If config didn't set output name, make a reasonable default.
if (OPTS.output_name == ""):
OPTS.output_name = "sram_{0}rw_{1}b_{2}w_{3}bank_{4}".format(OPTS.rw_ports,
OPTS.word_size,
OPTS.num_words,
OPTS.num_banks,
OPTS.tech_name)
# Don't delete the output dir, it may have other files! # Don't delete the output dir, it may have other files!
# make the directory if it doesn't exist # make the directory if it doesn't exist
try: try:
@ -176,6 +199,7 @@ def end_openram():
def cleanup_paths(): def cleanup_paths():
""" """
We should clean up the temp directory after execution. We should clean up the temp directory after execution.
@ -198,15 +222,13 @@ def setup_paths():
debug.error("$OPENRAM_HOME is not properly defined.",1) debug.error("$OPENRAM_HOME is not properly defined.",1)
debug.check(os.path.isdir(OPENRAM_HOME),"$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME)) debug.check(os.path.isdir(OPENRAM_HOME),"$OPENRAM_HOME does not exist: {0}".format(OPENRAM_HOME))
debug.check(os.path.isdir(OPENRAM_HOME+"/gdsMill"), # Add all of the subdirs to the python path
"$OPENRAM_HOME/gdsMill does not exist: {0}".format(OPENRAM_HOME+"/gdsMill")) # These subdirs are modules and don't need to be added: characterizer, verify
sys.path.append("{0}/gdsMill".format(OPENRAM_HOME)) for subdir in ["gdsMill", "tests", "router", "modules", "base", "pgates"]:
debug.check(os.path.isdir(OPENRAM_HOME+"/tests"), full_path = "{0}/{1}".format(OPENRAM_HOME,subdir)
"$OPENRAM_HOME/tests does not exist: {0}".format(OPENRAM_HOME+"/tests")) debug.check(os.path.isdir(full_path),
sys.path.append("{0}/tests".format(OPENRAM_HOME)) "$OPENRAM_HOME/{0} does not exist: {1}".format(subdir,full_path))
debug.check(os.path.isdir(OPENRAM_HOME+"/router"), sys.path.append("{0}".format(full_path))
"$OPENRAM_HOME/router does not exist: {0}".format(OPENRAM_HOME+"/router"))
sys.path.append("{0}/router".format(OPENRAM_HOME))
if not OPTS.openram_temp.endswith('/'): if not OPTS.openram_temp.endswith('/'):
OPTS.openram_temp += "/" OPTS.openram_temp += "/"
@ -245,7 +267,6 @@ def import_tech():
# Set the tech to the config file we read in instead of the command line value. # Set the tech to the config file we read in instead of the command line value.
OPTS.tech_name = OPTS.tech_name OPTS.tech_name = OPTS.tech_name
# environment variable should point to the technology dir # environment variable should point to the technology dir
try: try:
OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH")) OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
@ -270,3 +291,42 @@ def import_tech():
debug.error("Nonexistent technology_setup_file: {0}.py".format(filename)) debug.error("Nonexistent technology_setup_file: {0}.py".format(filename))
sys.exit(1) sys.exit(1)
import tech
# Set some default options now based on the technology...
if (OPTS.process_corners == ""):
OPTS.process_corners = tech.spice["fet_models"].keys()
if (OPTS.supply_voltages == ""):
OPTS.supply_voltages = tech.spice["supply_voltages"]
if (OPTS.temperatures == ""):
OPTS.temperatures = tech.spice["temperatures"]
def print_time(name, now_time, last_time=None):
""" Print a statement about the time delta. """
if last_time:
time = round((now_time-last_time).total_seconds(),1)
else:
time = now_time
print("** {0}: {1} seconds".format(name,time))
def report_status():
""" Check for valid arguments and report the info about the SRAM being generated """
# Check if all arguments are integers for bits, size, banks
if type(OPTS.word_size)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.word_size))
if type(OPTS.num_words)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.sram_size))
if type(OPTS.num_banks)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.num_banks))
if not OPTS.tech_name:
debug.error("Tech name must be specified in config file.")
print("Technology: {0}".format(OPTS.tech_name))
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size,
OPTS.num_words,
OPTS.num_banks))
if not OPTS.check_lvsdrc:
print("DRC/LVS/PEX checking is disabled.")

View File

@ -69,9 +69,10 @@ class control_logic(design.design):
c = reload(__import__(OPTS.replica_bitline)) c = reload(__import__(OPTS.replica_bitline))
replica_bitline = getattr(c, OPTS.replica_bitline) replica_bitline = getattr(c, OPTS.replica_bitline)
# FIXME: These should be tuned according to the size! # FIXME: These should be tuned according to the size!
FO4_stages = 4 delay_stages = 4 # This should be even so that the delay line is inverting!
bitcell_loads = int(math.ceil(self.num_rows / 10.0)) delay_fanout = 3
self.replica_bitline = replica_bitline(FO4_stages, bitcell_loads) bitcell_loads = int(math.ceil(self.num_rows / 5.0))
self.replica_bitline = replica_bitline(delay_stages, delay_fanout, bitcell_loads)
self.add_mod(self.replica_bitline) self.add_mod(self.replica_bitline)

View File

@ -8,7 +8,8 @@ from globals import OPTS
class delay_chain(design.design): class delay_chain(design.design):
""" """
Generate a logic effort based delay chain. Generate a delay chain with the given number of stages and fanout.
This automatically adds an extra inverter with no load on the input.
Input is a list contains the electrical effort of each stage. Input is a list contains the electrical effort of each stage.
""" """
@ -19,6 +20,9 @@ class delay_chain(design.design):
# and there should be functions to get # and there should be functions to get
# area efficient inverter stage list # area efficient inverter stage list
for f in fanout_list:
debug.check(f>0,"Must have non-zero fanouts for each stage.")
# number of inverters including any fanout loads. # number of inverters including any fanout loads.
self.fanout_list = fanout_list self.fanout_list = fanout_list
self.num_inverters = 1 + sum(fanout_list) self.num_inverters = 1 + sum(fanout_list)

29
compiler/modules/dff.py Normal file
View File

@ -0,0 +1,29 @@
import globals
import design
from math import log
import design
from tech import GDS,layer
import utils
class dff(design.design):
"""
Memory address flip-flop
"""
pin_names = ["d", "q", "clk", "vdd", "gnd"]
(width,height) = utils.get_libcell_size("dff", GDS["unit"], layer["boundary"])
pin_map = utils.get_libcell_pins(pin_names, "dff", GDS["unit"], layer["boundary"])
def __init__(self, name="dff"):
design.design.__init__(self, name)
self.width = dff.width
self.height = dff.height
self.pin_map = dff.pin_map
def analytical_delay(self, slew, load = 0.0):
# dont know how to calculate this now, use constant in tech file
from tech import spice
result = self.return_delay(spice["dff_delay"], spice["dff_slew"])
return result

View File

@ -0,0 +1,141 @@
import debug
import design
from tech import drc
from math import log
from vector import vector
from globals import OPTS
class dff_array(design.design):
"""
This is a simple row (or multiple rows) of flops.
Unlike the data flops, these are never spaced out.
"""
def __init__(self, rows, columns, name=""):
self.rows = rows
self.columns = columns
if name=="":
name = "dff_array_{0}x{1}".format(rows, columns)
design.design.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
c = reload(__import__(OPTS.dff))
self.mod_dff = getattr(c, OPTS.dff)
self.ms = self.mod_dff("dff")
self.add_mod(self.ms)
self.width = self.columns * self.ms.width
self.height = self.rows * self.ms.height
self.create_layout()
def create_layout(self):
self.add_pins()
self.create_dff_array()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
for row in range(self.rows):
for col in range(self.columns):
self.add_pin("din[{0}][{1}]".format(row,col))
for row in range(self.rows):
for col in range(self.columns):
self.add_pin("dout[{0}][{1}]".format(row,col))
#self.add_pin("dout_bar[{0}]".format(i))
self.add_pin("clk")
self.add_pin("vdd")
self.add_pin("gnd")
def create_dff_array(self):
self.dff_insts={}
for y in range(self.rows):
for x in range(self.columns):
name = "Xdff_r{0}_c{1}".format(y,x)
if (y % 2 == 0):
base = vector(x*self.ms.width,y*self.ms.height)
mirror = "R0"
else:
base = vector(x*self.ms.width,(y+1)*self.ms.height)
mirror = "MX"
self.dff_insts[x,y]=self.add_inst(name=name,
mod=self.ms,
offset=base,
mirror=mirror)
self.connect_inst(["din[{0}][{1}]".format(x,y),
"dout[{0}][{1}]".format(x,y),
"clk",
"vdd",
"gnd"])
def add_layout_pins(self):
for y in range(self.rows):
# Continous vdd rail along with label.
vdd_pin=self.dff_insts[0,y].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
offset=vdd_pin.ll(),
width=self.width,
height=self.m1_width)
# Continous gnd rail along with label.
gnd_pin=self.dff_insts[0,y].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
offset=gnd_pin.ll(),
width=self.width,
height=self.m1_width)
for y in range(self.rows):
for x in range(self.columns):
din_pin = self.dff_insts[x,y].get_pin("d")
debug.check(din_pin.layer=="metal2","DFF d pin not on metal2")
self.add_layout_pin(text="din[{0}][{1}]".format(x,y),
layer=din_pin.layer,
offset=din_pin.ll(),
width=din_pin.width(),
height=din_pin.height())
dout_pin = self.dff_insts[x,y].get_pin("q")
debug.check(dout_pin.layer=="metal2","DFF q pin not on metal2")
self.add_layout_pin(text="dout[{0}][{1}]".format(x,y),
layer=dout_pin.layer,
offset=dout_pin.ll(),
width=dout_pin.width(),
height=dout_pin.height())
# Create vertical spines to a single horizontal rail
clk_pin = self.dff_insts[0,0].get_pin("clk")
debug.check(clk_pin.layer=="metal2","DFF clk pin not on metal2")
if self.columns==1:
self.add_layout_pin(text="clk",
layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
else:
self.add_layout_pin(text="clk",
layer="metal3",
offset=clk_pin.ll().scale(0,1),
width=self.width,
height=self.m3_width)
for x in range(self.columns):
clk_pin = self.dff_insts[x,0].get_pin("clk")
# Make a vertical strip for each column
self.add_layout_pin(text="clk",
layer="metal2",
offset=clk_pin.ll().scale(1,0),
width=self.m2_width,
height=self.height)
# Drop a via to the M3 pin
self.add_via_center(layers=("metal2","via2","metal3"),
offset=clk_pin.center())
def analytical_delay(self, slew, load=0.0):
return self.ms.analytical_delay(slew=slew, load=load)

View File

@ -29,13 +29,13 @@ class precharge(pgate.pgate):
self.DRC_LVS() self.DRC_LVS()
def add_pins(self): def add_pins(self):
self.add_pin_list(["bl", "br", "clk", "vdd"]) self.add_pin_list(["bl", "br", "en", "vdd"])
def create_layout(self): def create_layout(self):
self.create_ptx() self.create_ptx()
self.add_ptx() self.add_ptx()
self.connect_poly() self.connect_poly()
self.add_pclk() self.add_en()
self.add_nwell_and_contact() self.add_nwell_and_contact()
self.add_vdd_rail() self.add_vdd_rail()
self.add_bitlines() self.add_bitlines()
@ -74,7 +74,7 @@ class precharge(pgate.pgate):
self.lower_pmos_inst=self.add_inst(name="lower_pmos", self.lower_pmos_inst=self.add_inst(name="lower_pmos",
mod=self.pmos, mod=self.pmos,
offset=self.lower_pmos_position) offset=self.lower_pmos_position)
self.connect_inst(["bl", "clk", "BR", "vdd"]) self.connect_inst(["bl", "en", "BR", "vdd"])
# adds the upper pmos(s) to layout # adds the upper pmos(s) to layout
ydiff = self.pmos.height + 2*self.m1_space + contact.poly.width ydiff = self.pmos.height + 2*self.m1_space + contact.poly.width
@ -82,13 +82,13 @@ class precharge(pgate.pgate):
self.upper_pmos1_inst=self.add_inst(name="upper_pmos1", self.upper_pmos1_inst=self.add_inst(name="upper_pmos1",
mod=self.pmos, mod=self.pmos,
offset=self.upper_pmos1_pos) offset=self.upper_pmos1_pos)
self.connect_inst(["bl", "clk", "vdd", "vdd"]) self.connect_inst(["bl", "en", "vdd", "vdd"])
upper_pmos2_pos = self.upper_pmos1_pos + self.overlap_offset upper_pmos2_pos = self.upper_pmos1_pos + self.overlap_offset
self.upper_pmos2_inst=self.add_inst(name="upper_pmos2", self.upper_pmos2_inst=self.add_inst(name="upper_pmos2",
mod=self.pmos, mod=self.pmos,
offset=upper_pmos2_pos) offset=upper_pmos2_pos)
self.connect_inst(["br", "clk", "vdd", "vdd"]) self.connect_inst(["br", "en", "vdd", "vdd"])
def connect_poly(self): def connect_poly(self):
"""Connects the upper and lower pmos together""" """Connects the upper and lower pmos together"""
@ -109,16 +109,16 @@ class precharge(pgate.pgate):
width=xlength, width=xlength,
height=self.poly_width) height=self.poly_width)
def add_pclk(self): def add_en(self):
"""Adds the pclk input rail, pclk contact/vias, and connects to the pmos""" """Adds the en input rail, en contact/vias, and connects to the pmos"""
# adds the pclk contact to connect the gates to the pclk rail on metal1 # adds the en contact to connect the gates to the en rail on metal1
offset = self.lower_pmos_inst.get_pin("G").ul() + vector(0,0.5*self.poly_space) offset = self.lower_pmos_inst.get_pin("G").ul() + vector(0,0.5*self.poly_space)
self.add_contact_center(layers=("poly", "contact", "metal1"), self.add_contact_center(layers=("poly", "contact", "metal1"),
offset=offset, offset=offset,
rotate=90) rotate=90)
# adds the pclk rail on metal1 # adds the en rail on metal1
self.add_layout_pin_center_segment(text="clk", self.add_layout_pin_center_segment(text="en",
layer="metal1", layer="metal1",
start=offset.scale(0,1), start=offset.scale(0,1),
end=offset.scale(0,1)+vector(self.width,0)) end=offset.scale(0,1)+vector(self.width,0))

View File

@ -46,7 +46,7 @@ class precharge_array(design.design):
self.add_layout_pin(text="en", self.add_layout_pin(text="en",
layer="metal1", layer="metal1",
offset=self.pc_cell.get_pin("clk").ll(), offset=self.pc_cell.get_pin("en").ll(),
width=self.width, width=self.width,
height=drc["minwidth_metal1"]) height=drc["minwidth_metal1"])

View File

@ -11,11 +11,11 @@ from globals import OPTS
class replica_bitline(design.design): class replica_bitline(design.design):
""" """
Generate a module that simulates the delay of control logic Generate a module that simulates the delay of control logic
and bit line charging. Stages is the depth of the FO4 delay and bit line charging. Stages is the depth of the delay
line and rows is the height of the replica bit loads. line and rows is the height of the replica bit loads.
""" """
def __init__(self, FO4_stages, bitcell_loads, name="replica_bitline"): def __init__(self, delay_stages, delay_fanout, bitcell_loads, name="replica_bitline"):
design.design.__init__(self, name) design.design.__init__(self, name)
g = reload(__import__(OPTS.delay_chain)) g = reload(__import__(OPTS.delay_chain))
@ -30,7 +30,8 @@ class replica_bitline(design.design):
for pin in ["en", "out", "vdd", "gnd"]: for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin) self.add_pin(pin)
self.bitcell_loads = bitcell_loads self.bitcell_loads = bitcell_loads
self.FO4_stages = FO4_stages self.delay_stages = delay_stages
self.delay_fanout = delay_fanout
self.create_modules() self.create_modules()
self.calculate_module_offsets() self.calculate_module_offsets()
@ -83,7 +84,7 @@ class replica_bitline(design.design):
self.add_mod(self.rbl) self.add_mod(self.rbl)
# FIXME: The FO and depth of this should be tuned # FIXME: The FO and depth of this should be tuned
self.delay_chain = self.mod_delay_chain([4]*self.FO4_stages) self.delay_chain = self.mod_delay_chain([self.delay_fanout]*self.delay_stages)
self.add_mod(self.delay_chain) self.add_mod(self.delay_chain)
self.inv = pinv() self.inv = pinv()

View File

@ -14,116 +14,49 @@ import sys,os
import datetime import datetime
import re import re
import importlib import importlib
import globals from globals import *
(OPTS, args) = globals.parse_args() (OPTS, args) = parse_args()
# Check that we are left with a single configuration file as argument.
if len(args) != 1:
print(USAGE)
sys.exit(2)
def print_time(name, now_time, last_time=None):
if last_time:
time = round((now_time-last_time).total_seconds(),1)
else:
time = now_time
print("** {0}: {1} seconds".format(name,time))
return now_time
# These depend on arguments, so don't load them until now. # These depend on arguments, so don't load them until now.
import debug import debug
# required positional args for using openram main exe
if len(args) < 1:
print(globals.USAGE)
sys.exit(2)
globals.print_banner() init_openram(config_file=args[0], is_unit_test=False)
globals.init_openram(args[0]) # Only print banner here so it's not in unit tests
print_banner()
# Check if all arguments are integers for bits, size, banks # Output info about this run
if type(OPTS.word_size)!=int: report_status()
debug.error("{0} is not an integer in config file.".format(OPTS.word_size))
if type(OPTS.num_words)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.sram_size))
if type(OPTS.num_banks)!=int:
debug.error("{0} is not an integer in config file.".format(OPTS.num_banks))
if not OPTS.tech_name: # Start importing design modules after we have the config file
debug.error("Tech name must be specified in config file.")
word_size = OPTS.word_size
num_words = OPTS.num_words
num_banks = OPTS.num_banks
if (OPTS.output_name == ""):
OPTS.output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,
num_words,
num_banks,
OPTS.tech_name)
print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
print("Technology: {0}".format(OPTS.tech_name))
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks))
# only start importing modules after we have the config file
import verify import verify
import sram import sram
print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
# Keep track of running stats
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
last_time = start_time print_time("Start",start_time)
print_time("Start",datetime.datetime.now())
if not OPTS.check_lvsdrc:
print("DRC/LVS/PEX checking is disabled.")
# import SRAM test generation # import SRAM test generation
s = sram.sram(word_size=word_size, s = sram.sram(word_size=OPTS.word_size,
num_words=num_words, num_words=OPTS.num_words,
num_banks=num_banks, num_banks=OPTS.num_banks,
name=OPTS.output_name) name=OPTS.output_name)
last_time=print_time("SRAM creation", datetime.datetime.now(), last_time)
# Output the files for the resulting SRAM # Output the files for the resulting SRAM
s.save_output()
spname = OPTS.output_path + s.name + ".sp" # Delete temp files etc.
print("SP: Writing to {0}".format(spname)) end_openram()
s.sp_write(spname)
last_time=print_time("Spice writing", datetime.datetime.now(), last_time)
# Output the extracted design
sram_file = spname
if OPTS.use_pex:
sram_file = OPTS.output_path + "temp_pex.sp"
verify.run_pex(s.name, gdsname, spname, output=sram_file)
# Characterize the design
from characterizer import lib
libname = OPTS.output_path + s.name + ".lib"
print("LIB: Writing to {0}".format(libname))
if OPTS.analytical_delay:
print("Using analytical delay models (no characterization)")
else:
if OPTS.spice_name!="":
print("Performing simulation-based characterization with {}".format(OPTS.spice_name))
if OPTS.trim_netlist:
print("Trimming netlist to speed up characterization.")
lib.lib(libname,s,sram_file)
last_time=print_time("Characterization", datetime.datetime.now(), last_time)
# Write the layout
gdsname = OPTS.output_path + s.name + ".gds"
print("GDS: Writing to {0}".format(gdsname))
s.gds_write(gdsname)
last_time=print_time("GDS", datetime.datetime.now(), last_time)
# Create a LEF physical model
lefname = OPTS.output_path + s.name + ".lef"
print("LEF: Writing to {0}".format(lefname))
s.lef_write(lefname)
last_time=print_time("LEF", datetime.datetime.now(), last_time)
# Write a verilog model
vname = OPTS.output_path + s.name + ".v"
print("Verilog: Writing to {0}".format(vname))
s.verilog_write(vname)
last_time=print_time("Verilog", datetime.datetime.now(), last_time)
globals.end_openram()
print_time("End",datetime.datetime.now(), start_time) print_time("End",datetime.datetime.now(), start_time)

View File

@ -39,17 +39,27 @@ class options(optparse.Values):
# Define the output file paths # Define the output file paths
output_path = "." output_path = "."
# Define the output file base name # Define the output file base name
output_name = "sram" output_name = ""
# Use analytical delay models by default rather than (slow) characterization # Use analytical delay models by default rather than (slow) characterization
analytical_delay = True analytical_delay = True
# Purge the temp directory after a successful run (doesn't purge on errors, anyhow) # Purge the temp directory after a successful run (doesn't purge on errors, anyhow)
purge_temp = True purge_temp = True
# These are the configuration parameters
rw_ports = 1
r_ports = 0
# These will get initialized by the the file
supply_voltages = ""
temperatures = ""
process_corners = ""
# These are the default modules that can be over-riden # These are the default modules that can be over-riden
decoder = "hierarchical_decoder" decoder = "hierarchical_decoder"
ms_flop = "ms_flop" ms_flop = "ms_flop"
ms_flop_array = "ms_flop_array" ms_flop_array = "ms_flop_array"
dff = "dff"
dff_array = "dff_array"
control_logic = "control_logic" control_logic = "control_logic"
bitcell_array = "bitcell_array" bitcell_array = "bitcell_array"
sense_amp = "sense_amp" sense_amp = "sense_amp"

View File

@ -8,7 +8,7 @@ from bank import bank
import datetime import datetime
import getpass import getpass
from vector import vector from vector import vector
from globals import OPTS from globals import OPTS, print_time
class sram(design.design): class sram(design.design):
@ -45,6 +45,7 @@ class sram(design.design):
debug.info(2, "create sram of size {0} with {1} num of words".format(self.word_size, debug.info(2, "create sram of size {0} with {1} num of words".format(self.word_size,
self.num_words)) self.num_words))
start_time = datetime.datetime.now()
design.design.__init__(self, name) design.design.__init__(self, name)
@ -74,6 +75,10 @@ class sram(design.design):
self.DRC_LVS(final_verification=True) self.DRC_LVS(final_verification=True)
if not OPTS.is_unit_test:
print_time("SRAM creation", datetime.datetime.now(), start_time)
def compute_sizes(self): def compute_sizes(self):
""" Computes the organization of the memory using bitcell size by trying to make it square.""" """ Computes the organization of the memory using bitcell size by trying to make it square."""
@ -1009,3 +1014,60 @@ class sram(design.design):
def analytical_delay(self,slew,load): def analytical_delay(self,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(slew,load)
def save_output(self):
""" Save all the output files while reporting time to do it as well. """
# Save the spice file
start_time = datetime.datetime.now()
spname = OPTS.output_path + self.name + ".sp"
print("SP: Writing to {0}".format(spname))
self.sp_write(spname)
print_time("Spice writing", datetime.datetime.now(), start_time)
# Save the extracted spice file
if OPTS.use_pex:
start_time = datetime.datetime.now()
# Output the extracted design if requested
sp_file = OPTS.output_path + "temp_pex.sp"
verify.run_pex(self.name, gdsname, spname, output=sp_file)
print_time("Extraction", datetime.datetime.now(), start_time)
else:
# Use generated spice file for characterization
sp_file = spname
# Characterize the design
start_time = datetime.datetime.now()
from characterizer import lib
print("LIB: Characterizing... ")
if OPTS.analytical_delay:
print("Using analytical delay models (no characterization)")
else:
if OPTS.spice_name!="":
print("Performing simulation-based characterization with {}".format(OPTS.spice_name))
if OPTS.trim_netlist:
print("Trimming netlist to speed up characterization.")
lib.lib(out_dir=OPTS.output_path, sram=self, sp_file=sp_file)
print_time("Characterization", datetime.datetime.now(), start_time)
# Write the layout
start_time = datetime.datetime.now()
gdsname = OPTS.output_path + self.name + ".gds"
print("GDS: Writing to {0}".format(gdsname))
self.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.name + ".lef"
print("LEF: Writing to {0}".format(lefname))
self.lef_write(lefname)
print_time("LEF", datetime.datetime.now(), start_time)
# Write a verilog model
start_time = datetime.datetime.now()
vname = OPTS.output_path + self.name + ".v"
print("Verilog: Writing to {0}".format(vname))
self.verilog_write(vname)
print_time("Verilog", datetime.datetime.now(), start_time)

View File

@ -35,6 +35,8 @@ class code_format_test(openram_test):
continue continue
if re.search("openram.py$", code): if re.search("openram.py$", code):
continue continue
if re.search("gen_stimulus.py$", code):
continue
errors += check_print_output(code) errors += check_print_output(code)
# fails if there are any tabs in any files # fails if there are any tabs in any files

View File

@ -0,0 +1,44 @@
#!/usr/bin/env python2.7
"""
Run a regresion test on a dff_array.
"""
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
class dff_array_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
global verify
import verify
OPTS.check_lvsdrc = False
import dff_array
debug.info(2, "Testing dff_array for 3x3")
a = dff_array.dff_array(rows=3, columns=3)
self.local_check(a)
debug.info(2, "Testing dff_array for 1x3")
a = dff_array.dff_array(rows=1, columns=3)
self.local_check(a)
debug.info(2, "Testing dff_array for 3x1")
a = dff_array.dff_array(rows=3, columns=1)
self.local_check(a)
OPTS.check_lvsdrc = True
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

@ -22,15 +22,16 @@ class replica_bitline_test(openram_test):
import replica_bitline import replica_bitline
stages=4 stages=4
fanout=4
rows=13 rows=13
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
a = replica_bitline.replica_bitline(stages,rows) a = replica_bitline.replica_bitline(stages,fanout,rows)
self.local_check(a) self.local_check(a)
stages=8 stages=8
rows=100 rows=100
debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows)) debug.info(2, "Testing RBL with {0} FO4 stages, {1} rows".format(stages,rows))
a = replica_bitline.replica_bitline(stages,rows) a = replica_bitline.replica_bitline(stages,fanout,rows)
self.local_check(a) self.local_check(a)
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True

View File

@ -27,7 +27,7 @@ class timing_sram_test(openram_test):
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram import sram
import tech
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size, s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words, num_words=OPTS.num_words,
@ -43,32 +43,35 @@ class timing_sram_test(openram_test):
probe_data = s.word_size - 1 probe_data = s.word_size - 1
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
d = delay.delay(s,tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
d = delay.delay(s,tempspice,corner)
import tech import tech
loads = [tech.spice["FF_in_cap"]*4] loads = [tech.spice["msflop_in_cap"]*4]
slews = [tech.spice["rise_time"]*2] slews = [tech.spice["rise_time"]*2]
data = d.analyze(probe_address, probe_data,slews,loads) data = d.analyze(probe_address, probe_data,slews,loads)
#print data #print data
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'read1_power': 0.0345742, golden_data = {'leakage_power': 0.0006964536000000001,
'read0_power': 0.03526189999999999, 'delay_lh': [0.0573055],
'write0_power': 0.0270014, 'read0_power': [0.0337812],
'delay1': [0.0573107], 'read1_power': [0.032946500000000004],
'delay0': [0.07055809999999998], 'write1_power': [0.0361529],
'min_period': 0.234, 'write0_power': [0.026179099999999997],
'write1_power': 0.0376625, 'slew_hl': [0.0285185],
'slew0': [0.0284344], 'min_period': 0.205,
'slew1': [0.0189185]} 'delay_hl': [0.070554],
'slew_lh': [0.0190073]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'read1_power': 11.2474, golden_data = {'leakage_power': 0.0004004581,
'read0_power': 11.3148, 'delay_lh': [0.6538954],
'write0_power': 6.9064, 'read0_power': [9.7622],
'delay1': [1.0298], 'read1_power': [9.589],
'delay0': [1.4102], 'write1_power': [10.2578],
'min_period': 4.063, 'write0_power': [6.928400000000001],
'write1_power': 11.6964, 'slew_hl': [0.8321625],
'slew0': [1.3118], 'min_period': 2.344,
'slew1': [0.9816656]} 'delay_hl': [0.9019090999999999],
'slew_lh': [0.5896232]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail
# Check if no too many or too few results # Check if no too many or too few results

View File

@ -31,19 +31,20 @@ class timing_setup_test(openram_test):
import tech import tech
slews = [tech.spice["rise_time"]*2] slews = [tech.spice["rise_time"]*2]
sh = setup_hold.setup_hold() corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
sh = setup_hold.setup_hold(corner)
data = sh.analyze(slews,slews) data = sh.analyze(slews,slews)
#print data
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'setup_times_LH': [0.014648399999999999], golden_data = {'setup_times_LH': [0.014648399999999999],
'hold_times_LH': [0.0024414], 'hold_times_LH': [0.0024414],
'hold_times_HL': [-0.0036620999999999997], 'hold_times_HL': [-0.0036620999999999997],
'setup_times_HL': [0.0085449]} 'setup_times_HL': [0.0085449]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'setup_times_LH': [0.1000977], golden_data = {'setup_times_LH': [0.08178709999999999],
'hold_times_LH': [0.020751999999999996], 'hold_times_LH': [0.0024414],
'hold_times_HL': [-0.0830078], 'hold_times_HL': [-0.0646973],
'setup_times_HL': [0.020751999999999996]} 'setup_times_HL': [0.0390625]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -27,7 +27,7 @@ class timing_sram_test(openram_test):
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1) debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram import sram
import tech
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size, s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words, num_words=OPTS.num_words,
@ -41,32 +41,35 @@ class timing_sram_test(openram_test):
probe_data = s.word_size - 1 probe_data = s.word_size - 1
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
d = delay.delay(s,tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
d = delay.delay(s,tempspice,corner)
import tech import tech
loads = [tech.spice["FF_in_cap"]*4] loads = [tech.spice["msflop_in_cap"]*4]
slews = [tech.spice["rise_time"]*2] slews = [tech.spice["rise_time"]*2]
data = d.analyze(probe_address, probe_data,slews,loads) data = d.analyze(probe_address, probe_data,slews,loads)
#print data #print data
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'read1_power': 0.03308298, golden_data = {'leakage_power': 0.0007348262,
'read0_power': 0.03866541, 'delay_lh': [0.05799613],
'write0_power': 0.02695139, 'read0_power': [0.0384102],
'delay1': [0.05840294000000001], 'read1_power': [0.03279848],
'delay0': [0.40787249999999997], 'write1_power': [0.03693655],
'min_period': 0.781, 'write0_power': [0.02717752],
'write1_power': 0.037257830000000006, 'slew_hl': [0.03607912],
'slew0': [0.035826199999999996], 'min_period': 0.742,
'slew1': [0.02059459]} 'delay_hl': [0.3929995],
'slew_lh': [0.02160862]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'read1_power': 10.31395, golden_data = {'leakage_power': 0.00142014,
'read0_power': 10.0321, 'delay_lh': [0.8018421],
'write0_power': 6.072756, 'read0_power': [11.44908],
'delay1': [1.042564], 'read1_power': [11.416549999999999],
'delay0': [1.412224], 'write1_power': [11.718020000000001],
'min_period': 4.688, 'write0_power': [8.250219],
'write1_power': 10.53758, 'slew_hl': [0.8273725],
'slew0': [1.355812], 'min_period': 2.734,
'slew1': [1.03401]} 'delay_hl': [1.085861],
'slew_lh': [0.5730144]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -30,19 +30,20 @@ class timing_setup_test(openram_test):
import tech import tech
slews = [tech.spice["rise_time"]*2] slews = [tech.spice["rise_time"]*2]
sh = setup_hold.setup_hold() corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
sh = setup_hold.setup_hold(corner)
data = sh.analyze(slews,slews) data = sh.analyze(slews,slews)
#print data
if OPTS.tech_name == "freepdk45": if OPTS.tech_name == "freepdk45":
golden_data = {'setup_times_LH': [0.01464844], golden_data = {'setup_times_LH': [0.01464844],
'hold_times_LH': [0.0024414059999999997], 'hold_times_LH': [0.0024414059999999997],
'hold_times_HL': [-0.003662109], 'hold_times_HL': [-0.003662109],
'setup_times_HL': [0.008544922]} 'setup_times_HL': [0.008544922]}
elif OPTS.tech_name == "scn3me_subm": elif OPTS.tech_name == "scn3me_subm":
golden_data = {'setup_times_LH': [0.1000977], golden_data = {'setup_times_LH': [0.07568359],
'hold_times_LH': [0.02075195], 'hold_times_LH': [0.008544922],
'hold_times_HL': [-0.08300781], 'hold_times_HL': [-0.05859374999999999],
'setup_times_HL': [0.02075195]} 'setup_times_HL': [0.03295898]}
else: else:
self.assertTrue(False) # other techs fail self.assertTrue(False) # other techs fail

View File

@ -29,9 +29,9 @@ class sram_func_test(openram_test):
import sram import sram
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size, s = sram.sram(word_size=1,
num_words=OPTS.num_words, num_words=16,
num_banks=OPTS.num_banks, num_banks=1,
name="sram_func_test") name="sram_func_test")
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
@ -43,14 +43,15 @@ class sram_func_test(openram_test):
probe_data = s.word_size - 1 probe_data = s.word_size - 1
debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data)) debug.info(1, "Probe address {0} probe data {1}".format(probe_address, probe_data))
d = delay.delay(s,tempspice) corner = (OPTS.process_corners[0], OPTS.supply_voltages[0], OPTS.temperatures[0])
d = delay.delay(s,tempspice,corner)
d.set_probe(probe_address,probe_data) d.set_probe(probe_address,probe_data)
# This will exit if it doesn't find a feasible period # This will exit if it doesn't find a feasible period
import tech import tech
load = tech.spice["FF_in_cap"]*4 d.load = tech.spice["msflop_in_cap"]*4
slew = tech.spice["rise_time"]*2 d.slew = tech.spice["rise_time"]*2
feasible_period = d.find_feasible_period(load,slew) feasible_period = d.find_feasible_period()
os.remove(tempspice) os.remove(tempspice)
OPTS.analytical_delay = True OPTS.analytical_delay = True

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM
import unittest import unittest
from testutils import header,openram_test from testutils import header,openram_test
import sys,os import sys,os,re
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
from globals import OPTS from globals import OPTS
@ -22,20 +22,26 @@ class lib_test(openram_test):
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
num_words=OPTS.num_words, num_words=16,
num_banks=OPTS.num_banks, num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name)) name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)
filename = s.name + "_analytical.lib" lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=True)
libname = OPTS.openram_temp + filename
lib.lib(libname=libname,sram=s,spfile=tempspice,use_model=True)
# let's diff the result with a golden model # get all of the .lib files generated
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) files = os.listdir(OPTS.openram_temp)
nametest = re.compile("\.lib$", re.IGNORECASE)
lib_files = filter(nametest.search, files)
# and compare them with the golden model
for filename in lib_files:
newname = filename.replace(".lib","_analytical.lib")
libname = "{0}/{1}".format(OPTS.openram_temp,filename)
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),newname)
self.isapproxdiff(libname,golden,0.15) self.isapproxdiff(libname,golden,0.15)
globals.end_openram() globals.end_openram()

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM with pruning
import unittest import unittest
from testutils import header,openram_test from testutils import header,openram_test
import sys,os import sys,os,re
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
from globals import OPTS from globals import OPTS
@ -31,21 +31,27 @@ class lib_test(openram_test):
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
num_words=OPTS.num_words, num_words=16,
num_banks=OPTS.num_banks, num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name)) name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)
filename = s.name + "_pruned.lib" lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=False)
libname = OPTS.openram_temp + filename
lib.lib(libname=libname,sram=s,spfile=tempspice,use_model=False)
# let's diff the result with a golden model # get all of the .lib files generated
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) files = os.listdir(OPTS.openram_temp)
self.isapproxdiff(libname,golden,0.30) nametest = re.compile("\.lib$", re.IGNORECASE)
lib_files = filter(nametest.search, files)
# and compare them with the golden model
for filename in lib_files:
newname = filename.replace(".lib","_pruned.lib")
libname = "{0}/{1}".format(OPTS.openram_temp,filename)
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),newname)
self.isapproxdiff(libname,golden,0.15)
OPTS.analytical_delay = True OPTS.analytical_delay = True
reload(characterizer) reload(characterizer)

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM
import unittest import unittest
from testutils import header,openram_test from testutils import header,openram_test
import sys,os import sys,os,re
sys.path.append(os.path.join(sys.path[0],"..")) sys.path.append(os.path.join(sys.path[0],".."))
import globals import globals
from globals import OPTS from globals import OPTS
@ -31,19 +31,24 @@ class lib_test(openram_test):
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2, s = sram.sram(word_size=2,
num_words=OPTS.num_words, num_words=16,
num_banks=OPTS.num_banks, num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name)) name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice) s.sp_write(tempspice)
filename = s.name + ".lib" lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=False)
libname = OPTS.openram_temp + filename
lib.lib(libname=libname,sram=s,spfile=tempspice,use_model=False)
# let's diff the result with a golden model # get all of the .lib files generated
files = os.listdir(OPTS.openram_temp)
nametest = re.compile("\.lib$", re.IGNORECASE)
lib_files = filter(nametest.search, files)
# and compare them with the golden model
for filename in lib_files:
libname = "{0}/{1}".format(OPTS.openram_temp,filename)
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename) golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
self.isapproxdiff(libname,golden,0.15) self.isapproxdiff(libname,golden,0.15)

View File

@ -52,11 +52,16 @@ class openram_test(openram_test):
os.system(cmd) os.system(cmd)
# assert an error until we actually check a resul # assert an error until we actually check a resul
for extension in ["gds", "v", "lef", "lib", "sp"]: for extension in ["gds", "v", "lef", "sp"]:
filename = "{0}/{1}.{2}".format(out_path,out_file,extension) filename = "{0}/{1}.{2}".format(out_path,out_file,extension)
debug.info(1,"Checking for file: " + filename) debug.info(1,"Checking for file: " + filename)
self.assertEqual(os.path.exists(filename),True) self.assertEqual(os.path.exists(filename),True)
# Make sure there is any .lib file
import glob
files = glob.glob('{0}/*.lib'.format(out_path))
self.assertTrue(len(files)>0)
# grep any errors from the output # grep any errors from the output
output = open("{0}/output.log".format(out_path),"r").read() output = open("{0}/output.log".format(out_path),"r").read()
self.assertEqual(len(re.findall('ERROR',output)),0) self.assertEqual(len(re.findall('ERROR',output)),0)

View File

@ -3,5 +3,8 @@ num_words = 16
num_banks = 1 num_banks = 1
tech_name = "freepdk45" tech_name = "freepdk45"
process_corners = ["TT"]
supply_voltages = [1.0]
temperatures = [25]

View File

@ -3,4 +3,7 @@ num_words = 16
num_banks = 1 num_banks = 1
tech_name = "scn3me_subm" tech_name = "scn3me_subm"
process_corners = ["TT"]
supply_voltages = [5.0]
temperatures = [25]

View File

@ -7,11 +7,11 @@ UNITS
END UNITS END UNITS
SITE MacroSite SITE MacroSite
CLASS Core ; CLASS Core ;
SIZE 21695.0 by 42337.5 ; SIZE 24385.0 by 42337.5 ;
END MacroSite END MacroSite
MACRO sram_2_16_1_freepdk45 MACRO sram_2_16_1_freepdk45
CLASS BLOCK ; CLASS BLOCK ;
SIZE 21695.0 BY 42337.5 ; SIZE 24385.0 BY 42337.5 ;
SYMMETRY X Y R90 ; SYMMETRY X Y R90 ;
SITE MacroSite ; SITE MacroSite ;
PIN DATA[0] PIN DATA[0]
@ -4165,12 +4165,15 @@ MACRO sram_2_16_1_freepdk45
RECT 750.0 30905.0 685.0 30970.0 ; RECT 750.0 30905.0 685.0 30970.0 ;
RECT 32.5 30615.0 -32.5 31175.0 ; RECT 32.5 30615.0 -32.5 31175.0 ;
RECT 1377.5 30615.0 1312.5 31175.0 ; RECT 1377.5 30615.0 1312.5 31175.0 ;
RECT 1377.5 39337.5 1312.5 36955.0 ; RECT 1377.5 38217.5 1312.5 39645.0 ;
RECT 1312.5 33907.5 1025.0 33972.5 ; RECT 1312.5 33907.5 1025.0 33972.5 ;
RECT 1312.5 36317.5 1025.0 36382.5 ; RECT 1312.5 36317.5 1025.0 36382.5 ;
RECT 1312.5 36597.5 1025.0 36662.5 ;
RECT 1312.5 39007.5 1025.0 39072.5 ;
RECT 1377.5 31862.5 935.0 31927.5 ; RECT 1377.5 31862.5 935.0 31927.5 ;
RECT 935.0 31862.5 230.0 31927.5 ; RECT 935.0 31862.5 230.0 31927.5 ;
RECT 20.0 35112.5 935.0 35177.5 ; RECT 20.0 35112.5 935.0 35177.5 ;
RECT 20.0 37802.5 935.0 37867.5 ;
RECT 20.0 32422.5 935.0 32487.5 ; RECT 20.0 32422.5 935.0 32487.5 ;
RECT 2005.0 33435.0 1940.0 34135.0 ; RECT 2005.0 33435.0 1940.0 34135.0 ;
RECT 2005.0 33627.5 1940.0 33692.5 ; RECT 2005.0 33627.5 1940.0 33692.5 ;
@ -4210,11 +4213,11 @@ MACRO sram_2_16_1_freepdk45
RECT 2330.0 33497.5 2465.0 33562.5 ; RECT 2330.0 33497.5 2465.0 33562.5 ;
RECT 2330.0 33497.5 2465.0 33562.5 ; RECT 2330.0 33497.5 2465.0 33562.5 ;
RECT 2330.0 33307.5 2465.0 33372.5 ; RECT 2330.0 33307.5 2465.0 33372.5 ;
RECT 1312.5 39272.5 1377.5 39337.5 ; RECT 1312.5 38152.5 1377.5 38217.5 ;
RECT 4002.5 39272.5 4067.5 39337.5 ; RECT 4002.5 38152.5 4067.5 38217.5 ;
RECT 1312.5 39175.0 1377.5 39305.0 ; RECT 1312.5 38055.0 1377.5 38185.0 ;
RECT 1345.0 39272.5 4035.0 39337.5 ; RECT 1345.0 38152.5 4035.0 38217.5 ;
RECT 4002.5 39175.0 4067.5 39305.0 ; RECT 4002.5 38055.0 4067.5 38185.0 ;
RECT 2875.0 34562.5 2690.0 34627.5 ; RECT 2875.0 34562.5 2690.0 34627.5 ;
RECT 4035.0 34562.5 3850.0 34627.5 ; RECT 4035.0 34562.5 3850.0 34627.5 ;
RECT 3917.5 34202.5 4067.5 34267.5 ; RECT 3917.5 34202.5 4067.5 34267.5 ;
@ -4361,90 +4364,6 @@ MACRO sram_2_16_1_freepdk45
RECT 2722.5 37495.0 2657.5 38055.0 ; RECT 2722.5 37495.0 2657.5 38055.0 ;
RECT 4067.5 37495.0 4002.5 38055.0 ; RECT 4067.5 37495.0 4002.5 38055.0 ;
RECT 3340.0 37620.0 3475.0 37685.0 ; RECT 3340.0 37620.0 3475.0 37685.0 ;
RECT 2875.0 38482.5 2690.0 38547.5 ;
RECT 4035.0 38482.5 3850.0 38547.5 ;
RECT 3917.5 38122.5 4067.5 38187.5 ;
RECT 3032.5 38122.5 2657.5 38187.5 ;
RECT 3917.5 38312.5 3032.5 38377.5 ;
RECT 3032.5 38122.5 2897.5 38187.5 ;
RECT 3032.5 38312.5 2897.5 38377.5 ;
RECT 3032.5 38312.5 2897.5 38377.5 ;
RECT 3032.5 38122.5 2897.5 38187.5 ;
RECT 3917.5 38122.5 3782.5 38187.5 ;
RECT 3917.5 38312.5 3782.5 38377.5 ;
RECT 3917.5 38312.5 3782.5 38377.5 ;
RECT 3917.5 38122.5 3782.5 38187.5 ;
RECT 2942.5 38482.5 2807.5 38547.5 ;
RECT 3917.5 38482.5 3782.5 38547.5 ;
RECT 3475.0 38180.0 3340.0 38245.0 ;
RECT 3475.0 38180.0 3340.0 38245.0 ;
RECT 3440.0 38345.0 3375.0 38410.0 ;
RECT 2722.5 38055.0 2657.5 38615.0 ;
RECT 4067.5 38055.0 4002.5 38615.0 ;
RECT 3340.0 38180.0 3475.0 38245.0 ;
RECT 2875.0 39042.5 2690.0 39107.5 ;
RECT 4035.0 39042.5 3850.0 39107.5 ;
RECT 3917.5 38682.5 4067.5 38747.5 ;
RECT 3032.5 38682.5 2657.5 38747.5 ;
RECT 3917.5 38872.5 3032.5 38937.5 ;
RECT 3032.5 38682.5 2897.5 38747.5 ;
RECT 3032.5 38872.5 2897.5 38937.5 ;
RECT 3032.5 38872.5 2897.5 38937.5 ;
RECT 3032.5 38682.5 2897.5 38747.5 ;
RECT 3917.5 38682.5 3782.5 38747.5 ;
RECT 3917.5 38872.5 3782.5 38937.5 ;
RECT 3917.5 38872.5 3782.5 38937.5 ;
RECT 3917.5 38682.5 3782.5 38747.5 ;
RECT 2942.5 39042.5 2807.5 39107.5 ;
RECT 3917.5 39042.5 3782.5 39107.5 ;
RECT 3475.0 38740.0 3340.0 38805.0 ;
RECT 3475.0 38740.0 3340.0 38805.0 ;
RECT 3440.0 38905.0 3375.0 38970.0 ;
RECT 2722.5 38615.0 2657.5 39175.0 ;
RECT 4067.5 38615.0 4002.5 39175.0 ;
RECT 3340.0 38740.0 3475.0 38805.0 ;
RECT 2505.0 38187.5 2690.0 38122.5 ;
RECT 1345.0 38187.5 1530.0 38122.5 ;
RECT 1462.5 38547.5 1312.5 38482.5 ;
RECT 2347.5 38547.5 2722.5 38482.5 ;
RECT 1462.5 38357.5 2347.5 38292.5 ;
RECT 2347.5 38547.5 2482.5 38482.5 ;
RECT 2347.5 38357.5 2482.5 38292.5 ;
RECT 2347.5 38357.5 2482.5 38292.5 ;
RECT 2347.5 38547.5 2482.5 38482.5 ;
RECT 1462.5 38547.5 1597.5 38482.5 ;
RECT 1462.5 38357.5 1597.5 38292.5 ;
RECT 1462.5 38357.5 1597.5 38292.5 ;
RECT 1462.5 38547.5 1597.5 38482.5 ;
RECT 2437.5 38187.5 2572.5 38122.5 ;
RECT 1462.5 38187.5 1597.5 38122.5 ;
RECT 1905.0 38490.0 2040.0 38425.0 ;
RECT 1905.0 38490.0 2040.0 38425.0 ;
RECT 1940.0 38325.0 2005.0 38260.0 ;
RECT 2657.5 38615.0 2722.5 38055.0 ;
RECT 1312.5 38615.0 1377.5 38055.0 ;
RECT 1905.0 38425.0 2040.0 38490.0 ;
RECT 2505.0 37627.5 2690.0 37562.5 ;
RECT 1345.0 37627.5 1530.0 37562.5 ;
RECT 1462.5 37987.5 1312.5 37922.5 ;
RECT 2347.5 37987.5 2722.5 37922.5 ;
RECT 1462.5 37797.5 2347.5 37732.5 ;
RECT 2347.5 37987.5 2482.5 37922.5 ;
RECT 2347.5 37797.5 2482.5 37732.5 ;
RECT 2347.5 37797.5 2482.5 37732.5 ;
RECT 2347.5 37987.5 2482.5 37922.5 ;
RECT 1462.5 37987.5 1597.5 37922.5 ;
RECT 1462.5 37797.5 1597.5 37732.5 ;
RECT 1462.5 37797.5 1597.5 37732.5 ;
RECT 1462.5 37987.5 1597.5 37922.5 ;
RECT 2437.5 37627.5 2572.5 37562.5 ;
RECT 1462.5 37627.5 1597.5 37562.5 ;
RECT 1905.0 37930.0 2040.0 37865.0 ;
RECT 1905.0 37930.0 2040.0 37865.0 ;
RECT 1940.0 37765.0 2005.0 37700.0 ;
RECT 2657.5 38055.0 2722.5 37495.0 ;
RECT 1312.5 38055.0 1377.5 37495.0 ;
RECT 1905.0 37865.0 2040.0 37930.0 ;
RECT 2505.0 37067.5 2690.0 37002.5 ; RECT 2505.0 37067.5 2690.0 37002.5 ;
RECT 1345.0 37067.5 1530.0 37002.5 ; RECT 1345.0 37067.5 1530.0 37002.5 ;
RECT 1462.5 37427.5 1312.5 37362.5 ; RECT 1462.5 37427.5 1312.5 37362.5 ;
@ -4572,24 +4491,32 @@ MACRO sram_2_16_1_freepdk45
RECT 1312.5 34695.0 1377.5 34135.0 ; RECT 1312.5 34695.0 1377.5 34135.0 ;
RECT 1905.0 34505.0 2040.0 34570.0 ; RECT 1905.0 34505.0 2040.0 34570.0 ;
RECT 3340.0 34425.0 3475.0 34490.0 ; RECT 3340.0 34425.0 3475.0 34490.0 ;
RECT 3340.0 36665.0 3475.0 36730.0 ; RECT 3340.0 36105.0 3475.0 36170.0 ;
RECT 3340.0 38905.0 3475.0 38970.0 ; RECT 3340.0 37785.0 3475.0 37850.0 ;
RECT 1905.0 36580.0 2040.0 36645.0 ; RECT 1905.0 36020.0 2040.0 36085.0 ;
RECT 3340.0 34260.0 3475.0 34325.0 ; RECT 3340.0 34260.0 3475.0 34325.0 ;
RECT 1940.0 34135.0 2005.0 34340.0 ; RECT 1940.0 34135.0 2005.0 34340.0 ;
RECT 2657.5 34135.0 2722.5 39175.0 ; RECT 2657.5 34135.0 2722.5 38055.0 ;
RECT 1312.5 34135.0 1377.5 39175.0 ; RECT 1312.5 34135.0 1377.5 38055.0 ;
RECT 4002.5 34135.0 4067.5 39175.0 ; RECT 4002.5 34135.0 4067.5 38055.0 ;
RECT 935.0 33800.0 225.0 32455.0 ; RECT 935.0 33800.0 225.0 32455.0 ;
RECT 935.0 33800.0 230.0 35145.0 ; RECT 935.0 33800.0 230.0 35145.0 ;
RECT 935.0 36490.0 230.0 35145.0 ; RECT 935.0 36490.0 230.0 35145.0 ;
RECT 935.0 36490.0 230.0 37835.0 ;
RECT 935.0 39180.0 230.0 37835.0 ;
RECT 1025.0 33907.5 140.0 33972.5 ; RECT 1025.0 33907.5 140.0 33972.5 ;
RECT 1025.0 36317.5 140.0 36382.5 ; RECT 1025.0 36317.5 140.0 36382.5 ;
RECT 1025.0 36597.5 140.0 36662.5 ;
RECT 1025.0 39007.5 140.0 39072.5 ;
RECT 1025.0 35112.5 140.0 35177.5 ; RECT 1025.0 35112.5 140.0 35177.5 ;
RECT 1025.0 37802.5 140.0 37867.5 ;
RECT 1025.0 33767.5 140.0 33832.5 ; RECT 1025.0 33767.5 140.0 33832.5 ;
RECT 1025.0 36457.5 140.0 36522.5 ; RECT 1025.0 36457.5 140.0 36522.5 ;
RECT 1025.0 39147.5 140.0 39212.5 ;
RECT 1345.0 33872.5 1280.0 34007.5 ; RECT 1345.0 33872.5 1280.0 34007.5 ;
RECT 1345.0 36282.5 1280.0 36417.5 ; RECT 1345.0 36282.5 1280.0 36417.5 ;
RECT 1345.0 36562.5 1280.0 36697.5 ;
RECT 1345.0 38972.5 1280.0 39107.5 ;
RECT 1342.5 34135.0 1277.5 34270.0 ; RECT 1342.5 34135.0 1277.5 34270.0 ;
RECT 1377.5 31760.0 1312.5 31895.0 ; RECT 1377.5 31760.0 1312.5 31895.0 ;
RECT 867.5 31862.5 1002.5 31927.5 ; RECT 867.5 31862.5 1002.5 31927.5 ;
@ -4600,7 +4527,7 @@ MACRO sram_2_16_1_freepdk45
RECT 682.5 32030.0 817.5 32095.0 ; RECT 682.5 32030.0 817.5 32095.0 ;
RECT 3475.0 31335.0 3410.0 34260.0 ; RECT 3475.0 31335.0 3410.0 34260.0 ;
RECT 2005.0 31335.0 1940.0 32100.0 ; RECT 2005.0 31335.0 1940.0 32100.0 ;
RECT 20.0 31335.0 -45.0 36577.5 ; RECT 20.0 31335.0 -45.0 39267.5 ;
RECT 2722.5 31335.0 2657.5 34135.0 ; RECT 2722.5 31335.0 2657.5 34135.0 ;
RECT 1377.5 31335.0 1312.5 31895.0 ; RECT 1377.5 31335.0 1312.5 31895.0 ;
RECT 4067.5 31335.0 4002.5 34135.0 ; RECT 4067.5 31335.0 4002.5 34135.0 ;
@ -5439,29 +5366,25 @@ MACRO sram_2_16_1_freepdk45
RECT 1610.0 26387.5 1540.0 26252.5 ; RECT 1610.0 26387.5 1540.0 26252.5 ;
RECT 2315.0 25737.5 2245.0 25602.5 ; RECT 2315.0 25737.5 2245.0 25602.5 ;
RECT 2315.0 26387.5 2245.0 26252.5 ; RECT 2315.0 26387.5 2245.0 26252.5 ;
RECT 1380.0 31895.0 1310.0 36955.0 ; RECT 1380.0 31895.0 1310.0 39645.0 ;
RECT 970.0 31895.0 900.0 36645.0 ; RECT 970.0 31895.0 900.0 39335.0 ;
RECT 265.0 31895.0 195.0 36645.0 ; RECT 265.0 31895.0 195.0 39335.0 ;
RECT 1207.5 32062.5 1137.5 32660.0 ; RECT 1207.5 32062.5 1137.5 32660.0 ;
RECT 785.0 32062.5 715.0 32342.5 ; RECT 785.0 32062.5 715.0 32342.5 ;
RECT 3372.5 34457.5 3442.5 34852.5 ; RECT 3372.5 34457.5 3442.5 34852.5 ;
RECT 3372.5 34852.5 3442.5 35412.5 ; RECT 3372.5 34852.5 3442.5 35412.5 ;
RECT 3372.5 35412.5 3442.5 35972.5 ; RECT 3372.5 35412.5 3442.5 35972.5 ;
RECT 3372.5 35972.5 3442.5 36532.5 ; RECT 3372.5 36137.5 3442.5 36532.5 ;
RECT 3372.5 36697.5 3442.5 37092.5 ; RECT 3372.5 36532.5 3442.5 37092.5 ;
RECT 3372.5 37092.5 3442.5 37652.5 ; RECT 3372.5 37092.5 3442.5 37652.5 ;
RECT 3372.5 37652.5 3442.5 38212.5 ; RECT 2655.0 37782.5 2725.0 37852.5 ;
RECT 3372.5 38212.5 3442.5 38772.5 ; RECT 2655.0 37302.5 2725.0 37372.5 ;
RECT 2655.0 38902.5 2725.0 38972.5 ; RECT 2690.0 37782.5 3407.5 37852.5 ;
RECT 2655.0 38422.5 2725.0 38492.5 ; RECT 2655.0 37337.5 2725.0 37817.5 ;
RECT 2690.0 38902.5 3407.5 38972.5 ; RECT 1972.5 37302.5 2690.0 37372.5 ;
RECT 2655.0 38457.5 2725.0 38937.5 ;
RECT 1972.5 38422.5 2690.0 38492.5 ;
RECT 1937.5 37897.5 2007.5 38457.5 ;
RECT 1937.5 37337.5 2007.5 37897.5 ;
RECT 1937.5 36777.5 2007.5 37337.5 ; RECT 1937.5 36777.5 2007.5 37337.5 ;
RECT 1937.5 36217.5 2007.5 36612.5 ; RECT 1937.5 36217.5 2007.5 36777.5 ;
RECT 1937.5 35657.5 2007.5 36217.5 ; RECT 1937.5 35657.5 2007.5 36052.5 ;
RECT 1937.5 35097.5 2007.5 35657.5 ; RECT 1937.5 35097.5 2007.5 35657.5 ;
RECT 1937.5 34537.5 2007.5 35097.5 ; RECT 1937.5 34537.5 2007.5 35097.5 ;
RECT 3340.0 34817.5 3475.0 34887.5 ; RECT 3340.0 34817.5 3475.0 34887.5 ;
@ -5470,10 +5393,6 @@ MACRO sram_2_16_1_freepdk45
RECT 3340.0 36497.5 3475.0 36567.5 ; RECT 3340.0 36497.5 3475.0 36567.5 ;
RECT 3340.0 37057.5 3475.0 37127.5 ; RECT 3340.0 37057.5 3475.0 37127.5 ;
RECT 3340.0 37617.5 3475.0 37687.5 ; RECT 3340.0 37617.5 3475.0 37687.5 ;
RECT 3340.0 38177.5 3475.0 38247.5 ;
RECT 3340.0 38737.5 3475.0 38807.5 ;
RECT 1905.0 38422.5 2040.0 38492.5 ;
RECT 1905.0 37862.5 2040.0 37932.5 ;
RECT 1905.0 37302.5 2040.0 37372.5 ; RECT 1905.0 37302.5 2040.0 37372.5 ;
RECT 1905.0 36742.5 2040.0 36812.5 ; RECT 1905.0 36742.5 2040.0 36812.5 ;
RECT 1905.0 36182.5 2040.0 36252.5 ; RECT 1905.0 36182.5 2040.0 36252.5 ;
@ -5481,18 +5400,22 @@ MACRO sram_2_16_1_freepdk45
RECT 1905.0 35062.5 2040.0 35132.5 ; RECT 1905.0 35062.5 2040.0 35132.5 ;
RECT 1905.0 34502.5 2040.0 34572.5 ; RECT 1905.0 34502.5 2040.0 34572.5 ;
RECT 3340.0 34422.5 3475.0 34492.5 ; RECT 3340.0 34422.5 3475.0 34492.5 ;
RECT 3340.0 36662.5 3475.0 36732.5 ; RECT 3340.0 36102.5 3475.0 36172.5 ;
RECT 3340.0 38902.5 3475.0 38972.5 ; RECT 3340.0 37782.5 3475.0 37852.5 ;
RECT 1905.0 36577.5 2040.0 36647.5 ; RECT 1905.0 36017.5 2040.0 36087.5 ;
RECT 935.0 33800.0 225.0 32455.0 ; RECT 935.0 33800.0 225.0 32455.0 ;
RECT 935.0 33800.0 230.0 35145.0 ; RECT 935.0 33800.0 230.0 35145.0 ;
RECT 935.0 36490.0 230.0 35145.0 ; RECT 935.0 36490.0 230.0 35145.0 ;
RECT 785.0 33700.0 715.0 36645.0 ; RECT 935.0 36490.0 230.0 37835.0 ;
RECT 450.0 33700.0 380.0 36645.0 ; RECT 935.0 39180.0 230.0 37835.0 ;
RECT 970.0 33700.0 900.0 36645.0 ; RECT 785.0 33700.0 715.0 39335.0 ;
RECT 265.0 33700.0 195.0 36645.0 ; RECT 450.0 33700.0 380.0 39335.0 ;
RECT 970.0 33700.0 900.0 39335.0 ;
RECT 265.0 33700.0 195.0 39335.0 ;
RECT 1347.5 33872.5 1277.5 34007.5 ; RECT 1347.5 33872.5 1277.5 34007.5 ;
RECT 1347.5 36282.5 1277.5 36417.5 ; RECT 1347.5 36282.5 1277.5 36417.5 ;
RECT 1347.5 36562.5 1277.5 36697.5 ;
RECT 1347.5 38972.5 1277.5 39107.5 ;
RECT 1345.0 34135.0 1275.0 34270.0 ; RECT 1345.0 34135.0 1275.0 34270.0 ;
RECT 1380.0 31760.0 1310.0 31895.0 ; RECT 1380.0 31760.0 1310.0 31895.0 ;
RECT 867.5 31860.0 1002.5 31930.0 ; RECT 867.5 31860.0 1002.5 31930.0 ;

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_freepdk45_lib){ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){
delay_model : "table_lookup"; delay_model : "table_lookup";
time_unit : "1ns" ; time_unit : "1ns" ;
voltage_unit : "1v" ; voltage_unit : "1v" ;
@ -7,9 +7,10 @@ library (sram_2_16_1_freepdk45_lib){
capacitive_load_unit(1 ,fF) ; capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ; leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ; pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){ operating_conditions(OC){
process : 1.0 ;
voltage : 1.0 ; voltage : 1.0 ;
temperature : 25.000 ; temperature : 25;
} }
input_threshold_pct_fall : 50.0 ; input_threshold_pct_fall : 50.0 ;
@ -21,6 +22,9 @@ library (sram_2_16_1_freepdk45_lib){
slew_lower_threshold_pct_rise : 10.0 ; slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ; slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 1.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ; default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ; default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ; default_input_pin_cap : 1.0 ;
@ -45,7 +49,7 @@ library (sram_2_16_1_freepdk45_lib){
index_2("0.00125, 0.005, 0.04"); index_2("0.00125, 0.005, 0.04");
} }
default_operating_conditions : TT; default_operating_conditions : OC;
type (DATA){ type (DATA){
@ -74,12 +78,18 @@ 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 : 918.5120625; area : 1032.3999375;
leakage_power () {
when : "CSb";
value : 0.00088149731;
}
cell_leakage_power : 0;
bus(DATA){ bus(DATA){
bus_type : DATA; bus_type : DATA;
direction : inout; direction : inout;
max_capacitance : 1.6728; max_capacitance : 1.6728;
min_capacitance : 0.052275;
three_state : "!OEb & !clk"; three_state : "!OEb & !clk";
memory_write(){ memory_write(){
address : ADDR; address : ADDR;
@ -89,15 +99,6 @@ cell (sram_2_16_1_freepdk45){
address : ADDR; address : ADDR;
} }
pin(DATA[1:0]){ pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0.04024341");
}
fall_power(scalar){
values("0.029869287");
}
}
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk"; related_pin : "clk";
@ -126,15 +127,6 @@ cell (sram_2_16_1_freepdk45){
"-0.004, -0.004, -0.016"); "-0.004, -0.004, -0.016");
} }
} }
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0.050563718");
}
fall_power(scalar){
values("0.055867096");
}
}
timing(){ timing(){
timing_sense : non_unate; timing_sense : non_unate;
related_pin : "clk"; related_pin : "clk";
@ -145,9 +137,9 @@ cell (sram_2_16_1_freepdk45){
"0.061, 0.062, 0.069"); "0.061, 0.062, 0.069");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.442, 0.443, 0.452",\ values("0.429, 0.43, 0.439",\
"0.442, 0.443, 0.453",\ "0.429, 0.431, 0.439",\
"0.448, 0.449, 0.458"); "0.435, 0.436, 0.446");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.013, 0.015, 0.026",\ values("0.013, 0.015, 0.026",\
@ -168,7 +160,6 @@ cell (sram_2_16_1_freepdk45){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
max_transition : 0.04; max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[3:0]){ pin(ADDR[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
@ -304,24 +295,51 @@ cell (sram_2_16_1_freepdk45){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("0.0173748762222");
}
fall_power(scalar){
values("0.0173748762222");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("0.0261209913889");
}
fall_power(scalar){
values("0.0261209913889");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk; related_pin : clk;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.449"); values("0.4295");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.449"); values("0.4295");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk; related_pin : clk;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.898"); values("0.859");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.898"); values("0.859");
} }
} }
} }

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_freepdk45_lib){ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){
delay_model : "table_lookup"; delay_model : "table_lookup";
time_unit : "1ns" ; time_unit : "1ns" ;
voltage_unit : "1v" ; voltage_unit : "1v" ;
@ -7,9 +7,10 @@ library (sram_2_16_1_freepdk45_lib){
capacitive_load_unit(1 ,fF) ; capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ; leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ; pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){ operating_conditions(OC){
process : 1.0 ;
voltage : 1.0 ; voltage : 1.0 ;
temperature : 25.000 ; temperature : 25;
} }
input_threshold_pct_fall : 50.0 ; input_threshold_pct_fall : 50.0 ;
@ -21,6 +22,9 @@ library (sram_2_16_1_freepdk45_lib){
slew_lower_threshold_pct_rise : 10.0 ; slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ; slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 1.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ; default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ; default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ; default_input_pin_cap : 1.0 ;
@ -45,7 +49,7 @@ library (sram_2_16_1_freepdk45_lib){
index_2("0.00125, 0.005, 0.04"); index_2("0.00125, 0.005, 0.04");
} }
default_operating_conditions : TT; default_operating_conditions : OC;
type (DATA){ type (DATA){
@ -74,12 +78,18 @@ 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 : 918.5120625; area : 1032.3999375;
leakage_power () {
when : "CSb";
value : 0;
}
cell_leakage_power : 0;
bus(DATA){ bus(DATA){
bus_type : DATA; bus_type : DATA;
direction : inout; direction : inout;
max_capacitance : 1.6728; max_capacitance : 1.6728;
min_capacitance : 0.052275;
three_state : "!OEb & !clk"; three_state : "!OEb & !clk";
memory_write(){ memory_write(){
address : ADDR; address : ADDR;
@ -89,15 +99,6 @@ cell (sram_2_16_1_freepdk45){
address : ADDR; address : ADDR;
} }
pin(DATA[1:0]){ pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk"; related_pin : "clk";
@ -126,15 +127,6 @@ cell (sram_2_16_1_freepdk45){
"0.001, 0.001, 0.001"); "0.001, 0.001, 0.001");
} }
} }
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_sense : non_unate; timing_sense : non_unate;
related_pin : "clk"; related_pin : "clk";
@ -168,7 +160,6 @@ cell (sram_2_16_1_freepdk45){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
max_transition : 0.04; max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[3:0]){ pin(ADDR[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
@ -304,6 +295,33 @@ cell (sram_2_16_1_freepdk45){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("0.0");
}
fall_power(scalar){
values("0.0");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("0.0");
}
fall_power(scalar){
values("0.0");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk; related_pin : clk;

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_freepdk45_lib){ library (sram_2_16_1_freepdk45_TT_1p0V_25C_lib){
delay_model : "table_lookup"; delay_model : "table_lookup";
time_unit : "1ns" ; time_unit : "1ns" ;
voltage_unit : "1v" ; voltage_unit : "1v" ;
@ -7,9 +7,10 @@ library (sram_2_16_1_freepdk45_lib){
capacitive_load_unit(1 ,fF) ; capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ; leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ; pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){ operating_conditions(OC){
process : 1.0 ;
voltage : 1.0 ; voltage : 1.0 ;
temperature : 25.000 ; temperature : 25;
} }
input_threshold_pct_fall : 50.0 ; input_threshold_pct_fall : 50.0 ;
@ -21,6 +22,9 @@ library (sram_2_16_1_freepdk45_lib){
slew_lower_threshold_pct_rise : 10.0 ; slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ; slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 1.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ; default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ; default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ; default_input_pin_cap : 1.0 ;
@ -45,7 +49,7 @@ library (sram_2_16_1_freepdk45_lib){
index_2("0.00125, 0.005, 0.04"); index_2("0.00125, 0.005, 0.04");
} }
default_operating_conditions : TT; default_operating_conditions : OC;
type (DATA){ type (DATA){
@ -74,12 +78,18 @@ 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 : 918.5120625; area : 1032.3999375;
leakage_power () {
when : "CSb";
value : 0.00088149731;
}
cell_leakage_power : 0;
bus(DATA){ bus(DATA){
bus_type : DATA; bus_type : DATA;
direction : inout; direction : inout;
max_capacitance : 1.6728; max_capacitance : 1.6728;
min_capacitance : 0.052275;
three_state : "!OEb & !clk"; three_state : "!OEb & !clk";
memory_write(){ memory_write(){
address : ADDR; address : ADDR;
@ -89,15 +99,6 @@ cell (sram_2_16_1_freepdk45){
address : ADDR; address : ADDR;
} }
pin(DATA[1:0]){ pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0.0370166");
}
fall_power(scalar){
values("0.026622831");
}
}
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk"; related_pin : "clk";
@ -126,15 +127,6 @@ cell (sram_2_16_1_freepdk45){
"-0.004, -0.004, -0.016"); "-0.004, -0.004, -0.016");
} }
} }
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0.034203045");
}
fall_power(scalar){
values("0.039377859");
}
}
timing(){ timing(){
timing_sense : non_unate; timing_sense : non_unate;
related_pin : "clk"; related_pin : "clk";
@ -145,9 +137,9 @@ cell (sram_2_16_1_freepdk45){
"0.06, 0.061, 0.067"); "0.06, 0.061, 0.067");
} }
cell_fall(CELL_TABLE) { cell_fall(CELL_TABLE) {
values("0.438, 0.439, 0.449",\ values("0.425, 0.426, 0.436",\
"0.439, 0.44, 0.449",\ "0.426, 0.427, 0.436",\
"0.445, 0.446, 0.455"); "0.432, 0.433, 0.442");
} }
rise_transition(CELL_TABLE) { rise_transition(CELL_TABLE) {
values("0.013, 0.014, 0.026",\ values("0.013, 0.014, 0.026",\
@ -168,7 +160,6 @@ cell (sram_2_16_1_freepdk45){
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
max_transition : 0.04; max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[3:0]){ pin(ADDR[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
@ -304,24 +295,51 @@ cell (sram_2_16_1_freepdk45){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 0.2091; capacitance : 0.2091;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("0.0158174252672");
}
fall_power(scalar){
values("0.0158174252672");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("0.0181396362394");
}
fall_power(scalar){
values("0.0181396362394");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk; related_pin : clk;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.449"); values("0.4295");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.449"); values("0.4295");
} }
} }
timing(){ timing(){
timing_type :"minimum_period"; timing_type :"minimum_period";
related_pin : clk; related_pin : clk;
rise_constraint(scalar) { rise_constraint(scalar) {
values("0.898"); values("0.859");
} }
fall_constraint(scalar) { fall_constraint(scalar) {
values("0.898"); values("0.859");
} }
} }
} }

View File

@ -7,11 +7,11 @@ UNITS
END UNITS END UNITS
SITE MacroSite SITE MacroSite
CLASS Core ; CLASS Core ;
SIZE 277800.0 by 440700.0 ; SIZE 305400.0 by 440700.0 ;
END MacroSite END MacroSite
MACRO sram_2_16_1_scn3me_subm MACRO sram_2_16_1_scn3me_subm
CLASS BLOCK ; CLASS BLOCK ;
SIZE 277800.0 BY 440700.0 ; SIZE 305400.0 BY 440700.0 ;
SYMMETRY X Y R90 ; SYMMETRY X Y R90 ;
SITE MacroSite ; SITE MacroSite ;
PIN DATA[0] PIN DATA[0]
@ -4105,12 +4105,15 @@ MACRO sram_2_16_1_scn3me_subm
RECT 16050.0 358350.0 15150.0 359250.0 ; RECT 16050.0 358350.0 15150.0 359250.0 ;
RECT 8850.0 353400.0 7950.0 363000.0 ; RECT 8850.0 353400.0 7950.0 363000.0 ;
RECT 22650.0 353400.0 21750.0 363000.0 ; RECT 22650.0 353400.0 21750.0 363000.0 ;
RECT 22650.0 499050.0 21750.0 430200.0 ; RECT 22650.0 479850.0 21750.0 457800.0 ;
RECT 21750.0 397050.0 17400.0 397950.0 ; RECT 21750.0 397050.0 17400.0 397950.0 ;
RECT 21750.0 420450.0 17400.0 421350.0 ; RECT 21750.0 420450.0 17400.0 421350.0 ;
RECT 21750.0 424650.0 17400.0 425550.0 ;
RECT 21750.0 448050.0 17400.0 448950.0 ;
RECT 22650.0 371550.0 16800.0 372450.0 ; RECT 22650.0 371550.0 16800.0 372450.0 ;
RECT 16800.0 371550.0 6600.0 372450.0 ; RECT 16800.0 371550.0 6600.0 372450.0 ;
RECT 4500.0 408600.0 16800.0 409500.0 ; RECT 4500.0 408600.0 16800.0 409500.0 ;
RECT 4500.0 436200.0 16800.0 437100.0 ;
RECT 4500.0 381000.0 16800.0 381900.0 ; RECT 4500.0 381000.0 16800.0 381900.0 ;
RECT 29250.0 397800.0 28350.0 410400.0 ; RECT 29250.0 397800.0 28350.0 410400.0 ;
RECT 29250.0 392850.0 28350.0 393750.0 ; RECT 29250.0 392850.0 28350.0 393750.0 ;
@ -4150,11 +4153,11 @@ MACRO sram_2_16_1_scn3me_subm
RECT 32550.0 398400.0 33750.0 399600.0 ; RECT 32550.0 398400.0 33750.0 399600.0 ;
RECT 32550.0 398400.0 33750.0 399600.0 ; RECT 32550.0 398400.0 33750.0 399600.0 ;
RECT 32550.0 396000.0 33750.0 397200.0 ; RECT 32550.0 396000.0 33750.0 397200.0 ;
RECT 21750.0 498150.0 22650.0 499050.0 ; RECT 21750.0 478950.0 22650.0 479850.0 ;
RECT 49350.0 498150.0 50250.0 499050.0 ; RECT 49350.0 478950.0 50250.0 479850.0 ;
RECT 21750.0 496800.0 22650.0 498600.0 ; RECT 21750.0 477600.0 22650.0 479400.0 ;
RECT 22200.0 498150.0 49800.0 499050.0 ; RECT 22200.0 478950.0 49800.0 479850.0 ;
RECT 49350.0 496800.0 50250.0 498600.0 ; RECT 49350.0 477600.0 50250.0 479400.0 ;
RECT 37950.0 417000.0 36000.0 418200.0 ; RECT 37950.0 417000.0 36000.0 418200.0 ;
RECT 49800.0 417000.0 47850.0 418200.0 ; RECT 49800.0 417000.0 47850.0 418200.0 ;
RECT 48450.0 412200.0 50250.0 413400.0 ; RECT 48450.0 412200.0 50250.0 413400.0 ;
@ -4301,90 +4304,6 @@ MACRO sram_2_16_1_scn3me_subm
RECT 36450.0 468000.0 35550.0 477600.0 ; RECT 36450.0 468000.0 35550.0 477600.0 ;
RECT 50250.0 468000.0 49350.0 477600.0 ; RECT 50250.0 468000.0 49350.0 477600.0 ;
RECT 42600.0 470400.0 43800.0 471600.0 ; RECT 42600.0 470400.0 43800.0 471600.0 ;
RECT 37950.0 484200.0 36000.0 485400.0 ;
RECT 49800.0 484200.0 47850.0 485400.0 ;
RECT 48450.0 479400.0 50250.0 480600.0 ;
RECT 39150.0 479400.0 35550.0 480600.0 ;
RECT 48450.0 482100.0 39150.0 483000.0 ;
RECT 39150.0 479400.0 37950.0 480600.0 ;
RECT 39150.0 481800.0 37950.0 483000.0 ;
RECT 39150.0 481800.0 37950.0 483000.0 ;
RECT 39150.0 479400.0 37950.0 480600.0 ;
RECT 48450.0 479400.0 47250.0 480600.0 ;
RECT 48450.0 481800.0 47250.0 483000.0 ;
RECT 48450.0 481800.0 47250.0 483000.0 ;
RECT 48450.0 479400.0 47250.0 480600.0 ;
RECT 38550.0 484200.0 37350.0 485400.0 ;
RECT 48450.0 484200.0 47250.0 485400.0 ;
RECT 43800.0 480000.0 42600.0 481200.0 ;
RECT 43800.0 480000.0 42600.0 481200.0 ;
RECT 43650.0 482550.0 42750.0 483450.0 ;
RECT 36450.0 477600.0 35550.0 487200.0 ;
RECT 50250.0 477600.0 49350.0 487200.0 ;
RECT 42600.0 480000.0 43800.0 481200.0 ;
RECT 37950.0 493800.0 36000.0 495000.0 ;
RECT 49800.0 493800.0 47850.0 495000.0 ;
RECT 48450.0 489000.0 50250.0 490200.0 ;
RECT 39150.0 489000.0 35550.0 490200.0 ;
RECT 48450.0 491700.0 39150.0 492600.0 ;
RECT 39150.0 489000.0 37950.0 490200.0 ;
RECT 39150.0 491400.0 37950.0 492600.0 ;
RECT 39150.0 491400.0 37950.0 492600.0 ;
RECT 39150.0 489000.0 37950.0 490200.0 ;
RECT 48450.0 489000.0 47250.0 490200.0 ;
RECT 48450.0 491400.0 47250.0 492600.0 ;
RECT 48450.0 491400.0 47250.0 492600.0 ;
RECT 48450.0 489000.0 47250.0 490200.0 ;
RECT 38550.0 493800.0 37350.0 495000.0 ;
RECT 48450.0 493800.0 47250.0 495000.0 ;
RECT 43800.0 489600.0 42600.0 490800.0 ;
RECT 43800.0 489600.0 42600.0 490800.0 ;
RECT 43650.0 492150.0 42750.0 493050.0 ;
RECT 36450.0 487200.0 35550.0 496800.0 ;
RECT 50250.0 487200.0 49350.0 496800.0 ;
RECT 42600.0 489600.0 43800.0 490800.0 ;
RECT 34050.0 480600.0 36000.0 479400.0 ;
RECT 22200.0 480600.0 24150.0 479400.0 ;
RECT 23550.0 485400.0 21750.0 484200.0 ;
RECT 32850.0 485400.0 36450.0 484200.0 ;
RECT 23550.0 482700.0 32850.0 481800.0 ;
RECT 32850.0 485400.0 34050.0 484200.0 ;
RECT 32850.0 483000.0 34050.0 481800.0 ;
RECT 32850.0 483000.0 34050.0 481800.0 ;
RECT 32850.0 485400.0 34050.0 484200.0 ;
RECT 23550.0 485400.0 24750.0 484200.0 ;
RECT 23550.0 483000.0 24750.0 481800.0 ;
RECT 23550.0 483000.0 24750.0 481800.0 ;
RECT 23550.0 485400.0 24750.0 484200.0 ;
RECT 33450.0 480600.0 34650.0 479400.0 ;
RECT 23550.0 480600.0 24750.0 479400.0 ;
RECT 28200.0 484800.0 29400.0 483600.0 ;
RECT 28200.0 484800.0 29400.0 483600.0 ;
RECT 28350.0 482250.0 29250.0 481350.0 ;
RECT 35550.0 487200.0 36450.0 477600.0 ;
RECT 21750.0 487200.0 22650.0 477600.0 ;
RECT 28200.0 483600.0 29400.0 484800.0 ;
RECT 34050.0 471000.0 36000.0 469800.0 ;
RECT 22200.0 471000.0 24150.0 469800.0 ;
RECT 23550.0 475800.0 21750.0 474600.0 ;
RECT 32850.0 475800.0 36450.0 474600.0 ;
RECT 23550.0 473100.0 32850.0 472200.0 ;
RECT 32850.0 475800.0 34050.0 474600.0 ;
RECT 32850.0 473400.0 34050.0 472200.0 ;
RECT 32850.0 473400.0 34050.0 472200.0 ;
RECT 32850.0 475800.0 34050.0 474600.0 ;
RECT 23550.0 475800.0 24750.0 474600.0 ;
RECT 23550.0 473400.0 24750.0 472200.0 ;
RECT 23550.0 473400.0 24750.0 472200.0 ;
RECT 23550.0 475800.0 24750.0 474600.0 ;
RECT 33450.0 471000.0 34650.0 469800.0 ;
RECT 23550.0 471000.0 24750.0 469800.0 ;
RECT 28200.0 475200.0 29400.0 474000.0 ;
RECT 28200.0 475200.0 29400.0 474000.0 ;
RECT 28350.0 472650.0 29250.0 471750.0 ;
RECT 35550.0 477600.0 36450.0 468000.0 ;
RECT 21750.0 477600.0 22650.0 468000.0 ;
RECT 28200.0 474000.0 29400.0 475200.0 ;
RECT 34050.0 461400.0 36000.0 460200.0 ; RECT 34050.0 461400.0 36000.0 460200.0 ;
RECT 22200.0 461400.0 24150.0 460200.0 ; RECT 22200.0 461400.0 24150.0 460200.0 ;
RECT 23550.0 466200.0 21750.0 465000.0 ; RECT 23550.0 466200.0 21750.0 465000.0 ;
@ -4512,22 +4431,29 @@ MACRO sram_2_16_1_scn3me_subm
RECT 21750.0 420000.0 22650.0 410400.0 ; RECT 21750.0 420000.0 22650.0 410400.0 ;
RECT 28200.0 416400.0 29400.0 417600.0 ; RECT 28200.0 416400.0 29400.0 417600.0 ;
RECT 42600.0 415200.0 43800.0 416400.0 ; RECT 42600.0 415200.0 43800.0 416400.0 ;
RECT 42600.0 453600.0 43800.0 454800.0 ; RECT 42600.0 444000.0 43800.0 445200.0 ;
RECT 42600.0 492000.0 43800.0 493200.0 ; RECT 42600.0 472800.0 43800.0 474000.0 ;
RECT 28200.0 452400.0 29400.0 453600.0 ; RECT 28200.0 442800.0 29400.0 444000.0 ;
RECT 42600.0 412800.0 43800.0 414000.0 ; RECT 42600.0 412800.0 43800.0 414000.0 ;
RECT 28350.0 410400.0 29250.0 414150.0 ; RECT 28350.0 410400.0 29250.0 414150.0 ;
RECT 35550.0 410400.0 36450.0 496800.0 ; RECT 35550.0 410400.0 36450.0 477600.0 ;
RECT 21750.0 410400.0 22650.0 496800.0 ; RECT 21750.0 410400.0 22650.0 477600.0 ;
RECT 49350.0 410400.0 50250.0 496800.0 ; RECT 49350.0 410400.0 50250.0 477600.0 ;
RECT 16800.0 395400.0 6600.0 381600.0 ; RECT 16800.0 395400.0 6600.0 381600.0 ;
RECT 16800.0 395400.0 6600.0 409200.0 ; RECT 16800.0 395400.0 6600.0 409200.0 ;
RECT 16800.0 423000.0 6600.0 409200.0 ; RECT 16800.0 423000.0 6600.0 409200.0 ;
RECT 16800.0 423000.0 6600.0 436800.0 ;
RECT 16800.0 450600.0 6600.0 436800.0 ;
RECT 17400.0 396900.0 6000.0 398100.0 ; RECT 17400.0 396900.0 6000.0 398100.0 ;
RECT 17400.0 420300.0 6000.0 421500.0 ; RECT 17400.0 420300.0 6000.0 421500.0 ;
RECT 17400.0 424500.0 6000.0 425700.0 ;
RECT 17400.0 447900.0 6000.0 449100.0 ;
RECT 17400.0 408600.0 6000.0 409500.0 ; RECT 17400.0 408600.0 6000.0 409500.0 ;
RECT 17400.0 436200.0 6000.0 437100.0 ;
RECT 22350.0 396900.0 21150.0 398100.0 ; RECT 22350.0 396900.0 21150.0 398100.0 ;
RECT 22350.0 420300.0 21150.0 421500.0 ; RECT 22350.0 420300.0 21150.0 421500.0 ;
RECT 22350.0 424500.0 21150.0 425700.0 ;
RECT 22350.0 447900.0 21150.0 449100.0 ;
RECT 22200.0 410400.0 21000.0 411600.0 ; RECT 22200.0 410400.0 21000.0 411600.0 ;
RECT 22800.0 370800.0 21600.0 372000.0 ; RECT 22800.0 370800.0 21600.0 372000.0 ;
RECT 16200.0 371400.0 17400.0 372600.0 ; RECT 16200.0 371400.0 17400.0 372600.0 ;
@ -4538,7 +4464,7 @@ MACRO sram_2_16_1_scn3me_subm
RECT 12600.0 375600.0 13800.0 376800.0 ; RECT 12600.0 375600.0 13800.0 376800.0 ;
RECT 43800.0 362400.0 42900.0 412800.0 ; RECT 43800.0 362400.0 42900.0 412800.0 ;
RECT 29250.0 362400.0 28350.0 375750.0 ; RECT 29250.0 362400.0 28350.0 375750.0 ;
RECT 4500.0 362400.0 3600.0 425250.0 ; RECT 4500.0 362400.0 3600.0 452850.0 ;
RECT 36450.0 362400.0 35550.0 410400.0 ; RECT 36450.0 362400.0 35550.0 410400.0 ;
RECT 22650.0 362400.0 21750.0 372000.0 ; RECT 22650.0 362400.0 21750.0 372000.0 ;
RECT 50250.0 362400.0 49350.0 410400.0 ; RECT 50250.0 362400.0 49350.0 410400.0 ;
@ -5348,29 +5274,25 @@ MACRO sram_2_16_1_scn3me_subm
RECT 10800.0 288450.0 9600.0 287250.0 ; RECT 10800.0 288450.0 9600.0 287250.0 ;
RECT 31200.0 263100.0 30000.0 261900.0 ; RECT 31200.0 263100.0 30000.0 261900.0 ;
RECT 31200.0 288450.0 30000.0 287250.0 ; RECT 31200.0 288450.0 30000.0 287250.0 ;
RECT 22650.0 372000.0 21750.0 430200.0 ; RECT 22650.0 372000.0 21750.0 457800.0 ;
RECT 17250.0 372000.0 16350.0 425400.0 ; RECT 17250.0 372000.0 16350.0 453000.0 ;
RECT 7050.0 372000.0 6150.0 425400.0 ; RECT 7050.0 372000.0 6150.0 453000.0 ;
RECT 20400.0 376200.0 19500.0 384300.0 ; RECT 20400.0 376200.0 19500.0 384300.0 ;
RECT 13650.0 376200.0 12750.0 381000.0 ; RECT 13650.0 376200.0 12750.0 381000.0 ;
RECT 42750.0 415800.0 43650.0 423000.0 ; RECT 42750.0 415800.0 43650.0 423000.0 ;
RECT 42750.0 423000.0 43650.0 432600.0 ; RECT 42750.0 423000.0 43650.0 432600.0 ;
RECT 42750.0 432600.0 43650.0 442200.0 ; RECT 42750.0 432600.0 43650.0 442200.0 ;
RECT 42750.0 442200.0 43650.0 451800.0 ; RECT 42750.0 444600.0 43650.0 451800.0 ;
RECT 42750.0 454200.0 43650.0 461400.0 ; RECT 42750.0 451800.0 43650.0 461400.0 ;
RECT 42750.0 461400.0 43650.0 471000.0 ; RECT 42750.0 461400.0 43650.0 471000.0 ;
RECT 42750.0 471000.0 43650.0 480600.0 ; RECT 35550.0 472950.0 36450.0 473850.0 ;
RECT 42750.0 480600.0 43650.0 490200.0 ; RECT 35550.0 464550.0 36450.0 465450.0 ;
RECT 35550.0 492150.0 36450.0 493050.0 ; RECT 36000.0 472950.0 43200.0 473850.0 ;
RECT 35550.0 483750.0 36450.0 484650.0 ; RECT 35550.0 465000.0 36450.0 473400.0 ;
RECT 36000.0 492150.0 43200.0 493050.0 ; RECT 28800.0 464550.0 36000.0 465450.0 ;
RECT 35550.0 484200.0 36450.0 492600.0 ;
RECT 28800.0 483750.0 36000.0 484650.0 ;
RECT 28350.0 474600.0 29250.0 484200.0 ;
RECT 28350.0 465000.0 29250.0 474600.0 ;
RECT 28350.0 455400.0 29250.0 465000.0 ; RECT 28350.0 455400.0 29250.0 465000.0 ;
RECT 28350.0 445800.0 29250.0 453000.0 ; RECT 28350.0 445800.0 29250.0 455400.0 ;
RECT 28350.0 436200.0 29250.0 445800.0 ; RECT 28350.0 436200.0 29250.0 443400.0 ;
RECT 28350.0 426600.0 29250.0 436200.0 ; RECT 28350.0 426600.0 29250.0 436200.0 ;
RECT 28350.0 417000.0 29250.0 426600.0 ; RECT 28350.0 417000.0 29250.0 426600.0 ;
RECT 42600.0 422400.0 43800.0 423600.0 ; RECT 42600.0 422400.0 43800.0 423600.0 ;
@ -5379,10 +5301,6 @@ MACRO sram_2_16_1_scn3me_subm
RECT 42600.0 451200.0 43800.0 452400.0 ; RECT 42600.0 451200.0 43800.0 452400.0 ;
RECT 42600.0 460800.0 43800.0 462000.0 ; RECT 42600.0 460800.0 43800.0 462000.0 ;
RECT 42600.0 470400.0 43800.0 471600.0 ; RECT 42600.0 470400.0 43800.0 471600.0 ;
RECT 42600.0 480000.0 43800.0 481200.0 ;
RECT 42600.0 489600.0 43800.0 490800.0 ;
RECT 28200.0 483600.0 29400.0 484800.0 ;
RECT 28200.0 474000.0 29400.0 475200.0 ;
RECT 28200.0 464400.0 29400.0 465600.0 ; RECT 28200.0 464400.0 29400.0 465600.0 ;
RECT 28200.0 454800.0 29400.0 456000.0 ; RECT 28200.0 454800.0 29400.0 456000.0 ;
RECT 28200.0 445200.0 29400.0 446400.0 ; RECT 28200.0 445200.0 29400.0 446400.0 ;
@ -5390,18 +5308,22 @@ MACRO sram_2_16_1_scn3me_subm
RECT 28200.0 426000.0 29400.0 427200.0 ; RECT 28200.0 426000.0 29400.0 427200.0 ;
RECT 28200.0 416400.0 29400.0 417600.0 ; RECT 28200.0 416400.0 29400.0 417600.0 ;
RECT 42600.0 415200.0 43800.0 416400.0 ; RECT 42600.0 415200.0 43800.0 416400.0 ;
RECT 42600.0 453600.0 43800.0 454800.0 ; RECT 42600.0 444000.0 43800.0 445200.0 ;
RECT 42600.0 492000.0 43800.0 493200.0 ; RECT 42600.0 472800.0 43800.0 474000.0 ;
RECT 28200.0 452400.0 29400.0 453600.0 ; RECT 28200.0 442800.0 29400.0 444000.0 ;
RECT 16800.0 395400.0 6600.0 381600.0 ; RECT 16800.0 395400.0 6600.0 381600.0 ;
RECT 16800.0 395400.0 6600.0 409200.0 ; RECT 16800.0 395400.0 6600.0 409200.0 ;
RECT 16800.0 423000.0 6600.0 409200.0 ; RECT 16800.0 423000.0 6600.0 409200.0 ;
RECT 13800.0 396000.0 12600.0 426600.0 ; RECT 16800.0 423000.0 6600.0 436800.0 ;
RECT 10800.0 394800.0 9600.0 425400.0 ; RECT 16800.0 450600.0 6600.0 436800.0 ;
RECT 17400.0 394800.0 16200.0 425400.0 ; RECT 13800.0 396000.0 12600.0 454200.0 ;
RECT 7200.0 394800.0 6000.0 425400.0 ; RECT 10800.0 394800.0 9600.0 453000.0 ;
RECT 17400.0 394800.0 16200.0 453000.0 ;
RECT 7200.0 394800.0 6000.0 453000.0 ;
RECT 22350.0 396900.0 21150.0 398100.0 ; RECT 22350.0 396900.0 21150.0 398100.0 ;
RECT 22350.0 420300.0 21150.0 421500.0 ; RECT 22350.0 420300.0 21150.0 421500.0 ;
RECT 22350.0 424500.0 21150.0 425700.0 ;
RECT 22350.0 447900.0 21150.0 449100.0 ;
RECT 22200.0 410400.0 21000.0 411600.0 ; RECT 22200.0 410400.0 21000.0 411600.0 ;
RECT 22800.0 370800.0 21600.0 372000.0 ; RECT 22800.0 370800.0 21600.0 372000.0 ;
RECT 16200.0 371400.0 17400.0 372600.0 ; RECT 16200.0 371400.0 17400.0 372600.0 ;

View File

@ -0,0 +1,347 @@
library (sram_2_16_1_scn3me_subm_TT_5p0V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
current_unit : "1mA" ;
resistance_unit : "1kohm" ;
capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(OC){
process : 1.0 ;
voltage : 5.0 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
output_threshold_pct_fall : 50.0 ;
input_threshold_pct_rise : 50.0 ;
output_threshold_pct_rise : 50.0 ;
slew_lower_threshold_pct_fall : 10.0 ;
slew_upper_threshold_pct_fall : 90.0 ;
slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ;
default_inout_pin_cap : 1.0 ;
default_output_pin_cap : 0.0 ;
default_max_transition : 0.5 ;
default_fanout_load : 1.0 ;
default_max_fanout : 4.0 ;
default_connection_class : universal ;
lu_table_template(CELL_TABLE){
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.0125, 0.05, 0.4");
index_2("0.0125, 0.05, 0.4");
}
default_operating_conditions : OC;
type (DATA){
base_type : array;
data_type : bit;
bit_width : 2;
bit_from : 0;
bit_to : 1;
}
type (ADDR){
base_type : array;
data_type : bit;
bit_width : 4;
bit_from : 0;
bit_to : 3;
}
cell (sram_2_16_1_scn3me_subm){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 134589.78;
leakage_power () {
when : "CSb";
value : 0.0011563287;
}
cell_leakage_power : 0;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
clocked_on : clk;
}
memory_read(){
address : ADDR;
}
pin(DATA[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
timing(){
timing_sense : non_unate;
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.473, 0.519, 0.888",\
"0.476, 0.522, 0.891",\
"0.516, 0.56, 0.928");
}
cell_fall(CELL_TABLE) {
values("0.582, 0.655, 1.256",\
"0.585, 0.658, 1.259",\
"0.625, 0.697, 1.295");
}
rise_transition(CELL_TABLE) {
values("0.154, 0.233, 1.086",\
"0.155, 0.234, 1.086",\
"0.158, 0.237, 1.086");
}
fall_transition(CELL_TABLE) {
values("0.278, 0.359, 1.499",\
"0.278, 0.361, 1.499",\
"0.28, 0.367, 1.5");
}
}
}
}
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
}
pin(CSb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(OEb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(WEb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(clk){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("4.91866674167");
}
fall_power(scalar){
values("4.91866674167");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("5.72315586111");
}
fall_power(scalar){
values("5.72315586111");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("1.875");
}
fall_constraint(scalar) {
values("1.875");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("3.75");
}
fall_constraint(scalar) {
values("3.75");
}
}
}
}
}

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_scn3me_subm_lib){ library (sram_2_16_1_scn3me_subm_TT_5p0V_25C_lib){
delay_model : "table_lookup"; delay_model : "table_lookup";
time_unit : "1ns" ; time_unit : "1ns" ;
voltage_unit : "1v" ; voltage_unit : "1v" ;
@ -7,9 +7,10 @@ library (sram_2_16_1_scn3me_subm_lib){
capacitive_load_unit(1 ,fF) ; capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ; leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ; pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){ operating_conditions(OC){
process : 1.0 ;
voltage : 5.0 ; voltage : 5.0 ;
temperature : 25.000 ; temperature : 25;
} }
input_threshold_pct_fall : 50.0 ; input_threshold_pct_fall : 50.0 ;
@ -21,6 +22,9 @@ library (sram_2_16_1_scn3me_subm_lib){
slew_lower_threshold_pct_rise : 10.0 ; slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ; slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ; default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ; default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ; default_input_pin_cap : 1.0 ;
@ -45,7 +49,7 @@ library (sram_2_16_1_scn3me_subm_lib){
index_2("0.0125, 0.05, 0.4"); index_2("0.0125, 0.05, 0.4");
} }
default_operating_conditions : TT; default_operating_conditions : OC;
type (DATA){ type (DATA){
@ -74,12 +78,18 @@ cell (sram_2_16_1_scn3me_subm){
dont_use : true; dont_use : true;
map_only : true; map_only : true;
dont_touch : true; dont_touch : true;
area : 122426.46; area : 134589.78;
leakage_power () {
when : "CSb";
value : 0;
}
cell_leakage_power : 0;
bus(DATA){ bus(DATA){
bus_type : DATA; bus_type : DATA;
direction : inout; direction : inout;
max_capacitance : 78.5936; max_capacitance : 78.5936;
min_capacitance : 2.45605;
three_state : "!OEb & !clk"; three_state : "!OEb & !clk";
memory_write(){ memory_write(){
address : ADDR; address : ADDR;
@ -89,15 +99,6 @@ cell (sram_2_16_1_scn3me_subm){
address : ADDR; address : ADDR;
} }
pin(DATA[1:0]){ pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
related_pin : "clk"; related_pin : "clk";
@ -126,15 +127,6 @@ cell (sram_2_16_1_scn3me_subm){
"0.001, 0.001, 0.001"); "0.001, 0.001, 0.001");
} }
} }
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_sense : non_unate; timing_sense : non_unate;
related_pin : "clk"; related_pin : "clk";
@ -168,7 +160,6 @@ cell (sram_2_16_1_scn3me_subm){
direction : input; direction : input;
capacitance : 9.8242; capacitance : 9.8242;
max_transition : 0.4; max_transition : 0.4;
fanout_load : 1.000000;
pin(ADDR[3:0]){ pin(ADDR[3:0]){
timing(){ timing(){
timing_type : setup_rising; timing_type : setup_rising;
@ -304,6 +295,33 @@ cell (sram_2_16_1_scn3me_subm){
clock : true; clock : true;
direction : input; direction : input;
capacitance : 9.8242; capacitance : 9.8242;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("0.0");
}
fall_power(scalar){
values("0.0");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("0.0");
}
fall_power(scalar){
values("0.0");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){ timing(){
timing_type :"min_pulse_width"; timing_type :"min_pulse_width";
related_pin : clk; related_pin : clk;

View File

@ -0,0 +1,347 @@
library (sram_2_16_1_scn3me_subm_TT_5p0V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
current_unit : "1mA" ;
resistance_unit : "1kohm" ;
capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(OC){
process : 1.0 ;
voltage : 5.0 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
output_threshold_pct_fall : 50.0 ;
input_threshold_pct_rise : 50.0 ;
output_threshold_pct_rise : 50.0 ;
slew_lower_threshold_pct_fall : 10.0 ;
slew_upper_threshold_pct_fall : 90.0 ;
slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ;
default_inout_pin_cap : 1.0 ;
default_output_pin_cap : 0.0 ;
default_max_transition : 0.5 ;
default_fanout_load : 1.0 ;
default_max_fanout : 4.0 ;
default_connection_class : universal ;
lu_table_template(CELL_TABLE){
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.0125, 0.05, 0.4");
index_2("0.0125, 0.05, 0.4");
}
default_operating_conditions : OC;
type (DATA){
base_type : array;
data_type : bit;
bit_width : 2;
bit_from : 0;
bit_to : 1;
}
type (ADDR){
base_type : array;
data_type : bit;
bit_width : 4;
bit_from : 0;
bit_to : 3;
}
cell (sram_2_16_1_scn3me_subm){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 134589.78;
leakage_power () {
when : "CSb";
value : 0.0011563287;
}
cell_leakage_power : 0;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
clocked_on : clk;
}
memory_read(){
address : ADDR;
}
pin(DATA[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
timing(){
timing_sense : non_unate;
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.458, 0.503, 0.87",\
"0.461, 0.505, 0.873",\
"0.5, 0.544, 0.911");
}
cell_fall(CELL_TABLE) {
values("0.573, 0.645, 1.246",\
"0.576, 0.648, 1.249",\
"0.616, 0.687, 1.286");
}
rise_transition(CELL_TABLE) {
values("0.153, 0.232, 1.084",\
"0.153, 0.233, 1.084",\
"0.156, 0.236, 1.084");
}
fall_transition(CELL_TABLE) {
values("0.277, 0.36, 1.499",\
"0.277, 0.362, 1.499",\
"0.278, 0.37, 1.5");
}
}
}
}
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
}
pin(CSb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(OEb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(WEb){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149",\
"0.076, 0.076, 0.149");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027",\
"0.039, 0.039, 0.027");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009",\
"-0.004, -0.004, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
pin(clk){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb & clk & !WEb";
rise_power(scalar){
values("4.39065104738");
}
fall_power(scalar){
values("4.39065104738");
}
}
internal_power(){
when : "!CSb & !clk & WEb";
rise_power(scalar){
values("5.00353945572");
}
fall_power(scalar){
values("5.00353945572");
}
}
internal_power(){
when : "CSb";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("1.875");
}
fall_constraint(scalar) {
values("1.875");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("3.75");
}
fall_constraint(scalar) {
values("3.75");
}
}
}
}
}

View File

@ -103,7 +103,7 @@ def run_drc(cell_name, gds_name):
OPTS.openram_temp, OPTS.openram_temp,
errfile, errfile,
outfile) outfile)
debug.info(1, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd) os.chdir(cwd)
@ -191,7 +191,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
OPTS.openram_temp, OPTS.openram_temp,
errfile, errfile,
outfile) outfile)
debug.info(1, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd) os.chdir(cwd)

View File

@ -152,7 +152,7 @@ def run_drc(cell_name, gds_name, extract=False):
cmd = "{0}run_drc.sh 2> {1} 1> {2}".format(OPTS.openram_temp, cmd = "{0}run_drc.sh 2> {1} 1> {2}".format(OPTS.openram_temp,
errfile, errfile,
outfile) outfile)
debug.info(1, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd) os.chdir(cwd)
@ -204,7 +204,7 @@ def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
cmd = "{0}run_lvs.sh lvs 2> {1} 1> {2}".format(OPTS.openram_temp, cmd = "{0}run_lvs.sh lvs 2> {1} 1> {2}".format(OPTS.openram_temp,
errfile, errfile,
outfile) outfile)
debug.info(1, cmd) debug.info(2, cmd)
os.system(cmd) os.system(cmd)
os.chdir(cwd) os.chdir(cwd)

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

View File

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 31 KiB

View File

@ -1,409 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="744.09448819"
height="1052.3622047"
id="svg2"
sodipodi:version="0.32"
inkscape:version="0.46"
sodipodi:docname="decoder_to _array.svg"
inkscape:output_extension="org.inkscape.output.svg.inkscape">
<defs
id="defs4">
<marker
inkscape:stockid="Arrow1Lend"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lend"
style="overflow:visible;">
<path
id="path3229"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none;"
transform="scale(0.8) rotate(180) translate(12.5,0)" />
</marker>
<marker
inkscape:stockid="Arrow1Lstart"
orient="auto"
refY="0.0"
refX="0.0"
id="Arrow1Lstart"
style="overflow:visible">
<path
id="path3226"
d="M 0.0,0.0 L 5.0,-5.0 L -12.5,0.0 L 5.0,5.0 L 0.0,0.0 z "
style="fill-rule:evenodd;stroke:#000000;stroke-width:1.0pt;marker-start:none"
transform="scale(0.8) translate(12.5,0)" />
</marker>
<linearGradient
inkscape:collect="always"
id="linearGradient2461">
<stop
style="stop-color:#b3b3b3;stop-opacity:1;"
offset="0"
id="stop2463" />
<stop
style="stop-color:#b3b3b3;stop-opacity:0;"
offset="1"
id="stop2465" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2451">
<stop
style="stop-color:#b3b3b3;stop-opacity:1;"
offset="0"
id="stop2453" />
<stop
style="stop-color:#b3b3b3;stop-opacity:0;"
offset="1"
id="stop2455" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient2445">
<stop
style="stop-color:#b3b3b3;stop-opacity:1;"
offset="0"
id="stop2447" />
<stop
style="stop-color:#b3b3b3;stop-opacity:0;"
offset="1"
id="stop2449" />
</linearGradient>
<inkscape:perspective
sodipodi:type="inkscape:persp3d"
inkscape:vp_x="0 : 526.18109 : 1"
inkscape:vp_y="0 : 1000 : 0"
inkscape:vp_z="744.09448 : 526.18109 : 1"
inkscape:persp3d-origin="372.04724 : 350.78739 : 1"
id="perspective10" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2445"
id="linearGradient2443"
x1="370.17203"
y1="408.19574"
x2="372.40872"
y2="517.79352"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7710419,0,0,0.8337292,8.1937292,7.8098171)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2451"
id="linearGradient2457"
x1="371.29037"
y1="409.31409"
x2="367.72989"
y2="523.38525"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.7712785,0,0,0.8337292,8.0871771,7.8098171)" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient2461"
id="linearGradient2467"
x1="551.34387"
y1="456.28641"
x2="551.34387"
y2="619.56287"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1,0,0,0.5308865,0,114.74779)" />
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
gridtolerance="10000"
guidetolerance="10"
objecttolerance="10"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="2.1448286"
inkscape:cx="309.70169"
inkscape:cy="808.88914"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="false"
showguides="true"
inkscape:guide-bbox="true"
inkscape:window-width="1600"
inkscape:window-height="1132"
inkscape:window-x="0"
inkscape:window-y="0" />
<metadata
id="metadata7">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1">
<rect
style="fill:url(#linearGradient2467);fill-opacity:1"
id="rect2459"
width="354.07697"
height="193.31812"
x="391.42059"
y="246.19127" />
<rect
style="fill:url(#linearGradient2457);fill-opacity:1"
id="rect2433"
width="127.34832"
height="191.49203"
x="228.03519"
y="248.01219" />
<rect
style="fill:#ff6600"
id="rect2549"
width="518.00879"
height="37.828362"
x="227.68326"
y="302.75879" />
<rect
style="fill:#00ff00"
id="rect2547"
width="544.10468"
height="38.307152"
x="201.76241"
y="243.43471" />
<rect
style="fill:url(#linearGradient2443);fill-opacity:1"
id="rect2383"
width="192.29077"
height="392.53891"
x="35.787025"
y="46.97047" />
<text
xml:space="preserve"
style="font-size:19.24255753px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="94.222366"
y="-121.21298"
id="text2387"
transform="matrix(-6.8463303e-3,1.0398304,-0.9616465,-7.4029511e-3,0,0)"><tspan
sodipodi:role="line"
id="tspan2389"
x="94.222366"
y="-121.21298">Address Decoder</tspan><tspan
sodipodi:role="line"
x="94.222366"
y="-97.15979"
id="tspan2391" /></text>
<rect
style="fill:#ff0000"
id="rect2393"
width="159.23743"
height="17.715534"
x="202.95409"
y="254.21713" />
<rect
style="fill:#0000ff"
id="rect2399"
width="159.23741"
height="17.715534"
x="202.9501"
y="280.85464" />
<rect
style="fill:#008000"
id="rect2401"
width="159.40862"
height="17.715534"
x="202.94533"
y="310.23676" />
<text
xml:space="preserve"
style="font-size:14.67683983000000048px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="254.6263"
y="281.54678"
id="text2403"
transform="scale(1.0494184,0.9529088)"><tspan
sodipodi:role="line"
id="tspan2405"
x="254.6263"
y="281.54678">Vdd </tspan></text>
<text
xml:space="preserve"
style="font-size:14.9124279px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="278.65591"
y="268.46613"
id="text2407"
transform="scale(0.9095598,1.0994329)"><tspan
sodipodi:role="line"
id="tspan2409"
x="278.65591"
y="268.46613">Word Line</tspan></text>
<text
xml:space="preserve"
style="font-size:15.81832218px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="277.87473"
y="316.27682"
id="text2411"
transform="scale(0.9736983,1.0270121)"><tspan
sodipodi:role="line"
id="tspan2413"
x="277.87473"
y="316.27682">Vss</tspan></text>
<rect
style="fill:#ff0000"
id="rect2469"
width="362.56842"
height="17.715534"
x="382.1893"
y="254.20079" />
<rect
style="fill:#0000ff"
id="rect2471"
width="363.03949"
height="17.715534"
x="382.1853"
y="280.83832" />
<rect
style="fill:#008000"
id="rect2473"
width="361.6424"
height="17.715534"
x="383.1106"
y="310.22043" />
<text
xml:space="preserve"
style="font-size:14.67683983px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="445.56149"
y="281.52963"
id="text2475"
transform="scale(1.0494184,0.9529088)"><tspan
sodipodi:role="line"
id="tspan2477"
x="445.56149"
y="281.52963">Vdd </tspan></text>
<text
xml:space="preserve"
style="font-size:14.9124279px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="498.65213"
y="268.45126"
id="text2479"
transform="scale(0.9095598,1.0994329)"><tspan
sodipodi:role="line"
id="tspan2481"
x="498.65213"
y="268.45126">Word Line</tspan></text>
<text
xml:space="preserve"
style="font-size:15.81830978px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="485.32767"
y="315.46939"
id="text2483"
transform="scale(0.9736983,1.0270121)"><tspan
sodipodi:role="line"
id="tspan2485"
x="485.32767"
y="315.46939">Vss</tspan></text>
<rect
style="fill:#ffffff"
id="rect2551"
width="16.346491"
height="152.72293"
x="364.29324"
y="215.42181" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:18.10000038;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 382.1893,263.0691 L 362.19151,263.07027"
id="path2487"
inkscape:connector-type="polyline"
inkscape:connection-start="#rect2469"
inkscape:connection-end="#rect2393" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:18.10000038;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 362.35394,319.0899 L 383.1106,319.08869"
id="path2491"
inkscape:connector-type="polyline"
inkscape:connection-start="#rect2401"
inkscape:connection-end="#rect2473" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:18.10000038;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 382.1853,289.70663 L 362.18752,289.70779"
id="path2493"
inkscape:connector-type="polyline"
inkscape:connection-start="#rect2471"
inkscape:connection-end="#rect2399" />
<text
xml:space="preserve"
style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="533.82971"
y="239.70804"
id="text2543"><tspan
sodipodi:role="line"
id="tspan2545"
x="533.82971"
y="239.70804">Array</tspan></text>
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:18.10000038;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 380.28173,247.63341 L 363.69741,247.63484"
id="path2553"
inkscape:connector-type="polyline" />
<path
style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.4;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:18.10000038;stroke-dasharray:none;marker-start:url(#Arrow1Lstart);marker-end:url(#Arrow1Lend)"
d="M 380.8161,335.38958 L 364.23178,335.39101"
id="path2563"
inkscape:connector-type="polyline" />
<text
xml:space="preserve"
style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="-238.96878"
y="379.59302"
id="text2583"
transform="matrix(0,-1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan2585"
x="-238.96878"
y="379.59302">}</tspan></text>
<text
xml:space="preserve"
style="font-size:24px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="345.11981"
y="380.30951"
id="text2587"
transform="matrix(0,1,1,0,0,0)"><tspan
sodipodi:role="line"
id="tspan2589"
x="345.11981"
y="380.30951">}</tspan></text>
<text
xml:space="preserve"
style="font-size:16.78106117px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="331.69421"
y="231.48781"
id="text2591"
transform="scale(1.0378936,0.9634899)"><tspan
sodipodi:role="line"
id="tspan2593"
x="331.69421"
y="231.48781">N-Well</tspan></text>
<text
xml:space="preserve"
style="font-size:16.01638031px;font-style:normal;font-weight:normal;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"
x="354.27347"
y="370.5802"
id="text2595"
transform="scale(0.9905987,1.0094905)"><tspan
sodipodi:role="line"
id="tspan2597"
x="354.27347"
y="370.5802">P-Well</tspan></text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -25,13 +25,13 @@
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="1"
inkscape:cx="161.5" inkscape:cx="20"
inkscape:cy="520" inkscape:cy="520"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
inkscape:window-width="1280" inkscape:window-width="3440"
inkscape:window-height="752" inkscape:window-height="1392"
inkscape:window-x="0" inkscape:window-x="0"
inkscape:window-y="0" inkscape:window-y="0"
inkscape:window-maximized="1"> inkscape:window-maximized="1">
@ -185,7 +185,7 @@
id="tspan4519" id="tspan4519"
x="184" x="184"
y="577.36218" y="577.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">BL</tspan></text> style="font-size:16px;line-height:1.25;font-family:sans-serif">bl</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
@ -196,7 +196,7 @@
id="tspan4523" id="tspan4523"
x="336" x="336"
y="577.36218" y="577.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">BL_bar</tspan></text> style="font-size:16px;line-height:1.25;font-family:sans-serif">br</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
@ -207,7 +207,7 @@
id="tspan4527" id="tspan4527"
x="287" x="287"
y="217.36218" y="217.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">VDD</tspan></text> style="font-size:16px;line-height:1.25;font-family:sans-serif">vdd</tspan></text>
<path <path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
d="m 237,346.36218 77,0" d="m 237,346.36218 77,0"
@ -263,7 +263,7 @@
id="tspan4793" id="tspan4793"
x="271" x="271"
y="334.36218" y="334.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">CLK</tspan></text> style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

View File

@ -13,8 +13,8 @@
height="1052.3622047" height="1052.3622047"
id="svg2" id="svg2"
version="1.1" version="1.1"
inkscape:version="0.48.3.1 r9886" inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="sense_amp.svg"> sodipodi:docname="sense_amp_schem.svg">
<defs <defs
id="defs4" /> id="defs4" />
<sodipodi:namedview <sodipodi:namedview
@ -24,16 +24,16 @@
borderopacity="1.0" borderopacity="1.0"
inkscape:pageopacity="0.0" inkscape:pageopacity="0.0"
inkscape:pageshadow="2" inkscape:pageshadow="2"
inkscape:zoom="1" inkscape:zoom="1.4142136"
inkscape:cx="199" inkscape:cx="78.947962"
inkscape:cy="520" inkscape:cy="503.38478"
inkscape:document-units="px" inkscape:document-units="px"
inkscape:current-layer="layer1" inkscape:current-layer="layer1"
showgrid="true" showgrid="true"
inkscape:window-width="1855" inkscape:window-width="3440"
inkscape:window-height="1056" inkscape:window-height="1392"
inkscape:window-x="65" inkscape:window-x="0"
inkscape:window-y="24" inkscape:window-y="0"
inkscape:window-maximized="1"> inkscape:window-maximized="1">
<inkscape:grid <inkscape:grid
type="xygrid" type="xygrid"
@ -47,7 +47,7 @@
<dc:format>image/svg+xml</dc:format> <dc:format>image/svg+xml</dc:format>
<dc:type <dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title> <dc:title />
</cc:Work> </cc:Work>
</rdf:RDF> </rdf:RDF>
</metadata> </metadata>
@ -55,37 +55,6 @@
inkscape:label="Layer 1" inkscape:label="Layer 1"
inkscape:groupmode="layer" inkscape:groupmode="layer"
id="layer1"> id="layer1">
<g
id="g3496"
transform="translate(-148.99875,80.014073)">
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3011">
<path
id="path3013"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 31.199,119.324 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3015">
<path
id="path3017"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 61.09,100.621 36.57,0"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3019">
<path
id="path3021"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 58.523,104.664 40.614,0"
inkscape:connector-curvature="0" />
</g>
</g>
<g <g
id="g3496-2" id="g3496-2"
transform="matrix(0,-1,1,0,-62.34811,791.36093)"> transform="matrix(0,-1,1,0,-62.34811,791.36093)">
@ -148,37 +117,6 @@
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
</g> </g>
</g> </g>
<g
id="g3496-7"
transform="translate(211.00125,80.014073)">
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3011-9">
<path
id="path3013-2"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 31.199,119.324 29.539,0 0,-14.66 36.922,0 0,14.66 29.539,0"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3015-8">
<path
id="path3017-9"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 61.09,100.621 36.57,0"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(1.25,0,0,1.25,240,223.19311)"
id="g3019-4">
<path
id="path3021-9"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 58.523,104.664 40.614,0"
inkscape:connector-curvature="0" />
</g>
</g>
<g <g
id="g3496-8" id="g3496-8"
transform="matrix(0,-1,1,0,-2.34811,920.37376)"> transform="matrix(0,-1,1,0,-2.34811,920.37376)">
@ -357,18 +295,18 @@
id="path4592" id="path4592"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 610,452.36218 30,0 0,-120 0,230" d="m 604,452.36218 h 30 v -120 230"
id="path4594" id="path4594"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 190,432.36218 0,-20 0,-10" d="m 184,416.36218 v -20 -10"
id="path4598" id="path4598"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 550,432.36218 0,-30" d="m 544,416.36218 v -30"
id="path4600" id="path4600"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<path <path
@ -406,11 +344,11 @@
</g> </g>
<g <g
id="g3319-3" id="g3319-3"
transform="matrix(1.25,0,0,1,129,112.20718)"> transform="matrix(1.25,0,0,1,125,112.20718)">
<path <path
inkscape:connector-curvature="0" inkscape:connector-curvature="0"
d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z" d="m 409.934,339.155 c 0,1.338 -0.864,2.417 -1.934,2.417 -1.07,0 -1.934,-1.079 -1.934,-2.417 0,-1.333 0.864,-2.417 1.934,-2.417 1.07,0 1.934,1.084 1.934,2.417 z"
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1.93475199;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path3321-5" /> id="path3321-5" />
</g> </g>
<g <g
@ -466,85 +404,165 @@
</g> </g>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="390" x="390"
y="172.36218" y="172.36218"
id="text4691" id="text4691"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4693" id="tspan4693"
x="390" x="390"
y="172.36218">VDD</tspan></text> y="172.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">vdd</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="488" x="488"
y="297.36218" y="297.36218"
id="text4695" id="text4695"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4697" id="tspan4697"
x="488" x="488"
y="297.36218">DATA</tspan></text> y="297.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">DATA</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="615" x="621"
y="577.36218" y="577.36218"
id="text4699" id="text4699"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4701" id="tspan4701"
x="615" x="621"
y="577.36218">BL_bar</tspan></text> y="577.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">br</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="89" x="89"
y="580.36218" y="580.36218"
id="text4703" id="text4703"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4705" id="tspan4705"
x="89" x="89"
y="580.36218">BL</tspan></text> y="580.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">bl</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="295" x="295"
y="588.36218" y="588.36218"
id="text4707" id="text4707"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4709" id="tspan4709"
x="295" x="295"
y="588.36218">EN</tspan></text> y="588.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="540" x="538"
y="398.36218" y="382.36218"
id="text4711" id="text4711"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4713" id="tspan4713"
x="540" x="538"
y="398.36218">EN</tspan></text> y="382.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<text <text
xml:space="preserve" xml:space="preserve"
style="font-size:16px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans" style="font-style:normal;font-weight:normal;line-height:0%;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none"
x="180" x="177.87868"
y="399.36218" y="376.02765"
id="text4715" id="text4715"><tspan
sodipodi:linespacing="125%"><tspan
sodipodi:role="line" sodipodi:role="line"
id="tspan4717" id="tspan4717"
x="180" x="177.87868"
y="399.36218">EN</tspan></text> y="376.02765"
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<path <path
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0" style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:0"
d="m 680,572.36218 0,-440 -620,0 0,610 620,0 z" d="m 680,572.36218 0,-440 -620,0 0,610 620,0 z"
id="path4738" id="path4738"
inkscape:connector-curvature="0" /> inkscape:connector-curvature="0" />
<g
transform="rotate(-90,322.13078,437.55515)"
id="g161">
<g
id="g147"
transform="matrix(1.25,0,0,1.25,-200,23.193113)">
<path
inkscape:connector-curvature="0"
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path145" />
</g>
<g
id="g151"
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
<path
inkscape:connector-curvature="0"
d="m 175.324,-407.199 h 29.539 v -14.66 h 36.922 v 14.66 h 29.539"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path149" />
</g>
<g
id="g155"
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
<path
inkscape:connector-curvature="0"
d="m 205.215,-425.902 h 36.57"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path153" />
</g>
<g
id="g159"
transform="matrix(0,1.25,-1.25,0,-200,23.193113)">
<path
inkscape:connector-curvature="0"
d="m 202.648,-421.859 h 40.614"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
id="path157" />
</g>
</g>
<g
id="g179"
transform="rotate(-90,502.65766,258.08202)">
<g
transform="matrix(1.25,0,0,1.25,-200,23.193113)"
id="g165">
<path
id="path163"
style="fill:none;stroke:#000000;stroke-width:1.30079997;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 434.398,221.727 c 0,2.207 -1.789,4 -4,4 -2.207,0 -4,-1.793 -4,-4 0,-2.211 1.793,-4 4,-4 2.211,0 4,1.789 4,4 z"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
id="g169">
<path
id="path167"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 175.324,-407.199 h 29.539 v -14.66 h 36.922 v 14.66 h 29.539"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
id="g173">
<path
id="path171"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 205.215,-425.902 h 36.57"
inkscape:connector-curvature="0" />
</g>
<g
transform="matrix(0,1.25,-1.25,0,-200,23.193113)"
id="g177">
<path
id="path175"
style="fill:none;stroke:#000000;stroke-width:1.60000002;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
d="m 202.648,-421.859 h 40.614"
inkscape:connector-curvature="0" />
</g>
</g>
</g> </g>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More