mirror of https://github.com/VLSIDA/OpenRAM.git
Merge branch 'dev' into elmore_model_tuning
This commit is contained in:
commit
c308dd34a4
|
|
@ -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/
|
||||
|
||||
|
|
@ -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}%)/'
|
||||
|
||||
26
README.md
26
README.md
|
|
@ -4,13 +4,9 @@
|
|||
[](./LICENSE)
|
||||
|
||||
Master:
|
||||
[](https://github.com/VLSIDA/OpenRAM/commits/master)
|
||||

|
||||
[](https://github.com/VLSIDA/OpenRAM/archive/master.zip)
|
||||
|
||||
Dev:
|
||||
[](https://github.com/VLSIDA/OpenRAM/commits/dev)
|
||||

|
||||
[](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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.")
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
Loading…
Reference in New Issue