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