Merge branch 'dev' into elmore_model_tuning

This commit is contained in:
Hunter Nichols 2021-02-15 14:50:56 -08:00
commit c308dd34a4
382 changed files with 5695 additions and 718 deletions

55
.github/workflows/ci.yml vendored Normal file
View File

@ -0,0 +1,55 @@
name: ci
on: [push]
jobs:
scn4me_subm:
runs-on: self-hosted
steps:
- name: Check out repository
uses: actions/checkout@v1
- name: SCMOS test
run: |
. /home/github-runner/setup-paths.sh
export OPENRAM_HOME="`pwd`/compiler"
export OPENRAM_TECH="`pwd`/technology:/software/PDKs/skywater-tech"
export OPENRAM_TMP="`pwd`/scn4me_subm"
python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 48 -t scn4m_subm
- name: Archive
if: ${{ failure() }}
uses: actions/upload-artifact@v2
with:
name: scn4me_subm Archives
path: $OPENRAM_TMP/
freepdk45:
runs-on: self-hosted
steps:
- name: Check out repository
uses: actions/checkout@v1
- name: FreePDK45 test
run: |
. /home/github-runner/setup-paths.sh
export OPENRAM_HOME="`pwd`/compiler"
export OPENRAM_TECH="`pwd`/technology:/software/PDKs/skywater-tech"
export OPENRAM_TMP="`pwd`/freepdk45"
python3-coverage run -p $OPENRAM_HOME/tests/regress.py -j 48 -t freepdk45
- name: Archive
if: ${{ failure() }}
uses: actions/upload-artifact@v2
with:
name: FreePDK45 Archives
path: $OPENRAM_TMP/
coverage:
if: ${{ always() }}
needs: [scn4me_subm, freepdk45]
runs-on: self-hosted
steps:
- name: Coverage stats
run: |
python3-coverage combine
python3-coverage report
python3-coverage html -d coverage_html
- name: Archive coverage
uses: actions/upload-artifact@v2
with:
name: code-coverage-report
path: coverage_html/

View File

@ -1,48 +0,0 @@
before_script:
- . /home/gitlab-runner/setup-paths.sh
- export OPENRAM_HOME="`pwd`/compiler"
- export OPENRAM_TECH="`pwd`/technology:/home/PDKs/skywater-tech"
stages:
- test
- coverage
freepdk45:
stage: test
script:
- coverage run -p $OPENRAM_HOME/tests/regress.py -t freepdk45
artifacts:
paths:
- .coverage.*
expire_in: 1 week
scn4m_subm:
stage: test
script:
- coverage run -p $OPENRAM_HOME/tests/regress.py -t scn4m_subm
artifacts:
paths:
- .coverage.*
expire_in: 1 week
# s8:
# stage: test
# script:
# - coverage run -p $OPENRAM_HOME/tests/regress.py -t s8
# artifacts:
# paths:
# - .coverage.*
# expire_in: 1 week
coverage:
stage: coverage
script:
- coverage combine
- coverage report
- coverage html -d coverage_html
artifacts:
paths:
- coverage_html
expire_in: 1 week
coverage: '/TOTAL.+ ([0-9]{1,3}%)/'

View File

@ -4,13 +4,9 @@
[![License: BSD 3-clause](./images/license_badge.svg)](./LICENSE)
Master:
[![Pipeline Status](https://scone.soe.ucsc.edu:8888/mrg/OpenRAM/badges/master/pipeline.svg)](https://github.com/VLSIDA/OpenRAM/commits/master)
![Coverage](https://scone.soe.ucsc.edu:8888/mrg/OpenRAM/badges/master/coverage.svg)
[![Download](./images/download-stable-blue.svg)](https://github.com/VLSIDA/OpenRAM/archive/master.zip)
Dev:
[![Pipeline Status](https://scone.soe.ucsc.edu:8888/mrg/OpenRAM/badges/dev/pipeline.svg)](https://github.com/VLSIDA/OpenRAM/commits/dev)
![Coverage](https://scone.soe.ucsc.edu:8888/mrg/OpenRAM/badges/dev/coverage.svg)
[![Download](./images/download-unstable-blue.svg)](https://github.com/VLSIDA/OpenRAM/archive/dev.zip)
An open-source static random access memory (SRAM) compiler.
@ -43,12 +39,12 @@ The OpenRAM compiler has very few dependencies:
If you want to perform DRC and LVS, you will need either:
+ Calibre (for [FreePDK45])
+ [Magic] 8.3.27 or higher (for [SCMOS])
+ [Netgen] 1.5 (for [SCMOS])
+ [Magic] 8.3.130 or newer
+ [Netgen] 1.5.164 or newer
You must set two environment variables:
+ OPENRAM\_HOME should point to the compiler source directory.
+ OPENERAM\_TECH should point to a root technology directory.
+ OPENERAM\_TECH should point to one or more root technology directories (colon separated).
## Environment
@ -65,11 +61,11 @@ You may also wish to add OPENRAM\_HOME to your PYTHONPATH:
export PYTHONPATH="$PYTHONPATH:$OPENRAM_HOME"
```
We include the tech files necessary for [SCMOS]
SCN4M_SUBM. The [SCMOS] spice models, however, are generic and should
be replaced with foundry models. If you are using [FreePDK45], you
should also have that set up and have the environment variable point
to the PDK. For example add this to your .bashrc:
We include the tech files necessary for [SCMOS] SCN4M_SUBM. The
[SCMOS] spice models, however, are generic and should be replaced with
foundry models. If you are using [FreePDK45], you should also have
that set up and have the environment variable point to the PDK. For
example add this to your .bashrc:
```
export FREEPDK45="/bsoe/software/design-kits/FreePDK45"
@ -160,9 +156,9 @@ specific technology (e.g., [FreePDK45]) should be a subdirectory
* dff.gds
* sense_amp.gds
* write_driver.gds
* cell_6t.gds
* replica\_cell\_6t.gds
* dummy\_cell\_6t.gds
* cell_1rw.gds
* replica\_cell\_1rw.gds
* dummy\_cell\_1rw.gds
* sp_lib folder with all the .sp (premade) library netlists for the above cells.
* layers.map
* A valid tech Python module (tech directory with \_\_init\_\_.py and tech.py) with:

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -57,6 +57,12 @@ class design(hierarchy_design):
self.cell_name,
GDS["unit"])
# Convert names back to the original names
# so that copying will use the new names
for pin_name in self.pin_map:
for index1, pin in enumerate(self.pin_map[pin_name]):
self.pin_map[pin_name][index1].name = self.get_original_pin_name(pin.name)
self.width = width
self.height = height

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -1235,7 +1235,6 @@ class layout():
self.add_power_pin(new_name, pin.center(), start_layer=start_layer)
def add_power_pin(self, name, loc, directions=None, start_layer="m1"):
# Hack for min area
if OPTS.tech_name == "sky130":
min_area = drc["minarea_{}".format(self.pwr_grid_layer)]

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,23 +1,26 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import os
import debug
import globals
from globals import OPTS,find_exe,get_tool
from globals import OPTS, find_exe, get_tool
from .lib import *
from .delay import *
from .elmore import *
from .linear_regression import *
from .setup_hold import *
from .functional import *
from .simulation import *
from .measurements import *
from .model_check import *
from .analytical_util import *
from .regression_model import *
debug.info(1,"Initializing characterizer...")
debug.info(1, "Initializing characterizer...")
OPTS.spice_exe = ""
if not OPTS.analytical_delay:
@ -26,17 +29,17 @@ if not OPTS.analytical_delay:
if OPTS.spice_name != "":
OPTS.spice_exe=find_exe(OPTS.spice_name)
if OPTS.spice_exe=="" or OPTS.spice_exe==None:
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_name),1)
debug.error("{0} not found. Unable to perform characterization.".format(OPTS.spice_name), 1)
else:
(OPTS.spice_name,OPTS.spice_exe) = get_tool("spice",["hspice", "ngspice", "ngspice.exe", "xa"])
(OPTS.spice_name, OPTS.spice_exe) = get_tool("spice", ["ngspice", "ngspice.exe", "hspice", "xa"])
# set the input dir for spice files if using ngspice
if OPTS.spice_name == "ngspice":
os.environ["NGSPICE_INPUT_DIR"] = "{0}".format(OPTS.openram_temp)
if OPTS.spice_exe == "":
debug.error("No recognizable spice version found. Unable to perform characterization.",1)
debug.error("No recognizable spice version found. Unable to perform characterization.", 1)
else:
debug.info(1,"Analytical model enabled.")
debug.info(1, "Analytical model enabled.")

View File

@ -0,0 +1,310 @@
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
import debug
import csv
import math
import numpy as np
import os
process_transform = {'SS':0.0, 'TT': 0.5, 'FF':1.0}
def get_data_names(file_name):
"""
Returns just the data names in the first row of the CSV
"""
with open(file_name, newline='') as csvfile:
csv_reader = csv.reader(csvfile, delimiter=' ', quotechar='|')
row_iter = 0
# reader is iterable not a list, probably a better way to do this
for row in csv_reader:
# Return names from first row
return row[0].split(',')
def get_data(file_name):
"""
Returns data in CSV as lists of features
"""
with open(file_name, newline='') as csvfile:
csv_reader = csv.reader(csvfile, delimiter=' ', quotechar='|')
row_iter = 0
for row in csv_reader:
row_iter += 1
if row_iter == 1:
feature_names = row[0].split(',')
input_list = [[] for _ in feature_names]
scaled_list = [[] for _ in feature_names]
try:
process_ind = feature_names.index('process')
except:
debug.error('Process not included as a feature.')
continue
data = []
split_str = row[0].split(',')
for i in range(len(split_str)):
if i == process_ind:
data.append(process_transform[split_str[i]])
else:
data.append(float(split_str[i]))
data[0] = math.log(data[0], 2)
for i in range(len(data)):
input_list[i].append(data[i])
return input_list
def apply_samples_to_data(all_data, algo_samples):
# Take samples from algorithm and match them to samples in data
data_samples, unused_data = [], []
sample_positions = set()
for sample in algo_samples:
sample_positions.add(find_sample_position_with_min_error(all_data, sample))
for i in range(len(all_data)):
if i in sample_positions:
data_samples.append(all_data[i])
else:
unused_data.append(all_data[i])
return data_samples, unused_data
def find_sample_position_with_min_error(data, sampled_vals):
min_error = 0
sample_pos = 0
count = 0
for data_slice in data:
error = squared_error(data_slice, sampled_vals)
if min_error == 0 or error < min_error:
min_error = error
sample_pos = count
count += 1
return sample_pos
def squared_error(list_a, list_b):
error_sum = 0;
for a,b in zip(list_a, list_b):
error_sum+=(a-b)**2
return error_sum
def get_max_min_from_datasets(dir):
if not os.path.isdir(dir):
debug.warning("Input Directory not found:{}".format(dir))
return [], [], []
# Assuming all files are CSV
data_files = [f for f in os.listdir(dir) if os.path.isfile(os.path.join(dir, f))]
maxs,mins,sums,total_count = [],[],[],0
for file in data_files:
data = get_data(os.path.join(dir, file))
# Get max, min, sum, and count from every file
data_max, data_min, data_sum, count = [],[],[], 0
for feature_list in data:
data_max.append(max(feature_list))
data_min.append(min(feature_list))
data_sum.append(sum(feature_list))
count = len(feature_list)
# Aggregate the data
if not maxs or not mins or not sums:
maxs,mins,sums,total_count = data_max,data_min,data_sum,count
else:
for i in range(len(maxs)):
maxs[i] = max(data_max[i], maxs[i])
mins[i] = min(data_min[i], mins[i])
sums[i] = data_sum[i]+sums[i]
total_count+=count
avgs = [s/total_count for s in sums]
return maxs,mins,avgs
def get_max_min_from_file(path):
if not os.path.isfile(path):
debug.warning("Input file not found: {}".format(path))
return [], [], []
data = get_data(path)
# Get max, min, sum, and count from every file
data_max, data_min, data_sum, count = [],[],[], 0
for feature_list in data:
data_max.append(max(feature_list))
data_min.append(min(feature_list))
data_sum.append(sum(feature_list))
count = len(feature_list)
avgs = [s/count for s in data_sum]
return data_max, data_min, avgs
def get_data_and_scale(file_name, sample_dir):
maxs,mins,avgs = get_max_min_from_datasets(sample_dir)
# Get data
all_data = get_data(file_name)
# Scale data from file
self_scaled_data = [[] for _ in range(len(all_data[0]))]
self_maxs,self_mins = [],[]
for feature_list, cur_max, cur_min in zip(all_data,maxs, mins):
for i in range(len(feature_list)):
self_scaled_data[i].append((feature_list[i]-cur_min)/(cur_max-cur_min))
return np.asarray(self_scaled_data)
def rescale_data(data, old_maxs, old_mins, new_maxs, new_mins):
# unscale from old values, rescale by new values
data_new_scaling = []
for data_row in data:
scaled_row = []
for val, old_max,old_min, cur_max, cur_min in zip(data_row, old_maxs,old_mins, new_maxs, new_mins):
unscaled_data = val*(old_max-old_min) + old_min
scaled_row.append((unscaled_data-cur_min)/(cur_max-cur_min))
data_new_scaling.append(scaled_row)
return data_new_scaling
def sample_from_file(num_samples, file_name, sample_dir=None):
"""
Get a portion of the data from CSV file and scale it based on max/min of dataset.
Duplicate samples are trimmed.
"""
if sample_dir:
maxs,mins,avgs = get_max_min_from_datasets(sample_dir)
else:
maxs,mins,avgs = [], [], []
# Get data
all_data = get_data(file_name)
# Get algorithms sample points, assuming hypercube for now
num_labels = 1
inp_dims = len(all_data) - num_labels
samples = np.random.rand(num_samples, inp_dims)
# Scale data from file
self_scaled_data = [[] for _ in range(len(all_data[0]))]
self_maxs,self_mins = [],[]
for feature_list in all_data:
max_val = max(feature_list)
self_maxs.append(max_val)
min_val = min(feature_list)
self_mins.append(min_val)
for i in range(len(feature_list)):
self_scaled_data[i].append((feature_list[i]-min_val)/(max_val-min_val))
# Apply algorithm sampling points to available data
sampled_data, unused_data = apply_samples_to_data(self_scaled_data,samples)
#unscale values and rescale using all available data (both sampled and unused points rescaled)
if len(maxs)!=0 and len(mins)!=0:
sampled_data = rescale_data(sampled_data, self_maxs,self_mins, maxs, mins)
unused_new_scaling = rescale_data(unused_data, self_maxs,self_mins, maxs, mins)
return np.asarray(sampled_data), np.asarray(unused_new_scaling)
def get_scaled_data(file_name):
"""Get data from CSV file and scale it based on max/min of dataset"""
if file_name:
maxs,mins,avgs = get_max_min_from_file(file_name)
else:
maxs,mins,avgs = [], [], []
# Get data
all_data = get_data(file_name)
# Data is scaled by max/min and data format is changed to points vs feature lists
self_scaled_data = scale_data_and_transform(all_data)
samples = np.asarray(self_scaled_data)
features, labels = samples[:, :-1], samples[:,-1:]
return features, labels
def scale_data_and_transform(data):
"""
Assume data is a list of features, change to a list of points and max/min scale
"""
scaled_data = [[] for _ in range(len(data[0]))]
for feature_list in data:
max_val = max(feature_list)
min_val = min(feature_list)
for i in range(len(feature_list)):
if max_val == min_val:
scaled_data[i].append(0.0)
else:
scaled_data[i].append((feature_list[i]-min_val)/(max_val-min_val))
return scaled_data
def scale_input_datapoint(point, file_path):
"""
Input data has no output and needs to be scaled like the model inputs during
training.
"""
maxs, mins, avgs = get_max_min_from_file(file_path)
debug.info(3, "maxs={}".format(maxs))
debug.info(3, "mins={}".format(mins))
debug.info(3, "point={}".format(point))
scaled_point = []
for feature, mx, mn in zip(point, maxs, mins):
if mx == mn:
scaled_point.append(0.0)
else:
scaled_point.append((feature-mn)/(mx-mn))
return scaled_point
def unscale_data(data, file_path, pos=None):
if file_path:
maxs,mins,avgs = get_max_min_from_file(file_path)
else:
debug.error("Must provide reference data to unscale")
return None
# Hard coded to only convert the last max/min (i.e. the label of the data)
if pos == None:
maxs,mins,avgs = [maxs[-1]],[mins[-1]],[avgs[-1]]
else:
maxs,mins,avgs = [maxs[pos]],[mins[pos]],[avgs[pos]]
unscaled_data = []
for data_row in data:
unscaled_row = []
for val, cur_max, cur_min in zip(data_row, maxs, mins):
unscaled_val = val*(cur_max-cur_min) + cur_min
unscaled_row.append(unscaled_val)
unscaled_data.append(unscaled_row)
return unscaled_data
def abs_error(labels, preds):
total_error = 0
for label_i, pred_i in zip(labels, preds):
cur_error = abs(label_i[0]-pred_i[0])/label_i[0]
total_error += cur_error
return total_error/len(labels)
def max_error(labels, preds):
mx_error = 0
for label_i, pred_i in zip(labels, preds):
cur_error = abs(label_i[0]-pred_i[0])/label_i[0]
mx_error = max(cur_error, mx_error)
return mx_error
def min_error(labels, preds):
mn_error = 1
for label_i, pred_i in zip(labels, preds):
cur_error = abs(label_i[0]-pred_i[0])/label_i[0]
mn_error = min(cur_error, mn_error)
return mn_error

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -52,21 +52,6 @@ class delay(simulation):
self.create_signal_names()
self.add_graph_exclusions()
def create_measurement_names(self):
""" Create measurement names. The names themselves currently define the type of measurement """
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
self.power_meas_names = ["read0_power",
"read1_power",
"write0_power",
"write1_power",
"disabled_read0_power",
"disabled_read1_power",
"disabled_write0_power",
"disabled_write1_power"]
# self.voltage_when_names = ["volt_bl", "volt_br"]
# self.bitline_delay_names = ["delay_bl", "delay_br"]
def create_measurement_objects(self):
""" Create the measurements used for read and write ports """
@ -525,7 +510,7 @@ class delay(simulation):
elif delay_obj.meta_str == sram_op.READ_ONE:
meas_cycle_delay = self.cycle_times[self.measure_cycles[port][delay_obj.meta_str]]
else:
debug.error("Unrecognised delay Index={}".format(delay_obj.meta_str),1)
debug.error("Unrecognized delay Index={}".format(delay_obj.meta_str),1)
# These measurements have there time further delayed to the neg. edge of the clock.
if delay_obj.meta_add_delay:
@ -1037,29 +1022,11 @@ class delay(simulation):
"""
Probe address and data can be set separately to utilize other
functions in this characterizer besides analyze.
Netlist reduced for simulation.
"""
self.probe_address = probe_address
self.probe_data = probe_data
self.bitline_column = self.get_data_bit_column_number(probe_address, probe_data)
self.wordline_row = self.get_address_row_number(probe_address)
super().set_probe(probe_address, probe_data)
self.prepare_netlist()
def get_data_bit_column_number(self, probe_address, probe_data):
"""Calculates bitline column number of data bit under test using bit position and mux size"""
if self.sram.col_addr_size>0:
col_address = int(probe_address[0:self.sram.col_addr_size], 2)
else:
col_address = 0
bl_column = int(self.sram.words_per_row * probe_data + col_address)
return bl_column
def get_address_row_number(self, probe_address):
"""Calculates wordline row number of data bit under test using address and column mux size"""
return int(probe_address[self.sram.col_addr_size:], 2)
def prepare_netlist(self):
""" Prepare a trimmed netlist and regular netlist. """
@ -1303,89 +1270,6 @@ class delay(simulation):
# Add test cycle of read/write port pair. One port could have been used already, but the other has not.
self.gen_test_cycles_one_port(cur_read_port, cur_write_port)
def sum_delays(self, delays):
"""Adds the delays (delay_data objects) so the correct slew is maintained"""
delay = delays[0]
for i in range(1, len(delays)):
delay+=delays[i]
return delay
def analytical_delay(self, slews, loads):
"""
Return the analytical model results for the SRAM.
"""
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
debug.warning("In analytical mode, all ports have the timing of the first read port.")
# Probe set to 0th bit, does not matter for analytical delay.
self.set_probe('0' * self.addr_size, 0)
self.create_graph()
self.set_internal_spice_names()
self.create_measurement_names()
port = self.read_ports[0]
self.graph.get_all_paths('{}{}'.format("clk", port),
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
# Select the path with the bitline (bl)
bl_name, br_name = self.get_bl_name(self.graph.all_paths, port)
bl_path = [path for path in self.graph.all_paths if bl_name in path][0]
# Set delay/power for slews and loads
port_data = self.get_empty_measure_data_dict()
power = self.analytical_power(slews, loads)
debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)')
max_delay = 0.0
for slew in slews:
for load in loads:
# Calculate delay based on slew and load
path_delays = self.graph.get_timing(bl_path, self.corner, slew, load)
total_delay = self.sum_delays(path_delays)
max_delay = max(max_delay, total_delay.delay)
debug.info(1,
'{}, {}, {}, {}'.format(slew,
load,
total_delay.delay / 1e3,
total_delay.slew / 1e3))
# Delay is only calculated on a single port and replicated for now.
for port in self.all_ports:
for mname in self.delay_meas_names + self.power_meas_names:
if "power" in mname:
port_data[port][mname].append(power.dynamic)
elif "delay" in mname and port in self.read_ports:
port_data[port][mname].append(total_delay.delay / 1e3)
elif "slew" in mname and port in self.read_ports:
port_data[port][mname].append(total_delay.slew / 1e3)
else:
debug.error("Measurement name not recognized: {}".format(mname), 1)
# Margin for error in period. Calculated by averaging required margin for a small and large
# memory. FIXME: margin is quite large, should be looked into.
period_margin = 1.85
sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin,
"leakage_power": power.leakage}
debug.info(2, "SRAM Data:\n{}".format(sram_data))
debug.info(2, "Port Data:\n{}".format(port_data))
return (sram_data, port_data)
def analytical_power(self, slews, loads):
"""Get the dynamic and leakage power from the SRAM"""
# slews unused, only last load is used
load = loads[-1]
power = self.sram.analytical_power(self.corner, load)
# convert from nW to mW
power.dynamic /= 1e6
power.leakage /= 1e6
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic))
debug.info(1, "Leakage Power: {0} mW".format(power.leakage))
return power
def gen_data(self):
""" Generates the PWL data inputs for a simulation timing test. """
@ -1412,11 +1296,3 @@ class delay(simulation):
self.stim.gen_pwl("CSB{0}".format(port), self.cycle_times, self.csb_values[port], self.period, self.slew, 0.05)
if port in self.readwrite_ports:
self.stim.gen_pwl("WEB{0}".format(port), self.cycle_times, self.web_values[port], self.period, self.slew, 0.05)
def get_empty_measure_data_dict(self):
"""Make a dict of lists for each type of delay and power measurement to append results to"""
measure_names = self.delay_meas_names + self.power_meas_names
# Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists.
measure_data = [{mname: [] for mname in measure_names} for i in self.all_ports]
return measure_data

View File

@ -0,0 +1,106 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from .simulation import simulation
from globals import OPTS
import debug
class elmore(simulation):
"""
Delay model for the SRAM which calculates Elmore delays along the SRAM critical path.
"""
def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner)
# self.targ_read_ports = []
# self.targ_write_ports = []
# self.period = 0
# if self.write_size:
# self.num_wmasks = int(math.ceil(self.word_size / self.write_size))
# else:
# self.num_wmasks = 0
#self.set_load_slew(0, 0)
self.set_corner(corner)
self.create_signal_names()
self.add_graph_exclusions()
def get_lib_values(self, slews, loads):
"""
Return the analytical model results for the SRAM.
"""
if OPTS.num_rw_ports > 1 or OPTS.num_w_ports > 0 and OPTS.num_r_ports > 0:
debug.warning("In analytical mode, all ports have the timing of the first read port.")
# Probe set to 0th bit, does not matter for analytical delay.
self.set_probe('0' * self.addr_size, 0)
self.create_graph()
self.set_internal_spice_names()
self.create_measurement_names()
port = self.read_ports[0]
self.graph.get_all_paths('{}{}'.format("clk", port),
'{}{}_{}'.format(self.dout_name, port, self.probe_data))
# Select the path with the bitline (bl)
bl_name, br_name = self.get_bl_name(self.graph.all_paths, port)
bl_path = [path for path in self.graph.all_paths if bl_name in path][0]
# Set delay/power for slews and loads
port_data = self.get_empty_measure_data_dict()
power = self.analytical_power(slews, loads)
debug.info(1, 'Slew, Load, Delay(ns), Slew(ns)')
max_delay = 0.0
for slew in slews:
for load in loads:
# Calculate delay based on slew and load
path_delays = self.graph.get_timing(bl_path, self.corner, slew, load)
total_delay = self.sum_delays(path_delays)
max_delay = max(max_delay, total_delay.delay)
debug.info(1,
'{}, {}, {}, {}'.format(slew,
load,
total_delay.delay / 1e3,
total_delay.slew / 1e3))
# Delay is only calculated on a single port and replicated for now.
for port in self.all_ports:
for mname in self.delay_meas_names + self.power_meas_names:
if "power" in mname:
port_data[port][mname].append(power.dynamic)
elif "delay" in mname and port in self.read_ports:
port_data[port][mname].append(total_delay.delay / 1e3)
elif "slew" in mname and port in self.read_ports:
port_data[port][mname].append(total_delay.slew / 1e3)
else:
debug.error("Measurement name not recognized: {}".format(mname), 1)
# Margin for error in period. Calculated by averaging required margin for a small and large
# memory. FIXME: margin is quite large, should be looked into.
period_margin = 1.85
sram_data = {"min_period": (max_delay / 1e3) * 2 * period_margin,
"leakage_power": power.leakage}
debug.info(2, "SRAM Data:\n{}".format(sram_data))
debug.info(2, "Port Data:\n{}".format(port_data))
return (sram_data, port_data)
def analytical_power(self, slews, loads):
"""Get the dynamic and leakage power from the SRAM"""
# slews unused, only last load is used
load = loads[-1]
power = self.sram.analytical_power(self.corner, load)
# convert from nW to mW
power.dynamic /= 1e6
power.leakage /= 1e6
debug.info(1, "Dynamic Power: {0} mW".format(power.dynamic))
debug.info(1, "Leakage Power: {0} mW".format(power.leakage))
return power

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -74,26 +74,38 @@ class lib:
self.corners = []
self.lib_files = []
# Nominal corner
corner_set = set()
nom_corner = (nom_process, nom_supply, nom_temperature)
corner_set.add(nom_corner)
if not OPTS.nominal_corner_only:
# Temperature corners
corner_set.add((nom_process, nom_supply, min_temperature))
corner_set.add((nom_process, nom_supply, max_temperature))
# Supply corners
corner_set.add((nom_process, min_supply, nom_temperature))
corner_set.add((nom_process, max_supply, nom_temperature))
# Process corners
corner_set.add((min_process, nom_supply, nom_temperature))
corner_set.add((max_process, nom_supply, nom_temperature))
# Enforce that nominal corner is the first to be characterized
self.add_corner(*nom_corner)
corner_set.remove(nom_corner)
for corner_tuple in corner_set:
if OPTS.use_specified_corners == None:
# Nominal corner
corner_tuples = set()
if OPTS.only_use_config_corners:
if OPTS.nominal_corner_only:
debug.warning("Nominal corner only option ignored if use only config corners is set.")
# Generate a powerset of input PVT lists
for p in self.process_corners:
for v in self.supply_voltages:
for t in self.temperatures:
corner_tuples.add((p, v, t))
else:
nom_corner = (nom_process, nom_supply, nom_temperature)
corner_tuples.add(nom_corner)
if not OPTS.nominal_corner_only:
# Temperature corners
corner_tuples.add((nom_process, nom_supply, min_temperature))
corner_tuples.add((nom_process, nom_supply, max_temperature))
# Supply corners
corner_tuples.add((nom_process, min_supply, nom_temperature))
corner_tuples.add((nom_process, max_supply, nom_temperature))
# Process corners
corner_tuples.add((min_process, nom_supply, nom_temperature))
corner_tuples.add((max_process, nom_supply, nom_temperature))
# Enforce that nominal corner is the first to be characterized
self.add_corner(*nom_corner)
corner_tuples.remove(nom_corner)
else:
corner_tuples = OPTS.use_specified_corners
for corner_tuple in corner_tuples:
self.add_corner(*corner_tuple)
def add_corner(self, proc, volt, temp):
@ -581,18 +593,28 @@ class lib:
def compute_delay(self):
"""Compute SRAM delays for current corner"""
self.d = delay(self.sram, self.sp_file, self.corner)
if self.use_model:
char_results = self.d.analytical_delay(self.slews,self.loads)
self.char_sram_results, self.char_port_results = char_results
model_name_lc = OPTS.model_name.lower()
if model_name_lc == "linear_regression":
from .linear_regression import linear_regression as model
elif model_name_lc == "elmore":
from .elmore import elmore as model
else:
debug.error("{} model not recognized. See options.py for available models.".format(OPTS.model_name))
import math
m = model(self.sram, self.sp_file, self.corner)
char_results = m.get_lib_values(self.slews,self.loads)
else:
self.d = delay(self.sram, self.sp_file, self.corner)
if (self.sram.num_spare_rows == 0):
probe_address = "1" * self.sram.addr_size
else:
probe_address = "0" + "1" * (self.sram.addr_size - 1)
probe_data = self.sram.word_size - 1
char_results = self.d.analyze(probe_address, probe_data, self.slews, self.loads)
self.char_sram_results, self.char_port_results = char_results
self.char_sram_results, self.char_port_results = char_results
def compute_setup_hold(self):
""" Do the analysis if we haven't characterized a FF yet """
@ -607,6 +629,79 @@ class lib:
def parse_info(self,corner,lib_name):
""" Copies important characterization data to datasheet.info to be added to datasheet """
if OPTS.output_datasheet_info:
datasheet_path = OPTS.output_path
else:
datasheet_path = OPTS.openram_temp
datasheet = open(datasheet_path +'/datasheet.info', 'a+')
self.write_inp_params_datasheet(datasheet, corner, lib_name)
self.write_signal_from_ports(datasheet,
"din{1}[{0}:0]".format(self.sram.word_size - 1, '{}'),
self.write_ports,
"setup_times_LH",
"setup_times_HL",
"hold_times_LH",
"hold_times_HL")
# self.write_signal_from_ports(datasheet,
# "dout{1}[{0}:0]".format(self.sram.word_size - 1, '{}'),
# self.read_ports,
# "delay_lh",
# "delay_hl",
# "slew_lh",
# "slew_hl")
for port in self.all_ports:
#dout timing
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"])))
))
self.write_signal_from_ports(datasheet,
"csb{}",
self.all_ports,
"setup_times_LH",
"setup_times_HL",
"hold_times_LH",
"hold_times_HL")
self.write_signal_from_ports(datasheet,
"addr{1}[{0}:0]".format(self.sram.addr_size - 1, '{}'),
self.all_ports,
"setup_times_LH",
"setup_times_HL",
"hold_times_LH",
"hold_times_HL")
self.write_signal_from_ports(datasheet,
"web{}",
self.readwrite_ports,
"setup_times_LH",
"setup_times_HL",
"hold_times_LH",
"hold_times_HL")
self.write_power_datasheet(datasheet)
self.write_model_params(datasheet)
datasheet.write("END\n")
datasheet.close()
def write_inp_params_datasheet(self, datasheet, corner, lib_name):
if OPTS.is_unit_test:
git_id = 'FFFFFFFFFFFFFFFFFFFF'
@ -624,11 +719,9 @@ class lib:
# check if git id is valid
if len(git_id) != 40:
debug.warning("Failed to retrieve git id")
git_id = 'Failed to retruieve'
datasheet = open(OPTS.openram_temp +'/datasheet.info', 'a+')
git_id = 'Failed to retrieve'
current_time = datetime.date.today()
# write static information to be parser later
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15},{16},".format(
OPTS.output_name,
@ -656,104 +749,26 @@ class lib:
# write area
datasheet.write(str(self.sram.width * self.sram.height) + ',')
# write timing information for all ports
for port in self.all_ports:
#din timings
if port in self.write_ports:
datasheet.write("{0},{1},{2},{3},{4},{5},{6},{7},{8},".format(
"din{1}[{0}:0]".format(self.sram.word_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:
#dout timing
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
def write_signal_from_ports(self, datasheet, signal, ports, time_pos_1, time_pos_2, time_pos_3, time_pos_4):
for port in ports:
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"]))),
signal.format(port),
min(list(map(round_time,self.times[time_pos_1]))),
max(list(map(round_time,self.times[time_pos_1]))),
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[time_pos_2]))),
max(list(map(round_time,self.times[time_pos_2]))),
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[time_pos_3]))),
max(list(map(round_time,self.times[time_pos_3]))),
min(list(map(round_time,self.times["hold_times_HL"]))),
max(list(map(round_time,self.times["hold_times_HL"])))
min(list(map(round_time,self.times[time_pos_4]))),
max(list(map(round_time,self.times[time_pos_4])))
))
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"])))
))
def write_power_datasheet(self, datasheet):
# write power information
for port in self.all_ports:
name = ''
@ -792,7 +807,31 @@ class lib:
control_str += ' & csb{0}'.format(i)
datasheet.write("{0},{1},{2},".format('leak', control_str, self.char_sram_results["leakage_power"]))
datasheet.write("END\n")
datasheet.close()
def write_model_params(self, datasheet):
"""Write values which will be used in the analytical model as inputs"""
datasheet.write("{0},{1},".format('words_per_row', OPTS.words_per_row))
datasheet.write("{0},{1},".format('slews', list(self.slews)))
datasheet.write("{0},{1},".format('loads', list(self.loads)))
for port in self.read_ports:
datasheet.write("{0},{1},".format('cell_rise_{}'.format(port), self.char_port_results[port]["delay_lh"]))
datasheet.write("{0},{1},".format('cell_fall_{}'.format(port), self.char_port_results[port]["delay_hl"]))
datasheet.write("{0},{1},".format('rise_transition_{}'.format(port), self.char_port_results[port]["slew_lh"]))
datasheet.write("{0},{1},".format('fall_transition_{}'.format(port), self.char_port_results[port]["slew_hl"]))
for port in self.write_ports:
write1_power = np.mean(self.char_port_results[port]["write1_power"])
write0_power = np.mean(self.char_port_results[port]["write0_power"])
datasheet.write("{0},{1},".format('write_rise_power_{}'.format(port), write1_power))
#FIXME: should be write_fall_power
datasheet.write("{0},{1},".format('read_fall_power_{}'.format(port), write0_power))
for port in self.read_ports:
read1_power = np.mean(self.char_port_results[port]["read1_power"])
read0_power = np.mean(self.char_port_results[port]["read0_power"])
datasheet.write("{0},{1},".format('read_rise_power_{}'.format(port), read1_power))
#FIXME: should be read_fall_power
datasheet.write("{0},{1},".format('write_fall_power_{}'.format(port), read0_power))

View File

@ -0,0 +1,38 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from .regression_model import regression_model
from globals import OPTS
import debug
from sklearn.linear_model import LinearRegression
class linear_regression(regression_model):
def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner)
def generate_model(self, features, labels):
"""
Supervised training of model.
"""
model = LinearRegression()
model.fit(features, labels)
return model
def model_prediction(self, model, features):
"""
Have the model perform a prediction and unscale the prediction
as the model is trained with scaled values.
"""
pred = model.predict(features)
return pred

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -0,0 +1,48 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from .regression_model import regression_model
from globals import OPTS
import debug
from tensorflow import keras
from tensorflow.keras import layers
import tensorflow as tf
class neural_network(regression_model):
def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner)
def generate_model(self, features, labels):
"""
Supervised training of model.
"""
model = keras.Sequential([
layers.Dense(32, activation=tf.nn.relu, input_shape=[features.shape[1]]),
layers.Dense(32, activation=tf.nn.relu),
layers.Dense(32, activation=tf.nn.relu),
layers.Dense(1)
])
optimizer = keras.optimizers.RMSprop(0.0099)
model.compile(loss='mean_squared_error', optimizer=optimizer)
model.fit(features, labels, epochs=100, verbose=0)
return model
def model_prediction(self, model, features):
"""
Have the model perform a prediction and unscale the prediction
as the model is trained with scaled values.
"""
pred = model.predict(features)
return pred

View File

@ -0,0 +1,140 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
#
from .analytical_util import *
from .simulation import simulation
from globals import OPTS
import debug
import math
relative_data_path = "/sim_data"
data_fnames = ["rise_delay.csv",
"fall_delay.csv",
"rise_slew.csv",
"fall_slew.csv",
"write1_power.csv",
"write0_power.csv",
"read1_power.csv",
"read0_power.csv",
"leakage_data.csv"]
# Positions must correspond to data_fname list
lib_dnames = ["delay_lh",
"delay_hl",
"slew_lh",
"slew_hl",
"write1_power",
"write0_power",
"read1_power",
"read0_power",
"leakage_power"]
# Check if another data dir was specified
if OPTS.sim_data_path == None:
data_dir = OPTS.openram_tech+relative_data_path
else:
data_dir = OPTS.sim_data_path
data_paths = {dname:data_dir +'/'+fname for dname, fname in zip(lib_dnames, data_fnames)}
class regression_model(simulation):
def __init__(self, sram, spfile, corner):
super().__init__(sram, spfile, corner)
self.set_corner(corner)
def get_lib_values(self, slews, loads):
"""
A model and prediction is created for each output needed for the LIB
"""
debug.info(1, "Characterizing SRAM using linear regression models.")
log_num_words = math.log(OPTS.num_words, 2)
model_inputs = [log_num_words,
OPTS.word_size,
OPTS.words_per_row,
self.sram.width * self.sram.height,
process_transform[self.process],
self.vdd_voltage,
self.temperature]
self.create_measurement_names()
models = self.train_models()
# Set delay/power for slews and loads
port_data = self.get_empty_measure_data_dict()
debug.info(1, 'Slew, Load, Port, Delay(ns), Slew(ns)')
max_delay = 0.0
for slew in slews:
for load in loads:
# List returned with value order being delay, power, leakage, slew
sram_vals = self.get_predictions(model_inputs+[slew, load], models)
# Delay is only calculated on a single port and replicated for now.
for port in self.all_ports:
port_data[port]['delay_lh'].append(sram_vals['delay_lh'])
port_data[port]['delay_hl'].append(sram_vals['delay_hl'])
port_data[port]['slew_lh'].append(sram_vals['slew_lh'])
port_data[port]['slew_hl'].append(sram_vals['slew_hl'])
port_data[port]['write1_power'].append(sram_vals['write1_power'])
port_data[port]['write0_power'].append(sram_vals['write0_power'])
port_data[port]['read1_power'].append(sram_vals['read1_power'])
port_data[port]['read0_power'].append(sram_vals['read0_power'])
# Disabled power not modeled. Copied from other power predictions
port_data[port]['disabled_write1_power'].append(sram_vals['write1_power'])
port_data[port]['disabled_write0_power'].append(sram_vals['write0_power'])
port_data[port]['disabled_read1_power'].append(sram_vals['read1_power'])
port_data[port]['disabled_read0_power'].append(sram_vals['read0_power'])
debug.info(1, '{}, {}, {}, {}, {}'.format(slew,
load,
port,
sram_vals['delay_lh'],
sram_vals['slew_lh']))
# Estimate the period as double the delay with margin
period_margin = 0.1
sram_data = {"min_period": sram_vals['delay_lh'] * 2,
"leakage_power": sram_vals["leakage_power"]}
debug.info(2, "SRAM Data:\n{}".format(sram_data))
debug.info(2, "Port Data:\n{}".format(port_data))
return (sram_data, port_data)
def get_predictions(self, model_inputs, models):
"""
Generate a model and prediction for LIB output
"""
#Scaled the inputs using first data file as a reference
data_name = lib_dnames[0]
scaled_inputs = np.asarray([scale_input_datapoint(model_inputs, data_paths[data_name])])
predictions = {}
for dname in data_paths.keys():
path = data_paths[dname]
m = models[dname]
features, labels = get_scaled_data(path)
scaled_pred = self.model_prediction(m, scaled_inputs)
pred = unscale_data(scaled_pred.tolist(), path)
debug.info(2,"Unscaled Prediction = {}".format(pred))
predictions[dname] = pred[0][0]
return predictions
def train_models(self):
"""
Generate and return models
"""
models = {}
for dname, dpath in data_paths.items():
features, labels = get_scaled_data(dpath)
model = self.generate_model(features, labels)
models[dname] = model
return models

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -39,6 +39,21 @@ class simulation():
else:
self.num_wmasks = 0
def create_measurement_names(self):
""" Create measurement names. The names themselves currently define the type of measurement """
self.delay_meas_names = ["delay_lh", "delay_hl", "slew_lh", "slew_hl"]
self.power_meas_names = ["read0_power",
"read1_power",
"write0_power",
"write1_power",
"disabled_read0_power",
"disabled_read1_power",
"disabled_write0_power",
"disabled_write1_power"]
# self.voltage_when_names = ["volt_bl", "volt_br"]
# self.bitline_delay_names = ["delay_bl", "delay_br"]
def set_corner(self, corner):
""" Set the corner values """
self.corner = corner
@ -92,6 +107,32 @@ class simulation():
self.cycle_comments = []
self.fn_cycle_comments = []
def set_probe(self, probe_address, probe_data):
"""
Probe address and data can be set separately to utilize other
functions in this characterizer besides analyze.
"""
self.probe_address = probe_address
self.probe_data = probe_data
self.bitline_column = self.get_data_bit_column_number(probe_address, probe_data)
self.wordline_row = self.get_address_row_number(probe_address)
def get_data_bit_column_number(self, probe_address, probe_data):
"""Calculates bitline column number of data bit under test using bit position and mux size"""
if self.sram.col_addr_size>0:
col_address = int(probe_address[0:self.sram.col_addr_size], 2)
else:
col_address = 0
bl_column = int(self.sram.words_per_row * probe_data + col_address)
return bl_column
def get_address_row_number(self, probe_address):
"""Calculates wordline row number of data bit under test using address and column mux size"""
return int(probe_address[self.sram.col_addr_size:], 2)
def add_control_one_port(self, port, op):
"""Appends control signals for operation to a given port"""
# Determine values to write to port
@ -544,6 +585,21 @@ class simulation():
for i in range(len(bl_names)):
bl_names[i] = bl_names[i].split('.')[-1]
return bl_names[0], bl_names[1]
def get_empty_measure_data_dict(self):
"""Make a dict of lists for each type of delay and power measurement to append results to"""
measure_names = self.delay_meas_names + self.power_meas_names
# Create list of dicts. List lengths is # of ports. Each dict maps the measurement names to lists.
measure_data = [{mname: [] for mname in measure_names} for i in self.all_ports]
return measure_data
def sum_delays(self, delays):
"""Adds the delays (delay_data objects) so the correct slew is maintained"""
delay = delays[0]
for i in range(1, len(delays)):
delay+=delays[i]
return delay

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -312,12 +312,12 @@ class stimuli():
cmd = "{0} {1} -c {2}xa.cfg -o {2}xa -mt {3}".format(OPTS.spice_exe,
temp_stim,
OPTS.openram_temp,
OPTS.num_threads)
OPTS.num_sim_threads)
valid_retcode=0
elif OPTS.spice_name == "hspice":
# TODO: Should make multithreading parameter a configuration option
cmd = "{0} -mt {1} -i {2} -o {3}timing".format(OPTS.spice_exe,
OPTS.num_threads,
OPTS.num_sim_threads,
temp_stim,
OPTS.openram_temp)
valid_retcode=0
@ -326,7 +326,7 @@ class stimuli():
# Measurements can't be made with a raw file set in ngspice
# -r {2}timing.raw
ng_cfg = open("{}.spiceinit".format(OPTS.openram_temp), "w")
ng_cfg.write("set num_threads={}\n".format(OPTS.num_threads))
ng_cfg.write("set num_threads={}\n".format(OPTS.num_sim_threads))
ng_cfg.close()
cmd = "{0} -b -o {2}timing.lis {1}".format(OPTS.spice_exe,

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -28,7 +28,11 @@ class datasheet():
# css styling is kept in a seperate file
self.html += datasheet_css.read()
with open(OPTS.openram_temp + "/datasheet.info") as info:
if OPTS.output_datasheet_info:
datasheet_path = OPTS.output_path
else:
datasheet_path = OPTS.openram_temp
with open(datasheet_path + "/datasheet.info") as info:
self.html += '<!--'
for row in info:
self.html += row

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -633,13 +633,16 @@ def parse_characterizer_csv(f, pages):
class datasheet_gen():
def datasheet_write(name):
"""writes the datasheet to a file"""
in_dir = OPTS.openram_temp
if OPTS.output_datasheet_info:
datasheet_path = OPTS.output_path
else:
datasheet_path = OPTS.openram_temp
if not (os.path.isdir(in_dir)):
os.mkdir(in_dir)
if not (os.path.isdir(datasheet_path)):
os.mkdir(datasheet_path)
datasheets = []
parse_characterizer_csv(in_dir + "/datasheet.info", datasheets)
parse_characterizer_csv(datasheet_path + "/datasheet.info", datasheets)
for sheets in datasheets:
with open(name, 'w+') as f:

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -2,7 +2,7 @@ word_size = 32
num_words = 256
write_size = 8
local_array_size = 16
#local_array_size = 16
num_rw_ports = 1
num_r_ports = 1
@ -11,9 +11,9 @@ num_w_ports = 0
tech_name = "sky130"
nominal_corner_only = True
route_supplies = False
#route_supplies = False
check_lvsdrc = True
perimeter_pins = False
#perimeter_pins = False
#netlist_only = True
#analytical_delay = False
output_name = "sram_{0}rw{1}r{2}w_{3}_{4}_{5}".format(num_rw_ports,

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.
@ -18,6 +18,9 @@ import sys
import re
import copy
import importlib
import getpass
import subprocess
VERSION = "1.1.9"
NAME = "OpenRAM v{}".format(VERSION)
@ -133,8 +136,9 @@ def print_banner():
debug.print_raw("|=========" + user_info.center(60) + "=========|")
dev_info = "Development help: openram-dev-group@ucsc.edu"
debug.print_raw("|=========" + dev_info.center(60) + "=========|")
temp_info = "Temp dir: {}".format(OPTS.openram_temp)
debug.print_raw("|=========" + temp_info.center(60) + "=========|")
if OPTS.openram_temp:
temp_info = "Temp dir: {}".format(OPTS.openram_temp)
debug.print_raw("|=========" + temp_info.center(60) + "=========|")
debug.print_raw("|=========" + "See LICENSE for license info".center(60) + "=========|")
debug.print_raw("|==============================================================================|")
@ -154,6 +158,17 @@ def check_versions():
# or, this could be done in each module (e.g. verify, characterizer, etc.)
global OPTS
def cmd_exists(cmd):
return subprocess.call("type " + cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0
if cmd_exists("coverage"):
OPTS.coverage_exe = "coverage run -p "
elif cmd_exists("python3-coverage"):
OPTS.coverage_exe = "python3-coverage run -p "
else:
OPTS.coverage_exe = ""
debug.warning("Failed to find coverage installation. This can be installed with pip3 install coverage")
try:
import coverage
OPTS.coverage = 1
@ -406,7 +421,7 @@ def setup_paths():
# Add all of the subdirs to the python path
# These subdirs are modules and don't need
# to be added: characterizer, verify
subdirlist = [ item for item in os.listdir(OPENRAM_HOME) if os.path.isdir(os.path.join(OPENRAM_HOME, item)) ]
subdirlist = [item for item in os.listdir(OPENRAM_HOME) if os.path.isdir(os.path.join(OPENRAM_HOME, item))]
for subdir in subdirlist:
full_path = "{0}/{1}".format(OPENRAM_HOME, subdir)
debug.check(os.path.isdir(full_path),
@ -414,6 +429,10 @@ def setup_paths():
if "__pycache__" not in full_path:
sys.path.append("{0}".format(full_path))
# Use a unique temp subdirectory
OPTS.openram_temp += "/openram_{0}_{1}_temp/".format(getpass.getuser(),
os.getpid())
if not OPTS.openram_temp.endswith('/'):
OPTS.openram_temp += "/"
debug.info(1, "Temporary files saved in " + OPTS.openram_temp)

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California
# Copyright (c) 2016-2021 Regents of the University of California
# All rights reserved.
#
from bitcell_base_array import bitcell_base_array

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

View File

@ -1,6 +1,6 @@
# See LICENSE for licensing information.
#
# Copyright (c) 2016-2019 Regents of the University of California and The Board
# Copyright (c) 2016-2021 Regents of the University of California and The Board
# of Regents for the Oklahoma Agricultural and Mechanical College
# (acting for and on behalf of Oklahoma State University)
# All rights reserved.

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