Update FPGA interchange to use IdStringList.

Signed-off-by: Keith Rothman <537074+litghost@users.noreply.github.com>
This commit is contained in:
Keith Rothman 2021-02-03 13:37:58 -08:00
parent 083f6afb1c
commit 78737ab01d
2 changed files with 138 additions and 133 deletions

View File

@ -35,13 +35,6 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
static std::pair<std::string, std::string> split_identifier_name(const std::string &name)
{
size_t first_slash = name.find('/');
NPNR_ASSERT(first_slash != std::string::npos);
return std::make_pair(name.substr(0, first_slash), name.substr(first_slash + 1));
};
static std::pair<std::string, std::string> split_identifier_name_dot(const std::string &name) static std::pair<std::string, std::string> split_identifier_name_dot(const std::string &name)
{ {
size_t first_dot = name.find('.'); size_t first_dot = name.find('.');
@ -103,7 +96,7 @@ void Arch::setup_byname() const
{ {
if (tile_by_name.empty()) { if (tile_by_name.empty()) {
for (int i = 0; i < chip_info->num_tiles; i++) { for (int i = 0; i < chip_info->num_tiles; i++) {
tile_by_name[chip_info->tiles[i].name.get()] = i; tile_by_name[id(chip_info->tiles[i].name.get())] = i;
} }
} }
@ -113,24 +106,25 @@ void Arch::setup_byname() const
auto &tile_type = chip_info->tile_types[tile.type]; auto &tile_type = chip_info->tile_types[tile.type];
for (int j = 0; j < tile_type.number_sites; j++) { for (int j = 0; j < tile_type.number_sites; j++) {
auto &site = chip_info->sites[tile.sites[j]]; auto &site = chip_info->sites[tile.sites[j]];
site_by_name[site.name.get()] = std::make_pair(i, j); site_by_name[id(site.name.get())] = std::make_pair(i, j);
} }
} }
} }
} }
BelId Arch::getBelByName(IdString name) const BelId Arch::getBelByName(IdStringList name) const
{ {
BelId ret; BelId ret;
if(name.ids.size() != 2) {
return BelId();
}
setup_byname(); setup_byname();
auto split = split_identifier_name(name.str(this));
int tile, site; int tile, site;
std::tie(tile, site) = site_by_name.at(split.first); std::tie(tile, site) = site_by_name.at(name.ids[0]);
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
IdString belname = id(split.second); IdString belname = name.ids[1];
for (int i = 0; i < tile_info.num_bels; i++) { for (int i = 0; i < tile_info.num_bels; i++) {
if (tile_info.bel_data[i].site == site && tile_info.bel_data[i].name == belname.index) { if (tile_info.bel_data[i].site == site && tile_info.bel_data[i].name == belname.index) {
ret.tile = tile; ret.tile = tile;
@ -191,23 +185,22 @@ PortType Arch::getBelPinType(BelId bel, IdString pin) const
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
WireId Arch::getWireByName(IdString name) const WireId Arch::getWireByName(IdStringList name) const
{ {
if (wire_by_name_cache.count(name))
return wire_by_name_cache.at(name);
WireId ret; WireId ret;
if(name.ids.size() != 2) {
return WireId();
}
setup_byname(); setup_byname();
const std::string &s = name.str(this); auto iter = site_by_name.find(name.ids[0]);
auto sp = split_identifier_name(s);
auto iter = site_by_name.find(sp.first);
if (iter != site_by_name.end()) { if (iter != site_by_name.end()) {
int tile; int tile;
int site; int site;
std::tie(tile, site) = iter->second; std::tie(tile, site) = iter->second;
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
IdString wirename = id(sp.second); IdString wirename = name.ids[1];
for (int i = 0; i < tile_info.num_wires; i++) { for (int i = 0; i < tile_info.num_wires; i++) {
if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == wirename.index) { if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == wirename.index) {
ret.tile = tile; ret.tile = tile;
@ -216,9 +209,9 @@ WireId Arch::getWireByName(IdString name) const
} }
} }
} else { } else {
int tile = tile_by_name.at(sp.first); int tile = tile_by_name.at(name.ids[0]);
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
IdString wirename = id(sp.second); IdString wirename = name.ids[1];
for (int i = 0; i < tile_info.num_wires; i++) { for (int i = 0; i < tile_info.num_wires; i++) {
if (tile_info.wire_data[i].site == -1 && tile_info.wire_data[i].name == wirename.index) { if (tile_info.wire_data[i].site == -1 && tile_info.wire_data[i].name == wirename.index) {
int32_t node = chip_info->tiles[tile].tile_wire_to_node[i]; int32_t node = chip_info->tiles[tile].tile_wire_to_node[i];
@ -236,8 +229,6 @@ WireId Arch::getWireByName(IdString name) const
} }
} }
wire_by_name_cache[name] = ret;
return ret; return ret;
} }
@ -249,35 +240,29 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
// ----------------------------------------------------------------------- // -----------------------------------------------------------------------
PipId Arch::getPipByName(IdString name) const PipId Arch::getPipByName(IdStringList name) const
{ {
// PIP name structure: // PIP name structure:
// Tile PIP: <tile name>/<source wire name>.<destination wire name> // Tile PIP: <tile name>/<source wire name>.<destination wire name>
// Site PIP: <site name>/<bel name>/<input bel pin name> // Site PIP: <site name>/<bel name>/<input bel pin name>
// Site pin: <site name>/<bel name> // Site pin: <site name>/<bel name>
// Psuedo site PIP: <site name>/<source wire name>.<destination wire name>
PipId ret;
setup_byname(); setup_byname();
const std::string &s = name.str(this); if(name.ids.size() == 3) {
auto sp = split_identifier_name(s); // This is a Site PIP.
auto iter = site_by_name.find(sp.first); IdString site_name = name.ids[0];
if (iter != site_by_name.end()) { IdString belname = name.ids[1];
// This is either a site pip or site pin. IdString pinname = name.ids[2];
int tile; int tile;
int site; int site;
std::tie(tile, site) = iter->second; std::tie(tile, site) = site_by_name.at(site_name);
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
// psuedo site pips are <site>/<src site wire>.<dst site wire> std::array<IdString, 2> ids{name.ids[0], belname};
// site pips are <site>/<bel>/<pin> BelId bel = getBelByName(IdStringList(ids));
// site pins are <site>/<bel>
auto split = sp.second.find('/');
if(split != std::string::npos) {
// This is a site pip!
IdString belname = id(sp.second.substr(0, split));
IdString pinname = id(sp.second.substr(split+1));
BelId bel = getBelByName(id(sp.first + '/' + belname.str(this)));
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
int pin_index = getBelPinIndex(bel, pinname); int pin_index = getBelPinIndex(bel, pinname);
@ -287,13 +272,26 @@ PipId Arch::getPipByName(IdString name) const
if (tile_info.pip_data[i].site == site && if (tile_info.pip_data[i].site == site &&
tile_info.pip_data[i].bel == bel.index && tile_info.pip_data[i].bel == bel.index &&
tile_info.pip_data[i].extra_data == pin_index) { tile_info.pip_data[i].extra_data == pin_index) {
PipId ret;
ret.tile = tile; ret.tile = tile;
ret.index = i; ret.index = i;
break; return ret;
} }
} }
} else { } else {
auto split = sp.second.find('.'); auto iter = site_by_name.find(name.ids[0]);
if (iter != site_by_name.end()) {
// This is either a site pin or a psuedo site pip.
// psuedo site pips are <site>/<src site wire>.<dst site wire>
// site pins are <site>/<bel>
int tile;
int site;
std::tie(tile, site) = iter->second;
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
std::string pip_second = name.ids[1].str(this);
auto split = pip_second.find('.');
if(split == std::string::npos) { if(split == std::string::npos) {
// This is a site pin! // This is a site pin!
BelId bel = getBelByName(name); BelId bel = getBelByName(name);
@ -302,17 +300,20 @@ PipId Arch::getPipByName(IdString name) const
for (int i = 0; i < tile_info.num_pips; i++) { for (int i = 0; i < tile_info.num_pips; i++) {
if (tile_info.pip_data[i].site == site && if (tile_info.pip_data[i].site == site &&
tile_info.pip_data[i].bel == bel.index) { tile_info.pip_data[i].bel == bel.index) {
PipId ret;
ret.tile = tile; ret.tile = tile;
ret.index = i; ret.index = i;
break; return ret;
} }
} }
} else { } else {
// This is a psuedo site pip! // This is a psuedo site pip!
IdString src_site_wire = id(sp.second.substr(0, split)); IdString src_site_wire = id(pip_second.substr(0, split));
IdString dst_site_wire = id(sp.second.substr(split+1)); IdString dst_site_wire = id(pip_second.substr(split+1));
int32_t src_index = -1; int32_t src_index = -1;
int32_t dst_index = -1; int32_t dst_index = -1;
for (int i = 0; i < tile_info.num_wires; i++) { for (int i = 0; i < tile_info.num_wires; i++) {
if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == src_site_wire.index) { if (tile_info.wire_data[i].site == site && tile_info.wire_data[i].name == src_site_wire.index) {
src_index = i; src_index = i;
@ -335,18 +336,20 @@ PipId Arch::getPipByName(IdString name) const
if (tile_info.pip_data[i].site == site && if (tile_info.pip_data[i].site == site &&
tile_info.pip_data[i].src_index == src_index && tile_info.pip_data[i].src_index == src_index &&
tile_info.pip_data[i].dst_index == dst_index) { tile_info.pip_data[i].dst_index == dst_index) {
PipId ret;
ret.tile = tile; ret.tile = tile;
ret.index = i; ret.index = i;
break; return ret;
}
} }
} }
} }
} else { } else {
int tile = tile_by_name.at(sp.first); int tile = tile_by_name.at(name.ids[0]);
auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type]; auto &tile_info = chip_info->tile_types[chip_info->tiles[tile].type];
auto spn = split_identifier_name_dot(sp.second); std::string pip_second = name.ids[1].str(this);
auto spn = split_identifier_name_dot(pip_second);
auto src_wire_name = id(spn.first); auto src_wire_name = id(spn.first);
auto dst_wire_name = id(spn.second); auto dst_wire_name = id(spn.second);
@ -373,17 +376,20 @@ PipId Arch::getPipByName(IdString name) const
for (int i = 0; i < tile_info.num_pips; i++) { for (int i = 0; i < tile_info.num_pips; i++) {
if (tile_info.pip_data[i].src_index == src_index && if (tile_info.pip_data[i].src_index == src_index &&
tile_info.pip_data[i].dst_index == dst_index) { tile_info.pip_data[i].dst_index == dst_index) {
PipId ret;
ret.tile = tile; ret.tile = tile;
ret.index = i; ret.index = i;
break; return ret;
}
} }
} }
} }
return ret; return PipId();
} }
IdString Arch::getPipName(PipId pip) const IdStringList Arch::getPipName(PipId pip) const
{ {
// PIP name structure: // PIP name structure:
// Tile PIP: <tile name>/<source wire name>.<destination wire name> // Tile PIP: <tile name>/<source wire name>.<destination wire name>
@ -401,24 +407,30 @@ IdString Arch::getPipName(PipId pip) const
IdString bel_name(bel.name); IdString bel_name(bel.name);
if(bel.category == BEL_CATEGORY_LOGIC) { if(bel.category == BEL_CATEGORY_LOGIC) {
// This is a psuedo pip // This is a psuedo pip
IdString src_wire_name = IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].src_index].name); IdString src_wire_name = IdString(tile_type.wire_data[pip_info.src_index].name);
IdString dst_wire_name = IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].dst_index].name); IdString dst_wire_name = IdString(tile_type.wire_data[pip_info.dst_index].name);
return id(site.name.get() + std::string("/") + src_wire_name.str(this) + "." + dst_wire_name.str(this)); IdString pip = id(src_wire_name.str(this) + "." + dst_wire_name.str(this));
std::array<IdString, 2> ids{id(site.name.get()), pip};
return IdStringList(ids);
} else if(bel.category == BEL_CATEGORY_ROUTING) { } else if(bel.category == BEL_CATEGORY_ROUTING) {
// This is a site pip. // This is a site pip.
IdString pin_name(bel.ports[pip_info.extra_data]); IdString pin_name(bel.ports[pip_info.extra_data]);
return id(site.name.get() + std::string("/") + bel_name.str(this) + "/" + pin_name.str(this)); std::array<IdString, 3> ids{id(site.name.get()), bel_name, pin_name};
return IdStringList(ids);
} else { } else {
NPNR_ASSERT(bel.category == BEL_CATEGORY_SITE_PORT); NPNR_ASSERT(bel.category == BEL_CATEGORY_SITE_PORT);
// This is a site pin, just the name of the BEL is a unique identifier. // This is a site pin, just the name of the BEL is a unique identifier.
return id(site.name.get() + std::string("/") + bel_name.str(this)); std::array<IdString, 2> ids{id(site.name.get()), bel_name};
return IdStringList(ids);
} }
} else { } else {
// This is a tile pip. // This is a tile pip.
return id(std::string(tile.name.get()) + "/" + IdString src_wire_name = IdString(tile_type.wire_data[pip_info.src_index].name);
IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].src_index].name).str(this) + "." + IdString dst_wire_name = IdString(tile_type.wire_data[pip_info.dst_index].name);
IdString(tile_type.wire_data[locInfo(pip).pip_data[pip.index].dst_index].name).str(this)); IdString pip = id(src_wire_name.str(this) + "." + dst_wire_name.str(this));
std::array<IdString, 2> ids{id(std::string(tile.name.get())), pip};
return IdStringList(ids);
} }
} }

View File

@ -29,8 +29,6 @@
NEXTPNR_NAMESPACE_BEGIN NEXTPNR_NAMESPACE_BEGIN
#include "fpga_interchange_generated_defs.h"
/**** Everything in this section must be kept in sync with chipdb.py ****/ /**** Everything in this section must be kept in sync with chipdb.py ****/
template <typename T> struct RelPtr template <typename T> struct RelPtr
@ -705,8 +703,8 @@ struct Arch : BaseCtx
boost::iostreams::mapped_file_source blob_file; boost::iostreams::mapped_file_source blob_file;
const ChipInfoPOD *chip_info; const ChipInfoPOD *chip_info;
mutable std::unordered_map<std::string, int> tile_by_name; mutable std::unordered_map<IdString, int> tile_by_name;
mutable std::unordered_map<std::string, std::pair<int, int>> site_by_name; mutable std::unordered_map<IdString, std::pair<int, int>> site_by_name;
std::unordered_map<WireId, NetInfo *> wire_to_net; std::unordered_map<WireId, NetInfo *> wire_to_net;
std::unordered_map<PipId, NetInfo *> pip_to_net; std::unordered_map<PipId, NetInfo *> pip_to_net;
@ -715,11 +713,10 @@ struct Arch : BaseCtx
struct TileStatus struct TileStatus
{ {
std::bitset<kMaxNumberOfCells> bel_available;
std::vector<CellInfo *> boundcells; std::vector<CellInfo *> boundcells;
}; };
std::unordered_map<TileStatus> tileStatus; std::vector<TileStatus> tileStatus;
ArchArgs args; ArchArgs args;
Arch(ArchArgs args); Arch(ArchArgs args);
@ -755,21 +752,22 @@ struct Arch : BaseCtx
int getTilePipDimZ(int x, int y) const { int getTilePipDimZ(int x, int y) const {
return chip_info->tile_types[chip_info->tiles[getTileIndex(x, y)].type].number_sites; return chip_info->tile_types[chip_info->tiles[getTileIndex(x, y)].type].number_sites;
} }
char getNameDelimiter() const { return '/'; }
// ------------------------------------------------- // -------------------------------------------------
void setup_byname() const; void setup_byname() const;
BelId getBelByName(IdString name) const; BelId getBelByName(IdStringList name) const;
IdString getBelName(BelId bel) const IdStringList getBelName(BelId bel) const
{ {
NPNR_ASSERT(bel != BelId()); NPNR_ASSERT(bel != BelId());
int site_index = locInfo(bel).bel_data[bel.index].site; int site_index = locInfo(bel).bel_data[bel.index].site;
NPNR_ASSERT(site_index >= 0); NPNR_ASSERT(site_index >= 0);
const SiteInstInfoPOD &site = chip_info->sites[chip_info->tiles[bel.tile].sites[site_index]]; const SiteInstInfoPOD &site = chip_info->sites[chip_info->tiles[bel.tile].sites[site_index]];
return id(std::string(site.name.get()) + std::array<IdString, 2> ids{id(site.name.get()), IdString(locInfo(bel).bel_data[bel.index].name)};
"/" + IdString(locInfo(bel).bel_data[bel.index].name).str(this)); return IdStringList(ids);
} }
uint32_t getBelChecksum(BelId bel) const { return bel.index; } uint32_t getBelChecksum(BelId bel) const { return bel.index; }
@ -880,7 +878,7 @@ struct Arch : BaseCtx
IdStringRange str_range; IdStringRange str_range;
str_range.b.cursor = &ports[0]; str_range.b.cursor = &ports[0];
str_range.b.cursor = &ports[num_bel_wires-1]; str_range.e.cursor = &ports[num_bel_wires-1];
return str_range; return str_range;
} }
@ -889,9 +887,7 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
mutable std::unordered_map<IdString, WireId> wire_by_name_cache; WireId getWireByName(IdStringList name) const;
WireId getWireByName(IdString name) const;
const TileWireInfoPOD &wireInfo(WireId wire) const const TileWireInfoPOD &wireInfo(WireId wire) const
{ {
@ -903,20 +899,21 @@ struct Arch : BaseCtx
} }
} }
IdString getWireName(WireId wire) const IdStringList getWireName(WireId wire) const
{ {
NPNR_ASSERT(wire != WireId()); NPNR_ASSERT(wire != WireId());
if (wire.tile != -1 && locInfo(wire).wire_data[wire.index].site != -1) { if (wire.tile != -1 && locInfo(wire).wire_data[wire.index].site != -1) {
int site_index = locInfo(wire).wire_data[wire.index].site; int site_index = locInfo(wire).wire_data[wire.index].site;
const SiteInstInfoPOD &site = chip_info->sites[chip_info->tiles[wire.tile].sites[site_index]]; const SiteInstInfoPOD &site = chip_info->sites[chip_info->tiles[wire.tile].sites[site_index]];
return id(site.name.get() +
std::string("/") + IdString(locInfo(wire).wire_data[wire.index].name).str(this)); std::array<IdString, 2> ids{id(site.name.get()), IdString(locInfo(wire).wire_data[wire.index].name)};
return IdStringList(ids);
} else { } else {
return id(std::string(chip_info int32_t tile = wire.tile == -1 ? chip_info->nodes[wire.index].tile_wires[0].tile
->tiles[wire.tile == -1 ? chip_info->nodes[wire.index].tile_wires[0].tile : wire.tile;
: wire.tile] IdString tile_name = id(chip_info->tiles[tile].name.get());
.name.get()) + std::array<IdString, 2> ids{tile_name, IdString(wireInfo(wire).name)};
"/" + IdString(wireInfo(wire).name).c_str(this)); return IdStringList(ids);
} }
} }
@ -1042,9 +1039,10 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
mutable std::unordered_map<IdString, PipId> pip_by_name_cache; PipId getPipByName(IdStringList name) const;
IdStringList getPipName(PipId pip) const;
PipId getPipByName(IdString name) const; IdString getPipType(PipId pip) const;
std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
void bindPip(PipId pip, NetInfo *net, PlaceStrength strength) void bindPip(PipId pip, NetInfo *net, PlaceStrength strength)
{ {
@ -1126,11 +1124,6 @@ struct Arch : BaseCtx
return loc; return loc;
} }
IdString getPipName(PipId pip) const;
IdString getPipType(PipId pip) const;
std::vector<std::pair<IdString, std::string>> getPipAttrs(PipId pip) const;
uint32_t getPipChecksum(PipId pip) const { return pip.index; } uint32_t getPipChecksum(PipId pip) const { return pip.index; }
WireId getPipSrcWire(PipId pip) const WireId getPipSrcWire(PipId pip) const
@ -1185,8 +1178,8 @@ struct Arch : BaseCtx
// ------------------------------------------------- // -------------------------------------------------
// FIXME: Use groups to get access to sites. // FIXME: Use groups to get access to sites.
GroupId getGroupByName(IdString name) const { return GroupId(); } GroupId getGroupByName(IdStringList name) const { return GroupId(); }
IdString getGroupName(GroupId group) const { return IdString(); } IdStringList getGroupName(GroupId group) const { return IdStringList(); }
std::vector<GroupId> getGroups() const { return {}; } std::vector<GroupId> getGroups() const { return {}; }
std::vector<BelId> getGroupBels(GroupId group) const { return {}; } std::vector<BelId> getGroupBels(GroupId group) const { return {}; }
std::vector<WireId> getGroupWires(GroupId group) const { return {}; } std::vector<WireId> getGroupWires(GroupId group) const { return {}; }