Skip to content

Commit 790959d

Browse files
ericastorcopybara-github
authored andcommitted
[codegen 1.5] Port & convert module signature generation to a pass
This pass runs on all blocks without signatures in a package and populates them. The latency calculation for pipelined blocks is simplified to use the schedule information, if present. For signature preservation, we also update block cloning to clone the signature and initiation interval. PiperOrigin-RevId: 853909739
1 parent a4372a8 commit 790959d

13 files changed

+1280
-69
lines changed

xls/codegen/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,7 @@ cc_library(
602602
"//xls/ir:op",
603603
"//xls/ir:register",
604604
"//xls/ir:xls_ir_interface_cc_proto",
605+
"@com_google_absl//absl/base:core_headers",
605606
"@com_google_absl//absl/container:flat_hash_map",
606607
"@com_google_absl//absl/log",
607608
"@com_google_absl//absl/log:check",

xls/codegen/codegen_options.h

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <utility>
2323
#include <vector>
2424

25+
#include "absl/base/optimization.h"
2526
#include "absl/container/flat_hash_map.h"
2627
#include "absl/log/check.h"
2728
#include "absl/types/span.h"
@@ -58,14 +59,24 @@ class CodegenOptions {
5859
static int64_t IOKindLatency(IOKind kind) {
5960
switch (kind) {
6061
case IOKind::kFlop:
61-
return 1;
6262
case IOKind::kSkidBuffer:
6363
return 1;
6464
case IOKind::kZeroLatencyBuffer:
6565
return 0;
66-
default:
67-
return 9999;
6866
}
67+
ABSL_UNREACHABLE();
68+
}
69+
70+
static int64_t FlopKindLatency(FlopKind kind) {
71+
switch (kind) {
72+
case FlopKind::kNone:
73+
case FlopKind::kZeroLatency:
74+
return 0;
75+
case FlopKind::kFlop:
76+
case FlopKind::kSkid:
77+
return 1;
78+
}
79+
ABSL_UNREACHABLE();
6980
}
7081

7182
// TODO(allight): Merge these two enums.

xls/codegen_v_1_5/BUILD

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ cc_library(
5353
":scheduled_block_conversion_pass",
5454
":scheduling_pass",
5555
":side_effect_condition_pass",
56+
":signature_generation_pass",
5657
":state_to_register_io_lowering_pass",
5758
"//xls/passes:dataflow_simplification_pass",
5859
"//xls/passes:dce_pass",
@@ -734,6 +735,63 @@ cc_test(
734735
],
735736
)
736737

738+
cc_library(
739+
name = "signature_generation_pass",
740+
srcs = ["signature_generation_pass.cc"],
741+
hdrs = ["signature_generation_pass.h"],
742+
deps = [
743+
":block_conversion_pass",
744+
"//xls/codegen:codegen_options",
745+
"//xls/codegen:module_signature",
746+
"//xls/codegen:module_signature_cc_proto",
747+
"//xls/codegen/vast",
748+
"//xls/common:casts",
749+
"//xls/common/logging:log_lines",
750+
"//xls/common/status:ret_check",
751+
"//xls/common/status:status_macros",
752+
"//xls/ir",
753+
"//xls/ir:channel",
754+
"//xls/ir:channel_cc_proto",
755+
"//xls/ir:type",
756+
"//xls/passes:pass_base",
757+
"@com_google_absl//absl/log",
758+
"@com_google_absl//absl/log:check",
759+
"@com_google_absl//absl/status:statusor",
760+
"@com_google_absl//absl/strings:str_format",
761+
],
762+
)
763+
764+
cc_test(
765+
name = "signature_generation_pass_test",
766+
srcs = ["signature_generation_pass_test.cc"],
767+
deps = [
768+
":block_conversion_pass",
769+
":channel_to_port_io_lowering_pass",
770+
":function_io_lowering_pass",
771+
":scheduled_block_conversion_pass",
772+
":signature_generation_pass",
773+
"//xls/codegen:codegen_options",
774+
"//xls/codegen:module_signature",
775+
"//xls/codegen:module_signature_cc_proto",
776+
"//xls/common:proto_test_utils",
777+
"//xls/common:xls_gunit_main",
778+
"//xls/common/status:matchers",
779+
"//xls/common/status:status_macros",
780+
"//xls/ir",
781+
"//xls/ir:channel",
782+
"//xls/ir:channel_cc_proto",
783+
"//xls/ir:channel_ops",
784+
"//xls/ir:clone_package",
785+
"//xls/ir:function_builder",
786+
"//xls/ir:ir_parser",
787+
"//xls/ir:ir_test_base",
788+
"//xls/ir:type",
789+
"//xls/passes:pass_base",
790+
"@com_google_absl//absl/status:statusor",
791+
"@googletest//:gtest",
792+
],
793+
)
794+
737795
cc_test(
738796
name = "scheduled_block_conversion_pass_test",
739797
srcs = ["scheduled_block_conversion_pass_test.cc"],

xls/codegen_v_1_5/block_conversion_pass_pipeline.cc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "xls/codegen_v_1_5/scheduled_block_conversion_pass.h"
3333
#include "xls/codegen_v_1_5/scheduling_pass.h"
3434
#include "xls/codegen_v_1_5/side_effect_condition_pass.h"
35+
#include "xls/codegen_v_1_5/signature_generation_pass.h"
3536
#include "xls/codegen_v_1_5/state_to_register_io_lowering_pass.h"
3637
#include "xls/passes/dataflow_simplification_pass.h"
3738
#include "xls/passes/dce_pass.h"
@@ -63,6 +64,9 @@ std::unique_ptr<BlockConversionCompoundPass> CreateBlockConversionPassPipeline(
6364
// Lower params and return values to ports.
6465
top->Add<FunctionIOLoweringPass>();
6566

67+
// Add module signatures.
68+
top->Add<SignatureGenerationPass>();
69+
6670
// Insert flow control between stages.
6771
top->Add<FlowControlInsertionPass>();
6872

xls/codegen_v_1_5/block_conversion_pass_pipeline_test.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ class BlockConversionTest : public BlockConversionTestFixture {
141141
}
142142

143143
CodegenOptions codegen_options() {
144-
return CodegenOptions().module_name(TestName());
144+
return CodegenOptions().module_name(TestName()).clock_name("clk");
145145
}
146146

147147
absl::StatusOr<Block*> ConvertToBlock(

xls/codegen_v_1_5/channel_to_port_io_lowering_pass.cc

Lines changed: 69 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,67 @@ GetLoopbackChannels(ScheduledBlock* block) {
266266
return loopback_channels;
267267
}
268268

269+
FlopKind GetDefaultFlopKind(bool enabled,
270+
::xls::verilog::CodegenOptions::IOKind kind) {
271+
if (!enabled) {
272+
return FlopKind::kNone;
273+
}
274+
return ::xls::verilog::CodegenOptions::IOKindToFlopKind(kind);
275+
}
276+
277+
absl::StatusOr<FlopKind> GetFlopKind(
278+
ChannelRef channel, ChannelDirection direction, ScheduledBlock* block,
279+
const BlockConversionPassOptions& options) {
280+
if (ChannelRefKind(channel) == ChannelKind::kSingleValue) {
281+
// NOTE: We control the flop insertion for single-value channels globally,
282+
// with no per-channel configuration. This matches the behavior in codegen
283+
// v1.0.
284+
if (!options.codegen_options.flop_single_value_channels()) {
285+
return FlopKind::kNone;
286+
}
287+
switch (direction) {
288+
case ChannelDirection::kSend: {
289+
if (!options.codegen_options.flop_outputs()) {
290+
return FlopKind::kNone;
291+
}
292+
return FlopKind::kFlop;
293+
}
294+
case ChannelDirection::kReceive: {
295+
if (!options.codegen_options.flop_inputs()) {
296+
return FlopKind::kNone;
297+
}
298+
return FlopKind::kFlop;
299+
}
300+
}
301+
ABSL_UNREACHABLE();
302+
return absl::InternalError(
303+
absl::StrFormat("Unknown channel direction %d", direction));
304+
}
305+
306+
if (std::holds_alternative<Channel*>(channel)) {
307+
XLS_RET_CHECK(!block->package()->ChannelsAreProcScoped())
308+
<< "For proc-scoped channels, the flop kind is set on the interface.";
309+
XLS_RET_CHECK_EQ(ChannelRefKind(channel), ChannelKind::kStreaming);
310+
StreamingChannel* streaming_channel =
311+
down_cast<StreamingChannel*>(std::get<Channel*>(channel));
312+
switch (direction) {
313+
case ChannelDirection::kSend:
314+
return streaming_channel->channel_config().output_flop_kind().value_or(
315+
GetDefaultFlopKind(options.codegen_options.flop_outputs(),
316+
options.codegen_options.flop_outputs_kind()));
317+
case ChannelDirection::kReceive:
318+
return streaming_channel->channel_config().input_flop_kind().value_or(
319+
GetDefaultFlopKind(options.codegen_options.flop_inputs(),
320+
options.codegen_options.flop_inputs_kind()));
321+
}
322+
ABSL_UNREACHABLE();
323+
return absl::InternalError(
324+
absl::StrFormat("Unknown channel direction %d", direction));
325+
} else {
326+
return std::get<ChannelInterface*>(channel)->flop_kind();
327+
}
328+
}
329+
269330
absl::StatusOr<Connector> AddPortsForSend(
270331
ChannelRef channel, ScheduledBlock* block,
271332
const BlockConversionPassOptions& options) {
@@ -317,12 +378,15 @@ absl::StatusOr<Connector> AddPortsForSend(
317378
.valid = valid,
318379
.ready = ready};
319380

381+
XLS_ASSIGN_OR_RETURN(
382+
FlopKind flop_kind,
383+
GetFlopKind(channel, ChannelDirection::kSend, block, options));
320384
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
321385
ChannelPortMetadata{.channel_name = std::string(ChannelRefName(channel)),
322386
.type = ChannelRefType(channel),
323387
.direction = ChannelDirection::kSend,
324388
.channel_kind = ChannelRefKind(channel),
325-
.flop_kind = FlopKind::kNone,
389+
.flop_kind = flop_kind,
326390
.data_port = data->GetName(),
327391
.valid_port = GetOptionalNodeName(valid),
328392
.ready_port = GetOptionalNodeName(ready)}));
@@ -378,12 +442,15 @@ absl::StatusOr<Connector> AddPortsForReceive(
378442
.valid = valid,
379443
.ready = ready};
380444

445+
XLS_ASSIGN_OR_RETURN(
446+
FlopKind flop_kind,
447+
GetFlopKind(channel, ChannelDirection::kReceive, block, options));
381448
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
382449
ChannelPortMetadata{.channel_name = std::string(ChannelRefName(channel)),
383450
.type = ChannelRefType(channel),
384451
.direction = ChannelDirection::kReceive,
385452
.channel_kind = ChannelRefKind(channel),
386-
.flop_kind = FlopKind::kNone,
453+
.flop_kind = flop_kind,
387454
.data_port = data->GetName(),
388455
.valid_port = GetOptionalNodeName(valid),
389456
.ready_port = GetOptionalNodeName(ready)}));
@@ -1123,67 +1190,6 @@ absl::flat_hash_set<std::string> GetRamChannelNames(
11231190
return ram_channel_names;
11241191
}
11251192

1126-
FlopKind GetDefaultFlopKind(bool enabled,
1127-
::xls::verilog::CodegenOptions::IOKind kind) {
1128-
if (!enabled) {
1129-
return FlopKind::kNone;
1130-
}
1131-
return ::xls::verilog::CodegenOptions::IOKindToFlopKind(kind);
1132-
}
1133-
1134-
absl::StatusOr<FlopKind> GetFlopKind(
1135-
ChannelRef channel, ChannelDirection direction, ScheduledBlock* block,
1136-
const BlockConversionPassOptions& options) {
1137-
if (ChannelRefKind(channel) == ChannelKind::kSingleValue) {
1138-
// NOTE: We control the flop insertion for single-value channels globally,
1139-
// with no per-channel configuration. This matches the behavior in codegen
1140-
// v1.0.
1141-
if (!options.codegen_options.flop_single_value_channels()) {
1142-
return FlopKind::kNone;
1143-
}
1144-
switch (direction) {
1145-
case ChannelDirection::kSend: {
1146-
if (!options.codegen_options.flop_outputs()) {
1147-
return FlopKind::kNone;
1148-
}
1149-
return FlopKind::kFlop;
1150-
}
1151-
case ChannelDirection::kReceive: {
1152-
if (!options.codegen_options.flop_inputs()) {
1153-
return FlopKind::kNone;
1154-
}
1155-
return FlopKind::kFlop;
1156-
}
1157-
}
1158-
ABSL_UNREACHABLE();
1159-
return absl::InternalError(
1160-
absl::StrFormat("Unknown channel direction %d", direction));
1161-
}
1162-
1163-
if (std::holds_alternative<Channel*>(channel)) {
1164-
XLS_RET_CHECK(!block->package()->ChannelsAreProcScoped())
1165-
<< "For proc-scoped channels, the flop kind is set on the interface.";
1166-
XLS_RET_CHECK_EQ(ChannelRefKind(channel), ChannelKind::kStreaming);
1167-
StreamingChannel* streaming_channel =
1168-
down_cast<StreamingChannel*>(std::get<Channel*>(channel));
1169-
switch (direction) {
1170-
case ChannelDirection::kSend:
1171-
return streaming_channel->channel_config().output_flop_kind().value_or(
1172-
GetDefaultFlopKind(options.codegen_options.flop_outputs(),
1173-
options.codegen_options.flop_outputs_kind()));
1174-
case ChannelDirection::kReceive:
1175-
return streaming_channel->channel_config().input_flop_kind().value_or(
1176-
GetDefaultFlopKind(options.codegen_options.flop_inputs(),
1177-
options.codegen_options.flop_inputs_kind()));
1178-
}
1179-
ABSL_UNREACHABLE();
1180-
return absl::InternalError(
1181-
absl::StrFormat("Unknown channel direction %d", direction));
1182-
} else {
1183-
return std::get<ChannelInterface*>(channel)->flop_kind();
1184-
}
1185-
}
1186-
11871193
// Adds a register between the node and all its downstream users.
11881194
// Returns the new register added.
11891195
absl::StatusOr<RegisterRead*> AddRegisterAfterNode(

xls/codegen_v_1_5/side_effect_condition_pass_test.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,10 @@ class SideEffectConditionPassTest
121121

122122
static BlockConversionPassOptions CreateBlockConversionPassOptions(
123123
::xls::verilog::CodegenOptions codegen_options =
124-
::xls::verilog::CodegenOptions().clock_name("clk")) {
124+
::xls::verilog::CodegenOptions()) {
125+
if (codegen_options.clock_name().value_or("").empty()) {
126+
codegen_options.clock_name("clk");
127+
}
125128
return BlockConversionPassOptions{
126129
.codegen_options = std::move(codegen_options),
127130
.package_schedule = {},

0 commit comments

Comments
 (0)