mistral: First pass at carry packing
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
7574eab2b6
commit
d39e67da7e
@ -183,6 +183,7 @@ struct ArchCellInfo : BaseClusterInfo
|
||||
int lut_bits_count;
|
||||
|
||||
bool is_carry, is_shared, is_extended;
|
||||
bool carry_start, carry_end;
|
||||
} combInfo;
|
||||
struct
|
||||
{
|
||||
|
@ -39,9 +39,9 @@ X(Q)
|
||||
|
||||
X(COMBOUT)
|
||||
X(SUM_OUT)
|
||||
X(CIN)
|
||||
X(CI)
|
||||
X(SHAREIN)
|
||||
X(COUT)
|
||||
X(CO)
|
||||
X(SHAREOUT)
|
||||
|
||||
X(CARRY_START)
|
||||
@ -64,8 +64,6 @@ X(LUT1)
|
||||
|
||||
X(D0)
|
||||
X(D1)
|
||||
X(CI)
|
||||
X(CO)
|
||||
X(SO)
|
||||
|
||||
X(WIRE)
|
||||
|
@ -48,7 +48,7 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
|
||||
share_in = arch->add_wire(x, y, id_CARRY_START);
|
||||
} else {
|
||||
// Output of last tile
|
||||
carry_in = arch->add_wire(x, y - 1, id_COUT);
|
||||
carry_in = arch->add_wire(x, y - 1, id_CO);
|
||||
share_in = arch->add_wire(x, y - 1, id_SHAREOUT);
|
||||
}
|
||||
} else {
|
||||
@ -57,7 +57,7 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
|
||||
share_in = arch->add_wire(x, y, arch->id(stringf("SHARE[%d]", (z * 2 + i) - 1)));
|
||||
}
|
||||
if (z == 9 && i == 1) {
|
||||
carry_out = arch->add_wire(x, y, id_COUT);
|
||||
carry_out = arch->add_wire(x, y, id_CO);
|
||||
share_out = arch->add_wire(x, y, id_SHAREOUT);
|
||||
} else {
|
||||
carry_out = arch->add_wire(x, y, arch->id(stringf("CARRY[%d]", z * 2 + i)));
|
||||
@ -75,9 +75,9 @@ static void create_alm(Arch *arch, int x, int y, int z, uint32_t lab_idx)
|
||||
arch->add_bel_pin(bel, id_F0, PORT_IN, arch->get_port(CycloneV::LAB, x, y, z, CycloneV::F0));
|
||||
arch->add_bel_pin(bel, id_F1, PORT_IN, arch->get_port(CycloneV::LAB, x, y, z, CycloneV::F1));
|
||||
// Carry/share chain
|
||||
arch->add_bel_pin(bel, id_CIN, PORT_IN, carry_in);
|
||||
arch->add_bel_pin(bel, id_CI, PORT_IN, carry_in);
|
||||
arch->add_bel_pin(bel, id_SHAREIN, PORT_IN, share_in);
|
||||
arch->add_bel_pin(bel, id_COUT, PORT_OUT, carry_out);
|
||||
arch->add_bel_pin(bel, id_CO, PORT_OUT, carry_out);
|
||||
arch->add_bel_pin(bel, id_SHAREOUT, PORT_OUT, share_out);
|
||||
// Combinational output
|
||||
alm.comb_out[i] = arch->add_wire(x, y, arch->id(stringf("COMBOUT[%d]", z * 2 + i)));
|
||||
@ -231,6 +231,8 @@ void Arch::assign_comb_info(CellInfo *cell) const
|
||||
cell->combInfo.is_carry = false;
|
||||
cell->combInfo.is_shared = false;
|
||||
cell->combInfo.is_extended = false;
|
||||
cell->combInfo.carry_start = false;
|
||||
cell->combInfo.carry_end = false;
|
||||
|
||||
if (cell->type == id_MISTRAL_ALUT_ARITH) {
|
||||
cell->combInfo.is_carry = true;
|
||||
@ -241,7 +243,13 @@ void Arch::assign_comb_info(CellInfo *cell) const
|
||||
for (auto pin : {id_A, id_B, id_C, id_D0, id_D1}) {
|
||||
cell->combInfo.lut_in[i++] = get_net_or_empty(cell, pin);
|
||||
}
|
||||
|
||||
const NetInfo *ci = get_net_or_empty(cell, id_CI);
|
||||
const NetInfo *co = get_net_or_empty(cell, id_CO);
|
||||
|
||||
cell->combInfo.comb_out = get_net_or_empty(cell, id_SO);
|
||||
cell->combInfo.carry_start = (ci == nullptr) || (ci->driver.cell == nullptr);
|
||||
cell->combInfo.carry_end = (co == nullptr) || (co->users.empty());
|
||||
} else {
|
||||
cell->combInfo.lut_input_count = 0;
|
||||
switch (cell->type.index) {
|
||||
@ -296,6 +304,22 @@ void Arch::assign_ff_info(CellInfo *cell) const
|
||||
cell->ffInfo.datain = get_net_or_empty(cell, id_DATAIN);
|
||||
}
|
||||
|
||||
namespace {
|
||||
// Check if the other side of a carry chain wire is being used
|
||||
bool carry_used(const Arch *arch, BelId bel, IdString pin)
|
||||
{
|
||||
WireId wire = arch->getBelPinWire(bel, pin);
|
||||
for (auto bp : arch->getWireBelPins(wire)) {
|
||||
if (bp.bel == bel)
|
||||
continue;
|
||||
CellInfo *ci = arch->getBoundBelCell(bp.bel);
|
||||
if (ci != nullptr && ci->combInfo.is_carry)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Validity checking functions
|
||||
bool Arch::is_alm_legal(uint32_t lab, uint8_t alm) const
|
||||
{
|
||||
@ -342,6 +366,16 @@ bool Arch::is_alm_legal(uint32_t lab, uint8_t alm) const
|
||||
return false;
|
||||
}
|
||||
|
||||
// Never allow two disjoint carry chains to accidentally stack
|
||||
for (int i = 0; i < 2; i++) {
|
||||
if (!luts[i])
|
||||
continue;
|
||||
if (luts[i]->combInfo.carry_start && carry_used(this, alm_data.lut_bels[i], id_CI))
|
||||
return false;
|
||||
if (luts[i]->combInfo.carry_end && carry_used(this, alm_data.lut_bels[i], id_CO))
|
||||
return false;
|
||||
}
|
||||
|
||||
// For each ALM half; check FF control set sharing and input routeability
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// There are two ways to route from the fabric into FF data - either routing through a LUT or using the E/F
|
||||
|
@ -275,11 +275,52 @@ struct MistralPacker
|
||||
}
|
||||
}
|
||||
|
||||
void constrain_carries()
|
||||
{
|
||||
for (auto cell : sorted(ctx->cells)) {
|
||||
CellInfo *ci = cell.second;
|
||||
if (ci->type != id_MISTRAL_ALUT_ARITH)
|
||||
continue;
|
||||
const NetInfo *cin = get_net_or_empty(ci, id_CI);
|
||||
if (cin != nullptr && cin->driver.cell != nullptr)
|
||||
continue; // not the start of a chain
|
||||
std::vector<CellInfo *> chain;
|
||||
CellInfo *cursor = ci;
|
||||
while (true) {
|
||||
chain.push_back(cursor);
|
||||
const NetInfo *co = get_net_or_empty(cursor, id_CO);
|
||||
if (co == nullptr || co->users.empty())
|
||||
break;
|
||||
if (co->users.size() > 1)
|
||||
log_error("Carry net %s has more than one sink!\n", ctx->nameOf(co));
|
||||
auto &usr = co->users.at(0);
|
||||
if (usr.port != id_CI)
|
||||
log_error("Carry net %s drives port %s, expected CI\n", ctx->nameOf(co), ctx->nameOf(usr.port));
|
||||
cursor = usr.cell;
|
||||
}
|
||||
|
||||
chain.at(0)->constr_abs_z = true;
|
||||
chain.at(0)->constr_z = 0;
|
||||
chain.at(0)->cluster = chain.at(0)->name;
|
||||
|
||||
for (int i = 1; i < int(chain.size()); i++) {
|
||||
chain.at(i)->constr_x = 0;
|
||||
chain.at(i)->constr_y = (i / 20);
|
||||
// 2 COMB, 4 FF per ALM
|
||||
chain.at(i)->constr_z = ((i / 2) % 10) * 6 + (i % 2);
|
||||
chain.at(i)->constr_abs_z = true;
|
||||
chain.at(i)->cluster = chain.at(0)->name;
|
||||
chain.at(0)->constr_children.push_back(chain.at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void run()
|
||||
{
|
||||
init_constant_nets();
|
||||
pack_constants();
|
||||
pack_io();
|
||||
constrain_carries();
|
||||
}
|
||||
};
|
||||
}; // namespace
|
||||
|
Loading…
Reference in New Issue
Block a user