diff options
Diffstat (limited to 'backends/cxxrtl/cxxrtl.h')
-rw-r--r-- | backends/cxxrtl/cxxrtl.h | 58 |
1 files changed, 50 insertions, 8 deletions
diff --git a/backends/cxxrtl/cxxrtl.h b/backends/cxxrtl/cxxrtl.h index d850fdba4..3c315c7df 100644 --- a/backends/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/cxxrtl.h @@ -36,22 +36,34 @@ #include <map> #include <algorithm> #include <memory> +#include <functional> #include <sstream> #include <backends/cxxrtl/cxxrtl_capi.h> +#ifndef __has_attribute +# define __has_attribute(x) 0 +#endif + // CXXRTL essentially uses the C++ compiler as a hygienic macro engine that feeds an instruction selector. // It generates a lot of specialized template functions with relatively large bodies that, when inlined // into the caller and (for those with loops) unrolled, often expose many new optimization opportunities. // Because of this, most of the CXXRTL runtime must be always inlined for best performance. -#ifndef __has_attribute -# define __has_attribute(x) 0 -#endif #if __has_attribute(always_inline) #define CXXRTL_ALWAYS_INLINE inline __attribute__((__always_inline__)) #else #define CXXRTL_ALWAYS_INLINE inline #endif +// Conversely, some functions in the generated code are extremely large yet very cold, with both of these +// properties being extreme enough to confuse C++ compilers into spending pathological amounts of time +// on a futile (the code becomes worse) attempt to optimize the least important parts of code. +#if __has_attribute(optnone) +#define CXXRTL_EXTREMELY_COLD __attribute__((__optnone__)) +#elif __has_attribute(optimize) +#define CXXRTL_EXTREMELY_COLD __attribute__((__optimize__(0))) +#else +#define CXXRTL_EXTREMELY_COLD +#endif // CXXRTL uses assert() to check for C++ contract violations (which may result in e.g. undefined behavior // of the simulation code itself), and CXXRTL_ASSERT to check for RTL contract violations (which may at @@ -843,6 +855,9 @@ typedef std::map<std::string, metadata> metadata_map; // Tag class to disambiguate values/wires and their aliases. struct debug_alias {}; +// Tag declaration to disambiguate values and debug outlines. +using debug_outline = ::_cxxrtl_outline; + // 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++. // @@ -851,10 +866,11 @@ struct debug_alias {}; struct debug_item : ::cxxrtl_object { // Object types. enum : uint32_t { - VALUE = CXXRTL_VALUE, - WIRE = CXXRTL_WIRE, - MEMORY = CXXRTL_MEMORY, - ALIAS = CXXRTL_ALIAS, + VALUE = CXXRTL_VALUE, + WIRE = CXXRTL_WIRE, + MEMORY = CXXRTL_MEMORY, + ALIAS = CXXRTL_ALIAS, + OUTLINE = CXXRTL_OUTLINE, }; // Object flags. @@ -881,6 +897,7 @@ struct debug_item : ::cxxrtl_object { zero_at = 0; curr = item.data; next = item.data; + outline = nullptr; } template<size_t Bits> @@ -895,6 +912,7 @@ struct debug_item : ::cxxrtl_object { zero_at = 0; curr = const_cast<chunk_t*>(item.data); next = nullptr; + outline = nullptr; } template<size_t Bits> @@ -910,6 +928,7 @@ struct debug_item : ::cxxrtl_object { zero_at = 0; curr = item.curr.data; next = item.next.data; + outline = nullptr; } template<size_t Width> @@ -924,6 +943,7 @@ struct debug_item : ::cxxrtl_object { zero_at = zero_offset; curr = item.data.empty() ? nullptr : item.data[0].data; next = nullptr; + outline = nullptr; } template<size_t Bits> @@ -938,6 +958,7 @@ struct debug_item : ::cxxrtl_object { zero_at = 0; curr = const_cast<chunk_t*>(item.data); next = nullptr; + outline = nullptr; } template<size_t Bits> @@ -953,6 +974,22 @@ struct debug_item : ::cxxrtl_object { zero_at = 0; curr = const_cast<chunk_t*>(item.curr.data); next = nullptr; + outline = nullptr; + } + + template<size_t Bits> + debug_item(debug_outline &group, const value<Bits> &item, size_t lsb_offset = 0) { + static_assert(sizeof(item) == value<Bits>::chunks * sizeof(chunk_t), + "value<Bits> is not compatible with C layout"); + type = OUTLINE; + flags = DRIVEN_COMB; + width = Bits; + lsb_at = lsb_offset; + depth = 1; + zero_at = 0; + curr = const_cast<chunk_t*>(item.data); + next = nullptr; + outline = &group; } }; static_assert(std::is_standard_layout<debug_item>::value, "debug_item is not compatible with C layout"); @@ -1029,11 +1066,16 @@ struct module { } // namespace cxxrtl -// Internal structure used to communicate with the implementation of the C interface. +// Internal structures used to communicate with the implementation of the C interface. + typedef struct _cxxrtl_toplevel { std::unique_ptr<cxxrtl::module> module; } *cxxrtl_toplevel; +typedef struct _cxxrtl_outline { + std::function<void()> eval; +} *cxxrtl_outline; + // Definitions of internal Yosys cells. Other than the functions in this namespace, CXXRTL is fully generic // and indepenent of Yosys implementation details. // |