aboutsummaryrefslogtreecommitdiffstats
path: root/ice40/arch.h
diff options
context:
space:
mode:
Diffstat (limited to 'ice40/arch.h')
-rw-r--r--ice40/arch.h309
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