Merged with dev, removed commented out code.

This commit is contained in:
Hunter Nichols 2018-12-12 16:02:16 -08:00
commit 0510aeb3ec
77 changed files with 13686 additions and 212 deletions

View File

@ -10,6 +10,7 @@ omit =
debug.py debug.py
[paths] [paths]
source = source =
../..
/home/gitlab-runner/builds/2fd64746/0 /home/gitlab-runner/builds/2fd64746/0
/home/gitlab-runner/builds/2fd64746/1 /home/gitlab-runner/builds/2fd64746/1
/home/gitlab-runner/builds/2fd64746/2 /home/gitlab-runner/builds/2fd64746/2

View File

@ -6,6 +6,8 @@ import debug
import os import os
from globals import OPTS from globals import OPTS
total_drc_errors = 0
total_lvs_errors = 0
class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout): class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
""" """
@ -14,7 +16,6 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
""" """
name_map = [] name_map = []
def __init__(self, name): def __init__(self, name):
try: try:
self.gds_file self.gds_file
@ -73,13 +74,23 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""Checks both DRC and LVS for a module""" """Checks both DRC and LVS for a module"""
# Unit tests will check themselves. # Unit tests will check themselves.
# Do not run if disabled in options. # Do not run if disabled in options.
if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
global total_drc_errors
global total_lvs_errors
tempspice = OPTS.openram_temp + "/temp.sp" tempspice = OPTS.openram_temp + "/temp.sp"
tempgds = OPTS.openram_temp + "/temp.gds" tempgds = OPTS.openram_temp + "/temp.gds"
self.sp_write(tempspice) self.sp_write(tempspice)
self.gds_write(tempgds) self.gds_write(tempgds)
debug.check(verify.run_drc(self.name, tempgds, final_verification) == 0,"DRC 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)) num_drc_errors = verify.run_drc(self.name, tempgds, final_verification)
num_lvs_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification)
debug.check(num_drc_errors == 0,"DRC failed for {0} with {1} error(s)".format(self.name,num_drc_errors))
debug.check(num_lvs_errors == 0,"LVS failed for {0} with {1} errors(s)".format(self.name,num_lvs_errors))
total_drc_errors += num_drc_errors
total_lvs_errors += num_lvs_errors
os.remove(tempspice) os.remove(tempspice)
os.remove(tempgds) os.remove(tempgds)
@ -87,22 +98,31 @@ class hierarchy_design(hierarchy_spice.spice, hierarchy_layout.layout):
"""Checks DRC for a module""" """Checks DRC for a module"""
# Unit tests will check themselves. # Unit tests will check themselves.
# Do not run if disabled in options. # Do not run if disabled in options.
if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
global total_drc_errors
tempgds = OPTS.openram_temp + "/temp.gds" tempgds = OPTS.openram_temp + "/temp.gds"
self.gds_write(tempgds) self.gds_write(tempgds)
debug.check(verify.run_drc(self.name, tempgds, final_verification) == 0,"DRC failed for {0}".format(self.name)) num_errors = verify.run_drc(self.name, tempgds, final_verification)
total_drc_errors += num_errors
debug.check(num_errors == 0,"DRC failed for {0} with {1} error(s)".format(self.name,num_error))
os.remove(tempgds) os.remove(tempgds)
def LVS(self, final_verification=False): def LVS(self, final_verification=False):
"""Checks LVS for a module""" """Checks LVS for a module"""
# Unit tests will check themselves. # Unit tests will check themselves.
# Do not run if disabled in options. # Do not run if disabled in options.
if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)): if (not OPTS.is_unit_test and OPTS.check_lvsdrc and (OPTS.inline_lvsdrc or final_verification)):
global total_lvs_errors
tempspice = OPTS.openram_temp + "/temp.sp" tempspice = OPTS.openram_temp + "/temp.sp"
tempgds = OPTS.openram_temp + "/temp.gds" tempgds = OPTS.openram_temp + "/temp.gds"
self.sp_write(tempspice) self.sp_write(tempspice)
self.gds_write(tempgds) self.gds_write(tempgds)
debug.check(verify.run_lvs(self.name, tempgds, tempspice, final_verification) == 0,"LVS failed for {0}".format(self.name)) num_errors = verify.run_lvs(self.name, tempgds, tempspice, final_verification)
total_lvs_errors += num_errors
debug.check(num_errors == 0,"LVS failed for {0} with {1} error(s)".format(self.name,num_errors))
os.remove(tempspice) os.remove(tempspice)
os.remove(tempgds) os.remove(tempgds)

View File

@ -84,7 +84,7 @@ class lib:
debug.info(1,"Writing to {0}".format(lib_name)) debug.info(1,"Writing to {0}".format(lib_name))
self.characterize() self.characterize()
self.lib.close() self.lib.close()
self.parse_info() self.parse_info(self.corner,lib_name)
def characterize(self): def characterize(self):
""" Characterize the current corner. """ """ Characterize the current corner. """
@ -503,36 +503,132 @@ class lib:
self.times = self.sh.analyze(self.slews,self.slews) self.times = self.sh.analyze(self.slews,self.slews)
def parse_info(self): def parse_info(self,corner,lib_name):
""" Copies important characterization data to datasheet.info to be added to datasheet """
if OPTS.is_unit_test: if OPTS.is_unit_test:
return git_id = 'AAAAAAAAAAAAAAAAAAAA'
else:
with open(os.devnull, 'wb') as devnull:
proc = subprocess.Popen(['git','rev-parse','HEAD'], stdout=subprocess.PIPE)
git_id = str(proc.stdout.read())
git_id = git_id[2:-3]
datasheet = open(OPTS.openram_temp +'/datasheet.info', 'a+') datasheet = open(OPTS.openram_temp +'/datasheet.info', 'a+')
for (corner, lib_name) in zip(self.corners, self.lib_files): datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},".format(
"sram_{0}_{1}_{2}".format(OPTS.word_size, OPTS.num_words, OPTS.tech_name),
OPTS.num_words,
OPTS.num_banks,
OPTS.num_rw_ports,
OPTS.num_w_ports,
OPTS.num_r_ports,
OPTS.tech_name,
corner[2],
corner[1],
corner[0],
round_time(self.char_sram_results["min_period"]),
self.out_dir,
lib_name,
OPTS.word_size,
git_id
))
# ports = "" for port in self.all_ports:
# if OPTS.num_rw_ports>0: #DIN timings
# ports += "{}_".format(OPTS.num_rw_ports) if port in self.write_ports:
# if OPTS.num_w_ports>0: datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
# ports += "{}_".format(OPTS.num_w_ports) "DIN{1}[{0}:0]".format(self.sram.word_size - 1, port),
# if OPTS.num_r_ports>0: min(list(map(round_time,self.times["setup_times_LH"]))),
# ports += "{}_".format(OPTS.num_r_ports) max(list(map(round_time,self.times["setup_times_LH"]))),
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13}".format("sram_{0}_{1}_{2}".format(OPTS.word_size, OPTS.num_words, OPTS.tech_name), min(list(map(round_time,self.times["setup_times_HL"]))),
OPTS.num_words, max(list(map(round_time,self.times["setup_times_HL"]))),
OPTS.num_banks,
OPTS.num_rw_ports, min(list(map(round_time,self.times["hold_times_LH"]))),
OPTS.num_w_ports, max(list(map(round_time,self.times["hold_times_LH"]))),
OPTS.num_r_ports,
OPTS.tech_name, min(list(map(round_time,self.times["hold_times_HL"]))),
self.corner[1], max(list(map(round_time,self.times["hold_times_HL"])))
self.corner[2],
self.corner[0], ))
round_time(self.char_sram_results["min_period"]),
self.out_dir, for port in self.all_ports:
lib_name, #DOUT timing
OPTS.word_size)) if port in self.read_ports:
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
"DOUT{1}[{0}:0]".format(self.sram.word_size - 1, port),
min(list(map(round_time,self.char_port_results[port]["delay_lh"]))),
max(list(map(round_time,self.char_port_results[port]["delay_lh"]))),
min(list(map(round_time,self.char_port_results[port]["delay_hl"]))),
max(list(map(round_time,self.char_port_results[port]["delay_hl"]))),
min(list(map(round_time,self.char_port_results[port]["slew_lh"]))),
max(list(map(round_time,self.char_port_results[port]["slew_lh"]))),
min(list(map(round_time,self.char_port_results[port]["slew_hl"]))),
max(list(map(round_time,self.char_port_results[port]["slew_hl"])))
))
for port in self.all_ports:
#CSb timings
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
"CSb{0}".format(port),
min(list(map(round_time,self.times["setup_times_LH"]))),
max(list(map(round_time,self.times["setup_times_LH"]))),
min(list(map(round_time,self.times["setup_times_HL"]))),
max(list(map(round_time,self.times["setup_times_HL"]))),
min(list(map(round_time,self.times["hold_times_LH"]))),
max(list(map(round_time,self.times["hold_times_LH"]))),
min(list(map(round_time,self.times["hold_times_HL"]))),
max(list(map(round_time,self.times["hold_times_HL"])))
))
for port in self.all_ports:
#ADDR timings
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
"ADDR{1}[{0}:0]".format(self.sram.addr_size - 1, port),
min(list(map(round_time,self.times["setup_times_LH"]))),
max(list(map(round_time,self.times["setup_times_LH"]))),
min(list(map(round_time,self.times["setup_times_HL"]))),
max(list(map(round_time,self.times["setup_times_HL"]))),
min(list(map(round_time,self.times["hold_times_LH"]))),
max(list(map(round_time,self.times["hold_times_LH"]))),
min(list(map(round_time,self.times["hold_times_HL"]))),
max(list(map(round_time,self.times["hold_times_HL"])))
))
for port in self.all_ports:
if port in self.readwrite_ports:
#WEb timings
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
"WEb{0}".format(port),
min(list(map(round_time,self.times["setup_times_LH"]))),
max(list(map(round_time,self.times["setup_times_LH"]))),
min(list(map(round_time,self.times["setup_times_HL"]))),
max(list(map(round_time,self.times["setup_times_HL"]))),
min(list(map(round_time,self.times["hold_times_LH"]))),
max(list(map(round_time,self.times["hold_times_LH"]))),
min(list(map(round_time,self.times["hold_times_HL"]))),
max(list(map(round_time,self.times["hold_times_HL"])))
))
datasheet.write("END\n")
datasheet.close() datasheet.close()

View File

@ -0,0 +1,28 @@
<style>
#data {
font-family: Trebuchet MS, Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 99%;
max-width: 799px
}
#data td, #data th {
border: 0px solid #ddd;
padding: 7px;
}
#data tr:nth-child(even){background-color: #f1f2f2;}
#data tr:hover {background-color: #ddd;}
#data th {
padding-top: 11px;
padding-bottom: 11px;
text-align: left;
background-color: #004184;
color: #F1B521;
}
</style>

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

View File

@ -1,6 +1,9 @@
from flask_table import * from flask_table import *
class characterization_corners(Table): class characterization_corners(Table):
"""
Set up characterization corners table columns and title information
"""
corner_name = Col('Corner Name') corner_name = Col('Corner Name')
process = Col('Process') process = Col('Process')
power_supply = Col('Power Supply') power_supply = Col('Power Supply')
@ -8,6 +11,9 @@ class characterization_corners(Table):
library_name_suffix = Col('Library Name Suffix') library_name_suffix = Col('Library Name Suffix')
class characterization_corners_item(object): class characterization_corners_item(object):
"""
Defines the contents of a charcaterization corner table row
"""
def __init__(self, corner_name, process, power_supply, temperature, library_name_suffix): def __init__(self, corner_name, process, power_supply, temperature, library_name_suffix):
self.corner_name = corner_name self.corner_name = corner_name
self.process = process self.process = process

View File

@ -4,11 +4,17 @@ from characterization_corners import *
from deliverables import * from deliverables import *
from timing_and_current_data import * from timing_and_current_data import *
from in_out import * from in_out import *
from hierarchy_design import total_drc_errors
from hierarchy_design import total_lvs_errors
import os import os
import csv
import base64
from globals import OPTS from globals import OPTS
class datasheet(): class datasheet():
"""
Defines the layout,but not the data, of the html datasheet
"""
def __init__(self,identifier): def __init__(self,identifier):
self.io = [] self.io = []
self.corners = [] self.corners = []
@ -20,50 +26,63 @@ class datasheet():
def generate_html(self): def generate_html(self):
self.html = """<style> """
#data { Generates html tables using flask-table
font-family: "Trebuchet MS", Arial, Helvetica, sans-serif; """
border-collapse: collapse; with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/datasheet.css', 'r') as datasheet_css:
width: 100%; #css styling is kept in a seperate file
max-width: 800px self.html += datasheet_css.read()
}
#data td, #data th { if OPTS.check_lvsdrc:
border: 1px solid #ddd;
padding: 8px;
}
#data tr:nth-child(even){background-color: #f2f2f2;} DRC = str(total_drc_errors) + ' errors'
LVS = str(total_lvs_errors) + ' errors'
PEX = 'n/a'
else:
DRC = 'skipped'
LVS = 'skipped'
PEX = 'skipped'
#data tr:hover {background-color: #ddd;} with open(OPTS.openram_temp + "/datasheet.info") as info:
self.html += '<!--'
for row in info:
self.html += row
self.html +='-->'
#data th { vlsi_logo = 0
padding-top: 12px; with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/vlsi_logo.png' , "rb") as image_file:
padding-bottom: 12px; vlsi_logo = base64.b64encode(image_file.read())
text-align: left;
background-color: #4CAF50;
color: white;
}
</style>"""
self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>'+ self.name + '.html' + '</p>'
# self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>{0}</p>'
# self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>{0}</p>'
self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>Ports and Configuration (DEBUG)</p>' openram_logo = 0
with open(os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/openram_logo_placeholder.png' , "rb") as image_file:
openram_logo = base64.b64encode(image_file.read())
self.html += '<a href="https://vlsida.soe.ucsc.edu/"><img src="data:image/png;base64,{0}" alt="VLSIDA"></a><a href="https://vlsida.github.io/OpenRAM"><img src="data:image/png;base64,{1}"="OpenRAM"></a>'.format(str(vlsi_logo)[2:-1],str(openram_logo)[2:-1])
self.html +='<p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">'+ self.name + '.html' + '</p>'
self.html +='<p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">'+ 'DRC: ' + str(DRC) + '</p>'
self.html +='<p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">'+ 'LVS: ' + str(LVS) + '</p>'
self.html += '<p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">'+ 'Git commit id: ' + str(self.git_id) + '</p>'
self.html +='<p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Ports and Configuration (DEBUG)</p>'
self.html += in_out(self.io,table_id='data').__html__().replace('&lt;','<').replace('&#34;','"').replace('&gt;',">") self.html += in_out(self.io,table_id='data').__html__().replace('&lt;','<').replace('&#34;','"').replace('&gt;',">")
self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>Operating Conditions</p>' self.html +='<p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Operating Conditions</p>'
self.html += operating_conditions(self.operating,table_id='data').__html__() self.html += operating_conditions(self.operating,table_id='data').__html__()
self.html += '<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>Timing and Current Data</p>' self.html += '<p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Timing and Current Data</p>'
self.html += timing_and_current_data(self.timing,table_id='data').__html__() self.html += timing_and_current_data(self.timing,table_id='data').__html__()
self.html += '<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>Characterization Corners</p>' self.html += '<p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Characterization Corners</p>'
self.html += characterization_corners(self.corners,table_id='data').__html__() self.html += characterization_corners(self.corners,table_id='data').__html__()
self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>Deliverables</p>' self.html +='<p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Deliverables</p>'
self.html += deliverables(self.dlv,table_id='data').__html__().replace('&lt;','<').replace('&#34;','"').replace('&gt;',">") self.html += deliverables(self.dlv,table_id='data').__html__().replace('&lt;','<').replace('&#34;','"').replace('&gt;',">")
self.html +='<p style=font-size: 20px;font-family: "Trebuchet MS", Arial, Helvetica, sans-serif;>*Feature only supported with characterizer</p>'
self.html +='<img src=' + os.path.abspath(os.environ.get("OPENRAM_HOME")) + '/datasheet/assets/vlsi_logo.png alt="VLSIDA" />'

View File

@ -1,13 +1,16 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
""" """
Datasheet Generator This is a script to load data from the characterization and layout processes into
a web friendly html datasheet. This script requres the python-flask and flask-table
TODO: packages to be installed.
locate all port elements in .lib
Locate all timing elements in .lib
Diagram generation
Improve css
""" """
#TODO:
#locate all port elements in .lib
#Locate all timing elements in .lib
#Diagram generation
#Improve css
import debug import debug
from globals import OPTS from globals import OPTS
@ -24,10 +27,13 @@ if OPTS.datasheet_gen:
from in_out import * from in_out import *
else: else:
debug.warning("Python library flask_table not found. Skipping html datasheet generation. This can be installed with pip install flask-table.") debug.warning("Python library flask_table not found. Skipping html datasheet generation. This can be installed with pip install flask-table.")
#make sure appropriate python libraries are installed
def process_name(corner): def process_name(corner):
"""
Expands the names of the characterization corner types into something human friendly
"""
if corner == "TT": if corner == "TT":
return "Typical - Typical" return "Typical - Typical"
if corner == "SS": if corner == "SS":
@ -37,34 +43,76 @@ def process_name(corner):
else: else:
return "custom" return "custom"
def parse_file(f,pages): def parse_characterizer_csv(sram,f,pages):
"""
Parses output data of the Liberty file generator in order to construct the timing and
current table
"""
with open(f) as csv_file: with open(f) as csv_file:
csv_reader = csv.reader(csv_file, delimiter=',') csv_reader = csv.reader(csv_file, delimiter=',')
line_count = 0 line_count = 0
for row in csv_reader: for row in csv_reader:
found = 0 found = 0
NAME = row[0] col = 0
NUM_WORDS = row[1]
NUM_BANKS = row[2] #defines layout of csv file
NUM_RW_PORTS = row[3] NAME = row[col]
NUM_W_PORTS = row[4] col += 1
NUM_R_PORTS = row[5]
TECH_NAME = row[6] NUM_WORDS = row[col]
TEMP = row[8] col += 1
VOLT = row[7]
PROC = row[9] NUM_BANKS = row[col]
MIN_PERIOD = row[10] col += 1
OUT_DIR = row[11]
LIB_NAME = row[12] NUM_RW_PORTS = row[col]
WORD_SIZE = row[13] col += 1
NUM_W_PORTS = row[col]
col += 1
NUM_R_PORTS = row[col]
col += 1
TECH_NAME = row[col]
col += 1
TEMP = row[col]
col += 1
VOLT = row[col]
col += 1
PROC = row[col]
col += 1
MIN_PERIOD = row[col]
col += 1
OUT_DIR = row[col]
col += 1
LIB_NAME = row[col]
col += 1
WORD_SIZE = row[col]
col += 1
ORIGIN_ID = row[col]
col += 1
for sheet in pages: for sheet in pages:
if sheet.name == row[0]: if sheet.name == NAME:
found = 1 found = 1
#if the .lib information is for an existing datasheet compare timing data #if the .lib information is for an existing datasheet compare timing data
for item in sheet.operating: for item in sheet.operating:
#check if the new corner data is worse than the previous worse corner data
if item.parameter == 'Operating Temperature': if item.parameter == 'Operating Temperature':
if float(TEMP) > float(item.max): if float(TEMP) > float(item.max):
@ -91,52 +139,345 @@ def parse_file(f,pages):
while(True):
if(row[col].startswith('DIN')):
start = col
for item in sheet.timing:
if item.parameter.startswith(row[col]):
if item.parameter.endswith('setup rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('setup falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
col += 1
elif(row[col].startswith('DOUT')):
start = col
for item in sheet.timing:
if item.parameter.startswith(row[col]):
if item.parameter.endswith('cell rise'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('cell fall'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('rise transition'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('fall transition'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
col += 1
elif(row[col].startswith('CSb')):
start = col
for item in sheet.timing:
if item.parameter.startswith(row[col]):
if item.parameter.endswith('setup rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('setup falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
col += 1
elif(row[col].startswith('WEb')):
start = col
for item in sheet.timing:
if item.parameter.startswith(row[col]):
if item.parameter.endswith('setup rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('setup falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
col += 1
elif(row[col].startswith('ADDR')):
start = col
for item in sheet.timing:
if item.parameter.startswith(row[col]):
if item.parameter.endswith('setup rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('setup falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold rising'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
elif item.parameter.endswith('hold falling'):
if float(row[col+1]) < float(item.min):
item.min = row[col+1]
if float(row[col+2]) > float(item.max):
item.max = row[col+2]
col += 2
col += 1
else:
break
#regardless of if there is already a corner for the current sram, append the new corner to the datasheet
new_sheet.corners.append(characterization_corners_item(PROC,process_name(PROC),VOLT,TEMP,LIB_NAME.replace(OUT_DIR,'').replace(NAME,''))) new_sheet.corners.append(characterization_corners_item(PROC,process_name(PROC),VOLT,TEMP,LIB_NAME.replace(OUT_DIR,'').replace(NAME,'')))
new_sheet.dlv.append(deliverables_item('.lib','Synthesis models','<a href="file://{0}">{1}</a>'.format(LIB_NAME,LIB_NAME.replace(OUT_DIR,'')))) new_sheet.dlv.append(deliverables_item('.lib','Synthesis models','<a href="file://{0}">{1}</a>'.format(LIB_NAME,LIB_NAME.replace(OUT_DIR,''))))
if found == 0: if found == 0:
#if this is the first corner for this sram, run first time configuration and set up tables
new_sheet = datasheet(NAME) new_sheet = datasheet(NAME)
pages.append(new_sheet) pages.append(new_sheet)
new_sheet.git_id = ORIGIN_ID
new_sheet.corners.append(characterization_corners_item(PROC,process_name(PROC),VOLT,TEMP,LIB_NAME.replace(OUT_DIR,'').replace(NAME,''))) new_sheet.corners.append(characterization_corners_item(PROC,process_name(PROC),VOLT,TEMP,LIB_NAME.replace(OUT_DIR,'').replace(NAME,'')))
new_sheet.operating.append(operating_conditions_item('Power supply (VDD) range',VOLT,VOLT,VOLT,'Volts')) new_sheet.operating.append(operating_conditions_item('Power supply (VDD) range',VOLT,VOLT,VOLT,'Volts'))
new_sheet.operating.append(operating_conditions_item('Operating Temperature',TEMP,TEMP,TEMP,'Celsius')) new_sheet.operating.append(operating_conditions_item('Operating Temperature',TEMP,TEMP,TEMP,'Celsius'))
try: try:
new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)*','','',str(math.floor(1000/float(MIN_PERIOD))),'MHz')) new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)','','',str(math.floor(1000/float(MIN_PERIOD))),'MHz'))
except Exception: except Exception:
new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)*','','',"unknown",'MHz')) #analytical model fails to provide MIN_PERIOD new_sheet.operating.append(operating_conditions_item('Operating Frequency (F)','','',"not available in netlist only",'MHz')) #failed to provide non-zero MIN_PERIOD
new_sheet.timing.append(timing_and_current_data_item('Cycle time','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('Access time','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('Positive clk setup','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('Positive clk hold','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('RW setup','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('RW hold','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('AC current','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('Standby current','2','3','4'))
new_sheet.timing.append(timing_and_current_data_item('Area','2','3','4'))
new_sheet.dlv.append(deliverables_item('.sp','SPICE netlists','<a href="file://{0}{1}.{2}">{1}.{2}</a>'.format(OUT_DIR,NAME,'sp'))) while(True):
new_sheet.dlv.append(deliverables_item('.v','Verilog simulation models','<a href="file://{0}{1}.{2}">{1}.{2}</a>'.format(OUT_DIR,NAME,'v'))) if(row[col].startswith('DIN')):
new_sheet.dlv.append(deliverables_item('.gds','GDSII layout views','<a href="file://{0}{1}.{2}">{1}.{2}</a>'.format(OUT_DIR,NAME,'gds'))) start = col
new_sheet.dlv.append(deliverables_item('.lef','LEF files','<a href="file://{0}{1}.{2}">{1}.{2}</a>'.format(OUT_DIR,NAME,'lef'))) new_sheet.timing.append(timing_and_current_data_item('{0} setup rising'.format(row[start]),row[col+1],row[col+2],'ns'))
new_sheet.dlv.append(deliverables_item('.lib','Synthesis models','<a href="file://{0}">{1}</a>'.format(LIB_NAME,LIB_NAME.replace(OUT_DIR,'')))) col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} setup falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
col +=1
elif(row[col].startswith('DOUT')):
start = col
new_sheet.timing.append(timing_and_current_data_item('{0} cell rise'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} cell fall'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} rise transition'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} fall transition'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
col +=1
elif(row[col].startswith('CSb')):
start = col
new_sheet.timing.append(timing_and_current_data_item('{0} setup rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} setup falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
col +=1
elif(row[col].startswith('WEb')):
start = col
new_sheet.timing.append(timing_and_current_data_item('{0} setup rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} setup falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
col +=1
elif(row[col].startswith('ADDR')):
start = col
new_sheet.timing.append(timing_and_current_data_item('{0} setup rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} setup falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold rising'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
new_sheet.timing.append(timing_and_current_data_item('{0} hold falling'.format(row[start]),row[col+1],row[col+2],'ns'))
col += 2
col +=1
else:
break
if not OPTS.netlist_only:
#physical layout files should not be generated in netlist only mode
new_sheet.dlv.append(deliverables_item('.gds','GDSII layout views','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'gds')))
new_sheet.dlv.append(deliverables_item('.lef','LEF files','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'lef')))
new_sheet.dlv.append(deliverables_item('.sp','SPICE netlists','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'sp')))
new_sheet.dlv.append(deliverables_item('.v','Verilog simulation models','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'v')))
new_sheet.dlv.append(deliverables_item('.html','This datasheet','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'html')))
new_sheet.dlv.append(deliverables_item('.lib','Synthesis models','<a href="{1}">{1}</a>'.format(LIB_NAME,LIB_NAME.replace(OUT_DIR,''))))
new_sheet.dlv.append(deliverables_item('.py','OpenRAM configuration file','<a href="{0}.{1}">{0}.{1}</a>'.format(OPTS.output_name,'py')))
#debug table for multiport information
new_sheet.io.append(in_out_item('WORD_SIZE',WORD_SIZE)) new_sheet.io.append(in_out_item('WORD_SIZE',WORD_SIZE))
new_sheet.io.append(in_out_item('NUM_WORDS',NUM_WORDS)) new_sheet.io.append(in_out_item('NUM_WORDS',NUM_WORDS))
new_sheet.io.append(in_out_item('NUM_BANKS',NUM_BANKS)) new_sheet.io.append(in_out_item('NUM_BANKS',NUM_BANKS))
new_sheet.io.append(in_out_item('NUM_RW_PORTS',NUM_RW_PORTS)) new_sheet.io.append(in_out_item('NUM_RW_PORTS',NUM_RW_PORTS))
new_sheet.io.append(in_out_item('NUM_R_PORTS',NUM_R_PORTS)) new_sheet.io.append(in_out_item('NUM_R_PORTS',NUM_R_PORTS))
new_sheet.io.append(in_out_item('NUM_W_PORTS',NUM_W_PORTS)) new_sheet.io.append(in_out_item('NUM_W_PORTS',NUM_W_PORTS))
new_sheet.io.append(in_out_item('Area',sram.width * sram.height))
class datasheet_gen(): class datasheet_gen():
def datasheet_write(name): def datasheet_write(sram,name):
if OPTS.datasheet_gen: if OPTS.datasheet_gen:
in_dir = OPTS.openram_temp in_dir = OPTS.openram_temp
@ -144,11 +485,9 @@ class datasheet_gen():
if not (os.path.isdir(in_dir)): if not (os.path.isdir(in_dir)):
os.mkdir(in_dir) os.mkdir(in_dir)
#if not (os.path.isdir(out_dir)):
# os.mkdir(out_dir)
datasheets = [] datasheets = []
parse_file(in_dir + "/datasheet.info", datasheets) parse_characterizer_csv(sram, in_dir + "/datasheet.info", datasheets)
for sheets in datasheets: for sheets in datasheets:

View File

@ -1,12 +1,18 @@
from flask_table import * from flask_table import *
class deliverables(Table): class deliverables(Table):
"""
Set up delivarables table columns and title information
"""
typ = Col('Type') typ = Col('Type')
description = Col('Description') description = Col('Description')
link = Col('Link') link = Col('Link')
class deliverables_item(object): class deliverables_item(object):
"""
Define deliverables table row elemenent information
"""
def __init__(self, typ, description,link): def __init__(self, typ, description,link):
self.typ = typ self.typ = typ
self.description = description self.description = description

View File

@ -1,11 +1,17 @@
from flask_table import * from flask_table import *
class in_out(Table): class in_out(Table):
"""
Set up I/O table columns and title information for multiport debugging
"""
typ = Col('Type') typ = Col('Type')
description = Col('Description') description = Col('Description')
class in_out_item(object): class in_out_item(object):
"""
Define table row element for I/O table
"""
def __init__(self, typ, description): def __init__(self, typ, description):
self.typ = typ self.typ = typ
self.description = description self.description = description

View File

@ -1,6 +1,9 @@
from flask_table import * from flask_table import *
class operating_conditions(Table): class operating_conditions(Table):
"""
Set up operating conditions columns and title information
"""
parameter = Col('Parameter') parameter = Col('Parameter')
min = Col('Min') min = Col('Min')
typ = Col('Typ') typ = Col('Typ')
@ -8,6 +11,9 @@ class operating_conditions(Table):
units = Col('Units') units = Col('Units')
class operating_conditions_item(object): class operating_conditions_item(object):
"""
Define operating conditions table row element
"""
def __init__(self, parameter, min, typ, max, units): def __init__(self, parameter, min, typ, max, units):
self.parameter = parameter self.parameter = parameter
self.min = min self.min = min

View File

@ -0,0 +1,24 @@
import os
import jinja2
from flask import Flask, render_template
from filelist import *
filedir = './files'
file_data = './filelist.info'
app = Flask('server_scripts')
if __name__ == '__main__':
files = filelist()
files.update_filelist(filedir,file_data)
f = open('./index.html','w')
with app.app_context():
f.write(render_template('index.html', filedir = filedir , os = os))

View File

@ -0,0 +1,7 @@
class deliverable:
def __init__(self, name, file_type, path, size):
self.name = name
self.file_type = file_type
self.path = path
self.size = size

View File

@ -0,0 +1,19 @@
import os
from deliverable import *
class filelist:
def __init__(self):
self.list = []
def update_filelist(self,path,outdir):
out_file = open(outdir,'w')
for root, dirs, files in os.walk(path):
for file in files:
self.list.append(root + '/' + file)
out_file.write('{}/{}\n'.format(root,file))
#print('{}/{}'.format(root,file))

View File

@ -0,0 +1,116 @@
<style>
#data {
font-family: Trebuchet MS, Arial, Helvetica, sans-serif;
border-collapse: collapse;
width: 99%;
max-width: 799px
}
#data td, #data th {
border: 0px solid #ddd;
padding: 7px;
}
#data tr:nth-child(even){background-color: #f1f2f2;}
#data tr:hover {background-color: #ddd;}
#data th {
padding-top: 11px;
padding-bottom: 11px;
text-align: left;
background-color: #004184;
color: #F1B521;
}
</style>
<!--sram_2_16_scn4m_subm,16,1,1,1,1,scn4m_subm,25,5.0,TT,0,/home/jesse/clones/PrivateRAM/compiler/temp/,/home/jesse/clones/PrivateRAM/compiler/temp/sram_2_16_scn4m_subm_TT_5p0V_25C.lib,2,DIN0[1:0],0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,DIN1[1:0],0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,DOUT0[1:0],0.079,0.079,0.079,0.079,0.001,0.001,0.001,0.001,DOUT2[1:0],0.079,0.079,0.079,0.079,0.001,0.001,0.001,0.001,CSb0,0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,CSb1,0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,CSb2,0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,ADDR0[3:0],0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,ADDR1[3:0],0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,ADDR2[3:0],0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,WEb0,0.009,0.009,0.009,0.009,0.001,0.001,0.001,0.001,END
--><a href="https://vlsida.soe.ucsc.edu/"><img src=/home/jesse/clones/PrivateRAM/compiler/datasheet/assets/vlsi_logo.png alt="VLSIDA"></a><a href="https://vlsida.github.io/OpenRAM"><img src=/home/jesse/clones/PrivateRAM/compiler/datasheet/assets/openram_logo_placeholder.png alt="OpenRAM"></a><p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">sram_2_16_scn4m_subm.html</p><p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">DRC: skipped</p><p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">LVS: skipped</p><p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Ports and Configuration (DEBUG)</p><table id="data">
<thead><tr><th>Type</th><th>Description</th></tr></thead>
<tbody>
<tr><td>WORD_SIZE</td><td>2</td></tr>
<tr><td>NUM_WORDS</td><td>16</td></tr>
<tr><td>NUM_BANKS</td><td>1</td></tr>
<tr><td>NUM_RW_PORTS</td><td>1</td></tr>
<tr><td>NUM_R_PORTS</td><td>1</td></tr>
<tr><td>NUM_W_PORTS</td><td>1</td></tr>
<tr><td>Area</td><td>0</td></tr>
</tbody>
</table><p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Operating Conditions</p><table id="data">
<thead><tr><th>Parameter</th><th>Min</th><th>Typ</th><th>Max</th><th>Units</th></tr></thead>
<tbody>
<tr><td>Power supply (VDD) range</td><td>5.0</td><td>5.0</td><td>5.0</td><td>Volts</td></tr>
<tr><td>Operating Temperature</td><td>25</td><td>25</td><td>25</td><td>Celsius</td></tr>
<tr><td>Operating Frequency (F)*</td><td></td><td></td><td>unknown</td><td>MHz</td></tr>
</tbody>
</table><p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Timing and Current Data</p><table id="data">
<thead><tr><th>Parameter</th><th>Min</th><th>Max</th><th>Units</th></tr></thead>
<tbody>
<tr><td>Cycle time</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>Access time</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>Positive clk setup</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>Positive clk hold</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>DIN0[1:0] setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>DIN0[1:0] setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>DIN0[1:0] hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DIN0[1:0] hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DIN1[1:0] setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>DIN1[1:0] setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>DIN1[1:0] hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DIN1[1:0] hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DOUT0[1:0] cell rise</td><td>0.079</td><td>0.079</td><td>ns</td></tr>
<tr><td>DOUT0[1:0] cell fall</td><td>0.079</td><td>0.079</td><td>ns</td></tr>
<tr><td>DOUT0[1:0] rise transition</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DOUT0[1:0] fall transition</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DOUT2[1:0] cell rise</td><td>0.079</td><td>0.079</td><td>ns</td></tr>
<tr><td>DOUT2[1:0] cell fall</td><td>0.079</td><td>0.079</td><td>ns</td></tr>
<tr><td>DOUT2[1:0] rise transition</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>DOUT2[1:0] fall transition</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb0 setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb0 setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb0 hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb0 hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb1 setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb1 setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb1 hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb1 hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb2 setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb2 setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>CSb2 hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>CSb2 hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR0[3:0] setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR0[3:0] setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR0[3:0] hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR0[3:0] hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR1[3:0] setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR1[3:0] setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR1[3:0] hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR1[3:0] hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR2[3:0] setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR2[3:0] setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>ADDR2[3:0] hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>ADDR2[3:0] hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>WEb0 setup rising</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>WEb0 setup falling</td><td>0.009</td><td>0.009</td><td>ns</td></tr>
<tr><td>WEb0 hold rising</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>WEb0 hold falling</td><td>0.001</td><td>0.001</td><td>ns</td></tr>
<tr><td>AC current</td><td>2</td><td>3</td><td>4</td></tr>
<tr><td>Standby current</td><td>2</td><td>3</td><td>4</td></tr>
</tbody>
</table><p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Characterization Corners</p><table id="data">
<thead><tr><th>Corner Name</th><th>Process</th><th>Power Supply</th><th>Temperature</th><th>Library Name Suffix</th></tr></thead>
<tbody>
<tr><td>TT</td><td>Typical - Typical</td><td>5.0</td><td>25</td><td>_TT_5p0V_25C.lib</td></tr>
</tbody>
</table><p style="font-size: 26px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">Deliverables</p><table id="data">
<thead><tr><th>Type</th><th>Description</th><th>Link</th></tr></thead>
<tbody>
<tr><td>.sp</td><td>SPICE netlists</td><td><a href="sram_2_16_scn4m_subm.sp">sram_2_16_scn4m_subm.sp</a></td></tr>
<tr><td>.v</td><td>Verilog simulation models</td><td><a href="sram_2_16_scn4m_subm.v">sram_2_16_scn4m_subm.v</a></td></tr>
<tr><td>.html</td><td>This datasheet</td><td><a href="sram_2_16_scn4m_subm.html">sram_2_16_scn4m_subm.html</a></td></tr>
<tr><td>.lib</td><td>Synthesis models</td><td><a href="sram_2_16_scn4m_subm_TT_5p0V_25C.lib">sram_2_16_scn4m_subm_TT_5p0V_25C.lib</a></td></tr>
<tr><td>.py</td><td>OpenRAM configuration file</td><td><a href="sram_2_16_scn4m_subm.py">sram_2_16_scn4m_subm.py</a></td></tr>
</tbody>
</table><p style="font-size: 18px;font-family: Trebuchet MS, Arial, Helvetica, sans-serif;">*Feature only supported with characterizer</p>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,18 @@
word_size = 2
num_words = 16
tech_name = "scn4m_subm"
process_corners = ["TT"]
supply_voltages = [ 5.0 ]
temperatures = [ 25 ]
output_path = "temp"
output_name = "sram_{0}_{1}_{2}".format(word_size,num_words,tech_name)
#Setting for multiport
netlist_only = True
bitcell = "pbitcell"
replica_bitcell="replica_pbitcell"
num_rw_ports = 1
num_r_ports = 1
num_w_ports = 1

View File

@ -0,0 +1,767 @@
**************************************************
* OpenRAM generated memory.
* Words: 16
* Data bits: 2
* Banks: 1
* Column mux: 1:1
**************************************************
*********************** "dff" ******************************
* Positive edge-triggered FF
.SUBCKT dff D Q clk vdd gnd
* SPICE3 file created from dff.ext - technology: scmos
M1000 vdd clk a_24_24# vdd p w=8u l=0.4u
M1001 a_84_296# D vdd vdd p w=4u l=0.4u
M1002 a_104_24# clk a_84_296# vdd p w=4u l=0.4u
M1003 a_140_296# a_24_24# a_104_24# vdd p w=4u l=0.4u
M1004 vdd a_152_16# a_140_296# vdd p w=4u l=0.4u
M1005 a_152_16# a_104_24# vdd vdd p w=4u l=0.4u
M1006 a_260_296# a_152_16# vdd vdd p w=4u l=0.4u
M1007 a_280_24# a_24_24# a_260_296# vdd p w=4u l=0.4u
M1008 a_320_336# clk a_280_24# vdd p w=2u l=0.4u
M1009 vdd Q a_320_336# vdd p w=2u l=0.4u
M1010 gnd clk a_24_24# gnd n w=4u l=0.4u
M1011 Q a_280_24# vdd vdd p w=8u l=0.4u
M1012 a_84_24# D gnd gnd n w=2u l=0.4u
M1013 a_104_24# a_24_24# a_84_24# gnd n w=2u l=0.4u
M1014 a_140_24# clk a_104_24# gnd n w=2u l=0.4u
M1015 gnd a_152_16# a_140_24# gnd n w=2u l=0.4u
M1016 a_152_16# a_104_24# gnd gnd n w=2u l=0.4u
M1017 a_260_24# a_152_16# gnd gnd n w=2u l=0.4u
M1018 a_280_24# clk a_260_24# gnd n w=2u l=0.4u
M1019 a_320_24# a_24_24# a_280_24# gnd n w=2u l=0.4u
M1020 gnd Q a_320_24# gnd n w=2u l=0.4u
M1021 Q a_280_24# gnd gnd n w=4u l=0.4u
.ENDS
* ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
* ptx M{0} {1} p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.SUBCKT pinv_2 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_2
.SUBCKT dff_inv_2 D Q Qb clk vdd gnd
Xdff_inv_dff D Q clk vdd gnd dff
Xdff_inv_inv1 Q Qb vdd gnd pinv_2
.ENDS dff_inv_2
.SUBCKT dff_inv_array_2x1_1 din_0 din_1 dout_0 dout_bar_0 dout_1 dout_bar_1 clk vdd gnd
XXdff_r0_c0 din_0 dout_0 dout_bar_0 clk vdd gnd dff_inv_2
XXdff_r1_c0 din_1 dout_1 dout_bar_1 clk vdd gnd dff_inv_2
.ENDS dff_inv_array_2x1_1
* ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.SUBCKT pnand2_1 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_1
.SUBCKT pnand3_1 A B C Z vdd gnd
Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand3_1
* ptx M{0} {1} n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.SUBCKT pinv_3 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_3
.SUBCKT pinv_4 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_4
* ptx M{0} {1} n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
* ptx M{0} {1} p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
.SUBCKT pinv_5 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_5
.SUBCKT pinvbuf_2_4_1 A Zb Z vdd gnd
Xbuf_inv1 A zb_int vdd gnd pinv_3
Xbuf_inv2 zb_int z_int vdd gnd pinv_4
Xbuf_inv3 z_int Zb vdd gnd pinv_5
Xbuf_inv4 zb_int Z vdd gnd pinv_5
.ENDS pinvbuf_2_4_1
.SUBCKT pinv_6 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_6
.SUBCKT pinv_7 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_7
* ptx M{0} {1} n m=1 w=12.8u l=0.4u pd=26.400000000000002u ps=26.400000000000002u as=12.8p ad=12.8p
* ptx M{0} {1} p m=1 w=25.6u l=0.4u pd=52.0u ps=52.0u as=25.6p ad=25.6p
.SUBCKT pinv_8 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=25.6u l=0.4u pd=52.0u ps=52.0u as=25.6p ad=25.6p
Mpinv_nmos Z A gnd gnd n m=1 w=12.8u l=0.4u pd=26.400000000000002u ps=26.400000000000002u as=12.8p ad=12.8p
.ENDS pinv_8
* ptx M{0} {1} n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
* ptx M{0} {1} p m=1 w=0.6000000000000001u l=0.4u pd=2.0u ps=2.0u as=0.6000000000000001p ad=0.6000000000000001p
* ptx M{0} {1} n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
* ptx M{0} {1} n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
.SUBCKT replica_pbitcell_1RW_1W_1R bl0 br0 bl1 br1 bl2 br2 wl0 wl1 wl2 vdd gnd
Minverter_nmos_left Q vdd gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Minverter_nmos_right gnd Q vdd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Minverter_pmos_left Q vdd vdd vdd p m=1 w=0.6000000000000001u l=0.4u pd=2.0u ps=2.0u as=0.6000000000000001p ad=0.6000000000000001p
Minverter_pmos_right vdd Q vdd vdd p m=1 w=0.6000000000000001u l=0.4u pd=2.0u ps=2.0u as=0.6000000000000001p ad=0.6000000000000001p
Mreadwrite_nmos_left0 bl0 wl0 Q gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mreadwrite_nmos_right0 vdd wl0 br0 gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mwrite_nmos_left0 bl1 wl1 Q gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mwrite_nmos_right0 vdd wl1 br1 gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mread_access_nmos_left0 RA_to_R_left0 vdd gnd gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_access_nmos_right0 gnd Q RA_to_R_right0 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_nmos_left0 bl2 wl2 RA_to_R_left0 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_nmos_right0 RA_to_R_right0 wl2 br2 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
.ENDS replica_pbitcell_1RW_1W_1R
.SUBCKT replica_pbitcell bl0 br0 bl1 br1 bl2 br2 wl0 wl1 wl2 vdd gnd
Xpbitcell bl0 br0 bl1 br1 bl2 br2 wl0 wl1 wl2 vdd gnd replica_pbitcell_1RW_1W_1R
.ENDS replica_pbitcell
.SUBCKT pbitcell_1RW_1W_1R bl0 br0 bl1 br1 bl2 br2 wl0 wl1 wl2 vdd gnd
Minverter_nmos_left Q Q_bar gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Minverter_nmos_right gnd Q Q_bar gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Minverter_pmos_left Q Q_bar vdd vdd p m=1 w=0.6000000000000001u l=0.4u pd=2.0u ps=2.0u as=0.6000000000000001p ad=0.6000000000000001p
Minverter_pmos_right vdd Q Q_bar vdd p m=1 w=0.6000000000000001u l=0.4u pd=2.0u ps=2.0u as=0.6000000000000001p ad=0.6000000000000001p
Mreadwrite_nmos_left0 bl0 wl0 Q gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mreadwrite_nmos_right0 Q_bar wl0 br0 gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mwrite_nmos_left0 bl1 wl1 Q gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mwrite_nmos_right0 Q_bar wl1 br1 gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Mread_access_nmos_left0 RA_to_R_left0 Q_bar gnd gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_access_nmos_right0 gnd Q RA_to_R_right0 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_nmos_left0 bl2 wl2 RA_to_R_left0 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
Mread_nmos_right0 RA_to_R_right0 wl2 br2 gnd n m=1 w=1.2000000000000002u l=0.4u pd=3.2u ps=3.2u as=1.2000000000000002p ad=1.2000000000000002p
.ENDS pbitcell_1RW_1W_1R
.SUBCKT bitcell_array_8x1_1 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_0 wl1_0 wl2_0 wl0_1 wl1_1 wl2_1 wl0_2 wl1_2 wl2_2 wl0_3 wl1_3 wl2_3 wl0_4 wl1_4 wl2_4 wl0_5 wl1_5 wl2_5 wl0_6 wl1_6 wl2_6 wl0_7 wl1_7 wl2_7 vdd gnd
Xbit_r0_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_0 wl1_0 wl2_0 vdd gnd pbitcell_1RW_1W_1R
Xbit_r1_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_1 wl1_1 wl2_1 vdd gnd pbitcell_1RW_1W_1R
Xbit_r2_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_2 wl1_2 wl2_2 vdd gnd pbitcell_1RW_1W_1R
Xbit_r3_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_3 wl1_3 wl2_3 vdd gnd pbitcell_1RW_1W_1R
Xbit_r4_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_4 wl1_4 wl2_4 vdd gnd pbitcell_1RW_1W_1R
Xbit_r5_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_5 wl1_5 wl2_5 vdd gnd pbitcell_1RW_1W_1R
Xbit_r6_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_6 wl1_6 wl2_6 vdd gnd pbitcell_1RW_1W_1R
Xbit_r7_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_7 wl1_7 wl2_7 vdd gnd pbitcell_1RW_1W_1R
.ENDS bitcell_array_8x1_1
.SUBCKT pinv_9 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_9
.SUBCKT delay_chain_1 in out vdd gnd
Xdinv0 in dout_1 vdd gnd pinv_9
Xdload_0_0 dout_1 n_0_0 vdd gnd pinv_9
Xdload_0_1 dout_1 n_0_1 vdd gnd pinv_9
Xdload_0_2 dout_1 n_0_2 vdd gnd pinv_9
Xdinv1 dout_1 dout_2 vdd gnd pinv_9
Xdload_1_0 dout_2 n_1_0 vdd gnd pinv_9
Xdload_1_1 dout_2 n_1_1 vdd gnd pinv_9
Xdload_1_2 dout_2 n_1_2 vdd gnd pinv_9
Xdinv2 dout_2 dout_3 vdd gnd pinv_9
Xdload_2_0 dout_3 n_2_0 vdd gnd pinv_9
Xdload_2_1 dout_3 n_2_1 vdd gnd pinv_9
Xdload_2_2 dout_3 n_2_2 vdd gnd pinv_9
Xdinv3 dout_3 out vdd gnd pinv_9
Xdload_3_0 out n_3_0 vdd gnd pinv_9
Xdload_3_1 out n_3_1 vdd gnd pinv_9
Xdload_3_2 out n_3_2 vdd gnd pinv_9
.ENDS delay_chain_1
.SUBCKT pinv_10 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_10
* ptx M{0} {1} p m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.SUBCKT replica_bitline_rw en out vdd gnd
Xrbl_inv bl0_0 out vdd gnd pinv_10
Mrbl_access_tx vdd delayed_en bl0_0 vdd p m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Xdelay_chain en delayed_en vdd gnd delay_chain_1
Xbitcell bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 delayed_en delayed_en delayed_en vdd gnd replica_pbitcell
Xload bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd vdd gnd bitcell_array_8x1_1
.ENDS replica_bitline_rw
.SUBCKT control_logic_rw csb web clk s_en w_en clk_buf_bar clk_buf vdd gnd
Xctrl_dffs csb web cs_bar cs we_bar we clk_buf vdd gnd dff_inv_array_2x1_1
Xclkbuf clk clk_buf_bar clk_buf vdd gnd pinvbuf_2_4_1
Xnand3_w_en_bar clk_buf_bar cs we w_en_bar vdd gnd pnand3_1
Xinv_pre_w_en w_en_bar pre_w_en vdd gnd pinv_6
Xinv_pre_w_en_bar pre_w_en pre_w_en_bar vdd gnd pinv_7
Xinv_w_en2 pre_w_en_bar w_en vdd gnd pinv_8
Xnand2_rbl_in_bar clk_buf_bar cs rbl_in_bar vdd gnd pnand2_1
Xinv_rbl_in rbl_in_bar rbl_in vdd gnd pinv_6
Xinv_pre_s_en_bar pre_s_en pre_s_en_bar vdd gnd pinv_7
Xinv_s_en pre_s_en_bar s_en vdd gnd pinv_8
Xreplica_bitline rbl_in pre_s_en vdd gnd replica_bitline_rw
.ENDS control_logic_rw
.SUBCKT pinv_12 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_12
.SUBCKT dff_inv_4 D Q Qb clk vdd gnd
Xdff_inv_dff D Q clk vdd gnd dff
Xdff_inv_inv1 Q Qb vdd gnd pinv_12
.ENDS dff_inv_4
.SUBCKT dff_inv_array_1x1_2 din_0 dout_0 dout_bar_0 clk vdd gnd
XXdff_r0_c0 din_0 dout_0 dout_bar_0 clk vdd gnd dff_inv_4
.ENDS dff_inv_array_1x1_2
.SUBCKT pnand2_2 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_2
.SUBCKT pnand3_2 A B C Z vdd gnd
Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand3_2
.SUBCKT pinv_13 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_13
.SUBCKT pinv_14 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_14
.SUBCKT pinv_15 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_15
.SUBCKT pinvbuf_2_4_2 A Zb Z vdd gnd
Xbuf_inv1 A zb_int vdd gnd pinv_13
Xbuf_inv2 zb_int z_int vdd gnd pinv_14
Xbuf_inv3 z_int Zb vdd gnd pinv_15
Xbuf_inv4 zb_int Z vdd gnd pinv_15
.ENDS pinvbuf_2_4_2
.SUBCKT pinv_16 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_16
.SUBCKT pinv_17 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_17
.SUBCKT pinv_18 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=25.6u l=0.4u pd=52.0u ps=52.0u as=25.6p ad=25.6p
Mpinv_nmos Z A gnd gnd n m=1 w=12.8u l=0.4u pd=26.400000000000002u ps=26.400000000000002u as=12.8p ad=12.8p
.ENDS pinv_18
.SUBCKT control_logic_w csb clk w_en clk_buf_bar clk_buf vdd gnd
Xctrl_dffs csb cs_bar cs clk_buf vdd gnd dff_inv_array_1x1_2
Xclkbuf clk clk_buf_bar clk_buf vdd gnd pinvbuf_2_4_2
Xnand3_w_en_bar clk_buf_bar cs w_en_bar vdd gnd pnand2_2
Xinv_pre_w_en w_en_bar pre_w_en vdd gnd pinv_16
Xinv_pre_w_en_bar pre_w_en pre_w_en_bar vdd gnd pinv_17
Xinv_w_en2 pre_w_en_bar w_en vdd gnd pinv_18
.ENDS control_logic_w
.SUBCKT pinv_20 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_20
.SUBCKT dff_inv_6 D Q Qb clk vdd gnd
Xdff_inv_dff D Q clk vdd gnd dff
Xdff_inv_inv1 Q Qb vdd gnd pinv_20
.ENDS dff_inv_6
.SUBCKT dff_inv_array_1x1_3 din_0 dout_0 dout_bar_0 clk vdd gnd
XXdff_r0_c0 din_0 dout_0 dout_bar_0 clk vdd gnd dff_inv_6
.ENDS dff_inv_array_1x1_3
.SUBCKT pnand2_3 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_3
.SUBCKT pnand3_3 A B C Z vdd gnd
Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand3_3
.SUBCKT pinv_21 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_21
.SUBCKT pinv_22 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
Mpinv_nmos Z A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pinv_22
.SUBCKT pinv_23 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_23
.SUBCKT pinvbuf_2_4_3 A Zb Z vdd gnd
Xbuf_inv1 A zb_int vdd gnd pinv_21
Xbuf_inv2 zb_int z_int vdd gnd pinv_22
Xbuf_inv3 z_int Zb vdd gnd pinv_23
Xbuf_inv4 zb_int Z vdd gnd pinv_23
.ENDS pinvbuf_2_4_3
.SUBCKT pinv_24 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_24
.SUBCKT pinv_25 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=6.4u l=0.4u pd=13.600000000000001u ps=13.600000000000001u as=6.4p ad=6.4p
Mpinv_nmos Z A gnd gnd n m=1 w=3.2u l=0.4u pd=7.2u ps=7.2u as=3.2p ad=3.2p
.ENDS pinv_25
.SUBCKT pinv_26 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=25.6u l=0.4u pd=52.0u ps=52.0u as=25.6p ad=25.6p
Mpinv_nmos Z A gnd gnd n m=1 w=12.8u l=0.4u pd=26.400000000000002u ps=26.400000000000002u as=12.8p ad=12.8p
.ENDS pinv_26
.SUBCKT bitcell_array_8x1_2 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_0 wl1_0 wl2_0 wl0_1 wl1_1 wl2_1 wl0_2 wl1_2 wl2_2 wl0_3 wl1_3 wl2_3 wl0_4 wl1_4 wl2_4 wl0_5 wl1_5 wl2_5 wl0_6 wl1_6 wl2_6 wl0_7 wl1_7 wl2_7 vdd gnd
Xbit_r0_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_0 wl1_0 wl2_0 vdd gnd pbitcell_1RW_1W_1R
Xbit_r1_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_1 wl1_1 wl2_1 vdd gnd pbitcell_1RW_1W_1R
Xbit_r2_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_2 wl1_2 wl2_2 vdd gnd pbitcell_1RW_1W_1R
Xbit_r3_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_3 wl1_3 wl2_3 vdd gnd pbitcell_1RW_1W_1R
Xbit_r4_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_4 wl1_4 wl2_4 vdd gnd pbitcell_1RW_1W_1R
Xbit_r5_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_5 wl1_5 wl2_5 vdd gnd pbitcell_1RW_1W_1R
Xbit_r6_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_6 wl1_6 wl2_6 vdd gnd pbitcell_1RW_1W_1R
Xbit_r7_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_7 wl1_7 wl2_7 vdd gnd pbitcell_1RW_1W_1R
.ENDS bitcell_array_8x1_2
.SUBCKT pinv_27 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_27
.SUBCKT delay_chain_2 in out vdd gnd
Xdinv0 in dout_1 vdd gnd pinv_27
Xdload_0_0 dout_1 n_0_0 vdd gnd pinv_27
Xdload_0_1 dout_1 n_0_1 vdd gnd pinv_27
Xdload_0_2 dout_1 n_0_2 vdd gnd pinv_27
Xdinv1 dout_1 dout_2 vdd gnd pinv_27
Xdload_1_0 dout_2 n_1_0 vdd gnd pinv_27
Xdload_1_1 dout_2 n_1_1 vdd gnd pinv_27
Xdload_1_2 dout_2 n_1_2 vdd gnd pinv_27
Xdinv2 dout_2 dout_3 vdd gnd pinv_27
Xdload_2_0 dout_3 n_2_0 vdd gnd pinv_27
Xdload_2_1 dout_3 n_2_1 vdd gnd pinv_27
Xdload_2_2 dout_3 n_2_2 vdd gnd pinv_27
Xdinv3 dout_3 out vdd gnd pinv_27
Xdload_3_0 out n_3_0 vdd gnd pinv_27
Xdload_3_1 out n_3_1 vdd gnd pinv_27
Xdload_3_2 out n_3_2 vdd gnd pinv_27
.ENDS delay_chain_2
.SUBCKT pinv_28 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_28
.SUBCKT replica_bitline_r en out vdd gnd
Xrbl_inv bl0_0 out vdd gnd pinv_28
Mrbl_access_tx vdd delayed_en bl0_0 vdd p m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
Xdelay_chain en delayed_en vdd gnd delay_chain_2
Xbitcell bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 delayed_en delayed_en delayed_en vdd gnd replica_pbitcell
Xload bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd gnd vdd gnd bitcell_array_8x1_2
.ENDS replica_bitline_r
.SUBCKT control_logic_r csb clk s_en clk_buf_bar clk_buf vdd gnd
Xctrl_dffs csb cs_bar cs clk_buf vdd gnd dff_inv_array_1x1_3
Xclkbuf clk clk_buf_bar clk_buf vdd gnd pinvbuf_2_4_3
Xnand2_rbl_in_bar clk_buf_bar cs rbl_in_bar vdd gnd pnand2_3
Xinv_rbl_in rbl_in_bar rbl_in vdd gnd pinv_24
Xinv_pre_s_en_bar pre_s_en pre_s_en_bar vdd gnd pinv_25
Xinv_s_en pre_s_en_bar s_en vdd gnd pinv_26
Xreplica_bitline rbl_in pre_s_en vdd gnd replica_bitline_r
.ENDS control_logic_r
.SUBCKT row_addr_dff din_0 din_1 din_2 din_3 dout_0 dout_1 dout_2 dout_3 clk vdd gnd
XXdff_r0_c0 din_0 dout_0 clk vdd gnd dff
XXdff_r1_c0 din_1 dout_1 clk vdd gnd dff
XXdff_r2_c0 din_2 dout_2 clk vdd gnd dff
XXdff_r3_c0 din_3 dout_3 clk vdd gnd dff
.ENDS row_addr_dff
.SUBCKT data_dff din_0 din_1 dout_0 dout_1 clk vdd gnd
XXdff_r0_c0 din_0 dout_0 clk vdd gnd dff
XXdff_r0_c1 din_1 dout_1 clk vdd gnd dff
.ENDS data_dff
.SUBCKT bitcell_array_16x2_1 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_0 wl1_0 wl2_0 wl0_1 wl1_1 wl2_1 wl0_2 wl1_2 wl2_2 wl0_3 wl1_3 wl2_3 wl0_4 wl1_4 wl2_4 wl0_5 wl1_5 wl2_5 wl0_6 wl1_6 wl2_6 wl0_7 wl1_7 wl2_7 wl0_8 wl1_8 wl2_8 wl0_9 wl1_9 wl2_9 wl0_10 wl1_10 wl2_10 wl0_11 wl1_11 wl2_11 wl0_12 wl1_12 wl2_12 wl0_13 wl1_13 wl2_13 wl0_14 wl1_14 wl2_14 wl0_15 wl1_15 wl2_15 vdd gnd
Xbit_r0_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_0 wl1_0 wl2_0 vdd gnd pbitcell_1RW_1W_1R
Xbit_r1_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_1 wl1_1 wl2_1 vdd gnd pbitcell_1RW_1W_1R
Xbit_r2_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_2 wl1_2 wl2_2 vdd gnd pbitcell_1RW_1W_1R
Xbit_r3_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_3 wl1_3 wl2_3 vdd gnd pbitcell_1RW_1W_1R
Xbit_r4_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_4 wl1_4 wl2_4 vdd gnd pbitcell_1RW_1W_1R
Xbit_r5_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_5 wl1_5 wl2_5 vdd gnd pbitcell_1RW_1W_1R
Xbit_r6_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_6 wl1_6 wl2_6 vdd gnd pbitcell_1RW_1W_1R
Xbit_r7_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_7 wl1_7 wl2_7 vdd gnd pbitcell_1RW_1W_1R
Xbit_r8_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_8 wl1_8 wl2_8 vdd gnd pbitcell_1RW_1W_1R
Xbit_r9_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_9 wl1_9 wl2_9 vdd gnd pbitcell_1RW_1W_1R
Xbit_r10_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_10 wl1_10 wl2_10 vdd gnd pbitcell_1RW_1W_1R
Xbit_r11_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_11 wl1_11 wl2_11 vdd gnd pbitcell_1RW_1W_1R
Xbit_r12_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_12 wl1_12 wl2_12 vdd gnd pbitcell_1RW_1W_1R
Xbit_r13_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_13 wl1_13 wl2_13 vdd gnd pbitcell_1RW_1W_1R
Xbit_r14_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_14 wl1_14 wl2_14 vdd gnd pbitcell_1RW_1W_1R
Xbit_r15_c0 bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 wl0_15 wl1_15 wl2_15 vdd gnd pbitcell_1RW_1W_1R
Xbit_r0_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_0 wl1_0 wl2_0 vdd gnd pbitcell_1RW_1W_1R
Xbit_r1_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_1 wl1_1 wl2_1 vdd gnd pbitcell_1RW_1W_1R
Xbit_r2_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_2 wl1_2 wl2_2 vdd gnd pbitcell_1RW_1W_1R
Xbit_r3_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_3 wl1_3 wl2_3 vdd gnd pbitcell_1RW_1W_1R
Xbit_r4_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_4 wl1_4 wl2_4 vdd gnd pbitcell_1RW_1W_1R
Xbit_r5_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_5 wl1_5 wl2_5 vdd gnd pbitcell_1RW_1W_1R
Xbit_r6_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_6 wl1_6 wl2_6 vdd gnd pbitcell_1RW_1W_1R
Xbit_r7_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_7 wl1_7 wl2_7 vdd gnd pbitcell_1RW_1W_1R
Xbit_r8_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_8 wl1_8 wl2_8 vdd gnd pbitcell_1RW_1W_1R
Xbit_r9_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_9 wl1_9 wl2_9 vdd gnd pbitcell_1RW_1W_1R
Xbit_r10_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_10 wl1_10 wl2_10 vdd gnd pbitcell_1RW_1W_1R
Xbit_r11_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_11 wl1_11 wl2_11 vdd gnd pbitcell_1RW_1W_1R
Xbit_r12_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_12 wl1_12 wl2_12 vdd gnd pbitcell_1RW_1W_1R
Xbit_r13_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_13 wl1_13 wl2_13 vdd gnd pbitcell_1RW_1W_1R
Xbit_r14_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_14 wl1_14 wl2_14 vdd gnd pbitcell_1RW_1W_1R
Xbit_r15_c1 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_15 wl1_15 wl2_15 vdd gnd pbitcell_1RW_1W_1R
.ENDS bitcell_array_16x2_1
* ptx M{0} {1} p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.SUBCKT precharge_1 bl br en vdd
Mlower_pmos bl en br vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mupper_pmos1 bl en vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mupper_pmos2 br en vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS precharge_1
.SUBCKT precharge_array_1 bl_0 br_0 bl_1 br_1 en vdd
Xpre_column_0 bl_0 br_0 en vdd precharge_1
Xpre_column_1 bl_1 br_1 en vdd precharge_1
.ENDS precharge_array_1
.SUBCKT precharge_2 bl br en vdd
Mlower_pmos bl en br vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mupper_pmos1 bl en vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mupper_pmos2 br en vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS precharge_2
.SUBCKT precharge_array_2 bl_0 br_0 bl_1 br_1 en vdd
Xpre_column_0 bl_0 br_0 en vdd precharge_2
Xpre_column_1 bl_1 br_1 en vdd precharge_2
.ENDS precharge_array_2
*********************** "sense_amp" ******************************
.SUBCKT sense_amp bl br dout en vdd gnd
* SPICE3 file created from sense_amp.ext - technology: scmos
M1000 gnd en a_56_432# gnd n w=1.8u l=0.4u
M1001 a_56_432# a_48_304# dout gnd n w=1.8u l=0.4u
M1002 a_48_304# dout a_56_432# gnd n w=1.8u l=0.4u
M1003 vdd a_48_304# dout vdd p w=3.6u l=0.4u
M1004 a_48_304# dout vdd vdd p w=3.6u l=0.4u
M1005 bl en dout vdd p w=4.8u l=0.4u
M1006 a_48_304# en br vdd p w=4.8u l=0.4u
.ENDS
.SUBCKT sense_amp_array data_0 bl_0 br_0 data_1 bl_1 br_1 en vdd gnd
Xsa_d0 bl_0 br_0 data_0 en vdd gnd sense_amp
Xsa_d1 bl_1 br_1 data_1 en vdd gnd sense_amp
.ENDS sense_amp_array
*********************** Write_Driver ******************************
.SUBCKT write_driver din bl br en vdd gnd
* SPICE3 file created from write_driver.ext - technology: scmos
M1000 a_44_708# a_36_700# bl gnd n w=2.4u l=0.4u
M1001 br a_16_500# a_44_708# gnd n w=2.4u l=0.4u
M1002 a_44_708# en gnd gnd n w=2.4u l=0.4u
M1003 gnd a_8_284# a_16_500# gnd n w=0.8u l=0.4u
M1004 a_36_700# a_20_328# gnd gnd n w=0.8u l=0.4u
M1005 vdd a_8_284# a_16_500# vdd p w=1.4u l=0.4u
M1006 a_36_700# a_20_328# vdd vdd p w=1.4u l=0.4u
M1007 vdd en a_20_328# vdd p w=1.4u l=0.4u
M1008 a_20_328# a_64_360# vdd vdd p w=1.4u l=0.4u
M1009 a_48_328# en a_20_328# gnd n w=1.4u l=0.4u
M1010 gnd a_64_360# a_48_328# gnd n w=1.4u l=0.4u
M1011 a_40_228# en a_8_284# gnd n w=1.4u l=0.4u
M1012 gnd din a_40_228# gnd n w=1.4u l=0.4u
M1013 a_64_360# din gnd gnd n w=0.8u l=0.4u
M1014 a_8_284# en vdd vdd p w=1.4u l=0.4u
M1015 vdd din a_8_284# vdd p w=1.4u l=0.4u
M1016 a_64_360# din vdd vdd p w=1.4u l=0.4u
.ENDS
.SUBCKT write_driver_array data_0 data_1 bl_0 br_0 bl_1 br_1 en vdd gnd
XXwrite_driver0 data_0 bl_0 br_0 en vdd gnd write_driver
XXwrite_driver1 data_1 bl_1 br_1 en vdd gnd write_driver
.ENDS write_driver_array
.SUBCKT pinv_29 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_29
.SUBCKT pnand2_4 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_4
.SUBCKT pnand3_4 A B C Z vdd gnd
Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand3_4
.SUBCKT pinv_30 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_30
.SUBCKT pnand2_5 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_5
.SUBCKT pre2x4 in_0 in_1 out_0 out_1 out_2 out_3 vdd gnd
XXpre_inv_0 in_0 inbar_0 vdd gnd pinv_30
XXpre_inv_1 in_1 inbar_1 vdd gnd pinv_30
XXpre_nand_inv_0 Z_0 out_0 vdd gnd pinv_30
XXpre_nand_inv_1 Z_1 out_1 vdd gnd pinv_30
XXpre_nand_inv_2 Z_2 out_2 vdd gnd pinv_30
XXpre_nand_inv_3 Z_3 out_3 vdd gnd pinv_30
XXpre2x4_nand_0 inbar_0 inbar_1 Z_0 vdd gnd pnand2_5
XXpre2x4_nand_1 in_0 inbar_1 Z_1 vdd gnd pnand2_5
XXpre2x4_nand_2 inbar_0 in_1 Z_2 vdd gnd pnand2_5
XXpre2x4_nand_3 in_0 in_1 Z_3 vdd gnd pnand2_5
.ENDS pre2x4
.SUBCKT pinv_31 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_31
.SUBCKT pnand3_5 A B C Z vdd gnd
Mpnand3_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_pmos3 Z C vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos1 Z C net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos2 net1 B net2 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand3_nmos3 net2 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand3_5
.SUBCKT pre3x8 in_0 in_1 in_2 out_0 out_1 out_2 out_3 out_4 out_5 out_6 out_7 vdd gnd
XXpre_inv_0 in_0 inbar_0 vdd gnd pinv_31
XXpre_inv_1 in_1 inbar_1 vdd gnd pinv_31
XXpre_inv_2 in_2 inbar_2 vdd gnd pinv_31
XXpre_nand_inv_0 Z_0 out_0 vdd gnd pinv_31
XXpre_nand_inv_1 Z_1 out_1 vdd gnd pinv_31
XXpre_nand_inv_2 Z_2 out_2 vdd gnd pinv_31
XXpre_nand_inv_3 Z_3 out_3 vdd gnd pinv_31
XXpre_nand_inv_4 Z_4 out_4 vdd gnd pinv_31
XXpre_nand_inv_5 Z_5 out_5 vdd gnd pinv_31
XXpre_nand_inv_6 Z_6 out_6 vdd gnd pinv_31
XXpre_nand_inv_7 Z_7 out_7 vdd gnd pinv_31
XXpre3x8_nand_0 inbar_0 inbar_1 inbar_2 Z_0 vdd gnd pnand3_5
XXpre3x8_nand_1 in_0 inbar_1 inbar_2 Z_1 vdd gnd pnand3_5
XXpre3x8_nand_2 inbar_0 in_1 inbar_2 Z_2 vdd gnd pnand3_5
XXpre3x8_nand_3 in_0 in_1 inbar_2 Z_3 vdd gnd pnand3_5
XXpre3x8_nand_4 inbar_0 inbar_1 in_2 Z_4 vdd gnd pnand3_5
XXpre3x8_nand_5 in_0 inbar_1 in_2 Z_5 vdd gnd pnand3_5
XXpre3x8_nand_6 inbar_0 in_1 in_2 Z_6 vdd gnd pnand3_5
XXpre3x8_nand_7 in_0 in_1 in_2 Z_7 vdd gnd pnand3_5
.ENDS pre3x8
.SUBCKT hierarchical_decoder_16rows addr_0 addr_1 addr_2 addr_3 decode_0 decode_1 decode_2 decode_3 decode_4 decode_5 decode_6 decode_7 decode_8 decode_9 decode_10 decode_11 decode_12 decode_13 decode_14 decode_15 vdd gnd
Xpre_0 addr_0 addr_1 out_0 out_1 out_2 out_3 vdd gnd pre2x4
Xpre_1 addr_2 addr_3 out_4 out_5 out_6 out_7 vdd gnd pre2x4
XDEC_NAND_0 out_0 out_4 Z_0 vdd gnd pnand2_4
XDEC_NAND_1 out_0 out_5 Z_1 vdd gnd pnand2_4
XDEC_NAND_2 out_0 out_6 Z_2 vdd gnd pnand2_4
XDEC_NAND_3 out_0 out_7 Z_3 vdd gnd pnand2_4
XDEC_NAND_4 out_1 out_4 Z_4 vdd gnd pnand2_4
XDEC_NAND_5 out_1 out_5 Z_5 vdd gnd pnand2_4
XDEC_NAND_6 out_1 out_6 Z_6 vdd gnd pnand2_4
XDEC_NAND_7 out_1 out_7 Z_7 vdd gnd pnand2_4
XDEC_NAND_8 out_2 out_4 Z_8 vdd gnd pnand2_4
XDEC_NAND_9 out_2 out_5 Z_9 vdd gnd pnand2_4
XDEC_NAND_10 out_2 out_6 Z_10 vdd gnd pnand2_4
XDEC_NAND_11 out_2 out_7 Z_11 vdd gnd pnand2_4
XDEC_NAND_12 out_3 out_4 Z_12 vdd gnd pnand2_4
XDEC_NAND_13 out_3 out_5 Z_13 vdd gnd pnand2_4
XDEC_NAND_14 out_3 out_6 Z_14 vdd gnd pnand2_4
XDEC_NAND_15 out_3 out_7 Z_15 vdd gnd pnand2_4
XDEC_INV_0 Z_0 decode_0 vdd gnd pinv_29
XDEC_INV_1 Z_1 decode_1 vdd gnd pinv_29
XDEC_INV_2 Z_2 decode_2 vdd gnd pinv_29
XDEC_INV_3 Z_3 decode_3 vdd gnd pinv_29
XDEC_INV_4 Z_4 decode_4 vdd gnd pinv_29
XDEC_INV_5 Z_5 decode_5 vdd gnd pinv_29
XDEC_INV_6 Z_6 decode_6 vdd gnd pinv_29
XDEC_INV_7 Z_7 decode_7 vdd gnd pinv_29
XDEC_INV_8 Z_8 decode_8 vdd gnd pinv_29
XDEC_INV_9 Z_9 decode_9 vdd gnd pinv_29
XDEC_INV_10 Z_10 decode_10 vdd gnd pinv_29
XDEC_INV_11 Z_11 decode_11 vdd gnd pinv_29
XDEC_INV_12 Z_12 decode_12 vdd gnd pinv_29
XDEC_INV_13 Z_13 decode_13 vdd gnd pinv_29
XDEC_INV_14 Z_14 decode_14 vdd gnd pinv_29
XDEC_INV_15 Z_15 decode_15 vdd gnd pinv_29
.ENDS hierarchical_decoder_16rows
.SUBCKT pinv_32 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_32
.SUBCKT pinv_33 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_33
.SUBCKT pnand2_6 A B Z vdd gnd
Mpnand2_pmos1 vdd A Z vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_pmos2 Z B vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos1 Z B net1 gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpnand2_nmos2 net1 A gnd gnd n m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
.ENDS pnand2_6
.SUBCKT wordline_driver in_0 in_1 in_2 in_3 in_4 in_5 in_6 in_7 in_8 in_9 in_10 in_11 in_12 in_13 in_14 in_15 wl_0 wl_1 wl_2 wl_3 wl_4 wl_5 wl_6 wl_7 wl_8 wl_9 wl_10 wl_11 wl_12 wl_13 wl_14 wl_15 en vdd gnd
Xwl_driver_inv_en0 en en_bar_0 vdd gnd pinv_33
Xwl_driver_nand0 en_bar_0 in_0 wl_bar_0 vdd gnd pnand2_6
Xwl_driver_inv0 wl_bar_0 wl_0 vdd gnd pinv_32
Xwl_driver_inv_en1 en en_bar_1 vdd gnd pinv_33
Xwl_driver_nand1 en_bar_1 in_1 wl_bar_1 vdd gnd pnand2_6
Xwl_driver_inv1 wl_bar_1 wl_1 vdd gnd pinv_32
Xwl_driver_inv_en2 en en_bar_2 vdd gnd pinv_33
Xwl_driver_nand2 en_bar_2 in_2 wl_bar_2 vdd gnd pnand2_6
Xwl_driver_inv2 wl_bar_2 wl_2 vdd gnd pinv_32
Xwl_driver_inv_en3 en en_bar_3 vdd gnd pinv_33
Xwl_driver_nand3 en_bar_3 in_3 wl_bar_3 vdd gnd pnand2_6
Xwl_driver_inv3 wl_bar_3 wl_3 vdd gnd pinv_32
Xwl_driver_inv_en4 en en_bar_4 vdd gnd pinv_33
Xwl_driver_nand4 en_bar_4 in_4 wl_bar_4 vdd gnd pnand2_6
Xwl_driver_inv4 wl_bar_4 wl_4 vdd gnd pinv_32
Xwl_driver_inv_en5 en en_bar_5 vdd gnd pinv_33
Xwl_driver_nand5 en_bar_5 in_5 wl_bar_5 vdd gnd pnand2_6
Xwl_driver_inv5 wl_bar_5 wl_5 vdd gnd pinv_32
Xwl_driver_inv_en6 en en_bar_6 vdd gnd pinv_33
Xwl_driver_nand6 en_bar_6 in_6 wl_bar_6 vdd gnd pnand2_6
Xwl_driver_inv6 wl_bar_6 wl_6 vdd gnd pinv_32
Xwl_driver_inv_en7 en en_bar_7 vdd gnd pinv_33
Xwl_driver_nand7 en_bar_7 in_7 wl_bar_7 vdd gnd pnand2_6
Xwl_driver_inv7 wl_bar_7 wl_7 vdd gnd pinv_32
Xwl_driver_inv_en8 en en_bar_8 vdd gnd pinv_33
Xwl_driver_nand8 en_bar_8 in_8 wl_bar_8 vdd gnd pnand2_6
Xwl_driver_inv8 wl_bar_8 wl_8 vdd gnd pinv_32
Xwl_driver_inv_en9 en en_bar_9 vdd gnd pinv_33
Xwl_driver_nand9 en_bar_9 in_9 wl_bar_9 vdd gnd pnand2_6
Xwl_driver_inv9 wl_bar_9 wl_9 vdd gnd pinv_32
Xwl_driver_inv_en10 en en_bar_10 vdd gnd pinv_33
Xwl_driver_nand10 en_bar_10 in_10 wl_bar_10 vdd gnd pnand2_6
Xwl_driver_inv10 wl_bar_10 wl_10 vdd gnd pinv_32
Xwl_driver_inv_en11 en en_bar_11 vdd gnd pinv_33
Xwl_driver_nand11 en_bar_11 in_11 wl_bar_11 vdd gnd pnand2_6
Xwl_driver_inv11 wl_bar_11 wl_11 vdd gnd pinv_32
Xwl_driver_inv_en12 en en_bar_12 vdd gnd pinv_33
Xwl_driver_nand12 en_bar_12 in_12 wl_bar_12 vdd gnd pnand2_6
Xwl_driver_inv12 wl_bar_12 wl_12 vdd gnd pinv_32
Xwl_driver_inv_en13 en en_bar_13 vdd gnd pinv_33
Xwl_driver_nand13 en_bar_13 in_13 wl_bar_13 vdd gnd pnand2_6
Xwl_driver_inv13 wl_bar_13 wl_13 vdd gnd pinv_32
Xwl_driver_inv_en14 en en_bar_14 vdd gnd pinv_33
Xwl_driver_nand14 en_bar_14 in_14 wl_bar_14 vdd gnd pnand2_6
Xwl_driver_inv14 wl_bar_14 wl_14 vdd gnd pinv_32
Xwl_driver_inv_en15 en en_bar_15 vdd gnd pinv_33
Xwl_driver_nand15 en_bar_15 in_15 wl_bar_15 vdd gnd pnand2_6
Xwl_driver_inv15 wl_bar_15 wl_15 vdd gnd pinv_32
.ENDS wordline_driver
.SUBCKT pinv_34 A Z vdd gnd
Mpinv_pmos Z A vdd vdd p m=1 w=1.6u l=0.4u pd=4.0u ps=4.0u as=1.6p ad=1.6p
Mpinv_nmos Z A gnd gnd n m=1 w=0.8u l=0.4u pd=2.4000000000000004u ps=2.4000000000000004u as=0.8p ad=0.8p
.ENDS pinv_34
.SUBCKT bank dout0_0 dout0_1 dout2_0 dout2_1 din0_0 din0_1 din1_0 din1_1 addr0_0 addr0_1 addr0_2 addr0_3 addr1_0 addr1_1 addr1_2 addr1_3 addr2_0 addr2_1 addr2_2 addr2_3 s_en0 s_en2 w_en0 w_en1 clk_buf_bar0 clk_buf0 clk_buf_bar1 clk_buf1 clk_buf_bar2 clk_buf2 vdd gnd
Xbitcell_array bl0_0 br0_0 bl1_0 br1_0 bl2_0 br2_0 bl0_1 br0_1 bl1_1 br1_1 bl2_1 br2_1 wl0_0 wl1_0 wl2_0 wl0_1 wl1_1 wl2_1 wl0_2 wl1_2 wl2_2 wl0_3 wl1_3 wl2_3 wl0_4 wl1_4 wl2_4 wl0_5 wl1_5 wl2_5 wl0_6 wl1_6 wl2_6 wl0_7 wl1_7 wl2_7 wl0_8 wl1_8 wl2_8 wl0_9 wl1_9 wl2_9 wl0_10 wl1_10 wl2_10 wl0_11 wl1_11 wl2_11 wl0_12 wl1_12 wl2_12 wl0_13 wl1_13 wl2_13 wl0_14 wl1_14 wl2_14 wl0_15 wl1_15 wl2_15 vdd gnd bitcell_array_16x2_1
Xprecharge_array0 bl0_0 br0_0 bl0_1 br0_1 clk_buf_bar0 vdd precharge_array_1
Xprecharge_array2 bl2_0 br2_0 bl2_1 br2_1 clk_buf_bar2 vdd precharge_array_2
Xsense_amp_array0 dout0_0 bl0_0 br0_0 dout0_1 bl0_1 br0_1 s_en0 vdd gnd sense_amp_array
Xsense_amp_array2 dout2_0 bl2_0 br2_0 dout2_1 bl2_1 br2_1 s_en2 vdd gnd sense_amp_array
Xwrite_driver_array0 din0_0 din0_1 bl0_0 br0_0 bl0_1 br0_1 w_en0 vdd gnd write_driver_array
Xwrite_driver_array1 din1_0 din1_1 bl1_0 br1_0 bl1_1 br1_1 w_en1 vdd gnd write_driver_array
Xrow_decoder0 addr0_0 addr0_1 addr0_2 addr0_3 dec_out0_0 dec_out0_1 dec_out0_2 dec_out0_3 dec_out0_4 dec_out0_5 dec_out0_6 dec_out0_7 dec_out0_8 dec_out0_9 dec_out0_10 dec_out0_11 dec_out0_12 dec_out0_13 dec_out0_14 dec_out0_15 vdd gnd hierarchical_decoder_16rows
Xrow_decoder1 addr1_0 addr1_1 addr1_2 addr1_3 dec_out1_0 dec_out1_1 dec_out1_2 dec_out1_3 dec_out1_4 dec_out1_5 dec_out1_6 dec_out1_7 dec_out1_8 dec_out1_9 dec_out1_10 dec_out1_11 dec_out1_12 dec_out1_13 dec_out1_14 dec_out1_15 vdd gnd hierarchical_decoder_16rows
Xrow_decoder2 addr2_0 addr2_1 addr2_2 addr2_3 dec_out2_0 dec_out2_1 dec_out2_2 dec_out2_3 dec_out2_4 dec_out2_5 dec_out2_6 dec_out2_7 dec_out2_8 dec_out2_9 dec_out2_10 dec_out2_11 dec_out2_12 dec_out2_13 dec_out2_14 dec_out2_15 vdd gnd hierarchical_decoder_16rows
Xwordline_driver0 dec_out0_0 dec_out0_1 dec_out0_2 dec_out0_3 dec_out0_4 dec_out0_5 dec_out0_6 dec_out0_7 dec_out0_8 dec_out0_9 dec_out0_10 dec_out0_11 dec_out0_12 dec_out0_13 dec_out0_14 dec_out0_15 wl0_0 wl0_1 wl0_2 wl0_3 wl0_4 wl0_5 wl0_6 wl0_7 wl0_8 wl0_9 wl0_10 wl0_11 wl0_12 wl0_13 wl0_14 wl0_15 clk_buf0 vdd gnd wordline_driver
Xwordline_driver1 dec_out1_0 dec_out1_1 dec_out1_2 dec_out1_3 dec_out1_4 dec_out1_5 dec_out1_6 dec_out1_7 dec_out1_8 dec_out1_9 dec_out1_10 dec_out1_11 dec_out1_12 dec_out1_13 dec_out1_14 dec_out1_15 wl1_0 wl1_1 wl1_2 wl1_3 wl1_4 wl1_5 wl1_6 wl1_7 wl1_8 wl1_9 wl1_10 wl1_11 wl1_12 wl1_13 wl1_14 wl1_15 clk_buf1 vdd gnd wordline_driver
Xwordline_driver2 dec_out2_0 dec_out2_1 dec_out2_2 dec_out2_3 dec_out2_4 dec_out2_5 dec_out2_6 dec_out2_7 dec_out2_8 dec_out2_9 dec_out2_10 dec_out2_11 dec_out2_12 dec_out2_13 dec_out2_14 dec_out2_15 wl2_0 wl2_1 wl2_2 wl2_3 wl2_4 wl2_5 wl2_6 wl2_7 wl2_8 wl2_9 wl2_10 wl2_11 wl2_12 wl2_13 wl2_14 wl2_15 clk_buf2 vdd gnd wordline_driver
.ENDS bank
.SUBCKT sram_2_16_scn4m_subm DIN0[0] DIN0[1] DIN1[0] DIN1[1] ADDR0[0] ADDR0[1] ADDR0[2] ADDR0[3] ADDR1[0] ADDR1[1] ADDR1[2] ADDR1[3] ADDR2[0] ADDR2[1] ADDR2[2] ADDR2[3] csb0 csb1 csb2 web0 clk0 clk1 clk2 DOUT0[0] DOUT0[1] DOUT2[0] DOUT2[1] vdd gnd
Xbank0 DOUT0[0] DOUT0[1] DOUT2[0] DOUT2[1] BANK_DIN0[0] BANK_DIN0[1] BANK_DIN1[0] BANK_DIN1[1] A0[0] A0[1] A0[2] A0[3] A1[0] A1[1] A1[2] A1[3] A2[0] A2[1] A2[2] A2[3] s_en0 s_en2 w_en0 w_en1 clk_buf_bar0 clk_buf0 clk_buf_bar1 clk_buf1 clk_buf_bar2 clk_buf2 vdd gnd bank
Xcontrol0 csb0 web0 clk0 s_en0 w_en0 clk_buf_bar0 clk_buf0 vdd gnd control_logic_rw
Xcontrol1 csb1 clk1 w_en1 clk_buf_bar1 clk_buf1 vdd gnd control_logic_w
Xcontrol2 csb2 clk2 s_en2 clk_buf_bar2 clk_buf2 vdd gnd control_logic_r
Xrow_address0 ADDR0[0] ADDR0[1] ADDR0[2] ADDR0[3] A0[0] A0[1] A0[2] A0[3] clk_buf0 vdd gnd row_addr_dff
Xrow_address1 ADDR1[0] ADDR1[1] ADDR1[2] ADDR1[3] A1[0] A1[1] A1[2] A1[3] clk_buf1 vdd gnd row_addr_dff
Xrow_address2 ADDR2[0] ADDR2[1] ADDR2[2] ADDR2[3] A2[0] A2[1] A2[2] A2[3] clk_buf2 vdd gnd row_addr_dff
Xdata_dff0 DIN0[0] DIN0[1] BANK_DIN0[0] BANK_DIN0[1] clk_buf0 vdd gnd data_dff
Xdata_dff1 DIN1[0] DIN1[1] BANK_DIN1[0] BANK_DIN1[1] clk_buf1 vdd gnd data_dff
.ENDS sram_2_16_scn4m_subm

View File

@ -0,0 +1,47 @@
// OpenRAM SRAM model
// Words: 16
// Word size: 2
module sram_2_16_scn4m_subm(DATA,ADDR,CSb,WEb,OEb,clk);
parameter DATA_WIDTH = 2 ;
parameter ADDR_WIDTH = 4 ;
parameter RAM_DEPTH = 1 << ADDR_WIDTH;
parameter DELAY = 3 ;
inout [DATA_WIDTH-1:0] DATA;
input [ADDR_WIDTH-1:0] ADDR;
input CSb; // active low chip select
input WEb; // active low write control
input OEb; // active output enable
input clk; // clock
reg [DATA_WIDTH-1:0] data_out ;
reg [DATA_WIDTH-1:0] mem [0:RAM_DEPTH-1];
// Tri-State Buffer control
// output : When WEb = 1, oeb = 0, csb = 0
assign DATA = (!CSb && !OEb && WEb) ? data_out : 2'bz;
// Memory Write Block
// Write Operation : When WEb = 0, CSb = 0
always @ (posedge clk)
begin : MEM_WRITE
if ( !CSb && !WEb ) begin
mem[ADDR] = DATA;
$display($time," Writing %m ABUS=%b DATA=%b",ADDR,DATA);
end
end
// Memory Read Block
// Read Operation : When WEb = 1, CSb = 0
always @ (posedge clk)
begin : MEM_READ
if (!CSb && WEb) begin
data_out <= #(DELAY) mem[ADDR];
$display($time," Reading %m ABUS=%b DATA=%b",ADDR,mem[ADDR]);
end
end
endmodule

View File

@ -0,0 +1,321 @@
library (sram_2_16_scn4m_subm_TT_3p3V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
current_unit : "1mA" ;
resistance_unit : "1kohm" ;
capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(OC){
process : 1.0 ;
voltage : 3.3 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
output_threshold_pct_fall : 50.0 ;
input_threshold_pct_rise : 50.0 ;
output_threshold_pct_rise : 50.0 ;
slew_lower_threshold_pct_fall : 10.0 ;
slew_upper_threshold_pct_fall : 90.0 ;
slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ;
default_inout_pin_cap : 1.0 ;
default_output_pin_cap : 0.0 ;
default_max_transition : 0.5 ;
default_fanout_load : 1.0 ;
default_max_fanout : 4.0 ;
default_connection_class : universal ;
lu_table_template(CELL_TABLE){
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.0125, 0.05, 0.4");
index_2("0.0125, 0.05, 0.4");
}
default_operating_conditions : OC;
type (DATA){
base_type : array;
data_type : bit;
bit_width : 2;
bit_from : 0;
bit_to : 1;
}
type (ADDR){
base_type : array;
data_type : bit;
bit_width : 4;
bit_from : 0;
bit_to : 3;
}
cell (sram_2_16_scn4m_subm){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 69426.85;
leakage_power () {
when : "CSb0";
value : 0.000179;
}
cell_leakage_power : 0;
bus(DIN0){
bus_type : DATA;
direction : input;
capacitance : 9.8242;
memory_write(){
address : ADDR0;
clocked_on : clk0;
}
pin(DIN0[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(DOUT0){
bus_type : DATA;
direction : output;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
memory_read(){
address : ADDR0;
}
pin(DOUT0[1:0]){
timing(){
timing_sense : non_unate;
related_pin : "clk0";
timing_type : rising_edge;
cell_rise(CELL_TABLE) {
values("0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268");
}
cell_fall(CELL_TABLE) {
values("0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268");
}
rise_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004");
}
fall_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004");
}
}
}
}
bus(ADDR0){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR0[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
pin(CSb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(WEb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(clk0){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb0 & clk0 & !WEb0";
rise_power(scalar){
values("2.46222038320038");
}
fall_power(scalar){
values("2.46222038320038");
}
}
internal_power(){
when : "!CSb0 & !clk0 & WEb0";
rise_power(scalar){
values("2.46222038320038");
}
fall_power(scalar){
values("2.46222038320038");
}
}
internal_power(){
when : "CSb0";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk0;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk0;
rise_constraint(scalar) {
values("0");
}
fall_constraint(scalar) {
values("0");
}
}
}
}
}

View File

@ -0,0 +1,321 @@
library (sram_2_16_scn4m_subm_TT_5V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
current_unit : "1mA" ;
resistance_unit : "1kohm" ;
capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(OC){
process : 1.0 ;
voltage : 5 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
output_threshold_pct_fall : 50.0 ;
input_threshold_pct_rise : 50.0 ;
output_threshold_pct_rise : 50.0 ;
slew_lower_threshold_pct_fall : 10.0 ;
slew_upper_threshold_pct_fall : 90.0 ;
slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ;
default_inout_pin_cap : 1.0 ;
default_output_pin_cap : 0.0 ;
default_max_transition : 0.5 ;
default_fanout_load : 1.0 ;
default_max_fanout : 4.0 ;
default_connection_class : universal ;
lu_table_template(CELL_TABLE){
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.0125, 0.05, 0.4");
index_2("0.0125, 0.05, 0.4");
}
default_operating_conditions : OC;
type (DATA){
base_type : array;
data_type : bit;
bit_width : 2;
bit_from : 0;
bit_to : 1;
}
type (ADDR){
base_type : array;
data_type : bit;
bit_width : 4;
bit_from : 0;
bit_to : 3;
}
cell (sram_2_16_scn4m_subm){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 68347.21;
leakage_power () {
when : "CSb0";
value : 0.000179;
}
cell_leakage_power : 0;
bus(DIN0){
bus_type : DATA;
direction : input;
capacitance : 9.8242;
memory_write(){
address : ADDR0;
clocked_on : clk0;
}
pin(DIN0[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(DOUT0){
bus_type : DATA;
direction : output;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
memory_read(){
address : ADDR0;
}
pin(DOUT0[1:0]){
timing(){
timing_sense : non_unate;
related_pin : "clk0";
timing_type : rising_edge;
cell_rise(CELL_TABLE) {
values("0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268");
}
cell_fall(CELL_TABLE) {
values("0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268",\
"0.268, 0.268, 0.268");
}
rise_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004");
}
fall_transition(CELL_TABLE) {
values("0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004",\
"0.004, 0.004, 0.004");
}
}
}
}
bus(ADDR0){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR0[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
pin(CSb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(WEb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(clk0){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb0 & clk0 & !WEb0";
rise_power(scalar){
values("2.46222038320038");
}
fall_power(scalar){
values("2.46222038320038");
}
}
internal_power(){
when : "!CSb0 & !clk0 & WEb0";
rise_power(scalar){
values("2.46222038320038");
}
fall_power(scalar){
values("2.46222038320038");
}
}
internal_power(){
when : "CSb0";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk0;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk0;
rise_constraint(scalar) {
values("0");
}
fall_constraint(scalar) {
values("0");
}
}
}
}
}

View File

@ -0,0 +1,625 @@
library (sram_2_16_scn4m_subm_TT_5p0V_25C_lib){
delay_model : "table_lookup";
time_unit : "1ns" ;
voltage_unit : "1v" ;
current_unit : "1mA" ;
resistance_unit : "1kohm" ;
capacitive_load_unit(1 ,fF) ;
leakage_power_unit : "1mW" ;
pulling_resistance_unit :"1kohm" ;
operating_conditions(OC){
process : 1.0 ;
voltage : 5.0 ;
temperature : 25;
}
input_threshold_pct_fall : 50.0 ;
output_threshold_pct_fall : 50.0 ;
input_threshold_pct_rise : 50.0 ;
output_threshold_pct_rise : 50.0 ;
slew_lower_threshold_pct_fall : 10.0 ;
slew_upper_threshold_pct_fall : 90.0 ;
slew_lower_threshold_pct_rise : 10.0 ;
slew_upper_threshold_pct_rise : 90.0 ;
nom_voltage : 5.0;
nom_temperature : 25;
nom_process : 1.0;
default_cell_leakage_power : 0.0 ;
default_leakage_power_density : 0.0 ;
default_input_pin_cap : 1.0 ;
default_inout_pin_cap : 1.0 ;
default_output_pin_cap : 0.0 ;
default_max_transition : 0.5 ;
default_fanout_load : 1.0 ;
default_max_fanout : 4.0 ;
default_connection_class : universal ;
lu_table_template(CELL_TABLE){
variable_1 : input_net_transition;
variable_2 : total_output_net_capacitance;
index_1("0.0125, 0.05, 0.4");
index_2("2.45605, 9.8242, 78.5936");
}
lu_table_template(CONSTRAINT_TABLE){
variable_1 : related_pin_transition;
variable_2 : constrained_pin_transition;
index_1("0.0125, 0.05, 0.4");
index_2("0.0125, 0.05, 0.4");
}
default_operating_conditions : OC;
type (DATA){
base_type : array;
data_type : bit;
bit_width : 2;
bit_from : 0;
bit_to : 1;
}
type (ADDR){
base_type : array;
data_type : bit;
bit_width : 4;
bit_from : 0;
bit_to : 3;
}
cell (sram_2_16_scn4m_subm){
memory(){
type : ram;
address_width : 4;
word_width : 2;
}
interface_timing : true;
dont_use : true;
map_only : true;
dont_touch : true;
area : 0;
leakage_power () {
when : "CSb0 & CSb1 & CSb2";
value : 0.000436;
}
cell_leakage_power : 0;
bus(DIN0){
bus_type : DATA;
direction : input;
capacitance : 9.8242;
memory_write(){
address : ADDR0;
clocked_on : clk0;
}
pin(DIN0[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(DOUT0){
bus_type : DATA;
direction : output;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
memory_read(){
address : ADDR0;
}
pin(DOUT0[1:0]){
timing(){
timing_sense : non_unate;
related_pin : "clk0";
timing_type : rising_edge;
cell_rise(CELL_TABLE) {
values("0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079");
}
cell_fall(CELL_TABLE) {
values("0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079");
}
rise_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(ADDR0){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR0[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
pin(CSb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(WEb0){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009",\
"0.009, 0.009, 0.009");
}
}
timing(){
timing_type : hold_rising;
related_pin : "clk0";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
pin(clk0){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb0 & clk0 & !WEb0";
rise_power(scalar){
values("15.41143495605");
}
fall_power(scalar){
values("15.41143495605");
}
}
internal_power(){
when : "!CSb0 & !clk0 & WEb0";
rise_power(scalar){
values("15.41143495605");
}
fall_power(scalar){
values("15.41143495605");
}
}
internal_power(){
when : "CSb0";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk0;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk0;
rise_constraint(scalar) {
values("0");
}
fall_constraint(scalar) {
values("0");
}
}
}
bus(DIN1){
bus_type : DATA;
direction : input;
capacitance : 9.8242;
memory_write(){
address : ADDR1;
clocked_on : clk1;
}
pin(DIN1[1:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk1";
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 : "clk1";
rise_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_constraint(CONSTRAINT_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(ADDR1){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR1[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk1";
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 : "clk1";
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(CSb1){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk1";
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 : "clk1";
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(clk1){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb1 & clk1";
rise_power(scalar){
values("15.41143495605");
}
fall_power(scalar){
values("15.41143495605");
}
}
internal_power(){
when : "CSb1";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk1;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk1;
rise_constraint(scalar) {
values("0");
}
fall_constraint(scalar) {
values("0");
}
}
}
bus(DOUT2){
bus_type : DATA;
direction : output;
max_capacitance : 78.5936;
min_capacitance : 2.45605;
memory_read(){
address : ADDR2;
}
pin(DOUT2[1:0]){
timing(){
timing_sense : non_unate;
related_pin : "clk2";
timing_type : rising_edge;
cell_rise(CELL_TABLE) {
values("0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079");
}
cell_fall(CELL_TABLE) {
values("0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079",\
"0.079, 0.079, 0.079");
}
rise_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
fall_transition(CELL_TABLE) {
values("0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001",\
"0.001, 0.001, 0.001");
}
}
}
}
bus(ADDR2){
bus_type : ADDR;
direction : input;
capacitance : 9.8242;
max_transition : 0.4;
pin(ADDR2[3:0]){
timing(){
timing_type : setup_rising;
related_pin : "clk2";
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 : "clk2";
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(CSb2){
direction : input;
capacitance : 9.8242;
timing(){
timing_type : setup_rising;
related_pin : "clk2";
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 : "clk2";
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(clk2){
clock : true;
direction : input;
capacitance : 9.8242;
internal_power(){
when : "!CSb2 & !clk2";
rise_power(scalar){
values("15.41143495605");
}
fall_power(scalar){
values("15.41143495605");
}
}
internal_power(){
when : "CSb2";
rise_power(scalar){
values("0");
}
fall_power(scalar){
values("0");
}
}
timing(){
timing_type :"min_pulse_width";
related_pin : clk2;
rise_constraint(scalar) {
values("0.0");
}
fall_constraint(scalar) {
values("0.0");
}
}
timing(){
timing_type :"minimum_period";
related_pin : clk2;
rise_constraint(scalar) {
values("0");
}
fall_constraint(scalar) {
values("0");
}
}
}
}
}

View File

@ -0,0 +1,25 @@
/* Style the button that is used to open and close the collapsible content */
.collapsible {
background-color: #eee;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
/* Add a background color to the button if it is clicked on (add the .active class with JS), and when you move the mouse over it (hover) */
.active, .collapsible:hover {
background-color: #ccc;
}
/* Style the collapsible content. Note: hidden by default */
.content {
padding: 0 18px;
display: none;
overflow: hidden;
background-color: #f1f1f1;
}

View File

@ -0,0 +1,42 @@
</ul>
<link rel="stylesheet" href="static/index.css">
<button class="collapsible">files</button>
<div class="content">
{% for root, dir, files in os.walk(filedir) %}
{% if root != filedir %}
<button class="collapsible">{{ root }}</button>
<div class="content">
{% for f in files %}
<button class="collapsible">{{ f }}</button>
<div class="content">
<a href="{{ root }}/{{ f }}">link</a>
</div>
{% endfor %}
</div>
{% endif %}
{% endfor %}
</div>
<script type="text/javascript">
var coll = document.getElementsByClassName("collapsible");
var i;
for (i = 0; i < coll.length; i++) {
coll[i].addEventListener("click", function() {
this.classList.toggle("active");
var content = this.nextElementSibling;
if (content.style.display === "block") {
content.style.display = "none";
} else {
content.style.display = "block";
}
});
}
</script>
</ul>

View File

@ -1,12 +1,18 @@
from flask_table import * from flask_table import *
class timing_and_current_data(Table): class timing_and_current_data(Table):
"""
Set up timing and current table columns and title information
"""
parameter = Col('Parameter') parameter = Col('Parameter')
min = Col('Min') min = Col('Min')
max = Col('Max') max = Col('Max')
units = Col('Units') units = Col('Units')
class timing_and_current_data_item(object): class timing_and_current_data_item(object):
"""
Define timing and current data row element
"""
def __init__(self, parameter, min, max, units): def __init__(self, parameter, min, max, units):
self.parameter = parameter self.parameter = parameter
self.min = min self.min = min

View File

@ -0,0 +1,827 @@
#!/usr/bin/python
# The MIT License (MIT)
#
# Copyright (c) 2011-2016 Aliaksei Chapyzhenka
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
# Translated to Python from original file:
# https://github.com/drom/wavedrom/blob/master/src/WaveDrom.js
#
import sys
import json
import math
import waveskin
font_width = 7
lane = {
"xs" : 20, # tmpgraphlane0.width
"ys" : 20, # tmpgraphlane0.height
"xg" : 120, # tmpgraphlane0.x
"yg" : 0, # head gap
"yh0" : 0, # head gap title
"yh1" : 0, # head gap
"yf0" : 0, # foot gap
"yf1" : 0, # foot gap
"y0" : 5, # tmpgraphlane0.y
"yo" : 30, # tmpgraphlane1.y - y0
"tgo" : -10, # tmptextlane0.x - xg
"ym" : 15, # tmptextlane0.y - y0
"xlabel" : 6, # tmptextlabel.x - xg
"xmax" : 1,
"scale" : 1,
"head" : {},
"foot" : {}
}
def genBrick (texts, extra, times) :
R = []
if len( texts ) == 4 :
for j in range( times ):
R.append(texts[0])
for i in range ( extra ):
R.append(texts[1])
R.append(texts[2])
for i in range ( extra ):
R.append(texts[3])
return R
if len( texts ) == 1 :
texts.append(texts[0])
R.append(texts[0])
for i in range (times * (2 * (extra + 1)) - 1) :
R.append(texts[1])
return R
def genFirstWaveBrick (text, extra, times) :
pattern = {
'p': ['pclk', '111', 'nclk', '000'],
'n': ['nclk', '000', 'pclk', '111'],
'P': ['Pclk', '111', 'nclk', '000'],
'N': ['Nclk', '000', 'pclk', '111'],
'l': ['000'],
'L': ['000'],
'0': ['000'],
'h': ['111'],
'H': ['111'],
'1': ['111'],
'=': ['vvv-2'],
'2': ['vvv-2'],
'3': ['vvv-3'],
'4': ['vvv-4'],
'5': ['vvv-5'],
'd': ['ddd'],
'u': ['uuu'],
'z': ['zzz']
}
return genBrick( pattern.get( text, ['xxx'] ) , extra, times );
def genWaveBrick (text, extra, times) :
x1 = {'p':'pclk', 'n':'nclk', 'P':'Pclk', 'N':'Nclk', 'h':'pclk', 'l':'nclk', 'H':'Pclk', 'L':'Nclk'}
x2 = {'0':'0', '1':'1', 'x':'x', 'd':'d', 'u':'u', 'z':'z', '=':'v', '2':'v', '3':'v', '4':'v', '5':'v' }
x3 = {'0': '', '1': '', 'x': '', 'd': '', 'u': '', 'z': '', '=':'-2', '2':'-2', '3':'-3', '4':'-4', '5':'-5'}
y1 = {
'p':'0', 'n':'1',
'P':'0', 'N':'1',
'h':'1', 'l':'0',
'H':'1', 'L':'0',
'0':'0', '1':'1', 'x':'x', 'd':'d', 'u':'u', 'z':'z', '=':'v', '2':'v', '3':'v', '4':'v', '5':'v'}
y2 = {
'p': '', 'n': '',
'P': '', 'N': '',
'h': '', 'l': '',
'H': '', 'L': '',
'0': '', '1': '', 'x': '', 'd': '', 'u': '', 'z': '', '=':'-2', '2':'-2', '3':'-3', '4':'-4', '5':'-5'}
x4 = {
'p': '111', 'n': '000',
'P': '111', 'N': '000',
'h': '111', 'l': '000',
'H': '111', 'L': '000',
'0': '000', '1': '111', 'x': 'xxx', 'd': 'ddd', 'u': 'uuu', 'z': 'zzz',
'=': 'vvv-2', '2': 'vvv-2', '3': 'vvv-3', '4': 'vvv-4', '5': 'vvv-5'}
x5 = {'p':'nclk', 'n':'pclk', 'P':'nclk', 'N':'pclk'}
x6 = {'p': '000', 'n': '111', 'P': '000', 'N': '111'}
xclude = {'hp':'111', 'Hp':'111', 'ln': '000', 'Ln': '000', 'nh':'111', 'Nh':'111', 'pl': '000', 'Pl':'000'}
#atext = text.split()
atext = text
tmp0 = x4.get(atext[1])
tmp1 = x1.get(atext[1])
if tmp1 == None :
tmp2 = x2.get(atext[1])
if tmp2 == None :
# unknown
return genBrick(['xxx'], extra, times)
else :
tmp3 = y1.get(atext[0])
if tmp3 == None :
# unknown
return genBrick(['xxx'], extra, times)
# soft curves
return genBrick([tmp3 + 'm' + tmp2 + y2[atext[0]] + x3[atext[1]], tmp0], extra, times)
else :
tmp4 = xclude.get(text)
if tmp4 != None :
tmp1 = tmp4
# sharp curves
tmp2 = x5.get(atext[1])
if tmp2 == None :
# hlHL
return genBrick([tmp1, tmp0], extra, times)
else :
# pnPN
return genBrick([tmp1, tmp0, tmp2, x6[atext[1]]], extra, times)
def parseWaveLane (text, extra) :
R = []
Stack = text
Next = Stack[0]
Stack = Stack[1:]
Repeats = 1
while len(Stack) and ( Stack[0] == '.' or Stack[0] == '|' ): # repeaters parser
Stack=Stack[1:]
Repeats += 1
R.extend(genFirstWaveBrick(Next, extra, Repeats))
while len(Stack) :
Top = Next
Next = Stack[0]
Stack = Stack[1:]
Repeats = 1
while len(Stack) and ( Stack[0] == '.' or Stack[0] == '|' ) : # repeaters parser
Stack=Stack[1:]
Repeats += 1
R.extend(genWaveBrick((Top + Next), extra, Repeats))
for i in range( lane['phase'] ):
R = R[1:]
return R
def parseWaveLanes (sig) :
def data_extract (e) :
tmp = e.get('data')
if tmp == None : return None
if is_type_str (tmp) : tmp=tmp.split()
return tmp
content = []
for sigx in sig :
lane['period'] = sigx.get('period',1)
lane['phase'] = int( sigx.get('phase',0 ) * 2 )
sub_content=[]
sub_content.append( [sigx.get('name',' '), sigx.get('phase',0 ) ] )
sub_content.append( parseWaveLane( sigx['wave'], int(lane['period'] * lane['hscale'] - 1 ) ) if sigx.get('wave') else None )
sub_content.append( data_extract(sigx) )
content.append(sub_content)
return content
def findLaneMarkers (lanetext) :
lcount = 0
gcount = 0
ret = []
for i in range( len( lanetext ) ) :
if lanetext[i] == 'vvv-2' or lanetext[i] == 'vvv-3' or lanetext[i] == 'vvv-4' or lanetext[i] == 'vvv-5' :
lcount += 1
else :
if lcount !=0 :
ret.append(gcount - ((lcount + 1) / 2))
lcount = 0
gcount += 1
if lcount != 0 :
ret.append(gcount - ((lcount + 1) / 2))
return ret
def renderWaveLane (root, content, index) :
xmax = 0
xgmax = 0
glengths = []
svgns = 'http://www.w3.org/2000/svg'
xlinkns = 'http://www.w3.org/1999/xlink'
xmlns = 'http://www.w3.org/XML/1998/namespace'
for j in range( len(content) ):
name = content[j][0][0]
if name : # check name
g = [
'g',
{
'id': 'wavelane_' + str(j) + '_' + str(index),
'transform': 'translate(0,' + str(lane['y0'] + j * lane['yo']) + ')'
}
]
root.append(g)
title = [
'text',
{
'x': lane['tgo'],
'y': lane['ym'],
'class': 'info',
'text-anchor': 'end',
'xml:space': 'preserve'
},
['tspan', name]
]
g.append(title)
glengths.append( len(name) * font_width + font_width )
xoffset = content[j][0][1]
xoffset = math.ceil(2 * xoffset) - 2 * xoffset if xoffset > 0 else -2 * xoffset
gg = [
'g',
{
'id': 'wavelane_draw_' + str(j) + '_' + str(index),
'transform': 'translate(' + str( xoffset * lane['xs'] ) + ', 0)'
}
]
g.append(gg)
if content[j][1] :
for i in range( len(content[j][1]) ) :
b = [
'use',
{
#'id': 'use_' + str(i) + '_' + str(j) + '_' + str(index),
'xmlns:xlink':xlinkns,
'xlink:href': '#' + str( content[j][1][i] ),
'transform': 'translate(' + str(i * lane['xs']) + ')'
}
]
gg.append(b)
if content[j][2] and len(content[j][2]) :
labels = findLaneMarkers(content[j][1])
if len(labels) != 0 :
for k in range( len(labels) ) :
if content[j][2] and k < len(content[j][2]) :
title = [
'text',
{
'x': int(labels[k]) * lane['xs'] + lane['xlabel'],
'y': lane['ym'],
'text-anchor': 'middle',
'xml:space': 'preserve'
},
['tspan',content[j][2][k]]
]
gg.append(title)
if len(content[j][1]) > xmax :
xmax = len(content[j][1])
lane['xmax'] = xmax
lane['xg'] = xgmax + 20
return glengths
def renderMarks (root, content, index) :
def captext ( g, cxt, anchor, y ) :
if cxt.get(anchor) and cxt[anchor].get('text') :
tmark = [
'text',
{
'x': float( cxt['xmax'] ) * float( cxt['xs'] ) / 2,
'y': y,
'text-anchor': 'middle',
'fill': '#000',
'xml:space': 'preserve'
}, cxt[anchor]['text']
]
g.append(tmark)
def ticktock ( g, cxt, ref1, ref2, x, dx, y, length ) :
L = []
if cxt.get(ref1) == None or cxt[ref1].get(ref2) == None :
return
val = cxt[ref1][ref2]
if is_type_str( val ) :
val = val.split()
elif type( val ) is int :
offset = val
val = []
for i in range ( length ) :
val.append(i + offset)
if type( val ) is list :
if len( val ) == 0 :
return
elif len( val ) == 1 :
offset = val[0]
if is_type_str(offset) :
L = val
else :
for i in range ( length ) :
L[i] = i + offset
elif len( val ) == 2:
offset = int(val[0])
step = int(val[1])
tmp = val[1].split('.')
if len( tmp ) == 2 :
dp = len( tmp[1] )
if is_type_str(offset) or is_type_str(step) :
L = val
else :
offset = step * offset
for i in range( length ) :
L[i] = "{0:.",dp,"f}".format(step * i + offset)
else :
L = val
else :
return
for i in range( length ) :
tmp = L[i]
tmark = [
'text',
{
'x': i * dx + x,
'y': y,
'text-anchor': 'middle',
'class': 'muted',
'xml:space': 'preserve'
}, str(tmp)
]
g.append(tmark)
mstep = 2 * int(lane['hscale'])
mmstep = mstep * lane['xs']
marks = int( lane['xmax'] / mstep )
gy = len( content ) * int(lane['yo'])
g = ['g', {'id': 'gmarks_' + str(index)}]
root.insert(0,g)
for i in range( marks + 1):
gg = [
'path',
{
'id': 'gmark_' + str(i) + '_' + str(index),
'd': 'm ' + str(i * mmstep) + ',' + '0' + ' 0,' + str(gy),
'style': 'stroke:#888;stroke-width:0.5;stroke-dasharray:1,3'
}
]
g.append( gg )
captext(g, lane, 'head', -33 if lane['yh0'] else -13 )
captext(g, lane, 'foot', gy + ( 45 if lane['yf0'] else 25 ) )
ticktock( g, lane, 'head', 'tick', 0, mmstep, -5, marks + 1)
ticktock( g, lane, 'head', 'tock', mmstep / 2, mmstep, -5, marks)
ticktock( g, lane, 'foot', 'tick', 0, mmstep, gy + 15, marks + 1)
ticktock( g, lane, 'foot', 'tock', mmstep / 2, mmstep, gy + 15, marks)
def renderArcs (root, source, index, top) :
Stack = []
Edge = {'words': [], 'frm': 0, 'shape': '', 'to': 0, 'label': ''}
Events = {}
svgns = 'http://www.w3.org/2000/svg'
xmlns = 'http://www.w3.org/XML/1998/namespace'
if source :
for i in range (len (source) ) :
lane['period'] = source[i].get('period',1)
lane['phase'] = int( source[i].get('phase',0 ) * 2 )
text = source[i].get('node')
if text:
Stack = text
pos = 0
while len( Stack ) :
eventname = Stack[0]
Stack=Stack[1:]
if eventname != '.' :
Events[eventname] = {
'x' : str( int( float( lane['xs'] ) * (2 * pos * lane['period'] * lane['hscale'] - lane['phase'] ) + float( lane['xlabel'] ) ) ),
'y' : str( int( i * lane['yo'] + lane['y0'] + float( lane['ys'] ) * 0.5 ) )
}
pos += 1
gg = [ 'g', { 'id' : 'wavearcs_' + str( index ) } ]
root.append(gg)
if top.get('edge') :
for i in range( len ( top['edge'] ) ) :
Edge['words'] = top['edge'][i].split()
Edge['label'] = top['edge'][i][len(Edge['words'][0]):]
Edge['label'] = Edge['label'][1:]
Edge['frm'] = Edge['words'][0][0]
Edge['to'] = Edge['words'][0][-1]
Edge['shape'] = Edge['words'][0][1:-1]
frm = Events[Edge['frm']]
to = Events[Edge['to']]
gmark = [
'path',
{
'id': 'gmark_' + Edge['frm'] + '_' + Edge['to'],
'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + to['x'] + ',' + to['y'],
'style': 'fill:none;stroke:#00F;stroke-width:1'
}
]
gg.append(gmark)
dx = float( to['x'] ) - float( frm['x'] )
dy = float( to['y'] ) - float( frm['y'] )
lx = (float(frm['x']) + float(to['x'])) / 2
ly = (float(frm['y']) + float(to['y'])) / 2
pattern = {
'~' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) },
'-~' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) },
'~-' : {'d': 'M ' + frm['x'] + ',' + frm['y'] + ' c ' + '0' + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy) },
'-|' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)},
'|-' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' 0,' + str(dy) + ' ' + str(dx) + ',0'},
'-|-' : {'d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'},
'->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none'},
'~>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)},
'-~>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)},
'~->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + '0' + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)},
'-|>' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)},
'|->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' 0,' + str(dy) + ' ' + str(dx) + ',0'},
'-|->' : {'style': 'marker-end:url(#arrowhead);stroke:#0041c4;stroke-width:1;fill:none', 'd': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'},
'<->' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none'},
'<~>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(0.3 * dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)},
'<-~>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'M ' + frm['x'] + ',' + frm['y'] + ' ' + 'c ' + str(0.7 * dx) + ', 0 ' + str(dx) + ', ' + str(dy) + ' ' + str(dx) + ', ' + str(dy)},
'<-|>' : {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx) + ',0 0,' + str(dy)},
'<-|->': {'style': 'marker-end:url(#arrowhead);marker-start:url(#arrowtail);stroke:#0041c4;stroke-width:1;fill:none','d': 'm ' + frm['x'] + ',' + frm['y'] + ' ' + str(dx / 2) + ',0 0,' + str(dy) + ' ' + str(dx / 2) + ',0'}
}
gmark[1].update( pattern.get( Edge['shape'], { 'style': 'fill:none;stroke:#00F;stroke-width:1' } ) )
if Edge['label']:
if Edge['shape'] == '-~' :
lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75
if Edge['shape'] == '~-' :
lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.25
if Edge['shape'] == '-|' :
lx = float(to['x'])
if Edge['shape'] == '|-' :
lx = float(frm['x'])
if Edge['shape'] == '-~>':
lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75
if Edge['shape'] == '~->':
lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.25
if Edge['shape'] == '-|>' :
lx = float(to['x'])
if Edge['shape'] == '|->' :
lx = float(frm['x'])
if Edge['shape'] == '<-~>':
lx = float(frm['x']) + (float(to['x']) - float(frm['x'])) * 0.75
if Edge['shape'] =='<-|>' :
lx = float(to['x'])
lwidth = len( Edge['label'] ) * font_width
label = [
'text',
{
'style': 'font-size:10px;',
'text-anchor': 'middle',
'xml:space': 'preserve',
'x': int( lx ),
'y': int( ly + 3 )
},
[ 'tspan', Edge['label'] ]
]
underlabel = [
'rect',
{
'height': 9,
'style': 'fill:#FFF;',
'width': lwidth,
'x': int( lx - lwidth / 2 ),
'y': int( ly - 5 )
}
]
gg.append(underlabel)
gg.append(label)
for k in Events:
if k.islower() :
if int( Events[k]['x'] ) > 0 :
lwidth = len( k ) * font_width
underlabel = [
'rect',
{
'x': float( Events[k]['x'] ) - float(lwidth) / 2,
'y': int( Events[k]['y'] ) - 4,
'height': 8,
'width': lwidth,
'style': 'fill:#FFF;'
}
]
gg.append(underlabel)
label = [
'text',
{
'style': 'font-size:8px;',
'x': int( Events[k]['x'] ),
'y': int( Events[k]['y'] ) + 2,
'width': lwidth,
'text-anchor': 'middle'
},
k
]
gg.append(label)
def parseConfig (source) :
lane['hscale'] = 1
if lane.get('hscale0') :
lane['hscale'] = lane['hscale0']
if source and source.get('config') and source.get('config').get('hscale'):
hscale = round(source.get('config').get('hscale'))
if hscale > 0 :
if hscale > 100 : hscale = 100
lane['hscale'] = hscale
lane['yh0'] = 0
lane['yh1'] = 0
if source and source.get('head') :
lane['head'] = source['head']
if source.get('head').get('tick',0) == 0 : lane['yh0'] = 20
if source.get('head').get('tock',0) == 0 : lane['yh0'] = 20
if source.get('head').get('text') : lane['yh1'] = 46; lane['head']['text'] = source['head']['text']
lane['yf0'] = 0
lane['yf1'] = 0
if source and source.get('foot') :
lane['foot'] = source['foot']
if source.get('foot').get('tick',0) == 0 : lane['yf0'] = 20
if source.get('foot').get('tock',0) == 0 : lane['yf0'] = 20
if source.get('foot').get('text') : lane['yf1'] = 46; lane['foot']['text'] = source['foot']['text']
def rec (tmp, state) :
name = str( tmp[0] )
delta_x = 25
state['x'] += delta_x
for i in range( len( tmp ) ) :
if type( tmp[i] ) is list :
old_y = state['y']
rec( tmp[i], state )
state['groups'].append( {'x':state['xx'], 'y':old_y, 'height':state['y'] - old_y, 'name': state['name'] } )
elif type( tmp[i] ) is dict :
state['lanes'].append(tmp[i])
state['width'].append(state['x'])
state['y'] += 1
state['xx'] = state['x']
state['x'] -= delta_x
state['name'] = name
def insertSVGTemplate (index, parent, source) :
e = waveskin.WaveSkin['default']
if source.get('config') and source.get('config').get('skin') :
if waveskin.WaveSkin.get( source.get('config').get('skin') ) :
e = waveskin.WaveSkin[ source.get('config').get('skin') ]
if index == 0 :
lane['xs'] = int( e[3][1][2][1]['width'] )
lane['ys'] = int( e[3][1][2][1]['height'] )
lane['xlabel'] = int( e[3][1][2][1]['x'] )
lane['ym'] = int( e[3][1][2][1]['y'] )
else :
e = ['svg', {'id': 'svg', 'xmlns': 'http://www.w3.org/2000/svg', 'xmlns:xlink': 'http://www.w3.org/1999/xlink', 'height': '0'},
['g', {'id': 'waves'},
['g', {'id': 'lanes'}],
['g', {'id': 'groups'}]
]
]
e[-1][1]['id'] = 'waves_' + str(index)
e[-1][2][1]['id'] = 'lanes_' + str(index)
e[-1][3][1]['id'] = 'groups_' + str(index)
e[1]['id'] = 'svgcontent_' + str(index)
e[1]['height'] = 0
parent.extend(e)
def renderWaveForm (index, source, output) :
xmax = 0
root = []
groups = []
if source.get('signal'):
insertSVGTemplate(index, output, source)
parseConfig( source )
ret = {'x':0, 'y':0, 'xmax':0, 'width':[], 'lanes':[], 'groups':[] }
rec( source['signal'], ret )
content = parseWaveLanes(ret['lanes'])
glengths = renderWaveLane(root, content, index)
for i in range( len( glengths ) ):
xmax = max( xmax, ( glengths[i] + ret['width'][i] ) )
renderMarks(root, content, index)
renderArcs(root, ret['lanes'], index, source)
renderGaps(root, ret['lanes'], index)
renderGroups(groups, ret['groups'], index)
lane['xg'] = int( math.ceil( float( xmax - lane['tgo'] ) / float(lane['xs'] ) ) ) * lane['xs']
width = (lane['xg'] + lane['xs'] * (lane['xmax'] + 1) )
height = len(content) * lane['yo'] + lane['yh0'] + lane['yh1'] + lane['yf0'] + lane['yf1']
output[1]={
'id' :'svgcontent_' + str(index),
'xmlns' :"http://www.w3.org/2000/svg",
'xmlns:xlink':"http://www.w3.org/1999/xlink",
'width' :str(width),
'height' :str(height),
'viewBox' :'0 0 ' + str(width) + ' ' + str(height),
'overflow' :"hidden"
}
output[-1][2][1]['transform']='translate(' + str(lane['xg'] + 0.5) + ', ' + str((float(lane['yh0']) + float(lane['yh1'])) + 0.5) + ')'
output[-1][2].extend(root)
output[-1][3].extend(groups)
def renderGroups (root, groups, index) :
svgns = 'http://www.w3.org/2000/svg',
xmlns = 'http://www.w3.org/XML/1998/namespace'
for i in range( len( groups ) ) :
group = [
'path',
{
'id': 'group_' + str(i) + '_' + str(index),
'd': 'm ' + str( groups[i]['x'] + 0.5 ) + ',' + str( groups[i]['y']* lane['yo'] + 3.5 + lane['yh0'] + lane['yh1'] ) + ' c -3,0 -5,2 -5,5 l 0,' + str( int( groups[i]['height'] * lane['yo'] - 16 ) ) + ' c 0,3 2,5 5,5',
'style': 'stroke:#0041c4;stroke-width:1;fill:none'
}
]
root.append(group)
name = groups[i]['name']
x = str( int( groups[i]['x'] - 10 ) )
y = str( int( lane['yo'] * (groups[i]['y'] + (float(groups[i]['height']) / 2)) + lane['yh0'] + lane['yh1'] ) )
label = [
['g',
{'transform': 'translate(' + x + ',' + y + ')'},
['g', {'transform': 'rotate(270)'},
'text',
{
'text-anchor': 'middle',
'class': 'info',
'xml:space' : 'preserve'
},
['tspan',name]
]
]
]
root.append(label)
def renderGaps (root, source, index) :
Stack = []
svgns = 'http://www.w3.org/2000/svg',
xlinkns = 'http://www.w3.org/1999/xlink'
if source:
gg = [
'g',
{ 'id': 'wavegaps_' + str(index) }
]
for i in range( len( source )):
lane['period'] = source[i].get('period',1)
lane['phase'] = int( source[i].get('phase',0 ) * 2 )
g = [
'g',
{
'id': 'wavegap_' + str(i) + '_' + str(index),
'transform': 'translate(0,' + str(lane['y0'] + i * lane['yo']) + ')'
}
]
gg.append(g)
if source[i].get('wave'):
text = source[i]['wave']
Stack = text
pos = 0
while len( Stack ) :
c = Stack [0]
Stack = Stack[1:]
if c == '|' :
b = [
'use',
{
'xmlns:xlink':xlinkns,
'xlink:href':'#gap',
'transform': 'translate(' + str(int(float(lane['xs']) * ((2 * pos + 1) * float(lane['period']) * float(lane['hscale']) - float(lane['phase'])))) + ')'
}
]
g.append(b)
pos += 1
root.append( gg )
def is_type_str( var ) :
if sys.version_info[0] < 3:
return type( var ) is str or type( var ) is unicode
else:
return type( var ) is str
def convert_to_svg( root ) :
svg_output = ''
if type( root ) is list:
if len(root) >= 2 and type( root[1] ) is dict:
if len( root ) == 2 :
svg_output += '<' + root[0] + convert_to_svg( root[1] ) + '/>\n'
elif len( root ) >= 3 :
svg_output += '<' + root[0] + convert_to_svg( root[1] ) + '>\n'
if len( root ) == 3:
svg_output += convert_to_svg( root[2] )
else:
svg_output += convert_to_svg( root[2:] )
svg_output += '</' + root[0] + '>\n'
elif type( root[0] ) is list:
for eleml in root:
svg_output += convert_to_svg( eleml )
else:
svg_output += '<' + root[0] + '>\n'
for eleml in root[1:]:
svg_output += convert_to_svg( eleml )
svg_output += '</' + root[0] + '>\n'
elif type( root ) is dict:
for elemd in root :
svg_output += ' ' + elemd + '="' + str(root[elemd]) + '"'
else:
svg_output += root
return svg_output
if __name__ == '__main__':
if len( sys.argv ) != 5:
print ( 'Usage : ' + sys.argv[0] + ' source <input.json> svg <output.svg>' )
exit(1)
if sys.argv[3] != 'svg' :
print ( 'Error: only SVG format supported.' )
exit(1)
output=[]
inputfile = sys.argv[2]
outputfile = sys.argv[4]
with open(inputfile,'r') as f:
jinput = json.load(f)
renderWaveForm(0,jinput,output)
svg_output = convert_to_svg(output)
with open(outputfile,'w') as f:
f.write( svg_output )

1
compiler/git_id Normal file
View File

@ -0,0 +1 @@
468eb9a4a038201c2b0004fe6e4ae9b2d37fdd57

View File

@ -114,6 +114,11 @@ def check_versions():
except: except:
OPTS.datasheet_gen = 0 OPTS.datasheet_gen = 0
try:
import coverage
OPTS.coverage = 1
except:
OPTS.coverage = 0
def init_openram(config_file, is_unit_test=True): def init_openram(config_file, is_unit_test=True):
"""Initialize the technology, paths, simulators, etc.""" """Initialize the technology, paths, simulators, etc."""
@ -200,6 +205,7 @@ def read_config(config_file, is_unit_test=True):
config_file = re.sub(r'\.py$', "", config_file) config_file = re.sub(r'\.py$', "", config_file)
# Expand the user if it is used # Expand the user if it is used
config_file = os.path.expanduser(config_file) config_file = os.path.expanduser(config_file)
OPTS.config_file = config_file
# Add the path to the system path so we can import things in the other directory # Add the path to the system path so we can import things in the other directory
dir_name = os.path.dirname(config_file) dir_name = os.path.dirname(config_file)
file_name = os.path.basename(config_file) file_name = os.path.basename(config_file)
@ -387,13 +393,17 @@ def import_tech():
OPTS.temperatures = tech.spice["temperatures"] OPTS.temperatures = tech.spice["temperatures"]
def print_time(name, now_time, last_time=None): def print_time(name, now_time, last_time=None, indentation=2):
""" Print a statement about the time delta. """ """ Print a statement about the time delta. """
if last_time: global OPTS
time = str(round((now_time-last_time).total_seconds(),1)) + " seconds"
else: # Don't print during testing
time = now_time.strftime('%m/%d/%Y %H:%M:%S') if not OPTS.is_unit_test or OPTS.debug_level>0:
print("** {0}: {1}".format(name,time)) if last_time:
time = str(round((now_time-last_time).total_seconds(),1)) + " seconds"
else:
time = now_time.strftime('%m/%d/%Y %H:%M:%S')
print("{0} {1}: {2}".format("*"*indentation,name,time))
def report_status(): def report_status():
@ -410,9 +420,13 @@ def report_status():
debug.error("Tech name must be specified in config file.") debug.error("Tech name must be specified in config file.")
print("Technology: {0}".format(OPTS.tech_name)) print("Technology: {0}".format(OPTS.tech_name))
print("Total size: {} kbits".format(OPTS.word_size*OPTS.num_words*OPTS.num_banks))
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size, print("Word size: {0}\nWords: {1}\nBanks: {2}".format(OPTS.word_size,
OPTS.num_words, OPTS.num_words,
OPTS.num_banks)) OPTS.num_banks))
print("RW ports: {0}\nR-only ports: {1}\nW-only ports: {2}".format(OPTS.num_rw_ports,
OPTS.num_r_ports,
OPTS.num_w_ports))
if OPTS.netlist_only: if OPTS.netlist_only:
print("Netlist only mode (no physical design is being done).") print("Netlist only mode (no physical design is being done).")

View File

@ -31,15 +31,23 @@ init_openram(config_file=args[0], is_unit_test=False)
# Only print banner here so it's not in unit tests # Only print banner here so it's not in unit tests
print_banner() print_banner()
# Keep track of running stats
start_time = datetime.datetime.now()
print_time("Start",start_time)
# Output info about this run # Output info about this run
report_status() report_status()
# Start importing design modules after we have the config file
import verify
from sram import sram
from sram_config import sram_config from sram_config import sram_config
# Configure the SRAM organization
c = sram_config(word_size=OPTS.word_size,
num_words=OPTS.num_words)
print("Words per row: {}".format(c.words_per_row))
#from parser import * #from parser import *
output_extensions = ["sp","v","lib"] output_extensions = ["sp","v","lib","py"]
if OPTS.datasheet_gen: if OPTS.datasheet_gen:
output_extensions.append("html") output_extensions.append("html")
if not OPTS.netlist_only: if not OPTS.netlist_only:
@ -48,15 +56,8 @@ output_files = ["{0}.{1}".format(OPTS.output_name,x) for x in output_extensions]
print("Output files are: ") print("Output files are: ")
print(*output_files,sep="\n") print(*output_files,sep="\n")
# Keep track of running stats
start_time = datetime.datetime.now()
print_time("Start",start_time)
# Configure the SRAM organization from sram import sram
c = sram_config(word_size=OPTS.word_size,
num_words=OPTS.num_words)
# import SRAM test generation
s = sram(sram_config=c, s = sram(sram_config=c,
name=OPTS.output_name) name=OPTS.output_name)

227
compiler/pgates/pdriver.py Normal file
View File

@ -0,0 +1,227 @@
import debug
import pgate
import math
from tech import drc
from math import log
from vector import vector
from globals import OPTS
from pinv import pinv
class pdriver(pgate.pgate):
"""
This instantiates an even or odd number of inverters sized for driving a load.
"""
unique_id = 1
def __init__(self, height=None, name="", neg_polarity=False, c_load=8, size_list = []):
self.stage_effort = 4
self.row_height = height
self.neg_polarity = neg_polarity
self.size_list = size_list
self.c_load = c_load
if len(self.size_list) > 0 and (self.c_load != 8 or self.neg_polarity):
raise Exception("Cannot specify both size_list and neg_polarity or c_load.")
self.compute_sizes()
if name=="":
name = "pdriver_{0}_{1}_".format(self.num_inv, pdriver.unique_id)
pdriver.unique_id += 1
pgate.pgate.__init__(self, name)
debug.info(1, "Creating {}".format(self.name))
self.create_netlist()
if not OPTS.netlist_only:
self.create_layout()
def compute_sizes(self):
# size_list specified
if len(self.size_list) > 0:
if not len(self.size_list) % 2:
neg_polarity = True
self.num_inv = len(self.size_list)
else:
# find the number of stages
#c_load is a unit inverter fanout, not a capacitance so c_in=1
num_stages = int(round(log(self.c_load)/log(4)))
# find inv_num and compute sizes
if self.neg_polarity:
if (num_stages % 2 == 0): # if num_stages is even
self.diff_polarity(num_stages=num_stages)
else: # if num_stages is odd
self.same_polarity(num_stages=num_stages)
else: # positive polarity
if (num_stages % 2 == 0):
self.same_polarity(num_stages=num_stages)
else:
self.diff_polarity(num_stages=num_stages)
def same_polarity(self, num_stages):
self.calc_size_list = []
self.num_inv = num_stages
# compute sizes
c_prev = self.c_load
for x in range(self.num_inv-1,-1,-1):
c_prev = int(round(c_prev/self.stage_effort))
self.calc_size_list.append(c_prev)
def diff_polarity(self, num_stages):
self.calc_size_list = []
# find which delay is smaller
delay_below = ((num_stages-1)*(self.c_load**(1/num_stages-1))) + num_stages-1
delay_above = ((num_stages+1)*(self.c_load**(1/num_stages+1))) + num_stages+1
if (delay_above < delay_below):
# recompute stage_effort for this delay
self.num_inv = num_stages+1
polarity_stage_effort = self.c_load**(1/self.num_inv)
else:
self.num_inv = num_stages-1
polarity_stage_effort = self.c_load**(1/self.num_inv)
# compute sizes
c_prev = self.c_load
for x in range(self.num_inv-1,-1,-1):
c_prev = int(round(c_prev/polarity_stage_effort))
self.calc_size_list.append(c_prev)
def create_netlist(self):
inv_list = []
self.add_pins()
self.add_modules()
self.create_insts()
def create_layout(self):
self.width = self.num_inv * self.inv_list[0].width
self.height = self.inv_list[0].height
self.place_modules()
self.route_wires()
self.add_layout_pins()
self.DRC_LVS()
def add_pins(self):
self.add_pin("A")
self.add_pin("Z")
self.add_pin("vdd")
self.add_pin("gnd")
def add_modules(self):
self.inv_list = []
if len(self.size_list) > 0: # size list specified
for x in range(len(self.size_list)):
self.inv_list.append(pinv(size=self.size_list[x], height=self.row_height))
self.add_mod(self.inv_list[x])
else: # find inv sizes
for x in range(len(self.calc_size_list)):
self.inv_list.append(pinv(size=self.calc_size_list[x], height=self.row_height))
self.add_mod(self.inv_list[x])
def create_insts(self):
self.inv_inst_list = []
for x in range(1,self.num_inv+1):
# Create first inverter
if x == 1:
zbx_int = "Zb{}_int".format(x);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
if self.num_inv == 1:
self.connect_inst(["A", "Z", "vdd", "gnd"])
else:
self.connect_inst(["A", zbx_int, "vdd", "gnd"])
# Create last inverter
elif x == self.num_inv:
zbn_int = "Zb{}_int".format(x-1);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
self.connect_inst([zbn_int, "Z", "vdd", "gnd"])
# Create middle inverters
else:
zbx_int = "Zb{}_int".format(x-1);
zbn_int = "Zb{}_int".format(x);
self.inv_inst_list.append(self.add_inst(name="buf_inv{}".format(x),
mod=self.inv_list[x-1]))
self.connect_inst([zbx_int, zbn_int, "vdd", "gnd"])
def place_modules(self):
# Add INV1 to the left
self.inv_inst_list[0].place(vector(0,0))
# Add inverters to the right of INV1
for x in range(1,len(self.inv_inst_list)):
self.inv_inst_list[x].place(vector(self.inv_inst_list[x-1].rx(),0))
def route_wires(self):
z_inst_list = []
a_inst_list = []
# inv_current Z to inv_next A
for x in range(0,len(self.inv_inst_list)-1):
z_inst_list.append(self.inv_inst_list[x].get_pin("Z"))
a_inst_list.append(self.inv_inst_list[x+1].get_pin("A"))
mid_point = vector(z_inst_list[x].cx(), a_inst_list[x].cy())
self.add_path("metal1", [z_inst_list[x].center(), mid_point, a_inst_list[x].center()])
def add_layout_pins(self):
# Continous vdd rail along with label.
vdd_pin=self.inv_inst_list[0].get_pin("vdd")
self.add_layout_pin(text="vdd",
layer="metal1",
offset=vdd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
# Continous gnd rail along with label.
gnd_pin=self.inv_inst_list[0].get_pin("gnd")
self.add_layout_pin(text="gnd",
layer="metal1",
offset=gnd_pin.ll().scale(0,1),
width=self.width,
height=vdd_pin.height())
z_pin = self.inv_inst_list[len(self.inv_inst_list)-1].get_pin("Z")
self.add_layout_pin_rect_center(text="Z",
layer=z_pin.layer,
offset=z_pin.center(),
width = z_pin.width(),
height = z_pin.height())
a_pin = self.inv_inst_list[0].get_pin("A")
self.add_layout_pin_rect_center(text="A",
layer=a_pin.layer,
offset=a_pin.center(),
width = a_pin.width(),
height = a_pin.height())
def analytical_delay(self, slew, load=0.0):
"""Calculate the analytical delay of INV1 -> ... -> INVn"""
delay = 0;
if len(self.inv_inst_list) == 1:
delay = self.inv_inst_list[x].analytical_delay(slew=slew);
else:
for x in range(len(self.inv_inst_list-1)):
load_next = 0.0
for n in range(x,len(self.inv_inst_list+1)):
load_next += self.inv_inst_list[x+1]
if x == 1:
delay += self.inv_inst_list[x].analytical_delay(slew=slew,
load=load_next)
else:
delay += self.inv_inst_list[x+1].analytical_delay(slew=delay.slew,
load=load_next)
return delay

5
compiler/profile_stats.py Executable file
View File

@ -0,0 +1,5 @@
import pstats
p = pstats.Stats('profile.dat')
p.strip_dirs()
p.sort_stats('cumulative')
p.print_stats(50)

View File

@ -46,12 +46,13 @@ class router(router_tech):
### The pin data structures ### The pin data structures
# A map of pin names to a set of pin_layout structures # A map of pin names to a set of pin_layout structures
# (i.e. pins with a given label)
self.pins = {} self.pins = {}
# This is a set of all pins (ignoring names) so that can quickly not create blockages for pins # This is a set of all pins (ignoring names) so that can quickly not create blockages for pins
# (They will be blocked based on the names we are routing) # (They will be blocked when we are routing other nets based on their name.)
self.all_pins = set() self.all_pins = set()
# A map of pin names to a list of pin groups # The labeled pins above categorized into pin groups that are touching/connected.
self.pin_groups = {} self.pin_groups = {}
### The blockage data structures ### The blockage data structures
@ -122,16 +123,6 @@ class router(router_tech):
debug.info(3,"Retrieved pin {}".format(str(pin))) debug.info(3,"Retrieved pin {}".format(str(pin)))
def find_pins(self,pin_name):
"""
Finds the pin shapes and converts to tracks.
Pin can either be a label or a location,layer pair: [[x,y],layer].
"""
debug.info(1,"Finding pins for {}.".format(pin_name))
self.retrieve_pins(pin_name)
self.analyze_pins(pin_name)
def find_blockages(self): def find_blockages(self):
""" """
Iterate through all the layers and write the obstacles to the routing grid. Iterate through all the layers and write the obstacles to the routing grid.
@ -142,7 +133,6 @@ class router(router_tech):
for layer in [self.vert_layer_number,self.horiz_layer_number]: for layer in [self.vert_layer_number,self.horiz_layer_number]:
self.retrieve_blockages(layer) self.retrieve_blockages(layer)
def find_pins_and_blockages(self, pin_list): def find_pins_and_blockages(self, pin_list):
""" """
Find the pins and blockages in the design Find the pins and blockages in the design
@ -150,31 +140,53 @@ class router(router_tech):
# This finds the pin shapes and sorts them into "groups" that are connected # This finds the pin shapes and sorts them into "groups" that are connected
# This must come before the blockages, so we can not count the pins themselves # This must come before the blockages, so we can not count the pins themselves
# as blockages. # as blockages.
for pin in pin_list: start_time = datetime.now()
self.find_pins(pin) for pin_name in pin_list:
self.retrieve_pins(pin_name)
print_time("Retrieving pins",datetime.now(), start_time, 4)
start_time = datetime.now()
for pin_name in pin_list:
self.analyze_pins(pin_name)
print_time("Analyzing pins",datetime.now(), start_time, 4)
# This will get all shapes as blockages and convert to grid units # This will get all shapes as blockages and convert to grid units
# This ignores shapes that were pins # This ignores shapes that were pins
start_time = datetime.now()
self.find_blockages() self.find_blockages()
print_time("Finding blockages",datetime.now(), start_time, 4)
# Convert the blockages to grid units # Convert the blockages to grid units
start_time = datetime.now()
self.convert_blockages() self.convert_blockages()
print_time("Converting blockages",datetime.now(), start_time, 4)
# This will convert the pins to grid units # This will convert the pins to grid units
# It must be done after blockages to ensure no DRCs between expanded pins and blocked grids # It must be done after blockages to ensure no DRCs between expanded pins and blocked grids
start_time = datetime.now()
for pin in pin_list: for pin in pin_list:
self.convert_pins(pin) self.convert_pins(pin)
print_time("Converting pins",datetime.now(), start_time, 4)
# Combine adjacent pins into pin groups to reduce run-time
# by reducing the number of maze routes.
# This algorithm is > O(n^2) so remove it for now
# start_time = datetime.now()
# for pin in pin_list:
# self.combine_adjacent_pins(pin)
# print_time("Combining adjacent pins",datetime.now(), start_time, 4)
#for pin in pin_list:
# self.combine_adjacent_pins(pin)
# Separate any adjacent grids of differing net names that overlap # Separate any adjacent grids of differing net names that overlap
# Must be done before enclosing pins # Must be done before enclosing pins
start_time = datetime.now()
self.separate_adjacent_pins(0) self.separate_adjacent_pins(0)
print_time("Separating adjacent pins",datetime.now(), start_time, 4)
# Enclose the continguous grid units in a metal rectangle to fix some DRCs # Enclose the continguous grid units in a metal rectangle to fix some DRCs
start_time = datetime.now()
self.enclose_pins() self.enclose_pins()
print_time("Enclosing pins",datetime.now(), start_time, 4)
def combine_adjacent_pins(self, pin_name): def combine_adjacent_pins(self, pin_name):
""" """
@ -236,16 +248,17 @@ class router(router_tech):
This will try to separate all grid pins by the supplied number of separation This will try to separate all grid pins by the supplied number of separation
tracks (default is to prevent adjacency). tracks (default is to prevent adjacency).
""" """
debug.info(1,"Separating adjacent pins.")
# Commented out to debug with SCMOS # Commented out to debug with SCMOS
#if separation==0: #if separation==0:
# return # return
pin_names = self.pin_groups.keys() pin_names = self.pin_groups.keys()
for pin_name1 in pin_names: for i,pin_name1 in enumerate(pin_names):
for pin_name2 in pin_names: for j,pin_name2 in enumerate(pin_names):
if pin_name1==pin_name2: if i==j:
continue continue
if i>j:
return
self.separate_adjacent_pin(pin_name1, pin_name2, separation) self.separate_adjacent_pin(pin_name1, pin_name2, separation)
def separate_adjacent_pin(self, pin_name1, pin_name2, separation): def separate_adjacent_pin(self, pin_name1, pin_name2, separation):
@ -256,14 +269,19 @@ class router(router_tech):
Try to do this intelligently to keep th pins enclosed. Try to do this intelligently to keep th pins enclosed.
""" """
debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2)) debug.info(1,"Comparing {0} and {1} adjacency".format(pin_name1, pin_name2))
removed_grids = 0
for index1,pg1 in enumerate(self.pin_groups[pin_name1]): for index1,pg1 in enumerate(self.pin_groups[pin_name1]):
for index2,pg2 in enumerate(self.pin_groups[pin_name2]): for index2,pg2 in enumerate(self.pin_groups[pin_name2]):
adj_grids = pg1.adjacent_grids(pg2, separation) adj_grids = pg1.adjacent_grids(pg2, separation)
removed_grids += len(adj_grids)
# These should have the same length, so... # These should have the same length, so...
if len(adj_grids)>0: if len(adj_grids)>0:
debug.info(3,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids)) debug.info(3,"Adjacent grids {0} {1} adj={2}".format(index1,index2,adj_grids))
self.remove_adjacent_grid(pg1, pg2, adj_grids) self.remove_adjacent_grid(pg1, pg2, adj_grids)
debug.info(1,"Removed {} adjacent grids.".format(removed_grids))
def remove_adjacent_grid(self, pg1, pg2, adj_grids): def remove_adjacent_grid(self, pg1, pg2, adj_grids):
""" """
Remove one of the adjacent grids in a heuristic manner. Remove one of the adjacent grids in a heuristic manner.
@ -666,37 +684,108 @@ class router(router_tech):
def analyze_pins(self, pin_name): def analyze_pins(self, pin_name):
""" """
Analyze the shapes of a pin and combine them into groups which are connected. Analyze the shapes of a pin and combine them into pin_groups which are connected.
""" """
debug.info(2,"Analyzing pin groups for {}.".format(pin_name)) debug.info(2,"Analyzing pin groups for {}.".format(pin_name))
pin_set = self.pins[pin_name] pin_set = self.pins[pin_name]
# Put each pin in an equivalence class of it's own # This will be a list of pin tuples that overlap
equiv_classes = [set([x]) for x in pin_set] overlap_list = []
def combine_classes(equiv_classes):
for class1 in equiv_classes:
for class2 in equiv_classes:
if class1 == class2:
continue
# Compare each pin in each class,
# and if any overlap, update equiv_classes to include the combined the class
for p1 in class1:
for p2 in class2:
if p1.overlaps(p2):
combined_class = class1 | class2
equiv_classes.remove(class1)
equiv_classes.remove(class2)
equiv_classes.append(combined_class)
return(equiv_classes)
return(equiv_classes)
old_length = math.inf # Sort the rectangles into a list with lower/upper y coordinates
while (len(equiv_classes)<old_length): bottom_y_coordinates = [(x.by(), x, "bottom") for x in pin_set]
old_length = len(equiv_classes) top_y_coordinates = [(x.uy(), x, "top") for x in pin_set]
equiv_classes = combine_classes(equiv_classes) y_coordinates = bottom_y_coordinates + top_y_coordinates
y_coordinates.sort(key=lambda x: x[0])
self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in equiv_classes] # Map the pins to the lower indices
bottom_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"}
top_index_map = {x[1]:i for i,x in enumerate(y_coordinates) if x[2]=="bottom"}
# Sort the pin list by x coordinate
pin_list = list(pin_set)
pin_list.sort(key=lambda x: x.lx())
# for shapes in x order
for pin in pin_list:
# start at pin's lower y coordinate
bottom_index = bottom_index_map[pin]
compared_pins = set()
for i in range(bottom_index,len(y_coordinates)):
compare_pin = y_coordinates[i][1]
# Don't overlap yourself
if pin==compare_pin:
continue
# Done when we encounter any shape above the pin
if compare_pin.by() > pin.uy():
break
# Don't double compare the same pin twice
if compare_pin in compared_pins:
continue
compared_pins.add(compare_pin)
# If we overlap, add them to the list
if pin.overlaps(compare_pin):
overlap_list.append((pin,compare_pin))
# Initial unique group assignments
group_id = {}
gid = 1
for pin in pin_list:
group_id[pin] = gid
gid += 1
for p in overlap_list:
(p1,p2) = p
for pin in pin_list:
if group_id[pin] == group_id[p2]:
group_id[pin] = group_id[p1]
# For each pin add it to it's group
group_map = {}
for pin in pin_list:
gid = group_id[pin]
if gid not in group_map.keys():
group_map[gid] = pin_group(name=pin_name, pin_set=[], router=self)
# We always add it to the first set since they are touching
group_map[gid].pins[0].add(pin)
self.pin_groups[pin_name] = list(group_map.values())
# This is the old O(n^2) implementation
# def analyze_pins(self, pin_name):
# """
# Analyze the shapes of a pin and combine them into pin_groups which are connected.
# """
# debug.info(2,"Analyzing pin groups for {}.".format(pin_name))
# pin_set = self.pins[pin_name]
# # Put each pin in an equivalence class of it's own
# equiv_classes = [set([x]) for x in pin_set]
# def combine_classes(equiv_classes):
# for class1 in equiv_classes:
# for class2 in equiv_classes:
# if class1 == class2:
# continue
# # Compare each pin in each class,
# # and if any overlap, update equiv_classes to include the combined the class
# for p1 in class1:
# for p2 in class2:
# if p1.overlaps(p2):
# combined_class = class1 | class2
# equiv_classes.remove(class1)
# equiv_classes.remove(class2)
# equiv_classes.append(combined_class)
# return(equiv_classes)
# return(equiv_classes)
# old_length = math.inf
# while (len(equiv_classes)<old_length):
# old_length = len(equiv_classes)
# equiv_classes = combine_classes(equiv_classes)
# self.pin_groups[pin_name] = [pin_group(name=pin_name, pin_set=x, router=self) for x in equiv_classes]
def convert_pins(self, pin_name): def convert_pins(self, pin_name):
""" """

View File

@ -65,9 +65,12 @@ class supply_router(router):
self.create_routing_grid() self.create_routing_grid()
# Get the pin shapes # Get the pin shapes
start_time = datetime.now()
self.find_pins_and_blockages([self.vdd_name, self.gnd_name]) self.find_pins_and_blockages([self.vdd_name, self.gnd_name])
print_time("Finding pins and blockages",datetime.now(), start_time, 3)
# Add the supply rails in a mesh network and connect H/V with vias # Add the supply rails in a mesh network and connect H/V with vias
start_time = datetime.now()
# Block everything # Block everything
self.prepare_blockages(self.gnd_name) self.prepare_blockages(self.gnd_name)
# Determine the rail locations # Determine the rail locations
@ -77,15 +80,19 @@ class supply_router(router):
self.prepare_blockages(self.vdd_name) self.prepare_blockages(self.vdd_name)
# Determine the rail locations # Determine the rail locations
self.route_supply_rails(self.vdd_name,1) self.route_supply_rails(self.vdd_name,1)
print_time("Routing supply rails",datetime.now(), start_time, 3)
start_time = datetime.now()
self.route_simple_overlaps(vdd_name) self.route_simple_overlaps(vdd_name)
self.route_simple_overlaps(gnd_name) self.route_simple_overlaps(gnd_name)
print_time("Simple overlap routing",datetime.now(), start_time, 3)
# Route the supply pins to the supply rails # Route the supply pins to the supply rails
# Route vdd first since we want it to be shorter # Route vdd first since we want it to be shorter
start_time = datetime.now()
self.route_pins_to_rails(vdd_name) self.route_pins_to_rails(vdd_name)
self.route_pins_to_rails(gnd_name) self.route_pins_to_rails(gnd_name)
print_time("Maze routing supplies",datetime.now(), start_time, 3)
#self.write_debug_gds("final.gds",False) #self.write_debug_gds("final.gds",False)
return True return True
@ -101,7 +108,7 @@ class supply_router(router):
# These are the wire tracks # These are the wire tracks
wire_tracks = self.supply_rail_tracks[pin_name] wire_tracks = self.supply_rail_tracks[pin_name]
routed_count=0
for pg in self.pin_groups[pin_name]: for pg in self.pin_groups[pin_name]:
if pg.is_routed(): if pg.is_routed():
continue continue
@ -109,6 +116,7 @@ class supply_router(router):
# First, check if we just overlap, if so, we are done. # First, check if we just overlap, if so, we are done.
overlap_grids = wire_tracks & pg.grids overlap_grids = wire_tracks & pg.grids
if len(overlap_grids)>0: if len(overlap_grids)>0:
routed_count += 1
pg.set_routed() pg.set_routed()
continue continue
@ -116,7 +124,7 @@ class supply_router(router):
#pg.create_simple_overlap_enclosure(pg.grids) #pg.create_simple_overlap_enclosure(pg.grids)
#pg.add_enclosure(self.cell) #pg.add_enclosure(self.cell)
debug.info(1,"Routed {} simple overlap pins".format(routed_count))
def finalize_supply_rails(self, name): def finalize_supply_rails(self, name):
""" """
@ -226,9 +234,9 @@ class supply_router(router):
min_yoffset = self.rg.ll.y min_yoffset = self.rg.ll.y
min_xoffset = self.rg.ll.x min_xoffset = self.rg.ll.x
start_offset = min_yoffset + supply_number
# Horizontal supply rails # Horizontal supply rails
start_offset = min_yoffset + supply_number
for offset in range(start_offset, max_yoffset, 2): for offset in range(start_offset, max_yoffset, 2):
# Seed the function at the location with the given width # Seed the function at the location with the given width
wave = [vector3d(min_xoffset,offset,0)] wave = [vector3d(min_xoffset,offset,0)]
@ -243,7 +251,7 @@ class supply_router(router):
wave = added_rail.neighbor(direction.EAST) wave = added_rail.neighbor(direction.EAST)
# Vertical supply rails # Vertical supply rails
max_offset = self.rg.ur.x start_offset = min_xoffset + supply_number
for offset in range(start_offset, max_xoffset, 2): for offset in range(start_offset, max_xoffset, 2):
# Seed the function at the location with the given width # Seed the function at the location with the given width
wave = [vector3d(offset,min_yoffset,1)] wave = [vector3d(offset,min_yoffset,1)]
@ -366,8 +374,8 @@ class supply_router(router):
""" """
remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name]) remaining_components = sum(not x.is_routed() for x in self.pin_groups[pin_name])
debug.info(1,"Routing {0} with {1} pin components to route.".format(pin_name, debug.info(1,"Maze routing {0} with {1} pin components to connect.".format(pin_name,
remaining_components)) remaining_components))
for index,pg in enumerate(self.pin_groups[pin_name]): for index,pg in enumerate(self.pin_groups[pin_name]):
if pg.is_routed(): if pg.is_routed():

3
compiler/run_profile.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/bash
python3 -m cProfile -o profile.dat ./openram.py example_config_scn4m_subm.py -v
echo "Run view_profile.py to view results"

View File

@ -14,8 +14,6 @@ class sram():
""" """
def __init__(self, sram_config, name): def __init__(self, sram_config, name):
#sram_config.words_per_row = 1 #Disables column mux generation
sram_config.compute_sizes()
sram_config.set_local_config(self) sram_config.set_local_config(self)
# reset the static duplicate name checker for unit tests # reset the static duplicate name checker for unit tests
@ -108,12 +106,20 @@ class sram():
lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file) lib(out_dir=OPTS.output_path, sram=self.s, sp_file=sp_file)
print_time("Characterization", datetime.datetime.now(), start_time) print_time("Characterization", datetime.datetime.now(), start_time)
# Write the config file
start_time = datetime.datetime.now()
from shutil import copyfile
copyfile(OPTS.config_file + '.py', OPTS.output_path + OPTS.output_name + '.py')
print("Config: writing to {0}".format(OPTS.output_path + OPTS.output_name + '.py'))
print_time("Config", datetime.datetime.now(), start_time)
# Write the datasheet # Write the datasheet
start_time = datetime.datetime.now() start_time = datetime.datetime.now()
from datasheet_gen import datasheet_gen from datasheet_gen import datasheet_gen
dname = OPTS.output_path + self.s.name + ".html" dname = OPTS.output_path + self.s.name + ".html"
print("Datasheet: writing to {0}".format(dname)) print("Datasheet: writing to {0}".format(dname))
datasheet_gen.datasheet_write(dname) datasheet_gen.datasheet_write(self.s,dname)
print_time("Datasheet", datetime.datetime.now(), start_time) print_time("Datasheet", datetime.datetime.now(), start_time)
# Write a verilog model # Write a verilog model

View File

@ -10,6 +10,7 @@ from globals import OPTS, print_time
from sram_base import sram_base from sram_base import sram_base
from bank import bank from bank import bank
from contact import m2m3
from dff_buf_array import dff_buf_array from dff_buf_array import dff_buf_array
from dff_array import dff_array from dff_array import dff_array
@ -202,9 +203,8 @@ class sram_1bank(sram_base):
offset=clk_steiner_pos, offset=clk_steiner_pos,
rotate=90) rotate=90)
# Note, the via to the control logic is taken care of when we route # Note, the via to the control logic is taken care of above
# the control logic to the bank self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, clk_steiner_pos])
self.add_wire(("metal3","via2","metal2"),[row_addr_clk_pos, mid1_pos, clk_steiner_pos, control_clk_buf_pos])
if self.col_addr_dff: if self.col_addr_dff:
dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk") dff_clk_pin = self.col_addr_dff_insts[port].get_pin("clk")
@ -216,6 +216,9 @@ class sram_1bank(sram_base):
data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk") data_dff_clk_pin = self.data_dff_insts[port].get_pin("clk")
data_dff_clk_pos = data_dff_clk_pin.center() data_dff_clk_pos = data_dff_clk_pin.center()
mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y) mid_pos = vector(clk_steiner_pos.x, data_dff_clk_pos.y)
# In some designs, the steiner via will be too close to the mid_pos via
# so make the wire as wide as the contacts
self.add_path("metal2",[mid_pos, clk_steiner_pos], width=max(m2m3.width,m2m3.height))
self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos]) self.add_wire(("metal3","via2","metal2"),[data_dff_clk_pos, mid_pos, clk_steiner_pos])

View File

@ -80,7 +80,7 @@ class sram_base(design):
if not OPTS.is_unit_test: if not OPTS.is_unit_test:
print_time("Netlisting",datetime.now(), start_time) print_time("Submodules",datetime.now(), start_time)
def create_layout(self): def create_layout(self):

View File

@ -14,7 +14,7 @@ class sram_config:
# This will get over-written when we determine the organization # This will get over-written when we determine the organization
self.words_per_row = None self.words_per_row = None
# Move the module names to this? self.compute_sizes()
def set_local_config(self, module): def set_local_config(self, module):
@ -54,6 +54,20 @@ class sram_config:
self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size) self.tentative_num_rows = self.num_bits_per_bank / (self.words_per_row*self.word_size)
self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row) self.words_per_row = self.amend_words_per_row(self.tentative_num_rows, self.words_per_row)
debug.info(1,"Words per row: {}".format(self.words_per_row))
self.recompute_sizes()
def recompute_sizes(self):
"""
Calculate the auxiliary values assuming fixed number of words per row.
This can be called multiple times from the unit test when we reconfigure an
SRAM for testing.
"""
# If the banks changed
self.num_words_per_bank = self.num_words/self.num_banks
self.num_bits_per_bank = self.word_size*self.num_words_per_bank
# Fix the number of columns and rows # Fix the number of columns and rows
self.num_cols = int(self.words_per_row*self.word_size) self.num_cols = int(self.words_per_row*self.word_size)
self.num_rows = int(self.num_words_per_bank/self.words_per_row) self.num_rows = int(self.num_words_per_bank/self.words_per_row)
@ -64,7 +78,6 @@ class sram_config:
self.bank_addr_size = self.col_addr_size + self.row_addr_size self.bank_addr_size = self.col_addr_size + self.row_addr_size
self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2)) self.addr_size = self.bank_addr_size + int(log(self.num_banks, 2))
debug.info(1,"Words per row: {}".format(self.words_per_row))
def estimate_words_per_row(self,tentative_num_cols, word_size): def estimate_words_per_row(self,tentative_num_cols, word_size):
""" """
@ -74,10 +87,14 @@ class sram_config:
if tentative_num_cols < 1.5*word_size: if tentative_num_cols < 1.5*word_size:
return 1 return 1
elif tentative_num_cols > 3*word_size: elif tentative_num_cols < 3*word_size:
return 2
elif tentative_num_cols < 6*word_size:
return 4 return 4
else: else:
return 2 if tentative_num_cols > 16*word_size:
debug.warning("Reaching column mux size limit. Consider increasing above 8-way.")
return 8
def amend_words_per_row(self,tentative_num_rows, words_per_row): def amend_words_per_row(self,tentative_num_rows, words_per_row):
""" """

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python3
"""
Run a regression test on a 2-row buffer cell
"""
import unittest
from testutils import header,openram_test
import sys,os
sys.path.append(os.path.join(sys.path[0],".."))
import globals
from globals import OPTS
import debug
@unittest.skip("SKIPPING 04_pdriver_test, LVS error in FreePDK45")
class pdriver_test(openram_test):
def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name))
global verify
import verify
import pdriver
debug.info(2, "Testing inverter/buffer 4x 8x")
# a tests the error message for specifying conflicting conditions
#a = pdriver.pdriver(c_load = 4,size_list = [1,2,4,8])
b = pdriver.pdriver(size_list = [1,2,4,8])
c = pdriver.pdriver(c_load = 50)
d = pdriver.pdriver(c_load = 50, neg_polarity = True)
e = pdriver.pdriver(c_load = 64)
f = pdriver.pdriver(c_load = 64, neg_polarity = True)
#self.local_check(a)
self.local_check(b)
self.local_check(c)
self.local_check(d)
self.local_check(e)
self.local_check(f)
globals.end_openram()
# instantiate a copdsay of the class to actually run the test
if __name__ == "__main__":
(OPTS, args) = globals.parse_args()
del sys.argv[1:]
header(__file__, OPTS.tech_name)
unittest.main()

View File

@ -24,18 +24,21 @@ class multi_bank_test(openram_test):
c.num_banks=2 c.num_banks=2
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "No column mux") debug.info(1, "No column mux")
a = bank(c, name="bank1_multi") a = bank(c, name="bank1_multi")
self.local_check(a) self.local_check(a)
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two way column mux") debug.info(1, "Two way column mux")
a = bank(c, name="bank2_multi") a = bank(c, name="bank2_multi")
self.local_check(a) self.local_check(a)
c.num_words=64 c.num_words=64
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Four way column mux") debug.info(1, "Four way column mux")
a = bank(c, name="bank3_multi") a = bank(c, name="bank3_multi")
self.local_check(a) self.local_check(a)
@ -43,6 +46,7 @@ class multi_bank_test(openram_test):
c.word_size=2 c.word_size=2
c.num_words=128 c.num_words=128
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Eight way column mux") debug.info(1, "Eight way column mux")
a = bank(c, name="bank4_multi") a = bank(c, name="bank4_multi")
self.local_check(a) self.local_check(a)

View File

@ -31,6 +31,7 @@ class psingle_bank_test(openram_test):
num_words=16) num_words=16)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "No column mux") debug.info(1, "No column mux")
name = "bank1_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) name = "bank1_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name) a = bank(c, name=name)
@ -38,6 +39,7 @@ class psingle_bank_test(openram_test):
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two way column mux") debug.info(1, "Two way column mux")
name = "bank2_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) name = "bank2_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name) a = bank(c, name=name)
@ -45,6 +47,7 @@ class psingle_bank_test(openram_test):
c.num_words=64 c.num_words=64
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Four way column mux") debug.info(1, "Four way column mux")
name = "bank3_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) name = "bank3_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name) a = bank(c, name=name)
@ -53,6 +56,7 @@ class psingle_bank_test(openram_test):
c.word_size=2 c.word_size=2
c.num_words=128 c.num_words=128
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Four way column mux") debug.info(1, "Four way column mux")
name = "bank4_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports) name = "bank4_{0}rw_{1}w_{2}r_single".format(OPTS.num_rw_ports, OPTS.num_w_ports, OPTS.num_r_ports)
a = bank(c, name=name) a = bank(c, name=name)

View File

@ -30,6 +30,7 @@ class psram_1bank_2mux_1rw_1w_test(openram_test):
num_banks=1) num_banks=1)
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -30,6 +30,7 @@ class psram_1bank_2mux_1w_1r_test(openram_test):
num_banks=1) num_banks=1)
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -31,6 +31,7 @@ class psram_1bank_2mux_test(openram_test):
num_banks=1) num_banks=1)
c.num_words=32 c.num_words=32
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class psram_1bank_4mux_1rw_1r_test(openram_test):
num_banks=1) num_banks=1)
c.num_words=64 c.num_words=64
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_2mux_1rw_1r_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_2mux_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_4mux_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_8mux_1rw_1r_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_8mux_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -29,6 +29,7 @@ class sram_1bank_nomux_1rw_1r_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -23,6 +23,7 @@ class sram_1bank_nomux_test(openram_test):
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Layout test for {}rw,{}r,{}w sram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -23,18 +23,21 @@ class sram_2bank_test(openram_test):
num_banks=2) num_banks=2)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Two bank, no column mux with control logic") debug.info(1, "Two bank, no column mux with control logic")
a = sram(c, "sram1") a = sram(c, "sram1")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)
c.num_words=64 c.num_words=64
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Two bank two way column mux with control logic") debug.info(1, "Two bank two way column mux with control logic")
a = sram(c, "sram2") a = sram(c, "sram2")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)
c.num_words=128 c.num_words=128
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Two bank, four way column mux with control logic") debug.info(1, "Two bank, four way column mux with control logic")
a = sram(c, "sram3") a = sram(c, "sram3")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)
@ -42,6 +45,7 @@ class sram_2bank_test(openram_test):
c.word_size=2 c.word_size=2
c.num_words=256 c.num_words=256
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Two bank, eight way column mux with control logic") debug.info(1, "Two bank, eight way column mux with control logic")
a = sram(c, "sram4") a = sram(c, "sram4")
self.local_check(a, final_verification=True) self.local_check(a, final_verification=True)

View File

@ -30,6 +30,7 @@ class timing_sram_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram(c, name="sram1") s = sram(c, name="sram1")

View File

@ -30,6 +30,7 @@ class timing_sram_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank") debug.info(1, "Testing timing for sample 1bit, 16words SRAM with 1 bank")
s = sram(c, name="sram1") s = sram(c, name="sram1")

View File

@ -36,6 +36,7 @@ class psram_1bank_2mux_1rw_1r_1w_func_test(openram_test):
num_words=64, num_words=64,
num_banks=1) num_banks=1)
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -36,6 +36,7 @@ class psram_1bank_4mux_func_test(openram_test):
num_words=256, num_words=256,
num_banks=1) num_banks=1)
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -36,6 +36,7 @@ class psram_1bank_8mux_func_test(openram_test):
num_words=256, num_words=256,
num_banks=1) num_banks=1)
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -36,6 +36,7 @@ class psram_1bank_nomux_func_test(openram_test):
num_words=32, num_words=32,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports, debug.info(1, "Functional test for {}rw,{}r,{}w psram with {} bit words, {} words, {} words per row, {} banks".format(OPTS.num_rw_ports,
OPTS.num_r_ports, OPTS.num_r_ports,
OPTS.num_w_ports, OPTS.num_w_ports,

View File

@ -31,6 +31,7 @@ class sram_1bank_2mux_func_test(openram_test):
num_words=64, num_words=64,
num_banks=1) num_banks=1)
c.words_per_row=2 c.words_per_row=2
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words, c.num_words,
c.words_per_row, c.words_per_row,

View File

@ -31,6 +31,7 @@ class sram_1bank_4mux_func_test(openram_test):
num_words=256, num_words=256,
num_banks=1) num_banks=1)
c.words_per_row=4 c.words_per_row=4
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words, c.num_words,
c.words_per_row, c.words_per_row,

View File

@ -34,6 +34,7 @@ class sram_1bank_8mux_func_test(openram_test):
num_words=256, num_words=256,
num_banks=1) num_banks=1)
c.words_per_row=8 c.words_per_row=8
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words, c.num_words,
c.words_per_row, c.words_per_row,

View File

@ -30,6 +30,7 @@ class sram_1bank_nomux_func_test(openram_test):
num_words=32, num_words=32,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, debug.info(1, "Functional test for sram with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words, c.num_words,
c.words_per_row, c.words_per_row,

View File

@ -36,6 +36,7 @@ class psram_1bank_nomux_func_test(openram_test):
num_words=32, num_words=32,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size, debug.info(1, "Functional test for sram 1rw,1r with {} bit words, {} words, {} words per row, {} banks".format(c.word_size,
c.num_words, c.num_words,
c.words_per_row, c.words_per_row,

View File

@ -23,6 +23,7 @@ class lib_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing analytical timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name)) s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))
tempspice = OPTS.openram_temp + "temp.sp" tempspice = OPTS.openram_temp + "temp.sp"

View File

@ -32,6 +32,7 @@ class lib_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing pruned timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name)) s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -32,6 +32,7 @@ class lib_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing timing for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name)) s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -23,6 +23,7 @@ class lef_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing LEF for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name)) s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -22,6 +22,7 @@ class verilog_test(openram_test):
num_words=16, num_words=16,
num_banks=1) num_banks=1)
c.words_per_row=1 c.words_per_row=1
c.recompute_sizes()
debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank") debug.info(1, "Testing Verilog for sample 2 bit, 16 words SRAM with 1 bank")
s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name)) s = sram(c, "sram_2_16_1_{0}".format(OPTS.tech_name))

View File

@ -39,7 +39,7 @@ class worst_case_timing_sram_test(openram_test):
num_words=num_words, num_words=num_words,
num_banks=num_banks) num_banks=num_banks)
c.words_per_row=1 c.words_per_row=1
#c.compute_sizes() c.recompute_sizes()
debug.info(1, "Testing the timing different bitecells inside a {}bit, {} words SRAM with {} bank".format( debug.info(1, "Testing the timing different bitecells inside a {}bit, {} words SRAM with {} bank".format(
word_size, num_words, num_banks)) word_size, num_words, num_banks))
s = sram(c, name="sram1") s = sram(c, name="sram1")

View File

@ -17,7 +17,8 @@ import getpass
class openram_test(openram_test): class openram_test(openram_test):
def runTest(self): def runTest(self):
globals.init_openram("config_20_{0}".format(OPTS.tech_name)) OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
globals.init_openram("{0}/tests/config_20_{1}".format(OPENRAM_HOME,OPTS.tech_name))
debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.") debug.info(1, "Testing top-level openram.py with 2-bit, 16 word SRAM.")
out_file = "testsram" out_file = "testsram"
@ -41,14 +42,16 @@ class openram_test(openram_test):
verbosity += " -v" verbosity += " -v"
OPENRAM_HOME = os.path.abspath(os.environ.get("OPENRAM_HOME"))
# Always perform code coverage # Always perform code coverage
if OPTS.coverage == 0:
debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage")
exe_name = "coverage run -p {0}/openram.py ".format(OPENRAM_HOME) exe_name = "coverage run -p {0}/openram.py ".format(OPENRAM_HOME)
cmd = "{0} -n -o {1} -p {2} {3} config_20_{4}.py 2>&1 > {5}/output.log".format(exe_name, config_name = "{0}config_20_{1}.py".format(OPENRAM_HOME + "/tests/",OPTS.tech_name)
cmd = "{0} -n -o {1} -p {2} {3} {4} 2>&1 > {5}/output.log".format(exe_name,
out_file, out_file,
out_path, out_path,
verbosity, verbosity,
OPTS.tech_name, config_name,
out_path) out_path)
debug.info(1, cmd) debug.info(1, cmd)
os.system(cmd) os.system(cmd)

6
compiler/view_profile.py Executable file
View File

@ -0,0 +1,6 @@
import pstats
p = pstats.Stats(profile.dat)
p.strip_dirs()
p.sort_stats(cumulative)
p.print_stats(50)