2016-11-08 18:57:35 +01:00
|
|
|
#!/usr/bin/env python2.7
|
|
|
|
|
"""
|
|
|
|
|
SRAM Compiler
|
|
|
|
|
|
|
|
|
|
The output files append the given suffixes to the output name:
|
|
|
|
|
a spice (.sp) file for circuit simulation
|
|
|
|
|
a GDS2 (.gds) file containing the layout
|
|
|
|
|
a LEF (.lef) file for preliminary P&R (real one should be from layout)
|
|
|
|
|
a Liberty (.lib) file for timing analysis/optimization
|
|
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import sys,os
|
|
|
|
|
import datetime
|
|
|
|
|
import re
|
|
|
|
|
import importlib
|
|
|
|
|
import globals
|
|
|
|
|
|
2016-11-15 18:36:15 +01:00
|
|
|
(OPTS, args) = globals.parse_args()
|
|
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
def print_time(name, now_time, last_time=None):
|
|
|
|
|
if last_time:
|
|
|
|
|
time = round((now_time-last_time).total_seconds(),1)
|
|
|
|
|
else:
|
|
|
|
|
time = now_time
|
|
|
|
|
print("** {0}: {1} seconds".format(name,time))
|
|
|
|
|
return now_time
|
|
|
|
|
|
2016-11-08 18:57:35 +01:00
|
|
|
# These depend on arguments, so don't load them until now.
|
|
|
|
|
import debug
|
|
|
|
|
|
|
|
|
|
# required positional args for using openram main exe
|
|
|
|
|
if len(args) < 1:
|
2017-06-13 00:02:48 +02:00
|
|
|
print(globals.USAGE)
|
2016-11-08 18:57:35 +01:00
|
|
|
sys.exit(2)
|
2016-11-15 19:14:04 +01:00
|
|
|
|
|
|
|
|
globals.print_banner()
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2016-11-15 18:36:15 +01:00
|
|
|
globals.init_openram(args[0])
|
|
|
|
|
|
2016-11-08 18:57:35 +01:00
|
|
|
# Check if all arguments are integers for bits, size, banks
|
|
|
|
|
if type(OPTS.config.word_size)!=int:
|
|
|
|
|
debug.error("{0} is not an integer in config file.".format(OPTS.config.word_size))
|
|
|
|
|
if type(OPTS.config.num_words)!=int:
|
|
|
|
|
debug.error("{0} is not an integer in config file.".format(OPTS.config.sram_size))
|
|
|
|
|
if type(OPTS.config.num_banks)!=int:
|
|
|
|
|
debug.error("{0} is not an integer in config file.".format(OPTS.config.num_banks))
|
|
|
|
|
|
|
|
|
|
if not OPTS.config.tech_name:
|
|
|
|
|
debug.error("Tech name must be specified in config file.")
|
|
|
|
|
|
|
|
|
|
word_size = OPTS.config.word_size
|
|
|
|
|
num_words = OPTS.config.num_words
|
|
|
|
|
num_banks = OPTS.config.num_banks
|
|
|
|
|
|
2017-06-12 23:37:15 +02:00
|
|
|
if (OPTS.output_name == ""):
|
|
|
|
|
OPTS.output_name = "sram_{0}_{1}_{2}_{3}".format(word_size,
|
2017-11-23 00:57:29 +01:00
|
|
|
num_words,
|
|
|
|
|
num_banks,
|
|
|
|
|
OPTS.tech_name)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
print("Output files are " + OPTS.output_name + ".(sp|gds|v|lib|lef)")
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-06-13 00:02:48 +02:00
|
|
|
print("Technology: {0}".format(OPTS.tech_name))
|
|
|
|
|
print("Word size: {0}\nWords: {1}\nBanks: {2}".format(word_size,num_words,num_banks))
|
2016-11-08 18:57:35 +01:00
|
|
|
|
|
|
|
|
# only start importing modules after we have the config file
|
2017-11-14 23:59:14 +01:00
|
|
|
import verify
|
2016-11-08 18:57:35 +01:00
|
|
|
import sram
|
|
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
start_time = datetime.datetime.now()
|
|
|
|
|
last_time = start_time
|
|
|
|
|
print_time("Start",datetime.datetime.now())
|
2018-01-05 17:32:23 +01:00
|
|
|
if not OPTS.check_lvsdrc:
|
|
|
|
|
print("DRC/LVS/PEX checking is disabled.")
|
2016-11-08 18:57:35 +01:00
|
|
|
# import SRAM test generation
|
|
|
|
|
s = sram.sram(word_size=word_size,
|
|
|
|
|
num_words=num_words,
|
|
|
|
|
num_banks=num_banks,
|
2017-06-12 23:37:15 +02:00
|
|
|
name=OPTS.output_name)
|
2017-11-14 22:24:14 +01:00
|
|
|
last_time=print_time("SRAM creation", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
# Measure design area
|
|
|
|
|
# Not working?
|
|
|
|
|
#cell_size = s.gds.measureSize(s.name)
|
2017-06-13 00:02:48 +02:00
|
|
|
#print("Area:", cell_size[0] * cell_size[1])
|
2016-11-08 18:57:35 +01:00
|
|
|
|
|
|
|
|
# Output the files for the resulting SRAM
|
|
|
|
|
|
2017-06-12 23:37:15 +02:00
|
|
|
spname = OPTS.output_path + s.name + ".sp"
|
2017-06-13 00:02:48 +02:00
|
|
|
print("SP: Writing to {0}".format(spname))
|
2016-11-08 18:57:35 +01:00
|
|
|
s.sp_write(spname)
|
2017-11-14 22:24:14 +01:00
|
|
|
last_time=print_time("Spice writing", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
# Output the extracted design
|
2016-11-08 18:57:35 +01:00
|
|
|
sram_file = spname
|
2016-11-15 18:03:16 +01:00
|
|
|
if OPTS.use_pex:
|
2017-06-12 23:37:15 +02:00
|
|
|
sram_file = OPTS.output_path + "temp_pex.sp"
|
2017-11-14 23:59:14 +01:00
|
|
|
verify.run_pex(s.name, gdsname, spname, output=sram_file)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
# Characterize the design
|
2017-11-16 02:02:53 +01:00
|
|
|
from characterizer import lib
|
2017-11-14 22:24:14 +01:00
|
|
|
libname = OPTS.output_path + s.name + ".lib"
|
|
|
|
|
print("LIB: Writing to {0}".format(libname))
|
2018-01-05 17:32:23 +01:00
|
|
|
if OPTS.analytical_delay:
|
|
|
|
|
print("Using analytical delay models (no characterization)")
|
|
|
|
|
else:
|
|
|
|
|
if OPTS.spice_name!="":
|
|
|
|
|
print("Performing simulation-based characterization with {}".format(OPTS.spice_name))
|
|
|
|
|
if OPTS.trim_netlist:
|
|
|
|
|
print("Trimming netlist to speed up characterization.")
|
2017-11-14 22:24:14 +01:00
|
|
|
lib.lib(libname,s,sram_file)
|
|
|
|
|
last_time=print_time("Characterization", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
# Write the layout
|
|
|
|
|
gdsname = OPTS.output_path + s.name + ".gds"
|
|
|
|
|
print("GDS: Writing to {0}".format(gdsname))
|
|
|
|
|
s.gds_write(gdsname)
|
|
|
|
|
last_time=print_time("GDS", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
# Create a LEF physical model
|
2017-06-12 23:37:15 +02:00
|
|
|
lefname = OPTS.output_path + s.name + ".lef"
|
2017-06-13 00:02:48 +02:00
|
|
|
print("LEF: Writing to {0}".format(lefname))
|
2017-12-19 18:01:24 +01:00
|
|
|
s.lef_write(lefname)
|
2017-12-19 18:55:59 +01:00
|
|
|
last_time=print_time("LEF", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2017-11-14 22:24:14 +01:00
|
|
|
# Write a verilog model
|
|
|
|
|
vname = OPTS.output_path + s.name + ".v"
|
|
|
|
|
print("Verilog: Writing to {0}".format(vname))
|
2017-12-19 18:01:24 +01:00
|
|
|
s.verilog_write(vname)
|
2017-12-19 18:55:59 +01:00
|
|
|
last_time=print_time("Verilog", datetime.datetime.now(), last_time)
|
2016-11-08 18:57:35 +01:00
|
|
|
|
2016-11-11 23:05:14 +01:00
|
|
|
globals.end_openram()
|
2017-11-14 22:24:14 +01:00
|
|
|
print_time("End",datetime.datetime.now(), start_time)
|