From ae9a7dc865b04cbb76d75741309df013a4f09a22 Mon Sep 17 00:00:00 2001 From: YRabbit Date: Tue, 16 Jun 2026 16:52:30 +1000 Subject: [PATCH] Gowin. BUGFIX. Alu optimization. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- himbaechel/uarch/gowin/pack_luts.cc | 59 ++++++++--------------------- 1 file changed, 16 insertions(+), 43 deletions(-) diff --git a/himbaechel/uarch/gowin/pack_luts.cc b/himbaechel/uarch/gowin/pack_luts.cc index 3e913615..aef5c07a 100644 --- a/himbaechel/uarch/gowin/pack_luts.cc +++ b/himbaechel/uarch/gowin/pack_luts.cc @@ -270,13 +270,6 @@ std::unique_ptr 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) {