Add getConflictingWireWire() arch API, streamline getConflictingXY semantic
Signed-off-by: Clifford Wolf <clifford@clifford.at>
This commit is contained in:
parent
ee8826b6e8
commit
f93129634b
@ -99,7 +99,6 @@ struct Router1
|
|||||||
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
|
std::priority_queue<QueuedWire, std::vector<QueuedWire>, QueuedWire::Greater> queue;
|
||||||
|
|
||||||
std::unordered_map<WireId, int> wireScores;
|
std::unordered_map<WireId, int> wireScores;
|
||||||
std::unordered_map<PipId, int> pipScores;
|
|
||||||
std::unordered_map<NetInfo*, int> netScores;
|
std::unordered_map<NetInfo*, int> netScores;
|
||||||
|
|
||||||
int arcs_with_ripup = 0;
|
int arcs_with_ripup = 0;
|
||||||
@ -125,6 +124,9 @@ struct Router1
|
|||||||
|
|
||||||
void arc_queue_insert(const arc_key &arc)
|
void arc_queue_insert(const arc_key &arc)
|
||||||
{
|
{
|
||||||
|
if (queued_arcs.count(arc))
|
||||||
|
return;
|
||||||
|
|
||||||
NetInfo *net_info = arc.net_info;
|
NetInfo *net_info = arc.net_info;
|
||||||
int user_idx = arc.user_idx;
|
int user_idx = arc.user_idx;
|
||||||
|
|
||||||
@ -151,10 +153,19 @@ struct Router1
|
|||||||
|
|
||||||
auto net_wires_copy = net->wires;
|
auto net_wires_copy = net->wires;
|
||||||
for (auto &it : net_wires_copy) {
|
for (auto &it : net_wires_copy) {
|
||||||
if (it.second.pip == PipId())
|
WireId w = it.first;
|
||||||
ripup_wire(it.first, 4);
|
|
||||||
else
|
for (auto &it : wire_to_arcs[w]) {
|
||||||
ripup_pip(it.second.pip, 4);
|
arc_to_wires[it].erase(w);
|
||||||
|
arc_queue_insert(it);
|
||||||
|
}
|
||||||
|
wire_to_arcs[w].clear();
|
||||||
|
|
||||||
|
if (ctx->debug)
|
||||||
|
log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx));
|
||||||
|
|
||||||
|
ctx->unbindWire(w);
|
||||||
|
wireScores[w]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ripup_flag = true;
|
ripup_flag = true;
|
||||||
@ -163,64 +174,54 @@ struct Router1
|
|||||||
void ripup_wire(WireId wire, int extra_indent = 0)
|
void ripup_wire(WireId wire, int extra_indent = 0)
|
||||||
{
|
{
|
||||||
if (ctx->debug)
|
if (ctx->debug)
|
||||||
log(" %*sripup wire %s\n", extra_indent, "", ctx->getWireName(wire).c_str(ctx));
|
log(" ripup wire %s\n", ctx->getWireName(wire).c_str(ctx));
|
||||||
|
|
||||||
wireScores[wire]++;
|
WireId w = ctx->getConflictingWireWire(wire);
|
||||||
|
|
||||||
if (ctx->getBoundWireNet(wire)) {
|
if (w == WireId()) {
|
||||||
for (auto &it : wire_to_arcs[wire]) {
|
NetInfo *n = ctx->getConflictingWireNet(wire);
|
||||||
arc_to_wires[it].erase(wire);
|
if (n != nullptr)
|
||||||
|
ripup_net(n);
|
||||||
|
} else {
|
||||||
|
for (auto &it : wire_to_arcs[w]) {
|
||||||
|
arc_to_wires[it].erase(w);
|
||||||
arc_queue_insert(it);
|
arc_queue_insert(it);
|
||||||
}
|
}
|
||||||
wire_to_arcs[wire].clear();
|
wire_to_arcs[w].clear();
|
||||||
ctx->unbindWire(wire);
|
|
||||||
}
|
|
||||||
|
|
||||||
NetInfo *net = ctx->getConflictingWireNet(wire);
|
if (ctx->debug)
|
||||||
if (net != nullptr) {
|
log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx));
|
||||||
wireScores[wire] += net->wires.size();
|
|
||||||
ripup_net(net);
|
ctx->unbindWire(w);
|
||||||
|
wireScores[w]++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ripup_flag = true;
|
ripup_flag = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ripup_pip(PipId pip, int extra_indent = 0)
|
void ripup_pip(PipId pip)
|
||||||
{
|
{
|
||||||
WireId wire = ctx->getPipDstWire(pip);
|
|
||||||
|
|
||||||
if (ctx->debug)
|
if (ctx->debug)
|
||||||
log(" %*sripup pip %s (%s)\n", extra_indent, "", ctx->getPipName(pip).c_str(ctx), ctx->getWireName(wire).c_str(ctx));
|
log(" ripup pip %s\n", ctx->getPipName(pip).c_str(ctx));
|
||||||
|
|
||||||
pipScores[pip]++;
|
WireId w = ctx->getConflictingPipWire(pip);
|
||||||
|
|
||||||
if (ctx->getBoundPipNet(pip)) {
|
if (w == WireId()) {
|
||||||
ctx->unbindPip(pip);
|
NetInfo *n = ctx->getConflictingPipNet(pip);
|
||||||
goto remove_wire_arcs;
|
if (n != nullptr)
|
||||||
}
|
ripup_net(n);
|
||||||
|
} else {
|
||||||
if (ctx->getBoundWireNet(wire)) {
|
for (auto &it : wire_to_arcs[w]) {
|
||||||
ctx->unbindWire(wire);
|
arc_to_wires[it].erase(w);
|
||||||
goto remove_wire_arcs;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (0) {
|
|
||||||
remove_wire_arcs:
|
|
||||||
wireScores[wire]++;
|
|
||||||
for (auto &it : wire_to_arcs[wire]) {
|
|
||||||
arc_to_wires[it].erase(wire);
|
|
||||||
arc_queue_insert(it);
|
arc_queue_insert(it);
|
||||||
}
|
}
|
||||||
wire_to_arcs[wire].clear();
|
wire_to_arcs[w].clear();
|
||||||
}
|
|
||||||
|
|
||||||
NetInfo *net = ctx->getConflictingPipNet(pip);
|
if (ctx->debug)
|
||||||
if (net != nullptr) {
|
log(" unbind wire %s\n", ctx->getWireName(w).c_str(ctx));
|
||||||
wire = ctx->getConflictingPipWire(pip);
|
|
||||||
if (wire != WireId())
|
ctx->unbindWire(w);
|
||||||
ripup_wire(wire, 2);
|
wireScores[w]++;
|
||||||
else
|
|
||||||
ripup_net(net);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ripup_flag = true;
|
ripup_flag = true;
|
||||||
@ -455,59 +456,82 @@ remove_wire_arcs:
|
|||||||
WireId next_wire = ctx->getPipDstWire(pip);
|
WireId next_wire = ctx->getPipDstWire(pip);
|
||||||
next_delay += ctx->getWireDelay(next_wire).maxDelay();
|
next_delay += ctx->getWireDelay(next_wire).maxDelay();
|
||||||
|
|
||||||
if (!ctx->checkWireAvail(next_wire)) {
|
WireId conflictWireWire = WireId(), conflictPipWire = WireId();
|
||||||
NetInfo *ripupWireNet = ctx->getConflictingWireNet(next_wire);
|
NetInfo *conflictWireNet = nullptr, *conflictPipNet = nullptr;
|
||||||
|
|
||||||
if (ripupWireNet == nullptr)
|
bool wire_reuse = net_info->wires.count(next_wire);
|
||||||
|
bool pip_reuse = wire_reuse && net_info->wires.at(next_wire).pip == pip;
|
||||||
|
|
||||||
|
if (!ctx->checkWireAvail(next_wire) && !wire_reuse) {
|
||||||
|
if (!ripup)
|
||||||
continue;
|
continue;
|
||||||
|
conflictWireWire = ctx->getConflictingWireWire(next_wire);
|
||||||
if (ripupWireNet == net_info) {
|
if (conflictWireWire == WireId()) {
|
||||||
next_bonus += cfg.wireReuseBonus;
|
conflictWireNet = ctx->getConflictingWireNet(next_wire);
|
||||||
} else {
|
if (conflictWireNet == nullptr)
|
||||||
if (!ripup)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
next_penalty += cfg.wireRipupPenalty;
|
|
||||||
|
|
||||||
auto scores_it = wireScores.find(next_wire);
|
|
||||||
if (scores_it != wireScores.end())
|
|
||||||
next_penalty += scores_it->second * cfg.wireRipupPenalty;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ctx->checkPipAvail(pip)) {
|
if (!ctx->checkPipAvail(pip) && !pip_reuse) {
|
||||||
NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
|
if (!ripup)
|
||||||
|
|
||||||
if (ripupPipNet == nullptr)
|
|
||||||
continue;
|
continue;
|
||||||
|
conflictPipWire = ctx->getConflictingPipWire(pip);
|
||||||
if (ripupPipNet == net_info) {
|
if (conflictPipWire == WireId()) {
|
||||||
auto net_info_wire_it = net_info->wires.find(next_wire);
|
conflictPipNet = ctx->getConflictingPipNet(pip);
|
||||||
if (net_info_wire_it == net_info->wires.end() || net_info_wire_it->second.pip != pip)
|
if (conflictPipNet == nullptr)
|
||||||
goto pip_self_ripup;
|
|
||||||
next_bonus += cfg.pipReuseBonus;
|
|
||||||
} else {
|
|
||||||
pip_self_ripup:
|
|
||||||
if (!ripup)
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
next_penalty += cfg.pipRipupPenalty;
|
|
||||||
|
|
||||||
auto pip_scores_it = pipScores.find(pip);
|
|
||||||
if (pip_scores_it != pipScores.end())
|
|
||||||
next_penalty += pip_scores_it->second * cfg.pipRipupPenalty;
|
|
||||||
|
|
||||||
if (ctx->getConflictingPipWire(pip) == WireId()) {
|
|
||||||
auto net_scores_it = netScores.find(ripupPipNet);
|
|
||||||
if (net_scores_it != netScores.end())
|
|
||||||
next_penalty += net_scores_it->second * cfg.netRipupPenalty;
|
|
||||||
|
|
||||||
next_penalty += ripupPipNet->wires.size() * cfg.wireRipupPenalty;
|
|
||||||
next_penalty += (ripupPipNet->wires.size()-1) * cfg.pipRipupPenalty;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (conflictWireNet != nullptr && conflictPipWire != WireId() && conflictWireNet->wires.count(conflictPipWire))
|
||||||
|
conflictPipWire = WireId();
|
||||||
|
|
||||||
|
if (conflictPipNet != nullptr && conflictWireWire != WireId() && conflictPipNet->wires.count(conflictWireWire))
|
||||||
|
conflictWireWire = WireId();
|
||||||
|
|
||||||
|
if (conflictWireWire == conflictPipWire)
|
||||||
|
conflictWireWire = WireId();
|
||||||
|
|
||||||
|
if (conflictWireNet == conflictPipNet)
|
||||||
|
conflictWireNet = nullptr;
|
||||||
|
|
||||||
|
if (wire_reuse)
|
||||||
|
next_bonus += cfg.wireReuseBonus;
|
||||||
|
|
||||||
|
if (pip_reuse)
|
||||||
|
next_bonus += cfg.pipReuseBonus;
|
||||||
|
|
||||||
|
if (conflictWireWire != WireId()) {
|
||||||
|
auto scores_it = wireScores.find(conflictWireWire);
|
||||||
|
if (scores_it != wireScores.end())
|
||||||
|
next_penalty += scores_it->second * cfg.wireRipupPenalty;
|
||||||
|
next_penalty += cfg.wireRipupPenalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conflictPipWire != WireId()) {
|
||||||
|
auto scores_it = wireScores.find(conflictPipWire);
|
||||||
|
if (scores_it != wireScores.end())
|
||||||
|
next_penalty += scores_it->second * cfg.wireRipupPenalty;
|
||||||
|
next_penalty += cfg.wireRipupPenalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conflictWireNet != nullptr) {
|
||||||
|
auto scores_it = netScores.find(conflictWireNet);
|
||||||
|
if (scores_it != netScores.end())
|
||||||
|
next_penalty += scores_it->second * cfg.netRipupPenalty;
|
||||||
|
next_penalty += cfg.netRipupPenalty;
|
||||||
|
next_penalty += conflictWireNet->wires.size() * cfg.wireRipupPenalty;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conflictPipNet != nullptr) {
|
||||||
|
auto scores_it = netScores.find(conflictPipNet);
|
||||||
|
if (scores_it != netScores.end())
|
||||||
|
next_penalty += scores_it->second * cfg.netRipupPenalty;
|
||||||
|
next_penalty += cfg.netRipupPenalty;
|
||||||
|
next_penalty += conflictPipNet->wires.size() * cfg.wireRipupPenalty;
|
||||||
|
}
|
||||||
|
|
||||||
delay_t next_score = next_delay + next_penalty;
|
delay_t next_score = next_delay + next_penalty;
|
||||||
NPNR_ASSERT(next_score >= 0);
|
NPNR_ASSERT(next_score >= 0);
|
||||||
|
|
||||||
@ -596,30 +620,20 @@ pip_self_ripup:
|
|||||||
if (ctx->debug)
|
if (ctx->debug)
|
||||||
log(" node %s\n", ctx->getWireName(cursor).c_str(ctx));
|
log(" node %s\n", ctx->getWireName(cursor).c_str(ctx));
|
||||||
|
|
||||||
if (!ctx->checkWireAvail(cursor)) {
|
if (pip == PipId())
|
||||||
NetInfo *ripupWireNet = ctx->getConflictingWireNet(cursor);
|
NPNR_ASSERT(cursor == src_wire);
|
||||||
NPNR_ASSERT(ripupWireNet != nullptr);
|
|
||||||
NPNR_ASSERT(ripupWireNet->wires.count(cursor));
|
|
||||||
|
|
||||||
if (ripupWireNet != net_info || net_info->wires.at(cursor).pip != pip) {
|
if (!net_info->wires.count(cursor) || net_info->wires.at(cursor).pip != pip) {
|
||||||
|
if (!ctx->checkWireAvail(cursor)) {
|
||||||
ripup_wire(cursor);
|
ripup_wire(cursor);
|
||||||
NPNR_ASSERT(ctx->checkWireAvail(cursor));
|
NPNR_ASSERT(ctx->checkWireAvail(cursor));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (pip == PipId()) {
|
if (pip != PipId() && !ctx->checkPipAvail(pip)) {
|
||||||
NPNR_ASSERT(cursor == src_wire);
|
ripup_pip(pip);
|
||||||
} else {
|
NPNR_ASSERT(ctx->checkPipAvail(pip));
|
||||||
if (!ctx->checkPipAvail(pip)) {
|
|
||||||
NetInfo *ripupPipNet = ctx->getConflictingPipNet(pip);
|
|
||||||
NPNR_ASSERT(ripupPipNet != nullptr);
|
|
||||||
|
|
||||||
if (ripupPipNet != net_info || !net_info->wires.count(cursor) || net_info->wires.at(cursor).pip != pip)
|
|
||||||
ripup_pip(pip);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (net_info->wires.count(cursor) == 0 || net_info->wires.at(cursor).pip != pip) {
|
|
||||||
if (pip == PipId()) {
|
if (pip == PipId()) {
|
||||||
if (ctx->debug)
|
if (ctx->debug)
|
||||||
log(" bind wire %s\n", ctx->getWireName(cursor).c_str(ctx));
|
log(" bind wire %s\n", ctx->getWireName(cursor).c_str(ctx));
|
||||||
@ -661,11 +675,10 @@ Router1Cfg::Router1Cfg(Context *ctx) : Settings(ctx)
|
|||||||
useEstimate = get<bool>("router1/useEstimate", true);
|
useEstimate = get<bool>("router1/useEstimate", true);
|
||||||
|
|
||||||
wireRipupPenalty = ctx->getRipupDelayPenalty();
|
wireRipupPenalty = ctx->getRipupDelayPenalty();
|
||||||
pipRipupPenalty = ctx->getRipupDelayPenalty();
|
netRipupPenalty = 10*ctx->getRipupDelayPenalty();
|
||||||
netRipupPenalty = ctx->getRipupDelayPenalty();
|
|
||||||
|
|
||||||
wireReuseBonus = wireRipupPenalty/8;
|
wireReuseBonus = wireRipupPenalty/8;
|
||||||
pipReuseBonus = pipRipupPenalty/8;
|
pipReuseBonus = wireRipupPenalty/2;
|
||||||
|
|
||||||
estimatePrecision = 100 * ctx->getRipupDelayPenalty();
|
estimatePrecision = 100 * ctx->getRipupDelayPenalty();
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ struct Router1Cfg : Settings
|
|||||||
bool fullCleanupReroute;
|
bool fullCleanupReroute;
|
||||||
bool useEstimate;
|
bool useEstimate;
|
||||||
delay_t wireRipupPenalty;
|
delay_t wireRipupPenalty;
|
||||||
delay_t pipRipupPenalty;
|
|
||||||
delay_t netRipupPenalty;
|
delay_t netRipupPenalty;
|
||||||
delay_t wireReuseBonus;
|
delay_t wireReuseBonus;
|
||||||
delay_t pipReuseBonus;
|
delay_t pipReuseBonus;
|
||||||
|
@ -215,14 +215,15 @@ Return true if the wire is available, i.e. can be bound to a net.
|
|||||||
|
|
||||||
Return the net a wire is bound to.
|
Return the net a wire is bound to.
|
||||||
|
|
||||||
### NetInfo \*getConflictingWireNet(WireId wire) const
|
### WireId getConflictingWireWire(WireId wire) const
|
||||||
|
|
||||||
If this returns a non-nullptr, then unbinding the wire from that net
|
If this returns a non-WireId(), then unbinding that wire
|
||||||
will make the given wire available.
|
will make the given wire available.
|
||||||
|
|
||||||
This returns nullptr if the wire is already available,
|
### NetInfo \*getConflictingWireNet(WireId wire) const
|
||||||
or if there is no net that can be unbound from the wire to make it
|
|
||||||
available.
|
If this returns a non-nullptr, then unbinding that entire net
|
||||||
|
will make the given wire available.
|
||||||
|
|
||||||
### DelayInfo getWireDelay(WireId wire) const
|
### DelayInfo getWireDelay(WireId wire) const
|
||||||
|
|
||||||
@ -282,28 +283,23 @@ This method must also update `NetInfo::wires`.
|
|||||||
|
|
||||||
Returns true if the given pip is available to be bound to a net.
|
Returns true if the given pip is available to be bound to a net.
|
||||||
|
|
||||||
|
Users must also check if the pip destination wire is available
|
||||||
|
with `checkWireAvail(getPipDstWire(pip))` before binding the
|
||||||
|
pip to a net.
|
||||||
|
|
||||||
### NetInfo \*getBoundPipNet(PipId pip) const
|
### NetInfo \*getBoundPipNet(PipId pip) const
|
||||||
|
|
||||||
Return the net this pip is bound to.
|
Return the net this pip is bound to.
|
||||||
|
|
||||||
### NetInfo \*getConflictingPipNet(PipId pip) const
|
|
||||||
|
|
||||||
Return the net that needs to be unbound in order to make this
|
|
||||||
pip available. Note that it may be neccessary to unroute that
|
|
||||||
entire net to make the pip available.
|
|
||||||
|
|
||||||
This returns nullptr if the pip is already available,
|
|
||||||
or if there is no single net that can be unrouted to make
|
|
||||||
the pip available.
|
|
||||||
|
|
||||||
### WireId getConflictingPipWire(PipId pip) const
|
### WireId getConflictingPipWire(PipId pip) const
|
||||||
|
|
||||||
Return the single wire that needs to be unbound in order to make this pip
|
If this returns a non-WireId(), then unbinding that wire
|
||||||
available.
|
will make the given pip available.
|
||||||
|
|
||||||
This returns WireId() if the pip is already available,
|
### NetInfo \*getConflictingPipNet(PipId pip) const
|
||||||
or if there is no single wire that can be unbound to make
|
|
||||||
the pip available.
|
If this returns a non-nullptr, then unbinding that entire net
|
||||||
|
will make the given pip available.
|
||||||
|
|
||||||
### const\_range\<PipId\> getPips() const
|
### const\_range\<PipId\> getPips() const
|
||||||
|
|
||||||
|
15
ecp5/arch.h
15
ecp5/arch.h
@ -619,6 +619,11 @@ struct Arch : BaseCtx
|
|||||||
return wire_to_net.at(wire);
|
return wire_to_net.at(wire);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WireId getConflictingWireWire(WireId wire) const
|
||||||
|
{
|
||||||
|
return wire;
|
||||||
|
}
|
||||||
|
|
||||||
NetInfo *getConflictingWireNet(WireId wire) const
|
NetInfo *getConflictingWireNet(WireId wire) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -724,6 +729,11 @@ struct Arch : BaseCtx
|
|||||||
return pip_to_net.at(pip);
|
return pip_to_net.at(pip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WireId getConflictingPipWire(PipId pip) const
|
||||||
|
{
|
||||||
|
return WireId();
|
||||||
|
}
|
||||||
|
|
||||||
NetInfo *getConflictingPipNet(PipId pip) const
|
NetInfo *getConflictingPipNet(PipId pip) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
@ -733,11 +743,6 @@ struct Arch : BaseCtx
|
|||||||
return pip_to_net.at(pip);
|
return pip_to_net.at(pip);
|
||||||
}
|
}
|
||||||
|
|
||||||
WireId getConflictingPipWire(PipId pip) const
|
|
||||||
{
|
|
||||||
return WireId();
|
|
||||||
}
|
|
||||||
|
|
||||||
AllPipRange getPips() const
|
AllPipRange getPips() const
|
||||||
{
|
{
|
||||||
AllPipRange range;
|
AllPipRange range;
|
||||||
|
@ -172,6 +172,7 @@ struct Arch : BaseCtx
|
|||||||
void unbindWire(WireId wire);
|
void unbindWire(WireId wire);
|
||||||
bool checkWireAvail(WireId wire) const;
|
bool checkWireAvail(WireId wire) const;
|
||||||
NetInfo *getBoundWireNet(WireId wire) const;
|
NetInfo *getBoundWireNet(WireId wire) const;
|
||||||
|
WireId getConflictingWireWire(WireId wire) const { return wire; }
|
||||||
NetInfo *getConflictingWireNet(WireId wire) const;
|
NetInfo *getConflictingWireNet(WireId wire) const;
|
||||||
DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
|
DelayInfo getWireDelay(WireId wire) const { return DelayInfo(); }
|
||||||
const std::vector<WireId> &getWires() const;
|
const std::vector<WireId> &getWires() const;
|
||||||
@ -186,8 +187,8 @@ struct Arch : BaseCtx
|
|||||||
void unbindPip(PipId pip);
|
void unbindPip(PipId pip);
|
||||||
bool checkPipAvail(PipId pip) const;
|
bool checkPipAvail(PipId pip) const;
|
||||||
NetInfo *getBoundPipNet(PipId pip) const;
|
NetInfo *getBoundPipNet(PipId pip) const;
|
||||||
NetInfo *getConflictingPipNet(PipId pip) const;
|
|
||||||
WireId getConflictingPipWire(PipId pip) const;
|
WireId getConflictingPipWire(PipId pip) const;
|
||||||
|
NetInfo *getConflictingPipNet(PipId pip) const;
|
||||||
const std::vector<PipId> &getPips() const;
|
const std::vector<PipId> &getPips() const;
|
||||||
Loc getPipLocation(PipId pip) const;
|
Loc getPipLocation(PipId pip) const;
|
||||||
WireId getPipSrcWire(PipId pip) const;
|
WireId getPipSrcWire(PipId pip) const;
|
||||||
|
@ -453,6 +453,8 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
|
|||||||
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
|
addProperty(topItem, QVariant::String, "Type", ctx->getWireType(wire).c_str(ctx));
|
||||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkWireAvail(wire));
|
||||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundWireNet(wire)), ElementType::NET);
|
||||||
|
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->getWireName(ctx->getConflictingWireWire(wire)).c_str(ctx),
|
||||||
|
ElementType::WIRE);
|
||||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingWireNet(wire)),
|
||||||
ElementType::NET);
|
ElementType::NET);
|
||||||
|
|
||||||
@ -513,10 +515,10 @@ void DesignWidget::onSelectionChanged(const QItemSelection &, const QItemSelecti
|
|||||||
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
|
addProperty(topItem, QVariant::String, "Type", ctx->getPipType(pip).c_str(ctx));
|
||||||
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
addProperty(topItem, QVariant::Bool, "Available", ctx->checkPipAvail(pip));
|
||||||
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
|
addProperty(topItem, QVariant::String, "Bound Net", ctx->nameOf(ctx->getBoundPipNet(pip)), ElementType::NET);
|
||||||
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
|
|
||||||
ElementType::NET);
|
|
||||||
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx),
|
addProperty(topItem, QVariant::String, "Conflicting Wire", ctx->getWireName(ctx->getConflictingPipWire(pip)).c_str(ctx),
|
||||||
ElementType::WIRE);
|
ElementType::WIRE);
|
||||||
|
addProperty(topItem, QVariant::String, "Conflicting Net", ctx->nameOf(ctx->getConflictingPipNet(pip)),
|
||||||
|
ElementType::NET);
|
||||||
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
|
addProperty(topItem, QVariant::String, "Src Wire", ctx->getWireName(ctx->getPipSrcWire(pip)).c_str(ctx),
|
||||||
ElementType::WIRE);
|
ElementType::WIRE);
|
||||||
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
|
addProperty(topItem, QVariant::String, "Dest Wire", ctx->getWireName(ctx->getPipDstWire(pip)).c_str(ctx),
|
||||||
|
45
ice40/arch.h
45
ice40/arch.h
@ -566,6 +566,11 @@ struct Arch : BaseCtx
|
|||||||
return wire_to_net[wire.index];
|
return wire_to_net[wire.index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WireId getConflictingWireWire(WireId wire) const
|
||||||
|
{
|
||||||
|
return wire;
|
||||||
|
}
|
||||||
|
|
||||||
NetInfo *getConflictingWireNet(WireId wire) const
|
NetInfo *getConflictingWireNet(WireId wire) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(wire != WireId());
|
NPNR_ASSERT(wire != WireId());
|
||||||
@ -642,28 +647,34 @@ struct Arch : BaseCtx
|
|||||||
refreshUiWire(dst);
|
refreshUiWire(dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool checkPipAvail(PipId pip) const
|
bool ice40_pip_hard_unavail(PipId pip) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pip != PipId());
|
NPNR_ASSERT(pip != PipId());
|
||||||
auto &pi = chip_info->pip_data[pip.index];
|
auto &pi = chip_info->pip_data[pip.index];
|
||||||
auto &si = chip_info->bits_info->switches[pi.switch_index];
|
auto &si = chip_info->bits_info->switches[pi.switch_index];
|
||||||
|
|
||||||
if (switches_locked[pi.switch_index] != WireId())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
|
if (pi.flags & PipInfoPOD::FLAG_ROUTETHRU) {
|
||||||
NPNR_ASSERT(si.bel >= 0);
|
NPNR_ASSERT(si.bel >= 0);
|
||||||
if (bel_to_cell[si.bel] != nullptr)
|
if (bel_to_cell[si.bel] != nullptr)
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pi.flags & PipInfoPOD::FLAG_NOCARRY) {
|
if (pi.flags & PipInfoPOD::FLAG_NOCARRY) {
|
||||||
NPNR_ASSERT(si.bel >= 0);
|
NPNR_ASSERT(si.bel >= 0);
|
||||||
if (bel_carry[si.bel])
|
if (bel_carry[si.bel])
|
||||||
return false;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkPipAvail(PipId pip) const
|
||||||
|
{
|
||||||
|
if (ice40_pip_hard_unavail(pip))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto &pi = chip_info->pip_data[pip.index];
|
||||||
|
return switches_locked[pi.switch_index] == WireId();
|
||||||
}
|
}
|
||||||
|
|
||||||
NetInfo *getBoundPipNet(PipId pip) const
|
NetInfo *getBoundPipNet(PipId pip) const
|
||||||
@ -672,19 +683,23 @@ struct Arch : BaseCtx
|
|||||||
return pip_to_net[pip.index];
|
return pip_to_net[pip.index];
|
||||||
}
|
}
|
||||||
|
|
||||||
NetInfo *getConflictingPipNet(PipId pip) const
|
|
||||||
{
|
|
||||||
NPNR_ASSERT(pip != PipId());
|
|
||||||
WireId wire = switches_locked[chip_info->pip_data[pip.index].switch_index];
|
|
||||||
return wire == WireId() ? nullptr : wire_to_net[wire.index];
|
|
||||||
}
|
|
||||||
|
|
||||||
WireId getConflictingPipWire(PipId pip) const
|
WireId getConflictingPipWire(PipId pip) const
|
||||||
{
|
{
|
||||||
NPNR_ASSERT(pip != PipId());
|
if (ice40_pip_hard_unavail(pip))
|
||||||
|
return WireId();
|
||||||
|
|
||||||
return switches_locked[chip_info->pip_data[pip.index].switch_index];
|
return switches_locked[chip_info->pip_data[pip.index].switch_index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetInfo *getConflictingPipNet(PipId pip) const
|
||||||
|
{
|
||||||
|
if (ice40_pip_hard_unavail(pip))
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
WireId wire = switches_locked[chip_info->pip_data[pip.index].switch_index];
|
||||||
|
return wire == WireId() ? nullptr : wire_to_net[wire.index];
|
||||||
|
}
|
||||||
|
|
||||||
AllPipRange getPips() const
|
AllPipRange getPips() const
|
||||||
{
|
{
|
||||||
AllPipRange range;
|
AllPipRange range;
|
||||||
|
Loading…
Reference in New Issue
Block a user