Skip to content

Commit

Permalink
Add channel "kind" to channel reference.
Browse files Browse the repository at this point in the history
Channel kind options are: streaming or single-value. Channel references must bind to channels of the same kind.

PiperOrigin-RevId: 597957835
  • Loading branch information
meheffernan authored and copybara-github committed Jan 12, 2024
1 parent 9d24b34 commit aa74093
Show file tree
Hide file tree
Showing 16 changed files with 148 additions and 89 deletions.
2 changes: 2 additions & 0 deletions xls/codegen/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -929,7 +929,9 @@ cc_library(
"//xls/common/logging",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:channel",
"//xls/ir:node_util",
"//xls/passes:bdd_function",
"//xls/passes:bdd_query_engine",
"//xls/passes:query_engine",
"@com_google_absl//absl/status:statusor",
Expand Down
19 changes: 9 additions & 10 deletions xls/codegen/bdd_io_analysis.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,18 @@
#include "xls/codegen/bdd_io_analysis.h"

#include <algorithm>
#include <memory>
#include <utility>
#include <cstdint>
#include <vector>

#include "absl/status/statusor.h"
#include "xls/common/logging/logging.h"
#include "xls/common/status/status_macros.h"
#include "xls/ir/function.h"
#include "xls/ir/channel.h"
#include "xls/ir/node.h"
#include "xls/ir/node_util.h"
#include "xls/ir/nodes.h"
#include "xls/ir/proc.h"
#include "xls/passes/bdd_function.h"
#include "xls/passes/bdd_query_engine.h"
#include "xls/passes/query_engine.h"

namespace xls {

Expand All @@ -51,18 +50,18 @@ bool UseNodeInBddEngine(const Node* node) {

} // namespace

absl::StatusOr<bool> AreStreamingOutputsMutuallyExclusive(FunctionBase* f) {
absl::StatusOr<bool> AreStreamingOutputsMutuallyExclusive(Proc* proc) {
// Find all send nodes associated with streaming channels.
int64_t streaming_send_count = 0;
std::vector<Node*> send_predicates;

for (Node* node : f->nodes()) {
for (Node* node : proc->nodes()) {
if (!node->Is<Send>()) {
continue;
}

XLS_ASSIGN_OR_RETURN(Channel * channel, GetChannelUsedByNode(node));
if (channel->kind() != ChannelKind::kStreaming) {
XLS_ASSIGN_OR_RETURN(ChannelRef channel, GetChannelRefUsedByNode(node));
if (ChannelRefKind(channel) != ChannelKind::kStreaming) {
continue;
}

Expand Down Expand Up @@ -92,7 +91,7 @@ absl::StatusOr<bool> AreStreamingOutputsMutuallyExclusive(FunctionBase* f) {
// if one is true, the rest are false.
BddQueryEngine query_engine(BddFunction::kDefaultPathLimit,
UseNodeInBddEngine);
XLS_RETURN_IF_ERROR(query_engine.Populate(f).status());
XLS_RETURN_IF_ERROR(query_engine.Populate(proc).status());

return query_engine.AtMostOneNodeTrue(send_predicates);
}
Expand Down
2 changes: 1 addition & 1 deletion xls/codegen/bdd_io_analysis.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace xls {
//
// TODO(tedhong): 2022-02-09 Add analysis of I/O dependencies
// TODO(tedhong): 2022-02-09 Add additional exclusivity analysis
absl::StatusOr<bool> AreStreamingOutputsMutuallyExclusive(FunctionBase* f);
absl::StatusOr<bool> AreStreamingOutputsMutuallyExclusive(Proc* proc);

} // namespace xls

Expand Down
13 changes: 0 additions & 13 deletions xls/codegen/bdd_io_analysis_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,6 @@ namespace {

class BddIOAnalysisPassTest : public IrTestBase {};

TEST_F(BddIOAnalysisPassTest, RunOnFunction) {
auto p = CreatePackage();
FunctionBuilder fb(TestName(), p.get());
BValue x = fb.Param("x", p->GetBitsType(4));
BValue y = fb.Param("y", p->GetBitsType(4));
fb.Concat({x, y});
XLS_ASSERT_OK_AND_ASSIGN(Function * f, fb.Build());

XLS_ASSERT_OK_AND_ASSIGN(bool mutually_exclusive,
AreStreamingOutputsMutuallyExclusive(f));
EXPECT_EQ(mutually_exclusive, true);
}

TEST_F(BddIOAnalysisPassTest, SingleStreamingSend) {
auto package_ptr = std::make_unique<Package>(TestName());
Package& package = *package_ptr;
Expand Down
10 changes: 9 additions & 1 deletion xls/ir/channel.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,8 +189,16 @@ Type* ChannelRefType(ChannelRef ref) {
return std::get<Channel*>(ref)->type();
}

ChannelKind ChannelRefKind(ChannelRef ref) {
if (std::holds_alternative<ChannelReference*>(ref)) {
return std::get<ChannelReference*>(ref)->kind();
}
return std::get<Channel*>(ref)->kind();
}

std::string ChannelReference::ToString() const {
return absl::StrFormat("%s: %s %s", name(), type()->ToString(),
return absl::StrFormat("%s: %s %s %s", name(), type()->ToString(),
ChannelKindToString(kind()),
direction() == Direction::kSend ? "out" : "in");
}

Expand Down
17 changes: 10 additions & 7 deletions xls/ir/channel.h
Original file line number Diff line number Diff line change
Expand Up @@ -324,8 +324,8 @@ std::string DirectionToString(Direction direction);
// references are bound to channel objects.
class ChannelReference {
public:
ChannelReference(std::string_view name, Type* type)
: name_(name), type_(type) {}
ChannelReference(std::string_view name, Type* type, ChannelKind kind)
: name_(name), type_(type), kind_(kind) {}
virtual ~ChannelReference() {}

// Like most IR constructs, ChannelReferences are passed around by pointer and
Expand All @@ -335,27 +335,29 @@ class ChannelReference {

std::string_view name() const { return name_; }
Type* type() const { return type_; }
ChannelKind kind() const { return kind_; }
virtual Direction direction() const = 0;

std::string ToString() const;

private:
std::string name_;
Type* type_;
ChannelKind kind_;
};

class SendChannelReference : public ChannelReference {
public:
SendChannelReference(std::string_view name, Type* type)
: ChannelReference(name, type) {}
SendChannelReference(std::string_view name, Type* type, ChannelKind kind)
: ChannelReference(name, type, kind) {}
~SendChannelReference() override {}
Direction direction() const override { return Direction::kSend; }
};

class ReceiveChannelReference : public ChannelReference {
public:
ReceiveChannelReference(std::string_view name, Type* type)
: ChannelReference(name, type) {}
ReceiveChannelReference(std::string_view name, Type* type, ChannelKind kind)
: ChannelReference(name, type, kind) {}
~ReceiveChannelReference() override {}
Direction direction() const override { return Direction::kReceive; }
};
Expand All @@ -375,9 +377,10 @@ using ChannelRef = std::variant<Channel*, ChannelReference*>;
using SendChannelRef = std::variant<Channel*, SendChannelReference*>;
using ReceiveChannelRef = std::variant<Channel*, ReceiveChannelReference*>;

// Return the name/type of a channel reference.
// Return the name/type/kind of a channel reference.
std::string_view ChannelRefName(ChannelRef ref);
Type* ChannelRefType(ChannelRef ref);
ChannelKind ChannelRefKind(ChannelRef ref);

} // namespace xls

Expand Down
30 changes: 19 additions & 11 deletions xls/ir/elaboration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -252,17 +252,25 @@ absl::StatusOr<Elaboration> Elaboration::Elaborate(Proc* top) {
for (ChannelReference* channel_ref : top->interface()) {
// TODO(https://github.com/google/xls/issues/869): Add options for
// fifo-config, strictness, etc.
elaboration.interface_channels_.push_back(
std::make_unique<StreamingChannel>(
channel_ref->name(), channel_id,
channel_ref->direction() == Direction::kSend
? ChannelOps::kSendOnly
: ChannelOps::kReceiveOnly,
channel_ref->type(), /*intial_values=*/absl::Span<const Value>(),
/*fifo_config=*/std::nullopt,
/*flow_control=*/FlowControl::kReadyValid,
/*strictness=*/ChannelStrictness::kProvenMutuallyExclusive,
ChannelMetadataProto()));
ChannelOps ops = channel_ref->direction() == Direction::kSend
? ChannelOps::kSendOnly
: ChannelOps::kReceiveOnly;
if (channel_ref->kind() == ChannelKind::kStreaming) {
elaboration.interface_channels_.push_back(
std::make_unique<StreamingChannel>(
channel_ref->name(), channel_id, ops, channel_ref->type(),
/*intial_values=*/absl::Span<const Value>(),
/*fifo_config=*/std::nullopt,
/*flow_control=*/FlowControl::kReadyValid,
/*strictness=*/ChannelStrictness::kProvenMutuallyExclusive,
ChannelMetadataProto()));
} else {
XLS_RET_CHECK_EQ(channel_ref->kind(), ChannelKind::kSingleValue);
elaboration.interface_channels_.push_back(
std::make_unique<SingleValueChannel>(channel_ref->name(), channel_id,
ops, channel_ref->type(),
ChannelMetadataProto()));
}
++channel_id;
elaboration.interface_channel_instances_.push_back(
std::make_unique<ChannelInstance>(ChannelInstance{
Expand Down
31 changes: 21 additions & 10 deletions xls/ir/function_builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1045,13 +1045,23 @@ ProcBuilder::ProcBuilder(NewStyleProc tag, std::string_view name,
Proc* ProcBuilder::proc() const { return down_cast<Proc*>(function()); }

absl::StatusOr<ChannelReferences> ProcBuilder::AddChannel(
std::string_view name, Type* type, absl::Span<const Value> initial_values) {
std::string_view name, Type* type, ChannelKind kind,
absl::Span<const Value> initial_values) {
XLS_RET_CHECK(proc()->is_new_style_proc());
XLS_RETURN_IF_ERROR(proc()
->package()
->CreateStreamingChannelInProc(
name, ChannelOps::kSendReceive, type, proc())
.status());
if (kind == ChannelKind::kStreaming) {
XLS_RETURN_IF_ERROR(proc()
->package()
->CreateStreamingChannelInProc(
name, ChannelOps::kSendReceive, type, proc())
.status());
} else {
XLS_RET_CHECK_EQ(kind, ChannelKind::kSingleValue);
XLS_RETURN_IF_ERROR(proc()
->package()
->CreateSingleValueChannelInProc(
name, ChannelOps::kSendReceive, type, proc())
.status());
}
ChannelReferences channel_refs;
XLS_ASSIGN_OR_RETURN(channel_refs.send_ref,
proc()->GetSendChannelReference(name));
Expand All @@ -1061,16 +1071,17 @@ absl::StatusOr<ChannelReferences> ProcBuilder::AddChannel(
}

absl::StatusOr<ReceiveChannelReference*> ProcBuilder::AddInputChannel(
std::string_view name, Type* type) {
std::string_view name, Type* type, ChannelKind kind) {
XLS_RET_CHECK(proc()->is_new_style_proc());
auto channel_ref = std::make_unique<ReceiveChannelReference>(name, type);
auto channel_ref =
std::make_unique<ReceiveChannelReference>(name, type, kind);
return proc()->AddInputChannelReference(std::move(channel_ref));
}

absl::StatusOr<SendChannelReference*> ProcBuilder::AddOutputChannel(
std::string_view name, Type* type) {
std::string_view name, Type* type, ChannelKind kind) {
XLS_RET_CHECK(proc()->is_new_style_proc());
auto channel_ref = std::make_unique<SendChannelReference>(name, type);
auto channel_ref = std::make_unique<SendChannelReference>(name, type, kind);
return proc()->AddOutputChannelReference(std::move(channel_ref));
}

Expand Down
9 changes: 6 additions & 3 deletions xls/ir/function_builder.h
Original file line number Diff line number Diff line change
Expand Up @@ -720,14 +720,17 @@ class ProcBuilder : public BuilderBase {
// style procs.
absl::StatusOr<ChannelReferences> AddChannel(
std::string_view name, Type* type,
ChannelKind kind = ChannelKind::kStreaming,
absl::Span<const Value> initial_values = {});

// Add an interface channel to the proc. Only can be called for new style
// procs.
absl::StatusOr<ReceiveChannelReference*> AddInputChannel(
std::string_view name, Type* type);
absl::StatusOr<SendChannelReference*> AddOutputChannel(std::string_view name,
Type* type);
std::string_view name, Type* type,
ChannelKind kind = ChannelKind::kStreaming);
absl::StatusOr<SendChannelReference*> AddOutputChannel(
std::string_view name, Type* type,
ChannelKind kind = ChannelKind::kStreaming);

// Returns true if there is an channel entity (a xls::Channel object for
// old-style proc or a proc-scoped channel or interface channel for new style
Expand Down
34 changes: 25 additions & 9 deletions xls/ir/ir_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1780,7 +1780,7 @@ absl::StatusOr<std::unique_ptr<ProcBuilder>> Parser::ParseProcSignature(
//
// OR for "new-style" procs with proc-scoped channels:
//
// proc foo<in_ch: bits[32] in: out_ch: bits[8] out>
// proc foo<in_ch: bits[32] streaming in: out_ch: bits[8] single_value out>
// (tok: token, state0: bits[32], state1: bits[42], init={42, 33}) {
// ...
//
Expand All @@ -1800,16 +1800,28 @@ absl::StatusOr<std::unique_ptr<ProcBuilder>> Parser::ParseProcSignature(
XLS_RETURN_IF_ERROR(
scanner_.DropTokenOrError(LexicalTokenType::kColon));
XLS_ASSIGN_OR_RETURN(Type * type, ParseType(package));
XLS_ASSIGN_OR_RETURN(
Token kind_token,
scanner_.PopTokenOrError(LexicalTokenType::kIdent, "channel kind"));
absl::StatusOr<ChannelKind> kind_status =
StringToChannelKind(kind_token.value());
if (!kind_status.ok()) {
return absl::InvalidArgumentError(absl::StrFormat(
"Invalid channel kind \"%s\" @ %s", kind_token.value(),
kind_token.pos().ToHumanString()));
}
ChannelKind kind = kind_status.value();

XLS_ASSIGN_OR_RETURN(Token direction_token,
scanner_.PopTokenOrError(LexicalTokenType::kIdent,
"channel direction"));
if (direction_token.value() == "in") {
interface_channels.push_back(
std::make_unique<ReceiveChannelReference>(channel_name.value(),
type));
type, kind));
} else if (direction_token.value() == "out") {
interface_channels.push_back(std::make_unique<SendChannelReference>(
channel_name.value(), type));
channel_name.value(), type, kind));
} else {
return absl::InvalidArgumentError(absl::StrFormat(
"Invalid direction string `%s`, expected `in` or `out`",
Expand Down Expand Up @@ -1894,13 +1906,17 @@ absl::StatusOr<std::unique_ptr<ProcBuilder>> Parser::ParseProcSignature(
for (const std::unique_ptr<ChannelReference>& channel_ref :
interface_channels) {
if (channel_ref->direction() == Direction::kReceive) {
XLS_RETURN_IF_ERROR(
builder->AddInputChannel(channel_ref->name(), channel_ref->type())
.status());
XLS_RETURN_IF_ERROR(builder
->AddInputChannel(channel_ref->name(),
channel_ref->type(),
channel_ref->kind())
.status());
} else {
XLS_RETURN_IF_ERROR(
builder->AddOutputChannel(channel_ref->name(), channel_ref->type())
.status());
XLS_RETURN_IF_ERROR(builder
->AddOutputChannel(channel_ref->name(),
channel_ref->type(),
channel_ref->kind())
.status());
}
}
} else {
Expand Down
Loading

0 comments on commit aa74093

Please sign in to comment.