From 5d1b8bf74469d0d5c5cc15e8c8e042da55da5357 Mon Sep 17 00:00:00 2001 From: gatecat Date: Sat, 1 May 2021 14:55:33 +0100 Subject: cyclonev: Add names and archcheck fixes Signed-off-by: gatecat --- common/idstringlist.cc | 19 ++++++++ common/idstringlist.h | 3 ++ cyclonev/arch.cc | 123 ++++++++++++++++++++++++++++++++++--------------- cyclonev/arch.h | 45 +++++++++++------- cyclonev/constids.inc | 2 + 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 +#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 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 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 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 Arch::getBelsByTile(int x, int y) const @@ -148,13 +197,13 @@ std::vector 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 attrs; - CellInfo *bound_cell; - std::unordered_map pins; - DecalXY decalxy; - int x, y, z; - bool gb; + // TODO }; struct WireInfo @@ -125,12 +119,13 @@ template struct key_range }; using AllWireRange = key_range>; +using AllBelRange = key_range>; struct ArchRanges : BaseArchRanges { using ArchArgsT = ArchArgs; // Bels - using AllBelsRangeT = const std::vector &; + using AllBelsRangeT = AllBelRange; using TileBelsRangeT = std::vector; using BelPinsRangeT = std::vector; // Wires @@ -147,9 +142,6 @@ struct Arch : BaseArch ArchArgs args; mistral::CycloneV *cyclonev; - std::unordered_map bels; - std::vector bel_list; - Arch(ArchArgs args); ArchArgs archArgs() const { return args; } @@ -159,18 +151,26 @@ struct Arch : BaseArch 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 &getBels() const override { return bel_list; } + AllBelRange getBels() const override { return AllBelRange(bels); } std::vector 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 // ------------------------------------------------- - 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 &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 &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 static const std::vector availableRouters; std::unordered_map wires; + std::unordered_map bels; // WIP to link without failure std::unordered_set all_pips; std::vector empty_pip_list; std::vector empty_belpin_list; + + // Conversion between numbers and rnode types and IdString, for fast wire name implementation + std::vector int2id; + std::unordered_map id2int; + + std::vector rn_t2id; + std::unordered_map id2rn_t; + + // This structure is only used for nextpnr-created wires + std::unordered_map 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 -- cgit v1.2.3