fabulous: Support for complex flops in PnR

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2023-02-27 09:04:11 +01:00 committed by myrtle
parent 1dcc2f777d
commit cdd7bb676f
4 changed files with 37 additions and 4 deletions

View File

@ -110,5 +110,8 @@ X(VDD)
X(_CONST0_DRV) X(_CONST0_DRV)
X(_CONST1_DRV) X(_CONST1_DRV)
X(_CONST0)
X(_CONST1)
X(_LUT_PERM) X(_LUT_PERM)
X(_LUT_PERM_IN) X(_LUT_PERM_IN)

View File

@ -43,8 +43,9 @@ struct ControlSetConfig
signal can drive for a CLB with 8 FFs and 2 clocks split at halfway, the first entry would be 0x0F and the second signal can drive for a CLB with 8 FFs and 2 clocks split at halfway, the first entry would be 0x0F and the second
0xF0 0xF0
*/ */
std::vector<route_mask_t> routing = {0b11111111}; // default 1 shared between all std::vector<route_mask_t> routing; // default 1 shared between all
bool have_signal = true; bool have_signal = true;
int can_mask = -1;
bool can_invert = false; bool can_invert = false;
}; };

View File

@ -52,6 +52,7 @@ struct FabulousImpl : ViaductAPI
log_error("unrecognised fabulous option '%s'\n", a.first.c_str()); log_error("unrecognised fabulous option '%s'\n", a.first.c_str());
} }
} }
~FabulousImpl(){}; ~FabulousImpl(){};
void init(Context *ctx) override void init(Context *ctx) override
{ {
@ -64,6 +65,7 @@ struct FabulousImpl : ViaductAPI
else else
is_new_fab = false; is_new_fab = false;
log_info("Detected FABulous %s format project.\n", is_new_fab ? "2.0" : "1.0"); log_info("Detected FABulous %s format project.\n", is_new_fab ? "2.0" : "1.0");
init_default_ctrlset_cfg();
// To consider: a faster serialised form of the device data (like bba that other arches use) so we don't have to // To consider: a faster serialised form of the device data (like bba that other arches use) so we don't have to
// go through the whole csv parsing malarkey each time // go through the whole csv parsing malarkey each time
blk_trk = std::make_unique<BlockTracker>(ctx, cfg); blk_trk = std::make_unique<BlockTracker>(ctx, cfg);
@ -76,6 +78,22 @@ struct FabulousImpl : ViaductAPI
ctx->ripup_penalty = 0.5; ctx->ripup_penalty = 0.5;
} }
void init_default_ctrlset_cfg()
{
// 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) {
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);
}
void update_cell_timing(Context *ctx) void update_cell_timing(Context *ctx)
{ {
// These timings are not realistic. They just make sure nextpnr does some timing-driven optimisation... // These timings are not realistic. They just make sure nextpnr does some timing-driven optimisation...
@ -605,9 +623,9 @@ struct FabulousImpl : ViaductAPI
return true; return true;
bool is_carry = cell_tags.get(lut).comb.carry_used; bool is_carry = cell_tags.get(lut).comb.carry_used;
if (is_carry) { if (is_carry) {
// Because you have to make sure you route _something_ to each HA input in this mode (undefined I1/I2 inputs aren't OK) // Because you have to make sure you route _something_ to each HA input in this mode (undefined I1/I2
// and you also can't swap I0 because it's fixed internally // inputs aren't OK) and you also can't swap I0 because it's fixed internally LUT permutation in carry
// LUT permutation in carry mode is just more trouble than it's worth. // mode is just more trouble than it's worth.
return false; return false;
} else { } else {
return true; // TODO: other cases where perm illegal; e.g. LUTRAM return true; // TODO: other cases where perm illegal; e.g. LUTRAM

View File

@ -62,6 +62,10 @@ void CellTagger::assign_for(const Context *ctx, const FabricConfig &cfg, const C
auto get_ctrlsig = [&](IdString name) { auto get_ctrlsig = [&](IdString name) {
const NetInfo *sig = ci->getPort(name); const NetInfo *sig = ci->getPort(name);
bool invert = sig && bool_or_default(ci->params, ctx->idf("NEG_%s", name.c_str(ctx))); bool invert = sig && bool_or_default(ci->params, ctx->idf("NEG_%s", name.c_str(ctx)));
if (sig && sig->driver.cell && sig->driver.cell->type.in(id__CONST0_DRV, id__CONST1_DRV)) {
return ControlSig(((sig->driver.cell->type == id__CONST1_DRV) ^ invert) ? id__CONST1 : id__CONST0,
false);
}
return ControlSig(sig ? sig->name : id___disconnected, invert); return ControlSig(sig ? sig->name : id___disconnected, invert);
}; };
t.ff.clk = get_ctrlsig(id_CLK); t.ff.clk = get_ctrlsig(id_CLK);
@ -132,6 +136,13 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
used_en(cfg.en.routing.size()); used_en(cfg.en.routing.size());
auto check_ctrlsig = [&](unsigned idx, ControlSig actual, const ControlSetConfig &ctrl, auto check_ctrlsig = [&](unsigned idx, ControlSig actual, const ControlSetConfig &ctrl,
SSOArray<ControlSig, 2> &used) { SSOArray<ControlSig, 2> &used) {
if (ctrl.can_mask != -1) {
// 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)) {
return true;
}
}
// see if we have an already-matching signal available // see if we have an already-matching signal available
for (unsigned i = 0; i < ctrl.routing.size(); i++) { for (unsigned i = 0; i < ctrl.routing.size(); i++) {
// doesn't route to this pin // doesn't route to this pin