Skip to content

Commit

Permalink
[FIRRTL] Add parser/emitter support for layer-associated probes (#6552)
Browse files Browse the repository at this point in the history
* [FIRRTL] Parse Layer-Associated Probes

Add support to the FIRRTL parse to handle probes associated with layers.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>

* [FIRRTL] Emit Layer-associated Probes

Add emitter support for layer-associated probes.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>

* fixup! [FIRRTL] Parse Layer-Associated Probes

* Add a fir version check for colored probes

---------

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@sifive.com>
Co-authored-by: Robert Young <rwy0717@gmail.com>
  • Loading branch information
seldridge and rwy7 authored Jan 29, 2024
1 parent 86246fd commit 8e3d29f
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 8 deletions.
22 changes: 21 additions & 1 deletion lib/Dialect/FIRRTL/Export/FIREmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,18 @@ struct Emitter {
[&](Value v) { emitSubExprIBox2(v); });
}

/// Emit a (potentially nested) symbol reference as `A.B.C`.
void emitSymbol(SymbolRefAttr symbol) {
ps.ibox(2, IndentStyle::Block);
ps << symbol.getRootReference();
for (auto nested : symbol.getNestedReferences()) {
ps.zerobreak();
ps << ".";
ps << nested.getAttr();
}
ps.end();
}

private:
/// Emit an error and remark that emission failed.
InFlightDiagnostic emitError(Operation *op, const Twine &message) {
Expand Down Expand Up @@ -1377,8 +1389,16 @@ void Emitter::emitType(Type type, bool includeConst) {
if (type.getForceable())
ps << "RW";
ps << "Probe<";
ps.cbox(2, IndentStyle::Block);
ps.zerobreak();
emitType(type.getType());
ps << ">";
if (auto layer = type.getLayer()) {
ps << ",";
ps.space();
emitSymbol(type.getLayer());
}
ps << BreakToken(0, -2) << ">";
ps.end();
})
.Case<AnyRefType>([&](AnyRefType type) { ps << "AnyRef"; })
.Case<StringType>([&](StringType type) { ps << "String"; })
Expand Down
35 changes: 31 additions & 4 deletions lib/Dialect/FIRRTL/Import/FIRParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,13 +934,30 @@ ParseResult FIRParser::parseType(FIRRTLType &result, const Twine &message) {
auto kind = getToken().getKind();
auto loc = getToken().getLoc();
consumeToken();
FIRRTLType type;

// Inner Type
FIRRTLType type;
if (parseToken(FIRToken::less, "expected '<' in reference type") ||
parseType(type, "expected probe data type") ||
parseToken(FIRToken::greater, "expected '>' in reference type"))
parseType(type, "expected probe data type"))
return failure();

// Probe Color
SmallVector<StringRef> layers;
if (getToken().getKind() == FIRToken::identifier) {
if (requireFeature({3, 2, 0}, "colored probes"))
return failure();
do {
StringRef layer;
loc = getToken().getLoc();
if (parseId(layer, "expected layer name"))
return failure();
layers.push_back(layer);
} while (consumeIf(FIRToken::period));
}

if (!consumeIf(FIRToken::greater))
return emitError(loc, "expected '>' to end reference type");

bool forceable = kind == FIRToken::kw_RWProbe;

auto innerType = type_dyn_cast<FIRRTLBaseType>(type);
Expand All @@ -953,7 +970,17 @@ ParseResult FIRParser::parseType(FIRRTLType &result, const Twine &message) {
if (forceable && innerType.containsConst())
return emitError(loc, "rwprobe cannot contain const");

result = RefType::get(innerType, forceable);
SymbolRefAttr layer;
if (!layers.empty()) {
auto nestedLayers =
llvm::map_range(ArrayRef(layers).drop_front(), [&](StringRef a) {
return FlatSymbolRefAttr::get(getContext(), a);
});
layer = SymbolRefAttr::get(getContext(), layers.front(),
llvm::to_vector(nestedLayers));
}

result = RefType::get(innerType, forceable, layer);
break;
}

Expand Down
36 changes: 34 additions & 2 deletions test/Dialect/FIRRTL/emit-basic.mlir
Original file line number Diff line number Diff line change
Expand Up @@ -704,13 +704,18 @@ firrtl.circuit "Foo" {
}
}
// CHECK: module ModuleWithGroups :
// CHECK-NEXT: layerblock GroupA :
// CHECK-NEXT: output a : Probe<UInt<1>, GroupA>
// CHECK-NEXT: output b : RWProbe<UInt<1>, GroupA.GroupB>
// CHECK: layerblock GroupA :
// CHECK-NEXT: layerblock GroupB :
// CHECK-NEXT: layerblock GroupC :
// CHECK-NEXT: layerblock GroupD :
// CHECK-NEXT: layerblock GroupE :
// CHECK-NEXT: layerblock GroupF :
firrtl.module @ModuleWithGroups() {
firrtl.module @ModuleWithGroups(
out %a: !firrtl.probe<uint<1>, @GroupA>,
out %b: !firrtl.rwprobe<uint<1>, @GroupA::@GroupB>
) {
firrtl.layerblock @GroupA {
firrtl.layerblock @GroupA::@GroupB {
firrtl.layerblock @GroupA::@GroupB::@GroupC {
Expand All @@ -725,6 +730,33 @@ firrtl.circuit "Foo" {
}
}

// Test line-breaks for very large layer associations.
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {
firrtl.layer @Group1234567890 bind {}
}
}
}
}
}
}
}

// CHECK: module ModuleWithLongProbeColor
// CHECK-NEXT: output o : Probe<
// CHECK-NEXT: UInt<1>,
// CHECK-NEXT: Group1234567890.Group1234567890.Group1234567890.Group1234567890
// CHECK-NEXT: .Group1234567890.Group1234567890.Group1234567890.Group1234567890
// CHECK-NEXT: >
firrtl.module @ModuleWithLongProbeColor(
out %o: !firrtl.probe<uint<1>, @Group1234567890::@Group1234567890::@Group1234567890::@Group1234567890::@Group1234567890::@Group1234567890::@Group1234567890::@Group1234567890>
) {}

// CHECK: module RWProbe :
// CHECK-NEXT: input in : { a : UInt<1> }[2]
// CHECK-NEXT: output p : RWProbe<UInt<1>>
Expand Down
6 changes: 5 additions & 1 deletion test/Dialect/FIRRTL/parse-basic.fir
Original file line number Diff line number Diff line change
Expand Up @@ -1671,9 +1671,13 @@ circuit Layers:
; CHECK-NEXT: }
; CHECK-NEXT: }

; CHECK: firrtl.module @Layers
; CHECK: firrtl.module @Layers
; CHECK-SAME: out %b: !firrtl.probe<uint<1>, @A>
; CHECK-SAME: out %c: !firrtl.rwprobe<uint<1>, @A::@B>
module Layers:
input a: UInt<1>
output b: Probe<UInt<1>, A>
output c: RWProbe<UInt<1>, A.B>

layerblock A:
node A_a = a
Expand Down
61 changes: 61 additions & 0 deletions test/Dialect/FIRRTL/parse-errors.fir
Original file line number Diff line number Diff line change
Expand Up @@ -1253,3 +1253,64 @@ circuit Foo:
option Platform:
FPGA
FPGA

;// -----
FIRRTL version 3.1.0
circuit Foo:

module Foo:
; expected-error @below {{colored probes are a FIRRTL 3.2.0+ feature, but the specified FIRRTL version was 3.1.0}}
output a: Probe<UInt<1>, A>

;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
output a: Probe<
; expected-error @below {{expected probe data type}}
;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
; expected-error @below {{expected '<' in reference type}}
output a: Probe X

;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
output a: Probe
; expected-error @below {{expected '<' in reference type}}
;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
; expected-error @below {{expected probe data type}}
output a: Probe<>

;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
; expected-error @below {{expected '>' to end reference type}}
output a: Probe<UInt<1>
;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
; expected-error @below {{expected '>' to end reference type}}
output a: Probe<UInt<1> A

;// -----
FIRRTL version 4.0.0
circuit Foo:
layer A bind:
module Foo:
; expected-error @below {{expected layer name}}
output a: Probe<UInt<1> A.>

0 comments on commit 8e3d29f

Please sign in to comment.