1 /*
2  *  nextpnr -- Next Generation Place and Route
3  *
4  *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
5  *
6  *  Permission to use, copy, modify, and/or distribute this software for any
7  *  purpose with or without fee is hereby granted, provided that the above
8  *  copyright notice and this permission notice appear in all copies.
9  *
10  *  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  *  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  *  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  *  ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  *  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  *  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  *  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17  *
18  */
19 
20 #ifndef NEXTPNR_H
21 #error Include "arch.h" via "nextpnr.h" only.
22 #endif
23 
24 NEXTPNR_NAMESPACE_BEGIN
25 
26 /**** Everything in this section must be kept in sync with chipdb.py ****/
27 
28 template <typename T> struct RelPtr
29 {
30     int32_t offset;
31 
32     // void set(const T *ptr) {
33     //     offset = reinterpret_cast<const char*>(ptr) -
34     //              reinterpret_cast<const char*>(this);
35     // }
36 
getRelPtr37     const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); }
38 
39     const T &operator[](size_t index) const { return get()[index]; }
40 
41     const T &operator*() const { return *(get()); }
42 
43     const T *operator->() const { return get(); }
44 };
45 
46 NPNR_PACKED_STRUCT(struct BelWirePOD {
47     int32_t port;
48     int32_t type;
49     int32_t wire_index;
50 });
51 
52 NPNR_PACKED_STRUCT(struct BelInfoPOD {
53     RelPtr<char> name;
54     int32_t type;
55     int32_t num_bel_wires;
56     RelPtr<BelWirePOD> bel_wires;
57     int8_t x, y, z;
58     int8_t padding_0;
59 });
60 
61 NPNR_PACKED_STRUCT(struct BelPortPOD {
62     int32_t bel_index;
63     int32_t port;
64 });
65 
66 NPNR_PACKED_STRUCT(struct PipInfoPOD {
67     enum PipFlags : uint32_t
68     {
69         FLAG_NONE = 0,
70         FLAG_ROUTETHRU = 1,
71         FLAG_NOCARRY = 2
72     };
73 
74     // RelPtr<char> name;
75     int32_t src, dst;
76     int32_t fast_delay;
77     int32_t slow_delay;
78     int8_t x, y;
79     int16_t src_seg, dst_seg;
80     int16_t switch_mask;
81     int32_t switch_index;
82     PipFlags flags;
83 });
84 
85 NPNR_PACKED_STRUCT(struct WireSegmentPOD {
86     int8_t x, y;
87     int16_t index;
88 });
89 
90 NPNR_PACKED_STRUCT(struct WireInfoPOD {
91     enum WireType : int8_t
92     {
93         WIRE_TYPE_NONE = 0,
94         WIRE_TYPE_GLB2LOCAL = 1,
95         WIRE_TYPE_GLB_NETWK = 2,
96         WIRE_TYPE_LOCAL = 3,
97         WIRE_TYPE_LUTFF_IN = 4,
98         WIRE_TYPE_LUTFF_IN_LUT = 5,
99         WIRE_TYPE_LUTFF_LOUT = 6,
100         WIRE_TYPE_LUTFF_OUT = 7,
101         WIRE_TYPE_LUTFF_COUT = 8,
102         WIRE_TYPE_LUTFF_GLOBAL = 9,
103         WIRE_TYPE_CARRY_IN_MUX = 10,
104         WIRE_TYPE_SP4_V = 11,
105         WIRE_TYPE_SP4_H = 12,
106         WIRE_TYPE_SP12_V = 13,
107         WIRE_TYPE_SP12_H = 14
108     };
109 
110     RelPtr<char> name;
111     int32_t num_uphill, num_downhill;
112     RelPtr<int32_t> pips_uphill, pips_downhill;
113 
114     int32_t num_bel_pins;
115     RelPtr<BelPortPOD> bel_pins;
116 
117     int32_t num_segments;
118     RelPtr<WireSegmentPOD> segments;
119 
120     int32_t fast_delay;
121     int32_t slow_delay;
122 
123     int8_t x, y, z;
124     WireType type;
125 });
126 
127 NPNR_PACKED_STRUCT(struct PackagePinPOD {
128     RelPtr<char> name;
129     int32_t bel_index;
130 });
131 
132 NPNR_PACKED_STRUCT(struct PackageInfoPOD {
133     RelPtr<char> name;
134     int32_t num_pins;
135     RelPtr<PackagePinPOD> pins;
136 });
137 
138 enum TileType : uint32_t
139 {
140     TILE_NONE = 0,
141     TILE_LOGIC = 1,
142     TILE_IO = 2,
143     TILE_RAMB = 3,
144     TILE_RAMT = 4,
145     TILE_DSP0 = 5,
146     TILE_DSP1 = 6,
147     TILE_DSP2 = 7,
148     TILE_DSP3 = 8,
149     TILE_IPCON = 9
150 };
151 
152 NPNR_PACKED_STRUCT(struct ConfigBitPOD { int8_t row, col; });
153 
154 NPNR_PACKED_STRUCT(struct ConfigEntryPOD {
155     RelPtr<char> name;
156     int32_t num_bits;
157     RelPtr<ConfigBitPOD> bits;
158 });
159 
160 NPNR_PACKED_STRUCT(struct TileInfoPOD {
161     int8_t cols, rows;
162     int16_t num_config_entries;
163     RelPtr<ConfigEntryPOD> entries;
164 });
165 
166 static const int max_switch_bits = 5;
167 
168 NPNR_PACKED_STRUCT(struct SwitchInfoPOD {
169     int32_t num_bits;
170     int32_t bel;
171     int8_t x, y;
172     ConfigBitPOD cbits[max_switch_bits];
173 });
174 
175 NPNR_PACKED_STRUCT(struct IerenInfoPOD {
176     int8_t iox, ioy, ioz;
177     int8_t ierx, iery, ierz;
178 });
179 
180 NPNR_PACKED_STRUCT(struct BitstreamInfoPOD {
181     int32_t num_switches, num_ierens;
182     RelPtr<TileInfoPOD> tiles_nonrouting;
183     RelPtr<SwitchInfoPOD> switches;
184     RelPtr<IerenInfoPOD> ierens;
185 });
186 
187 NPNR_PACKED_STRUCT(struct BelConfigEntryPOD {
188     RelPtr<char> entry_name;
189     RelPtr<char> cbit_name;
190     int8_t x, y;
191     int16_t padding;
192 });
193 
194 // Stores mapping between bel parameters and config bits,
195 // for extra cells where this mapping is non-trivial
196 NPNR_PACKED_STRUCT(struct BelConfigPOD {
197     int32_t bel_index;
198     int32_t num_entries;
199     RelPtr<BelConfigEntryPOD> entries;
200 });
201 
202 NPNR_PACKED_STRUCT(struct CellPathDelayPOD {
203     int32_t from_port;
204     int32_t to_port;
205     int32_t fast_delay;
206     int32_t slow_delay;
207 });
208 
209 NPNR_PACKED_STRUCT(struct CellTimingPOD {
210     int32_t type;
211     int32_t num_paths;
212     RelPtr<CellPathDelayPOD> path_delays;
213 });
214 
215 NPNR_PACKED_STRUCT(struct GlobalNetworkInfoPOD {
216     uint8_t gb_x;
217     uint8_t gb_y;
218 
219     uint8_t pi_gb_x;
220     uint8_t pi_gb_y;
221     uint8_t pi_gb_pio;
222 
223     uint8_t pi_eb_bank;
224     uint16_t pi_eb_x;
225     uint16_t pi_eb_y;
226 
227     uint16_t pad;
228 });
229 
230 NPNR_PACKED_STRUCT(struct ChipInfoPOD {
231     int32_t width, height;
232     int32_t num_bels, num_wires, num_pips;
233     int32_t num_switches, num_belcfgs, num_packages;
234     int32_t num_timing_cells, num_global_networks;
235     RelPtr<BelInfoPOD> bel_data;
236     RelPtr<WireInfoPOD> wire_data;
237     RelPtr<PipInfoPOD> pip_data;
238     RelPtr<TileType> tile_grid;
239     RelPtr<BitstreamInfoPOD> bits_info;
240     RelPtr<BelConfigPOD> bel_config;
241     RelPtr<PackageInfoPOD> packages_data;
242     RelPtr<CellTimingPOD> cell_timing;
243     RelPtr<GlobalNetworkInfoPOD> global_network_info;
244     RelPtr<RelPtr<char>> tile_wire_names;
245 });
246 
247 /************************ End of chipdb section. ************************/
248 
249 struct BelIterator
250 {
251     int cursor;
252 
253     BelIterator operator++()
254     {
255         cursor++;
256         return *this;
257     }
258     BelIterator operator++(int)
259     {
260         BelIterator prior(*this);
261         cursor++;
262         return prior;
263     }
264 
265     bool operator!=(const BelIterator &other) const { return cursor != other.cursor; }
266 
267     bool operator==(const BelIterator &other) const { return cursor == other.cursor; }
268 
269     BelId operator*() const
270     {
271         BelId ret;
272         ret.index = cursor;
273         return ret;
274     }
275 };
276 
277 struct BelRange
278 {
279     BelIterator b, e;
beginBelRange280     BelIterator begin() const { return b; }
endBelRange281     BelIterator end() const { return e; }
282 };
283 
284 // -----------------------------------------------------------------------
285 
286 struct BelPinIterator
287 {
288     const BelPortPOD *ptr = nullptr;
289 
290     void operator++() { ptr++; }
291     bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
292 
293     BelPin operator*() const
294     {
295         BelPin ret;
296         ret.bel.index = ptr->bel_index;
297         ret.pin = ptr->port;
298         return ret;
299     }
300 };
301 
302 struct BelPinRange
303 {
304     BelPinIterator b, e;
beginBelPinRange305     BelPinIterator begin() const { return b; }
endBelPinRange306     BelPinIterator end() const { return e; }
307 };
308 
309 // -----------------------------------------------------------------------
310 
311 struct WireIterator
312 {
313     int cursor = -1;
314 
315     void operator++() { cursor++; }
316     bool operator!=(const WireIterator &other) const { return cursor != other.cursor; }
317 
318     WireId operator*() const
319     {
320         WireId ret;
321         ret.index = cursor;
322         return ret;
323     }
324 };
325 
326 struct WireRange
327 {
328     WireIterator b, e;
beginWireRange329     WireIterator begin() const { return b; }
endWireRange330     WireIterator end() const { return e; }
331 };
332 
333 // -----------------------------------------------------------------------
334 
335 struct AllPipIterator
336 {
337     int cursor = -1;
338 
339     void operator++() { cursor++; }
340     bool operator!=(const AllPipIterator &other) const { return cursor != other.cursor; }
341 
342     PipId operator*() const
343     {
344         PipId ret;
345         ret.index = cursor;
346         return ret;
347     }
348 };
349 
350 struct AllPipRange
351 {
352     AllPipIterator b, e;
beginAllPipRange353     AllPipIterator begin() const { return b; }
endAllPipRange354     AllPipIterator end() const { return e; }
355 };
356 
357 // -----------------------------------------------------------------------
358 
359 struct PipIterator
360 {
361     const int *cursor = nullptr;
362 
363     void operator++() { cursor++; }
364     bool operator!=(const PipIterator &other) const { return cursor != other.cursor; }
365 
366     PipId operator*() const
367     {
368         PipId ret;
369         ret.index = *cursor;
370         return ret;
371     }
372 };
373 
374 struct PipRange
375 {
376     PipIterator b, e;
beginPipRange377     PipIterator begin() const { return b; }
endPipRange378     PipIterator end() const { return e; }
379 };
380 
381 struct ArchArgs
382 {
383     enum ArchArgsTypes
384     {
385         NONE,
386         LP384,
387         LP1K,
388         LP4K,
389         LP8K,
390         HX1K,
391         HX4K,
392         HX8K,
393         UP3K,
394         UP5K,
395         U1K,
396         U2K,
397         U4K
398     } type = NONE;
399     std::string package;
400 };
401 
402 struct Arch : BaseCtx
403 {
404     bool fast_part;
405     const ChipInfoPOD *chip_info;
406     const PackageInfoPOD *package_info;
407 
408     mutable std::unordered_map<IdString, int> bel_by_name;
409     mutable std::unordered_map<IdString, int> wire_by_name;
410     mutable std::unordered_map<IdString, int> pip_by_name;
411     mutable std::unordered_map<Loc, int> bel_by_loc;
412 
413     std::vector<bool> bel_carry;
414     std::vector<CellInfo *> bel_to_cell;
415     std::vector<NetInfo *> wire_to_net;
416     std::vector<NetInfo *> pip_to_net;
417     std::vector<WireId> switches_locked;
418 
419     ArchArgs args;
420     Arch(ArchArgs args);
421 
422     static bool isAvailable(ArchArgs::ArchArgsTypes chip);
423     static std::vector<std::string> getSupportedPackages(ArchArgs::ArchArgsTypes chip);
424 
425     std::string getChipName() const;
426 
archIdArch427     IdString archId() const { return id("ice40"); }
archArgsArch428     ArchArgs archArgs() const { return args; }
429     IdString archArgsToId(ArchArgs args) const;
430 
431     // -------------------------------------------------
432 
getGridDimXArch433     int getGridDimX() const { return chip_info->width; }
getGridDimYArch434     int getGridDimY() const { return chip_info->height; }
getTileBelDimZArch435     int getTileBelDimZ(int, int) const { return 8; }
getTilePipDimZArch436     int getTilePipDimZ(int, int) const { return 1; }
437 
438     // -------------------------------------------------
439 
440     BelId getBelByName(IdString name) const;
441 
getBelNameArch442     IdString getBelName(BelId bel) const
443     {
444         NPNR_ASSERT(bel != BelId());
445         return id(chip_info->bel_data[bel.index].name.get());
446     }
447 
getBelChecksumArch448     uint32_t getBelChecksum(BelId bel) const { return bel.index; }
449 
bindBelArch450     void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
451     {
452         NPNR_ASSERT(bel != BelId());
453         NPNR_ASSERT(bel_to_cell[bel.index] == nullptr);
454 
455         bel_to_cell[bel.index] = cell;
456         bel_carry[bel.index] = (cell->type == id_ICESTORM_LC && cell->lcInfo.carryEnable);
457         cell->bel = bel;
458         cell->belStrength = strength;
459         refreshUiBel(bel);
460     }
461 
unbindBelArch462     void unbindBel(BelId bel)
463     {
464         NPNR_ASSERT(bel != BelId());
465         NPNR_ASSERT(bel_to_cell[bel.index] != nullptr);
466         bel_to_cell[bel.index]->bel = BelId();
467         bel_to_cell[bel.index]->belStrength = STRENGTH_NONE;
468         bel_to_cell[bel.index] = nullptr;
469         bel_carry[bel.index] = false;
470         refreshUiBel(bel);
471     }
472 
checkBelAvailArch473     bool checkBelAvail(BelId bel) const
474     {
475         NPNR_ASSERT(bel != BelId());
476         return bel_to_cell[bel.index] == nullptr;
477     }
478 
getBoundBelCellArch479     CellInfo *getBoundBelCell(BelId bel) const
480     {
481         NPNR_ASSERT(bel != BelId());
482         return bel_to_cell[bel.index];
483     }
484 
getConflictingBelCellArch485     CellInfo *getConflictingBelCell(BelId bel) const
486     {
487         NPNR_ASSERT(bel != BelId());
488         return bel_to_cell[bel.index];
489     }
490 
getBelsArch491     BelRange getBels() const
492     {
493         BelRange range;
494         range.b.cursor = 0;
495         range.e.cursor = chip_info->num_bels;
496         return range;
497     }
498 
getBelLocationArch499     Loc getBelLocation(BelId bel) const
500     {
501         NPNR_ASSERT(bel != BelId());
502         Loc loc;
503         loc.x = chip_info->bel_data[bel.index].x;
504         loc.y = chip_info->bel_data[bel.index].y;
505         loc.z = chip_info->bel_data[bel.index].z;
506         return loc;
507     }
508 
509     BelId getBelByLocation(Loc loc) const;
510     BelRange getBelsByTile(int x, int y) const;
511 
getBelGlobalBufArch512     bool getBelGlobalBuf(BelId bel) const { return chip_info->bel_data[bel.index].type == ID_SB_GB; }
513 
getBelTypeArch514     IdString getBelType(BelId bel) const
515     {
516         NPNR_ASSERT(bel != BelId());
517         return IdString(chip_info->bel_data[bel.index].type);
518     }
519 
520     std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId bel) const;
521 
522     WireId getBelPinWire(BelId bel, IdString pin) const;
523     PortType getBelPinType(BelId bel, IdString pin) const;
524     std::vector<IdString> getBelPins(BelId bel) const;
525 
526     bool isBelLocked(BelId bel) const;
527 
528     // -------------------------------------------------
529 
530     WireId getWireByName(IdString name) const;
531 
getWireNameArch532     IdString getWireName(WireId wire) const
533     {
534         NPNR_ASSERT(wire != WireId());
535         return id(chip_info->wire_data[wire.index].name.get());
536     }
537 
538     IdString getWireType(WireId wire) const;
539     std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId wire) const;
540 
getWireChecksumArch541     uint32_t getWireChecksum(WireId wire) const { return wire.index; }
542 
bindWireArch543     void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
544     {
545         NPNR_ASSERT(wire != WireId());
546         NPNR_ASSERT(wire_to_net[wire.index] == nullptr);
547         wire_to_net[wire.index] = net;
548         net->wires[wire].pip = PipId();
549         net->wires[wire].strength = strength;
550         refreshUiWire(wire);
551     }
552 
unbindWireArch553     void unbindWire(WireId wire)
554     {
555         NPNR_ASSERT(wire != WireId());
556         NPNR_ASSERT(wire_to_net[wire.index] != nullptr);
557 
558         auto &net_wires = wire_to_net[wire.index]->wires;
559         auto it = net_wires.find(wire);
560         NPNR_ASSERT(it != net_wires.end());
561 
562         auto pip = it->second.pip;
563         if (pip != PipId()) {
564             pip_to_net[pip.index] = nullptr;
565             switches_locked[chip_info->pip_data[pip.index].switch_index] = WireId();
566         }
567 
568         net_wires.erase(it);
569         wire_to_net[wire.index] = nullptr;
570         refreshUiWire(wire);
571     }
572 
checkWireAvailArch573     bool checkWireAvail(WireId wire) const
574     {
575         NPNR_ASSERT(wire != WireId());
576         return wire_to_net[wire.index] == nullptr;
577     }
578 
getBoundWireNetArch579     NetInfo *getBoundWireNet(WireId wire) const
580     {
581         NPNR_ASSERT(wire != WireId());
582         return wire_to_net[wire.index];
583     }
584 
getConflictingWireWireArch585     WireId getConflictingWireWire(WireId wire) const { return wire; }
586 
getConflictingWireNetArch587     NetInfo *getConflictingWireNet(WireId wire) const
588     {
589         NPNR_ASSERT(wire != WireId());
590         return wire_to_net[wire.index];
591     }
592 
getWireDelayArch593     DelayInfo getWireDelay(WireId wire) const
594     {
595         DelayInfo delay;
596         NPNR_ASSERT(wire != WireId());
597         if (fast_part)
598             delay.delay = chip_info->wire_data[wire.index].fast_delay;
599         else
600             delay.delay = chip_info->wire_data[wire.index].slow_delay;
601         return delay;
602     }
603 
getWireBelPinsArch604     BelPinRange getWireBelPins(WireId wire) const
605     {
606         BelPinRange range;
607         NPNR_ASSERT(wire != WireId());
608         range.b.ptr = chip_info->wire_data[wire.index].bel_pins.get();
609         range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bel_pins;
610         return range;
611     }
612 
getWiresArch613     WireRange getWires() const
614     {
615         WireRange range;
616         range.b.cursor = 0;
617         range.e.cursor = chip_info->num_wires;
618         return range;
619     }
620 
621     // -------------------------------------------------
622 
623     PipId getPipByName(IdString name) const;
624 
bindPipArch625     void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
626     {
627         NPNR_ASSERT(pip != PipId());
628         NPNR_ASSERT(pip_to_net[pip.index] == nullptr);
629         NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == WireId());
630 
631         WireId dst;
632         dst.index = chip_info->pip_data[pip.index].dst;
633         NPNR_ASSERT(wire_to_net[dst.index] == nullptr);
634 
635         pip_to_net[pip.index] = net;
636         switches_locked[chip_info->pip_data[pip.index].switch_index] = dst;
637 
638         wire_to_net[dst.index] = net;
639         net->wires[dst].pip = pip;
640         net->wires[dst].strength = strength;
641         refreshUiPip(pip);
642         refreshUiWire(dst);
643     }
644 
unbindPipArch645     void unbindPip(PipId pip)
646     {
647         NPNR_ASSERT(pip != PipId());
648         NPNR_ASSERT(pip_to_net[pip.index] != nullptr);
649         NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != WireId());
650 
651         WireId dst;
652         dst.index = chip_info->pip_data[pip.index].dst;
653         NPNR_ASSERT(wire_to_net[dst.index] != nullptr);
654         wire_to_net[dst.index] = nullptr;
655         pip_to_net[pip.index]->wires.erase(dst);
656 
657         pip_to_net[pip.index] = nullptr;
658         switches_locked[chip_info->pip_data[pip.index].switch_index] = WireId();
659         refreshUiPip(pip);
660         refreshUiWire(dst);
661     }
662 
ice40_pip_hard_unavailArch663     bool ice40_pip_hard_unavail(PipId pip) const
664     {
665         NPNR_ASSERT(pip != PipId());
666         auto &pi = chip_info->pip_data[pip.index];
667         auto &si = chip_info->bits_info->switches[pi.switch_index];
668 
669         if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
670             NPNR_ASSERT(si.bel >= 0);
671             if (bel_to_cell[si.bel] != nullptr)
672                 return true;
673         }
674 
675         if (pi.flags & PipInfoPOD::FLAG_NOCARRY) {
676             NPNR_ASSERT(si.bel >= 0);
677             if (bel_carry[si.bel])
678                 return true;
679         }
680 
681         return false;
682     }
683 
checkPipAvailArch684     bool checkPipAvail(PipId pip) const
685     {
686         if (ice40_pip_hard_unavail(pip))
687             return false;
688 
689         auto &pi = chip_info->pip_data[pip.index];
690         return switches_locked[pi.switch_index] == WireId();
691     }
692 
getBoundPipNetArch693     NetInfo *getBoundPipNet(PipId pip) const
694     {
695         NPNR_ASSERT(pip != PipId());
696         return pip_to_net[pip.index];
697     }
698 
getConflictingPipWireArch699     WireId getConflictingPipWire(PipId pip) const
700     {
701         if (ice40_pip_hard_unavail(pip))
702             return WireId();
703 
704         return switches_locked[chip_info->pip_data[pip.index].switch_index];
705     }
706 
getConflictingPipNetArch707     NetInfo *getConflictingPipNet(PipId pip) const
708     {
709         if (ice40_pip_hard_unavail(pip))
710             return nullptr;
711 
712         WireId wire = switches_locked[chip_info->pip_data[pip.index].switch_index];
713         return wire == WireId() ? nullptr : wire_to_net[wire.index];
714     }
715 
getPipsArch716     AllPipRange getPips() const
717     {
718         AllPipRange range;
719         range.b.cursor = 0;
720         range.e.cursor = chip_info->num_pips;
721         return range;
722     }
723 
getPipLocationArch724     Loc getPipLocation(PipId pip) const
725     {
726         Loc loc;
727         loc.x = chip_info->pip_data[pip.index].x;
728         loc.y = chip_info->pip_data[pip.index].y;
729         loc.z = 0;
730         return loc;
731     }
732 
733     IdString getPipName(PipId pip) const;
734 
735     IdString getPipType(PipId pip) const;
736     std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
737 
getPipChecksumArch738     uint32_t getPipChecksum(PipId pip) const { return pip.index; }
739 
getPipSrcWireArch740     WireId getPipSrcWire(PipId pip) const
741     {
742         WireId wire;
743         NPNR_ASSERT(pip != PipId());
744         wire.index = chip_info->pip_data[pip.index].src;
745         return wire;
746     }
747 
getPipDstWireArch748     WireId getPipDstWire(PipId pip) const
749     {
750         WireId wire;
751         NPNR_ASSERT(pip != PipId());
752         wire.index = chip_info->pip_data[pip.index].dst;
753         return wire;
754     }
755 
getPipDelayArch756     DelayInfo getPipDelay(PipId pip) const
757     {
758         DelayInfo delay;
759         NPNR_ASSERT(pip != PipId());
760         if (fast_part)
761             delay.delay = chip_info->pip_data[pip.index].fast_delay;
762         else
763             delay.delay = chip_info->pip_data[pip.index].slow_delay;
764         return delay;
765     }
766 
getPipsDownhillArch767     PipRange getPipsDownhill(WireId wire) const
768     {
769         PipRange range;
770         NPNR_ASSERT(wire != WireId());
771         range.b.cursor = chip_info->wire_data[wire.index].pips_downhill.get();
772         range.e.cursor = range.b.cursor + chip_info->wire_data[wire.index].num_downhill;
773         return range;
774     }
775 
getPipsUphillArch776     PipRange getPipsUphill(WireId wire) const
777     {
778         PipRange range;
779         NPNR_ASSERT(wire != WireId());
780         range.b.cursor = chip_info->wire_data[wire.index].pips_uphill.get();
781         range.e.cursor = range.b.cursor + chip_info->wire_data[wire.index].num_uphill;
782         return range;
783     }
784 
getWireAliasesArch785     PipRange getWireAliases(WireId wire) const
786     {
787         PipRange range;
788         NPNR_ASSERT(wire != WireId());
789         range.b.cursor = nullptr;
790         range.e.cursor = nullptr;
791         return range;
792     }
793 
794     BelId getPackagePinBel(const std::string &pin) const;
795     std::string getBelPackagePin(BelId bel) const;
796 
797     // -------------------------------------------------
798 
799     GroupId getGroupByName(IdString name) const;
800     IdString getGroupName(GroupId group) const;
801     std::vector<GroupId> getGroups() const;
802     std::vector<BelId> getGroupBels(GroupId group) const;
803     std::vector<WireId> getGroupWires(GroupId group) const;
804     std::vector<PipId> getGroupPips(GroupId group) const;
805     std::vector<GroupId> getGroupGroups(GroupId group) const;
806 
807     // -------------------------------------------------
808 
809     delay_t estimateDelay(WireId src, WireId dst) const;
810     delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
getDelayEpsilonArch811     delay_t getDelayEpsilon() const { return 20; }
getRipupDelayPenaltyArch812     delay_t getRipupDelayPenalty() const { return 200; }
getDelayNSArch813     float getDelayNS(delay_t v) const { return v * 0.001; }
getDelayFromNSArch814     DelayInfo getDelayFromNS(float ns) const
815     {
816         DelayInfo del;
817         del.delay = delay_t(ns * 1000);
818         return del;
819     }
getDelayChecksumArch820     uint32_t getDelayChecksum(delay_t v) const { return v; }
821     bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
822 
823     ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
824 
825     // -------------------------------------------------
826 
827     bool pack();
828     bool place();
829     bool route();
830 
831     // -------------------------------------------------
832 
833     std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
834 
835     DecalXY getBelDecal(BelId bel) const;
836     DecalXY getWireDecal(WireId wire) const;
837     DecalXY getPipDecal(PipId pip) const;
838     DecalXY getGroupDecal(GroupId group) const;
839 
840     // -------------------------------------------------
841 
842     // Get the delay through a cell from one port to another, returning false
843     // if no path exists. This only considers combinational delays, as required by the Arch API
844     bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
845     // getCellDelayInternal is similar to the above, but without false path checks and including clock to out delays
846     // for internal arch use only
847     bool getCellDelayInternal(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
848     // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
849     TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
850     // Get the TimingClockingInfo of a port
851     TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
852     // Return true if a port is a net
853     bool isGlobalNet(const NetInfo *net) const;
854 
855     // -------------------------------------------------
856 
857     // Perform placement validity checks, returning false on failure (all
858     // implemented in arch_place.cc)
859 
860     // Whether or not a given cell can be placed at a given Bel
861     // This is not intended for Bel type checks, but finer-grained constraints
862     // such as conflicting set/reset signals, etc
863     bool isValidBelForCell(CellInfo *cell, BelId bel) const;
864 
865     // Return true whether all Bels at a given location are valid
866     bool isBelLocationValid(BelId bel) const;
867 
868     // Helper function for above
869     bool logicCellsCompatible(const CellInfo **it, const size_t size) const;
870 
871     // -------------------------------------------------
872     // Assign architecure-specific arguments to nets and cells, which must be
873     // called between packing or further
874     // netlist modifications, and validity checks
875     void assignArchInfo();
876     void assignCellInfo(CellInfo *cell);
877 
878     // -------------------------------------------------
getIOBSharingPLLPinArch879     BelPin getIOBSharingPLLPin(BelId pll, IdString pll_pin) const
880     {
881         auto wire = getBelPinWire(pll, pll_pin);
882         for (auto src_bel : getWireBelPins(wire)) {
883             if (getBelType(src_bel.bel) == id_SB_IO && src_bel.pin == id_D_IN_0) {
884                 return src_bel;
885             }
886         }
887         NPNR_ASSERT_FALSE("Expected PLL pin to share an output with an SB_IO D_IN_{0,1}");
888     }
889 
getDrivenGlobalNetworkArch890     int getDrivenGlobalNetwork(BelId bel) const
891     {
892         NPNR_ASSERT(getBelType(bel) == id_SB_GB);
893         IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT));
894         return std::stoi(std::string("") + glb_net.str(this).back());
895     }
896 
897     static const std::string defaultPlacer;
898     static const std::vector<std::string> availablePlacers;
899     static const std::string defaultRouter;
900     static const std::vector<std::string> availableRouters;
901 };
902 
903 void ice40DelayFuzzerMain(Context *ctx);
904 
905 NEXTPNR_NAMESPACE_END
906