Starts placement onto all Xilinx sites
This commit is contained in:
parent
45009ac09d
commit
8cddc49abc
61
xc7/arch.cc
61
xc7/arch.cc
@ -32,6 +32,12 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
|
||||
const DDB *ddb = nullptr;
|
||||
const Sites *ddbSites = nullptr;
|
||||
const Tiles *ddbTiles = nullptr;
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
void IdString::initialize_arch(const BaseCtx *ctx)
|
||||
@ -61,6 +67,9 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
// }
|
||||
// if (package_info == nullptr)
|
||||
// log_error("Unsupported package '%s'.\n", args.package.c_str());
|
||||
|
||||
ddbSites = &ddb->getSites();
|
||||
ddbTiles = &ddb->getTiles();
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
@ -89,14 +98,9 @@ BelId Arch::getBelByName(IdString name) const
|
||||
{
|
||||
BelId ret;
|
||||
|
||||
if (bel_by_name.empty()) {
|
||||
for (int i = 0; i < chip_info->num_bels; i++)
|
||||
bel_by_name[id(chip_info->bel_data[i].name.get())] = i;
|
||||
}
|
||||
|
||||
auto it = bel_by_name.find(name);
|
||||
if (it != bel_by_name.end())
|
||||
ret.index = it->second;
|
||||
auto it = ddbSites->findSiteIndex(name.str(this));
|
||||
if (it != SiteIndex(-1))
|
||||
ret.index = it;
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -106,32 +110,29 @@ BelId Arch::getBelByLocation(Loc loc) const
|
||||
BelId bel;
|
||||
|
||||
if (bel_by_loc.empty()) {
|
||||
for (int i = 0; i < chip_info->num_bels; i++) {
|
||||
for (SiteIndex i(0); i < ddbSites->getSiteCount(); ++i) {
|
||||
BelId b;
|
||||
b.index = i;
|
||||
bel_by_loc[getBelLocation(b)] = i;
|
||||
bel_by_loc[getBelLocation(b)] = b;
|
||||
}
|
||||
}
|
||||
|
||||
auto it = bel_by_loc.find(loc);
|
||||
if (it != bel_by_loc.end())
|
||||
bel.index = it->second;
|
||||
bel = it->second;
|
||||
|
||||
return bel;
|
||||
}
|
||||
|
||||
BelRange Arch::getBelsByTile(int x, int y) const
|
||||
{
|
||||
// In iCE40 chipdb bels at the same tile are consecutive and dense z ordinates
|
||||
// are used
|
||||
BelRange br;
|
||||
|
||||
br.b.cursor = Arch::getBelByLocation(Loc(x, y, 0)).index;
|
||||
br.b.cursor = std::next(ddbSites->getSites().begin(), Arch::getBelByLocation(Loc(x, y, 0)).index);
|
||||
br.e.cursor = br.b.cursor;
|
||||
|
||||
if (br.e.cursor != -1) {
|
||||
while (br.e.cursor < chip_info->num_bels && chip_info->bel_data[br.e.cursor].x == x &&
|
||||
chip_info->bel_data[br.e.cursor].y == y)
|
||||
if (br.e.cursor != ddbSites->getSites().end()) {
|
||||
while (br.e.cursor < ddbSites->getSites().end() && ddbSites->getSite((*br.e).index).getTileIndex() == ddbSites->getSite((*br.b).index).getTileIndex())
|
||||
br.e.cursor++;
|
||||
}
|
||||
|
||||
@ -316,23 +317,23 @@ IdString Arch::getPipName(PipId pip) const
|
||||
|
||||
BelId Arch::getPackagePinBel(const std::string &pin) const
|
||||
{
|
||||
for (int i = 0; i < package_info->num_pins; i++) {
|
||||
if (package_info->pins[i].name.get() == pin) {
|
||||
BelId id;
|
||||
id.index = package_info->pins[i].bel_index;
|
||||
return id;
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < package_info->num_pins; i++) {
|
||||
// if (package_info->pins[i].name.get() == pin) {
|
||||
// BelId id;
|
||||
// id.index = package_info->pins[i].bel_index;
|
||||
// return id;
|
||||
// }
|
||||
// }
|
||||
return BelId();
|
||||
}
|
||||
|
||||
std::string Arch::getBelPackagePin(BelId bel) const
|
||||
{
|
||||
for (int i = 0; i < package_info->num_pins; i++) {
|
||||
if (package_info->pins[i].bel_index == bel.index) {
|
||||
return std::string(package_info->pins[i].name.get());
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < package_info->num_pins; i++) {
|
||||
// if (package_info->pins[i].bel_index == bel.index) {
|
||||
// return std::string(package_info->pins[i].name.get());
|
||||
// }
|
||||
// }
|
||||
return "";
|
||||
}
|
||||
|
||||
@ -617,7 +618,7 @@ std::vector<GraphicElement> Arch::getDecalGraphics(DecalId decal) const
|
||||
|
||||
if (decal.type == DecalId::TYPE_BEL) {
|
||||
BelId bel;
|
||||
bel.index = decal.index;
|
||||
bel.index = SiteIndex(decal.index);
|
||||
|
||||
auto bel_type = getBelType(bel);
|
||||
|
||||
|
60
xc7/arch.h
60
xc7/arch.h
@ -24,6 +24,7 @@
|
||||
#include "torc/Architecture.hpp"
|
||||
#include "torc/Common.hpp"
|
||||
using namespace torc::architecture;
|
||||
using namespace torc::architecture::xilinx;
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
@ -231,23 +232,17 @@ NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||
RelPtr<CellTimingPOD> cell_timing;
|
||||
});
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
extern const char *chipdb_blob_384;
|
||||
extern const char *chipdb_blob_1k;
|
||||
extern const char *chipdb_blob_5k;
|
||||
extern const char *chipdb_blob_8k;
|
||||
#else
|
||||
extern const char chipdb_blob_384[];
|
||||
extern const char chipdb_blob_1k[];
|
||||
extern const char chipdb_blob_5k[];
|
||||
extern const char chipdb_blob_8k[];
|
||||
#endif
|
||||
|
||||
extern const DDB *ddb;
|
||||
extern const Sites *ddbSites;
|
||||
extern const Tiles *ddbTiles;
|
||||
|
||||
|
||||
/************************ End of chipdb section. ************************/
|
||||
|
||||
struct BelIterator
|
||||
{
|
||||
int cursor;
|
||||
Array<const Site>::iterator cursor;
|
||||
|
||||
BelIterator operator++()
|
||||
{
|
||||
@ -268,7 +263,7 @@ struct BelIterator
|
||||
BelId operator*() const
|
||||
{
|
||||
BelId ret;
|
||||
ret.index = cursor;
|
||||
ret.index = SiteIndex(std::distance(ddbSites->getSites().begin(), cursor));
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
@ -284,16 +279,17 @@ struct BelRange
|
||||
|
||||
struct BelPinIterator
|
||||
{
|
||||
const BelPortPOD *ptr = nullptr;
|
||||
const BelId bel;
|
||||
Array<const WireIndex>::iterator it;
|
||||
|
||||
void operator++() { ptr++; }
|
||||
bool operator!=(const BelPinIterator &other) const { return ptr != other.ptr; }
|
||||
void operator++() { it++; }
|
||||
bool operator!=(const BelPinIterator &other) const { return it != other.it && bel != other.bel; }
|
||||
|
||||
BelPin operator*() const
|
||||
{
|
||||
BelPin ret;
|
||||
ret.bel.index = ptr->bel_index;
|
||||
ret.pin = ptr->port;
|
||||
ret.bel = bel;
|
||||
ret.pin = IdString();
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
@ -391,13 +387,11 @@ struct Arch : BaseCtx
|
||||
{
|
||||
bool fast_part;
|
||||
const ChipInfoPOD *chip_info;
|
||||
const DDB *ddb;
|
||||
const PackageInfoPOD *package_info;
|
||||
|
||||
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;
|
||||
mutable std::unordered_map<Loc, int> bel_by_loc;
|
||||
mutable std::unordered_map<Loc, BelId> bel_by_loc;
|
||||
|
||||
std::vector<bool> bel_carry;
|
||||
std::vector<CellInfo *> bel_to_cell;
|
||||
@ -428,7 +422,7 @@ struct Arch : BaseCtx
|
||||
IdString getBelName(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return id(chip_info->bel_data[bel.index].name.get());
|
||||
return id(ddbSites->getSite(bel.index).getName());
|
||||
}
|
||||
|
||||
uint32_t getBelChecksum(BelId bel) const { return bel.index; }
|
||||
@ -477,17 +471,19 @@ struct Arch : BaseCtx
|
||||
BelRange getBels() const
|
||||
{
|
||||
BelRange range;
|
||||
range.b.cursor = 0;
|
||||
range.e.cursor = chip_info->num_bels;
|
||||
range.b.cursor = ddbSites->getSites().begin();
|
||||
range.e.cursor = ddbSites->getSites().end();
|
||||
return range;
|
||||
}
|
||||
|
||||
Loc getBelLocation(BelId bel) const
|
||||
{
|
||||
const auto& site = ddbSites->getSite(bel.index);
|
||||
const auto& tile_info = ddbTiles->getTileInfo(site.getTileIndex());
|
||||
Loc loc;
|
||||
loc.x = chip_info->bel_data[bel.index].x;
|
||||
loc.y = chip_info->bel_data[bel.index].y;
|
||||
loc.z = chip_info->bel_data[bel.index].z;
|
||||
loc.x = tile_info.getCol();
|
||||
loc.y = tile_info.getRow();
|
||||
loc.z = 0;
|
||||
return loc;
|
||||
}
|
||||
|
||||
@ -499,7 +495,9 @@ struct Arch : BaseCtx
|
||||
IdString getBelType(BelId bel) const
|
||||
{
|
||||
NPNR_ASSERT(bel != BelId());
|
||||
return IdString(chip_info->bel_data[bel.index].type);
|
||||
const auto& site = ddbSites->getSite(bel.index);
|
||||
const auto& tile_info = ddbTiles->getTileInfo(site.getTileIndex());
|
||||
return id(ddbTiles->getTileTypeName(tile_info.getTypeIndex()));
|
||||
}
|
||||
|
||||
WireId getBelPinWire(BelId bel, IdString pin) const;
|
||||
@ -582,9 +580,9 @@ struct Arch : BaseCtx
|
||||
BelPinRange getWireBelPins(WireId wire) const
|
||||
{
|
||||
BelPinRange range;
|
||||
NPNR_ASSERT(wire != WireId());
|
||||
range.b.ptr = chip_info->wire_data[wire.index].bel_pins.get();
|
||||
range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bel_pins;
|
||||
//NPNR_ASSERT(wire != WireId());
|
||||
//range.b.ptr = chip_info->wire_data[wire.index].bel_pins.get();
|
||||
//range.e.ptr = range.b.ptr + chip_info->wire_data[wire.index].num_bel_pins;
|
||||
return range;
|
||||
}
|
||||
|
||||
|
@ -93,70 +93,70 @@ bool Arch::isBelLocationValid(BelId bel) const
|
||||
|
||||
bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
|
||||
{
|
||||
if (cell->type == id_ICESTORM_LC) {
|
||||
NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC);
|
||||
|
||||
std::array<const CellInfo *, 8> bel_cells;
|
||||
size_t num_cells = 0;
|
||||
|
||||
Loc bel_loc = getBelLocation(bel);
|
||||
for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
|
||||
CellInfo *ci_other = getBoundBelCell(bel_other);
|
||||
if (ci_other != nullptr && bel_other != bel)
|
||||
bel_cells[num_cells++] = ci_other;
|
||||
}
|
||||
|
||||
bel_cells[num_cells++] = cell;
|
||||
return logicCellsCompatible(bel_cells.data(), num_cells);
|
||||
} else if (cell->type == id_SB_IO) {
|
||||
// Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to.
|
||||
|
||||
// Find shared PLL by looking for driving bel siblings from D_IN_0
|
||||
// that are a PLL clock output.
|
||||
auto wire = getBelPinWire(bel, id_D_IN_0);
|
||||
IdString pll_bel_pin;
|
||||
BelId pll_bel;
|
||||
for (auto pin : getWireBelPins(wire)) {
|
||||
if (pin.pin == id_PLLOUT_A || pin.pin == id_PLLOUT_B) {
|
||||
pll_bel = pin.bel;
|
||||
pll_bel_pin = pin.pin;
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Is there a PLL that shares this IO buffer?
|
||||
if (pll_bel.index != -1) {
|
||||
auto pll_cell = getBoundBelCell(pll_bel);
|
||||
// Is a PLL placed in this PLL bel?
|
||||
if (pll_cell != nullptr) {
|
||||
// Is the shared port driving a net?
|
||||
auto pi = pll_cell->ports[pll_bel_pin];
|
||||
if (pi.net != nullptr) {
|
||||
// Are we perhaps a PAD INPUT Bel that can be placed here?
|
||||
if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return getBelPackagePin(bel) != "";
|
||||
} else if (cell->type == id_SB_GB) {
|
||||
NPNR_ASSERT(cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net != nullptr);
|
||||
const NetInfo *net = cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net;
|
||||
IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT));
|
||||
int glb_id = std::stoi(std::string("") + glb_net.str(this).back());
|
||||
if (net->is_reset && net->is_enable)
|
||||
return false;
|
||||
else if (net->is_reset)
|
||||
return (glb_id % 2) == 0;
|
||||
else if (net->is_enable)
|
||||
return (glb_id % 2) == 1;
|
||||
else
|
||||
return true;
|
||||
} else {
|
||||
// TODO: IO cell clock checks
|
||||
// if (cell->type == id_ICESTORM_LC) {
|
||||
// NPNR_ASSERT(getBelType(bel) == id_ICESTORM_LC);
|
||||
//
|
||||
// std::array<const CellInfo *, 8> bel_cells;
|
||||
// size_t num_cells = 0;
|
||||
//
|
||||
// Loc bel_loc = getBelLocation(bel);
|
||||
// for (auto bel_other : getBelsByTile(bel_loc.x, bel_loc.y)) {
|
||||
// CellInfo *ci_other = getBoundBelCell(bel_other);
|
||||
// if (ci_other != nullptr && bel_other != bel)
|
||||
// bel_cells[num_cells++] = ci_other;
|
||||
// }
|
||||
//
|
||||
// bel_cells[num_cells++] = cell;
|
||||
// return logicCellsCompatible(bel_cells.data(), num_cells);
|
||||
// } else if (cell->type == id_SB_IO) {
|
||||
// // Do not allow placement of input SB_IOs on blocks where there a PLL is outputting to.
|
||||
//
|
||||
// // Find shared PLL by looking for driving bel siblings from D_IN_0
|
||||
// // that are a PLL clock output.
|
||||
// auto wire = getBelPinWire(bel, id_D_IN_0);
|
||||
// IdString pll_bel_pin;
|
||||
// BelId pll_bel;
|
||||
// for (auto pin : getWireBelPins(wire)) {
|
||||
// if (pin.pin == id_PLLOUT_A || pin.pin == id_PLLOUT_B) {
|
||||
// pll_bel = pin.bel;
|
||||
// pll_bel_pin = pin.pin;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// // Is there a PLL that shares this IO buffer?
|
||||
// if (pll_bel.index != -1) {
|
||||
// auto pll_cell = getBoundBelCell(pll_bel);
|
||||
// // Is a PLL placed in this PLL bel?
|
||||
// if (pll_cell != nullptr) {
|
||||
// // Is the shared port driving a net?
|
||||
// auto pi = pll_cell->ports[pll_bel_pin];
|
||||
// if (pi.net != nullptr) {
|
||||
// // Are we perhaps a PAD INPUT Bel that can be placed here?
|
||||
// if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(this)) {
|
||||
// return true;
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return getBelPackagePin(bel) != "";
|
||||
// } else if (cell->type == id_SB_GB) {
|
||||
// NPNR_ASSERT(cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net != nullptr);
|
||||
// const NetInfo *net = cell->ports.at(id_GLOBAL_BUFFER_OUTPUT).net;
|
||||
// IdString glb_net = getWireName(getBelPinWire(bel, id_GLOBAL_BUFFER_OUTPUT));
|
||||
// int glb_id = std::stoi(std::string("") + glb_net.str(this).back());
|
||||
// if (net->is_reset && net->is_enable)
|
||||
// return false;
|
||||
// else if (net->is_reset)
|
||||
// return (glb_id % 2) == 0;
|
||||
// else if (net->is_enable)
|
||||
// return (glb_id % 2) == 1;
|
||||
// else
|
||||
// return true;
|
||||
// } else {
|
||||
// // TODO: IO cell clock checks
|
||||
return true;
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -21,6 +21,9 @@
|
||||
#error Include "archdefs.h" via "nextpnr.h" only.
|
||||
#endif
|
||||
|
||||
#include "torc/Architecture.hpp"
|
||||
using namespace torc::architecture::xilinx;
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
typedef int delay_t;
|
||||
@ -62,7 +65,7 @@ enum ConstIds
|
||||
|
||||
struct BelId
|
||||
{
|
||||
int32_t index = -1;
|
||||
SiteIndex index = SiteIndex(-1);
|
||||
|
||||
bool operator==(const BelId &other) const { return index == other.index; }
|
||||
bool operator!=(const BelId &other) const { return index != other.index; }
|
||||
|
Loading…
Reference in New Issue
Block a user