diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..b7f8359
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,63 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# DarwiNN Runtime Libaries.
+
+package(default_visibility = ["//visibility:public"])
+
+# All Google Owned Code except :
+# - certain files in port/default/ that are under Apache 2.0 license.
+licenses(["notice"])
+
+exports_files([
+ "LICENSE",
+])
+
+# If --define darwinn_portable=1, compile without google3 deps.
+config_setting(
+ name = "darwinn_portable",
+ values = {
+ "define": "darwinn_portable=1",
+ },
+)
+
+# If --define darwinn_portable=1 AND this is an otherwise non-portable config.
+config_setting(
+ name = "darwinn_portable_with_non_portable_os",
+ flag_values = {"//tools/cpp:cc_target_os": "linux-google"},
+ values = {"define": "darwinn_portable=1"},
+)
+
+# If --define darwinn_firmware=1, compile with minimal deps.
+config_setting(
+ name = "darwinn_firmware",
+ values = {
+ "define": "darwinn_firmware=1",
+ },
+)
+
+config_setting(
+ name = "windows",
+ values = {
+ "cpu": "x64_windows",
+ },
+)
+
+config_setting(
+ name = "darwin",
+ values = {
+ "cpu": "darwin",
+ },
+)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..3414802
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,28 @@
+# How to Contribute
+
+This project is not currently accepting contributions.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement (CLA). You (or your employer) retain the copyright to your
+contribution; this simply gives us permission to use and redistribute your
+contributions as part of the project. Head over to
+ to see your current agreements on file or
+to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google/conduct/).
\ No newline at end of file
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4e1e782
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,115 @@
+# Copyright 2019 Google LLC
+#
+# 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
+#
+# https://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.
+SHELL := /bin/bash
+MAKEFILE_DIR := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+OUT_DIR := $(MAKEFILE_DIR)/out
+OS := $(shell uname -s)
+
+ifeq ($(OS),Linux)
+CPU ?= k8
+else ifeq ($(OS),Darwin)
+CPU ?= darwin
+else
+$(error $(OS) is not supported)
+endif
+
+ifeq ($(filter $(CPU),k8 armv6 armv7a aarch64 darwin),)
+$(error CPU must be k8, armv7a, armv6, aarch64, or darwin)
+endif
+
+COMPILATION_MODE ?= opt
+ifeq ($(filter $(COMPILATION_MODE),opt dbg),)
+$(error COMPILATION_MODE must be opt or dbg)
+endif
+
+BAZEL_OUT_DIR := $(MAKEFILE_DIR)/bazel-out/$(CPU)-$(COMPILATION_MODE)/bin
+
+# Linux-specific parameters
+BAZEL_BUILD_TARGET_Linux := //tflite/public:libedgetpu_direct_all.so
+# --experimental_repo_remote_exec for remotable parameter used in
+# --`repository_rule` from TF.
+BAZEL_BUILD_FLAGS_Linux := --crosstool_top=@crosstool//:toolchains \
+ --compiler=gcc \
+ --linkopt=-l:libusb-1.0.so \
+ --experimental_repo_remote_exec
+BAZEL_BUILD_OUTPUT_FILE_Linux := libedgetpu.so.1.0
+BAZEL_BUILD_OUTPUT_SYMLINK_Linux := libedgetpu.so.1
+
+ifeq ($(COMPILATION_MODE), opt)
+BAZEL_BUILD_FLAGS_Linux += --linkopt=-Wl,--strip-all
+endif
+ifeq ($(CPU), armv6)
+BAZEL_BUILD_FLAGS_Linux += --linkopt=-L/usr/lib/arm-linux-gnueabihf/
+endif
+
+# Darwin-specific parameters
+BAZEL_BUILD_TARGET_Darwin := //tflite/public:libedgetpu_direct_usb.dylib
+BAZEL_BUILD_FLAGS_Darwin := --linkopt=-L/opt/local/lib \
+ --linkopt=-lusb-1.0 \
+ --copt=-fvisibility=hidden
+BAZEL_BUILD_OUTPUT_FILE_Darwin := libedgetpu.1.0.dylib
+BAZEL_BUILD_OUTPUT_SYMLINK_Darwin := libedgetpu.1.dylib
+
+# Common parameters
+BAZEL_BUILD_FLAGS := --sandbox_debug --subcommands \
+ --compilation_mode=$(COMPILATION_MODE) \
+ --define darwinn_portable=1 \
+ --copt=-DSTRIP_LOG=1 \
+ --copt=-DEDGETPU_EXTERNAL_RELEASE_RUNTIME \
+ --copt=-fno-rtti \
+ --copt=-fno-exceptions \
+ --copt='-D__FILE__=""' \
+ --cpu=$(CPU)
+BAZEL_BUILD_FLAGS += $(BAZEL_BUILD_FLAGS_$(OS))
+BAZEL_BUILD_TARGET := $(BAZEL_BUILD_TARGET_$(OS))
+BAZEL_BUILD_OUTPUT_FILE := $(BAZEL_BUILD_OUTPUT_FILE_$(OS))
+BAZEL_BUILD_OUTPUT_SYMLINK := $(BAZEL_BUILD_OUTPUT_SYMLINK_$(OS))
+
+define copy_out
+mkdir -p $(OUT_DIR)/$(1)/$(CPU) && \
+cp -f $(BAZEL_OUT_DIR)/tflite/public/*$(suffix $(BAZEL_BUILD_TARGET)) \
+ $(OUT_DIR)/$(1)/$(CPU)/$(BAZEL_BUILD_OUTPUT_FILE) && \
+ln -fs $(BAZEL_BUILD_OUTPUT_FILE) \
+ $(OUT_DIR)/$(1)/$(CPU)/$(BAZEL_BUILD_OUTPUT_SYMLINK)
+endef
+
+ifeq ($(OS),Darwin)
+ifeq ($(COMPILATION_MODE),opt)
+define strip_out
+strip -x -S -o $(OUT_DIR)/$(1)/$(CPU)/$(BAZEL_BUILD_OUTPUT_FILE) \
+ $(OUT_DIR)/$(1)/$(CPU)/$(BAZEL_BUILD_OUTPUT_FILE)
+endef
+endif
+endif
+
+libedgetpu: libedgetpu-direct libedgetpu-throttled
+
+libedgetpu-direct:
+ bazel build $(BAZEL_BUILD_FLAGS) $(BAZEL_BUILD_TARGET)
+ $(call copy_out,direct)
+ $(call strip_out,direct)
+
+libedgetpu-throttled:
+ bazel build $(BAZEL_BUILD_FLAGS) --copt=-DTHROTTLE_EDGE_TPU $(BAZEL_BUILD_TARGET)
+ $(call copy_out,throttled)
+ $(call strip_out,throttled)
+
+clean:
+ rm -rf $(OUT_DIR)
+
+ifdef DOCKER_MK
+DOCKER_WORKSPACE := $(MAKEFILE_DIR)
+DOCKER_TAG_BASE=coral-libedgetpu
+include $(DOCKER_MK)
+endif
diff --git a/README.md b/README.md
index 38f3e77..16da0e5 100644
--- a/README.md
+++ b/README.md
@@ -1,2 +1,33 @@
-# libedgetpu
-Source code for the userspace level runtime driver for Coral.ai devices.
+# Edge TPU runtime library (libedgetpu)
+
+This repo contains the source code for the userspace
+level runtime driver for [Coral devices](https://coral.ai/products).
+This software is distributed in the binary form at [coral.ai/software](https://coral.ai/software/).
+
+## Building
+
+At present only Bazel build system is supported, but it can be invoked from the Makefile.
+
+## Support
+
+If you have question, comments or requests concerning this library, please
+reach out to coral-support@google.com.
+
+## License
+
+[Apache License 2.0](LICENSE)
+
+## Warning
+
+If you're using the Coral USB Accelerator, it may heat up during operation, depending
+on the computation workloads and operating frequency. Touching the metal part of the USB
+Accelerator after it has been operating for an extended period of time may lead to discomfort
+and/or skin burns. As such, if you enable the Edge TPU runtime using the maximum operating
+frequency, the USB Accelerator should be operated at an ambient temperature of 25°C or less.
+Alternatively, if you enable the Edge TPU runtime using the reduced operating frequency, then
+the device is intended to safely operate at an ambient temperature of 35°C or less.
+
+Google does not accept any responsibility for any loss or damage if the device
+is operated outside of the recommended ambient temperature range.
+
+Note: This issue affects only USB-based Coral devices, and is irrelevant for PCIe devices.
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..7060b32
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,75 @@
+# Copyright 2019 Google LLC
+#
+# 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
+#
+# https://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.
+workspace(name = "libedgetpu")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "io_bazel_rules_closure",
+ sha256 = "5b00383d08dd71f28503736db0500b6fb4dda47489ff5fc6bed42557c07c6ba9",
+ strip_prefix = "rules_closure-308b05b2419edb5c8ee0471b67a40403df940149",
+ urls = [
+ "http://mirror.tensorflow.org/github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz",
+ "https://github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz", # 2019-06-13
+ ],
+)
+
+# Be consistent with tensorflow/WORKSPACE.
+http_archive(
+ name = "bazel_skylib",
+ sha256 = "1dde365491125a3db70731e25658dfdd3bc5dbdfd11b840b3e987ecf043c7ca0",
+ urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/0.9.0/bazel_skylib-0.9.0.tar.gz"],
+) # https://github.com/bazelbuild/bazel-skylib/releases
+
+# The TF commit # here must be in sync with that specified under Gob edgetpu
+# repo WORKSPACE file.
+# TODO: figure out a way to keep single source of truth of the
+# TF commit # used.
+TENSORFLOW_COMMIT = "f394a768719a55b5c351ed1ecab2ec6f16f99dd4";
+# Command to calculate: curl -OL | sha256sum | awk '{print $1}'
+TENSORFLOW_SHA256 = "cb286abee7ee9cf5c8701d85fcc88f0fd59e72492ec4f254156de486e3e905c1"
+http_archive(
+ name = "org_tensorflow",
+ sha256 = TENSORFLOW_SHA256,
+ strip_prefix = "tensorflow-" + TENSORFLOW_COMMIT,
+ urls = [
+ "https://github.com/tensorflow/tensorflow/archive/" + TENSORFLOW_COMMIT + ".tar.gz",
+ ],
+)
+
+load("@org_tensorflow//tensorflow:workspace.bzl", "tf_workspace")
+tf_workspace(tf_repo_name = "org_tensorflow")
+
+http_archive(
+ name = "coral_crosstool",
+ sha256 = "cb31b1417ccdcf7dd9fca5ec63e1571672372c30427730255997a547569d2feb",
+ strip_prefix = "crosstool-9e00d5be43bf001f883b5700f5d04882fea00229",
+ urls = [
+ "https://github.com/google-coral/crosstool/archive/9e00d5be43bf001f883b5700f5d04882fea00229.tar.gz",
+ ],
+)
+load("@coral_crosstool//:configure.bzl", "cc_crosstool")
+cc_crosstool(name = "crosstool")
+new_local_repository(
+ name = "libusb",
+ path = "/usr/include/",
+ build_file_content = """
+cc_library(
+ name = "headers",
+ includes = ["."],
+ hdrs = ["libusb-1.0/libusb.h"],
+ visibility = ["//visibility:public"],
+)
+"""
+)
diff --git a/api/BUILD b/api/BUILD
new file mode 100644
index 0000000..9f06da5
--- /dev/null
+++ b/api/BUILD
@@ -0,0 +1,179 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# Darwinn API headers
+load(
+ "@flatbuffers//:build_defs.bzl",
+ "flatbuffer_cc_library",
+)
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+cc_library(
+ name = "chip",
+ hdrs = ["chip.h"],
+)
+
+cc_library(
+ name = "tensor_util",
+ srcs = ["tensor_util.cc"],
+ hdrs = ["tensor_util.h"],
+ deps = [
+ "//executable:executable_fbs",
+ "//port",
+ "//port:string_util",
+ ],
+)
+
+cc_library(
+ name = "layer_information",
+ srcs = ["layer_information.cc"],
+ hdrs = ["layer_information.h"],
+ deps = [
+ ":buffer",
+ ":tensor_util",
+ "//executable:executable_fbs",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "request",
+ hdrs = ["request.h"],
+ deps = [
+ ":buffer",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "driver",
+ hdrs = ["driver.h"],
+ deps = [
+ ":buffer",
+ ":package_reference",
+ ":request",
+ ":timing",
+ "//api:telemeter_interface",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "driver_options_helper",
+ srcs = ["driver_options_helper.cc"],
+ hdrs = ["driver_options_helper.h"],
+ deps = [
+ ":driver",
+ ":driver_options_fbs",
+ ],
+)
+
+cc_library(
+ name = "allocated_buffer",
+ srcs = ["allocated_buffer.cc"],
+ hdrs = ["allocated_buffer.h"],
+ deps = ["//port"],
+)
+
+cc_library(
+ name = "dram_buffer",
+ hdrs = ["dram_buffer.h"],
+ deps = ["//port"],
+)
+
+cc_library(
+ name = "buffer",
+ srcs = ["buffer.cc"],
+ hdrs = ["buffer.h"],
+ deps = [
+ ":allocated_buffer",
+ ":dram_buffer",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "driver_factory",
+ srcs = ["driver_factory.cc"],
+ hdrs = ["driver_factory.h"],
+ deps = [
+ ":chip",
+ ":driver",
+ ":driver_options_fbs",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "package_reference",
+ hdrs = ["package_reference.h"],
+ deps = [
+ ":execution_context_interface",
+ ":layer_information",
+ "//executable:executable_fbs",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "runtime_version",
+ hdrs = ["runtime_version.h"],
+)
+
+flatbuffer_cc_library(
+ name = "driver_options_fbs",
+ srcs = ["driver_options.fbs"],
+ flatc_args = [""],
+)
+
+cc_library(
+ name = "timing",
+ hdrs = ["timing.h"],
+ deps = [
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "watchdog",
+ srcs = ["watchdog.cc"],
+ hdrs = ["watchdog.h"],
+ deps = [
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:timer",
+ ],
+)
+
+cc_library(
+ name = "telemeter_interface",
+ hdrs = [
+ "telemeter_interface.h",
+ ],
+ deps = [
+ ":execution_context_interface",
+ ],
+)
+
+cc_library(
+ name = "execution_context_interface",
+ hdrs = [
+ "execution_context_interface.h",
+ ],
+)
diff --git a/api/allocated_buffer.cc b/api/allocated_buffer.cc
new file mode 100644
index 0000000..4a00d31
--- /dev/null
+++ b/api/allocated_buffer.cc
@@ -0,0 +1,33 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/allocated_buffer.h"
+
+#include "port/logging.h"
+
+namespace platforms {
+namespace darwinn {
+
+AllocatedBuffer::AllocatedBuffer(unsigned char* ptr, size_t size_bytes,
+ FreeCallback free_callback)
+ : ptr_(ptr),
+ size_bytes_(size_bytes),
+ free_callback_(std::move(free_callback)) {
+ CHECK(ptr != nullptr);
+}
+
+AllocatedBuffer::~AllocatedBuffer() { free_callback_(ptr_); }
+
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/allocated_buffer.h b/api/allocated_buffer.h
new file mode 100644
index 0000000..97740f0
--- /dev/null
+++ b/api/allocated_buffer.h
@@ -0,0 +1,63 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_ALLOCATED_BUFFER_H_
+#define DARWINN_API_ALLOCATED_BUFFER_H_
+
+#include
+
+namespace platforms {
+namespace darwinn {
+
+// A type for buffer that holds (owns) allocated host memory. This class takes
+// ownership of the buffer pointers passed into it, freeing them using the given
+// Free function when destroyed.
+class AllocatedBuffer {
+ public:
+ // A type for the callback executed to free the buffer.
+ using FreeCallback = std::function;
+
+ AllocatedBuffer(unsigned char* ptr, size_t size_bytes,
+ FreeCallback free_callback);
+
+ ~AllocatedBuffer();
+
+ // Not copyable or movable
+ AllocatedBuffer(const AllocatedBuffer&) = delete;
+ AllocatedBuffer& operator=(const AllocatedBuffer&) = delete;
+
+ // Returns const buffer pointer.
+ const unsigned char* ptr() const { return ptr_; }
+
+ // Returns buffer pointer.
+ unsigned char* ptr() { return ptr_; }
+
+ // Size of this buffer in bytes.
+ size_t size_bytes() const { return size_bytes_; }
+
+ private:
+ // Points to allocated buffer.
+ unsigned char* ptr_;
+
+ // Size of the buffer.
+ size_t size_bytes_;
+
+ // Callback executed to free the buffer.
+ FreeCallback free_callback_;
+};
+
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_ALLOCATED_BUFFER_H_
diff --git a/api/buffer.cc b/api/buffer.cc
new file mode 100644
index 0000000..0e9c01f
--- /dev/null
+++ b/api/buffer.cc
@@ -0,0 +1,173 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/buffer.h"
+
+#include
+
+#include "api/allocated_buffer.h"
+#include "port/errors.h"
+#include "port/logging.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+
+Buffer::Buffer(unsigned char* buffer, size_t size_bytes)
+ : type_(Type::kWrapped), size_bytes_(size_bytes), ptr_(buffer) {}
+
+Buffer::Buffer(const unsigned char* buffer, size_t size_bytes)
+ : Buffer(const_cast(buffer), size_bytes) {}
+
+Buffer::Buffer(void* buffer, size_t size_bytes)
+ : Buffer(reinterpret_cast(buffer), size_bytes) {}
+
+Buffer::Buffer(const void* buffer, size_t size_bytes)
+ : Buffer(const_cast(buffer), size_bytes) {}
+
+Buffer::Buffer(int fd, size_t size_bytes, bool on_device_dram)
+ : type_(on_device_dram ? Type::kDramWrapped : Type::kFileDescriptor),
+ size_bytes_(size_bytes),
+ file_descriptor_(fd) {}
+
+Buffer::Buffer(std::shared_ptr allocated_buffer)
+ : type_(Type::kAllocated),
+ size_bytes_(allocated_buffer->size_bytes()),
+ ptr_(allocated_buffer->ptr()),
+ allocated_buffer_(std::move(allocated_buffer)) {}
+
+Buffer::Buffer(std::shared_ptr dram_buffer)
+ : type_(Type::kDram),
+ size_bytes_(dram_buffer->size_bytes()),
+ file_descriptor_(dram_buffer->fd()),
+ dram_buffer_(std::move(dram_buffer)) {}
+
+bool Buffer::operator==(const Buffer& rhs) const {
+ return type_ == rhs.type_ && size_bytes_ == rhs.size_bytes_ &&
+ ptr_ == rhs.ptr_ && allocated_buffer_ == rhs.allocated_buffer_;
+}
+
+bool Buffer::operator!=(const Buffer& rhs) const { return !(*this == rhs); }
+
+Buffer::Buffer(Buffer&& other)
+ : type_(other.type_),
+ size_bytes_(other.size_bytes_),
+ ptr_(other.ptr_),
+ allocated_buffer_(std::move(other.allocated_buffer_)),
+ file_descriptor_(other.file_descriptor_),
+ dram_buffer_(std::move(other.dram_buffer_)) {
+ // Explicitly clear out other.
+ other.type_ = Type::kInvalid;
+ other.ptr_ = 0;
+ other.size_bytes_ = 0;
+ other.file_descriptor_ = -1;
+ // other.allocated_buffer handled in move above.
+}
+
+Buffer& Buffer::operator=(Buffer&& other) {
+ if (this != &other) {
+ type_ = other.type_;
+ size_bytes_ = other.size_bytes_;
+ ptr_ = other.ptr_;
+ file_descriptor_ = other.file_descriptor_;
+ allocated_buffer_ = std::move(other.allocated_buffer_);
+ dram_buffer_ = std::move(other.dram_buffer_);
+
+ // Explicitly clear out other.
+ other.type_ = Type::kInvalid;
+ other.ptr_ = 0;
+ other.file_descriptor_ = 0;
+ other.size_bytes_ = 0;
+ // other.allocated_buffer handled in move above.
+ }
+ return *this;
+}
+
+Buffer Buffer::Slice(size_t offset, size_t length) const {
+ CHECK_LE(offset + length, size_bytes_);
+ CHECK(!FileDescriptorBacked() || offset == 0);
+
+ Buffer ret = *this;
+ ret.ptr_ += offset;
+ ret.size_bytes_ = length;
+ return ret;
+}
+
+const unsigned char* Buffer::ptr() const {
+ // FD and DRAM type Buffers need to be mapped before use.
+ if (type_ == Type::kFileDescriptor ||
+ type_ == Type::kDram ||
+ type_ == Type::kDramWrapped) {
+ LOG(FATAL) << "Called ptr() on buffer type " << type_;
+ }
+
+ return ptr_;
+}
+
+unsigned char* Buffer::ptr() {
+ // FD and DRAM type Buffers need to be mapped before use.
+ if (type_ == Type::kFileDescriptor ||
+ type_ == Type::kDram ||
+ type_ == Type::kDramWrapped) {
+ LOG(FATAL) << "Called ptr() on buffer type " << type_;
+ }
+
+ return ptr_;
+}
+
+int Buffer::fd() const {
+ // Only valid with Type == kFileDescriptor, kDram or kDramWrapped
+ if (type_ != Type::kFileDescriptor &&
+ type_ != Type::kDram &&
+ type_ != Type::kDramWrapped) {
+ LOG(FATAL) << "Called fd() on buffer type " << type_;
+ }
+
+ return file_descriptor_;
+}
+
+util::StatusOr> Buffer::GetDramBuffer() {
+ if (type_ != Type::kDram) {
+ return util::FailedPreconditionError(
+ StringPrintf("Called GetDramBuffer on a buffer of type %d.", type_));
+ }
+ return dram_buffer_;
+}
+
+std::string Buffer::ToString() const {
+ if (FileDescriptorBacked()) {
+ return StringPrintf("Buffer(fd=%d)", file_descriptor_);
+ } else {
+ return StringPrintf("Buffer(ptr=%p)", ptr_);
+ }
+}
+
+std::ostream& operator<<(std::ostream& stream, const Buffer::Type& type) {
+ switch (type) {
+ case Buffer::Type::kInvalid:
+ return (stream << "kInvalid");
+ case Buffer::Type::kWrapped:
+ return (stream << "kWrapped");
+ case Buffer::Type::kAllocated:
+ return (stream << "kAllocated");
+ case Buffer::Type::kFileDescriptor:
+ return (stream << "kFileDescriptor");
+ case Buffer::Type::kDram:
+ return (stream << "kDram");
+ case Buffer::Type::kDramWrapped:
+ return (stream << "kDramWrapped");
+ }
+}
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/buffer.h b/api/buffer.h
new file mode 100644
index 0000000..2a9ee29
--- /dev/null
+++ b/api/buffer.h
@@ -0,0 +1,183 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_BUFFER_H_
+#define DARWINN_API_BUFFER_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#include "api/allocated_buffer.h"
+#include "api/dram_buffer.h"
+#include "port/statusor.h"
+
+namespace platforms {
+namespace darwinn {
+
+// Abstracts a buffer. Movable and copyable.
+// TODO: Consider adding two different variants of this class
+// for indicating Const and Mutable variants (like ArraySlice). For now,
+// const Buffer, requires that contents of underlying buffer is const.
+class Buffer {
+ public:
+ // Convenience structure for keeping track of named array of Buffers.
+ using NamedMap = std::unordered_map>;
+
+ // Default constructor. Defaults to an invalid non-existent buffer.
+ Buffer() = default;
+
+ // Constructors for wrapping an existing host buffer.
+ Buffer(void* buffer, size_t size_bytes);
+ Buffer(const void* buffer, size_t size_bytes);
+
+ // Constructors for wrapping an existing host buffer, and optionally hints
+ // the runtime to cache it in on-chip memory outside the DarwiNN core.
+ Buffer(unsigned char* buffer, size_t size_bytes);
+ Buffer(const unsigned char* buffer, size_t size_bytes);
+
+ // Constructors for wrapping an allocated buffer.
+ explicit Buffer(std::shared_ptr allocated_buffer);
+
+ // Constructor for wrapping a file descriptor for existing memory.
+ // on_device_dram: =true, the allocated memory is on DRAM,
+ // =false, the allocated memory is mmap-able shared memory.
+ Buffer(int fd, size_t size_bytes, bool on_device_dram = false);
+
+ // Constructors for wrapping an on-chip DRAM buffer.
+ explicit Buffer(std::shared_ptr dram_buffer);
+
+ // This type is copyable, with default implementations.
+ Buffer(const Buffer&) = default;
+ Buffer& operator=(const Buffer&) = default;
+
+ // This type is movable.
+ Buffer(Buffer&& other);
+ Buffer& operator=(Buffer&& other);
+
+ // Destructors.
+ ~Buffer() = default;
+
+ // Get a slice of this buffer. Note that this does not resize the underlying
+ // storage, and the original buffer is still valid. The slice will be of the
+ // same type as this buffer. In particular, that means there will be an
+ // additional shared_ptr reference to the backing memory for allocated
+ // buffers.
+ // TODO: File descriptor-based buffers cannot be sliced unless
+ // the offset is 0.
+ Buffer Slice(size_t offset, size_t length) const;
+
+ // Size of this buffer in bytes.
+ size_t size_bytes() const { return size_bytes_; }
+
+ // Returns true if buffer is valid.
+ bool IsValid() const { return type_ != Type::kInvalid; }
+
+ // Returns buffer pointer.
+ const unsigned char* ptr() const;
+
+ // Returns buffer pointer.
+ unsigned char* ptr();
+
+ // Returns true if the buffer is backed by some host memory, may or may not be
+ // owned by this Buffer.
+ bool IsPtrType() const {
+ return type_ == Type::kWrapped || type_ == Type::kAllocated;
+ }
+
+ // Returns file descriptor.
+ int fd() const;
+
+ // Returns true if the buffer is backed by a file descriptor.
+ bool FileDescriptorBacked() const {
+ return type_ == Type::kFileDescriptor ||
+ type_ == Type::kDram ||
+ type_ == Type::kDramWrapped;
+ }
+
+ // Returns true if this buffer is backed by a DramBuffer.
+ bool IsDramType() const {
+ return type_ == Type::kDram || type_ == Type::kDramWrapped;
+ }
+
+ // Returns true if the buffer is managed by the runtime,
+ // i.e., the buffer does not wrap existing memory allocated
+ // outside the runtime.
+ bool IsManagedType() const {
+ return type_ == Type::kAllocated || type_ == Type::kDram;
+ }
+
+ // Returns the underlying DRAM Buffer if this buffer is wrapping one managed
+ // by the runtime.
+ util::StatusOr> GetDramBuffer();
+
+ // Returns a string representation of the buffer for logging/debugging.
+ std::string ToString() const;
+
+ // Equality operators.
+ bool operator==(const Buffer& rhs) const;
+ bool operator!=(const Buffer& rhs) const;
+
+ private:
+ // Type for the buffer.
+ enum class Type {
+ // Invalid.
+ kInvalid = 0,
+
+ // Wraps an existing host process addressable buffer.
+ kWrapped = 1,
+
+ // Wraps an allocated host process addressable buffer.
+ kAllocated = 2,
+
+ // Wraps an mmap-able file descriptor, possibly from ION.
+ kFileDescriptor = 3,
+
+ // Wraps a buffer allocated from on-chip DRAM and managed by the runtime.
+ kDram = 4,
+
+ // Wraps an existing, i.e., externally allocated, on-chip DRAM
+ // allocated buffer not managed by the runtime.
+ kDramWrapped = 5,
+ };
+
+ // To allow Buffer::Type being tested in CHECK() et al.
+ friend std::ostream& operator<< (std::ostream& stream, const Type& type);
+
+ // Type for the buffer.
+ Type type_{Type::kInvalid};
+
+ // Size of the buffer.
+ size_t size_bytes_{0};
+
+ // Points to host buffer. Valid when type is kWrapped / kAllocated.
+ unsigned char* ptr_{nullptr};
+
+ // Points to allocated buffer. Valid when type is kAllocated.
+ std::shared_ptr allocated_buffer_;
+
+ // File descriptor. Valid when type is kFileDescriptor, kDram or kDramWrapped.
+ // Reset to -1 when moved.
+ int file_descriptor_{-1};
+
+ // Points to the DramBuffer. Valid when type is kDram.
+ std::shared_ptr dram_buffer_;
+};
+
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_BUFFER_H_
diff --git a/api/chip.h b/api/chip.h
new file mode 100644
index 0000000..7cfdfa8
--- /dev/null
+++ b/api/chip.h
@@ -0,0 +1,63 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_CHIP_H_
+#define DARWINN_API_CHIP_H_
+
+#include
+
+#include
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Target chip for runtime stack.
+enum class Chip {
+ kBeagle,
+ kUnknown,
+};
+
+static const struct {
+ Chip chip;
+ const char* names[2];
+} kChipNames[] = {
+ {Chip::kBeagle, {"beagle", "beagle_fpga"}},
+};
+
+// Returns correct Chip for given |chip_name|.
+static inline Chip GetChipByName(const char* chip_name) {
+ for (auto& pair : kChipNames)
+ for (auto name : pair.names)
+ if (name != nullptr && strcmp(chip_name, name) == 0) return pair.chip;
+ return Chip::kUnknown;
+}
+
+// Returns correct Chip for given |chip_name|.
+static inline Chip GetChipByName(const std::string& chip_name) {
+ return GetChipByName(chip_name.c_str());
+}
+
+// Returns the name of the given |chip|.
+static inline std::string GetChipName(Chip chip) {
+ for (auto& pair : kChipNames)
+ if (pair.chip == chip) return pair.names[0];
+ return "unknown";
+}
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_CHIP_H_
diff --git a/api/dram_buffer.h b/api/dram_buffer.h
new file mode 100644
index 0000000..54f0ea3
--- /dev/null
+++ b/api/dram_buffer.h
@@ -0,0 +1,45 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_DRAM_BUFFER_H_
+#define DARWINN_API_DRAM_BUFFER_H_
+
+#include "port/status.h"
+
+namespace platforms {
+namespace darwinn {
+
+// Represents a buffer backed by on-chip DRAM.
+class DramBuffer {
+ public:
+ DramBuffer() = default;
+ virtual ~DramBuffer() = default;
+
+ // Returns the file descriptor to the DRAM buffer.
+ virtual int fd() const = 0;
+
+ // Returns size of the buffer in bytes.
+ virtual size_t size_bytes() const = 0;
+
+ // Copies size_bytes() bytes of data from source to the buffer.
+ virtual util::Status ReadFrom(void* source) = 0;
+
+ // Copies size_bytes() bytes ofr data from buffer to the destination address.
+ virtual util::Status WriteTo(void* destination) = 0;
+};
+
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_DRAM_BUFFER_H_
diff --git a/api/driver.h b/api/driver.h
new file mode 100644
index 0000000..58aa671
--- /dev/null
+++ b/api/driver.h
@@ -0,0 +1,241 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_DRIVER_H_
+#define DARWINN_API_DRIVER_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#include "api/buffer.h"
+#include "api/package_reference.h"
+#include "api/request.h"
+#include "api/telemeter_interface.h"
+#include "api/timing.h"
+#include "port/statusor.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// DarwiNN driver. Thread-safe, but not all functions can be called in
+// callback context.
+//
+// Typical usage:
+// Driver driver = driverFactory.get();
+//
+// m1 = driver.RegisterExecutable()
+// m2 = driver.RegisterExecutable()
+//
+// driver.Open();
+// r1 = driver.CreateRequest(m1, done_callback);
+// r2 = driver.CreateRequest(m1, done_callback);
+// driver.Submit(r1);
+// driver.Submit(r2).
+// driver.Close();
+//...
+// After some time, application can try to re-open the driver again.
+// driver.Open();
+// ...
+// driver.Close();
+class Driver {
+ public:
+ // Callback for thermal warnings. Set with SetThermalWarningCallback().
+ using ThermalWarningCallback = std::function;
+
+ // Callback for fatal, unrecoverable failure. Set with
+ // SetFatalErrorCallback().
+ using FatalErrorCallback = std::function;
+
+ // Driver options. Opaque pointer to an options::Options FB object.
+ using Options = std::vector;
+
+ // Current driver option version. Should match the version in
+ // driver_options.fbs.
+ static constexpr int kOptionsVersion = 1;
+
+ // Specifies how driver should be closed.
+ enum class ClosingMode {
+ // Lets the active requests (the ones that have started DMA) finish and
+ // cancels pending requests. This may take a few milliseconds.
+ kGraceful = 0,
+
+ // Cancels all active and pending requests. This is the fastest way we can
+ // close the driver without risk of crashing.
+ kAsap = 1,
+ };
+
+ // Specifies the way a model is preferred to be ran in terms of power/
+ // performance trade-off. This can mapped to equivalent settings in higher
+ // level APIs (e.g. PreferenceCode in NNAPI). Please note that the enum
+ // integer values may be different from those in NNAPI or other APIs. The
+ // values here are defined in the order of priority when there are multiple
+ // models requesting different preferences (e.g. sustained speed takes
+ // priority over low power). For more information, please see:
+ // http://go/noronha-execution-preference
+ enum class ExecutionPreference {
+ // Run at the absolute maximum performance.
+ kSingleFastAnswer = 0,
+
+ // Ideal for cases in which we are trying to optimize for power.
+ kLowPower = 1,
+
+ // Run at the maximum performance but in a way that does not require power /
+ // thermal throttling in the long run.
+ kSustainedSpeed = 2,
+ };
+
+ // Encapsulates different TPU (and related components) operational settings
+ // that can impact runtime behavior.
+ struct OperationalSettings {
+ // TPU clock-rate in hertz.
+ int64 tpu_frequency_hz;
+
+ // Data transfer bandwidth between host DRAM and TPU in bytes per second.
+ int64 host_to_tpu_bps;
+ };
+
+ Driver() = default;
+ virtual ~Driver() = default;
+
+ // This class is neither copyable nor movable.
+ Driver(const Driver&) = delete;
+ Driver& operator=(const Driver&) = delete;
+
+ // Returns true if the driver is open state.
+ virtual bool IsOpen() const = 0;
+
+ // Returns true if underlying hardware is in an error state.
+ virtual bool IsError() const = 0;
+
+ // Registers a file containing pre-compiled DarwiNN executable and returns a
+ // reference to the registered executable. The reference can be used for
+ // constructing requests later on.
+ virtual util::StatusOr RegisterExecutableFile(
+ const std::string& executable_filename) = 0;
+
+ // Registers a string with serialized contents of a pre-compiled DarwiNN
+ // executable and returns a reference to the registered executable. The
+ // reference can be used for constructing requests later on.
+ virtual util::StatusOr RegisterExecutableSerialized(
+ const std::string& executable_content) = 0;
+ virtual util::StatusOr RegisterExecutableSerialized(
+ const char* executable_content, size_t length) = 0;
+
+ // Unregisters a previously registered model.
+ virtual util::Status UnregisterExecutable(
+ const PackageReference* executable_ref) = 0;
+
+ // Opens and initializes the underlying hardware. If debug_mode is true,
+ // the hardware is setup for use with a debugger. If context_lost is true
+ // driver assumes all data on chip (e.g. on DRAM) a from previous open has
+ // been lost.
+ virtual util::Status Open(bool debug_mode = false,
+ bool context_lost = false) = 0;
+
+ // Creates a request object initialized with the given ExecutableReference.
+ virtual util::StatusOr> CreateRequest(
+ const PackageReference* executable_ref) = 0;
+
+ // Submits a request for asynchronous execution. On success, done_callback
+ // will eventually be executed with the request status. The caller is expected
+ // to exit the done_callback as soon as possible. It is acceptable to only
+ // call #Submit() in the context of this callback.
+ virtual util::Status Submit(std::shared_ptr request,
+ Request::Done done_callback) = 0;
+
+ // Executes a request synchronously. Calling thread will block until execution
+ // is complete.
+ virtual util::Status Execute(std::shared_ptr request) = 0;
+
+ // Executes a series of requests synchronously in the given order. Calling
+ // thread will block until execution is complete.
+ virtual util::Status Execute(
+ const std::vector>& request) = 0;
+
+ // Attempts to cancel a request. This is best effort cancellation. As in,
+ // requests already submitted to the hardware will be allowed to complete.
+ // Other requests will be cancelled, and will invoke done_callback with
+ // cancelled error.
+ virtual util::Status Cancel(std::shared_ptr request) = 0;
+
+ // Best effort cancellation of all submitted requests.
+ virtual util::Status CancelAllRequests() = 0;
+
+ // Closes and shutdowns underlying hardware possibly, switching it off.
+ // Pending requests are cancelled or completed and callbacks issued. Once
+ // closed, requests can no longer be submitted.
+ virtual util::Status Close(ClosingMode mode) = 0;
+
+ // Buffer allocation alignment and granularity.
+ // Buffers allocated with this alignment may avoid additional copies within
+ // the driver.
+ virtual uint64_t allocation_alignment_bytes() const = 0;
+
+ // Allocates size_bytes bytes and returns a Buffer for application use. The
+ // allocated memory is tied to the lifecycle of the Buffer object which in
+ // turn is tied to the life cycle of the driver instance.
+ virtual Buffer MakeBuffer(size_t size_bytes) const = 0;
+
+ // Sets the callback for fatal, unrecoverable failure. When a fatal
+ // error is raised, the driver is pushed into an error state. All new
+ // submitted requests will fail. Application can generate a bug report and
+ // should close the driver, at which point all pending requests will fail and
+ // their callbacks executed.
+ virtual void SetFatalErrorCallback(FatalErrorCallback callback) = 0;
+
+ // Sets the callback for thermal warnings. Application may be required to
+ // to reduce performance level and/or throttle new requests.
+ virtual void SetThermalWarningCallback(ThermalWarningCallback callback) = 0;
+
+ // Enters/leaves real-time mode, if applicable. This is best effort as it
+ // relies on user provided timing information, and the fact that current
+ // generations of DarwiNN is not preemptable.
+ virtual util::Status SetRealtimeMode(bool on) = 0;
+
+ // Sets expected arrival rates and max execution time (in milliseconds) for an
+ // package. Only used in real-time mode.
+ virtual util::Status SetExecutableTiming(
+ const api::PackageReference* executable, const api::Timing& timing) = 0;
+
+ // Sets the provided execution preference for the provided package. Execution
+ // preferences are hints to the driver for how to adjust its settings in
+ // accordance with power/perf trade-off. Driver will try to keep all requested
+ // preferences satisfied erring on the side of performance.
+ virtual util::Status SetExecutionPreference(
+ const api::PackageReference* package, ExecutionPreference preference) = 0;
+
+ // Sets the perferred telemeter interface. This interface is platform
+ // specific. By default, telemetry operations are NOPs. The
+ // telemeter_interface is not owned by api::Driver, so the telemeter's
+ // lifetime must remain valid as long as the driver object is valid.
+ virtual void SetTelemeterInterface(
+ api::TelemeterInterface* telemeter_interface) = 0;
+
+ // Updates the operational settings in the driver. This method is to be called
+ // when any of these settings change (e.g. due to thermal throttling).
+ virtual void UpdateOperationalSettings(
+ const OperationalSettings& settings) = 0;
+
+ // TODO: Add function for dumping bugreport.
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_DRIVER_H_
diff --git a/api/driver_factory.cc b/api/driver_factory.cc
new file mode 100644
index 0000000..9a037f1
--- /dev/null
+++ b/api/driver_factory.cc
@@ -0,0 +1,90 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/driver_factory.h"
+
+#include "port/unreachable.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+namespace {
+
+Driver* NewDriver(const Device& device, const Driver::Options& options) {
+ // Build Driver.
+ auto factory = DriverFactory::GetOrCreate();
+ auto backing_driver = factory->CreateDriver(device, options).ValueOrDie();
+ return backing_driver.release();
+}
+
+} // namespace
+
+Driver* DriverFactory::CreateDriverAsSingleton(const Device& device,
+ const Driver::Options& options) {
+ static api::Driver* driver = NewDriver(device, options);
+ return driver;
+}
+
+Device::Type GetTypeByName(const std::string& device_type) {
+ if (device_type == "PCI" || device_type == "pci") {
+ return Device::Type::PCI;
+ } else if (device_type == "USB" || device_type == "usb") {
+ return Device::Type::USB;
+ } else if (device_type == "PLATFORM" || device_type == "platform") {
+ return Device::Type::PLATFORM;
+ } else if (device_type == "REFERENCE" || device_type == "reference") {
+ return Device::Type::REFERENCE;
+ } else if (device_type == "SIMULATOR" || device_type == "simulator") {
+ return Device::Type::SIMULATOR;
+ } else if (device_type == "REMOTE_PCI" || device_type == "remote_pci") {
+ return Device::Type::REMOTE_PCI;
+ } else if (device_type == "REMOTE_USB" || device_type == "remote_usb") {
+ return Device::Type::REMOTE_USB;
+ } else if (device_type == "REMOTE_PLATFORM" ||
+ device_type == "remote_platform") {
+ return Device::Type::REMOTE_PLATFORM;
+ } else {
+ LOG(FATAL) << "Unknown device type: " << device_type
+ << R"error(, which should be either "PCI", "USB", "PLATFORM", "REFERENCE", "REMOTE_PCI", "REMOTE_USB", "REMOTE_PLATFORM", or "SIMULATOR")error";
+ unreachable(); // NOLINT
+ }
+}
+
+std::string GetTypeName(Device::Type device_type) {
+ switch (device_type) {
+ case Device::Type::PCI:
+ return "pci";
+ case Device::Type::USB:
+ return "usb";
+ case Device::Type::PLATFORM:
+ return "platform";
+ case Device::Type::REMOTE_PCI:
+ return "remote_pci";
+ case Device::Type::REMOTE_USB:
+ return "remote_usb";
+ case Device::Type::REMOTE_PLATFORM:
+ return "remote_platform";
+ case Device::Type::REFERENCE:
+ return "reference";
+ case Device::Type::SIMULATOR:
+ return "simulator";
+ default:
+ return "unknown";
+ }
+}
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/driver_factory.h b/api/driver_factory.h
new file mode 100644
index 0000000..19c4213
--- /dev/null
+++ b/api/driver_factory.h
@@ -0,0 +1,131 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_DRIVER_FACTORY_H_
+#define DARWINN_API_DRIVER_FACTORY_H_
+
+#include
+#include
+#include
+#include
+
+#include "api/chip.h"
+#include "api/driver.h"
+#include "api/driver_options_generated.h"
+#include "port/integral_types.h"
+#include "port/statusor.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// A type for uniquely identifying a DarwiNN device.
+struct Device {
+ // Device type.
+ enum class Type {
+ // PCI device.
+ // Path format: "/dev/"
+ // Example: /dev/apex_0
+ PCI = 0,
+
+ // USB device.
+ // Path format: "/sys/bus/usb/devices/-"
+ // Example: /sys/bus/usb/devices/3-5.1.2.1.2
+ USB = 1,
+
+ // Platform (integrated) device.
+ // Path format: "/dev/"
+ PLATFORM = 2,
+
+ // Remote PCI device (for testing.)
+ // Path format: ":"
+ REMOTE_PCI = 10,
+
+ // Remote USB device (for testing.)
+ // Path format: ":"
+ REMOTE_USB = 11,
+
+ // Remote Platform device (for testing.)
+ // Path format: ":"
+ REMOTE_PLATFORM = 12,
+
+ // Reference driver (for testing.)
+ REFERENCE = 30,
+
+ // Simulator driver (for testing.) Path is ignored,
+ // Chip determines which simulator is instantiated.
+ SIMULATOR = 31,
+ };
+
+ // TODO: Replace map of strings with something better.
+ using Attributes = std::unordered_map;
+
+ // Chip
+ Chip chip;
+
+ // Device type.
+ Type type;
+
+ // String that uniquely identifies the device.
+ // Set this to DriverFactory::kDefaultDevicePath for default device picked by
+ // the factory.
+ std::string path;
+
+ // Device attributes discovered through enumeration.
+ // The exact set of possible key-value pairs is provider-specific.
+ Attributes attributes;
+};
+
+// Returns correct Device::Type for given |device_type|.
+Device::Type GetTypeByName(const std::string& device_type);
+
+// Returns the name of the given |device_type|.
+std::string GetTypeName(Device::Type device_type);
+
+// Enumerates devices and creates drivers for those devices.
+class DriverFactory {
+ public:
+ static constexpr const char* kDefaultDevicePath = "default";
+
+ // Creates a singleton driver.
+ static Driver* CreateDriverAsSingleton(const Device& device,
+ const Driver::Options& options);
+
+ // Creates or returns the singleton instance of the driver factory.
+ static DriverFactory* GetOrCreate();
+
+ virtual ~DriverFactory() = default;
+
+ // Enumerates all available devices.
+ virtual std::vector Enumerate() = 0;
+
+ // Creates a driver instance that interfaces to the specified device.
+ virtual util::StatusOr> CreateDriver(
+ const Device& device) = 0;
+
+ // Creates a driver instance that interfaces to the specified device with
+ // custom options.
+ virtual util::StatusOr> CreateDriver(
+ const Device& device, const Driver::Options& options) = 0;
+
+ protected:
+ // Constructor.
+ DriverFactory() = default;
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_DRIVER_FACTORY_H_
diff --git a/api/driver_options.fbs b/api/driver_options.fbs
new file mode 100644
index 0000000..c095a4d
--- /dev/null
+++ b/api/driver_options.fbs
@@ -0,0 +1,91 @@
+// IDL file for DarwiNN Driver Options.
+
+namespace platforms.darwinn.api;
+
+enum PerformanceExpectation : int {
+ // Clock-rate setting affecting performance.
+ Low,
+ Medium,
+ High,
+ Max
+}
+
+// USB-specific options
+table DriverUsbOptions {
+ // Path to the DFU firmware. Empty string implies default values(s).
+ dfu_firmware:string;
+
+ // If true, always performs DFU. Otherwise, only performs DFU if
+ // device is in DFU mode.
+ always_dfu:bool = true;
+
+ // If true, driver would fail to open if the current connection is low,
+ // full, or high speed. If the connection speed is not observable from
+ // underlying provider, this option is ignored.
+ has_fail_if_slower_than_superspeed: bool = false;
+ fail_if_slower_than_superspeed: bool = false;
+
+ // If true, bulk-in data is transmitted in largest chunks possible.
+ // By default, driver uses 1KB chunk size for USB3 and 256B for USB2.
+ // This is part of workaround for b/73181174
+ has_force_largest_bulk_in_chunk_size: bool = false;
+ force_largest_bulk_in_chunk_size: bool = false;
+
+ // If true, the fence between bulk-out and bulk-in would be lifted, allowing
+ // bulk-in to be issued before all bulk-out are finished. This feature could
+ // improve performance significantly on Android platform.
+ has_enable_overlapping_bulk_in_and_out: bool = false;
+ enable_overlapping_bulk_in_and_out: bool = true;
+
+ // If true, multiple bulk-in requests would be issued instead of just one at
+ // any moment. enable_overlapping_bulk_in_and_out must also be true for
+ // this feature to be enabled.
+ has_enable_queued_bulk_in_requests: bool = false;
+ enable_queued_bulk_in_requests: bool = true;
+
+ // Max number of buffers to queue when enable_queued_bulk_in_requests
+ // is true.
+ has_bulk_in_queue_capacity: bool = false;
+ bulk_in_queue_capacity: int = 32;
+}
+
+table DriverOptions {
+ // Forwarded compatibility is possible only within the same version number
+ // by following Flatbuffer schema evolution guidelines.
+ // https://google.github.io/flatbuffers/md__schemas.html
+ version:int = 1;
+ usb:DriverUsbOptions;
+
+ // Debug message verbosity inside the driver.
+ verbosity:int = 0;
+ performance_expectation:PerformanceExpectation = High;
+
+ // The public key used for verifying executable packages in PEM format.
+ public_key:string;
+
+ // The amount of time (in nanoseconds) that runtime waits to hear back from
+ // TPU (when it expects to) until it decides TPU is stuck and we need to
+ // perform a reset. A TPU reset results in all pending requests to be
+ // cancelled. 0 means Unlimited.
+ watchdog_timeout_ns:long = 0;
+
+ // Operating frequency. Used for computing initial max execution time for
+ // drivers supporting real-time mode.
+ // -1 means no operating frequency supplied (for drivers without real-time
+ // mode support).
+ tpu_frequency_hz:int64 = -1;
+
+ // The maximum amount of work (in terms of nanoseconds spent on TPU) that can
+ // be scheduled in the DMA scheduler at any given point in time. -1 means no
+ // maximum and all tasks get scheduled immediately. Exceptions are:
+ // 1. P0 requests.
+ // 2. When a single inference takes longer than this time and there is no
+ // other task scheduled (avoid starvation).
+ max_scheduled_work_ns:int64 = -1;
+
+ // Data transfer bandwidth between host and TPU in bytes per second. -1 means
+ // assume infinite bandwidth.
+ host_to_tpu_bps:int64 = -1;
+}
+
+root_type DriverOptions;
diff --git a/api/driver_options_helper.cc b/api/driver_options_helper.cc
new file mode 100644
index 0000000..6330634
--- /dev/null
+++ b/api/driver_options_helper.cc
@@ -0,0 +1,67 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/driver_options_helper.h"
+
+#include "api/driver_options_generated.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+constexpr int64 kOperatingFrequency = 1000000LL;
+constexpr int64 kHostTpuBps = 1000000000LL;
+
+// Returns driver options for default.
+Driver::Options DriverOptionsHelper::Defaults() {
+ flatbuffers::FlatBufferBuilder builder;
+ auto options_offset = api::CreateDriverOptions(
+ builder,
+ /*version=*/1,
+ /*usb=*/0,
+ /*verbosity=*/0,
+ /*performance_expectation=*/api::PerformanceExpectation_High,
+ /*public_key=*/builder.CreateString(""),
+ /*watchdog_timeout_ns=*/0,
+ /*tpu_frequency_hz=*/kOperatingFrequency,
+ /*max_scheduled_work_ns=*/-1,
+ /*host_to_tpu_bps=*/kHostTpuBps);
+ builder.Finish(options_offset);
+ return api::Driver::Options(builder.GetBufferPointer(),
+ builder.GetBufferPointer() + builder.GetSize());
+}
+
+// Returns driver options for maximum performance.
+Driver::Options DriverOptionsHelper::MaxPerformance() {
+ flatbuffers::FlatBufferBuilder builder;
+ auto options_offset = api::CreateDriverOptions(
+ builder,
+ /*version=*/1,
+ /*usb=*/0,
+ /*verbosity=*/0,
+ /*performance_expectation=*/api::PerformanceExpectation_Max,
+ /*public_key=*/builder.CreateString(""),
+ /*watchdog_timeout_ns=*/0,
+ /*tpu_frequency_hz=*/kOperatingFrequency,
+ /*max_scheduled_work_ns=*/-1,
+ /*host_to_tpu_bps=*/kHostTpuBps);
+ builder.Finish(options_offset);
+ return api::Driver::Options(builder.GetBufferPointer(),
+ builder.GetBufferPointer() + builder.GetSize());
+}
+
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/driver_options_helper.h b/api/driver_options_helper.h
new file mode 100644
index 0000000..11ad3b9
--- /dev/null
+++ b/api/driver_options_helper.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_DRIVER_OPTIONS_HELPER_H_
+#define DARWINN_API_DRIVER_OPTIONS_HELPER_H_
+
+#include "api/driver.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// A simpler wrapper around several static helper functions.
+class DriverOptionsHelper {
+ public:
+ // Returns driver options for default.
+ static Driver::Options Defaults();
+
+ // Returns driver options for maximum performance.
+ static Driver::Options MaxPerformance();
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_DRIVER_OPTIONS_HELPER_H_
diff --git a/api/execution_context_interface.h b/api/execution_context_interface.h
new file mode 100644
index 0000000..91298f3
--- /dev/null
+++ b/api/execution_context_interface.h
@@ -0,0 +1,35 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_EXECUTION_CONTEXT_INTERFACE_H_
+#define DARWINN_API_EXECUTION_CONTEXT_INTERFACE_H_
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// This class stores information related to on-device execution on the TPU. This
+// empty base interface may be inherited to store any kind of execution related
+// info. Info may include ML model information, process name, etc. This class is
+// NOT thread-safe.
+class ExecutionContextInterface {
+ public:
+ virtual ~ExecutionContextInterface() = default;
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_EXECUTION_CONTEXT_INTERFACE_H_
diff --git a/api/layer_information.cc b/api/layer_information.cc
new file mode 100644
index 0000000..f6d251c
--- /dev/null
+++ b/api/layer_information.cc
@@ -0,0 +1,457 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/layer_information.h"
+
+#include
+#include
+
+#include "api/buffer.h"
+#include "api/tensor_util.h"
+#include "executable/executable_generated.h"
+#include "port/errors.h"
+#include "port/logging.h"
+#include "port/status.h"
+#include "port/status_macros.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+namespace {
+
+// Performs sanity check for the output shape information. Returns error if
+// slice layout information is invalid.
+util::Status SanityCheckShapeInformation(const OutputShapeInfo& shape_info,
+ int data_type_size) {
+ for (int i = 0; i < shape_info.slice_layout()->size(); ++i) {
+ // Each slice shape is stored in its own slice layout. Make sure the layout
+ // is valid.
+ const auto& slice_layout = *shape_info.slice_layout()->Get(i);
+ if (!tensor_util::IsValidLayout(slice_layout)) {
+ return util::FailedPreconditionError(
+ StringPrintf("Invalid shape for slice %d: %s", i,
+ tensor_util::DumpLayout(slice_layout).c_str()));
+ }
+ const int slice_offset = shape_info.slice_offset()->Get(i);
+ if (slice_offset % data_type_size != 0) {
+ return util::FailedPreconditionError(StringPrintf(
+ "Slice offset [%d] is not aliged to data type size [%d].",
+ slice_offset, data_type_size));
+ }
+ }
+
+ return util::OkStatus();
+}
+
+// Copies elements in source shape to dest address. Destination layout is in
+// dest_shape.
+void CopyShape(const TensorShapeT& source_shape,
+ const TensorLayout& source_layout,
+ const unsigned char* source_address,
+ const TensorLayout& dest_layout, unsigned char* dest_address,
+ int bytes_per_element, int dimension) {
+ CHECK_LT(dimension, tensor_util::kNumDimensions);
+ CHECK_GE(dimension, 0);
+
+ // Source shape can be in non-contiguous memory space if there are z-padding
+ // elements.
+ if (tensor_util::IsShapeInContiguousLayout(source_layout, source_shape) &&
+ tensor_util::IsShapeInContiguousLayout(dest_layout, source_shape)) {
+ const int dest_offset =
+ tensor_util::GetFirstMemoryIndexForShape(dest_layout, source_shape) *
+ bytes_per_element;
+ const int source_offset =
+ tensor_util::GetFirstMemoryIndexForShape(source_layout, source_shape) *
+ bytes_per_element;
+
+ // Do mem copy for the shape.
+ memcpy(
+ dest_address + dest_offset, source_address + source_offset,
+ tensor_util::GetNumElementsInShape(source_shape) * bytes_per_element);
+ } else {
+ const auto range = source_shape.dimension.at(dimension);
+ for (int i = range.start(); i <= range.end(); ++i) {
+ auto slice = source_shape;
+ slice.dimension.at(dimension) = {i, i};
+ CopyShape(slice, source_layout, source_address, dest_layout, dest_address,
+ bytes_per_element, dimension + 1);
+ }
+ }
+}
+
+} // namespace
+
+LayerInformation::LayerInformation(const Layer* layer) : layer_(layer) {
+ CHECK(layer != nullptr);
+}
+
+int LayerInformation::DataTypeSize() const {
+ return TensorDataTypeSize(layer()->data_type());
+}
+
+bool LayerInformation::SignedDataType() const {
+ switch (layer()->data_type()) {
+ case DataType_SIGNED_FIXED_POINT8:
+ case DataType_SIGNED_FIXED_POINT16:
+ return true;
+
+ case DataType_FIXED_POINT8:
+ case DataType_FIXED_POINT16:
+ // TODO: DataType_SIGNED_FIXED_POINT32 (previously
+ // DataType_FIXED_POINT32) is a signed number, see b/135944737.
+ // However, the function returns false, which looks like a bug. Please
+ // confirm it.
+ case DataType_SIGNED_FIXED_POINT32:
+ case DataType_BFLOAT:
+ case DataType_HALF:
+ case DataType_SINGLE:
+ return false;
+ }
+}
+
+util::Status LayerInformation::TransformSignedDataType(Buffer buffer) const {
+ const auto data_type_size = DataTypeSize();
+ if (buffer.size_bytes() < ActualSizeBytes()) {
+ return util::InvalidArgumentError(StringPrintf(
+ "Provided buffer size (%zu) is less than actual size_bytes (%d).",
+ buffer.size_bytes(), ActualSizeBytes()));
+ }
+ auto buffer_pointer = buffer.ptr();
+ int buffer_index = 0;
+
+ for (int y = 0; y < y_dim(); ++y) {
+ for (int x = 0; x < x_dim(); ++x) {
+ for (int z = 0; z < z_dim(); ++z) {
+ // XORing with 128 on the last byte of each entry will flip the MSB of
+ // each entry. Please note that bytes are stored little endian.
+ int msb_index = buffer_index + data_type_size - 1;
+ buffer_pointer[msb_index] = buffer_pointer[msb_index] ^ 128;
+ buffer_index += data_type_size;
+ }
+ }
+ }
+
+ return util::OkStatus();
+}
+
+InputLayerInformation::InputLayerInformation(const Layer* layer)
+ : LayerInformation(layer) {}
+
+OutputLayerInformation::OutputLayerInformation(const Layer* layer)
+ : LayerInformation(layer),
+ output_layer_(layer->any_layer_as_OutputLayer()) {
+ CHECK(output_layer_ != nullptr);
+}
+
+OutputLayerInformation::YBufferIndex OutputLayerInformation::GetYBufferIndex(
+ int y) const {
+ const auto& layout = output_layer_->layout();
+ YBufferIndex output;
+ output.y_linearized_tile_id =
+ layout->y_coordinate_to_linear_tile_id_map()->Get(y);
+ output.local_y_coordinate = layout->y_coordinate_to_local_y_offset()->Get(y);
+ return output;
+}
+
+int OutputLayerInformation::GetBufferIndex(const YBufferIndex& y_buffer_index,
+ int x, int z) const {
+ const auto& layout = output_layer_->layout();
+ const int linear_tile_id =
+ y_buffer_index.y_linearized_tile_id +
+ layout->x_coordinate_to_linear_tile_id_map()->Get(x);
+ const int global_tile_byte_offset =
+ layout->linearized_tile_byte_offset()->Get(linear_tile_id);
+
+ const int local_x_byte_offset =
+ layout->x_coordinate_to_local_byte_offset()->Get(x);
+ const int local_y_byte_offset =
+ y_buffer_index.local_y_coordinate *
+ layout->x_coordinate_to_local_y_row_size()->Get(x);
+
+ return global_tile_byte_offset + local_y_byte_offset + local_x_byte_offset +
+ z;
+}
+
+int OutputLayerInformation::GetBufferIndex(int y, int x, int z) const {
+ return GetBufferIndex(GetYBufferIndex(y), x, z);
+}
+
+bool OutputLayerInformation::NeedsRelayout() const {
+ if (!output_layer_->shape_info()) {
+ return true;
+ }
+ // Relayout is not needed when output layout has only one shape with no
+ // padding between elements.
+ const auto& slice_layouts = *output_layer_->shape_info()->slice_layout();
+ return slice_layouts.size() > 1 ||
+ !tensor_util::IsNoPaddingLayout(*slice_layouts.Get(0));
+}
+
+// TODO Add unit tests for this method.
+util::Status OutputLayerInformation::Relayout(unsigned char* dest,
+ const unsigned char* src) const {
+ // TODO: re-use the same buffer and avoid an unnecessary memcopy
+ // when relayout is not needed.
+ if (!NeedsRelayout()) {
+ memcpy(dest, src,
+ batch_dim() * y_dim() * x_dim() * z_dim() * DataTypeSize());
+ return util::OkStatus();
+ }
+
+ if (output_layer_->shape_info()) {
+ // If output shape info exists in the executable, use the new re-layout
+ // function. Currently, this is only enabled for models with multiple
+ // batches.
+ return RelayoutWithShapeInformation(dest, src);
+ }
+
+ const auto data_type_size = DataTypeSize();
+ const int z_bytes = z_dim() * data_type_size;
+
+ if (y_dim() == 1 && x_dim() == 1) {
+ // One dimensional output (only z-dimension).
+ if (src != dest) {
+ const int padded_size_bytes = PaddedSizeBytes();
+ const int actual_size_bytes = ActualSizeBytes();
+ const int executions = execution_count_per_inference();
+ if (executions == 1 || padded_size_bytes == actual_size_bytes) {
+ memcpy(dest, src, z_bytes * executions);
+ } else {
+ // Remove padding values at the end of each execution.
+ const int padded_size_per_execution =
+ (padded_size_bytes - actual_size_bytes) / executions;
+ for (int i = 0; i < executions; ++i) {
+ memcpy(dest, src, z_bytes);
+ dest += z_bytes;
+ src += z_bytes + padded_size_per_execution;
+ }
+ }
+ }
+ } else {
+ int z_bytes_padded;
+ if (x_dim() > 1) {
+ // If x-dim is > 1, padded-z-size can be deduced by looking at difference
+ // between offset of element y=0,x=0,z=0 and y=0,x=1,z=0.
+ z_bytes_padded = GetBufferIndex(0, 1, 0) - GetBufferIndex(0, 0, 0);
+ } else {
+ // Otherwise when x-dim is 1 (y-dim must be > 1 in that case),
+ // padded-z-size can be deduced by looking at difference between offset of
+ // element y=0,x=0,z=0 and y=1,x=0,z=0.
+ z_bytes_padded = GetBufferIndex(1, 0, 0) - GetBufferIndex(0, 0, 0);
+ }
+ z_bytes_padded *= data_type_size;
+
+ const auto* layout = output_layer_->layout();
+ int last_x = 0;
+ int last_x_tile = layout->x_coordinate_to_linear_tile_id_map()->Get(0);
+ std::vector active_tile_x_sizes;
+ for (int x = 1; x < x_dim(); ++x) {
+ int cur_x_tile = layout->x_coordinate_to_linear_tile_id_map()->Get(x);
+ if (cur_x_tile != last_x_tile) {
+ active_tile_x_sizes.push_back(x - last_x);
+ last_x_tile = cur_x_tile;
+ last_x = x;
+ }
+ }
+ active_tile_x_sizes.push_back(x_dim() - last_x);
+
+// When the num_z_bytes parameter is a compile-time constant, the conditions
+// in the innermost loop will be replaced with a single optimized path,
+// specialized for that value.
+// Specialization is provided for num_z_bytes value of 1 and 3.
+// We can also make this a helper function and still realize the benefits
+// provided we have a guaranteed way of ensuring this function would be inlined
+// so that the compiler optimizations based on compile-time-constants can kick
+// in.
+#define RELAYOUT_WITH_Z_BYTES_SPECIALIZATION( \
+ num_z_bytes, num_z_bytes_padded) \
+ do { \
+ for (int y = 0; y < y_dim(); ++y) { \
+ const auto y_buffer_index = GetYBufferIndex(y); \
+ int tile_starting_x = 0; \
+ for (int x_tile = 0; x_tile < active_tile_x_sizes.size(); ++x_tile) { \
+ const unsigned char* source = \
+ src + GetBufferIndex(y_buffer_index, tile_starting_x, /*z=*/0) * \
+ data_type_size; \
+ const int tile_x_size = active_tile_x_sizes[x_tile]; \
+ for (int local_offset_x = 0; local_offset_x < tile_x_size; \
+ ++local_offset_x) { \
+ if ((num_z_bytes) == 1) { \
+ *dest = *source; \
+ } else if ((num_z_bytes) == 3) { \
+ *(dest + 0) = *(source + 0); \
+ *(dest + 1) = *(source + 1); \
+ *(dest + 2) = *(source + 2); \
+ } else { \
+ memcpy(dest, source, (num_z_bytes)); \
+ } \
+ dest += (num_z_bytes); \
+ source += (num_z_bytes_padded); \
+ } \
+ tile_starting_x += tile_x_size; \
+ } \
+ } \
+ } while (0)
+
+ if (z_bytes != z_bytes_padded) {
+ if (z_bytes == 1) {
+ // Specialization for z_bytes = 1 (grayscale image).
+ RELAYOUT_WITH_Z_BYTES_SPECIALIZATION(1, 4);
+ } else if (z_bytes == 3) {
+ // Specialization for z_bytes = 3 (RGB image).
+ RELAYOUT_WITH_Z_BYTES_SPECIALIZATION(3, 4);
+ } else {
+ // Default.
+ RELAYOUT_WITH_Z_BYTES_SPECIALIZATION(z_bytes, z_bytes_padded);
+ }
+ } else {
+ // TODO: test models impacted with this relayout method.
+ const int first_y_tile =
+ layout->y_coordinate_to_linear_tile_id_map()->Get(0);
+ const int last_y_tile =
+ layout->y_coordinate_to_linear_tile_id_map()->Get(y_dim() - 1);
+
+ // If there's only one output shape from one tile and no Z padding, copy
+ // data directly.
+ const bool need_relayout =
+ active_tile_x_sizes.size() > 1 || first_y_tile != last_y_tile;
+
+ if (need_relayout) {
+ // If there's no z padding, copy one xz block on one tile at a time.
+ for (int y = 0; y < y_dim(); ++y) {
+ const auto y_buffer_index = GetYBufferIndex(y);
+ int tile_starting_x = 0;
+ for (int x_tile = 0; x_tile < active_tile_x_sizes.size(); ++x_tile) {
+ const unsigned char* source =
+ src + GetBufferIndex(y_buffer_index, tile_starting_x, /*z=*/0) *
+ data_type_size;
+ const int tile_x_size = active_tile_x_sizes[x_tile];
+ const int tile_x_z_bytes = z_bytes * tile_x_size;
+ memcpy(dest, source, tile_x_z_bytes);
+ dest += tile_x_z_bytes;
+ tile_starting_x += tile_x_size;
+ }
+ }
+ } else {
+ // TODO: avoid copy and assign in caller directly.
+ memcpy(dest, src, x_dim() * y_dim() * z_bytes);
+ }
+ }
+
+#undef RELAYOUT_WITH_Z_BYTES_SPECIALIZATION
+
+ // TODO: If iteration count is more than 1, we need to make sure we
+ // advance 'src' and 'dest' correctly due to padding issue. We don't have
+ // test case now.
+ CHECK_EQ(execution_count_per_inference(), 1)
+ << "Verification is missing if execution count is greater than 1";
+ }
+
+ return util::OkStatus();
+}
+
+util::Status OutputLayerInformation::RelayoutWithShapeInformation(
+ unsigned char* dest, const unsigned char* src) const {
+ CHECK_EQ(execution_count_per_inference(), 1)
+ << "Multiple inference execution not supported in the new relayout "
+ "(b/129301507).";
+
+ const auto data_type_size = DataTypeSize();
+ const auto& shape_info = *output_layer_->shape_info();
+
+ RETURN_IF_ERROR(SanityCheckShapeInformation(shape_info, data_type_size));
+
+ flatbuffers::FlatBufferBuilder builder;
+ const auto fb_layout = tensor_util::BuildPackedLayout(*layer()->shape());
+ builder.Finish(darwinn::TensorLayout::Pack(builder, fb_layout.get()));
+ const TensorLayout& dest_layout =
+ *flatbuffers::GetRoot(builder.GetBufferPointer());
+ unsigned char* dest_address = dest;
+
+ const auto& slice_layouts = *shape_info.slice_layout();
+ for (int i = 0; i < slice_layouts.size(); ++i) {
+ // Each slice is stored in a contiguous memory space.
+ const TensorLayout& source_layout = *slice_layouts.Get(i);
+ TensorShapeT source_shape;
+ source_layout.shape()->UnPackTo(&source_shape);
+ const unsigned char* source_address =
+ src + shape_info.slice_offset()->Get(i);
+
+ CopyShape(source_shape, source_layout, source_address, dest_layout,
+ dest_address, data_type_size, tensor_util::kBatch);
+ }
+
+ return util::OkStatus();
+}
+
+int OutputLayerInformation::GetBufferIndex(
+ const std::vector& element_position) const {
+ const auto* shape_info = output_layer_->shape_info();
+ if (!shape_info) {
+ CHECK_EQ(element_position.size(), 4);
+ CHECK_EQ(element_position[tensor_util::kBatch], 0);
+ return GetBufferIndex(/*y=*/element_position[tensor_util::kY],
+ /*x=*/element_position[tensor_util::kX],
+ /*z=*/element_position[tensor_util::kZ]);
+ }
+
+ const int data_type_size = DataTypeSize();
+ const auto& slice_layouts = *shape_info->slice_layout();
+ for (int i = 0; i < slice_layouts.size(); ++i) {
+ const TensorLayout& slice_layout = *slice_layouts.Get(i);
+ const TensorShape& slice_shape = *slice_layout.shape();
+ if (tensor_util::IsElementInShape(slice_shape, element_position)) {
+ const int index = tensor_util::GetMemoryIndexFromPosition(
+ slice_layout, element_position);
+ const int slice_base_offset_in_bytes = shape_info->slice_offset()->Get(i);
+ CHECK_EQ(slice_base_offset_in_bytes % data_type_size, 0);
+ const int slice_base_offset_in_elements =
+ slice_base_offset_in_bytes / data_type_size;
+ return slice_base_offset_in_elements + index;
+ }
+ }
+
+ std::string position_string;
+ for (int index : element_position) {
+ position_string += StringPrintf("[%d]", index);
+ }
+
+ LOG(FATAL) << "Cannot find element in output: " << position_string;
+ return 0;
+}
+
+int TensorDataTypeSize(DataType data_type) {
+ switch (data_type) {
+ case DataType_FIXED_POINT8:
+ case DataType_SIGNED_FIXED_POINT8:
+ return 1;
+ case DataType_FIXED_POINT16:
+ case DataType_SIGNED_FIXED_POINT16:
+ return 2;
+ case DataType_SIGNED_FIXED_POINT32:
+ return 4;
+ case DataType_BFLOAT:
+ return 2;
+ case DataType_HALF:
+ return 2;
+ case DataType_SINGLE:
+ return 4;
+ }
+}
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/layer_information.h b/api/layer_information.h
new file mode 100644
index 0000000..168fe1f
--- /dev/null
+++ b/api/layer_information.h
@@ -0,0 +1,177 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_LAYER_INFORMATION_H_
+#define DARWINN_API_LAYER_INFORMATION_H_
+
+#include
+
+#include "api/buffer.h"
+#include "api/tensor_util.h"
+#include "executable/executable_generated.h"
+#include "port/status.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Provides information on input and output layers.
+class LayerInformation {
+ public:
+ virtual ~LayerInformation() = default;
+
+ // Copyable.
+ LayerInformation(const LayerInformation& rhs) = default;
+ LayerInformation& operator=(const LayerInformation& rhs) = default;
+
+ // Returns layer name.
+ std::string name() const { return layer_->name()->str(); }
+
+ // Layer dimensions.
+ int x_dim() const { return layer_->x_dim(); }
+ int y_dim() const { return layer_->y_dim(); }
+ int z_dim() const { return layer_->z_dim(); }
+ int batch_dim() const {
+ if (layer_->shape()) {
+ return tensor_util::GetDimensionLength(*layer_->shape(), 0);
+ } else {
+ return 1;
+ }
+ }
+
+ // Returns the zero point value.
+ int zero_point() const { return layer_->numerics()->zero_point(); }
+
+ // Returns the execution count per inference.
+ int execution_count_per_inference() const {
+ return layer_->execution_count_per_inference();
+ }
+
+ // Returns the dequantization factor.
+ float dequantization_factor() const {
+ return layer_->numerics()->dequantization_factor();
+ }
+
+ // Returns data type in this layer.
+ darwinn::DataType data_type() const { return layer_->data_type(); }
+
+ // Returns the size of the data type in this layer in bytes.
+ int DataTypeSize() const;
+
+ // Returns true if the data type is signed.
+ bool SignedDataType() const;
+
+ // Returns the expected byte size of activations for given layer. This
+ // excludes padding.
+ int ActualSizeBytes() const {
+ const int num_elements =
+ (layer_->shape()) ? tensor_util::GetNumElementsInShape(*layer_->shape())
+ : x_dim() * y_dim() * z_dim();
+ return num_elements * DataTypeSize() *
+ layer_->execution_count_per_inference();
+ }
+
+ // Returns the expected size of activations for given layer including padding
+ // bytes.
+ int PaddedSizeBytes() const {
+ return SizeBytesPerIteration() * layer_->execution_count_per_inference();
+ }
+
+ int SizeBytesPerIteration() const { return layer_->size_bytes(); }
+
+ // Returns true if activations of this input/output layer need to be cached on
+ // DRAM.
+ bool CacheOnDram() const { return layer_->cache_on_dram(); }
+
+ // Converts unsigned values for a provided buffer of this layer to signed and
+ // vice versa.
+ util::Status TransformSignedDataType(Buffer buffer) const;
+
+ protected:
+ explicit LayerInformation(const Layer* layer);
+
+ const Layer* layer() const { return layer_; }
+
+ private:
+ const Layer* layer_;
+};
+
+// Provides detailed information on input layers.
+class InputLayerInformation : public LayerInformation {
+ public:
+ explicit InputLayerInformation(const Layer* layer);
+ ~InputLayerInformation() override = default;
+};
+
+// Provides detailed information on output layers.
+class OutputLayerInformation : public LayerInformation {
+ public:
+ // Holds y-dependent values that are needed to calculate buffer index.
+ // Expected usage is as follows:
+ //
+ // for (int y = 0; y < y_dim(); ++y) {
+ // const YBufferIndex y_buffer_index = GetYBufferIndex(y);
+ // for (int x = 0; x < x_dim(); ++x) {
+ // const int src_offset =
+ // GetBufferIndex(y_buffer_index, x, /*z=*/0) * data_type_size;
+ // ...
+ // }
+ // }
+ struct YBufferIndex {
+ // Holds the linearized tile ID for a given y value.
+ int y_linearized_tile_id;
+ // Holds local offset within a data chunk returned by a given tile.
+ int local_y_coordinate;
+ };
+
+ explicit OutputLayerInformation(const Layer* layer);
+ ~OutputLayerInformation() override = default;
+
+ // Returns an index value of output buffer for a given tensor coordinate.
+ int GetBufferIndex(int y, int x, int z) const;
+ int GetBufferIndex(const std::vector& element_position) const;
+
+ // Essentially does the same thing as functions above, but these two split
+ // functions allow a user to save some computation such as using the samve
+ // value from GetYBufferIndex across all x pixels.
+ YBufferIndex GetYBufferIndex(int y) const;
+ int GetBufferIndex(const YBufferIndex& y_buffer_index, int x, int z) const;
+
+ // Relayout the source DarwiNN output buffer (TYXZ layout, T = Tile) into
+ // user output buffer (YXZ layout).
+ //
+ // TODO Move this method down to driver internal classes once all
+ // dependencies are removed.
+ util::Status Relayout(unsigned char* dest, const unsigned char* src) const;
+
+ // Returns true if relayout is needed.
+ bool NeedsRelayout() const;
+
+ private:
+ // Re-layouts the output activation stream from the tiles into a desired
+ // format in the host memory.
+ util::Status RelayoutWithShapeInformation(unsigned char* dest,
+ const unsigned char* src) const;
+
+ const OutputLayer* output_layer_;
+};
+
+// Returns the byte size of a provided tensor data type.
+int TensorDataTypeSize(DataType data_type);
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_LAYER_INFORMATION_H_
diff --git a/api/package_reference.h b/api/package_reference.h
new file mode 100644
index 0000000..b249be0
--- /dev/null
+++ b/api/package_reference.h
@@ -0,0 +1,156 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_PACKAGE_REFERENCE_H_
+#define DARWINN_API_PACKAGE_REFERENCE_H_
+
+#include
+#include
+#include
+#include
+
+#include "api/execution_context_interface.h"
+#include "api/layer_information.h"
+#include "executable/executable_generated.h"
+#include "port/integral_types.h"
+#include "port/statusor.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Specifies the most recent package identifier for executable.fbs.
+constexpr const char* kHeadPackageIdentifier = "DWN1";
+
+// Type for a registered executable.
+class PackageReference {
+ public:
+ virtual ~PackageReference() = default;
+
+ // This class is neither copyable nor movable.
+ PackageReference(const PackageReference&) = delete;
+ PackageReference& operator=(const PackageReference&) = delete;
+
+ // Verifies the digital signature of the backing executable package.
+ virtual util::Status VerifySignature() const = 0;
+
+ // Returns the index of input layer with given name.
+ virtual util::StatusOr InputIndex(const std::string& name) const = 0;
+
+ // Returns the index of output layer with given name.
+ virtual util::StatusOr OutputIndex(const std::string& name) const = 0;
+
+ // Returns number of input layers.
+ virtual int NumInputLayers() const = 0;
+
+ // Returns number of output layers.
+ virtual int NumOutputLayers() const = 0;
+
+ // Returns list of input layer names.
+ virtual const std::vector& InputLayerNames() const = 0;
+
+ // Returns list of output layer names.
+ virtual const std::vector& OutputLayerNames() const = 0;
+
+ // Returns information on given input layer. Returns nullptr if index is out
+ // of bounds.
+ virtual const InputLayerInformation* InputLayer(int index) const = 0;
+
+ // Returns information on given output layer. Returns nullptr if index is out
+ // of bounds.
+ virtual const OutputLayerInformation* OutputLayer(int index) const = 0;
+
+ // Returns information on given input layer.
+ virtual util::StatusOr InputLayer(
+ const std::string& layer_name) const = 0;
+
+ // Returns information on given output layer.
+ virtual util::StatusOr OutputLayer(
+ const std::string& layer_name) const = 0;
+
+ // Returns the expected byte size of activations for given input layer index.
+ virtual int InputLayerSizeBytes(int index) const = 0;
+
+ // Returns the expected byte size of activations for given input layer index.
+ // This is post-padding, if any.
+ // TODO Remove this method.
+ virtual int InputLayerPaddedSizeBytes(int index) const = 0;
+
+ // Returns the expected byte size of activations for given output layer index.
+ virtual int OutputLayerSizeBytes(int index) const = 0;
+
+ // Returns the expected size (in value count) of activations for given input
+ // layer index. This is pre-padding, if any.
+ virtual int InputLayerSize(int index) const = 0;
+
+ // Returns the expected size (in value count) of activations for given input
+ // layer index. This is pre-padding, if any.
+ virtual int OutputLayerSize(int index) const = 0;
+
+ // Returns the expected size of activations for given input layer.
+ // Prefer index based APIs for performance.
+ virtual util::StatusOr InputLayerSizeBytes(
+ const std::string& name) const = 0;
+
+ // Returns the expected size of activations for given input layer including
+ // padding bytes.
+ // Prefer index based APIs for performance.
+ // TODO Remove this method.
+ virtual util::StatusOr InputLayerPaddedSizeBytes(
+ const std::string& name) const = 0;
+
+ // Returns the expected size of activations for given output layer.
+ // Prefer index based APIs for performance.
+ virtual util::StatusOr OutputLayerSizeBytes(
+ const std::string& name) const = 0;
+
+ // Returns name for given input layer index.
+ virtual std::string InputLayerName(int index) const = 0;
+
+ // Returns name for given output layer index.
+ virtual std::string OutputLayerName(int index) const = 0;
+
+ // Returns batch size.
+ virtual int BatchSize() const = 0;
+
+ // Sets the execution context (info related to execution). The execution
+ // context is later used for logging purposes.
+ virtual void SetExecutionContextInterface(
+ std::unique_ptr
+ execution_context_interface) = 0;
+
+ // Sets the maximum amount of time this package can tolerate for an inference
+ // to finish. Setting this will make driver check if it can meet the latency
+ // target on each inference. If it cannot, it will immediately return a
+ // deadline exceeded error. Parameter-caching or anything extra that driver
+ // needs to run in order to complete an inference will be counted towards this
+ // target. If a batch request is submitted, the total time to complete the
+ // batch is counted (not a single batch element).
+ virtual util::Status SetLatencyTolerance(int64 max_latency_ms) = 0;
+
+ // Returns a unique user-specified string identifies the model. It returns
+ // empty string if no identifier is set. This is available for limited cases
+ // only.
+ virtual std::string ModelIdentifier() const = 0;
+
+ protected:
+ PackageReference() = default;
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_PACKAGE_REFERENCE_H_
+
diff --git a/api/request.h b/api/request.h
new file mode 100644
index 0000000..ab9b7a7
--- /dev/null
+++ b/api/request.h
@@ -0,0 +1,136 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_REQUEST_H_
+#define DARWINN_API_REQUEST_H_
+
+#include
+#include
+#include
+
+#include "api/buffer.h"
+#include "port/integral_types.h"
+#include "port/status_macros.h"
+#include "port/statusor.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Compute request. Thread-unsafe.
+class Request {
+ public:
+ // A type for request completion callback.
+ // The int argument is the same as return value of id().
+ using Done = std::function;
+
+ // Fine grain timing information
+ struct TimingEvent {
+ // Classify each TPU Request (sub-requests) for logging.
+ enum class TpuRequestType {
+ PARAMETER_CACHING, // Request for parameter caching.
+ INFERENCE // Inference request, single hardware batch.
+ };
+
+ // Classify the TimingEvents based on what is happening to the TPU Request.
+ enum class EventType {
+ SUBMITTED, // The sub-request was submitted.
+ COMPLETED // The sub-request was completed.
+ };
+
+ int64 timestamp; // When the event occurred.
+ TpuRequestType request_type; // Request classification for logging.
+ EventType event_type; // What happened (request creation, completion).
+
+ // In DarwiNN 1.0, requests are sent in order. If that changes in the
+ // future, need to add a request_id to correlate events belonging to a
+ // single request, while multiple requests are in flight.
+
+ TimingEvent(int64 timestamp, TpuRequestType type, EventType state)
+ : timestamp(timestamp),
+ request_type(type),
+ event_type(state){}
+ };
+
+ // Encapsulates timing information of a request.
+ struct Timing {
+ // Timestamp (in nanoseconds) of when the request was first created.
+ int64 created_ns;
+
+ // Timestamp (in nanoseconds) of when the request was submitted to the
+ // device for execution. In case of batched requests, this is the time when
+ // the first batch element is submitted.
+ int64 submitted_ns;
+
+ // Timestamp (in nanoseconds) of when the request was completed in hardware.
+ // In case of batched requests, this is the time that the last batch element
+ // completed execution.
+ int64 completed_ns;
+
+ // Capture finegrain event timestamps for each single_tpu_request
+ std::vector detail_timing;
+ };
+
+ Request() = default;
+ virtual ~Request() = default;
+
+ // This class is neither copyable nor movable.
+ Request(const Request&) = delete;
+ Request& operator=(const Request&) = delete;
+
+ // Adds an input buffer. This may be called repeatedly depending
+ // on the batch size as long as the request instance is not submitted. The
+ // size constraints on the input and output buffers will be evaluated during
+ // Device#Submit. Memory backing the buffer instance must be valid throughout
+ // the life of the request.
+ // IMPORTANT: For better performance, please make sure input buffers are
+ // aligned with at least minimum_alignment_bytes (architecture dependent). If
+ // possible use Driver::MakeBuffer to get a buffer with this requirement met.
+ // Buffers with and without padding are both acceptable.
+ virtual util::Status AddInput(const std::string& name,
+ const Buffer& input) = 0;
+
+ // Adds an output buffer. This may be called repeatedly depending
+ // on the batch size as long as the request instance is not submitted. The
+ // size constraints on the input and output buffers will be evaluated during
+ // Device#Submit. Memory backing the buffer instance must be valid throughout
+ // the life of the request.
+ //
+ // If the output buffer is user-allocated on-device DRAM, the model must
+ // ensure that no post-processing will be needed for this output, such as
+ // re-layout or sign processing.
+ // TODO -- the API implementation does not currently validate
+ // that no post-processing will be needed for a user-allocated on-device DRAM
+ // output.
+ virtual util::Status AddOutput(const std::string& name, Buffer output) = 0;
+
+ // Sets the scheduling priority of this request (must be a positive int) where
+ // 0 is highest priority. P0 requests are immediately scheduled for execution
+ // while lower priorities (higher in value) may get preempted if device is
+ // busy. By default, a request is P0.
+ virtual util::Status SetPriority(int priority) = 0;
+
+ // Returns timing information of this request. It can only be called when the
+ // request is done.
+ virtual util::StatusOr GetTiming() const = 0;
+
+ // Returns an ID to track the request.
+ virtual int id() const = 0;
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_REQUEST_H_
diff --git a/api/runtime_version.h b/api/runtime_version.h
new file mode 100644
index 0000000..1463268
--- /dev/null
+++ b/api/runtime_version.h
@@ -0,0 +1,44 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_RUNTIME_VERSION_H_
+#define DARWINN_API_RUNTIME_VERSION_H_
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+enum RuntimeVersion {
+ // A DariwiNN package carrying runtime version less than or equal to this
+ // value would trigger a warning from driver, during model registration.
+ // This is the lower bound of kCurrent, and shall not be modified.
+ kMinValidRuntimeVersion = 10,
+
+ // Increase this number everytime a change involving both compiler and runtime
+ // happens. This number is used in binary compatibility checks for DarwiNN
+ // packages.
+ kCurrent = 13,
+ // This is the runtime version that has native batch support.
+ kWithNativeBatchSupport = 11,
+ // This is the runtime version that has support for int8 as host data type.
+ kWithInt8HostDataTypeSupport = 12,
+ // This is the runtime version that has support for 16-bit floating point.
+ kWithFp16Support = 13,
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_RUNTIME_VERSION_H_
diff --git a/api/telemeter_interface.h b/api/telemeter_interface.h
new file mode 100644
index 0000000..07d4f89
--- /dev/null
+++ b/api/telemeter_interface.h
@@ -0,0 +1,42 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_TELEMETER_INTERFACE_H_
+#define DARWINN_API_TELEMETER_INTERFACE_H_
+
+#include
+
+#include "api/execution_context_interface.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// This class collects data related to on-device execution on the TPU, and may
+// report them back to a server for further analysis. The data could be
+// related to performance or execution failure.
+// This class is thread-safe.
+class TelemeterInterface {
+ public:
+ virtual ~TelemeterInterface() = default;
+
+ // Logs the watchdog timeout event.
+ virtual void LogWatchdogTimeout(const ExecutionContextInterface& context) = 0;
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_TELEMETER_INTERFACE_H_
diff --git a/api/tensor_util.cc b/api/tensor_util.cc
new file mode 100644
index 0000000..d19ef55
--- /dev/null
+++ b/api/tensor_util.cc
@@ -0,0 +1,325 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/tensor_util.h"
+
+#include "port/logging.h"
+#include "port/string_util.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+namespace tensor_util {
+
+TensorShapeT MakeTensorShape(const std::vector& dimensions) {
+ TensorShapeT shape;
+ shape.dimension.resize(dimensions.size());
+ for (int i = 0; i < dimensions.size(); ++i) {
+ shape.dimension[i] = {0, dimensions[i] - 1};
+ }
+ return shape;
+}
+
+TensorShapeT MakeTensorShape(const std::vector& ranges) {
+ TensorShapeT shape;
+ shape.dimension.resize(ranges.size());
+ for (int i = 0; i < ranges.size(); ++i) {
+ shape.dimension[i] = ranges[i];
+ }
+ return shape;
+}
+
+TensorShapeT GetIntersectShape(const TensorShapeT& one,
+ const TensorShapeT& two) {
+ CHECK_EQ(one.dimension.size(), two.dimension.size());
+ TensorShapeT intersect;
+ intersect.dimension.resize(one.dimension.size());
+ for (int i = 0; i < one.dimension.size(); ++i) {
+ intersect.dimension[i] = {
+ std::max(one.dimension[i].start(), two.dimension[i].start()),
+ std::min(one.dimension[i].end(), two.dimension[i].end())};
+ }
+ return intersect;
+}
+
+bool IsValidShape(const TensorShape& shape) {
+ if (shape.dimension()->size() == 0) {
+ return false;
+ }
+
+ for (int i = 0; i < shape.dimension()->size(); ++i) {
+ if (shape.dimension()->Get(i)->start() > shape.dimension()->Get(i)->end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsValidShape(const TensorShapeT& shape) {
+ if (shape.dimension.empty()) {
+ return false;
+ }
+
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ if (shape.dimension[i].start() > shape.dimension[i].end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+int GetNumElementsInShape(const TensorShape& shape) {
+ int num_elements = 1;
+ for (int i = 0; i < shape.dimension()->size(); ++i) {
+ const int length = shape.dimension()->Get(i)->end() -
+ shape.dimension()->Get(i)->start() + 1;
+ CHECK_GT(length, 0);
+ num_elements *= length;
+ }
+ return num_elements;
+}
+
+int GetNumElementsInShape(const TensorShapeT& shape) {
+ int num_elements = 1;
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ const int length =
+ shape.dimension[i].end() - shape.dimension[i].start() + 1;
+ CHECK_GT(length, 0);
+ num_elements *= length;
+ }
+ return num_elements;
+}
+
+int GetDimensionLength(const TensorShape& shape, int dimension) {
+ return shape.dimension()->Get(dimension)->end() -
+ shape.dimension()->Get(dimension)->start() + 1;
+}
+
+int GetDimensionLength(const TensorShapeT& shape, int dimension) {
+ return shape.dimension.at(dimension).end() -
+ shape.dimension.at(dimension).start() + 1;
+}
+
+bool IsElementInShape(const TensorShape& shape,
+ const std::vector& position) {
+ CHECK_EQ(position.size(), shape.dimension()->size());
+ for (int i = 0; i < shape.dimension()->size(); ++i) {
+ const auto range = shape.dimension()->Get(i);
+ if (position[i] < range->start() || position[i] > range->end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool IsElementInShape(const TensorShapeT& shape,
+ const std::vector& position) {
+ CHECK_EQ(position.size(), shape.dimension.size());
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ const auto& range = shape.dimension[i];
+ if (position[i] < range.start() || position[i] > range.end()) {
+ return false;
+ }
+ }
+ return true;
+}
+
+std::unique_ptr BuildPackedLayout(const TensorShape& shape) {
+ auto layout = gtl::MakeUnique();
+
+ // Fill shape information.
+ layout->shape = gtl::MakeUnique();
+ shape.UnPackTo(layout->shape.get());
+
+ // Fill stride information.
+ layout->stride.resize(layout->shape->dimension.size());
+ int current_stride = 1;
+ for (int i = layout->shape->dimension.size() - 1; i >= 0; --i) {
+ layout->stride[i] = current_stride;
+ current_stride *= GetDimensionLength(*layout->shape, i);
+ }
+
+ return layout;
+}
+
+std::unique_ptr BuildPackedLayout(const TensorShapeT& shape) {
+ auto layout = gtl::MakeUnique();
+
+ // Fill shape information.
+ layout->shape = gtl::MakeUnique(shape);
+
+ // Fill stride information.
+ layout->stride.resize(layout->shape->dimension.size());
+ int current_stride = 1;
+ for (int i = layout->shape->dimension.size() - 1; i >= 0; --i) {
+ layout->stride[i] = current_stride;
+ current_stride *= GetDimensionLength(*layout->shape, i);
+ }
+
+ return layout;
+}
+
+bool IsValidLayout(const TensorLayout& layout) {
+ const auto& shape = *layout.shape();
+ if (!IsValidShape(shape)) {
+ return false;
+ }
+
+ for (int i = 0; i < shape.dimension()->size() - 1; ++i) {
+ if (layout.stride()->Get(i) <
+ layout.stride()->Get(i + 1) * GetDimensionLength(shape, i + 1)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IsValidLayout(const TensorLayoutT& layout) {
+ const auto& shape = *layout.shape;
+ if (!IsValidShape(shape)) {
+ return false;
+ }
+
+ for (int i = 0; i < shape.dimension.size() - 1; ++i) {
+ if (layout.stride[i] <
+ layout.stride[i + 1] * GetDimensionLength(shape, i + 1)) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+bool IsNoPaddingLayout(const TensorLayout& layout) {
+ CHECK(IsValidLayout(layout));
+ const auto& shape = *layout.shape();
+
+ // There's no padding in layout if the stride equals to the dimension size.
+ for (int i = 0; i < shape.dimension()->size() - 1; ++i) {
+ if (layout.stride()->Get(i) !=
+ layout.stride()->Get(i + 1) * GetDimensionLength(shape, i + 1)) {
+ return false;
+ }
+ }
+ return true;
+}
+
+int GetLayoutSizeInElements(const TensorLayout& layout) {
+ CHECK(IsValidLayout(layout));
+ return GetDimensionLength(*layout.shape(), 0) * layout.stride()->Get(0);
+}
+
+int GetLayoutSizeInElements(const TensorLayoutT& layout) {
+ CHECK(IsValidLayout(layout)) << DumpLayout(layout);
+ return GetDimensionLength(*layout.shape, 0) * layout.stride[0];
+}
+
+int GetMemoryIndexFromPosition(const TensorLayout& layout,
+ const std::vector& position) {
+ CHECK(IsElementInShape(*layout.shape(), position));
+ int memory_index = 0;
+ for (int i = 0; i < position.size(); ++i) {
+ const int min_index = layout.shape()->dimension()->Get(i)->start();
+ const int stride = layout.stride()->Get(i);
+ memory_index += stride * (position[i] - min_index);
+ }
+ return memory_index;
+}
+
+int GetMemoryIndexFromPosition(const TensorLayoutT& layout,
+ const std::vector& position) {
+ CHECK(IsElementInShape(*layout.shape, position));
+ int memory_index = 0;
+ for (int i = 0; i < position.size(); ++i) {
+ const int min_index = layout.shape->dimension.at(i).start();
+ const int stride = layout.stride.at(i);
+ memory_index += stride * (position[i] - min_index);
+ }
+ return memory_index;
+}
+
+int GetFirstMemoryIndexForShape(const TensorLayout& layout,
+ const TensorShapeT& shape) {
+ std::vector position(shape.dimension.size());
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ position[i] = shape.dimension[i].start();
+ }
+ return GetMemoryIndexFromPosition(layout, position);
+}
+
+int GetLastMemoryIndexForShape(const TensorLayout& layout,
+ const TensorShapeT& shape) {
+ std::vector position(shape.dimension.size());
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ position[i] = shape.dimension[i].end();
+ }
+ return GetMemoryIndexFromPosition(layout, position);
+}
+
+bool IsShapeInContiguousLayout(const TensorLayout& layout,
+ const TensorShapeT& shape) {
+ const int first_index = GetFirstMemoryIndexForShape(layout, shape);
+ const int last_index = GetLastMemoryIndexForShape(layout, shape);
+ return GetNumElementsInShape(shape) == (last_index - first_index + 1);
+}
+
+std::string DumpShape(const TensorShape& shape) {
+ std::string str;
+ for (int i = 0; i < shape.dimension()->size(); ++i) {
+ const auto range = shape.dimension()->Get(i);
+ StrAppend(&str, StringPrintf("[%d:%d]", range->start(), range->end()));
+ }
+ return str;
+}
+
+std::string DumpShape(const TensorShapeT& shape) {
+ std::string str;
+ for (int i = 0; i < shape.dimension.size(); ++i) {
+ StrAppend(&str, StringPrintf("[%d:%d]", shape.dimension[i].start(),
+ shape.dimension[i].end()));
+ }
+ return str;
+}
+
+std::string DumpLayout(const TensorLayout& layout) {
+ std::string str =
+ StringPrintf("shape=%s", DumpShape(*layout.shape()).c_str());
+ StrAppend(&str, ",stride=");
+ for (int i = 0; i < layout.stride()->size(); ++i) {
+ if (i > 0) {
+ StrAppend(&str, "/");
+ }
+ StrAppend(&str, StringPrintf("%d", layout.stride()->Get(i)));
+ }
+ return str;
+}
+
+std::string DumpLayout(const TensorLayoutT& layout) {
+ std::string str = StringPrintf("shape=%s", DumpShape(*layout.shape).c_str());
+ StrAppend(&str, ",stride=");
+ for (int i = 0; i < layout.stride.size(); ++i) {
+ if (i > 0) {
+ StrAppend(&str, "/");
+ }
+ StrAppend(&str, StringPrintf("%d", layout.stride[i]));
+ }
+ return str;
+}
+
+} // namespace tensor_util
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/tensor_util.h b/api/tensor_util.h
new file mode 100644
index 0000000..8f36436
--- /dev/null
+++ b/api/tensor_util.h
@@ -0,0 +1,116 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_TENSOR_UTIL_H_
+#define DARWINN_API_TENSOR_UTIL_H_
+
+#include
+#include
+
+#include "executable/executable_generated.h"
+#include "port/logging.h"
+#include "port/ptr_util.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+namespace tensor_util {
+
+// Enum for Tensor shape dimension index.
+enum ShapeDimension {
+ kBatch = 0,
+ kY = 1,
+ kX = 2,
+ kZ = 3,
+ kNumDimensions = 4,
+};
+
+// Creates a tensor shape object for the dimension lengths.
+TensorShapeT MakeTensorShape(const std::vector& dimensions);
+
+// Create a tensor shape object with range information for each dimension.
+TensorShapeT MakeTensorShape(const std::vector& ranges);
+
+// Returns true if all dimensions have valid index ranges.
+bool IsValidShape(const TensorShape& shape);
+bool IsValidShape(const TensorShapeT& shape);
+
+// Returns an intersection of two shapes. It will return an invalid shape if
+// there is no intersection.
+TensorShapeT GetIntersectShape(const TensorShapeT& one,
+ const TensorShapeT& two);
+
+// Returns number of elemens in a tensor shape.
+int GetNumElementsInShape(const TensorShape& shape);
+int GetNumElementsInShape(const TensorShapeT& shape);
+
+// Returns the length of a shape dimension.
+int GetDimensionLength(const TensorShape& shape, int dimension);
+int GetDimensionLength(const TensorShapeT& shape, int dimension);
+
+// Returns true if a tensor element specified by the position is included in the
+// shape.
+bool IsElementInShape(const TensorShape& shape,
+ const std::vector& position);
+bool IsElementInShape(const TensorShapeT& shape,
+ const std::vector& position);
+
+// Returns a row-major-packed layout for a tensor shape.
+std::unique_ptr BuildPackedLayout(const TensorShape& shape);
+std::unique_ptr BuildPackedLayout(const TensorShapeT& shape);
+
+// Returns true if all dimensions have valid index ranges.
+bool IsValidLayout(const TensorLayout& layout);
+bool IsValidLayout(const TensorLayoutT& layout);
+
+// Returns true if the layout has no padding.
+bool IsNoPaddingLayout(const TensorLayout& layout);
+
+// Return the memory space size for the layout. This can be different from the
+// number of valid elements in the layout due to stride.
+int GetLayoutSizeInElements(const TensorLayout& layout);
+int GetLayoutSizeInElements(const TensorLayoutT& layout);
+
+// Returns a linear memory index from a tensor position (a list of indexes).
+int GetMemoryIndexFromPosition(const TensorLayout& layout,
+ const std::vector& position);
+int GetMemoryIndexFromPosition(const TensorLayoutT& layout,
+ const std::vector& position);
+
+// Returns a linear memory index of a tensor's first element in memory.
+int GetFirstMemoryIndexForShape(const TensorLayout& layout,
+ const TensorShapeT& shape);
+
+// Returns a linear memory index of a tensor's last element in memory.
+int GetLastMemoryIndexForShape(const TensorLayout& layout,
+ const TensorShapeT& shape);
+
+// Returns true if all tensor elements are stored in a contiguous layout.
+bool IsShapeInContiguousLayout(const TensorLayout& layout,
+ const TensorShapeT& shape);
+
+// Dumps shape information.
+std::string DumpShape(const TensorShape& shape);
+std::string DumpShape(const TensorShapeT& shape);
+
+// Dumps layout information.
+std::string DumpLayout(const TensorLayout& layout);
+std::string DumpLayout(const TensorLayoutT& layout);
+
+} // namespace tensor_util
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_TENSOR_UTIL_H_
diff --git a/api/timing.h b/api/timing.h
new file mode 100644
index 0000000..22608d9
--- /dev/null
+++ b/api/timing.h
@@ -0,0 +1,53 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_TIMING_H_
+#define DARWINN_API_TIMING_H_
+#include "port/stringprintf.h"
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Timing information for real-time/QoS scheduler when applicable.
+struct Timing {
+ // Inference arrival rate, in FPS.
+ int fps{0};
+ // Max execution time (MET), in milliseconds.
+ int max_execution_time_ms{0};
+ // Tolerance, or how much an inference can be delayed. Also in milliseconds.
+ // 0 <= Tolerance <= (1/FPS - MET).
+ int tolerance_ms{0};
+
+ std::string Dump() const {
+ return StringPrintf("(%d FPS; max execution time %d ms; tolerance %d ms)",
+ fps, max_execution_time_ms, tolerance_ms);
+ }
+};
+
+// Trivial equality operator for Timing.
+inline bool operator==(const Timing& lhs, const Timing& rhs) {
+ return lhs.fps == rhs.fps &&
+ lhs.max_execution_time_ms == rhs.max_execution_time_ms &&
+ lhs.tolerance_ms == rhs.tolerance_ms;
+}
+
+inline bool operator!=(const Timing& lhs, const Timing& rhs) {
+ return !(lhs == rhs);
+}
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_TIMING_H_
diff --git a/api/watchdog.cc b/api/watchdog.cc
new file mode 100644
index 0000000..0f5bf5a
--- /dev/null
+++ b/api/watchdog.cc
@@ -0,0 +1,390 @@
+// Copyright 2019 Google LLC
+//
+// 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 "api/watchdog.h"
+
+#include // NOLINT(build/c++11)
+#include
+#include // NOLINT(build/c++11)
+#include
+
+#include "port/errors.h"
+#include "port/integral_types.h"
+#include "port/logging.h"
+#include "port/ptr_util.h"
+#include "port/status.h"
+#include "port/status_macros.h"
+#include "port/std_mutex_lock.h"
+#include "port/stringprintf.h"
+#include "port/time.h"
+#include "port/timer.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+namespace {
+
+inline int64 GetNextActivationId(int64 current_id) {
+ return (current_id == INT64_MAX) ? 0 : current_id + 1;
+}
+
+} // namespace
+
+std::unique_ptr Watchdog::MakeWatchdog(int64 timeout_ns,
+ Expire expire) {
+ if (timeout_ns > 0) {
+ return gtl::MakeUnique(timeout_ns, expire);
+ }
+ return gtl::MakeUnique();
+}
+
+TimerFdWatchdog::TimerFdWatchdog(int64 timeout_ns, Expire expire)
+ : TimerFdWatchdog(timeout_ns, std::move(expire),
+ gtl::MakeUnique()) {}
+
+TimerFdWatchdog::TimerFdWatchdog(int64 timeout_ns, Expire expire,
+ std::unique_ptr timer)
+ : expire_(std::move(expire)),
+ timeout_ns_(timeout_ns),
+ timer_(std::move(timer)) {
+ CHECK_GT(timeout_ns_, 0);
+ watcher_thread_ = std::thread([this]() { Watcher(); });
+}
+
+TimerFdWatchdog::~TimerFdWatchdog() {
+ {
+ StdMutexLock lock(&mutex_);
+ // 'DESTROYED' indicates that the watcher_thread_ should exit the loop.
+ // In case the watchdog is still BARKING, we set it to DESTROYED, so the
+ // watcher_thread_ can gracefully exit after the callback returns. The only
+ // side effect is that state_ is DESTROYED even though callback is running.
+ // Should be okay since nobody will query the watchdog state after this.
+ CHECK(state_ == WatchdogState::INACTIVE ||
+ state_ == WatchdogState::BARKING);
+ state_ = WatchdogState::DESTROYED;
+ CHECK_OK(timer_->Set(1));
+ }
+
+ watcher_thread_.join();
+}
+
+util::StatusOr TimerFdWatchdog::Activate() {
+ StdMutexLock lock(&mutex_);
+ switch (state_) {
+ case WatchdogState::ACTIVE:
+ break; // Already active: Return old activation_id.
+ case WatchdogState::BARKING:
+ return util::FailedPreconditionError(
+ "Cannot activate a barking watchdog.");
+ case WatchdogState::INACTIVE:
+ VLOG(5) << "Activating the watchdog.";
+ RETURN_IF_ERROR(timer_->Set(timeout_ns_));
+ state_ = WatchdogState::ACTIVE;
+ activation_id_ = GetNextActivationId(activation_id_);
+ break;
+ case WatchdogState::DESTROYED:
+ return util::FailedPreconditionError(
+ "Cannot activate a destroyed watchdog.");
+ }
+ return activation_id_;
+}
+
+util::Status TimerFdWatchdog::Signal() {
+ StdMutexLock lock(&mutex_);
+ switch (state_) {
+ case WatchdogState::ACTIVE:
+ VLOG(5) << "Signalling the watchdog.";
+ RETURN_IF_ERROR(timer_->Set(timeout_ns_));
+ return util::OkStatus();
+ case WatchdogState::BARKING:
+ return util::OkStatus();
+ case WatchdogState::INACTIVE:
+ case WatchdogState::DESTROYED:
+ return util::FailedPreconditionError(
+ "Cannot signal an in-active / destroyed watchdog.");
+ }
+}
+
+util::Status TimerFdWatchdog::Deactivate() {
+ StdMutexLock lock(&mutex_);
+ switch (state_) {
+ case WatchdogState::ACTIVE:
+ VLOG(5) << "De-activating an active watchdog.";
+ RETURN_IF_ERROR(timer_->Set(0));
+ state_ = WatchdogState::INACTIVE;
+ return util::OkStatus();
+ case WatchdogState::BARKING:
+ case WatchdogState::INACTIVE:
+ // Watchdog is either inactive or will become inactive. Nothing to do.
+ return util::OkStatus();
+ case WatchdogState::DESTROYED:
+ return util::FailedPreconditionError(
+ "Cannot deactivate a destroyed watchdog.");
+ }
+}
+
+util::Status TimerFdWatchdog::UpdateTimeout(int64 timeout_ns) {
+ if (timeout_ns <= 0) {
+ return util::InvalidArgumentError(StringPrintf(
+ "Watchdog timeout should be a positive integer. %lld was provided",
+ static_cast(timeout_ns)));
+ }
+
+ StdMutexLock lock(&mutex_);
+ timeout_ns_ = timeout_ns;
+
+ return util::OkStatus();
+}
+
+void TimerFdWatchdog::Watcher() {
+ while (true) {
+ auto expirations_or_error = timer_->Wait();
+ CHECK_OK(expirations_or_error.status());
+ auto expirations = expirations_or_error.ValueOrDie();
+ if (expirations == 0) {
+ continue;
+ }
+ CHECK_EQ(expirations, 1);
+
+ // Local copies of shared state to be used when we don't have the lock.
+ int64 activation_id = 0;
+ bool do_expire = false;
+
+ // Acquire lock to query and update shared state.
+ {
+ StdMutexLock lock(&mutex_);
+
+ if (state_ == WatchdogState::DESTROYED) {
+ VLOG(5) << "Callback watcher thread ended.";
+ return;
+ }
+
+ if (state_ != WatchdogState::ACTIVE) {
+ VLOG(1) << "Timer got triggered but watchdog is not active.";
+ continue;
+ }
+
+ do_expire = true;
+ state_ = WatchdogState::BARKING;
+ activation_id = activation_id_;
+ }
+
+ if (do_expire) {
+ // Callback occurs outside locked region since it might take more time.
+ VLOG(2) << "Calling watchdog expiration callback with ID:"
+ << activation_id;
+ expire_(activation_id);
+
+ // Acquire lock again to update shared state after calling expire_.
+ {
+ StdMutexLock lock(&mutex_);
+ // Watchdog might be destroyed while callback was running.
+ // In that case, retain the 'DESTROYED' state.
+ if (state_ != WatchdogState::DESTROYED) {
+ state_ = WatchdogState::INACTIVE;
+ }
+ }
+ }
+ }
+}
+
+CountingWatch::~CountingWatch() {
+ StdMutexLock lock(&mutex_);
+ if (counter_ != 0) {
+ LOG(WARNING) << StringPrintf(
+ "Destructing counting watch while counter is %lld",
+ static_cast(counter_));
+ }
+}
+
+util::Status CountingWatch::Increment() {
+ StdMutexLock lock(&mutex_);
+
+ if (counter_ == LLONG_MAX) {
+ return util::InternalError("Reached max counter value.");
+ }
+
+ counter_++;
+ VLOG(5) << StringPrintf("Incrementing watch counter to %lld.",
+ static_cast(counter_));
+ return watchdog_->Activate().status();
+}
+
+util::Status CountingWatch::Decrement() {
+ StdMutexLock lock(&mutex_);
+ if (counter_ <= 0) {
+ return util::FailedPreconditionError(
+ StringPrintf("Cannot decrement when counter is %lld.",
+ static_cast(counter_)));
+ }
+
+ counter_--;
+ VLOG(5) << StringPrintf("Decrementing watch counter to %lld.",
+ static_cast(counter_));
+
+ RETURN_IF_ERROR(watchdog_->Signal());
+
+ if (counter_ == 0) {
+ RETURN_IF_ERROR(watchdog_->Deactivate());
+ }
+
+ return util::OkStatus();
+}
+
+CascadeWatchdog::CascadeWatchdog(const std::vector& configs)
+ : CascadeWatchdog(configs, [](int64 timeout_ns, Expire expire) {
+ return gtl::MakeUnique(timeout_ns, std::move(expire));
+ }) {}
+
+CascadeWatchdog::CascadeWatchdog(const std::vector& configs,
+ WatchdogMaker make_watchdog)
+ : configs_(configs) {
+ CHECK_GT(configs.size(), 0);
+ watchdogs_.reserve(configs.size());
+
+ expiration_callback_thread_ = std::thread([this]() { CallbackExecutor(); });
+
+ // Set callbacks for each watchdog. Note that there are 3 levels of callback.
+ // 'make_watchdog' has an anonymous method that calls 'WatchdogExpired', which
+ // in turn does some checks / book-keeping and invokes the actual callback
+ // that is registered in the 'configs_' vector.
+ for (int i = 0; i < configs.size(); ++i) {
+ watchdogs_.push_back(make_watchdog(
+ configs[i].timeout_ns,
+ [this, i](int64 activation_id) { WatchdogExpired(activation_id, i); }));
+ }
+}
+
+CascadeWatchdog::~CascadeWatchdog() {
+ {
+ StdMutexLock lock(&mutex_);
+ is_alive_ = false;
+ child_expired_.notify_one();
+ }
+
+ expiration_callback_thread_.join();
+}
+
+void CascadeWatchdog::WatchdogExpired(int64 child_activation_id, int child_id) {
+ StdMutexLock lock(&mutex_);
+ if (child_activation_id != child_activation_id_ ||
+ child_id != currently_active_) {
+ // This means this is a delayed callback for an earlier activation, we
+ // should skip it.
+ return;
+ }
+
+ auto expire = configs_[currently_active_].expire;
+ auto activation_id = activation_id_;
+ expirations_.push_back([expire, activation_id]() { expire(activation_id); });
+ child_expired_.notify_one();
+
+ if (currently_active_ < watchdogs_.size() - 1) {
+ ++currently_active_;
+ child_activation_id_ =
+ watchdogs_[currently_active_]->Activate().ValueOrDie();
+ } else {
+ currently_active_ = kNoneActive;
+ }
+}
+
+util::Status CascadeWatchdog::StartFirstWatchdog() {
+ ASSIGN_OR_RETURN(child_activation_id_, watchdogs_[0]->Activate());
+ currently_active_ = 0;
+ return util::OkStatus();
+}
+
+util::Status CascadeWatchdog::DeactivateInternal() {
+ if (currently_active_ == kNoneActive) {
+ return util::OkStatus();
+ }
+
+ // There is a chance that we end up deactivating an already expired watchdog
+ // which will result in this call returning OK status but still getting the
+ // callback. However, callback notices that currently_active_ = kNoneActive
+ // and does not execute the expiration function.
+ RETURN_IF_ERROR(watchdogs_[currently_active_]->Deactivate());
+ currently_active_ = kNoneActive;
+
+ return util::OkStatus();
+}
+
+util::StatusOr CascadeWatchdog::Activate() {
+ StdMutexLock lock(&mutex_);
+ if (currently_active_ != kNoneActive) {
+ return activation_id_;
+ }
+ RETURN_IF_ERROR(StartFirstWatchdog());
+ activation_id_ = GetNextActivationId(activation_id_);
+ return activation_id_;
+}
+
+util::Status CascadeWatchdog::Signal() {
+ // Early exit if watchdog is not active
+ StdMutexLock lock(&mutex_);
+ if (currently_active_ == kNoneActive) {
+ VLOG(2) << "Signalled inactive CascadeWatchdog. Ignoring.";
+ return util::OkStatus();
+ }
+
+ RETURN_IF_ERROR(DeactivateInternal());
+ return StartFirstWatchdog();
+}
+
+util::Status CascadeWatchdog::Deactivate() {
+ StdMutexLock lock(&mutex_);
+ return DeactivateInternal();
+}
+
+util::Status CascadeWatchdog::UpdateTimeout(int64 timeout_ns) {
+ return watchdogs_[0]->UpdateTimeout(timeout_ns);
+}
+
+util::Status CascadeWatchdog::UpdateTimeout(int child_index, int64 timeout_ns) {
+ if (child_index >= watchdogs_.size()) {
+ return util::InvalidArgumentError(StringPrintf(
+ "Invalid child_index %d. We only have %zu child watchdogs.",
+ child_index, watchdogs_.size()));
+ }
+ return watchdogs_[child_index]->UpdateTimeout(timeout_ns);
+}
+
+void CascadeWatchdog::CallbackExecutor() {
+ while (true) {
+ std::vector> expirations;
+
+ {
+ StdCondMutexLock lock(&mutex_);
+ while (expirations_.empty() && is_alive_) {
+ child_expired_.wait(lock);
+ }
+
+ if (!is_alive_) {
+ return;
+ }
+
+ expirations = std::move(expirations_);
+ expirations_.clear();
+ }
+
+ for (const auto& expiration : expirations) {
+ expiration();
+ }
+ }
+}
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
diff --git a/api/watchdog.h b/api/watchdog.h
new file mode 100644
index 0000000..695f58f
--- /dev/null
+++ b/api/watchdog.h
@@ -0,0 +1,314 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_API_WATCHDOG_H_
+#define DARWINN_API_WATCHDOG_H_
+
+#include // NOLINT(build/c++11)
+#include
+#include // NOLINT(build/c++11)
+#include // NOLINT(build/c++11)
+#include
+
+#include "port/integral_types.h"
+#include "port/status.h"
+#include "port/statusor.h"
+#include "port/thread_annotations.h"
+#include "port/time.h"
+#include "port/timer.h"
+
+namespace platforms {
+namespace darwinn {
+namespace api {
+
+// Watchdog is a class responsible for keeping track of TPU status and sending
+// notifications when it is unresponsive.
+class Watchdog {
+ public:
+ // A callback function to be called when the watch timeout is reached.
+ using Expire = std::function;
+
+ Watchdog() = default;
+ virtual ~Watchdog() = default;
+
+ // This class is movable.
+ Watchdog(Watchdog&& rhs);
+ Watchdog& operator=(Watchdog&& rhs);
+
+ // This class is not copyable.
+ Watchdog(const Watchdog&) = delete;
+ Watchdog& operator=(const Watchdog&) = delete;
+
+ // Decides which watchdog concrete implementation to create based on the
+ // provided parameters, creates and returns it.
+ static std::unique_ptr MakeWatchdog(int64 timeout_ns,
+ Expire expire);
+
+ // Starts the watch. It returns an activation id that can be later on
+ // used to verify which activation an expiration callback belongs to.
+ virtual util::StatusOr Activate() = 0;
+
+ // Signals the watchdog that we are still active and healthy.
+ virtual util::Status Signal() = 0;
+
+ // Ends the watch.
+ virtual util::Status Deactivate() = 0;
+
+ // Updates watchdog timeout to the provided value in nanoseconds. By
+ // definition, the new timeout will be effective from the next activation /
+ // signal.
+ virtual util::Status UpdateTimeout(int64 timeout_ns) = 0;
+};
+
+// A No-Op watchdog used for when we don't need a watch (e.g. in tests,
+// simulator, etc.).
+class NoopWatchdog : public Watchdog {
+ public:
+ NoopWatchdog() = default;
+ ~NoopWatchdog() override = default;
+
+ // This class is movable.
+ NoopWatchdog(NoopWatchdog&& rhs);
+ NoopWatchdog& operator=(NoopWatchdog&& rhs);
+
+ // This class is not copyable.
+ NoopWatchdog(const NoopWatchdog&) = delete;
+ NoopWatchdog& operator=(const NoopWatchdog&) = delete;
+
+ util::StatusOr Activate() override { return 0; }
+ util::Status Signal() override { return util::OkStatus(); }
+ util::Status Deactivate() override { return util::OkStatus(); }
+ util::Status UpdateTimeout(int64 timeout_ns) override {
+ return util::OkStatus();
+ }
+};
+
+// A watchdog implementation that uses timerfd (or similar timers) underneath.
+class TimerFdWatchdog : public Watchdog {
+ public:
+ // This constructor uses timerfd system call.
+ TimerFdWatchdog(int64 timeout_ns, Expire expire);
+
+ // Accepts any timer interface. In most cases, it is recommended to use the
+ // first constructor.
+ TimerFdWatchdog(int64 timeout_ns, Expire expire,
+ std::unique_ptr timer);
+
+ ~TimerFdWatchdog() override;
+
+ // This class is movable.
+ TimerFdWatchdog(TimerFdWatchdog&& rhs);
+ TimerFdWatchdog& operator=(TimerFdWatchdog&& rhs);
+
+ // This class is not copyable.
+ TimerFdWatchdog(const TimerFdWatchdog&) = delete;
+ TimerFdWatchdog& operator=(const TimerFdWatchdog&) = delete;
+
+ enum class WatchdogState {
+ // State Transitions:
+ // |```````````````````V
+ // INACTIVE*-->ACTIVE-->BARKING-->INACTIVE-->DESTROYED
+ // ^--------------------^
+ INACTIVE, // Not yet activated or has finished barking.
+ ACTIVE, // Activated, but not yet barked - signal now to prevent barking.
+ BARKING, // Activated, and timer expired - callback is being executed.
+ DESTROYED // Watchdog Destructor has been called - exit watcher thread.
+ };
+
+ const char* GetStateString() const EXCLUSIVE_LOCKS_REQUIRED(mutex_) {
+ switch (state_) {
+ case WatchdogState::ACTIVE:
+ return "ACTIVE";
+ case WatchdogState::INACTIVE:
+ return "INACTIVE";
+ case WatchdogState::BARKING:
+ return "BARKING";
+ case WatchdogState::DESTROYED:
+ return "DESTROYED";
+ }
+ }
+
+ util::StatusOr Activate() override LOCKS_EXCLUDED(mutex_);
+ util::Status Signal() override LOCKS_EXCLUDED(mutex_);
+ util::Status Deactivate() override LOCKS_EXCLUDED(mutex_);
+ util::Status UpdateTimeout(int64 timeout_ns) override LOCKS_EXCLUDED(mutex_);
+
+ private:
+ // This function runs the watch thread that periodically checks the last time
+ // we heard anything.
+ void Watcher();
+
+ // Validates that the watchdog is currently active.
+ util::Status ValidateActive() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Callback function for when we time out.
+ const Expire expire_;
+
+ // The amount of time watchdog has to be active and not get a signal in order
+ // for it to expire.
+ int64 timeout_ns_;
+
+ // The timer to be used for keeping track of expiration deadlines.
+ std::unique_ptr timer_;
+
+ // A single mutex to protect mutable fields in this class.
+ std::mutex mutex_;
+
+ // Watchdog state machine:
+ WatchdogState state_ GUARDED_BY(mutex_){WatchdogState::INACTIVE};
+
+ // An id to verify the origin of an expiration callback.
+ int64 activation_id_ GUARDED_BY(mutex_){0};
+
+ // The watcher thread that runs Watcher() method.
+ std::thread watcher_thread_;
+};
+
+// A wrapper around Watchdog that keeps track of device/code-state health by
+// keeping track of the number of things in a pipeline.
+class CountingWatch {
+ public:
+ // Constructor expects a configured watchdog. Its expiration callback is
+ // called if Decrement is not called within the timeout and counter is not 0.
+ explicit CountingWatch(std::unique_ptr watchdog)
+ : watchdog_(std::move(watchdog)) {}
+
+ ~CountingWatch();
+
+ // Increments the number of elements in the pipeline by 1. This will result in
+ // activating the watchdog.
+ util::Status Increment() LOCKS_EXCLUDED(mutex_);
+
+ // Decrements the number of elements in the pipeline. It fails if counter has
+ // already reached 0.
+ util::Status Decrement() LOCKS_EXCLUDED(mutex_);
+
+ private:
+ // The watchdog we are wrapping.
+ std::unique_ptr watchdog_;
+
+ // A mutex to ensure thread-safety for accessing members.
+ std::mutex mutex_;
+
+ // A counter to keep track of number of elements in the pipeline.
+ int64 counter_ GUARDED_BY(mutex_) = 0;
+};
+
+// CascadeWatchdog is a multi-level watchdog that has an expiration callback and
+// timeout for each level. After activation, if first level timeout expires,
+// its callback function gets called and the second watch gets activated
+// immediately after. Signaling or de-activating this watchdog resets everything
+// back to first level.
+class CascadeWatchdog : public Watchdog {
+ public:
+ // Encapsulates the configuration needed for each level in the cascade.
+ struct Config {
+ // Expiration function for when this watch level expires.
+ Expire expire;
+
+ // Timeout for triggering the watch (relative to the previous level).
+ int64 timeout_ns;
+ };
+
+ // Creates a CascadeWatchdog provided a vector of configs. The configs are
+ // used in the provided order meaning the first callback to get triggered is
+ // the one in configs[0]. There has to be at least one config.
+ explicit CascadeWatchdog(const std::vector& configs);
+
+ ~CascadeWatchdog() override;
+
+ // This class is movable.
+ CascadeWatchdog(CascadeWatchdog&& rhs);
+ CascadeWatchdog& operator=(CascadeWatchdog&& rhs);
+
+ // This class is not copyable.
+ CascadeWatchdog(const CascadeWatchdog&) = delete;
+ CascadeWatchdog& operator=(const CascadeWatchdog&) = delete;
+
+ util::StatusOr Activate() override LOCKS_EXCLUDED(mutex_);
+ util::Status Signal() override LOCKS_EXCLUDED(mutex_);
+ util::Status Deactivate() override LOCKS_EXCLUDED(mutex_);
+
+ // Updates the timeout of the first child watchdog (the first one that expires
+ // ). Use the overloaded method for updating timeouts of other child
+ // watchdogs.
+ util::Status UpdateTimeout(int64 timeout_ns) override;
+
+ // Updates the timeout of the child watchdog at the provided index.
+ util::Status UpdateTimeout(int child_index, int64 timeout_ns);
+
+ protected:
+ // A method that can create and return a child watchdog to be used here.
+ using WatchdogMaker = std::function(int64, Expire)>;
+
+ // A constructor that accepts a WatchdogMaker to use for creating the child
+ // watchdogs.
+ CascadeWatchdog(const std::vector& configs,
+ WatchdogMaker make_watchdog);
+
+ // A vector of the underlying child watchdogs in the same order as configs.
+ std::vector> watchdogs_;
+
+ private:
+ // The method that gets called in any of the child watchdogs expire.
+ void WatchdogExpired(int64 child_activation_id, int child_id)
+ LOCKS_EXCLUDED(mutex_);
+
+ // The function responsible for executing expiration callbacks.
+ void CallbackExecutor();
+
+ // Start the first watchdog. Called by Activate and Signal.
+ util::Status StartFirstWatchdog() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // Implement actual Deactivate method here to simplify some mutex locking.
+ util::Status DeactivateInternal() EXCLUSIVE_LOCKS_REQUIRED(mutex_);
+
+ // The list of watchdog configs as provided by the object owner.
+ const std::vector configs_;
+
+ // A mutex to protect mutable class fields.
+ std::mutex mutex_;
+
+ // Specifies which child watchdog is currently active. It can be used as an
+ // index to configs_ or watchdogs_. -1 means all watchdogs are inactive.
+ static constexpr int kNoneActive = -1;
+ int currently_active_ GUARDED_BY(mutex_){kNoneActive};
+
+ // The current/last generated activation ID for the caller of Activate on this
+ // class.
+ int64 activation_id_ GUARDED_BY(mutex_){0};
+
+ // At any given point in time at most 1 child watchdog is active. This field
+ // specifies the activation ID of that watchdog.
+ int64 child_activation_id_ GUARDED_BY(mutex_){0};
+
+ // A list of expiration callbacks that need to be executed.
+ std::vector> expirations_ GUARDED_BY(mutex_);
+
+ // To notify that at least one child watchdog has expired.
+ std::condition_variable child_expired_;
+
+ // The thread that executes expiration callbacks.
+ std::thread expiration_callback_thread_;
+
+ // Specifies if watchdog is alive. This is used in the destructor to signal
+ // other threads that it is time to quit.
+ bool is_alive_ GUARDED_BY(mutex_){true};
+};
+
+} // namespace api
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_API_WATCHDOG_H_
diff --git a/bazel/WORKSPACE b/bazel/WORKSPACE
new file mode 100644
index 0000000..f9cb049
--- /dev/null
+++ b/bazel/WORKSPACE
@@ -0,0 +1,63 @@
+# Copyright 2019 Google LLC
+#
+# 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
+#
+# https://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.
+workspace(name = "libedgetpu")
+
+load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
+
+http_archive(
+ name = "io_bazel_rules_closure",
+ sha256 = "5b00383d08dd71f28503736db0500b6fb4dda47489ff5fc6bed42557c07c6ba9",
+ strip_prefix = "rules_closure-308b05b2419edb5c8ee0471b67a40403df940149",
+ urls = [
+ "http://mirror.tensorflow.org/github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz",
+ "https://github.com/bazelbuild/rules_closure/archive/308b05b2419edb5c8ee0471b67a40403df940149.tar.gz", # 2019-06-13
+ ],
+)
+
+# Be consistent with tensorflow/WORKSPACE.
+http_archive(
+ name = "bazel_skylib",
+ sha256 = "1dde365491125a3db70731e25658dfdd3bc5dbdfd11b840b3e987ecf043c7ca0",
+ urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/0.9.0/bazel_skylib-0.9.0.tar.gz"],
+) # https://github.com/bazelbuild/bazel-skylib/releases
+
+# The TF commit # here must be in sync with that specified under Gob edgetpu
+# repo WORKSPACE file.
+# TODO: figure out a way to keep single source of truth of the
+# TF commit # used.
+TENSORFLOW_COMMIT = "f394a768719a55b5c351ed1ecab2ec6f16f99dd4";
+# Command to calculate: curl -OL | sha256sum | awk '{print $1}'
+TENSORFLOW_SHA256 = "cb286abee7ee9cf5c8701d85fcc88f0fd59e72492ec4f254156de486e3e905c1"
+http_archive(
+ name = "org_tensorflow",
+ sha256 = TENSORFLOW_SHA256,
+ strip_prefix = "tensorflow-" + TENSORFLOW_COMMIT,
+ urls = [
+ "https://github.com/tensorflow/tensorflow/archive/" + TENSORFLOW_COMMIT + ".tar.gz",
+ ],
+)
+
+load("@org_tensorflow//tensorflow:workspace.bzl", "tf_workspace")
+tf_workspace(tf_repo_name = "org_tensorflow")
+
+http_archive(
+ name = "coral_crosstool",
+ sha256 = "cb31b1417ccdcf7dd9fca5ec63e1571672372c30427730255997a547569d2feb",
+ strip_prefix = "crosstool-9e00d5be43bf001f883b5700f5d04882fea00229",
+ urls = [
+ "https://github.com/google-coral/crosstool/archive/9e00d5be43bf001f883b5700f5d04882fea00229.tar.gz",
+ ],
+)
+load("@coral_crosstool//:configure.bzl", "cc_crosstool")
+cc_crosstool(name = "crosstool")
diff --git a/bazel/WORKSPACE.darwin b/bazel/WORKSPACE.darwin
new file mode 100644
index 0000000..ad08cb5
--- /dev/null
+++ b/bazel/WORKSPACE.darwin
@@ -0,0 +1,13 @@
+# Use libusb from MacPorts.
+new_local_repository(
+ name = "libusb",
+ path = "/opt/local/include/",
+ build_file_content = """
+cc_library(
+ name = "headers",
+ includes = ["."],
+ hdrs = ["libusb-1.0/libusb.h"],
+ visibility = ["//visibility:public"],
+)
+"""
+)
diff --git a/bazel/WORKSPACE.linux b/bazel/WORKSPACE.linux
new file mode 100644
index 0000000..c33e185
--- /dev/null
+++ b/bazel/WORKSPACE.linux
@@ -0,0 +1,12 @@
+new_local_repository(
+ name = "libusb",
+ path = "/usr/include/",
+ build_file_content = """
+cc_library(
+ name = "headers",
+ includes = ["."],
+ hdrs = ["libusb-1.0/libusb.h"],
+ visibility = ["//visibility:public"],
+)
+"""
+)
diff --git a/bazel/WORKSPACE.windows b/bazel/WORKSPACE.windows
new file mode 100644
index 0000000..9994174
--- /dev/null
+++ b/bazel/WORKSPACE.windows
@@ -0,0 +1,21 @@
+# For Windows, extract libusb archive to ../libusb-1.0.22
+# Unfortunately, can't use http_archive here, as bazel doesn't support 7z.
+# https://github.com/libusb/libusb/releases/download/v1.0.22/libusb-1.0.22.7z
+new_local_repository(
+ name = "libusb",
+ path = "../libusb-1.0.22",
+ build_file_content = """
+cc_library(
+ name = "headers",
+ includes = ["include"],
+ hdrs = ["include/libusb-1.0/libusb.h"],
+ visibility = ["//visibility:public"],
+)
+cc_import(
+ name = "shared",
+ interface_library = "MS64/dll/libusb-1.0.lib",
+ shared_library = "MS64/dll/libusb-1.0.dll",
+ visibility = ["//visibility:public"],
+)
+"""
+)
\ No newline at end of file
diff --git a/build.bat b/build.bat
new file mode 100644
index 0000000..12d0acc
--- /dev/null
+++ b/build.bat
@@ -0,0 +1,74 @@
+:: Copyright 2019 Google LLC
+::
+:: 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
+::
+:: https://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.
+echo off
+
+setlocal
+
+set THROTTLED=0
+set COMPILATION_MODE=opt
+set OUT_DIR=%~dp0\out
+set CPU=x64_windows
+
+:PROCESSARGS
+set ARG=%1
+if defined ARG (
+ if "%ARG%"=="/DBG" (
+ set COMPILATION_MODE=dbg
+ ) else (
+ set LEFTOVER_ARGS=%LEFTOVER_ARGS% %ARG%
+ )
+ shift
+ goto PROCESSARGS
+)
+
+set BAZEL_INFO_FLAGS=^
+--experimental_repo_remote_exec
+for /f %%i in ('bazel info %BAZEL_INFO_FLAGS% output_path') do set "BAZEL_OUTPUT_PATH=%%i"
+set BAZEL_OUTPUT_PATH=%BAZEL_OUTPUT_PATH:/=\%
+set BAZEL_OUT_DIR=%BAZEL_OUTPUT_PATH%\%CPU%-%COMPILATION_MODE%\bin
+
+
+set TARGET=//tflite/public:edgetpu_direct_usb.dll
+set BAZEL_VS=C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools
+set BAZEL_VC=C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC
+set BAZEL_BUILD_FLAGS= ^
+--experimental_repo_remote_exec ^
+--compilation_mode %COMPILATION_MODE% ^
+--define darwinn_portable=1 ^
+--copt=/DSTRIP_LOG=1 ^
+--copt=/DABSL_FLAGS_STRIP_NAMES ^
+--copt=/DEDGETPU_EXTERNAL_RELEASE_RUNTIME ^
+--copt=/GR- ^
+--copt=/DWIN32_LEAN_AND_MEAN ^
+--copt=/D_WINSOCKAPI_ ^
+--copt=/std:c++latest
+
+call "%BAZEL_VC%\Auxiliary\Build\vcvars64.bat"
+
+bazel build %BAZEL_BUILD_FLAGS% %LEFTOVER_ARGS% %TARGET%
+md %OUT_DIR%\direct\%CPU%
+copy %BAZEL_OUT_DIR%\tflite\public\edgetpu_direct_usb.dll ^
+ %OUT_DIR%\direct\%CPU%\
+python %~dp0\rename_library.py ^
+ --input_dll %OUT_DIR%\direct\%CPU%\edgetpu_direct_usb.dll ^
+ --output_dll %OUT_DIR%\direct\%CPU%\edgetpu.dll
+
+set BAZEL_BUILD_FLAGS=%BAZEL_BUILD_FLAGS% --copt=/DTHROTTLE_EDGE_TPU
+bazel build %BAZEL_BUILD_FLAGS% %LEFTOVER_ARGS% %TARGET%
+md %OUT_DIR%\throttled\%CPU%
+copy %BAZEL_OUT_DIR%\tflite\public\edgetpu_direct_usb.dll ^
+ %OUT_DIR%\throttled\%CPU%\
+python %~dp0\rename_library.py ^
+ --input_dll %OUT_DIR%\throttled\%CPU%\edgetpu_direct_usb.dll ^
+ --output_dll %OUT_DIR%\throttled\%CPU%\edgetpu.dll
\ No newline at end of file
diff --git a/build_defs.bzl b/build_defs.bzl
new file mode 100644
index 0000000..5d465fb
--- /dev/null
+++ b/build_defs.bzl
@@ -0,0 +1,13 @@
+"""Utilities for darwinn."""
+
+def darwinn_port_defines():
+ """Generates a list of port defines suitable for the build.
+
+ Returns:
+ List of defines.
+ """
+ return select({
+ "//:darwinn_portable": ["DARWINN_PORT_DEFAULT"],
+ "//:darwinn_firmware": ["DARWINN_PORT_FIRMWARE"],
+ "//conditions:default": ["DARWINN_PORT_GOOGLE3"],
+ })
diff --git a/driver/BUILD b/driver/BUILD
new file mode 100644
index 0000000..49d6e9d
--- /dev/null
+++ b/driver/BUILD
@@ -0,0 +1,454 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# Portable DarwiNN driver implementation.
+
+package(
+ default_visibility = ["//visibility:public"],
+)
+
+licenses(["notice"])
+
+exports_files(["libdarwinn_driver.lds"])
+
+# Utility functions.
+cc_library(
+ name = "util",
+ hdrs = [
+ "bitfield.h",
+ ],
+ deps = [
+ "//port:integral_types",
+ "//port:logging",
+ ],
+)
+
+cc_library(
+ name = "allocator",
+ srcs = [
+ "aligned_allocator.cc",
+ "allocator.cc",
+ ],
+ hdrs = [
+ "aligned_allocator.h",
+ "allocator.h",
+ ],
+ deps = [
+ "//api:allocated_buffer",
+ "//api:buffer",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "device_buffer",
+ srcs = ["device_buffer.cc"],
+ hdrs = ["device_buffer.h"],
+ deps = [
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "executable_util",
+ srcs = ["executable_util.cc"],
+ hdrs = ["executable_util.h"],
+ deps = [
+ "//api:buffer",
+ "//executable:executable_fbs",
+ "//port",
+ ],
+)
+
+# Driver Factory.
+cc_library(
+ name = "driver_factory",
+ srcs = ["driver_factory.cc"] + select({
+ "//:windows": ["driver_factory_windows.cc"],
+ "//:darwin": ["driver_factory_darwin.cc"],
+ "//conditions:default": ["driver_factory_default.cc"],
+ }),
+ hdrs = [
+ "driver_factory.h",
+ ],
+ deps = [
+ ":driver",
+ "//api:chip",
+ "//api:driver",
+ "//api:driver_factory",
+ "//api:driver_options_fbs",
+ "//api:driver_options_helper",
+ "//driver/config",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ ],
+)
+
+cc_library(
+ name = "driver_helper",
+ srcs = ["driver_helper.cc"],
+ hdrs = ["driver_helper.h"],
+ deps = [
+ ":executable_util",
+ ":package_registry",
+ ":test_vector",
+ "//api:buffer",
+ "//api:chip",
+ "//api:driver",
+ "//api:package_reference",
+ "//api:request",
+ "//api:telemeter_interface",
+ "//api:timing",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ ],
+)
+
+cc_library(
+ name = "instruction_buffers",
+ srcs = ["instruction_buffers.cc"],
+ hdrs = ["instruction_buffers.h"],
+ deps = [
+ ":allocator",
+ ":device_buffer_mapper",
+ ":executable_util",
+ "//api:buffer",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "run_controller",
+ srcs = ["run_controller.cc"],
+ hdrs = ["run_controller.h"],
+ deps = [
+ ":hardware_structures",
+ "//driver/config",
+ "//driver/config:register_constants",
+ "//driver/registers",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "scalar_core_controller",
+ srcs = ["scalar_core_controller.cc"],
+ hdrs = ["scalar_core_controller.h"],
+ deps = [
+ "//driver/config",
+ "//driver/interrupt:interrupt_controller",
+ "//driver/registers",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ ],
+)
+
+cc_library(
+ name = "hardware_structures",
+ hdrs = ["hardware_structures.h"],
+ deps = [
+ "//port:integral_types",
+ "//port:macros",
+ ],
+)
+
+cc_library(
+ name = "driver",
+ srcs = ["driver.cc"],
+ hdrs = ["driver.h"],
+ deps = [
+ ":default_telemeter",
+ ":device_buffer_mapper",
+ ":package_registry",
+ ":request",
+ ":tpu_request",
+ "@com_google_absl//absl/strings:str_format",
+ "//api:buffer",
+ "//api:chip",
+ "//api:driver",
+ "//api:execution_context_interface",
+ "//api:package_reference",
+ "//api:request",
+ "//api:telemeter_interface",
+ "//driver/memory:dma_direction",
+ "//driver/time_stamper",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:blocking_counter",
+ "//port:shared_mutex",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "default_telemeter",
+ hdrs = ["default_telemeter.h"],
+ deps = [
+ "//api:telemeter_interface",
+ ],
+)
+
+cc_library(
+ name = "mmio_driver",
+ srcs = ["mmio_driver.cc"],
+ hdrs = ["mmio_driver.h"],
+ deps = [
+ ":allocator",
+ ":device_buffer",
+ ":device_buffer_mapper",
+ ":dma_info_extractor",
+ ":driver",
+ ":hardware_structures",
+ ":package_registry",
+ ":real_time_dma_scheduler",
+ ":run_controller",
+ ":scalar_core_controller",
+ ":single_tpu_request",
+ ":top_level_handler",
+ ":tpu_request",
+ "//api:allocated_buffer",
+ "//api:buffer",
+ "//api:watchdog",
+ "//driver/config",
+ "//driver/config:register_constants",
+ "//driver/interrupt:interrupt_controller_interface",
+ "//driver/interrupt:interrupt_handler",
+ "//driver/interrupt:top_level_interrupt_manager",
+ "//driver/memory:address_space",
+ "//driver/memory:address_utilities",
+ "//driver/memory:dma_direction",
+ "//driver/memory:dram_allocator",
+ "//driver/memory:mmu_mapper",
+ "//driver/mmio:host_queue",
+ "//driver/registers",
+ "//driver/time_stamper",
+ "//driver/time_stamper:driver_time_stamper",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "dma_info",
+ srcs = ["dma_info.cc"],
+ hdrs = ["dma_info.h"],
+ deps = [
+ ":device_buffer",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "device_buffer_mapper",
+ srcs = ["device_buffer_mapper.cc"],
+ hdrs = ["device_buffer_mapper.h"],
+ deps = [
+ ":device_buffer",
+ ":hardware_structures",
+ "//api:buffer",
+ "//driver/memory:address_space",
+ "//driver/memory:address_utilities",
+ "//driver/memory:dma_direction",
+ "//port",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "dma_info_extractor",
+ srcs = ["dma_info_extractor.cc"],
+ hdrs = ["dma_info_extractor.h"],
+ deps = [
+ ":device_buffer_mapper",
+ ":dma_info",
+ ":package_registry",
+ "//driver/memory:address_utilities",
+ "//executable:executable_fbs",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "dma_scheduler",
+ hdrs = ["dma_scheduler.h"],
+ deps = [
+ ":dma_info",
+ ":tpu_request",
+ "//api:driver",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "single_queue_dma_scheduler",
+ srcs = ["single_queue_dma_scheduler.cc"],
+ hdrs = ["single_queue_dma_scheduler.h"],
+ deps = [
+ ":dma_info",
+ ":dma_scheduler",
+ ":tpu_request",
+ "//api:driver",
+ "//api:watchdog",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "real_time_dma_scheduler",
+ srcs = ["real_time_dma_scheduler.cc"],
+ hdrs = ["real_time_dma_scheduler.h"],
+ deps = [
+ ":dma_info",
+ ":dma_scheduler",
+ ":package_registry",
+ ":single_queue_dma_scheduler",
+ ":tpu_request",
+ "@com_google_absl//absl/strings:str_format",
+ "//api:driver",
+ "//api:package_reference",
+ "//api:timing",
+ "//api:watchdog",
+ "//driver/time_stamper",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ ],
+)
+
+cc_library(
+ name = "dma_chunker",
+ srcs = ["dma_chunker.cc"],
+ hdrs = ["dma_chunker.h"],
+ deps = [
+ ":device_buffer",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "top_level_handler",
+ hdrs = ["top_level_handler.h"],
+ deps = ["//port"],
+)
+
+cc_library(
+ name = "package_registry",
+ srcs = ["package_registry.cc"],
+ hdrs = ["package_registry.h"],
+ deps = [
+ ":allocator",
+ ":device_buffer_mapper",
+ ":instruction_buffers",
+ ":package_verifier",
+ "//api:buffer",
+ "//api:chip",
+ "//api:driver_options_fbs",
+ "//api:execution_context_interface",
+ "//api:layer_information",
+ "//api:package_reference",
+ "//api:runtime_version",
+ "//driver/memory:dram_allocator",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "package_verifier",
+ srcs = ["package_verifier.cc"],
+ hdrs = ["package_verifier.h"],
+ deps = [
+ "//executable:executable_fbs",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "tpu_request",
+ hdrs = ["tpu_request.h"],
+ deps = [
+ ":dma_info",
+ ":package_registry",
+ "//api:buffer",
+ "//api:request",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "single_tpu_request",
+ srcs = ["single_tpu_request.cc"],
+ hdrs = ["single_tpu_request.h"],
+ deps = [
+ ":allocator",
+ ":device_buffer",
+ ":device_buffer_mapper",
+ ":dma_info",
+ ":dma_info_extractor",
+ ":executable_util",
+ ":hardware_structures",
+ ":instruction_buffers",
+ ":package_registry",
+ ":request",
+ ":tpu_request",
+ "//api:allocated_buffer",
+ "//api:buffer",
+ "//driver/memory:address_space",
+ "//driver/memory:dram_allocator",
+ "//executable:executable_fbs",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+cc_library(
+ name = "request",
+ srcs = ["request.cc"],
+ hdrs = ["request.h"],
+ deps = [
+ ":tpu_request",
+ "//api:request",
+ "//driver/time_stamper",
+ "//driver/time_stamper:driver_time_stamper_factory",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ "//port:tracing",
+ ],
+)
+
+filegroup(
+ name = "linker_script",
+ srcs = ["libdarwinn_driver.lds"],
+)
diff --git a/driver/aligned_allocator.cc b/driver/aligned_allocator.cc
new file mode 100644
index 0000000..0896b06
--- /dev/null
+++ b/driver/aligned_allocator.cc
@@ -0,0 +1,45 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/aligned_allocator.h"
+
+#include
+#include
+
+#include "port/aligned_malloc.h"
+#include "port/integral_types.h"
+#include "port/logging.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+AlignedAllocator::AlignedAllocator(uint64 alignment_bytes)
+ : alignment_bytes_(alignment_bytes) {
+ // Check for power of 2, since we use arithmetic that relies on it elsewhere.
+ CHECK_EQ((alignment_bytes - 1) & alignment_bytes, 0);
+}
+
+void* AlignedAllocator::Allocate(size_t size) {
+ int aligned_size = (size + alignment_bytes_ - 1) & ~(alignment_bytes_ - 1);
+ return aligned_malloc(aligned_size, alignment_bytes_);
+}
+
+void AlignedAllocator::Free(void* aligned_memory) {
+ aligned_free(aligned_memory);
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/aligned_allocator.h b/driver/aligned_allocator.h
new file mode 100644
index 0000000..89aede7
--- /dev/null
+++ b/driver/aligned_allocator.h
@@ -0,0 +1,51 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_ALIGNED_ALLOCATOR_H_
+#define DARWINN_DRIVER_ALIGNED_ALLOCATOR_H_
+
+#include
+
+#include "driver/allocator.h"
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Convenience class to allocate aligned buffers.
+class AlignedAllocator : public Allocator {
+ public:
+ // All allocated buffers will be aligned to |alignment_bytes| with a size
+ // granulairy of |alignment_bytes|.
+ explicit AlignedAllocator(uint64 alignment_bytes);
+ ~AlignedAllocator() = default;
+
+ // This class is neither copyable nor movable.
+ AlignedAllocator(const AlignedAllocator&) = delete;
+ AlignedAllocator& operator=(const AlignedAllocator&) = delete;
+
+ void* Allocate(size_t size) override;
+ void Free(void* aligned_memory) override;
+
+ private:
+ // Alignment
+ const uint64 alignment_bytes_;
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_ALIGNED_ALLOCATOR_H_
diff --git a/driver/allocator.cc b/driver/allocator.cc
new file mode 100644
index 0000000..6a16e8f
--- /dev/null
+++ b/driver/allocator.cc
@@ -0,0 +1,39 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/allocator.h"
+
+#include
+#include
+
+#include "api/allocated_buffer.h"
+#include "api/buffer.h"
+#include "port/integral_types.h"
+#include "port/ptr_util.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+Buffer Allocator::MakeBuffer(size_t size_bytes) {
+ auto free_cb = [this](void* ptr) { Free(ptr); };
+
+ uint8* ptr = static_cast(Allocate(size_bytes));
+ return Buffer(
+ std::make_shared(ptr, size_bytes, std::move(free_cb)));
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/allocator.h b/driver/allocator.h
new file mode 100644
index 0000000..ad300ca
--- /dev/null
+++ b/driver/allocator.h
@@ -0,0 +1,47 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_ALLOCATOR_H_
+#define DARWINN_DRIVER_ALLOCATOR_H_
+
+#include
+
+#include "api/buffer.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Interface for a class that can allocate host memory.
+class Allocator {
+ public:
+ virtual ~Allocator() = default;
+
+ // Allocates buffer of specified size.
+ virtual void* Allocate(size_t size) = 0;
+
+ // Frees a previous allocated buffer.
+ virtual void Free(void* buffer) = 0;
+
+ // Allocates and returns a buffer of the specified size. The lifecycle of the
+ // the returned buffer is tied to the Allocator instance. It is thus important
+ // to ensure that the allocator class outlives the returned buffer instances.
+ Buffer MakeBuffer(size_t size_bytes);
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_ALLOCATOR_H_
diff --git a/driver/beagle/BUILD b/driver/beagle/BUILD
new file mode 100644
index 0000000..b38a989
--- /dev/null
+++ b/driver/beagle/BUILD
@@ -0,0 +1,259 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# Beagle Specific functionality.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+# Provides Beagle USB Driver for internal (=no_external_release) usage.
+# libUSB is statically linked in this version.
+cc_library(
+ name = "beagle_usb_driver_provider_no_external_release",
+ srcs = ["beagle_usb_driver_provider.cc"],
+ deps = [
+ ":beagle_top_level_handler",
+ ":beagle_top_level_interrupt_manager",
+ "@com_google_absl//absl/strings",
+ "//api:chip",
+ "//api:driver",
+ "//api:driver_options_fbs",
+ "//driver:allocator",
+ "//driver:driver_factory",
+ "//driver:package_registry",
+ "//driver:package_verifier",
+ "//driver:run_controller",
+ "//driver:scalar_core_controller",
+ "//driver/config/beagle:beagle_chip_config",
+ "//driver/interrupt:grouped_interrupt_controller",
+ "//driver/interrupt:interrupt_controller",
+ "//driver/interrupt:interrupt_controller_interface",
+ "//driver/memory:null_dram_allocator",
+ "//driver/time_stamper:driver_time_stamper",
+ "//driver/usb:local_usb_device_no_external_release",
+ "//driver/usb:usb_device_interface",
+ "//driver/usb:usb_driver",
+ "//driver/usb:usb_ml_commands",
+ "//driver/usb:usb_registers",
+ "//port",
+ "//port:tracing",
+ ],
+ alwayslink = 1,
+)
+
+# Provides Beagle USB Driver.
+# libUSB is dynamically linked in this version.
+cc_library(
+ name = "beagle_usb_driver_provider",
+ srcs = ["beagle_usb_driver_provider.cc"],
+ deps = [
+ ":beagle_top_level_handler",
+ ":beagle_top_level_interrupt_manager",
+ "@com_google_absl//absl/strings",
+ "//api:chip",
+ "//api:driver",
+ "//api:driver_options_fbs",
+ "//driver:allocator",
+ "//driver:driver_factory",
+ "//driver:package_registry",
+ "//driver:package_verifier",
+ "//driver:run_controller",
+ "//driver:scalar_core_controller",
+ "//driver/config/beagle:beagle_chip_config",
+ "//driver/interrupt:grouped_interrupt_controller",
+ "//driver/interrupt:interrupt_controller",
+ "//driver/interrupt:interrupt_controller_interface",
+ "//driver/memory:null_dram_allocator",
+ "//driver/time_stamper:driver_time_stamper",
+ "//driver/usb:local_usb_device",
+ "//driver/usb:usb_device_interface",
+ "//driver/usb:usb_driver",
+ "//driver/usb:usb_ml_commands",
+ "//driver/usb:usb_registers",
+ "//port",
+ "//port:tracing",
+ ],
+ alwayslink = 1,
+)
+
+# Provides Beagle PCI Driver.
+cc_library(
+ name = "beagle_pci_driver_provider",
+ srcs = ["beagle_pci_driver_provider.cc"],
+ deps = [
+ ":beagle_kernel_top_level_handler",
+ "//api:chip",
+ "//api:driver",
+ "//driver:allocator",
+ "//driver:driver_factory",
+ "//driver:hardware_structures",
+ "//driver:mmio_driver",
+ "//driver:package_registry",
+ "//driver:package_verifier",
+ "//driver:run_controller",
+ "//driver:scalar_core_controller",
+ "//driver/config",
+ "//driver/config/beagle:beagle_chip_config",
+ "//driver/interrupt:dummy_interrupt_controller",
+ "//driver/interrupt:grouped_interrupt_controller",
+ "//driver/interrupt:interrupt_handler",
+ "//driver/interrupt:top_level_interrupt_manager",
+ "//driver/kernel:kernel_coherent_allocator",
+ "//driver/kernel:kernel_interrupt_handler",
+ "//driver/kernel:kernel_mmu_mapper",
+ "//driver/kernel:kernel_registers",
+ "//driver/kernel:kernel_wire_interrupt_handler",
+ "//driver/memory:dual_address_space",
+ "//driver/memory:null_dram_allocator",
+ "//driver/mmio:host_queue",
+ "//driver/time_stamper:driver_time_stamper",
+ "//port",
+ ],
+ alwayslink = 1,
+)
+
+# Provides Beagle USB/PCI Driver. Used by an Android side script to
+# populate dependencies for a unified Beagle provider in Beagle NNAPI HAL.
+cc_library(
+ name = "beagle_all_driver_provider",
+ srcs = [
+ "beagle_pci_driver_provider.cc",
+ "beagle_usb_driver_provider.cc",
+ ],
+ deps = [
+ ":beagle_kernel_top_level_handler",
+ ":beagle_top_level_handler",
+ ":beagle_top_level_interrupt_manager",
+ "@com_google_absl//absl/strings",
+ "//api:chip",
+ "//api:driver",
+ "//api:driver_options_fbs",
+ "//driver:allocator",
+ "//driver:driver_factory",
+ "//driver:hardware_structures",
+ "//driver:mmio_driver",
+ "//driver:package_registry",
+ "//driver:package_verifier",
+ "//driver:run_controller",
+ "//driver:scalar_core_controller",
+ "//driver/config",
+ "//driver/config/beagle:beagle_chip_config",
+ "//driver/interrupt:dummy_interrupt_controller",
+ "//driver/interrupt:grouped_interrupt_controller",
+ "//driver/interrupt:interrupt_controller",
+ "//driver/interrupt:interrupt_controller_interface",
+ "//driver/interrupt:interrupt_handler",
+ "//driver/interrupt:top_level_interrupt_manager",
+ "//driver/kernel:kernel_coherent_allocator",
+ "//driver/kernel:kernel_interrupt_handler",
+ "//driver/kernel:kernel_mmu_mapper",
+ "//driver/kernel:kernel_registers",
+ "//driver/kernel:kernel_wire_interrupt_handler",
+ "//driver/memory:dual_address_space",
+ "//driver/memory:null_dram_allocator",
+ "//driver/mmio:host_queue",
+ "//driver/time_stamper:driver_time_stamper",
+ "//driver/usb:local_usb_device",
+ "//driver/usb:usb_device_interface",
+ "//driver/usb:usb_driver",
+ "//driver/usb:usb_ml_commands",
+ "//driver/usb:usb_registers",
+ "//port",
+ "//port:tracing",
+ ],
+ alwayslink = 1,
+)
+
+cc_library(
+ name = "beagle_top_level_interrupt_manager",
+ srcs = ["beagle_top_level_interrupt_manager.cc"],
+ hdrs = ["beagle_top_level_interrupt_manager.h"],
+ deps = [
+ "//driver/config",
+ "//driver/interrupt:interrupt_controller_interface",
+ "//driver/interrupt:top_level_interrupt_manager",
+ "//driver/registers",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "beagle_top_level_handler",
+ srcs = ["beagle_top_level_handler.cc"],
+ hdrs = ["beagle_top_level_handler.h"],
+ deps = [
+ "//api:driver_options_fbs",
+ "//driver:top_level_handler",
+ "//driver/config",
+ "//driver/registers",
+ "//port",
+ ],
+)
+
+cc_library(
+ name = "beagle_ioctl",
+ hdrs = ["beagle_ioctl.h"],
+)
+
+cc_library(
+ name = "beagle_kernel_top_level_handler",
+ srcs = ["beagle_kernel_top_level_handler.cc"],
+ hdrs = ["beagle_kernel_top_level_handler.h"],
+ deps = [
+ ":beagle_ioctl",
+ "//api:driver_options_fbs",
+ "//driver:top_level_handler",
+ "//port",
+ "//port:std_mutex_lock",
+ "//port:thread_annotations",
+ ],
+)
+
+# Standalone shared library that can be linked into a binary built elsewhere.
+cc_binary(
+ name = "libbeagle-usb.so",
+
+ # Setting DT_SONAME for the result .so.
+ # See b/72234056
+ linkopts = [
+ "-Wl,-soname,libbeagle-usb.so",
+ "-Wl,--version-script=$(location //driver:libdarwinn_driver.lds)",
+ ],
+ linkshared = 1,
+ linkstatic = 1,
+ deps = [
+ ":beagle_usb_driver_provider",
+ "//driver:libdarwinn_driver.lds",
+ ],
+)
+
+# Standalone shared library that can be linked into a binary built elsewhere.
+cc_binary(
+ name = "libbeagle-pci.so",
+
+ # Setting DT_SONAME for the result .so.
+ # See b/72234056
+ linkopts = [
+ "-Wl,-soname,libbeagle-pci.so",
+ "-Wl,--version-script=$(location //driver:libdarwinn_driver.lds)",
+ ],
+ linkshared = 1,
+ linkstatic = 1,
+ deps = [
+ ":beagle_pci_driver_provider",
+ "//driver:libdarwinn_driver.lds",
+ ],
+)
diff --git a/driver/beagle/beagle_ioctl.h b/driver/beagle/beagle_ioctl.h
new file mode 100644
index 0000000..5f2e44e
--- /dev/null
+++ b/driver/beagle/beagle_ioctl.h
@@ -0,0 +1,61 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+/*
+ * Apex kernel-userspace interface definitions.
+ */
+#ifndef __APEX_IOCTL_H__
+#define __APEX_IOCTL_H__
+
+#include
+#ifndef __KERNEL__
+#include
+#endif
+
+/* Clock Gating ioctl. */
+struct apex_gate_clock_ioctl {
+ /* Enter or leave clock gated state. */
+ uint64_t enable;
+
+ /* If set, enter clock gating state, regardless of custom block's
+ * internal idle state.
+ */
+ uint64_t force_idle;
+};
+
+/* Performance expectation ioctl. */
+enum apex_performance_expectation {
+ APEX_PERFORMANCE_LOW = 0,
+ APEX_PERFORMANCE_MED = 1,
+ APEX_PERFORMANCE_HIGH = 2,
+ APEX_PERFORMANCE_MAX = 3,
+};
+
+struct apex_performance_expectation_ioctl {
+ /* Expected performance from apex. */
+ uint32_t performance;
+};
+
+/* Base number for all Apex-common IOCTLs. */
+#define APEX_IOCTL_BASE 0x7F
+
+/* Enable/Disable clock gating. */
+#define APEX_IOCTL_GATE_CLOCK \
+ _IOW(APEX_IOCTL_BASE, 0, struct apex_gate_clock_ioctl)
+
+/* Change performance expectation. */
+#define APEX_IOCTL_PERFORMANCE_EXPECTATION \
+ _IOW(APEX_IOCTL_BASE, 1, struct apex_performance_expectation_ioctl)
+
+#endif /* __APEX_IOCTL_H__ */
diff --git a/driver/beagle/beagle_kernel_top_level_handler.cc b/driver/beagle/beagle_kernel_top_level_handler.cc
new file mode 100644
index 0000000..fd0df0d
--- /dev/null
+++ b/driver/beagle/beagle_kernel_top_level_handler.cc
@@ -0,0 +1,146 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/beagle/beagle_kernel_top_level_handler.h"
+
+#include
+#include
+#include
+#include
+
+#include "api/driver_options_generated.h"
+#include "driver/beagle/beagle_ioctl.h"
+#include "port/errors.h"
+#include "port/logging.h"
+#include "port/status.h"
+#include "port/status_macros.h"
+#include "port/std_mutex_lock.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+BeagleKernelTopLevelHandler::BeagleKernelTopLevelHandler(
+ const std::string &device_path, api::PerformanceExpectation performance)
+ : device_path_(device_path), performance_(performance) {}
+
+util::Status BeagleKernelTopLevelHandler::DisableSoftwareClockGate() {
+ StdMutexLock lock(&mutex_);
+
+ if (!clock_gated_) {
+ return util::Status(); // OK
+ }
+
+ apex_gate_clock_ioctl ioctl_buffer;
+ memset(&ioctl_buffer, 0, sizeof(ioctl_buffer));
+ ioctl_buffer.enable = 0;
+
+ if (ioctl(fd_, APEX_IOCTL_GATE_CLOCK, &ioctl_buffer) != 0) {
+ return util::FailedPreconditionError(StringPrintf(
+ "Could not Disable Clock Gating : %d (%s)", fd_, strerror(errno)));
+ }
+
+ clock_gated_ = false;
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleKernelTopLevelHandler::EnableSoftwareClockGate() {
+ StdMutexLock lock(&mutex_);
+
+ if (clock_gated_) {
+ return util::Status(); // OK
+ }
+
+ apex_gate_clock_ioctl ioctl_buffer;
+ memset(&ioctl_buffer, 0, sizeof(ioctl_buffer));
+ ioctl_buffer.enable = 1;
+
+ if (ioctl(fd_, APEX_IOCTL_GATE_CLOCK, &ioctl_buffer) != 0) {
+ return util::FailedPreconditionError(
+ StringPrintf("Could not Clock Gate : %d (%s)", fd_, strerror(errno)));
+ }
+
+ clock_gated_ = true;
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleKernelTopLevelHandler::Open() {
+ StdMutexLock lock(&mutex_);
+ if (fd_ != -1) {
+ return util::FailedPreconditionError("Device already open.");
+ }
+
+ fd_ = open(device_path_.c_str(), O_RDWR);
+ if (fd_ < 0) {
+ return util::FailedPreconditionError(
+ StringPrintf("Device open failed : %d (%s)", fd_, strerror(errno)));
+ }
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleKernelTopLevelHandler::Close() {
+ StdMutexLock lock(&mutex_);
+ if (fd_ == -1) {
+ return util::FailedPreconditionError("Device not open.");
+ }
+
+ close(fd_);
+ fd_ = -1;
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleKernelTopLevelHandler::QuitReset() {
+ apex_performance_expectation_ioctl ioctl_buffer;
+ memset(&ioctl_buffer, 0, sizeof(ioctl_buffer));
+
+ switch (performance_) {
+ case api::PerformanceExpectation_Low:
+ ioctl_buffer.performance = APEX_PERFORMANCE_LOW;
+ break;
+
+ case api::PerformanceExpectation_Medium:
+ ioctl_buffer.performance = APEX_PERFORMANCE_MED;
+ break;
+
+ case api::PerformanceExpectation_High:
+ ioctl_buffer.performance = APEX_PERFORMANCE_HIGH;
+ break;
+
+ case api::PerformanceExpectation_Max:
+ ioctl_buffer.performance = APEX_PERFORMANCE_MAX;
+ break;
+
+ default:
+ return util::InvalidArgumentError(
+ StringPrintf("Bad performance setting %d.", performance_));
+ }
+
+ StdMutexLock lock(&mutex_);
+ if (ioctl(fd_, APEX_IOCTL_PERFORMANCE_EXPECTATION, &ioctl_buffer) != 0) {
+ LOG(WARNING) << StringPrintf(
+ "Could not set performance expectation : %d (%s)", fd_,
+ strerror(errno));
+ }
+
+ return util::Status(); // OK
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/beagle/beagle_kernel_top_level_handler.h b/driver/beagle/beagle_kernel_top_level_handler.h
new file mode 100644
index 0000000..085cd01
--- /dev/null
+++ b/driver/beagle/beagle_kernel_top_level_handler.h
@@ -0,0 +1,64 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_BEAGLE_BEAGLE_KERNEL_TOP_LEVEL_HANDLER_H_
+#define DARWINN_DRIVER_BEAGLE_BEAGLE_KERNEL_TOP_LEVEL_HANDLER_H_
+
+#include // NOLINT
+
+#include "api/driver_options_generated.h"
+#include "driver/top_level_handler.h"
+#include "port/status.h"
+#include "port/thread_annotations.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Handles chip specific resets.
+class BeagleKernelTopLevelHandler : public TopLevelHandler {
+ public:
+ BeagleKernelTopLevelHandler(const std::string &device_path,
+ api::PerformanceExpectation performance);
+ ~BeagleKernelTopLevelHandler() override = default;
+
+ // Implements ResetHandler interface.
+ util::Status Open() override;
+ util::Status Close() override;
+ util::Status EnableSoftwareClockGate() override;
+ util::Status DisableSoftwareClockGate() override;
+ util::Status QuitReset() override;
+
+ private:
+ // Device path.
+ const std::string device_path_;
+
+ // File descriptor of the opened device.
+ int fd_ GUARDED_BY(mutex_){-1};
+
+ // Mutex that guards fd_.
+ std::mutex mutex_;
+
+ // Chip starts in clock gated state.
+ bool clock_gated_{true};
+
+ // Performance setting.
+ const api::PerformanceExpectation performance_;
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_BEAGLE_BEAGLE_KERNEL_TOP_LEVEL_HANDLER_H_
diff --git a/driver/beagle/beagle_pci_driver_provider.cc b/driver/beagle/beagle_pci_driver_provider.cc
new file mode 100644
index 0000000..a080221
--- /dev/null
+++ b/driver/beagle/beagle_pci_driver_provider.cc
@@ -0,0 +1,178 @@
+// Copyright 2019 Google LLC
+//
+// 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
+#include
+#include
+
+#include "api/chip.h"
+#include "api/driver.h"
+#include "driver/aligned_allocator.h"
+#include "driver/beagle/beagle_kernel_top_level_handler.h"
+#include "driver/config/beagle/beagle_chip_config.h"
+#include "driver/config/chip_structures.h"
+#include "driver/driver_factory.h"
+#include "driver/hardware_structures.h"
+#include "driver/interrupt/dummy_interrupt_controller.h"
+#include "driver/interrupt/grouped_interrupt_controller.h"
+#include "driver/interrupt/interrupt_handler.h"
+#include "driver/interrupt/top_level_interrupt_manager.h"
+#include "driver/kernel/kernel_coherent_allocator.h"
+#include "driver/kernel/kernel_interrupt_handler.h"
+#include "driver/kernel/kernel_mmu_mapper.h"
+#include "driver/kernel/kernel_registers.h"
+#include "driver/kernel/kernel_wire_interrupt_handler.h"
+#include "driver/memory/dual_address_space.h"
+#include "driver/memory/null_dram_allocator.h"
+#include "driver/mmio/host_queue.h"
+#include "driver/mmio_driver.h"
+#include "driver/package_registry.h"
+#include "driver/package_verifier.h"
+#include "driver/run_controller.h"
+#include "driver/scalar_core_controller.h"
+#include "driver/time_stamper/driver_time_stamper.h"
+#include "port/integral_types.h"
+#include "port/ptr_util.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace {
+
+using platforms::darwinn::api::Chip;
+using platforms::darwinn::api::Device;
+
+} // namespace
+
+class BeaglePciDriverProvider : public DriverProvider {
+ public:
+ static std::unique_ptr CreateDriverProvider() {
+ return gtl::WrapUnique(new BeaglePciDriverProvider());
+ }
+
+ ~BeaglePciDriverProvider() override = default;
+
+ std::vector Enumerate() override;
+ bool CanCreate(const Device& device) override;
+ util::StatusOr> CreateDriver(
+ const Device& device, const api::DriverOptions& options) override;
+
+ private:
+ BeaglePciDriverProvider() = default;
+};
+
+REGISTER_DRIVER_PROVIDER(BeaglePciDriverProvider);
+
+std::vector BeaglePciDriverProvider::Enumerate() {
+ return EnumerateSysfs("apex", Chip::kBeagle, Device::Type::PCI);
+}
+
+bool BeaglePciDriverProvider::CanCreate(const Device& device) {
+ return device.type == Device::Type::PCI && device.chip == Chip::kBeagle;
+}
+
+util::StatusOr>
+BeaglePciDriverProvider::CreateDriver(const Device& device,
+ const api::DriverOptions& options) {
+ if (!CanCreate(device)) {
+ return util::NotFoundError("Unsupported device.");
+ }
+
+ // TODO: Following queue size could come from a config.
+ constexpr int kInstructionQueueSize = 256;
+
+ // Coherent memory block granted to the Host Queue
+ constexpr int kCoherentAllocatorMaxSizeByte = 0x4000;
+
+ auto config = gtl::MakeUnique();
+
+ // Offsets are embedded in the CSR spec.
+ constexpr uint64 kTileConfig0Offset = 0x40000;
+ constexpr uint64 kScalarCoreOffset = 0x44000;
+ constexpr uint64 kUserHibOffset = 0x48000;
+
+ // Memory mapping must be aligned with page size. Assuming 4KB page size.
+ constexpr uint64 kSectionSize = 0x1000;
+
+ const std::vector regions = {
+ {kTileConfig0Offset, kSectionSize},
+ {kScalarCoreOffset, kSectionSize},
+ {kUserHibOffset, kSectionSize},
+ };
+ auto registers = gtl::MakeUnique(device.path, regions,
+ /*read_only=*/false);
+
+ auto interrupt_handler = gtl::MakeUnique(device.path);
+ auto top_level_handler = gtl::MakeUnique(
+ device.path, options.performance_expectation());
+ auto mmu_mapper = gtl::MakeUnique(device.path);
+ auto address_space = gtl::MakeUnique(
+ config->GetChipStructures(), mmu_mapper.get());
+ int allocation_alignment_bytes =
+ config->GetChipStructures().allocation_alignment_bytes;
+ auto allocator =
+ gtl::MakeUnique(allocation_alignment_bytes);
+ auto coherent_allocator = gtl::MakeUnique(
+ device.path, allocation_alignment_bytes, kCoherentAllocatorMaxSizeByte);
+ auto host_queue =
+ gtl::MakeUnique>(
+ config->GetInstructionQueueCsrOffsets(), config->GetChipStructures(),
+ registers.get(), std::move(coherent_allocator),
+ kInstructionQueueSize, /*single_descriptor_mode=*/false);
+
+ // Keeping the number of interrupt so MmioDriver would still register for four
+ // interrupt handlers.
+ constexpr int kNumTopLevelInterrupts = 4;
+ auto top_level_interrupt_controller =
+ gtl::MakeUnique(kNumTopLevelInterrupts);
+
+ // TODO Bridge top level interrupts to higher level logic.
+ // TopLevelInterruptManager initialized with DummyInterruptController leaves
+ // top level interrupts not really handled. We will have to further
+ // extend TopLevelInterruptManager to bridge top level interrupt to
+ // application/driver logic.
+ auto top_level_interrupt_manager = gtl::MakeUnique(
+ std::move(top_level_interrupt_controller));
+
+ auto fatal_error_interrupt_controller = gtl::MakeUnique(
+ config->GetFatalErrorInterruptCsrOffsets(), registers.get());
+ auto scalar_core_controller =
+ gtl::MakeUnique(*config, registers.get());
+ auto run_controller =
+ gtl::MakeUnique(*config, registers.get());
+
+ auto dram_allocator = gtl::MakeUnique();
+
+ ASSIGN_OR_RETURN(
+ auto verifier,
+ MakeExecutableVerifier(flatbuffers::GetString(options.public_key())));
+ auto executable_registry = gtl::MakeUnique(
+ device.chip, std::move(verifier), dram_allocator.get());
+ auto time_stamper = gtl::MakeUnique();
+
+ return {gtl::MakeUnique(
+ options, std::move(config), std::move(registers),
+ std::move(dram_allocator), std::move(mmu_mapper),
+ std::move(address_space), std::move(allocator), std::move(host_queue),
+ std::move(interrupt_handler), std::move(top_level_interrupt_manager),
+ std::move(fatal_error_interrupt_controller),
+ std::move(scalar_core_controller), std::move(run_controller),
+ std::move(top_level_handler), std::move(executable_registry),
+ std::move(time_stamper))};
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/beagle/beagle_top_level_handler.cc b/driver/beagle/beagle_top_level_handler.cc
new file mode 100644
index 0000000..6890d2a
--- /dev/null
+++ b/driver/beagle/beagle_top_level_handler.cc
@@ -0,0 +1,265 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/beagle/beagle_top_level_handler.h"
+
+#include "driver/config/beagle_csr_helper.h"
+#include "driver/config/common_csr_helper.h"
+#include "driver/registers/registers.h"
+#include "port/errors.h"
+#include "port/integral_types.h"
+#include "port/logging.h"
+#include "port/status_macros.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+namespace {
+
+using config::registers::ScuCtrl3;
+
+} // namespace
+
+BeagleTopLevelHandler::BeagleTopLevelHandler(
+ const config::ChipConfig& config, Registers* registers, bool use_usb,
+ api::PerformanceExpectation performance)
+ : cb_bridge_offsets_(config.GetCbBridgeCsrOffsets()),
+ hib_user_offsets_(config.GetHibUserCsrOffsets()),
+ misc_offsets_(config.GetMiscCsrOffsets()),
+ reset_offsets_(config.GetScuCsrOffsets()),
+ scalar_core_offsets_(config.GetScalarCoreCsrOffsets()),
+ tile_config_offsets_(config.GetTileConfigCsrOffsets()),
+ tile_offsets_(config.GetTileCsrOffsets()),
+ registers_(registers),
+ performance_(performance),
+ use_usb_(use_usb) {
+ CHECK(registers != nullptr);
+}
+
+util::Status BeagleTopLevelHandler::Open() {
+ // By reading top level registers, figure out whether chip is in clock gated
+ // mode.
+ software_clock_gated_ = false;
+ hardware_clock_gated_ = false;
+
+ // 1. Always disable inactive mode.
+ // Read the register to preserve other fields.
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_0_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_0));
+ config::registers::ScuCtrl0 helper(scu_ctrl_0_reg);
+ helper.set_rg_pcie_inact_phy_mode(0);
+ helper.set_rg_usb_inact_phy_mode(0);
+ RETURN_IF_ERROR(registers_->Write32(reset_offsets_.scu_ctrl_0, helper.raw()));
+
+ // 2. Check "rg_gated_gcb".
+ // 0x0: deprecated
+ // 0x1: hardware clock gated
+ // 0x2: no clock gating
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_2_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_2));
+ config::registers::ScuCtrl2 scu_ctrl_2(scu_ctrl_2_reg);
+ if (scu_ctrl_2.rg_gated_gcb() == 0x1) {
+ hardware_clock_gated_ = true;
+ }
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelHandler::QuitReset() {
+ // Disable Sleep Mode (Partial Software Control)
+ // 1. Make "rg_force_sleep" to be b10. Read the register to preserve other
+ // fields.
+ // 2. Set GCB, AXI, and 8051 clock rate according to desired performance
+ // level.
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ config::registers::ScuCtrl3 helper(scu_ctrl_3_reg);
+ helper.set_rg_force_sleep(0b10);
+
+ switch (performance_) {
+ case api::PerformanceExpectation_Low:
+ helper.set_gcb_clock_rate(ScuCtrl3::GcbClock::k63MHZ);
+ helper.set_axi_clock_rate(ScuCtrl3::AxiClock::k125MHZ);
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k250MHZ);
+ break;
+
+ case api::PerformanceExpectation_Medium:
+ helper.set_gcb_clock_rate(ScuCtrl3::GcbClock::k125MHZ);
+ helper.set_axi_clock_rate(ScuCtrl3::AxiClock::k125MHZ);
+ if (use_usb_) {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k500MHZ);
+ } else {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k250MHZ);
+ }
+ break;
+
+ case api::PerformanceExpectation_High:
+ helper.set_gcb_clock_rate(ScuCtrl3::GcbClock::k250MHZ);
+ helper.set_axi_clock_rate(ScuCtrl3::AxiClock::k125MHZ);
+ if (use_usb_) {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k500MHZ);
+ } else {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k250MHZ);
+ }
+ break;
+
+ case api::PerformanceExpectation_Max:
+ helper.set_gcb_clock_rate(ScuCtrl3::GcbClock::k500MHZ);
+ if (use_usb_) {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k500MHZ);
+ helper.set_axi_clock_rate(ScuCtrl3::AxiClock::k250MHZ);
+ } else {
+ helper.set_usb_8051_clock_rate(ScuCtrl3::Usb8051Clock::k250MHZ);
+ helper.set_axi_clock_rate(ScuCtrl3::AxiClock::k125MHZ);
+ }
+ break;
+
+ default:
+ return util::InvalidArgumentError(
+ StringPrintf("Bad performance setting %d.", performance_));
+ }
+
+ RETURN_IF_ERROR(registers_->Write32(reset_offsets_.scu_ctrl_3, helper.raw()));
+
+ // 2. Poll until "cur_pwr_state" is 0x0. Other fields might change as well,
+ // hence "cur_pwr_state" field has to be explicitly checked.
+ ASSIGN_OR_RETURN(scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ helper.set_raw(scu_ctrl_3_reg);
+ while (helper.cur_pwr_state() != 0x0) {
+ ASSIGN_OR_RETURN(scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ helper.set_raw(scu_ctrl_3_reg);
+ }
+
+ // 3. Confirm that moved out of reset by reading any CSR with known initial
+ // value. scalar core run control should be zero.
+ RETURN_IF_ERROR(
+ registers_->Poll(scalar_core_offsets_.scalarCoreRunControl, 0));
+
+ // 4. Enable idle register.
+ config::registers::IdleRegister idle_reg;
+ idle_reg.set_enable();
+ idle_reg.set_counter(1);
+ RETURN_IF_ERROR(
+ registers_->Write(misc_offsets_.idleRegister, idle_reg.raw()));
+
+ // 5. Update sleep/wake delay for tiles. toSleepDelay = 2, toWakeDelay = 30.
+ // Broadcast to tiles.
+ // TODO: helper uses 7-bits as defined by CSR. Extract bitwidth
+ // automatically for different chips.
+ config::registers::TileConfig<7> tile_config_reg;
+ tile_config_reg.set_broadcast();
+ RETURN_IF_ERROR(registers_->Write(tile_config_offsets_.tileconfig0,
+ tile_config_reg.raw()));
+ // Wait until tileconfig0 is set correctly. Subsequent writes are going to
+ // tiles, but hardware does not guarantee correct ordering with previous
+ // write.
+ RETURN_IF_ERROR(registers_->Poll(tile_config_offsets_.tileconfig0,
+ tile_config_reg.raw()));
+
+ config::registers::DeepSleep deep_sleep_reg;
+ deep_sleep_reg.set_to_sleep_delay(2);
+ deep_sleep_reg.set_to_wake_delay(30);
+ RETURN_IF_ERROR(
+ registers_->Write(tile_offsets_.deepSleep, deep_sleep_reg.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelHandler::EnableReset() {
+ // If already in reset, skip reset. Otherwise, HIB CSR accesses will not be
+ // valid.
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ config::registers::ScuCtrl3 helper(scu_ctrl_3_reg);
+ if (helper.rg_force_sleep() == 0x3) {
+ return util::Status(); // OK
+ }
+
+ // Enable Sleep Mode (Partial Software Control).
+ if (!use_usb_) {
+ // Do Software Force GCB Idle.
+ // Make sure all outstanding DMAs are drained. Note that USB does not have
+ // to do step 1/2 as host controls DMAs.
+ // 1. Enable DMA pause.
+ RETURN_IF_ERROR(registers_->Write(hib_user_offsets_.dma_pause, 1));
+
+ // 2. Wait until DMA is paused.
+ RETURN_IF_ERROR(registers_->Poll(hib_user_offsets_.dma_paused, 1));
+ }
+
+ // Actual enable sleep mode.
+ // 3. Set "rg_force_sleep" to 0x3. Read the register to preserve other fields.
+ helper.set_rg_force_sleep(0x3);
+ RETURN_IF_ERROR(registers_->Write32(reset_offsets_.scu_ctrl_3, helper.raw()));
+
+ // 4. Poll until "cur_pwr_state" becomes 0x2. Other fields might change as
+ // well, hence "cur_pwr_state" field has to be explicitly checked.
+ ASSIGN_OR_RETURN(scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ helper.set_raw(scu_ctrl_3_reg);
+ while (helper.cur_pwr_state() != 0x2) {
+ ASSIGN_OR_RETURN(scu_ctrl_3_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_3));
+ helper.set_raw(scu_ctrl_3_reg);
+ }
+
+ // 5. Clear BULK credit by pulsing LSBs of "gcbb_credit0".
+ RETURN_IF_ERROR(registers_->Write32(cb_bridge_offsets_.gcbb_credit0, 0xF));
+ return registers_->Write32(cb_bridge_offsets_.gcbb_credit0, 0x0);
+}
+
+util::Status BeagleTopLevelHandler::EnableHardwareClockGate() {
+ if (hardware_clock_gated_) {
+ return util::Status(); // OK
+ }
+
+ // Enable Hardware Clock Gate (GCB)
+ // 1. Write "rg_gated_gcb" to 0x1. Read the register to preserve other fields.
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_2_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_2));
+ config::registers::ScuCtrl2 scu_ctrl_2(scu_ctrl_2_reg);
+ scu_ctrl_2.set_rg_gated_gcb(0x1);
+ RETURN_IF_ERROR(
+ registers_->Write32(reset_offsets_.scu_ctrl_2, scu_ctrl_2.raw()));
+
+ hardware_clock_gated_ = true;
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelHandler::DisableHardwareClockGate() {
+ if (!hardware_clock_gated_) {
+ return util::Status(); // OK
+ }
+
+ // Disable Software Clock Gate (GCB)
+ // 1. Force clock on by writing "rg_gated_gcb" to 0x2. Read the register to
+ // preserve other fields.
+ ASSIGN_OR_RETURN(uint32 scu_ctrl_2_reg,
+ registers_->Read32(reset_offsets_.scu_ctrl_2));
+ config::registers::ScuCtrl2 scu_ctrl_2(scu_ctrl_2_reg);
+ scu_ctrl_2.set_rg_gated_gcb(0x2);
+ RETURN_IF_ERROR(
+ registers_->Write32(reset_offsets_.scu_ctrl_2, scu_ctrl_2.raw()));
+
+ hardware_clock_gated_ = false;
+ return util::Status(); // OK
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/beagle/beagle_top_level_handler.h b/driver/beagle/beagle_top_level_handler.h
new file mode 100644
index 0000000..d2d9e31
--- /dev/null
+++ b/driver/beagle/beagle_top_level_handler.h
@@ -0,0 +1,78 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_HANDLER_H_
+#define DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_HANDLER_H_
+
+#include "api/driver_options_generated.h"
+#include "driver/config/cb_bridge_csr_offsets.h"
+#include "driver/config/chip_config.h"
+#include "driver/config/hib_user_csr_offsets.h"
+#include "driver/config/misc_csr_offsets.h"
+#include "driver/config/scalar_core_csr_offsets.h"
+#include "driver/config/scu_csr_offsets.h"
+#include "driver/config/tile_config_csr_offsets.h"
+#include "driver/config/tile_csr_offsets.h"
+#include "driver/registers/registers.h"
+#include "driver/top_level_handler.h"
+#include "port/status.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Handles beagle resets. Only used in remote driver as this will be handled in
+// kernel space in kernel driver.
+class BeagleTopLevelHandler : public TopLevelHandler {
+ public:
+ BeagleTopLevelHandler(const config::ChipConfig& config, Registers* registers,
+ bool use_usb, api::PerformanceExpectation performance);
+ ~BeagleTopLevelHandler() override = default;
+
+ // Implements ResetHandler interface.
+ util::Status Open() override;
+ util::Status QuitReset() override;
+ util::Status EnableReset() override;
+ util::Status EnableHardwareClockGate() override;
+ util::Status DisableHardwareClockGate() override;
+
+ private:
+ // CSR offsets.
+ const config::CbBridgeCsrOffsets& cb_bridge_offsets_;
+ const config::HibUserCsrOffsets& hib_user_offsets_;
+ const config::MiscCsrOffsets& misc_offsets_;
+ const config::ScuCsrOffsets& reset_offsets_;
+ const config::ScalarCoreCsrOffsets& scalar_core_offsets_;
+ const config::TileConfigCsrOffsets& tile_config_offsets_;
+ const config::TileCsrOffsets& tile_offsets_;
+
+ // CSR interface.
+ Registers* const registers_;
+
+ // Select clock combinations for performance.
+ const api::PerformanceExpectation performance_;
+
+ // Whether USB is used for Beagle.
+ const bool use_usb_;
+
+ // True if clock gated. Starts at non-clock gated mode.
+ bool software_clock_gated_{false};
+ bool hardware_clock_gated_{false};
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_HANDLER_H_
diff --git a/driver/beagle/beagle_top_level_interrupt_manager.cc b/driver/beagle/beagle_top_level_interrupt_manager.cc
new file mode 100644
index 0000000..57ca521
--- /dev/null
+++ b/driver/beagle/beagle_top_level_interrupt_manager.cc
@@ -0,0 +1,359 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/beagle/beagle_top_level_interrupt_manager.h"
+
+#include
+
+#include "driver/config/beagle_csr_helper.h"
+#include "driver/interrupt/interrupt_controller_interface.h"
+#include "driver/registers/registers.h"
+#include "port/errors.h"
+#include "port/integral_types.h"
+#include "port/logging.h"
+#include "port/status_macros.h"
+#include "port/stringprintf.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace {
+
+// Top Level Interrupt ids:
+// https://g3doc.corp.google.com/platforms/darwinn/silo/g3doc/spec/index.md#interrupt-handling
+constexpr int kThermalShutdownId = 0;
+constexpr int kPcieErrorId = 1;
+constexpr int kMbistId = 2;
+constexpr int kThermalWarningId = 3;
+
+} // namespace
+
+BeagleTopLevelInterruptManager::BeagleTopLevelInterruptManager(
+ std::unique_ptr interrupt_controller,
+ const config::ChipConfig& config, Registers* registers)
+ : TopLevelInterruptManager(std::move(interrupt_controller)),
+ apex_csr_offsets_(config.GetApexCsrOffsets()),
+ scu_csr_offsets_(config.GetScuCsrOffsets()),
+ registers_(registers) {
+ CHECK(registers != nullptr);
+}
+
+util::Status BeagleTopLevelInterruptManager::DoEnableInterrupts() {
+ RETURN_IF_ERROR(EnableThermalWarningInterrupt());
+ RETURN_IF_ERROR(EnableMbistInterrupt());
+ RETURN_IF_ERROR(EnablePcieErrorInterrupt());
+ RETURN_IF_ERROR(EnableThermalShutdownInterrupt());
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DoDisableInterrupts() {
+ RETURN_IF_ERROR(DisableThermalWarningInterrupt());
+ RETURN_IF_ERROR(DisableMbistInterrupt());
+ RETURN_IF_ERROR(DisablePcieErrorInterrupt());
+ RETURN_IF_ERROR(DisableThermalShutdownInterrupt());
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DoHandleInterrupt(int id) {
+ switch (id) {
+ case kThermalWarningId:
+ return HandleThermalWarningInterrupt();
+
+ case kMbistId:
+ return HandleMbistInterrupt();
+
+ case kPcieErrorId:
+ return HandlePcieErrorInterrupt();
+
+ case kThermalShutdownId:
+ return HandleThermalShutdownInterrupt();
+
+ default:
+ return util::InvalidArgumentError(
+ StringPrintf("Unknown top level id: %d", id));
+ }
+}
+
+util::Status BeagleTopLevelInterruptManager::EnableThermalWarningInterrupt() {
+ // 1. Enable thermal warning through omc0_d4.
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 omc0_d4_read,
+ registers_->Read32(apex_csr_offsets_.omc0_d4));
+ driver::config::registers::Omc0D4 omc0_d4_helper(omc0_d4_read);
+ omc0_d4_helper.set_thm_warn_en(1);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.omc0_d4, omc0_d4_helper.raw()));
+
+ // 2. Set thermal warning threshold temperature.
+ // TODO: This is important in the real chip, but not for DV purposes
+ // now.
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::EnableMbistInterrupt() {
+ // 1. Unmask interrupts, and clear interrupt status.
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 rambist_ctrl_1_read,
+ registers_->Read32(apex_csr_offsets_.rambist_ctrl_1));
+ driver::config::registers::RamBistCtrl1 ram_bist_ctrl_1_helper(
+ rambist_ctrl_1_read);
+ // rg_mbist_int_status is write 1 to clear. Set it to 0 not to clear it.
+ ram_bist_ctrl_1_helper.set_rg_mbist_int_status(0);
+ ram_bist_ctrl_1_helper.set_rg_mbist_int_mask(0);
+
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.rambist_ctrl_1,
+ ram_bist_ctrl_1_helper.raw()));
+
+ // 2. Unmask interrupts, and clear interrupt status in scu_ctr_7.
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 scu_ctr_7_read,
+ registers_->Read32(scu_csr_offsets_.scu_ctr_7));
+ driver::config::registers::ScuCtrl7 scu7_helper(scu_ctr_7_read);
+ // pll_lock_failure, and usb_sel_failure are write 1 to clear. Set them to 0
+ // not to clear them.
+ scu7_helper.set_pll_lock_failure(0);
+ scu7_helper.set_usb_sel_failure(0);
+ scu7_helper.set_rg_boot_failure_mask(0);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(scu_csr_offsets_.scu_ctr_7, scu7_helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::EnablePcieErrorInterrupt() {
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 1));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 1));
+ // Write 0x3 to unmask.
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.slv_err_resp_isr_mask, 0x3));
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.mst_err_resp_isr_mask, 0x3));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::EnableThermalShutdownInterrupt() {
+ // 1. Enable thermal shutdown through omc0_d8.
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 omc0_d8_read,
+ registers_->Read32(apex_csr_offsets_.omc0_d8));
+ driver::config::registers::Omc0D8 omc0_d8_helper(omc0_d8_read);
+ omc0_d8_helper.set_sd_en(1);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.omc0_d8, omc0_d8_helper.raw()));
+
+ // 2. Set thermal shutdown threshold temperature.
+ // TODO: This is important in the real chip, but not for DV purposes
+ // now.
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DisableThermalWarningInterrupt() {
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 omc0_d4_read,
+ registers_->Read32(apex_csr_offsets_.omc0_d4));
+ driver::config::registers::Omc0D4 omc0_d4_helper(omc0_d4_read);
+ omc0_d4_helper.set_thm_warn_en(0);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.omc0_d4, omc0_d4_helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DisableMbistInterrupt() {
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 rambist_ctrl_1_read,
+ registers_->Read32(apex_csr_offsets_.rambist_ctrl_1));
+ driver::config::registers::RamBistCtrl1 ram_bist_ctrl_1_helper(
+ rambist_ctrl_1_read);
+ ram_bist_ctrl_1_helper.set_rg_mbist_int_mask(0x7);
+
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.rambist_ctrl_1,
+ ram_bist_ctrl_1_helper.raw()));
+
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 scu_ctr_7_read,
+ registers_->Read32(scu_csr_offsets_.scu_ctr_7));
+ driver::config::registers::ScuCtrl7 scu7_helper(scu_ctr_7_read);
+ scu7_helper.set_rg_boot_failure_mask(0x3);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(scu_csr_offsets_.scu_ctr_7, scu7_helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DisablePcieErrorInterrupt() {
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 0));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 0));
+ // Write 0x0 to mask.
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.slv_err_resp_isr_mask, 0));
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.mst_err_resp_isr_mask, 0));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::DisableThermalShutdownInterrupt() {
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 omc0_d8_read,
+ registers_->Read32(apex_csr_offsets_.omc0_d8));
+ driver::config::registers::Omc0D8 omc0_d8_helper(omc0_d8_read);
+ omc0_d8_helper.set_sd_en(0);
+
+ RETURN_IF_ERROR(
+ registers_->Write32(apex_csr_offsets_.omc0_d8, omc0_d8_helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::HandleThermalWarningInterrupt() {
+ // Read register to preserve other fields. Also, warn_o field needs to be read
+ // before clearing warn_clear, i.e. read before write field.
+ ASSIGN_OR_RETURN(const uint32 omc0_dc_read,
+ registers_->Read32(apex_csr_offsets_.omc0_dc));
+ driver::config::registers::Omc0DC helper(omc0_dc_read);
+
+ // Unconditionally clears interrupts. Proper interrupt management has to
+ // handle the thermal warning and wait for temperature to go down below
+ // threshold before re-enabling.
+ if (helper.warn_o()) {
+ VLOG(5) << "Thermal warning interrupt received";
+ helper.set_warn_clear(1); // Writes 1 to clear.
+ }
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.omc0_dc, helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::HandleMbistInterrupt() {
+ ASSIGN_OR_RETURN(const uint32 rambist_ctrl_1_read,
+ registers_->Read32(apex_csr_offsets_.rambist_ctrl_1));
+ driver::config::registers::RamBistCtrl1 ram_bist_ctrl_1_helper(
+ rambist_ctrl_1_read);
+
+ // Proper interrupt management is required in the real chip. For DV, just
+ // print whether we received the correct interrupt.
+ uint64 status_value = 0x0;
+ constexpr uint64 kMbistFail = 0x1;
+ if ((ram_bist_ctrl_1_helper.rg_mbist_int_status() & kMbistFail) ==
+ kMbistFail) {
+ VLOG(5) << "Mbist fail interrupt received";
+ status_value |= kMbistFail;
+ }
+
+ constexpr uint64 kMbistTimeout = 0x2;
+ if ((ram_bist_ctrl_1_helper.rg_mbist_int_status() & kMbistTimeout) ==
+ kMbistTimeout) {
+ VLOG(5) << "Mbist timeout interrupt received";
+ status_value |= kMbistTimeout;
+ }
+
+ constexpr uint64 kMbistFinish = 0x4;
+ if ((ram_bist_ctrl_1_helper.rg_mbist_int_status() & kMbistFinish) ==
+ kMbistFinish) {
+ VLOG(5) << "Mbist finish interrupt received";
+ status_value |= kMbistFinish;
+ }
+
+ ram_bist_ctrl_1_helper.set_rg_mbist_int_status(status_value);
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.rambist_ctrl_1,
+ ram_bist_ctrl_1_helper.raw()));
+
+ // Read register to preserve other fields.
+ ASSIGN_OR_RETURN(const uint32 scu_ctr_7_read,
+ registers_->Read32(scu_csr_offsets_.scu_ctr_7));
+ driver::config::registers::ScuCtrl7 scu7_helper(scu_ctr_7_read);
+
+ // Proper interrupt management is required in the real chip. For DV, just
+ // print whether we received the correct interrupt.
+ if (scu7_helper.usb_sel_failure()) {
+ VLOG(5) << "bt_usb_sel violates the eFuse interrupt received";
+ scu7_helper.set_usb_sel_failure(1);
+ }
+ if (scu7_helper.pll_lock_failure()) {
+ VLOG(5) << "PLL lock timeout interrupt received";
+ scu7_helper.set_pll_lock_failure(1);
+ }
+
+ RETURN_IF_ERROR(
+ registers_->Write32(scu_csr_offsets_.scu_ctr_7, scu7_helper.raw()));
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::HandlePcieErrorInterrupt() {
+ // Disable and enable abm_en to handle interrupts.
+ ASSIGN_OR_RETURN(const uint32 slave_write_error,
+ registers_->Read32(apex_csr_offsets_.slv_wr_err_resp));
+ if (slave_write_error == 1) {
+ VLOG(5) << "Slave write interrupt received";
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 0));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 1));
+ }
+ ASSIGN_OR_RETURN(const uint32 slave_read_error,
+ registers_->Read32(apex_csr_offsets_.slv_rd_err_resp));
+ if (slave_read_error == 1) {
+ VLOG(5) << "Slave read interrupt received";
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 0));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.slv_abm_en, 1));
+ }
+
+ ASSIGN_OR_RETURN(const uint32 master_write_error,
+ registers_->Read32(apex_csr_offsets_.mst_wr_err_resp));
+ if (master_write_error == 1) {
+ VLOG(5) << "Master write interrupt received";
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 0));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 1));
+ }
+ ASSIGN_OR_RETURN(const uint32 master_read_error,
+ registers_->Read32(apex_csr_offsets_.mst_rd_err_resp));
+ if (master_read_error == 1) {
+ VLOG(5) << "Master read interrupt received";
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 0));
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.mst_abm_en, 1));
+ }
+
+ return util::Status(); // OK
+}
+
+util::Status BeagleTopLevelInterruptManager::HandleThermalShutdownInterrupt() {
+ // Read register to preserve other fields. Also, sd_o field needs to be read
+ // before clearing sd_clear, i.e. read before write field.
+ ASSIGN_OR_RETURN(const uint32 omc0_dc_read,
+ registers_->Read32(apex_csr_offsets_.omc0_dc));
+ driver::config::registers::Omc0DC helper(omc0_dc_read);
+
+ // Unconditionally clears interrupts. Proper interrupt management has to
+ // handle the thermal shutdown, and wait for temperature to go down below
+ // threshold before re-enabling.
+ if (helper.sd_o()) {
+ VLOG(5) << "Thermal shutdown interrupt received";
+ helper.set_sd_clear(1); // Writes 1 clear.
+ }
+ RETURN_IF_ERROR(registers_->Write32(apex_csr_offsets_.omc0_dc, helper.raw()));
+
+ return util::Status(); // OK
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/beagle/beagle_top_level_interrupt_manager.h b/driver/beagle/beagle_top_level_interrupt_manager.h
new file mode 100644
index 0000000..dddf9da
--- /dev/null
+++ b/driver/beagle/beagle_top_level_interrupt_manager.h
@@ -0,0 +1,79 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_INTERRUPT_MANAGER_H_
+#define DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_INTERRUPT_MANAGER_H_
+
+#include
+
+#include "driver/config/apex_csr_offsets.h"
+#include "driver/config/chip_config.h"
+#include "driver/config/scu_csr_offsets.h"
+#include "driver/interrupt/interrupt_controller_interface.h"
+#include "driver/interrupt/top_level_interrupt_manager.h"
+#include "driver/registers/registers.h"
+#include "port/status.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Beagle-specific top level interrupt management.
+class BeagleTopLevelInterruptManager : public TopLevelInterruptManager {
+ public:
+ BeagleTopLevelInterruptManager(
+ std::unique_ptr interrupt_controller,
+ const config::ChipConfig& config, Registers* registers);
+ ~BeagleTopLevelInterruptManager() override = default;
+
+ protected:
+ // Implements interfaces.
+ util::Status DoEnableInterrupts() override;
+ util::Status DoDisableInterrupts() override;
+ util::Status DoHandleInterrupt(int id) override;
+
+ private:
+ // Implements extra CSR managements to enable top level interrupts.
+ util::Status EnableThermalWarningInterrupt();
+ util::Status EnableMbistInterrupt();
+ util::Status EnablePcieErrorInterrupt();
+ util::Status EnableThermalShutdownInterrupt();
+
+ // Implements extra CSR managements to disable top level interrupts.
+ util::Status DisableThermalWarningInterrupt();
+ util::Status DisableMbistInterrupt();
+ util::Status DisablePcieErrorInterrupt();
+ util::Status DisableThermalShutdownInterrupt();
+
+ // Implements top level interrupt handling.
+ util::Status HandleThermalWarningInterrupt();
+ util::Status HandleMbistInterrupt();
+ util::Status HandlePcieErrorInterrupt();
+ util::Status HandleThermalShutdownInterrupt();
+
+ // Apex CSR offsets.
+ const config::ApexCsrOffsets& apex_csr_offsets_;
+
+ // SCU CSR offsets.
+ const config::ScuCsrOffsets scu_csr_offsets_;
+
+ // CSR interface.
+ Registers* const registers_;
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_BEAGLE_BEAGLE_TOP_LEVEL_INTERRUPT_MANAGER_H_
diff --git a/driver/beagle/beagle_usb_driver_provider.cc b/driver/beagle/beagle_usb_driver_provider.cc
new file mode 100644
index 0000000..3e8ad1a
--- /dev/null
+++ b/driver/beagle/beagle_usb_driver_provider.cc
@@ -0,0 +1,374 @@
+// Copyright 2019 Google LLC
+//
+// 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
+#include
+#include
+#include
+#include
+
+#if !defined(DARWINN_PORT_ANDROID_SYSTEM) && \
+ !defined(DARWINN_PORT_ANDROID_EMULATOR)
+#include "absl/strings/numbers.h"
+#endif
+
+#include "api/chip.h"
+#include "api/driver.h"
+#include "api/driver_options_generated.h"
+#include "driver/aligned_allocator.h"
+#include "driver/beagle/beagle_top_level_handler.h"
+#include "driver/beagle/beagle_top_level_interrupt_manager.h"
+#include "driver/config/beagle/beagle_chip_config.h"
+#include "driver/driver_factory.h"
+#include "driver/interrupt/grouped_interrupt_controller.h"
+#include "driver/interrupt/interrupt_controller.h"
+#include "driver/interrupt/interrupt_controller_interface.h"
+#include "driver/memory/null_dram_allocator.h"
+#include "driver/package_registry.h"
+#include "driver/package_verifier.h"
+#include "driver/run_controller.h"
+#include "driver/scalar_core_controller.h"
+#include "driver/time_stamper/driver_time_stamper.h"
+#include "driver/usb/local_usb_device.h"
+#include "driver/usb/usb_device_interface.h"
+#include "driver/usb/usb_driver.h"
+#include "driver/usb/usb_ml_commands.h"
+#include "driver/usb/usb_registers.h"
+#include "port/gflags.h"
+#include "port/ptr_util.h"
+#include "port/tracing.h"
+
+namespace {
+bool GetEnv(const char* env_var, bool default_value) {
+#if !defined(DARWINN_PORT_ANDROID_SYSTEM) && \
+ !defined(DARWINN_PORT_ANDROID_EMULATOR)
+ bool value;
+ const char* value_str = std::getenv(env_var);
+ if (value_str != nullptr && absl::SimpleAtob(value_str, &value)) return value;
+#endif
+ return default_value;
+}
+
+int GetEnv(const char* env_var, int default_value) {
+#if !defined(DARWINN_PORT_ANDROID_SYSTEM) && \
+ !defined(DARWINN_PORT_ANDROID_EMULATOR)
+ int value;
+ const char* value_str = std::getenv(env_var);
+ if (value_str != nullptr && absl::SimpleAtoi(value_str, &value)) return value;
+#endif
+ return default_value;
+}
+
+#if defined(__APPLE__)
+constexpr int kDefaultUsbMaxNumAsyncTransfers = 1;
+#else
+constexpr int kDefaultUsbMaxNumAsyncTransfers = 3;
+#endif
+} // namespace
+
+/*
+ * There are only 3 modes of operation regarding
+ * usb_enable_bulk_out_descriptors_from_device and
+ * usb_enable_processing_of_hints:
+ *
+ * 1) both true, we follow the hints, and
+ * use descriptors sent from device as validation. This mode doesn't work if
+ * the device sends a lot of bulk-out or bulk-in descriptors out which could
+ * clog the descriptor/bulk-in pipeline.
+ *
+ * 2) disable descriptors but enable hints. We blindly follow the hints and
+ * send data to device as fast as we can. The mode is similar to the
+ * previous one, but could be slightly faster.
+ *
+ * 3) enable descriptors but disable the hints. we use descriptors from
+ * device and pretend there is no hint from code gen, except for first one
+ * (for instructions). This mode doesn't work with multiple instruction
+ * chunks, as device is not capable of generating descriptors for
+ * instructions.
+ *
+ */
+ABSL_FLAG(bool, usb_enable_bulk_descriptors_from_device,
+ GetEnv("USB_ENABLE_BULK_DESCRIPTORS_FROM_DEVICE", false),
+ "USB set to true if bulk in/out descriptors from device are needed.");
+ABSL_FLAG(bool, usb_enable_processing_of_hints,
+ GetEnv("USB_ENABLE_PROCESSING_OF_HINTS", true),
+ "USB set to true for driver to proactively send data to device.");
+ABSL_FLAG(int, usb_timeout_millis, GetEnv("USB_TIMEOUT_MILLIS", 6000),
+ "USB timeout in milliseconds");
+ABSL_FLAG(bool, usb_reset_back_to_dfu_mode,
+ GetEnv("USB_RESET_BACK_TO_DFU_MODE", false),
+ "USB find device in app mode, reset back to DFU mode, and terminate");
+ABSL_FLAG(
+ int, usb_software_credits_low_limit,
+ GetEnv("USB_SOFTWARE_CREDITS_LOW_LIMIT", 8192),
+ "USB lower bound of bulk out transfer size in bytes, when used in mode 1");
+ABSL_FLAG(int, usb_operating_mode, GetEnv("USB_OPERATING_MODE", 2),
+ "USB driver operating mode: 0:Multiple-Ep w/ HW, 1:Multiple-Ep w/ "
+ "SW, 2:Single-Ep");
+ABSL_FLAG(int, usb_max_bulk_out_transfer,
+ GetEnv("USB_MAX_BULK_OUT_TRANSFER", 1024 * 1024),
+ "USB max bulk out transfer size in bytes");
+ABSL_FLAG(int, usb_max_num_async_transfers,
+ GetEnv("USB_MAX_NUM_ASYNC_TRANSFERS",
+ kDefaultUsbMaxNumAsyncTransfers),
+ "USB max number of pending async bulk out transfer");
+ABSL_FLAG(
+ bool, usb_force_largest_bulk_in_chunk_size,
+ GetEnv("USB_FORCE_LARGEST_BULK_IN_CHUNK_SIZE", false),
+ "If true, bulk-in data is transmitted in largest chunks possible. Setting "
+ "this to true increase performance on USB2.");
+ABSL_FLAG(bool, usb_enable_overlapping_requests,
+ GetEnv("USB_ENABLE_OVERLAPPING_REQUESTS", true),
+ "Allows the next queued request to be partially overlapped with "
+ "the current one.");
+ABSL_FLAG(bool, usb_enable_overlapping_bulk_in_and_out,
+ GetEnv("USB_ENABLE_OVERLAPPING_BULK_IN_AND_OUT", true),
+ "Allows bulk-in trasnfer to be submitted before previous bulk-out "
+ "requests complete.");
+ABSL_FLAG(bool, usb_enable_queued_bulk_in_requests,
+ GetEnv("USB_ENABLE_QUEUED_BULK_IN_REQUESTS", true),
+ "Allows bulk-in transfers to be queued to improve performance.");
+ABSL_FLAG(
+ bool, usb_fail_if_slower_than_superspeed,
+ GetEnv("USB_FAIL_IF_SLOWER_THAN_SUPERSPEED", false),
+ "USB driver open would fail if the connection is slower than superspeed.");
+ABSL_FLAG(int, usb_bulk_in_queue_capacity,
+ GetEnv("USB_BULK_IN_QUEUE_CAPACITY", 32),
+ "Max number of USB bulk-in requests that can be queued. This "
+ "option is only effective when it is positive.");
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace {
+
+using platforms::darwinn::api::Chip;
+using platforms::darwinn::api::Device;
+
+constexpr uint16_t kTargetAppVendorId = 0x18D1;
+constexpr uint16_t kTargetAppProductId = 0x9302;
+
+constexpr uint16_t kTargetDfuVendorId = 0x1A6E;
+constexpr uint16_t kTargetDfuProductId = 0x089A;
+
+// TODO add proper error handling to this function.
+// Convenience function to read a file to a vector.
+std::vector ReadToVector(const std::string& file_name) {
+ VLOG(10) << __func__ << file_name;
+
+ // TODO directly read into the vector instead of transcopying through
+ // a string.
+ std::ifstream ifs(file_name);
+ std::string content_string((std::istreambuf_iterator(ifs)),
+ (std::istreambuf_iterator()));
+
+ std::vector result;
+ auto data = reinterpret_cast(content_string.c_str());
+ result.insert(result.end(), data, data + content_string.size());
+ return result;
+}
+} // namespace
+
+class BeagleUsbDriverProvider : public DriverProvider {
+ public:
+ static std::unique_ptr CreateDriverProvider() {
+ return gtl::WrapUnique(new BeagleUsbDriverProvider());
+ }
+
+ ~BeagleUsbDriverProvider() override = default;
+
+ std::vector Enumerate() override;
+ bool CanCreate(const Device& device) override;
+ util::StatusOr> CreateDriver(
+ const Device& device, const api::DriverOptions& options) override;
+
+ private:
+ BeagleUsbDriverProvider() = default;
+};
+
+REGISTER_DRIVER_PROVIDER(BeagleUsbDriverProvider);
+
+std::vector BeagleUsbDriverProvider::Enumerate() {
+ TRACE_SCOPE("BeagleUsbDriverProvider::Enumerate");
+
+ LocalUsbDeviceFactory usb_device_factory;
+ std::vector device_list;
+
+ auto usb_dfu_device_list_or_error = usb_device_factory.EnumerateDevices(
+ kTargetDfuVendorId, kTargetDfuProductId);
+
+ auto usb_app_device_list_or_error = usb_device_factory.EnumerateDevices(
+ kTargetAppVendorId, kTargetAppProductId);
+
+ if (usb_dfu_device_list_or_error.ok()) {
+ for (const auto& path : usb_dfu_device_list_or_error.ValueOrDie()) {
+ device_list.push_back({Chip::kBeagle, Device::Type::USB, path});
+ VLOG(10) << StringPrintf("%s: adding path [%s]", __func__, path.c_str());
+ }
+ }
+
+ if (usb_app_device_list_or_error.ok()) {
+ for (const auto& path : usb_app_device_list_or_error.ValueOrDie()) {
+ device_list.push_back({Chip::kBeagle, Device::Type::USB, path});
+ VLOG(10) << StringPrintf("%s: adding path [%s]", __func__, path.c_str());
+ }
+ }
+
+ return device_list;
+}
+
+bool BeagleUsbDriverProvider::CanCreate(const Device& device) {
+ return device.type == Device::Type::USB && device.chip == Chip::kBeagle;
+}
+
+util::StatusOr>
+BeagleUsbDriverProvider::CreateDriver(
+ const Device& device, const api::DriverOptions& driver_options) {
+ TRACE_SCOPE("BeagleUsbDriverProvider::CreateDriver");
+
+ if (!CanCreate(device)) {
+ return util::NotFoundError("Unsupported device.");
+ }
+
+ auto config = gtl::MakeUnique();
+
+ UsbDriver::UsbDriverOptions options;
+ options.usb_force_largest_bulk_in_chunk_size =
+ absl::GetFlag(FLAGS_usb_force_largest_bulk_in_chunk_size);
+ options.usb_enable_bulk_descriptors_from_device =
+ absl::GetFlag(FLAGS_usb_enable_bulk_descriptors_from_device);
+ options.usb_enable_processing_of_hints =
+ absl::GetFlag(FLAGS_usb_enable_processing_of_hints);
+ options.usb_max_num_async_transfers =
+ absl::GetFlag(FLAGS_usb_max_num_async_transfers);
+ options.mode = static_cast(
+ absl::GetFlag(FLAGS_usb_operating_mode));
+ options.max_bulk_out_transfer_size_in_bytes =
+ absl::GetFlag(FLAGS_usb_max_bulk_out_transfer);
+ options.software_credits_lower_limit_in_bytes =
+ absl::GetFlag(FLAGS_usb_software_credits_low_limit);
+ options.usb_enable_overlapping_requests =
+ absl::GetFlag(FLAGS_usb_enable_overlapping_requests);
+ options.usb_enable_overlapping_bulk_in_and_out =
+ absl::GetFlag(FLAGS_usb_enable_overlapping_bulk_in_and_out);
+ options.usb_fail_if_slower_than_superspeed =
+ absl::GetFlag(FLAGS_usb_fail_if_slower_than_superspeed);
+ options.usb_enable_queued_bulk_in_requests =
+ absl::GetFlag(FLAGS_usb_enable_queued_bulk_in_requests);
+ options.usb_bulk_in_queue_capacity =
+ absl::GetFlag(FLAGS_usb_bulk_in_queue_capacity);
+
+ auto usb_registers = gtl::MakeUnique();
+ std::vector>
+ top_level_interrupt_controllers;
+ top_level_interrupt_controllers.push_back(
+ gtl::MakeUnique(
+ config->GetUsbTopLevel0InterruptCsrOffsets(), usb_registers.get()));
+ top_level_interrupt_controllers.push_back(
+ gtl::MakeUnique(
+ config->GetUsbTopLevel1InterruptCsrOffsets(), usb_registers.get()));
+ top_level_interrupt_controllers.push_back(
+ gtl::MakeUnique(
+ config->GetUsbTopLevel2InterruptCsrOffsets(), usb_registers.get()));
+ top_level_interrupt_controllers.push_back(
+ gtl::MakeUnique(
+ config->GetUsbTopLevel3InterruptCsrOffsets(), usb_registers.get()));
+ auto top_level_interrupt_controller =
+ gtl::MakeUnique(
+ &top_level_interrupt_controllers);
+
+ auto top_level_interrupt_manager =
+ gtl::MakeUnique(
+ std::move(top_level_interrupt_controller), *config,
+ usb_registers.get());
+
+ auto fatal_error_interrupt_controller = gtl::MakeUnique(
+ config->GetUsbFatalErrorInterruptCsrOffsets(), usb_registers.get());
+
+ auto top_level_handler = gtl::MakeUnique(
+ *config, usb_registers.get(),
+ /*use_usb=*/true, driver_options.performance_expectation());
+
+ const api::DriverUsbOptions* usb_options = driver_options.usb();
+ if (usb_options != nullptr) {
+ if (usb_options->dfu_firmware() != nullptr) {
+ auto provided_dfu_path = usb_options->dfu_firmware()->str();
+ if (!provided_dfu_path.empty()) {
+ // try loading firmware into memory.
+ options.usb_firmware_image = ReadToVector(provided_dfu_path);
+ }
+ }
+ options.usb_always_dfu = usb_options->always_dfu();
+
+ // Override command line options if driver options are set.
+ // Command line options are easier to use for command line tools, but
+ // most other use cases should set the driver option.
+
+ if (usb_options->has_fail_if_slower_than_superspeed()) {
+ options.usb_fail_if_slower_than_superspeed =
+ usb_options->fail_if_slower_than_superspeed();
+ }
+
+ if (usb_options->has_force_largest_bulk_in_chunk_size()) {
+ options.usb_force_largest_bulk_in_chunk_size =
+ usb_options->force_largest_bulk_in_chunk_size();
+ }
+
+ if (usb_options->has_enable_overlapping_bulk_in_and_out()) {
+ options.usb_enable_overlapping_bulk_in_and_out =
+ usb_options->enable_overlapping_bulk_in_and_out();
+ }
+
+ if (usb_options->has_enable_queued_bulk_in_requests()) {
+ options.usb_enable_queued_bulk_in_requests =
+ usb_options->enable_queued_bulk_in_requests();
+ }
+
+ if (usb_options->has_bulk_in_queue_capacity()) {
+ options.usb_bulk_in_queue_capacity =
+ usb_options->bulk_in_queue_capacity();
+ }
+ }
+
+ auto dram_allocator = gtl::MakeUnique();
+
+ std::string path(device.path);
+ ASSIGN_OR_RETURN(auto verifier, MakeExecutableVerifier(flatbuffers::GetString(
+ driver_options.public_key())));
+ auto executable_registry = gtl::MakeUnique(
+ device.chip, std::move(verifier), dram_allocator.get());
+
+ auto time_stamper = gtl::MakeUnique();
+
+ // Note that although driver_options is passed into constructor of UsbDriver,
+ // it's USB portion is not used by the driver directly, due to historical
+ // reasons.
+ return {gtl::MakeUnique(
+ driver_options, std::move(config),
+ [path] {
+ LocalUsbDeviceFactory usb_device_factory;
+
+ return usb_device_factory.OpenDevice(
+ path, absl::GetFlag(FLAGS_usb_timeout_millis));
+ },
+ std::move(usb_registers), std::move(top_level_interrupt_manager),
+ std::move(fatal_error_interrupt_controller), std::move(top_level_handler),
+ std::move(dram_allocator), std::move(executable_registry), options,
+ std::move(time_stamper))};
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/bitfield.h b/driver/bitfield.h
new file mode 100644
index 0000000..7634832
--- /dev/null
+++ b/driver/bitfield.h
@@ -0,0 +1,104 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+// Helper class to get/set command status register (CSR) fields. Assumes 64-bit
+// CSR registers.
+//
+// Usage:
+// Bitfield<2, 3> field; // Read and write to 0b000XXX00 part of a byte
+//
+// // Access entire value with raw_value or read/write individual fields.
+// // Unused bitfield can be left out. Bitfields are uninitialized because
+// // they are expected to be used within union.
+// union {
+// uint64 raw_value;
+// Bitfield<0, 1> enable;
+// Bitfield<1, 9> status;
+// } reg;
+//
+// // Explicitly assign default value if exists.
+// reg.enable = 1;
+// reg.status = 0xF;
+//
+// LSB_POSITION defines the starting bit of the field specified from the LSB.
+// BITS defines the length of the field. Writes to the field that have bits set
+// outside of BITS length will cause an error. The values passed in for setting
+// and returned from reading will be right aligned (BITS bits starting from the
+// LSB).
+
+#ifndef DARWINN_DRIVER_BITFIELD_H_
+#define DARWINN_DRIVER_BITFIELD_H_
+
+#include
+#include
+
+#include
+
+#include "port/integral_types.h"
+#include "port/logging.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+template
+class Bitfield {
+ public:
+ // Sets the bitfield to |value|. |value| is right aligned, and should set bits
+ // in the range of NUM_BITS.
+ Bitfield& operator=(uint64 value) {
+ CHECK_EQ(value & kMask, value);
+
+ // Since Bitfield is expected to be used with unions, other bits from value
+ // must be preserved.
+ uint64 preserved_bits = value_ & ~(kMask << LSB_POSITION);
+ value_ = preserved_bits | (value << LSB_POSITION);
+ return *this;
+ }
+
+ // Returns the value in a right aligned form.
+ constexpr uint64 operator()() const {
+ return (value_ >> LSB_POSITION) & kMask;
+ }
+
+ // Returns mask for Bitfield.
+ constexpr uint64 mask() const {
+ return kMask;
+ }
+
+ private:
+ // Supported bits in the underlying value.
+ static constexpr size_t kMaxBits = sizeof(uint64) * CHAR_BIT;
+ static_assert(NUM_BITS > 0, "Bitfield must use at least 1 bit");
+ static_assert(NUM_BITS <= kMaxBits,
+ "Bitfield cannot have more bits than 64 bits");
+ static_assert(LSB_POSITION < kMaxBits,
+ "Bitfield cannot start at LSB position higher than 63-bit");
+ static_assert(LSB_POSITION + NUM_BITS <= kMaxBits,
+ "Bitfield cannot have its MSB position past 64-bit");
+
+ // Any attempt to write outside of kMask will cause an error.
+ static constexpr uint64 kMask =
+ (NUM_BITS == kMaxBits) ? (std::numeric_limits::max())
+ : (1ULL << NUM_BITS) - 1;
+
+ // Underlying value for Bitfield.
+ uint64 value_;
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_BITFIELD_H_
diff --git a/driver/config/BUILD b/driver/config/BUILD
new file mode 100644
index 0000000..c2e79a6
--- /dev/null
+++ b/driver/config/BUILD
@@ -0,0 +1,92 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# Chip specific configuration and CSR Layouts.
+#
+# When compiled in google3 environment, gen_rule generated headers in
+# platforms/... is used directly.
+# When compiled in non-google3 environment, pregenerated headers in
+# ${PROJECT}/... is used.
+
+DEFAULT_VISIBILITY = [
+ "//:internal",
+]
+
+package(default_visibility = ["//visibility:public"])
+
+# All Google Owned Code except :
+# - certain files in port/default/ that are under Apache 2.0 license.
+licenses(["notice"])
+
+# Configuration structures.
+cc_library(
+ name = "config",
+ hdrs = [
+ "apex_csr_offsets.h",
+ "beagle_csr_helper.h",
+ "breakpoint_csr_offsets.h",
+ "cb_bridge_csr_offsets.h",
+ "chip_config.h",
+ "chip_structures.h",
+ "common_csr_helper.h",
+ "debug_hib_user_csr_offsets.h",
+ "debug_scalar_core_csr_offsets.h",
+ "debug_tile_csr_offsets.h",
+ "hib_kernel_csr_offsets.h",
+ "hib_user_csr_offsets.h",
+ "interrupt_csr_offsets.h",
+ "memory_csr_offsets.h",
+ "misc_csr_offsets.h",
+ "msix_csr_offsets.h",
+ "power_throttle_csr_helper.h",
+ "queue_csr_offsets.h",
+ "register_file_csr_offsets.h",
+ "scalar_core_csr_offsets.h",
+ "scu_csr_offsets.h",
+ "sync_flag_csr_offsets.h",
+ "tile_config_csr_offsets.h",
+ "tile_csr_offsets.h",
+ "tile_thread_csr_offsets.h",
+ "tile_thread_trace_csr_offsets.h",
+ "trace_csr_offsets.h",
+ "usb_csr_offsets.h",
+ "wire_csr_offsets.h",
+ ],
+ deps = [
+ "//api:chip",
+ "//driver:util",
+ "//port:integral_types",
+ "//port:logging",
+ "//port:unreachable",
+ ],
+)
+
+cc_library(
+ name = "register_constants",
+ hdrs = ["register_constants.h"],
+ deps = [
+ "//port:integral_types",
+ ],
+)
+
+cc_library(
+ name = "scalar_core_csr_offsets_helper",
+ hdrs = ["scalar_core_csr_offsets_helper.h"],
+ deps = [
+ "//base",
+ "//driver:util",
+ "//util/bits",
+ ],
+)
diff --git a/driver/config/apex_csr_offsets.h b/driver/config/apex_csr_offsets.h
new file mode 100644
index 0000000..f1e8c8f
--- /dev/null
+++ b/driver/config/apex_csr_offsets.h
@@ -0,0 +1,54 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_APEX_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_APEX_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for apex in Beagle.
+// Members are intentionally named to match the GCSR register names.
+struct ApexCsrOffsets {
+ uint64 omc0_00;
+
+ uint64 omc0_d4;
+ uint64 omc0_d8;
+ uint64 omc0_dc;
+
+ uint64 mst_abm_en;
+ uint64 slv_abm_en;
+ uint64 slv_err_resp_isr_mask;
+ uint64 mst_err_resp_isr_mask;
+
+ uint64 mst_wr_err_resp;
+ uint64 mst_rd_err_resp;
+ uint64 slv_wr_err_resp;
+ uint64 slv_rd_err_resp;
+
+ uint64 rambist_ctrl_1;
+
+ uint64 efuse_00;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_APEX_CSR_OFFSETS_H_
diff --git a/driver/config/beagle/BUILD b/driver/config/beagle/BUILD
new file mode 100644
index 0000000..73f1c37
--- /dev/null
+++ b/driver/config/beagle/BUILD
@@ -0,0 +1,45 @@
+# Copyright 2019 Google LLC
+#
+# 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.
+
+# Description:
+# Beagle-specific configuration and CSR Layouts.
+
+package(default_visibility = ["//visibility:public"])
+
+licenses(["notice"])
+
+exports_files(glob(["**/*"]))
+
+cc_library(
+ name = "beagle_config",
+ hdrs = [
+ "beagle_chip_structures.h",
+ "beagle_csr_offsets.h",
+ ],
+ deps = [
+ "//driver/config",
+ "//driver/config:register_constants",
+ ],
+)
+
+cc_library(
+ name = "beagle_chip_config",
+ hdrs = ["beagle_chip_config.h"],
+ deps = [
+ ":beagle_config",
+ "//driver/config",
+ "//port:logging",
+ "//port:unreachable",
+ ],
+)
diff --git a/driver/config/beagle/beagle_chip_config.h b/driver/config/beagle/beagle_chip_config.h
new file mode 100644
index 0000000..d760e01
--- /dev/null
+++ b/driver/config/beagle/beagle_chip_config.h
@@ -0,0 +1,333 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_CONFIG_H_
+#define DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_CONFIG_H_
+
+#include "driver/config/beagle/beagle_chip_structures.h"
+#include "driver/config/beagle/beagle_csr_offsets.h"
+#include "driver/config/chip_config.h"
+#include "port/logging.h"
+#include "port/unreachable.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// Beagle-specific configuration.
+class BeagleChipConfig : public ChipConfig {
+ public:
+ ~BeagleChipConfig() override = default;
+
+ api::Chip GetChip() const override { return api::Chip::kBeagle; }
+
+ // Extracts CSR offsets for various modules in DarwiNN.
+ const HibKernelCsrOffsets& GetHibKernelCsrOffsets() const override {
+ return kBeagleHibKernelCsrOffsets;
+ }
+ const HibUserCsrOffsets& GetHibUserCsrOffsets() const override {
+ return kBeagleHibUserCsrOffsets;
+ }
+ const QueueCsrOffsets& GetInstructionQueueCsrOffsets() const override {
+ return kBeagleInstructionQueueCsrOffsets;
+ }
+ const HibUserCsrOffsets& GetContextSpecificHibUserCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleHibUserCsrOffsets;
+ }
+ const QueueCsrOffsets& GetContextSpecificInstructionQueueCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleInstructionQueueCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetContextSpecificScalarCoreInterruptCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleScHostIntInterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetContextSpecificTopLevelInterruptCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleTopLevelIntInterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetContextSpecificFatalErrorInterruptCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleFatalErrIntInterruptCsrOffsets;
+ }
+ const WireCsrOffsets& GetContextSpecificWireCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleWireCsrOffsets;
+ }
+ const DebugHibUserCsrOffsets& GetContextSpecificDebugHibUserCsrOffsets(
+ int context_id) const override {
+ CHECK_EQ(context_id, 0);
+ return kBeagleDebugHibUserCsrOffsets;
+ }
+ const ScalarCoreCsrOffsets& GetScalarCoreCsrOffsets() const override {
+ return kBeagleScalarCoreCsrOffsets;
+ }
+ const TileConfigCsrOffsets& GetTileConfigCsrOffsets() const override {
+ return kBeagleTileConfigCsrOffsets;
+ }
+ const TileCsrOffsets& GetTileCsrOffsets() const override {
+ return kBeagleTileCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetScalarCoreInterruptCsrOffsets() const override {
+ return kBeagleScHostIntInterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetTopLevelInterruptCsrOffsets() const override {
+ return kBeagleTopLevelIntInterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetFatalErrorInterruptCsrOffsets() const override {
+ return kBeagleFatalErrIntInterruptCsrOffsets;
+ }
+
+ // Extracts CSR offsets that supports specific functionality in DarwiNN.
+ const MsixCsrOffsets& GetMsixCsrOffsets() const override {
+ return kBeagleMsixCsrOffsets;
+ }
+ const WireCsrOffsets& GetWireCsrOffsets() const override {
+ LOG(FATAL) << "Wire interrupt not supported.";
+ unreachable();
+ }
+ const MiscCsrOffsets& GetMiscCsrOffsets() const {
+ return kBeagleMiscCsrOffsets;
+ }
+
+ // Extracts chip-specific constants in DarwiNN.
+ const ChipStructures& GetChipStructures() const override {
+ return kBeagleChipStructures;
+ }
+
+ // Extracts CSR offsets used by scalar core debugger in DarwiNN.
+ const BreakpointCsrOffsets& GetScalarCoreBreakpointCsrOffsets()
+ const override {
+ return kBeagleScalarcoreBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetScalarCoreActivationTtuBreakpointCsrOffsets()
+ const override {
+ return kBeagleAvdatapopBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetScalarCoreInfeedTtuBreakpointCsrOffsets()
+ const override {
+ return kBeagleInfeedBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetScalarCoreOutfeedTtuBreakpointCsrOffsets()
+ const override {
+ return kBeagleOutfeedBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetScalarCoreParameterTtuBreakpointCsrOffsets()
+ const override {
+ return kBeagleParameterpopBreakpointCsrOffsets;
+ }
+
+ const RegisterFileCsrOffsets& GetScalarRegisterFileCsrOffsets()
+ const override {
+ return kBeagleScalarRegisterFileCsrOffsets;
+ }
+ const RegisterFileCsrOffsets& GetPredicateRegisterFileCsrOffsets()
+ const override {
+ return kBeaglePredicateRegisterFileCsrOffsets;
+ }
+
+ const MemoryCsrOffsets& GetScalarCoreMemoryCsrOffsets() const override {
+ return kBeagleScmemoryMemoryCsrOffsets;
+ }
+
+ // Extracts CSR offsets used by tile debugger in DarwiNN.
+ const BreakpointCsrOffsets& GetTileOpTtuBreakpointCsrOffsets() const {
+ return kBeagleOpBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileWideToNarrowTtuBreakpointCsrOffsets()
+ const {
+ return kBeagleWidetonarrowBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileNarrowToWideTtuBreakpointCsrOffsets()
+ const {
+ return kBeagleNarrowtowideBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileRingBusConsumer0TtuBreakpointCsrOffsets()
+ const {
+ return kBeagleRingbusconsumer0BreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileRingBusConsumer1TtuBreakpointCsrOffsets()
+ const {
+ return kBeagleRingbusconsumer1BreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileRingBusProducerTtuBreakpointCsrOffsets()
+ const {
+ return kBeagleRingbusproducerBreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileMeshBus0TtuBreakpointCsrOffsets() const {
+ return kBeagleMeshbus0BreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileMeshBus1TtuBreakpointCsrOffsets() const {
+ return kBeagleMeshbus1BreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileMeshBus2TtuBreakpointCsrOffsets() const {
+ return kBeagleMeshbus2BreakpointCsrOffsets;
+ }
+ const BreakpointCsrOffsets& GetTileMeshBus3TtuBreakpointCsrOffsets() const {
+ return kBeagleMeshbus3BreakpointCsrOffsets;
+ }
+
+ const MemoryCsrOffsets& GetTileMemoryCsrOffsets() const override {
+ return kBeagleMemoryMemoryCsrOffsets;
+ }
+
+ // Extracts CSR offsets used by scalar core performance tracing.
+ const TraceCsrOffsets& GetScalarCoreActivationTtuTraceCsrOffsets()
+ const override {
+ return kBeagleAvdatapopTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetScalarCoreInfeedTtuTraceCsrOffsets()
+ const override {
+ return kBeagleInfeedTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetScalarCoreOutfeedTtuTraceCsrOffsets()
+ const override {
+ return kBeagleOutfeedTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetScalarCoreParameterTtuTraceCsrOffsets()
+ const override {
+ return kBeagleParameterpopTraceCsrOffsets;
+ }
+
+ // Extracts CSR offsets used by tile performance tracing.
+ const TraceCsrOffsets& GetTileOpTtuTraceCsrOffsets() const {
+ return kBeagleOpTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileWideToNarrowTtuTraceCsrOffsets() const {
+ return kBeagleDmawidetonarrowTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileNarrowToWideTtuTraceCsrOffsets() const {
+ return kBeagleDmanarrowtowideTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileRingBusConsumer0TtuTraceCsrOffsets() const {
+ return kBeagleDmaringbusconsumer0TraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileRingBusConsumer1TtuTraceCsrOffsets() const {
+ return kBeagleDmaringbusconsumer1TraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileRingBusProducerTtuTraceCsrOffsets() const {
+ return kBeagleDmaringbusproducerTraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileMeshBus0TtuTraceCsrOffsets() const {
+ return kBeagleDmameshbus0TraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileMeshBus1TtuTraceCsrOffsets() const {
+ return kBeagleDmameshbus1TraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileMeshBus2TtuTraceCsrOffsets() const {
+ return kBeagleDmameshbus2TraceCsrOffsets;
+ }
+ const TraceCsrOffsets& GetTileMeshBus3TtuTraceCsrOffsets() const {
+ return kBeagleDmameshbus3TraceCsrOffsets;
+ }
+
+ // Extracts CSR offsets used to access sync flags in scalar core.
+ const SyncFlagCsrOffsets& GetScalarCoreAvdataPopSyncFlagCsrOffsets()
+ const override {
+ return kBeagleAvdataPopSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreParameterPopSyncFlagCsrOffsets()
+ const override {
+ return kBeagleParameterPopSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreAvdataInfeedSyncFlagCsrOffsets()
+ const override {
+ return kBeagleAvdataInfeedSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreParameterInfeedSyncFlagCsrOffsets()
+ const override {
+ return kBeagleParameterInfeedSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreScalarInfeedSyncFlagCsrOffsets()
+ const override {
+ return kBeagleScalarInfeedSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreProducerASyncFlagCsrOffsets()
+ const override {
+ return kBeagleProducerASyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreProducerBSyncFlagCsrOffsets()
+ const override {
+ return kBeagleProducerBSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreRingOutfeedSyncFlagCsrOffsets()
+ const override {
+ return kBeagleRingOutfeedSyncFlagCsrOffsets;
+ }
+ const SyncFlagCsrOffsets& GetScalarCoreScalarPipelineSyncFlagCsrOffsets()
+ const override {
+ return kBeagleScalarPipelineSyncFlagCsrOffsets;
+ }
+
+ // Extracts CSR offsets used by bug report generator in DarwiNN.
+ const DebugHibUserCsrOffsets& GetDebugHibUserCsrOffsets() const override {
+ return kBeagleDebugHibUserCsrOffsets;
+ }
+ const DebugScalarCoreCsrOffsets& GetDebugScalarCoreCsrOffsets()
+ const override {
+ return kBeagleDebugScalarCoreCsrOffsets;
+ }
+ const DebugTileCsrOffsets& GetDebugTileCsrOffsets() const override {
+ return kBeagleDebugTileCsrOffsets;
+ }
+
+ // Beagle-specific.
+ const ApexCsrOffsets& GetApexCsrOffsets() const override {
+ return kBeagleApexCsrOffsets;
+ }
+ const ScuCsrOffsets& GetScuCsrOffsets() const override {
+ return kBeagleScuCsrOffsets;
+ }
+ const CbBridgeCsrOffsets& GetCbBridgeCsrOffsets() const override {
+ return kBeagleCbBridgeCsrOffsets;
+ }
+ const UsbCsrOffsets& GetUsbCsrOffsets() const override {
+ return kBeagleUsbCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetUsbFatalErrorInterruptCsrOffsets()
+ const override {
+ return kBeagleUsbFatalErrIntInterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetUsbTopLevel0InterruptCsrOffsets()
+ const override {
+ return kBeagleUsbTopLevelInt0InterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetUsbTopLevel1InterruptCsrOffsets()
+ const override {
+ return kBeagleUsbTopLevelInt1InterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetUsbTopLevel2InterruptCsrOffsets()
+ const override {
+ return kBeagleUsbTopLevelInt2InterruptCsrOffsets;
+ }
+ const InterruptCsrOffsets& GetUsbTopLevel3InterruptCsrOffsets()
+ const override {
+ return kBeagleUsbTopLevelInt3InterruptCsrOffsets;
+ }
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_CONFIG_H_
diff --git a/driver/config/beagle/beagle_chip_structures.h b/driver/config/beagle/beagle_chip_structures.h
new file mode 100644
index 0000000..51fb901
--- /dev/null
+++ b/driver/config/beagle/beagle_chip_structures.h
@@ -0,0 +1,58 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+// AUTO GENERATED FILE.
+// See http://go/darwinn-chip-structure for more info.
+
+#ifndef DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_STRUCTURES_H_
+#define DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_STRUCTURES_H_
+
+#include "driver/config/chip_structures.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+const ChipStructures kBeagleChipStructures = {
+ 8ULL, // NOLINT: minimum_alignment_bytes
+ 4096ULL, // NOLINT: allocation_alignment_bytes
+ 0ULL, // NOLINT: axi_dma_burst_limiter
+ 0ULL, // NOLINT: num_wire_interrupts
+ 8192ULL, // NOLINT: num_page_table_entries
+ 64ULL, // NOLINT: physical_address_bits
+ 0ULL, // NOLINT: tpu_dram_size_bytes
+ 196608ULL, // NOLINT: narrow_memory_capacity
+ 262144ULL, // NOLINT: external_narrow_memory_translate_entry_size_bytes
+ 4ULL, // NOLINT: number_x_tiles
+ 4ULL, // NOLINT: number_y_tiles
+ 1ULL, // NOLINT: number_compute_threads
+ 0ULL, // NOLINT: number_of_ring_virtual_networks
+ 0ULL, // NOLINT: last_z_out_cell_disable_incompatible_with_sparsity
+ 0ULL, // NOLINT: nlu_buffer_backpressure_causes_assertion
+ 0ULL, // NOLINT: mesh_rx_queue_depth
+ 0ULL, // NOLINT: default_vn_buffer_memory_lines
+ 6291456ULL, // NOLINT: csr_region_base_offset
+ 2097152ULL, // NOLINT: csr_region_size_bytes
+ 0ULL, // NOLINT: support_trace_arch_registers
+ 0ULL, // NOLINT: base_and_bound_unit_size_bytes
+ 1ULL, // NOLINT: number_of_scalar_core_contexts
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CHIP_STRUCTURES_H_
diff --git a/driver/config/beagle/beagle_csr_offsets.h b/driver/config/beagle/beagle_csr_offsets.h
new file mode 100644
index 0000000..73a1bed
--- /dev/null
+++ b/driver/config/beagle/beagle_csr_offsets.h
@@ -0,0 +1,1705 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+// AUTO GENERATED FILE.
+// See http://go/darwinn-chip-structure for more info.
+
+#ifndef DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CSR_OFFSETS_H_
+
+#include "driver/config/apex_csr_offsets.h"
+#include "driver/config/breakpoint_csr_offsets.h"
+#include "driver/config/cb_bridge_csr_offsets.h"
+#include "driver/config/debug_hib_user_csr_offsets.h"
+#include "driver/config/debug_scalar_core_csr_offsets.h"
+#include "driver/config/debug_tile_csr_offsets.h"
+#include "driver/config/hib_kernel_csr_offsets.h"
+#include "driver/config/hib_user_csr_offsets.h"
+#include "driver/config/interrupt_csr_offsets.h"
+#include "driver/config/memory_csr_offsets.h"
+#include "driver/config/misc_csr_offsets.h"
+#include "driver/config/msix_csr_offsets.h"
+#include "driver/config/queue_csr_offsets.h"
+#include "driver/config/register_constants.h"
+#include "driver/config/register_file_csr_offsets.h"
+#include "driver/config/scalar_core_csr_offsets.h"
+#include "driver/config/scu_csr_offsets.h"
+#include "driver/config/sync_flag_csr_offsets.h"
+#include "driver/config/tile_config_csr_offsets.h"
+#include "driver/config/tile_csr_offsets.h"
+#include "driver/config/trace_csr_offsets.h"
+#include "driver/config/usb_csr_offsets.h"
+#include "driver/config/wire_csr_offsets.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+const InterruptCsrOffsets kBeagleFatalErrIntInterruptCsrOffsets = {
+ 0x486c0, // NOLINT: fatal_err_int_control
+ 0x486c8, // NOLINT: fatal_err_int_status
+};
+
+const InterruptCsrOffsets kBeagleScHostIntInterruptCsrOffsets = {
+ 0x486a0, // NOLINT: sc_host_int_control
+ 0x486a8, // NOLINT: sc_host_int_status
+};
+
+const InterruptCsrOffsets kBeagleTopLevelIntInterruptCsrOffsets = {
+ 0x486b0, // NOLINT: top_level_int_control
+ 0x486b8, // NOLINT: top_level_int_status
+};
+
+const BreakpointCsrOffsets kBeagleAvdatapopBreakpointCsrOffsets = {
+ 0x44158, // NOLINT: avDataPopRunControl
+ 0x44168, // NOLINT: avDataPopRunStatus
+ 0x44160, // NOLINT: avDataPopBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleInfeedBreakpointCsrOffsets = {
+ 0x441d8, // NOLINT: infeedRunControl
+ 0x441e0, // NOLINT: infeedRunStatus
+ 0x441e8, // NOLINT: infeedBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleOutfeedBreakpointCsrOffsets = {
+ 0x44218, // NOLINT: outfeedRunControl
+ 0x44220, // NOLINT: outfeedRunStatus
+ 0x44228, // NOLINT: outfeedBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleParameterpopBreakpointCsrOffsets = {
+ 0x44198, // NOLINT: parameterPopRunControl
+ 0x441a8, // NOLINT: parameterPopRunStatus
+ 0x441a0, // NOLINT: parameterPopBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleScalarcoreBreakpointCsrOffsets = {
+ 0x44018, // NOLINT: scalarCoreRunControl
+ 0x44258, // NOLINT: scalarCoreRunStatus
+ 0x44020, // NOLINT: scalarCoreBreakPoint
+};
+
+const RegisterFileCsrOffsets kBeaglePredicateRegisterFileCsrOffsets = {
+ 0x44500, // NOLINT: predicateRegisterFile
+};
+
+const RegisterFileCsrOffsets kBeagleScalarRegisterFileCsrOffsets = {
+ 0x44400, // NOLINT: scalarRegisterFile
+};
+
+const SyncFlagCsrOffsets kBeagleAvdataInfeedSyncFlagCsrOffsets = {
+ 0x44060, // NOLINT: SyncCounter_AVDATA_INFEED
+};
+
+const SyncFlagCsrOffsets kBeagleAvdataPopSyncFlagCsrOffsets = {
+ 0x44050, // NOLINT: SyncCounter_AVDATA_POP
+};
+
+const SyncFlagCsrOffsets kBeagleParameterInfeedSyncFlagCsrOffsets = {
+ 0x44068, // NOLINT: SyncCounter_PARAMETER_INFEED
+};
+
+const SyncFlagCsrOffsets kBeagleParameterPopSyncFlagCsrOffsets = {
+ 0x44058, // NOLINT: SyncCounter_PARAMETER_POP
+};
+
+const SyncFlagCsrOffsets kBeagleProducerASyncFlagCsrOffsets = {
+ 0x44078, // NOLINT: SyncCounter_PRODUCER_A
+};
+
+const SyncFlagCsrOffsets kBeagleProducerBSyncFlagCsrOffsets = {
+ 0x44080, // NOLINT: SyncCounter_PRODUCER_B
+};
+
+const SyncFlagCsrOffsets kBeagleRingOutfeedSyncFlagCsrOffsets = {
+ 0x44088, // NOLINT: SyncCounter_RING_OUTFEED
+};
+
+const SyncFlagCsrOffsets kBeagleScalarInfeedSyncFlagCsrOffsets = {
+ 0x44070, // NOLINT: SyncCounter_SCALAR_INFEED
+};
+
+const SyncFlagCsrOffsets kBeagleScalarPipelineSyncFlagCsrOffsets = {
+ 0x44090, // NOLINT: SyncCounter_SCALAR_PIPELINE
+};
+
+const TraceCsrOffsets kBeagleAvdatapopTraceCsrOffsets = {
+ 0x44170, // NOLINT: avDataPopOverwriteMode
+ 0x44178, // NOLINT: avDataPopEnableTracing
+ 0x442c0, // NOLINT: avDataPopTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPopTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPopStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleInfeedTraceCsrOffsets = {
+ 0x441f0, // NOLINT: infeedOverwriteMode
+ 0x441f8, // NOLINT: infeedEnableTracing
+ 0x44340, // NOLINT: infeedTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeedTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeedStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleIrqcompletionbufferTraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, irqCompletionBufferOverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, irqCompletionBufferEnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, irqCompletionBufferTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, irqCompletionBufferTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // irqCompletionBufferStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOutfeedTraceCsrOffsets = {
+ 0x44230, // NOLINT: outfeedOverwriteMode
+ 0x44238, // NOLINT: outfeedEnableTracing
+ 0x44380, // NOLINT: outfeedTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeedTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeedStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleParameterpopTraceCsrOffsets = {
+ 0x441b0, // NOLINT: parameterPopOverwriteMode
+ 0x441b8, // NOLINT: parameterPopEnableTracing
+ 0x44300, // NOLINT: parameterPopTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPopTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPopStallCauseSelect
+};
+
+const BreakpointCsrOffsets kBeagleMeshbus0BreakpointCsrOffsets = {
+ 0x42250, // NOLINT: meshBus0RunControl
+ 0x42258, // NOLINT: meshBus0RunStatus
+ 0x42260, // NOLINT: meshBus0BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleMeshbus1BreakpointCsrOffsets = {
+ 0x42298, // NOLINT: meshBus1RunControl
+ 0x422a0, // NOLINT: meshBus1RunStatus
+ 0x422a8, // NOLINT: meshBus1BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleMeshbus2BreakpointCsrOffsets = {
+ 0x422e0, // NOLINT: meshBus2RunControl
+ 0x422e8, // NOLINT: meshBus2RunStatus
+ 0x422f0, // NOLINT: meshBus2BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleMeshbus3BreakpointCsrOffsets = {
+ 0x42328, // NOLINT: meshBus3RunControl
+ 0x42330, // NOLINT: meshBus3RunStatus
+ 0x42338, // NOLINT: meshBus3BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleNarrowtowideBreakpointCsrOffsets = {
+ 0x42150, // NOLINT: narrowToWideRunControl
+ 0x42158, // NOLINT: narrowToWideRunStatus
+ 0x42160, // NOLINT: narrowToWideBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleOpBreakpointCsrOffsets = {
+ 0x420c0, // NOLINT: opRunControl
+ 0x420e0, // NOLINT: opRunStatus
+ 0x420d0, // NOLINT: opBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleRingbusconsumer0BreakpointCsrOffsets = {
+ 0x42190, // NOLINT: ringBusConsumer0RunControl
+ 0x42198, // NOLINT: ringBusConsumer0RunStatus
+ 0x421a0, // NOLINT: ringBusConsumer0BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleRingbusconsumer1BreakpointCsrOffsets = {
+ 0x421d0, // NOLINT: ringBusConsumer1RunControl
+ 0x421d8, // NOLINT: ringBusConsumer1RunStatus
+ 0x421e0, // NOLINT: ringBusConsumer1BreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleRingbusproducerBreakpointCsrOffsets = {
+ 0x42210, // NOLINT: ringBusProducerRunControl
+ 0x42218, // NOLINT: ringBusProducerRunStatus
+ 0x42220, // NOLINT: ringBusProducerBreakPoint
+};
+
+const BreakpointCsrOffsets kBeagleWidetonarrowBreakpointCsrOffsets = {
+ 0x42110, // NOLINT: wideToNarrowRunControl
+ 0x42118, // NOLINT: wideToNarrowRunStatus
+ 0x42120, // NOLINT: wideToNarrowBreakPoint
+};
+
+const SyncFlagCsrOffsets kBeagleAvdataSyncFlagCsrOffsets = {
+ 0x42028, // NOLINT: SyncCounter_AVDATA
+};
+
+const SyncFlagCsrOffsets kBeagleMeshEastInSyncFlagCsrOffsets = {
+ 0x42048, // NOLINT: SyncCounter_MESH_EAST_IN
+};
+
+const SyncFlagCsrOffsets kBeagleMeshEastOutSyncFlagCsrOffsets = {
+ 0x42068, // NOLINT: SyncCounter_MESH_EAST_OUT
+};
+
+const SyncFlagCsrOffsets kBeagleMeshNorthInSyncFlagCsrOffsets = {
+ 0x42040, // NOLINT: SyncCounter_MESH_NORTH_IN
+};
+
+const SyncFlagCsrOffsets kBeagleMeshNorthOutSyncFlagCsrOffsets = {
+ 0x42060, // NOLINT: SyncCounter_MESH_NORTH_OUT
+};
+
+const SyncFlagCsrOffsets kBeagleMeshSouthInSyncFlagCsrOffsets = {
+ 0x42050, // NOLINT: SyncCounter_MESH_SOUTH_IN
+};
+
+const SyncFlagCsrOffsets kBeagleMeshSouthOutSyncFlagCsrOffsets = {
+ 0x42070, // NOLINT: SyncCounter_MESH_SOUTH_OUT
+};
+
+const SyncFlagCsrOffsets kBeagleMeshWestInSyncFlagCsrOffsets = {
+ 0x42058, // NOLINT: SyncCounter_MESH_WEST_IN
+};
+
+const SyncFlagCsrOffsets kBeagleMeshWestOutSyncFlagCsrOffsets = {
+ 0x42078, // NOLINT: SyncCounter_MESH_WEST_OUT
+};
+
+const SyncFlagCsrOffsets kBeagleNarrowToWideSyncFlagCsrOffsets = {
+ 0x42090, // NOLINT: SyncCounter_NARROW_TO_WIDE
+};
+
+const SyncFlagCsrOffsets kBeagleParametersSyncFlagCsrOffsets = {
+ 0x42030, // NOLINT: SyncCounter_PARAMETERS
+};
+
+const SyncFlagCsrOffsets kBeaglePartialSumsSyncFlagCsrOffsets = {
+ 0x42038, // NOLINT: SyncCounter_PARTIAL_SUMS
+};
+
+const SyncFlagCsrOffsets kBeagleRingProducerASyncFlagCsrOffsets = {
+ 0x420b0, // NOLINT: SyncCounter_RING_PRODUCER_A
+};
+
+const SyncFlagCsrOffsets kBeagleRingProducerBSyncFlagCsrOffsets = {
+ 0x420b8, // NOLINT: SyncCounter_RING_PRODUCER_B
+};
+
+const SyncFlagCsrOffsets kBeagleRingReadASyncFlagCsrOffsets = {
+ 0x42098, // NOLINT: SyncCounter_RING_READ_A
+};
+
+const SyncFlagCsrOffsets kBeagleRingReadBSyncFlagCsrOffsets = {
+ 0x420a0, // NOLINT: SyncCounter_RING_READ_B
+};
+
+const SyncFlagCsrOffsets kBeagleRingWriteSyncFlagCsrOffsets = {
+ 0x420a8, // NOLINT: SyncCounter_RING_WRITE
+};
+
+const SyncFlagCsrOffsets kBeagleWideToNarrowSyncFlagCsrOffsets = {
+ 0x42080, // NOLINT: SyncCounter_WIDE_TO_NARROW
+};
+
+const SyncFlagCsrOffsets kBeagleWideToScalingSyncFlagCsrOffsets = {
+ 0x42088, // NOLINT: SyncCounter_WIDE_TO_SCALING
+};
+
+const TraceCsrOffsets kBeagleDmameshbus0TraceCsrOffsets = {
+ 0x42270, // NOLINT: dmaMeshBus0OverwriteMode
+ 0x42278, // NOLINT: dmaMeshBus0EnableTracing
+ 0x42740, // NOLINT: dmaMeshBus0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus0TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus0StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmameshbus1TraceCsrOffsets = {
+ 0x422b8, // NOLINT: dmaMeshBus1OverwriteMode
+ 0x422c0, // NOLINT: dmaMeshBus1EnableTracing
+ 0x427c0, // NOLINT: dmaMeshBus1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus1TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus1StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmameshbus2TraceCsrOffsets = {
+ 0x42300, // NOLINT: dmaMeshBus2OverwriteMode
+ 0x42308, // NOLINT: dmaMeshBus2EnableTracing
+ 0x42840, // NOLINT: dmaMeshBus2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus2TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus2StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmameshbus3TraceCsrOffsets = {
+ 0x42348, // NOLINT: dmaMeshBus3OverwriteMode
+ 0x42350, // NOLINT: dmaMeshBus3EnableTracing
+ 0x428c0, // NOLINT: dmaMeshBus3Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus3TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus3StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtonarrowTraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToNarrowOverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToNarrowEnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToNarrowTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToNarrowTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToNarrowStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide0TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_0TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_0StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide1TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_1TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_1StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide2TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_2OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_2EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_2TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_2StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide3TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_3OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_3EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_3Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_3TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_3StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide4TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_4OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_4EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_4Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_4TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_4StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide5TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_5OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_5EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_5Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_5TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_5StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide6TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_6OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_6EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_6Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_6TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_6StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowide7TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_7OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_7EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_7Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWide_7TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaNarrowToWide_7StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmanarrowtowideTraceCsrOffsets = {
+ 0x42168, // NOLINT: dmaNarrowToWideOverwriteMode
+ 0x42170, // NOLINT: dmaNarrowToWideEnableTracing
+ 0x42600, // NOLINT: dmaNarrowToWideTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWideTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWideStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmaringbusconsumer0TraceCsrOffsets = {
+ 0x421a8, // NOLINT: dmaRingBusConsumer0OverwriteMode
+ 0x421b0, // NOLINT: dmaRingBusConsumer0EnableTracing
+ 0x42640, // NOLINT: dmaRingBusConsumer0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaRingBusConsumer0TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusConsumer0StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmaringbusconsumer1TraceCsrOffsets = {
+ 0x421e8, // NOLINT: dmaRingBusConsumer1OverwriteMode
+ 0x421f0, // NOLINT: dmaRingBusConsumer1EnableTracing
+ 0x42680, // NOLINT: dmaRingBusConsumer1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaRingBusConsumer1TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusConsumer1StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmaringbusproducerTraceCsrOffsets = {
+ 0x42228, // NOLINT: dmaRingBusProducerOverwriteMode
+ 0x42230, // NOLINT: dmaRingBusProducerEnableTracing
+ 0x426c0, // NOLINT: dmaRingBusProducerTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaRingBusProducerTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusProducerStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow0TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_0TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_0StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow1TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_1TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_1StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow2TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_2OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_2EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_2TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_2StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow3TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_3OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_3EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_3Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_3TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_3StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow4TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_4OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_4EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_4Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_4TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_4StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow5TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_5OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_5EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_5Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_5TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_5StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow6TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_6OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_6EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_6Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_6TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_6StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrow7TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_7OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_7EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_7Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrow_7TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaWideToNarrow_7StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleDmawidetonarrowTraceCsrOffsets = {
+ 0x42128, // NOLINT: dmaWideToNarrowOverwriteMode
+ 0x42130, // NOLINT: dmaWideToNarrowEnableTracing
+ 0x42500, // NOLINT: dmaWideToNarrowTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrowTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrowStallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp0TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_0TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_0StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp1TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_1TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_1StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp2TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_2OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_2EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_2TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_2StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp3TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_3OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_3EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_3Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_3TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_3StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp4TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_4OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_4EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_4Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_4TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_4StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp5TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_5OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_5EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_5Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_5TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_5StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp6TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_6OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_6EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_6Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_6TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_6StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOp7TraceCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_7OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_7EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_7Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_7TimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, Op_7StallCauseSelect
+};
+
+const TraceCsrOffsets kBeagleOpTraceCsrOffsets = {
+ 0x420e8, // NOLINT: OpOverwriteMode
+ 0x420f0, // NOLINT: OpEnableTracing
+ 0x42400, // NOLINT: OpTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, OpTimeStampUnit
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, OpStallCauseSelect
+};
+
+const DebugHibUserCsrOffsets kBeagleDebugHibUserCsrOffsets = {
+ 0x48010, // NOLINT: instruction_inbound_queue_total_occupancy
+ 0x48018, // NOLINT: instruction_inbound_queue_threshold_counter
+ 0x48020, // NOLINT: instruction_inbound_queue_insertion_counter
+ 0x48028, // NOLINT: instruction_inbound_queue_full_counter
+ 0x48030, // NOLINT: input_actv_inbound_queue_total_occupancy
+ 0x48038, // NOLINT: input_actv_inbound_queue_threshold_counter
+ 0x48040, // NOLINT: input_actv_inbound_queue_insertion_counter
+ 0x48048, // NOLINT: input_actv_inbound_queue_full_counter
+ 0x48050, // NOLINT: param_inbound_queue_total_occupancy
+ 0x48058, // NOLINT: param_inbound_queue_threshold_counter
+ 0x48060, // NOLINT: param_inbound_queue_insertion_counter
+ 0x48068, // NOLINT: param_inbound_queue_full_counter
+ 0x48070, // NOLINT: output_actv_inbound_queue_total_occupancy
+ 0x48078, // NOLINT: output_actv_inbound_queue_threshold_counter
+ 0x48080, // NOLINT: output_actv_inbound_queue_insertion_counter
+ 0x48088, // NOLINT: output_actv_inbound_queue_full_counter
+ 0x48090, // NOLINT: status_block_write_inbound_queue_total_occupancy
+ 0x48098, // NOLINT: status_block_write_inbound_queue_threshold_counter
+ 0x480a0, // NOLINT: status_block_write_inbound_queue_insertion_counter
+ 0x480a8, // NOLINT: status_block_write_inbound_queue_full_counter
+ 0x480b0, // NOLINT: queue_fetch_inbound_queue_total_occupancy
+ 0x480b8, // NOLINT: queue_fetch_inbound_queue_threshold_counter
+ 0x480c0, // NOLINT: queue_fetch_inbound_queue_insertion_counter
+ 0x480c8, // NOLINT: queue_fetch_inbound_queue_full_counter
+ 0x480d0, // NOLINT: instruction_outbound_queue_total_occupancy
+ 0x480d8, // NOLINT: instruction_outbound_queue_threshold_counter
+ 0x480e0, // NOLINT: instruction_outbound_queue_insertion_counter
+ 0x480e8, // NOLINT: instruction_outbound_queue_full_counter
+ 0x480f0, // NOLINT: input_actv_outbound_queue_total_occupancy
+ 0x480f8, // NOLINT: input_actv_outbound_queue_threshold_counter
+ 0x48100, // NOLINT: input_actv_outbound_queue_insertion_counter
+ 0x48108, // NOLINT: input_actv_outbound_queue_full_counter
+ 0x48110, // NOLINT: param_outbound_queue_total_occupancy
+ 0x48118, // NOLINT: param_outbound_queue_threshold_counter
+ 0x48120, // NOLINT: param_outbound_queue_insertion_counter
+ 0x48128, // NOLINT: param_outbound_queue_full_counter
+ 0x48130, // NOLINT: output_actv_outbound_queue_total_occupancy
+ 0x48138, // NOLINT: output_actv_outbound_queue_threshold_counter
+ 0x48140, // NOLINT: output_actv_outbound_queue_insertion_counter
+ 0x48148, // NOLINT: output_actv_outbound_queue_full_counter
+ 0x48150, // NOLINT: status_block_write_outbound_queue_total_occupancy
+ 0x48158, // NOLINT: status_block_write_outbound_queue_threshold_counter
+ 0x48160, // NOLINT: status_block_write_outbound_queue_insertion_counter
+ 0x48168, // NOLINT: status_block_write_outbound_queue_full_counter
+ 0x48170, // NOLINT: queue_fetch_outbound_queue_total_occupancy
+ 0x48178, // NOLINT: queue_fetch_outbound_queue_threshold_counter
+ 0x48180, // NOLINT: queue_fetch_outbound_queue_insertion_counter
+ 0x48188, // NOLINT: queue_fetch_outbound_queue_full_counter
+ 0x48190, // NOLINT: page_table_request_outbound_queue_total_occupancy
+ 0x48198, // NOLINT: page_table_request_outbound_queue_threshold_counter
+ 0x481a0, // NOLINT: page_table_request_outbound_queue_insertion_counter
+ 0x481a8, // NOLINT: page_table_request_outbound_queue_full_counter
+ 0x481b0, // NOLINT: read_tracking_fifo_total_occupancy
+ 0x481b8, // NOLINT: read_tracking_fifo_threshold_counter
+ 0x481c0, // NOLINT: read_tracking_fifo_insertion_counter
+ 0x481c8, // NOLINT: read_tracking_fifo_full_counter
+ 0x481d0, // NOLINT: write_tracking_fifo_total_occupancy
+ 0x481d8, // NOLINT: write_tracking_fifo_threshold_counter
+ 0x481e0, // NOLINT: write_tracking_fifo_insertion_counter
+ 0x481e8, // NOLINT: write_tracking_fifo_full_counter
+ 0x481f0, // NOLINT: read_buffer_total_occupancy
+ 0x481f8, // NOLINT: read_buffer_threshold_counter
+ 0x48200, // NOLINT: read_buffer_insertion_counter
+ 0x48208, // NOLINT: read_buffer_full_counter
+ 0x48210, // NOLINT: axi_aw_credit_shim_total_occupancy
+ 0x48218, // NOLINT: axi_aw_credit_shim_threshold_counter
+ 0x48220, // NOLINT: axi_aw_credit_shim_insertion_counter
+ 0x48228, // NOLINT: axi_aw_credit_shim_full_counter
+ 0x48230, // NOLINT: axi_ar_credit_shim_total_occupancy
+ 0x48238, // NOLINT: axi_ar_credit_shim_threshold_counter
+ 0x48240, // NOLINT: axi_ar_credit_shim_insertion_counter
+ 0x48248, // NOLINT: axi_ar_credit_shim_full_counter
+ 0x48250, // NOLINT: axi_w_credit_shim_total_occupancy
+ 0x48258, // NOLINT: axi_w_credit_shim_threshold_counter
+ 0x48260, // NOLINT: axi_w_credit_shim_insertion_counter
+ 0x48268, // NOLINT: axi_w_credit_shim_full_counter
+ 0x48270, // NOLINT: instruction_inbound_queue_empty_cycles_count
+ 0x48278, // NOLINT: input_actv_inbound_queue_empty_cycles_count
+ 0x48280, // NOLINT: param_inbound_queue_empty_cycles_count
+ 0x48288, // NOLINT: output_actv_inbound_queue_empty_cycles_count
+ 0x48290, // NOLINT: status_block_write_inbound_queue_empty_cycles_count
+ 0x48298, // NOLINT: queue_fetch_inbound_queue_empty_cycles_count
+ 0x482a0, // NOLINT: instruction_outbound_queue_empty_cycles_count
+ 0x482a8, // NOLINT: input_actv_outbound_queue_empty_cycles_count
+ 0x482b0, // NOLINT: param_outbound_queue_empty_cycles_count
+ 0x482b8, // NOLINT: output_actv_outbound_queue_empty_cycles_count
+ 0x482c0, // NOLINT: status_block_write_outbound_queue_empty_cycles_count
+ 0x482c8, // NOLINT: queue_fetch_outbound_queue_empty_cycles_count
+ 0x482d0, // NOLINT: page_table_request_outbound_queue_empty_cycles_count
+ 0x482d8, // NOLINT: read_tracking_fifo_empty_cycles_count
+ 0x482e0, // NOLINT: write_tracking_fifo_empty_cycles_count
+ 0x482e8, // NOLINT: read_buffer_empty_cycles_count
+ 0x482f0, // NOLINT: read_request_arbiter_instruction_request_cycles
+ 0x482f8, // NOLINT: read_request_arbiter_instruction_blocked_cycles
+ 0x48300, // NOLINT:
+ // read_request_arbiter_instruction_blocked_by_arbitration_cycles
+ 0x48308, // NOLINT:
+ // read_request_arbiter_instruction_cycles_blocked_over_threshold
+ 0x48310, // NOLINT: read_request_arbiter_input_actv_request_cycles
+ 0x48318, // NOLINT: read_request_arbiter_input_actv_blocked_cycles
+ 0x48320, // NOLINT:
+ // read_request_arbiter_input_actv_blocked_by_arbitration_cycles
+ 0x48328, // NOLINT:
+ // read_request_arbiter_input_actv_cycles_blocked_over_threshold
+ 0x48330, // NOLINT: read_request_arbiter_param_request_cycles
+ 0x48338, // NOLINT: read_request_arbiter_param_blocked_cycles
+ 0x48340, // NOLINT:
+ // read_request_arbiter_param_blocked_by_arbitration_cycles
+ 0x48348, // NOLINT:
+ // read_request_arbiter_param_cycles_blocked_over_threshold
+ 0x48350, // NOLINT: read_request_arbiter_queue_fetch_request_cycles
+ 0x48358, // NOLINT: read_request_arbiter_queue_fetch_blocked_cycles
+ 0x48360, // NOLINT:
+ // read_request_arbiter_queue_fetch_blocked_by_arbitration_cycles
+ 0x48368, // NOLINT:
+ // read_request_arbiter_queue_fetch_cycles_blocked_over_threshold
+ 0x48370, // NOLINT: read_request_arbiter_page_table_request_request_cycles
+ 0x48378, // NOLINT: read_request_arbiter_page_table_request_blocked_cycles
+ 0x48380, // NOLINT:
+ // read_request_arbiter_page_table_request_blocked_by_arbitration_cycles
+ 0x48388, // NOLINT:
+ // read_request_arbiter_page_table_request_cycles_blocked_over_threshold
+ 0x48390, // NOLINT: write_request_arbiter_output_actv_request_cycles
+ 0x48398, // NOLINT: write_request_arbiter_output_actv_blocked_cycles
+ 0x483a0, // NOLINT:
+ // write_request_arbiter_output_actv_blocked_by_arbitration_cycles
+ 0x483a8, // NOLINT:
+ // write_request_arbiter_output_actv_cycles_blocked_over_threshold
+ 0x483b0, // NOLINT: write_request_arbiter_status_block_write_request_cycles
+ 0x483b8, // NOLINT: write_request_arbiter_status_block_write_blocked_cycles
+ 0x483c0, // NOLINT:
+ // write_request_arbiter_status_block_write_blocked_by_arbitration_cycles
+ 0x483c8, // NOLINT:
+ // write_request_arbiter_status_block_write_cycles_blocked_over_threshold
+ 0x483d0, // NOLINT: address_translation_arbiter_instruction_request_cycles
+ 0x483d8, // NOLINT: address_translation_arbiter_instruction_blocked_cycles
+ 0x483e0, // NOLINT:
+ // address_translation_arbiter_instruction_blocked_by_arbitration_cycles
+ 0x483e8, // NOLINT:
+ // address_translation_arbiter_instruction_cycles_blocked_over_threshold
+ 0x483f0, // NOLINT: address_translation_arbiter_input_actv_request_cycles
+ 0x483f8, // NOLINT: address_translation_arbiter_input_actv_blocked_cycles
+ 0x48400, // NOLINT:
+ // address_translation_arbiter_input_actv_blocked_by_arbitration_cycles
+ 0x48408, // NOLINT:
+ // address_translation_arbiter_input_actv_cycles_blocked_over_threshold
+ 0x48410, // NOLINT: address_translation_arbiter_param_request_cycles
+ 0x48418, // NOLINT: address_translation_arbiter_param_blocked_cycles
+ 0x48420, // NOLINT:
+ // address_translation_arbiter_param_blocked_by_arbitration_cycles
+ 0x48428, // NOLINT:
+ // address_translation_arbiter_param_cycles_blocked_over_threshold
+ 0x48430, // NOLINT:
+ // address_translation_arbiter_status_block_write_request_cycles
+ 0x48438, // NOLINT:
+ // address_translation_arbiter_status_block_write_blocked_cycles
+ 0x48440, // NOLINT:
+ // address_translation_arbiter_status_block_write_blocked_by_arbitration_cycles
+ 0x48448, // NOLINT:
+ // address_translation_arbiter_status_block_write_cycles_blocked_over_threshold
+ 0x48450, // NOLINT: address_translation_arbiter_output_actv_request_cycles
+ 0x48458, // NOLINT: address_translation_arbiter_output_actv_blocked_cycles
+ 0x48460, // NOLINT:
+ // address_translation_arbiter_output_actv_blocked_by_arbitration_cycles
+ 0x48468, // NOLINT:
+ // address_translation_arbiter_output_actv_cycles_blocked_over_threshold
+ 0x48470, // NOLINT: address_translation_arbiter_queue_fetch_request_cycles
+ 0x48478, // NOLINT: address_translation_arbiter_queue_fetch_blocked_cycles
+ 0x48480, // NOLINT:
+ // address_translation_arbiter_queue_fetch_blocked_by_arbitration_cycles
+ 0x48488, // NOLINT:
+ // address_translation_arbiter_queue_fetch_cycles_blocked_over_threshold
+ 0x48490, // NOLINT: issued_interrupt_count
+ 0x48498, // NOLINT: data_read_16byte_count
+ 0x484a0, // NOLINT: waiting_for_tag_cycles
+ 0x484a8, // NOLINT: waiting_for_axi_cycles
+ 0x484b0, // NOLINT: simple_translations
+ 0x484c8, // NOLINT: instruction_credits_per_cycle_sum
+ 0x484d0, // NOLINT: input_actv_credits_per_cycle_sum
+ 0x484d8, // NOLINT: param_credits_per_cycle_sum
+ 0x484e0, // NOLINT: output_actv_credits_per_cycle_sum
+ 0x484e8, // NOLINT: status_block_write_credits_per_cycle_sum
+ 0x484f0, // NOLINT: queue_fetch_credits_per_cycle_sum
+ 0x484f8, // NOLINT: page_table_request_credits_per_cycle_sum
+ 0x48500, // NOLINT: output_actv_queue_control
+ 0x48508, // NOLINT: output_actv_queue_status
+ 0x48510, // NOLINT: output_actv_queue_descriptor_size
+ 0x48518, // NOLINT: output_actv_queue_minimum_size
+ 0x48520, // NOLINT: output_actv_queue_maximum_size
+ 0x48528, // NOLINT: output_actv_queue_base
+ 0x48530, // NOLINT: output_actv_queue_status_block_base
+ 0x48538, // NOLINT: output_actv_queue_size
+ 0x48540, // NOLINT: output_actv_queue_tail
+ 0x48548, // NOLINT: output_actv_queue_fetched_head
+ 0x48550, // NOLINT: output_actv_queue_completed_head
+ 0x48558, // NOLINT: output_actv_queue_int_control
+ 0x48560, // NOLINT: output_actv_queue_int_status
+ 0x48568, // NOLINT: instruction_queue_control
+ 0x48570, // NOLINT: instruction_queue_status
+ 0x48578, // NOLINT: instruction_queue_descriptor_size
+ 0x48580, // NOLINT: instruction_queue_minimum_size
+ 0x48588, // NOLINT: instruction_queue_maximum_size
+ 0x48590, // NOLINT: instruction_queue_base
+ 0x48598, // NOLINT: instruction_queue_status_block_base
+ 0x485a0, // NOLINT: instruction_queue_size
+ 0x485a8, // NOLINT: instruction_queue_tail
+ 0x485b0, // NOLINT: instruction_queue_fetched_head
+ 0x485b8, // NOLINT: instruction_queue_completed_head
+ 0x485c0, // NOLINT: instruction_queue_int_control
+ 0x485c8, // NOLINT: instruction_queue_int_status
+ 0x485d0, // NOLINT: input_actv_queue_control
+ 0x485d8, // NOLINT: input_actv_queue_status
+ 0x485e0, // NOLINT: input_actv_queue_descriptor_size
+ 0x485e8, // NOLINT: input_actv_queue_minimum_size
+ 0x485f0, // NOLINT: input_actv_queue_maximum_size
+ 0x485f8, // NOLINT: input_actv_queue_base
+ 0x48600, // NOLINT: input_actv_queue_status_block_base
+ 0x48608, // NOLINT: input_actv_queue_size
+ 0x48610, // NOLINT: input_actv_queue_tail
+ 0x48618, // NOLINT: input_actv_queue_fetched_head
+ 0x48620, // NOLINT: input_actv_queue_completed_head
+ 0x48628, // NOLINT: input_actv_queue_int_control
+ 0x48630, // NOLINT: input_actv_queue_int_status
+ 0x48638, // NOLINT: param_queue_control
+ 0x48640, // NOLINT: param_queue_status
+ 0x48648, // NOLINT: param_queue_descriptor_size
+ 0x48650, // NOLINT: param_queue_minimum_size
+ 0x48658, // NOLINT: param_queue_maximum_size
+ 0x48660, // NOLINT: param_queue_base
+ 0x48668, // NOLINT: param_queue_status_block_base
+ 0x48670, // NOLINT: param_queue_size
+ 0x48678, // NOLINT: param_queue_tail
+ 0x48680, // NOLINT: param_queue_fetched_head
+ 0x48688, // NOLINT: param_queue_completed_head
+ 0x48690, // NOLINT: param_queue_int_control
+ 0x48698, // NOLINT: param_queue_int_status
+ 0x486a0, // NOLINT: sc_host_int_control
+ 0x486a8, // NOLINT: sc_host_int_status
+ 0x486b0, // NOLINT: top_level_int_control
+ 0x486b8, // NOLINT: top_level_int_status
+ 0x486c0, // NOLINT: fatal_err_int_control
+ 0x486c8, // NOLINT: fatal_err_int_status
+ 0x486d0, // NOLINT: sc_host_int_count
+ 0x486d8, // NOLINT: dma_pause
+ 0x486e0, // NOLINT: dma_paused
+ 0x486e8, // NOLINT: status_block_update
+ 0x486f0, // NOLINT: hib_error_status
+ 0x486f8, // NOLINT: hib_error_mask
+ 0x48700, // NOLINT: hib_first_error_status
+ 0x48708, // NOLINT: hib_first_error_timestamp
+ 0x48710, // NOLINT: hib_inject_error
+ 0x48718, // NOLINT: read_request_arbiter
+ 0x48720, // NOLINT: write_request_arbiter
+ 0x48728, // NOLINT: address_translation_arbiter
+ 0x48730, // NOLINT: sender_queue_threshold
+ 0x48738, // NOLINT: page_fault_address
+ 0x48740, // NOLINT: instruction_credits
+ 0x48748, // NOLINT: input_actv_credits
+ 0x48750, // NOLINT: param_credits
+ 0x48758, // NOLINT: output_actv_credits
+ 0x48760, // NOLINT: pause_state
+ 0x48768, // NOLINT: snapshot
+ 0x48770, // NOLINT: idle_assert
+ 0x48778, // NOLINT: wire_int_pending_bit_array
+ 0x48788, // NOLINT: tileconfig0
+ 0x48790, // NOLINT: tileconfig1
+};
+
+const DebugScalarCoreCsrOffsets kBeagleDebugScalarCoreCsrOffsets = {
+ 0x44000, // NOLINT: topology
+ 0x44008, // NOLINT: scMemoryCapacity
+ 0x44010, // NOLINT: tileMemoryCapacity
+ 0x44040, // NOLINT: scMemoryAccess
+ 0x44048, // NOLINT: scMemoryData
+ 0x44288, // NOLINT: Timeout
+ 0x44260, // NOLINT: Error_ScalarCore
+ 0x44268, // NOLINT: Error_Mask_ScalarCore
+ 0x44270, // NOLINT: Error_Force_ScalarCore
+ 0x44278, // NOLINT: Error_Timestamp_ScalarCore
+ 0x44280, // NOLINT: Error_Info_ScalarCore
+ 0x44018, // NOLINT: scalarCoreRunControl
+ 0x44020, // NOLINT: scalarCoreBreakPoint
+ 0x44028, // NOLINT: currentPc
+ 0x44038, // NOLINT: executeControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, currentPc_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, currentPc_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_2BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, currentPc_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_3RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_3BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, currentPc_3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_3
+ 0x44050, // NOLINT: SyncCounter_AVDATA_POP
+ 0x44058, // NOLINT: SyncCounter_PARAMETER_POP
+ 0x44060, // NOLINT: SyncCounter_AVDATA_INFEED
+ 0x44068, // NOLINT: SyncCounter_PARAMETER_INFEED
+ 0x44070, // NOLINT: SyncCounter_SCALAR_INFEED
+ 0x44078, // NOLINT: SyncCounter_PRODUCER_A
+ 0x44080, // NOLINT: SyncCounter_PRODUCER_B
+ 0x44088, // NOLINT: SyncCounter_RING_OUTFEED
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_POP_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_POP_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_INFEED_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_INFEED_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_SCALAR_INFEED_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_A_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_B_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_RING_OUTFEED_0_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_POP_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_POP_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_INFEED_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_INFEED_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_SCALAR_INFEED_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_A_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_B_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_RING_OUTFEED_1_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_POP_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_POP_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_INFEED_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_INFEED_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_SCALAR_INFEED_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_A_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_B_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_RING_OUTFEED_2_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_POP_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_POP_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_AVDATA_INFEED_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PARAMETER_INFEED_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_SCALAR_INFEED_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_A_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_PRODUCER_B_3_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, SyncCounter_RING_OUTFEED_3_0
+ 0x44158, // NOLINT: avDataPopRunControl
+ 0x44160, // NOLINT: avDataPopBreakPoint
+ 0x44168, // NOLINT: avDataPopRunStatus
+ 0x44170, // NOLINT: avDataPopOverwriteMode
+ 0x44178, // NOLINT: avDataPopEnableTracing
+ 0x44180, // NOLINT: avDataPopStartCycle
+ 0x44188, // NOLINT: avDataPopEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPopStallCycleCount
+ 0x44190, // NOLINT: avDataPopProgramCounter
+ 0x442a0, // NOLINT: avDataPopTtuStateRegFile
+ 0x442c0, // NOLINT: avDataPopTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3Trace
+ 0x44198, // NOLINT: parameterPopRunControl
+ 0x441a0, // NOLINT: parameterPopBreakPoint
+ 0x441a8, // NOLINT: parameterPopRunStatus
+ 0x441b0, // NOLINT: parameterPopOverwriteMode
+ 0x441b8, // NOLINT: parameterPopEnableTracing
+ 0x441c0, // NOLINT: parameterPopStartCycle
+ 0x441c8, // NOLINT: parameterPopEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPopStallCycleCount
+ 0x441d0, // NOLINT: parameterPopProgramCounter
+ 0x442e0, // NOLINT: parameterPopTtuStateRegFile
+ 0x44300, // NOLINT: parameterPopTrace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3Trace
+ 0x441d8, // NOLINT: infeedRunControl
+ 0x441e0, // NOLINT: infeedRunStatus
+ 0x441e8, // NOLINT: infeedBreakPoint
+ 0x441f0, // NOLINT: infeedOverwriteMode
+ 0x441f8, // NOLINT: infeedEnableTracing
+ 0x44200, // NOLINT: infeedStartCycle
+ 0x44208, // NOLINT: infeedEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeedStallCycleCount
+ 0x44210, // NOLINT: infeedProgramCounter
+ 0x44320, // NOLINT: infeedTtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1TtuStateRegFile
+ 0x44218, // NOLINT: outfeedRunControl
+ 0x44220, // NOLINT: outfeedRunStatus
+ 0x44228, // NOLINT: outfeedBreakPoint
+ 0x44230, // NOLINT: outfeedOverwriteMode
+ 0x44238, // NOLINT: outfeedEnableTracing
+ 0x44240, // NOLINT: outfeedStartCycle
+ 0x44248, // NOLINT: outfeedEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeedStallCycleCount
+ 0x44250, // NOLINT: outfeedProgramCounter
+ 0x44360, // NOLINT: outfeedTtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0TtuStateRegFile
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1RunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1BreakPoint
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1OverwriteMode
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1EnableTracing
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1StartCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1StallCycleCount
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1ProgramCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1TtuStateRegFile
+ 0x44258, // NOLINT: scalarCoreRunStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarCoreRunStatus_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarCoreRunStatus_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarCoreRunStatus_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarCoreRunStatus_3
+};
+
+const DebugTileCsrOffsets kBeagleDebugTileCsrOffsets = {
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, TileClockControl
+ 0x42000, // NOLINT: tileid
+ 0x42008, // NOLINT: scratchpad
+ 0x42010, // NOLINT: memoryAccess
+ 0x42018, // NOLINT: memoryData
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_3
+ 0x42020, // NOLINT: deepSleep
+ 0x42028, // NOLINT: SyncCounter_AVDATA
+ 0x42030, // NOLINT: SyncCounter_PARAMETERS
+ 0x42038, // NOLINT: SyncCounter_PARTIAL_SUMS
+ 0x42040, // NOLINT: SyncCounter_MESH_NORTH_IN
+ 0x42048, // NOLINT: SyncCounter_MESH_EAST_IN
+ 0x42050, // NOLINT: SyncCounter_MESH_SOUTH_IN
+ 0x42058, // NOLINT: SyncCounter_MESH_WEST_IN
+ 0x42060, // NOLINT: SyncCounter_MESH_NORTH_OUT
+ 0x42068, // NOLINT: SyncCounter_MESH_EAST_OUT
+ 0x42070, // NOLINT: SyncCounter_MESH_SOUTH_OUT
+ 0x42078, // NOLINT: SyncCounter_MESH_WEST_OUT
+ 0x42080, // NOLINT: SyncCounter_WIDE_TO_NARROW
+ 0x42088, // NOLINT: SyncCounter_WIDE_TO_SCALING
+ 0x42090, // NOLINT: SyncCounter_NARROW_TO_WIDE
+ 0x42098, // NOLINT: SyncCounter_RING_READ_A
+ 0x420a0, // NOLINT: SyncCounter_RING_READ_B
+ 0x420a8, // NOLINT: SyncCounter_RING_WRITE
+ 0x420b0, // NOLINT: SyncCounter_RING_PRODUCER_A
+ 0x420b8, // NOLINT: SyncCounter_RING_PRODUCER_B
+ 0x420c0, // NOLINT: opRunControl
+ 0x420c8, // NOLINT: PowerSaveData
+ 0x420d0, // NOLINT: opBreakPoint
+ 0x420d8, // NOLINT: StallCounter
+ 0x420e0, // NOLINT: opRunStatus
+ 0x420e8, // NOLINT: OpOverwriteMode
+ 0x420f0, // NOLINT: OpEnableTracing
+ 0x420f8, // NOLINT: OpStartCycle
+ 0x42100, // NOLINT: OpEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, OpStallCycleCount
+ 0x42108, // NOLINT: OpProgramCounter
+ 0x42110, // NOLINT: wideToNarrowRunControl
+ 0x42118, // NOLINT: wideToNarrowRunStatus
+ 0x42120, // NOLINT: wideToNarrowBreakPoint
+ 0x42128, // NOLINT: dmaWideToNarrowOverwriteMode
+ 0x42130, // NOLINT: dmaWideToNarrowEnableTracing
+ 0x42138, // NOLINT: dmaWideToNarrowStartCycle
+ 0x42140, // NOLINT: dmaWideToNarrowEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaWideToNarrowStallCycleCount
+ 0x42148, // NOLINT: dmaWideToNarrowProgramCounter
+ 0x42150, // NOLINT: narrowToWideRunControl
+ 0x42158, // NOLINT: narrowToWideRunStatus
+ 0x42160, // NOLINT: narrowToWideBreakPoint
+ 0x42168, // NOLINT: dmaNarrowToWideOverwriteMode
+ 0x42170, // NOLINT: dmaNarrowToWideEnableTracing
+ 0x42178, // NOLINT: dmaNarrowToWideStartCycle
+ 0x42180, // NOLINT: dmaNarrowToWideEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaNarrowToWideStallCycleCount
+ 0x42188, // NOLINT: dmaNarrowToWideProgramCounter
+ 0x42190, // NOLINT: ringBusConsumer0RunControl
+ 0x42198, // NOLINT: ringBusConsumer0RunStatus
+ 0x421a0, // NOLINT: ringBusConsumer0BreakPoint
+ 0x421a8, // NOLINT: dmaRingBusConsumer0OverwriteMode
+ 0x421b0, // NOLINT: dmaRingBusConsumer0EnableTracing
+ 0x421b8, // NOLINT: dmaRingBusConsumer0StartCycle
+ 0x421c0, // NOLINT: dmaRingBusConsumer0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusConsumer0StallCycleCount
+ 0x421c8, // NOLINT: dmaRingBusConsumer0ProgramCounter
+ 0x421d0, // NOLINT: ringBusConsumer1RunControl
+ 0x421d8, // NOLINT: ringBusConsumer1RunStatus
+ 0x421e0, // NOLINT: ringBusConsumer1BreakPoint
+ 0x421e8, // NOLINT: dmaRingBusConsumer1OverwriteMode
+ 0x421f0, // NOLINT: dmaRingBusConsumer1EnableTracing
+ 0x421f8, // NOLINT: dmaRingBusConsumer1StartCycle
+ 0x42200, // NOLINT: dmaRingBusConsumer1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusConsumer1StallCycleCount
+ 0x42208, // NOLINT: dmaRingBusConsumer1ProgramCounter
+ 0x42210, // NOLINT: ringBusProducerRunControl
+ 0x42218, // NOLINT: ringBusProducerRunStatus
+ 0x42220, // NOLINT: ringBusProducerBreakPoint
+ 0x42228, // NOLINT: dmaRingBusProducerOverwriteMode
+ 0x42230, // NOLINT: dmaRingBusProducerEnableTracing
+ 0x42238, // NOLINT: dmaRingBusProducerStartCycle
+ 0x42240, // NOLINT: dmaRingBusProducerEndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED,
+ // dmaRingBusProducerStallCycleCount
+ 0x42248, // NOLINT: dmaRingBusProducerProgramCounter
+ 0x42250, // NOLINT: meshBus0RunControl
+ 0x42258, // NOLINT: meshBus0RunStatus
+ 0x42260, // NOLINT: meshBus0BreakPoint
+ 0x42270, // NOLINT: dmaMeshBus0OverwriteMode
+ 0x42278, // NOLINT: dmaMeshBus0EnableTracing
+ 0x42280, // NOLINT: dmaMeshBus0StartCycle
+ 0x42288, // NOLINT: dmaMeshBus0EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus0StallCycleCount
+ 0x42290, // NOLINT: dmaMeshBus0ProgramCounter
+ 0x42298, // NOLINT: meshBus1RunControl
+ 0x422a0, // NOLINT: meshBus1RunStatus
+ 0x422a8, // NOLINT: meshBus1BreakPoint
+ 0x422b8, // NOLINT: dmaMeshBus1OverwriteMode
+ 0x422c0, // NOLINT: dmaMeshBus1EnableTracing
+ 0x422c8, // NOLINT: dmaMeshBus1StartCycle
+ 0x422d0, // NOLINT: dmaMeshBus1EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus1StallCycleCount
+ 0x422d8, // NOLINT: dmaMeshBus1ProgramCounter
+ 0x422e0, // NOLINT: meshBus2RunControl
+ 0x422e8, // NOLINT: meshBus2RunStatus
+ 0x422f0, // NOLINT: meshBus2BreakPoint
+ 0x42300, // NOLINT: dmaMeshBus2OverwriteMode
+ 0x42308, // NOLINT: dmaMeshBus2EnableTracing
+ 0x42310, // NOLINT: dmaMeshBus2StartCycle
+ 0x42318, // NOLINT: dmaMeshBus2EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus2StallCycleCount
+ 0x42320, // NOLINT: dmaMeshBus2ProgramCounter
+ 0x42328, // NOLINT: meshBus3RunControl
+ 0x42330, // NOLINT: meshBus3RunStatus
+ 0x42338, // NOLINT: meshBus3BreakPoint
+ 0x42348, // NOLINT: dmaMeshBus3OverwriteMode
+ 0x42350, // NOLINT: dmaMeshBus3EnableTracing
+ 0x42358, // NOLINT: dmaMeshBus3StartCycle
+ 0x42360, // NOLINT: dmaMeshBus3EndCycle
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dmaMeshBus3StallCycleCount
+ 0x42368, // NOLINT: dmaMeshBus3ProgramCounter
+ 0x42370, // NOLINT: Error_Tile
+ 0x42378, // NOLINT: Error_Mask_Tile
+ 0x42380, // NOLINT: Error_Force_Tile
+ 0x42388, // NOLINT: Error_Timestamp_Tile
+ 0x42390, // NOLINT: Error_Info_Tile
+ 0x42398, // NOLINT: Timeout
+ 0x423c0, // NOLINT: opTtuStateRegFile
+ 0x42400, // NOLINT: OpTrace
+ 0x42480, // NOLINT: wideToNarrowTtuStateRegFile
+ 0x42500, // NOLINT: dmaWideToNarrowTrace
+ 0x42580, // NOLINT: narrowToWideTtuStateRegFile
+ 0x42600, // NOLINT: dmaNarrowToWideTrace
+ 0x42620, // NOLINT: ringBusConsumer0TtuStateRegFile
+ 0x42640, // NOLINT: dmaRingBusConsumer0Trace
+ 0x42660, // NOLINT: ringBusConsumer1TtuStateRegFile
+ 0x42680, // NOLINT: dmaRingBusConsumer1Trace
+ 0x426a0, // NOLINT: ringBusProducerTtuStateRegFile
+ 0x426c0, // NOLINT: dmaRingBusProducerTrace
+ 0x42700, // NOLINT: meshBus0TtuStateRegFile
+ 0x42740, // NOLINT: dmaMeshBus0Trace
+ 0x42780, // NOLINT: meshBus1TtuStateRegFile
+ 0x427c0, // NOLINT: dmaMeshBus1Trace
+ 0x42800, // NOLINT: meshBus2TtuStateRegFile
+ 0x42840, // NOLINT: dmaMeshBus2Trace
+ 0x42880, // NOLINT: meshBus3TtuStateRegFile
+ 0x428c0, // NOLINT: dmaMeshBus3Trace
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryIsolation
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryRetention
+};
+
+const HibKernelCsrOffsets kBeagleHibKernelCsrOffsets = {
+ 0x46000, // NOLINT: page_table_size
+ 0x46008, // NOLINT: extended_table
+ 0x46050, // NOLINT: dma_pause
+ 0x46078, // NOLINT: page_table_init
+ 0x46080, // NOLINT: msix_table_init
+ 0x50000, // NOLINT: page_table
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, dma_burst_limiter
+};
+
+const HibUserCsrOffsets kBeagleHibUserCsrOffsets = {
+ 0x486b0, // NOLINT: top_level_int_control
+ 0x486b8, // NOLINT: top_level_int_status
+ 0x486d0, // NOLINT: sc_host_int_count
+ 0x486d8, // NOLINT: dma_pause
+ 0x486e0, // NOLINT: dma_paused
+ 0x486e8, // NOLINT: status_block_update
+ 0x486f0, // NOLINT: hib_error_status
+ 0x486f8, // NOLINT: hib_error_mask
+ 0x48700, // NOLINT: hib_first_error_status
+ 0x48708, // NOLINT: hib_first_error_timestamp
+ 0x48710, // NOLINT: hib_inject_error
+ 0x487a8, // NOLINT: dma_burst_limiter
+};
+
+const QueueCsrOffsets kBeagleInstructionQueueCsrOffsets = {
+ 0x48568, // NOLINT: instruction_queue_control
+ 0x48570, // NOLINT: instruction_queue_status
+ 0x48578, // NOLINT: instruction_queue_descriptor_size
+ 0x48590, // NOLINT: instruction_queue_base
+ 0x48598, // NOLINT: instruction_queue_status_block_base
+ 0x485a0, // NOLINT: instruction_queue_size
+ 0x485a8, // NOLINT: instruction_queue_tail
+ 0x485b0, // NOLINT: instruction_queue_fetched_head
+ 0x485b8, // NOLINT: instruction_queue_completed_head
+ 0x485c0, // NOLINT: instruction_queue_int_control
+ 0x485c8, // NOLINT: instruction_queue_int_status
+ 0x48580, // NOLINT: instruction_queue_minimum_size
+ 0x48588, // NOLINT: instruction_queue_maximum_size
+ 0x46018, // NOLINT: instruction_queue_int_vector
+};
+
+const MemoryCsrOffsets kBeagleMemoryMemoryCsrOffsets = {
+ 0x42010, // NOLINT: memoryAccess
+ 0x42018, // NOLINT: memoryData
+};
+
+const ScalarCoreCsrOffsets kBeagleScalarCoreCsrOffsets = {
+ 0x44018, // NOLINT: scalarCoreRunControl
+ 0x44038, // NOLINT: executeControl
+ 0x44158, // NOLINT: avDataPopRunControl
+ 0x44198, // NOLINT: parameterPopRunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_2RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, scalarDatapath_3RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, executeControl_3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, avDataPop_3RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, parameterPop_3RunControl
+ 0x441d8, // NOLINT: infeedRunControl
+ 0x44218, // NOLINT: outfeedRunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, contextControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, contextStatus
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_0_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_0_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_1_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_1_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_2_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_2_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_0RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, infeed_3_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, outfeed_3_1RunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, TilePowerInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakPowerSampleInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpPowerSampleInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtPowerSampleInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakSampleAccumulator
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpSampleAccumulator
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtSampleAccumulator
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakThreshold0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakThreshold1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakThreshold2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakThreshold3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpThreshold0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpThreshold1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpThreshold2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpThreshold3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtThreshold0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakActionTable
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpActionTable
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtActionTable
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakRunningSum
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, peakRunningSumInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpRunningSum
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, tdpRunningSumInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtRunningSum
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtRunningSumInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtDifference
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, packageTdpAction
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, ThrottleStallCounter
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, cycleCount
+};
+
+const MemoryCsrOffsets kBeagleScmemoryMemoryCsrOffsets = {
+ 0x44040, // NOLINT: scMemoryAccess
+ 0x44048, // NOLINT: scMemoryData
+};
+
+const TileConfigCsrOffsets kBeagleTileConfigCsrOffsets = {
+ 0x48788, // NOLINT: tileconfig0
+ 0x48790, // NOLINT: tileconfig1
+};
+
+const TileCsrOffsets kBeagleTileCsrOffsets = {
+ 0x400c0, // NOLINT: opRunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToNarrowRunControl
+ 0x40150, // NOLINT: narrowToWideRunControl
+ 0x40110, // NOLINT: wideToNarrowRunControl
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_3
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_4
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_4
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_4
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_5
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_5
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_5
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_6
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_6
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_6
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opRunControl_7
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowToWideRunControl_7
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, wideToNarrowRunControl_7
+ 0x40190, // NOLINT: ringBusConsumer0RunControl
+ 0x401d0, // NOLINT: ringBusConsumer1RunControl
+ 0x40210, // NOLINT: ringBusProducerRunControl
+ 0x40250, // NOLINT: meshBus0RunControl
+ 0x40298, // NOLINT: meshBus1RunControl
+ 0x402e0, // NOLINT: meshBus2RunControl
+ 0x40328, // NOLINT: meshBus3RunControl
+ 0x40020, // NOLINT: deepSleep
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryIsolation
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryRetention
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, EnergyTable
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtSampleInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtRunningSumInterval
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, opAccumulateRegister
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtRunningSumRegister
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, didtThreshold0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_0
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_1
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_2
+ kCsrRegisterSpaceInvalidOffset, // UNUSED, narrowMemoryContext_3
+};
+
+const WireCsrOffsets kBeagleWireCsrOffsets = {
+ 0x48778, // NOLINT: wire_int_pending_bit_array
+ 0x48780, // NOLINT: wire_int_mask_array
+};
+
+const InterruptCsrOffsets kBeagleUsbFatalErrIntInterruptCsrOffsets = {
+ 0x4c060, // NOLINT: fatal_err_int_control
+ 0x4c068, // NOLINT: fatal_err_int_status
+};
+
+const InterruptCsrOffsets kBeagleUsbScHostInt0InterruptCsrOffsets = {
+ 0x4c0b0, // NOLINT: sc_host_int_0_control
+ 0x4c0b8, // NOLINT: sc_host_int_0_status
+};
+
+const InterruptCsrOffsets kBeagleUsbScHostInt1InterruptCsrOffsets = {
+ 0x4c0c8, // NOLINT: sc_host_int_1_control
+ 0x4c0d0, // NOLINT: sc_host_int_1_status
+};
+
+const InterruptCsrOffsets kBeagleUsbScHostInt2InterruptCsrOffsets = {
+ 0x4c0e0, // NOLINT: sc_host_int_2_control
+ 0x4c0e8, // NOLINT: sc_host_int_2_status
+};
+
+const InterruptCsrOffsets kBeagleUsbScHostInt3InterruptCsrOffsets = {
+ 0x4c0f8, // NOLINT: sc_host_int_3_control
+ 0x4c100, // NOLINT: sc_host_int_3_status
+};
+
+const InterruptCsrOffsets kBeagleUsbTopLevelInt0InterruptCsrOffsets = {
+ 0x4c070, // NOLINT: top_level_int_0_control
+ 0x4c078, // NOLINT: top_level_int_0_status
+};
+
+const InterruptCsrOffsets kBeagleUsbTopLevelInt1InterruptCsrOffsets = {
+ 0x4c080, // NOLINT: top_level_int_1_control
+ 0x4c088, // NOLINT: top_level_int_1_status
+};
+
+const InterruptCsrOffsets kBeagleUsbTopLevelInt2InterruptCsrOffsets = {
+ 0x4c090, // NOLINT: top_level_int_2_control
+ 0x4c098, // NOLINT: top_level_int_2_status
+};
+
+const InterruptCsrOffsets kBeagleUsbTopLevelInt3InterruptCsrOffsets = {
+ 0x4c0a0, // NOLINT: top_level_int_3_control
+ 0x4c0a8, // NOLINT: top_level_int_3_status
+};
+
+const ApexCsrOffsets kBeagleApexCsrOffsets = {
+ 0x1a000, // NOLINT: omc0_00
+ 0x1a0d4, // NOLINT: omc0_d4
+ 0x1a0d8, // NOLINT: omc0_d8
+ 0x1a0dc, // NOLINT: omc0_dc
+ 0x1a600, // NOLINT: mst_abm_en
+ 0x1a500, // NOLINT: slv_abm_en
+ 0x1a558, // NOLINT: slv_err_resp_isr_mask
+ 0x1a658, // NOLINT: mst_err_resp_isr_mask
+ 0x1a640, // NOLINT: mst_wr_err_resp
+ 0x1a644, // NOLINT: mst_rd_err_resp
+ 0x1a540, // NOLINT: slv_wr_err_resp
+ 0x1a544, // NOLINT: slv_rd_err_resp
+ 0x1a704, // NOLINT: rambist_ctrl_1
+ 0x1a200, // NOLINT: efuse_00
+};
+
+const CbBridgeCsrOffsets kBeagleCbBridgeCsrOffsets = {
+ 0x19018, // NOLINT: bo0_fifo_status
+ 0x1901c, // NOLINT: bo1_fifo_status
+ 0x19020, // NOLINT: bo2_fifo_status
+ 0x19024, // NOLINT: bo3_fifo_status
+ 0x1907c, // NOLINT: gcbb_credit0
+};
+
+const MiscCsrOffsets kBeagleMiscCsrOffsets = {
+ 0x4a000, // NOLINT: idleRegister
+};
+
+const MsixCsrOffsets kBeagleMsixCsrOffsets = {
+ 0x46018, // NOLINT: instruction_queue_int_vector
+ 0x46020, // NOLINT: input_actv_queue_int_vector
+ 0x46028, // NOLINT: param_queue_int_vector
+ 0x46030, // NOLINT: output_actv_queue_int_vector
+ 0x46040, // NOLINT: top_level_int_vector
+ 0x46038, // NOLINT: sc_host_int_vector
+ 0x46048, // NOLINT: fatal_err_int_vector
+ 0x46068, // NOLINT: msix_pending_bit_array0
+ 0x46800, // NOLINT: msix_table
+};
+
+const ScuCsrOffsets kBeagleScuCsrOffsets = {
+ 0x1a30c, // NOLINT: scu_ctrl_0
+ 0x1a310, // NOLINT: scu_ctrl_1
+ 0x1a314, // NOLINT: scu_ctrl_2
+ 0x1a318, // NOLINT: scu_ctrl_3
+ 0x1a31c, // NOLINT: scu_ctrl_4
+ 0x1a320, // NOLINT: scu_ctrl_5
+ 0x1a32c, // NOLINT: scu_ctr_6
+ 0x1a33c, // NOLINT: scu_ctr_7
+};
+
+const UsbCsrOffsets kBeagleUsbCsrOffsets = {
+ 0x4c058, // NOLINT: outfeed_chunk_length
+ 0x4c148, // NOLINT: descr_ep
+ 0x4c150, // NOLINT: ep_status_credit
+ 0x4c160, // NOLINT: multi_bo_ep
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_BEAGLE_BEAGLE_CSR_OFFSETS_H_
diff --git a/driver/config/beagle_csr_helper.h b/driver/config/beagle_csr_helper.h
new file mode 100644
index 0000000..474795a
--- /dev/null
+++ b/driver/config/beagle_csr_helper.h
@@ -0,0 +1,544 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_BEAGLE_CSR_HELPER_H_
+#define DARWINN_DRIVER_CONFIG_BEAGLE_CSR_HELPER_H_
+
+#include "driver/bitfield.h"
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+namespace registers {
+
+// CSR helper to access fields for omc0_d4 CSR.
+class Omc0D4 {
+ public:
+ // Defaults to reset value.
+ Omc0D4() : Omc0D4(0x1ULL) {}
+ explicit Omc0D4(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_method_sel(uint64 value) { reg_.method_sel_ = value; }
+ uint64 method_sel() const { return reg_.method_sel_(); }
+
+ void set_thm_warn1(uint64 value) { reg_.thm_warn1_ = value; }
+ uint64 thm_warn1() const { return reg_.thm_warn1_(); }
+
+ void set_thm_warn_en(uint64 value) { reg_.thm_warn_en_ = value; }
+ uint64 thm_warn_en() const { return reg_.thm_warn_en_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> method_sel_;
+ platforms::darwinn::driver::Bitfield<1, 15> field_01_;
+ platforms::darwinn::driver::Bitfield<16, 10> thm_warn1_;
+ platforms::darwinn::driver::Bitfield<26, 5> field_26_;
+ platforms::darwinn::driver::Bitfield<31, 1> thm_warn_en_;
+ } reg_;
+};
+
+// CSR helper to access fields for omc0_d8 CSR.
+class Omc0D8 {
+ public:
+ // Defaults to reset value.
+ Omc0D8() : Omc0D8(0ULL) {}
+ explicit Omc0D8(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_enbg(uint64 value) { reg_.enbg_ = value; }
+ uint64 enbg() const { return reg_.enbg_(); }
+
+ void set_envr(uint64 value) { reg_.envr_ = value; }
+ uint64 envr() const { return reg_.envr_(); }
+
+ void set_enad(uint64 value) { reg_.enad_ = value; }
+ uint64 enad() const { return reg_.enad_(); }
+
+ void set_thm_warn2(uint64 value) { reg_.thm_warn2_ = value; }
+ uint64 thm_warn2() const { return reg_.thm_warn2_(); }
+
+ void set_sd_en(uint64 value) { reg_.sd_en_ = value; }
+ uint64 sd_en() const { return reg_.sd_en_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> enbg_;
+ platforms::darwinn::driver::Bitfield<1, 1> envr_;
+ platforms::darwinn::driver::Bitfield<2, 1> enad_;
+ platforms::darwinn::driver::Bitfield<3, 13> field_03_;
+ platforms::darwinn::driver::Bitfield<16, 10> thm_warn2_;
+ platforms::darwinn::driver::Bitfield<26, 5> field_26_;
+ platforms::darwinn::driver::Bitfield<31, 1> sd_en_;
+ } reg_;
+};
+
+// CSR helper to access fields for omc0_dc CSR.
+class Omc0DC {
+ public:
+ // Defaults to reset value.
+ Omc0DC() : Omc0DC(0ULL) { set_data(0x3FF); }
+ explicit Omc0DC(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_data(uint64 value) { reg_.data_ = value; }
+ uint64 data() const { return reg_.data_(); }
+
+ void set_sd_clear(uint64 value) { reg_.sd_clear_ = value; }
+ uint64 sd_clear() const { return reg_.sd_clear_(); }
+
+ void set_warn_clear(uint64 value) { reg_.warn_clear_ = value; }
+ uint64 warn_clear() const { return reg_.warn_clear_(); }
+
+ // Read-Only.
+ uint64 sd_o() const { return reg_.sd_o_(); }
+ uint64 warn_o() const { return reg_.warn_o_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> enthmc_;
+ platforms::darwinn::driver::Bitfield<1, 15> field_01_;
+ platforms::darwinn::driver::Bitfield<16, 10> data_;
+ platforms::darwinn::driver::Bitfield<26, 2> field_26_;
+ platforms::darwinn::driver::Bitfield<28, 1> sd_clear_;
+ platforms::darwinn::driver::Bitfield<29, 1> warn_clear_;
+ platforms::darwinn::driver::Bitfield<30, 1> sd_o_;
+ platforms::darwinn::driver::Bitfield<31, 1> warn_o_;
+ } reg_;
+};
+
+// CSR helper to access fields for rambist_ctrl_1 CSR.
+class RamBistCtrl1 {
+ public:
+ // Defaults to reset value.
+ RamBistCtrl1() : RamBistCtrl1(0ULL) {
+ set_rg_rambist_gcbsel(0x1F);
+ set_rg_rambist_topsel(0x3);
+ set_rg_mbist_int_mask(0x7);
+ }
+ explicit RamBistCtrl1(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_rambist_gcbsel(uint64 value) { reg_.rg_rambist_gcbsel_ = value; }
+ uint64 rg_rambist_gcbsel() const { return reg_.rg_rambist_gcbsel_(); }
+
+ void set_rg_rambist_topsel(uint64 value) { reg_.rg_rambist_topsel_ = value; }
+ uint64 rg_rambist_topsel() const { return reg_.rg_rambist_topsel_(); }
+
+ void set_rg_rambist_tckmode(uint64 value) {
+ reg_.rg_rambist_tckmode_ = value;
+ }
+ uint64 rg_rambist_tckmode() const { return reg_.rg_rambist_tckmode_(); }
+
+ void set_rg_rambist_req(uint64 value) { reg_.rg_rambist_req_ = value; }
+ uint64 rg_rambist_req() const { return reg_.rg_rambist_req_(); }
+
+ void set_rg_tck_invert(uint64 value) { reg_.rg_tck_invert_ = value; }
+ uint64 rg_tck_invert() const { return reg_.rg_tck_invert_(); }
+
+ void set_mbist_status(uint64 value) { reg_.mbist_status_ = value; }
+ uint64 mbist_status() const { return reg_.mbist_status_(); }
+
+ void set_rg_mbist_int_status(uint64 value) {
+ reg_.rg_mbist_int_status_ = value;
+ }
+ uint64 rg_mbist_int_status() const { return reg_.rg_mbist_int_status_(); }
+
+ void set_rg_mbist_int_mask(uint64 value) { reg_.rg_mbist_int_mask_ = value; }
+ uint64 rg_mbist_int_mask() const { return reg_.rg_mbist_int_mask_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 5> rg_rambist_gcbsel_;
+ platforms::darwinn::driver::Bitfield<5, 2> rg_rambist_topsel_;
+ platforms::darwinn::driver::Bitfield<7, 1> field_07_;
+ platforms::darwinn::driver::Bitfield<8, 1> rg_rambist_tckmode_;
+ platforms::darwinn::driver::Bitfield<9, 1> rg_rambist_req_;
+ platforms::darwinn::driver::Bitfield<10, 1> rg_tck_invert_;
+ platforms::darwinn::driver::Bitfield<11, 1> field_11_;
+ platforms::darwinn::driver::Bitfield<12, 2> mbist_status_;
+ platforms::darwinn::driver::Bitfield<14, 2> field_14_;
+ platforms::darwinn::driver::Bitfield<16, 3> rg_mbist_int_status_;
+ platforms::darwinn::driver::Bitfield<19, 1> field_19_;
+ platforms::darwinn::driver::Bitfield<20, 3> rg_mbist_int_mask_;
+ platforms::darwinn::driver::Bitfield<23, 9> field_23_;
+ } reg_;
+};
+
+// CSR helper to access fields for efuse_00 CSR.
+class Efuse00 {
+ public:
+ // Defaults to reset value.
+ Efuse00() : Efuse00(0ULL) {}
+ explicit Efuse00(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_ef_int_mask(uint64 value) { reg_.ef_int_mask_ = value; }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> ef_single_step_dis_;
+ platforms::darwinn::driver::Bitfield<1, 2> ef_prod_sel_;
+ platforms::darwinn::driver::Bitfield<3, 3> ef_refclk_sel_ovr_;
+ platforms::darwinn::driver::Bitfield<6, 1> ef_pcie_gen1_link_;
+ platforms::darwinn::driver::Bitfield<7, 1> ef_usb_ssc_mode_0_;
+ platforms::darwinn::driver::Bitfield<8, 5> ef_i2caddr_ovr_;
+ platforms::darwinn::driver::Bitfield<13, 3> ef_psigma_;
+ platforms::darwinn::driver::Bitfield<16, 1> ef_mbist_dis_;
+ platforms::darwinn::driver::Bitfield<17, 1> ef_w_dis_;
+ platforms::darwinn::driver::Bitfield<18, 1> ef_thm_int_mask_;
+ platforms::darwinn::driver::Bitfield<19, 1> ef_int_mask_;
+ platforms::darwinn::driver::Bitfield<20, 2> ef_pwr_state_dis_;
+ platforms::darwinn::driver::Bitfield<22, 1> ef_usb_ssc_mode_1_;
+ platforms::darwinn::driver::Bitfield<23, 1> ef_8051_rom_500m_;
+ platforms::darwinn::driver::Bitfield<24, 8> ef_pll_M_;
+ } reg_;
+};
+
+// CSR helper to access fields for scu_ctrl_0 CSR.
+class ScuCtrl0 {
+ public:
+ // Defaults to reset value.
+ ScuCtrl0() : ScuCtrl0(0ULL) {
+ set_rg_pllclk_sel(1);
+ set_rg_usb_slp_phy_mode(1);
+ set_rg_pcie_inact_phy_mode(1);
+ set_rg_usb_inact_phy_mode(1);
+ }
+ explicit ScuCtrl0(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_pllclk_sel(uint64 value) { reg_.rg_pllclk_sel_ = value; }
+ uint64 rg_pllclk_sel() const { return reg_.rg_pllclk_sel_(); }
+
+ void set_rg_usb_slp_phy_mode(uint64 value) {
+ reg_.rg_usb_slp_phy_mode_ = value;
+ }
+ uint64 rg_usb_slp_phy_mode() const { return reg_.rg_usb_slp_phy_mode_(); }
+
+ void set_rg_pcie_inact_phy_mode(uint64 value) {
+ reg_.rg_pcie_inact_phy_mode_ = value;
+ }
+ uint64 rg_pcie_inact_phy_mode() const {
+ return reg_.rg_pcie_inact_phy_mode_();
+ }
+
+ void set_rg_usb_inact_phy_mode(uint64 value) {
+ reg_.rg_usb_inact_phy_mode_ = value;
+ }
+ uint64 rg_usb_inact_phy_mode() const { return reg_.rg_usb_inact_phy_mode_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> rg_pllclk_sel_;
+ platforms::darwinn::driver::Bitfield<1, 1> rg_single_exit_;
+ platforms::darwinn::driver::Bitfield<2, 1> rg_single_link_rstn_;
+ platforms::darwinn::driver::Bitfield<3, 1> rg_sleep_chk_idle_;
+ platforms::darwinn::driver::Bitfield<4, 2> rg_pcie_slp_phy_mode_;
+ platforms::darwinn::driver::Bitfield<6, 2> rg_usb_slp_phy_mode_;
+ platforms::darwinn::driver::Bitfield<8, 3> rg_pcie_inact_phy_mode_;
+ platforms::darwinn::driver::Bitfield<11, 3> rg_usb_inact_phy_mode_;
+ platforms::darwinn::driver::Bitfield<14, 2> rg_mem_mode_dis_;
+ platforms::darwinn::driver::Bitfield<16, 1> rg_phy_prg_;
+ platforms::darwinn::driver::Bitfield<17, 1> bt_phy_prg_;
+ platforms::darwinn::driver::Bitfield<18, 1> bt_vbus_sel_;
+ platforms::darwinn::driver::Bitfield<19, 1> bt_bus_pwr_;
+ } reg_;
+};
+
+// CSR helper to access fields for scu_ctrl_2 CSR.
+class ScuCtrl2 {
+ public:
+ // Defaults to reset value.
+ ScuCtrl2() : ScuCtrl2(0ULL) {}
+ explicit ScuCtrl2(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_gated_gcb(uint64 value) { reg_.rg_gated_gcb_ = value; }
+ uint64 rg_gated_gcb() const { return reg_.rg_gated_gcb_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> rg_rst_pcie_;
+ platforms::darwinn::driver::Bitfield<1, 1> rg_rst_pcie_axi_;
+ platforms::darwinn::driver::Bitfield<2, 2> rg_rst_gcb_;
+ platforms::darwinn::driver::Bitfield<4, 1> rg_rst_pcieslv_abm_;
+ platforms::darwinn::driver::Bitfield<5, 1> rg_rst_pciemst_abm_;
+ platforms::darwinn::driver::Bitfield<6, 1> rg_rst_omc_;
+ platforms::darwinn::driver::Bitfield<7, 1> rg_rst_mbist_;
+ platforms::darwinn::driver::Bitfield<8, 1> rg_rst_usb_;
+ platforms::darwinn::driver::Bitfield<9, 1> rg_rst_usb_subsys_;
+ platforms::darwinn::driver::Bitfield<10, 1> rg_rst_full_;
+ platforms::darwinn::driver::Bitfield<11, 1> rg_rst_link_;
+ platforms::darwinn::driver::Bitfield<12, 1> rg_rst_i2c_;
+ platforms::darwinn::driver::Bitfield<13, 1> rg_rst_scu_;
+ platforms::darwinn::driver::Bitfield<14, 1> rg_self_rst_subsys_;
+ platforms::darwinn::driver::Bitfield<15, 1> rg_rst_brg_;
+ platforms::darwinn::driver::Bitfield<16, 1> rg_gated_pcie_;
+ platforms::darwinn::driver::Bitfield<17, 1> rg_gated_phy_cfg_;
+ platforms::darwinn::driver::Bitfield<18, 2> rg_gated_gcb_;
+ platforms::darwinn::driver::Bitfield<20, 1> rg_gated_pcieslv_abm_;
+ platforms::darwinn::driver::Bitfield<21, 1> rg_gated_pciemst_abm_;
+ platforms::darwinn::driver::Bitfield<22, 1> rg_gated_omc_;
+ platforms::darwinn::driver::Bitfield<23, 1> rg_gated_mbist_;
+ platforms::darwinn::driver::Bitfield<24, 1> rg_gated_usb_;
+ platforms::darwinn::driver::Bitfield<25, 1> rg_gated_usb_subsys_;
+ platforms::darwinn::driver::Bitfield<26, 1> rg_gated_8051_;
+ } reg_;
+};
+
+// CSR helper to access fields for scu_ctrl_3 CSR.
+class ScuCtrl3 {
+ public:
+ enum class GcbClock {
+ k63MHZ,
+ k125MHZ,
+ k250MHZ,
+ k500MHZ,
+ };
+ enum class AxiClock {
+ k125MHZ,
+ k250MHZ,
+ };
+ enum class Usb8051Clock {
+ k250MHZ,
+ k500MHZ,
+ };
+
+ // Defaults to reset value.
+ ScuCtrl3() : ScuCtrl3(0x80050410ULL) {}
+ explicit ScuCtrl3(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_force_sleep(uint64 value) { reg_.rg_force_sleep_ = value; }
+ uint64 rg_force_sleep() const { return reg_.rg_force_sleep_(); }
+
+ void set_cur_pwr_state(uint64 value) { reg_.cur_pwr_state_ = value; }
+ uint64 cur_pwr_state() const { return reg_.cur_pwr_state_(); }
+
+ void set_gcb_clock_rate(GcbClock rate) {
+ switch (rate) {
+ case GcbClock::k63MHZ:
+ reg_.rg_gcb_clkdiv_ = 3;
+ break;
+ case GcbClock::k125MHZ:
+ reg_.rg_gcb_clkdiv_ = 2;
+ break;
+ case GcbClock::k250MHZ:
+ reg_.rg_gcb_clkdiv_ = 1;
+ break;
+ case GcbClock::k500MHZ:
+ reg_.rg_gcb_clkdiv_ = 0;
+ break;
+ }
+ }
+
+ GcbClock gcb_clock_rate() const {
+ switch (reg_.rg_gcb_clkdiv_()) {
+ case 3:
+ return GcbClock::k63MHZ;
+ case 2:
+ return GcbClock::k125MHZ;
+ case 1:
+ return GcbClock::k250MHZ;
+ default:
+ return GcbClock::k500MHZ;
+ }
+ }
+
+ void set_axi_clock_rate(AxiClock rate) {
+ switch (rate) {
+ case AxiClock::k125MHZ:
+ reg_.rg_axi_clk_125m_ = 1;
+ break;
+ case AxiClock::k250MHZ:
+ reg_.rg_axi_clk_125m_ = 0;
+ break;
+ }
+ }
+
+ AxiClock axi_clock_rate() const {
+ if (reg_.rg_axi_clk_125m_()) {
+ return AxiClock::k125MHZ;
+ } else {
+ return AxiClock::k250MHZ;
+ }
+ }
+
+ void set_usb_8051_clock_rate(Usb8051Clock rate) {
+ switch (rate) {
+ case Usb8051Clock::k250MHZ:
+ reg_.rg_8051_clk_250m_ = 1;
+ break;
+ case Usb8051Clock::k500MHZ:
+ reg_.rg_8051_clk_250m_ = 0;
+ break;
+ }
+ }
+
+ Usb8051Clock usb_8051_clock_rate() const {
+ if (reg_.rg_8051_clk_250m_()) {
+ return Usb8051Clock::k250MHZ;
+ } else {
+ return Usb8051Clock::k500MHZ;
+ }
+ }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 1> pcie_state_l1p2_;
+ platforms::darwinn::driver::Bitfield<1, 1> pcie_state_l0s_;
+ platforms::darwinn::driver::Bitfield<2, 1> pcie_state_l0_;
+ platforms::darwinn::driver::Bitfield<3, 1> cur_gated_gcb_;
+ platforms::darwinn::driver::Bitfield<4, 1> cur_rst_gcb_;
+ platforms::darwinn::driver::Bitfield<5, 1> field_05_;
+ platforms::darwinn::driver::Bitfield<6, 1> cur_gcb_sram_sd_;
+ platforms::darwinn::driver::Bitfield<7, 1> cur_gcb_sram_dslp_;
+ platforms::darwinn::driver::Bitfield<8, 2> cur_pwr_state_;
+ platforms::darwinn::driver::Bitfield<10, 2> pcie_gen_info_;
+ platforms::darwinn::driver::Bitfield<12, 2> rg_force_ram_dslp_;
+ platforms::darwinn::driver::Bitfield<14, 2> rg_force_ram_sd_;
+ platforms::darwinn::driver::Bitfield<16, 3> rg_sd2wk_dly_;
+ platforms::darwinn::driver::Bitfield<19, 1> rg_slp_mode_req_;
+ platforms::darwinn::driver::Bitfield<20, 2> rg_force_inact_;
+ platforms::darwinn::driver::Bitfield<22, 2> rg_force_sleep_;
+ platforms::darwinn::driver::Bitfield<24, 1> field_24_;
+ platforms::darwinn::driver::Bitfield<25, 1> rg_link_rdy_ovr_;
+ platforms::darwinn::driver::Bitfield<26, 2> rg_pwr_state_ovr_;
+ platforms::darwinn::driver::Bitfield<28, 2> rg_gcb_clkdiv_;
+ platforms::darwinn::driver::Bitfield<30, 1> rg_axi_clk_125m_;
+ platforms::darwinn::driver::Bitfield<31, 1> rg_8051_clk_250m_;
+ } reg_;
+};
+
+// CSR helper to access fields for scu_ctrl_6 CSR.
+class ScuCtrl6 {
+ public:
+ // Defaults to reset value.
+ ScuCtrl6() : ScuCtrl6(0ULL) {}
+ explicit ScuCtrl6(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_gcb_spare_in(uint64 value) { reg_.rg_gcb_spare_in_ = value; }
+ uint64 rg_gcb_spare_in() const { return reg_.rg_gcb_spare_in_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 2> rg_pad_ds_;
+ platforms::darwinn::driver::Bitfield<2, 2> rg_pad_ds_i2c_;
+ platforms::darwinn::driver::Bitfield<4, 2> rg_pad_ds_gpio_;
+ platforms::darwinn::driver::Bitfield<6, 2> rg_pad_ds_xin_;
+ platforms::darwinn::driver::Bitfield<8, 8> rg_pinmux_sel_;
+ platforms::darwinn::driver::Bitfield<16, 4> rg_gcb_spare_in_;
+ platforms::darwinn::driver::Bitfield<20, 4> gcb_spare_out_;
+ platforms::darwinn::driver::Bitfield<24, 1> warning_o_;
+ platforms::darwinn::driver::Bitfield<25, 1> int_mbist_;
+ platforms::darwinn::driver::Bitfield<26, 1> err_resp_isr_0_;
+ platforms::darwinn::driver::Bitfield<27, 1> err_resp_isr_1_;
+ platforms::darwinn::driver::Bitfield<28, 2> rg_jtag_sel_;
+ platforms::darwinn::driver::Bitfield<30, 1> rg_jtag_io_sel_;
+ platforms::darwinn::driver::Bitfield<31, 1> field_31_;
+ } reg_;
+};
+
+// CSR helper to access fields for scu_ctr_7 CSR.
+class ScuCtrl7 {
+ public:
+ // Defaults to reset value.
+ ScuCtrl7() : ScuCtrl7(0ULL) {
+ set_rg_inact_thd(0x3F);
+ set_rg_boot_failure_mask(0x3);
+ }
+ explicit ScuCtrl7(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_rg_boot_failure_mask(uint64 value) {
+ reg_.rg_boot_failure_mask_ = value;
+ }
+ uint64 rg_boot_failure_mask() const { return reg_.rg_boot_failure_mask_(); }
+
+ void set_rg_inact_thd(uint64 value) { reg_.rg_inact_thd_ = value; }
+ uint64 rg_inact_thd() const { return reg_.rg_inact_thd_(); }
+
+ void set_rg_boot_failure_raw(uint64 value) {
+ reg_.rg_boot_failure_raw_ = value;
+ }
+ uint64 rg_boot_failure_raw() const { return reg_.rg_boot_failure_raw_(); }
+
+ void set_pll_lock_failure(uint64 value) { reg_.pll_lock_failure_ = value; }
+ uint64 pll_lock_failure() const { return reg_.pll_lock_failure_(); }
+
+ void set_usb_sel_failure(uint64 value) { reg_.usb_sel_failure_ = value; }
+ uint64 usb_sel_failure() const { return reg_.usb_sel_failure_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 16> rg_inact_thd_;
+ platforms::darwinn::driver::Bitfield<16, 1> pll_lock_failure_;
+ platforms::darwinn::driver::Bitfield<17, 1> usb_sel_failure_;
+ platforms::darwinn::driver::Bitfield<18, 2> rg_boot_failure_mask_;
+ platforms::darwinn::driver::Bitfield<20, 2> rg_boot_failure_raw_;
+ platforms::darwinn::driver::Bitfield<22, 10> field_22_;
+ } reg_;
+};
+
+} // namespace registers
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_BEAGLE_CSR_HELPER_H_
diff --git a/driver/config/breakpoint_csr_offsets.h b/driver/config/breakpoint_csr_offsets.h
new file mode 100644
index 0000000..2cb9cb4
--- /dev/null
+++ b/driver/config/breakpoint_csr_offsets.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_BREAKPOINT_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_BREAKPOINT_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for breakpointing a hardware component.
+// e.g. scalar core, TTU, etc.
+// Members are intentionally named to match the GCSR register names.
+struct BreakpointCsrOffsets {
+ uint64 RunControl;
+ uint64 RunStatus;
+ uint64 BreakPoint;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_BREAKPOINT_CSR_OFFSETS_H_
diff --git a/driver/config/cb_bridge_csr_offsets.h b/driver/config/cb_bridge_csr_offsets.h
new file mode 100644
index 0000000..2f9ae0d
--- /dev/null
+++ b/driver/config/cb_bridge_csr_offsets.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_CB_BRIDGE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_CB_BRIDGE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for cb_bridge in Beagle.
+// Members are intentionally named to match the GCSR register names.
+struct CbBridgeCsrOffsets {
+ uint64 bo0_fifo_status;
+ uint64 bo1_fifo_status;
+ uint64 bo2_fifo_status;
+ uint64 bo3_fifo_status;
+ uint64 gcbb_credit0;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_CB_BRIDGE_CSR_OFFSETS_H_
diff --git a/driver/config/chip_config.h b/driver/config/chip_config.h
new file mode 100644
index 0000000..76f6a49
--- /dev/null
+++ b/driver/config/chip_config.h
@@ -0,0 +1,399 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_CHIP_CONFIG_H_
+#define DARWINN_DRIVER_CONFIG_CHIP_CONFIG_H_
+
+#include "api/chip.h"
+#include "driver/config/apex_csr_offsets.h"
+#include "driver/config/breakpoint_csr_offsets.h"
+#include "driver/config/cb_bridge_csr_offsets.h"
+#include "driver/config/chip_structures.h"
+#include "driver/config/debug_hib_user_csr_offsets.h"
+#include "driver/config/debug_scalar_core_csr_offsets.h"
+#include "driver/config/debug_tile_csr_offsets.h"
+#include "driver/config/hib_kernel_csr_offsets.h"
+#include "driver/config/hib_user_csr_offsets.h"
+#include "driver/config/interrupt_csr_offsets.h"
+#include "driver/config/memory_csr_offsets.h"
+#include "driver/config/misc_csr_offsets.h"
+#include "driver/config/msix_csr_offsets.h"
+#include "driver/config/queue_csr_offsets.h"
+#include "driver/config/register_file_csr_offsets.h"
+#include "driver/config/scalar_core_csr_offsets.h"
+#include "driver/config/scu_csr_offsets.h"
+#include "driver/config/sync_flag_csr_offsets.h"
+#include "driver/config/tile_config_csr_offsets.h"
+#include "driver/config/tile_csr_offsets.h"
+#include "driver/config/tile_thread_csr_offsets.h"
+#include "driver/config/trace_csr_offsets.h"
+#include "driver/config/usb_csr_offsets.h"
+#include "driver/config/wire_csr_offsets.h"
+#include "port/logging.h"
+#include "port/unreachable.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// Project-independent interface for CSR offsets and system constants.
+class ChipConfig {
+ public:
+ virtual ~ChipConfig() = default;
+
+ virtual api::Chip GetChip() const = 0;
+
+ // Extracts CSR offsets for various modules in DarwiNN.
+ virtual const HibKernelCsrOffsets& GetHibKernelCsrOffsets() const = 0;
+ virtual const HibUserCsrOffsets& GetHibUserCsrOffsets() const = 0;
+ virtual const QueueCsrOffsets& GetInstructionQueueCsrOffsets() const = 0;
+ virtual const HibUserCsrOffsets& GetContextSpecificHibUserCsrOffsets(
+ int context_id) const = 0;
+ virtual const QueueCsrOffsets& GetContextSpecificInstructionQueueCsrOffsets(
+ int context_id) const = 0;
+ virtual const ScalarCoreCsrOffsets& GetScalarCoreCsrOffsets() const = 0;
+ virtual const TileConfigCsrOffsets& GetTileConfigCsrOffsets() const = 0;
+ virtual const TileCsrOffsets& GetTileCsrOffsets() const = 0;
+ virtual bool HasThreadCsrOffsets() const { return false; }
+ virtual const TileThreadCsrOffsets& GetTileThread0CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 0 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread1CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 1 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread2CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 2 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread3CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 3 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread4CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 4 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread5CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 5 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread6CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 6 not supported.";
+ unreachable();
+ }
+ virtual const TileThreadCsrOffsets& GetTileThread7CsrOffsets() const {
+ LOG(FATAL) << "Tile thread 7 not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetScalarCoreInterruptCsrOffsets()
+ const = 0;
+ virtual const InterruptCsrOffsets& GetTopLevelInterruptCsrOffsets() const = 0;
+ virtual const InterruptCsrOffsets& GetFatalErrorInterruptCsrOffsets()
+ const = 0;
+ virtual const InterruptCsrOffsets&
+ GetContextSpecificScalarCoreInterruptCsrOffsets(int context_id) const = 0;
+ virtual const InterruptCsrOffsets&
+ GetContextSpecificTopLevelInterruptCsrOffsets(int context_id) const = 0;
+ virtual const InterruptCsrOffsets&
+ GetContextSpecificFatalErrorInterruptCsrOffsets(int context_id) const = 0;
+ // Extracts CSR offsets that supports specific functionality in DarwiNN.
+ virtual const MsixCsrOffsets& GetMsixCsrOffsets() const {
+ LOG(FATAL) << "MSIX interrupt not supported.";
+ unreachable();
+ }
+ virtual const WireCsrOffsets& GetWireCsrOffsets() const = 0;
+ virtual const WireCsrOffsets& GetContextSpecificWireCsrOffsets(
+ int context_id) const = 0;
+ virtual const MiscCsrOffsets& GetMiscCsrOffsets() const {
+ LOG(FATAL) << "Misc not supported.";
+ unreachable();
+ }
+
+ // Extracts chip-specific constants in DarwiNN.
+ virtual const ChipStructures& GetChipStructures() const = 0;
+
+ // Extracts CSR offsets used by scalar core debugger in DarwiNN.
+ virtual const BreakpointCsrOffsets& GetScalarCoreBreakpointCsrOffsets()
+ const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetScalarCoreActivationTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetScalarCoreInfeedTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetScalarCoreOutfeedTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetScalarCoreParameterTtuBreakpointCsrOffsets() const = 0;
+
+ virtual const RegisterFileCsrOffsets& GetScalarRegisterFileCsrOffsets()
+ const = 0;
+ virtual const RegisterFileCsrOffsets& GetPredicateRegisterFileCsrOffsets()
+ const = 0;
+
+ virtual const MemoryCsrOffsets& GetScalarCoreMemoryCsrOffsets() const = 0;
+
+ // Extracts CSR offsets used by tile debugger in DarwiNN.
+ virtual const BreakpointCsrOffsets& GetTileOpTtuBreakpointCsrOffsets()
+ const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetTileWideToNarrowTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetTileNarrowToWideTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetTileRingBusConsumer0TtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetTileRingBusConsumer1TtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets&
+ GetTileRingBusProducerTtuBreakpointCsrOffsets() const = 0;
+ virtual const BreakpointCsrOffsets& GetTileMeshBus0TtuBreakpointCsrOffsets()
+ const = 0;
+ virtual const BreakpointCsrOffsets& GetTileMeshBus1TtuBreakpointCsrOffsets()
+ const = 0;
+ virtual const BreakpointCsrOffsets& GetTileMeshBus2TtuBreakpointCsrOffsets()
+ const = 0;
+ virtual const BreakpointCsrOffsets& GetTileMeshBus3TtuBreakpointCsrOffsets()
+ const = 0;
+
+ virtual const MemoryCsrOffsets& GetTileMemoryCsrOffsets() const = 0;
+
+ // Extracts CSR offsets used by scalar core performance tracing.
+ virtual const TraceCsrOffsets& GetScalarCoreActivationTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetScalarCoreInfeedTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetScalarCoreOutfeedTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetScalarCoreParameterTtuTraceCsrOffsets()
+ const = 0;
+
+ // Extracts CSR offsets used by tile performance tracing.
+ virtual const TraceCsrOffsets& GetTileOpTtuTraceCsrOffsets() const = 0;
+ virtual const TraceCsrOffsets& GetTileWideToNarrowTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetTileNarrowToWideTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetTileRingBusConsumer0TtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetTileRingBusConsumer1TtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetTileRingBusProducerTtuTraceCsrOffsets()
+ const = 0;
+ virtual const TraceCsrOffsets& GetTileMeshBus0TtuTraceCsrOffsets() const = 0;
+ virtual const TraceCsrOffsets& GetTileMeshBus1TtuTraceCsrOffsets() const = 0;
+ virtual const TraceCsrOffsets& GetTileMeshBus2TtuTraceCsrOffsets() const = 0;
+ virtual const TraceCsrOffsets& GetTileMeshBus3TtuTraceCsrOffsets() const = 0;
+
+ virtual const TraceCsrOffsets&
+ GetScalarCoreIrqCompletionBufferTraceCsrOffsets() const {
+ LOG(FATAL) << "Irq completion buffer trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide0TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 0 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide1TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 1 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide2TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 2 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide3TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 3 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide4TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 4 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide5TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 5 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide6TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 6 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToWide7TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to wide 7 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow0TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 0 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow1TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 1 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow2TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 2 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow3TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 3 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow4TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 4 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow5TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 5 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow6TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 6 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaWideToNarrow7TraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA wide to narrow 7 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileDmaNarrowToNarrowTraceCsrOffsets()
+ const {
+ LOG(FATAL) << "DMA narrow to narrow trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp0TraceCsrOffsets() const {
+ LOG(FATAL) << "Op0 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp1TraceCsrOffsets() const {
+ LOG(FATAL) << "Op1 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp2TraceCsrOffsets() const {
+ LOG(FATAL) << "Op2 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp3TraceCsrOffsets() const {
+ LOG(FATAL) << "Op3 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp4TraceCsrOffsets() const {
+ LOG(FATAL) << "Op4 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp5TraceCsrOffsets() const {
+ LOG(FATAL) << "Op5 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp6TraceCsrOffsets() const {
+ LOG(FATAL) << "Op6 trace not supported.";
+ unreachable();
+ }
+ virtual const TraceCsrOffsets& GetTileOp7TraceCsrOffsets() const {
+ LOG(FATAL) << "Op7 trace not supported.";
+ unreachable();
+ }
+
+ // Extracts CSR offsets used to access sync flags in scalar core.
+ virtual const SyncFlagCsrOffsets& GetScalarCoreAvdataPopSyncFlagCsrOffsets()
+ const = 0;
+ virtual const SyncFlagCsrOffsets&
+ GetScalarCoreParameterPopSyncFlagCsrOffsets() const = 0;
+ virtual const SyncFlagCsrOffsets&
+ GetScalarCoreAvdataInfeedSyncFlagCsrOffsets() const = 0;
+ virtual const SyncFlagCsrOffsets&
+ GetScalarCoreParameterInfeedSyncFlagCsrOffsets() const = 0;
+ virtual const SyncFlagCsrOffsets&
+ GetScalarCoreScalarInfeedSyncFlagCsrOffsets() const = 0;
+ virtual const SyncFlagCsrOffsets& GetScalarCoreProducerASyncFlagCsrOffsets()
+ const = 0;
+ virtual const SyncFlagCsrOffsets& GetScalarCoreProducerBSyncFlagCsrOffsets()
+ const = 0;
+ virtual const SyncFlagCsrOffsets& GetScalarCoreRingOutfeedSyncFlagCsrOffsets()
+ const = 0;
+ virtual const SyncFlagCsrOffsets&
+ GetScalarCoreScalarPipelineSyncFlagCsrOffsets() const = 0;
+
+ // Extracts CSR offsets used by bug report generator in DarwiNN.
+ virtual const DebugHibUserCsrOffsets& GetDebugHibUserCsrOffsets() const = 0;
+ virtual const DebugHibUserCsrOffsets&
+ GetContextSpecificDebugHibUserCsrOffsets(int context_id) const = 0;
+ virtual const DebugScalarCoreCsrOffsets& GetDebugScalarCoreCsrOffsets()
+ const = 0;
+ virtual const DebugTileCsrOffsets& GetDebugTileCsrOffsets() const = 0;
+
+ // Beagle-specific.
+ virtual const ApexCsrOffsets& GetApexCsrOffsets() const {
+ LOG(FATAL) << "Apex not supported.";
+ unreachable();
+ }
+ virtual const ScuCsrOffsets& GetScuCsrOffsets() const {
+ LOG(FATAL) << "SCU not supported.";
+ unreachable();
+ }
+ virtual const CbBridgeCsrOffsets& GetCbBridgeCsrOffsets() const {
+ LOG(FATAL) << "CB bridge not supported.";
+ unreachable();
+ }
+ virtual const UsbCsrOffsets& GetUsbCsrOffsets() const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetUsbFatalErrorInterruptCsrOffsets()
+ const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetUsbTopLevel0InterruptCsrOffsets()
+ const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetUsbTopLevel1InterruptCsrOffsets()
+ const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetUsbTopLevel2InterruptCsrOffsets()
+ const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+ virtual const InterruptCsrOffsets& GetUsbTopLevel3InterruptCsrOffsets()
+ const {
+ LOG(FATAL) << "USB not supported.";
+ unreachable();
+ }
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_CHIP_CONFIG_H_
diff --git a/driver/config/chip_structures.h b/driver/config/chip_structures.h
new file mode 100644
index 0000000..5f2a58b
--- /dev/null
+++ b/driver/config/chip_structures.h
@@ -0,0 +1,102 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_CHIP_STRUCTURES_H_
+#define DARWINN_DRIVER_CONFIG_CHIP_STRUCTURES_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+struct ChipStructures {
+ // Hardware required minimum alignment on buffers.
+ uint64 minimum_alignment_bytes;
+
+ // Buffer allocation alignment and granularity. Typically this would be same
+ // as minimum_alignment_bytes above, however may also factor in other
+ // requirements such as host cache line size, cache API constraints etc.
+ uint64 allocation_alignment_bytes;
+
+ // Controls AXI burst length.
+ uint64 axi_dma_burst_limiter;
+
+ // Number of wire interrupts.
+ uint64 num_wire_interrupts;
+
+ // Number of page table entries.
+ uint64 num_page_table_entries;
+
+ // Number of physical address bits generated by the hardware.
+ uint64 physical_address_bits;
+
+ // Addressable byte size of TPU DRAM (if any). This must be divisible by host
+ // table size.
+ uint64 tpu_dram_size_bytes;
+
+ // Total size of narrow memory per tile in bytes.
+ uint64 narrow_memory_capacity;
+
+ // Size of address translation entry for external narrow memory interface.
+ uint64 external_narrow_memory_translate_entry_size_bytes;
+
+ // Number of X tiles.
+ uint64 number_x_tiles;
+
+ // Number of Y tiles.
+ uint64 number_y_tiles;
+
+ // Number of compute threads.
+ uint64 number_compute_threads;
+
+ // Number of virtual networks.
+ uint64 number_of_ring_virtual_networks;
+
+ uint64 last_z_out_cell_disable_incompatible_with_sparsity;
+
+ uint64 nlu_buffer_backpressure_causes_assertion;
+
+ // Mesh queue depth.
+ uint64 mesh_rx_queue_depth;
+
+ // Default VN buffer size.
+ uint64 default_vn_buffer_memory_lines;
+
+ // Base offset for CSR
+ uint64 csr_region_base_offset;
+
+ // Size CSR Region
+ uint64 csr_region_size_bytes;
+
+ // Support trace architectural registers.
+ uint64 support_trace_arch_registers;
+
+ // Shared Memory's base-and-bound unit size in bytes. This value is needed
+ // when determining how to program shared memory base and size for parameter,
+ // instruction, activation, and scalar memory partitions.
+ uint64 base_and_bound_unit_size_bytes;
+
+ // Number of scalar core contexts supported. Default 1 is legacy behavior with
+ // no context switching.
+ uint64 number_of_scalar_core_contexts;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_CHIP_STRUCTURES_H_
diff --git a/driver/config/common_csr_helper.h b/driver/config/common_csr_helper.h
new file mode 100644
index 0000000..f070b33
--- /dev/null
+++ b/driver/config/common_csr_helper.h
@@ -0,0 +1,623 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_COMMON_CSR_HELPER_H_
+#define DARWINN_DRIVER_CONFIG_COMMON_CSR_HELPER_H_
+
+#include "driver/bitfield.h"
+#include "port/integral_types.h"
+#include "port/unreachable.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+namespace registers {
+
+// CSR helper to access fields for HibError* CSRs.
+class HibError {
+ public:
+ HibError() : HibError(0ULL) {}
+ explicit HibError(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_inbound_page_fault(uint64 value) {
+ reg_.inbound_page_fault_ = value;
+ }
+ uint64 inbound_page_fault() const { return reg_.inbound_page_fault_(); }
+ void set_extended_page_fault(uint64 value) {
+ reg_.extended_page_fault_ = value;
+ }
+ uint64 extended_page_fault() const { return reg_.extended_page_fault_(); }
+ void set_csr_parity_error(uint64 value) { reg_.csr_parity_error_ = value; }
+ uint64 csr_parity_error() const { return reg_.csr_parity_error_(); }
+ void set_axi_slave_b_error(uint64 value) { reg_.axi_slave_b_error_ = value; }
+ uint64 axi_slave_b_error() const { return reg_.axi_slave_b_error_(); }
+ void set_axi_slave_r_error(uint64 value) { reg_.axi_slave_r_error_ = value; }
+ uint64 axi_slave_r_error() const { return reg_.axi_slave_r_error_(); }
+ void set_instruction_queue_bad_configuration(uint64 value) {
+ reg_.instruction_queue_bad_configuration_ = value;
+ }
+ uint64 instruction_queue_bad_configuration() const {
+ return reg_.instruction_queue_bad_configuration_();
+ }
+ void set_input_actv_queue_bad_configuration(uint64 value) {
+ reg_.input_actv_queue_bad_configuration_ = value;
+ }
+ uint64 input_actv_queue_bad_configuration() const {
+ return reg_.input_actv_queue_bad_configuration_();
+ }
+ void set_param_queue_bad_configuration(uint64 value) {
+ reg_.param_queue_bad_configuration_ = value;
+ }
+ uint64 param_queue_bad_configuration() const {
+ return reg_.param_queue_bad_configuration_();
+ }
+ void set_output_actv_queue_bad_configuration(uint64 value) {
+ reg_.output_actv_queue_bad_configuration_ = value;
+ }
+ uint64 output_actv_queue_bad_configuration() const {
+ return reg_.output_actv_queue_bad_configuration_();
+ }
+ void set_instruction_queue_invalid(uint64 value) {
+ reg_.instruction_queue_invalid_ = value;
+ }
+ uint64 instruction_queue_invalid() const {
+ return reg_.instruction_queue_invalid_();
+ }
+ void set_input_actv_queue_invalid(uint64 value) {
+ reg_.input_actv_queue_invalid_ = value;
+ }
+ uint64 input_actv_queue_invalid() const {
+ return reg_.input_actv_queue_invalid_();
+ }
+ void set_param_queue_invalid(uint64 value) {
+ reg_.param_queue_invalid_ = value;
+ }
+ uint64 param_queue_invalid() const { return reg_.param_queue_invalid_(); }
+ void set_output_actv_queue_invalid(uint64 value) {
+ reg_.output_actv_queue_invalid_ = value;
+ }
+ uint64 output_actv_queue_invalid() const {
+ return reg_.output_actv_queue_invalid_();
+ }
+ void set_length_0_dma(uint64 value) { reg_.length_0_dma_ = value; }
+ uint64 length_0_dma() const { return reg_.length_0_dma_(); }
+ void set_virt_table_rdata_uncorr(uint64 value) {
+ reg_.virt_table_rdata_uncorr_ = value;
+ }
+ uint64 virt_table_rdata_uncorr() const {
+ return reg_.virt_table_rdata_uncorr_();
+ }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> inbound_page_fault_;
+ platforms::darwinn::driver::Bitfield<1, 1> extended_page_fault_;
+ platforms::darwinn::driver::Bitfield<2, 1> csr_parity_error_;
+ platforms::darwinn::driver::Bitfield<3, 1> axi_slave_b_error_;
+ platforms::darwinn::driver::Bitfield<4, 1> axi_slave_r_error_;
+ platforms::darwinn::driver::Bitfield<5, 1>
+ instruction_queue_bad_configuration_;
+ platforms::darwinn::driver::Bitfield<6, 1>
+ input_actv_queue_bad_configuration_;
+ platforms::darwinn::driver::Bitfield<7, 1> param_queue_bad_configuration_;
+ platforms::darwinn::driver::Bitfield<8, 1>
+ output_actv_queue_bad_configuration_;
+ platforms::darwinn::driver::Bitfield<9, 1> instruction_queue_invalid_;
+ platforms::darwinn::driver::Bitfield<10, 1> input_actv_queue_invalid_;
+ platforms::darwinn::driver::Bitfield<11, 1> param_queue_invalid_;
+ platforms::darwinn::driver::Bitfield<12, 1> output_actv_queue_invalid_;
+ platforms::darwinn::driver::Bitfield<13, 1> length_0_dma_;
+ platforms::darwinn::driver::Bitfield<14, 1> virt_table_rdata_uncorr_;
+ } reg_;
+};
+
+// CSR helper to access fields for *QueueControl CSR.
+class QueueControl {
+ public:
+ QueueControl() : QueueControl(0ULL) {}
+ explicit QueueControl(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_enable(uint64 value) { reg_.enable_ = value; }
+ uint64 enable() const { return reg_.enable_(); }
+ void set_sc_desc_select(uint64 value) { reg_.sc_desc_select_ = value; }
+ uint64 sc_desc_select() const { return reg_.sc_desc_select_(); }
+ void set_sb_wr_enable(uint64 value) { reg_.sb_wr_enable_ = value; }
+ uint64 sb_wr_enable() const { return reg_.sb_wr_enable_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> enable_;
+ platforms::darwinn::driver::Bitfield<1, 1> sc_desc_select_;
+ platforms::darwinn::driver::Bitfield<2, 1> sb_wr_enable_;
+ } reg_;
+};
+
+// CSR helper to access fields for ScHostIntCount CSR.
+class ScHostIntCount {
+ public:
+ ScHostIntCount() : ScHostIntCount(0ULL) {}
+ explicit ScHostIntCount(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_cnt0(uint64 value) { reg_.cnt0_ = value; }
+ uint64 cnt0() const { return reg_.cnt0_(); }
+ void set_cnt1(uint64 value) { reg_.cnt1_ = value; }
+ uint64 cnt1() const { return reg_.cnt1_(); }
+ void set_cnt2(uint64 value) { reg_.cnt2_ = value; }
+ uint64 cnt2() const { return reg_.cnt2_(); }
+ void set_cnt3(uint64 value) { reg_.cnt3_ = value; }
+ uint64 cnt3() const { return reg_.cnt3_(); }
+
+ // Sets |index|-th field from LSB to |value|.
+ void set_field(int index, uint64 value) {
+ switch (index) {
+ case 0:
+ reg_.cnt0_ = value;
+ break;
+
+ case 1:
+ reg_.cnt1_ = value;
+ break;
+
+ case 2:
+ reg_.cnt2_ = value;
+ break;
+
+ case 3:
+ reg_.cnt3_ = value;
+ break;
+
+ default:
+ CHECK(false) << "Unknown field index: " << index;
+ break;
+ }
+ }
+
+ // Returns |index|-th field from LSB.
+ uint64 get_field(int index) {
+ switch (index) {
+ case 0:
+ return reg_.cnt0_();
+
+ case 1:
+ return reg_.cnt1_();
+
+ case 2:
+ return reg_.cnt2_();
+
+ case 3:
+ return reg_.cnt3_();
+
+ default:
+ LOG(FATAL) << "Unknown field index: " << index;
+ unreachable();
+ }
+ }
+
+ // Returns masked |value| for |index|-th field from LSB.
+ uint64 mask_field(int index, uint64 value) {
+ switch (index) {
+ case 0:
+ return value & reg_.cnt0_.mask();
+
+ case 1:
+ return value & reg_.cnt1_.mask();
+
+ case 2:
+ return value & reg_.cnt2_.mask();
+
+ case 3:
+ return value & reg_.cnt3_.mask();
+
+ default:
+ LOG(FATAL) << "Unknown field index: " << index;
+ unreachable();
+ }
+ }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 16> cnt0_;
+ platforms::darwinn::driver::Bitfield<16, 16> cnt1_;
+ platforms::darwinn::driver::Bitfield<32, 16> cnt2_;
+ platforms::darwinn::driver::Bitfield<48, 16> cnt3_;
+ } reg_;
+};
+
+// CSR helper to access fields for ScHostIntStatus CSR.
+class ScHostIntStatus {
+ public:
+ ScHostIntStatus() : ScHostIntStatus(0ULL) {}
+ explicit ScHostIntStatus(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_hot0(uint64 value) { reg_.hot0_ = value; }
+ uint64 hot0() const { return reg_.hot0_(); }
+ void set_hot1(uint64 value) { reg_.hot1_ = value; }
+ uint64 hot1() const { return reg_.hot1_(); }
+ void set_hot2(uint64 value) { reg_.hot2_ = value; }
+ uint64 hot2() const { return reg_.hot2_(); }
+ void set_hot3(uint64 value) { reg_.hot3_ = value; }
+ uint64 hot3() const { return reg_.hot3_(); }
+
+ // Sets |index|-th field from LSB to |value|.
+ void set_field(int index, uint64 value) {
+ switch (index) {
+ case 0:
+ reg_.hot0_ = value;
+ break;
+
+ case 1:
+ reg_.hot1_ = value;
+ break;
+
+ case 2:
+ reg_.hot2_ = value;
+ break;
+
+ case 3:
+ reg_.hot3_ = value;
+ break;
+
+ default:
+ CHECK(false) << "Unknown field index: " << index;
+ break;
+ }
+ }
+
+ // Returns |index|-th field from LSB.
+ uint64 get_field(int index) {
+ switch (index) {
+ case 0:
+ return reg_.hot0_();
+
+ case 1:
+ return reg_.hot1_();
+
+ case 2:
+ return reg_.hot2_();
+
+ case 3:
+ return reg_.hot3_();
+
+ default:
+ LOG(FATAL) << "Unknown field index: " << index;
+ unreachable();
+ }
+ }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> hot0_;
+ platforms::darwinn::driver::Bitfield<1, 1> hot1_;
+ platforms::darwinn::driver::Bitfield<2, 1> hot2_;
+ platforms::darwinn::driver::Bitfield<3, 1> hot3_;
+ } reg_;
+};
+
+// CSR helper to access fields for ScHostIntVector CSR.
+class ScHostIntVector {
+ public:
+ ScHostIntVector() : ScHostIntVector(0ULL) {}
+ explicit ScHostIntVector(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_vector0(uint64 value) { reg_.vector0_ = value; }
+ uint64 vector0() const { return reg_.vector0_(); }
+ void set_vector1(uint64 value) { reg_.vector1_ = value; }
+ uint64 vector1() const { return reg_.vector1_(); }
+ void set_vector2(uint64 value) { reg_.vector2_ = value; }
+ uint64 vector2() const { return reg_.vector2_(); }
+ void set_vector3(uint64 value) { reg_.vector3_ = value; }
+ uint64 vector3() const { return reg_.vector3_(); }
+
+ // Sets |index|-th field from LSB to |value|.
+ void set_field(int index, uint64 value) {
+ switch (index) {
+ case 0:
+ reg_.vector0_ = value;
+ break;
+
+ case 1:
+ reg_.vector1_ = value;
+ break;
+
+ case 2:
+ reg_.vector2_ = value;
+ break;
+
+ case 3:
+ reg_.vector3_ = value;
+ break;
+
+ default:
+ CHECK(false) << "Unknown field index: " << index;
+ break;
+ }
+ }
+
+ // Returns |index|-th field from LSB.
+ uint64 get_field(int index) {
+ switch (index) {
+ case 0:
+ return reg_.vector0_();
+
+ case 1:
+ return reg_.vector1_();
+
+ case 2:
+ return reg_.vector2_();
+
+ case 3:
+ return reg_.vector3_();
+
+ default:
+ LOG(FATAL) << "Unknown field index: " << index;
+ unreachable();
+ }
+ }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 7> vector0_;
+ platforms::darwinn::driver::Bitfield<7, 7> vector1_;
+ platforms::darwinn::driver::Bitfield<14, 7> vector2_;
+ platforms::darwinn::driver::Bitfield<21, 7> vector3_;
+ } reg_;
+};
+
+// CSR helper to access fields for WireIntPendingBitArray and
+// WireIntMaskArray CSR.
+class WireIntBitArray {
+ public:
+ WireIntBitArray() : WireIntBitArray(0ULL) {}
+ explicit WireIntBitArray(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_instruction_queue(uint64 value) { reg_.instruction_queue_ = value; }
+ uint64 instruction_queue() const { return reg_.instruction_queue_(); }
+ void set_input_actv_queue(uint64 value) { reg_.input_actv_queue_ = value; }
+ uint64 input_actv_queue() const { return reg_.input_actv_queue_(); }
+ void set_param_queue(uint64 value) { reg_.param_queue_ = value; }
+ uint64 param_queue() const { return reg_.param_queue_(); }
+ void set_output_actv_queue(uint64 value) { reg_.output_actv_queue_ = value; }
+ uint64 output_actv_queue() const { return reg_.output_actv_queue_(); }
+ void set_sc_host_0(uint64 value) { reg_.sc_host_0_ = value; }
+ uint64 sc_host_0() const { return reg_.sc_host_0_(); }
+ void set_sc_host_1(uint64 value) { reg_.sc_host_1_ = value; }
+ uint64 sc_host_1() const { return reg_.sc_host_1_(); }
+ void set_sc_host_2(uint64 value) { reg_.sc_host_2_ = value; }
+ uint64 sc_host_2() const { return reg_.sc_host_2_(); }
+ void set_sc_host_3(uint64 value) { reg_.sc_host_3_ = value; }
+ uint64 sc_host_3() const { return reg_.sc_host_3_(); }
+ void set_top_level_0(uint64 value) { reg_.top_level_0_ = value; }
+ uint64 top_level_0() const { return reg_.top_level_0_(); }
+ void set_top_level_1(uint64 value) { reg_.top_level_1_ = value; }
+ uint64 top_level_1() const { return reg_.top_level_1_(); }
+ void set_top_level_2(uint64 value) { reg_.top_level_2_ = value; }
+ uint64 top_level_2() const { return reg_.top_level_2_(); }
+ void set_top_level_3(uint64 value) { reg_.top_level_3_ = value; }
+ uint64 top_level_3() const { return reg_.top_level_3_(); }
+ void set_fatal_err(uint64 value) { reg_.fatal_err_ = value; }
+ uint64 fatal_err() const { return reg_.fatal_err_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> instruction_queue_;
+ platforms::darwinn::driver::Bitfield<1, 1> input_actv_queue_;
+ platforms::darwinn::driver::Bitfield<2, 1> param_queue_;
+ platforms::darwinn::driver::Bitfield<3, 1> output_actv_queue_;
+ platforms::darwinn::driver::Bitfield<4, 1> sc_host_0_;
+ platforms::darwinn::driver::Bitfield<5, 1> sc_host_1_;
+ platforms::darwinn::driver::Bitfield<6, 1> sc_host_2_;
+ platforms::darwinn::driver::Bitfield<7, 1> sc_host_3_;
+ platforms::darwinn::driver::Bitfield<8, 1> top_level_0_;
+ platforms::darwinn::driver::Bitfield<9, 1> top_level_1_;
+ platforms::darwinn::driver::Bitfield<10, 1> top_level_2_;
+ platforms::darwinn::driver::Bitfield<11, 1> top_level_3_;
+ platforms::darwinn::driver::Bitfield<12, 1> fatal_err_;
+ } reg_;
+};
+
+// Interface to access fields for tile configs.
+class TileConfigInterface {
+ public:
+ virtual ~TileConfigInterface() = default;
+
+ // Access to aggregated value.
+ virtual void set_raw(uint64 value) = 0;
+ virtual uint64 raw() const = 0;
+
+ // Sets tile id.
+ virtual void set_broadcast() = 0;
+ virtual void set_tile(uint64 value) = 0;
+
+ // Returns tile field.
+ virtual uint64 tile() const = 0;
+};
+
+// Implements TileConfigInterface with given TILE_BITS.
+template
+class TileConfig : public TileConfigInterface {
+ public:
+ TileConfig() : TileConfig(0ULL) {}
+ explicit TileConfig(uint64 value) { reg_.raw_ = value; }
+ ~TileConfig() = default;
+
+ void set_raw(uint64 value) override { reg_.raw_ = value; }
+ uint64 raw() const override { return reg_.raw_; }
+
+ void set_broadcast() override {
+ reg_.tile_ = static_cast(-1) & reg_.tile_.mask();
+ }
+ void set_tile(uint64 value) { reg_.tile_ = value; }
+ uint64 tile() const override { return reg_.tile_(); }
+
+ private:
+ union {
+ // Entire CSR value.
+ uint64 raw_;
+ // Tile id field.
+ platforms::darwinn::driver::Bitfield<0, TILE_BITS> tile_;
+ } reg_;
+};
+
+// CSR helper to access fields for clockEnableReg CSR.
+class ClockEnableReg {
+ public:
+ ClockEnableReg() : ClockEnableReg(0ULL) {}
+ explicit ClockEnableReg(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+ void set_clock_enable(uint64 value) { reg_.clock_enable_ = value; }
+ uint64 clock_enable() const { return reg_.clock_enable_(); }
+ void set_idle_override(uint64 value) { reg_.idle_override_ = value; }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> clock_enable_;
+ platforms::darwinn::driver::Bitfield<1, 1> idle_override_;
+ } reg_;
+};
+
+// CSR helper to access fields for idleRegister CSR.
+class IdleRegister {
+ public:
+ // Defaults to reset value.
+ IdleRegister() : IdleRegister(0x00009000ULL) {}
+ explicit IdleRegister(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_enable() { reg_.disable_idle_ = 0; }
+ void set_disable() { reg_.disable_idle_ = 1; }
+ void set_counter(uint64 value) { reg_.counter_ = value; }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 31> counter_;
+ platforms::darwinn::driver::Bitfield<31, 1> disable_idle_;
+ } reg_;
+};
+
+// CSR helper to access fields for logicShutdownPreReg/logicShutdownAllReg.
+template
+class ShutdownReg {
+ public:
+ // Defaults to reset value.
+ ShutdownReg() : ShutdownReg(0x0) {
+ set_logic_shutdown((1ULL << NUM_BITS) - 1);
+ }
+ explicit ShutdownReg(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_logic_shutdown(uint64 value) { reg_.logic_shutdown_ = value; }
+ void set_logic_shutdown_ack(uint64 value) {
+ reg_.logic_shutdown_ack_ = value;
+ }
+ uint64 logic_shutdown() const { return reg_.logic_shutdown_(); }
+ uint64 logic_shutdown_ack() const { return reg_.logic_shutdown_ack_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, NUM_BITS> logic_shutdown_;
+ platforms::darwinn::driver::Bitfield
+ logic_shutdown_ack_;
+ } reg_;
+};
+
+// CSR helper to access fields for deepSleep.
+class DeepSleep {
+ public:
+ // Defaults to reset value.
+ DeepSleep() : DeepSleep(0x0) {}
+ explicit DeepSleep(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_to_sleep_delay(uint64 value) { reg_.to_sleep_delay_ = value; }
+ void set_to_wake_delay(uint64 value) { reg_.to_wake_delay_ = value; }
+ uint64 narrow_mem_deep_sleep() const { return reg_.narrow_mem_deep_sleep_(); }
+ uint64 wide_mem_deep_sleep() const { return reg_.wide_mem_deep_sleep_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ // These are named after fields in the spec.
+ platforms::darwinn::driver::Bitfield<0, 8> to_sleep_delay_;
+ platforms::darwinn::driver::Bitfield<8, 8> to_wake_delay_;
+ platforms::darwinn::driver::Bitfield<16, 1> narrow_mem_deep_sleep_;
+ platforms::darwinn::driver::Bitfield<17, 1> wide_mem_deep_sleep_;
+ } reg_;
+};
+
+// Implements field level access for SharedMemoryInitControl CSR.
+class SharedMemoryInitControl {
+ public:
+ SharedMemoryInitControl() : SharedMemoryInitControl(/*value=*/0ULL) {}
+ SharedMemoryInitControl(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_trigger(uint64 value) { reg_.trigger_ = value; }
+ uint64 trigger() const { return reg_.trigger_(); }
+
+ void set_run(uint64 value) { reg_.run_ = value; }
+ uint64 run() const { return reg_.run_(); }
+
+ void set_done(uint64 value) { reg_.done_ = value; }
+ uint64 done() const { return reg_.done_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 1> trigger_;
+ platforms::darwinn::driver::Bitfield<1, 1> run_;
+ platforms::darwinn::driver::Bitfield<2, 1> done_;
+ } reg_;
+};
+
+} // namespace registers
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_COMMON_CSR_HELPER_H_
diff --git a/driver/config/debug_hib_user_csr_offsets.h b/driver/config/debug_hib_user_csr_offsets.h
new file mode 100644
index 0000000..b5c62ed
--- /dev/null
+++ b/driver/config/debug_hib_user_csr_offsets.h
@@ -0,0 +1,276 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_DEBUG_HIB_USER_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_DEBUG_HIB_USER_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets that will be dumped as part of the
+// driver bug report for user hib. Members are intentionally named to match the
+// GCSR register names.
+struct DebugHibUserCsrOffsets {
+ uint64 instruction_inbound_queue_total_occupancy;
+ uint64 instruction_inbound_queue_threshold_counter;
+ uint64 instruction_inbound_queue_insertion_counter;
+ uint64 instruction_inbound_queue_full_counter;
+ uint64 input_actv_inbound_queue_total_occupancy;
+ uint64 input_actv_inbound_queue_threshold_counter;
+ uint64 input_actv_inbound_queue_insertion_counter;
+ uint64 input_actv_inbound_queue_full_counter;
+ uint64 param_inbound_queue_total_occupancy;
+ uint64 param_inbound_queue_threshold_counter;
+ uint64 param_inbound_queue_insertion_counter;
+ uint64 param_inbound_queue_full_counter;
+ uint64 output_actv_inbound_queue_total_occupancy;
+ uint64 output_actv_inbound_queue_threshold_counter;
+ uint64 output_actv_inbound_queue_insertion_counter;
+ uint64 output_actv_inbound_queue_full_counter;
+ uint64 status_block_write_inbound_queue_total_occupancy;
+ uint64 status_block_write_inbound_queue_threshold_counter;
+ uint64 status_block_write_inbound_queue_insertion_counter;
+ uint64 status_block_write_inbound_queue_full_counter;
+ uint64 queue_fetch_inbound_queue_total_occupancy;
+ uint64 queue_fetch_inbound_queue_threshold_counter;
+ uint64 queue_fetch_inbound_queue_insertion_counter;
+ uint64 queue_fetch_inbound_queue_full_counter;
+ uint64 instruction_outbound_queue_total_occupancy;
+ uint64 instruction_outbound_queue_threshold_counter;
+ uint64 instruction_outbound_queue_insertion_counter;
+ uint64 instruction_outbound_queue_full_counter;
+ uint64 input_actv_outbound_queue_total_occupancy;
+ uint64 input_actv_outbound_queue_threshold_counter;
+ uint64 input_actv_outbound_queue_insertion_counter;
+ uint64 input_actv_outbound_queue_full_counter;
+ uint64 param_outbound_queue_total_occupancy;
+ uint64 param_outbound_queue_threshold_counter;
+ uint64 param_outbound_queue_insertion_counter;
+ uint64 param_outbound_queue_full_counter;
+ uint64 output_actv_outbound_queue_total_occupancy;
+ uint64 output_actv_outbound_queue_threshold_counter;
+ uint64 output_actv_outbound_queue_insertion_counter;
+ uint64 output_actv_outbound_queue_full_counter;
+ uint64 status_block_write_outbound_queue_total_occupancy;
+ uint64 status_block_write_outbound_queue_threshold_counter;
+ uint64 status_block_write_outbound_queue_insertion_counter;
+ uint64 status_block_write_outbound_queue_full_counter;
+ uint64 queue_fetch_outbound_queue_total_occupancy;
+ uint64 queue_fetch_outbound_queue_threshold_counter;
+ uint64 queue_fetch_outbound_queue_insertion_counter;
+ uint64 queue_fetch_outbound_queue_full_counter;
+ uint64 page_table_request_outbound_queue_total_occupancy;
+ uint64 page_table_request_outbound_queue_threshold_counter;
+ uint64 page_table_request_outbound_queue_insertion_counter;
+ uint64 page_table_request_outbound_queue_full_counter;
+ uint64 read_tracking_fifo_total_occupancy;
+ uint64 read_tracking_fifo_threshold_counter;
+ uint64 read_tracking_fifo_insertion_counter;
+ uint64 read_tracking_fifo_full_counter;
+ uint64 write_tracking_fifo_total_occupancy;
+ uint64 write_tracking_fifo_threshold_counter;
+ uint64 write_tracking_fifo_insertion_counter;
+ uint64 write_tracking_fifo_full_counter;
+ uint64 read_buffer_total_occupancy;
+ uint64 read_buffer_threshold_counter;
+ uint64 read_buffer_insertion_counter;
+ uint64 read_buffer_full_counter;
+ uint64 axi_aw_credit_shim_total_occupancy;
+ uint64 axi_aw_credit_shim_threshold_counter;
+ uint64 axi_aw_credit_shim_insertion_counter;
+ uint64 axi_aw_credit_shim_full_counter;
+ uint64 axi_ar_credit_shim_total_occupancy;
+ uint64 axi_ar_credit_shim_threshold_counter;
+ uint64 axi_ar_credit_shim_insertion_counter;
+ uint64 axi_ar_credit_shim_full_counter;
+ uint64 axi_w_credit_shim_total_occupancy;
+ uint64 axi_w_credit_shim_threshold_counter;
+ uint64 axi_w_credit_shim_insertion_counter;
+ uint64 axi_w_credit_shim_full_counter;
+ uint64 instruction_inbound_queue_empty_cycles_count;
+ uint64 input_actv_inbound_queue_empty_cycles_count;
+ uint64 param_inbound_queue_empty_cycles_count;
+ uint64 output_actv_inbound_queue_empty_cycles_count;
+ uint64 status_block_write_inbound_queue_empty_cycles_count;
+ uint64 queue_fetch_inbound_queue_empty_cycles_count;
+ uint64 instruction_outbound_queue_empty_cycles_count;
+ uint64 input_actv_outbound_queue_empty_cycles_count;
+ uint64 param_outbound_queue_empty_cycles_count;
+ uint64 output_actv_outbound_queue_empty_cycles_count;
+ uint64 status_block_write_outbound_queue_empty_cycles_count;
+ uint64 queue_fetch_outbound_queue_empty_cycles_count;
+ uint64 page_table_request_outbound_queue_empty_cycles_count;
+ uint64 read_tracking_fifo_empty_cycles_count;
+ uint64 write_tracking_fifo_empty_cycles_count;
+ uint64 read_buffer_empty_cycles_count;
+ uint64 read_request_arbiter_instruction_request_cycles;
+ uint64 read_request_arbiter_instruction_blocked_cycles;
+ uint64 read_request_arbiter_instruction_blocked_by_arbitration_cycles;
+ uint64 read_request_arbiter_instruction_cycles_blocked_over_threshold;
+ uint64 read_request_arbiter_input_actv_request_cycles;
+ uint64 read_request_arbiter_input_actv_blocked_cycles;
+ uint64 read_request_arbiter_input_actv_blocked_by_arbitration_cycles;
+ uint64 read_request_arbiter_input_actv_cycles_blocked_over_threshold;
+ uint64 read_request_arbiter_param_request_cycles;
+ uint64 read_request_arbiter_param_blocked_cycles;
+ uint64 read_request_arbiter_param_blocked_by_arbitration_cycles;
+ uint64 read_request_arbiter_param_cycles_blocked_over_threshold;
+ uint64 read_request_arbiter_queue_fetch_request_cycles;
+ uint64 read_request_arbiter_queue_fetch_blocked_cycles;
+ uint64 read_request_arbiter_queue_fetch_blocked_by_arbitration_cycles;
+ uint64 read_request_arbiter_queue_fetch_cycles_blocked_over_threshold;
+ uint64 read_request_arbiter_page_table_request_request_cycles;
+ uint64 read_request_arbiter_page_table_request_blocked_cycles;
+ uint64 read_request_arbiter_page_table_request_blocked_by_arbitration_cycles;
+ uint64 read_request_arbiter_page_table_request_cycles_blocked_over_threshold;
+ uint64 write_request_arbiter_output_actv_request_cycles;
+ uint64 write_request_arbiter_output_actv_blocked_cycles;
+ uint64 write_request_arbiter_output_actv_blocked_by_arbitration_cycles;
+ uint64 write_request_arbiter_output_actv_cycles_blocked_over_threshold;
+ uint64 write_request_arbiter_status_block_write_request_cycles;
+ uint64 write_request_arbiter_status_block_write_blocked_cycles;
+ uint64 write_request_arbiter_status_block_write_blocked_by_arbitration_cycles;
+ uint64 write_request_arbiter_status_block_write_cycles_blocked_over_threshold;
+ uint64 address_translation_arbiter_instruction_request_cycles;
+ uint64 address_translation_arbiter_instruction_blocked_cycles;
+ uint64 address_translation_arbiter_instruction_blocked_by_arbitration_cycles;
+ uint64 address_translation_arbiter_instruction_cycles_blocked_over_threshold;
+ uint64 address_translation_arbiter_input_actv_request_cycles;
+ uint64 address_translation_arbiter_input_actv_blocked_cycles;
+ uint64 address_translation_arbiter_input_actv_blocked_by_arbitration_cycles;
+ uint64 address_translation_arbiter_input_actv_cycles_blocked_over_threshold;
+ uint64 address_translation_arbiter_param_request_cycles;
+ uint64 address_translation_arbiter_param_blocked_cycles;
+ uint64 address_translation_arbiter_param_blocked_by_arbitration_cycles;
+ uint64 address_translation_arbiter_param_cycles_blocked_over_threshold;
+ uint64 address_translation_arbiter_status_block_write_request_cycles;
+ uint64 address_translation_arbiter_status_block_write_blocked_cycles;
+ uint64
+ address_translation_arbiter_status_block_write_blocked_by_arbitration_cycles; // NOLINT
+ uint64
+ address_translation_arbiter_status_block_write_cycles_blocked_over_threshold; // NOLINT
+ uint64 address_translation_arbiter_output_actv_request_cycles;
+ uint64 address_translation_arbiter_output_actv_blocked_cycles;
+ uint64 address_translation_arbiter_output_actv_blocked_by_arbitration_cycles;
+ uint64 address_translation_arbiter_output_actv_cycles_blocked_over_threshold;
+ uint64 address_translation_arbiter_queue_fetch_request_cycles;
+ uint64 address_translation_arbiter_queue_fetch_blocked_cycles;
+ uint64 address_translation_arbiter_queue_fetch_blocked_by_arbitration_cycles;
+ uint64 address_translation_arbiter_queue_fetch_cycles_blocked_over_threshold;
+ uint64 issued_interrupt_count;
+ uint64 data_read_16byte_count;
+ uint64 waiting_for_tag_cycles;
+ uint64 waiting_for_axi_cycles;
+ uint64 simple_translations;
+ uint64 instruction_credits_per_cycle_sum;
+ uint64 input_actv_credits_per_cycle_sum;
+ uint64 param_credits_per_cycle_sum;
+ uint64 output_actv_credits_per_cycle_sum;
+ uint64 status_block_write_credits_per_cycle_sum;
+ uint64 queue_fetch_credits_per_cycle_sum;
+ uint64 page_table_request_credits_per_cycle_sum;
+ uint64 output_actv_queue_control;
+ uint64 output_actv_queue_status;
+ uint64 output_actv_queue_descriptor_size;
+ uint64 output_actv_queue_minimum_size;
+ uint64 output_actv_queue_maximum_size;
+ uint64 output_actv_queue_base;
+ uint64 output_actv_queue_status_block_base;
+ uint64 output_actv_queue_size;
+ uint64 output_actv_queue_tail;
+ uint64 output_actv_queue_fetched_head;
+ uint64 output_actv_queue_completed_head;
+ uint64 output_actv_queue_int_control;
+ uint64 output_actv_queue_int_status;
+ uint64 instruction_queue_control;
+ uint64 instruction_queue_status;
+ uint64 instruction_queue_descriptor_size;
+ uint64 instruction_queue_minimum_size;
+ uint64 instruction_queue_maximum_size;
+ uint64 instruction_queue_base;
+ uint64 instruction_queue_status_block_base;
+ uint64 instruction_queue_size;
+ uint64 instruction_queue_tail;
+ uint64 instruction_queue_fetched_head;
+ uint64 instruction_queue_completed_head;
+ uint64 instruction_queue_int_control;
+ uint64 instruction_queue_int_status;
+ uint64 input_actv_queue_control;
+ uint64 input_actv_queue_status;
+ uint64 input_actv_queue_descriptor_size;
+ uint64 input_actv_queue_minimum_size;
+ uint64 input_actv_queue_maximum_size;
+ uint64 input_actv_queue_base;
+ uint64 input_actv_queue_status_block_base;
+ uint64 input_actv_queue_size;
+ uint64 input_actv_queue_tail;
+ uint64 input_actv_queue_fetched_head;
+ uint64 input_actv_queue_completed_head;
+ uint64 input_actv_queue_int_control;
+ uint64 input_actv_queue_int_status;
+ uint64 param_queue_control;
+ uint64 param_queue_status;
+ uint64 param_queue_descriptor_size;
+ uint64 param_queue_minimum_size;
+ uint64 param_queue_maximum_size;
+ uint64 param_queue_base;
+ uint64 param_queue_status_block_base;
+ uint64 param_queue_size;
+ uint64 param_queue_tail;
+ uint64 param_queue_fetched_head;
+ uint64 param_queue_completed_head;
+ uint64 param_queue_int_control;
+ uint64 param_queue_int_status;
+ uint64 sc_host_int_control;
+ uint64 sc_host_int_status;
+ uint64 top_level_int_control;
+ uint64 top_level_int_status;
+ uint64 fatal_err_int_control;
+ uint64 fatal_err_int_status;
+ uint64 sc_host_int_count;
+ uint64 dma_pause;
+ uint64 dma_paused;
+ uint64 status_block_update;
+ uint64 hib_error_status;
+ uint64 hib_error_mask;
+ uint64 hib_first_error_status;
+ uint64 hib_first_error_timestamp;
+ uint64 hib_inject_error;
+ uint64 read_request_arbiter;
+ uint64 write_request_arbiter;
+ uint64 address_translation_arbiter;
+ uint64 sender_queue_threshold;
+ uint64 page_fault_address;
+ uint64 instruction_credits;
+ uint64 input_actv_credits;
+ uint64 param_credits;
+ uint64 output_actv_credits;
+ uint64 pause_state;
+ uint64 snapshot;
+ uint64 idle_assert;
+ uint64 wire_int_pending_bit_array;
+ uint64 tileconfig0;
+ uint64 tileconfig1;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_DEBUG_HIB_USER_CSR_OFFSETS_H_
diff --git a/driver/config/debug_scalar_core_csr_offsets.h b/driver/config/debug_scalar_core_csr_offsets.h
new file mode 100644
index 0000000..f8ebf20
--- /dev/null
+++ b/driver/config/debug_scalar_core_csr_offsets.h
@@ -0,0 +1,437 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_DEBUG_SCALAR_CORE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_DEBUG_SCALAR_CORE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets that will be dumped as part of the
+// driver bug report for scalar core. Members are intentionally named to match
+// the GCSR register names.
+struct DebugScalarCoreCsrOffsets {
+ uint64 topology;
+ uint64 scMemoryCapacity;
+ uint64 tileMemoryCapacity;
+ uint64 scMemoryAccess;
+ uint64 scMemoryData;
+ uint64 Timeout;
+ uint64 Error_ScalarCore;
+ uint64 Error_Mask_ScalarCore;
+ uint64 Error_Force_ScalarCore;
+ uint64 Error_Timestamp_ScalarCore;
+ uint64 Error_Info_ScalarCore;
+
+ // Contextual CSRs in Scalar Datapaths
+ uint64 scalarCoreRunControl;
+ uint64 scalarCoreBreakPoint;
+ uint64 currentPc;
+ uint64 executeControl;
+ // Context 0
+ uint64 scalarDatapath_0RunControl;
+ uint64 scalarDatapath_0BreakPoint;
+ uint64 currentPc_0;
+ uint64 executeControl_0;
+ // Context 1
+ uint64 scalarDatapath_1RunControl;
+ uint64 scalarDatapath_1BreakPoint;
+ uint64 currentPc_1;
+ uint64 executeControl_1;
+ // Context 2
+ uint64 scalarDatapath_2RunControl;
+ uint64 scalarDatapath_2BreakPoint;
+ uint64 currentPc_2;
+ uint64 executeControl_2;
+ // Context 3
+ uint64 scalarDatapath_3RunControl;
+ uint64 scalarDatapath_3BreakPoint;
+ uint64 currentPc_3;
+ uint64 executeControl_3;
+ // Sync Flag CSRs
+ uint64 SyncCounter_AVDATA_POP;
+ uint64 SyncCounter_PARAMETER_POP;
+ uint64 SyncCounter_AVDATA_INFEED;
+ uint64 SyncCounter_PARAMETER_INFEED;
+ uint64 SyncCounter_SCALAR_INFEED;
+ uint64 SyncCounter_PRODUCER_A;
+ uint64 SyncCounter_PRODUCER_B;
+ uint64 SyncCounter_RING_OUTFEED;
+ // Context 0
+ uint64 SyncCounter_AVDATA_POP_0_0;
+ uint64 SyncCounter_PARAMETER_POP_0_0;
+ uint64 SyncCounter_AVDATA_INFEED_0_0;
+ uint64 SyncCounter_PARAMETER_INFEED_0_0;
+ uint64 SyncCounter_SCALAR_INFEED_0_0;
+ uint64 SyncCounter_PRODUCER_A_0_0;
+ uint64 SyncCounter_PRODUCER_B_0_0;
+ uint64 SyncCounter_RING_OUTFEED_0_0;
+ // Context 1
+ uint64 SyncCounter_AVDATA_POP_1_0;
+ uint64 SyncCounter_PARAMETER_POP_1_0;
+ uint64 SyncCounter_AVDATA_INFEED_1_0;
+ uint64 SyncCounter_PARAMETER_INFEED_1_0;
+ uint64 SyncCounter_SCALAR_INFEED_1_0;
+ uint64 SyncCounter_PRODUCER_A_1_0;
+ uint64 SyncCounter_PRODUCER_B_1_0;
+ uint64 SyncCounter_RING_OUTFEED_1_0;
+ // Context 2
+ uint64 SyncCounter_AVDATA_POP_2_0;
+ uint64 SyncCounter_PARAMETER_POP_2_0;
+ uint64 SyncCounter_AVDATA_INFEED_2_0;
+ uint64 SyncCounter_PARAMETER_INFEED_2_0;
+ uint64 SyncCounter_SCALAR_INFEED_2_0;
+ uint64 SyncCounter_PRODUCER_A_2_0;
+ uint64 SyncCounter_PRODUCER_B_2_0;
+ uint64 SyncCounter_RING_OUTFEED_2_0;
+ // Context 3
+ uint64 SyncCounter_AVDATA_POP_3_0;
+ uint64 SyncCounter_PARAMETER_POP_3_0;
+ uint64 SyncCounter_AVDATA_INFEED_3_0;
+ uint64 SyncCounter_PARAMETER_INFEED_3_0;
+ uint64 SyncCounter_SCALAR_INFEED_3_0;
+ uint64 SyncCounter_PRODUCER_A_3_0;
+ uint64 SyncCounter_PRODUCER_B_3_0;
+ uint64 SyncCounter_RING_OUTFEED_3_0;
+
+ // Pop Input Control Units
+ uint64 avDataPopRunControl;
+ uint64 avDataPopBreakPoint;
+ uint64 avDataPopRunStatus;
+ uint64 avDataPopOverwriteMode;
+ uint64 avDataPopEnableTracing;
+ uint64 avDataPopStartCycle;
+ uint64 avDataPopEndCycle;
+ uint64 avDataPopStallCycleCount;
+ uint64 avDataPopProgramCounter;
+ uint64 avDataPopTtuStateRegFile;
+ uint64 avDataPopTrace;
+ // Context 0
+ uint64 avDataPop_0RunControl;
+ uint64 avDataPop_0BreakPoint;
+ uint64 avDataPop_0RunStatus;
+ uint64 avDataPop_0OverwriteMode;
+ uint64 avDataPop_0EnableTracing;
+ uint64 avDataPop_0StartCycle;
+ uint64 avDataPop_0EndCycle;
+ uint64 avDataPop_0StallCycleCount;
+ uint64 avDataPop_0ProgramCounter;
+ uint64 avDataPop_0TtuStateRegFile;
+ uint64 avDataPop_0Trace;
+ // Context 1
+ uint64 avDataPop_1RunControl;
+ uint64 avDataPop_1BreakPoint;
+ uint64 avDataPop_1RunStatus;
+ uint64 avDataPop_1OverwriteMode;
+ uint64 avDataPop_1EnableTracing;
+ uint64 avDataPop_1StartCycle;
+ uint64 avDataPop_1EndCycle;
+ uint64 avDataPop_1StallCycleCount;
+ uint64 avDataPop_1ProgramCounter;
+ uint64 avDataPop_1TtuStateRegFile;
+ uint64 avDataPop_1Trace;
+ // Context 2
+ uint64 avDataPop_2RunControl;
+ uint64 avDataPop_2BreakPoint;
+ uint64 avDataPop_2RunStatus;
+ uint64 avDataPop_2OverwriteMode;
+ uint64 avDataPop_2EnableTracing;
+ uint64 avDataPop_2StartCycle;
+ uint64 avDataPop_2EndCycle;
+ uint64 avDataPop_2StallCycleCount;
+ uint64 avDataPop_2ProgramCounter;
+ uint64 avDataPop_2TtuStateRegFile;
+ uint64 avDataPop_2Trace;
+ // Context 3
+ uint64 avDataPop_3RunControl;
+ uint64 avDataPop_3BreakPoint;
+ uint64 avDataPop_3RunStatus;
+ uint64 avDataPop_3OverwriteMode;
+ uint64 avDataPop_3EnableTracing;
+ uint64 avDataPop_3StartCycle;
+ uint64 avDataPop_3EndCycle;
+ uint64 avDataPop_3StallCycleCount;
+ uint64 avDataPop_3ProgramCounter;
+ uint64 avDataPop_3TtuStateRegFile;
+ uint64 avDataPop_3Trace;
+
+ uint64 parameterPopRunControl;
+ uint64 parameterPopBreakPoint;
+ uint64 parameterPopRunStatus;
+ uint64 parameterPopOverwriteMode;
+ uint64 parameterPopEnableTracing;
+ uint64 parameterPopStartCycle;
+ uint64 parameterPopEndCycle;
+ uint64 parameterPopStallCycleCount;
+ uint64 parameterPopProgramCounter;
+ uint64 parameterPopTtuStateRegFile;
+ uint64 parameterPopTrace;
+ // Context 0
+ uint64 parameterPop_0RunControl;
+ uint64 parameterPop_0BreakPoint;
+ uint64 parameterPop_0RunStatus;
+ uint64 parameterPop_0OverwriteMode;
+ uint64 parameterPop_0EnableTracing;
+ uint64 parameterPop_0StartCycle;
+ uint64 parameterPop_0EndCycle;
+ uint64 parameterPop_0StallCycleCount;
+ uint64 parameterPop_0ProgramCounter;
+ uint64 parameterPop_0TtuStateRegFile;
+ uint64 parameterPop_0Trace;
+ // Context 1
+ uint64 parameterPop_1RunControl;
+ uint64 parameterPop_1BreakPoint;
+ uint64 parameterPop_1RunStatus;
+ uint64 parameterPop_1OverwriteMode;
+ uint64 parameterPop_1EnableTracing;
+ uint64 parameterPop_1StartCycle;
+ uint64 parameterPop_1EndCycle;
+ uint64 parameterPop_1StallCycleCount;
+ uint64 parameterPop_1ProgramCounter;
+ uint64 parameterPop_1TtuStateRegFile;
+ uint64 parameterPop_1Trace;
+ // Context 2
+ uint64 parameterPop_2RunControl;
+ uint64 parameterPop_2BreakPoint;
+ uint64 parameterPop_2RunStatus;
+ uint64 parameterPop_2OverwriteMode;
+ uint64 parameterPop_2EnableTracing;
+ uint64 parameterPop_2StartCycle;
+ uint64 parameterPop_2EndCycle;
+ uint64 parameterPop_2StallCycleCount;
+ uint64 parameterPop_2ProgramCounter;
+ uint64 parameterPop_2TtuStateRegFile;
+ uint64 parameterPop_2Trace;
+ // Context 3
+ uint64 parameterPop_3RunControl;
+ uint64 parameterPop_3BreakPoint;
+ uint64 parameterPop_3RunStatus;
+ uint64 parameterPop_3OverwriteMode;
+ uint64 parameterPop_3EnableTracing;
+ uint64 parameterPop_3StartCycle;
+ uint64 parameterPop_3EndCycle;
+ uint64 parameterPop_3StallCycleCount;
+ uint64 parameterPop_3ProgramCounter;
+ uint64 parameterPop_3TtuStateRegFile;
+ uint64 parameterPop_3Trace;
+ // Infeed Control Units
+ uint64 infeedRunControl;
+ uint64 infeedRunStatus;
+ uint64 infeedBreakPoint;
+ uint64 infeedOverwriteMode;
+ uint64 infeedEnableTracing;
+ uint64 infeedStartCycle;
+ uint64 infeedEndCycle;
+ uint64 infeedStallCycleCount;
+ uint64 infeedProgramCounter;
+ uint64 infeedTtuStateRegFile;
+ // Context 0
+ uint64 infeed_0_0RunControl;
+ uint64 infeed_0_0RunStatus;
+ uint64 infeed_0_0BreakPoint;
+ uint64 infeed_0_0OverwriteMode;
+ uint64 infeed_0_0EnableTracing;
+ uint64 infeed_0_0StartCycle;
+ uint64 infeed_0_0EndCycle;
+ uint64 infeed_0_0StallCycleCount;
+ uint64 infeed_0_0ProgramCounter;
+ uint64 infeed_0_0TtuStateRegFile;
+ uint64 infeed_0_1RunControl;
+ uint64 infeed_0_1RunStatus;
+ uint64 infeed_0_1BreakPoint;
+ uint64 infeed_0_1OverwriteMode;
+ uint64 infeed_0_1EnableTracing;
+ uint64 infeed_0_1StartCycle;
+ uint64 infeed_0_1EndCycle;
+ uint64 infeed_0_1StallCycleCount;
+ uint64 infeed_0_1ProgramCounter;
+ uint64 infeed_0_1TtuStateRegFile;
+ // Context 1
+ uint64 infeed_1_0RunControl;
+ uint64 infeed_1_0RunStatus;
+ uint64 infeed_1_0BreakPoint;
+ uint64 infeed_1_0OverwriteMode;
+ uint64 infeed_1_0EnableTracing;
+ uint64 infeed_1_0StartCycle;
+ uint64 infeed_1_0EndCycle;
+ uint64 infeed_1_0StallCycleCount;
+ uint64 infeed_1_0ProgramCounter;
+ uint64 infeed_1_0TtuStateRegFile;
+ uint64 infeed_1_1RunControl;
+ uint64 infeed_1_1RunStatus;
+ uint64 infeed_1_1BreakPoint;
+ uint64 infeed_1_1OverwriteMode;
+ uint64 infeed_1_1EnableTracing;
+ uint64 infeed_1_1StartCycle;
+ uint64 infeed_1_1EndCycle;
+ uint64 infeed_1_1StallCycleCount;
+ uint64 infeed_1_1ProgramCounter;
+ uint64 infeed_1_1TtuStateRegFile;
+ // Context 2
+ uint64 infeed_2_0RunControl;
+ uint64 infeed_2_0RunStatus;
+ uint64 infeed_2_0BreakPoint;
+ uint64 infeed_2_0OverwriteMode;
+ uint64 infeed_2_0EnableTracing;
+ uint64 infeed_2_0StartCycle;
+ uint64 infeed_2_0EndCycle;
+ uint64 infeed_2_0StallCycleCount;
+ uint64 infeed_2_0ProgramCounter;
+ uint64 infeed_2_0TtuStateRegFile;
+ uint64 infeed_2_1RunControl;
+ uint64 infeed_2_1RunStatus;
+ uint64 infeed_2_1BreakPoint;
+ uint64 infeed_2_1OverwriteMode;
+ uint64 infeed_2_1EnableTracing;
+ uint64 infeed_2_1StartCycle;
+ uint64 infeed_2_1EndCycle;
+ uint64 infeed_2_1StallCycleCount;
+ uint64 infeed_2_1ProgramCounter;
+ uint64 infeed_2_1TtuStateRegFile;
+ // Context 3
+ uint64 infeed_3_0RunControl;
+ uint64 infeed_3_0RunStatus;
+ uint64 infeed_3_0BreakPoint;
+ uint64 infeed_3_0OverwriteMode;
+ uint64 infeed_3_0EnableTracing;
+ uint64 infeed_3_0StartCycle;
+ uint64 infeed_3_0EndCycle;
+ uint64 infeed_3_0StallCycleCount;
+ uint64 infeed_3_0ProgramCounter;
+ uint64 infeed_3_0TtuStateRegFile;
+ uint64 infeed_3_1RunControl;
+ uint64 infeed_3_1RunStatus;
+ uint64 infeed_3_1BreakPoint;
+ uint64 infeed_3_1OverwriteMode;
+ uint64 infeed_3_1EnableTracing;
+ uint64 infeed_3_1StartCycle;
+ uint64 infeed_3_1EndCycle;
+ uint64 infeed_3_1StallCycleCount;
+ uint64 infeed_3_1ProgramCounter;
+ uint64 infeed_3_1TtuStateRegFile;
+
+ // Outfeed Control Units
+ uint64 outfeedRunControl;
+ uint64 outfeedRunStatus;
+ uint64 outfeedBreakPoint;
+ uint64 outfeedOverwriteMode;
+ uint64 outfeedEnableTracing;
+ uint64 outfeedStartCycle;
+ uint64 outfeedEndCycle;
+ uint64 outfeedStallCycleCount;
+ uint64 outfeedProgramCounter;
+ uint64 outfeedTtuStateRegFile;
+ // Context 0
+ uint64 outfeed_0_0RunControl;
+ uint64 outfeed_0_0RunStatus;
+ uint64 outfeed_0_0BreakPoint;
+ uint64 outfeed_0_0OverwriteMode;
+ uint64 outfeed_0_0EnableTracing;
+ uint64 outfeed_0_0StartCycle;
+ uint64 outfeed_0_0EndCycle;
+ uint64 outfeed_0_0StallCycleCount;
+ uint64 outfeed_0_0ProgramCounter;
+ uint64 outfeed_0_0TtuStateRegFile;
+ uint64 outfeed_0_1RunControl;
+ uint64 outfeed_0_1RunStatus;
+ uint64 outfeed_0_1BreakPoint;
+ uint64 outfeed_0_1OverwriteMode;
+ uint64 outfeed_0_1EnableTracing;
+ uint64 outfeed_0_1StartCycle;
+ uint64 outfeed_0_1EndCycle;
+ uint64 outfeed_0_1StallCycleCount;
+ uint64 outfeed_0_1ProgramCounter;
+ uint64 outfeed_0_1TtuStateRegFile;
+ // Context 1
+ uint64 outfeed_1_0RunControl;
+ uint64 outfeed_1_0RunStatus;
+ uint64 outfeed_1_0BreakPoint;
+ uint64 outfeed_1_0OverwriteMode;
+ uint64 outfeed_1_0EnableTracing;
+ uint64 outfeed_1_0StartCycle;
+ uint64 outfeed_1_0EndCycle;
+ uint64 outfeed_1_0StallCycleCount;
+ uint64 outfeed_1_0ProgramCounter;
+ uint64 outfeed_1_0TtuStateRegFile;
+ uint64 outfeed_1_1RunControl;
+ uint64 outfeed_1_1RunStatus;
+ uint64 outfeed_1_1BreakPoint;
+ uint64 outfeed_1_1OverwriteMode;
+ uint64 outfeed_1_1EnableTracing;
+ uint64 outfeed_1_1StartCycle;
+ uint64 outfeed_1_1EndCycle;
+ uint64 outfeed_1_1StallCycleCount;
+ uint64 outfeed_1_1ProgramCounter;
+ uint64 outfeed_1_1TtuStateRegFile;
+ // Context 2
+ uint64 outfeed_2_0RunControl;
+ uint64 outfeed_2_0RunStatus;
+ uint64 outfeed_2_0BreakPoint;
+ uint64 outfeed_2_0OverwriteMode;
+ uint64 outfeed_2_0EnableTracing;
+ uint64 outfeed_2_0StartCycle;
+ uint64 outfeed_2_0EndCycle;
+ uint64 outfeed_2_0StallCycleCount;
+ uint64 outfeed_2_0ProgramCounter;
+ uint64 outfeed_2_0TtuStateRegFile;
+ uint64 outfeed_2_1RunControl;
+ uint64 outfeed_2_1RunStatus;
+ uint64 outfeed_2_1BreakPoint;
+ uint64 outfeed_2_1OverwriteMode;
+ uint64 outfeed_2_1EnableTracing;
+ uint64 outfeed_2_1StartCycle;
+ uint64 outfeed_2_1EndCycle;
+ uint64 outfeed_2_1StallCycleCount;
+ uint64 outfeed_2_1ProgramCounter;
+ uint64 outfeed_2_1TtuStateRegFile;
+ // Context 3
+ uint64 outfeed_3_0RunControl;
+ uint64 outfeed_3_0RunStatus;
+ uint64 outfeed_3_0BreakPoint;
+ uint64 outfeed_3_0OverwriteMode;
+ uint64 outfeed_3_0EnableTracing;
+ uint64 outfeed_3_0StartCycle;
+ uint64 outfeed_3_0EndCycle;
+ uint64 outfeed_3_0StallCycleCount;
+ uint64 outfeed_3_0ProgramCounter;
+ uint64 outfeed_3_0TtuStateRegFile;
+ uint64 outfeed_3_1RunControl;
+ uint64 outfeed_3_1RunStatus;
+ uint64 outfeed_3_1BreakPoint;
+ uint64 outfeed_3_1OverwriteMode;
+ uint64 outfeed_3_1EnableTracing;
+ uint64 outfeed_3_1StartCycle;
+ uint64 outfeed_3_1EndCycle;
+ uint64 outfeed_3_1StallCycleCount;
+ uint64 outfeed_3_1ProgramCounter;
+ uint64 outfeed_3_1TtuStateRegFile;
+
+ // Scalar Pipeline
+ uint64 scalarCoreRunStatus;
+ uint64 scalarCoreRunStatus_0;
+ uint64 scalarCoreRunStatus_1;
+ uint64 scalarCoreRunStatus_2;
+ uint64 scalarCoreRunStatus_3;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_DEBUG_SCALAR_CORE_CSR_OFFSETS_H_
diff --git a/driver/config/debug_tile_csr_offsets.h b/driver/config/debug_tile_csr_offsets.h
new file mode 100644
index 0000000..ad95c68
--- /dev/null
+++ b/driver/config/debug_tile_csr_offsets.h
@@ -0,0 +1,185 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_DEBUG_TILE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_DEBUG_TILE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets that will be dumped as part of the
+// driver bug report for tiles. Members are intentionally named to match
+// the GCSR register names.
+struct DebugTileCsrOffsets {
+ uint64 TileClockControl;
+ uint64 tileid;
+ uint64 scratchpad;
+ uint64 memoryAccess;
+ uint64 memoryData;
+ uint64 narrowMemoryContext_0;
+ uint64 narrowMemoryContext_1;
+ uint64 narrowMemoryContext_2;
+ uint64 narrowMemoryContext_3;
+ uint64 deepSleep;
+ uint64 SyncCounter_AVDATA;
+ uint64 SyncCounter_PARAMETERS;
+ uint64 SyncCounter_PARTIAL_SUMS;
+ uint64 SyncCounter_MESH_NORTH_IN;
+ uint64 SyncCounter_MESH_EAST_IN;
+ uint64 SyncCounter_MESH_SOUTH_IN;
+ uint64 SyncCounter_MESH_WEST_IN;
+ uint64 SyncCounter_MESH_NORTH_OUT;
+ uint64 SyncCounter_MESH_EAST_OUT;
+ uint64 SyncCounter_MESH_SOUTH_OUT;
+ uint64 SyncCounter_MESH_WEST_OUT;
+ uint64 SyncCounter_WIDE_TO_NARROW;
+ uint64 SyncCounter_WIDE_TO_SCALING;
+ uint64 SyncCounter_NARROW_TO_WIDE;
+ uint64 SyncCounter_RING_READ_A;
+ uint64 SyncCounter_RING_READ_B;
+ uint64 SyncCounter_RING_WRITE;
+ uint64 SyncCounter_RING_PRODUCER_A;
+ uint64 SyncCounter_RING_PRODUCER_B;
+ uint64 opRunControl;
+ uint64 PowerSaveData;
+ uint64 opBreakPoint;
+ uint64 StallCounter;
+ uint64 opRunStatus;
+ uint64 OpOverwriteMode;
+ uint64 OpEnableTracing;
+ uint64 OpStartCycle;
+ uint64 OpEndCycle;
+ uint64 OpStallCycleCount;
+ uint64 OpProgramCounter;
+ uint64 wideToNarrowRunControl;
+ uint64 wideToNarrowRunStatus;
+ uint64 wideToNarrowBreakPoint;
+ uint64 dmaWideToNarrowOverwriteMode;
+ uint64 dmaWideToNarrowEnableTracing;
+ uint64 dmaWideToNarrowStartCycle;
+ uint64 dmaWideToNarrowEndCycle;
+ uint64 dmaWideToNarrowStallCycleCount;
+ uint64 dmaWideToNarrowProgramCounter;
+ uint64 narrowToWideRunControl;
+ uint64 narrowToWideRunStatus;
+ uint64 narrowToWideBreakPoint;
+ uint64 dmaNarrowToWideOverwriteMode;
+ uint64 dmaNarrowToWideEnableTracing;
+ uint64 dmaNarrowToWideStartCycle;
+ uint64 dmaNarrowToWideEndCycle;
+ uint64 dmaNarrowToWideStallCycleCount;
+ uint64 dmaNarrowToWideProgramCounter;
+ uint64 ringBusConsumer0RunControl;
+ uint64 ringBusConsumer0RunStatus;
+ uint64 ringBusConsumer0BreakPoint;
+ uint64 dmaRingBusConsumer0OverwriteMode;
+ uint64 dmaRingBusConsumer0EnableTracing;
+ uint64 dmaRingBusConsumer0StartCycle;
+ uint64 dmaRingBusConsumer0EndCycle;
+ uint64 dmaRingBusConsumer0StallCycleCount;
+ uint64 dmaRingBusConsumer0ProgramCounter;
+ uint64 ringBusConsumer1RunControl;
+ uint64 ringBusConsumer1RunStatus;
+ uint64 ringBusConsumer1BreakPoint;
+ uint64 dmaRingBusConsumer1OverwriteMode;
+ uint64 dmaRingBusConsumer1EnableTracing;
+ uint64 dmaRingBusConsumer1StartCycle;
+ uint64 dmaRingBusConsumer1EndCycle;
+ uint64 dmaRingBusConsumer1StallCycleCount;
+ uint64 dmaRingBusConsumer1ProgramCounter;
+ uint64 ringBusProducerRunControl;
+ uint64 ringBusProducerRunStatus;
+ uint64 ringBusProducerBreakPoint;
+ uint64 dmaRingBusProducerOverwriteMode;
+ uint64 dmaRingBusProducerEnableTracing;
+ uint64 dmaRingBusProducerStartCycle;
+ uint64 dmaRingBusProducerEndCycle;
+ uint64 dmaRingBusProducerStallCycleCount;
+ uint64 dmaRingBusProducerProgramCounter;
+ uint64 meshBus0RunControl;
+ uint64 meshBus0RunStatus;
+ uint64 meshBus0BreakPoint;
+ uint64 dmaMeshBus0OverwriteMode;
+ uint64 dmaMeshBus0EnableTracing;
+ uint64 dmaMeshBus0StartCycle;
+ uint64 dmaMeshBus0EndCycle;
+ uint64 dmaMeshBus0StallCycleCount;
+ uint64 dmaMeshBus0ProgramCounter;
+ uint64 meshBus1RunControl;
+ uint64 meshBus1RunStatus;
+ uint64 meshBus1BreakPoint;
+ uint64 dmaMeshBus1OverwriteMode;
+ uint64 dmaMeshBus1EnableTracing;
+ uint64 dmaMeshBus1StartCycle;
+ uint64 dmaMeshBus1EndCycle;
+ uint64 dmaMeshBus1StallCycleCount;
+ uint64 dmaMeshBus1ProgramCounter;
+ uint64 meshBus2RunControl;
+ uint64 meshBus2RunStatus;
+ uint64 meshBus2BreakPoint;
+ uint64 dmaMeshBus2OverwriteMode;
+ uint64 dmaMeshBus2EnableTracing;
+ uint64 dmaMeshBus2StartCycle;
+ uint64 dmaMeshBus2EndCycle;
+ uint64 dmaMeshBus2StallCycleCount;
+ uint64 dmaMeshBus2ProgramCounter;
+ uint64 meshBus3RunControl;
+ uint64 meshBus3RunStatus;
+ uint64 meshBus3BreakPoint;
+ uint64 dmaMeshBus3OverwriteMode;
+ uint64 dmaMeshBus3EnableTracing;
+ uint64 dmaMeshBus3StartCycle;
+ uint64 dmaMeshBus3EndCycle;
+ uint64 dmaMeshBus3StallCycleCount;
+ uint64 dmaMeshBus3ProgramCounter;
+ uint64 Error_Tile;
+ uint64 Error_Mask_Tile;
+ uint64 Error_Force_Tile;
+ uint64 Error_Timestamp_Tile;
+ uint64 Error_Info_Tile;
+ uint64 Timeout;
+ uint64 opTtuStateRegFile;
+ uint64 OpTrace;
+ uint64 wideToNarrowTtuStateRegFile;
+ uint64 dmaWideToNarrowTrace;
+ uint64 narrowToWideTtuStateRegFile;
+ uint64 dmaNarrowToWideTrace;
+ uint64 ringBusConsumer0TtuStateRegFile;
+ uint64 dmaRingBusConsumer0Trace;
+ uint64 ringBusConsumer1TtuStateRegFile;
+ uint64 dmaRingBusConsumer1Trace;
+ uint64 ringBusProducerTtuStateRegFile;
+ uint64 dmaRingBusProducerTrace;
+ uint64 meshBus0TtuStateRegFile;
+ uint64 dmaMeshBus0Trace;
+ uint64 meshBus1TtuStateRegFile;
+ uint64 dmaMeshBus1Trace;
+ uint64 meshBus2TtuStateRegFile;
+ uint64 dmaMeshBus2Trace;
+ uint64 meshBus3TtuStateRegFile;
+ uint64 dmaMeshBus3Trace;
+ uint64 narrowMemoryIsolation;
+ uint64 narrowMemoryRetention;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_DEBUG_TILE_CSR_OFFSETS_H_
diff --git a/driver/config/hib_kernel_csr_offsets.h b/driver/config/hib_kernel_csr_offsets.h
new file mode 100644
index 0000000..d793264
--- /dev/null
+++ b/driver/config/hib_kernel_csr_offsets.h
@@ -0,0 +1,49 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_HIB_KERNEL_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_HIB_KERNEL_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for kernel space in HIB. Members are
+// intentionally named to match the GCSR register names.
+struct HibKernelCsrOffsets {
+ uint64 page_table_size;
+ uint64 extended_table;
+ uint64 dma_pause;
+
+ // Tracks whether initialization is done.
+ uint64 page_table_init;
+ uint64 msix_table_init;
+
+ // Points to the first entry in the page table. Subsequent entries can be
+ // accessed with increasing offsets if they exist.
+ uint64 page_table;
+
+ // Limits AXI DMA burst.
+ uint64 dma_burst_limiter;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_HIB_KERNEL_CSR_OFFSETS_H_
diff --git a/driver/config/hib_user_csr_offsets.h b/driver/config/hib_user_csr_offsets.h
new file mode 100644
index 0000000..9ff44b0
--- /dev/null
+++ b/driver/config/hib_user_csr_offsets.h
@@ -0,0 +1,58 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_HIB_USER_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_HIB_USER_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for user space in HIB. Members are
+// intentionally named to match the GCSR register names.
+struct HibUserCsrOffsets {
+ // Interrupt control and status for top level.
+ uint64 top_level_int_control;
+ uint64 top_level_int_status;
+
+ // Interrupt count for scalar core.
+ uint64 sc_host_int_count;
+
+ // DMA pauses.
+ uint64 dma_pause;
+ uint64 dma_paused;
+
+ // Enable/disable status block update.
+ uint64 status_block_update;
+
+ // HIB errors.
+ uint64 hib_error_status;
+ uint64 hib_error_mask;
+ uint64 hib_first_error_status;
+ uint64 hib_first_error_timestamp;
+ uint64 hib_inject_error;
+
+ // Limits AXI DMA burst.
+ uint64 dma_burst_limiter;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_HIB_USER_CSR_OFFSETS_H_
diff --git a/driver/config/interrupt_csr_offsets.h b/driver/config/interrupt_csr_offsets.h
new file mode 100644
index 0000000..e2445d8
--- /dev/null
+++ b/driver/config/interrupt_csr_offsets.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_INTERRUPT_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_INTERRUPT_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for enabling/disabling/clearing
+// interrupts. Members are intentionally named to match the GCSR register
+// names.
+struct InterruptCsrOffsets {
+ // Interrupt control and status CSRs.
+ uint64 control;
+ uint64 status;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_INTERRUPT_CSR_OFFSETS_H_
diff --git a/driver/config/memory_csr_offsets.h b/driver/config/memory_csr_offsets.h
new file mode 100644
index 0000000..ca034cf
--- /dev/null
+++ b/driver/config/memory_csr_offsets.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_MEMORY_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_MEMORY_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for configuring memory accesses for
+// scalar core and tiles.
+// Members are intentionally named to match the GCSR register names.
+struct MemoryCsrOffsets {
+ uint64 Access;
+ uint64 Data;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_MEMORY_CSR_OFFSETS_H_
diff --git a/driver/config/misc_csr_offsets.h b/driver/config/misc_csr_offsets.h
new file mode 100644
index 0000000..4576177
--- /dev/null
+++ b/driver/config/misc_csr_offsets.h
@@ -0,0 +1,36 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_MISC_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_MISC_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for custom block misc.
+// Members are intentionally named to match the GCSR register names.
+struct MiscCsrOffsets {
+ uint64 idleRegister;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_MISC_CSR_OFFSETS_H_
diff --git a/driver/config/msix_csr_offsets.h b/driver/config/msix_csr_offsets.h
new file mode 100644
index 0000000..b872eeb
--- /dev/null
+++ b/driver/config/msix_csr_offsets.h
@@ -0,0 +1,61 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_MSIX_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_MSIX_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for programming MSIX interrupts.
+// Members are intentionally named to match the GCSR register names.
+struct MsixCsrOffsets {
+ // Interrupt vectors for descriptor queues.
+ uint64 instruction_queue_int_vector;
+ uint64 input_actv_queue_int_vector;
+ uint64 param_queue_int_vector;
+ uint64 output_actv_queue_int_vector;
+
+ // top_level_int_vector contains indices for four interrupts.
+ // [27:21] | [20:14] | [13:7] | [6:0]
+ // thermal | mbist | PCIe | thermalShutdown
+ uint64 top_level_int_vector;
+
+ // sc_host_int_vector contains indices for four interrupts.
+ // [27:21] | [20:14] | [13:7] | [6:0]
+ // INT_3 | INT_2 | INT_1 | INT_0
+ uint64 sc_host_int_vector;
+
+ // HIB fatal error.
+ uint64 fatal_err_int_vector;
+
+ // Points to the first bit array. Subsequent bit arrays can be accessed with
+ // increasing offsets if they exist.
+ uint64 msix_pending_bit_array0;
+
+ // Points to the first entry in the table. Subsequent entries can be accessed
+ // with increasing offsets if they exist.
+ uint64 msix_table;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_MSIX_CSR_OFFSETS_H_
diff --git a/driver/config/power_throttle_csr_helper.h b/driver/config/power_throttle_csr_helper.h
new file mode 100644
index 0000000..31d251e
--- /dev/null
+++ b/driver/config/power_throttle_csr_helper.h
@@ -0,0 +1,220 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_POWER_THROTTLE_CSR_HELPER_H_
+#define DARWINN_DRIVER_CONFIG_POWER_THROTTLE_CSR_HELPER_H_
+
+#include "driver/bitfield.h"
+#include "port/integral_types.h"
+#include "port/unreachable.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+namespace registers {
+
+// Implements field level access for the EneryTable CSR register.
+class EnergyTable {
+ public:
+ EnergyTable() : EnergyTable(/*value=*/0ULL) {}
+ EnergyTable(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_idle_power(uint64 value) { reg_.idle_power_ = value; }
+ uint64 idle_power() const { return reg_.idle_power_(); }
+
+ void set_ring_bus(uint64 value) { reg_.ring_bus_ = value; }
+ uint64 ring_bus() const { return reg_.ring_bus_(); }
+
+ void set_nlu_active(uint64 value) { reg_.nlu_active_ = value; }
+ uint64 nlu_active() const { return reg_.nlu_active_(); }
+
+ void set_wide_byte_access(uint64 value) { reg_.wide_byte_access_ = value; }
+ uint64 wide_byte_access() const { return reg_.wide_byte_access_(); }
+
+ void set_narrow_mem_word_access(uint64 value) {
+ reg_.narrow_mem_word_access_ = value;
+ }
+ uint64 narrow_mem_word_access() const {
+ return reg_.narrow_mem_word_access_();
+ }
+
+ void set_int_multiply(uint64 value) { reg_.int_multiply_ = value; }
+ uint64 int_multiply() const { return reg_.int_multiply_(); }
+
+ void set_int_adder(uint64 value) { reg_.int_adder_ = value; }
+ uint64 int_adder() const { return reg_.int_adder_(); }
+
+ void set_float_32_adder(uint64 value) { reg_.float_32_adder_ = value; }
+ uint64 float_32_adder() const { return reg_.float_32_adder_(); }
+
+ void set_input_bus_transfer(uint64 value) {
+ reg_.input_bus_transfer_ = value;
+ }
+ uint64 input_bus_transfer() const { return reg_.input_bus_transfer_(); }
+
+ void set_wide_data_transfer(uint64 value) {
+ reg_.wide_data_transfer_ = value;
+ }
+ uint64 wide_data_transfer() const { return reg_.wide_data_transfer_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 2> idle_power_;
+ platforms::darwinn::driver::Bitfield<2, 2> ring_bus_;
+ platforms::darwinn::driver::Bitfield<4, 2> nlu_active_;
+ platforms::darwinn::driver::Bitfield<6, 2> wide_byte_access_;
+ platforms::darwinn::driver::Bitfield<8, 2> narrow_mem_word_access_;
+ platforms::darwinn::driver::Bitfield<10, 2> int_multiply_;
+ platforms::darwinn::driver::Bitfield<12, 2> int_adder_;
+ platforms::darwinn::driver::Bitfield<14, 2> float_32_adder_;
+ platforms::darwinn::driver::Bitfield<16, 2> input_bus_transfer_;
+ platforms::darwinn::driver::Bitfield<18, 2> wide_data_transfer_;
+ } reg_;
+};
+
+// Implements field level access for *SampleInterval CSR.
+class SampleInterval {
+ public:
+ SampleInterval() : SampleInterval(/*value=*/0ULL) {}
+ SampleInterval(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_value(uint64 value) { reg_.value_ = value; }
+ uint64 value() const { return reg_.value_(); }
+
+ void set_enable(uint64 value) { reg_.enable_ = value; }
+ uint64 enable() const { return reg_.enable_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 7> value_;
+ platforms::darwinn::driver::Bitfield<7, 1> enable_;
+ } reg_;
+};
+
+// Implements field level access for tdpSampleInterval CSR.
+class tdpSampleInterval {
+ public:
+ tdpSampleInterval() : tdpSampleInterval(/*value=*/0ULL) {}
+ tdpSampleInterval(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_value(uint64 value) { reg_.value_ = value; }
+ uint64 value() const { return reg_.value_(); }
+
+ void set_enable(uint64 value) { reg_.enable_ = value; }
+ uint64 enable() const { return reg_.enable_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 14> value_;
+ platforms::darwinn::driver::Bitfield<14, 1> enable_;
+ } reg_;
+};
+
+// Implements field level access for *RunningSumInterval CSR.
+class RunningSumInterval {
+ public:
+ RunningSumInterval() : RunningSumInterval(/*value=*/0ULL) {}
+ RunningSumInterval(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_value(uint64 value) { reg_.value_ = value; }
+ uint64 value() const { return reg_.value_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 2> value_;
+ } reg_;
+};
+
+// Implements field level access for didtThreshold CSR.
+class didtThreshold {
+ public:
+ didtThreshold() : didtThreshold(/*value=*/0ULL) {}
+ didtThreshold(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_value(uint64 value) { reg_.value_ = value; }
+ uint64 value() const { return reg_.value_(); }
+
+ void set_enable(uint64 value) { reg_.enable_ = value; }
+ uint64 enable() const { return reg_.enable_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 11> value_;
+ platforms::darwinn::driver::Bitfield<11, 1> enable_;
+ } reg_;
+};
+
+// Implements field level access for *ActionTable CSR.
+class ActionTable {
+ public:
+ ActionTable() : ActionTable(/*value=*/0ULL) {}
+ ActionTable(uint64 value) { reg_.raw_ = value; }
+
+ void set_raw(uint64 value) { reg_.raw_ = value; }
+ uint64 raw() const { return reg_.raw_; }
+
+ void set_action0(uint64 value) { reg_.action0_ = value; }
+ uint64 action0() const { return reg_.action0_(); }
+
+ void set_action1(uint64 value) { reg_.action1_ = value; }
+ uint64 action1() const { return reg_.action1_(); }
+
+ void set_action2(uint64 value) { reg_.action2_ = value; }
+ uint64 action2() const { return reg_.action2_(); }
+
+ void set_action3(uint64 value) { reg_.action3_ = value; }
+ uint64 action3() const { return reg_.action3_(); }
+
+ void set_enable(uint64 value) { reg_.enable_ = value; }
+ uint64 enable() const { return reg_.enable_(); }
+
+ private:
+ union {
+ uint64 raw_;
+ platforms::darwinn::driver::Bitfield<0, 3> action0_;
+ platforms::darwinn::driver::Bitfield<3, 3> action1_;
+ platforms::darwinn::driver::Bitfield<6, 3> action2_;
+ platforms::darwinn::driver::Bitfield<9, 3> action3_;
+ platforms::darwinn::driver::Bitfield<12, 1> enable_;
+ } reg_;
+};
+
+} // namespace registers
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_POWER_THROTTLE_CSR_HELPER_H_
diff --git a/driver/config/queue_csr_offsets.h b/driver/config/queue_csr_offsets.h
new file mode 100644
index 0000000..860a773
--- /dev/null
+++ b/driver/config/queue_csr_offsets.h
@@ -0,0 +1,51 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_QUEUE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_QUEUE_CSR_OFFSETS_H_
+
+#include
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds the various CSR offsets for programming queue behaviors.
+// Members are intentionally named to match the GCSR register names.
+struct QueueCsrOffsets {
+ uint64 queue_control;
+ uint64 queue_status;
+ uint64 queue_descriptor_size;
+ uint64 queue_base;
+ uint64 queue_status_block_base;
+ uint64 queue_size;
+ uint64 queue_tail;
+ uint64 queue_fetched_head;
+ uint64 queue_completed_head;
+ uint64 queue_int_control;
+ uint64 queue_int_status;
+ uint64 queue_minimum_size;
+ uint64 queue_maximum_size;
+ uint64 queue_int_vector;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_QUEUE_CSR_OFFSETS_H_
diff --git a/driver/config/register_constants.h b/driver/config/register_constants.h
new file mode 100644
index 0000000..87f10da
--- /dev/null
+++ b/driver/config/register_constants.h
@@ -0,0 +1,23 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_REGISTER_CONSTANTS_H_
+#define DARWINN_DRIVER_CONFIG_REGISTER_CONSTANTS_H_
+
+#include "port/integral_types.h"
+
+// Offset used when a register does not exist for a project.
+#define kCsrRegisterSpaceInvalidOffset static_cast(-1)
+
+#endif // DARWINN_DRIVER_CONFIG_REGISTER_CONSTANTS_H_
diff --git a/driver/config/register_file_csr_offsets.h b/driver/config/register_file_csr_offsets.h
new file mode 100644
index 0000000..ed51c7b
--- /dev/null
+++ b/driver/config/register_file_csr_offsets.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_REGISTER_FILE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_REGISTER_FILE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds CSR offsets for accessing register file. Members are
+// intentionally named to match the GCSR register names.
+struct RegisterFileCsrOffsets {
+ // Points to first register in the register file. Subsequent registers can be
+ // accessed with increasing offsets if they exist.
+ uint64 RegisterFile;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_REGISTER_FILE_CSR_OFFSETS_H_
diff --git a/driver/config/scalar_core_csr_offsets.h b/driver/config/scalar_core_csr_offsets.h
new file mode 100644
index 0000000..bf872d0
--- /dev/null
+++ b/driver/config/scalar_core_csr_offsets.h
@@ -0,0 +1,127 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_SCALAR_CORE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_SCALAR_CORE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for scalar core.
+// Members are intentionally named to match the GCSR register names.
+struct ScalarCoreCsrOffsets {
+ // RunControls.
+ // Legacy
+ uint64 scalarCoreRunControl;
+ uint64 executeControl;
+ uint64 avDataPopRunControl;
+ uint64 parameterPopRunControl;
+
+ // Context 0
+ uint64 scalarDatapath_0RunControl;
+ uint64 executeControl_0;
+ uint64 avDataPop_0RunControl;
+ uint64 parameterPop_0RunControl;
+ // Context 1
+ uint64 scalarDatapath_1RunControl;
+ uint64 executeControl_1;
+ uint64 avDataPop_1RunControl;
+ uint64 parameterPop_1RunControl;
+ // Context 2
+ uint64 scalarDatapath_2RunControl;
+ uint64 executeControl_2;
+ uint64 avDataPop_2RunControl;
+ uint64 parameterPop_2RunControl;
+ // Context 3
+ uint64 scalarDatapath_3RunControl;
+ uint64 executeControl_3;
+ uint64 avDataPop_3RunControl;
+ uint64 parameterPop_3RunControl;
+
+ // Legacy
+ uint64 infeedRunControl;
+ uint64 outfeedRunControl;
+ uint64 infeed1RunControl;
+ uint64 outfeed1RunControl;
+
+ // Context Switching
+ uint64 contextControl;
+ uint64 contextStatus;
+
+ // Context 0
+ uint64 infeed_0_0RunControl;
+ uint64 outfeed_0_0RunControl;
+ uint64 infeed_0_1RunControl;
+ uint64 outfeed_0_1RunControl;
+ // Context 1
+ uint64 infeed_1_0RunControl;
+ uint64 outfeed_1_0RunControl;
+ uint64 infeed_1_1RunControl;
+ uint64 outfeed_1_1RunControl;
+ // Context 2
+ uint64 infeed_2_0RunControl;
+ uint64 outfeed_2_0RunControl;
+ uint64 infeed_2_1RunControl;
+ uint64 outfeed_2_1RunControl;
+ // Context 3
+ uint64 infeed_3_0RunControl;
+ uint64 outfeed_3_0RunControl;
+ uint64 infeed_3_1RunControl;
+ uint64 outfeed_3_1RunControl;
+
+ // Power related.
+ uint64 TilePowerInterval;
+ uint64 peakPowerSampleInterval;
+ uint64 tdpPowerSampleInterval;
+ uint64 didtPowerSampleInterval;
+ uint64 peakSampleAccumulator;
+ uint64 tdpSampleAccumulator;
+ uint64 didtSampleAccumulator;
+ uint64 peakThreshold0;
+ uint64 peakThreshold1;
+ uint64 peakThreshold2;
+ uint64 peakThreshold3;
+ uint64 tdpThreshold0;
+ uint64 tdpThreshold1;
+ uint64 tdpThreshold2;
+ uint64 tdpThreshold3;
+ uint64 didtThreshold0;
+ uint64 peakActionTable;
+ uint64 tdpActionTable;
+ uint64 didtActionTable;
+ uint64 peakRunningSum;
+ uint64 peakRunningSumInterval;
+ uint64 tdpRunningSum;
+ uint64 tdpRunningSumInterval;
+ uint64 didtRunningSum;
+ uint64 didtRunningSumInterval;
+ uint64 didtDifference;
+ uint64 packageTdpAction;
+ uint64 ThrottleStallCounter;
+
+ // Scalar core cycle count. This could be used to synchronize timestamp
+ // between host and the TPU
+ uint64 cycleCount;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_SCALAR_CORE_CSR_OFFSETS_H_
diff --git a/driver/config/scu_csr_offsets.h b/driver/config/scu_csr_offsets.h
new file mode 100644
index 0000000..b80d66e
--- /dev/null
+++ b/driver/config/scu_csr_offsets.h
@@ -0,0 +1,46 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_SCU_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_SCU_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for programming the SCU in Beagle
+// (the block containing state machines to control boot and power sequences)
+// Members are intentionally named to match the GCSR register names.
+struct ScuCsrOffsets {
+ // The SCU control registers have generic names but each contain many small
+ // fields which are reflected in the spec (should use csr_helper to access)
+ uint64 scu_ctrl_0;
+ uint64 scu_ctrl_1;
+ uint64 scu_ctrl_2;
+ uint64 scu_ctrl_3;
+ uint64 scu_ctrl_4;
+ uint64 scu_ctrl_5;
+ uint64 scu_ctr_6;
+ uint64 scu_ctr_7;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_SCU_CSR_OFFSETS_H_
diff --git a/driver/config/sync_flag_csr_offsets.h b/driver/config/sync_flag_csr_offsets.h
new file mode 100644
index 0000000..dc9fc0a
--- /dev/null
+++ b/driver/config/sync_flag_csr_offsets.h
@@ -0,0 +1,37 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_SYNC_FLAG_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_SYNC_FLAG_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for accessing sync flags for scalar
+// core and tiles.
+struct SyncFlagCsrOffsets {
+ // Intentionally named to match the GCSR register names.
+ uint64 SyncCounter;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_SYNC_FLAG_CSR_OFFSETS_H_
diff --git a/driver/config/tile_config_csr_offsets.h b/driver/config/tile_config_csr_offsets.h
new file mode 100644
index 0000000..8a09f24
--- /dev/null
+++ b/driver/config/tile_config_csr_offsets.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_TILE_CONFIG_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_TILE_CONFIG_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for configuring indirect tile accesses.
+// Members are intentionally named to match the GCSR register names.
+struct TileConfigCsrOffsets {
+ // Used only by driver.
+ uint64 tileconfig0;
+
+ // Used by debugger, and other purposes.
+ uint64 tileconfig1;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_TILE_CONFIG_CSR_OFFSETS_H_
diff --git a/driver/config/tile_csr_offsets.h b/driver/config/tile_csr_offsets.h
new file mode 100644
index 0000000..d234ede
--- /dev/null
+++ b/driver/config/tile_csr_offsets.h
@@ -0,0 +1,98 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_TILE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_TILE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for tiles. Members are intentionally
+// named to match the GCSR register names.
+struct TileCsrOffsets {
+ // RunControls to change run state.
+ uint64 opRunControl;
+ uint64 narrowToNarrowRunControl;
+ uint64 narrowToWideRunControl;
+ uint64 wideToNarrowRunControl;
+ // When we enable the wider thread issue feature, we get multiple
+ // of these run controls per pipeline for the opcontrol, narrow to wide
+ // and wide to narrow. We're using 8 of these as a maximum issue width
+ // at this point. The driver will only use the registers that are valid
+ // for any given configuration.
+ // TODO
+ uint64 opRunControl_0;
+ uint64 narrowToWideRunControl_0;
+ uint64 wideToNarrowRunControl_0;
+ uint64 opRunControl_1;
+ uint64 narrowToWideRunControl_1;
+ uint64 wideToNarrowRunControl_1;
+ uint64 opRunControl_2;
+ uint64 narrowToWideRunControl_2;
+ uint64 wideToNarrowRunControl_2;
+ uint64 opRunControl_3;
+ uint64 narrowToWideRunControl_3;
+ uint64 wideToNarrowRunControl_3;
+ uint64 opRunControl_4;
+ uint64 narrowToWideRunControl_4;
+ uint64 wideToNarrowRunControl_4;
+ uint64 opRunControl_5;
+ uint64 narrowToWideRunControl_5;
+ uint64 wideToNarrowRunControl_5;
+ uint64 opRunControl_6;
+ uint64 narrowToWideRunControl_6;
+ uint64 wideToNarrowRunControl_6;
+ uint64 opRunControl_7;
+ uint64 narrowToWideRunControl_7;
+ uint64 wideToNarrowRunControl_7;
+ uint64 ringBusConsumer0RunControl;
+ uint64 ringBusConsumer1RunControl;
+ uint64 ringBusProducerRunControl;
+ uint64 meshBus0RunControl;
+ uint64 meshBus1RunControl;
+ uint64 meshBus2RunControl;
+ uint64 meshBus3RunControl;
+
+ // Deep sleep register to control power state.
+ uint64 deepSleep;
+
+ // Narrow memory retention and isolation.
+ uint64 narrowMemoryIsolation;
+ uint64 narrowMemoryRetention;
+
+ // Power related.
+ uint64 EnergyTable;
+ uint64 didtSampleInterval;
+ uint64 didtRunningSumInterval;
+ uint64 opAccumulateRegister;
+ uint64 didtRunningSumRegister;
+ uint64 didtThreshold0;
+
+ // Narrow memory base and bound of virtual contexts.
+ uint64 narrowMemoryContext_0;
+ uint64 narrowMemoryContext_1;
+ uint64 narrowMemoryContext_2;
+ uint64 narrowMemoryContext_3;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_TILE_CSR_OFFSETS_H_
diff --git a/driver/config/tile_thread_csr_offsets.h b/driver/config/tile_thread_csr_offsets.h
new file mode 100644
index 0000000..da6a1ba
--- /dev/null
+++ b/driver/config/tile_thread_csr_offsets.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_TILE_THREAD_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_TILE_THREAD_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for tilethreads.
+// Members are intentionally named to match the GCSR register names.
+struct TileThreadCsrOffsets {
+ // RunControls to change run state.
+ uint64 opRunControl_0;
+ uint64 narrowToWideRunControl_0;
+ uint64 wideToNarrowRunControl_0;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_TILE_THREAD_CSR_OFFSETS_H_
diff --git a/driver/config/tile_thread_trace_csr_offsets.h b/driver/config/tile_thread_trace_csr_offsets.h
new file mode 100644
index 0000000..646e77c
--- /dev/null
+++ b/driver/config/tile_thread_trace_csr_offsets.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_TILE_THREAD_TRACE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_TILE_THREAD_TRACE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for tilethreads.
+// Members are intentionally named to match the GCSR register names.
+struct TileThreadTraceCsrOffsets {
+ // RunControls to change run state.
+ uint64 TimeStampUnit;
+ uint64 StallCauseSelect;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_TILE_THREAD_TRACE_CSR_OFFSETS_H_
diff --git a/driver/config/trace_csr_offsets.h b/driver/config/trace_csr_offsets.h
new file mode 100644
index 0000000..79f1740
--- /dev/null
+++ b/driver/config/trace_csr_offsets.h
@@ -0,0 +1,40 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_TRACE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_TRACE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for performance tracing.
+// Members are intentionally named to match the GCSR register names.
+struct TraceCsrOffsets {
+ uint64 OverwriteMode;
+ uint64 EnableTracing;
+ uint64 Trace;
+ uint64 TimeStampUnit;
+ uint64 StallCauseSelect;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_TRACE_CSR_OFFSETS_H_
diff --git a/driver/config/usb_csr_offsets.h b/driver/config/usb_csr_offsets.h
new file mode 100644
index 0000000..9dbafd4
--- /dev/null
+++ b/driver/config/usb_csr_offsets.h
@@ -0,0 +1,39 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_USB_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_USB_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for USB HIB.
+// Members are intentionally named to match the GCSR register names.
+struct UsbCsrOffsets {
+ uint64 outfeed_chunk_length;
+ uint64 descr_ep;
+ uint64 ep_status_credit;
+ uint64 multi_bo_ep;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_USB_CSR_OFFSETS_H_
diff --git a/driver/config/wire_csr_offsets.h b/driver/config/wire_csr_offsets.h
new file mode 100644
index 0000000..5cd5755
--- /dev/null
+++ b/driver/config/wire_csr_offsets.h
@@ -0,0 +1,38 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_CONFIG_WIRE_CSR_OFFSETS_H_
+#define DARWINN_DRIVER_CONFIG_WIRE_CSR_OFFSETS_H_
+
+#include "port/integral_types.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+namespace config {
+
+// This struct holds various CSR offsets for handling wire interrupts.
+// Members are intentionally named to match the GCSR register names.
+struct WireCsrOffsets {
+ // Tells which interrupts should be serviced.
+ uint64 wire_int_pending_bit_array;
+ uint64 wire_int_mask_array;
+};
+
+} // namespace config
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_CONFIG_WIRE_CSR_OFFSETS_H_
diff --git a/driver/default_telemeter.h b/driver/default_telemeter.h
new file mode 100644
index 0000000..5f6019c
--- /dev/null
+++ b/driver/default_telemeter.h
@@ -0,0 +1,36 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_DEFAULT_TELEMETER_H_
+#define DARWINN_DRIVER_DEFAULT_TELEMETER_H_
+
+#include "api/telemeter_interface.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// This is the default implementation of TelemeterInterface. By default, every
+// operation is a NOP.
+class DefaultTelemeter : public api::TelemeterInterface {
+ public:
+ void LogWatchdogTimeout(
+ const api::ExecutionContextInterface& context) override {}
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_DEFAULT_TELEMETER_H_
diff --git a/driver/device_buffer.cc b/driver/device_buffer.cc
new file mode 100644
index 0000000..d7c394d
--- /dev/null
+++ b/driver/device_buffer.cc
@@ -0,0 +1,76 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/device_buffer.h"
+
+#include
+
+#include "port/integral_types.h"
+#include "port/logging.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+void DeviceBuffer::Clear() {
+ type_ = Type::kInvalid;
+ size_bytes_ = 0;
+ device_address_ = 0;
+}
+
+DeviceBuffer::DeviceBuffer(uint64 device_address, size_t size_bytes)
+ : type_(Type::kDefault),
+ size_bytes_(size_bytes),
+ device_address_(device_address) {}
+
+bool DeviceBuffer::operator==(const DeviceBuffer& rhs) const {
+ return type_ == rhs.type_ && size_bytes_ == rhs.size_bytes_ &&
+ device_address_ == rhs.device_address_;
+}
+
+bool DeviceBuffer::operator!=(const DeviceBuffer& rhs) const {
+ return !(*this == rhs);
+}
+
+DeviceBuffer::DeviceBuffer(DeviceBuffer&& other)
+ : type_(other.type_),
+ size_bytes_(other.size_bytes_),
+ device_address_(other.device_address_) {
+ other.Clear();
+}
+
+DeviceBuffer& DeviceBuffer::operator=(DeviceBuffer&& other) {
+ if (this != &other) {
+ type_ = other.type_;
+ size_bytes_ = other.size_bytes_;
+ device_address_ = other.device_address_;
+
+ other.Clear();
+ }
+ return *this;
+}
+
+DeviceBuffer DeviceBuffer::Slice(uint64 byte_offset, size_t size_bytes,
+ bool allow_overflow) const {
+ if (!allow_overflow) {
+ CHECK_LE(byte_offset + size_bytes, size_bytes_)
+ << "Overflowed underlying DeviceBuffer";
+ }
+ const uint64 new_device_address = device_address_ + byte_offset;
+ return DeviceBuffer(new_device_address, size_bytes);
+}
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
diff --git a/driver/device_buffer.h b/driver/device_buffer.h
new file mode 100644
index 0000000..1b5d7d4
--- /dev/null
+++ b/driver/device_buffer.h
@@ -0,0 +1,99 @@
+// Copyright 2019 Google LLC
+//
+// 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.
+
+#ifndef DARWINN_DRIVER_DEVICE_BUFFER_H_
+#define DARWINN_DRIVER_DEVICE_BUFFER_H_
+
+#include
+#include
+#include
+#include
+
+#include "port/integral_types.h"
+#include "port/logging.h"
+
+namespace platforms {
+namespace darwinn {
+namespace driver {
+
+// Abstracts a device addressable buffer. Movable and copyable.
+class DeviceBuffer {
+ public:
+ // Convenience structure for keeping track of named array of DeviceBuffers.
+ using NamedMap = std::unordered_map>;
+
+ // Default constructor. Defaults to an invalid non-existent buffer.
+ DeviceBuffer() = default;
+
+ // Constructors for a device accessible buffer.
+ DeviceBuffer(uint64 device_address, size_t size_bytes);
+
+ // This type is copyable, with default implementations.
+ DeviceBuffer(const DeviceBuffer&) = default;
+ DeviceBuffer& operator=(const DeviceBuffer&) = default;
+
+ // This type is movable.
+ DeviceBuffer(DeviceBuffer&& other);
+ DeviceBuffer& operator=(DeviceBuffer&& other);
+
+ // Destructors.
+ ~DeviceBuffer() = default;
+
+ // Size of this buffer in bytes.
+ size_t size_bytes() const { return size_bytes_; }
+
+ // Returns true if buffer is valid.
+ bool IsValid() const { return type_ != Type::kInvalid; }
+
+ // Returns the device address.
+ uint64 device_address() const { return device_address_; }
+
+ // Equality operators.
+ bool operator==(const DeviceBuffer& rhs) const;
+ bool operator!=(const DeviceBuffer& rhs) const;
+
+ // Returns a DeviceBuffer that starts from the "byte_offset" and consumes
+ // "size_bytes". Internally fails if created DeviceBuffer accesses outside of
+ // current DeviceBuffer and "allow_overflow" is false (the default).
+ DeviceBuffer Slice(uint64 byte_offset, size_t size_bytes,
+ bool allow_overflow = false) const;
+
+ private:
+ // Type for the buffer.
+ enum class Type {
+ // Invalid.
+ kInvalid = 0,
+
+ // Default device buffer (only one type for now.)
+ kDefault = 1,
+ };
+
+ // Clears all variables.
+ void Clear();
+
+ // Type for the buffer.
+ Type type_{Type::kInvalid};
+
+ // Size of the buffer.
+ size_t size_bytes_{0};
+
+ // Points to device addressable buffer. Valid when type is kDeviceBuffer.
+ uint64 device_address_{0};
+};
+
+} // namespace driver
+} // namespace darwinn
+} // namespace platforms
+
+#endif // DARWINN_DRIVER_DEVICE_BUFFER_H_
diff --git a/driver/device_buffer_mapper.cc b/driver/device_buffer_mapper.cc
new file mode 100644
index 0000000..51ac8f5
--- /dev/null
+++ b/driver/device_buffer_mapper.cc
@@ -0,0 +1,249 @@
+// Copyright 2019 Google LLC
+//
+// 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 "driver/device_buffer_mapper.h"
+
+#include
+#include
+#include