2.3. 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.

2.3.1. 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

2.3.2. Database

The question now is where do we store this these information? Answer: MongoDB.

2.3.2.1. 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.

2.3.2.2. 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.

2.3.3. Examples

2.3.3.1. 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()

2.3.3.2. 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()