aboutsummaryrefslogtreecommitdiffstats
path: root/backends/cxxrtl/cxxrtl.h
diff options
context:
space:
mode:
Diffstat (limited to 'backends/cxxrtl/cxxrtl.h')
-rw-r--r--backends/cxxrtl/cxxrtl.h46
1 files changed, 45 insertions, 1 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index 7b91742e0..14613afb0 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -49,6 +49,8 @@ namespace cxxrtl {
// invisible to the compiler, (b) we often operate on non-power-of-2 values and have to clear the high bits anyway.
// Therefore, using relatively wide chunks and clearing the high bits explicitly and only when we know they may be
// clobbered results in simpler generated code.
+typedef uint32_t chunk_t;
+
template<typename T>
struct chunk_traits {
static_assert(std::is_integral<T>::value && std::is_unsigned<T>::value,
@@ -65,7 +67,7 @@ template<size_t Bits>
struct value : public expr_base<value<Bits>> {
static constexpr size_t bits = Bits;
- using chunk = chunk_traits<uint32_t>;
+ using chunk = chunk_traits<chunk_t>;
static constexpr chunk::type msb_mask = (Bits % chunk::bits == 0) ? chunk::mask
: chunk::mask >> (chunk::bits - (Bits % chunk::bits));
@@ -712,6 +714,46 @@ struct metadata {
typedef std::map<std::string, metadata> metadata_map;
+// This structure is intended for consumption via foreign function interfaces, like Python's ctypes.
+// Because of this it uses a C-style layout that is easy to parse rather than more idiomatic C++.
+struct debug_item {
+ enum : uint32_t {
+ VALUE = 0,
+ WIRE = 1,
+ MEMORY = 2,
+ } type;
+
+ size_t width; // in bits
+ size_t depth; // 1 if `type != MEMORY`
+ chunk_t *curr;
+ chunk_t *next; // nullptr if `type == VALUE || type == MEMORY`
+
+ template<size_t Bits>
+ debug_item(value<Bits> &item) : type(VALUE), width(Bits), depth(1),
+ curr(item.data), next(nullptr) {
+ static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t),
+ "value<Bits> is not compatible with C layout");
+ }
+
+ template<size_t Bits>
+ debug_item(wire<Bits> &item) : type(WIRE), width(Bits), depth(1),
+ curr(item.curr.data), next(item.next.data) {
+ static_assert(sizeof(item.curr) == value<Bits>::chunks * sizeof(chunk_t) &&
+ sizeof(item.next) == value<Bits>::chunks * sizeof(chunk_t),
+ "wire<Bits> is not compatible with C layout");
+ }
+
+ template<size_t Width>
+ debug_item(memory<Width> &item) : type(MEMORY), width(Width), depth(item.data.size()),
+ curr(item.data.empty() ? nullptr : item.data[0].data), next(nullptr) {
+ static_assert(sizeof(item.data[0]) == value<Width>::chunks * sizeof(chunk_t),
+ "memory<Width> is not compatible with C layout");
+ }
+};
+static_assert(std::is_standard_layout<debug_item>::value, "debug_item is not compatible with C layout");
+
+typedef std::map<std::string, debug_item> debug_items;
+
struct module {
module() {}
virtual ~module() {}
@@ -731,6 +773,8 @@ struct module {
} while (commit() && !converged);
return deltas;
}
+
+ virtual void debug_info(debug_items &items, std::string path = "") {}
};
} // namespace cxxrtl