Fixed merging issues with power branch

This commit is contained in:
Hunter Nichols 2018-02-14 15:21:42 -08:00
commit 8ea384a761
145 changed files with 3924 additions and 4543 deletions

4
.gitignore vendored
View File

@ -2,3 +2,7 @@
*~
*.pyc
*.log
*.aux
*.out
*.toc
*.synctex.gz

View File

@ -7,9 +7,14 @@ https://github.com/mguthaus/OpenRAM/blob/master/OpenRAM_ICCAD_2016_presentation.
The OpenRAM compiler has very few dependencies:
* ngspice-26 (or later) or HSpice I-2013.12-1 (or later) or CustomSim 2017 (or later)
* Python 2.7 and higher (currently excludes Python 3 and up)
* Python numpy
* a setup script for each technology
* a technology directory for each technology with the base cells
If you want to perform DRC and LVS, you will need either:
* Calibre (for FreePDK45 or SCMOS)
* Magic + Netgen (for SCMOS only)
You must set two environment variables: OPENRAM_HOME should point to
the compiler source directory. OPENERAM_TECH should point to a root
technology directory that contains subdirs of all other technologies.
@ -36,6 +41,12 @@ For example, in csh/tcsh, add to your .tcshrc:
We do not distribute the PDK, but you may get it from:
https://www.eda.ncsu.edu/wiki/FreePDK45:Contents
If you are using SCMOS, you should install Magic and netgen from:
http://opencircuitdesign.com/magic/
http://opencircuitdesign.com/netgen/
In addition, you will need to install the MOSIS SCMOS rules for scn3me_subm
that are part of QFlow:
http://opencircuitdesign.com/qflow/
# DIRECTORY STRUCTURE
@ -120,27 +131,34 @@ This is where simulations and DRC/LVS get run so there is no network
traffic. The directory name is unique for each person and run of
OpenRAM to not clobber any files and allow simultaneous runs. If it
passes, the files are deleted. If it fails, you will see these files:
* _calibreDRC.rul_ is the DRC rule file.
* dc_runset is the command file for caliber.
* temp.gds is the layout
* test1.drc.err is the std err output of the command
* test1.drc.out is the standard output of the command
* test1.drc.db is the DRC results file
* (.mag files if using SCMOS)
* temp.sp is the netlist
* test1.drc.err is the std err output of the DRC command
* test1.drc.out is the standard output of the DRC command
* test1.drc.results is the DRC results file
* test1.lvs.err is the std err output of the LVS command
* test1.lvs.out is the standard output of the LVS command
* test1.lvs.results is the DRC results file
Depending on your DRC/LVS tools, there will also be:
* _calibreDRC.rul_ is the DRC rule file (Calibre)
* dc_runset is the command file (Calibre)
* extracted.sp (Calibre)
* run_lvs.sh is a Netgen script for LVS (Netgen)
* run_drc.sh is a Magic script for DRC (Magic)
* <topcell>.spice (Magic)
If DRC/LVS fails, the first thing is to check if it ran in the .out and
.err file. This shows the standard output and error output from
running DRC/LVS. If there is a setup problem it will be shown here.
If DRC/LVS runs, but doesn't pass, you then should look at the .db
If DRC/LVS runs, but doesn't pass, you then should look at the .results
file. If the DRC fails, it will typically show you the command that was used
to run caliber. It is something like this:
```
calibre -gui -drc /tmp/openram_mrg_28781_temp/drc_runset -batch 2>
/tmp/openram_mrg_28781_temp/test1.drc.err 1>
/tmp/openram_mrg_28781_temp/test1.drc.out
```
To debug, you will need a layout viewer. I prefer to use glade on my
Mac, but you can also use Calibre, Magic, etc.
to run Calibre or Magic+Netgen.
To debug, you will need a layout viewer. I prefer to use Glade
on my Mac, but you can also use Calibre, Magic, etc.
1. Calibre
@ -184,12 +202,19 @@ ui().importCds("default",
between processes, you have to change the importCds command (or you
can manually run the command each time you start glade).
To load the errors, you simply do Verify->Import Caliber Errors select
the .db file from calibre.
To load the errors, you simply do Verify->Import Calibre Errors select
the .results file from Calibre.
3. It is possible to use other viewers as well, such as:
3. Magic
Magic is only supported in SCMOS. You will need to install the MOSIS SCMOS rules
and Magic from: http://opencircuitdesign.com/
When running DRC or extraction, OpenRAM will load the GDS file, save
the .ext/.mag files, and export an extracted netlist (.spice).
4. It is possible to use other viewers as well, such as:
* LayoutEditor http://www.layouteditor.net/
* Magic http://opencircuitdesign.com/magic/
# Example to output/input .gds layout files from/to Cadence

View File

@ -77,7 +77,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
return inst_map
def DRC_LVS(self):
def DRC_LVS(self, final_verification=False):
"""Checks both DRC and LVS for a module"""
if OPTS.check_lvsdrc:
tempspice = OPTS.openram_temp + "/temp.sp"
@ -85,7 +85,7 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
self.sp_write(tempspice)
self.gds_write(tempgds)
debug.check(verify.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
debug.check(verify.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
debug.check(verify.run_lvs(self.name, tempgds, tempspice, final_verification) == 0,"LVS failed for {0}".format(self.name))
os.remove(tempspice)
os.remove(tempgds)
@ -97,14 +97,14 @@ class design(hierarchy_spice.spice, hierarchy_layout.layout):
debug.check(verify.run_drc(self.name, tempgds) == 0,"DRC failed for {0}".format(self.name))
os.remove(tempgds)
def LVS(self):
def LVS(self, final_verification=False):
"""Checks LVS for a module"""
if OPTS.check_lvsdrc:
tempspice = OPTS.openram_temp + "/temp.sp"
tempgds = OPTS.openram_temp + "/temp.gds"
self.sp_write(tempspice)
self.gds_write(tempgds)
debug.check(verify.run_lvs(self.name, tempgds, tempspice) == 0,"LVS failed for {0}".format(self.name))
debug.check(verify.run_lvs(self.name, tempgds, tempspice, final_verification) == 0,"LVS failed for {0}".format(self.name))
os.remove(tempspice)
os.remove(tempgds)

View File

@ -60,21 +60,44 @@ class layout(lef.lef):
def find_lowest_coords(self):
"""Finds the lowest set of 2d cartesian coordinates within
this layout"""
lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label")
lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label")
lowestx2 = min(inst.lx() for inst in self.insts)
lowesty2 = min(inst.by() for inst in self.insts)
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2))
if len(self.objs)>0:
lowestx1 = min(obj.lx() for obj in self.objs if obj.name!="label")
lowesty1 = min(obj.by() for obj in self.objs if obj.name!="label")
else:
lowestx1=lowesty1=None
if len(self.insts)>0:
lowestx2 = min(inst.lx() for inst in self.insts)
lowesty2 = min(inst.by() for inst in self.insts)
else:
lowestx2=lowesty2=None
if lowestx1==None:
return vector(lowestx2,lowesty2)
elif lowestx2==None:
return vector(lowestx1,lowesty1)
else:
return vector(min(lowestx1, lowestx2), min(lowesty1, lowesty2))
def find_highest_coords(self):
"""Finds the highest set of 2d cartesian coordinates within
this layout"""
highestx1 = min(obj.rx() for obj in self.objs if obj.name!="label")
highesty1 = min(obj.uy() for obj in self.objs if obj.name!="label")
highestx2 = min(inst.rx() for inst in self.insts)
highesty2 = min(inst.uy() for inst in self.insts)
return vector(min(highestx1, highestx2), min(highesty1, highesty2))
if len(self.objs)>0:
highestx1 = max(obj.rx() for obj in self.objs if obj.name!="label")
highesty1 = max(obj.uy() for obj in self.objs if obj.name!="label")
else:
highestx1=highesty1=None
if len(self.insts)>0:
highestx2 = max(inst.rx() for inst in self.insts)
highesty2 = max(inst.uy() for inst in self.insts)
else:
highestx2=highesty2=None
if highestx1==None:
return vector(highestx2,highesty2)
elif highestx2==None:
return vector(highestx1,highesty1)
else:
return vector(max(highestx1, highestx2), max(highesty1, highesty2))
def translate_all(self, offset):
@ -143,9 +166,11 @@ class layout(lef.lef):
debug.error("Nonrectilinear center rect!",-1)
elif start.x!=end.x:
offset = vector(0,0.5*minwidth_layer)
return self.add_rect(layer,start-offset,end.x-start.x,minwidth_layer)
else:
offset = vector(0.5*minwidth_layer,0)
return self.add_rect(layer,start-offset,end.x-start.x,minwidth_layer)
return self.add_rect(layer,start-offset,minwidth_layer,end.y-start.y)
def get_pin(self, text):
@ -283,7 +308,7 @@ class layout(lef.lef):
path.path(obj=self,
layer=layer,
position_list=coordinates,
width=drc["minwidth_{}".format(layer)])
width=width)
def add_route(self, design, layers, coordinates):
"""Connects a routing path on given layer,coordinates,width. The

View File

@ -92,7 +92,8 @@ class path():
self.add_line(layer_name=self.layer_name,
length=abs(line_length),
offset=offset,
orientation="horizontal")
orientation="horizontal",
layer_width=self.layer_width)
# if we have y motion
elif pl[index][1] != pl[index + 1][1]:
line_length = pl[index + 1][1] - pl[index][1]
@ -104,15 +105,15 @@ class path():
self.add_line(layer_name=self.layer_name,
length=abs(line_length),
offset=offset,
orientation="vertical")
orientation="vertical",
layer_width=self.layer_width)
def add_line(self, layer_name, length, offset, orientation):
def add_line(self, layer_name, length, offset, orientation, layer_width):
"""
straight line object with layer_minwidth
(orientation: "vertical" or "horizontal") default is vertical
"""
layer_width = drc["minwidth_{0}".format(layer_name)]
width = layer_width
height = length

View File

@ -7,7 +7,7 @@ from vector3d import vector3d
class route():
"""
Object route
Object route (used by the router module)
Add a route of minimium metal width between a set of points.
The wire must be completely rectilinear and the
z-dimension of the points refers to the layers (plus via)

View File

@ -12,8 +12,6 @@ class wire(path):
The points are the center of the wire.
The layer stack is the vertical, contact/via, and horizontal layers, respectively.
"""
unique_id = 1
def __init__(self, obj, layer_stack, position_list):
self.obj = obj
self.layer_stack = layer_stack
@ -85,7 +83,8 @@ class wire(path):
self.add_line(layer_name=self.horiz_layer_name,
length=abs(line_length),
offset=temp_offset,
orientation="horizontal")
orientation="horizontal",
layer_width=self.horiz_layer_width)
elif pl[index][1] != pl[index + 1][1]:
line_length = pl[index + 1][1] - pl[index][1]
temp_offset = [pl[index][0] - 0.5 * self.vert_layer_width,
@ -96,7 +95,8 @@ class wire(path):
self.add_line(layer_name=self.vert_layer_name,
length=abs(line_length),
offset=temp_offset,
orientation="vertical")
orientation="vertical",
layer_width=self.vert_layer_width)
def assert_node(self, A, B):
""" Check if the node movements are not big enough for the

View File

@ -10,20 +10,25 @@ from globals import OPTS
class delay():
"""
Functions to measure the delay of the SRAM at a given address and
Functions to measure the delay of an SRAM at a given address and
data bit.
"""
def __init__(self,sram,spfile):
def __init__(self,sram,spfile, corner):
self.name = sram.name
self.num_words = sram.num_words
self.word_size = sram.word_size
self.addr_size = sram.addr_size
self.sram_sp_file = spfile
self.vdd = tech.spice["supply_voltage"]
self.gnd = tech.spice["gnd_voltage"]
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 check_arguments(self):
"""Checks if arguments given for write_stimulus() meets requirements"""
@ -40,9 +45,9 @@ class delay():
def write_stimulus(self, period, load, slew):
"""Creates a stimulus file for simulations to probe a certain bitcell, given an address and data-position of the data-word
(probe-address form: '111010000' LSB=0, MSB=1)
(probe_data form: number corresponding to the bit position of data-bus, begins with position 0)
""" Creates a stimulus file for simulations to probe a bitcell at a given clock period.
Address and bit were previously set with set_probe().
Input slew (in ns) and output capacitive load (in fF) are required for charaterization.
"""
self.check_arguments()
@ -52,159 +57,160 @@ class delay():
# 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("* Stimulus for period of {0}n load={1} slew={2}\n\n".format(period,load,slew))
self.sf.write("* Stimulus for period of {0}n load={1}fF slew={2}ns\n\n".format(period,load,slew))
self.stim = stimuli.stimuli(self.sf, self.corner)
# include files in stimulus file
model_list = tech.spice["fet_models"] + [self.sram_sp_file]
stimuli.write_include(stim_file=self.sf, models=model_list)
self.stim.write_include(self.sram_sp_file)
# add vdd/gnd statements
self.sf.write("* Global Power Supplies\n")
stimuli.write_supply(self.sf)
self.sf.write("\n* Global Power Supplies\n")
self.stim.write_supply()
# instantiate the sram
self.sf.write("* 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* Instantiation of the SRAM\n")
self.stim.inst_sram(abits=self.addr_size,
dbits=self.word_size,
sram_name=self.name)
self.sf.write("* SRAM output loads\n")
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("* Transmission Gates for data-bus and control signals\n")
stimuli.inst_accesstx(stim_file=self.sf, dbits=self.word_size)
self.sf.write("\n* Transmission Gates for data-bus and control signals\n")
self.stim.inst_accesstx(dbits=self.word_size)
# generate data and addr signals
self.sf.write("* 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):
if i == self.probe_data:
stimuli.gen_data(stim_file=self.sf,
clk_times=self.cycle_times,
sig_name="data[{0}]".format(i),
period=period,
slew=slew)
self.gen_data(clk_times=self.cycle_times,
sig_name="data[{0}]".format(i),
period=period,
slew=slew)
else:
stimuli.gen_constant(stim_file=self.sf,
sig_name="d[{0}]".format(i),
v_val=self.gnd)
self.stim.gen_constant(sig_name="d[{0}]".format(i),
v_val=self.gnd_voltage)
stimuli.gen_addr(self.sf,
clk_times=self.cycle_times,
addr=self.probe_address,
period=period,
slew=slew)
self.gen_addr(clk_times=self.cycle_times,
addr=self.probe_address,
period=period,
slew=slew)
# generate control signals
self.sf.write("* Generation of control signals\n")
stimuli.gen_csb(self.sf, self.cycle_times, period, slew)
stimuli.gen_web(self.sf, self.cycle_times, period, slew)
stimuli.gen_oeb(self.sf, self.cycle_times, period, slew)
self.sf.write("\n* Generation of control signals\n")
self.gen_csb(self.cycle_times, period, slew)
self.gen_web(self.cycle_times, period, slew)
self.gen_oeb(self.cycle_times, period, slew)
self.sf.write("* Generation of global clock signal\n")
stimuli.gen_pulse(stim_file=self.sf,
sig_name="CLK",
v1=self.gnd,
v2=self.vdd,
offset=period,
period=period,
t_rise = slew,
t_fall = slew)
self.sf.write("\n* Generation of global clock signal\n")
self.stim.gen_pulse(sig_name="CLK",
v1=self.gnd_voltage,
v2=self.vdd_voltage,
offset=period,
period=period,
t_rise=slew,
t_fall=slew)
self.write_measures(period)
# run until the last cycle time
stimuli.write_control(self.sf,self.cycle_times[-1])
# run until the end of the cycle time
self.stim.write_control(self.cycle_times[-1] + period)
self.sf.close()
def write_measures(self,period):
# meas statement for delay and power measurements
self.sf.write("* Measure statements for delay and power\n")
"""
Write the measure statements to quantify the delay and power results.
"""
self.sf.write("\n* Measure statements for delay and power\n")
# Output some comments to aid where cycles start and
# what is happening
for comment in self.cycle_comments:
self.sf.write("* {}\n".format(comment))
# Trigger on the clk of the appropriate cycle
trig_name = "clk"
targ_name = "{0}".format("d[{0}]".format(self.probe_data))
trig_val = targ_val = 0.5 * self.vdd
# add measure statments for delay0
# delay the target to measure after the negetive edge
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="DELAY0",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="FALL",
targ_dir="FALL",
td=self.cycle_times[self.read0_cycle]+0.5*period)
trig_val = targ_val = 0.5 * self.vdd_voltage
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="DELAY1",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="FALL",
targ_dir="RISE",
td=self.cycle_times[self.read1_cycle]+0.5*period)
# Delay the target to measure after the negative edge
self.stim.gen_meas_delay(meas_name="DELAY0",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="FALL",
targ_dir="FALL",
trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]+0.5*period)
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="SLEW0",
trig_name=targ_name,
targ_name=targ_name,
trig_val=0.9*self.vdd,
targ_val=0.1*self.vdd,
trig_dir="FALL",
targ_dir="FALL",
td=self.cycle_times[self.read0_cycle]+0.5*period)
self.stim.gen_meas_delay(meas_name="DELAY1",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="FALL",
targ_dir="RISE",
trig_td=self.cycle_times[self.read1_cycle],
targ_td=self.cycle_times[self.read1_cycle]+0.5*period)
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="SLEW1",
trig_name=targ_name,
targ_name=targ_name,
trig_val=0.1*self.vdd,
targ_val=0.9*self.vdd,
trig_dir="RISE",
targ_dir="RISE",
td=self.cycle_times[self.read1_cycle]+0.5*period)
self.stim.gen_meas_delay(meas_name="SLEW0",
trig_name=targ_name,
targ_name=targ_name,
trig_val=0.9*self.vdd_voltage,
targ_val=0.1*self.vdd_voltage,
trig_dir="FALL",
targ_dir="FALL",
trig_td=self.cycle_times[self.read0_cycle],
targ_td=self.cycle_times[self.read0_cycle]+0.5*period)
self.stim.gen_meas_delay(meas_name="SLEW1",
trig_name=targ_name,
targ_name=targ_name,
trig_val=0.1*self.vdd_voltage,
targ_val=0.9*self.vdd_voltage,
trig_dir="RISE",
targ_dir="RISE",
trig_td=self.cycle_times[self.read1_cycle],
targ_td=self.cycle_times[self.read1_cycle]+0.5*period)
# add measure statements for power
t_initial = self.cycle_times[self.write0_cycle]
t_final = self.cycle_times[self.write0_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf,
meas_name="WRITE0_POWER",
t_initial=t_initial,
t_final=t_final)
self.stim.gen_meas_power(meas_name="WRITE0_POWER",
t_initial=t_initial,
t_final=t_final)
t_initial = self.cycle_times[self.write1_cycle]
t_final = self.cycle_times[self.write1_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf,
meas_name="WRITE1_POWER",
t_initial=t_initial,
t_final=t_final)
self.stim.gen_meas_power(meas_name="WRITE1_POWER",
t_initial=t_initial,
t_final=t_final)
t_initial = self.cycle_times[self.read0_cycle]
t_final = self.cycle_times[self.read0_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf,
meas_name="READ0_POWER",
t_initial=t_initial,
t_final=t_final)
self.stim.gen_meas_power(meas_name="READ0_POWER",
t_initial=t_initial,
t_final=t_final)
t_initial = self.cycle_times[self.read1_cycle]
t_final = self.cycle_times[self.read1_cycle+1]
stimuli.gen_meas_power(stim_file=self.sf,
meas_name="READ1_POWER",
t_initial=t_initial,
t_final=t_final)
self.stim.gen_meas_power(meas_name="READ1_POWER",
t_initial=t_initial,
t_final=t_final)
def find_feasible_period(self, load, slew):
"""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
the given clock period is valid and if it's not, we continue to
double the period until we find a valid period to use as a
starting point. """
starting point.
"""
feasible_period = tech.spice["feasible_period"]
time_out = 8
@ -220,17 +226,23 @@ class delay():
feasible_period = 2 * feasible_period
continue
debug.info(1, "Found feasible_period: {0}ns feasible_delay1/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,feasible_delay1,feasible_delay0,feasible_slew1,feasible_slew0))
debug.info(1, "Found feasible_period: {0}ns feasible_delay1/0 {1}ns/{2}ns slew {3}ns/{4}ns".format(feasible_period,
feasible_delay1,
feasible_delay0,
feasible_slew1,
feasible_slew0))
return (feasible_period, feasible_delay1, feasible_delay0)
def run_simulation(self, period, load, slew):
""" This tries to simulate a period and checks if the result
works. If so, it returns True and the delays and slews."""
"""
This tries to simulate a period and checks if the result
works. If so, it returns True and the delays and slews.
"""
# Checking from not data_value to data_value
self.write_stimulus(period, load, slew)
stimuli.run_sim()
self.stim.run_sim()
delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0"))
delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1"))
slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0"))
@ -238,15 +250,37 @@ class delay():
# 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))
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.
#key=raw_input("press return to continue")
# The delay is from the negative edge for our SRAM
@ -255,8 +289,10 @@ class delay():
def find_min_period(self,feasible_period, load, slew, feasible_delay1, feasible_delay0):
"""Searches for the smallest period with output delays being within 5% of
long period. """
"""
Searches for the smallest period with output delays being within 5% of
long period.
"""
previous_period = ub_period = feasible_period
lb_period = 0.0
@ -284,26 +320,36 @@ class delay():
def try_period(self, period, load, slew, feasible_delay1, feasible_delay0):
""" 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."""
"""
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.
"""
# Checking from not data_value to data_value
self.write_stimulus(period,load,slew)
stimuli.run_sim()
self.stim.run_sim()
delay0 = ch.convert_to_float(ch.parse_output("timing", "delay0"))
delay1 = ch.convert_to_float(ch.parse_output("timing", "delay1"))
slew0 = ch.convert_to_float(ch.parse_output("timing", "slew0"))
slew1 = ch.convert_to_float(ch.parse_output("timing", "slew1"))
# 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,"Invalid measures: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
debug.info(2,"Invalid measures: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period,
delay0,
delay1,
slew0,
slew1))
return False
delay0 *= 1e9
delay1 *= 1e9
slew0 *= 1e9
slew1 *= 1e9
if delay0>period or delay1>period or slew0>period or slew1>period:
debug.info(2,"Too long delay/slew: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period, delay0, delay1, slew0, slew1))
debug.info(2,"Too long delay/slew: Period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period,
delay0,
delay1,
slew0,
slew1))
return False
else:
if not ch.relative_compare(delay1,feasible_delay1,error_tolerance=0.05):
@ -316,7 +362,11 @@ class delay():
#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, delay0, delay1, slew0, slew1))
debug.info(2,"Successful period {0}, delay0={1}ns, delay1={2}ns slew0={3}ns slew1={4}ns".format(period,
delay0,
delay1,
slew0,
slew1))
return True
def set_probe(self,probe_address, probe_data):
@ -394,47 +444,96 @@ class delay():
of the cycles to do a timing evaluation. The last time is the end of the simulation
and does not need a rising edge."""
# idle cycle, no operation
t_current = period
self.cycle_comments = []
self.cycle_times = []
# cycle0: W data 1 address 1111 to initialize cell to a value
t_current = 0
# idle cycle, no operation
msg = "Idle cycle (no clock)"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(0,
t_current,
msg))
self.cycle_times.append(t_current)
t_current += period
# cycle1: W data 0 address 1111 (to ensure a write of value works)
# One period
msg = "W data 1 address 11..11 to initialize cell"
self.cycle_times.append(t_current)
self.write0_cycle=1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# One period
msg = "W data 0 address 11..11 (to ensure a write of value works)"
self.cycle_times.append(t_current)
self.write0_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle2: W data 1 address 0000 (to clear the data bus cap)
# One period
msg = "W data 1 address 00..00 (to clear bus caps)"
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# One period
msg = "R data 0 address 11..11 to check W0 worked"
self.cycle_times.append(t_current)
self.read0_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# One period
msg = "Idle cycle"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
self.cycle_times.append(t_current)
t_current += period
# cycle3: R data 0 address 1111 to check W0 works
# One period
msg = "W data 1 address 11..11 (to ensure a write of value worked)"
self.cycle_times.append(t_current)
self.read0_cycle=3
self.write1_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle4: W data 1 address 1111 (to ensure a write of value works)
self.cycle_times.append(t_current)
self.write1_cycle=4
t_current += period
# cycle5: W data 0 address 0000 (to clear the data bus cap)
# One period
msg = "W data 0 address 00..00 (to clear bus caps)"
self.cycle_times.append(t_current)
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle6: R data 1 address 1111 to check W1 works
# One period
msg = "R data 1 address 11..11 to check W1 worked"
self.cycle_times.append(t_current)
self.read1_cycle=6
self.read1_cycle=len(self.cycle_times)-1
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
t_current += period
# cycle7: wait a clock period to end the simulation
# One period
msg = "Idle cycle"
self.cycle_comments.append("Cycle{0}\t{1}ns:\t{2}".format(len(self.cycle_times)-1,
t_current,
msg))
self.cycle_times.append(t_current)
t_current += period
def analytical_model(self,sram, slews, loads):
""" Just return the analytical model results for the SRAM.
"""
@ -465,3 +564,54 @@ class delay():
}
return data
def gen_data(self, clk_times, sig_name, period, slew):
""" Generates the PWL data inputs for a simulation timing test. """
# 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
# the read to be "worst case". Otherwise, it can actually assist the read.
values = [0, 1, 0, 1, 1, 1, 1, 0, 0, 0 ]
self.stim.gen_pwl(sig_name, clk_times, values, period, slew, 0.05)
def gen_addr(self, clk_times, addr, period, slew):
"""
Generates the address inputs for a simulation timing test.
This alternates between all 1's and all 0's for the address.
"""
zero_values = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0 ]
ones_values = [1, 1, 1, 0, 1, 0, 1, 0, 1, 1 ]
for i in range(len(addr)):
sig_name = "A[{0}]".format(i)
if addr[i]=="1":
self.stim.gen_pwl(sig_name, clk_times, ones_values, period, slew, 0.05)
else:
self.stim.gen_pwl(sig_name, clk_times, zero_values, period, slew, 0.05)
def gen_csb(self, clk_times, period, slew):
""" Generates the PWL CSb signal """
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep CSb asserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 0, 0, 0, 0, 0, 0]
self.stim.gen_pwl("csb", clk_times, values, period, slew, 0.05)
def gen_web(self, clk_times, period, slew):
""" Generates the PWL WEb signal """
# values for NOP, W1, W0, W1, R0, NOP, W1, W0, R1, NOP
# Keep WEb deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
self.stim.gen_pwl("web", clk_times, values, period, slew, 0.05)
# Keep acc_en deasserted in NOP for measuring >1 period
values = [1, 0, 0, 0, 1, 1, 0, 0, 1, 1]
self.stim.gen_pwl("acc_en", clk_times, values, period, slew, 0)
values = [0, 1, 1, 1, 0, 0, 1, 1, 0, 0]
self.stim.gen_pwl("acc_en_inv", clk_times, values, period, slew, 0)
def gen_oeb(self, clk_times, period, slew):
""" Generates the PWL WEb signal """
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
# Keep OEb asserted in NOP for measuring >1 period
values = [1, 1, 1, 1, 0, 0, 1, 1, 0, 0]
self.stim.gen_pwl("oeb", clk_times, values, period, slew, 0.05)

View File

@ -1,8 +1,5 @@
import os
import sys
import re
import os,sys,re,shutil
import debug
import tech
import math
import setup_hold
import delay
@ -15,15 +12,23 @@ from globals import OPTS
class lib:
""" 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.sp_file = spfile
self.sp_file = sp_file
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
self.prepare_netlist()
self.prepare_tables()
self.create_corners()
self.characterize_corners()
def prepare_netlist(self):
""" Determine whether to use regular or trimmed netlist. """
# Set up to trim the netlist here if that is enabled
if OPTS.trim_netlist:
self.sim_sp_file = "{}reduced.sp".format(OPTS.openram_temp)
@ -34,13 +39,17 @@ class lib:
self.sram.word_size)
else:
# Else, use the non-reduced netlist file for simulation
self.sim_sp_file = self.sp_file
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 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
#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])
self.load = tech.spice["FF_in_cap"]
self.load = tech.spice["msflop_in_cap"]
self.loads = self.load_scales*self.load
debug.info(1,"Loads: {0}".format(self.loads))
@ -50,9 +59,43 @@ class lib:
self.slew = tech.spice["rise_time"]
self.slews = self.slew_scales*self.slew
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(".","") # 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()
def characterize(self):
""" Characterize the current corner. """
self.write_header()
@ -68,7 +111,7 @@ class lib:
def write_header(self):
""" 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(" delay_model : \"table_lookup\";\n")
@ -80,12 +123,12 @@ class lib:
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(" memory(){ \n")
self.lib.write(" type : ram;\n")
self.lib.write(" address_width : {0};\n".format(self.addr_size))
self.lib.write(" word_width : {0};\n".format(self.word_size))
self.lib.write(" address_width : {0};\n".format(self.sram.addr_size))
self.lib.write(" word_width : {0};\n".format(self.sram.word_size))
self.lib.write(" }\n")
self.lib.write(" interface_timing : true;\n")
self.lib.write(" dont_use : true;\n")
@ -104,9 +147,9 @@ class lib:
self.lib.write(" capacitive_load_unit(1 ,fF) ;\n")
self.lib.write(" leakage_power_unit : \"1mW\" ;\n")
self.lib.write(" pulling_resistance_unit :\"1kohm\" ;\n")
self.lib.write(" operating_conditions(TT){\n")
self.lib.write(" voltage : {0} ;\n".format(tech.spice["supply_voltage"]))
self.lib.write(" temperature : 25.000 ;\n")
self.lib.write(" operating_conditions({}){{\n".format(self.process))
self.lib.write(" voltage : {} ;\n".format(self.voltage))
self.lib.write(" temperature : {};\n".format(self.temperature))
self.lib.write(" }\n\n")
def write_defaults(self):
@ -207,17 +250,17 @@ class lib:
self.lib.write(" type (DATA){\n")
self.lib.write(" base_type : array;\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_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(" type (ADDR){\n")
self.lib.write(" base_type : array;\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_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")
@ -261,7 +304,7 @@ class lib:
self.lib.write(" bus(DATA){\n")
self.lib.write(" bus_type : DATA; \n")
self.lib.write(" direction : inout; \n")
self.lib.write(" max_capacitance : {0}; \n".format(8*tech.spice["FF_in_cap"]))
self.lib.write(" max_capacitance : {0}; \n".format(8*tech.spice["msflop_in_cap"]))
self.lib.write(" three_state : \"!OEb & !clk\"; \n")
self.lib.write(" memory_write(){ \n")
self.lib.write(" address : ADDR; \n")
@ -270,7 +313,7 @@ class lib:
self.lib.write(" memory_read(){ \n")
self.lib.write(" address : ADDR; \n")
self.lib.write(" }\n")
self.lib.write(" pin(DATA[{0}:0])".format(self.word_size - 1))
self.lib.write(" pin(DATA[{0}:0])".format(self.sram.word_size - 1))
self.lib.write("{\n")
self.lib.write(" internal_power(){\n")
@ -325,10 +368,10 @@ class lib:
self.lib.write(" bus(ADDR){\n")
self.lib.write(" bus_type : ADDR; \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["msflop_in_cap"]))
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.addr_size - 1))
self.lib.write(" pin(ADDR[{0}:0])".format(self.sram.addr_size - 1))
self.lib.write("{\n")
self.write_FF_setuphold()
@ -344,7 +387,7 @@ class lib:
self.lib.write(" pin({0})".format(i))
self.lib.write("{\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["msflop_in_cap"]))
self.write_FF_setuphold()
self.lib.write(" }\n\n")
@ -357,7 +400,7 @@ class lib:
self.lib.write(" pin(clk){\n")
self.lib.write(" clock : true;\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["msflop_in_cap"]))
min_pulse_width = ch.round_time(self.delay["min_period"])/2.0
min_period = ch.round_time(self.delay["min_period"])
self.lib.write(" timing(){ \n")
@ -389,12 +432,12 @@ class lib:
try:
self.d
except AttributeError:
self.d = delay.delay(self.sram, self.sim_sp_file)
self.d = delay.delay(self.sram, self.sim_sp_file, self.corner)
if self.use_model:
self.delay = self.d.analytical_model(self.sram,self.slews,self.loads)
else:
probe_address = "1" * self.addr_size
probe_data = self.word_size - 1
probe_address = "1" * self.sram.addr_size
probe_data = self.sram.word_size - 1
# We must trim based on a specific address and data bit
if OPTS.trim_netlist:
self.trimsp.trim(probe_address,probe_data)
@ -406,7 +449,7 @@ class lib:
try:
self.sh
except AttributeError:
self.sh = setup_hold.setup_hold()
self.sh = setup_hold.setup_hold(self.corner)
if self.use_model:
self.times = self.sh.analytical_model(self.slews,self.loads)
else:

View File

@ -13,18 +13,23 @@ class setup_hold():
(Bisection Methodology)
"""
def __init__(self):
def __init__(self, corner):
# This must match the spice model order
self.pins = ["data", "dout", "dout_bar", "clk", "vdd", "gnd"]
self.model_name = "ms_flop"
self.model_location = OPTS.openram_tech + "sp_lib/ms_flop.sp"
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))
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):
@ -33,14 +38,14 @@ class setup_hold():
# creates and opens the stimulus file for writing
temp_stim = OPTS.openram_temp + "stim.sp"
self.sf = open(temp_stim, "w")
self.stim = stimuli.stimuli(self.sf, self.corner)
self.write_header(correct_value)
# instantiate the master-slave d-flip-flop
self.sf.write("* Instantiation of the Master-Slave D-flip-flop\n")
stimuli.inst_model(stim_file=self.sf,
pins=self.pins,
model_name=self.model_name)
self.sf.write("\n* Instantiation of the Master-Slave D-flip-flop\n")
self.stim.inst_model(pins=self.pins,
model_name=self.model_name)
self.write_data(mode=mode,
target_time=target_time,
@ -52,22 +57,20 @@ class setup_hold():
correct_value=correct_value)
stimuli.write_control(self.sf,4*self.period)
self.stim.write_control(4*self.period)
self.sf.close()
def write_header(self, correct_value):
""" Write the header file with all the models and the power supplies. """
self.sf.write("* 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
self.model_list = tech.spice["fet_models"] + [self.model_location]
stimuli.write_include(stim_file=self.sf,
models=self.model_list)
self.stim.write_include(self.model_location)
# add vdd/gnd statements
self.sf.write("* Global Power Supplies\n")
stimuli.write_supply(self.sf)
self.sf.write("\n* Global Power Supplies\n")
self.stim.write_supply()
def write_data(self, mode, target_time, correct_value):
@ -76,8 +79,8 @@ class setup_hold():
characterization.
"""
self.sf.write("* Generation of the data and clk signals\n")
incorrect_value = stimuli.get_inverse_value(correct_value)
self.sf.write("\n* Generation of the data and clk signals\n")
incorrect_value = self.stim.get_inverse_value(correct_value)
if mode=="HOLD":
init_value = incorrect_value
start_value = correct_value
@ -87,29 +90,27 @@ class setup_hold():
start_value = incorrect_value
end_value = correct_value
stimuli.gen_pwl(stim_file=self.sf,
sig_name="data",
clk_times=[self.period, target_time],
data_values=[init_value, start_value, end_value],
period=target_time,
slew=self.constrained_input_slew,
setup=0)
self.stim.gen_pwl(sig_name="data",
clk_times=[0, self.period, target_time],
data_values=[init_value, start_value, end_value],
period=target_time,
slew=self.constrained_input_slew,
setup=0)
def write_clock(self):
""" Create the clock signal for setup/hold analysis. First period initializes the FF
while the second is used for characterization."""
stimuli.gen_pwl(stim_file=self.sf,
sig_name="clk",
# initial clk edge is right after the 0 time to initialize a flop
# without using .IC on an internal node.
# Return input to value after one period.
# The second pulse is the characterization one at 2*period
clk_times=[0.1*self.period,self.period,2*self.period],
data_values=[0, 1, 0, 1],
period=2*self.period,
slew=self.constrained_input_slew,
setup=0)
self.stim.gen_pwl(sig_name="clk",
# initial clk edge is right after the 0 time to initialize a flop
# without using .IC on an internal node.
# Return input to value after one period.
# The second pulse is the characterization one at 2*period
clk_times=[0, 0.1*self.period,self.period,2*self.period],
data_values=[0, 1, 0, 1],
period=2*self.period,
slew=self.constrained_input_slew,
setup=0)
@ -132,33 +133,33 @@ class setup_hold():
din_rise_or_fall = "RISE"
self.sf.write("* Measure statements for pass/fail verification\n")
self.sf.write("\n* Measure statements for pass/fail verification\n")
trig_name = "clk"
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
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="clk2q_delay",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="RISE",
targ_dir=dout_rise_or_fall,
td=1.9*self.period)
self.stim.gen_meas_delay(meas_name="clk2q_delay",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="RISE",
targ_dir=dout_rise_or_fall,
trig_td=1.9*self.period,
targ_td=1.9*self.period)
targ_name = "data"
# Start triggers right after initialize value is returned to normal
# at one period
stimuli.gen_meas_delay(stim_file=self.sf,
meas_name="setup_hold_time",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="RISE",
targ_dir=din_rise_or_fall,
td=1.2*self.period)
self.stim.gen_meas_delay(meas_name="setup_hold_time",
trig_name=trig_name,
targ_name=targ_name,
trig_val=trig_val,
targ_val=targ_val,
trig_dir="RISE",
targ_dir=din_rise_or_fall,
trig_td=1.2*self.period,
targ_td=1.2*self.period)
@ -184,7 +185,7 @@ class setup_hold():
self.write_stimulus(mode=mode,
target_time=feasible_bound,
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"))
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))
@ -217,7 +218,7 @@ class setup_hold():
feasible_bound))
stimuli.run_sim()
self.stim.run_sim()
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"))
if type(clk_to_q)==float and (clk_to_q<1.1*ideal_clk_to_q) and type(setuphold_time)==float:

View File

@ -1,7 +1,7 @@
"""
This file generates the test structure and stimulus for an sram
simulation. There are various functions that can be be used to
generate stimulus for other simulations as well.
This file generates simple spice cards for simulation. There are
various functions that can be be used to generate stimulus for other
simulations as well.
"""
import tech
@ -12,316 +12,301 @@ import sys
import numpy as np
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):
"""function to instatiate the sram subckt"""
stim_file.write("Xsram ")
for i in range(dbits):
stim_file.write("D[{0}] ".format(i))
for i in range(abits):
stim_file.write("A[{0}] ".format(i))
for i in tech.spice["control_signals"]:
stim_file.write("{0} ".format(i))
stim_file.write("{0} ".format(tech.spice["clk"]))
stim_file.write("{0} {1} ".format(vdd_name, gnd_name))
stim_file.write("{0}\n\n".format(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"]
def inst_model(stim_file, pins, model_name):
"""function to instantiate a model"""
stim_file.write("X{0} ".format(model_name))
for pin in pins:
stim_file.write("{0} ".format(pin))
stim_file.write("{0}\n".format(model_name))
def create_inverter(stim_file, size=1, beta=2.5):
"""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))
stim_file.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name,
pmos_name,
beta * size * tx_width,
tx_length))
stim_file.write("mninv out in {0} {0} {1} w={2}u l={3}u\n".format(gnd_name,
nmos_name,
size * tx_width,
tx_length))
stim_file.write(".ENDS test_inv\n")
def create_buffer(stim_file, buffer_name, size=[1,3], beta=2.5):
"""Generates buffer for top level signals (only for sim
purposes). Size is pair for PMOS, NMOS width multiple. It includes
a beta of 3."""
stim_file.write(".SUBCKT test_{2} in out {0} {1}\n".format(vdd_name,
gnd_name,
buffer_name))
stim_file.write("mpinv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(vdd_name,
pmos_name,
beta * size[0] * tx_width,
tx_length))
stim_file.write("mninv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(gnd_name,
nmos_name,
size[0] * tx_width,
tx_length))
stim_file.write("mpinv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(vdd_name,
pmos_name,
beta * size[1] * tx_width,
tx_length))
stim_file.write("mninv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(gnd_name,
nmos_name,
size[1] * tx_width,
tx_length))
stim_file.write(".ENDS test_{0}\n\n".format(buffer_name))
def inst_buffer(stim_file, buffer_name, signal_list):
"""Adds buffers to each top level signal that is in signal_list (only for sim purposes)"""
for signal in signal_list:
stim_file.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal,
"test"+vdd_name,
"test"+gnd_name,
buffer_name))
def inst_inverter(stim_file, signal_list):
"""Adds inv for each signal that needs its inverted version (only for sim purposes)"""
for signal in signal_list:
stim_file.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal,
"test"+vdd_name,
"test"+gnd_name))
def inst_accesstx(stim_file, dbits):
"""Adds transmission gate for inputs to data-bus (only for sim purposes)"""
stim_file.write("* Tx Pin-list: Drain Gate Source Body\n")
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"
stim_file.write(pmos_access_string.format(i,
"test"+vdd_name,
pmos_name,
2 * tx_width,
tx_length))
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,
"test"+gnd_name,
nmos_name,
2 * tx_width,
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):
"""Generates a periodic signal with 50% duty cycle and slew rates. Period is measured
from 50% to 50%."""
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,
v1,
v2,
offset,
t_rise,
t_fall,
0.5*period-0.5*t_rise-0.5*t_fall,
period))
def gen_pwl(stim_file, sig_name, clk_times, data_values, period, slew, setup):
# the initial value is not a clock time
debug.check(len(clk_times)+1==len(data_values),"Clock and data value lengths don't match.")
# shift signal times earlier for setup time
times = np.array(clk_times) - setup*period
values = np.array(data_values) * vdd_voltage
half_slew = 0.5 * slew
stim_file.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
for i in range(len(times)):
stim_file.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
values[i],
times[i]+half_slew,
values[i+1]))
stim_file.write(")\n")
def gen_data(stim_file, clk_times, sig_name, period, slew):
"""Generates the PWL data inputs for a simulation timing test."""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
# 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.
values = [0, 1, 0, 1, 1, 1, 0, 0, 0 ]
gen_pwl(stim_file, sig_name, clk_times, values, period, slew, 0.05)
def gen_addr(stim_file, clk_times, addr, period, slew):
"""Generates the address inputs for a simulation timing test.
One cycle is different to clear the bus
"""
zero_values = [0, 0, 0, 1, 0, 0, 1, 0, 0 ]
ones_values = [1, 1, 1, 0, 1, 1, 0, 1, 1 ]
for i in range(len(addr)):
sig_name = "A[{0}]".format(i)
if addr[i]=="1":
gen_pwl(stim_file, sig_name, clk_times, ones_values, period, slew, 0.05)
else:
gen_pwl(stim_file, sig_name, clk_times, zero_values, period, slew, 0.05)
def gen_constant(stim_file, sig_name, v_val):
"""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))
def gen_csb(stim_file, clk_times, period, slew):
""" Generates the PWL CSb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 0, 0, 0, 0, 0, 0, 0, 1]
gen_pwl(stim_file, "csb", clk_times, values, period, slew, 0.05)
def gen_web(stim_file, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 0, 0, 0, 1, 0, 0, 1, 1]
gen_pwl(stim_file, "web", clk_times, values, period, slew, 0.05)
values = [1, 0, 0, 0, 1, 0, 0, 1, 1]
gen_pwl(stim_file, "acc_en", clk_times, values, period, slew, 0)
values = [0, 1, 1, 1, 0, 1, 1, 0, 0]
gen_pwl(stim_file, "acc_en_inv", clk_times, values, period, slew, 0)
def gen_oeb(stim_file, clk_times, period, slew):
""" Generates the PWL WEb signal"""
# values for NOP, W1, W0, W1, R0, W1, W0, R1, NOP
values = [1, 1, 1, 1, 0, 1, 1, 0, 1]
gen_pwl(stim_file, "oeb", clk_times, values, period, slew, 0.05)
def get_inverse_voltage(value):
if value > 0.5*vdd_voltage:
return gnd_voltage
elif value <= 0.5*vdd_voltage:
return vdd_voltage
else:
debug.error("Invalid value to get an inverse of: {0}".format(value))
def get_inverse_value(value):
if value > 0.5:
return 0
elif value <= 0.5:
return 1
else:
debug.error("Invalid value to get an inverse of: {0}".format(value))
self.sf = stim_file
(self.process, self.voltage, self.temperature) = corner
self.device_models = tech.spice["fet_models"][self.process]
def gen_meas_delay(stim_file, meas_name, trig_name, targ_name, trig_val, targ_val, trig_dir, targ_dir, td):
"""Creates the .meas statement for the measurement of delay"""
measure_string=".meas tran {0} TRIG v({1}) VAL={2} {3}=1 TD={7}n TARG v({4}) VAL={5} {6}=1 TD={7}n\n\n"
stim_file.write(measure_string.format(meas_name,
trig_name,
trig_val,
trig_dir,
targ_name,
targ_val,
targ_dir,
td))
def gen_meas_power(stim_file, meas_name, t_initial, t_final):
"""Creates the .meas statement for the measurement of avg power"""
# power mea cmd is different in different spice:
if OPTS.spice_name == "hspice":
power_exp = "power"
else:
power_exp = "par('(-1*v(" + str(vdd_name) + ")*I(v" + str(vdd_name) + "))')"
stim_file.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name,
power_exp,
t_initial,
t_final))
stim_file.write("\n")
def write_control(stim_file, end_time):
# UIC is needed for ngspice to converge
stim_file.write(".TRAN 5p {0}n UIC\n".format(end_time))
stim_file.write(".OPTIONS POST=1 RUNLVL=4 PROBE\n")
# create plots for all signals
stim_file.write("* probe is used for hspice/xa, while plot is used in ngspice\n")
if OPTS.debug_level>0:
if OPTS.spice_name in ["hspice","xa"]:
stim_file.write(".probe V(*)\n")
else:
stim_file.write(".plot V(*)\n")
else:
stim_file.write("*.probe V(*)\n")
stim_file.write("*.plot V(*)\n")
# end the stimulus file
stim_file.write(".end\n\n")
def inst_sram(self, abits, dbits, sram_name):
""" Function to instatiate an SRAM subckt. """
self.sf.write("Xsram ")
for i in range(dbits):
self.sf.write("D[{0}] ".format(i))
for i in range(abits):
self.sf.write("A[{0}] ".format(i))
for i in tech.spice["control_signals"]:
self.sf.write("{0} ".format(i))
self.sf.write("{0} ".format(tech.spice["clk"]))
self.sf.write("{0} {1} ".format(self.vdd_name, self.gnd_name))
self.sf.write("{0}\n".format(sram_name))
def write_include(stim_file, models):
"""Writes include statements, inputs are lists of model files"""
for item in list(models):
stim_file.write(".include \"{0}\"\n\n".format(item))
def inst_model(self, pins, model_name):
""" Function to instantiate a generic model with a set of pins """
self.sf.write("X{0} ".format(model_name))
for pin in pins:
self.sf.write("{0} ".format(pin))
self.sf.write("{0}\n".format(model_name))
def write_supply(stim_file):
"""Writes supply voltage statements"""
stim_file.write("V{0} {0} 0.0 {1}\n".format(vdd_name, vdd_voltage))
stim_file.write("V{0} {0} 0.0 {1}\n".format(gnd_name, gnd_voltage))
# This is for the test power supply
stim_file.write("V{0} {0} 0.0 {1}\n".format("test"+vdd_name, vdd_voltage))
stim_file.write("V{0} {0} 0.0 {1}\n\n".format("test"+gnd_name, gnd_voltage))
def create_inverter(self, size=1, beta=2.5):
""" Generates inverter for the top level signals (only for sim purposes) """
self.sf.write(".SUBCKT test_inv in out {0} {1}\n".format(self.vdd_name, self.gnd_name))
self.sf.write("mpinv out in {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
self.pmos_name,
beta * size * self.tx_width,
self.tx_length))
self.sf.write("mninv out in {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
self.nmos_name,
size * self.tx_width,
self.tx_length))
self.sf.write(".ENDS test_inv\n")
def run_sim():
"""Run hspice in batch mode and output rawfile to parse."""
temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
import datetime
start_time = datetime.datetime.now()
debug.check(OPTS.spice_exe!="","No spice simulator has been found.")
if OPTS.spice_name == "xa":
# Output the xa configurations here. FIXME: Move this to write it once.
xa_cfg = open("{}xa.cfg".format(OPTS.openram_temp), "w")
xa_cfg.write("set_sim_level -level 7\n")
xa_cfg.write("set_powernet_level 7 -node vdd\n")
xa_cfg.close()
cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt 20".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
elif OPTS.spice_name == "hspice":
# TODO: Should make multithreading parameter a configuration option
cmd = "{0} -mt 2 -i {1} -o {2}timing".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
else:
cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
# for some reason, ngspice-25 returns 1 when it only has acceptable warnings
valid_retcode=1
def create_buffer(self, buffer_name, size=[1,3], beta=2.5):
"""
Generates buffer for top level signals (only for sim
purposes). Size is pair for PMOS, NMOS width multiple.
"""
self.sf.write(".SUBCKT test_{2} in out {0} {1}\n".format(self.vdd_name,
self.gnd_name,
buffer_name))
self.sf.write("mpinv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
self.pmos_name,
beta * size[0] * self.tx_width,
self.tx_length))
self.sf.write("mninv1 out_inv in {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
self.nmos_name,
size[0] * self.tx_width,
self.tx_length))
self.sf.write("mpinv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(self.vdd_name,
self.pmos_name,
beta * size[1] * self.tx_width,
self.tx_length))
self.sf.write("mninv2 out out_inv {0} {0} {1} w={2}u l={3}u\n".format(self.gnd_name,
self.nmos_name,
size[1] * self.tx_width,
self.tx_length))
self.sf.write(".ENDS test_{0}\n\n".format(buffer_name))
def inst_buffer(self, buffer_name, signal_list):
""" Adds buffers to each top level signal that is in signal_list (only for sim purposes) """
for signal in signal_list:
self.sf.write("X{0}_buffer {0} {0}_buf {1} {2} test_{3}\n".format(signal,
"test"+self.vdd_name,
"test"+self.gnd_name,
buffer_name))
def inst_inverter(self, signal_list):
""" Adds inv for each signal that needs its inverted version (only for sim purposes) """
for signal in signal_list:
self.sf.write("X{0}_inv {0} {0}_inv {1} {2} test_inv\n".format(signal,
"test"+self.vdd_name,
"test"+self.gnd_name))
spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
def inst_accesstx(self, dbits):
""" Adds transmission gate for inputs to data-bus (only for sim purposes) """
self.sf.write("* Tx Pin-list: Drain Gate Source Body\n")
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"
self.sf.write(pmos_access_string.format(i,
"test"+self.vdd_name,
self.pmos_name,
2 * self.tx_width,
self.tx_length))
nmos_access_string="mn{0} DATA[{0}] acc_en_inv D[{0}] {1} {2} w={3}u l={4}u\n"
self.sf.write(nmos_access_string.format(i,
"test"+self.gnd_name,
self.nmos_name,
2 * self.tx_width,
self.tx_length))
debug.info(3, cmd)
retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
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
from 50% to 50%.
"""
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"
self.sf.write(pulse_string.format(sig_name,
v1,
v2,
offset,
t_rise,
t_fall,
0.5*period-0.5*t_rise-0.5*t_fall,
period))
spice_stdout.close()
spice_stderr.close()
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.
Automatically creates slews and ensures each data occurs a setup before the clock
edge. The first clk_time should be 0 and is the initial time that corresponds
to the initial value.
"""
# the initial value is not a clock time
debug.check(len(clk_times)==len(data_values),"Clock and data value lengths don't match.")
if (retcode > valid_retcode):
debug.error("Spice simulation error: " + cmd, -1)
else:
end_time = datetime.datetime.now()
delta_time = round((end_time-start_time).total_seconds(),1)
debug.info(2,"*** Spice: {} seconds".format(delta_time))
# shift signal times earlier for setup time
times = np.array(clk_times) - setup*period
values = np.array(data_values) * self.voltage
half_slew = 0.5 * slew
self.sf.write("* (time, data): {}\n".format(zip(clk_times, data_values)))
self.sf.write("V{0} {0} 0 PWL (0n {1}v ".format(sig_name, values[0]))
for i in range(1,len(times)):
self.sf.write("{0}n {1}v {2}n {3}v ".format(times[i]-half_slew,
values[i-1],
times[i]+half_slew,
values[i]))
self.sf.write(")\n")
def gen_constant(self, sig_name, v_val):
""" Generates a constant signal with reference voltage and the voltage value """
self.sf.write("V{0} {0} 0 DC {1}\n".format(sig_name, v_val))
def get_inverse_voltage(self, value):
if value > 0.5*self.voltage:
return 0
elif value <= 0.5*self.voltage:
return self.voltage
else:
debug.error("Invalid value to get an inverse of: {0}".format(value))
def get_inverse_value(self, value):
if value > 0.5:
return 0
elif value <= 0.5:
return 1
else:
debug.error("Invalid value to get an inverse of: {0}".format(value))
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 """
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"
self.sf.write(measure_string.format(meas_name,
trig_name,
trig_val,
trig_dir,
trig_td,
targ_name,
targ_val,
targ_dir,
targ_td))
def gen_meas_power(self, meas_name, t_initial, t_final):
""" Creates the .meas statement for the measurement of avg power """
# power mea cmd is different in different spice:
if OPTS.spice_name == "hspice":
power_exp = "power"
else:
power_exp = "par('(-1*v(" + str(self.vdd_name) + ")*I(v" + str(self.vdd_name) + "))')"
self.sf.write(".meas tran {0} avg {1} from={2}n to={3}n\n\n".format(meas_name,
power_exp,
t_initial,
t_final))
def write_control(self, end_time):
""" Write the control cards to run and end the simulation """
# UIC is needed for ngspice to converge
self.sf.write(".TRAN 5p {0}n UIC\n".format(end_time))
if OPTS.spice_name == "ngspice":
# ngspice sometimes has convergence problems if not using gear 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
# unless you figure out what these are.
self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE method=gear TEMP={}\n".format(self.temperature))
else:
self.sf.write(".OPTIONS POST=1 RUNLVL=4 PROBE TEMP={}\n".format(self.temperature))
# create plots for all signals
self.sf.write("* probe is used for hspice/xa, while plot is used in ngspice\n")
if OPTS.debug_level>0:
if OPTS.spice_name in ["hspice","xa"]:
self.sf.write(".probe V(*)\n")
else:
self.sf.write(".plot V(*)\n")
else:
self.sf.write("*.probe V(*)\n")
self.sf.write("*.plot V(*)\n")
# end the stimulus file
self.sf.write(".end\n\n")
def write_include(self, circuit):
"""Writes include statements, inputs are lists of model files"""
includes = self.device_models + [circuit]
self.sf.write("* {} process corner\n".format(self.process))
for item in list(includes):
if os.path.isfile(item):
self.sf.write(".include \"{0}\"\n".format(item))
else:
debug.error("Could not find spice model: {0}\nSet SPICE_MODEL_DIR to over-ride path.\n".format(item))
def write_supply(self):
""" Writes supply voltage statements """
self.sf.write("V{0} {0} 0.0 {1}\n".format(self.vdd_name, self.voltage))
self.sf.write("V{0} {0} 0.0 {1}\n".format(self.gnd_name, 0))
# This is for the test power supply
self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.vdd_name, self.voltage))
self.sf.write("V{0} {0} 0.0 {1}\n".format("test"+self.gnd_name, 0))
def run_sim(self):
""" Run hspice in batch mode and output rawfile to parse. """
temp_stim = "{0}stim.sp".format(OPTS.openram_temp)
import datetime
start_time = datetime.datetime.now()
debug.check(OPTS.spice_exe!="","No spice simulator has been found.")
if OPTS.spice_name == "xa":
# Output the xa configurations here. FIXME: Move this to write it once.
xa_cfg = open("{}xa.cfg".format(OPTS.openram_temp), "w")
xa_cfg.write("set_sim_level -level 7\n")
xa_cfg.write("set_powernet_level 7 -node vdd\n")
xa_cfg.close()
cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt 2".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
elif OPTS.spice_name == "hspice":
# TODO: Should make multithreading parameter a configuration option
cmd = "{0} -mt 2 -i {1} -o {2}timing".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
else:
cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp)
# for some reason, ngspice-25 returns 1 when it only has acceptable warnings
valid_retcode=1
spice_stdout = open("{0}spice_stdout.log".format(OPTS.openram_temp), 'w')
spice_stderr = open("{0}spice_stderr.log".format(OPTS.openram_temp), 'w')
debug.info(3, cmd)
retcode = subprocess.call(cmd, stdout=spice_stdout, stderr=spice_stderr, shell=True)
spice_stdout.close()
spice_stderr.close()
if (retcode > valid_retcode):
debug.error("Spice simulation error: " + cmd, -1)
else:
end_time = datetime.datetime.now()
delta_time = round((end_time-start_time).total_seconds(),1)
debug.info(2,"*** Spice: {} seconds".format(delta_time))

View File

@ -45,27 +45,38 @@ class trim_spice():
# Always start fresh if we do multiple reductions
self.sp_buffer = self.spice
# Find the row and column indices for the removals
# Convert address froms tring to int
address = int(address,2)
array_row = address >> self.col_addr_size
# Which word in the array (0 if only one word)
if self.col_addr_size>0:
lower_mask = int(self.col_addr_size-1)
lower_address = address & lower_mask
else:
lower_address=0
# Which bit in the array
array_bit = lower_address*self.word_size + data_bit
# Split up the address and convert to an int
wl_address = int(address[self.col_addr_size:],2)
if self.col_addr_size>1:
col_address = int(address[0:self.col_addr_size],2)
else:
col_address = 0
# 1. Keep cells in the bitcell array based on WL and BL
wl_name = "wl[{}]".format(array_row)
bl_name = "bl[{}]".format(array_bit)
wl_name = "wl[{}]".format(wl_address)
bl_name = "bl[{}]".format(self.words_per_row*data_bit + col_address)
# Prepend info about the trimming
addr_msg = "Keeping {} address".format(address)
self.sp_buffer.insert(0, "* "+addr_msg)
debug.info(1,addr_msg)
data_msg = "Keeping {} data bit".format(data_bit)
self.sp_buffer.insert(0, "* "+data_msg)
debug.info(1,data_msg)
bl_msg = "Keeping {} (trimming other BLs)".format(bl_name)
wl_msg = "Keeping {} (trimming other WLs)".format(wl_name)
self.sp_buffer.insert(0, "* "+bl_msg)
debug.info(1,bl_msg)
self.sp_buffer.insert(0, "* "+wl_msg)
debug.info(1,wl_msg)
self.sp_buffer.insert(0, "* It should NOT be used for LVS!!")
self.sp_buffer.insert(0, "* WARNING: This is a TRIMMED NETLIST.")
self.remove_insts("bitcell_array",[wl_name,bl_name])
# 2. Keep sense amps basd on BL
self.remove_insts("sense_amp_array",[bl_name])
# FIXME: The bit lines are not indexed the same in sense_amp_array
#self.remove_insts("sense_amp_array",[bl_name])
# 3. Keep column muxes basd on BL
self.remove_insts("column_mux_array",[bl_name])

View File

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

View File

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

View File

@ -11,20 +11,11 @@ import sys
import re
import importlib
# Current version of OpenRAM.
VERSION = "1.01"
USAGE = "Usage: openram.py [options] <config file>\nUse -h for help.\n"
# Anonymous object that will be the 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():
""" Parse the optional arguments for OpenRAM """
@ -39,8 +30,6 @@ def parse_args():
help="Output file(s) location"),
optparse.make_option("-n", "--nocheck", action="store_false",
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",
help="Increase the verbosity level"),
optparse.make_option("-t", "--tech", dest="tech_name",
@ -50,14 +39,16 @@ def parse_args():
optparse.make_option("-r", "--remove_netlist_trimming", action="store_false", dest="trim_netlist",
help="Disable removal of noncritical memory cells during characterization"),
optparse.make_option("-c", "--characterize", action="store_false", dest="analytical_delay",
help="Perform characterization to calculate delays (default is analytical models)")
help="Perform characterization to calculate delays (default is analytical models)"),
optparse.make_option("-d", "--dontpurge", action="store_false", dest="purge_temp",
help="Don't purge the contents of the temp directory after a successful run")
# -h --help is implicit.
}
parser = optparse.OptionParser(option_list=option_list,
description="Compile and/or characterize an SRAM.",
usage=USAGE,
version="OpenRAM v" + VERSION)
version="OpenRAM")
(options, args) = parser.parse_args(values=OPTS)
# If we don't specify a tech, assume freepdk45.
@ -67,17 +58,17 @@ def parse_args():
# Alias SCMOS to AMI 0.5um
if OPTS.tech_name == "scmos":
OPTS.tech_name = "scn3me_subm"
return (options, args)
def print_banner():
""" Conditionally print the banner to stdout """
global OPTS
if not OPTS.print_banner:
if OPTS.is_unit_test:
return
print("|==============================================================================|")
name = "OpenRAM Compiler v"+VERSION
name = "OpenRAM Compiler"
print("|=========" + name.center(60) + "=========|")
print("|=========" + " ".center(60) + "=========|")
print("|=========" + "VLSI Design and Automation Lab".center(60) + "=========|")
@ -86,22 +77,41 @@ def print_banner():
print("|=========" + "VLSI Computer Architecture Research Group".center(60) + "=========|")
print("|=========" + "Oklahoma State University ECE Department".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("|==============================================================================|")
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."""
check_versions()
debug.info(1,"Initializing OpenRAM...")
setup_paths()
read_config(config_file)
read_config(config_file, is_unit_test)
import_tech()
def get_tool(tool_type, preferences):
"""
Find which tool we have from a list of preferences and return the
@ -121,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
config file is just a Python file that defines some config
@ -159,6 +169,16 @@ def read_config(config_file):
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!
# make the directory if it doesn't exist
try:
@ -174,17 +194,17 @@ def read_config(config_file):
def end_openram():
""" Clean up openram for a proper exit """
cleanup_paths()
# Reset the static duplicate name checker for unit tests.
# This is needed for running unit tests.
import design
design.design.name_map=[]
def cleanup_paths():
"""
We should clean up the temp directory after execution.
"""
if not OPTS.purge_temp:
debug.info(0,"Preserving temp directory: {}".format(OPTS.openram_temp))
return
if os.path.exists(OPTS.openram_temp):
shutil.rmtree(OPTS.openram_temp, ignore_errors=True)
@ -199,16 +219,14 @@ def setup_paths():
except:
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+"/gdsMill"),
"$OPENRAM_HOME/gdsMill does not exist: {0}".format(OPENRAM_HOME+"/gdsMill"))
sys.path.append("{0}/gdsMill".format(OPENRAM_HOME))
debug.check(os.path.isdir(OPENRAM_HOME+"/tests"),
"$OPENRAM_HOME/tests does not exist: {0}".format(OPENRAM_HOME+"/tests"))
sys.path.append("{0}/tests".format(OPENRAM_HOME))
debug.check(os.path.isdir(OPENRAM_HOME+"/router"),
"$OPENRAM_HOME/router does not exist: {0}".format(OPENRAM_HOME+"/router"))
sys.path.append("{0}/router".format(OPENRAM_HOME))
# Add all of the subdirs to the python path
# These subdirs are modules and don't need to be added: characterizer, verify
for subdir in ["gdsMill", "tests", "router", "modules", "base", "pgates"]:
full_path = "{0}/{1}".format(OPENRAM_HOME,subdir)
debug.check(os.path.isdir(full_path),
"$OPENRAM_HOME/{0} does not exist: {1}".format(subdir,full_path))
sys.path.append("{0}".format(full_path))
if not OPTS.openram_temp.endswith('/'):
OPTS.openram_temp += "/"
@ -246,9 +264,8 @@ def import_tech():
# Set the tech to the config file we read in instead of the command line value.
OPTS.tech_name = OPTS.tech_name
# environment variable should point to the technology dir
# environment variable should point to the technology dir
try:
OPENRAM_TECH = os.path.abspath(os.environ.get("OPENRAM_TECH"))
except:
@ -272,3 +289,43 @@ def import_tech():
debug.error("Nonexistent technology_setup_file: {0}.py".format(filename))
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("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(OPTS.word_size,
OPTS.num_words,
OPTS.num_banks))
if not OPTS.check_lvsdrc:
print("DRC/LVS/PEX checking is disabled.")

View File

@ -99,8 +99,10 @@ class bank(design.design):
self.add_precharge_array()
if self.col_addr_size > 0:
# The m2 width is because the 6T cell may have vias on the boundary edge for
# overlapping when making the array
self.column_mux_height = self.column_mux_array.height + 0.5*self.m2_width
self.add_column_mux_array()
self.column_mux_height = self.column_mux_array.height
else:
self.column_mux_height = 0
if self.col_addr_size > 1: # size 1 is from addr FF
@ -249,7 +251,7 @@ class bank(design.design):
def add_column_mux_array(self):
""" Adding Column Mux when words_per_row > 1 . """
y_offset = self.column_mux_array.height
y_offset = self.column_mux_height
self.col_mux_array_inst=self.add_inst(name="column_mux_array",
mod=self.column_mux_array,
offset=vector(0,y_offset).scale(-1,-1))
@ -434,7 +436,8 @@ class bank(design.design):
# Place the col decoder just to the left of the control bus
x_off = self.m2_pitch + self.overall_central_bus_width + self.col_decoder.width
gap = max(drc["pwell_to_nwell"], 2*self.m2_pitch)
x_off = gap + self.overall_central_bus_width + self.col_decoder.width
# Place the col decoder below the the address flops which are below the row decoder (lave some space for wells)
vertical_gap = max(drc["pwell_to_nwell"], 2*self.m2_pitch)
y_off = self.decoder.predecoder_height + self.msf_address.width + self.col_decoder.height + 2*vertical_gap

View File

@ -68,7 +68,10 @@ class control_logic(design.design):
c = reload(__import__(OPTS.replica_bitline))
replica_bitline = getattr(c, OPTS.replica_bitline)
self.replica_bitline = replica_bitline(rows=int(math.ceil(self.num_rows / 10.0)))
# FIXME: These should be tuned according to the size!
FO4_stages = 8
bitcell_loads = int(math.ceil(self.num_rows / 10.0))
self.replica_bitline = replica_bitline(FO4_stages, bitcell_loads)
self.add_mod(self.replica_bitline)
@ -77,8 +80,6 @@ class control_logic(design.design):
# These aren't for instantiating, but we use them to get the dimensions
self.poly_contact_offset = vector(0.5*contact.poly.width,0.5*contact.poly.height)
# For different layer width vias
self.m1m2_offset_fix = vector(0,0.5*(drc["minwidth_metal2"]-drc["minwidth_metal1"]))
# M1/M2 routing pitch is based on contacted pitch
self.m1_pitch = max(contact.m1m2.width,contact.m1m2.height) + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"])
self.m2_pitch = max(contact.m2m3.width,contact.m2m3.height) + max(drc["metal2_to_metal2"],drc["metal3_to_metal3"])
@ -87,10 +88,6 @@ class control_logic(design.design):
# Some cells may have pwell/nwell spacing problems too when the wells are different heights.
self.cell_gap = max(self.m2_pitch,drc["pwell_to_nwell"])
# Amount to shift a 90 degree rotated via from center-line path routing to it's offset
self.m1m2_via_offset = vector(contact.m1m2.first_layer_height,-0.5*drc["minwidth_metal2"])
self.m2m3_via_offset = vector(contact.m2m3.first_layer_height,-0.5*drc["minwidth_metal3"])
# First RAIL Parameters: gnd, oe, oebar, cs, we, clk_buf, clk_bar
self.rail_1_start_x = 0
self.num_rails_1 = 8
@ -326,6 +323,7 @@ class control_logic(design.design):
x_off += self.inv1.width
# BUFFER INVERTERS FOR W_EN
# FIXME: Can we remove these two invs and size the previous one?
self.pre_w_en_bar_offset = vector(x_off, y_off)
self.pre_w_en_bar=self.add_inst(name="inv_pre_w_en_bar",
mod=self.inv1,
@ -512,11 +510,25 @@ class control_logic(design.design):
offset=clk_buf_rail_position,
rotate=90)
# clk_bar
self.connect_rail_from_left_m2m3(self.clk_bar,"Z","clk_bar")
# clk_bar, routes over the clock buffer vdd rail
clk_pin = self.clk_bar.get_pin("Z")
vdd_pin = self.clk_bar.get_pin("vdd")
# move the output pin up to metal2
self.add_via_center(layers=("metal1","via1","metal2"),
offset=self.clk_bar.get_pin("Z").rc(),
offset=clk_pin.rc(),
rotate=90)
# route to a position over the supply rail
in_pos = vector(clk_pin.rx(), vdd_pin.cy())
self.add_path("metal2",[clk_pin.rc(), in_pos])
# connect that position to the control bus
rail_pos = vector(self.rail_1_x_offsets["clk_bar"], in_pos.y)
self.add_wire(("metal3","via2","metal2"),[in_pos, rail_pos])
self.add_via_center(layers=("metal2","via2","metal3"),
offset=in_pos,
rotate=90)
self.add_via_center(layers=("metal2","via2","metal3"),
offset=rail_pos,
rotate=90)
# clk_buf to msf control flops
msf_clk_pos = self.msf_inst.get_pin("clk").bc()

View File

@ -8,7 +8,8 @@ from globals import OPTS
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.
"""

View File

@ -250,9 +250,9 @@ class hierarchical_predecode(design.design):
index_lst= nand_input_line_combination[k]
if self.number_of_inputs == 2:
gate_lst = ["B","A"]
gate_lst = ["A","B"]
else:
gate_lst = ["C","B","A"]
gate_lst = ["A","B","C"]
# this will connect pins A,B or A,B,C
for rail_pin,gate_pin in zip(index_lst,gate_lst):

View File

@ -27,10 +27,10 @@ class hierarchical_predecode2x4(hierarchical_predecode):
self.create_rails()
self.add_input_inverters()
self.add_output_inverters()
connections =[["in[0]", "in[1]", "Z[3]", "vdd", "gnd"],
["inbar[0]", "in[1]", "Z[2]", "vdd", "gnd"],
connections =[["inbar[0]", "inbar[1]", "Z[0]", "vdd", "gnd"],
["in[0]", "inbar[1]", "Z[1]", "vdd", "gnd"],
["inbar[0]", "inbar[1]", "Z[0]", "vdd", "gnd"]]
["inbar[0]", "in[1]", "Z[2]", "vdd", "gnd"],
["in[0]", "in[1]", "Z[3]", "vdd", "gnd"]]
self.add_nand(connections)
self.route()

View File

@ -29,13 +29,13 @@ class precharge(pgate.pgate):
self.DRC_LVS()
def add_pins(self):
self.add_pin_list(["bl", "br", "clk", "vdd"])
self.add_pin_list(["bl", "br", "en", "vdd"])
def create_layout(self):
self.create_ptx()
self.add_ptx()
self.connect_poly()
self.add_pclk()
self.add_en()
self.add_nwell_and_contact()
self.add_vdd_rail()
self.add_bitlines()
@ -74,7 +74,7 @@ class precharge(pgate.pgate):
self.lower_pmos_inst=self.add_inst(name="lower_pmos",
mod=self.pmos,
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
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",
mod=self.pmos,
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
self.upper_pmos2_inst=self.add_inst(name="upper_pmos2",
mod=self.pmos,
offset=upper_pmos2_pos)
self.connect_inst(["br", "clk", "vdd", "vdd"])
self.connect_inst(["br", "en", "vdd", "vdd"])
def connect_poly(self):
"""Connects the upper and lower pmos together"""
@ -109,16 +109,16 @@ class precharge(pgate.pgate):
width=xlength,
height=self.poly_width)
def add_pclk(self):
"""Adds the pclk input rail, pclk contact/vias, and connects to the pmos"""
# adds the pclk contact to connect the gates to the pclk rail on metal1
def add_en(self):
"""Adds the en input rail, en contact/vias, and connects to the pmos"""
# 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)
self.add_contact_center(layers=("poly", "contact", "metal1"),
offset=offset,
rotate=90)
# adds the pclk rail on metal1
self.add_layout_pin_center_segment(text="clk",
# adds the en rail on metal1
self.add_layout_pin_center_segment(text="en",
layer="metal1",
start=offset.scale(0,1),
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",
layer="metal1",
offset=self.pc_cell.get_pin("clk").ll(),
offset=self.pc_cell.get_pin("en").ll(),
width=self.width,
height=drc["minwidth_metal1"])

View File

@ -10,12 +10,12 @@ from globals import OPTS
class replica_bitline(design.design):
"""
Generate a module that simulate the delay of control logic
and bit line charging.
Used for memory timing control
Generate a module that simulates the delay of control logic
and bit line charging. Stages is the depth of the FO4 delay
line and rows is the height of the replica bit loads.
"""
def __init__(self, rows, name="replica_bitline"):
def __init__(self, FO4_stages, bitcell_loads, name="replica_bitline"):
design.design.__init__(self, name)
g = reload(__import__(OPTS.delay_chain))
@ -29,7 +29,8 @@ class replica_bitline(design.design):
for pin in ["en", "out", "vdd", "gnd"]:
self.add_pin(pin)
self.rows = rows
self.bitcell_loads = bitcell_loads
self.FO4_stages = FO4_stages
self.create_modules()
self.calculate_module_offsets()
@ -78,10 +79,11 @@ class replica_bitline(design.design):
self.add_mod(self.bitcell)
# This is the replica bitline load column that is the height of our array
self.rbl = bitcell_array(name="bitline_load", cols=1, rows=self.rows)
self.rbl = bitcell_array(name="bitline_load", cols=1, rows=self.bitcell_loads)
self.add_mod(self.rbl)
self.delay_chain = self.mod_delay_chain([1, 1, 1])
# FIXME: The FO and depth of this should be tuned
self.delay_chain = self.mod_delay_chain([4]*self.FO4_stages)
self.add_mod(self.delay_chain)
self.inv = pinv()
@ -123,7 +125,7 @@ class replica_bitline(design.design):
self.rbl_inst=self.add_inst(name="load",
mod=self.rbl,
offset=self.rbl_offset)
self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.rows + ["vdd", "gnd"])
self.connect_inst(["bl[0]", "br[0]"] + ["gnd"]*self.bitcell_loads + ["vdd", "gnd"])
@ -239,56 +241,61 @@ class replica_bitline(design.design):
def route_gnd(self):
""" Route all signals connected to gnd """
# Add a rail in M1 from bottom to two along delay chain
gnd_start = self.rbl_inv_inst.get_pin("gnd").ll() - self.offset_fix
gnd_start = self.rbl_inv_inst.get_pin("gnd").bc()
gnd_end = vector(gnd_start.x, self.rbl_inst.uy()+2*self.m2_pitch)
# It is the height of the entire RBL and bitcell
self.add_rect(layer="metal2",
offset=gnd_start,
width=self.m2_width,
height=self.rbl.height+self.bitcell.height+self.inv.width+self.m2_pitch)
self.add_layout_pin(text="gnd",
layer="metal1",
offset=gnd_start.scale(1,0),
width=self.m2_width,
height=2*self.inv.width)
# Add a rail in M1 from bottom of delay chain to two above the RBL
# This prevents DRC errors with vias for the WL
dc_top = self.dc_inst.ur()
self.add_segment_center(layer="metal1",
start=vector(gnd_start.x, dc_top.y),
end=gnd_end)
# Add a rail in M2 from RBL inverter to two above the RBL
self.add_segment_center(layer="metal2",
start=gnd_start,
end=gnd_end)
# Add pin from bottom to RBL inverter
self.add_layout_pin_center_segment(text="gnd",
layer="metal1",
start=gnd_start.scale(1,0),
end=gnd_start)
# Connect the WL pins directly to gnd
for row in range(self.rows):
gnd_pin = self.get_pin("gnd").rc()
for row in range(self.bitcell_loads):
wl = "wl[{}]".format(row)
pin = self.rbl_inst.get_pin(wl)
offset = vector(gnd_start.x,pin.by())
self.add_rect(layer="metal1",
offset=offset,
width=self.rbl_offset.x-gnd_start.x,
height=self.m1_width)
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset)
start = vector(gnd_pin.x,pin.cy())
self.add_segment_center(layer="metal1",
start=start,
end=pin.lc())
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=start)
# Add via for the delay chain
offset = self.delay_chain_offset - vector(0.5*self.m1_width,0) - self.offset_fix
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset)
offset = self.dc_inst.get_pins("gnd")[0].bc() + vector(0.5*contact.m1m2.width,0.5*contact.m1m2.height)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=offset)
# Add via for the inverter
offset = self.rbl_inv_offset - vector(0.5*self.m1_width,contact.m1m2.height) - self.offset_fix
self.add_via(layers=("metal1", "via1", "metal2"),
offset=offset)
offset = self.rbl_inv_inst.get_pin("gnd").bc() - vector(0,0.5*contact.m1m2.height)
self.add_via_center(layers=("metal1", "via1", "metal2"),
offset=offset)
# Connect the bitcell gnd pin to the rail
# Connect the bitcell gnd pins to the rail
gnd_pins = self.get_pins("gnd")
gnd_start = gnd_pins[0].uc()
gnd_start = gnd_pins[0].ul()
rbl_gnd_pins = self.rbl_inst.get_pins("gnd")
# Find the left most rail on M2
gnd_pin = None
# Add L shapes to each vertical gnd rail
for pin in rbl_gnd_pins:
if gnd_pin == None or (pin.layer=="metal2" and pin.lx()<gnd_pin.lx()):
gnd_pin = pin
gnd_end = gnd_pin.uc()
# Add a couple midpoints so that the wire will drop a via and then route horizontal on M1
gnd_mid1 = gnd_start + vector(0,self.m2_pitch)
gnd_mid2 = gnd_end + vector(0,self.m2_pitch)
self.add_wire(("metal1","via1","metal2"), [gnd_start, gnd_mid1, gnd_mid2, gnd_end])
if pin.layer != "metal2":
continue
gnd_end = pin.uc()
gnd_mid = vector(gnd_end.x, gnd_start.y)
self.add_wire(("metal1","via1","metal2"), [gnd_start, gnd_mid, gnd_end])
gnd_start = gnd_mid
# Add a second gnd pin to the second delay chain rail. No need for full length.

View File

@ -12,9 +12,10 @@ class single_level_column_mux(design.design):
Creates a single columnmux cell.
"""
def __init__(self, name, tx_size):
def __init__(self, tx_size):
name="single_level_column_mux_{}".format(tx_size)
design.design.__init__(self, name)
debug.info(2, "create single columnmux cell: {0}".format(name))
debug.info(2, "create single column mux cell: {0}".format(name))
c = reload(__import__(OPTS.bitcell))
self.mod_bitcell = getattr(c, OPTS.bitcell)
@ -27,9 +28,9 @@ class single_level_column_mux(design.design):
def create_layout(self):
self.add_ptx()
self.pin_height = 2*self.m2_width
self.width = self.bitcell.width
self.height = self.nmos2.uy()
self.height = self.nmos2.uy() + self.pin_height
self.connect_poly()
self.add_gnd_rail()
self.add_bitline_pins()
@ -42,26 +43,25 @@ class single_level_column_mux(design.design):
bl_pos = vector(self.bitcell.get_pin("BL").lx(), 0)
br_pos = vector(self.bitcell.get_pin("BR").lx(), 0)
pin_height = 2*self.m2_width
# bl and br
self.add_layout_pin(text="bl",
layer="metal2",
offset=bl_pos + vector(0,self.height - pin_height),
height=pin_height)
offset=bl_pos + vector(0,self.height - self.pin_height),
height=self.pin_height)
self.add_layout_pin(text="br",
layer="metal2",
offset=br_pos + vector(0,self.height - pin_height),
height=pin_height)
offset=br_pos + vector(0,self.height - self.pin_height),
height=self.pin_height)
# bl_out and br_out
self.add_layout_pin(text="bl_out",
layer="metal2",
offset=bl_pos,
height=pin_height)
height=self.pin_height)
self.add_layout_pin(text="br_out",
layer="metal2",
offset=br_pos,
height=pin_height)
height=self.pin_height)
def add_ptx(self):

View File

@ -40,26 +40,28 @@ class single_level_column_mux_array(design.design):
self.setup_layout_constants()
self.create_array()
self.add_routing()
# Find the highest shapes to determine height before adding well
highest = self.find_highest_coords()
self.height = highest.y
self.add_layout_pins()
self.add_enclosure(self.mux_inst, "pwell")
def add_modules(self):
self.mux = single_level_column_mux(name="single_level_column_mux",
tx_size=8)
# FIXME: Why is this 8x?
self.mux = single_level_column_mux(tx_size=8)
self.add_mod(self.mux)
def setup_layout_constants(self):
self.column_addr_size = num_of_inputs = int(self.words_per_row / 2)
self.width = self.columns * self.mux.width
self.m1_pitch = contact.m1m2.width + max(drc["metal1_to_metal1"],drc["metal2_to_metal2"])
# To correct the offset between M1 and M2 via enclosures
self.offset_fix = vector(0,0.5*(drc["minwidth_metal2"]-drc["minwidth_metal1"]))
# one set of metal1 routes for select signals and a pair to interconnect the mux outputs bl/br
# one extra route pitch is to space from the sense amp
self.route_height = (self.words_per_row + 3)*self.m1_pitch
# mux height plus routing signal height plus well spacing at the top
self.height = self.mux.height + self.route_height + drc["pwell_to_nwell"]
def create_array(self):
@ -72,28 +74,6 @@ class single_level_column_mux_array(design.design):
self.mux_inst.append(self.add_inst(name=name,
mod=self.mux,
offset=x_off))
offset = self.mux_inst[-1].get_pin("bl").ll()
self.add_layout_pin(text="bl[{}]".format(col_num),
layer="metal2",
offset=offset,
height=self.height-offset.y)
offset = self.mux_inst[-1].get_pin("br").ll()
self.add_layout_pin(text="br[{}]".format(col_num),
layer="metal2",
offset=offset,
height=self.height-offset.y)
gnd_pins = self.mux_inst[-1].get_pins("gnd")
for gnd_pin in gnd_pins:
# only do even colums to avoid duplicates
offset = gnd_pin.ll()
if col_num % 2 == 0:
self.add_layout_pin(text="gnd",
layer="metal2",
offset=offset.scale(1,0),
height=self.height)
self.connect_inst(["bl[{}]".format(col_num),
"br[{}]".format(col_num),
@ -102,7 +82,34 @@ class single_level_column_mux_array(design.design):
"sel[{}]".format(col_num % self.words_per_row),
"gnd"])
def add_layout_pins(self):
""" Add the pins after we determine the height. """
# For every column, add a pass gate
for col_num in range(self.columns):
mux_inst = self.mux_inst[col_num]
offset = mux_inst.get_pin("bl").ll()
self.add_layout_pin(text="bl[{}]".format(col_num),
layer="metal2",
offset=offset,
height=self.height-offset.y)
offset = mux_inst.get_pin("br").ll()
self.add_layout_pin(text="br[{}]".format(col_num),
layer="metal2",
offset=offset,
height=self.height-offset.y)
gnd_pins = mux_inst.get_pins("gnd")
for gnd_pin in gnd_pins:
# only do even colums to avoid duplicates
offset = gnd_pin.ll()
if col_num % 2 == 0:
self.add_layout_pin(text="gnd",
layer="metal2",
offset=offset.scale(1,0),
height=self.height)
def add_routing(self):
self.add_horizontal_input_rail()

View File

@ -14,116 +14,47 @@ import sys,os
import datetime
import re
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.
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
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))
# Output info about this run
report_status()
if not OPTS.tech_name:
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
# Start importing design modules after we have the config file
import verify
import sram
# Keep track of running stats
start_time = datetime.datetime.now()
last_time = start_time
print_time("Start",datetime.datetime.now())
if not OPTS.check_lvsdrc:
print("DRC/LVS/PEX checking is disabled.")
print_time("Start",start_time)
# import SRAM test generation
s = sram.sram(word_size=word_size,
num_words=num_words,
num_banks=num_banks,
s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
name=OPTS.output_name)
last_time=print_time("SRAM creation", datetime.datetime.now(), last_time)
# Output the files for the resulting SRAM
s.save_output()
spname = OPTS.output_path + s.name + ".sp"
print("SP: Writing to {0}".format(spname))
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()
# Delete temp files etc.
end_openram()
print_time("End",datetime.datetime.now(), start_time)

View File

@ -39,9 +39,20 @@ class options(optparse.Values):
# Define the output file paths
output_path = "."
# Define the output file base name
output_name = "sram"
output_name = ""
# Use analytical delay models by default rather than (slow) characterization
analytical_delay = True
# Purge the temp directory after a successful run (doesn't purge on errors, anyhow)
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
decoder = "hierarchical_decoder"

View File

@ -63,10 +63,15 @@ class ptx(design.design):
# self.spice.append("\n.SUBCKT {0} {1}".format(self.name,
# " ".join(self.pins)))
self.spice_device="M{{0}} {{1}} {0} m={1} w={2}u l={3}u".format(spice[self.tx_type],
self.mults,
self.tx_width,
drc["minwidth_poly"])
# Just make a guess since these will actually be decided in the layout later.
area_sd = 2.5*drc["minwidth_poly"]*self.tx_width
perimeter_sd = 2*drc["minwidth_poly"] + 2*self.tx_width
self.spice_device="M{{0}} {{1}} {0} m={1} w={2}u l={3}u pd={4}u ps={4}u as={5}p ad={5}p".format(spice[self.tx_type],
self.mults,
self.tx_width,
drc["minwidth_poly"],
perimeter_sd,
area_sd)
self.spice.append("\n* ptx " + self.spice_device)
# self.spice.append(".ENDS {0}".format(self.name))

View File

@ -8,7 +8,7 @@ from bank import bank
import datetime
import getpass
from vector import vector
from globals import OPTS
from globals import OPTS, print_time
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,
self.num_words))
start_time = datetime.datetime.now()
design.design.__init__(self, name)
@ -72,7 +73,11 @@ class sram(design.design):
self.width = sizes[0]
self.height = sizes[1]
self.DRC_LVS()
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):
""" Computes the organization of the memory using bitcell size by trying to make it square."""
@ -650,7 +655,7 @@ class sram(design.design):
# Connect the output bar to select 0
msb_out_pin = self.msb_address_inst.get_pin("dout_bar[0]")
msb_out_pos = msb_out_pin.rc()
out_extend_right_pos = msb_out_pos + vector(self.m2_pitch,0)
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
out_extend_up_pos = out_extend_right_pos + vector(0,self.m2_width)
rail_pos = vector(self.vert_control_bus_positions["bank_sel[0]"].x,out_extend_up_pos.y)
self.add_path("metal2",[msb_out_pos,out_extend_right_pos,out_extend_up_pos])
@ -660,7 +665,7 @@ class sram(design.design):
# Connect the output to select 1
msb_out_pin = self.msb_address_inst.get_pin("dout[0]")
msb_out_pos = msb_out_pin.rc()
out_extend_right_pos = msb_out_pos + vector(self.m2_pitch,0)
out_extend_right_pos = msb_out_pos + vector(2*self.m2_pitch,0)
out_extend_down_pos = out_extend_right_pos - vector(0,2*self.m1_pitch)
rail_pos = vector(self.vert_control_bus_positions["bank_sel[1]"].x,out_extend_down_pos.y)
self.add_path("metal2",[msb_out_pos,out_extend_right_pos,out_extend_down_pos])
@ -989,7 +994,13 @@ class sram(design.design):
############################################################
sp = open(sp_name, 'w')
sp.write("**************************************************\n")
sp.write("* OpenRAM generated memory.\n")
sp.write("* Words: {}\n".format(self.num_words))
sp.write("* Data bits: {}\n".format(self.word_size))
sp.write("* Banks: {}\n".format(self.num_banks))
sp.write("* Column mux: {}:1\n".format(self.words_per_row))
sp.write("**************************************************\n")
# This causes unit test mismatch
# sp.write("* Created: {0}\n".format(datetime.datetime.now()))
# sp.write("* User: {0}\n".format(getpass.getuser()))
@ -1007,3 +1018,59 @@ class sram(design.design):
def analytical_power(self,slew,load):
""" Just a test function for the power."""
return self.bank.analytical_power(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

@ -32,6 +32,10 @@ class hierarchical_decoder_test(openram_test):
# a = hierarchical_decoder.hierarchical_decoder(rows=8)
# self.local_check(a)
debug.info(1, "Testing 16 row sample for hierarchical_decoder")
a = hierarchical_decoder.hierarchical_decoder(rows=16)
self.local_check(a)
debug.info(1, "Testing 32 row sample for hierarchical_decoder")
a = hierarchical_decoder.hierarchical_decoder(rows=32)
self.local_check(a)

View File

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

View File

@ -23,19 +23,19 @@ class sram_1bank_test(openram_test):
debug.info(1, "Single bank, no column mux with control logic")
a = sram.sram(word_size=4, num_words=16, num_banks=1, name="sram1")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Single bank two way column mux with control logic")
a = sram.sram(word_size=4, num_words=32, num_banks=1, name="sram2")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Single bank, four way column mux with control logic")
a = sram.sram(word_size=4, num_words=64, num_banks=1, name="sram3")
self.local_check(a)
self.local_check(a, final_verification=True)
# debug.info(1, "Single bank, eight way column mux with control logic")
# a = sram.sram(word_size=2, num_words=128, num_banks=1, name="sram4")
# self.local_check(a)
# self.local_check(a, final_verification=True)
OPTS.check_lvsdrc = True
globals.end_openram()

View File

@ -23,19 +23,19 @@ class sram_2bank_test(openram_test):
debug.info(1, "Two bank, no column mux with control logic")
a = sram.sram(word_size=16, num_words=32, num_banks=2, name="sram1")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Two bank two way column mux with control logic")
a = sram.sram(word_size=16, num_words=64, num_banks=2, name="sram2")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Two bank, four way column mux with control logic")
a = sram.sram(word_size=16, num_words=128, num_banks=2, name="sram3")
self.local_check(a)
self.local_check(a, final_verification=True)
# debug.info(1, "Two bank, eight way column mux with control logic")
# a = sram.sram(word_size=2, num_words=256 num_banks=2, name="sram4")
# self.local_check(a)
# self.local_check(a, final_verification=True)
OPTS.check_lvsdrc = True
globals.end_openram()

View File

@ -23,19 +23,19 @@ class sram_4bank_test(openram_test):
debug.info(1, "Four bank, no column mux with control logic")
a = sram.sram(word_size=16, num_words=64, num_banks=4, name="sram1")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Four bank two way column mux with control logic")
a = sram.sram(word_size=16, num_words=128, num_banks=4, name="sram2")
self.local_check(a)
self.local_check(a, final_verification=True)
debug.info(1, "Four bank, four way column mux with control logic")
a = sram.sram(word_size=16, num_words=256, num_banks=4, name="sram3")
self.local_check(a)
self.local_check(a, final_verification=True)
# debug.info(1, "Four bank, eight way column mux with control logic")
# a = sram.sram(word_size=2, num_words=256, num_banks=4, name="sram4")
# self.local_check(a)
# self.local_check(a, final_verification=True)
OPTS.check_lvsdrc = True
globals.end_openram()

View File

@ -27,7 +27,7 @@ class timing_sram_test(openram_test):
debug.error("Could not find {} simulator.".format(OPTS.spice_name),-1)
import sram
import tech
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words,
@ -43,31 +43,33 @@ class timing_sram_test(openram_test):
probe_data = s.word_size - 1
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
loads = [tech.spice["FF_in_cap"]*4]
loads = [tech.spice["msflop_in_cap"]*4]
slews = [tech.spice["rise_time"]*2]
data = d.analyze(probe_address, probe_data,slews,loads)
#print data
if OPTS.tech_name == "freepdk45":
golden_data = {'read1_power': 0.0296933,
'read0_power': 0.029897899999999998,
'write0_power': 0.0258029,
'delay1': [0.049100700000000004],
'delay0': [0.13766139999999996],
'min_period': 0.322,
'write1_power': 0.0260398,
'slew0': [0.0265264],
'slew1': [0.0195507]}
golden_data = {'read1_power': 0.0356004,
'read0_power': 0.0364339,
'write0_power': 0.0262249,
'delay1': [0.0572987],
'delay0': [0.0705677],
'min_period': 0.41,
'write1_power': 0.038824700000000004,
'slew0': [0.028478],
'slew1': [0.0190058]}
elif OPTS.tech_name == "scn3me_subm":
golden_data = {'read1_power': 4.443,
'read0_power': 4.4712,
'write0_power': 3.0032,
'delay1': [0.8596608],
'delay0': [1.9534000000000002],
'min_period': 5.625,
'write1_power': 2.8086,
'slew0': [1.2982],
'slew1': [0.9909933]}
golden_data = {'read1_power': 10.3442,
'read0_power': 10.5159,
'write0_power': 6.9292,
'delay1': [0.6536728],
'delay0': [0.9019465999999999],
'min_period': 4.531,
'write1_power': 11.3108,
'slew0': [0.8320245],
'slew1': [0.5897582]}
else:
self.assertTrue(False) # other techs fail
# Check if no too many or too few results

View File

@ -31,19 +31,20 @@ class timing_setup_test(openram_test):
import tech
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)
#print data
if OPTS.tech_name == "freepdk45":
golden_data = {'setup_times_LH': [0.014648399999999999],
'hold_times_LH': [0.0024414],
'hold_times_HL': [-0.0036620999999999997],
'setup_times_HL': [0.0085449]}
elif OPTS.tech_name == "scn3me_subm":
golden_data = {'setup_times_LH': [0.1000977],
'hold_times_LH': [0.020751999999999996],
'hold_times_HL': [-0.0830078],
'setup_times_HL': [0.020751999999999996]}
golden_data = {'setup_times_LH': [0.08178709999999999],
'hold_times_LH': [0.0024414],
'hold_times_HL': [-0.0646973],
'setup_times_HL': [0.0390625]}
else:
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)
import sram
import tech
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram.sram(word_size=OPTS.word_size,
num_words=OPTS.num_words,
@ -41,31 +41,33 @@ class timing_sram_test(openram_test):
probe_data = s.word_size - 1
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
loads = [tech.spice["FF_in_cap"]*4]
loads = [tech.spice["msflop_in_cap"]*4]
slews = [tech.spice["rise_time"]*2]
data = d.analyze(probe_address, probe_data,slews,loads)
#print data
if OPTS.tech_name == "freepdk45":
golden_data = {'read1_power': 0.026660760000000002,
'read0_power': 0.02711731,
'write0_power': 0.02501428,
'delay1': [0.04867702],
'delay0': [0.1423633],
'min_period': 0.332,
'write1_power': 0.024162890000000003,
'slew0': [0.02733451],
'slew1': [0.02121624]}
golden_data = {'read1_power': 0.03308298,
'read0_power': 0.03866541,
'write0_power': 0.02695139,
'delay1': [0.05840294000000001],
'delay0': [0.40787249999999997],
'min_period': 0.781,
'write1_power': 0.037257830000000006,
'slew0': [0.035826199999999996],
'slew1': [0.02059459]}
elif OPTS.tech_name == "scn3me_subm":
golden_data = {'read1_power': 4.250786000000001,
'read0_power': 4.093461,
'write0_power': 2.762675,
'delay1': [0.920068],
'delay0': [2.051821],
'min_period': 6.563,
'write1_power': 2.4545719999999998,
'slew0': [1.342015],
'slew1': [1.040868]}
golden_data = {'read1_power': 10.31395,
'read0_power': 10.0321,
'write0_power': 6.072756,
'delay1': [1.042564],
'delay0': [1.412224],
'min_period': 4.688,
'write1_power': 10.53758,
'slew0': [1.355812],
'slew1': [1.03401]}
else:
self.assertTrue(False) # other techs fail

View File

@ -30,19 +30,20 @@ class timing_setup_test(openram_test):
import tech
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)
#print data
if OPTS.tech_name == "freepdk45":
golden_data = {'setup_times_LH': [0.01464844],
'hold_times_LH': [0.0024414059999999997],
'hold_times_HL': [-0.003662109],
'setup_times_HL': [0.008544922]}
elif OPTS.tech_name == "scn3me_subm":
golden_data = {'setup_times_LH': [0.1000977],
'hold_times_LH': [0.02075195],
'hold_times_HL': [-0.08300781],
'setup_times_HL': [0.02075195]}
golden_data = {'setup_times_LH': [0.1855469],
'hold_times_LH': [-0.009765625],
'hold_times_HL': [-0.15625],
'setup_times_HL': [0.12451169999999999]}
else:
self.assertTrue(False) # other techs fail

View File

@ -43,12 +43,13 @@ class sram_func_test(openram_test):
probe_data = s.word_size - 1
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)
# This will exit if it doesn't find a feasible period
import tech
load = tech.spice["FF_in_cap"]*4
load = tech.spice["msflop_in_cap"]*4
slew = tech.spice["rise_time"]*2
feasible_period = d.find_feasible_period(load,slew)

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM
import unittest
from testutils import header,openram_test
import sys,os
import sys,os,re
sys.path.append(os.path.join(sys.path[0],".."))
import globals
from globals import OPTS
@ -22,22 +22,28 @@ class lib_test(openram_test):
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2,
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
filename = s.name + "_analytical.lib"
libname = OPTS.openram_temp + filename
lib.lib(libname=libname,sram=s,spfile=tempspice,use_model=True)
lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=True)
# let's diff the result with a golden model
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
self.isapproxdiff(libname,golden,0.15)
# 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:
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)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM with pruning
import unittest
from testutils import header,openram_test
import sys,os
import sys,os,re
sys.path.append(os.path.join(sys.path[0],".."))
import globals
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")
s = sram.sram(word_size=2,
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
filename = s.name + "_pruned.lib"
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
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
self.isapproxdiff(libname,golden,0.30)
lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=False)
# 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:
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
reload(characterizer)

View File

@ -5,7 +5,7 @@ Check the .lib file for an SRAM
import unittest
from testutils import header,openram_test
import sys,os
import sys,os,re
sys.path.append(os.path.join(sys.path[0],".."))
import globals
from globals import OPTS
@ -31,21 +31,26 @@ class lib_test(openram_test):
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram.sram(word_size=2,
num_words=OPTS.num_words,
num_banks=OPTS.num_banks,
num_words=16,
num_banks=1,
name="sram_2_16_1_{0}".format(OPTS.tech_name))
OPTS.check_lvsdrc = True
tempspice = OPTS.openram_temp + "temp.sp"
s.sp_write(tempspice)
filename = s.name + ".lib"
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
golden = "{0}/golden/{1}".format(os.path.dirname(os.path.realpath(__file__)),filename)
self.isapproxdiff(libname,golden,0.15)
lib.lib(out_dir=OPTS.openram_temp, sram=s, sp_file=tempspice, use_model=False)
# 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)
self.isapproxdiff(libname,golden,0.15)
OPTS.analytical_delay = True
OPTS.trim_netlist = True

View File

@ -20,8 +20,8 @@ class openram_test(openram_test):
debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.")
out_file = "testsram"
# make a temp directory for output
out_path = "/tmp/testsram"
# make a temp directory for output
out_path = "/tmp/testsram_{0}".format(OPTS.tech_name)
# make sure we start without the files existing
if os.path.exists(out_path):
@ -52,11 +52,16 @@ class openram_test(openram_test):
os.system(cmd)
# 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)
debug.info(1,"Checking for file: " + filename)
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
output = open("{0}/output.log".format(out_path),"r").read()
self.assertEqual(len(re.findall('ERROR',output)),0)

View File

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

View File

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

View File

@ -7,11 +7,11 @@ UNITS
END UNITS
SITE MacroSite
CLASS Core ;
SIZE 175.0 by 135.0 ;
SIZE 21695.0 by 42337.5 ;
END MacroSite
MACRO sram_2_16_1_freepdk45
CLASS BLOCK ;
SIZE 175.0 BY 135.0 ;
SIZE 21695.0 BY 42337.5 ;
SYMMETRY X Y R90 ;
SITE MacroSite ;
PIN DATA[0]
@ -606,14 +606,14 @@ MACRO sram_2_16_1_freepdk45
RECT 10785.0 10360.0 10420.0 10425.0 ;
RECT 11060.0 11122.5 9125.0 11187.5 ;
RECT 10785.0 12467.5 8850.0 12532.5 ;
RECT 9675.0 8722.5 8292.5 8787.5 ;
RECT 9400.0 8937.5 8550.0 9002.5 ;
RECT 9125.0 10562.5 8292.5 10627.5 ;
RECT 9400.0 10347.5 8550.0 10412.5 ;
RECT 9675.0 11412.5 8292.5 11477.5 ;
RECT 8850.0 11627.5 8550.0 11692.5 ;
RECT 9125.0 13252.5 8292.5 13317.5 ;
RECT 8850.0 13037.5 8550.0 13102.5 ;
RECT 9675.0 8937.5 8550.0 9002.5 ;
RECT 9400.0 8722.5 8292.5 8787.5 ;
RECT 9125.0 10347.5 8550.0 10412.5 ;
RECT 9400.0 10562.5 8292.5 10627.5 ;
RECT 9675.0 11627.5 8550.0 11692.5 ;
RECT 8850.0 11412.5 8292.5 11477.5 ;
RECT 9125.0 13037.5 8550.0 13102.5 ;
RECT 8850.0 13252.5 8292.5 13317.5 ;
RECT 7845.0 8937.5 7780.0 9002.5 ;
RECT 7845.0 8925.0 7780.0 8990.0 ;
RECT 8062.5 8937.5 7812.5 9002.5 ;
@ -894,14 +894,14 @@ MACRO sram_2_16_1_freepdk45
RECT 9057.5 11122.5 9192.5 11187.5 ;
RECT 10717.5 12467.5 10852.5 12532.5 ;
RECT 8782.5 12467.5 8917.5 12532.5 ;
RECT 9607.5 8722.5 9742.5 8787.5 ;
RECT 9332.5 8937.5 9467.5 9002.5 ;
RECT 9057.5 10562.5 9192.5 10627.5 ;
RECT 9332.5 10347.5 9467.5 10412.5 ;
RECT 9607.5 11412.5 9742.5 11477.5 ;
RECT 8782.5 11627.5 8917.5 11692.5 ;
RECT 9057.5 13252.5 9192.5 13317.5 ;
RECT 8782.5 13037.5 8917.5 13102.5 ;
RECT 9607.5 8937.5 9742.5 9002.5 ;
RECT 9332.5 8722.5 9467.5 8787.5 ;
RECT 9057.5 10347.5 9192.5 10412.5 ;
RECT 9332.5 10562.5 9467.5 10627.5 ;
RECT 9607.5 11627.5 9742.5 11692.5 ;
RECT 8782.5 11412.5 8917.5 11477.5 ;
RECT 9057.5 13037.5 9192.5 13102.5 ;
RECT 8782.5 13252.5 8917.5 13317.5 ;
RECT 7335.0 8925.0 7130.0 8990.0 ;
RECT 7335.0 10360.0 7130.0 10425.0 ;
RECT 7335.0 11615.0 7130.0 11680.0 ;
@ -925,14 +925,14 @@ MACRO sram_2_16_1_freepdk45
RECT 10785.0 15740.0 10420.0 15805.0 ;
RECT 11060.0 16502.5 9125.0 16567.5 ;
RECT 10785.0 17847.5 8850.0 17912.5 ;
RECT 9675.0 14102.5 8292.5 14167.5 ;
RECT 9400.0 14317.5 8550.0 14382.5 ;
RECT 9125.0 15942.5 8292.5 16007.5 ;
RECT 9400.0 15727.5 8550.0 15792.5 ;
RECT 9675.0 16792.5 8292.5 16857.5 ;
RECT 8850.0 17007.5 8550.0 17072.5 ;
RECT 9125.0 18632.5 8292.5 18697.5 ;
RECT 8850.0 18417.5 8550.0 18482.5 ;
RECT 9675.0 14317.5 8550.0 14382.5 ;
RECT 9400.0 14102.5 8292.5 14167.5 ;
RECT 9125.0 15727.5 8550.0 15792.5 ;
RECT 9400.0 15942.5 8292.5 16007.5 ;
RECT 9675.0 17007.5 8550.0 17072.5 ;
RECT 8850.0 16792.5 8292.5 16857.5 ;
RECT 9125.0 18417.5 8550.0 18482.5 ;
RECT 8850.0 18632.5 8292.5 18697.5 ;
RECT 7845.0 14317.5 7780.0 14382.5 ;
RECT 7845.0 14305.0 7780.0 14370.0 ;
RECT 8062.5 14317.5 7812.5 14382.5 ;
@ -1213,14 +1213,14 @@ MACRO sram_2_16_1_freepdk45
RECT 9057.5 16502.5 9192.5 16567.5 ;
RECT 10717.5 17847.5 10852.5 17912.5 ;
RECT 8782.5 17847.5 8917.5 17912.5 ;
RECT 9607.5 14102.5 9742.5 14167.5 ;
RECT 9332.5 14317.5 9467.5 14382.5 ;
RECT 9057.5 15942.5 9192.5 16007.5 ;
RECT 9332.5 15727.5 9467.5 15792.5 ;
RECT 9607.5 16792.5 9742.5 16857.5 ;
RECT 8782.5 17007.5 8917.5 17072.5 ;
RECT 9057.5 18632.5 9192.5 18697.5 ;
RECT 8782.5 18417.5 8917.5 18482.5 ;
RECT 9607.5 14317.5 9742.5 14382.5 ;
RECT 9332.5 14102.5 9467.5 14167.5 ;
RECT 9057.5 15727.5 9192.5 15792.5 ;
RECT 9332.5 15942.5 9467.5 16007.5 ;
RECT 9607.5 17007.5 9742.5 17072.5 ;
RECT 8782.5 16792.5 8917.5 16857.5 ;
RECT 9057.5 18417.5 9192.5 18482.5 ;
RECT 8782.5 18632.5 8917.5 18697.5 ;
RECT 7335.0 14305.0 7130.0 14370.0 ;
RECT 7335.0 15740.0 7130.0 15805.0 ;
RECT 7335.0 16995.0 7130.0 17060.0 ;
@ -4165,9 +4165,11 @@ MACRO sram_2_16_1_freepdk45
RECT 750.0 30905.0 685.0 30970.0 ;
RECT 32.5 30615.0 -32.5 31175.0 ;
RECT 1377.5 30615.0 1312.5 31175.0 ;
RECT 1380.0 33907.5 935.0 33972.5 ;
RECT 1380.0 36317.5 935.0 36382.5 ;
RECT 1345.0 36817.5 935.0 36882.5 ;
RECT 1377.5 39337.5 1312.5 36955.0 ;
RECT 1312.5 33907.5 1025.0 33972.5 ;
RECT 1312.5 36317.5 1025.0 36382.5 ;
RECT 1377.5 31862.5 935.0 31927.5 ;
RECT 935.0 31862.5 230.0 31927.5 ;
RECT 20.0 35112.5 935.0 35177.5 ;
RECT 20.0 32422.5 935.0 32487.5 ;
RECT 2005.0 33435.0 1940.0 34135.0 ;
@ -4208,11 +4210,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 33307.5 2465.0 33372.5 ;
RECT 1312.5 35352.5 1377.5 35417.5 ;
RECT 4002.5 35352.5 4067.5 35417.5 ;
RECT 1312.5 35255.0 1377.5 35385.0 ;
RECT 1345.0 35352.5 4035.0 35417.5 ;
RECT 4002.5 35255.0 4067.5 35385.0 ;
RECT 1312.5 39272.5 1377.5 39337.5 ;
RECT 4002.5 39272.5 4067.5 39337.5 ;
RECT 1312.5 39175.0 1377.5 39305.0 ;
RECT 1345.0 39272.5 4035.0 39337.5 ;
RECT 4002.5 39175.0 4067.5 39305.0 ;
RECT 2875.0 34562.5 2690.0 34627.5 ;
RECT 4035.0 34562.5 3850.0 34627.5 ;
RECT 3917.5 34202.5 4067.5 34267.5 ;
@ -4254,6 +4256,279 @@ MACRO sram_2_16_1_freepdk45
RECT 2722.5 34695.0 2657.5 35255.0 ;
RECT 4067.5 34695.0 4002.5 35255.0 ;
RECT 3340.0 34820.0 3475.0 34885.0 ;
RECT 2875.0 35682.5 2690.0 35747.5 ;
RECT 4035.0 35682.5 3850.0 35747.5 ;
RECT 3917.5 35322.5 4067.5 35387.5 ;
RECT 3032.5 35322.5 2657.5 35387.5 ;
RECT 3917.5 35512.5 3032.5 35577.5 ;
RECT 3032.5 35322.5 2897.5 35387.5 ;
RECT 3032.5 35512.5 2897.5 35577.5 ;
RECT 3032.5 35512.5 2897.5 35577.5 ;
RECT 3032.5 35322.5 2897.5 35387.5 ;
RECT 3917.5 35322.5 3782.5 35387.5 ;
RECT 3917.5 35512.5 3782.5 35577.5 ;
RECT 3917.5 35512.5 3782.5 35577.5 ;
RECT 3917.5 35322.5 3782.5 35387.5 ;
RECT 2942.5 35682.5 2807.5 35747.5 ;
RECT 3917.5 35682.5 3782.5 35747.5 ;
RECT 3475.0 35380.0 3340.0 35445.0 ;
RECT 3475.0 35380.0 3340.0 35445.0 ;
RECT 3440.0 35545.0 3375.0 35610.0 ;
RECT 2722.5 35255.0 2657.5 35815.0 ;
RECT 4067.5 35255.0 4002.5 35815.0 ;
RECT 3340.0 35380.0 3475.0 35445.0 ;
RECT 2875.0 36242.5 2690.0 36307.5 ;
RECT 4035.0 36242.5 3850.0 36307.5 ;
RECT 3917.5 35882.5 4067.5 35947.5 ;
RECT 3032.5 35882.5 2657.5 35947.5 ;
RECT 3917.5 36072.5 3032.5 36137.5 ;
RECT 3032.5 35882.5 2897.5 35947.5 ;
RECT 3032.5 36072.5 2897.5 36137.5 ;
RECT 3032.5 36072.5 2897.5 36137.5 ;
RECT 3032.5 35882.5 2897.5 35947.5 ;
RECT 3917.5 35882.5 3782.5 35947.5 ;
RECT 3917.5 36072.5 3782.5 36137.5 ;
RECT 3917.5 36072.5 3782.5 36137.5 ;
RECT 3917.5 35882.5 3782.5 35947.5 ;
RECT 2942.5 36242.5 2807.5 36307.5 ;
RECT 3917.5 36242.5 3782.5 36307.5 ;
RECT 3475.0 35940.0 3340.0 36005.0 ;
RECT 3475.0 35940.0 3340.0 36005.0 ;
RECT 3440.0 36105.0 3375.0 36170.0 ;
RECT 2722.5 35815.0 2657.5 36375.0 ;
RECT 4067.5 35815.0 4002.5 36375.0 ;
RECT 3340.0 35940.0 3475.0 36005.0 ;
RECT 2875.0 36802.5 2690.0 36867.5 ;
RECT 4035.0 36802.5 3850.0 36867.5 ;
RECT 3917.5 36442.5 4067.5 36507.5 ;
RECT 3032.5 36442.5 2657.5 36507.5 ;
RECT 3917.5 36632.5 3032.5 36697.5 ;
RECT 3032.5 36442.5 2897.5 36507.5 ;
RECT 3032.5 36632.5 2897.5 36697.5 ;
RECT 3032.5 36632.5 2897.5 36697.5 ;
RECT 3032.5 36442.5 2897.5 36507.5 ;
RECT 3917.5 36442.5 3782.5 36507.5 ;
RECT 3917.5 36632.5 3782.5 36697.5 ;
RECT 3917.5 36632.5 3782.5 36697.5 ;
RECT 3917.5 36442.5 3782.5 36507.5 ;
RECT 2942.5 36802.5 2807.5 36867.5 ;
RECT 3917.5 36802.5 3782.5 36867.5 ;
RECT 3475.0 36500.0 3340.0 36565.0 ;
RECT 3475.0 36500.0 3340.0 36565.0 ;
RECT 3440.0 36665.0 3375.0 36730.0 ;
RECT 2722.5 36375.0 2657.5 36935.0 ;
RECT 4067.5 36375.0 4002.5 36935.0 ;
RECT 3340.0 36500.0 3475.0 36565.0 ;
RECT 2875.0 37362.5 2690.0 37427.5 ;
RECT 4035.0 37362.5 3850.0 37427.5 ;
RECT 3917.5 37002.5 4067.5 37067.5 ;
RECT 3032.5 37002.5 2657.5 37067.5 ;
RECT 3917.5 37192.5 3032.5 37257.5 ;
RECT 3032.5 37002.5 2897.5 37067.5 ;
RECT 3032.5 37192.5 2897.5 37257.5 ;
RECT 3032.5 37192.5 2897.5 37257.5 ;
RECT 3032.5 37002.5 2897.5 37067.5 ;
RECT 3917.5 37002.5 3782.5 37067.5 ;
RECT 3917.5 37192.5 3782.5 37257.5 ;
RECT 3917.5 37192.5 3782.5 37257.5 ;
RECT 3917.5 37002.5 3782.5 37067.5 ;
RECT 2942.5 37362.5 2807.5 37427.5 ;
RECT 3917.5 37362.5 3782.5 37427.5 ;
RECT 3475.0 37060.0 3340.0 37125.0 ;
RECT 3475.0 37060.0 3340.0 37125.0 ;
RECT 3440.0 37225.0 3375.0 37290.0 ;
RECT 2722.5 36935.0 2657.5 37495.0 ;
RECT 4067.5 36935.0 4002.5 37495.0 ;
RECT 3340.0 37060.0 3475.0 37125.0 ;
RECT 2875.0 37922.5 2690.0 37987.5 ;
RECT 4035.0 37922.5 3850.0 37987.5 ;
RECT 3917.5 37562.5 4067.5 37627.5 ;
RECT 3032.5 37562.5 2657.5 37627.5 ;
RECT 3917.5 37752.5 3032.5 37817.5 ;
RECT 3032.5 37562.5 2897.5 37627.5 ;
RECT 3032.5 37752.5 2897.5 37817.5 ;
RECT 3032.5 37752.5 2897.5 37817.5 ;
RECT 3032.5 37562.5 2897.5 37627.5 ;
RECT 3917.5 37562.5 3782.5 37627.5 ;
RECT 3917.5 37752.5 3782.5 37817.5 ;
RECT 3917.5 37752.5 3782.5 37817.5 ;
RECT 3917.5 37562.5 3782.5 37627.5 ;
RECT 2942.5 37922.5 2807.5 37987.5 ;
RECT 3917.5 37922.5 3782.5 37987.5 ;
RECT 3475.0 37620.0 3340.0 37685.0 ;
RECT 3475.0 37620.0 3340.0 37685.0 ;
RECT 3440.0 37785.0 3375.0 37850.0 ;
RECT 2722.5 37495.0 2657.5 38055.0 ;
RECT 4067.5 37495.0 4002.5 38055.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 1345.0 37067.5 1530.0 37002.5 ;
RECT 1462.5 37427.5 1312.5 37362.5 ;
RECT 2347.5 37427.5 2722.5 37362.5 ;
RECT 1462.5 37237.5 2347.5 37172.5 ;
RECT 2347.5 37427.5 2482.5 37362.5 ;
RECT 2347.5 37237.5 2482.5 37172.5 ;
RECT 2347.5 37237.5 2482.5 37172.5 ;
RECT 2347.5 37427.5 2482.5 37362.5 ;
RECT 1462.5 37427.5 1597.5 37362.5 ;
RECT 1462.5 37237.5 1597.5 37172.5 ;
RECT 1462.5 37237.5 1597.5 37172.5 ;
RECT 1462.5 37427.5 1597.5 37362.5 ;
RECT 2437.5 37067.5 2572.5 37002.5 ;
RECT 1462.5 37067.5 1597.5 37002.5 ;
RECT 1905.0 37370.0 2040.0 37305.0 ;
RECT 1905.0 37370.0 2040.0 37305.0 ;
RECT 1940.0 37205.0 2005.0 37140.0 ;
RECT 2657.5 37495.0 2722.5 36935.0 ;
RECT 1312.5 37495.0 1377.5 36935.0 ;
RECT 1905.0 37305.0 2040.0 37370.0 ;
RECT 2505.0 36507.5 2690.0 36442.5 ;
RECT 1345.0 36507.5 1530.0 36442.5 ;
RECT 1462.5 36867.5 1312.5 36802.5 ;
RECT 2347.5 36867.5 2722.5 36802.5 ;
RECT 1462.5 36677.5 2347.5 36612.5 ;
RECT 2347.5 36867.5 2482.5 36802.5 ;
RECT 2347.5 36677.5 2482.5 36612.5 ;
RECT 2347.5 36677.5 2482.5 36612.5 ;
RECT 2347.5 36867.5 2482.5 36802.5 ;
RECT 1462.5 36867.5 1597.5 36802.5 ;
RECT 1462.5 36677.5 1597.5 36612.5 ;
RECT 1462.5 36677.5 1597.5 36612.5 ;
RECT 1462.5 36867.5 1597.5 36802.5 ;
RECT 2437.5 36507.5 2572.5 36442.5 ;
RECT 1462.5 36507.5 1597.5 36442.5 ;
RECT 1905.0 36810.0 2040.0 36745.0 ;
RECT 1905.0 36810.0 2040.0 36745.0 ;
RECT 1940.0 36645.0 2005.0 36580.0 ;
RECT 2657.5 36935.0 2722.5 36375.0 ;
RECT 1312.5 36935.0 1377.5 36375.0 ;
RECT 1905.0 36745.0 2040.0 36810.0 ;
RECT 2505.0 35947.5 2690.0 35882.5 ;
RECT 1345.0 35947.5 1530.0 35882.5 ;
RECT 1462.5 36307.5 1312.5 36242.5 ;
RECT 2347.5 36307.5 2722.5 36242.5 ;
RECT 1462.5 36117.5 2347.5 36052.5 ;
RECT 2347.5 36307.5 2482.5 36242.5 ;
RECT 2347.5 36117.5 2482.5 36052.5 ;
RECT 2347.5 36117.5 2482.5 36052.5 ;
RECT 2347.5 36307.5 2482.5 36242.5 ;
RECT 1462.5 36307.5 1597.5 36242.5 ;
RECT 1462.5 36117.5 1597.5 36052.5 ;
RECT 1462.5 36117.5 1597.5 36052.5 ;
RECT 1462.5 36307.5 1597.5 36242.5 ;
RECT 2437.5 35947.5 2572.5 35882.5 ;
RECT 1462.5 35947.5 1597.5 35882.5 ;
RECT 1905.0 36250.0 2040.0 36185.0 ;
RECT 1905.0 36250.0 2040.0 36185.0 ;
RECT 1940.0 36085.0 2005.0 36020.0 ;
RECT 2657.5 36375.0 2722.5 35815.0 ;
RECT 1312.5 36375.0 1377.5 35815.0 ;
RECT 1905.0 36185.0 2040.0 36250.0 ;
RECT 2505.0 35387.5 2690.0 35322.5 ;
RECT 1345.0 35387.5 1530.0 35322.5 ;
RECT 1462.5 35747.5 1312.5 35682.5 ;
RECT 2347.5 35747.5 2722.5 35682.5 ;
RECT 1462.5 35557.5 2347.5 35492.5 ;
RECT 2347.5 35747.5 2482.5 35682.5 ;
RECT 2347.5 35557.5 2482.5 35492.5 ;
RECT 2347.5 35557.5 2482.5 35492.5 ;
RECT 2347.5 35747.5 2482.5 35682.5 ;
RECT 1462.5 35747.5 1597.5 35682.5 ;
RECT 1462.5 35557.5 1597.5 35492.5 ;
RECT 1462.5 35557.5 1597.5 35492.5 ;
RECT 1462.5 35747.5 1597.5 35682.5 ;
RECT 2437.5 35387.5 2572.5 35322.5 ;
RECT 1462.5 35387.5 1597.5 35322.5 ;
RECT 1905.0 35690.0 2040.0 35625.0 ;
RECT 1905.0 35690.0 2040.0 35625.0 ;
RECT 1940.0 35525.0 2005.0 35460.0 ;
RECT 2657.5 35815.0 2722.5 35255.0 ;
RECT 1312.5 35815.0 1377.5 35255.0 ;
RECT 1905.0 35625.0 2040.0 35690.0 ;
RECT 2505.0 34827.5 2690.0 34762.5 ;
RECT 1345.0 34827.5 1530.0 34762.5 ;
RECT 1462.5 35187.5 1312.5 35122.5 ;
@ -4297,13 +4572,14 @@ MACRO sram_2_16_1_freepdk45
RECT 1312.5 34695.0 1377.5 34135.0 ;
RECT 1905.0 34505.0 2040.0 34570.0 ;
RECT 3340.0 34425.0 3475.0 34490.0 ;
RECT 3340.0 34985.0 3475.0 35050.0 ;
RECT 1905.0 34900.0 2040.0 34965.0 ;
RECT 3340.0 36665.0 3475.0 36730.0 ;
RECT 3340.0 38905.0 3475.0 38970.0 ;
RECT 1905.0 36580.0 2040.0 36645.0 ;
RECT 3340.0 34260.0 3475.0 34325.0 ;
RECT 1940.0 34135.0 2005.0 34340.0 ;
RECT 2657.5 34135.0 2722.5 35255.0 ;
RECT 1312.5 34135.0 1377.5 35255.0 ;
RECT 4002.5 34135.0 4067.5 35255.0 ;
RECT 2657.5 34135.0 2722.5 39175.0 ;
RECT 1312.5 34135.0 1377.5 39175.0 ;
RECT 4002.5 34135.0 4067.5 39175.0 ;
RECT 935.0 33800.0 225.0 32455.0 ;
RECT 935.0 33800.0 230.0 35145.0 ;
RECT 935.0 36490.0 230.0 35145.0 ;
@ -4312,12 +4588,12 @@ MACRO sram_2_16_1_freepdk45
RECT 1025.0 35112.5 140.0 35177.5 ;
RECT 1025.0 33767.5 140.0 33832.5 ;
RECT 1025.0 36457.5 140.0 36522.5 ;
RECT 1377.5 33907.5 1312.5 34042.5 ;
RECT 1377.5 36317.5 1312.5 36452.5 ;
RECT 1377.5 34135.0 1312.5 34270.0 ;
RECT 1345.0 33872.5 1280.0 34007.5 ;
RECT 1345.0 36282.5 1280.0 36417.5 ;
RECT 1342.5 34135.0 1277.5 34270.0 ;
RECT 1377.5 31760.0 1312.5 31895.0 ;
RECT 1277.5 36817.5 1412.5 36882.5 ;
RECT 867.5 36817.5 1002.5 36882.5 ;
RECT 867.5 31862.5 1002.5 31927.5 ;
RECT 162.5 31862.5 297.5 31927.5 ;
RECT 2005.0 33367.5 1940.0 33502.5 ;
RECT 1105.0 32627.5 1240.0 32692.5 ;
RECT 1105.0 32030.0 1240.0 32095.0 ;
@ -4326,7 +4602,7 @@ MACRO sram_2_16_1_freepdk45
RECT 2005.0 31335.0 1940.0 32100.0 ;
RECT 20.0 31335.0 -45.0 36577.5 ;
RECT 2722.5 31335.0 2657.5 34135.0 ;
RECT 1380.0 31335.0 1310.0 32455.0 ;
RECT 1377.5 31335.0 1312.5 31895.0 ;
RECT 4067.5 31335.0 4002.5 34135.0 ;
RECT 3455.0 26182.5 3390.0 26047.5 ;
RECT 3455.0 22102.5 3390.0 21967.5 ;
@ -4529,14 +4805,14 @@ MACRO sram_2_16_1_freepdk45
RECT 9057.5 11120.0 9192.5 11190.0 ;
RECT 10717.5 12465.0 10852.5 12535.0 ;
RECT 8782.5 12465.0 8917.5 12535.0 ;
RECT 9607.5 8720.0 9742.5 8790.0 ;
RECT 9332.5 8935.0 9467.5 9005.0 ;
RECT 9057.5 10560.0 9192.5 10630.0 ;
RECT 9332.5 10345.0 9467.5 10415.0 ;
RECT 9607.5 11410.0 9742.5 11480.0 ;
RECT 8782.5 11625.0 8917.5 11695.0 ;
RECT 9057.5 13250.0 9192.5 13320.0 ;
RECT 8782.5 13035.0 8917.5 13105.0 ;
RECT 9607.5 8935.0 9742.5 9005.0 ;
RECT 9332.5 8720.0 9467.5 8790.0 ;
RECT 9057.5 10345.0 9192.5 10415.0 ;
RECT 9332.5 10560.0 9467.5 10630.0 ;
RECT 9607.5 11625.0 9742.5 11695.0 ;
RECT 8782.5 11410.0 8917.5 11480.0 ;
RECT 9057.5 13035.0 9192.5 13105.0 ;
RECT 8782.5 13250.0 8917.5 13320.0 ;
RECT 11095.0 8330.0 11025.0 13570.0 ;
RECT 10820.0 8330.0 10750.0 13570.0 ;
RECT 9160.0 13710.0 9090.0 18950.0 ;
@ -4583,14 +4859,14 @@ MACRO sram_2_16_1_freepdk45
RECT 9057.5 16500.0 9192.5 16570.0 ;
RECT 10717.5 17845.0 10852.5 17915.0 ;
RECT 8782.5 17845.0 8917.5 17915.0 ;
RECT 9607.5 14100.0 9742.5 14170.0 ;
RECT 9332.5 14315.0 9467.5 14385.0 ;
RECT 9057.5 15940.0 9192.5 16010.0 ;
RECT 9332.5 15725.0 9467.5 15795.0 ;
RECT 9607.5 16790.0 9742.5 16860.0 ;
RECT 8782.5 17005.0 8917.5 17075.0 ;
RECT 9057.5 18630.0 9192.5 18700.0 ;
RECT 8782.5 18415.0 8917.5 18485.0 ;
RECT 9607.5 14315.0 9742.5 14385.0 ;
RECT 9332.5 14100.0 9467.5 14170.0 ;
RECT 9057.5 15725.0 9192.5 15795.0 ;
RECT 9332.5 15940.0 9467.5 16010.0 ;
RECT 9607.5 17005.0 9742.5 17075.0 ;
RECT 8782.5 16790.0 8917.5 16860.0 ;
RECT 9057.5 18415.0 9192.5 18485.0 ;
RECT 8782.5 18630.0 8917.5 18700.0 ;
RECT 11095.0 13710.0 11025.0 18950.0 ;
RECT 10820.0 13710.0 10750.0 18950.0 ;
RECT 7385.0 19695.0 7455.0 19765.0 ;
@ -5088,6 +5364,7 @@ MACRO sram_2_16_1_freepdk45
RECT 4035.0 26695.0 8.881784197e-13 26765.0 ;
RECT 4035.0 26900.0 8.881784197e-13 26970.0 ;
RECT 4035.0 27310.0 8.881784197e-13 27380.0 ;
RECT 3422.5 22000.0 2690.0 22070.0 ;
RECT 2520.0 19467.5 2450.0 26115.0 ;
RECT 4035.0 26285.0 3830.0 26355.0 ;
RECT 2895.0 27105.0 2690.0 27175.0 ;
@ -5162,25 +5439,51 @@ MACRO sram_2_16_1_freepdk45
RECT 1610.0 26387.5 1540.0 26252.5 ;
RECT 2315.0 25737.5 2245.0 25602.5 ;
RECT 2315.0 26387.5 2245.0 26252.5 ;
RECT 1380.0 31895.0 1310.0 36750.0 ;
RECT 1380.0 32455.0 1310.0 32660.0 ;
RECT 1380.0 32660.0 1310.0 36850.0 ;
RECT 970.0 36645.0 900.0 36850.0 ;
RECT 1380.0 31895.0 1310.0 36955.0 ;
RECT 970.0 31895.0 900.0 36645.0 ;
RECT 265.0 31895.0 195.0 36645.0 ;
RECT 1207.5 32062.5 1137.5 32660.0 ;
RECT 785.0 32062.5 715.0 32342.5 ;
RECT 3372.5 34457.5 3442.5 34852.5 ;
RECT 2655.0 34982.5 2725.0 35052.5 ;
RECT 2655.0 35062.5 2725.0 35132.5 ;
RECT 2690.0 34982.5 3407.5 35052.5 ;
RECT 2655.0 35017.5 2725.0 35097.5 ;
RECT 1972.5 35062.5 2690.0 35132.5 ;
RECT 1937.5 34537.5 2007.5 34932.5 ;
RECT 3372.5 34852.5 3442.5 35412.5 ;
RECT 3372.5 35412.5 3442.5 35972.5 ;
RECT 3372.5 35972.5 3442.5 36532.5 ;
RECT 3372.5 36697.5 3442.5 37092.5 ;
RECT 3372.5 37092.5 3442.5 37652.5 ;
RECT 3372.5 37652.5 3442.5 38212.5 ;
RECT 3372.5 38212.5 3442.5 38772.5 ;
RECT 2655.0 38902.5 2725.0 38972.5 ;
RECT 2655.0 38422.5 2725.0 38492.5 ;
RECT 2690.0 38902.5 3407.5 38972.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 36217.5 2007.5 36612.5 ;
RECT 1937.5 35657.5 2007.5 36217.5 ;
RECT 1937.5 35097.5 2007.5 35657.5 ;
RECT 1937.5 34537.5 2007.5 35097.5 ;
RECT 3340.0 34817.5 3475.0 34887.5 ;
RECT 3340.0 35377.5 3475.0 35447.5 ;
RECT 3340.0 35937.5 3475.0 36007.5 ;
RECT 3340.0 36497.5 3475.0 36567.5 ;
RECT 3340.0 37057.5 3475.0 37127.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 36742.5 2040.0 36812.5 ;
RECT 1905.0 36182.5 2040.0 36252.5 ;
RECT 1905.0 35622.5 2040.0 35692.5 ;
RECT 1905.0 35062.5 2040.0 35132.5 ;
RECT 1905.0 34502.5 2040.0 34572.5 ;
RECT 3340.0 34422.5 3475.0 34492.5 ;
RECT 3340.0 34982.5 3475.0 35052.5 ;
RECT 1905.0 34897.5 2040.0 34967.5 ;
RECT 3340.0 36662.5 3475.0 36732.5 ;
RECT 3340.0 38902.5 3475.0 38972.5 ;
RECT 1905.0 36577.5 2040.0 36647.5 ;
RECT 935.0 33800.0 225.0 32455.0 ;
RECT 935.0 33800.0 230.0 35145.0 ;
RECT 935.0 36490.0 230.0 35145.0 ;
@ -5188,19 +5491,19 @@ MACRO sram_2_16_1_freepdk45
RECT 450.0 33700.0 380.0 36645.0 ;
RECT 970.0 33700.0 900.0 36645.0 ;
RECT 265.0 33700.0 195.0 36645.0 ;
RECT 1380.0 33907.5 1310.0 34042.5 ;
RECT 1380.0 36317.5 1310.0 36452.5 ;
RECT 1380.0 34135.0 1310.0 34270.0 ;
RECT 1347.5 33872.5 1277.5 34007.5 ;
RECT 1347.5 36282.5 1277.5 36417.5 ;
RECT 1345.0 34135.0 1275.0 34270.0 ;
RECT 1380.0 31760.0 1310.0 31895.0 ;
RECT 1277.5 36815.0 1412.5 36885.0 ;
RECT 867.5 36815.0 1002.5 36885.0 ;
RECT 867.5 31860.0 1002.5 31930.0 ;
RECT 162.5 31860.0 297.5 31930.0 ;
RECT 1105.0 32625.0 1240.0 32695.0 ;
RECT 1105.0 32027.5 1240.0 32097.5 ;
RECT 682.5 32027.5 817.5 32097.5 ;
RECT 3457.5 26182.5 3387.5 26047.5 ;
RECT 3457.5 22102.5 3387.5 21967.5 ;
RECT 3457.5 27617.5 3387.5 27482.5 ;
RECT 3457.5 22102.5 3387.5 21967.5 ;
RECT 2725.0 22102.5 2655.0 21967.5 ;
RECT 2725.0 27617.5 2655.0 27482.5 ;
RECT 2520.0 19535.0 2450.0 19400.0 ;
RECT 1965.0 26182.5 1895.0 26047.5 ;
RECT 1750.0 26592.5 1680.0 26457.5 ;
@ -5299,7 +5602,7 @@ MACRO sram_2_16_1_freepdk45
RECT 905.0 25670.0 835.0 26320.0 ;
RECT 1610.0 25670.0 1540.0 26320.0 ;
RECT 2315.0 25670.0 2245.0 26320.0 ;
RECT 3457.5 22035.0 3387.5 27550.0 ;
RECT 2725.0 22035.0 2655.0 27550.0 ;
RECT 2020.0 27550.0 1950.0 29062.5 ;
RECT 1805.0 27345.0 1735.0 29320.0 ;
RECT 482.5 19230.0 552.5 19370.0 ;
@ -5321,8 +5624,8 @@ MACRO sram_2_16_1_freepdk45
RECT 1610.0 26387.5 1540.0 26252.5 ;
RECT 2315.0 25737.5 2245.0 25602.5 ;
RECT 2315.0 26387.5 2245.0 26252.5 ;
RECT 3457.5 22102.5 3387.5 21967.5 ;
RECT 3457.5 27617.5 3387.5 27482.5 ;
RECT 2725.0 22102.5 2655.0 21967.5 ;
RECT 2725.0 27617.5 2655.0 27482.5 ;
RECT 2020.0 29130.0 1950.0 28995.0 ;
RECT 2020.0 27617.5 1950.0 27482.5 ;
RECT 1805.0 29387.5 1735.0 29252.5 ;

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_scn3me_subm_lib){
library (sram_2_16_1_freepdk45_TT_10V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
@ -8,8 +8,8 @@ library (sram_2_16_1_scn3me_subm_lib){
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){
voltage : 5.0 ;
temperature : 25.000 ;
voltage : 1.0 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
@ -34,15 +34,15 @@ library (sram_2_16_1_scn3me_subm_lib){
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");
index_1("0.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728");
}
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");
index_1("0.00125, 0.005, 0.04");
index_2("0.00125, 0.005, 0.04");
}
default_operating_conditions : TT;
@ -64,7 +64,7 @@ library (sram_2_16_1_scn3me_subm_lib){
bit_to : 3;
}
cell (sram_2_16_1_scn3me_subm){
cell (sram_2_16_1_freepdk45){
memory(){
type : ram;
address_width : 4;
@ -74,12 +74,12 @@ cell (sram_2_16_1_scn3me_subm){
dont_use : true;
map_only : true;
dont_touch : true;
area : 2.7;
area : 918.5120625;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 78.5936;
max_capacitance : 1.6728;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
@ -92,47 +92,47 @@ cell (sram_2_16_1_scn3me_subm){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("2.8745");
values("0.042347092");
}
fall_power(scalar){
values("3.0265");
values("0.029908723");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
values("0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
values("0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016");
}
}
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("4.4921");
values("0.054779642");
}
fall_power(scalar){
values("4.5139");
values("0.060081573");
}
}
timing(){
@ -140,24 +140,24 @@ cell (sram_2_16_1_scn3me_subm){
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.496, 0.579, 1.253",\
"0.499, 0.581, 1.258",\
"0.547, 0.627, 1.305");
values("0.055, 0.056, 0.063",\
"0.056, 0.057, 0.063",\
"0.061, 0.062, 0.069");
}
cell_fall(CELL_TABLE) {
values("1.429, 1.539, 2.523",\
"1.433, 1.544, 2.526",\
"1.485, 1.595, 2.578");
values("0.522, 0.523, 0.533",\
"0.523, 0.524, 0.533",\
"0.528, 0.529, 0.539");
}
rise_transition(CELL_TABLE) {
values("0.189, 0.335, 1.879",\
"0.19, 0.336, 1.879",\
"0.192, 0.337, 1.879");
values("0.013, 0.015, 0.026",\
"0.013, 0.015, 0.026",\
"0.013, 0.015, 0.026");
}
fall_transition(CELL_TABLE) {
values("0.224, 0.437, 2.462",\
"0.225, 0.437, 2.472",\
"0.225, 0.436, 2.458");
values("0.029, 0.031, 0.044",\
"0.029, 0.031, 0.044",\
"0.029, 0.031, 0.044");
}
}
}
@ -166,36 +166,36 @@ cell (sram_2_16_1_scn3me_subm){
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
capacitance : 0.2091;
max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
values("0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
values("0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016");
}
}
}
@ -203,99 +203,99 @@ cell (sram_2_16_1_scn3me_subm){
pin(CSb){
direction : input;
capacitance : 9.8242;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
values("0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
values("0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016");
}
}
}
pin(OEb){
direction : input;
capacitance : 9.8242;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
values("0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
values("0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016");
}
}
}
pin(WEb){
direction : input;
capacitance : 9.8242;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
values("0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015",\
"0.009, 0.009, 0.015");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
values("0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004",\
"0.002, 0.002, -0.004");
}
fall_constraint(CONSTRAINT_TABLE) {
values("-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016",\
"-0.004, -0.004, -0.016");
}
}
}
@ -303,25 +303,25 @@ cell (sram_2_16_1_scn3me_subm){
pin(clk){
clock : true;
direction : input;
capacitance : 9.8242;
capacitance : 0.2091;
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("4.375");
values("0.5275");
}
fall_constraint(scalar) {
values("4.375");
values("0.5275");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("8.75");
values("1.055");
}
fall_constraint(scalar) {
values("8.75");
values("1.055");
}
}
}

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_freepdk45_lib){
library (sram_2_16_1_freepdk45_TT_10V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
@ -9,7 +9,7 @@ library (sram_2_16_1_freepdk45_lib){
pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){
voltage : 1.0 ;
temperature : 25.000 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
@ -74,7 +74,7 @@ cell (sram_2_16_1_freepdk45){
dont_use : true;
map_only : true;
dont_touch : true;
area : 0.023625;
area : 918.5120625;
bus(DATA){
bus_type : DATA;
@ -92,19 +92,19 @@ cell (sram_2_16_1_freepdk45){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0.027781");
values("0.039115101");
}
fall_power(scalar){
values("0.026752");
values("0.026662611");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -129,10 +129,10 @@ cell (sram_2_16_1_freepdk45){
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0.031198");
values("0.036300681");
}
fall_power(scalar){
values("0.031252");
values("0.041472985");
}
}
timing(){
@ -140,24 +140,24 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.046, 0.047, 0.054",\
"0.047, 0.047, 0.054",\
"0.052, 0.052, 0.059");
values("0.054, 0.055, 0.061",\
"0.055, 0.055, 0.062",\
"0.06, 0.061, 0.067");
}
cell_fall(CELL_TABLE) {
values("0.132, 0.133, 0.142",\
"0.133, 0.134, 0.142",\
"0.138, 0.139, 0.147");
values("0.519, 0.52, 0.529",\
"0.519, 0.52, 0.53",\
"0.525, 0.526, 0.535");
}
rise_transition(CELL_TABLE) {
values("0.014, 0.015, 0.027",\
"0.014, 0.015, 0.027",\
"0.014, 0.015, 0.027");
values("0.013, 0.014, 0.026",\
"0.013, 0.014, 0.026",\
"0.013, 0.015, 0.026");
}
fall_transition(CELL_TABLE) {
values("0.018, 0.02, 0.036",\
"0.019, 0.02, 0.036",\
"0.019, 0.02, 0.036");
values("0.027, 0.029, 0.043",\
"0.027, 0.029, 0.043",\
"0.027, 0.029, 0.043");
}
}
}
@ -174,9 +174,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -208,9 +208,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -241,9 +241,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -274,9 +274,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -308,20 +308,20 @@ cell (sram_2_16_1_freepdk45){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("0.1955");
values("0.5275");
}
fall_constraint(scalar) {
values("0.1955");
values("0.5275");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("0.391");
values("1.055");
}
fall_constraint(scalar) {
values("0.391");
values("1.055");
}
}
}

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_freepdk45_lib){
library (sram_2_16_1_freepdk45_TT_10V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
@ -9,7 +9,7 @@ library (sram_2_16_1_freepdk45_lib){
pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){
voltage : 1.0 ;
temperature : 25.000 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
@ -74,7 +74,7 @@ cell (sram_2_16_1_freepdk45){
dont_use : true;
map_only : true;
dont_touch : true;
area : 0.023625;
area : 918.5120625;
bus(DATA){
bus_type : DATA;
@ -92,19 +92,19 @@ cell (sram_2_16_1_freepdk45){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0.027781");
values("0.039115101");
}
fall_power(scalar){
values("0.026752");
values("0.026662611");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -129,10 +129,10 @@ cell (sram_2_16_1_freepdk45){
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0.031198");
values("0.036300681");
}
fall_power(scalar){
values("0.031252");
values("0.041472985");
}
}
timing(){
@ -140,24 +140,24 @@ cell (sram_2_16_1_freepdk45){
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.046, 0.047, 0.054",\
"0.047, 0.047, 0.054",\
"0.052, 0.052, 0.059");
values("0.054, 0.055, 0.061",\
"0.055, 0.055, 0.062",\
"0.06, 0.061, 0.067");
}
cell_fall(CELL_TABLE) {
values("0.132, 0.133, 0.142",\
"0.133, 0.134, 0.142",\
"0.138, 0.139, 0.147");
values("0.519, 0.52, 0.529",\
"0.519, 0.52, 0.53",\
"0.525, 0.526, 0.535");
}
rise_transition(CELL_TABLE) {
values("0.014, 0.015, 0.027",\
"0.014, 0.015, 0.027",\
"0.014, 0.015, 0.027");
values("0.013, 0.014, 0.026",\
"0.013, 0.014, 0.026",\
"0.013, 0.015, 0.026");
}
fall_transition(CELL_TABLE) {
values("0.018, 0.02, 0.036",\
"0.019, 0.02, 0.036",\
"0.019, 0.02, 0.036");
values("0.027, 0.029, 0.043",\
"0.027, 0.029, 0.043",\
"0.027, 0.029, 0.043");
}
}
}
@ -174,9 +174,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -208,9 +208,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -241,9 +241,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -274,9 +274,9 @@ cell (sram_2_16_1_freepdk45){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027",\
"0.009, 0.015, 0.027");
values("0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.015",\
@ -308,20 +308,20 @@ cell (sram_2_16_1_freepdk45){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("0.1955");
values("0.5275");
}
fall_constraint(scalar) {
values("0.1955");
values("0.5275");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("0.391");
values("1.055");
}
fall_constraint(scalar) {
values("0.391");
values("1.055");
}
}
}

View File

@ -1,329 +0,0 @@
library (sram_2_16_1_freepdk45_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(TT){
voltage : 1.0 ;
temperature : 25.000 ;
}
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 ;
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.00125, 0.005, 0.04");
index_2("0.052275, 0.2091, 1.6728");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.00125, 0.005, 0.04");
index_2("0.00125, 0.005, 0.04");
}
default_operating_conditions : TT;
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_freepdk45){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 0.023625;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 1.6728;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
clocked_on : clk;
}
memory_read(){
address : ADDR;
}
pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_sense : non_unate;
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.123, 0.124, 0.133",\
"0.123, 0.124, 0.133",\
"0.123, 0.124, 0.133");
}
cell_fall(CELL_TABLE) {
values("0.123, 0.124, 0.133",\
"0.123, 0.124, 0.133",\
"0.123, 0.124, 0.133");
}
rise_transition(CELL_TABLE) {
values("0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018");
}
fall_transition(CELL_TABLE) {
values("0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018",\
"0.006, 0.007, 0.018");
}
}
}
}
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 0.2091;
max_transition : 0.04;
fanout_load : 1.000000;
pin(ADDR[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
pin(CSb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(OEb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(WEb){
direction : input;
capacitance : 0.2091;
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(clk){
clock : true;
direction : input;
capacitance : 0.2091;
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
}
}
}

View File

@ -7,11 +7,11 @@ UNITS
END UNITS
SITE MacroSite
CLASS Core ;
SIZE 2250.0 by 1200.0 ;
SIZE 277800.0 by 440700.0 ;
END MacroSite
MACRO sram_2_16_1_scn3me_subm
CLASS BLOCK ;
SIZE 2250.0 BY 1200.0 ;
SIZE 277800.0 BY 440700.0 ;
SYMMETRY X Y R90 ;
SITE MacroSite ;
PIN DATA[0]
@ -577,14 +577,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 127050.0 109650.0 122100.0 110550.0 ;
RECT 130050.0 118350.0 105450.0 119250.0 ;
RECT 127050.0 132150.0 102450.0 133050.0 ;
RECT 111450.0 93750.0 94500.0 94650.0 ;
RECT 108450.0 96450.0 97500.0 97350.0 ;
RECT 105450.0 111150.0 94500.0 112050.0 ;
RECT 108450.0 108450.0 97500.0 109350.0 ;
RECT 111450.0 121350.0 94500.0 122250.0 ;
RECT 102450.0 124050.0 97500.0 124950.0 ;
RECT 105450.0 138750.0 94500.0 139650.0 ;
RECT 102450.0 136050.0 97500.0 136950.0 ;
RECT 111450.0 96450.0 97500.0 97350.0 ;
RECT 108450.0 93750.0 94500.0 94650.0 ;
RECT 105450.0 108450.0 97500.0 109350.0 ;
RECT 108450.0 111150.0 94500.0 112050.0 ;
RECT 111450.0 124050.0 97500.0 124950.0 ;
RECT 102450.0 121350.0 94500.0 122250.0 ;
RECT 105450.0 136050.0 97500.0 136950.0 ;
RECT 102450.0 138750.0 94500.0 139650.0 ;
RECT 88050.0 96450.0 87150.0 97350.0 ;
RECT 88050.0 95250.0 87150.0 96150.0 ;
RECT 92100.0 96450.0 87600.0 97350.0 ;
@ -865,14 +865,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 104850.0 118200.0 106050.0 119400.0 ;
RECT 126450.0 132000.0 127650.0 133200.0 ;
RECT 101850.0 132000.0 103050.0 133200.0 ;
RECT 110850.0 93600.0 112050.0 94800.0 ;
RECT 107850.0 96300.0 109050.0 97500.0 ;
RECT 104850.0 111000.0 106050.0 112200.0 ;
RECT 107850.0 108300.0 109050.0 109500.0 ;
RECT 110850.0 121200.0 112050.0 122400.0 ;
RECT 101850.0 123900.0 103050.0 125100.0 ;
RECT 104850.0 138600.0 106050.0 139800.0 ;
RECT 101850.0 135900.0 103050.0 137100.0 ;
RECT 110850.0 96300.0 112050.0 97500.0 ;
RECT 107850.0 93600.0 109050.0 94800.0 ;
RECT 104850.0 108300.0 106050.0 109500.0 ;
RECT 107850.0 111000.0 109050.0 112200.0 ;
RECT 110850.0 123900.0 112050.0 125100.0 ;
RECT 101850.0 121200.0 103050.0 122400.0 ;
RECT 104850.0 135900.0 106050.0 137100.0 ;
RECT 101850.0 138600.0 103050.0 139800.0 ;
RECT 79650.0 95250.0 75900.0 96150.0 ;
RECT 79650.0 109650.0 75900.0 110550.0 ;
RECT 79650.0 122850.0 75900.0 123750.0 ;
@ -896,14 +896,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 127050.0 164850.0 122100.0 165750.0 ;
RECT 130050.0 173550.0 105450.0 174450.0 ;
RECT 127050.0 187350.0 102450.0 188250.0 ;
RECT 111450.0 148950.0 94500.0 149850.0 ;
RECT 108450.0 151650.0 97500.0 152550.0 ;
RECT 105450.0 166350.0 94500.0 167250.0 ;
RECT 108450.0 163650.0 97500.0 164550.0 ;
RECT 111450.0 176550.0 94500.0 177450.0 ;
RECT 102450.0 179250.0 97500.0 180150.0 ;
RECT 105450.0 193950.0 94500.0 194850.0 ;
RECT 102450.0 191250.0 97500.0 192150.0 ;
RECT 111450.0 151650.0 97500.0 152550.0 ;
RECT 108450.0 148950.0 94500.0 149850.0 ;
RECT 105450.0 163650.0 97500.0 164550.0 ;
RECT 108450.0 166350.0 94500.0 167250.0 ;
RECT 111450.0 179250.0 97500.0 180150.0 ;
RECT 102450.0 176550.0 94500.0 177450.0 ;
RECT 105450.0 191250.0 97500.0 192150.0 ;
RECT 102450.0 193950.0 94500.0 194850.0 ;
RECT 88050.0 151650.0 87150.0 152550.0 ;
RECT 88050.0 150450.0 87150.0 151350.0 ;
RECT 92100.0 151650.0 87600.0 152550.0 ;
@ -1184,14 +1184,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 104850.0 173400.0 106050.0 174600.0 ;
RECT 126450.0 187200.0 127650.0 188400.0 ;
RECT 101850.0 187200.0 103050.0 188400.0 ;
RECT 110850.0 148800.0 112050.0 150000.0 ;
RECT 107850.0 151500.0 109050.0 152700.0 ;
RECT 104850.0 166200.0 106050.0 167400.0 ;
RECT 107850.0 163500.0 109050.0 164700.0 ;
RECT 110850.0 176400.0 112050.0 177600.0 ;
RECT 101850.0 179100.0 103050.0 180300.0 ;
RECT 104850.0 193800.0 106050.0 195000.0 ;
RECT 101850.0 191100.0 103050.0 192300.0 ;
RECT 110850.0 151500.0 112050.0 152700.0 ;
RECT 107850.0 148800.0 109050.0 150000.0 ;
RECT 104850.0 163500.0 106050.0 164700.0 ;
RECT 107850.0 166200.0 109050.0 167400.0 ;
RECT 110850.0 179100.0 112050.0 180300.0 ;
RECT 101850.0 176400.0 103050.0 177600.0 ;
RECT 104850.0 191100.0 106050.0 192300.0 ;
RECT 101850.0 193800.0 103050.0 195000.0 ;
RECT 79650.0 150450.0 75900.0 151350.0 ;
RECT 79650.0 164850.0 75900.0 165750.0 ;
RECT 79650.0 178050.0 75900.0 178950.0 ;
@ -4105,9 +4105,11 @@ MACRO sram_2_16_1_scn3me_subm
RECT 16050.0 358350.0 15150.0 359250.0 ;
RECT 8850.0 353400.0 7950.0 363000.0 ;
RECT 22650.0 353400.0 21750.0 363000.0 ;
RECT 22650.0 396900.0 16800.0 397800.0 ;
RECT 22650.0 420300.0 16800.0 421200.0 ;
RECT 22200.0 427650.0 16800.0 428550.0 ;
RECT 22650.0 499050.0 21750.0 430200.0 ;
RECT 21750.0 397050.0 17400.0 397950.0 ;
RECT 21750.0 420450.0 17400.0 421350.0 ;
RECT 22650.0 371550.0 16800.0 372450.0 ;
RECT 16800.0 371550.0 6600.0 372450.0 ;
RECT 4500.0 408600.0 16800.0 409500.0 ;
RECT 4500.0 381000.0 16800.0 381900.0 ;
RECT 29250.0 397800.0 28350.0 410400.0 ;
@ -4148,11 +4150,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 396000.0 33750.0 397200.0 ;
RECT 21750.0 430950.0 22650.0 431850.0 ;
RECT 49350.0 430950.0 50250.0 431850.0 ;
RECT 21750.0 429600.0 22650.0 431400.0 ;
RECT 22200.0 430950.0 49800.0 431850.0 ;
RECT 49350.0 429600.0 50250.0 431400.0 ;
RECT 21750.0 498150.0 22650.0 499050.0 ;
RECT 49350.0 498150.0 50250.0 499050.0 ;
RECT 21750.0 496800.0 22650.0 498600.0 ;
RECT 22200.0 498150.0 49800.0 499050.0 ;
RECT 49350.0 496800.0 50250.0 498600.0 ;
RECT 37950.0 417000.0 36000.0 418200.0 ;
RECT 49800.0 417000.0 47850.0 418200.0 ;
RECT 48450.0 412200.0 50250.0 413400.0 ;
@ -4194,6 +4196,279 @@ MACRO sram_2_16_1_scn3me_subm
RECT 36450.0 420000.0 35550.0 429600.0 ;
RECT 50250.0 420000.0 49350.0 429600.0 ;
RECT 42600.0 422400.0 43800.0 423600.0 ;
RECT 37950.0 436200.0 36000.0 437400.0 ;
RECT 49800.0 436200.0 47850.0 437400.0 ;
RECT 48450.0 431400.0 50250.0 432600.0 ;
RECT 39150.0 431400.0 35550.0 432600.0 ;
RECT 48450.0 434100.0 39150.0 435000.0 ;
RECT 39150.0 431400.0 37950.0 432600.0 ;
RECT 39150.0 433800.0 37950.0 435000.0 ;
RECT 39150.0 433800.0 37950.0 435000.0 ;
RECT 39150.0 431400.0 37950.0 432600.0 ;
RECT 48450.0 431400.0 47250.0 432600.0 ;
RECT 48450.0 433800.0 47250.0 435000.0 ;
RECT 48450.0 433800.0 47250.0 435000.0 ;
RECT 48450.0 431400.0 47250.0 432600.0 ;
RECT 38550.0 436200.0 37350.0 437400.0 ;
RECT 48450.0 436200.0 47250.0 437400.0 ;
RECT 43800.0 432000.0 42600.0 433200.0 ;
RECT 43800.0 432000.0 42600.0 433200.0 ;
RECT 43650.0 434550.0 42750.0 435450.0 ;
RECT 36450.0 429600.0 35550.0 439200.0 ;
RECT 50250.0 429600.0 49350.0 439200.0 ;
RECT 42600.0 432000.0 43800.0 433200.0 ;
RECT 37950.0 445800.0 36000.0 447000.0 ;
RECT 49800.0 445800.0 47850.0 447000.0 ;
RECT 48450.0 441000.0 50250.0 442200.0 ;
RECT 39150.0 441000.0 35550.0 442200.0 ;
RECT 48450.0 443700.0 39150.0 444600.0 ;
RECT 39150.0 441000.0 37950.0 442200.0 ;
RECT 39150.0 443400.0 37950.0 444600.0 ;
RECT 39150.0 443400.0 37950.0 444600.0 ;
RECT 39150.0 441000.0 37950.0 442200.0 ;
RECT 48450.0 441000.0 47250.0 442200.0 ;
RECT 48450.0 443400.0 47250.0 444600.0 ;
RECT 48450.0 443400.0 47250.0 444600.0 ;
RECT 48450.0 441000.0 47250.0 442200.0 ;
RECT 38550.0 445800.0 37350.0 447000.0 ;
RECT 48450.0 445800.0 47250.0 447000.0 ;
RECT 43800.0 441600.0 42600.0 442800.0 ;
RECT 43800.0 441600.0 42600.0 442800.0 ;
RECT 43650.0 444150.0 42750.0 445050.0 ;
RECT 36450.0 439200.0 35550.0 448800.0 ;
RECT 50250.0 439200.0 49350.0 448800.0 ;
RECT 42600.0 441600.0 43800.0 442800.0 ;
RECT 37950.0 455400.0 36000.0 456600.0 ;
RECT 49800.0 455400.0 47850.0 456600.0 ;
RECT 48450.0 450600.0 50250.0 451800.0 ;
RECT 39150.0 450600.0 35550.0 451800.0 ;
RECT 48450.0 453300.0 39150.0 454200.0 ;
RECT 39150.0 450600.0 37950.0 451800.0 ;
RECT 39150.0 453000.0 37950.0 454200.0 ;
RECT 39150.0 453000.0 37950.0 454200.0 ;
RECT 39150.0 450600.0 37950.0 451800.0 ;
RECT 48450.0 450600.0 47250.0 451800.0 ;
RECT 48450.0 453000.0 47250.0 454200.0 ;
RECT 48450.0 453000.0 47250.0 454200.0 ;
RECT 48450.0 450600.0 47250.0 451800.0 ;
RECT 38550.0 455400.0 37350.0 456600.0 ;
RECT 48450.0 455400.0 47250.0 456600.0 ;
RECT 43800.0 451200.0 42600.0 452400.0 ;
RECT 43800.0 451200.0 42600.0 452400.0 ;
RECT 43650.0 453750.0 42750.0 454650.0 ;
RECT 36450.0 448800.0 35550.0 458400.0 ;
RECT 50250.0 448800.0 49350.0 458400.0 ;
RECT 42600.0 451200.0 43800.0 452400.0 ;
RECT 37950.0 465000.0 36000.0 466200.0 ;
RECT 49800.0 465000.0 47850.0 466200.0 ;
RECT 48450.0 460200.0 50250.0 461400.0 ;
RECT 39150.0 460200.0 35550.0 461400.0 ;
RECT 48450.0 462900.0 39150.0 463800.0 ;
RECT 39150.0 460200.0 37950.0 461400.0 ;
RECT 39150.0 462600.0 37950.0 463800.0 ;
RECT 39150.0 462600.0 37950.0 463800.0 ;
RECT 39150.0 460200.0 37950.0 461400.0 ;
RECT 48450.0 460200.0 47250.0 461400.0 ;
RECT 48450.0 462600.0 47250.0 463800.0 ;
RECT 48450.0 462600.0 47250.0 463800.0 ;
RECT 48450.0 460200.0 47250.0 461400.0 ;
RECT 38550.0 465000.0 37350.0 466200.0 ;
RECT 48450.0 465000.0 47250.0 466200.0 ;
RECT 43800.0 460800.0 42600.0 462000.0 ;
RECT 43800.0 460800.0 42600.0 462000.0 ;
RECT 43650.0 463350.0 42750.0 464250.0 ;
RECT 36450.0 458400.0 35550.0 468000.0 ;
RECT 50250.0 458400.0 49350.0 468000.0 ;
RECT 42600.0 460800.0 43800.0 462000.0 ;
RECT 37950.0 474600.0 36000.0 475800.0 ;
RECT 49800.0 474600.0 47850.0 475800.0 ;
RECT 48450.0 469800.0 50250.0 471000.0 ;
RECT 39150.0 469800.0 35550.0 471000.0 ;
RECT 48450.0 472500.0 39150.0 473400.0 ;
RECT 39150.0 469800.0 37950.0 471000.0 ;
RECT 39150.0 472200.0 37950.0 473400.0 ;
RECT 39150.0 472200.0 37950.0 473400.0 ;
RECT 39150.0 469800.0 37950.0 471000.0 ;
RECT 48450.0 469800.0 47250.0 471000.0 ;
RECT 48450.0 472200.0 47250.0 473400.0 ;
RECT 48450.0 472200.0 47250.0 473400.0 ;
RECT 48450.0 469800.0 47250.0 471000.0 ;
RECT 38550.0 474600.0 37350.0 475800.0 ;
RECT 48450.0 474600.0 47250.0 475800.0 ;
RECT 43800.0 470400.0 42600.0 471600.0 ;
RECT 43800.0 470400.0 42600.0 471600.0 ;
RECT 43650.0 472950.0 42750.0 473850.0 ;
RECT 36450.0 468000.0 35550.0 477600.0 ;
RECT 50250.0 468000.0 49350.0 477600.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 22200.0 461400.0 24150.0 460200.0 ;
RECT 23550.0 466200.0 21750.0 465000.0 ;
RECT 32850.0 466200.0 36450.0 465000.0 ;
RECT 23550.0 463500.0 32850.0 462600.0 ;
RECT 32850.0 466200.0 34050.0 465000.0 ;
RECT 32850.0 463800.0 34050.0 462600.0 ;
RECT 32850.0 463800.0 34050.0 462600.0 ;
RECT 32850.0 466200.0 34050.0 465000.0 ;
RECT 23550.0 466200.0 24750.0 465000.0 ;
RECT 23550.0 463800.0 24750.0 462600.0 ;
RECT 23550.0 463800.0 24750.0 462600.0 ;
RECT 23550.0 466200.0 24750.0 465000.0 ;
RECT 33450.0 461400.0 34650.0 460200.0 ;
RECT 23550.0 461400.0 24750.0 460200.0 ;
RECT 28200.0 465600.0 29400.0 464400.0 ;
RECT 28200.0 465600.0 29400.0 464400.0 ;
RECT 28350.0 463050.0 29250.0 462150.0 ;
RECT 35550.0 468000.0 36450.0 458400.0 ;
RECT 21750.0 468000.0 22650.0 458400.0 ;
RECT 28200.0 464400.0 29400.0 465600.0 ;
RECT 34050.0 451800.0 36000.0 450600.0 ;
RECT 22200.0 451800.0 24150.0 450600.0 ;
RECT 23550.0 456600.0 21750.0 455400.0 ;
RECT 32850.0 456600.0 36450.0 455400.0 ;
RECT 23550.0 453900.0 32850.0 453000.0 ;
RECT 32850.0 456600.0 34050.0 455400.0 ;
RECT 32850.0 454200.0 34050.0 453000.0 ;
RECT 32850.0 454200.0 34050.0 453000.0 ;
RECT 32850.0 456600.0 34050.0 455400.0 ;
RECT 23550.0 456600.0 24750.0 455400.0 ;
RECT 23550.0 454200.0 24750.0 453000.0 ;
RECT 23550.0 454200.0 24750.0 453000.0 ;
RECT 23550.0 456600.0 24750.0 455400.0 ;
RECT 33450.0 451800.0 34650.0 450600.0 ;
RECT 23550.0 451800.0 24750.0 450600.0 ;
RECT 28200.0 456000.0 29400.0 454800.0 ;
RECT 28200.0 456000.0 29400.0 454800.0 ;
RECT 28350.0 453450.0 29250.0 452550.0 ;
RECT 35550.0 458400.0 36450.0 448800.0 ;
RECT 21750.0 458400.0 22650.0 448800.0 ;
RECT 28200.0 454800.0 29400.0 456000.0 ;
RECT 34050.0 442200.0 36000.0 441000.0 ;
RECT 22200.0 442200.0 24150.0 441000.0 ;
RECT 23550.0 447000.0 21750.0 445800.0 ;
RECT 32850.0 447000.0 36450.0 445800.0 ;
RECT 23550.0 444300.0 32850.0 443400.0 ;
RECT 32850.0 447000.0 34050.0 445800.0 ;
RECT 32850.0 444600.0 34050.0 443400.0 ;
RECT 32850.0 444600.0 34050.0 443400.0 ;
RECT 32850.0 447000.0 34050.0 445800.0 ;
RECT 23550.0 447000.0 24750.0 445800.0 ;
RECT 23550.0 444600.0 24750.0 443400.0 ;
RECT 23550.0 444600.0 24750.0 443400.0 ;
RECT 23550.0 447000.0 24750.0 445800.0 ;
RECT 33450.0 442200.0 34650.0 441000.0 ;
RECT 23550.0 442200.0 24750.0 441000.0 ;
RECT 28200.0 446400.0 29400.0 445200.0 ;
RECT 28200.0 446400.0 29400.0 445200.0 ;
RECT 28350.0 443850.0 29250.0 442950.0 ;
RECT 35550.0 448800.0 36450.0 439200.0 ;
RECT 21750.0 448800.0 22650.0 439200.0 ;
RECT 28200.0 445200.0 29400.0 446400.0 ;
RECT 34050.0 432600.0 36000.0 431400.0 ;
RECT 22200.0 432600.0 24150.0 431400.0 ;
RECT 23550.0 437400.0 21750.0 436200.0 ;
RECT 32850.0 437400.0 36450.0 436200.0 ;
RECT 23550.0 434700.0 32850.0 433800.0 ;
RECT 32850.0 437400.0 34050.0 436200.0 ;
RECT 32850.0 435000.0 34050.0 433800.0 ;
RECT 32850.0 435000.0 34050.0 433800.0 ;
RECT 32850.0 437400.0 34050.0 436200.0 ;
RECT 23550.0 437400.0 24750.0 436200.0 ;
RECT 23550.0 435000.0 24750.0 433800.0 ;
RECT 23550.0 435000.0 24750.0 433800.0 ;
RECT 23550.0 437400.0 24750.0 436200.0 ;
RECT 33450.0 432600.0 34650.0 431400.0 ;
RECT 23550.0 432600.0 24750.0 431400.0 ;
RECT 28200.0 436800.0 29400.0 435600.0 ;
RECT 28200.0 436800.0 29400.0 435600.0 ;
RECT 28350.0 434250.0 29250.0 433350.0 ;
RECT 35550.0 439200.0 36450.0 429600.0 ;
RECT 21750.0 439200.0 22650.0 429600.0 ;
RECT 28200.0 435600.0 29400.0 436800.0 ;
RECT 34050.0 423000.0 36000.0 421800.0 ;
RECT 22200.0 423000.0 24150.0 421800.0 ;
RECT 23550.0 427800.0 21750.0 426600.0 ;
@ -4237,25 +4512,26 @@ MACRO sram_2_16_1_scn3me_subm
RECT 21750.0 420000.0 22650.0 410400.0 ;
RECT 28200.0 416400.0 29400.0 417600.0 ;
RECT 42600.0 415200.0 43800.0 416400.0 ;
RECT 42600.0 424800.0 43800.0 426000.0 ;
RECT 28200.0 423600.0 29400.0 424800.0 ;
RECT 42600.0 453600.0 43800.0 454800.0 ;
RECT 42600.0 492000.0 43800.0 493200.0 ;
RECT 28200.0 452400.0 29400.0 453600.0 ;
RECT 42600.0 412800.0 43800.0 414000.0 ;
RECT 28350.0 410400.0 29250.0 414150.0 ;
RECT 35550.0 410400.0 36450.0 429600.0 ;
RECT 21750.0 410400.0 22650.0 429600.0 ;
RECT 49350.0 410400.0 50250.0 429600.0 ;
RECT 35550.0 410400.0 36450.0 496800.0 ;
RECT 21750.0 410400.0 22650.0 496800.0 ;
RECT 49350.0 410400.0 50250.0 496800.0 ;
RECT 16800.0 395400.0 6600.0 381600.0 ;
RECT 16800.0 395400.0 6600.0 409200.0 ;
RECT 16800.0 423000.0 6600.0 409200.0 ;
RECT 17400.0 396900.0 6000.0 398100.0 ;
RECT 17400.0 420300.0 6000.0 421500.0 ;
RECT 17400.0 408600.0 6000.0 409500.0 ;
RECT 22650.0 396900.0 21450.0 398100.0 ;
RECT 22650.0 420300.0 21450.0 421500.0 ;
RECT 22650.0 410400.0 21450.0 411600.0 ;
RECT 22650.0 370800.0 21450.0 372000.0 ;
RECT 21600.0 427500.0 22800.0 428700.0 ;
RECT 16200.0 427500.0 17400.0 428700.0 ;
RECT 22350.0 396900.0 21150.0 398100.0 ;
RECT 22350.0 420300.0 21150.0 421500.0 ;
RECT 22200.0 410400.0 21000.0 411600.0 ;
RECT 22800.0 370800.0 21600.0 372000.0 ;
RECT 16200.0 371400.0 17400.0 372600.0 ;
RECT 6000.0 371400.0 7200.0 372600.0 ;
RECT 29400.0 397200.0 28200.0 398400.0 ;
RECT 19350.0 383700.0 20550.0 384900.0 ;
RECT 19350.0 375600.0 20550.0 376800.0 ;
@ -4264,7 +4540,7 @@ MACRO sram_2_16_1_scn3me_subm
RECT 29250.0 362400.0 28350.0 375750.0 ;
RECT 4500.0 362400.0 3600.0 425250.0 ;
RECT 36450.0 362400.0 35550.0 410400.0 ;
RECT 22650.0 362400.0 21750.0 381600.0 ;
RECT 22650.0 362400.0 21750.0 372000.0 ;
RECT 50250.0 362400.0 49350.0 410400.0 ;
RECT 43950.0 285750.0 42750.0 284550.0 ;
RECT 43950.0 244800.0 42750.0 243600.0 ;
@ -4461,14 +4737,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 104850.0 118200.0 106050.0 119400.0 ;
RECT 126450.0 132000.0 127650.0 133200.0 ;
RECT 101850.0 132000.0 103050.0 133200.0 ;
RECT 110850.0 93600.0 112050.0 94800.0 ;
RECT 107850.0 96300.0 109050.0 97500.0 ;
RECT 104850.0 111000.0 106050.0 112200.0 ;
RECT 107850.0 108300.0 109050.0 109500.0 ;
RECT 110850.0 121200.0 112050.0 122400.0 ;
RECT 101850.0 123900.0 103050.0 125100.0 ;
RECT 104850.0 138600.0 106050.0 139800.0 ;
RECT 101850.0 135900.0 103050.0 137100.0 ;
RECT 110850.0 96300.0 112050.0 97500.0 ;
RECT 107850.0 93600.0 109050.0 94800.0 ;
RECT 104850.0 108300.0 106050.0 109500.0 ;
RECT 107850.0 111000.0 109050.0 112200.0 ;
RECT 110850.0 123900.0 112050.0 125100.0 ;
RECT 101850.0 121200.0 103050.0 122400.0 ;
RECT 104850.0 135900.0 106050.0 137100.0 ;
RECT 101850.0 138600.0 103050.0 139800.0 ;
RECT 130500.0 89100.0 129600.0 142500.0 ;
RECT 127500.0 89100.0 126600.0 142500.0 ;
RECT 105900.0 144300.0 105000.0 197700.0 ;
@ -4515,14 +4791,14 @@ MACRO sram_2_16_1_scn3me_subm
RECT 104850.0 173400.0 106050.0 174600.0 ;
RECT 126450.0 187200.0 127650.0 188400.0 ;
RECT 101850.0 187200.0 103050.0 188400.0 ;
RECT 110850.0 148800.0 112050.0 150000.0 ;
RECT 107850.0 151500.0 109050.0 152700.0 ;
RECT 104850.0 166200.0 106050.0 167400.0 ;
RECT 107850.0 163500.0 109050.0 164700.0 ;
RECT 110850.0 176400.0 112050.0 177600.0 ;
RECT 101850.0 179100.0 103050.0 180300.0 ;
RECT 104850.0 193800.0 106050.0 195000.0 ;
RECT 101850.0 191100.0 103050.0 192300.0 ;
RECT 110850.0 151500.0 112050.0 152700.0 ;
RECT 107850.0 148800.0 109050.0 150000.0 ;
RECT 104850.0 163500.0 106050.0 164700.0 ;
RECT 107850.0 166200.0 109050.0 167400.0 ;
RECT 110850.0 179100.0 112050.0 180300.0 ;
RECT 101850.0 176400.0 103050.0 177600.0 ;
RECT 104850.0 191100.0 106050.0 192300.0 ;
RECT 101850.0 193800.0 103050.0 195000.0 ;
RECT 130500.0 144300.0 129600.0 197700.0 ;
RECT 127500.0 144300.0 126600.0 197700.0 ;
RECT 80250.0 206850.0 81150.0 207750.0 ;
@ -5006,6 +5282,7 @@ MACRO sram_2_16_1_scn3me_subm
RECT 49800.0 292800.0 1.42108547152e-11 293700.0 ;
RECT 49800.0 295500.0 1.42108547152e-11 296400.0 ;
RECT 49800.0 300900.0 1.42108547152e-11 301800.0 ;
RECT 43350.0 243750.0 36000.0 244650.0 ;
RECT 33750.0 205350.0 32850.0 285150.0 ;
RECT 49800.0 287400.0 47100.0 288300.0 ;
RECT 38700.0 298200.0 36000.0 299100.0 ;
@ -5071,25 +5348,51 @@ MACRO sram_2_16_1_scn3me_subm
RECT 10800.0 288450.0 9600.0 287250.0 ;
RECT 31200.0 263100.0 30000.0 261900.0 ;
RECT 31200.0 288450.0 30000.0 287250.0 ;
RECT 22650.0 372000.0 21750.0 427500.0 ;
RECT 22650.0 381600.0 21750.0 384300.0 ;
RECT 22650.0 384300.0 21750.0 428100.0 ;
RECT 17250.0 425400.0 16350.0 428100.0 ;
RECT 22650.0 372000.0 21750.0 430200.0 ;
RECT 17250.0 372000.0 16350.0 425400.0 ;
RECT 7050.0 372000.0 6150.0 425400.0 ;
RECT 20400.0 376200.0 19500.0 384300.0 ;
RECT 13650.0 376200.0 12750.0 381000.0 ;
RECT 42750.0 415800.0 43650.0 423000.0 ;
RECT 35550.0 424950.0 36450.0 425850.0 ;
RECT 35550.0 426150.0 36450.0 427050.0 ;
RECT 36000.0 424950.0 43200.0 425850.0 ;
RECT 35550.0 425400.0 36450.0 426600.0 ;
RECT 28800.0 426150.0 36000.0 427050.0 ;
RECT 28350.0 417000.0 29250.0 424200.0 ;
RECT 42750.0 423000.0 43650.0 432600.0 ;
RECT 42750.0 432600.0 43650.0 442200.0 ;
RECT 42750.0 442200.0 43650.0 451800.0 ;
RECT 42750.0 454200.0 43650.0 461400.0 ;
RECT 42750.0 461400.0 43650.0 471000.0 ;
RECT 42750.0 471000.0 43650.0 480600.0 ;
RECT 42750.0 480600.0 43650.0 490200.0 ;
RECT 35550.0 492150.0 36450.0 493050.0 ;
RECT 35550.0 483750.0 36450.0 484650.0 ;
RECT 36000.0 492150.0 43200.0 493050.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 445800.0 29250.0 453000.0 ;
RECT 28350.0 436200.0 29250.0 445800.0 ;
RECT 28350.0 426600.0 29250.0 436200.0 ;
RECT 28350.0 417000.0 29250.0 426600.0 ;
RECT 42600.0 422400.0 43800.0 423600.0 ;
RECT 42600.0 432000.0 43800.0 433200.0 ;
RECT 42600.0 441600.0 43800.0 442800.0 ;
RECT 42600.0 451200.0 43800.0 452400.0 ;
RECT 42600.0 460800.0 43800.0 462000.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 454800.0 29400.0 456000.0 ;
RECT 28200.0 445200.0 29400.0 446400.0 ;
RECT 28200.0 435600.0 29400.0 436800.0 ;
RECT 28200.0 426000.0 29400.0 427200.0 ;
RECT 28200.0 416400.0 29400.0 417600.0 ;
RECT 42600.0 415200.0 43800.0 416400.0 ;
RECT 42600.0 424800.0 43800.0 426000.0 ;
RECT 28200.0 423600.0 29400.0 424800.0 ;
RECT 42600.0 453600.0 43800.0 454800.0 ;
RECT 42600.0 492000.0 43800.0 493200.0 ;
RECT 28200.0 452400.0 29400.0 453600.0 ;
RECT 16800.0 395400.0 6600.0 381600.0 ;
RECT 16800.0 395400.0 6600.0 409200.0 ;
RECT 16800.0 423000.0 6600.0 409200.0 ;
@ -5097,19 +5400,19 @@ MACRO sram_2_16_1_scn3me_subm
RECT 10800.0 394800.0 9600.0 425400.0 ;
RECT 17400.0 394800.0 16200.0 425400.0 ;
RECT 7200.0 394800.0 6000.0 425400.0 ;
RECT 22650.0 396900.0 21450.0 398100.0 ;
RECT 22650.0 420300.0 21450.0 421500.0 ;
RECT 22650.0 410400.0 21450.0 411600.0 ;
RECT 22650.0 370800.0 21450.0 372000.0 ;
RECT 21600.0 427500.0 22800.0 428700.0 ;
RECT 16200.0 427500.0 17400.0 428700.0 ;
RECT 22350.0 396900.0 21150.0 398100.0 ;
RECT 22350.0 420300.0 21150.0 421500.0 ;
RECT 22200.0 410400.0 21000.0 411600.0 ;
RECT 22800.0 370800.0 21600.0 372000.0 ;
RECT 16200.0 371400.0 17400.0 372600.0 ;
RECT 6000.0 371400.0 7200.0 372600.0 ;
RECT 19350.0 383700.0 20550.0 384900.0 ;
RECT 19350.0 375600.0 20550.0 376800.0 ;
RECT 12600.0 375600.0 13800.0 376800.0 ;
RECT 43950.0 285750.0 42750.0 284550.0 ;
RECT 43950.0 244800.0 42750.0 243600.0 ;
RECT 43950.0 304650.0 42750.0 303450.0 ;
RECT 43950.0 244800.0 42750.0 243600.0 ;
RECT 36600.0 244800.0 35400.0 243600.0 ;
RECT 36600.0 304650.0 35400.0 303450.0 ;
RECT 33900.0 205950.0 32700.0 204750.0 ;
RECT 29850.0 285750.0 28650.0 284550.0 ;
RECT 27150.0 291150.0 25950.0 289950.0 ;
@ -5202,7 +5505,7 @@ MACRO sram_2_16_1_scn3me_subm
RECT 23550.0 262500.0 22050.0 295950.0 ;
RECT 10950.0 262500.0 9450.0 287850.0 ;
RECT 31350.0 262500.0 29850.0 287850.0 ;
RECT 44100.0 244200.0 42600.0 304050.0 ;
RECT 36750.0 244200.0 35250.0 304050.0 ;
RECT 30750.0 304050.0 29250.0 327900.0 ;
RECT 28050.0 301350.0 26550.0 330900.0 ;
RECT 4200.0 203400.0 6000.0 205200.0 ;
@ -5220,8 +5523,8 @@ MACRO sram_2_16_1_scn3me_subm
RECT 11100.0 288750.0 9300.0 286950.0 ;
RECT 31500.0 263400.0 29700.0 261600.0 ;
RECT 31500.0 288750.0 29700.0 286950.0 ;
RECT 44250.0 245100.0 42450.0 243300.0 ;
RECT 44250.0 304950.0 42450.0 303150.0 ;
RECT 36900.0 245100.0 35100.0 243300.0 ;
RECT 36900.0 304950.0 35100.0 303150.0 ;
RECT 30900.0 328800.0 29100.0 327000.0 ;
RECT 30900.0 304950.0 29100.0 303150.0 ;
RECT 28200.0 331800.0 26400.0 330000.0 ;

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_scn3me_subm_lib){
library (sram_2_16_1_scn3me_subm_TT_50V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
@ -9,7 +9,7 @@ library (sram_2_16_1_scn3me_subm_lib){
pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){
voltage : 5.0 ;
temperature : 25.000 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
@ -74,7 +74,7 @@ cell (sram_2_16_1_scn3me_subm){
dont_use : true;
map_only : true;
dont_touch : true;
area : 2.7;
area : 122426.46;
bus(DATA){
bus_type : DATA;
@ -92,47 +92,47 @@ cell (sram_2_16_1_scn3me_subm){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("3.2612");
values("11.756062");
}
fall_power(scalar){
values("3.5985");
values("7.1840422");
}
}
timing(){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
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.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
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.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
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.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("5.1597");
values("10.730552");
}
fall_power(scalar){
values("5.1863");
values("10.584523");
}
}
timing(){
@ -140,24 +140,24 @@ cell (sram_2_16_1_scn3me_subm){
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.509, 0.592, 1.265",\
"0.512, 0.595, 1.271",\
"0.561, 0.642, 1.317");
values("0.458, 0.503, 0.87",\
"0.461, 0.505, 0.873",\
"0.5, 0.544, 0.911");
}
cell_fall(CELL_TABLE) {
values("1.449, 1.549, 2.511",\
"1.453, 1.555, 2.518",\
"1.505, 1.607, 2.568");
values("0.573, 0.649, 1.249",\
"0.576, 0.651, 1.252",\
"0.616, 0.69, 1.289");
}
rise_transition(CELL_TABLE) {
values("0.19, 0.335, 1.887",\
"0.192, 0.336, 1.886",\
"0.194, 0.339, 1.886");
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.282, 0.465, 2.464",\
"0.283, 0.466, 2.463",\
"0.283, 0.465, 2.455");
values("0.277, 0.355, 1.499",\
"0.277, 0.357, 1.499",\
"0.278, 0.362, 1.499");
}
}
}
@ -174,28 +174,28 @@ cell (sram_2_16_1_scn3me_subm){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
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.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
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.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
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.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
@ -208,28 +208,28 @@ cell (sram_2_16_1_scn3me_subm){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
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.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
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.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
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.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
@ -241,28 +241,28 @@ cell (sram_2_16_1_scn3me_subm){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
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.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
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.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
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.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
@ -274,28 +274,28 @@ cell (sram_2_16_1_scn3me_subm){
timing_type : setup_rising;
related_pin : "clk";
rise_constraint(CONSTRAINT_TABLE) {
values("0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186",\
"0.082, 0.088, 0.186");
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.021, 0.021, 0.027",\
"0.021, 0.021, 0.027",\
"0.021, 0.021, 0.027");
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.009, 0.015, 0.021",\
"0.009, 0.015, 0.021",\
"0.009, 0.015, 0.021");
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.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175",\
"-0.065, -0.071, -0.175");
values("-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132",\
"-0.052, -0.059, -0.132");
}
}
}
@ -308,20 +308,20 @@ cell (sram_2_16_1_scn3me_subm){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("4.375");
values("2.344");
}
fall_constraint(scalar) {
values("4.375");
values("2.344");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("8.75");
values("4.688");
}
fall_constraint(scalar) {
values("8.75");
values("4.688");
}
}
}

View File

@ -1,4 +1,4 @@
library (sram_2_16_1_scn3me_subm_lib){
library (sram_2_16_1_scn3me_subm_TT_50V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
@ -9,7 +9,7 @@ library (sram_2_16_1_scn3me_subm_lib){
pulling_resistance_unit :"1kohm" ;
operating_conditions(TT){
voltage : 5.0 ;
temperature : 25.000 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
@ -74,7 +74,7 @@ cell (sram_2_16_1_scn3me_subm){
dont_use : true;
map_only : true;
dont_touch : true;
area : 2.7;
area : 122426.46;
bus(DATA){
bus_type : DATA;
@ -140,14 +140,14 @@ cell (sram_2_16_1_scn3me_subm){
related_pin : "clk";
timing_type : falling_edge;
cell_rise(CELL_TABLE) {
values("0.561, 0.608, 1.049",\
"0.561, 0.608, 1.049",\
"0.561, 0.608, 1.049");
values("0.556, 0.603, 1.044",\
"0.556, 0.603, 1.044",\
"0.556, 0.603, 1.044");
}
cell_fall(CELL_TABLE) {
values("0.561, 0.608, 1.049",\
"0.561, 0.608, 1.049",\
"0.561, 0.608, 1.049");
values("0.556, 0.603, 1.044",\
"0.556, 0.603, 1.044",\
"0.556, 0.603, 1.044");
}
rise_transition(CELL_TABLE) {
values("0.024, 0.081, 0.61",\

View File

@ -0,0 +1,329 @@
library (sram_2_16_1_scn3me_subm_TT_50V_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(TT){
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 ;
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 : TT;
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 : 122426.46;
bus(DATA){
bus_type : DATA;
direction : inout;
max_capacitance : 78.5936;
three_state : "!OEb & !clk";
memory_write(){
address : ADDR;
clocked_on : clk;
}
memory_read(){
address : ADDR;
}
pin(DATA[1:0]){
internal_power(){
when : "OEb & !clk";
rise_power(scalar){
values("11.756062");
}
fall_power(scalar){
values("7.1840422");
}
}
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");
}
}
internal_power(){
when : "!OEb & !clk";
rise_power(scalar){
values("10.730552");
}
fall_power(scalar){
values("10.584523");
}
}
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.649, 1.249",\
"0.576, 0.651, 1.252",\
"0.616, 0.69, 1.289");
}
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.355, 1.499",\
"0.277, 0.357, 1.499",\
"0.278, 0.362, 1.499");
}
}
}
}
bus(ADDR){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
fanout_load : 1.000000;
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;
timing(){
timing_type :"min_pulse_width";
related_pin : clk;
rise_constraint(scalar) {
values("2.344");
}
fall_constraint(scalar) {
values("2.344");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk;
rise_constraint(scalar) {
values("4.688");
}
fall_constraint(scalar) {
values("4.688");
}
}
}
}
}

View File

@ -1,8 +1,9 @@
import unittest
import unittest,warnings
import sys,os,glob
sys.path.append(os.path.join(sys.path[0],".."))
import globals
from globals import OPTS
import debug
class openram_test(unittest.TestCase):
""" Base unit test that we have some shared classes in. """
@ -17,8 +18,8 @@ class openram_test(unittest.TestCase):
for f in files:
os.remove(f)
def local_check(self, a):
def local_check(self, a, final_verification=False):
tempspice = OPTS.openram_temp + "temp.sp"
tempgds = OPTS.openram_temp + "temp.gds"
@ -34,17 +35,17 @@ class openram_test(unittest.TestCase):
try:
self.assertTrue(verify.run_lvs(a.name, tempgds, tempspice)==0)
self.assertTrue(verify.run_lvs(a.name, tempgds, tempspice, final_verification)==0)
except:
self.reset()
self.fail("LVS mismatch: {}".format(a.name))
self.cleanup()
self.reset()
if OPTS.purge_temp:
self.cleanup()
def cleanup(self):
""" Reset the duplicate checker and cleanup files. """
self.reset()
files = glob.glob(OPTS.openram_temp + '*')
for f in files:
# Only remove the files

View File

@ -137,9 +137,11 @@ def run_drc(cell_name, gds_name):
return errors
def run_lvs(cell_name, gds_name, sp_name):
def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
"""Run LVS check on a given top-level name which is
implemented in gds_name and sp_name. """
implemented in gds_name and sp_name. Final verification will
ensure that there are no remaining virtual conections. """
from tech import drc
lvs_rules = drc["lvs_rules"]
lvs_runset = {
@ -154,7 +156,6 @@ def run_lvs(cell_name, gds_name, sp_name):
'lvsPowerNames': 'vdd',
'lvsGroundNames': 'gnd',
'lvsIncludeSVRFCmds': 1,
'lvsSVRFCmds': '{VIRTUAL CONNECT NAME VDD? GND? ?}',
'lvsIgnorePorts': 1,
'lvsERCDatabase': OPTS.openram_temp + cell_name + ".erc.results",
'lvsERCSummaryFile': OPTS.openram_temp + cell_name + ".erc.summary",
@ -162,10 +163,18 @@ def run_lvs(cell_name, gds_name, sp_name):
'lvsMaskDBFile': OPTS.openram_temp + cell_name + ".maskdb",
'cmnFDILayerMapFile': drc["layer_map"],
'cmnFDIUseLayerMap': 1,
'cmnVConnectNames': 'vdd, gnd',
'lvsRecognizeGates': 'NONE'
#'cmnVConnectNamesState' : 'ALL', #connects all nets with the same name
}
# This should be removed for final verification
if not final_verification:
lvs_runset['cmnVConnectReport']=1
lvs_runset['cmnVConnectNamesState']='SOME'
lvs_runset['cmnVConnectNames']='vdd gnd'
# write the runset file
f = open(OPTS.openram_temp + "lvs_runset", "w")
for k in sorted(lvs_runset.iterkeys()):

View File

@ -44,8 +44,8 @@ EOF
3. netgen can perform LVS with:
#!/bin/sh
netgen -noconsole <<EOF
readnet $1.spice
readnet $1.sp
readnet spice $1.spice
readnet spice $1.sp
ignore class c
equate class {$1.spice nfet} {$2.sp n}
equate class {$1.spice pfet} {$2.sp p}
@ -86,7 +86,7 @@ def write_magic_script(cell_name, gds_name, extract=False):
f.write("drc count total\n")
f.write("drc count\n")
if extract:
f.write("extract\n")
f.write("extract all\n")
f.write("ext2spice hierarchy on\n")
f.write("ext2spice scale off\n")
# Can choose hspice, ngspice, or spice3,
@ -113,21 +113,26 @@ def write_netgen_script(cell_name, sp_name):
f = open(run_file, "w")
f.write("#!/bin/sh\n")
f.write("{} -noconsole << EOF\n".format(OPTS.lvs_exe[1]))
f.write("readnet {}.spice\n".format(cell_name))
f.write("readnet {}\n".format(sp_name))
f.write("readnet spice {}.spice\n".format(cell_name))
f.write("readnet spice {}\n".format(sp_name))
f.write("ignore class c\n")
f.write("permute transistors\n")
f.write("equate class {{{0}.spice nfet}} {{{1} n}}\n".format(cell_name, sp_name))
f.write("equate class {{{0}.spice pfet}} {{{1} p}}\n".format(cell_name, sp_name))
# This circuit has symmetries and needs to be flattened to resolve them or the banks won't pass
# Is there a more elegant way to add this when needed?
f.write("flatten class {{{0}.spice precharge_array}}\n".format(cell_name))
f.write("property {{{0}.spice nfet}} remove as ad ps pd\n".format(cell_name))
f.write("property {{{0}.spice pfet}} remove as ad ps pd\n".format(cell_name))
f.write("property {{{0} n}} remove as ad ps pd\n".format(sp_name))
f.write("property {{{0} p}} remove as ad ps pd\n".format(sp_name))
# Allow some flexibility in W size because magic will snap to a lambda grid
# This can also cause disconnects unfortunately!
# f.write("property {{{0}{1}.spice nfet}} tolerance {{w 0.1}}\n".format(OPTS.openram_temp,
# cell_name))
# f.write("property {{{0}{1}.spice pfet}} tolerance {{w 0.1}}\n".format(OPTS.openram_temp,
# cell_name))
f.write("lvs {0}.spice {{{1} {0}}} setup.tcl lvs.results\n".format(cell_name, sp_name))
f.write("lvs {0}.spice {{{1} {0}}} setup.tcl {0}.lvs.report\n".format(cell_name, sp_name))
f.write("quit\n")
f.write("EOF\n")
f.close()
@ -142,7 +147,7 @@ def run_drc(cell_name, gds_name, extract=False):
cwd = os.getcwd()
os.chdir(OPTS.openram_temp)
errfile = "{0}{1}.drc.err".format(OPTS.openram_temp, cell_name)
outfile = "{0}{1}.drc.out".format(OPTS.openram_temp, cell_name)
outfile = "{0}{1}.drc.summary".format(OPTS.openram_temp, cell_name)
cmd = "{0}run_drc.sh 2> {1} 1> {2}".format(OPTS.openram_temp,
errfile,
@ -181,9 +186,10 @@ def run_drc(cell_name, gds_name, extract=False):
return errors
def run_lvs(cell_name, gds_name, sp_name):
def run_lvs(cell_name, gds_name, sp_name, final_verification=False):
"""Run LVS check on a given top-level name which is
implemented in gds_name and sp_name. """
implemented in gds_name and sp_name. Final verification will
ensure that there are no remaining virtual conections. """
run_drc(cell_name, gds_name, extract=True)
write_netgen_script(cell_name, sp_name)
@ -193,7 +199,7 @@ def run_lvs(cell_name, gds_name, sp_name):
os.chdir(OPTS.openram_temp)
errfile = "{0}{1}.lvs.err".format(OPTS.openram_temp, cell_name)
outfile = "{0}{1}.lvs.out".format(OPTS.openram_temp, cell_name)
resultsfile = "{0}lvs.results".format(OPTS.openram_temp, cell_name)
resultsfile = "{0}{1}.lvs.report".format(OPTS.openram_temp, cell_name)
cmd = "{0}run_lvs.sh lvs 2> {1} 1> {2}".format(OPTS.openram_temp,
errfile,
@ -216,10 +222,12 @@ def run_lvs(cell_name, gds_name, sp_name):
propertyerrors = filter(test.search, results)
# Require pins to match?
# Cell pin lists for pnand2_1.spice and pnand2_1 altered to match.
test = re.compile(".*altered to match.")
pinerrors = filter(test.search, results)
total_errors = len(propertyerrors) + len(incorrect) + len(pinerrors)
# test = re.compile(".*altered to match.")
# pinerrors = filter(test.search, results)
# if len(pinerrors)>0:
# debug.warning("Pins altered to match in {}.".format(cell_name))
total_errors = len(propertyerrors) + len(incorrect)
# If we want to ignore property errors
#total_errors = len(incorrect)
#if len(propertyerrors)>0:
@ -236,7 +244,7 @@ def run_lvs(cell_name, gds_name, sp_name):
# Just print out the whole file, it is short.
for e in results:
debug.info(1,e.strip("\n"))
debug.error("LVS mismatch (results in {}lvs.results)".format(OPTS.openram_temp))
debug.error("LVS mismatch (results in {})".format(resultsfile))
return total_errors

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:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="161.5"
inkscape:cx="20"
inkscape:cy="520"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1280"
inkscape:window-height="752"
inkscape:window-width="3440"
inkscape:window-height="1392"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
@ -185,7 +185,7 @@
id="tspan4519"
x="184"
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
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"
@ -196,7 +196,7 @@
id="tspan4523"
x="336"
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
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"
@ -207,7 +207,7 @@
id="tspan4527"
x="287"
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
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"
@ -263,7 +263,7 @@
id="tspan4793"
x="271"
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
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"

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"
id="svg2"
version="1.1"
inkscape:version="0.48.3.1 r9886"
sodipodi:docname="sense_amp.svg">
inkscape:version="0.92.2 5c3e80d, 2017-08-06"
sodipodi:docname="sense_amp_schem.svg">
<defs
id="defs4" />
<sodipodi:namedview
@ -24,16 +24,16 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1"
inkscape:cx="199"
inkscape:cy="520"
inkscape:zoom="1.4142136"
inkscape:cx="78.947962"
inkscape:cy="503.38478"
inkscape:document-units="px"
inkscape:current-layer="layer1"
showgrid="true"
inkscape:window-width="1855"
inkscape:window-height="1056"
inkscape:window-x="65"
inkscape:window-y="24"
inkscape:window-width="3440"
inkscape:window-height="1392"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="1">
<inkscape:grid
type="xygrid"
@ -47,7 +47,7 @@
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
<dc:title />
</cc:Work>
</rdf:RDF>
</metadata>
@ -55,37 +55,6 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
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
id="g3496-2"
transform="matrix(0,-1,1,0,-62.34811,791.36093)">
@ -148,37 +117,6 @@
inkscape:connector-curvature="0" />
</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
id="g3496-8"
transform="matrix(0,-1,1,0,-2.34811,920.37376)">
@ -357,18 +295,18 @@
id="path4592"
inkscape:connector-curvature="0" />
<path
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
d="m 610,452.36218 30,0 0,-120 0,230"
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 604,452.36218 h 30 v -120 230"
id="path4594"
inkscape:connector-curvature="0" />
<path
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 190,432.36218 0,-20 0,-10"
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 184,416.36218 v -20 -10"
id="path4598"
inkscape:connector-curvature="0" />
<path
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 550,432.36218 0,-30"
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 544,416.36218 v -30"
id="path4600"
inkscape:connector-curvature="0" />
<path
@ -406,11 +344,11 @@
</g>
<g
id="g3319-3"
transform="matrix(1.25,0,0,1,129,112.20718)">
transform="matrix(1.25,0,0,1,125,112.20718)">
<path
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"
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" />
</g>
<g
@ -466,85 +404,165 @@
</g>
<text
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"
y="172.36218"
id="text4691"
sodipodi:linespacing="125%"><tspan
id="text4691"><tspan
sodipodi:role="line"
id="tspan4693"
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
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"
y="297.36218"
id="text4695"
sodipodi:linespacing="125%"><tspan
id="text4695"><tspan
sodipodi:role="line"
id="tspan4697"
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
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"
x="615"
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="621"
y="577.36218"
id="text4699"
sodipodi:linespacing="125%"><tspan
id="text4699"><tspan
sodipodi:role="line"
id="tspan4701"
x="615"
y="577.36218">BL_bar</tspan></text>
x="621"
y="577.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">br</tspan></text>
<text
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"
y="580.36218"
id="text4703"
sodipodi:linespacing="125%"><tspan
id="text4703"><tspan
sodipodi:role="line"
id="tspan4705"
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
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"
y="588.36218"
id="text4707"
sodipodi:linespacing="125%"><tspan
id="text4707"><tspan
sodipodi:role="line"
id="tspan4709"
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
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"
x="540"
y="398.36218"
id="text4711"
sodipodi:linespacing="125%"><tspan
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="538"
y="382.36218"
id="text4711"><tspan
sodipodi:role="line"
id="tspan4713"
x="540"
y="398.36218">EN</tspan></text>
x="538"
y="382.36218"
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<text
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"
x="180"
y="399.36218"
id="text4715"
sodipodi:linespacing="125%"><tspan
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="177.87868"
y="376.02765"
id="text4715"><tspan
sodipodi:role="line"
id="tspan4717"
x="180"
y="399.36218">EN</tspan></text>
x="177.87868"
y="376.02765"
style="font-size:16px;line-height:1.25;font-family:sans-serif">en</tspan></text>
<path
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"
id="path4738"
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>
</svg>

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 32 KiB

After

Width:  |  Height:  |  Size: 60 KiB

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