diff --git a/include/circt/Dialect/HW/HWStructure.td b/include/circt/Dialect/HW/HWStructure.td index f92bf2884b75..d0b6676f27ce 100644 --- a/include/circt/Dialect/HW/HWStructure.td +++ b/include/circt/Dialect/HW/HWStructure.td @@ -26,6 +26,22 @@ include "mlir/IR/SymbolInterfaces.td" include "mlir/Interfaces/ControlFlowInterfaces.td" include "mlir/Interfaces/SideEffectInterfaces.td" +def ContainerOp : HWOp<"container", + [IsolatedFromAbove, SymbolTable, SingleBlock, NoTerminator, + NoRegionArguments, InnerRefNamespace]> { + let summary = "HW Container (of modules and other things)"; + let description = [{ + A HW container is a top-level container of HW operations (and anything + else). This is roughly analogous to `builtin.module`, except that it also + implements an `InnerRefNamespace` which allows for verification of inner + refs. + }]; + let arguments = (ins OptionalAttr:$sym_name, + OptionalAttr:$sym_visibility); + let regions = (region SizedRegion<1>:$bodyRegion); + let assemblyFormat = "($sym_name^)? attr-dict-with-keyword $bodyRegion"; +} + /// Base class factoring out some of the additional class declarations common to /// the module-like operations. class HWModuleOpBase traits = []> : @@ -34,7 +50,7 @@ class HWModuleOpBase traits = []> : DeclareOpInterfaceMethods, DeclareOpInterfaceMethods, Symbol, InnerSymbolTable, - OpAsmOpInterface, HasParent<"mlir::ModuleOp">]> { + OpAsmOpInterface, ParentOneOf<["mlir::ModuleOp", "hw::ContainerOp"]>]> { /// Additional class declarations inside the module op. code extraModuleClassDeclaration = ?; @@ -304,7 +320,7 @@ def HWModuleExternOp : HWModuleOpBase<"module.extern"> { } def HWGeneratorSchemaOp : HWOp<"generator.schema", - [Symbol, HasParent<"mlir::ModuleOp">]> { + [Symbol, ParentOneOf<["mlir::ModuleOp", "hw::ContainerOp"]>]> { let summary = "HW Generator Schema declaration"; let description = [{ The "hw.generator.schema" operation declares a kind of generated module by diff --git a/test/Dialect/HW/basic.mlir b/test/Dialect/HW/basic.mlir index 3e0e6275abbb..0d83091ef8a5 100644 --- a/test/Dialect/HW/basic.mlir +++ b/test/Dialect/HW/basic.mlir @@ -270,3 +270,9 @@ hw.module @aggregate_const(out o : !hw.array<1x!seq.clock>) { %0 = hw.aggregate_constant [#seq : !seq.clock] : !hw.array<1x!seq.clock> hw.output %0 : !hw.array<1x!seq.clock> } + +hw.container { + + hw.module @Foo() {} + +} diff --git a/test/Dialect/HW/errors.mlir b/test/Dialect/HW/errors.mlir index 3e79e8447d46..ec3c2afc5e29 100644 --- a/test/Dialect/HW/errors.mlir +++ b/test/Dialect/HW/errors.mlir @@ -546,3 +546,15 @@ hw.array_get %0[%1] : !hw.array<1000xi42>, i9 %2 = hw.constant 0 : i42 // expected-error @below {{index bit width equals ceil(log2(length(input))), or 0 or 1 if input contains only one element}} hw.array_inject %0[%1], %2 : !hw.array<1000xi42>, i9 + +// ----- + +hw.container { + + // expected-error @below {{operation with symbol: #hw.innerNameRef<@Foo::@b> was not found}} + hw.hierpath @path [@Foo::@b] + hw.module @Foo(in %in: i1) { + %a = hw.wire %in sym @a : i1 + } + +}