Merge branch 'master' of github.com:YosysHQ/nextpnr
This commit is contained in:
commit
8531658019
2
.github/workflows/interchange_ci.yml
vendored
2
.github/workflows/interchange_ci.yml
vendored
@ -114,7 +114,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright
|
RAPIDWRIGHT_PATH: ${{ github.workspace }}/RapidWright
|
||||||
PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange
|
PYTHON_INTERCHANGE_PATH: ${{ github.workspace }}/python-fpga-interchange
|
||||||
PYTHON_INTERCHANGE_TAG: v0.0.15
|
PYTHON_INTERCHANGE_TAG: v0.0.16
|
||||||
PRJOXIDE_REVISION: 1bf30dee9c023c4c66cfc44fd0bc28addd229c89
|
PRJOXIDE_REVISION: 1bf30dee9c023c4c66cfc44fd0bc28addd229c89
|
||||||
DEVICE: ${{ matrix.device }}
|
DEVICE: ${{ matrix.device }}
|
||||||
run: |
|
run: |
|
||||||
|
@ -855,7 +855,7 @@ struct Arch : ArchAPI<ArchRanges>
|
|||||||
const CellInfo *cell = tile_status.boundcells[bel.index];
|
const CellInfo *cell = tile_status.boundcells[bel.index];
|
||||||
|
|
||||||
if (cell != nullptr) {
|
if (cell != nullptr) {
|
||||||
if (cell->cluster == ClusterId() && !dedicated_interconnect.isBelLocationValid(bel, cell))
|
if (!dedicated_interconnect.isBelLocationValid(bel, cell))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (io_port_types.count(cell->type)) {
|
if (io_port_types.count(cell->type)) {
|
||||||
|
@ -193,6 +193,8 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel,
|
|||||||
const Context *ctx = getCtx();
|
const Context *ctx = getCtx();
|
||||||
const Cluster &packed_cluster = clusters.at(cluster);
|
const Cluster &packed_cluster = clusters.at(cluster);
|
||||||
|
|
||||||
|
auto &cluster_data = cluster_info(chip_info, packed_cluster.index);
|
||||||
|
|
||||||
CellInfo *root_cell = getClusterRootCell(cluster);
|
CellInfo *root_cell = getClusterRootCell(cluster);
|
||||||
if (!ctx->isValidBelForCellType(root_cell->type, root_bel))
|
if (!ctx->isValidBelForCellType(root_cell->type, root_bel))
|
||||||
return false;
|
return false;
|
||||||
@ -205,8 +207,6 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel,
|
|||||||
next_bel = root_bel;
|
next_bel = root_bel;
|
||||||
} else {
|
} else {
|
||||||
// Find next chained cluster node
|
// Find next chained cluster node
|
||||||
auto &cluster_data = cluster_info(chip_info, packed_cluster.index);
|
|
||||||
|
|
||||||
IdString next_bel_pin(cluster_data.chainable_ports[0].bel_source);
|
IdString next_bel_pin(cluster_data.chainable_ports[0].bel_source);
|
||||||
WireId next_bel_pin_wire = ctx->getBelPinWire(next_bel, next_bel_pin);
|
WireId next_bel_pin_wire = ctx->getBelPinWire(next_bel, next_bel_pin);
|
||||||
next_bel = BelId();
|
next_bel = BelId();
|
||||||
@ -256,7 +256,8 @@ bool Arch::getClusterPlacement(ClusterId cluster, BelId root_bel,
|
|||||||
WireId bel_pin_wire = ctx->getBelPinWire(next_bel, bel_pin);
|
WireId bel_pin_wire = ctx->getBelPinWire(next_bel, bel_pin);
|
||||||
|
|
||||||
ExpansionDirection direction = port_type == PORT_IN ? CLUSTER_UPHILL_DIR : CLUSTER_DOWNHILL_DIR;
|
ExpansionDirection direction = port_type == PORT_IN ? CLUSTER_UPHILL_DIR : CLUSTER_DOWNHILL_DIR;
|
||||||
pool<BelId> cluster_bels = find_cluster_bels(ctx, bel_pin_wire, direction);
|
pool<BelId> cluster_bels =
|
||||||
|
find_cluster_bels(ctx, bel_pin_wire, direction, (bool)cluster_data.out_of_site_clusters);
|
||||||
|
|
||||||
if (cluster_bels.size() == 0)
|
if (cluster_bels.size() == 0)
|
||||||
continue;
|
continue;
|
||||||
|
@ -34,7 +34,7 @@ NEXTPNR_NAMESPACE_BEGIN
|
|||||||
* kExpectedChipInfoVersion
|
* kExpectedChipInfoVersion
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static constexpr int32_t kExpectedChipInfoVersion = 11;
|
static constexpr int32_t kExpectedChipInfoVersion = 12;
|
||||||
|
|
||||||
// Flattened site indexing.
|
// Flattened site indexing.
|
||||||
//
|
//
|
||||||
@ -421,6 +421,7 @@ NPNR_PACKED_STRUCT(struct ClusterPOD {
|
|||||||
RelSlice<uint32_t> root_cell_types;
|
RelSlice<uint32_t> root_cell_types;
|
||||||
RelSlice<ChainablePortPOD> chainable_ports;
|
RelSlice<ChainablePortPOD> chainable_ports;
|
||||||
RelSlice<ClusterCellPortPOD> cluster_cells_map;
|
RelSlice<ClusterCellPortPOD> cluster_cells_map;
|
||||||
|
uint32_t out_of_site_clusters;
|
||||||
});
|
});
|
||||||
|
|
||||||
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
NPNR_PACKED_STRUCT(struct ChipInfoPOD {
|
||||||
|
@ -39,6 +39,12 @@ enum WireNodeState
|
|||||||
IN_SOURCE_SITE = 2
|
IN_SOURCE_SITE = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ExpansionDirection
|
||||||
|
{
|
||||||
|
EXPAND_DOWNHILL = 0,
|
||||||
|
EXPAND_UPHILL = 1
|
||||||
|
};
|
||||||
|
|
||||||
struct WireNode
|
struct WireNode
|
||||||
{
|
{
|
||||||
WireId wire;
|
WireId wire;
|
||||||
@ -52,6 +58,50 @@ struct WireNode
|
|||||||
// interconnect.
|
// interconnect.
|
||||||
constexpr int kMaxDepth = 6;
|
constexpr int kMaxDepth = 6;
|
||||||
|
|
||||||
|
static uint32_t get_num_pips(const Context *ctx, WireId wire, ExpansionDirection direction)
|
||||||
|
{
|
||||||
|
uint32_t num_pips = 0;
|
||||||
|
|
||||||
|
if (direction == EXPAND_DOWNHILL) {
|
||||||
|
for (PipId pip : ctx->getPipsDownhill(wire)) {
|
||||||
|
auto &pip_data = pip_info(ctx->chip_info, pip);
|
||||||
|
if (pip_data.pseudo_cell_wires.size() > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->getPipDstWire(pip) == WireId())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->is_pip_synthetic(pip))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->is_site_port(pip))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
num_pips++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NPNR_ASSERT(direction == EXPAND_UPHILL);
|
||||||
|
for (PipId pip : ctx->getPipsUphill(wire)) {
|
||||||
|
auto &pip_data = pip_info(ctx->chip_info, pip);
|
||||||
|
if (pip_data.pseudo_cell_wires.size() > 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->getPipSrcWire(pip) == WireId())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->is_pip_synthetic(pip))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (ctx->is_site_port(pip))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
num_pips++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return num_pips;
|
||||||
|
}
|
||||||
|
|
||||||
void DedicatedInterconnect::init(const Context *ctx)
|
void DedicatedInterconnect::init(const Context *ctx)
|
||||||
{
|
{
|
||||||
this->ctx = ctx;
|
this->ctx = ctx;
|
||||||
@ -99,6 +149,16 @@ bool DedicatedInterconnect::check_routing(BelId src_bel, IdString src_bel_pin, B
|
|||||||
WireNode node_to_expand = nodes_to_expand.back();
|
WireNode node_to_expand = nodes_to_expand.back();
|
||||||
nodes_to_expand.pop_back();
|
nodes_to_expand.pop_back();
|
||||||
|
|
||||||
|
auto num_pips = get_num_pips(ctx, node_to_expand.wire, EXPAND_DOWNHILL);
|
||||||
|
|
||||||
|
// Usually, dedicated interconnects do not have more than one PIPs in the out-of-site
|
||||||
|
if (node_to_expand.depth > 1 && node_to_expand.state == IN_ROUTING && num_pips > 1) {
|
||||||
|
if (ctx->verbose)
|
||||||
|
log_info("Wire %s is on a non-dedicated path (number of pips %d)\n",
|
||||||
|
ctx->nameOfWire(node_to_expand.wire), num_pips);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
|
for (PipId pip : ctx->getPipsDownhill(node_to_expand.wire)) {
|
||||||
if (ctx->is_pip_synthetic(pip)) {
|
if (ctx->is_pip_synthetic(pip)) {
|
||||||
continue;
|
continue;
|
||||||
@ -147,7 +207,7 @@ bool DedicatedInterconnect::check_routing(BelId src_bel, IdString src_bel_pin, B
|
|||||||
#ifdef DEBUG_EXPANSION
|
#ifdef DEBUG_EXPANSION
|
||||||
log_info(" - Not dedicated site routing because loop!");
|
log_info(" - Not dedicated site routing because loop!");
|
||||||
#endif
|
#endif
|
||||||
return false;
|
continue;
|
||||||
}
|
}
|
||||||
next_node.state = IN_SINK_SITE;
|
next_node.state = IN_SINK_SITE;
|
||||||
break;
|
break;
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
@ -483,37 +484,44 @@ DelayQuad Arch::getWireTypeDelay(IdString wire)
|
|||||||
|
|
||||||
void Arch::read_cst(std::istream &in)
|
void Arch::read_cst(std::istream &in)
|
||||||
{
|
{
|
||||||
std::regex iobre = std::regex("IO_LOC +\"([^\"]+)\" +([^ ;]+);");
|
std::regex iobre = std::regex("IO_LOC +\"([^\"]+)\" +([^ ;]+) *;.*");
|
||||||
|
std::regex portre = std::regex("IO_PORT +\"([^\"]+)\" +([^ =;]+=[^ =;]+) *;.*");
|
||||||
std::smatch match;
|
std::smatch match;
|
||||||
std::string line;
|
std::string line;
|
||||||
|
bool io_loc;
|
||||||
while (!in.eof()) {
|
while (!in.eof()) {
|
||||||
std::getline(in, line);
|
std::getline(in, line);
|
||||||
|
io_loc = true;
|
||||||
if (!std::regex_match(line, match, iobre)) {
|
if (!std::regex_match(line, match, iobre)) {
|
||||||
// empty line or comment
|
if (std::regex_match(line, match, portre)) {
|
||||||
if (line.empty() || line.rfind("//", 0) == 0) {
|
io_loc = false;
|
||||||
continue;
|
|
||||||
} else {
|
} else {
|
||||||
log_warning("Invalid constraint: %s\n", line.c_str());
|
if ((!line.empty()) && (line.rfind("//", 0) == std::string::npos)) {
|
||||||
|
log_warning("Invalid constraint: %s\n", line.c_str());
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// std::cout << match[1] << " " << match[2] << std::endl;
|
|
||||||
IdString net = id(match[1]);
|
IdString net = id(match[1]);
|
||||||
IdString pinname = id(match[2]);
|
|
||||||
const PairPOD *belname = pairLookup(package->pins.get(), package->num_pins, pinname.index);
|
|
||||||
if (belname == nullptr)
|
|
||||||
log_error("Pin %s not found\n", pinname.c_str(this));
|
|
||||||
// BelId bel = getBelByName(belname->src_id);
|
|
||||||
// for (auto cell : sorted(cells)) {
|
|
||||||
// std::cout << cell.first.str(this) << std::endl;
|
|
||||||
// }
|
|
||||||
auto it = cells.find(net);
|
auto it = cells.find(net);
|
||||||
if (it == cells.end()) {
|
if (it == cells.end()) {
|
||||||
log_info("Cell %s not found\n", net.c_str(this));
|
log_info("Cell %s not found\n", net.c_str(this));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
std::string bel = IdString(belname->src_id).str(this);
|
if (io_loc) { // IO_LOC name pin
|
||||||
it->second->attrs[IdString(ID_BEL)] = bel;
|
IdString pinname = id(match[2]);
|
||||||
|
const PairPOD *belname = pairLookup(package->pins.get(), package->num_pins, pinname.index);
|
||||||
|
if (belname == nullptr)
|
||||||
|
log_error("Pin %s not found\n", pinname.c_str(this));
|
||||||
|
std::string bel = IdString(belname->src_id).str(this);
|
||||||
|
it->second->attrs[IdString(ID_BEL)] = bel;
|
||||||
|
} else { // IO_PORT attr=value
|
||||||
|
std::string attr = "&";
|
||||||
|
attr += match[2];
|
||||||
|
boost::algorithm::to_upper(attr);
|
||||||
|
it->second->attrs[id(attr)] = 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user