mirror of https://github.com/YosysHQ/nextpnr.git
Gowin. BUGFIX. Alu optimization.
Adding freeing of the addition/subtraction mode switch PIP. We're limiting optimization to just one constant input—cases with two constant inputs are rare, and this raises questions about how such ALUs are generated in synthesis. LUT knowledge calculations have been replaced with table constants—faster and easier to verify. Addresses https://github.com/YosysHQ/apicula/issues/514 Signed-off-by: YRabbit <rabbit@yrabbit.cyou>
This commit is contained in:
parent
2dfdba6efc
commit
ae9a7dc865
|
|
@ -270,13 +270,6 @@ std::unique_ptr<CellInfo> GowinPacker::alu_add_dummy_block(Context *ctx, CellInf
|
|||
// 0110 -> 0011
|
||||
void GowinPacker::optimize_alu_lut(CellInfo *ci, int mode)
|
||||
{
|
||||
auto uni_shift = [&](unsigned int val, int amount) {
|
||||
if (amount < 0) {
|
||||
return val >> -amount;
|
||||
}
|
||||
return val << amount;
|
||||
};
|
||||
|
||||
IdString vcc_net_name = ctx->id("$PACKER_VCC");
|
||||
IdString gnd_net_name = ctx->id("$PACKER_GND");
|
||||
bool optimized = false;
|
||||
|
|
@ -288,57 +281,37 @@ void GowinPacker::optimize_alu_lut(CellInfo *ci, int mode)
|
|||
// representation.
|
||||
// If ADDSUB dynamically switches between + and -,
|
||||
// optimization is not possible.
|
||||
int possible_carry = 0b1100U;
|
||||
IdString inp_net_name = ci->getPort(id_I3)->name;
|
||||
if (inp_net_name != vcc_net_name && inp_net_name != gnd_net_name) {
|
||||
break;
|
||||
}
|
||||
if (inp_net_name == gnd_net_name) {
|
||||
possible_carry = 0b0011U;
|
||||
}
|
||||
unsigned int alu_lut = 0b0110000010011010U;
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
if (i == 2) {
|
||||
break;
|
||||
}
|
||||
|
||||
bool addition = inp_net_name == vcc_net_name;
|
||||
unsigned int alu_lut;
|
||||
|
||||
for (int i = 0; i < 2; ++i) {
|
||||
IdString inp_name = ctx->idf("I%d", i);
|
||||
inp_net_name = ci->getPort(inp_name)->name;
|
||||
if (inp_net_name == vcc_net_name || inp_net_name == gnd_net_name) {
|
||||
ci->disconnectPort(inp_name);
|
||||
// disconnect +/- selector
|
||||
ci->disconnectPort(id_I3);
|
||||
optimized = true;
|
||||
|
||||
// fix the carry
|
||||
if (i == 0) {
|
||||
if (inp_net_name == vcc_net_name) {
|
||||
alu_lut |= 0xfU;
|
||||
alu_lut = addition ? 0x303fU : 0xc0cfU;
|
||||
} else {
|
||||
alu_lut &= ~0xfU;
|
||||
alu_lut |= possible_carry;
|
||||
alu_lut = addition ? 0xc0c0U : 0x3030U;
|
||||
}
|
||||
} else {
|
||||
if (inp_net_name == vcc_net_name) {
|
||||
alu_lut = addition ? 0x505aU : 0xa0aaU;
|
||||
} else {
|
||||
alu_lut = addition ? 0xa0aaU : 0x505aU;
|
||||
}
|
||||
}
|
||||
|
||||
// We rearrange bits to account for constant networks
|
||||
int bit_n = 4;
|
||||
int copy_dist = 1 << i;
|
||||
if (inp_net_name == vcc_net_name) {
|
||||
bit_n += copy_dist;
|
||||
copy_dist = -copy_dist;
|
||||
}
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
alu_lut &= ~(1 << (bit_n + copy_dist));
|
||||
alu_lut |= uni_shift(alu_lut & (1 << bit_n), copy_dist);
|
||||
switch (i) {
|
||||
case 0: // skip the service bits
|
||||
bit_n += j == 1 ? 5 : 1;
|
||||
break;
|
||||
case 1: // skip the service bits
|
||||
bit_n += j == 1 ? 6 : 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
++bit_n;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (optimized) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue