aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorgatecat <gatecat@ds0.me>2021-05-01 14:55:33 +0100
committergatecat <gatecat@ds0.me>2021-05-15 14:54:33 +0100
commit5d1b8bf74469d0d5c5cc15e8c8e042da55da5357 (patch)
tree425eddfd77e269c54235edfd4f945e4e16933bad
parentaf0bffbae905d92942492e0fdf42a4b02686b224 (diff)
downloadnextpnr-5d1b8bf74469d0d5c5cc15e8c8e042da55da5357.tar.gz
nextpnr-5d1b8bf74469d0d5c5cc15e8c8e042da55da5357.tar.bz2
nextpnr-5d1b8bf74469d0d5c5cc15e8c8e042da55da5357.zip
cyclonev: Add names and archcheck fixes
Signed-off-by: gatecat <gatecat@ds0.me>
-rw-r--r--common/idstringlist.cc19
-rw-r--r--common/idstringlist.h3
-rw-r--r--cyclonev/arch.cc123
-rw-r--r--cyclonev/arch.h45
-rw-r--r--cyclonev/constids.inc2
5 files changed, 138 insertions, 54 deletions
diff --git a/common/idstringlist.cc b/common/idstringlist.cc
index 9900f92a..6f6f8cd0 100644
--- a/common/idstringlist.cc
+++ b/common/idstringlist.cc
@@ -58,4 +58,23 @@ std::string IdStringList::str(const Context *ctx) const
return s;
}
+IdStringList IdStringList::concat(IdStringList a, IdStringList b)
+{
+ IdStringList result(a.size() + b.size());
+ for (size_t i = 0; i < a.size(); i++)
+ result.ids[i] = a[i];
+ for (size_t i = 0; i < b.size(); i++)
+ result.ids[a.size() + i] = b[i];
+ return result;
+}
+
+IdStringList IdStringList::slice(size_t s, size_t e) const
+{
+ NPNR_ASSERT(e >= s);
+ IdStringList result(e - s);
+ for (size_t i = 0; i < result.size(); i++)
+ result.ids[i] = ids[s + i];
+ return result;
+}
+
NEXTPNR_NAMESPACE_END
diff --git a/common/idstringlist.h b/common/idstringlist.h
index 6a6a554d..24a46731 100644
--- a/common/idstringlist.h
+++ b/common/idstringlist.h
@@ -64,6 +64,9 @@ struct IdStringList
}
return false;
}
+
+ static IdStringList concat(IdStringList a, IdStringList b);
+ IdStringList slice(size_t s, size_t e) const;
};
NEXTPNR_NAMESPACE_END
diff --git a/cyclonev/arch.cc b/cyclonev/arch.cc
index 642806e3..eff6660e 100644
--- a/cyclonev/arch.cc
+++ b/cyclonev/arch.cc
@@ -18,6 +18,7 @@
#include <algorithm>
+#include "log.h"
#include "nextpnr.h"
#include "cyclonev.h"
@@ -41,6 +42,19 @@ Arch::Arch(ArchArgs args)
this->cyclonev = mistral::CycloneV::get_model(args.device, args.mistral_root);
NPNR_ASSERT(this->cyclonev != nullptr);
+ // Setup fast identifier maps
+ for (int i = 0; i < 1024; i++) {
+ IdString int_id = id(stringf("%d", i));
+ int2id.push_back(int_id);
+ id2int[int_id] = i;
+ }
+
+ for (int t = int(CycloneV::NONE); t <= int(CycloneV::DCMUX); t++) {
+ IdString rnode_id = id(CycloneV::rnode_type_names[t]);
+ rn_t2id.push_back(rnode_id);
+ id2rn_t[rnode_id] = CycloneV::rnode_type_t(t);
+ }
+
for (int x = 0; x < cyclonev->get_tile_sx(); x++) {
for (int y = 0; y < cyclonev->get_tile_sy(); y++) {
CycloneV::pos_t pos = cyclonev->xy2pos(x, y);
@@ -56,13 +70,13 @@ Arch::Arch(ArchArgs args)
* One ALM contains 2 LUT outputs and 4 flop outputs.
*/
for (int z = 0; z < 60; z++) {
- this->bel_list.push_back(BelId(pos, z));
+ bels[BelId(pos, (bel << 8 | z))];
}
break;
case CycloneV::block_type_t::GPIO:
// GPIO tiles contain 4 pins.
for (int z = 0; z < 4; z++) {
- this->bel_list.push_back(BelId(pos, z));
+ bels[BelId(pos, (bel << 8 | z))];
}
break;
default:
@@ -71,44 +85,25 @@ Arch::Arch(ArchArgs args)
}
}
}
+
+ BaseArch::init_cell_types();
+ BaseArch::init_bel_buckets();
}
int Arch::getTileBelDimZ(int x, int y) const
{
- CycloneV::pos_t pos = cyclonev->xy2pos(x, y);
-
- for (CycloneV::block_type_t bel : cyclonev->pos_get_bels(pos)) {
- switch (bel) {
- case CycloneV::block_type_t::LAB:
- /*
- * nextpnr and mistral disagree on what a BEL is: mistral thinks an entire LAB
- * is one BEL, but nextpnr wants something with more precision.
- *
- * One LAB contains 10 ALMs.
- * One ALM contains 2 LUT outputs and 4 flop outputs.
- */
- return 60;
- case CycloneV::block_type_t::GPIO:
- // GPIO tiles contain 4 pins.
- return 4;
- default:
- continue;
- }
- }
-
- // As a temporary hack, only LABs and IO are allowed to be placed, so every other tile type has zero BELs.
- return 0;
+ // FIXME: currently encoding type in z (this will be fixed soon when site contents are implemented)
+ return 16384;
}
BelId Arch::getBelByName(IdStringList name) const
{
- char bel_type_str[80] = {0};
- int x = 0, y = 0, z = 0;
BelId bel;
-
- sscanf(name[0].c_str(this), "%25s.%d.%d.%d", bel_type_str, &x, &y, &z);
-
- auto bel_type = cyclonev->block_type_lookup(std::string{bel_type_str});
+ NPNR_ASSERT(name.size() == 4);
+ auto bel_type = cyclonev->block_type_lookup(name[0].str(this));
+ int x = id2int.at(name[1]);
+ int y = id2int.at(name[2]);
+ int z = id2int.at(name[3]);
bel.pos = CycloneV::xy2pos(x, y);
bel.z = (bel_type << 8) | z;
@@ -118,16 +113,70 @@ BelId Arch::getBelByName(IdStringList name) const
IdStringList Arch::getBelName(BelId bel) const
{
- char bel_str[80] = {0};
-
int x = CycloneV::pos2x(bel.pos);
int y = CycloneV::pos2y(bel.pos);
int z = bel.z & 0xFF;
int bel_type = bel.z >> 8;
- snprintf(bel_str, 80, "%s.%03d.%03d.%03d", cyclonev->block_type_names[bel_type], x, y, z);
+ std::array<IdString, 4> ids{
+ id(cyclonev->block_type_names[bel_type]),
+ int2id.at(x),
+ int2id.at(y),
+ int2id.at(z),
+ };
+
+ return IdStringList(ids);
+}
- return IdStringList(id(bel_str));
+WireId Arch::getWireByName(IdStringList name) const
+{
+ // non-mistral wires
+ auto found_npnr = npnr_wirebyname.find(name);
+ if (found_npnr != npnr_wirebyname.end())
+ return found_npnr->second;
+ // mistral wires
+ NPNR_ASSERT(name.size() == 4);
+ CycloneV::rnode_type_t ty = id2rn_t.at(name[0]);
+ int x = id2int.at(name[1]);
+ int y = id2int.at(name[2]);
+ int z = id2int.at(name[3]);
+ return WireId(CycloneV::rnode(ty, x, y, z));
+}
+
+IdStringList Arch::getWireName(WireId wire) const
+{
+ if (wire.is_nextpnr_created()) {
+ // non-mistral wires
+ std::array<IdString, 4> ids{
+ id_WIRE,
+ int2id.at(CycloneV::rn2x(wire.node)),
+ int2id.at(CycloneV::rn2y(wire.node)),
+ wires.at(wire).name_override,
+ };
+ return IdStringList(ids);
+ } else {
+ std::array<IdString, 4> ids{
+ rn_t2id.at(CycloneV::rn2t(wire.node)),
+ int2id.at(CycloneV::rn2x(wire.node)),
+ int2id.at(CycloneV::rn2y(wire.node)),
+ int2id.at(CycloneV::rn2z(wire.node)),
+ };
+ return IdStringList(ids);
+ }
+}
+
+PipId Arch::getPipByName(IdStringList name) const
+{
+ WireId src = getWireByName(name.slice(0, 4));
+ WireId dst = getWireByName(name.slice(4, 8));
+ NPNR_ASSERT(src != WireId());
+ NPNR_ASSERT(dst != WireId());
+ return PipId(src.node, dst.node);
+}
+
+IdStringList Arch::getPipName(PipId pip) const
+{
+ return IdStringList::concat(getWireName(getPipSrcWire(pip)), getWireName(getPipDstWire(pip)));
}
std::vector<BelId> Arch::getBelsByTile(int x, int y) const
@@ -148,13 +197,13 @@ std::vector<BelId> Arch::getBelsByTile(int x, int y) const
* One ALM contains 2 LUT outputs and 4 flop outputs.
*/
for (int z = 0; z < 60; z++) {
- bels.push_back(BelId(pos, z));
+ bels.push_back(BelId(pos, (cvbel << 8 | z)));
}
break;
case CycloneV::block_type_t::GPIO:
// GPIO tiles contain 4 pins.
for (int z = 0; z < 4; z++) {
- bels.push_back(BelId(pos, z));
+ bels.push_back(BelId(pos, (cvbel << 8 | z)));
}
break;
default:
diff --git a/cyclonev/arch.h b/cyclonev/arch.h
index 4e6443c4..11f0162b 100644
--- a/cyclonev/arch.h
+++ b/cyclonev/arch.h
@@ -46,13 +46,7 @@ struct PinInfo
struct BelInfo
{
- IdString name, type;
- std::map<IdString, std::string> attrs;
- CellInfo *bound_cell;
- std::unordered_map<IdString, PinInfo> pins;
- DecalXY decalxy;
- int x, y, z;
- bool gb;
+ // TODO
};
struct WireInfo
@@ -125,12 +119,13 @@ template <typename T> struct key_range
};
using AllWireRange = key_range<std::unordered_map<WireId, WireInfo>>;
+using AllBelRange = key_range<std::unordered_map<BelId, BelInfo>>;
struct ArchRanges : BaseArchRanges
{
using ArchArgsT = ArchArgs;
// Bels
- using AllBelsRangeT = const std::vector<BelId> &;
+ using AllBelsRangeT = AllBelRange;
using TileBelsRangeT = std::vector<BelId>;
using BelPinsRangeT = std::vector<IdString>;
// Wires
@@ -147,9 +142,6 @@ struct Arch : BaseArch<ArchRanges>
ArchArgs args;
mistral::CycloneV *cyclonev;
- std::unordered_map<BelId, BelInfo> bels;
- std::vector<BelId> bel_list;
-
Arch(ArchArgs args);
ArchArgs archArgs() const { return args; }
@@ -159,18 +151,26 @@ struct Arch : BaseArch<ArchRanges>
int getGridDimX() const override { return cyclonev->get_tile_sx(); }
int getGridDimY() const override { return cyclonev->get_tile_sy(); }
int getTileBelDimZ(int x, int y) const override; // arch.cc
+ char getNameDelimiter() const override { return '.'; }
// -------------------------------------------------
BelId getBelByName(IdStringList name) const override; // arch.cc
IdStringList getBelName(BelId bel) const override; // arch.cc
- const std::vector<BelId> &getBels() const override { return bel_list; }
+ AllBelRange getBels() const override { return AllBelRange(bels); }
std::vector<BelId> getBelsByTile(int x, int y) const override;
Loc getBelLocation(BelId bel) const override
{
return Loc(CycloneV::pos2x(bel.pos), CycloneV::pos2y(bel.pos), bel.z);
}
- BelId getBelByLocation(Loc loc) const override { return BelId(CycloneV::xy2pos(loc.x, loc.y), loc.z); }
+ BelId getBelByLocation(Loc loc) const override
+ {
+ BelId id = BelId(CycloneV::xy2pos(loc.x, loc.y), loc.z);
+ if (bels.count(id))
+ return id;
+ else
+ return BelId();
+ }
IdString getBelType(BelId bel) const override; // arch.cc
WireId getBelPinWire(BelId bel, IdString pin) const override { return WireId(); }
PortType getBelPinType(BelId bel, IdString pin) const override { return PORT_IN; }
@@ -178,18 +178,18 @@ struct Arch : BaseArch<ArchRanges>
// -------------------------------------------------
- WireId getWireByName(IdStringList name) const override { return WireId(); }
- IdStringList getWireName(WireId wire) const override { return IdStringList(); }
+ WireId getWireByName(IdStringList name) const override;
+ IdStringList getWireName(WireId wire) const override;
DelayQuad getWireDelay(WireId wire) const override { return DelayQuad(0); }
const std::vector<BelPin> &getWireBelPins(WireId wire) const override { return empty_belpin_list; }
AllWireRange getWires() const override { return AllWireRange(wires); }
// -------------------------------------------------
- PipId getPipByName(IdStringList name) const override { return PipId(); }
+ PipId getPipByName(IdStringList name) const override;
const std::unordered_set<PipId> &getPips() const override { return all_pips; }
Loc getPipLocation(PipId pip) const override { return Loc(0, 0, 0); }
- IdStringList getPipName(PipId pip) const override { return IdStringList(); }
+ IdStringList getPipName(PipId pip) const override;
WireId getPipSrcWire(PipId pip) const override { return WireId(pip.src); };
WireId getPipDstWire(PipId pip) const override { return WireId(pip.dst); };
DelayQuad getPipDelay(PipId pip) const override { return DelayQuad(0); }
@@ -228,11 +228,22 @@ struct Arch : BaseArch<ArchRanges>
static const std::vector<std::string> availableRouters;
std::unordered_map<WireId, WireInfo> wires;
+ std::unordered_map<BelId, BelInfo> bels;
// WIP to link without failure
std::unordered_set<PipId> all_pips;
std::vector<PipId> empty_pip_list;
std::vector<BelPin> empty_belpin_list;
+
+ // Conversion between numbers and rnode types and IdString, for fast wire name implementation
+ std::vector<IdString> int2id;
+ std::unordered_map<IdString, int> id2int;
+
+ std::vector<IdString> rn_t2id;
+ std::unordered_map<IdString, CycloneV::rnode_type_t> id2rn_t;
+
+ // This structure is only used for nextpnr-created wires
+ std::unordered_map<IdStringList, WireId> npnr_wirebyname;
};
NEXTPNR_NAMESPACE_END
diff --git a/cyclonev/constids.inc b/cyclonev/constids.inc
index 7efee143..bb9fee55 100644
--- a/cyclonev/constids.inc
+++ b/cyclonev/constids.inc
@@ -49,3 +49,5 @@ X(D1)
X(CI)
X(CO)
X(SO)
+
+X(WIRE) \ No newline at end of file