1 /*
2  *  nextpnr -- Next Generation Place and Route
3  *
4  *  Copyright (C) 2018  Clifford Wolf <clifford@symbioticeda.com>
5  *  Copyright (C) 2018  David Shah <david@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 "arch.h" via "nextpnr.h" only.
23 #endif
24 
25 #include <set>
26 #include <sstream>
27 
28 NEXTPNR_NAMESPACE_BEGIN
29 
30 /**** Everything in this section must be kept in sync with chipdb.py ****/
31 
32 template <typename T> struct RelPtr
33 {
34     int32_t offset;
35 
36     // void set(const T *ptr) {
37     //     offset = reinterpret_cast<const char*>(ptr) -
38     //              reinterpret_cast<const char*>(this);
39     // }
40 
getRelPtr41     const T *get() const { return reinterpret_cast<const T *>(reinterpret_cast<const char *>(this) + offset); }
42 
43     const T &operator[](size_t index) const { return get()[index]; }
44 
45     const T &operator*() const { return *(get()); }
46 
47     const T *operator->() const { return get(); }
48 };
49 
50 NPNR_PACKED_STRUCT(struct BelWirePOD {
51     LocationPOD rel_wire_loc;
52     int32_t wire_index;
53     int32_t port;
54     int32_t type;
55 });
56 
57 NPNR_PACKED_STRUCT(struct BelInfoPOD {
58     RelPtr<char> name;
59     int32_t type;
60     int32_t z;
61     int32_t num_bel_wires;
62     RelPtr<BelWirePOD> bel_wires;
63 });
64 
65 NPNR_PACKED_STRUCT(struct BelPortPOD {
66     LocationPOD rel_bel_loc;
67     int32_t bel_index;
68     int32_t port;
69 });
70 
71 NPNR_PACKED_STRUCT(struct PipInfoPOD {
72     LocationPOD rel_src_loc, rel_dst_loc;
73     int32_t src_idx, dst_idx;
74     int32_t timing_class;
75     int16_t tile_type;
76     int8_t pip_type;
77     int8_t padding_0;
78 });
79 
80 NPNR_PACKED_STRUCT(struct PipLocatorPOD {
81     LocationPOD rel_loc;
82     int32_t index;
83 });
84 
85 NPNR_PACKED_STRUCT(struct WireInfoPOD {
86     RelPtr<char> name;
87     int32_t type;
88     int32_t tile_wire;
89     int32_t num_uphill, num_downhill;
90     RelPtr<PipLocatorPOD> pips_uphill, pips_downhill;
91 
92     int32_t num_bel_pins;
93     RelPtr<BelPortPOD> bel_pins;
94 });
95 
96 NPNR_PACKED_STRUCT(struct LocationTypePOD {
97     int32_t num_bels, num_wires, num_pips;
98     RelPtr<BelInfoPOD> bel_data;
99     RelPtr<WireInfoPOD> wire_data;
100     RelPtr<PipInfoPOD> pip_data;
101 });
102 
103 NPNR_PACKED_STRUCT(struct PIOInfoPOD {
104     LocationPOD abs_loc;
105     int32_t bel_index;
106     RelPtr<char> function_name;
107     int16_t bank;
108     int16_t dqsgroup;
109 });
110 
111 NPNR_PACKED_STRUCT(struct PackagePinPOD {
112     RelPtr<char> name;
113     LocationPOD abs_loc;
114     int32_t bel_index;
115 });
116 
117 NPNR_PACKED_STRUCT(struct PackageInfoPOD {
118     RelPtr<char> name;
119     int32_t num_pins;
120     RelPtr<PackagePinPOD> pin_data;
121 });
122 
123 NPNR_PACKED_STRUCT(struct TileNamePOD {
124     RelPtr<char> name;
125     int16_t type_idx;
126     int16_t padding;
127 });
128 
129 NPNR_PACKED_STRUCT(struct TileInfoPOD {
130     int32_t num_tiles;
131     RelPtr<TileNamePOD> tile_names;
132 });
133 
134 enum TapDirection : int8_t
135 {
136     TAP_DIR_LEFT = 0,
137     TAP_DIR_RIGHT = 1
138 };
139 
140 enum GlobalQuadrant : int8_t
141 {
142     QUAD_UL = 0,
143     QUAD_UR = 1,
144     QUAD_LL = 2,
145     QUAD_LR = 3,
146 };
147 
148 NPNR_PACKED_STRUCT(struct GlobalInfoPOD {
149     int16_t tap_col;
150     TapDirection tap_dir;
151     GlobalQuadrant quad;
152     int16_t spine_row;
153     int16_t spine_col;
154 });
155 
156 NPNR_PACKED_STRUCT(struct CellPropDelayPOD {
157     int32_t from_port;
158     int32_t to_port;
159     int32_t min_delay;
160     int32_t max_delay;
161 });
162 
163 NPNR_PACKED_STRUCT(struct CellSetupHoldPOD {
164     int32_t sig_port;
165     int32_t clock_port;
166     int32_t min_setup;
167     int32_t max_setup;
168     int32_t min_hold;
169     int32_t max_hold;
170 });
171 
172 NPNR_PACKED_STRUCT(struct CellTimingPOD {
173     int32_t cell_type;
174     int32_t num_prop_delays;
175     int32_t num_setup_holds;
176     RelPtr<CellPropDelayPOD> prop_delays;
177     RelPtr<CellSetupHoldPOD> setup_holds;
178 });
179 
180 NPNR_PACKED_STRUCT(struct PipDelayPOD {
181     int32_t min_base_delay;
182     int32_t max_base_delay;
183     int32_t min_fanout_adder;
184     int32_t max_fanout_adder;
185 });
186 
187 NPNR_PACKED_STRUCT(struct SpeedGradePOD {
188     int32_t num_cell_timings;
189     int32_t num_pip_classes;
190     RelPtr<CellTimingPOD> cell_timings;
191     RelPtr<PipDelayPOD> pip_classes;
192 });
193 
194 NPNR_PACKED_STRUCT(struct ChipInfoPOD {
195     int32_t width, height;
196     int32_t num_tiles;
197     int32_t num_location_types;
198     int32_t num_packages, num_pios;
199     int32_t const_id_count;
200     RelPtr<LocationTypePOD> locations;
201     RelPtr<int32_t> location_type;
202     RelPtr<GlobalInfoPOD> location_glbinfo;
203     RelPtr<RelPtr<char>> tiletype_names;
204     RelPtr<PackageInfoPOD> package_info;
205     RelPtr<PIOInfoPOD> pio_info;
206     RelPtr<TileInfoPOD> tile_info;
207     RelPtr<SpeedGradePOD> speed_grades;
208 });
209 
210 /************************ End of chipdb section. ************************/
211 
212 struct BelIterator
213 {
214     const ChipInfoPOD *chip;
215     int cursor_index;
216     int cursor_tile;
217 
218     BelIterator operator++()
219     {
220         cursor_index++;
221         while (cursor_tile < chip->num_tiles &&
222                cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_bels) {
223             cursor_index = 0;
224             cursor_tile++;
225         }
226         return *this;
227     }
228     BelIterator operator++(int)
229     {
230         BelIterator prior(*this);
231         ++(*this);
232         return prior;
233     }
234 
235     bool operator!=(const BelIterator &other) const
236     {
237         return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile;
238     }
239 
240     bool operator==(const BelIterator &other) const
241     {
242         return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile;
243     }
244 
245     BelId operator*() const
246     {
247         BelId ret;
248         ret.location.x = cursor_tile % chip->width;
249         ret.location.y = cursor_tile / chip->width;
250         ret.index = cursor_index;
251         return ret;
252     }
253 };
254 
255 struct BelRange
256 {
257     BelIterator b, e;
beginBelRange258     BelIterator begin() const { return b; }
endBelRange259     BelIterator end() const { return e; }
260 };
261 
262 // -----------------------------------------------------------------------
263 
264 struct BelPinIterator
265 {
266     const BelPortPOD *ptr = nullptr;
267     Location wire_loc;
268     void operator++() { ptr++; }
269     bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
270 
271     BelPin operator*() const
272     {
273         BelPin ret;
274         ret.bel.index = ptr->bel_index;
275         ret.bel.location = wire_loc + ptr->rel_bel_loc;
276         ret.pin.index = ptr->port;
277         return ret;
278     }
279 };
280 
281 struct BelPinRange
282 {
283     BelPinIterator b, e;
beginBelPinRange284     BelPinIterator begin() const { return b; }
endBelPinRange285     BelPinIterator end() const { return e; }
286 };
287 
288 // -----------------------------------------------------------------------
289 
290 struct WireIterator
291 {
292     const ChipInfoPOD *chip;
293     int cursor_index;
294     int cursor_tile;
295 
296     WireIterator operator++()
297     {
298         cursor_index++;
299         while (cursor_tile < chip->num_tiles &&
300                cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_wires) {
301             cursor_index = 0;
302             cursor_tile++;
303         }
304         return *this;
305     }
306     WireIterator operator++(int)
307     {
308         WireIterator prior(*this);
309         ++(*this);
310         return prior;
311     }
312 
313     bool operator!=(const WireIterator &other) const
314     {
315         return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile;
316     }
317 
318     bool operator==(const WireIterator &other) const
319     {
320         return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile;
321     }
322 
323     WireId operator*() const
324     {
325         WireId ret;
326         ret.location.x = cursor_tile % chip->width;
327         ret.location.y = cursor_tile / chip->width;
328         ret.index = cursor_index;
329         return ret;
330     }
331 };
332 
333 struct WireRange
334 {
335     WireIterator b, e;
beginWireRange336     WireIterator begin() const { return b; }
endWireRange337     WireIterator end() const { return e; }
338 };
339 
340 // -----------------------------------------------------------------------
341 
342 struct AllPipIterator
343 {
344     const ChipInfoPOD *chip;
345     int cursor_index;
346     int cursor_tile;
347 
348     AllPipIterator operator++()
349     {
350         cursor_index++;
351         while (cursor_tile < chip->num_tiles &&
352                cursor_index >= chip->locations[chip->location_type[cursor_tile]].num_pips) {
353             cursor_index = 0;
354             cursor_tile++;
355         }
356         return *this;
357     }
358     AllPipIterator operator++(int)
359     {
360         AllPipIterator prior(*this);
361         ++(*this);
362         return prior;
363     }
364 
365     bool operator!=(const AllPipIterator &other) const
366     {
367         return cursor_index != other.cursor_index || cursor_tile != other.cursor_tile;
368     }
369 
370     bool operator==(const AllPipIterator &other) const
371     {
372         return cursor_index == other.cursor_index && cursor_tile == other.cursor_tile;
373     }
374 
375     PipId operator*() const
376     {
377         PipId ret;
378         ret.location.x = cursor_tile % chip->width;
379         ret.location.y = cursor_tile / chip->width;
380         ret.index = cursor_index;
381         return ret;
382     }
383 };
384 
385 struct AllPipRange
386 {
387     AllPipIterator b, e;
beginAllPipRange388     AllPipIterator begin() const { return b; }
endAllPipRange389     AllPipIterator end() const { return e; }
390 };
391 
392 // -----------------------------------------------------------------------
393 
394 struct PipIterator
395 {
396 
397     const PipLocatorPOD *cursor = nullptr;
398     Location wire_loc;
399 
400     void operator++() { cursor++; }
401     bool operator!=(const PipIterator &other) const { return cursor != other.cursor; }
402 
403     PipId operator*() const
404     {
405         PipId ret;
406         ret.index = cursor->index;
407         ret.location = wire_loc + cursor->rel_loc;
408         return ret;
409     }
410 };
411 
412 struct PipRange
413 {
414     PipIterator b, e;
beginPipRange415     PipIterator begin() const { return b; }
endPipRange416     PipIterator end() const { return e; }
417 };
418 
419 struct ArchArgs
420 {
421     enum ArchArgsTypes
422     {
423         NONE,
424         LFE5U_12F,
425         LFE5U_25F,
426         LFE5U_45F,
427         LFE5U_85F,
428         LFE5UM_25F,
429         LFE5UM_45F,
430         LFE5UM_85F,
431         LFE5UM5G_25F,
432         LFE5UM5G_45F,
433         LFE5UM5G_85F,
434     } type = NONE;
435     std::string package;
436     enum SpeedGrade
437     {
438         SPEED_6 = 0,
439         SPEED_7,
440         SPEED_8,
441         SPEED_8_5G,
442     } speed = SPEED_6;
443 };
444 
445 struct DelayKey
446 {
447     IdString celltype, from, to;
448     inline bool operator==(const DelayKey &other) const
449     {
450         return celltype == other.celltype && from == other.from && to == other.to;
451     }
452 };
453 
454 NEXTPNR_NAMESPACE_END
455 namespace std {
456 template <> struct hash<NEXTPNR_NAMESPACE_PREFIX DelayKey>
457 {
458     std::size_t operator()(const NEXTPNR_NAMESPACE_PREFIX DelayKey &dk) const noexcept
459     {
460         std::size_t seed = std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.celltype);
461         seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.from) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
462         seed ^= std::hash<NEXTPNR_NAMESPACE_PREFIX IdString>()(dk.to) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
463         return seed;
464     }
465 };
466 } // namespace std
467 NEXTPNR_NAMESPACE_BEGIN
468 
469 struct Arch : BaseCtx
470 {
471     const ChipInfoPOD *chip_info;
472     const PackageInfoPOD *package_info;
473     const SpeedGradePOD *speed_grade;
474 
475     mutable std::unordered_map<IdString, BelId> bel_by_name;
476     mutable std::unordered_map<IdString, WireId> wire_by_name;
477     mutable std::unordered_map<IdString, PipId> pip_by_name;
478 
479     std::vector<CellInfo *> bel_to_cell;
480     std::unordered_map<WireId, NetInfo *> wire_to_net;
481     std::unordered_map<PipId, NetInfo *> pip_to_net;
482     std::unordered_map<WireId, int> wire_fanout;
483 
484     ArchArgs args;
485     Arch(ArchArgs args);
486 
487     static bool isAvailable(ArchArgs::ArchArgsTypes chip);
488     static std::vector<std::string> getSupportedPackages(ArchArgs::ArchArgsTypes chip);
489 
490     std::string getChipName() const;
491     std::string getFullChipName() const;
492 
493     IdString archId() const { return id("ecp5"); }
494     ArchArgs archArgs() const { return args; }
495     IdString archArgsToId(ArchArgs args) const;
496 
497     // -------------------------------------------------
498 
499     static const int max_loc_bels = 20;
500 
501     int getGridDimX() const { return chip_info->width; };
502     int getGridDimY() const { return chip_info->height; };
503     int getTileBelDimZ(int, int) const { return max_loc_bels; };
504     int getTilePipDimZ(int, int) const { return 1; };
505 
506     // -------------------------------------------------
507 
508     BelId getBelByName(IdString name) const;
509 
510     template <typename Id> const LocationTypePOD *locInfo(Id &id) const
511     {
512         return &(chip_info->locations[chip_info->location_type[id.location.y * chip_info->width + id.location.x]]);
513     }
514 
515     IdString getBelName(BelId bel) const
516     {
517         NPNR_ASSERT(bel != BelId());
518         std::stringstream name;
519         name << "X" << bel.location.x << "/Y" << bel.location.y << "/" << locInfo(bel)->bel_data[bel.index].name.get();
520         return id(name.str());
521     }
522 
523     uint32_t getBelChecksum(BelId bel) const { return bel.index; }
524 
525     int getBelFlatIndex(BelId bel) const
526     {
527         return (bel.location.y * chip_info->width + bel.location.x) * max_loc_bels + bel.index;
528     }
529 
530     void bindBel(BelId bel, CellInfo *cell, PlaceStrength strength)
531     {
532         NPNR_ASSERT(bel != BelId());
533         int idx = getBelFlatIndex(bel);
534         NPNR_ASSERT(bel_to_cell.at(idx) == nullptr);
535         bel_to_cell[idx] = cell;
536         cell->bel = bel;
537         cell->belStrength = strength;
538         refreshUiBel(bel);
539     }
540 
541     void unbindBel(BelId bel)
542     {
543         NPNR_ASSERT(bel != BelId());
544         int idx = getBelFlatIndex(bel);
545         NPNR_ASSERT(bel_to_cell.at(idx) != nullptr);
546         bel_to_cell[idx]->bel = BelId();
547         bel_to_cell[idx]->belStrength = STRENGTH_NONE;
548         bel_to_cell[idx] = nullptr;
549         refreshUiBel(bel);
550     }
551 
552     Loc getBelLocation(BelId bel) const
553     {
554         Loc loc;
555         loc.x = bel.location.x;
556         loc.y = bel.location.y;
557         loc.z = locInfo(bel)->bel_data[bel.index].z;
558         return loc;
559     }
560 
561     BelId getBelByLocation(Loc loc) const;
562     BelRange getBelsByTile(int x, int y) const;
563 
564     bool getBelGlobalBuf(BelId bel) const { return getBelType(bel) == id_DCCA; }
565 
566     bool checkBelAvail(BelId bel) const
567     {
568         NPNR_ASSERT(bel != BelId());
569         return bel_to_cell[getBelFlatIndex(bel)] == nullptr;
570     }
571 
572     CellInfo *getBoundBelCell(BelId bel) const
573     {
574         NPNR_ASSERT(bel != BelId());
575         return bel_to_cell[getBelFlatIndex(bel)];
576     }
577 
578     CellInfo *getConflictingBelCell(BelId bel) const
579     {
580         NPNR_ASSERT(bel != BelId());
581         return bel_to_cell[getBelFlatIndex(bel)];
582     }
583 
584     BelRange getBels() const
585     {
586         BelRange range;
587         range.b.cursor_tile = 0;
588         range.b.cursor_index = -1;
589         range.b.chip = chip_info;
590         ++range.b; //-1 and then ++ deals with the case of no Bels in the first tile
591         range.e.cursor_tile = chip_info->width * chip_info->height;
592         range.e.cursor_index = 0;
593         range.e.chip = chip_info;
594         return range;
595     }
596 
597     IdString getBelType(BelId bel) const
598     {
599         NPNR_ASSERT(bel != BelId());
600         IdString id;
601         id.index = locInfo(bel)->bel_data[bel.index].type;
602         return id;
603     }
604 
605     std::vector<std::pair<IdString, std::string>> getBelAttrs(BelId) const
606     {
607         std::vector<std::pair<IdString, std::string>> ret;
608         return ret;
609     }
610 
611     WireId getBelPinWire(BelId bel, IdString pin) const;
612 
613     BelPinRange getWireBelPins(WireId wire) const
614     {
615         BelPinRange range;
616         NPNR_ASSERT(wire != WireId());
617         range.b.ptr = locInfo(wire)->wire_data[wire.index].bel_pins.get();
618         range.b.wire_loc = wire.location;
619         range.e.ptr = range.b.ptr + locInfo(wire)->wire_data[wire.index].num_bel_pins;
620         range.e.wire_loc = wire.location;
621         return range;
622     }
623 
624     std::vector<IdString> getBelPins(BelId bel) const;
625 
626     // -------------------------------------------------
627 
628     WireId getWireByName(IdString name) const;
629 
630     IdString getWireName(WireId wire) const
631     {
632         NPNR_ASSERT(wire != WireId());
633 
634         std::stringstream name;
635         name << "X" << wire.location.x << "/Y" << wire.location.y << "/"
636              << locInfo(wire)->wire_data[wire.index].name.get();
637         return id(name.str());
638     }
639 
640     IdString getWireType(WireId wire) const
641     {
642         NPNR_ASSERT(wire != WireId());
643         IdString id;
644         id.index = locInfo(wire)->wire_data[wire.index].type;
645         return id;
646     }
647 
648     std::vector<std::pair<IdString, std::string>> getWireAttrs(WireId) const;
649 
650     uint32_t getWireChecksum(WireId wire) const { return wire.index; }
651 
652     void bindWire(WireId wire, NetInfo *net, PlaceStrength strength)
653     {
654         NPNR_ASSERT(wire != WireId());
655         NPNR_ASSERT(wire_to_net[wire] == nullptr);
656         wire_to_net[wire] = net;
657         net->wires[wire].pip = PipId();
658         net->wires[wire].strength = strength;
659         refreshUiWire(wire);
660     }
661 
662     void unbindWire(WireId wire)
663     {
664         NPNR_ASSERT(wire != WireId());
665         NPNR_ASSERT(wire_to_net[wire] != nullptr);
666 
667         auto &net_wires = wire_to_net[wire]->wires;
668         auto it = net_wires.find(wire);
669         NPNR_ASSERT(it != net_wires.end());
670 
671         auto pip = it->second.pip;
672         if (pip != PipId()) {
673             wire_fanout[getPipSrcWire(pip)]--;
674             pip_to_net[pip] = nullptr;
675         }
676 
677         net_wires.erase(it);
678         wire_to_net[wire] = nullptr;
679         refreshUiWire(wire);
680     }
681 
682     bool checkWireAvail(WireId wire) const
683     {
684         NPNR_ASSERT(wire != WireId());
685         return wire_to_net.find(wire) == wire_to_net.end() || wire_to_net.at(wire) == nullptr;
686     }
687 
688     NetInfo *getBoundWireNet(WireId wire) const
689     {
690         NPNR_ASSERT(wire != WireId());
691         if (wire_to_net.find(wire) == wire_to_net.end())
692             return nullptr;
693         else
694             return wire_to_net.at(wire);
695     }
696 
697     WireId getConflictingWireWire(WireId wire) const { return wire; }
698 
699     NetInfo *getConflictingWireNet(WireId wire) const
700     {
701         NPNR_ASSERT(wire != WireId());
702         if (wire_to_net.find(wire) == wire_to_net.end())
703             return nullptr;
704         else
705             return wire_to_net.at(wire);
706     }
707 
708     DelayInfo getWireDelay(WireId wire) const
709     {
710         DelayInfo delay;
711         delay.min_delay = 0;
712         delay.max_delay = 0;
713         return delay;
714     }
715 
716     WireRange getWires() const
717     {
718         WireRange range;
719         range.b.cursor_tile = 0;
720         range.b.cursor_index = -1;
721         range.b.chip = chip_info;
722         ++range.b; //-1 and then ++ deals with the case of no wries in the first tile
723         range.e.cursor_tile = chip_info->width * chip_info->height;
724         range.e.cursor_index = 0;
725         range.e.chip = chip_info;
726         return range;
727     }
728 
729     IdString getWireBasename(WireId wire) const { return id(locInfo(wire)->wire_data[wire.index].name.get()); }
730 
731     WireId getWireByLocAndBasename(Location loc, std::string basename) const
732     {
733         WireId wireId;
734         wireId.location = loc;
735         for (int i = 0; i < locInfo(wireId)->num_wires; i++) {
736             if (locInfo(wireId)->wire_data[i].name.get() == basename) {
737                 wireId.index = i;
738                 return wireId;
739             }
740         }
741         return WireId();
742     }
743 
744     // -------------------------------------------------
745 
746     PipId getPipByName(IdString name) const;
747     IdString getPipName(PipId pip) const;
748 
749     IdString getPipType(PipId pip) const { return IdString(); }
750 
751     std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId) const
752     {
753         std::vector<std::pair<IdString, std::string>> ret;
754         return ret;
755     }
756 
757     uint32_t getPipChecksum(PipId pip) const { return pip.index; }
758 
759     void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
760     {
761         NPNR_ASSERT(pip != PipId());
762         NPNR_ASSERT(pip_to_net[pip] == nullptr);
763 
764         pip_to_net[pip] = net;
765         wire_fanout[getPipSrcWire(pip)]++;
766 
767         WireId dst;
768         dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
769         dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
770         NPNR_ASSERT(wire_to_net[dst] == nullptr);
771         wire_to_net[dst] = net;
772         net->wires[dst].pip = pip;
773         net->wires[dst].strength = strength;
774     }
775 
776     void unbindPip(PipId pip)
777     {
778         NPNR_ASSERT(pip != PipId());
779         NPNR_ASSERT(pip_to_net[pip] != nullptr);
780         wire_fanout[getPipSrcWire(pip)]--;
781 
782         WireId dst;
783         dst.index = locInfo(pip)->pip_data[pip.index].dst_idx;
784         dst.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
785         NPNR_ASSERT(wire_to_net[dst] != nullptr);
786         wire_to_net[dst] = nullptr;
787         pip_to_net[pip]->wires.erase(dst);
788 
789         pip_to_net[pip] = nullptr;
790     }
791 
792     bool checkPipAvail(PipId pip) const
793     {
794         NPNR_ASSERT(pip != PipId());
795         return pip_to_net.find(pip) == pip_to_net.end() || pip_to_net.at(pip) == nullptr;
796     }
797 
798     NetInfo *getBoundPipNet(PipId pip) const
799     {
800         NPNR_ASSERT(pip != PipId());
801         if (pip_to_net.find(pip) == pip_to_net.end())
802             return nullptr;
803         else
804             return pip_to_net.at(pip);
805     }
806 
807     WireId getConflictingPipWire(PipId pip) const { return WireId(); }
808 
809     NetInfo *getConflictingPipNet(PipId pip) const
810     {
811         NPNR_ASSERT(pip != PipId());
812         if (pip_to_net.find(pip) == pip_to_net.end())
813             return nullptr;
814         else
815             return pip_to_net.at(pip);
816     }
817 
818     AllPipRange getPips() const
819     {
820         AllPipRange range;
821         range.b.cursor_tile = 0;
822         range.b.cursor_index = -1;
823         range.b.chip = chip_info;
824         ++range.b; //-1 and then ++ deals with the case of no wries in the first tile
825         range.e.cursor_tile = chip_info->width * chip_info->height;
826         range.e.cursor_index = 0;
827         range.e.chip = chip_info;
828         return range;
829     }
830 
831     WireId getPipSrcWire(PipId pip) const
832     {
833         WireId wire;
834         NPNR_ASSERT(pip != PipId());
835         wire.index = locInfo(pip)->pip_data[pip.index].src_idx;
836         wire.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_src_loc;
837         return wire;
838     }
839 
840     WireId getPipDstWire(PipId pip) const
841     {
842         WireId wire;
843         NPNR_ASSERT(pip != PipId());
844         wire.index = locInfo(pip)->pip_data[pip.index].dst_idx;
845         wire.location = pip.location + locInfo(pip)->pip_data[pip.index].rel_dst_loc;
846         return wire;
847     }
848 
849     DelayInfo getPipDelay(PipId pip) const
850     {
851         DelayInfo delay;
852         NPNR_ASSERT(pip != PipId());
853         int fanout = 0;
854         auto fnd_fanout = wire_fanout.find(getPipSrcWire(pip));
855         if (fnd_fanout != wire_fanout.end())
856             fanout = fnd_fanout->second;
857         NPNR_ASSERT(locInfo(pip)->pip_data[pip.index].timing_class < speed_grade->num_pip_classes);
858         delay.min_delay =
859                 speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].min_base_delay +
860                 fanout * speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].min_fanout_adder;
861         delay.max_delay =
862                 speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].max_base_delay +
863                 fanout * speed_grade->pip_classes[locInfo(pip)->pip_data[pip.index].timing_class].max_fanout_adder;
864         return delay;
865     }
866 
867     PipRange getPipsDownhill(WireId wire) const
868     {
869         PipRange range;
870         NPNR_ASSERT(wire != WireId());
871         range.b.cursor = locInfo(wire)->wire_data[wire.index].pips_downhill.get();
872         range.b.wire_loc = wire.location;
873         range.e.cursor = range.b.cursor + locInfo(wire)->wire_data[wire.index].num_downhill;
874         range.e.wire_loc = wire.location;
875         return range;
876     }
877 
878     PipRange getPipsUphill(WireId wire) const
879     {
880         PipRange range;
881         NPNR_ASSERT(wire != WireId());
882         range.b.cursor = locInfo(wire)->wire_data[wire.index].pips_uphill.get();
883         range.b.wire_loc = wire.location;
884         range.e.cursor = range.b.cursor + locInfo(wire)->wire_data[wire.index].num_uphill;
885         range.e.wire_loc = wire.location;
886         return range;
887     }
888 
889     PipRange getWireAliases(WireId wire) const
890     {
891         PipRange range;
892         NPNR_ASSERT(wire != WireId());
893         range.b.cursor = nullptr;
894         range.e.cursor = nullptr;
895         return range;
896     }
897 
898     std::string getPipTilename(PipId pip) const
899     {
900         auto &tileloc = chip_info->tile_info[pip.location.y * chip_info->width + pip.location.x];
901         for (int i = 0; i < tileloc.num_tiles; i++) {
902             if (tileloc.tile_names[i].type_idx == locInfo(pip)->pip_data[pip.index].tile_type)
903                 return tileloc.tile_names[i].name.get();
904         }
905         NPNR_ASSERT_FALSE("failed to find Pip tile");
906     }
907 
908     std::string getPipTiletype(PipId pip) const
909     {
910         return chip_info->tiletype_names[locInfo(pip)->pip_data[pip.index].tile_type].get();
911     }
912 
913     Loc getPipLocation(PipId pip) const
914     {
915         Loc loc;
916         loc.x = pip.location.x;
917         loc.y = pip.location.y;
918         loc.z = 0;
919         return loc;
920     }
921 
922     int8_t getPipClass(PipId pip) const { return locInfo(pip)->pip_data[pip.index].pip_type; }
923 
924     BelId getPackagePinBel(const std::string &pin) const;
925     std::string getBelPackagePin(BelId bel) const;
926     int getPioBelBank(BelId bel) const;
927     // For getting GCLK, PLL, Vref, etc, pins
928     std::string getPioFunctionName(BelId bel) const;
929     BelId getPioByFunctionName(const std::string &name) const;
930 
931     PortType getBelPinType(BelId bel, IdString pin) const;
932 
933     // -------------------------------------------------
934 
935     GroupId getGroupByName(IdString name) const;
936     IdString getGroupName(GroupId group) const;
937     std::vector<GroupId> getGroups() const;
938     std::vector<BelId> getGroupBels(GroupId group) const;
939     std::vector<WireId> getGroupWires(GroupId group) const;
940     std::vector<PipId> getGroupPips(GroupId group) const;
941     std::vector<GroupId> getGroupGroups(GroupId group) const;
942 
943     // -------------------------------------------------
944 
945     delay_t estimateDelay(WireId src, WireId dst) const;
946     ArcBounds getRouteBoundingBox(WireId src, WireId dst) const;
947     delay_t predictDelay(const NetInfo *net_info, const PortRef &sink) const;
948     delay_t getDelayEpsilon() const { return 20; }
949     delay_t getRipupDelayPenalty() const;
950     float getDelayNS(delay_t v) const { return v * 0.001; }
951     DelayInfo getDelayFromNS(float ns) const
952     {
953         DelayInfo del;
954         del.min_delay = delay_t(ns * 1000);
955         del.max_delay = delay_t(ns * 1000);
956         return del;
957     }
958     uint32_t getDelayChecksum(delay_t v) const { return v; }
959     bool getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay_t &budget) const;
960 
961     // -------------------------------------------------
962 
963     bool pack();
964     bool place();
965     bool route();
966 
967     // -------------------------------------------------
968 
969     std::vector<GraphicElement> getDecalGraphics(DecalId decal) const;
970 
971     DecalXY getBelDecal(BelId bel) const;
972     DecalXY getWireDecal(WireId wire) const;
973     DecalXY getPipDecal(PipId pip) const;
974     DecalXY getGroupDecal(GroupId group) const;
975 
976     // -------------------------------------------------
977 
978     // Get the delay through a cell from one port to another, returning false
979     // if no path exists
980     bool getCellDelay(const CellInfo *cell, IdString fromPort, IdString toPort, DelayInfo &delay) const;
981     // Get the port class, also setting clockInfoCount to the number of TimingClockingInfos associated with a port
982     TimingPortClass getPortTimingClass(const CellInfo *cell, IdString port, int &clockInfoCount) const;
983     // Get the TimingClockingInfo of a port
984     TimingClockingInfo getPortClockingInfo(const CellInfo *cell, IdString port, int index) const;
985     // Return true if a port is a net
986     bool isGlobalNet(const NetInfo *net) const;
987 
988     bool getDelayFromTimingDatabase(IdString tctype, IdString from, IdString to, DelayInfo &delay) const;
989     void getSetupHoldFromTimingDatabase(IdString tctype, IdString clock, IdString port, DelayInfo &setup,
990                                         DelayInfo &hold) const;
991 
992     // -------------------------------------------------
993     // Placement validity checks
994     bool isValidBelForCell(CellInfo *cell, BelId bel) const;
995     bool isBelLocationValid(BelId bel) const;
996 
997     // Helper function for above
998     bool slicesCompatible(const std::vector<const CellInfo *> &cells) const;
999 
1000     void assignArchInfo();
1001 
1002     void permute_luts();
1003 
1004     std::vector<std::pair<std::string, std::string>> getTilesAtLocation(int row, int col);
1005     std::string getTileByTypeAndLocation(int row, int col, std::string type) const
1006     {
1007         auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
1008         for (int i = 0; i < tileloc.num_tiles; i++) {
1009             if (chip_info->tiletype_names[tileloc.tile_names[i].type_idx].get() == type)
1010                 return tileloc.tile_names[i].name.get();
1011         }
1012         NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type " +
1013                               type);
1014     }
1015 
1016     std::string getTileByTypeAndLocation(int row, int col, const std::set<std::string> &type) const
1017     {
1018         auto &tileloc = chip_info->tile_info[row * chip_info->width + col];
1019         for (int i = 0; i < tileloc.num_tiles; i++) {
1020             if (type.count(chip_info->tiletype_names[tileloc.tile_names[i].type_idx].get()))
1021                 return tileloc.tile_names[i].name.get();
1022         }
1023         NPNR_ASSERT_FALSE_STR("no tile at (" + std::to_string(col) + ", " + std::to_string(row) + ") with type in set");
1024     }
1025 
1026     std::string getTileByType(std::string type) const
1027     {
1028         for (int i = 0; i < chip_info->height * chip_info->width; i++) {
1029             auto &tileloc = chip_info->tile_info[i];
1030             for (int j = 0; j < tileloc.num_tiles; j++)
1031                 if (chip_info->tiletype_names[tileloc.tile_names[j].type_idx].get() == type)
1032                     return tileloc.tile_names[j].name.get();
1033         }
1034         NPNR_ASSERT_FALSE_STR("no tile with type " + type);
1035     }
1036 
1037     GlobalInfoPOD globalInfoAtLoc(Location loc);
1038 
1039     bool getPIODQSGroup(BelId pio, bool &dqsright, int &dqsrow);
1040     BelId getDQSBUF(bool dqsright, int dqsrow);
1041     WireId getBankECLK(int bank, int eclk);
1042 
1043     // Apply LPF constraints to the context
1044     bool applyLPF(std::string filename, std::istream &in);
1045 
1046     IdString id_trellis_slice;
1047     IdString id_clk, id_lsr;
1048     IdString id_clkmux, id_lsrmux;
1049     IdString id_srmode, id_mode;
1050 
1051     // Special case for delay estimates due to its physical location
1052     // being far from the logical location of its primitive
1053     WireId gsrclk_wire;
1054     // Improves directivity of routing to DSP inputs, avoids issues
1055     // with different routes to the same physical reset wire causing
1056     // conflicts and slow routing
1057     std::unordered_map<WireId, std::pair<int, int>> wire_loc_overrides;
1058     void setupWireLocations();
1059 
1060     mutable std::unordered_map<DelayKey, std::pair<bool, DelayInfo>> celldelay_cache;
1061 
1062     static const std::string defaultPlacer;
1063     static const std::vector<std::string> availablePlacers;
1064     static const std::string defaultRouter;
1065     static const std::vector<std::string> availableRouters;
1066 };
1067 
1068 NEXTPNR_NAMESPACE_END
1069