EDA Analytics Central - User Documentation¶
EDAAC is a Python package to collect, store and analyze data coming out of EDA (Electronic Design Automation) Flows.
$ pip install -U edaac
- Tutorial
A quick tutorial extracting Design Rule Violations (DRVs) from Cadence Innovus log file to get you up and running with EDAAC.
- User Guide
The Full guide to EDAAC — from collecting metrics to storing them, from querying data to advanced analytics and everything in-between.
- License
EDAAC is open-source under BSD-3 license.
- Feedback
EDAAC is community-driven. Please, share with us your feedback and feature requests.
Community¶
To get help with using EDAAC, use the GitHub Issues and label the issue with question.
Contributing¶
Yes please!
EDAAC is a young project and we are looking for contributions, additions and improvements.
The source is available on GitHub and contributions are always encouraged. Contributions can be as simple as minor tweaks to this documentation, API names, or event the core architecture.
To contribute, fork the project on GitHub and send a pull request.
Tutorial¶
This tutorial introduces EDAAC by means of example — we will walk through how to extract metrics from a log file that comes out of an EDA tool.
Metrics are essential information that we extract about a circuit (hardware design) at a specific stage of the tape-out process. For example, after Logic Synthesis, we might be interested to know the total number of standard cells used after mapping the design to a standard cell library. After Routing, we would be concerned with the total number of Design Rule Violations (DRVs). Instead of looking at the log files of EDA tools and searching through them for the important piece of information, EDAAC makes this straightforward for you.
To make use of the extracted metrics, EDAAC offers data models to store the collected metrics into a document-based database (MongoDB). This database can be used for further research and development of EDA tools.
Getting Started¶
If you haven’t installed EDAAC, simply use pip to install it like so:
$ pip install edaac
To verify the installation:
>>> import edaac
>>> edaac.version()
EDA Analytics Central (EDAAC) v0.0.11
Extracting Metrics¶
In this example, we show how to extract Design Rule Violations (DRVs) from a log file saved by Cadence Innovus.
Note
Since Cadence tools are proprietary software, we are unable to publish raw log files outputted by the tool. We will update this tutorial with example log files once we support open-source EDA tools.
Assuming you have generated a DRC report using a proper command within Innovus
to verify that the design meets the technology-defined constraints. The log file
is located at ./test_design.drc.rpt
.
Now, you can use the below Python code to extract DRVs into a metrics dictionary:
from edaac.metrics.parsers import parse_innovus_drc_report
log_file = './test_design.drc.rpt'
metrics = parse_innovus_drc_report(log_file)
print(metrics)
An example output would be:
{
'drv_total': 76,
'drv_short_metal_total': 30,
'drv_short_metal_area': 0.06930000,
'drv_short_cut_total': 0,
'drv_short_cut_area': 0.0,
'drv_out_of_die_total': 0,
'drv_out_of_die_area': 0.0,
'drv_spacing_total': 32,
'drv_spacing_parallel_run_length_total': 19,
'drv_spacing_eol_total': 13,
'drv_spacing_cut_total': 0,
'drv_min_area_total': 14
}
What just happened? Underneath, the function mines the log files for a number of metrics that it registered. In its core, it heavily uses regular expressions to look for patterns.
Why I can’t find the metric I’m looking for?
Most probably, the metric is not yet registered in the parsing function.
Help us improve the package by submitting an issue
with label enhancement
What’s Next?¶
EDAAC comes pre-loaded with a number of parsers ( ..and more under development). But that’s not all. Storing metrics effeciently for post-processing is as important as -if not more important than- collecting the metrics themeselves.
In the User Guide, we show more examples of using EDAAC for metrics processing and storage.
User Guide¶
Installing EDAAC¶
To use EDAAC, you will need to download MongoDB and ensure it is running in an accessible location. You will also need MongoEngine to use EDAAC, but if you install EDAAC using setuptools, then the dependencies will be handled for you.
EDAAC is available on PyPI, so you can use pip:
$ pip install edaac
Alternatively, if you don’t have setuptools installed, download it from PyPi and run
$ python setup.py install
To use the bleeding-edge version of EDAAC, you can get the source from GitHub and install it as above:
$ git clone git://github.com/EDAAC/EDAAC
$ cd EDAAC
$ python setup.py install
Collecting Metrics¶
Metrics are characteristics of design artifacts, processes, and inter-process communications during the an SoC design flow. The main idea behind pervasively collecting metrics is to measure the design process and quantify its Quality of Results (QoR). This has always been a prerequisite to optimizing it and continuously achieving maximum productivity.
EDAAC implements Metrics collection functionality in edaac.metrics
sub-package. Below, we document its functionality.
Synthsis Stats¶
We can extract useful statistics about a synthesized netlist that aid in the physical design process.
Supported Tools¶
Yosys
Usage¶
Generate a report from Yosys using the stat command.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_yosys_log metrics = parse_yosys_log('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
Version of yosys build used |
|
Total numner of standard cells |
|
Total area of standard cells |
|
Total number of wires |
|
Total number of wirebits |
|
Total number of memories |
|
Total number of memory bits |
|
Total number of warnings |
|
Total number of unique warnings |
|
CPU usage |
|
Memory usage |
Example¶
metrics = {
'run__synth__yosys_version': '0.9+1706 (git sha1 UNKNOWN, gcc 7.3.1 -fPIC -Os)',
'synth__inst__num__total': 272,
'synth__inst__stdcell__area__total': 407.512000,
'synth__wire__num__total': 297,
'synth__wirebits__num__total': 343,
'synth__memory__num__total': 0,
'synth__memorybits__num__total': 0,
'run__synth__warning__total': 90,
'run__synth__warning__unique__total': 26,
'run__synth__cpu__total': 1.21,
'run__synth__mem__total': 28.78
}
Design Rule Check¶
Design rules are geometric constraints imposed on an SoC to ensure that the design functions properly, reliably and can be manufactured by fabs.
A Design Rule Violation (DRV) is a record that represents a violation to the design rules defined by the technology library used.
Supported Tools¶
Cadence Innovus
Usage¶
Generate a report from Innovus using the instructions here.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_drc_report metrics = parse_innovus_drc_report('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
The total number of DRVs |
|
Total numner of short metal violations |
|
Total area of short metal violations |
|
Total number of cut spacing violations |
|
Total area of cut spacing violations |
|
Total number of components placed/routed out of die |
|
Total area of components placed/routed out of die |
|
Total number of spacing violations |
|
Total number of parallel run length violations |
|
Total number of end-of-line spacing violations |
|
Total number of cut spacing violations |
|
Total number of min-area violations |
Example¶
metrics = {
'drv_total': 101,
'drv_short_metal_total': 2,
'drv_short_metal_area': 0.02382500,
'drv_short_cut_total': 1,
'drv_short_cut_area': 0.0012500,
'drv_out_of_die_total': 0,
'drv_out_of_die_area': 0.0,
'drv_spacing_total': 41,
'drv_spacing_parallel_run_length_total': 7,
'drv_spacing_eol_total': 9,
'drv_spacing_cut_total': 25,
'drv_min_area_total': 57
}
Connectivity¶
This ensures that the circuit components are connected as in the schematic.
Supported Tools¶
Cadence Innovus
Usage¶
Generate a report from Innovus using the instructions here.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_conn_report metrics = parse_innovus_conn_report('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
Total number of open nets |
Example¶
metrics = {
'conn_open_nets': 22
}
Static Timing Analysis (STA)¶
Static Timing Analysis validates the timing performance of a design by checking all possible paths for timing violations under worst-case conditions.
The arrival time of a signal is the time elapsed for a signal to arrive at a certain point.
The required time is the latest time at which a signal can arrive without making the clock cycle longer than desired.
The slack associated with each connection is the difference between the required time and the arrival time. A positive slack s at some node implies that the arrival time at that node may be increased by s, without affecting the overall delay of the circuit. Conversely, negative slack implies that a path is too slow, and the path must be sped up (or the reference signal delayed) if the whole circuit is to work at the desired speed.
The critical path is defined as the path between an input and an output with the maximum delay. The critical path is sometimes referred to as the worst path. If this path has a negative slack, the circuit won’t work as expected at the desired speed.
Supported Tools¶
Cadence Innovus
OpenSTA
Usage¶
Generate a report from Innovus using the appropriate command. Or generate a report from OpenSTA using
report_tns
,report_wns
andreport_design_area
.Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_timing_report metrics = parse_innovus_timing_report('/path/to/report')
from edaac.metrics.parsers import parse_openroad_log metrics = parse_openroad_log('/path/to/report', 'OpenSTA')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary from Innovus¶
Key |
Meaning |
---|---|
|
Worst negative slack |
|
Total negative slack |
|
Number of violating paths |
Example¶
metrics = {
'timing_tns': -27.496,
'timing_wns': -0.851,
'timing_violating_paths': 35
}
Dictionary from OpenSTA¶
Key |
Meaning |
---|---|
|
Total negative slack |
|
Worst negative slack |
|
Total standard cell area |
|
Core utilization |
Example¶
metrics = {
'slack__negative__total': 0.00,
'slack__negative__worst': 0.00,
'std__area__total': 491.0,
'util': 8.0
}
Power¶
This reports the power consumption of the circuit.
Supported Tools¶
Cadence Innovus
Usage¶
Generate a report from Innovus using the appropriate command.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_power_report metrics = parse_innovus_power_report('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
Total internal power |
|
Total switching power |
|
Total leakage power |
|
Total power (sumof the above) |
|
Internal power / Total * 100.0 |
|
Swithing power / Total * 100.0 |
|
Leakage power / Total * 100.0 |
Example¶
metrics = {
'power_internal_total': 26.31116662,
'power_switching_total': 21.61735782,
'power_leakage_total': 13.58182182,
'power_total': 61.51034631,
'power_internal_percentage': 42.7752,
'power_switching_percentage': 35.1443,
'power_leakage_percentage': 22.0805
}
Area¶
This reports the area of the standard cells in addition to the cell count.
Supported Tools¶
Cadence Innovus
Usage¶
Generate the area report from Innovus using the appropriate command.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_area metrics = parse_innovus_area_report('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
Total area of standard cells (um^2) |
|
Total number of standard cells |
Example¶
metrics = {
'area_stdcell': 48191.040,
'area_stdcell_count': 11306
}
Compute Resources¶
This reports the compute resources (cpu, memory) used by a flow process.
Supported Tools¶
Cadence Innovus
Usage¶
Dump Innovus logs (that are shown on stdout) to a file.
Use
edaac.metrics.parsers
to parse the report.from edaac.metrics.parsers import parse_innovus_log metrics = parse_innovus_log('/path/to/report')
metrics
is a Python dictionary ofkey: value
pairs.print(metrics)
Dictionary¶
Key |
Meaning |
---|---|
|
Total time from all CPU cores (seconds) |
|
Total wall clock time (seconds) |
|
Total memory usage (MB) |
Example¶
metrics = {
'compute_cpu_time_total': 540,
'compute_real_time_total':184,
'compute_mem_total': 2287.4
}
Data Model¶
Managing the storage of the collected Metrics is a challenging task. Collecting metrics from hundreds, or even thousands, of EDA flows introduces the pondering question: How should we structure the data to make efficient use of it in predictive analytics applications?
EDAAC implements a general-purpose data model in edaac.models
sub-package. Below, we document its functionality.
Documents¶
EDAAC’s data model is an unstructured document that represents an SoC project during its different life stages (from logic synthesis to routing).
The root of the data model is a Project
document.
A Project
is a container for all related artifacts of the design lifecycle.
Below is a complete birds-eye view of the Project
document.
Usage: from edaac.models import Project
Every embedded document in the project has a class representation in edaac.models
.
For example, the technology
key in the project should be an instance of edaac.models.Technology
.
Similarly, design
, flow
, stage
and tool
should be instances of
edaac.models.Design
, edaac.models.Flow
, edaac.models.Stage
and edaac.models.Tool
respectively.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | {
"name": "<Project Name>",
"description": "<Project Description>",
"technology": {
"foundry": "<Example: TSMC>",
"process": 65,
"beol": "<Back End Of Line>",
"tracl": "<The height of the track>",
"opv": "<Operating voltage>",
"vt": "<Voltage threshold>",
"channel_width": "<Channel width>",
"config": "<Configuration>",
"version": "<Version>",
"rag": "<Red | Amber | Green>"
},
"design": {
"name": "<Design Name>",
"rtl_files": [
"<Absolute Path of verilog RTL file>",
"<Absolute Path of verilog RTL file>"
],
"netlist_file": "<Absolute path of netlist file (after synthesis)>",
"sdc_file": "<Absolute path of constraints file (ins .sdc format)>",
"runset_tag": "<RTL related tags for the release candidates>",
"runset_id": "<ID of the release candidates>",
"rtl_config": "<Configuration of RTL>",
"rtl_tag": "<Tags for the RTL>",
"rtl_rag": "<Red | Amber | Green>"
},
"flows": [
{
"flow_directory": "<Directory of the Flow>",
"params": {
"<Flow parameter>": "<value>",
"<Flow parameter>": "<value>"
},
"stages": [
{
"name": "<Stage name>",
"tool": {
"name": "<Tool name>",
"version": "<Tool version>"
},
"machine": "<Host name running this stage>",
"collection_mode": "<OFFLINE_FROM_LOGS | DURING_RUN_TIME>",
"status": "<NOT_STARTED | RUNNING | COMPLETED_SUCCESSFULLY | COMPLETED_WITH_ERRORS>",
"log_files": [
"<Absolute path of log file>",
"<Absolute path of log file>"
],
"metrics": {
"<Metric key>": "<value>",
"<Metric key>": "<value>"
}
}
],
"log_files": [
"<Absolute path of log file>",
"<Absolute path of log file>"
]
}
]
}
|
Note
rag: red: no verification ran on the design. amber: alpha or beta release with some levels of verifications. green: release candidate
Database¶
The question now is where do we store this these information? Answer: MongoDB.
Starting a MongoDB Server¶
Option 1: Docker
This is the easiest option to get started. Use the following command to start a local database server
docker run -d -p 27017:27017 -v /path/to/local/folder:/data/db --name edaac_db mongo
This will start a local MongoDB server on port 27017
(the default port for MongoDB).
It will also mount a folder at /path/to/local/folder
to the container to persist data when the container is stopped.
Option 2: Install Locally
Follow the instructions on the official documentation.
Option 3: Cloud Instance
Create a MongoDB instance on your cloud provider account using MongoDB Atlas.
Connecting to MongoDB¶
After starting the server, download MongoDB Compass to graphically connect to the database and ensure that it is running correctly.
Next, create a database with a give it a name (e.g. test_db) using MongoDB Compass.
From Python, connect to the database using:
import mongoengine as mongo
mongo.connect('test_db')
The above code will connect automatically to a MongoDB server running on the localhost with the default port, username and password.
If you are running a remote MongoDB instance, provide the credentials as below:
import mongoengine as mongo
mongo.connect('test_db', host='', port='', username='', password='')
Note
mongoengine
package is installed as part of edaac
dependencies.
Examples¶
Creating a Project¶
The only required key of a project document is its name
.
All other keys can be updated later by retrieving the project, modifying it and then saving it back.
import mongoengine as mongo
from edaac.models import Project, Technology, Design
mongo.connect('test_db')
# create project
project = Project(
name='test-project',
description='demonstrates the use of edaac models',
technology=Technology(
foundry='TestFoundry',
process=45
),
design=Design(
name='test-design',
rtl_files=['/path/to/rtl1.v', '/path/to/rtl2.v'],
netlist_file='/path/to/netlist.v',
sdc_file='/path/to/const.sdc'
)
)
project.save()
mongo.disconnect()
Update Project Data¶
The below code retrieves an existing project and updates its data.
import mongoengine as mongo
from edaac.models import Project, Flow, Stage, Design, Tool
from edaac.enum import StageStatus, DataCollectionMode
mongo.connect('test_db')
# retrieve project
project = Project.objects(name='test-project-flows').first()
self.assertIsNotNone(project)
project.design = Design(
name='test-design',
rtl_files=['/path/to/rtl1.v', '/path/to/rtl2.v'],
netlist_file='/path/to/netlist.v',
sdc_file='/path/to/const.sdc'
)
project.flows.append(
Flow(
flow_directory='/path/to/flow/directory',
params={
'param1': 'value1',
'param2': 'value2'
},
stages=[
Stage(
name='synth',
tool=Tool(
name='synth_tool',
version='0.0.0'
),
machine='test-machine',
collection_mode=DataCollectionMode.OFFLINE_FROM_LOGS.name,
status=StageStatus.COMPLETED_SUCCESSFULLY.name,
log_files=['/path/to/log1',
'/path/to/drc', '/path/to/timing'],
metrics={} # should be extracted using edaac.parsers
),
Stage(
name='placement',
tool=Tool(
name='placement_tool',
version='0.0.0'
),
machine='test-machine',
collection_mode=DataCollectionMode.OFFLINE_FROM_LOGS.name,
status=StageStatus.COMPLETED_SUCCESSFULLY.name,
log_files=['/path/to/log1',
'/path/to/drc', '/path/to/timing'],
metrics={} # should be extracted using edaac.parsers
),
Stage(
name='routing',
tool=Tool(
name='routing_tool',
version='0.0.0'
),
machine='test-machine',
collection_mode=DataCollectionMode.OFFLINE_FROM_LOGS.name,
status=StageStatus.COMPLETED_SUCCESSFULLY.name,
log_files=['/path/to/log1',
'/path/to/drc', '/path/to/timing'],
metrics={} # should be extracted using edaac.parsers
)
],
log_files=['/path/to/log1', '/path/to/log2']
)
)
result = project.save()
mongo.disconnect()
License¶
EDA Analytics Central (EDAAC)
Copyright (c) 2019, See AUTHORS All rights reserved.
BSD 3-Clause License
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Feedback¶
EDAAC is an on-going effort and we would like it to be shaped by our community. If you have feedback for the project (e.g. feature request, metrics collection capabilities, data model improvement), please create an issue on GitHub.
You can also reach out to Abdelrahman, the main contributor, at abdelrahman_hosny@brown.edu.