From 6a718db8da6c65e8d736a4d3cf928a5bd4c6ab3b Mon Sep 17 00:00:00 2001 From: Georges Rotival Date: Mon, 28 Aug 2023 02:48:35 -0700 Subject: [PATCH] tools/codegen: Extract all the non flag/filesystem logic into a separated class. This is done in preparation for surfacing a runtime_build_action for codegen in xls/public. PiperOrigin-RevId: 560652403 --- xls/tools/BUILD | 40 ++++-- xls/tools/codegen.cc | 261 ++++++++++++++++++++++++++++++++++++++ xls/tools/codegen.h | 39 ++++++ xls/tools/codegen_main.cc | 244 ++++------------------------------- 4 files changed, 353 insertions(+), 231 deletions(-) create mode 100644 xls/tools/codegen.cc create mode 100644 xls/tools/codegen.h diff --git a/xls/tools/BUILD b/xls/tools/BUILD index ab13364355..5caac12b6f 100644 --- a/xls/tools/BUILD +++ b/xls/tools/BUILD @@ -965,12 +965,11 @@ cc_library( ], ) -cc_binary( - name = "codegen_main", - srcs = ["codegen_main.cc"], - visibility = ["//xls:xls_users"], +cc_library( + name = "codegen", + srcs = ["codegen.cc"], + hdrs = ["codegen.h"], deps = [ - ":codegen_flags", ":codegen_flags_cc_proto", ":scheduling_options_flags", "//xls/codegen:codegen_options", @@ -979,9 +978,6 @@ cc_binary( "//xls/codegen:op_override_impls", "//xls/codegen:pipeline_generator", "//xls/codegen:ram_configuration", - "//xls/common:exit_status", - "//xls/common:init_xls", - "//xls/common/file:filesystem", "//xls/common/logging", "//xls/common/status:ret_check", "//xls/common/status:status_macros", @@ -989,19 +985,43 @@ cc_binary( "//xls/delay_model:ffi_delay_estimator", "//xls/fdo:synthesizer", "//xls/ir", - "//xls/ir:ir_parser", "//xls/ir:op", "//xls/scheduling:pipeline_schedule", + "//xls/scheduling:pipeline_schedule_cc_proto", "//xls/scheduling:scheduling_options", "//xls/scheduling:scheduling_pass", "//xls/scheduling:scheduling_pass_pipeline", - "@com_google_absl//absl/flags:flag", "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings:str_format", ], ) +cc_binary( + name = "codegen_main", + srcs = ["codegen_main.cc"], + visibility = ["//xls:xls_users"], + deps = [ + ":codegen", + ":codegen_flags", + ":codegen_flags_cc_proto", + ":scheduling_options_flags", + "//xls/codegen:module_signature", + "//xls/common:exit_status", + "//xls/common:init_xls", + "//xls/common/file:filesystem", + "//xls/common/logging", + "//xls/common/status:ret_check", + "//xls/common/status:status_macros", + "//xls/ir", + "//xls/ir:ir_parser", + "//xls/scheduling:pipeline_schedule_cc_proto", + "@com_google_absl//absl/flags:flag", + "@com_google_absl//absl/status", + "@com_google_absl//absl/strings:str_format", + ], +) + cc_binary( name = "simulate_module_main", srcs = ["simulate_module_main.cc"], diff --git a/xls/tools/codegen.cc b/xls/tools/codegen.cc new file mode 100644 index 0000000000..5cf60a6181 --- /dev/null +++ b/xls/tools/codegen.cc @@ -0,0 +1,261 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "xls/tools/codegen.h" + +#include +#include +#include +#include +#include +#include + +#include "absl/status/status.h" +#include "absl/status/statusor.h" +#include "absl/strings/str_format.h" +#include "xls/codegen/codegen_options.h" +#include "xls/codegen/combinational_generator.h" +#include "xls/codegen/module_signature.h" +#include "xls/codegen/op_override_impls.h" +#include "xls/codegen/pipeline_generator.h" +#include "xls/codegen/ram_configuration.h" +#include "xls/common/logging/logging.h" +#include "xls/common/status/ret_check.h" +#include "xls/common/status/status_macros.h" +#include "xls/delay_model/delay_estimator.h" +#include "xls/delay_model/ffi_delay_estimator.h" +#include "xls/fdo/synthesizer.h" +#include "xls/ir/function_base.h" +#include "xls/ir/op.h" +#include "xls/ir/verifier.h" +#include "xls/scheduling/pipeline_schedule.h" +#include "xls/scheduling/scheduling_options.h" +#include "xls/scheduling/scheduling_pass.h" +#include "xls/scheduling/scheduling_pass_pipeline.h" +#include "xls/tools/codegen_flags.pb.h" +#include "xls/tools/scheduling_options_flags.h" + +namespace xls { +namespace { + +verilog::CodegenOptions::IOKind ToIOKind(IOKindProto p) { + switch (p) { + case IO_KIND_INVALID: + case IO_KIND_FLOP: + return verilog::CodegenOptions::IOKind::kFlop; + case IO_KIND_SKID_BUFFER: + return verilog::CodegenOptions::IOKind::kSkidBuffer; + case IO_KIND_ZERO_LATENCY_BUFFER: + return verilog::CodegenOptions::IOKind::kZeroLatencyBuffer; + default: + XLS_LOG(FATAL) << "Invalid IOKindProto value: " << static_cast(p); + } +} + +absl::StatusOr CodegenOptionsFromProto( + const CodegenFlagsProto& p) { + verilog::CodegenOptions options; + + if (p.generator() == GENERATOR_KIND_PIPELINE) { + options = verilog::BuildPipelineOptions(); + + if (!p.input_valid_signal().empty()) { + std::optional output_signal; + if (!p.output_valid_signal().empty()) { + output_signal = p.output_valid_signal(); + } + options.valid_control(p.input_valid_signal(), output_signal); + } else if (!p.manual_load_enable_signal().empty()) { + options.manual_control(p.manual_load_enable_signal()); + } + options.flop_inputs(p.flop_inputs()); + options.flop_outputs(p.flop_outputs()); + options.flop_inputs_kind(ToIOKind(p.flop_inputs_kind())); + options.flop_outputs_kind(ToIOKind(p.flop_outputs_kind())); + + options.flop_single_value_channels(p.flop_single_value_channels()); + options.add_idle_output(p.add_idle_output()); + + if (!p.reset().empty()) { + options.reset(p.reset(), p.reset_asynchronous(), p.reset_active_low(), + p.reset_data_path()); + } + } + + if (!p.module_name().empty()) { + options.module_name(p.module_name()); + } + + options.use_system_verilog(p.use_system_verilog()); + options.separate_lines(p.separate_lines()); + + if (!p.gate_format().empty()) { + options.SetOpOverride( + Op::kGate, + std::make_unique(p.gate_format())); + } + + if (!p.assert_format().empty()) { + options.SetOpOverride( + Op::kAssert, + std::make_unique(p.assert_format())); + } + + if (!p.smulp_format().empty()) { + options.SetOpOverride( + Op::kSMulp, + std::make_unique(p.smulp_format())); + } + + if (!p.umulp_format().empty()) { + options.SetOpOverride( + Op::kUMulp, + std::make_unique(p.umulp_format())); + } + + options.streaming_channel_data_suffix(p.streaming_channel_data_suffix()); + options.streaming_channel_valid_suffix(p.streaming_channel_valid_suffix()); + options.streaming_channel_ready_suffix(p.streaming_channel_ready_suffix()); + + std::vector> ram_configurations; + ram_configurations.reserve(p.ram_configurations_size()); + for (const std::string& config_text : p.ram_configurations()) { + XLS_ASSIGN_OR_RETURN(std::unique_ptr config, + verilog::RamConfiguration::ParseString(config_text)); + ram_configurations.push_back(std::move(config)); + } + options.ram_configurations(ram_configurations); + + options.gate_recvs(p.gate_recvs()); + options.array_index_bounds_checking(p.array_index_bounds_checking()); + + return options; +} + +absl::StatusOr RunSchedulingPipeline( + FunctionBase* main, const SchedulingOptions& scheduling_options, + const DelayEstimator* delay_estimator, + synthesis::Synthesizer* synthesizer) { + Package* p = main->package(); + SchedulingPassOptions sched_options; + sched_options.scheduling_options = scheduling_options; + sched_options.delay_estimator = delay_estimator; + sched_options.synthesizer = synthesizer; + std::unique_ptr scheduling_pipeline = + CreateSchedulingPassPipeline(); + SchedulingPassResults results; + SchedulingUnit<> scheduling_unit = {p, /*schedule=*/std::nullopt}; + absl::Status scheduling_status = + scheduling_pipeline->Run(&scheduling_unit, sched_options, &results) + .status(); + if (!scheduling_status.ok()) { + if (absl::IsResourceExhausted(scheduling_status)) { + // Resource exhausted error indicates that the schedule was + // infeasible. Emit a meaningful error in this case. + std::string error_message = "Design cannot be scheduled"; + if (scheduling_options.pipeline_stages().has_value()) { + absl::StrAppendFormat(&error_message, " in %d stages", + scheduling_options.pipeline_stages().value()); + } + if (scheduling_options.clock_period_ps().has_value()) { + absl::StrAppendFormat(&error_message, " with a %dps clock", + scheduling_options.clock_period_ps().value()); + } + return xabsl::StatusBuilder(scheduling_status).SetPrepend() + << error_message << ": "; + } + return scheduling_status; + } + XLS_RET_CHECK(scheduling_unit.schedule.has_value()); + + return scheduling_unit.schedule.value(); +} + +} // namespace + +absl::StatusOr ScheduleAndCodegen( + Package* p, const CodegenFlagsProto& codegen_flags_proto, + bool with_delay_model) { + if (!codegen_flags_proto.top().empty()) { + XLS_RETURN_IF_ERROR(p->SetTopByName(codegen_flags_proto.top())); + } + XLS_ASSIGN_OR_RETURN(verilog::CodegenOptions codegen_options, + CodegenOptionsFromProto(codegen_flags_proto)); + + XLS_RET_CHECK(p->GetTop().has_value()) + << "Package " << p->name() << " needs a top function/proc."; + auto main = [&p]() -> FunctionBase* { return p->GetTop().value(); }; + + XLS_ASSIGN_OR_RETURN(SchedulingOptions scheduling_options, + SetUpSchedulingOptions(p)); + if (codegen_flags_proto.generator() == GENERATOR_KIND_PIPELINE) { + XLS_QCHECK(scheduling_options.pipeline_stages() != 0 || + scheduling_options.clock_period_ps() != 0) + << "Must specify --pipeline_stages or --clock_period_ps (or both)."; + + // Add IO constraints for RAMs. + for (const std::unique_ptr& ram_config : + codegen_options.ram_configurations()) { + for (const IOConstraint& ram_constraint : + ram_config->GetIOConstraints()) { + scheduling_options.add_constraint(ram_constraint); + } + } + + XLS_ASSIGN_OR_RETURN(const DelayEstimator* base_estimator, + SetUpDelayEstimator()); + const FfiDelayEstimator ffi_estimator( + scheduling_options.ffi_fallback_delay_ps()); + + FirstMatchDelayEstimator delay_estimator("combined_estimator", + {base_estimator, &ffi_estimator}); + + synthesis::Synthesizer* synthesizer = nullptr; + if (!scheduling_options.fdo_synthesizer_name().empty()) { + XLS_ASSIGN_OR_RETURN(synthesizer, SetUpSynthesizer()); + } + + XLS_ASSIGN_OR_RETURN(PipelineSchedule schedule, + RunSchedulingPipeline(main(), scheduling_options, + &delay_estimator, synthesizer)); + + XLS_RETURN_IF_ERROR(VerifyPackage(p, /*codegen=*/true)); + + XLS_ASSIGN_OR_RETURN( + verilog::ModuleGeneratorResult result, + verilog::ToPipelineModuleText(schedule, main(), codegen_options, + &delay_estimator)); + return CodegenResult{ + .module_generator_result = result, + .pipeline_schedule_proto = schedule.ToProto(delay_estimator), + }; + } + + if (codegen_flags_proto.generator() == GENERATOR_KIND_COMBINATIONAL) { + const DelayEstimator* delay_estimator = nullptr; + if (with_delay_model) { + XLS_ASSIGN_OR_RETURN(delay_estimator, SetUpDelayEstimator()); + } + XLS_ASSIGN_OR_RETURN(verilog::ModuleGeneratorResult result, + verilog::GenerateCombinationalModule( + main(), codegen_options, delay_estimator)); + return CodegenResult{.module_generator_result = result}; + } + + // Note: this should already be validated by CodegenFlagsFromAbslFlags(). + XLS_LOG(FATAL) << "Invalid generator kind: " + << static_cast(codegen_flags_proto.generator()); +} + +} // namespace xls diff --git a/xls/tools/codegen.h b/xls/tools/codegen.h new file mode 100644 index 0000000000..ec28dd71f2 --- /dev/null +++ b/xls/tools/codegen.h @@ -0,0 +1,39 @@ +// Copyright 2024 The XLS Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "absl/status/statusor.h" +#include "xls/codegen/module_signature.h" +#include "xls/ir/package.h" +#include "xls/scheduling/pipeline_schedule.pb.h" +#include "xls/tools/codegen_flags.pb.h" + +#ifndef XLS_TOOLS_CODEGEN_H_ +#define XLS_TOOLS_CODEGEN_H_ + +namespace xls { + +struct CodegenResult { + verilog::ModuleGeneratorResult module_generator_result; + std::optional pipeline_schedule_proto = std::nullopt; +}; + +absl::StatusOr ScheduleAndCodegen( + Package* p, const CodegenFlagsProto& codegen_flags_proto, + bool with_delay_model); + +} // namespace xls + +#endif // XLS_TOOLS_CODEGEN_H_ diff --git a/xls/tools/codegen_main.cc b/xls/tools/codegen_main.cc index b9f3a2df87..979326fd98 100644 --- a/xls/tools/codegen_main.cc +++ b/xls/tools/codegen_main.cc @@ -11,7 +11,6 @@ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. - #include #include // NOLINT #include @@ -19,36 +18,23 @@ #include #include #include -#include #include #include "absl/flags/flag.h" #include "absl/status/status.h" -#include "absl/status/statusor.h" #include "absl/strings/str_format.h" -#include "xls/codegen/codegen_options.h" -#include "xls/codegen/combinational_generator.h" #include "xls/codegen/module_signature.h" -#include "xls/codegen/op_override_impls.h" -#include "xls/codegen/pipeline_generator.h" -#include "xls/codegen/ram_configuration.h" #include "xls/common/exit_status.h" #include "xls/common/file/filesystem.h" #include "xls/common/init_xls.h" #include "xls/common/logging/logging.h" #include "xls/common/status/ret_check.h" #include "xls/common/status/status_macros.h" -#include "xls/delay_model/delay_estimator.h" -#include "xls/delay_model/ffi_delay_estimator.h" -#include "xls/fdo/synthesizer.h" #include "xls/ir/function_base.h" #include "xls/ir/ir_parser.h" -#include "xls/ir/op.h" #include "xls/ir/verifier.h" -#include "xls/scheduling/pipeline_schedule.h" -#include "xls/scheduling/scheduling_options.h" -#include "xls/scheduling/scheduling_pass.h" -#include "xls/scheduling/scheduling_pass_pipeline.h" +#include "xls/scheduling/pipeline_schedule.pb.h" +#include "xls/tools/codegen.h" #include "xls/tools/codegen_flags.h" #include "xls/tools/codegen_flags.pb.h" #include "xls/tools/scheduling_options_flags.h" @@ -71,230 +57,46 @@ Emit a feed-forward pipelined module: namespace xls { namespace { -verilog::CodegenOptions::IOKind ToIOKind(IOKindProto p) { - switch (p) { - case IO_KIND_INVALID: - case IO_KIND_FLOP: - return verilog::CodegenOptions::IOKind::kFlop; - case IO_KIND_SKID_BUFFER: - return verilog::CodegenOptions::IOKind::kSkidBuffer; - case IO_KIND_ZERO_LATENCY_BUFFER: - return verilog::CodegenOptions::IOKind::kZeroLatencyBuffer; - default: - XLS_LOG(FATAL) << "Invalid IOKindProto value: " << static_cast(p); - } -} - -absl::StatusOr CodegenOptionsFromProto( - const CodegenFlagsProto& p) { - verilog::CodegenOptions options; - - if (p.generator() == GENERATOR_KIND_PIPELINE) { - options = verilog::BuildPipelineOptions(); - - if (!p.input_valid_signal().empty()) { - std::optional output_signal; - if (!p.output_valid_signal().empty()) { - output_signal = p.output_valid_signal(); - } - options.valid_control(p.input_valid_signal(), output_signal); - } else if (!p.manual_load_enable_signal().empty()) { - options.manual_control(p.manual_load_enable_signal()); - } - options.flop_inputs(p.flop_inputs()); - options.flop_outputs(p.flop_outputs()); - options.flop_inputs_kind(ToIOKind(p.flop_inputs_kind())); - options.flop_outputs_kind(ToIOKind(p.flop_outputs_kind())); - - options.flop_single_value_channels(p.flop_single_value_channels()); - options.add_idle_output(p.add_idle_output()); - - if (!p.reset().empty()) { - options.reset(p.reset(), p.reset_asynchronous(), p.reset_active_low(), - p.reset_data_path()); - } - } - - if (!p.module_name().empty()) { - options.module_name(p.module_name()); - } - - options.use_system_verilog(p.use_system_verilog()); - options.separate_lines(p.separate_lines()); - - if (!p.gate_format().empty()) { - options.SetOpOverride( - Op::kGate, - std::make_unique(p.gate_format())); - } - - if (!p.assert_format().empty()) { - options.SetOpOverride( - Op::kAssert, - std::make_unique(p.assert_format())); - } - - if (!p.smulp_format().empty()) { - options.SetOpOverride( - Op::kSMulp, - std::make_unique(p.smulp_format())); - } - - if (!p.umulp_format().empty()) { - options.SetOpOverride( - Op::kUMulp, - std::make_unique(p.umulp_format())); - } - - options.streaming_channel_data_suffix(p.streaming_channel_data_suffix()); - options.streaming_channel_valid_suffix(p.streaming_channel_valid_suffix()); - options.streaming_channel_ready_suffix(p.streaming_channel_ready_suffix()); - - std::vector> ram_configurations; - ram_configurations.reserve(p.ram_configurations_size()); - for (const std::string& config_text : p.ram_configurations()) { - XLS_ASSIGN_OR_RETURN(std::unique_ptr config, - verilog::RamConfiguration::ParseString(config_text)); - ram_configurations.push_back(std::move(config)); - } - options.ram_configurations(ram_configurations); - - options.gate_recvs(p.gate_recvs()); - options.array_index_bounds_checking(p.array_index_bounds_checking()); - - return options; -} - -absl::StatusOr RunSchedulingPipeline( - FunctionBase* main, const SchedulingOptions& scheduling_options, - const DelayEstimator* delay_estimator, - synthesis::Synthesizer* synthesizer) { - Package* p = main->package(); - SchedulingPassOptions sched_options; - sched_options.scheduling_options = scheduling_options; - sched_options.delay_estimator = delay_estimator; - sched_options.synthesizer = synthesizer; - std::unique_ptr scheduling_pipeline = - CreateSchedulingPassPipeline(); - SchedulingPassResults results; - SchedulingUnit<> scheduling_unit = {p, /*schedule=*/std::nullopt}; - absl::Status scheduling_status = - scheduling_pipeline->Run(&scheduling_unit, sched_options, &results) - .status(); - if (!scheduling_status.ok()) { - if (absl::IsResourceExhausted(scheduling_status)) { - // Resource exhausted error indicates that the schedule was - // infeasible. Emit a meaningful error in this case. - std::string error_message = "Design cannot be scheduled"; - if (scheduling_options.pipeline_stages().has_value()) { - absl::StrAppendFormat(&error_message, " in %d stages", - scheduling_options.pipeline_stages().value()); - } - if (scheduling_options.clock_period_ps().has_value()) { - absl::StrAppendFormat(&error_message, " with a %dps clock", - scheduling_options.clock_period_ps().value()); - } - return xabsl::StatusBuilder(scheduling_status).SetPrepend() - << error_message << ": "; - } - return scheduling_status; - } - XLS_RET_CHECK(scheduling_unit.schedule.has_value()); - - return scheduling_unit.schedule.value(); -} - absl::Status RealMain(std::string_view ir_path) { - XLS_ASSIGN_OR_RETURN(CodegenFlagsProto codegen_flags_proto, - GetCodegenFlags()); if (ir_path == "-") { ir_path = "/dev/stdin"; } - XLS_ASSIGN_OR_RETURN(std::string ir_contents, GetFileContents(ir_path)); XLS_ASSIGN_OR_RETURN(std::unique_ptr p, Parser::ParsePackage(ir_contents, ir_path)); + XLS_ASSIGN_OR_RETURN(CodegenFlagsProto codegen_flags_proto, + GetCodegenFlags()); if (!codegen_flags_proto.top().empty()) { XLS_RETURN_IF_ERROR(p->SetTopByName(codegen_flags_proto.top())); } + XLS_RET_CHECK(p->GetTop().has_value()) << "Package " << p->name() << " needs a top function/proc."; auto main = [&p]() -> FunctionBase* { return p->GetTop().value(); }; - verilog::ModuleGeneratorResult result; - - XLS_ASSIGN_OR_RETURN(verilog::CodegenOptions codegen_options, - CodegenOptionsFromProto(codegen_flags_proto)); - - XLS_ASSIGN_OR_RETURN(SchedulingOptions scheduling_options, - SetUpSchedulingOptions(p.get())); - if (codegen_flags_proto.generator() == GENERATOR_KIND_PIPELINE) { - XLS_QCHECK(scheduling_options.pipeline_stages() != 0 || - scheduling_options.clock_period_ps() != 0) - << "Must specify --pipeline_stages or --clock_period_ps (or both)."; - - // Add IO constraints for RAMs. - for (const std::unique_ptr& ram_config : - codegen_options.ram_configurations()) { - for (const IOConstraint& ram_constraint : - ram_config->GetIOConstraints()) { - scheduling_options.add_constraint(ram_constraint); - } - } - - XLS_ASSIGN_OR_RETURN(const DelayEstimator* base_estimator, - SetUpDelayEstimator()); - const FfiDelayEstimator ffi_estimator( - scheduling_options.ffi_fallback_delay_ps()); + XLS_ASSIGN_OR_RETURN(bool delay_model_flag_passed, + IsDelayModelSpecifiedViaFlag()); + XLS_ASSIGN_OR_RETURN(CodegenResult r, + ScheduleAndCodegen(p.get(), codegen_flags_proto, + delay_model_flag_passed)); + verilog::ModuleGeneratorResult result = r.module_generator_result; + std::optional schedule = r.pipeline_schedule_proto; - FirstMatchDelayEstimator delay_estimator("combined_estimator", - {base_estimator, &ffi_estimator}); - - synthesis::Synthesizer* synthesizer = nullptr; - if (!scheduling_options.fdo_synthesizer_name().empty()) { - XLS_ASSIGN_OR_RETURN(synthesizer, SetUpSynthesizer()); - } - - XLS_ASSIGN_OR_RETURN(PipelineSchedule schedule, - RunSchedulingPipeline(main(), scheduling_options, - &delay_estimator, synthesizer)); - - XLS_RETURN_IF_ERROR(VerifyPackage(p.get(), /*codegen=*/true)); - - if (!absl::GetFlag(FLAGS_output_schedule_ir_path).empty()) { - XLS_RETURN_IF_ERROR( - SetFileContents(absl::GetFlag(FLAGS_output_schedule_ir_path), - main()->package()->DumpIr())); - } - - XLS_ASSIGN_OR_RETURN( - result, verilog::ToPipelineModuleText(schedule, main(), codegen_options, - &delay_estimator)); + if (!absl::GetFlag(FLAGS_output_schedule_ir_path).empty()) { + XLS_RETURN_IF_ERROR( + SetFileContents(absl::GetFlag(FLAGS_output_schedule_ir_path), + main()->package()->DumpIr())); + } - if (!absl::GetFlag(FLAGS_output_schedule_path).empty()) { + if (!absl::GetFlag(FLAGS_output_schedule_path).empty()) { + if (schedule.has_value()) { + XLS_RETURN_IF_ERROR(SetTextProtoFile( + absl::GetFlag(FLAGS_output_schedule_path), schedule.value())); + } else { XLS_RETURN_IF_ERROR( - SetTextProtoFile(absl::GetFlag(FLAGS_output_schedule_path), - schedule.ToProto(delay_estimator))); + SetFileContents(absl::GetFlag(FLAGS_output_schedule_path), "")); } - } else if (codegen_flags_proto.generator() == GENERATOR_KIND_COMBINATIONAL) { - if (!absl::GetFlag(FLAGS_output_schedule_ir_path).empty()) { - XLS_RETURN_IF_ERROR( - SetFileContents(absl::GetFlag(FLAGS_output_schedule_ir_path), "")); - } - // Estimate combinational delays if the `delay_model` flag was provided). - const DelayEstimator* delay_estimator = nullptr; - XLS_ASSIGN_OR_RETURN(bool delay_model_flag_passed, - IsDelayModelSpecifiedViaFlag()); - if (delay_model_flag_passed) { - XLS_ASSIGN_OR_RETURN(delay_estimator, SetUpDelayEstimator()); - } - XLS_ASSIGN_OR_RETURN(result, verilog::GenerateCombinationalModule( - main(), codegen_options, delay_estimator)); - } else { - // Note: this should already be validated by CodegenFlagsFromAbslFlags(). - XLS_LOG(FATAL) << "Invalid generator kind: " - << static_cast(codegen_flags_proto.generator()); } if (!absl::GetFlag(FLAGS_output_block_ir_path).empty()) {