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.h29
1 files changed, 26 insertions, 3 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h
index 7d3a8485c..eb7d7eaeb 100644
--- a/backends/cxxrtl/cxxrtl.h
+++ b/backends/cxxrtl/cxxrtl.h
@@ -110,9 +110,11 @@ struct value : public expr_base<value<Bits>> {
explicit constexpr value(Init ...init) : data{init...} {}
value(const value<Bits> &) = default;
- value(value<Bits> &&) = default;
value<Bits> &operator=(const value<Bits> &) = default;
+ value(value<Bits> &&) = default;
+ value<Bits> &operator=(value<Bits> &&) = default;
+
// A (no-op) helper that forces the cast to value<>.
CXXRTL_ALWAYS_INLINE
const value<Bits> &val() const {
@@ -661,10 +663,16 @@ struct wire {
template<typename... Init>
explicit constexpr wire(Init ...init) : curr{init...}, next{init...} {}
+ // Copying and copy-assigning values is natural. If, however, a value is replaced with a wire,
+ // e.g. because a module is built with a different optimization level, then existing code could
+ // unintentionally copy a wire instead, which would create a subtle but serious bug. To make sure
+ // this doesn't happen, prohibit copying and copy-assigning wires.
wire(const wire<Bits> &) = delete;
- wire(wire<Bits> &&) = default;
wire<Bits> &operator=(const wire<Bits> &) = delete;
+ wire(wire<Bits> &&) = default;
+ wire<Bits> &operator=(wire<Bits> &&) = default;
+
template<class IntegerT>
CXXRTL_ALWAYS_INLINE
IntegerT get() const {
@@ -706,6 +714,9 @@ struct memory {
memory(const memory<Width> &) = delete;
memory<Width> &operator=(const memory<Width> &) = delete;
+ memory(memory<Width> &&) = default;
+ memory<Width> &operator=(memory<Width> &&) = default;
+
// The only way to get the compiler to put the initializer in .rodata and do not copy it on stack is to stuff it
// into a plain array. You'd think an std::initializer_list would work here, but it doesn't, because you can't
// construct an initializer_list in a constexpr (or something) and so if you try to do that the whole thing is
@@ -829,7 +840,7 @@ struct metadata {
typedef std::map<std::string, metadata> metadata_map;
-// Helper class to disambiguate values/wires and their aliases.
+// Tag class to disambiguate values/wires and their aliases.
struct debug_alias {};
// This structure is intended for consumption via foreign function interfaces, like Python's ctypes.
@@ -979,13 +990,25 @@ struct debug_items {
}
};
+// Tag class to disambiguate module move constructor and module constructor that takes black boxes
+// out of another instance of the module.
+struct adopt {};
+
struct module {
module() {}
virtual ~module() {}
+ // Modules with black boxes cannot be copied. Although not all designs include black boxes,
+ // delete the copy constructor and copy assignment operator to make sure that any downstream
+ // code that manipulates modules doesn't accidentally depend on their availability.
module(const module &) = delete;
module &operator=(const module &) = delete;
+ module(module &&) = default;
+ module &operator=(module &&) = default;
+
+ virtual void reset() = 0;
+
virtual bool eval() = 0;
virtual bool commit() = 0;