fabulous: Support for complex flops in PnR
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
1dcc2f777d
commit
cdd7bb676f
@ -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)
|
||||||
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user