diff --git a/include/circt/Dialect/FIRRTL/FIRRTLTypesImpl.td b/include/circt/Dialect/FIRRTL/FIRRTLTypesImpl.td index 06c87ce6fbae..86c36079292f 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLTypesImpl.td +++ b/include/circt/Dialect/FIRRTL/FIRRTLTypesImpl.td @@ -380,7 +380,8 @@ def RefImpl : FIRRTLImplType<"Ref", }]; let parameters = (ins TypeParameter<"::circt::firrtl::FIRRTLBaseType", "Type of reference target">:$type, - "bool":$forceable); + "bool":$forceable, + OptionalParameter<"::mlir::SymbolRefAttr">:$layer); let genAccessors = true; let genStorageClass = true; let genVerifyDecl = true; @@ -388,7 +389,8 @@ def RefImpl : FIRRTLImplType<"Ref", let skipDefaultBuilders = true; let builders = [ TypeBuilderWithInferredContext<(ins "::circt::firrtl::FIRRTLBaseType":$type, - CArg<"bool", "false">:$forceable)> + CArg<"bool", "false">:$forceable, + CArg<"::mlir::SymbolRefAttr", "{}">:$layer)> ]; let extraClassDeclaration = [{ diff --git a/include/circt/Dialect/FIRRTL/FIRRTLUtils.h b/include/circt/Dialect/FIRRTL/FIRRTLUtils.h index 50cb3aa09167..14fc65845bd6 100644 --- a/include/circt/Dialect/FIRRTL/FIRRTLUtils.h +++ b/include/circt/Dialect/FIRRTL/FIRRTLUtils.h @@ -234,7 +234,8 @@ inline FIRRTLType mapBaseType(FIRRTLType type, return TypeSwitch(type) .Case([&](auto base) { return fn(base); }) .Case([&](auto ref) { - return RefType::get(fn(ref.getType()), ref.getForceable()); + return RefType::get(fn(ref.getType()), ref.getForceable(), + ref.getLayer()); }); } @@ -250,7 +251,7 @@ mapBaseTypeNullable(FIRRTLType type, auto result = fn(ref.getType()); if (!result) return {}; - return RefType::get(result, ref.getForceable()); + return RefType::get(result, ref.getForceable(), ref.getLayer()); }); } diff --git a/lib/Dialect/FIRRTL/FIRRTLTypes.cpp b/lib/Dialect/FIRRTL/FIRRTLTypes.cpp index 483fa58cef20..52310fee2caa 100644 --- a/lib/Dialect/FIRRTL/FIRRTLTypes.cpp +++ b/lib/Dialect/FIRRTL/FIRRTLTypes.cpp @@ -105,11 +105,13 @@ static LogicalResult customTypePrinter(Type type, AsmPrinter &os) { printNestedType(vectorType.getElementType(), os); os << ", " << vectorType.getNumElements() << '>'; }) - .Case([&](auto refType) { + .Case([&](RefType refType) { if (refType.getForceable()) os << "rw"; os << "probe<"; printNestedType(refType.getType(), os); + if (auto layer = refType.getLayer()) + os << ", " << layer; os << '>'; }) .Case([&](auto stringType) { os << "string"; }) @@ -329,31 +331,43 @@ static OptionalParseResult customTypeParser(AsmParser &parser, StringRef name, // For now, support both firrtl.ref and firrtl.probe. if (name.equals("ref") || name.equals("probe")) { FIRRTLBaseType type; + SymbolRefAttr layer; // Don't pass `isConst` to `parseNestedBaseType since `ref` can point to // either `const` or non-`const` types - if (parser.parseLess() || parseNestedBaseType(type, parser) || - parser.parseGreater()) + if (parser.parseLess() || parseNestedBaseType(type, parser)) + return failure(); + if (parser.parseOptionalComma().succeeded()) + if (parser.parseOptionalAttribute(layer).value()) + return parser.emitError(parser.getNameLoc(), + "expected symbol reference"); + if (parser.parseGreater()) return failure(); if (failed(RefType::verify( [&]() { return parser.emitError(parser.getNameLoc()); }, type, - false))) + false, layer))) return failure(); - return result = RefType::get(type, false), success(); + return result = RefType::get(type, false, layer), success(); } if (name.equals("rwprobe")) { FIRRTLBaseType type; - if (parser.parseLess() || parseNestedBaseType(type, parser) || - parser.parseGreater()) + SymbolRefAttr layer; + if (parser.parseLess() || parseNestedBaseType(type, parser)) + return failure(); + if (parser.parseOptionalComma().succeeded()) + if (parser.parseOptionalAttribute(layer).value()) + return parser.emitError(parser.getNameLoc(), + "expected symbol reference"); + if (parser.parseGreater()) return failure(); if (failed(RefType::verify( - [&]() { return parser.emitError(parser.getNameLoc()); }, type, - true))) + [&]() { return parser.emitError(parser.getNameLoc()); }, type, true, + layer))) return failure(); - return result = RefType::get(type, true), success(); + return result = RefType::get(type, true, layer), success(); } if (name.equals("class")) { if (isConst) @@ -2400,12 +2414,14 @@ BaseTypeAliasType::getIndexAndSubfieldID(uint64_t fieldID) const { // RefType //===----------------------------------------------------------------------===// -auto RefType::get(FIRRTLBaseType type, bool forceable) -> RefType { - return Base::get(type.getContext(), type, forceable); +auto RefType::get(FIRRTLBaseType type, bool forceable, SymbolRefAttr layer) + -> RefType { + return Base::get(type.getContext(), type, forceable, layer); } auto RefType::verify(function_ref emitErrorFn, - FIRRTLBaseType base, bool forceable) -> LogicalResult { + FIRRTLBaseType base, bool forceable, SymbolRefAttr layer) + -> LogicalResult { if (!base.isPassive()) return emitErrorFn() << "reference base type must be passive"; if (forceable && base.containsConst()) diff --git a/lib/Dialect/FIRRTL/Transforms/DropConst.cpp b/lib/Dialect/FIRRTL/Transforms/DropConst.cpp index 2f1b5466f6fd..24a811bfff22 100644 --- a/lib/Dialect/FIRRTL/Transforms/DropConst.cpp +++ b/lib/Dialect/FIRRTL/Transforms/DropConst.cpp @@ -35,7 +35,8 @@ static Type convertType(Type type) { if (auto refType = type_dyn_cast(type)) { if (auto converted = convertType(refType.getType())) - return RefType::get(converted, refType.getForceable()); + return RefType::get(converted, refType.getForceable(), + refType.getLayer()); } return {}; diff --git a/lib/Dialect/FIRRTL/Transforms/VBToBV.cpp b/lib/Dialect/FIRRTL/Transforms/VBToBV.cpp index ce83cb811145..efacd6020286 100644 --- a/lib/Dialect/FIRRTL/Transforms/VBToBV.cpp +++ b/lib/Dialect/FIRRTL/Transforms/VBToBV.cpp @@ -174,7 +174,8 @@ RefType Visitor::convertType(RefType type) { auto cached = typeMap.lookup(type); if (cached) return type_cast(cached); - auto converted = RefType::get(convertType(type.getType())); + auto converted = RefType::get(convertType(type.getType()), + type.getForceable(), type.getLayer()); typeMap.insert({type, converted}); return converted; } diff --git a/test/Dialect/FIRRTL/round-trip.mlir b/test/Dialect/FIRRTL/round-trip.mlir index 721bfe53874c..d77628057736 100644 --- a/test/Dialect/FIRRTL/round-trip.mlir +++ b/test/Dialect/FIRRTL/round-trip.mlir @@ -44,4 +44,16 @@ firrtl.module @Foo(in %clock: !firrtl.clock) { firrtl.strictconnect %inst_clock, %clock : !firrtl.clock } +firrtl.layer @LayerA bind { + firrtl.layer @LayerB bind {} +} + +// CHECK-LABEL: firrtl.module @Layers +// CHECK-SAME: out %a: !firrtl.probe, @LayerA> +// CHECK-SAME: out %b: !firrtl.rwprobe, @LayerA::@LayerB> +firrtl.module @Layers( + out %a: !firrtl.probe, @LayerA>, + out %b: !firrtl.rwprobe, @LayerA::@LayerB> +) {} + }