diff --git a/xls/contrib/mlir/BUILD b/xls/contrib/mlir/BUILD index 7f203ac36c..2e0ef943a2 100644 --- a/xls/contrib/mlir/BUILD +++ b/xls/contrib/mlir/BUILD @@ -539,7 +539,6 @@ cc_library( "//xls/tools:scheduling_options_flags_cc_proto", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/container:inlined_vector", "@com_google_absl//absl/log:check", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", diff --git a/xls/contrib/mlir/IR/xls_ops.td b/xls/contrib/mlir/IR/xls_ops.td index c6729e045e..22f4c2e590 100644 --- a/xls/contrib/mlir/IR/xls_ops.td +++ b/xls/contrib/mlir/IR/xls_ops.td @@ -203,6 +203,61 @@ def Xls_FifoConfig : Xls_Attr<"FifoConfig"> { let assemblyFormat = "`<` struct(params) `>`"; } +def Xls_SchedulingOptions : Xls_Attr<"SchedulingOptions"> { + let summary = "Scheduling options for XLS pipeline generation"; + let description = [{ + Specifies scheduling options for XLS pipeline generation. + }]; + + let parameters = (ins + DefaultValuedParameter<"int64_t", "0", "Target clock period, in picoseconds.">:$clock_period_ps, + DefaultValuedParameter<"int64_t", "0", "The number of stages in the generated pipeline.">:$pipeline_stages, + DefaultValuedParameter<"::mlir::StringAttr", "::mlir::StringAttr()", "Delay model name to use from registry.">:$delay_model, + DefaultValuedParameter<"int64_t", "0", "The percentage of clock period to set aside as a margin to ensure timing is met.">:$clock_margin_percent, + DefaultValuedParameter<"int64_t", "1", "Allow scheduling a pipeline with worst-case throughput no slower than once per N cycles.">:$worst_case_throughput, + DefaultValuedParameter<"bool", "false", "If true, schedule all procs and codegen them all.">:$multi_proc + ); + + let mnemonic = "scheduling_options"; + let assemblyFormat = "`<` struct(params) `>`"; +} + +def Xls_OptimizationOptions : Xls_Attr<"OptimizationOptions"> { + let summary = "Optimization options for XLS IR"; + let description = [{ + Specifies optimization options for XLS IR transformation. + }]; + + let parameters = (ins + DefaultValuedParameter<"int64_t", "3", "Optimization level (0-3).">:$opt_level, + DefaultValuedParameter<"int64_t", "0", "Threshold for converting array indices to select chains.">:$convert_array_index_to_select, + DefaultValuedParameter<"bool", "false", "Use context narrowing analysis during optimization.">:$use_context_narrowing_analysis, + DefaultValuedParameter<"bool", "false", "Optimize for best-case throughput.">:$optimize_for_best_case_throughput, + DefaultValuedParameter<"bool", "false", "Enable resource sharing optimization.">:$enable_resource_sharing, + DefaultValuedParameter<"bool", "false", "Force resource sharing.">:$force_resource_sharing, + DefaultValuedParameter<"::mlir::StringAttr", "::mlir::StringAttr()", "Custom pass pipeline specification.">:$pass_pipeline + ); + + let mnemonic = "opt_options"; + let assemblyFormat = "`<` struct(params) `>`"; +} + +def Xls_CodegenOptions : Xls_Attr<"CodegenOptions"> { + let summary = "Codegen options for Verilog generation"; + let description = [{ + Specifies code generation options for Verilog output. + }]; + + let parameters = (ins + DefaultValuedParameter<"bool", "true", "If true, emit SystemVerilog otherwise emit Verilog.">:$use_system_verilog, + DefaultValuedParameter<"bool", "true", "If true, emit bounds checking on array-index operations in Verilog.">:$array_index_bounds_checking, + DefaultValuedParameter<"bool", "true", "If true, emit logic to gate the data value to zero for a receive operation in Verilog.">:$gate_recvs + ); + + let mnemonic = "codegen_options"; + let assemblyFormat = "`<` struct(params) `>`"; +} + def Xls_BoundaryChannelAttr : Xls_Attr<"BoundaryChannelAttr"> { let summary = "Boundary channel attribute"; let description = [{ diff --git a/xls/contrib/mlir/testdata/codegen_attrs.mlir b/xls/contrib/mlir/testdata/codegen_attrs.mlir new file mode 100644 index 0000000000..1291f7f988 --- /dev/null +++ b/xls/contrib/mlir/testdata/codegen_attrs.mlir @@ -0,0 +1,16 @@ +// RUN: xls_opt %s | FileCheck %s + +// Test that codegen attributes parse and print correctly +module attributes { + xls.scheduling_options = #xls.scheduling_options, + xls.opt_options = #xls.opt_options, + xls.codegen_options = #xls.codegen_options +} { + // CHECK: xls.scheduling_options = #xls.scheduling_options + // CHECK: xls.opt_options = #xls.opt_options + // CHECK: xls.codegen_options = #xls.codegen_options + + func.func @dummy() { + return + } +} diff --git a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc index 581d0bc54c..d5103ff385 100644 --- a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc +++ b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.cc @@ -1838,4 +1838,43 @@ absl::StatusOr> DslxPackageCache::import( return package; } +void PopulateSchedulingOptionsFromAttr( + SchedulingOptions attr, ::xls::SchedulingOptionsFlagsProto& proto) { + proto.set_clock_period_ps(attr.getClockPeriodPs()); + proto.set_pipeline_stages(attr.getPipelineStages()); + if (auto delay_model = attr.getDelayModel()) { + proto.set_delay_model(delay_model.getValue().str()); + } + proto.set_clock_margin_percent(attr.getClockMarginPercent()); + proto.set_worst_case_throughput(attr.getWorstCaseThroughput()); + proto.set_multi_proc(attr.getMultiProc()); +} + +void PopulateOptOptionsFromAttr(OptimizationOptions attr, + ::xls::tools::OptOptions& options) { + options.opt_level = attr.getOptLevel(); + options.convert_array_index_to_select = attr.getConvertArrayIndexToSelect(); + options.use_context_narrowing_analysis = + attr.getUseContextNarrowingAnalysis(); + options.optimize_for_best_case_throughput = + attr.getOptimizeForBestCaseThroughput(); + options.enable_resource_sharing = attr.getEnableResourceSharing(); + options.force_resource_sharing = attr.getForceResourceSharing(); + if (auto pass_pipeline_str = attr.getPassPipeline()) { + // TODO(jpienaar): This should be verified on the attribute so that when + // we get here, it can't fail. + ::xls::PassPipelineProto pass_pipeline; + CHECK(google::protobuf::TextFormat::ParseFromString( + pass_pipeline_str.getValue().str(), &pass_pipeline)); + options.pass_pipeline = pass_pipeline; + } +} + +void PopulateCodegenFlagsFromAttr(CodegenOptions attr, + ::xls::CodegenFlagsProto& proto) { + proto.set_use_system_verilog(attr.getUseSystemVerilog()); + proto.set_array_index_bounds_checking(attr.getArrayIndexBoundsChecking()); + proto.set_gate_recvs(attr.getGateRecvs()); +} + } // namespace mlir::xls diff --git a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.h b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.h index 22cb0b9951..8021f6abec 100644 --- a/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.h +++ b/xls/contrib/mlir/tools/xls_translate/xls_translate_from_mlir.h @@ -51,6 +51,11 @@ class Package; namespace mlir::xls { +// Forward declarations of XLS attribute types. +class SchedulingOptions; +class OptimizationOptions; +class CodegenOptions; + // Caches DSLX translation results. DSLX translation is expensive, so this // avoids re-translating the same file multiple times across calls to // MlirXlsToXlsTranslate. @@ -102,6 +107,18 @@ struct MlirXlsToXlsTranslateOptions { DieUnlessOk(::xls::GetSchedulingOptionsFlagsProto()); }; +// Populates SchedulingOptionsFlagsProto from SchedulingOptions attribute. +void PopulateSchedulingOptionsFromAttr( + SchedulingOptions attr, ::xls::SchedulingOptionsFlagsProto& proto); + +// Populates OptOptions from OptimizationOptions attribute. +void PopulateOptOptionsFromAttr(OptimizationOptions attr, + ::xls::tools::OptOptions& options); + +// Populates CodegenFlagsProto from CodegenOptions attribute. +void PopulateCodegenFlagsFromAttr(CodegenOptions attr, + ::xls::CodegenFlagsProto& proto); + // Callback for reporting codegen metrics. using MetricsReporter = llvm::function_ref;