1 /*
2  *  nextpnr -- Next Generation Place and Route
3  *
4  *  Copyright (C) 2018  David Shah <david@symbioticeda.com>
5  *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
6  *
7  *  Permission to use, copy, modify, and/or distribute this software for any
8  *  purpose with or without fee is hereby granted, provided that the above
9  *  copyright notice and this permission notice appear in all copies.
10  *
11  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18  *
19  */
20 
21 #ifndef NEXTPNR_H
22 #error Include "archdefs.h" via "nextpnr.h" only.
23 #endif
24 
25 #include <boost/functional/hash.hpp>
26 
27 NEXTPNR_NAMESPACE_BEGIN
28 
29 typedef int delay_t;
30 
31 struct DelayInfo
32 {
33     delay_t min_delay = 0, max_delay = 0;
34 
minRaiseDelayDelayInfo35     delay_t minRaiseDelay() const { return min_delay; }
maxRaiseDelayDelayInfo36     delay_t maxRaiseDelay() const { return max_delay; }
37 
minFallDelayDelayInfo38     delay_t minFallDelay() const { return min_delay; }
maxFallDelayDelayInfo39     delay_t maxFallDelay() const { return max_delay; }
40 
minDelayDelayInfo41     delay_t minDelay() const { return min_delay; }
maxDelayDelayInfo42     delay_t maxDelay() const { return max_delay; }
43 
44     DelayInfo operator+(const DelayInfo &other) const
45     {
46         DelayInfo ret;
47         ret.min_delay = this->min_delay + other.min_delay;
48         ret.max_delay = this->max_delay + other.max_delay;
49         return ret;
50     }
51 };
52 
53 // -----------------------------------------------------------------------
54 
55 // https://bugreports.qt.io/browse/QTBUG-80789
56 
57 #ifndef Q_MOC_RUN
58 enum ConstIds
59 {
60     ID_NONE
61 #define X(t) , ID_##t
62 #include "constids.inc"
63 #undef X
64     ,
65     DB_CONST_ID_COUNT
66 };
67 
68 #define X(t) static constexpr auto id_##t = IdString(ID_##t);
69 #include "constids.inc"
70 #undef X
71 #endif
72 
73 NPNR_PACKED_STRUCT(struct LocationPOD { int16_t x, y; });
74 
75 struct Location
76 {
77     int16_t x = -1, y = -1;
LocationLocation78     Location() : x(-1), y(-1){};
LocationLocation79     Location(int16_t x, int16_t y) : x(x), y(y){};
LocationLocation80     Location(const LocationPOD &pod) : x(pod.x), y(pod.y){};
LocationLocation81     Location(const Location &loc) : x(loc.x), y(loc.y){};
82 
83     bool operator==(const Location &other) const { return x == other.x && y == other.y; }
84     bool operator!=(const Location &other) const { return x != other.x || y != other.y; }
85     bool operator<(const Location &other) const { return y == other.y ? x < other.x : y < other.y; }
86 };
87 
88 inline Location operator+(const Location &a, const Location &b) { return Location(a.x + b.x, a.y + b.y); }
89 
90 struct BelId
91 {
92     Location location;
93     int32_t index = -1;
94 
95     bool operator==(const BelId &other) const { return index == other.index && location == other.location; }
96     bool operator!=(const BelId &other) const { return index != other.index || location != other.location; }
97     bool operator<(const BelId &other) const
98     {
99         return location == other.location ? index < other.index : location < other.location;
100     }
101 };
102 
103 struct WireId
104 {
105     Location location;
106     int32_t index = -1;
107 
108     bool operator==(const WireId &other) const { return index == other.index && location == other.location; }
109     bool operator!=(const WireId &other) const { return index != other.index || location != other.location; }
110     bool operator<(const WireId &other) const
111     {
112         return location == other.location ? index < other.index : location < other.location;
113     }
114 };
115 
116 struct PipId
117 {
118     Location location;
119     int32_t index = -1;
120 
121     bool operator==(const PipId &other) const { return index == other.index && location == other.location; }
122     bool operator!=(const PipId &other) const { return index != other.index || location != other.location; }
123     bool operator<(const PipId &other) const
124     {
125         return location == other.location ? index < other.index : location < other.location;
126     }
127 };
128 
129 struct GroupId
130 {
131     enum : int8_t
132     {
133         TYPE_NONE,
134         TYPE_SWITCHBOX
135     } type = TYPE_NONE;
136     Location location;
137 
138     bool operator==(const GroupId &other) const { return (type == other.type) && (location == other.location); }
139     bool operator!=(const GroupId &other) const { return (type != other.type) || (location != other.location); }
140 };
141 
142 struct DecalId
143 {
144     enum
145     {
146         TYPE_NONE,
147         TYPE_BEL,
148         TYPE_WIRE,
149         TYPE_PIP,
150         TYPE_GROUP
151     } type = TYPE_NONE;
152     Location location;
153     uint32_t z = 0;
154     bool active = false;
155     bool operator==(const DecalId &other) const
156     {
157         return type == other.type && location == other.location && z == other.z && active == other.active;
158     }
159     bool operator!=(const DecalId &other) const
160     {
161         return type != other.type || location != other.location || z != other.z || active != other.active;
162     }
163 };
164 
165 struct ArchNetInfo
166 {
167     bool is_global = false;
168 };
169 
170 struct ArchCellInfo
171 {
172     struct
173     {
174         bool using_dff;
175         bool has_l6mux;
176         bool is_carry;
177         IdString clk_sig, lsr_sig, clkmux, lsrmux, srmode;
178         int sd0, sd1;
179     } sliceInfo;
180     struct
181     {
182         bool is_pdp;
183         // Are the outputs from a DP16KD registered (OUTREG)
184         // or non-registered (NOREG)
185         bool is_output_a_registered;
186         bool is_output_b_registered;
187         // Which timing information to use for a DP16KD. Depends on registering
188         // configuration.
189         nextpnr_ecp5::IdString regmode_timing_id;
190     } ramInfo;
191     struct
192     {
193         bool is_clocked;
194         nextpnr_ecp5::IdString timing_id;
195     } multInfo;
196 };
197 
198 NEXTPNR_NAMESPACE_END
199 
200 namespace std {
201 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX Location>
202 {
203     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX Location &loc) const noexcept
204     {
205         std::size_t seed = std::hash<int>()(loc.x);
206         seed ^= std::hash<int>()(loc.y) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
207         return seed;
208     }
209 };
210 
211 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX BelId>
212 {
213     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX BelId &bel) const noexcept
214     {
215         std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(bel.location);
216         seed ^= std::hash<int>()(bel.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
217         return seed;
218     }
219 };
220 
221 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX WireId>
222 {
223     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX WireId &wire) const noexcept
224     {
225         std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(wire.location);
226         seed ^= std::hash<int>()(wire.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
227         return seed;
228     }
229 };
230 
231 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX PipId>
232 {
233     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX PipId &pip) const noexcept
234     {
235         std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX Location>()(pip.location);
236         seed ^= std::hash<int>()(pip.index) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
237         return seed;
238     }
239 };
240 
241 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX GroupId>
242 {
243     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX GroupId &group) const noexcept
244     {
245         std::size_t seed = 0;
246         boost::hash_combine(seed, hash<int>()(group.type));
247         boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(group.location));
248         return seed;
249     }
250 };
251 
252 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DecalId>
253 {
254     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DecalId &decal) const noexcept
255     {
256         std::size_t seed = 0;
257         boost::hash_combine(seed, hash<int>()(decal.type));
258         boost::hash_combine(seed, hash<NEXTPNR_NAMESPACE_PREFIX Location>()(decal.location));
259         boost::hash_combine(seed, hash<int>()(decal.z));
260         boost::hash_combine(seed, hash<bool>()(decal.active));
261         return seed;
262     }
263 };
264 
265 } // namespace std
266