Skip to content

Commit

Permalink
[FIRRTL] Add OMIR emission pass (llvm#2010)
Browse files Browse the repository at this point in the history
Add a pass to the FIRRTL dialect that consumes `OMIRAnnotation`s on the
circuit, gathers the tracker nodes back up, and serializes the data back
into a JSON blob.
  • Loading branch information
fabianschuiki committed Oct 21, 2021
1 parent 86ae1e8 commit 4cd3709
Show file tree
Hide file tree
Showing 10 changed files with 901 additions and 15 deletions.
100 changes: 100 additions & 0 deletions docs/FIRRTLAnnotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -517,6 +517,106 @@ Example:
}
```

### OMIRFileAnnotation

| Property | Type | Description |
| ---------- | ------ | ------------- |
| class | string | `freechips.rocketchip.objectmodel.OMIRFileAnnotation` |
| filename | string | Output file to emit OMIR to |

This annotation defines the output file to write the JSON-serialized OMIR to after compilation.

Example:
```json
{
"class": "freechips.rocketchip.objectmodel.OMIRFileAnnotation",
"filename": "path/to/omir.json"
}
```

### OMIRAnnotation

| Property | Type | Description |
| ---------- | ------ | ------------- |
| class | string | `freechips.rocketchip.objectmodel.OMIRAnnotation` |
| nodes | array | A list of OMIR nodes |

This annotation specifies a piece of Object Model 2.0 IR. The `nodes` field
is an array of individual OMIR nodes (Scala class `OMNode`), which have the
following form:
```json
{
"info": "@[FileA line:col FileB line:col ...]",
"id": "OMID:42",
"fields": [/*...*/]
}
```
The `fields` entry is an array of individual OMIR fields (Scala class `OMField`), which have the following form:
```json
{
"info": "@[FileA line:col FileB line:col ...]",
"name": "foo",
"value": /*...*/
}
```
The `value` field can be a JSON array or dictionary (corresponding to the `OMArray` and `OMMap` Scala classes, respectively), or any of the string-encoded OMIR classes:

- `OMMap:<fields>`
- `OMArray:<elements>`
- `OMReference:<id>`
- `OMBigInt:<value>`
- `OMInt:<value>`
- `OMLong:<value>`
- `OMString:<value>`
- `OMBoolean:<value>`
- `OMDouble:<value>`
- `OMBigDecimal:<value>`
- `OMFrozenTarget:<omir>`
- `OMDeleted`
- `OMConstant:<literal>`
- `OMReferenceTarget:<target>`
- `OMMemberReferenceTarget:<target>`
- `OMMemberInstanceTarget:<target>`
- `OMInstanceTarget:<target>`
- `OMDontTouchedReferenceTarget:<target>`

Example:
```json
{
"class": "freechips.rocketchip.objectmodel.OMIRAnnotation",
"nodes": [
{
"info": "",
"id": "OMID:0",
"fields": [
{"info": "", "name": "a", "value": "OMReference:0"},
{"info": "", "name": "b", "value": "OMBigInt:42"},
{"info": "", "name": "c", "value": "OMLong:ff"},
{"info": "", "name": "d", "value": "OMString:hello"},
{"info": "", "name": "f", "value": "OMBigDecimal:10.5"},
{"info": "", "name": "g", "value": "OMDeleted:"},
{"info": "", "name": "h", "value": "OMConstant:UInt<2>(\"h1\")"},
{"info": "", "name": "i", "value": 42},
{"info": "", "name": "j", "value": true},
{"info": "", "name": "k", "value": 3.14}
]
},
{
"info": "",
"id": "OMID:1",
"fields": [
{"info": "", "name": "a", "value": "OMReferenceTarget:~Foo|Foo"},
{"info": "", "name": "b", "value": "OMInstanceTarget:~Foo|Foo"},
{"info": "", "name": "c", "value": "OMMemberReferenceTarget:~Foo|Foo"},
{"info": "", "name": "d", "value": "OMMemberInstanceTarget:~Foo|Foo"},
{"info": "", "name": "e", "value": "OMDontTouchedReferenceTarget:~Foo|Foo"},
{"info": "", "name": "f", "value": "OMReferenceTarget:~Foo|Bar"}
]
}
]
}
```

### RetimeModuleAnnotation

| Property | Type | Description |
Expand Down
2 changes: 2 additions & 0 deletions include/circt/Dialect/FIRRTL/Passes.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ createCreateSiFiveMetadataPass(bool replSeqMem = false,
StringRef replSeqMemCircuit = "",
StringRef replSeqMemFile = "");

std::unique_ptr<mlir::Pass> createEmitOMIRPass(StringRef outputFilename = "");

std::unique_ptr<mlir::Pass> createExpandWhensPass();

std::unique_ptr<mlir::Pass> createInferWidthsPass();
Expand Down
13 changes: 13 additions & 0 deletions include/circt/Dialect/FIRRTL/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,19 @@ def CreateSiFiveMetadata : Pass<"firrtl-emit-metadata", "firrtl::CircuitOp"> {
];
}

def EmitOMIR : Pass<"firrtl-emit-omir", "firrtl::CircuitOp"> {
let summary = "Emit OMIR annotations";
let description = [{
This pass gathers the `OMIRAnnotation`s in the design, updates the contained
targets with the trackers that were scattered throughout the design upon
reading the OMIR, and serializes the resulting data into a JSON file.
}];
let constructor = "circt::firrtl::createEmitOMIRPass()";
let options = [Option<"outputFilename", "file", "std::string", "",
"Output file for the JSON-serialized OMIR data">];
let dependentDialects = ["sv::SVDialect", "hw::HWDialect"];
}

def ExpandWhens : Pass<"firrtl-expand-whens", "firrtl::FModuleOp"> {
let summary = "Remove all when conditional blocks.";
let description = [{
Expand Down
4 changes: 3 additions & 1 deletion lib/Dialect/FIRRTL/Import/FIRAnnotations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ namespace json = llvm::json;

using namespace circt;
using namespace firrtl;
using mlir::UnitAttr;

/// Split a target into a base target (including a reference if one exists) and
/// an optional array of subfield/subindex tokens.
Expand Down Expand Up @@ -891,6 +892,7 @@ scatterOMIR(Attribute original, unsigned &annotationID,
NamedAttrList fields;
fields.append("id",
IntegerAttr::get(IntegerType::get(ctx, 64), annotationID++));
fields.append("omir.tracker", UnitAttr::get(ctx));
fields.append("type", StringAttr::get(ctx, tpe));
return DictionaryAttr::getWithSorted(ctx, fields);
};
Expand All @@ -916,9 +918,9 @@ scatterOMIR(Attribute original, unsigned &annotationID,
tpe == "OMMemberInstanceTarget" || tpe == "OMInstanceTarget" ||
tpe == "OMDontTouchedReferenceTarget") {
NamedAttrList tracker;
tracker.append("class", StringAttr::get(ctx, omirTrackerAnnoClass));
tracker.append(
"id", IntegerAttr::get(IntegerType::get(ctx, 64), annotationID));
tracker.append("type", StringAttr::get(ctx, tpe));

auto canonTarget = canonicalizeTarget(value);
if (!canonTarget)
Expand Down
1 change: 1 addition & 0 deletions lib/Dialect/FIRRTL/Transforms/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ add_circt_dialect_library(CIRCTFIRRTLTransforms
BlackBoxReader.cpp
CheckCombCycles.cpp
CreateSiFiveMetadata.cpp
EmitOMIR.cpp
ExpandWhens.cpp
GrandCentral.cpp
GrandCentralTaps.cpp
Expand Down
Loading

0 comments on commit 4cd3709

Please sign in to comment.