mirror of https://github.com/YosysHQ/nextpnr.git
fabulous: fix block tracking of FABULOUS_LC, improve debug messages, fix masking of 1
Signed-off-by: Leo Moser <leomoser99@gmail.com>
This commit is contained in:
parent
20de8b72e8
commit
3e0ef57793
|
|
@ -45,7 +45,12 @@ struct ControlSetConfig
|
|||
*/
|
||||
std::vector<route_mask_t> routing; // default 1 shared between all
|
||||
bool have_signal = true;
|
||||
int can_mask = -1;
|
||||
enum MaskType
|
||||
{
|
||||
MASK_NONE = -1,
|
||||
MASK_ZERO = 0,
|
||||
MASK_ONE = 1
|
||||
} can_mask = MaskType::MASK_NONE;
|
||||
bool can_invert = false;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -87,16 +87,16 @@ struct FabulousImpl : ViaductAPI
|
|||
{
|
||||
// TODO: loading from file or something
|
||||
uint64_t default_routing = (1ULL << (cfg.clb.lc_per_clb * cfg.clb.ff_per_lc)) - 1;
|
||||
auto setup_cfg = [&](ControlSetConfig &ctrl, int mask) {
|
||||
auto setup_cfg = [&](ControlSetConfig &ctrl, ControlSetConfig::MaskType mask) {
|
||||
ctrl.routing.clear();
|
||||
ctrl.routing.push_back(default_routing);
|
||||
ctrl.can_mask = mask;
|
||||
ctrl.can_invert = false;
|
||||
};
|
||||
|
||||
setup_cfg(cfg.clb.clk, -1);
|
||||
setup_cfg(cfg.clb.en, 1);
|
||||
setup_cfg(cfg.clb.sr, 0);
|
||||
setup_cfg(cfg.clb.clk, ControlSetConfig::MaskType::MASK_NONE); // clk can not be masked
|
||||
setup_cfg(cfg.clb.en, ControlSetConfig::MaskType::MASK_ONE); // en can be masked with 1
|
||||
setup_cfg(cfg.clb.sr, ControlSetConfig::MaskType::MASK_ZERO); // sr can be masked with 0
|
||||
}
|
||||
|
||||
void update_cell_timing(Context *ctx)
|
||||
|
|
@ -154,9 +154,38 @@ struct FabulousImpl : ViaductAPI
|
|||
assign_cell_info();
|
||||
update_cell_timing(ctx);
|
||||
}
|
||||
|
||||
void postPlace() override
|
||||
{
|
||||
if (ctx->debug) {
|
||||
log_info("================== Final Placement ==================\n");
|
||||
for (auto &cell : ctx->cells) {
|
||||
auto ci = cell.second.get();
|
||||
if (ci->bel != BelId()) {
|
||||
log_info("%s: %s\n", ctx->nameOfBel(ci->bel), ctx->nameOf(ci));
|
||||
if (ctx->getBelType(ci->bel).in(id_FABULOUS_LC)) {
|
||||
for (IdString port : {id_CLK, id_SR, id_EN}) {
|
||||
if (ci->ports.count(port)) {
|
||||
WireId wire = ctx->getBelPinWire(ci->bel, port);
|
||||
PortInfo pi = ci->ports[port];
|
||||
if (pi.net) {
|
||||
log_info("- %s/%s: %s\n", ctx->getWireName(wire)[0].c_str(ctx),
|
||||
ctx->getWireName(wire)[1].c_str(ctx), pi.net->name.c_str(ctx));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
log_info("unknown: %s\n", ctx->nameOf(ci));
|
||||
}
|
||||
}
|
||||
log_break();
|
||||
}
|
||||
}
|
||||
|
||||
bool isBelLocationValid(BelId bel, bool explain_invalid) const override
|
||||
{
|
||||
return blk_trk->check_validity(bel, cfg, cell_tags);
|
||||
return blk_trk->check_validity(bel, cfg, cell_tags, explain_invalid);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -382,6 +411,11 @@ struct FabulousImpl : ViaductAPI
|
|||
Loc loc = tile_loc(tile);
|
||||
curr_bel = ctx->addBel(IdStringList::concat(tile, bel_name), bel_type, Loc(loc.x, loc.y, bel_z), false,
|
||||
false);
|
||||
|
||||
// add FABULOUS_LC to the block tracker to check the control set
|
||||
if (bel_type.in(id_FABULOUS_LC)) {
|
||||
blk_trk->set_bel_type(curr_bel, BelFlags::BLOCK_CLB, BelFlags::FUNC_LC_COMB, bel_z);
|
||||
}
|
||||
} else if (cmd.in(id_I, id_O)) {
|
||||
IdString port = csv.next_field().to_id(ctx);
|
||||
auto wire_name = csv.next_field().split('.');
|
||||
|
|
|
|||
|
|
@ -130,16 +130,18 @@ void BlockTracker::update_bel(BelId bel, CellInfo *old_cell, CellInfo *new_cell)
|
|||
}
|
||||
}
|
||||
|
||||
bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_data)
|
||||
bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_data, bool explain_invalid)
|
||||
{
|
||||
SSOArray<ControlSig, 2> used_clk(cfg.clk.routing.size()), used_sr(cfg.sr.routing.size()),
|
||||
used_en(cfg.en.routing.size());
|
||||
|
||||
auto check_ctrlsig = [&](unsigned idx, ControlSig actual, const ControlSetConfig &ctrl,
|
||||
SSOArray<ControlSig, 2> &used) {
|
||||
if (ctrl.can_mask != -1) {
|
||||
if (ctrl.can_mask != ControlSetConfig::MaskType::MASK_NONE) {
|
||||
// Using the per-entry control signal masking
|
||||
if (actual.net == id___disconnected || (actual.net == id__CONST0 && ctrl.can_mask == 0) ||
|
||||
(actual.net == id__CONST1 && ctrl.can_mask == 0)) {
|
||||
if (actual.net == id___disconnected ||
|
||||
(actual.net == id__CONST0 && ctrl.can_mask == ControlSetConfig::MaskType::MASK_ZERO) ||
|
||||
(actual.net == id__CONST1 && ctrl.can_mask == ControlSetConfig::MaskType::MASK_ONE)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -164,6 +166,7 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
|
|||
// no option available
|
||||
return false;
|
||||
};
|
||||
|
||||
for (unsigned z = 0; z < cfg.lc_per_clb; z++) {
|
||||
// flipflop control set checking
|
||||
if (cfg.split_lc) {
|
||||
|
|
@ -176,15 +179,28 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
|
|||
auto &lct = cell_data.get(lc);
|
||||
if (lct.ff.ff_used) {
|
||||
// check shared control signals
|
||||
if (!check_ctrlsig(z, lct.ff.clk, cfg.clk, used_clk))
|
||||
if (!check_ctrlsig(z, lct.ff.clk, cfg.clk, used_clk)) {
|
||||
if (explain_invalid) {
|
||||
log_nonfatal_error("CLK control signal invalid.\n");
|
||||
}
|
||||
return false;
|
||||
if (cfg.en.have_signal && !check_ctrlsig(z, lct.ff.en, cfg.en, used_en))
|
||||
}
|
||||
if (cfg.en.have_signal && !check_ctrlsig(z, lct.ff.en, cfg.en, used_en)) {
|
||||
if (explain_invalid) {
|
||||
log_nonfatal_error("EN control signal invalid.\n");
|
||||
}
|
||||
return false;
|
||||
if (cfg.sr.have_signal && !check_ctrlsig(z, lct.ff.sr, cfg.sr, used_sr))
|
||||
}
|
||||
if (cfg.sr.have_signal && !check_ctrlsig(z, lct.ff.sr, cfg.sr, used_sr)) {
|
||||
if (explain_invalid) {
|
||||
log_nonfatal_error("SR control signal invalid.\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// don't allow mixed MUX types in the classic fabulous arch where ctrl sigs are shared
|
||||
int tile_mux_type = 0;
|
||||
for (unsigned z = 0; z < cfg.lc_per_clb; z++) {
|
||||
|
|
@ -202,14 +218,19 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
|
|||
NPNR_ASSERT_FALSE("unknown mux type");
|
||||
if (tile_mux_type == 0)
|
||||
tile_mux_type = this_mux;
|
||||
else if (tile_mux_type != this_mux)
|
||||
else if (tile_mux_type != this_mux) {
|
||||
if (explain_invalid) {
|
||||
log_nonfatal_error("Invalid mux type.\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// TODO: other checks...
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockTracker::check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data)
|
||||
bool BlockTracker::check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data, bool explain_invalid)
|
||||
{
|
||||
if (bel.index >= int(bel_data.size()))
|
||||
return true; // some kind of bel not being tracked
|
||||
|
|
@ -224,7 +245,7 @@ bool BlockTracker::check_validity(BelId bel, const FabricConfig &cfg, const Cell
|
|||
return true; // some kind of bel not being tracked
|
||||
const auto &entry = row.at(loc.x);
|
||||
if (flags.block == BelFlags::BLOCK_CLB) {
|
||||
return entry.clb->check_validity(cfg.clb, cell_data);
|
||||
return entry.clb->check_validity(cfg.clb, cell_data, explain_invalid);
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ struct CLBState
|
|||
std::unique_ptr<CellInfo *[]> ff;
|
||||
// If there is (a) separate mux bel(s), map them to cells
|
||||
std::unique_ptr<CellInfo *[]> mux;
|
||||
bool check_validity(const LogicConfig &cfg, const CellTagger &cell_data);
|
||||
bool check_validity(const LogicConfig &cfg, const CellTagger &cell_data, bool explain_invalid = false);
|
||||
};
|
||||
|
||||
struct BlockTracker
|
||||
|
|
@ -119,7 +119,7 @@ struct BlockTracker
|
|||
// ...
|
||||
};
|
||||
std::vector<std::vector<TileData>> tiles;
|
||||
bool check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data);
|
||||
bool check_validity(BelId bel, const FabricConfig &cfg, const CellTagger &cell_data, bool explain_invalid);
|
||||
};
|
||||
|
||||
struct PseudoPipTags
|
||||
|
|
|
|||
Loading…
Reference in New Issue