xilinx: Fix BRAM placement, clangformat
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
38e5faca85
commit
d3c0f945da
@ -48,7 +48,7 @@ struct FasmBackend
|
|||||||
|
|
||||||
dict<IdString, pool<IdString>> invertible_pins;
|
dict<IdString, pool<IdString>> invertible_pins;
|
||||||
|
|
||||||
FasmBackend(Context *ctx, XilinxImpl *uarch, std::ostream &out) : ctx(ctx), uarch(uarch), out(out){};
|
FasmBackend(Context *ctx, XilinxImpl *uarch, std::ostream &out) : ctx(ctx), uarch(uarch), out(out) {};
|
||||||
|
|
||||||
void push(const std::string &x) { fasm_ctx.push_back(x); }
|
void push(const std::string &x) { fasm_ctx.push_back(x); }
|
||||||
|
|
||||||
|
@ -39,7 +39,7 @@ struct XilinxPacker
|
|||||||
Context *ctx;
|
Context *ctx;
|
||||||
XilinxImpl *uarch;
|
XilinxImpl *uarch;
|
||||||
|
|
||||||
XilinxPacker(Context *ctx, XilinxImpl *uarch) : ctx(ctx), uarch(uarch){};
|
XilinxPacker(Context *ctx, XilinxImpl *uarch) : ctx(ctx), uarch(uarch) {};
|
||||||
|
|
||||||
// Generic cell transformation
|
// Generic cell transformation
|
||||||
// Given cell name map and port map
|
// Given cell name map and port map
|
||||||
@ -170,7 +170,7 @@ struct XilinxPacker
|
|||||||
|
|
||||||
struct XC7Packer : public XilinxPacker
|
struct XC7Packer : public XilinxPacker
|
||||||
{
|
{
|
||||||
XC7Packer(Context *ctx, XilinxImpl *uarch) : XilinxPacker(ctx, uarch){};
|
XC7Packer(Context *ctx, XilinxImpl *uarch) : XilinxPacker(ctx, uarch) {};
|
||||||
|
|
||||||
// Carries
|
// Carries
|
||||||
bool has_illegal_fanout(NetInfo *carry);
|
bool has_illegal_fanout(NetInfo *carry);
|
||||||
|
@ -316,9 +316,10 @@ void XilinxPacker::pack_dram()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<NetInfo *> address(cs.wa.begin(), cs.wa.begin() + std::min<size_t>(cs.wa.size(), 6));
|
std::vector<NetInfo *> address(cs.wa.begin(), cs.wa.begin() + std::min<size_t>(cs.wa.size(), 6));
|
||||||
CellInfo *ram = create_dram_lut(cell->name.str(ctx) + "/ADDR", base, cs, address, cell->getPort(id_D), cell->getPort(id_O), z);
|
CellInfo *ram = create_dram_lut(cell->name.str(ctx) + "/ADDR", base, cs, address, cell->getPort(id_D),
|
||||||
|
cell->getPort(id_O), z);
|
||||||
if (cell->params.count(id_INIT))
|
if (cell->params.count(id_INIT))
|
||||||
ram->params[id_INIT] = cell->params[id_INIT];
|
ram->params[id_INIT] = cell->params[id_INIT];
|
||||||
if (base == nullptr)
|
if (base == nullptr)
|
||||||
base = ram;
|
base = ram;
|
||||||
z--;
|
z--;
|
||||||
|
@ -26,16 +26,18 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
static bool is_cascade_input(const PortInfo& port, const Context *ctx)
|
static bool is_cascade_input(const PortInfo &port, const Context *ctx)
|
||||||
{
|
{
|
||||||
if(port.name == id_CARRYCASCIN || port.name == id_MULTSIGNIN) return true;
|
if (port.name == id_CARRYCASCIN || port.name == id_MULTSIGNIN)
|
||||||
const std::string& str = port.name.c_str(ctx);
|
return true;
|
||||||
|
const std::string &str = port.name.c_str(ctx);
|
||||||
return boost::starts_with(str, "ACIN") || boost::starts_with(str, "BCIN") || boost::starts_with(str, "PCIN");
|
return boost::starts_with(str, "ACIN") || boost::starts_with(str, "BCIN") || boost::starts_with(str, "PCIN");
|
||||||
}
|
}
|
||||||
static bool is_cascade_output(const PortInfo& port, const Context *ctx)
|
static bool is_cascade_output(const PortInfo &port, const Context *ctx)
|
||||||
{
|
{
|
||||||
if(port.name == id_CARRYCASCOUT || port.name == id_MULTSIGNOUT) return true;
|
if (port.name == id_CARRYCASCOUT || port.name == id_MULTSIGNOUT)
|
||||||
const std::string& str = port.name.c_str(ctx);
|
return true;
|
||||||
|
const std::string &str = port.name.c_str(ctx);
|
||||||
return boost::starts_with(str, "ACOUT") || boost::starts_with(str, "BCOUT") || boost::starts_with(str, "PCOUT");
|
return boost::starts_with(str, "ACOUT") || boost::starts_with(str, "BCOUT") || boost::starts_with(str, "PCOUT");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,31 +47,33 @@ unsigned XC7Packer::walk_dsp(CellInfo *root, CellInfo *current_cell, int constr_
|
|||||||
CellInfo *cascaded_cell = nullptr;
|
CellInfo *cascaded_cell = nullptr;
|
||||||
unsigned num_casc = 0;
|
unsigned num_casc = 0;
|
||||||
|
|
||||||
auto check_illegal_fanout = [&] (NetInfo *ni, std::string port) {
|
auto check_illegal_fanout = [&](NetInfo *ni, std::string port) {
|
||||||
if (ni->users.entries() > 1)
|
if (ni->users.entries() > 1)
|
||||||
log_error("Port %s connected to net %s has more than one user", port.c_str(), ni->name.c_str(ctx));
|
log_error("Port %s connected to net %s has more than one user", port.c_str(), ni->name.c_str(ctx));
|
||||||
|
|
||||||
PortRef& user = *ni->users.begin();
|
PortRef &user = *ni->users.begin();
|
||||||
if (user.cell->type != id_DSP48E1_DSP48E1)
|
if (user.cell->type != id_DSP48E1_DSP48E1)
|
||||||
log_error("User %s of net %s is not a DSP block, but %s",
|
log_error("User %s of net %s is not a DSP block, but %s", user.cell->name.c_str(ctx), ni->name.c_str(ctx),
|
||||||
user.cell->name.c_str(ctx), ni->name.c_str(ctx), user.cell->type.c_str(ctx));
|
user.cell->type.c_str(ctx));
|
||||||
};
|
};
|
||||||
|
|
||||||
// see if any cascade outputs are connected
|
// see if any cascade outputs are connected
|
||||||
for (auto port : current_cell->ports) {
|
for (auto port : current_cell->ports) {
|
||||||
if (!is_cascade_output(port.second, ctx)) continue;
|
if (!is_cascade_output(port.second, ctx))
|
||||||
|
continue;
|
||||||
NetInfo *cout_net = port.second.net;
|
NetInfo *cout_net = port.second.net;
|
||||||
|
|
||||||
if (cout_net == nullptr || cout_net->users.empty()) continue;
|
if (cout_net == nullptr || cout_net->users.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
check_illegal_fanout(cout_net, port.first.c_str(ctx));
|
check_illegal_fanout(cout_net, port.first.c_str(ctx));
|
||||||
PortRef& user = *cout_net->users.begin();
|
PortRef &user = *cout_net->users.begin();
|
||||||
CellInfo *cout_cell = user.cell;
|
CellInfo *cout_cell = user.cell;
|
||||||
NPNR_ASSERT(cout_cell != nullptr);
|
NPNR_ASSERT(cout_cell != nullptr);
|
||||||
|
|
||||||
if (cascaded_cell != nullptr && cout_cell != cascaded_cell)
|
if (cascaded_cell != nullptr && cout_cell != cascaded_cell)
|
||||||
log_error("the cascading outputs of DSP block %s are connected to different cells",
|
log_error("the cascading outputs of DSP block %s are connected to different cells",
|
||||||
current_cell->name.c_str(ctx));
|
current_cell->name.c_str(ctx));
|
||||||
|
|
||||||
cascaded_cell = cout_cell;
|
cascaded_cell = cout_cell;
|
||||||
}
|
}
|
||||||
@ -109,7 +113,7 @@ void XC7Packer::pack_dsps()
|
|||||||
for (auto &cell : ctx->cells) {
|
for (auto &cell : ctx->cells) {
|
||||||
CellInfo *ci = cell.second.get();
|
CellInfo *ci = cell.second.get();
|
||||||
|
|
||||||
auto add_const_pin = [&](PortInfo& port, std::string& pins, std::string& pin_name, std::string net) {
|
auto add_const_pin = [&](PortInfo &port, std::string &pins, std::string &pin_name, std::string net) {
|
||||||
if (port.net && port.net->name == ctx->id(net)) {
|
if (port.net && port.net->name == ctx->id(net)) {
|
||||||
ci->disconnectPort(port.name);
|
ci->disconnectPort(port.name);
|
||||||
pins += " " + pin_name;
|
pins += " " + pin_name;
|
||||||
@ -138,16 +142,13 @@ void XC7Packer::pack_dsps()
|
|||||||
// prjxray has extra bits for these ports to hardwire them to VCC/GND
|
// prjxray has extra bits for these ports to hardwire them to VCC/GND
|
||||||
// as these seem to be interal to the tile,
|
// as these seem to be interal to the tile,
|
||||||
// this saves us from having to route those externally
|
// this saves us from having to route those externally
|
||||||
if (boost::starts_with(n, "D") ||
|
if (boost::starts_with(n, "D") || boost::starts_with(n, "RSTD") ||
|
||||||
boost::starts_with(n, "RSTD") ||
|
|
||||||
// TODO: these seem to be inverted for unknown reasons
|
// TODO: these seem to be inverted for unknown reasons
|
||||||
// boost::starts_with(n, "INMODE") ||
|
// boost::starts_with(n, "INMODE") ||
|
||||||
// boost::starts_with(n, "ALUMODE2") ||
|
// boost::starts_with(n, "ALUMODE2") ||
|
||||||
// boost::starts_with(n, "ALUMODE3") ||
|
// boost::starts_with(n, "ALUMODE3") ||
|
||||||
boost::starts_with(n, "CARRYINSEL2") ||
|
boost::starts_with(n, "CARRYINSEL2") || boost::starts_with(n, "CED") ||
|
||||||
boost::starts_with(n, "CED") ||
|
boost::starts_with(n, "CEAD") || boost::starts_with(n, "CEINMODE") ||
|
||||||
boost::starts_with(n, "CEAD") ||
|
|
||||||
boost::starts_with(n, "CEINMODE") ||
|
|
||||||
boost::starts_with(n, "CEALUMODE")) {
|
boost::starts_with(n, "CEALUMODE")) {
|
||||||
add_const_pin(port.second, gnd_pins, n, "$PACKER_GND_NET");
|
add_const_pin(port.second, gnd_pins, n, "$PACKER_GND_NET");
|
||||||
add_const_pin(port.second, vcc_pins, n, "$PACKER_VCC_NET");
|
add_const_pin(port.second, vcc_pins, n, "$PACKER_VCC_NET");
|
||||||
@ -164,7 +165,8 @@ void XC7Packer::pack_dsps()
|
|||||||
for (auto ci : all_dsps) {
|
for (auto ci : all_dsps) {
|
||||||
bool cascade_input_used = false;
|
bool cascade_input_used = false;
|
||||||
for (auto port : ci->ports) {
|
for (auto port : ci->ports) {
|
||||||
if (!is_cascade_input(port.second, ctx)) continue;
|
if (!is_cascade_input(port.second, ctx))
|
||||||
|
continue;
|
||||||
if (port.second.net != nullptr) {
|
if (port.second.net != nullptr) {
|
||||||
cascade_input_used = true;
|
cascade_input_used = true;
|
||||||
break;
|
break;
|
||||||
@ -182,13 +184,13 @@ void XC7Packer::pack_dsps()
|
|||||||
root->constr_abs_z = true;
|
root->constr_abs_z = true;
|
||||||
root->constr_z = BEL_LOWER_DSP;
|
root->constr_z = BEL_LOWER_DSP;
|
||||||
unsigned loc_casc = walk_dsp(root, root, BEL_UPPER_DSP);
|
unsigned loc_casc = walk_dsp(root, root, BEL_UPPER_DSP);
|
||||||
if(loc_casc > 0) {
|
if (loc_casc > 0) {
|
||||||
root->cluster = root->name;
|
root->cluster = root->name;
|
||||||
}
|
}
|
||||||
num_casc += loc_casc;
|
num_casc += loc_casc;
|
||||||
}
|
}
|
||||||
if(num_casc > 0) {
|
if (num_casc > 0) {
|
||||||
log_info("Found %u cascaded DSP from %u roots\n", num_casc, (unsigned)dsp_roots.size());
|
log_info("Found %u cascaded DSP from %u roots\n", num_casc, (unsigned)dsp_roots.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@
|
|||||||
|
|
||||||
NEXTPNR_NAMESPACE_BEGIN
|
NEXTPNR_NAMESPACE_BEGIN
|
||||||
|
|
||||||
XilinxImpl::~XilinxImpl(){};
|
XilinxImpl::~XilinxImpl() {};
|
||||||
|
|
||||||
void XilinxImpl::init_database(Arch *arch)
|
void XilinxImpl::init_database(Arch *arch)
|
||||||
{
|
{
|
||||||
@ -178,7 +178,19 @@ void XilinxImpl::update_logic_bel(BelId bel, CellInfo *cell)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void XilinxImpl::update_bram_bel(BelId bel, CellInfo *cell) {}
|
void XilinxImpl::update_bram_bel(BelId bel, CellInfo *cell)
|
||||||
|
{
|
||||||
|
IdString type = ctx->getBelType(bel);
|
||||||
|
if (!type.in(id_RAMBFIFO18E2_RAMBFIFO18E2, id_RAMBFIFO36E2_RAMBFIFO36E2, id_RAMB18E2_RAMB18E2, id_FIFO36E2_FIFO36E2,
|
||||||
|
id_RAMBFIFO36E1_RAMBFIFO36E1, id_RAMB36E1_RAMB36E1, id_RAMB18E1_RAMB18E1))
|
||||||
|
return;
|
||||||
|
auto &tts = tile_status.at(bel.tile);
|
||||||
|
if (!tts.bts)
|
||||||
|
tts.bts = std::make_unique<BRAMTileStatus>();
|
||||||
|
int z = ctx->getBelLocation(bel).z;
|
||||||
|
NPNR_ASSERT(z >= 0 && z < 12);
|
||||||
|
tts.bts->cells[z] = cell;
|
||||||
|
}
|
||||||
|
|
||||||
bool XilinxImpl::is_pip_unavail(PipId pip) const
|
bool XilinxImpl::is_pip_unavail(PipId pip) const
|
||||||
{
|
{
|
||||||
@ -545,7 +557,7 @@ BoundingBox XilinxImpl::getRouteBoundingBox(WireId src, WireId dst) const
|
|||||||
namespace {
|
namespace {
|
||||||
struct XilinxArch : HimbaechelArch
|
struct XilinxArch : HimbaechelArch
|
||||||
{
|
{
|
||||||
XilinxArch() : HimbaechelArch("xilinx"){};
|
XilinxArch() : HimbaechelArch("xilinx") {};
|
||||||
bool match_device(const std::string &device) override { return device.size() > 3 && device.substr(0, 3) == "xc7"; }
|
bool match_device(const std::string &device) override { return device.size() > 3 && device.substr(0, 3) == "xc7"; }
|
||||||
std::unique_ptr<HimbaechelAPI> create(const std::string &device, const dict<std::string, std::string> &args)
|
std::unique_ptr<HimbaechelAPI> create(const std::string &device, const dict<std::string, std::string> &args)
|
||||||
{
|
{
|
||||||
|
@ -63,8 +63,8 @@ struct XilinxCellTags
|
|||||||
|
|
||||||
struct SiteIndex
|
struct SiteIndex
|
||||||
{
|
{
|
||||||
SiteIndex() : tile(-1), site(-1){};
|
SiteIndex() : tile(-1), site(-1) {};
|
||||||
SiteIndex(int32_t tile, int32_t site) : tile(tile), site(site){};
|
SiteIndex(int32_t tile, int32_t site) : tile(tile), site(site) {};
|
||||||
|
|
||||||
int32_t tile;
|
int32_t tile;
|
||||||
int32_t site;
|
int32_t site;
|
||||||
|
Loading…
Reference in New Issue
Block a user