fabulous: Pack, validity check and FASM support for muxes
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
124c0fc812
commit
3826a31ad3
@ -317,12 +317,13 @@ struct FabulousImpl : ViaductAPI
|
|||||||
}
|
}
|
||||||
// K select inputs
|
// K select inputs
|
||||||
for (unsigned j = 0; j < k; j++) {
|
for (unsigned j = 0; j < k; j++) {
|
||||||
ctx->addBelInput(mux, ctx->idf("S%d", j), data.pins.at(ctx->idf("S%d",
|
ctx->addBelInput(mux, ctx->idf("S%d", j),
|
||||||
(m == 8 && j == 2) ? 3 : ((i / m) * k + j)
|
data.pins.at(ctx->idf("S%d", (m == 8 && j == 2) ? 3 : ((i / m) * k + j))).wire);
|
||||||
)).wire);
|
|
||||||
}
|
}
|
||||||
// Output
|
// Output
|
||||||
IdString output = (m == 2) ? mux_outs.at(i / m) : (m == 4) ? mux_outs.at((i / m) * k + 1) : mux_outs.at(3);
|
IdString output = (m == 2) ? mux_outs.at(i / m)
|
||||||
|
: (m == 4) ? mux_outs.at((i / m) * k + 1)
|
||||||
|
: mux_outs.at(3);
|
||||||
ctx->addBelOutput(mux, id_O, data.pins.at(output).wire);
|
ctx->addBelOutput(mux, id_O, data.pins.at(output).wire);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,14 @@ struct FabFasmWriter
|
|||||||
write_bool(lc, "NEG_SR");
|
write_bool(lc, "NEG_SR");
|
||||||
write_bool(lc, "ASYNC_SR");
|
write_bool(lc, "ASYNC_SR");
|
||||||
}
|
}
|
||||||
|
if (lc->type.in(id_FABULOUS_MUX4, id_FABULOUS_MUX8)) {
|
||||||
|
// TODO: don't hardcode prefix
|
||||||
|
out << prefix << "I.c0" << std::endl;
|
||||||
|
}
|
||||||
|
if (lc->type == id_FABULOUS_MUX8) {
|
||||||
|
// TODO: don't hardcode prefix
|
||||||
|
out << prefix << "I.c1" << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write_io(const CellInfo *io)
|
void write_io(const CellInfo *io)
|
||||||
@ -161,7 +169,8 @@ struct FabFasmWriter
|
|||||||
void write_cell(const CellInfo *ci)
|
void write_cell(const CellInfo *ci)
|
||||||
{
|
{
|
||||||
out << stringf("# config for cell '%s'\n", ctx->nameOf(ci)) << std::endl;
|
out << stringf("# config for cell '%s'\n", ctx->nameOf(ci)) << std::endl;
|
||||||
if (ci->type.in(id_FABULOUS_COMB, id_FABULOUS_FF, id_FABULOUS_LC))
|
if (ci->type.in(id_FABULOUS_COMB, id_FABULOUS_FF, id_FABULOUS_LC, id_FABULOUS_MUX2, id_FABULOUS_MUX4,
|
||||||
|
id_FABULOUS_MUX8))
|
||||||
write_logic(ci);
|
write_logic(ci);
|
||||||
else if (ci->type == id_IO_1_bidirectional_frame_config_pass)
|
else if (ci->type == id_IO_1_bidirectional_frame_config_pass)
|
||||||
write_io(ci);
|
write_io(ci);
|
||||||
|
@ -132,6 +132,53 @@ struct FabulousPacker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pack_muxes()
|
||||||
|
{
|
||||||
|
// TODO: don't hardcode z-offset -- we should come up with our own constraint structure
|
||||||
|
int lut_muxes_dz = 9;
|
||||||
|
int lut_lut_dz = 1;
|
||||||
|
for (auto &cell : ctx->cells) {
|
||||||
|
CellInfo *ci = cell.second.get();
|
||||||
|
unsigned k = 0;
|
||||||
|
if (ci->type == id_FABULOUS_MUX2)
|
||||||
|
k = 1;
|
||||||
|
else if (ci->type == id_FABULOUS_MUX4)
|
||||||
|
k = 2;
|
||||||
|
else if (ci->type == id_FABULOUS_MUX8)
|
||||||
|
k = 3;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
unsigned m = (1U << k);
|
||||||
|
std::vector<CellInfo *> luts;
|
||||||
|
for (unsigned i = 0; i < m; i++) {
|
||||||
|
NetInfo *ii = ci->getPort(ctx->idf("I%d", i));
|
||||||
|
if (!ii || !ii->driver.cell || !ii->driver.cell->type.in(id_FABULOUS_LC, id_FABULOUS_COMB) ||
|
||||||
|
ii->driver.port != id_O)
|
||||||
|
log_error("mux %s input I%d net %s is not driven by a LUT!\n", ctx->nameOf(ci), i, ctx->nameOf(ii));
|
||||||
|
CellInfo *lut = ii->driver.cell;
|
||||||
|
NPNR_ASSERT(lut->cluster == ClusterId());
|
||||||
|
luts.push_back(lut);
|
||||||
|
}
|
||||||
|
luts.at(0)->cluster = luts.at(0)->name;
|
||||||
|
for (unsigned i = 0; i < m; i++) {
|
||||||
|
luts.at(i)->cluster = luts.at(0)->name;
|
||||||
|
luts.at(i)->constr_x = 0;
|
||||||
|
luts.at(i)->constr_y = 0;
|
||||||
|
luts.at(i)->constr_z = i * lut_lut_dz;
|
||||||
|
luts.at(i)->constr_abs_z = false;
|
||||||
|
if (i > 0)
|
||||||
|
luts.at(0)->constr_children.push_back(luts.at(i));
|
||||||
|
}
|
||||||
|
int extra_mux_dz = (m == 8) ? 7 : (m == 4) ? 1 : 0;
|
||||||
|
ci->cluster = luts.at(0)->name;
|
||||||
|
ci->constr_x = 0;
|
||||||
|
ci->constr_y = 0;
|
||||||
|
ci->constr_z = lut_muxes_dz + extra_mux_dz;
|
||||||
|
ci->constr_abs_z = false;
|
||||||
|
luts.at(0)->constr_children.push_back(ci);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pack_ffs()
|
void pack_ffs()
|
||||||
{
|
{
|
||||||
pool<IdString> to_delete;
|
pool<IdString> to_delete;
|
||||||
@ -238,6 +285,7 @@ struct FabulousPacker
|
|||||||
handle_constants();
|
handle_constants();
|
||||||
handle_io();
|
handle_io();
|
||||||
pack_luts();
|
pack_luts();
|
||||||
|
pack_muxes();
|
||||||
prepare_ffs();
|
prepare_ffs();
|
||||||
pack_ffs();
|
pack_ffs();
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,7 @@ CLBState::CLBState(const LogicConfig &cfg)
|
|||||||
if (cfg.split_lc) {
|
if (cfg.split_lc) {
|
||||||
ff = std::make_unique<CellInfo *[]>(cfg.lc_per_clb * cfg.ff_per_lc);
|
ff = std::make_unique<CellInfo *[]>(cfg.lc_per_clb * cfg.ff_per_lc);
|
||||||
}
|
}
|
||||||
|
mux = std::make_unique<CellInfo *[]>(cfg.lc_per_clb);
|
||||||
// TODO: mux
|
// TODO: mux
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +174,26 @@ bool CLBState::check_validity(const LogicConfig &cfg, const CellTagger &cell_dat
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// 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++) {
|
||||||
|
const CellInfo *m = mux[z];
|
||||||
|
if (!m)
|
||||||
|
continue;
|
||||||
|
int this_mux = 0;
|
||||||
|
if (m->type == id_FABULOUS_MUX2)
|
||||||
|
this_mux = 2;
|
||||||
|
else if (m->type == id_FABULOUS_MUX4)
|
||||||
|
this_mux = 4;
|
||||||
|
else if (m->type == id_FABULOUS_MUX8)
|
||||||
|
this_mux = 8;
|
||||||
|
else
|
||||||
|
NPNR_ASSERT_FALSE("unknown mux type");
|
||||||
|
if (tile_mux_type == 0)
|
||||||
|
tile_mux_type = this_mux;
|
||||||
|
else if (tile_mux_type != this_mux)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// TODO: other checks...
|
// TODO: other checks...
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user