|
6 | 6 | #include "vpr_types.h"
|
7 | 7 | #include "router_delay_profiling.h"
|
8 | 8 |
|
| 9 | +#ifndef __has_attribute |
| 10 | +# define __has_attribute(x) 0 // Compatibility with non-clang compilers. |
| 11 | +#endif |
| 12 | + |
| 13 | +#if defined(COMPILER_GCC) && defined(NDEBUG) |
| 14 | +# define ALWAYS_INLINE inline __attribute__((__always_inline__)) |
| 15 | +#elif defined(COMPILER_MSVC) && defined(NDEBUG) |
| 16 | +# define ALWAYS_INLINE __forceinline |
| 17 | +#elif __has_attribute(always_inline) |
| 18 | +# define ALWAYS_INLINE __attribute__((always_inline)) // clang |
| 19 | +#else |
| 20 | +# define ALWAYS_INLINE inline |
| 21 | +#endif |
| 22 | + |
9 | 23 | //Abstract interface to a placement delay model
|
10 | 24 | class PlaceDelayModel {
|
11 | 25 | public:
|
@@ -95,13 +109,29 @@ class OverrideDelayModel : public PlaceDelayModel {
|
95 | 109 | short delta_x;
|
96 | 110 | short delta_y;
|
97 | 111 |
|
98 |
| - friend bool operator<(const t_override& lhs, const t_override& rhs) { |
99 |
| - return std::tie(lhs.from_type, lhs.to_type, lhs.from_class, lhs.to_class, lhs.delta_x, lhs.delta_y) |
100 |
| - < std::tie(rhs.from_type, rhs.to_type, rhs.from_class, rhs.to_class, rhs.delta_x, rhs.delta_y); |
| 112 | + //A combination of ALWAYS_INLINE attribute and std::lexicographical_compare |
| 113 | + //is required for operator< to be inlined by compiler. |
| 114 | + //Proper inlining of the function reduces place time by around 5%. |
| 115 | + //For more information: https://github.com/verilog-to-routing/vtr-verilog-to-routing/issues/1225 |
| 116 | + friend ALWAYS_INLINE bool operator<(const t_override& lhs, const t_override& rhs) { |
| 117 | + const short* left = reinterpret_cast<const short*>(&lhs); |
| 118 | + const short* right = reinterpret_cast<const short*>(&rhs); |
| 119 | + constexpr size_t NUM_T_OVERRIDE_MEMBERS = sizeof(t_override) / sizeof(short); |
| 120 | + return std::lexicographical_compare(left, left + NUM_T_OVERRIDE_MEMBERS, right, right + NUM_T_OVERRIDE_MEMBERS); |
101 | 121 | }
|
102 | 122 | };
|
103 | 123 |
|
104 | 124 | vtr::flat_map2<t_override, float> delay_overrides_;
|
| 125 | + |
| 126 | + //operator< treats memory layout of t_override as an array of short |
| 127 | + //this requires all members of t_override are shorts and there is no padding between members of t_override |
| 128 | + static_assert(sizeof(t_override) == sizeof(t_override::from_type) + sizeof(t_override::to_type) + sizeof(t_override::from_class) + sizeof(t_override::to_class) + sizeof(t_override::delta_x) + sizeof(t_override::delta_y), "Expect t_override to have a memory layout equivalent to an array of short (no padding)"); |
| 129 | + static_assert(sizeof(t_override::from_type) == sizeof(short), "Expect all t_override data members to be shorts"); |
| 130 | + static_assert(sizeof(t_override::to_type) == sizeof(short), "Expect all t_override data members to be shorts"); |
| 131 | + static_assert(sizeof(t_override::from_class) == sizeof(short), "Expect all t_override data members to be shorts"); |
| 132 | + static_assert(sizeof(t_override::to_class) == sizeof(short), "Expect all t_override data members to be shorts"); |
| 133 | + static_assert(sizeof(t_override::delta_x) == sizeof(short), "Expect all t_override data members to be shorts"); |
| 134 | + static_assert(sizeof(t_override::delta_y) == sizeof(short), "Expect all t_override data members to be shorts"); |
105 | 135 | };
|
106 | 136 |
|
107 | 137 | #endif
|
0 commit comments