diff --git a/lib/Conversion/SeqToSV/SeqToSV.cpp b/lib/Conversion/SeqToSV/SeqToSV.cpp index eadf888ae1cc..2539c9af13b3 100644 --- a/lib/Conversion/SeqToSV/SeqToSV.cpp +++ b/lib/Conversion/SeqToSV/SeqToSV.cpp @@ -81,7 +81,6 @@ struct ModuleLoweringState { struct FragmentInfo { bool needsRegFragment = false; - bool needsMemFragment = false; } fragment; HWModuleOp module; @@ -591,9 +590,11 @@ void SeqToSVPass::runOnOperation() { // Identify memories and group them by module. auto uniqueMems = memLowering.collectMemories(modules); MapVector> memsByModule; + SmallVector generatedModules; for (auto &[config, memOps] : uniqueMems) { // Create the `HWModuleGeneratedOp`s for each unique configuration. auto genOp = memLowering.createMemoryModule(config, memOps); + generatedModules.push_back(genOp); // Group memories by their parent module for parallelism. for (auto memOp : memOps) { @@ -630,10 +631,10 @@ void SeqToSVPass::runOnOperation() { if (auto *it = memsByModule.find(module); it != memsByModule.end()) { memLowering.lowerMemoriesInModule(module, it->second); - if (!disableMemRandomization) { - state.fragment.needsMemFragment = true; - } + // Generated memories need register randomization since `HWMemSimImpl` + // may add registers. needsMemRandomization = true; + needsRegRandomization = true; } return state.immutableValueLowering.lower(); }); @@ -650,8 +651,8 @@ void SeqToSVPass::runOnOperation() { for (auto &[_, state] : moduleLoweringStates) { const auto &info = state.fragment; - if (!info.needsRegFragment && !info.needsMemFragment) { - // If neither is emitted, just skip it. + // Do not add fragments if not needed. + if (!info.needsRegFragment) { continue; } @@ -661,16 +662,28 @@ void SeqToSVPass::runOnOperation() { module->getAttrOfType(emit::getFragmentsAttrName())) fragmentAttrs = llvm::to_vector(others); - if (info.needsRegFragment) + if (info.needsRegFragment) { fragmentAttrs.push_back(randomInitRegFragmentName); - if (info.needsMemFragment) - fragmentAttrs.push_back(randomInitMemFragmentName); - fragmentAttrs.push_back(randomInitFragmentName); + fragmentAttrs.push_back(randomInitFragmentName); + } module->setAttr(emit::getFragmentsAttrName(), ArrayAttr::get(context, fragmentAttrs)); } + // Set fragments for generated modules. + SmallVector genModFragments; + if (!disableRegRandomization) + genModFragments.push_back(randomInitRegFragmentName); + if (!disableMemRandomization) + genModFragments.push_back(randomInitMemFragmentName); + if (!genModFragments.empty()) { + genModFragments.push_back(randomInitFragmentName); + auto fragmentAttr = ArrayAttr::get(context, genModFragments); + for (auto genOp : generatedModules) + genOp->setAttr(emit::getFragmentsAttrName(), fragmentAttr); + } + // Mark all ops which can have clock types as illegal. SeqToSVTypeConverter typeConverter; ConversionTarget target(*context); diff --git a/test/Conversion/SeqToSV/header.mlir b/test/Conversion/SeqToSV/header.mlir index aa81cf67c834..4c540b7ef4be 100644 --- a/test/Conversion/SeqToSV/header.mlir +++ b/test/Conversion/SeqToSV/header.mlir @@ -68,8 +68,11 @@ emit.fragment @SomeFragment {} +// CHECK-LABEL: hw.module.generated +// CHECK-SAME: emit.fragments = [@RANDOM_INIT_REG_FRAGMENT, @RANDOM_INIT_MEM_FRAGMENT, @RANDOM_INIT_FRAGMENT] + // CHECK-LABEL: hw.module @fragment_ref(in %clk : i1) -// CHECK-SAME: emit.fragments = [@SomeFragment, @RANDOM_INIT_REG_FRAGMENT, @RANDOM_INIT_MEM_FRAGMENT, @RANDOM_INIT_FRAGMENT] +// CHECK-SAME: emit.fragments = [@SomeFragment, @RANDOM_INIT_REG_FRAGMENT, @RANDOM_INIT_FRAGMENT] hw.module @fragment_ref(in %clk : !seq.clock) attributes {emit.fragments = [@SomeFragment]} { %cst0_i32 = hw.constant 0 : i32 %rA = seq.firreg %cst0_i32 clock %clk sym @regA : i32