From f6931e21e5580bdbc65c22a6ae38a34623ca02fa Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 10:30:00 +0100 Subject: [PATCH 01/12] fuse --- include/dynamatic/Support/RTL/RTL.h | 48 +++- .../HandshakeToHW/HandshakeToHW.cpp | 156 ++++++++++++ lib/Support/RTL/RTL.cpp | 235 ++---------------- tools/integration/TEST_SUITE.cpp | 179 ++++++++++++- 4 files changed, 396 insertions(+), 222 deletions(-) diff --git a/include/dynamatic/Support/RTL/RTL.h b/include/dynamatic/Support/RTL/RTL.h index 0d775930c0..b75dc53344 100644 --- a/include/dynamatic/Support/RTL/RTL.h +++ b/include/dynamatic/Support/RTL/RTL.h @@ -25,6 +25,8 @@ #include "llvm/Support/JSON.h" #include #include +#include "mlir/IR/Types.h" +#include "dynamatic/Dialect/Handshake/HandshakeTypes.h" namespace dynamatic { @@ -54,6 +56,42 @@ replaceRegexes(StringRef input, std::string substituteParams(StringRef input, const ParameterMappings ¶meters); + +/// Returns the bitwidth of the type as string. If the type is a control type 0. +inline std::string getBitwidthString(mlir::Type type) { + return std::to_string(dynamatic::handshake::getHandshakeTypeBitWidth(type)); +} + +/// Serialize all extra signals present to string. +inline std::string serializeExtraSignals(const mlir::Type &type) { + assert(type.isa() && + "type should be ChannelType or ControlType"); + + dynamatic::handshake::ExtraSignalsTypeInterface extraSignalsType = + type.cast(); + + std::string extraSignalsValue; + llvm::raw_string_ostream extraSignals(extraSignalsValue); + + extraSignals << "{"; + bool first = true; + for (const dynamatic::handshake::ExtraSignal &extraSignal : + extraSignalsType.getExtraSignals()) { + if (!first) + extraSignals << ", "; + first = false; + + extraSignals << "\"" << extraSignal.name << "\": "; + extraSignals << extraSignal.getBitWidth(); + } + extraSignals << "}"; + + return std::string("'") + extraSignals.str() + std::string("'"); +} + +/// Compute serialized parameters from a handshake operation +dynamatic::ParameterMappings computeSerializedParameters(llvm::StringRef handshakeOp, hw::ModuleType modType); + class RTLMatch; class RTLParameter; class RTLComponent; @@ -293,15 +331,7 @@ class RTLMatch { /// Temporary function. These parameters should be added to hw.parameters /// (generation_params in the future) LogicalResult registerParameters(hw::HWModuleExternOp &modOp); - - LogicalResult registerBitwidthParameter(hw::HWModuleExternOp &modOp, - llvm::StringRef modName, - hw::ModuleType &modType); - - LogicalResult registerExtraSignalParameters(hw::HWModuleExternOp &modOp, - llvm::StringRef modName, - hw::ModuleType &modType); - + /// Attempts to concretize the matched RTL component using the original RTL /// request that created the match. Generic components are copied to the /// output directory while generated components are produced by the diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 3cb605cca5..7ad8e8045c 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -24,6 +24,7 @@ #include "dynamatic/Support/Attribute.h" #include "dynamatic/Support/Backedge.h" #include "dynamatic/Support/Utils/Utils.h" +#include "dynamatic/Support/RTL/RTL.h" #include "dynamatic/Transforms/HandshakeMaterialize.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Attributes.h" @@ -99,6 +100,133 @@ static Type lowerType(Type type) { .Default([](auto type) { return nullptr; }); } +// Compute serialized textual parameters (moved from RTL.cpp). +dynamatic::ParameterMappings dynamatic::computeSerializedParameters( + llvm::StringRef handshakeOp, hw::ModuleType modType) { + ParameterMappings pm; + + // Bitwidth + if ( + // default + handshakeOp == "handshake.addi" || handshakeOp == "handshake.andi" || + handshakeOp == "handshake.buffer" || handshakeOp == "handshake.cmpi" || + handshakeOp == "handshake.fork" || handshakeOp == "handshake.lazy_fork" || + handshakeOp == "handshake.merge" || handshakeOp == "handshake.muli" || + handshakeOp == "handshake.sink" || handshakeOp == "handshake.subi" || + handshakeOp == "handshake.shli" || handshakeOp == "handshake.blocker" || + handshakeOp == "handshake.uitofp" || handshakeOp == "handshake.sitofp" || + handshakeOp == "handshake.fptosi" || + handshakeOp == "handshake.rigidifier" || handshakeOp == "handshake.ori" || + handshakeOp == "handshake.shrsi" || handshakeOp == "handshake.xori" || + handshakeOp == "handshake.negf" || handshakeOp == "handshake.divsi" || + handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || + handshakeOp == "handshake.shrui" || handshakeOp == "handshake.remsi" || + handshakeOp == "handshake.not" || + // the first input has data bitwidth + handshakeOp == "handshake.speculator" || + handshakeOp == "handshake.spec_commit" || + handshakeOp == "handshake.spec_save_commit" || + handshakeOp == "handshake.sharing_wrapper" || + handshakeOp == "handshake.non_spec") { + pm["BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + } else if (handshakeOp == "handshake.cond_br" || + handshakeOp == "handshake.select") { + pm["BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.constant") { + pm["BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); + } else if (handshakeOp == "handshake.control_merge") { + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); + } else if (handshakeOp == "handshake.extsi" || + handshakeOp == "handshake.trunci" || + handshakeOp == "handshake.extui") { + pm["INPUT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["OUTPUT_BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); + } else if (handshakeOp == "handshake.load") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); + } else if (handshakeOp == "handshake.mux") { + pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.store") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.speculating_branch") { + pm["SPEC_TAG_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.mem_controller" || + handshakeOp == "handshake.lsq") { + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["ADDR_BITWIDTH"] = + getBitwidthString(modType.getOutputType(modType.getNumOutputs() - 2)); + } else if (handshakeOp == "mem_to_bram") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(4)); + } else if (handshakeOp == "handshake.addf" || + handshakeOp == "handshake.cmpf" || + handshakeOp == "handshake.mulf" || + handshakeOp == "handshake.subf" || + handshakeOp == "handshake.divf") { + int bitwidth = handshake::getHandshakeTypeBitWidth(modType.getInputType(0)); + pm["IS_DOUBLE"] = bitwidth == 64 ? "True" : "False"; + } else if (handshakeOp == "handshake.valid_merger") { + pm["LEFT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["RIGHT_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.source" || + handshakeOp == "mem_controller" || + handshakeOp == "handshake.truncf" || + handshakeOp == "handshake.extf" || + handshakeOp == "handshake.maximumf" || + handshakeOp == "handshake.minimumf" || + handshakeOp == "handshake.join") { + // nothing + } else if (handshakeOp == "handshake.ram") { + pm["ADDR_WIDTH"] = getBitwidthString(modType.getInputType(1)); + pm["DATA_WIDTH"] = getBitwidthString(modType.getInputType(4)); + } + + // Extra signals + if ( + // default + handshakeOp == "handshake.addf" || handshakeOp == "handshake.addi" || + handshakeOp == "handshake.andi" || handshakeOp == "handshake.buffer" || + handshakeOp == "handshake.cmpf" || handshakeOp == "handshake.cmpi" || + handshakeOp == "handshake.cond_br" || + handshakeOp == "handshake.constant" || handshakeOp == "handshake.extsi" || + handshakeOp == "handshake.fork" || handshakeOp == "handshake.merge" || + handshakeOp == "handshake.mulf" || handshakeOp == "handshake.muli" || + handshakeOp == "handshake.select" || handshakeOp == "handshake.sink" || + handshakeOp == "handshake.subf" || handshakeOp == "handshake.extui" || + handshakeOp == "handshake.shli" || handshakeOp == "handshake.subi" || + handshakeOp == "handshake.spec_save_commit" || + handshakeOp == "handshake.speculator" || + handshakeOp == "handshake.trunci" || handshakeOp == "handshake.mux" || + handshakeOp == "handshake.control_merge" || + handshakeOp == "handshake.blocker" || handshakeOp == "handshake.uitofp" || + handshakeOp == "handshake.sitofp" || handshakeOp == "handshake.fptosi" || + handshakeOp == "handshake.lazy_fork" || handshakeOp == "handshake.divf" || + handshakeOp == "handshake.ori" || handshakeOp == "handshake.shrsi" || + handshakeOp == "handshake.xori" || handshakeOp == "handshake.negf" || + handshakeOp == "handshake.truncf" || handshakeOp == "handshake.divsi" || + handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || + handshakeOp == "handshake.extf" || handshakeOp == "handshake.maximumf" || + handshakeOp == "handshake.minimumf" || handshakeOp == "handshake.shrui" || + handshakeOp == "handshake.join" || handshakeOp == "handshake.remsi" || + handshakeOp == "handshake.not" || + // the first input has extra signals + handshakeOp == "handshake.load" || handshakeOp == "handshake.store" || + handshakeOp == "handshake.spec_commit" || + handshakeOp == "handshake.speculating_branch") { + pm["EXTRA_SIGNALS"] = serializeExtraSignals(modType.getInputType(0)); + } else if (handshakeOp == "handshake.source" || + handshakeOp == "handshake.non_spec") { + pm["EXTRA_SIGNALS"] = serializeExtraSignals(modType.getOutputType(0)); + } + + return pm; +} + + namespace { /// Helper class to build HW modules progressively by adding inputs/outputs @@ -1109,6 +1237,23 @@ hw::InstanceOp HWBuilder::createInstance(ModuleDiscriminator &discriminator, extModOp = builder.create(loc, modNameAttr, modBuilder.getPortInfo()); discriminator.setParameters(extModOp); + + // Compute serialized textual parameters and put them to the external module so export-rtl can read them. + MLIRContext *ctx = extModOp.getContext(); + StringRef rtlName = extModOp->getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); + auto serialized = dynamatic::computeSerializedParameters(rtlName, + extModOp.getModuleType()); + std::vector serialAttrs; + for (auto it = serialized.begin(); it != serialized.end(); ++it) { + StringRef key = it->first(); + const std::string &val = it->second; + serialAttrs.emplace_back(StringAttr::get(ctx, key), + StringAttr::get(ctx, val)); + } + if (!serialAttrs.empty()){ + extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), DictionaryAttr::get(ctx, serialAttrs)); + } + builder.restoreInsertionPoint(instInsertPoint); } @@ -1905,6 +2050,17 @@ MemToBRAMConverter::buildExternalModule(hw::HWModuleOp circuitMod, IntegerAttr::get(i32, memState.ports.addrWidth)); extModOp->setAttr(RTL_PARAMETERS_ATTR_NAME, DictionaryAttr::get(ctx, parameters)); + // Compute and add serialized parameters so the RTL exporter can read them + { + ParameterMappings pm = dynamatic::computeSerializedParameters(HW_NAME, extModOp.getModuleType()); + std::vector serializedAttrs; + for (auto it = pm.begin(); it != pm.end(); ++it) { + StringRef key = it->getKey(); + std::string &val = it->getValue(); + serializedAttrs.emplace_back(StringAttr::get(ctx, key), StringAttr::get(ctx, val)); + } + extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), DictionaryAttr::get(ctx, serializedAttrs)); + } return extModOp; } diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index 01ffe8b3cd..3f0800a422 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -246,221 +246,32 @@ MapVector RTLMatch::getGenericParameterValues() const { return values; } -static std::string serializeExtraSignalsInner(const Type &type) { - assert(type.isa() && - "type should be ChannelType or ControlType"); - - handshake::ExtraSignalsTypeInterface extraSignalsType = - type.cast(); - - std::string extraSignalsValue; - llvm::raw_string_ostream extraSignals(extraSignalsValue); - - extraSignals << "{"; - bool first = true; - for (const handshake::ExtraSignal &extraSignal : - extraSignalsType.getExtraSignals()) { - if (!first) - extraSignals << ", "; - first = false; - - extraSignals << "\"" << extraSignal.name << "\": "; - extraSignals << extraSignal.getBitWidth(); - } - extraSignals << "}"; - - return extraSignals.str(); -} - -static std::string serializeExtraSignals(const Type &type) { - return "'" + serializeExtraSignalsInner(type) + "'"; -} - -/// Returns the bitwidth of the type as string. -/// If the type is a control type, returns "0". -static std::string getBitwidthString(Type type) { - return std::to_string(handshake::getHandshakeTypeBitWidth(type)); -} - LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { - auto handshakeOp = - modOp->template getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); - auto modType = modOp.getModuleType(); - - LogicalResult gotBitwidth = - registerBitwidthParameter(modOp, handshakeOp, modType); - LogicalResult gotExtraSignals = - registerExtraSignalParameters(modOp, handshakeOp, modType); - - return success(gotBitwidth.succeeded() && gotExtraSignals.succeeded()); -} - -LogicalResult RTLMatch::registerBitwidthParameter(hw::HWModuleExternOp &modOp, - llvm::StringRef handshakeOp, - hw::ModuleType &modType) { - if ( - // default (All(Data)TypesMatch) - handshakeOp == "handshake.addi" || handshakeOp == "handshake.andi" || - handshakeOp == "handshake.buffer" || handshakeOp == "handshake.cmpi" || - handshakeOp == "handshake.fork" || handshakeOp == "handshake.lazy_fork" || - handshakeOp == "handshake.merge" || handshakeOp == "handshake.muli" || - handshakeOp == "handshake.sink" || handshakeOp == "handshake.subi" || - handshakeOp == "handshake.shli" || handshakeOp == "handshake.blocker" || - handshakeOp == "handshake.uitofp" || handshakeOp == "handshake.sitofp" || - handshakeOp == "handshake.fptosi" || - handshakeOp == "handshake.rigidifier" || handshakeOp == "handshake.ori" || - handshakeOp == "handshake.shrsi" || handshakeOp == "handshake.xori" || - handshakeOp == "handshake.negf" || handshakeOp == "handshake.divsi" || - handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || - handshakeOp == "handshake.shrui" || handshakeOp == "handshake.remsi" || - handshakeOp == "handshake.not" || - // the first input has data bitwidth - handshakeOp == "handshake.speculator" || - handshakeOp == "handshake.spec_commit" || - handshakeOp == "handshake.spec_save_commit" || - handshakeOp == "handshake.sharing_wrapper" || - handshakeOp == "handshake.non_spec") { - // Default - serializedParams["BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - } else if (handshakeOp == "handshake.cond_br" || - handshakeOp == "handshake.select") { - serializedParams["BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.constant") { - serializedParams["BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); - } else if (handshakeOp == "handshake.control_merge") { - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["INDEX_BITWIDTH"] = - getBitwidthString(modType.getOutputType(1)); - } else if (handshakeOp == "handshake.extsi" || - handshakeOp == "handshake.trunci" || - handshakeOp == "handshake.extui") { - serializedParams["INPUT_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["OUTPUT_BITWIDTH"] = - getBitwidthString(modType.getOutputType(0)); - } else if (handshakeOp == "handshake.load") { - serializedParams["ADDR_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getOutputType(1)); - } else if (handshakeOp == "handshake.mux") { - serializedParams["INDEX_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.store") { - serializedParams["ADDR_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.speculating_branch") { - serializedParams["SPEC_TAG_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.mem_controller" || - handshakeOp == "handshake.lsq") { - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - // Warning: Ports differ from instance to instance. - // Therefore, mod.getNumOutputs() is also variable. - serializedParams["ADDR_BITWIDTH"] = - getBitwidthString(modType.getOutputType(modType.getNumOutputs() - 2)); - } else if (handshakeOp == "mem_to_bram") { - serializedParams["ADDR_BITWIDTH"] = - getBitwidthString(modType.getInputType(1)); - serializedParams["DATA_BITWIDTH"] = - getBitwidthString(modType.getInputType(4)); - } else if (handshakeOp == "handshake.addf" || - handshakeOp == "handshake.cmpf" || - handshakeOp == "handshake.mulf" || - handshakeOp == "handshake.subf" || - handshakeOp == "handshake.divf") { - int bitwidth = handshake::getHandshakeTypeBitWidth(modType.getInputType(0)); - serializedParams["IS_DOUBLE"] = bitwidth == 64 ? "True" : "False"; - } else if (handshakeOp == "handshake.valid_merger") { - serializedParams["LEFT_BITWIDTH"] = - getBitwidthString(modType.getInputType(0)); - serializedParams["RIGHT_BITWIDTH"] = - getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.source" || - handshakeOp == "mem_controller" || - handshakeOp == "handshake.truncf" || - handshakeOp == "handshake.extf" || - handshakeOp == "handshake.maximumf" || - handshakeOp == "handshake.minimumf" || - handshakeOp == "handshake.join") { - // Skip - } else if (handshakeOp == "handshake.ram") { - // NOTE: this port order is currently hardcoded in HandshakeToHW.cpp - // Input 0: loadEn - // Input 1: loadAddr - // Input 2: storeEn - // Input 3: storeAddr - // Input 4: storeData - // Output 0: loadData - serializedParams["ADDR_WIDTH"] = getBitwidthString(modType.getInputType(1)); - serializedParams["DATA_WIDTH"] = getBitwidthString(modType.getInputType(4)); - } else { - modOp->emitError("Failed to get bitwidth of operation"); - return failure(); + // Require precomputed serialized parameters attached during lowering as + // the `hw.serialized_parameters` attribute. + if (auto dict = modOp->getAttrOfType("hw.serialized_parameters")) { + for (auto namedAttr : dict.getValue()) { + StringRef key = namedAttr.getName().getValue(); + Attribute val = namedAttr.getValue(); + if (auto s = val.dyn_cast()) { + serializedParams[key.str()] = s.getValue().str(); + } else if (auto i = val.dyn_cast()) { + serializedParams[key.str()] = std::to_string(i.getInt()); + } else { + // // neither string nor integer attribute... use print method of attribute + // std::string tmp; + // llvm::raw_string_ostream os(tmp); + // val.print(os); + // serializedParams[key.str()] = os.str(); + return failure(); + } + } + return success(); } - return success(); -} -LogicalResult -RTLMatch::registerExtraSignalParameters(hw::HWModuleExternOp &modOp, - llvm::StringRef handshakeOp, - hw::ModuleType &modType) { - - if ( - // default (AllExtraSignalsMatch) - handshakeOp == "handshake.addf" || handshakeOp == "handshake.addi" || - handshakeOp == "handshake.andi" || handshakeOp == "handshake.buffer" || - handshakeOp == "handshake.cmpf" || handshakeOp == "handshake.cmpi" || - handshakeOp == "handshake.cond_br" || - handshakeOp == "handshake.constant" || handshakeOp == "handshake.extsi" || - handshakeOp == "handshake.fork" || handshakeOp == "handshake.merge" || - handshakeOp == "handshake.mulf" || handshakeOp == "handshake.muli" || - handshakeOp == "handshake.select" || handshakeOp == "handshake.sink" || - handshakeOp == "handshake.subf" || handshakeOp == "handshake.extui" || - handshakeOp == "handshake.shli" || handshakeOp == "handshake.subi" || - handshakeOp == "handshake.spec_save_commit" || - handshakeOp == "handshake.speculator" || - handshakeOp == "handshake.trunci" || handshakeOp == "handshake.mux" || - handshakeOp == "handshake.control_merge" || - handshakeOp == "handshake.blocker" || handshakeOp == "handshake.uitofp" || - handshakeOp == "handshake.sitofp" || handshakeOp == "handshake.fptosi" || - handshakeOp == "handshake.lazy_fork" || handshakeOp == "handshake.divf" || - handshakeOp == "handshake.ori" || handshakeOp == "handshake.shrsi" || - handshakeOp == "handshake.xori" || handshakeOp == "handshake.negf" || - handshakeOp == "handshake.truncf" || handshakeOp == "handshake.divsi" || - handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || - handshakeOp == "handshake.extf" || handshakeOp == "handshake.maximumf" || - handshakeOp == "handshake.minimumf" || handshakeOp == "handshake.shrui" || - handshakeOp == "handshake.join" || handshakeOp == "handshake.remsi" || - handshakeOp == "handshake.not" || - // the first input has extra signals - handshakeOp == "handshake.load" || handshakeOp == "handshake.store" || - handshakeOp == "handshake.spec_commit" || - handshakeOp == "handshake.speculating_branch") { - serializedParams["EXTRA_SIGNALS"] = - serializeExtraSignals(modType.getInputType(0)); - } else if (handshakeOp == "handshake.source" || - handshakeOp == "handshake.non_spec") { - serializedParams["EXTRA_SIGNALS"] = - serializeExtraSignals(modType.getOutputType(0)); - } else if (handshakeOp == "handshake.mem_controller" || - handshakeOp == "mem_to_bram" || handshakeOp == "handshake.lsq" || - handshakeOp == "handshake.sharing_wrapper" || - handshakeOp == "handshake.ram") { - // Skip - } else { - modOp.emitError("Failed to get extra signals of operation"); - return failure(); - } - return success(); + // No serialized parameters found => failure + modOp.emitError("No serialized parameters found (hw.serialized_parameters)"); + return failure(); } LogicalResult RTLMatch::concretize(const RTLRequest &request, diff --git a/tools/integration/TEST_SUITE.cpp b/tools/integration/TEST_SUITE.cpp index 2f45eb34c6..b066dd0b2c 100644 --- a/tools/integration/TEST_SUITE.cpp +++ b/tools/integration/TEST_SUITE.cpp @@ -22,6 +22,9 @@ class CBCSolverFixture : public testing::TestWithParam {}; // Use FPL22 placement algorithm on a small subset of MiscBenchmarks class FPL22Fixture : public testing::TestWithParam {}; +class VerilogFixture : public testing::TestWithParam {}; +class VerilogMemoryFixture : public testing::TestWithParam {}; +class VerilogSharingFixture : public testing::TestWithParam {}; class MemoryFixture : public testing::TestWithParam {}; class SharingFixture : public testing::TestWithParam {}; class SharingUnitTestFixture : public testing::TestWithParam {}; @@ -182,7 +185,7 @@ TEST_P(SharingFixture, sharing_NoCI) { RecordProperty("cycles", std::to_string(configWithSharing.simTime)); } -TEST_P(SpecFixture, spec) { +TEST_P(SpecFixture, spec_NoCI) { const std::string &name = GetParam(); int simTime = -1; @@ -191,6 +194,70 @@ TEST_P(SpecFixture, spec) { RecordProperty("cycles", std::to_string(simTime)); } +// Verilog +TEST_P(VerilogFixture, verilog_CI) { + IntegrationTestData config{ + // clang-format off + .name = GetParam(), + .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test", + .useVerilog = true, + .useSharing = false, + .milpSolver = "gurobi", + .bufferAlgorithm = "fpga20", + .simTime = -1 + // clang-format on + }; + EXPECT_EQ(runIntegrationTest(config), 0); + RecordProperty("cycles", std::to_string(config.simTime)); +} +TEST_P(VerilogMemoryFixture, verilog_CI) { + IntegrationTestData config{ + // clang-format off + .name = GetParam(), + .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test" / "memory", + .useVerilog = true, + .useSharing = false, + .milpSolver = "gurobi", + .bufferAlgorithm = "fpga20", + .simTime = -1 + // clang-format on + }; + EXPECT_EQ(runIntegrationTest(config), 0); + RecordProperty("cycles", std::to_string(config.simTime)); +} + +TEST_P(VerilogSharingFixture, verilog_CI) { + IntegrationTestData config{ + // clang-format off + .name = GetParam(), + .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test" / "sharing", + .useVerilog = true, + .useSharing = false, + .milpSolver = "gurobi", + .bufferAlgorithm = "fpga20", + .simTime = -1 + // clang-format on + }; + EXPECT_EQ(runIntegrationTest(config), 0); + RecordProperty("cycles", std::to_string(config.simTime)); +} + +TEST_P(VerilogFixture, verilog_NoCI) { + IntegrationTestData config{ + // clang-format off + .name = GetParam(), + .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test", + .useVerilog = true, + .useSharing = false, + .milpSolver = "gurobi", + .bufferAlgorithm = "fpga20", + .simTime = -1 + // clang-format on + }; + EXPECT_EQ(runIntegrationTest(config), 0); + RecordProperty("cycles", std::to_string(config.simTime)); +} + // clang-format off INSTANTIATE_TEST_SUITE_P( MiscBenchmarks, BasicFixture, @@ -356,3 +423,113 @@ INSTANTIATE_TEST_SUITE_P(SpecBenchmarks, SpecFixture, ), [](const auto &info) { return "spec_" + info.param; }); // clang-format on + +// Verilog tests: CI safe +INSTANTIATE_TEST_SUITE_P( + VerilogSharingTestsCI, VerilogSharingFixture, + testing::Values( + "share_test_1", + "share_test_2" + ), + [](const auto &info) { return "sharing_" + info.param; }); + +INSTANTIATE_TEST_SUITE_P( + VerilogMemoryTestsCI, VerilogMemoryFixture, + testing::Values( + "test_flatten_array", + "test_memory_1", + "test_memory_10", + "test_memory_11", + "test_memory_12", + "test_memory_13", + "test_memory_14", + "test_memory_15", + "test_memory_16", + "test_memory_17", + "test_memory_18", + "test_memory_2", + "test_memory_3", + "test_memory_4", + "test_memory_5", + "test_memory_6", + "test_memory_7", + "test_memory_8", + "test_memory_9", + "test_smallbound" + ), + [](const auto &info) { return "memory_" + info.param; }); + +INSTANTIATE_TEST_SUITE_P( + VerilogTestsCI, VerilogFixture, + testing::Values( + "bicg", + "binary_search", + "factorial", + "fir", + "gaussian", + "gcd", + "gemver", + "if_loop_1", + "if_loop_2", + "if_loop_3", + "iir", + "image_resize", + "insertion_sort", + "iterative_division", + "iterative_sqrt", + "jacobi_1d_imper", + "kernel_2mm", + "kernel_3mm", + "kmp", + "loop_array", + "matrix", + "matrix_power", + "matvec", + "mul_example", + "pivot", + "polyn_mult", + "simple_example_1", + "sobel", + "spmv", + "stencil_2d", + "sumi3_mem", + "test_loop_free", + "test_stdint", + "threshold", + "triangular", + "vector_rescale", + "video_filter", + "while_loop_1", + "while_loop_3" + ), + [](const auto &info) { return info.param; } +); + +// Verilog tests: NoCI +INSTANTIATE_TEST_SUITE_P( + VerilogTests_NoCI, VerilogFixture, + testing::Values( + "atax", + "atax_float", + "bicg_float", + "float_basic", + "gemm", + "gemm_float", + "gemver_float", + "gesummv_float", + "get_tanh", + "gsum", + "gsumif", + "histogram", + "if_loop_add", + "if_loop_mul", + "kernel_2mm_float", + "kernel_3mm_float", + "lu", + "matching", + "matching_2", + "mvt_float", + "symm_float", + "syr2k_float" + ), + [](const auto &info) { return info.param; }); From 966c78e23e9c61d64cc08e92afffc25ed71d1a88 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 11:04:42 +0100 Subject: [PATCH 02/12] formatting --- include/dynamatic/Support/RTL/RTL.h | 11 +- .../HandshakeToHW/HandshakeToHW.cpp | 45 ++++--- lib/Support/RTL/RTL.cpp | 11 +- tools/integration/TEST_SUITE.cpp | 124 ++++-------------- 4 files changed, 64 insertions(+), 127 deletions(-) diff --git a/include/dynamatic/Support/RTL/RTL.h b/include/dynamatic/Support/RTL/RTL.h index b75dc53344..9891b7269b 100644 --- a/include/dynamatic/Support/RTL/RTL.h +++ b/include/dynamatic/Support/RTL/RTL.h @@ -19,14 +19,14 @@ #define DYNAMATIC_SUPPORT_RTL_RTL_H #include "dynamatic/Dialect/HW/HWOps.h" +#include "dynamatic/Dialect/Handshake/HandshakeTypes.h" #include "dynamatic/Support/LLVM.h" #include "dynamatic/Support/RTL/RTLTypes.h" #include "dynamatic/Support/Utils/Utils.h" +#include "mlir/IR/Types.h" #include "llvm/Support/JSON.h" #include #include -#include "mlir/IR/Types.h" -#include "dynamatic/Dialect/Handshake/HandshakeTypes.h" namespace dynamatic { @@ -56,7 +56,6 @@ replaceRegexes(StringRef input, std::string substituteParams(StringRef input, const ParameterMappings ¶meters); - /// Returns the bitwidth of the type as string. If the type is a control type 0. inline std::string getBitwidthString(mlir::Type type) { return std::to_string(dynamatic::handshake::getHandshakeTypeBitWidth(type)); @@ -90,7 +89,9 @@ inline std::string serializeExtraSignals(const mlir::Type &type) { } /// Compute serialized parameters from a handshake operation -dynamatic::ParameterMappings computeSerializedParameters(llvm::StringRef handshakeOp, hw::ModuleType modType); +dynamatic::ParameterMappings +computeSerializedParameters(llvm::StringRef handshakeOp, + hw::ModuleType modType); class RTLMatch; class RTLParameter; @@ -331,7 +332,7 @@ class RTLMatch { /// Temporary function. These parameters should be added to hw.parameters /// (generation_params in the future) LogicalResult registerParameters(hw::HWModuleExternOp &modOp); - + /// Attempts to concretize the matched RTL component using the original RTL /// request that created the match. Generic components are copied to the /// output directory while generated components are produced by the diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 7ad8e8045c..319241b4a6 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -23,8 +23,8 @@ #include "dynamatic/Dialect/Handshake/MemoryInterfaces.h" #include "dynamatic/Support/Attribute.h" #include "dynamatic/Support/Backedge.h" -#include "dynamatic/Support/Utils/Utils.h" #include "dynamatic/Support/RTL/RTL.h" +#include "dynamatic/Support/Utils/Utils.h" #include "dynamatic/Transforms/HandshakeMaterialize.h" #include "mlir/Dialect/MemRef/IR/MemRef.h" #include "mlir/IR/Attributes.h" @@ -101,8 +101,9 @@ static Type lowerType(Type type) { } // Compute serialized textual parameters (moved from RTL.cpp). -dynamatic::ParameterMappings dynamatic::computeSerializedParameters( - llvm::StringRef handshakeOp, hw::ModuleType modType) { +dynamatic::ParameterMappings +dynamatic::computeSerializedParameters(llvm::StringRef handshakeOp, + hw::ModuleType modType) { ParameterMappings pm; // Bitwidth @@ -226,7 +227,6 @@ dynamatic::ParameterMappings dynamatic::computeSerializedParameters( return pm; } - namespace { /// Helper class to build HW modules progressively by adding inputs/outputs @@ -235,7 +235,7 @@ class ModuleBuilder { public: /// The MLIR context is used to create string attributes for port names /// and types for the clock and reset ports, should they be added. - ModuleBuilder(MLIRContext *ctx) : ctx(ctx) {}; + ModuleBuilder(MLIRContext *ctx) : ctx(ctx){}; /// Builds the module port information from the current list of inputs and /// outputs. @@ -362,7 +362,7 @@ struct InternalMemLoweringState { InternalMemLoweringState(handshake::RAMOp ramOp, handshake::MemoryOpInterface memInterface) : ramOp(ramOp), memInterface(memInterface), - ports(getMemoryPorts(memInterface)), portNames(memInterface) {}; + ports(getMemoryPorts(memInterface)), portNames(memInterface){}; }; /// Summarizes information to convert a Handshake function into a @@ -475,7 +475,7 @@ MemLoweringState::getMemOutputPorts(hw::HWModuleOp modOp) { LoweringState::LoweringState(mlir::ModuleOp modOp, NameAnalysis &namer, OpBuilder &builder) - : modOp(modOp), namer(namer), edgeBuilder(builder, modOp.getLoc()) {}; + : modOp(modOp), namer(namer), edgeBuilder(builder, modOp.getLoc()){}; /// Attempts to find an external HW module in the MLIR module with the /// provided name. Returns it if it exists, otherwise returns `nullptr`. @@ -1049,7 +1049,7 @@ namespace { class HWBuilder { public: /// Creates the hardware builder. - HWBuilder(MLIRContext *ctx) : modBuilder(ctx) {}; + HWBuilder(MLIRContext *ctx) : modBuilder(ctx){}; /// Adds a value to the list of operands for the future instance, and its type /// to the future external module's input port information. @@ -1238,11 +1238,13 @@ hw::InstanceOp HWBuilder::createInstance(ModuleDiscriminator &discriminator, modBuilder.getPortInfo()); discriminator.setParameters(extModOp); - // Compute serialized textual parameters and put them to the external module so export-rtl can read them. + // Compute serialized textual parameters and put them to the external module + // so export-rtl can read them. MLIRContext *ctx = extModOp.getContext(); - StringRef rtlName = extModOp->getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); - auto serialized = dynamatic::computeSerializedParameters(rtlName, - extModOp.getModuleType()); + StringRef rtlName = + extModOp->getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); + auto serialized = dynamatic::computeSerializedParameters( + rtlName, extModOp.getModuleType()); std::vector serialAttrs; for (auto it = serialized.begin(); it != serialized.end(); ++it) { StringRef key = it->first(); @@ -1250,10 +1252,11 @@ hw::InstanceOp HWBuilder::createInstance(ModuleDiscriminator &discriminator, serialAttrs.emplace_back(StringAttr::get(ctx, key), StringAttr::get(ctx, val)); } - if (!serialAttrs.empty()){ - extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), DictionaryAttr::get(ctx, serialAttrs)); + if (!serialAttrs.empty()) { + extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), + DictionaryAttr::get(ctx, serialAttrs)); } - + builder.restoreInsertionPoint(instInsertPoint); } @@ -1942,8 +1945,7 @@ class MemToBRAMConverter : public ConverterBuilder { OpBuilder &builder) : ConverterBuilder(buildExternalModule(circuitMod, state, builder), IOMapping(state.outputIdx, 0, 5), IOMapping(0, 0, 8), - IOMapping(0, 5, 2), - IOMapping(8, state.inputIdx, 1)) {}; + IOMapping(0, 5, 2), IOMapping(8, state.inputIdx, 1)){}; private: /// Creates, inserts, and returns the external harware module corresponding to @@ -2052,14 +2054,17 @@ MemToBRAMConverter::buildExternalModule(hw::HWModuleOp circuitMod, DictionaryAttr::get(ctx, parameters)); // Compute and add serialized parameters so the RTL exporter can read them { - ParameterMappings pm = dynamatic::computeSerializedParameters(HW_NAME, extModOp.getModuleType()); + ParameterMappings pm = dynamatic::computeSerializedParameters( + HW_NAME, extModOp.getModuleType()); std::vector serializedAttrs; for (auto it = pm.begin(); it != pm.end(); ++it) { StringRef key = it->getKey(); std::string &val = it->getValue(); - serializedAttrs.emplace_back(StringAttr::get(ctx, key), StringAttr::get(ctx, val)); + serializedAttrs.emplace_back(StringAttr::get(ctx, key), + StringAttr::get(ctx, val)); } - extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), DictionaryAttr::get(ctx, serializedAttrs)); + extModOp->setAttr(StringAttr::get(ctx, "hw.serialized_parameters"), + DictionaryAttr::get(ctx, serializedAttrs)); } return extModOp; } diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index 3f0800a422..43b3140932 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -98,8 +98,7 @@ std::string dynamatic::substituteParams(StringRef input, RTLRequestFromOp::RTLRequestFromOp(Operation *op, const llvm::Twine &name) : RTLRequest(op->getLoc()), name(name.str()), op(op), - parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)) { - }; + parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)){}; Attribute RTLRequestFromOp::getParameter(const RTLParameter ¶m) const { if (!parameters) @@ -249,7 +248,8 @@ MapVector RTLMatch::getGenericParameterValues() const { LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { // Require precomputed serialized parameters attached during lowering as // the `hw.serialized_parameters` attribute. - if (auto dict = modOp->getAttrOfType("hw.serialized_parameters")) { + if (auto dict = + modOp->getAttrOfType("hw.serialized_parameters")) { for (auto namedAttr : dict.getValue()) { StringRef key = namedAttr.getName().getValue(); Attribute val = namedAttr.getValue(); @@ -258,9 +258,8 @@ LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { } else if (auto i = val.dyn_cast()) { serializedParams[key.str()] = std::to_string(i.getInt()); } else { - // // neither string nor integer attribute... use print method of attribute - // std::string tmp; - // llvm::raw_string_ostream os(tmp); + // // neither string nor integer attribute... use print method of + // attribute std::string tmp; llvm::raw_string_ostream os(tmp); // val.print(os); // serializedParams[key.str()] = os.str(); return failure(); diff --git a/tools/integration/TEST_SUITE.cpp b/tools/integration/TEST_SUITE.cpp index b066dd0b2c..1f18267b61 100644 --- a/tools/integration/TEST_SUITE.cpp +++ b/tools/integration/TEST_SUITE.cpp @@ -425,111 +425,43 @@ INSTANTIATE_TEST_SUITE_P(SpecBenchmarks, SpecFixture, // clang-format on // Verilog tests: CI safe -INSTANTIATE_TEST_SUITE_P( - VerilogSharingTestsCI, VerilogSharingFixture, - testing::Values( - "share_test_1", - "share_test_2" - ), - [](const auto &info) { return "sharing_" + info.param; }); +INSTANTIATE_TEST_SUITE_P(VerilogSharingTestsCI, VerilogSharingFixture, + testing::Values("share_test_1", "share_test_2"), + [](const auto &info) { + return "sharing_" + info.param; + }); INSTANTIATE_TEST_SUITE_P( VerilogMemoryTestsCI, VerilogMemoryFixture, - testing::Values( - "test_flatten_array", - "test_memory_1", - "test_memory_10", - "test_memory_11", - "test_memory_12", - "test_memory_13", - "test_memory_14", - "test_memory_15", - "test_memory_16", - "test_memory_17", - "test_memory_18", - "test_memory_2", - "test_memory_3", - "test_memory_4", - "test_memory_5", - "test_memory_6", - "test_memory_7", - "test_memory_8", - "test_memory_9", - "test_smallbound" - ), + testing::Values("test_flatten_array", "test_memory_1", "test_memory_10", + "test_memory_11", "test_memory_12", "test_memory_13", + "test_memory_14", "test_memory_15", "test_memory_16", + "test_memory_17", "test_memory_18", "test_memory_2", + "test_memory_3", "test_memory_4", "test_memory_5", + "test_memory_6", "test_memory_7", "test_memory_8", + "test_memory_9", "test_smallbound"), [](const auto &info) { return "memory_" + info.param; }); INSTANTIATE_TEST_SUITE_P( VerilogTestsCI, VerilogFixture, - testing::Values( - "bicg", - "binary_search", - "factorial", - "fir", - "gaussian", - "gcd", - "gemver", - "if_loop_1", - "if_loop_2", - "if_loop_3", - "iir", - "image_resize", - "insertion_sort", - "iterative_division", - "iterative_sqrt", - "jacobi_1d_imper", - "kernel_2mm", - "kernel_3mm", - "kmp", - "loop_array", - "matrix", - "matrix_power", - "matvec", - "mul_example", - "pivot", - "polyn_mult", - "simple_example_1", - "sobel", - "spmv", - "stencil_2d", - "sumi3_mem", - "test_loop_free", - "test_stdint", - "threshold", - "triangular", - "vector_rescale", - "video_filter", - "while_loop_1", - "while_loop_3" - ), - [](const auto &info) { return info.param; } -); + testing::Values("bicg", "binary_search", "factorial", "fir", "gaussian", + "gcd", "gemver", "if_loop_1", "if_loop_2", "if_loop_3", + "iir", "image_resize", "insertion_sort", + "iterative_division", "iterative_sqrt", "jacobi_1d_imper", + "kernel_2mm", "kernel_3mm", "kmp", "loop_array", "matrix", + "matrix_power", "matvec", "mul_example", "pivot", + "polyn_mult", "simple_example_1", "sobel", "spmv", + "stencil_2d", "sumi3_mem", "test_loop_free", "test_stdint", + "threshold", "triangular", "vector_rescale", "video_filter", + "while_loop_1", "while_loop_3"), + [](const auto &info) { return info.param; }); // Verilog tests: NoCI INSTANTIATE_TEST_SUITE_P( VerilogTests_NoCI, VerilogFixture, - testing::Values( - "atax", - "atax_float", - "bicg_float", - "float_basic", - "gemm", - "gemm_float", - "gemver_float", - "gesummv_float", - "get_tanh", - "gsum", - "gsumif", - "histogram", - "if_loop_add", - "if_loop_mul", - "kernel_2mm_float", - "kernel_3mm_float", - "lu", - "matching", - "matching_2", - "mvt_float", - "symm_float", - "syr2k_float" - ), + testing::Values("atax", "atax_float", "bicg_float", "float_basic", "gemm", + "gemm_float", "gemver_float", "gesummv_float", "get_tanh", + "gsum", "gsumif", "histogram", "if_loop_add", "if_loop_mul", + "kernel_2mm_float", "kernel_3mm_float", "lu", "matching", + "matching_2", "mvt_float", "symm_float", "syr2k_float"), [](const auto &info) { return info.param; }); From cebfbe25c3c55b1c59aff13a91027bf25a3caf91 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 11:11:59 +0100 Subject: [PATCH 03/12] format --- lib/Conversion/HandshakeToHW/HandshakeToHW.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 319241b4a6..4a8948cb64 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -235,7 +235,7 @@ class ModuleBuilder { public: /// The MLIR context is used to create string attributes for port names /// and types for the clock and reset ports, should they be added. - ModuleBuilder(MLIRContext *ctx) : ctx(ctx){}; + ModuleBuilder(MLIRContext *ctx) : ctx(ctx) {} /// Builds the module port information from the current list of inputs and /// outputs. @@ -362,7 +362,7 @@ struct InternalMemLoweringState { InternalMemLoweringState(handshake::RAMOp ramOp, handshake::MemoryOpInterface memInterface) : ramOp(ramOp), memInterface(memInterface), - ports(getMemoryPorts(memInterface)), portNames(memInterface){}; + ports(getMemoryPorts(memInterface)), portNames(memInterface) {} }; /// Summarizes information to convert a Handshake function into a @@ -475,7 +475,7 @@ MemLoweringState::getMemOutputPorts(hw::HWModuleOp modOp) { LoweringState::LoweringState(mlir::ModuleOp modOp, NameAnalysis &namer, OpBuilder &builder) - : modOp(modOp), namer(namer), edgeBuilder(builder, modOp.getLoc()){}; + : modOp(modOp), namer(namer), edgeBuilder(builder, modOp.getLoc()) {} /// Attempts to find an external HW module in the MLIR module with the /// provided name. Returns it if it exists, otherwise returns `nullptr`. @@ -1049,7 +1049,7 @@ namespace { class HWBuilder { public: /// Creates the hardware builder. - HWBuilder(MLIRContext *ctx) : modBuilder(ctx){}; + HWBuilder(MLIRContext *ctx) : modBuilder(ctx) {} /// Adds a value to the list of operands for the future instance, and its type /// to the future external module's input port information. From 02f45dc90aa036b57bb2a4d9e501c45df30cb7e1 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 11:15:18 +0100 Subject: [PATCH 04/12] format --- lib/Conversion/HandshakeToHW/HandshakeToHW.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 4a8948cb64..2f4362de70 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -1945,7 +1945,7 @@ class MemToBRAMConverter : public ConverterBuilder { OpBuilder &builder) : ConverterBuilder(buildExternalModule(circuitMod, state, builder), IOMapping(state.outputIdx, 0, 5), IOMapping(0, 0, 8), - IOMapping(0, 5, 2), IOMapping(8, state.inputIdx, 1)){}; + IOMapping(0, 5, 2), IOMapping(8, state.inputIdx, 1)) {} private: /// Creates, inserts, and returns the external harware module corresponding to From a5c14a09b07150d126d5f4e70ac483721b83691f Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 11:18:21 +0100 Subject: [PATCH 05/12] format --- lib/Support/RTL/RTL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index 43b3140932..4d6b0939db 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -98,7 +98,7 @@ std::string dynamatic::substituteParams(StringRef input, RTLRequestFromOp::RTLRequestFromOp(Operation *op, const llvm::Twine &name) : RTLRequest(op->getLoc()), name(name.str()), op(op), - parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)){}; + parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)){} Attribute RTLRequestFromOp::getParameter(const RTLParameter ¶m) const { if (!parameters) From 3b9b064ccfdb9d04ad106c601cb7ae489c941a4c Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Tue, 4 Nov 2025 11:31:01 +0100 Subject: [PATCH 06/12] dummy commit to run tests again --- lib/Support/RTL/RTL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index 4d6b0939db..a48aba7694 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -260,7 +260,7 @@ LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { } else { // // neither string nor integer attribute... use print method of // attribute std::string tmp; llvm::raw_string_ostream os(tmp); - // val.print(os); + // val.print(os); // serializedParams[key.str()] = os.str(); return failure(); } From 3b2906aedf01996a637687479d821dfe7ecb11a3 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Sun, 9 Nov 2025 23:02:37 +0100 Subject: [PATCH 07/12] moving code --- include/dynamatic/Support/RTL/RTL.h | 42 +-- .../HandshakeToHW/HandshakeToHW.cpp | 301 ++++++++++-------- 2 files changed, 180 insertions(+), 163 deletions(-) diff --git a/include/dynamatic/Support/RTL/RTL.h b/include/dynamatic/Support/RTL/RTL.h index 9891b7269b..dc98df7e51 100644 --- a/include/dynamatic/Support/RTL/RTL.h +++ b/include/dynamatic/Support/RTL/RTL.h @@ -19,11 +19,9 @@ #define DYNAMATIC_SUPPORT_RTL_RTL_H #include "dynamatic/Dialect/HW/HWOps.h" -#include "dynamatic/Dialect/Handshake/HandshakeTypes.h" #include "dynamatic/Support/LLVM.h" #include "dynamatic/Support/RTL/RTLTypes.h" #include "dynamatic/Support/Utils/Utils.h" -#include "mlir/IR/Types.h" #include "llvm/Support/JSON.h" #include #include @@ -56,42 +54,10 @@ replaceRegexes(StringRef input, std::string substituteParams(StringRef input, const ParameterMappings ¶meters); -/// Returns the bitwidth of the type as string. If the type is a control type 0. -inline std::string getBitwidthString(mlir::Type type) { - return std::to_string(dynamatic::handshake::getHandshakeTypeBitWidth(type)); -} - -/// Serialize all extra signals present to string. -inline std::string serializeExtraSignals(const mlir::Type &type) { - assert(type.isa() && - "type should be ChannelType or ControlType"); - - dynamatic::handshake::ExtraSignalsTypeInterface extraSignalsType = - type.cast(); - - std::string extraSignalsValue; - llvm::raw_string_ostream extraSignals(extraSignalsValue); - - extraSignals << "{"; - bool first = true; - for (const dynamatic::handshake::ExtraSignal &extraSignal : - extraSignalsType.getExtraSignals()) { - if (!first) - extraSignals << ", "; - first = false; - - extraSignals << "\"" << extraSignal.name << "\": "; - extraSignals << extraSignal.getBitWidth(); - } - extraSignals << "}"; - - return std::string("'") + extraSignals.str() + std::string("'"); -} - -/// Compute serialized parameters from a handshake operation -dynamatic::ParameterMappings -computeSerializedParameters(llvm::StringRef handshakeOp, - hw::ModuleType modType); +/* Helper utilities for handshake type bitwidth and extra-signal serialization + were intentionally moved out of this header to avoid exposing Handshake + specific APIs from the general RTL header. Implementations that need these + utilities should provide their own local helpers. */ class RTLMatch; class RTLParameter; diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 2f4362de70..5a59e352ff 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -100,133 +100,44 @@ static Type lowerType(Type type) { .Default([](auto type) { return nullptr; }); } -// Compute serialized textual parameters (moved from RTL.cpp). -dynamatic::ParameterMappings -dynamatic::computeSerializedParameters(llvm::StringRef handshakeOp, - hw::ModuleType modType) { - ParameterMappings pm; +// Local helper: return handshake type bitwidth as string. Kept local to this +// translation unit because it's only used by the Handshake->HW conversion. +static std::string getBitwidthString(mlir::Type type) { + return std::to_string(dynamatic::handshake::getHandshakeTypeBitWidth(type)); +} - // Bitwidth - if ( - // default - handshakeOp == "handshake.addi" || handshakeOp == "handshake.andi" || - handshakeOp == "handshake.buffer" || handshakeOp == "handshake.cmpi" || - handshakeOp == "handshake.fork" || handshakeOp == "handshake.lazy_fork" || - handshakeOp == "handshake.merge" || handshakeOp == "handshake.muli" || - handshakeOp == "handshake.sink" || handshakeOp == "handshake.subi" || - handshakeOp == "handshake.shli" || handshakeOp == "handshake.blocker" || - handshakeOp == "handshake.uitofp" || handshakeOp == "handshake.sitofp" || - handshakeOp == "handshake.fptosi" || - handshakeOp == "handshake.rigidifier" || handshakeOp == "handshake.ori" || - handshakeOp == "handshake.shrsi" || handshakeOp == "handshake.xori" || - handshakeOp == "handshake.negf" || handshakeOp == "handshake.divsi" || - handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || - handshakeOp == "handshake.shrui" || handshakeOp == "handshake.remsi" || - handshakeOp == "handshake.not" || - // the first input has data bitwidth - handshakeOp == "handshake.speculator" || - handshakeOp == "handshake.spec_commit" || - handshakeOp == "handshake.spec_save_commit" || - handshakeOp == "handshake.sharing_wrapper" || - handshakeOp == "handshake.non_spec") { - pm["BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - } else if (handshakeOp == "handshake.cond_br" || - handshakeOp == "handshake.select") { - pm["BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.constant") { - pm["BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); - } else if (handshakeOp == "handshake.control_merge") { - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); - } else if (handshakeOp == "handshake.extsi" || - handshakeOp == "handshake.trunci" || - handshakeOp == "handshake.extui") { - pm["INPUT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["OUTPUT_BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); - } else if (handshakeOp == "handshake.load") { - pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); - } else if (handshakeOp == "handshake.mux") { - pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.store") { - pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.speculating_branch") { - pm["SPEC_TAG_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.mem_controller" || - handshakeOp == "handshake.lsq") { - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["ADDR_BITWIDTH"] = - getBitwidthString(modType.getOutputType(modType.getNumOutputs() - 2)); - } else if (handshakeOp == "mem_to_bram") { - pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(4)); - } else if (handshakeOp == "handshake.addf" || - handshakeOp == "handshake.cmpf" || - handshakeOp == "handshake.mulf" || - handshakeOp == "handshake.subf" || - handshakeOp == "handshake.divf") { - int bitwidth = handshake::getHandshakeTypeBitWidth(modType.getInputType(0)); - pm["IS_DOUBLE"] = bitwidth == 64 ? "True" : "False"; - } else if (handshakeOp == "handshake.valid_merger") { - pm["LEFT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); - pm["RIGHT_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); - } else if (handshakeOp == "handshake.source" || - handshakeOp == "mem_controller" || - handshakeOp == "handshake.truncf" || - handshakeOp == "handshake.extf" || - handshakeOp == "handshake.maximumf" || - handshakeOp == "handshake.minimumf" || - handshakeOp == "handshake.join") { - // nothing - } else if (handshakeOp == "handshake.ram") { - pm["ADDR_WIDTH"] = getBitwidthString(modType.getInputType(1)); - pm["DATA_WIDTH"] = getBitwidthString(modType.getInputType(4)); - } +// Local helper: serialize ExtraSignals attached to a ChannelType/ControlType +// into the same JSON-ish string form previously exposed from the RTL header. +static std::string serializeExtraSignalsLocal(const mlir::Type &type) { + assert(type.isa() && + "type should be ChannelType or ControlType"); - // Extra signals - if ( - // default - handshakeOp == "handshake.addf" || handshakeOp == "handshake.addi" || - handshakeOp == "handshake.andi" || handshakeOp == "handshake.buffer" || - handshakeOp == "handshake.cmpf" || handshakeOp == "handshake.cmpi" || - handshakeOp == "handshake.cond_br" || - handshakeOp == "handshake.constant" || handshakeOp == "handshake.extsi" || - handshakeOp == "handshake.fork" || handshakeOp == "handshake.merge" || - handshakeOp == "handshake.mulf" || handshakeOp == "handshake.muli" || - handshakeOp == "handshake.select" || handshakeOp == "handshake.sink" || - handshakeOp == "handshake.subf" || handshakeOp == "handshake.extui" || - handshakeOp == "handshake.shli" || handshakeOp == "handshake.subi" || - handshakeOp == "handshake.spec_save_commit" || - handshakeOp == "handshake.speculator" || - handshakeOp == "handshake.trunci" || handshakeOp == "handshake.mux" || - handshakeOp == "handshake.control_merge" || - handshakeOp == "handshake.blocker" || handshakeOp == "handshake.uitofp" || - handshakeOp == "handshake.sitofp" || handshakeOp == "handshake.fptosi" || - handshakeOp == "handshake.lazy_fork" || handshakeOp == "handshake.divf" || - handshakeOp == "handshake.ori" || handshakeOp == "handshake.shrsi" || - handshakeOp == "handshake.xori" || handshakeOp == "handshake.negf" || - handshakeOp == "handshake.truncf" || handshakeOp == "handshake.divsi" || - handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || - handshakeOp == "handshake.extf" || handshakeOp == "handshake.maximumf" || - handshakeOp == "handshake.minimumf" || handshakeOp == "handshake.shrui" || - handshakeOp == "handshake.join" || handshakeOp == "handshake.remsi" || - handshakeOp == "handshake.not" || - // the first input has extra signals - handshakeOp == "handshake.load" || handshakeOp == "handshake.store" || - handshakeOp == "handshake.spec_commit" || - handshakeOp == "handshake.speculating_branch") { - pm["EXTRA_SIGNALS"] = serializeExtraSignals(modType.getInputType(0)); - } else if (handshakeOp == "handshake.source" || - handshakeOp == "handshake.non_spec") { - pm["EXTRA_SIGNALS"] = serializeExtraSignals(modType.getOutputType(0)); + dynamatic::handshake::ExtraSignalsTypeInterface extraSignalsType = + type.cast(); + + std::string extraSignalsValue; + llvm::raw_string_ostream extraSignals(extraSignalsValue); + + extraSignals << "{"; + bool first = true; + for (const dynamatic::handshake::ExtraSignal &extraSignal : + extraSignalsType.getExtraSignals()) { + if (!first) + extraSignals << ", "; + first = false; + + extraSignals << "\"" << extraSignal.name << "\": "; + extraSignals << extraSignal.getBitWidth(); } + extraSignals << "}"; - return pm; + return std::string("'") + extraSignals.str() + std::string("'"); } +// NOTE: The definition of `dynamatic::computeSerializedParameters` is +// provided after the `ModuleDiscriminator` implementation so it can forward +// to the static method placed next to the discriminator's logic. + namespace { /// Helper class to build HW modules progressively by adding inputs/outputs @@ -598,6 +509,12 @@ class ModuleDiscriminator { /// component. void setParameters(hw::HWModuleExternOp modOp); + /// Computes the textual/serialized parameter mappings for an operation given + /// its handshake operation name and the external module type. + static ::dynamatic::ParameterMappings + computeSerializedParameters(llvm::StringRef handshakeOp, + hw::ModuleType modType); + /// Whether the operations is currently unsupported. Check after construction /// and produce a failure if this returns true. bool opUnsupported() { return unsupported; } @@ -1038,6 +955,140 @@ void ModuleDiscriminator::setParameters(hw::HWModuleExternOp modOp) { DictionaryAttr::get(ctx, parameters)); } +// Implementation of the parameter serialization logic colocated with the +// ModuleDiscriminator. +::dynamatic::ParameterMappings +ModuleDiscriminator::computeSerializedParameters(llvm::StringRef handshakeOp, + hw::ModuleType modType) { + ParameterMappings pm; + + // Bitwidth + if ( + // default + handshakeOp == "handshake.addi" || handshakeOp == "handshake.andi" || + handshakeOp == "handshake.buffer" || handshakeOp == "handshake.cmpi" || + handshakeOp == "handshake.fork" || handshakeOp == "handshake.lazy_fork" || + handshakeOp == "handshake.merge" || handshakeOp == "handshake.muli" || + handshakeOp == "handshake.sink" || handshakeOp == "handshake.subi" || + handshakeOp == "handshake.shli" || handshakeOp == "handshake.blocker" || + handshakeOp == "handshake.uitofp" || handshakeOp == "handshake.sitofp" || + handshakeOp == "handshake.fptosi" || + handshakeOp == "handshake.rigidifier" || handshakeOp == "handshake.ori" || + handshakeOp == "handshake.shrsi" || handshakeOp == "handshake.xori" || + handshakeOp == "handshake.negf" || handshakeOp == "handshake.divsi" || + handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || + handshakeOp == "handshake.shrui" || handshakeOp == "handshake.remsi" || + handshakeOp == "handshake.not" || + // the first input has data bitwidth + handshakeOp == "handshake.speculator" || + handshakeOp == "handshake.spec_commit" || + handshakeOp == "handshake.spec_save_commit" || + handshakeOp == "handshake.sharing_wrapper" || + handshakeOp == "handshake.non_spec") { + pm["BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + } else if (handshakeOp == "handshake.cond_br" || + handshakeOp == "handshake.select") { + pm["BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.constant") { + pm["BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); + } else if (handshakeOp == "handshake.control_merge") { + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); + } else if (handshakeOp == "handshake.extsi" || + handshakeOp == "handshake.trunci" || + handshakeOp == "handshake.extui") { + pm["INPUT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["OUTPUT_BITWIDTH"] = getBitwidthString(modType.getOutputType(0)); + } else if (handshakeOp == "handshake.load") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getOutputType(1)); + } else if (handshakeOp == "handshake.mux") { + pm["INDEX_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.store") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.speculating_branch") { + pm["SPEC_TAG_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.mem_controller" || + handshakeOp == "handshake.lsq") { + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["ADDR_BITWIDTH"] = + getBitwidthString(modType.getOutputType(modType.getNumOutputs() - 2)); + } else if (handshakeOp == "mem_to_bram") { + pm["ADDR_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + pm["DATA_BITWIDTH"] = getBitwidthString(modType.getInputType(4)); + } else if (handshakeOp == "handshake.addf" || + handshakeOp == "handshake.cmpf" || + handshakeOp == "handshake.mulf" || + handshakeOp == "handshake.subf" || + handshakeOp == "handshake.divf") { + int bitwidth = handshake::getHandshakeTypeBitWidth(modType.getInputType(0)); + pm["IS_DOUBLE"] = bitwidth == 64 ? "True" : "False"; + } else if (handshakeOp == "handshake.valid_merger") { + pm["LEFT_BITWIDTH"] = getBitwidthString(modType.getInputType(0)); + pm["RIGHT_BITWIDTH"] = getBitwidthString(modType.getInputType(1)); + } else if (handshakeOp == "handshake.source" || + handshakeOp == "mem_controller" || + handshakeOp == "handshake.truncf" || + handshakeOp == "handshake.extf" || + handshakeOp == "handshake.maximumf" || + handshakeOp == "handshake.minimumf" || + handshakeOp == "handshake.join") { + // nothing + } else if (handshakeOp == "handshake.ram") { + pm["ADDR_WIDTH"] = getBitwidthString(modType.getInputType(1)); + pm["DATA_WIDTH"] = getBitwidthString(modType.getInputType(4)); + } + + // Extra signals + if ( + // default + handshakeOp == "handshake.addf" || handshakeOp == "handshake.addi" || + handshakeOp == "handshake.andi" || handshakeOp == "handshake.buffer" || + handshakeOp == "handshake.cmpf" || handshakeOp == "handshake.cmpi" || + handshakeOp == "handshake.cond_br" || + handshakeOp == "handshake.constant" || handshakeOp == "handshake.extsi" || + handshakeOp == "handshake.fork" || handshakeOp == "handshake.merge" || + handshakeOp == "handshake.mulf" || handshakeOp == "handshake.muli" || + handshakeOp == "handshake.select" || handshakeOp == "handshake.sink" || + handshakeOp == "handshake.subf" || handshakeOp == "handshake.extui" || + handshakeOp == "handshake.shli" || handshakeOp == "handshake.subi" || + handshakeOp == "handshake.spec_save_commit" || + handshakeOp == "handshake.speculator" || + handshakeOp == "handshake.trunci" || handshakeOp == "handshake.mux" || + handshakeOp == "handshake.control_merge" || + handshakeOp == "handshake.blocker" || handshakeOp == "handshake.uitofp" || + handshakeOp == "handshake.sitofp" || handshakeOp == "handshake.fptosi" || + handshakeOp == "handshake.lazy_fork" || handshakeOp == "handshake.divf" || + handshakeOp == "handshake.ori" || handshakeOp == "handshake.shrsi" || + handshakeOp == "handshake.xori" || handshakeOp == "handshake.negf" || + handshakeOp == "handshake.truncf" || handshakeOp == "handshake.divsi" || + handshakeOp == "handshake.absf" || handshakeOp == "handshake.divui" || + handshakeOp == "handshake.extf" || handshakeOp == "handshake.maximumf" || + handshakeOp == "handshake.minimumf" || handshakeOp == "handshake.shrui" || + handshakeOp == "handshake.join" || handshakeOp == "handshake.remsi" || + handshakeOp == "handshake.not" || + // the first input has extra signals + handshakeOp == "handshake.load" || handshakeOp == "handshake.store" || + handshakeOp == "handshake.spec_commit" || + handshakeOp == "handshake.speculating_branch") { + pm["EXTRA_SIGNALS"] = serializeExtraSignalsLocal(modType.getInputType(0)); + } else if (handshakeOp == "handshake.source" || + handshakeOp == "handshake.non_spec") { + pm["EXTRA_SIGNALS"] = serializeExtraSignalsLocal(modType.getOutputType(0)); + } + + return pm; +} + +// NOTE: The serialized-parameter helper has been moved inside this +// translation unit and is invoked directly from the places that need it +// (see usage sites below). We intentionally do not provide a free-function +// in the `dynamatic` namespace here to avoid exposing this handshake-specific +// logic from the general RTL header. + namespace { /// Builder for hardware instances (`hw::InstanceOp`) and their associated @@ -1243,8 +1294,8 @@ hw::InstanceOp HWBuilder::createInstance(ModuleDiscriminator &discriminator, MLIRContext *ctx = extModOp.getContext(); StringRef rtlName = extModOp->getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); - auto serialized = dynamatic::computeSerializedParameters( - rtlName, extModOp.getModuleType()); + auto serialized = ModuleDiscriminator::computeSerializedParameters( + rtlName, extModOp.getModuleType()); std::vector serialAttrs; for (auto it = serialized.begin(); it != serialized.end(); ++it) { StringRef key = it->first(); @@ -2054,8 +2105,8 @@ MemToBRAMConverter::buildExternalModule(hw::HWModuleOp circuitMod, DictionaryAttr::get(ctx, parameters)); // Compute and add serialized parameters so the RTL exporter can read them { - ParameterMappings pm = dynamatic::computeSerializedParameters( - HW_NAME, extModOp.getModuleType()); + ParameterMappings pm = ModuleDiscriminator::computeSerializedParameters( + HW_NAME, extModOp.getModuleType()); std::vector serializedAttrs; for (auto it = pm.begin(); it != pm.end(); ++it) { StringRef key = it->getKey(); From 6099dd3bc3f1622c61b1c12be9b3b8f5800f9457 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Sun, 9 Nov 2025 23:04:05 +0100 Subject: [PATCH 08/12] comment removed --- include/dynamatic/Support/RTL/RTL.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/include/dynamatic/Support/RTL/RTL.h b/include/dynamatic/Support/RTL/RTL.h index dc98df7e51..4957c9d188 100644 --- a/include/dynamatic/Support/RTL/RTL.h +++ b/include/dynamatic/Support/RTL/RTL.h @@ -54,11 +54,6 @@ replaceRegexes(StringRef input, std::string substituteParams(StringRef input, const ParameterMappings ¶meters); -/* Helper utilities for handshake type bitwidth and extra-signal serialization - were intentionally moved out of this header to avoid exposing Handshake - specific APIs from the general RTL header. Implementations that need these - utilities should provide their own local helpers. */ - class RTLMatch; class RTLParameter; class RTLComponent; @@ -96,7 +91,7 @@ class RTLParameter { RTLParameter &operator=(const RTLParameter &) = delete; RTLParameter(RTLParameter &&other) noexcept - : name(std::move(other.name)), type(std::move(other.type)){}; + : name(std::move(other.name)), type(std::move(other.type)) {}; RTLParameter &operator=(RTLParameter &&other) noexcept { name = std::move(other.name); @@ -161,7 +156,7 @@ struct ParamMatch { /// Construts a parameter match object from the state and an optional /// serialization for the parameter value. ParamMatch(State state, const llvm::Twine &serial = "") - : state(state), serialized(serial.str()){}; + : state(state), serialized(serial.str()) {}; }; /// A parameterized request for RTL components that match certain properties. @@ -174,7 +169,7 @@ class RTLRequest { Location loc; /// Creates an RTL request reporting errors at the provided location. - RTLRequest(Location loc) : loc(loc){}; + RTLRequest(Location loc) : loc(loc) {}; /// Returns the MLIR attribute holding the RTL parameter's value if it exists; /// otherwise returns nullptr. From 1ce1b234de5810e56c29e2b520b74215b02e4c81 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Sun, 9 Nov 2025 23:05:14 +0100 Subject: [PATCH 09/12] c --- lib/Conversion/HandshakeToHW/HandshakeToHW.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp index 5a59e352ff..5ea2c40457 100644 --- a/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp +++ b/lib/Conversion/HandshakeToHW/HandshakeToHW.cpp @@ -1294,8 +1294,8 @@ hw::InstanceOp HWBuilder::createInstance(ModuleDiscriminator &discriminator, MLIRContext *ctx = extModOp.getContext(); StringRef rtlName = extModOp->getAttrOfType(RTL_NAME_ATTR_NAME).getValue(); - auto serialized = ModuleDiscriminator::computeSerializedParameters( - rtlName, extModOp.getModuleType()); + auto serialized = ModuleDiscriminator::computeSerializedParameters( + rtlName, extModOp.getModuleType()); std::vector serialAttrs; for (auto it = serialized.begin(); it != serialized.end(); ++it) { StringRef key = it->first(); @@ -2105,8 +2105,8 @@ MemToBRAMConverter::buildExternalModule(hw::HWModuleOp circuitMod, DictionaryAttr::get(ctx, parameters)); // Compute and add serialized parameters so the RTL exporter can read them { - ParameterMappings pm = ModuleDiscriminator::computeSerializedParameters( - HW_NAME, extModOp.getModuleType()); + ParameterMappings pm = ModuleDiscriminator::computeSerializedParameters( + HW_NAME, extModOp.getModuleType()); std::vector serializedAttrs; for (auto it = pm.begin(); it != pm.end(); ++it) { StringRef key = it->getKey(); From 39b3790f624427616682acd7f754c394463f15a0 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Sun, 9 Nov 2025 23:47:05 +0100 Subject: [PATCH 10/12] fix --- lib/Support/RTL/RTL.cpp | 4 ++-- test/Conversion/HandshakeToHW/types.mlir | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index a48aba7694..9313680866 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -98,7 +98,7 @@ std::string dynamatic::substituteParams(StringRef input, RTLRequestFromOp::RTLRequestFromOp(Operation *op, const llvm::Twine &name) : RTLRequest(op->getLoc()), name(name.str()), op(op), - parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)){} + parameters(op->getAttrOfType(RTL_PARAMETERS_ATTR_NAME)) {} Attribute RTLRequestFromOp::getParameter(const RTLParameter ¶m) const { if (!parameters) @@ -260,7 +260,7 @@ LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { } else { // // neither string nor integer attribute... use print method of // attribute std::string tmp; llvm::raw_string_ostream os(tmp); - // val.print(os); + // val.print(os); // serializedParams[key.str()] = os.str(); return failure(); } diff --git a/test/Conversion/HandshakeToHW/types.mlir b/test/Conversion/HandshakeToHW/types.mlir index 70e692511b..75ac4aa20c 100644 --- a/test/Conversion/HandshakeToHW/types.mlir +++ b/test/Conversion/HandshakeToHW/types.mlir @@ -7,7 +7,7 @@ // CHECK: hw.instance "sink0" @handshake_sink_0(ins: %[[VAL_0]]: !handshake.channel, clk: %[[VAL_2]]: i1, rst: %[[VAL_3]]: i1) -> () // CHECK: hw.output %[[VAL_1]] : !handshake.control<> // CHECK: } -// CHECK: hw.module.extern @handshake_sink_0(in %[[VAL_5:.*]] : !handshake.channel, in %[[VAL_6:.*]] : i1, in %[[VAL_7:.*]] : i1) attributes {hw.name = "handshake.sink", hw.parameters = {DATA_TYPE = !handshake.channel}} +// CHECK: hw.module.extern @handshake_sink_0(in %[[VAL_5:.*]] : !handshake.channel, in %[[VAL_6:.*]] : i1, in %[[VAL_7:.*]] : i1) attributes {hw.name = "handshake.sink", hw.parameters = {DATA_TYPE = !handshake.channel}, hw.serialized_parameters = {BITWIDTH = "32", EXTRA_SIGNALS = "'{}'"}} handshake.func @dontChangeTypes(%arg : !handshake.channel, %start: !handshake.control<>) -> !handshake.control<> { sink %arg : end %start : <> @@ -21,7 +21,9 @@ handshake.func @dontChangeTypes(%arg : !handshake.channel, %start: !handsha // CHECK: %[[VAL_4:.*]] = hw.instance "addf0" @handshake_addf_0(lhs: %[[VAL_0]]: !handshake.channel, rhs: %[[VAL_1]]: !handshake.channel, clk: %[[VAL_2]]: i1, rst: %[[VAL_3]]: i1) -> (result: !handshake.channel) // CHECK: hw.output %[[VAL_4]] : !handshake.channel // CHECK: } -// CHECK: hw.module.extern @handshake_addf_0(in %[[VAL_6:.*]] : !handshake.channel, in %[[VAL_7:.*]] : !handshake.channel, in %[[VAL_8:.*]] : i1, in %[[VAL_9:.*]] : i1, out result : !handshake.channel) attributes {hw.name = "handshake.addf", hw.parameters = {DATA_TYPE = !handshake.channel, FPU_IMPL = "flopoco", INTERNAL_DELAY = "0_0", LATENCY = 1 : ui32}} +// CHECK: hw.module.extern @handshake_addf_0(in %[[VAL_6:.*]] : !handshake.channel, in %[[VAL_7:.*]] : !handshake.channel, in %[[VAL_8:.*]] : i1, in %[[VAL_9:.*]] : i1, out result : !handshake.channel) attributes {hw.name = "handshake.addf", +// CHECK-SAME: hw.parameters = {DATA_TYPE = !handshake.channel, FPU_IMPL = "flopoco", INTERNAL_DELAY = "0_0", LATENCY = 1 : ui32} +// CHECK-SAME: hw.serialized_parameters handshake.func @lowerNonIntTypes(%arg0 : !handshake.channel, %arg1 : !handshake.channel) -> !handshake.channel { %res = addf %arg0, %arg1 {latency = 1}: end %res : From f09c42589c3edd6878f126e7e6df08baba555db5 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Mon, 10 Nov 2025 00:15:14 +0100 Subject: [PATCH 11/12] comment --- lib/Support/RTL/RTL.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Support/RTL/RTL.cpp b/lib/Support/RTL/RTL.cpp index 9313680866..938be4b458 100644 --- a/lib/Support/RTL/RTL.cpp +++ b/lib/Support/RTL/RTL.cpp @@ -246,7 +246,7 @@ MapVector RTLMatch::getGenericParameterValues() const { } LogicalResult RTLMatch::registerParameters(hw::HWModuleExternOp &modOp) { - // Require precomputed serialized parameters attached during lowering as + // Require precomputed serialized parameters attached during lowering since // the `hw.serialized_parameters` attribute. if (auto dict = modOp->getAttrOfType("hw.serialized_parameters")) { From 8b7537412c0b7d619cb507bed2f727efdf778d91 Mon Sep 17 00:00:00 2001 From: Ian Ganz Date: Mon, 10 Nov 2025 09:20:07 +0100 Subject: [PATCH 12/12] reset Test_suite.cpp --- tools/integration/TEST_SUITE.cpp | 113 +------------------------------ 1 file changed, 2 insertions(+), 111 deletions(-) diff --git a/tools/integration/TEST_SUITE.cpp b/tools/integration/TEST_SUITE.cpp index 1f18267b61..d09f4dbc89 100644 --- a/tools/integration/TEST_SUITE.cpp +++ b/tools/integration/TEST_SUITE.cpp @@ -22,9 +22,6 @@ class CBCSolverFixture : public testing::TestWithParam {}; // Use FPL22 placement algorithm on a small subset of MiscBenchmarks class FPL22Fixture : public testing::TestWithParam {}; -class VerilogFixture : public testing::TestWithParam {}; -class VerilogMemoryFixture : public testing::TestWithParam {}; -class VerilogSharingFixture : public testing::TestWithParam {}; class MemoryFixture : public testing::TestWithParam {}; class SharingFixture : public testing::TestWithParam {}; class SharingUnitTestFixture : public testing::TestWithParam {}; @@ -185,7 +182,7 @@ TEST_P(SharingFixture, sharing_NoCI) { RecordProperty("cycles", std::to_string(configWithSharing.simTime)); } -TEST_P(SpecFixture, spec_NoCI) { +TEST_P(SpecFixture, spec) { const std::string &name = GetParam(); int simTime = -1; @@ -194,70 +191,6 @@ TEST_P(SpecFixture, spec_NoCI) { RecordProperty("cycles", std::to_string(simTime)); } -// Verilog -TEST_P(VerilogFixture, verilog_CI) { - IntegrationTestData config{ - // clang-format off - .name = GetParam(), - .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test", - .useVerilog = true, - .useSharing = false, - .milpSolver = "gurobi", - .bufferAlgorithm = "fpga20", - .simTime = -1 - // clang-format on - }; - EXPECT_EQ(runIntegrationTest(config), 0); - RecordProperty("cycles", std::to_string(config.simTime)); -} -TEST_P(VerilogMemoryFixture, verilog_CI) { - IntegrationTestData config{ - // clang-format off - .name = GetParam(), - .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test" / "memory", - .useVerilog = true, - .useSharing = false, - .milpSolver = "gurobi", - .bufferAlgorithm = "fpga20", - .simTime = -1 - // clang-format on - }; - EXPECT_EQ(runIntegrationTest(config), 0); - RecordProperty("cycles", std::to_string(config.simTime)); -} - -TEST_P(VerilogSharingFixture, verilog_CI) { - IntegrationTestData config{ - // clang-format off - .name = GetParam(), - .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test" / "sharing", - .useVerilog = true, - .useSharing = false, - .milpSolver = "gurobi", - .bufferAlgorithm = "fpga20", - .simTime = -1 - // clang-format on - }; - EXPECT_EQ(runIntegrationTest(config), 0); - RecordProperty("cycles", std::to_string(config.simTime)); -} - -TEST_P(VerilogFixture, verilog_NoCI) { - IntegrationTestData config{ - // clang-format off - .name = GetParam(), - .benchmarkPath = fs::path(DYNAMATIC_ROOT) / "integration-test", - .useVerilog = true, - .useSharing = false, - .milpSolver = "gurobi", - .bufferAlgorithm = "fpga20", - .simTime = -1 - // clang-format on - }; - EXPECT_EQ(runIntegrationTest(config), 0); - RecordProperty("cycles", std::to_string(config.simTime)); -} - // clang-format off INSTANTIATE_TEST_SUITE_P( MiscBenchmarks, BasicFixture, @@ -422,46 +355,4 @@ INSTANTIATE_TEST_SUITE_P(SpecBenchmarks, SpecFixture, "subdiag_fast" ), [](const auto &info) { return "spec_" + info.param; }); -// clang-format on - -// Verilog tests: CI safe -INSTANTIATE_TEST_SUITE_P(VerilogSharingTestsCI, VerilogSharingFixture, - testing::Values("share_test_1", "share_test_2"), - [](const auto &info) { - return "sharing_" + info.param; - }); - -INSTANTIATE_TEST_SUITE_P( - VerilogMemoryTestsCI, VerilogMemoryFixture, - testing::Values("test_flatten_array", "test_memory_1", "test_memory_10", - "test_memory_11", "test_memory_12", "test_memory_13", - "test_memory_14", "test_memory_15", "test_memory_16", - "test_memory_17", "test_memory_18", "test_memory_2", - "test_memory_3", "test_memory_4", "test_memory_5", - "test_memory_6", "test_memory_7", "test_memory_8", - "test_memory_9", "test_smallbound"), - [](const auto &info) { return "memory_" + info.param; }); - -INSTANTIATE_TEST_SUITE_P( - VerilogTestsCI, VerilogFixture, - testing::Values("bicg", "binary_search", "factorial", "fir", "gaussian", - "gcd", "gemver", "if_loop_1", "if_loop_2", "if_loop_3", - "iir", "image_resize", "insertion_sort", - "iterative_division", "iterative_sqrt", "jacobi_1d_imper", - "kernel_2mm", "kernel_3mm", "kmp", "loop_array", "matrix", - "matrix_power", "matvec", "mul_example", "pivot", - "polyn_mult", "simple_example_1", "sobel", "spmv", - "stencil_2d", "sumi3_mem", "test_loop_free", "test_stdint", - "threshold", "triangular", "vector_rescale", "video_filter", - "while_loop_1", "while_loop_3"), - [](const auto &info) { return info.param; }); - -// Verilog tests: NoCI -INSTANTIATE_TEST_SUITE_P( - VerilogTests_NoCI, VerilogFixture, - testing::Values("atax", "atax_float", "bicg_float", "float_basic", "gemm", - "gemm_float", "gemver_float", "gesummv_float", "get_tanh", - "gsum", "gsumif", "histogram", "if_loop_add", "if_loop_mul", - "kernel_2mm_float", "kernel_3mm_float", "lu", "matching", - "matching_2", "mvt_float", "symm_float", "syr2k_float"), - [](const auto &info) { return info.param; }); +// clang-format on \ No newline at end of file