diff options
Diffstat (limited to 'ice40/arch.h')
-rw-r--r-- | ice40/arch.h | 309 |
1 files changed, 173 insertions, 136 deletions
diff --git a/ice40/arch.h b/ice40/arch.h index 25ed8ebf..a02e0ced 100644 --- a/ice40/arch.h +++ b/ice40/arch.h @@ -2,7 +2,6 @@ * nextpnr -- Next Generation Place and Route * * Copyright (C) 2018 Clifford Wolf <clifford@symbioticeda.com> - * Copyright (C) 2018 Serge Bazanski <q3k@symbioticeda.com> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -325,37 +324,19 @@ struct ArchArgs std::string package; }; -/// Forward declare proxy classes for Arch. - -class ArchMutateMethods; -class ArchReadMethods; - -/// Arch/Context -// Arch is the main state class of the PnR algorithms. It keeps note of mapped -// cells/nets, locked switches, etc. -// -// In order to mutate state in Arch, you can do one of two things: -// - directly call one of the wrapper methods to mutate state -// - get a read or readwrite proxy to the Arch, and call methods on it - -class Arch : public BaseCtx +struct Arch : BaseCtx { - // We let proxy methods access our state. - friend class ArchMutateMethods; - friend class ArchReadMethods; + const ChipInfoPOD *chip_info; + const PackageInfoPOD *package_info; - private: - std::vector<IdString> bel_to_cell; - std::vector<IdString> wire_to_net; - std::vector<IdString> pip_to_net; - std::vector<IdString> switches_locked; mutable std::unordered_map<IdString, int> bel_by_name; mutable std::unordered_map<IdString, int> wire_by_name; mutable std::unordered_map<IdString, int> pip_by_name; - public: - const ChipInfoPOD *chip_info; - const PackageInfoPOD *package_info; + std::vector<IdString> bel_to_cell; + std::vector<IdString> wire_to_net; + std::vector<IdString> pip_to_net; + std::vector<IdString> switches_locked; ArchArgs args; Arch(ArchArgs args); @@ -373,8 +354,7 @@ class Arch : public BaseCtx // ------------------------------------------------- - /// Methods to get chip info - don't need to use a wrapper, as these are - /// static per lifetime of object. + BelId getBelByName(IdString name) const; IdString getBelName(BelId bel) const { @@ -384,6 +364,42 @@ class Arch : public BaseCtx uint32_t getBelChecksum(BelId bel) const { return bel.index; } + void bindBel(BelId bel, IdString cell, PlaceStrength strength) + { + NPNR_ASSERT(bel != BelId()); + NPNR_ASSERT(bel_to_cell[bel.index] == IdString()); + bel_to_cell[bel.index] = cell; + cells[cell]->bel = bel; + cells[cell]->belStrength = strength; + } + + void unbindBel(BelId bel) + { + NPNR_ASSERT(bel != BelId()); + NPNR_ASSERT(bel_to_cell[bel.index] != IdString()); + cells[bel_to_cell[bel.index]]->bel = BelId(); + cells[bel_to_cell[bel.index]]->belStrength = STRENGTH_NONE; + bel_to_cell[bel.index] = IdString(); + } + + bool checkBelAvail(BelId bel) const + { + NPNR_ASSERT(bel != BelId()); + return bel_to_cell[bel.index] == IdString(); + } + + IdString getBoundBelCell(BelId bel) const + { + NPNR_ASSERT(bel != BelId()); + return bel_to_cell[bel.index]; + } + + IdString getConflictingBelCell(BelId bel) const + { + NPNR_ASSERT(bel != BelId()); + return bel_to_cell[bel.index]; + } + BelRange getBels() const { BelRange range; @@ -397,11 +413,11 @@ class Arch : public BaseCtx BelRange range; // FIXME #if 0 - if (type == "TYPE_A") { - range.b.cursor = bels_type_a_begin; - range.e.cursor = bels_type_a_end; - } - ... + if (type == "TYPE_A") { + range.b.cursor = bels_type_a_begin; + range.e.cursor = bels_type_a_end; + } + ... #endif return range; } @@ -414,6 +430,8 @@ class Arch : public BaseCtx return chip_info->bel_data[bel.index].type; } + WireId getWireBelPin(BelId bel, PortPin pin) const; + BelPin getBelPinUphill(WireId wire) const { BelPin ret; @@ -438,6 +456,8 @@ class Arch : public BaseCtx // ------------------------------------------------- + WireId getWireByName(IdString name) const; + IdString getWireName(WireId wire) const { NPNR_ASSERT(wire != WireId()); @@ -446,6 +466,115 @@ class Arch : public BaseCtx uint32_t getWireChecksum(WireId wire) const { return wire.index; } + void bindWire(WireId wire, IdString net, PlaceStrength strength) + { + NPNR_ASSERT(wire != WireId()); + NPNR_ASSERT(wire_to_net[wire.index] == IdString()); + wire_to_net[wire.index] = net; + nets[net]->wires[wire].pip = PipId(); + nets[net]->wires[wire].strength = strength; + } + + void unbindWire(WireId wire) + { + NPNR_ASSERT(wire != WireId()); + NPNR_ASSERT(wire_to_net[wire.index] != IdString()); + + auto &net_wires = nets[wire_to_net[wire.index]]->wires; + auto it = net_wires.find(wire); + NPNR_ASSERT(it != net_wires.end()); + + auto pip = it->second.pip; + if (pip != PipId()) { + pip_to_net[pip.index] = IdString(); + switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); + } + + net_wires.erase(it); + wire_to_net[wire.index] = IdString(); + } + + bool checkWireAvail(WireId wire) const + { + NPNR_ASSERT(wire != WireId()); + return wire_to_net[wire.index] == IdString(); + } + + IdString getBoundWireNet(WireId wire) const + { + NPNR_ASSERT(wire != WireId()); + return wire_to_net[wire.index]; + } + + IdString getConflictingWireNet(WireId wire) const + { + NPNR_ASSERT(wire != WireId()); + return wire_to_net[wire.index]; + } + + WireRange getWires() const + { + WireRange range; + range.b.cursor = 0; + range.e.cursor = chip_info->num_wires; + return range; + } + + // ------------------------------------------------- + + PipId getPipByName(IdString name) const; + + void bindPip(PipId pip, IdString net, PlaceStrength strength) + { + NPNR_ASSERT(pip != PipId()); + NPNR_ASSERT(pip_to_net[pip.index] == IdString()); + NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString()); + + pip_to_net[pip.index] = net; + switches_locked[chip_info->pip_data[pip.index].switch_index] = net; + + WireId dst; + dst.index = chip_info->pip_data[pip.index].dst; + NPNR_ASSERT(wire_to_net[dst.index] == IdString()); + wire_to_net[dst.index] = net; + nets[net]->wires[dst].pip = pip; + nets[net]->wires[dst].strength = strength; + } + + void unbindPip(PipId pip) + { + NPNR_ASSERT(pip != PipId()); + NPNR_ASSERT(pip_to_net[pip.index] != IdString()); + NPNR_ASSERT(switches_locked[chip_info->pip_data[pip.index].switch_index] != IdString()); + + WireId dst; + dst.index = chip_info->pip_data[pip.index].dst; + NPNR_ASSERT(wire_to_net[dst.index] != IdString()); + wire_to_net[dst.index] = IdString(); + nets[pip_to_net[pip.index]]->wires.erase(dst); + + pip_to_net[pip.index] = IdString(); + switches_locked[chip_info->pip_data[pip.index].switch_index] = IdString(); + } + + bool checkPipAvail(PipId pip) const + { + NPNR_ASSERT(pip != PipId()); + return switches_locked[chip_info->pip_data[pip.index].switch_index] == IdString(); + } + + IdString getBoundPipNet(PipId pip) const + { + NPNR_ASSERT(pip != PipId()); + return pip_to_net[pip.index]; + } + + IdString getConflictingPipNet(PipId pip) const + { + NPNR_ASSERT(pip != PipId()); + return switches_locked[chip_info->pip_data[pip.index].switch_index]; + } + AllPipRange getPips() const { AllPipRange range; @@ -453,7 +582,7 @@ class Arch : public BaseCtx range.e.cursor = chip_info->num_pips; return range; } - + IdString getPipName(PipId pip) const; uint32_t getPipChecksum(PipId pip) const { return pip.index; } @@ -509,20 +638,11 @@ class Arch : public BaseCtx return range; } - WireRange getWires() const - { - WireRange range; - range.b.cursor = 0; - range.e.cursor = chip_info->num_wires; - return range; - } - BelId getPackagePinBel(const std::string &pin) const; std::string getBelPackagePin(BelId bel) const; // ------------------------------------------------- - // TODO(q3k) move this to archproxies? GroupId getGroupByName(IdString name) const; IdString getGroupName(GroupId group) const; std::vector<GroupId> getGroups() const; @@ -533,8 +653,6 @@ class Arch : public BaseCtx // ------------------------------------------------- - // These are also specific to the chip and not state, so they're available - // on arch directly. void estimatePosition(BelId bel, int &x, int &y, bool &gb) const; delay_t estimateDelay(WireId src, WireId dst) const; delay_t getDelayEpsilon() const { return 20; } @@ -550,7 +668,8 @@ class Arch : public BaseCtx // ------------------------------------------------- - // TODO(q3k) move this to archproxies? + std::vector<GraphicElement> getDecalGraphics(DecalId decal) const; + DecalXY getFrameDecal() const; DecalXY getBelDecal(BelId bel) const; DecalXY getWireDecal(WireId wire) const; @@ -571,106 +690,24 @@ class Arch : public BaseCtx // ------------------------------------------------- - IdString id_glb_buf_out; - IdString id_icestorm_lc, id_sb_io, id_sb_gb; - IdString id_cen, id_clk, id_sr; - IdString id_i0, id_i1, id_i2, id_i3; - IdString id_dff_en, id_neg_clk; -}; + // Perform placement validity checks, returning false on failure (all implemented in arch_place.cc) -// Read-only methods on Arch that require state access. -class ArchReadMethods : public BaseReadCtx -{ - private: - const Arch *parent_; - const ChipInfoPOD *chip_info; - const std::vector<IdString> &bel_to_cell; - const std::vector<IdString> &wire_to_net; - const std::vector<IdString> &pip_to_net; - const std::vector<IdString> &switches_locked; - std::unordered_map<IdString, int> &bel_by_name; - std::unordered_map<IdString, int> &wire_by_name; - std::unordered_map<IdString, int> &pip_by_name; - - public: - ~ArchReadMethods() noexcept {} - ArchReadMethods(const Arch *parent) - : BaseReadCtx(parent), parent_(parent), chip_info(parent->chip_info), bel_to_cell(parent->bel_to_cell), - wire_to_net(parent->wire_to_net), pip_to_net(parent->pip_to_net), - switches_locked(parent->switches_locked), bel_by_name(parent->bel_by_name), - wire_by_name(parent->wire_by_name), pip_by_name(parent->pip_by_name) - { - } - ArchReadMethods(ArchReadMethods &&other) noexcept : ArchReadMethods(other.parent_) {} - ArchReadMethods(const ArchReadMethods &other) : ArchReadMethods(other.parent_) {} - - /// Perform placement validity checks, returning false on failure (all implemented in arch_place.cc) // Whether or not a given cell can be placed at a given Bel // This is not intended for Bel type checks, but finer-grained constraints // such as conflicting set/reset signals, etc bool isValidBelForCell(CellInfo *cell, BelId bel) const; + // Return true whether all Bels at a given location are valid bool isBelLocationValid(BelId bel) const; + // Helper function for above bool logicCellsCompatible(const std::vector<const CellInfo *> &cells) const; - bool checkWireAvail(WireId wire) const; - bool checkPipAvail(PipId pip) const; - bool checkBelAvail(BelId bel) const; - - WireId getWireByName(IdString name) const; - WireId getWireBelPin(BelId bel, PortPin pin) const; - PipId getPipByName(IdString name) const; - - IdString getConflictingWireNet(WireId wire) const; - IdString getConflictingPipNet(PipId pip) const; - IdString getConflictingBelCell(BelId bel) const; - - IdString getBoundWireNet(WireId wire) const; - IdString getBoundPipNet(PipId pip) const; - IdString getBoundBelCell(BelId bel) const; - - BelId getBelByName(IdString name) const; - - std::vector<GraphicElement> getDecalGraphics(DecalId decal) const; -}; - -// State mutating methods on Arch. -class ArchMutateMethods : public BaseMutateCtx -{ - friend class MutateContext; - - private: - Arch *parent_; - const ChipInfoPOD *chip_info; - std::vector<IdString> &bel_to_cell; - std::vector<IdString> &wire_to_net; - std::vector<IdString> &pip_to_net; - std::vector<IdString> &switches_locked; - std::unordered_map<IdString, int> &bel_by_name; - std::unordered_map<IdString, int> &wire_by_name; - std::unordered_map<IdString, int> &pip_by_name; - - public: - ArchMutateMethods(Arch *parent) - : BaseMutateCtx(parent), parent_(parent), chip_info(parent->chip_info), bel_to_cell(parent->bel_to_cell), - wire_to_net(parent->wire_to_net), pip_to_net(parent->pip_to_net), - switches_locked(parent->switches_locked), bel_by_name(parent->bel_by_name), - wire_by_name(parent->wire_by_name), pip_by_name(parent->pip_by_name) - { - } - ArchMutateMethods(ArchMutateMethods &&other) : ArchMutateMethods(other.parent_) {} - ArchMutateMethods(const ArchMutateMethods &other) : ArchMutateMethods(other.parent_) {} - ~ArchMutateMethods() {} - - void unbindWire(WireId wire); - void unbindPip(PipId pip); - void unbindBel(BelId bel); - void bindWire(WireId wire, IdString net, PlaceStrength strength); - void bindPip(PipId pip, IdString net, PlaceStrength strength); - void bindBel(BelId bel, IdString cell, PlaceStrength strength); - // Returned pointer is valid as long as Proxy object exists. - CellInfo *getCell(IdString cell); + IdString id_glb_buf_out; + IdString id_icestorm_lc, id_sb_io, id_sb_gb; + IdString id_cen, id_clk, id_sr; + IdString id_i0, id_i1, id_i2, id_i3; + IdString id_dff_en, id_neg_clk; }; NEXTPNR_NAMESPACE_END |