Carry chains now routable
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
6f12f2b7e8
commit
21d5a04501
@ -1,9 +1,9 @@
|
|||||||
module top(input clk, cen, rst, ina, inb, output outa, outb, outc, outd);
|
module top(input clk, cen, rst, ina, inb, output outa, outb, outc, outd);
|
||||||
|
|
||||||
reg [3:0] ctr = 0;
|
reg [15:0] ctr = 0;
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
ctr <= ctr + 1'b1;
|
ctr <= ctr + 1'b1;
|
||||||
|
|
||||||
assign {outa, outb, outc, outd} = ctr;
|
assign {outa, outb, outc, outd} = ctr[15:12];
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -41,11 +41,11 @@
|
|||||||
#include "nextpnr.h"
|
#include "nextpnr.h"
|
||||||
#include "pack.h"
|
#include "pack.h"
|
||||||
#include "pcf.h"
|
#include "pcf.h"
|
||||||
|
#include "place_legaliser.h"
|
||||||
#include "place_sa.h"
|
#include "place_sa.h"
|
||||||
#include "route.h"
|
#include "route.h"
|
||||||
#include "timing.h"
|
#include "timing.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "place_legaliser.h"
|
|
||||||
|
|
||||||
USING_NEXTPNR_NAMESPACE
|
USING_NEXTPNR_NAMESPACE
|
||||||
|
|
||||||
|
@ -178,12 +178,27 @@ static void pack_carries(Context *ctx)
|
|||||||
std::unique_ptr<CellInfo> created_lc =
|
std::unique_ptr<CellInfo> created_lc =
|
||||||
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), cell.first.str(ctx) + "$CARRY");
|
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), cell.first.str(ctx) + "$CARRY");
|
||||||
carry_lc = created_lc.get();
|
carry_lc = created_lc.get();
|
||||||
|
created_lc->ports.at(ctx->id("I1")).net = i0_net;
|
||||||
|
if (i0_net) {
|
||||||
|
PortRef pr;
|
||||||
|
pr.cell = created_lc.get();
|
||||||
|
pr.port = ctx->id("I1");
|
||||||
|
i0_net->users.push_back(pr);
|
||||||
|
}
|
||||||
|
created_lc->ports.at(ctx->id("I2")).net = i1_net;
|
||||||
|
if (i1_net) {
|
||||||
|
PortRef pr;
|
||||||
|
pr.cell = created_lc.get();
|
||||||
|
pr.port = ctx->id("I2");
|
||||||
|
i1_net->users.push_back(pr);
|
||||||
|
}
|
||||||
new_cells.push_back(std::move(created_lc));
|
new_cells.push_back(std::move(created_lc));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
carry_lc = ctx->cells.at(*carry_lcs.begin()).get();
|
carry_lc = ctx->cells.at(*carry_lcs.begin()).get();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
carry_lc->attrs[ctx->id("CARRY_ENABLE")] = "1";
|
carry_lc->params[ctx->id("CARRY_ENABLE")] = "1";
|
||||||
replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN"));
|
replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN"));
|
||||||
replace_port(ci, ctx->id("CO"), carry_lc, ctx->id("COUT"));
|
replace_port(ci, ctx->id("CO"), carry_lc, ctx->id("COUT"));
|
||||||
if (i0_net) {
|
if (i0_net) {
|
||||||
@ -203,8 +218,8 @@ static void pack_carries(Context *ctx)
|
|||||||
if (carry_lc->ports.at(ctx->id("CIN")).net != nullptr) {
|
if (carry_lc->ports.at(ctx->id("CIN")).net != nullptr) {
|
||||||
IdString cin_net = carry_lc->ports.at(ctx->id("CIN")).net->name;
|
IdString cin_net = carry_lc->ports.at(ctx->id("CIN")).net->name;
|
||||||
if (cin_net == ctx->id("$PACKER_GND_NET") || cin_net == ctx->id("$PACKER_VCC_NET")) {
|
if (cin_net == ctx->id("$PACKER_GND_NET") || cin_net == ctx->id("$PACKER_VCC_NET")) {
|
||||||
carry_lc->attrs[ctx->id("CIN_CONST")] = "1";
|
carry_lc->params[ctx->id("CIN_CONST")] = "1";
|
||||||
carry_lc->attrs[ctx->id("CIN_SET")] = cin_net == ctx->id("$PACKER_VCC_NET") ? "1" : "0";
|
carry_lc->params[ctx->id("CIN_SET")] = cin_net == ctx->id("$PACKER_VCC_NET") ? "1" : "0";
|
||||||
carry_lc->ports.at(ctx->id("CIN")).net = nullptr;
|
carry_lc->ports.at(ctx->id("CIN")).net = nullptr;
|
||||||
auto cin_users = ctx->nets.at(cin_net)->users;
|
auto cin_users = ctx->nets.at(cin_net)->users;
|
||||||
cin_users.erase(
|
cin_users.erase(
|
||||||
|
@ -129,15 +129,36 @@ class PlacementLegaliser
|
|||||||
std::vector<CellChain> carry_chains = find_chains(
|
std::vector<CellChain> carry_chains = find_chains(
|
||||||
ctx, is_lc,
|
ctx, is_lc,
|
||||||
[](const Context *ctx, const CellInfo *cell) {
|
[](const Context *ctx, const CellInfo *cell) {
|
||||||
return net_driven_by(ctx, cell->ports.at(ctx->id("CIN")).net, is_lc, ctx->id("COUT"));
|
CellInfo *carry_prev =
|
||||||
|
net_driven_by(ctx, cell->ports.at(ctx->id("CIN")).net, is_lc, ctx->id("COUT"));
|
||||||
|
if (carry_prev != nullptr)
|
||||||
|
return carry_prev;
|
||||||
|
CellInfo *i3_prev = net_driven_by(ctx, cell->ports.at(ctx->id("I3")).net, is_lc, ctx->id("COUT"));
|
||||||
|
if (i3_prev != nullptr)
|
||||||
|
return i3_prev;
|
||||||
|
return (CellInfo *)nullptr;
|
||||||
},
|
},
|
||||||
[](const Context *ctx, const CellInfo *cell) {
|
[](const Context *ctx, const CellInfo *cell) {
|
||||||
return net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("CIN"), false);
|
CellInfo *carry_next =
|
||||||
|
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("CIN"), false);
|
||||||
|
if (carry_next != nullptr)
|
||||||
|
return carry_next;
|
||||||
|
CellInfo *i3_next =
|
||||||
|
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("I3"), false);
|
||||||
|
if (i3_next != nullptr)
|
||||||
|
return i3_next;
|
||||||
|
return (CellInfo *)nullptr;
|
||||||
});
|
});
|
||||||
bool success = true;
|
bool success = true;
|
||||||
// Find midpoints for all chains, before we start tearing them up
|
// Find midpoints for all chains, before we start tearing them up
|
||||||
std::vector<CellChain> all_chains;
|
std::vector<CellChain> all_chains;
|
||||||
for (auto &base_chain : carry_chains) {
|
for (auto &base_chain : carry_chains) {
|
||||||
|
if (ctx->verbose) {
|
||||||
|
log_info("Found carry chain: \n");
|
||||||
|
for (auto entry : base_chain.cells)
|
||||||
|
log_info(" %s\n", entry->name.c_str(ctx));
|
||||||
|
log_info("\n");
|
||||||
|
}
|
||||||
std::vector<CellChain> split_chains = split_carry_chain(base_chain);
|
std::vector<CellChain> split_chains = split_carry_chain(base_chain);
|
||||||
for (auto &chain : split_chains) {
|
for (auto &chain : split_chains) {
|
||||||
get_chain_midpoint(ctx, chain, chain.mid_x, chain.mid_y);
|
get_chain_midpoint(ctx, chain, chain.mid_x, chain.mid_y);
|
||||||
@ -146,6 +167,8 @@ class PlacementLegaliser
|
|||||||
}
|
}
|
||||||
// Actual chain placement
|
// Actual chain placement
|
||||||
for (auto &chain : all_chains) {
|
for (auto &chain : all_chains) {
|
||||||
|
if (ctx->verbose)
|
||||||
|
log_info("Placing carry chain starting at '%s'\n", chain.cells.front()->name.c_str(ctx));
|
||||||
float base_x = chain.mid_x, base_y = chain.mid_y - (chain.cells.size() / 16.0f);
|
float base_x = chain.mid_x, base_y = chain.mid_y - (chain.cells.size() / 16.0f);
|
||||||
// Find Bel meeting requirements closest to the target base, returning location as <x, y, z>
|
// Find Bel meeting requirements closest to the target base, returning location as <x, y, z>
|
||||||
auto chain_origin_bel = find_closest_bel(base_x, base_y, int(chain.cells.size()));
|
auto chain_origin_bel = find_closest_bel(base_x, base_y, int(chain.cells.size()));
|
||||||
@ -166,6 +189,9 @@ class PlacementLegaliser
|
|||||||
for (int i = 0; i < int(chain.cells.size()); i++) {
|
for (int i = 0; i < int(chain.cells.size()); i++) {
|
||||||
int target_z = place_y * 8 + place_z + i;
|
int target_z = place_y * 8 + place_z + i;
|
||||||
place_lc(chain.cells.at(i), place_x, target_z / 8, target_z % 8);
|
place_lc(chain.cells.at(i), place_x, target_z / 8, target_z % 8);
|
||||||
|
if (ctx->verbose)
|
||||||
|
log_info(" Cell '%s' placed at (%d, %d, %d)\n", chain.cells.at(i)->name.c_str(ctx), place_x,
|
||||||
|
target_z / 8, target_z % 8);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return success;
|
return success;
|
||||||
@ -234,9 +260,13 @@ class PlacementLegaliser
|
|||||||
} else {
|
} else {
|
||||||
NetInfo *carry_net = cell->ports.at(ctx->id("COUT")).net;
|
NetInfo *carry_net = cell->ports.at(ctx->id("COUT")).net;
|
||||||
if (carry_net != nullptr && carry_net->users.size() > 1) {
|
if (carry_net != nullptr && carry_net->users.size() > 1) {
|
||||||
CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")));
|
if (carry_net->users.size() > 2 ||
|
||||||
chains.back().cells.push_back(passout);
|
(net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), false) !=
|
||||||
tile.push_back(passout);
|
net_only_drives(ctx, carry_net, is_lc, ctx->id("CIN"), false))) {
|
||||||
|
CellInfo *passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")));
|
||||||
|
chains.back().cells.push_back(passout);
|
||||||
|
tile.push_back(passout);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
++curr_cell;
|
++curr_cell;
|
||||||
}
|
}
|
||||||
@ -257,8 +287,12 @@ class PlacementLegaliser
|
|||||||
rippedCells.insert(existing);
|
rippedCells.insert(existing);
|
||||||
ctx->unbindBel(bel);
|
ctx->unbindBel(bel);
|
||||||
}
|
}
|
||||||
|
if (cell->bel != BelId()) {
|
||||||
|
ctx->unbindBel(cell->bel);
|
||||||
|
}
|
||||||
ctx->bindBel(bel, cell->name, STRENGTH_LOCKED);
|
ctx->bindBel(bel, cell->name, STRENGTH_LOCKED);
|
||||||
loc.second = true; // Bel is now unavailable for further use
|
rippedCells.erase(cell->name); // If cell was ripped up previously, no need to re-place
|
||||||
|
loc.second = true; // Bel is now unavailable for further use
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert a logic cell to legalise a COUT->fabric connection
|
// Insert a logic cell to legalise a COUT->fabric connection
|
||||||
@ -324,12 +358,10 @@ class PlacementLegaliser
|
|||||||
bool placed = place_single_cell(ci);
|
bool placed = place_single_cell(ci);
|
||||||
if (!placed) {
|
if (!placed) {
|
||||||
if (ctx->force) {
|
if (ctx->force) {
|
||||||
log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx),
|
log_warning("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), ci->type.c_str(ctx));
|
||||||
ci->type.c_str(ctx));
|
|
||||||
success = false;
|
success = false;
|
||||||
} else {
|
} else {
|
||||||
log_error("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx),
|
log_error("failed to place cell '%s' of type '%s'\n", cell.c_str(ctx), ci->type.c_str(ctx));
|
||||||
ci->type.c_str(ctx));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user