Skip to content

Commit

Permalink
Use elaboration instances in the interpreter and JIT.
Browse files Browse the repository at this point in the history
Rather than creating one continuation (channel queue) per Proc (Channel) IR object, one continuation (channel queue) is created per _instance_ of these IR objects. No functional change, but this lays the groundwork for the interpreter and JIT working with new-style procs with proc-scoped channels where channels and procs can be instantiated multiple times.

PiperOrigin-RevId: 595811756
  • Loading branch information
meheffernan authored and copybara-github committed Jan 4, 2024
1 parent a32cbfd commit b06b78f
Show file tree
Hide file tree
Showing 25 changed files with 758 additions and 350 deletions.
54 changes: 53 additions & 1 deletion xls/interpreter/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -110,11 +110,14 @@ cc_library(
":ir_interpreter",
":proc_evaluator",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/types:span",
"//xls/common/status:ret_check",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:bits",
"//xls/ir:elaboration",
"//xls/ir:events",
"//xls/ir:value",
"//xls/ir:value_helpers",
Expand All @@ -141,11 +144,18 @@ cc_test(
deps = [
":channel_queue",
":channel_queue_test_base",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/types:span",
"//xls/common:xls_gunit",
"//xls/common:xls_gunit_main",
"//xls/common/status:matchers",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:channel",
"//xls/ir:channel_ops",
"//xls/ir:elaboration",
"//xls/ir:ir_test_base",
],
)

Expand Down Expand Up @@ -225,12 +235,20 @@ cc_library(
srcs = ["channel_queue.cc"],
hdrs = ["channel_queue.h"],
deps = [
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/container:flat_hash_set",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings:str_format",
"@com_google_absl//absl/synchronization",
"@com_google_absl//absl/types:span",
"//xls/common/logging",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:channel",
"//xls/ir:type",
"//xls/ir:elaboration",
"//xls/ir:value",
"//xls/ir:value_helpers",
],
Expand Down Expand Up @@ -279,11 +297,17 @@ cc_library(
hdrs = ["channel_queue_test_base.h"],
deps = [
":channel_queue",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"//xls/common/status:matchers",
"//xls/ir",
"//xls/ir:bits",
"//xls/ir:channel",
"//xls/ir:channel_cc_proto",
"//xls/ir:channel_ops",
"//xls/ir:elaboration",
"//xls/ir:ir_test_base",
"//xls/ir:value",
"@com_google_benchmark//:benchmark",
"@com_google_googletest//:gtest",
],
Expand All @@ -295,9 +319,11 @@ cc_library(
hdrs = ["proc_evaluator.h"],
deps = [
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings:str_format",
"//xls/common/logging",
"//xls/ir",
"//xls/ir:channel",
"//xls/ir:elaboration",
"//xls/ir:events",
"//xls/ir:value",
],
Expand All @@ -316,6 +342,8 @@ cc_library(
"//xls/ir",
"//xls/ir:bits",
"//xls/ir:channel",
"//xls/ir:channel_ops",
"//xls/ir:elaboration",
"//xls/ir:function_builder",
"//xls/ir:ir_test_base",
"//xls/ir:value",
Expand All @@ -331,10 +359,20 @@ cc_library(
deps = [
":channel_queue",
":proc_evaluator",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:str_format",
"//xls/common/logging",
"//xls/common/logging:vlog_is_on",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:channel",
"//xls/ir:channel_ops",
"//xls/ir:elaboration",
"//xls/ir:events",
"//xls/ir:value",
"//xls/jit:jit_channel_queue",
],
)
Expand All @@ -347,9 +385,15 @@ cc_library(
":channel_queue",
":proc_evaluator",
":proc_runtime",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/memory",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings:str_format",
"//xls/common/logging",
"//xls/common/status:ret_check",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:elaboration",
],
)

Expand All @@ -376,15 +420,20 @@ cc_library(
srcs = ["proc_runtime_test_base.cc"],
hdrs = ["proc_runtime_test_base.h"],
deps = [
":channel_queue",
":proc_runtime",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"//xls/common/status:matchers",
"//xls/ir",
"//xls/ir:bits",
"//xls/ir:channel",
"//xls/ir:channel_ops",
"//xls/ir:function_builder",
"//xls/ir:ir_parser",
"//xls/ir:ir_test_base",
"//xls/ir:value",
"@com_google_benchmark//:benchmark",
"@com_google_googletest//:gtest",
],
Expand All @@ -399,7 +448,10 @@ cc_library(
":proc_evaluator",
":proc_interpreter",
":serial_proc_runtime",
"@com_google_absl//absl/status:statusor",
"//xls/common/status:status_macros",
"//xls/ir",
"//xls/ir:elaboration",
"//xls/ir:value",
],
)
107 changes: 68 additions & 39 deletions xls/interpreter/channel_queue.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,25 @@
#include "xls/interpreter/channel_queue.h"

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

#include "absl/container/flat_hash_set.h"
#include "absl/memory/memory.h"
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/str_format.h"
#include "absl/synchronization/mutex.h"
#include "xls/common/logging/logging.h"
#include "xls/common/status/status_macros.h"
#include "xls/ir/type.h"
#include "xls/ir/channel.h"
#include "xls/ir/elaboration.h"
#include "xls/ir/package.h"
#include "xls/ir/value.h"
#include "xls/ir/value_helpers.h"

namespace xls {
Expand All @@ -34,7 +43,7 @@ absl::Status ChannelQueue::AttachGenerator(GeneratorFn generator) {
if (generator_.has_value()) {
return absl::InternalError("ChannelQueue already has a generator attached");
}
if (channel_->kind() == ChannelKind::kSingleValue) {
if (channel()->kind() == ChannelKind::kSingleValue) {
return absl::InternalError(
absl::StrFormat("ChannelQueues for single-value channels cannot have a "
"generator. Channel: %s",
Expand All @@ -45,17 +54,18 @@ absl::Status ChannelQueue::AttachGenerator(GeneratorFn generator) {
}

absl::Status ChannelQueue::Write(const Value& value) {
XLS_VLOG(4) << absl::StreamFormat("Writing value to channel %s: { %s }",
channel_->name(), value.ToString());
XLS_VLOG(4) << absl::StreamFormat(
"Writing value to channel instance `%s`: { %s }",
channel_instance()->ToString(), value.ToString());
absl::MutexLock lock(&mutex_);
if (generator_.has_value()) {
return absl::InternalError(
"Cannot write to ChannelQueue because it has a generator function.");
}
if (!ValueConformsToType(value, channel_->type())) {
if (!ValueConformsToType(value, channel()->type())) {
return absl::InvalidArgumentError(absl::StrFormat(
"Channel %s expects values to have type %s, got: %s", channel_->name(),
channel_->type()->ToString(), value.ToString()));
"Channel `%s` expects values to have type %s, got: %s",
channel()->name(), channel()->type()->ToString(), value.ToString()));
}

WriteInternal(value);
Expand Down Expand Up @@ -90,7 +100,8 @@ std::optional<Value> ChannelQueue::Read() {
}
std::optional<Value> value = ReadInternal();
XLS_VLOG(4) << absl::StreamFormat(
"Reading data from channel %s: %s", channel_->name(),
"Reading data from channel instance %s: %s",
channel_instance()->ToString(),
value.has_value() ? value->ToString() : "(none)");
XLS_VLOG(4) << absl::StreamFormat("Channel now has %d elements",
queue_.size());
Expand All @@ -110,62 +121,76 @@ std::optional<Value> ChannelQueue::ReadInternal() {
return std::move(value);
}

/* static */ absl::StatusOr<std::unique_ptr<ChannelQueueManager>>
ChannelQueueManager::Create(Package* package) {
XLS_ASSIGN_OR_RETURN(Elaboration elaboration,
Elaboration::ElaborateOldStylePackage(package));
return Create(std::move(elaboration));
}

/* static */
absl::StatusOr<std::unique_ptr<ChannelQueueManager>>
ChannelQueueManager::Create(std::vector<std::unique_ptr<ChannelQueue>>&& queues,
Package* package) {
Elaboration elaboration) {
// Verify there is exactly one queue per channel.
absl::flat_hash_set<Channel*> proc_channels(package->channels().begin(),
package->channels().end());
absl::flat_hash_set<Channel*> queue_channels;
absl::flat_hash_set<ChannelInstance*> channel_instances(
elaboration.channel_instances().begin(),
elaboration.channel_instances().end());
absl::flat_hash_set<ChannelInstance*> queue_chan_instances;
for (const std::unique_ptr<ChannelQueue>& queue : queues) {
if (!proc_channels.contains(queue->channel())) {
if (!channel_instances.contains(queue->channel_instance())) {
return absl::InvalidArgumentError(absl::StrFormat(
"Channel `%s` for queue does not exist in package `%s`",
queue->channel()->name(), package->name()));
"Channel instance `%s` for queue does not exist in package `%s`",
queue->channel_instance()->ToString(),
elaboration.package()->name()));
}
auto [ir, inserted] = queue_channels.insert(queue->channel());
auto [ir, inserted] =
queue_chan_instances.insert(queue->channel_instance());
if (!inserted) {
return absl::InvalidArgumentError(
absl::StrFormat("Multiple queues specified for channel `%s`",
queue->channel()->name()));
absl::StrFormat("Multiple queues specified for channel instance `%s`",
queue->channel_instance()->ToString()));
}
}
for (Channel* channel : package->channels()) {
if (!queue_channels.contains(channel)) {
return absl::InvalidArgumentError(absl::StrFormat(
"No queue specified for channel `%s`", channel->name()));
for (ChannelInstance* instance : elaboration.channel_instances()) {
if (!queue_chan_instances.contains(instance)) {
return absl::InvalidArgumentError(
absl::StrFormat("No queue specified for channel instance `%s`",
instance->ToString()));
}
}

return absl::WrapUnique(new ChannelQueueManager(package, std::move(queues)));
return absl::WrapUnique(
new ChannelQueueManager(std::move(elaboration), std::move(queues)));
}

/* static */
absl::StatusOr<std::unique_ptr<ChannelQueueManager>>
ChannelQueueManager::Create(Package* package) {
ChannelQueueManager::Create(Elaboration elaboration) {
std::vector<std::unique_ptr<ChannelQueue>> queues;

// Create a queue per channel in the package.
for (Channel* channel : package->channels()) {
if (channel->kind() != ChannelKind::kStreaming &&
channel->kind() != ChannelKind::kSingleValue) {
// Create a queue per channel instance in the elaboration.
for (ChannelInstance* channel_instance : elaboration.channel_instances()) {
if (channel_instance->channel->kind() != ChannelKind::kStreaming &&
channel_instance->channel->kind() != ChannelKind::kSingleValue) {
return absl::UnimplementedError(
"Only streaming and single-value channels are supported.");
}
queues.push_back(std::make_unique<ChannelQueue>(channel));
queues.push_back(std::make_unique<ChannelQueue>(channel_instance));
}

return absl::WrapUnique(new ChannelQueueManager(package, std::move(queues)));
return absl::WrapUnique(
new ChannelQueueManager(std::move(elaboration), std::move(queues)));
}

ChannelQueueManager::ChannelQueueManager(
Package* package, std::vector<std::unique_ptr<ChannelQueue>>&& queues)
: package_(package) {
Elaboration elaboration,
std::vector<std::unique_ptr<ChannelQueue>>&& queues)
: elaboration_(std::move(elaboration)) {
for (std::unique_ptr<ChannelQueue>& queue : queues) {
Channel* channel = queue->channel();
queues_[channel] = std::move(queue);
queue_vec_.push_back(queues_[channel].get());
ChannelInstance* instance = queue->channel_instance();
queues_[instance] = std::move(queue);
queue_vec_.push_back(queues_[instance].get());
}
// Stably sort the queues by channel ID.
std::sort(queue_vec_.begin(), queue_vec_.end(),
Expand All @@ -176,14 +201,18 @@ ChannelQueueManager::ChannelQueueManager(

absl::StatusOr<ChannelQueue*> ChannelQueueManager::GetQueueById(
int64_t channel_id) {
XLS_ASSIGN_OR_RETURN(Channel * channel, package_->GetChannel(channel_id));
return queues_.at(channel).get();
XLS_ASSIGN_OR_RETURN(Channel * channel, package()->GetChannel(channel_id));
XLS_ASSIGN_OR_RETURN(ChannelInstance * instance,
elaboration().GetUniqueInstance(channel));
return queues_.at(instance).get();
}

absl::StatusOr<ChannelQueue*> ChannelQueueManager::GetQueueByName(
std::string_view name) {
XLS_ASSIGN_OR_RETURN(Channel * channel, package_->GetChannel(name));
return queues_.at(channel).get();
XLS_ASSIGN_OR_RETURN(Channel * channel, package()->GetChannel(name));
XLS_ASSIGN_OR_RETURN(ChannelInstance * instance,
elaboration().GetUniqueInstance(channel));
return queues_.at(instance).get();
}

} // namespace xls
Loading

0 comments on commit b06b78f

Please sign in to comment.