Skip to content

Commit

Permalink
Add serialization of channel port metadata in block IR.
Browse files Browse the repository at this point in the history
Channel port metadata maps ports to the channel components (data/ready/valid) they are associated with.

PiperOrigin-RevId: 722699509
  • Loading branch information
meheffernan authored and copybara-github committed Feb 3, 2025
1 parent ea7f4a4 commit b54dce5
Show file tree
Hide file tree
Showing 13 changed files with 425 additions and 131 deletions.
35 changes: 13 additions & 22 deletions xls/codegen/block_conversion.cc
Original file line number Diff line number Diff line change
Expand Up @@ -345,12 +345,9 @@ absl::Status UpdateChannelMetadata(const StreamingIOPipeline& io,
ready_name);

if (input.IsExternal()) {
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(ChannelPortMetadata{
.channel_name = std::string{input.channel->name()},
.direction = PortDirection::kInput,
.data_port = input.port.value()->GetName(),
.valid_port = input.port_valid->GetName(),
.ready_port = input.port_ready->GetName()}));
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
input.channel, PortDirection::kInput, input.port.value()->GetName(),
input.port_valid->GetName(), input.port_ready->GetName()));
}
}
}
Expand All @@ -375,12 +372,10 @@ absl::Status UpdateChannelMetadata(const StreamingIOPipeline& io,
ready_name);

if (output.IsExternal()) {
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(ChannelPortMetadata{
.channel_name = std::string{output.channel->name()},
.direction = PortDirection::kOutput,
.data_port = output.port.value()->GetName(),
.valid_port = output.port_valid->GetName(),
.ready_port = output.port_ready->GetName()}));
XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
output.channel, PortDirection::kOutput,
output.port.value()->GetName(), output.port_valid->GetName(),
output.port_ready->GetName()));
}
}
}
Expand All @@ -393,11 +388,9 @@ absl::Status UpdateChannelMetadata(const StreamingIOPipeline& io,
->AddBlockPortMapping(block->name(), input.port->name());

XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{input.channel->name()},
.direction = PortDirection::kInput,
.data_port = std::string{input.port->name()},
.valid_port = std::nullopt,
.ready_port = std::nullopt}));
input.channel, PortDirection::kInput, input.port->GetName(),
/*valid_port=*/std::nullopt,
/*ready_port=*/std::nullopt));
}

for (const SingleValueOutput& output : io.single_value_outputs) {
Expand All @@ -408,11 +401,9 @@ absl::Status UpdateChannelMetadata(const StreamingIOPipeline& io,
->AddBlockPortMapping(block->name(), output.port->name());

XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{output.channel->name()},
.direction = PortDirection::kOutput,
.data_port = std::string{output.port->name()},
.valid_port = std::nullopt,
.ready_port = std::nullopt}));
output.channel, PortDirection::kOutput, output.port->GetName(),
/*valid_port=*/std::nullopt,
/*ready_port=*/std::nullopt));
}

return absl::OkStatus();
Expand Down
28 changes: 8 additions & 20 deletions xls/codegen/block_stitching_pass.cc
Original file line number Diff line number Diff line change
Expand Up @@ -237,11 +237,8 @@ absl::Status ExposeStreamingOutput(
.status());

XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{output->channel->name()},
.direction = PortDirection::kOutput,
.data_port = output->port.value()->GetName(),
.valid_port = output->port_valid->GetName(),
.ready_port = output->port_ready->GetName()}));
output->channel, PortDirection::kOutput, output->port.value()->GetName(),
output->port_valid->GetName(), output->port_ready->GetName()));

return absl::OkStatus();
}
Expand Down Expand Up @@ -289,11 +286,8 @@ absl::Status ExposeStreamingInput(
block->AddOutputPort(input->port_ready->GetName(), block_ready).status());

XLS_RETURN_IF_ERROR(block->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{input->channel->name()},
.direction = PortDirection::kInput,
.data_port = input->port.value()->GetName(),
.valid_port = input->port_valid->GetName(),
.ready_port = input->port_ready->GetName()}));
input->channel, PortDirection::kInput, input->port.value()->GetName(),
input->port_valid->GetName(), input->port_ready->GetName()));

return absl::OkStatus();
}
Expand Down Expand Up @@ -339,11 +333,8 @@ absl::Status StitchSingleValueChannel(
input_node, container->AddInputPort(subblock_input->port->GetName(),
subblock_input->port->GetType()));
XLS_RETURN_IF_ERROR(container->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{channel->name()},
.direction = PortDirection::kInput,
.data_port = subblock_input->port->GetName(),
.valid_port = std::nullopt,
.ready_port = std::nullopt}));
channel, PortDirection::kInput, subblock_input->port->GetName(),
/*valid_port=*/std::nullopt, /*ready_port=*/std::nullopt));
}
if (has_input) {
auto subblock_inst_iter = instantiations.find(
Expand All @@ -364,11 +355,8 @@ absl::Status StitchSingleValueChannel(
container->AddOutputPort(subblock_output->port->GetName(), input_node)
.status());
return container->AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{channel->name()},
.direction = PortDirection::kOutput,
.data_port = subblock_output->port->GetName(),
.valid_port = std::nullopt,
.ready_port = std::nullopt});
channel, PortDirection::kOutput, subblock_output->port->GetName(),
/*valid_port=*/std::nullopt, /*ready_port=*/std::nullopt);
}

// Stitch two ends of a streaming channel together.
Expand Down
63 changes: 63 additions & 0 deletions xls/ir/block.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,26 @@

namespace xls {

std::string ChannelPortMetadata::ToString() const {
std::string result = absl::StrFormat(
"channel_ports(name=%s, type=%s, direction=%s, kind=%s", channel_name,
type->ToString(), direction == PortDirection::kInput ? "in" : "out",
ChannelKindToString(channel_kind));
if (flop_kind != FlopKind::kNone) {
absl::StrAppendFormat(&result, ", flop=%s", FlopKindToString(flop_kind));
}
if (data_port.has_value()) {
absl::StrAppendFormat(&result, ", data_port=%s", *data_port);
}
if (ready_port.has_value()) {
absl::StrAppendFormat(&result, ", ready_port=%s", *ready_port);
}
if (valid_port.has_value()) {
absl::StrAppendFormat(&result, ", valid_port=%s", *valid_port);
}
return result + ")";
}

// For each node in the block, compute the fewest number of registers
// (RegisterWrite/RegisterRead pair) in a path from the node to a user-less node
// (e.g., OutputPort) where path length is measured by the number of registers
Expand Down Expand Up @@ -239,6 +259,10 @@ std::string Block::DumpIr() const {
std::string res = absl::StrFormat("block %s(%s) {\n", name(),
absl::StrJoin(port_strings, ", "));

for (const std::string& channel_name : GetChannelNames()) {
absl::StrAppendFormat(&res, " #![%s]\n",
channel_port_metadata_.at(channel_name).ToString());
}
for (Instantiation* instantiation : GetInstantiations()) {
absl::StrAppendFormat(&res, " %s\n", instantiation->ToString());
}
Expand Down Expand Up @@ -530,14 +554,23 @@ absl::Status Block::RemoveNode(Node* n) {
// tuple typed channels).
for (auto& [channel_name, metadata] : channel_port_metadata_) {
if (metadata.data_port.has_value() && port_name == *metadata.data_port) {
VLOG(3) << absl::StreamFormat(
"Data port for channel `%s` in block `%s` removed: %s",
metadata.channel_name, name(), metadata.data_port.value());
metadata.data_port = std::nullopt;
break;
} else if (metadata.ready_port.has_value() &&
port_name == *metadata.ready_port) {
VLOG(3) << absl::StreamFormat(
"Ready port for channel `%s` in block `%s` removed: %s",
metadata.channel_name, name(), metadata.ready_port.value());
metadata.ready_port = std::nullopt;
break;
} else if (metadata.valid_port.has_value() &&
port_name == *metadata.valid_port) {
VLOG(3) << absl::StreamFormat(
"Valid port for channel `%s` in block `%s` removed: %s",
metadata.channel_name, name(), metadata.valid_port.value());
metadata.valid_port = std::nullopt;
break;
}
Expand Down Expand Up @@ -940,10 +973,40 @@ absl::Status Block::AddChannelPortMetadata(ChannelPortMetadata metadata) {
metadata.data_port.value(), name(), metadata.channel_name);
}
}
VLOG(3) << "AddChannelPortMetadata for block `" << name()
<< "`: " << metadata.ToString();
channel_port_metadata_[metadata.channel_name] = std::move(metadata);
return absl::OkStatus();
}

absl::Status Block::AddChannelPortMetadata(
Channel* channel, PortDirection direction,
std::optional<std::string> data_port, std::optional<std::string> valid_port,
std::optional<std::string> ready_port) {
FlopKind flop_kind;
if (StreamingChannel* streaming_channel =
dynamic_cast<StreamingChannel*>(channel);
streaming_channel != nullptr) {
flop_kind =
direction == PortDirection::kInput
? streaming_channel->channel_config().input_flop_kind().value_or(
FlopKind::kNone)
: streaming_channel->channel_config().output_flop_kind().value_or(
FlopKind::kNone);
} else {
flop_kind = FlopKind::kNone;
}
return AddChannelPortMetadata(
ChannelPortMetadata{.channel_name = std::string{channel->name()},
.type = channel->type(),
.direction = direction,
.channel_kind = channel->kind(),
.flop_kind = flop_kind,
.data_port = data_port,
.valid_port = valid_port,
.ready_port = ready_port});
}

absl::StatusOr<ChannelPortMetadata> Block::GetChannelPortMetadata(
std::string_view channel_name) const {
XLS_ASSIGN_OR_RETURN(const ChannelPortMetadata* metadata,
Expand Down
15 changes: 13 additions & 2 deletions xls/ir/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,19 @@ namespace xls {
// Metadata which maps ports back to the channels the were derived from.
struct ChannelPortMetadata {
std::string channel_name;
Type* type;
// The direction of the data/valid port (input or output).
PortDirection direction;
ChannelKind channel_kind;
FlopKind flop_kind;

// Names of the ports for data/valid/ready signals for the channel. The value
// is std::nullopt if no such port exists.
std::optional<std::string> data_port;
std::optional<std::string> valid_port;
std::optional<std::string> ready_port;

std::string ToString() const;
};

// Abstraction representing a Verilog module used in code generation. Blocks are
Expand Down Expand Up @@ -229,12 +235,18 @@ class Block : public FunctionBase {
// Add metadata describing the mapping from ports to the channel they are
// derived from.
absl::Status AddChannelPortMetadata(ChannelPortMetadata metadata);
absl::Status AddChannelPortMetadata(Channel* channel, PortDirection direction,
std::optional<std::string> data_port,
std::optional<std::string> valid_port,
std::optional<std::string> ready_port);

// Returns the port metadata for the channel with the given name or an error
// if no such metadata exists.
absl::StatusOr<ChannelPortMetadata> GetChannelPortMetadata(
std::string_view channel_name) const;

bool HasChannelPortMetadata(std::string_view channel_name) const {
return channel_port_metadata_.contains(channel_name);
}
// Returns the port node associated with the ready/valid/data signal for the
// given channel. Returns an error if no port metadata exists for the given
// channel. Returns std::nullopt if port metadata exists for the channel but
Expand Down Expand Up @@ -276,7 +288,6 @@ class Block : public FunctionBase {

absl::StatusOr<const ChannelPortMetadata*> GetChannelPortMetadataInternal(
std::string_view channel_name) const;
absl::Status AddChannelPortMetadataInternal(ChannelPortMetadata metadata);

// All ports in the block in the order they appear in the Verilog module.
std::vector<Port> ports_;
Expand Down
Loading

0 comments on commit b54dce5

Please sign in to comment.