diff --git a/include/circt-c/Firtool/Firtool.h b/include/circt-c/Firtool/Firtool.h index 810c01d3d370..8b8597c2d846 100644 --- a/include/circt-c/Firtool/Firtool.h +++ b/include/circt-c/Firtool/Firtool.h @@ -12,25 +12,126 @@ extern "C" { #endif +//===----------------------------------------------------------------------===// +// Option API. +//===----------------------------------------------------------------------===// + +#define DEFINE_C_API_STRUCT(name, storage) \ + struct name { \ + storage *ptr; \ + }; \ + typedef struct name name + +DEFINE_C_API_STRUCT(FirtoolOptions, void); + +#undef DEFINE_C_API_STRUCT + +// NOLINTNEXTLINE(modernize-use-using) +typedef enum FirtoolPreserveAggregateMode { + FIRTOOL_PRESERVE_AGGREGATE_MODE_NONE, + FIRTOOL_PRESERVE_AGGREGATE_MODE_ONE_DIM_VEC, + FIRTOOL_PRESERVE_AGGREGATE_MODE_VEC, + FIRTOOL_PRESERVE_AGGREGATE_MODE_ALL, +} FirtoolPreserveAggregateMode; + +// NOLINTNEXTLINE(modernize-use-using) +typedef enum FirtoolPreserveValuesMode { + FIRTOOL_PRESERVE_VALUES_MODE_NONE, + FIRTOOL_PRESERVE_VALUES_MODE_NAMED, + FIRTOOL_PRESERVE_VALUES_MODE_ALL, +} FirtoolPreserveValuesMode; + +// NOLINTNEXTLINE(modernize-use-using) +typedef enum FirtoolBuildMode { + FIRTOOL_BUILD_MODE_DEBUG, + FIRTOOL_BUILD_MODE_RELEASE, +} FirtoolBuildMode; + +// NOLINTNEXTLINE(modernize-use-using) +typedef enum FirtoolRandomKind { + FIRTOOL_RANDOM_KIND_NONE, + FIRTOOL_RANDOM_KIND_MEM, + FIRTOOL_RANDOM_KIND_REG, + FIRTOOL_RANDOM_KIND_ALL, +} FirtoolRandomKind; + +MLIR_CAPI_EXPORTED FirtoolOptions firtoolOptionsCreateDefault(); +MLIR_CAPI_EXPORTED void firtoolOptionsDestroy(FirtoolOptions options); + +#define DECLARE_FIRTOOL_OPTION(name, type) \ + MLIR_CAPI_EXPORTED void firtoolOptionsSet##name(FirtoolOptions options, \ + type value); \ + MLIR_CAPI_EXPORTED type firtoolOptionsGet##name(FirtoolOptions options) + +DECLARE_FIRTOOL_OPTION(OutputFilename, MlirStringRef); +DECLARE_FIRTOOL_OPTION(DisableAnnotationsUnknown, bool); +DECLARE_FIRTOOL_OPTION(DisableAnnotationsClassless, bool); +DECLARE_FIRTOOL_OPTION(LowerAnnotationsNoRefTypePorts, bool); +DECLARE_FIRTOOL_OPTION(PreserveAggregate, FirtoolPreserveAggregateMode); +DECLARE_FIRTOOL_OPTION(PreserveValues, FirtoolPreserveValuesMode); +DECLARE_FIRTOOL_OPTION(BuildMode, FirtoolBuildMode); +DECLARE_FIRTOOL_OPTION(DisableOptimization, bool); +DECLARE_FIRTOOL_OPTION(ExportChiselInterface, bool); +DECLARE_FIRTOOL_OPTION(ChiselInterfaceOutDirectory, MlirStringRef); +DECLARE_FIRTOOL_OPTION(VbToBv, bool); +DECLARE_FIRTOOL_OPTION(Dedup, bool); +DECLARE_FIRTOOL_OPTION(GrandCentralInstantiateCompanionOnly, bool); +DECLARE_FIRTOOL_OPTION(DisableAggressiveMergeConnections, bool); +DECLARE_FIRTOOL_OPTION(EmitOMIR, bool); +DECLARE_FIRTOOL_OPTION(OMIROutFile, MlirStringRef); +DECLARE_FIRTOOL_OPTION(LowerMemories, bool); +DECLARE_FIRTOOL_OPTION(BlackBoxRootPath, MlirStringRef); +DECLARE_FIRTOOL_OPTION(ReplSeqMem, bool); +DECLARE_FIRTOOL_OPTION(ReplSeqMemFile, MlirStringRef); +DECLARE_FIRTOOL_OPTION(ExtractTestCode, bool); +DECLARE_FIRTOOL_OPTION(IgnoreReadEnableMem, bool); +DECLARE_FIRTOOL_OPTION(DisableRandom, FirtoolRandomKind); +DECLARE_FIRTOOL_OPTION(OutputAnnotationFilename, MlirStringRef); +DECLARE_FIRTOOL_OPTION(EnableAnnotationWarning, bool); +DECLARE_FIRTOOL_OPTION(AddMuxPragmas, bool); +DECLARE_FIRTOOL_OPTION(EmitChiselAssertsAsSVA, bool); +DECLARE_FIRTOOL_OPTION(EmitSeparateAlwaysBlocks, bool); +DECLARE_FIRTOOL_OPTION(EtcDisableInstanceExtraction, bool); +DECLARE_FIRTOOL_OPTION(EtcDisableRegisterExtraction, bool); +DECLARE_FIRTOOL_OPTION(EtcDisableModuleInlining, bool); +DECLARE_FIRTOOL_OPTION(AddVivadoRAMAddressConflictSynthesisBugWorkaround, bool); +DECLARE_FIRTOOL_OPTION(CkgModuleName, MlirStringRef); +DECLARE_FIRTOOL_OPTION(CkgInputName, MlirStringRef); +DECLARE_FIRTOOL_OPTION(CkgOutputName, MlirStringRef); +DECLARE_FIRTOOL_OPTION(CkgEnableName, MlirStringRef); +DECLARE_FIRTOOL_OPTION(CkgTestEnableName, MlirStringRef); +DECLARE_FIRTOOL_OPTION(ExportModuleHierarchy, bool); +DECLARE_FIRTOOL_OPTION(StripFirDebugInfo, bool); +DECLARE_FIRTOOL_OPTION(StripDebugInfo, bool); + +#undef DECLARE_FIRTOOL_OPTION + +//===----------------------------------------------------------------------===// +// Populate API. +//===----------------------------------------------------------------------===// + MLIR_CAPI_EXPORTED MlirLogicalResult -firtoolPopulatePreprocessTransforms(MlirPassManager pm); +firtoolPopulatePreprocessTransforms(MlirPassManager pm, FirtoolOptions options); MLIR_CAPI_EXPORTED MlirLogicalResult firtoolPopulateCHIRRTLToLowFIRRTL( - MlirPassManager pm, MlirModule module, MlirStringRef inputFilename); + MlirPassManager pm, FirtoolOptions options, MlirModule module, + MlirStringRef inputFilename); MLIR_CAPI_EXPORTED MlirLogicalResult -firtoolPopulateLowFIRRTLToHW(MlirPassManager pm); - -MLIR_CAPI_EXPORTED MlirLogicalResult firtoolPopulateHWToSV(MlirPassManager pm); +firtoolPopulateLowFIRRTLToHW(MlirPassManager pm, FirtoolOptions options); -MLIR_CAPI_EXPORTED MlirLogicalResult firtoolPopulateExportVerilog( - MlirPassManager pm, MlirStringCallback callback, void *userData); +MLIR_CAPI_EXPORTED MlirLogicalResult +firtoolPopulateHWToSV(MlirPassManager pm, FirtoolOptions options); MLIR_CAPI_EXPORTED MlirLogicalResult -firtoolPopulateExportSplitVerilog(MlirPassManager pm, MlirStringRef directory); +firtoolPopulateExportVerilog(MlirPassManager pm, FirtoolOptions options, + MlirStringCallback callback, void *userData); + +MLIR_CAPI_EXPORTED MlirLogicalResult firtoolPopulateExportSplitVerilog( + MlirPassManager pm, FirtoolOptions options, MlirStringRef directory); MLIR_CAPI_EXPORTED MlirLogicalResult -firtoolPopulateFinalizeIR(MlirPassManager pm); +firtoolPopulateFinalizeIR(MlirPassManager pm, FirtoolOptions options); #ifdef __cplusplus } diff --git a/include/circt/Firtool/Firtool.h b/include/circt/Firtool/Firtool.h index 5a650e8e6dd3..fbce2daf5390 100644 --- a/include/circt/Firtool/Firtool.h +++ b/include/circt/Firtool/Firtool.h @@ -21,6 +21,7 @@ namespace circt { namespace firtool { +// Remember to sync changes to C-API struct FirtoolOptions { llvm::cl::OptionCategory &category; diff --git a/lib/CAPI/Firtool/Firtool.cpp b/lib/CAPI/Firtool/Firtool.cpp index ac81ae84ccae..7705dd52a776 100644 --- a/lib/CAPI/Firtool/Firtool.cpp +++ b/lib/CAPI/Firtool/Firtool.cpp @@ -16,45 +16,249 @@ using namespace circt; -// TODO: Custom options with C-API -static auto tempDefaultCategory = llvm::cl::OptionCategory{"temp-firtool-capi"}; -static auto tempDefaultOptions = firtool::FirtoolOptions{tempDefaultCategory}; +//===----------------------------------------------------------------------===// +// Option API. +//===----------------------------------------------------------------------===// + +DEFINE_C_API_PTR_METHODS(FirtoolOptions, firtool::FirtoolOptions) + +FirtoolOptions firtoolOptionsCreateDefault() { + static auto category = llvm::cl::OptionCategory{"Firtool Options"}; + auto *options = new firtool::FirtoolOptions{category}; + return wrap(options); +} + +void firtoolOptionsDestroy(FirtoolOptions options) { delete unwrap(options); } + +#define DEFINE_FIRTOOL_OPTION_STRING(name, field) \ + void firtoolOptionsSet##name(FirtoolOptions options, MlirStringRef value) { \ + unwrap(options)->field = unwrap(value).str(); \ + } \ + MlirStringRef firtoolOptionsGet##name(FirtoolOptions options) { \ + return wrap(unwrap(options)->field.getValue()); \ + } + +#define DEFINE_FIRTOOL_OPTION_BOOL(name, field) \ + void firtoolOptionsSet##name(FirtoolOptions options, bool value) { \ + unwrap(options)->field = value; \ + } \ + bool firtoolOptionsGet##name(FirtoolOptions options) { \ + return unwrap(options)->field; \ + } + +#define DEFINE_FIRTOOL_OPTION_ENUM(name, field, enum_type, c_to_cpp, cpp_to_c) \ + void firtoolOptionsSet##name(FirtoolOptions options, enum_type value) { \ + unwrap(options)->field = c_to_cpp(value); \ + } \ + enum_type firtoolOptionsGet##name(FirtoolOptions options) { \ + return cpp_to_c(unwrap(options)->field); \ + } + +DEFINE_FIRTOOL_OPTION_STRING(OutputFilename, outputFilename); +DEFINE_FIRTOOL_OPTION_BOOL(DisableAnnotationsUnknown, + disableAnnotationsUnknown); +DEFINE_FIRTOOL_OPTION_BOOL(DisableAnnotationsClassless, + disableAnnotationsClassless); +DEFINE_FIRTOOL_OPTION_BOOL(LowerAnnotationsNoRefTypePorts, + lowerAnnotationsNoRefTypePorts); +DEFINE_FIRTOOL_OPTION_ENUM( + PreserveAggregate, preserveAggregate, FirtoolPreserveAggregateMode, + [](FirtoolPreserveAggregateMode value) { + switch (value) { + case FIRTOOL_PRESERVE_AGGREGATE_MODE_NONE: + return firrtl::PreserveAggregate::None; + case FIRTOOL_PRESERVE_AGGREGATE_MODE_ONE_DIM_VEC: + return firrtl::PreserveAggregate::OneDimVec; + case FIRTOOL_PRESERVE_AGGREGATE_MODE_VEC: + return firrtl::PreserveAggregate::Vec; + case FIRTOOL_PRESERVE_AGGREGATE_MODE_ALL: + return firrtl::PreserveAggregate::All; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown preserve aggregate mode"); + } + }, + [](firrtl::PreserveAggregate::PreserveMode value) { + switch (value) { + case firrtl::PreserveAggregate::None: + return FIRTOOL_PRESERVE_AGGREGATE_MODE_NONE; + case firrtl::PreserveAggregate::OneDimVec: + return FIRTOOL_PRESERVE_AGGREGATE_MODE_ONE_DIM_VEC; + case firrtl::PreserveAggregate::Vec: + return FIRTOOL_PRESERVE_AGGREGATE_MODE_VEC; + case firrtl::PreserveAggregate::All: + return FIRTOOL_PRESERVE_AGGREGATE_MODE_ALL; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown preserve aggregate mode"); + } + }); +DEFINE_FIRTOOL_OPTION_ENUM( + PreserveValues, preserveMode, FirtoolPreserveValuesMode, + [](FirtoolPreserveValuesMode value) { + switch (value) { + case FIRTOOL_PRESERVE_VALUES_MODE_NONE: + return firrtl::PreserveValues::None; + case FIRTOOL_PRESERVE_VALUES_MODE_NAMED: + return firrtl::PreserveValues::Named; + case FIRTOOL_PRESERVE_VALUES_MODE_ALL: + return firrtl::PreserveValues::All; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown preserve values mode"); + } + }, + [](firrtl::PreserveValues::PreserveMode value) { + switch (value) { + case firrtl::PreserveValues::None: + return FIRTOOL_PRESERVE_VALUES_MODE_NONE; + case firrtl::PreserveValues::Named: + return FIRTOOL_PRESERVE_VALUES_MODE_NAMED; + case firrtl::PreserveValues::All: + return FIRTOOL_PRESERVE_VALUES_MODE_ALL; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown preserve values mode"); + } + }); +DEFINE_FIRTOOL_OPTION_ENUM( + BuildMode, buildMode, FirtoolBuildMode, + [](FirtoolBuildMode value) { + switch (value) { + case FIRTOOL_BUILD_MODE_DEBUG: + return firtool::FirtoolOptions::BuildModeDebug; + case FIRTOOL_BUILD_MODE_RELEASE: + return firtool::FirtoolOptions::BuildModeRelease; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown build mode"); + } + }, + [](firtool::FirtoolOptions::BuildMode value) { + switch (value) { + case firtool::FirtoolOptions::BuildModeDebug: + return FIRTOOL_BUILD_MODE_DEBUG; + case firtool::FirtoolOptions::BuildModeRelease: + return FIRTOOL_BUILD_MODE_RELEASE; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown build mode"); + } + }); +DEFINE_FIRTOOL_OPTION_BOOL(DisableOptimization, disableOptimization); +DEFINE_FIRTOOL_OPTION_BOOL(ExportChiselInterface, exportChiselInterface); +DEFINE_FIRTOOL_OPTION_STRING(ChiselInterfaceOutDirectory, + chiselInterfaceOutDirectory); +DEFINE_FIRTOOL_OPTION_BOOL(VbToBv, vbToBV); +DEFINE_FIRTOOL_OPTION_BOOL(Dedup, dedup); +DEFINE_FIRTOOL_OPTION_BOOL(GrandCentralInstantiateCompanionOnly, + grandCentralInstantiateCompanionOnly); +DEFINE_FIRTOOL_OPTION_BOOL(DisableAggressiveMergeConnections, + disableAggressiveMergeConnections); +DEFINE_FIRTOOL_OPTION_BOOL(EmitOMIR, emitOMIR); +DEFINE_FIRTOOL_OPTION_STRING(OMIROutFile, omirOutFile); +DEFINE_FIRTOOL_OPTION_BOOL(LowerMemories, lowerMemories); +DEFINE_FIRTOOL_OPTION_STRING(BlackBoxRootPath, blackBoxRootPath); +DEFINE_FIRTOOL_OPTION_BOOL(ReplSeqMem, replSeqMem); +DEFINE_FIRTOOL_OPTION_STRING(ReplSeqMemFile, replSeqMemFile); +DEFINE_FIRTOOL_OPTION_BOOL(ExtractTestCode, extractTestCode); +DEFINE_FIRTOOL_OPTION_BOOL(IgnoreReadEnableMem, ignoreReadEnableMem); +DEFINE_FIRTOOL_OPTION_ENUM( + DisableRandom, disableRandom, FirtoolRandomKind, + [](FirtoolRandomKind value) { + switch (value) { + case FIRTOOL_RANDOM_KIND_NONE: + return firtool::FirtoolOptions::RandomKind::None; + case FIRTOOL_RANDOM_KIND_MEM: + return firtool::FirtoolOptions::RandomKind::Mem; + case FIRTOOL_RANDOM_KIND_REG: + return firtool::FirtoolOptions::RandomKind::Reg; + case FIRTOOL_RANDOM_KIND_ALL: + return firtool::FirtoolOptions::RandomKind::All; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown random kind"); + } + }, + [](firtool::FirtoolOptions::RandomKind value) { + switch (value) { + case firtool::FirtoolOptions::RandomKind::None: + return FIRTOOL_RANDOM_KIND_NONE; + case firtool::FirtoolOptions::RandomKind::Mem: + return FIRTOOL_RANDOM_KIND_MEM; + case firtool::FirtoolOptions::RandomKind::Reg: + return FIRTOOL_RANDOM_KIND_REG; + case firtool::FirtoolOptions::RandomKind::All: + return FIRTOOL_RANDOM_KIND_ALL; + default: // NOLINT(clang-diagnostic-covered-switch-default) + llvm_unreachable("unknown random kind"); + } + }); +DEFINE_FIRTOOL_OPTION_STRING(OutputAnnotationFilename, + outputAnnotationFilename); +DEFINE_FIRTOOL_OPTION_BOOL(EnableAnnotationWarning, enableAnnotationWarning); +DEFINE_FIRTOOL_OPTION_BOOL(AddMuxPragmas, addMuxPragmas); +DEFINE_FIRTOOL_OPTION_BOOL(EmitChiselAssertsAsSVA, emitChiselAssertsAsSVA); +DEFINE_FIRTOOL_OPTION_BOOL(EmitSeparateAlwaysBlocks, emitSeparateAlwaysBlocks); +DEFINE_FIRTOOL_OPTION_BOOL(EtcDisableInstanceExtraction, + etcDisableInstanceExtraction); +DEFINE_FIRTOOL_OPTION_BOOL(EtcDisableRegisterExtraction, + etcDisableRegisterExtraction); +DEFINE_FIRTOOL_OPTION_BOOL(EtcDisableModuleInlining, etcDisableModuleInlining); +DEFINE_FIRTOOL_OPTION_BOOL(AddVivadoRAMAddressConflictSynthesisBugWorkaround, + addVivadoRAMAddressConflictSynthesisBugWorkaround); +DEFINE_FIRTOOL_OPTION_STRING(CkgModuleName, ckgModuleName); +DEFINE_FIRTOOL_OPTION_STRING(CkgInputName, ckgInputName); +DEFINE_FIRTOOL_OPTION_STRING(CkgOutputName, ckgOutputName); +DEFINE_FIRTOOL_OPTION_STRING(CkgEnableName, ckgEnableName); +DEFINE_FIRTOOL_OPTION_STRING(CkgTestEnableName, ckgTestEnableName); +DEFINE_FIRTOOL_OPTION_BOOL(ExportModuleHierarchy, exportModuleHierarchy); +DEFINE_FIRTOOL_OPTION_BOOL(StripFirDebugInfo, stripFirDebugInfo); +DEFINE_FIRTOOL_OPTION_BOOL(StripDebugInfo, stripDebugInfo); + +#undef DEFINE_FIRTOOL_OPTION_STRING +#undef DEFINE_FIRTOOL_OPTION_BOOL +#undef DEFINE_FIRTOOL_OPTION_ENUM + +//===----------------------------------------------------------------------===// +// Populate API. +//===----------------------------------------------------------------------===// -MlirLogicalResult firtoolPopulatePreprocessTransforms(MlirPassManager pm) { +MlirLogicalResult firtoolPopulatePreprocessTransforms(MlirPassManager pm, + FirtoolOptions options) { return wrap( - firtool::populatePreprocessTransforms(*unwrap(pm), tempDefaultOptions)); + firtool::populatePreprocessTransforms(*unwrap(pm), *unwrap(options))); } MlirLogicalResult -firtoolPopulateCHIRRTLToLowFIRRTL(MlirPassManager pm, MlirModule module, +firtoolPopulateCHIRRTLToLowFIRRTL(MlirPassManager pm, FirtoolOptions options, + MlirModule module, MlirStringRef inputFilename) { return wrap(firtool::populateCHIRRTLToLowFIRRTL( - *unwrap(pm), tempDefaultOptions, unwrap(module), unwrap(inputFilename))); + *unwrap(pm), *unwrap(options), unwrap(module), unwrap(inputFilename))); } -MlirLogicalResult firtoolPopulateLowFIRRTLToHW(MlirPassManager pm) { - return wrap(firtool::populateLowFIRRTLToHW(*unwrap(pm), tempDefaultOptions)); +MlirLogicalResult firtoolPopulateLowFIRRTLToHW(MlirPassManager pm, + FirtoolOptions options) { + return wrap(firtool::populateLowFIRRTLToHW(*unwrap(pm), *unwrap(options))); } -MlirLogicalResult firtoolPopulateHWToSV(MlirPassManager pm) { - return wrap(firtool::populateHWToSV(*unwrap(pm), tempDefaultOptions)); +MlirLogicalResult firtoolPopulateHWToSV(MlirPassManager pm, + FirtoolOptions options) { + return wrap(firtool::populateHWToSV(*unwrap(pm), *unwrap(options))); } MlirLogicalResult firtoolPopulateExportVerilog(MlirPassManager pm, + FirtoolOptions options, MlirStringCallback callback, void *userData) { auto stream = std::make_unique(callback, userData); - return wrap(firtool::populateExportVerilog(*unwrap(pm), tempDefaultOptions, + return wrap(firtool::populateExportVerilog(*unwrap(pm), *unwrap(options), std::move(stream))); } MlirLogicalResult firtoolPopulateExportSplitVerilog(MlirPassManager pm, + FirtoolOptions options, MlirStringRef directory) { - return wrap(firtool::populateExportSplitVerilog( - *unwrap(pm), tempDefaultOptions, unwrap(directory))); + return wrap(firtool::populateExportSplitVerilog(*unwrap(pm), *unwrap(options), + unwrap(directory))); } -MlirLogicalResult firtoolPopulateFinalizeIR(MlirPassManager pm) { - return wrap(firtool::populateFinalizeIR(*unwrap(pm), tempDefaultOptions)); +MlirLogicalResult firtoolPopulateFinalizeIR(MlirPassManager pm, + FirtoolOptions options) { + return wrap(firtool::populateFinalizeIR(*unwrap(pm), *unwrap(options))); }