diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index f36566a0..1a6c1bf5 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -448,6 +448,27 @@ void GateMateImpl::postRoute() } log_info("Check CPEs..\n"); dict cfg; + dict port_mapping; + auto add_input = [&](IdString orig_port, IdString port) { + static dict convert_port = { + {ctx->id("CPE.IN1"),id_IN1}, + {ctx->id("CPE.IN2"),id_IN2}, + {ctx->id("CPE.IN3"),id_IN3}, + {ctx->id("CPE.IN4"),id_IN4}, + {ctx->id("CPE.IN5"),id_IN1}, + {ctx->id("CPE.IN6"),id_IN2}, + {ctx->id("CPE.IN7"),id_IN3}, + {ctx->id("CPE.IN8"),id_IN4}, + {ctx->id("CPE.PINY1"),id_PINY1}, + {ctx->id("CPE.CINX"),id_CINX}, + {ctx->id("CPE.PINX"),id_PINX} + }; + if (convert_port.count(port)) { + printf("CONVERTED %s %s\n",orig_port.c_str(ctx), port.c_str(ctx)); + port_mapping.emplace(orig_port, convert_port[port]); + }; + + }; auto check_input = [&](CellInfo *cell, IdString port) { if (cell->getPort(port)) { NetInfo *net = cell->getPort(port); @@ -462,6 +483,7 @@ void GateMateImpl::postRoute() if (extra_data.type == PipExtra::PIP_EXTRA_MUX) { printf("name:%s %d\n",IdString(extra_data.name).c_str(ctx),extra_data.value); cfg.emplace(IdString(extra_data.name),extra_data.value); + add_input(port, ctx->getWireName(src)[1]); } if (net->wires.count(src)) { @@ -474,6 +496,7 @@ void GateMateImpl::postRoute() if (extra_data.type == PipExtra::PIP_EXTRA_MUX) { printf("name:%s %d\n",IdString(extra_data.name).c_str(ctx),extra_data.value); cfg.emplace(IdString(extra_data.name),extra_data.value); + add_input(port, ctx->getWireName(src)[1]); } @@ -487,6 +510,7 @@ void GateMateImpl::postRoute() if (extra_data.type == PipExtra::PIP_EXTRA_MUX) { printf("name:%s %d\n",IdString(extra_data.name).c_str(ctx),extra_data.value); cfg.emplace(IdString(extra_data.name),extra_data.value); + add_input(port, ctx->getWireName(src)[1]); } } else { @@ -508,10 +532,12 @@ void GateMateImpl::postRoute() ((lut & 0b0100) >> 1) | // b2 -> bit 1 ((lut & 0b0001)); // b0 -> bit 0 }; + for (auto &cell : ctx->cells) { - if (cell.second->type.in(id_CPE_L2T4,id_CPE_ADDF, id_CPE_ADDF2)) { + if (cell.second->type.in(id_CPE_L2T4)) { printf("\n"); cfg.clear(); + port_mapping.clear(); printf("type:%s name:%s\n",cell.second->type.c_str(ctx),cell.second->name.c_str(ctx)); int l00 = int_or_default(cell.second->params, id_INIT_L00, 0); int l01 = int_or_default(cell.second->params, id_INIT_L01, 0); @@ -525,91 +551,59 @@ void GateMateImpl::postRoute() check_input(cell.second.get(), id_D1_01); check_input(cell.second.get(), id_D0_10); check_input(cell.second.get(), id_D1_10); - if (cfg.count(ctx->id("CPE.D0_11")) || cfg.count(ctx->id("CPE.D0_10"))) { + if (cfg.count(ctx->id("LUT2_11")) || cfg.count(ctx->id("LUT2_10"))) { printf("LUT2 like\n"); - - if (cfg.count(ctx->id("CPE.D0_11"))) { //lower - printf("lower\n"); - if (cfg.at(ctx->id("CPE.D0_11"))==1) - l10 = swap_lut2_inputs(l10); - if (cfg.count(ctx->id("CPE.D0_02"))) { // 1st LUT2 - l00 = 0b1010; // LUT_D0 - we propagate only - if (cfg.at(ctx->id("CPE.D0_02"))==1) { - l00 = swap_lut2_inputs(l00); - if (cfg.count(ctx->id("CPE.C_I3"))) { - printf("D0_10 -> PINY1\n"); - cell.second->renamePort(id_D0_10, id_PINY1); - } else { - printf("D0_10 -> IN2\n"); - cell.second->renamePort(id_D0_10, id_IN2); - } - printf("D1_10 -> IN1\n"); - cell.second->renamePort(id_D1_10, id_IN1); - } else { - printf("D0_10 -> IN1\n"); - cell.second->renamePort(id_D0_10, id_IN1); - if (cfg.count(ctx->id("CPE.C_I3"))) { - printf("D1_10 -> PINY1\n"); - cell.second->renamePort(id_D1_10, id_PINY1); - } else { - printf("D1_10 -> IN2\n"); - cell.second->renamePort(id_D1_10, id_IN2); - } + if (cfg.count(ctx->id("LUT2_11"))) { //lower + if (cfg.count(ctx->id("LUT2_02")) && !cfg.count(ctx->id("LUT2_03"))) { + // both inputs on 02 + l00 = l10; // config is now in 02 + l10 = 0b1010; // LUT_D0 - we propagate only + } else if (!cfg.count(ctx->id("LUT2_02")) && cfg.count(ctx->id("LUT2_03"))) { + // both inputs on 03 + l01 = l10; // config is now in 03 + l10 = 0b1010; // LUT_D0 - we propagate only + } else { + // one input on 02, other on 03 (or LUT1) + if (cfg.count(ctx->id("LUT2_02"))) { + l00 = 0b1010; // LUT_D0 - we propagate only } - } else { //second LUT2 - l01 = 0b1010; // LUT_D0 - we propagate only - if (cfg.at(ctx->id("CPE.D0_03"))==1) { - l01 = swap_lut2_inputs(l01); - if (cfg.count(ctx->id("CPE.C_I4"))) { - printf("D0_10 -> PINX\n"); - cell.second->renamePort(id_D0_10, id_PINX); - } else { - printf("D0_10 -> IN4\n"); - cell.second->renamePort(id_D0_10, id_IN4); - } - printf("D1_10 -> IN3\n"); - cell.second->renamePort(id_D1_10, id_IN3); - } else { - printf("D0_10 -> IN3\n"); - cell.second->renamePort(id_D0_10, id_IN3); - if (cfg.count(ctx->id("CPE.C_I4"))) { - printf("D1_10 -> PINX\n"); - cell.second->renamePort(id_D1_10, id_PINX); - } - else { - printf("D1_10 -> IN4\n"); - cell.second->renamePort(id_D1_10, id_IN4); - } + if (cfg.count(ctx->id("LUT2_03"))) { + l01 = 0b1010; // LUT_D0 - we propagate only } } + + if (cfg.at(ctx->id("LUT2_11"))==1) + l10 = swap_lut2_inputs(l10); + if (cfg.count(ctx->id("LUT2_02")) && (cfg.at(ctx->id("LUT2_02"))==1)) + l00 = swap_lut2_inputs(l00); + if (cfg.count(ctx->id("LUT2_03")) && (cfg.at(ctx->id("LUT2_03"))==1)) + l01 = swap_lut2_inputs(l01); } else { // upper part - printf("upper\n"); - if (cfg.at(ctx->id("CPE.D0_10"))==1) { - printf("SWAP L10"); - l10 = swap_lut2_inputs(l10); - } - if (cfg.count(ctx->id("CPE.D0_00"))) { // 1st LUT2 - l00 = 0b1010; // LUT_D0 - we propagate only - if (cfg.at(ctx->id("CPE.D0_00"))==1) { - l00 = swap_lut2_inputs(l00); - cell.second->renamePort(id_D0_10, id_IN2); - cell.second->renamePort(id_D1_10, id_IN1); - } else { - cell.second->renamePort(id_D0_10, id_IN1); - cell.second->renamePort(id_D1_10, id_IN2); + if (cfg.count(ctx->id("LUT2_00")) && !cfg.count(ctx->id("LUT2_01"))) { + // both inputs on 02 + l00 = l10; // config is now in 02 + l10 = 0b1010; // LUT_D0 - we propagate only + } else if (!cfg.count(ctx->id("LUT2_00")) && cfg.count(ctx->id("LUT2_01"))) { + // both inputs on 03 + l01 = l10; // config is now in 03 + l10 = 0b1010; // LUT_D0 - we propagate only + } else { + // one input on 02, other on 03 (or LUT1) + if (cfg.count(ctx->id("LUT2_00"))) { + l00 = 0b1010; // LUT_D0 - we propagate only } + if (cfg.count(ctx->id("LUT2_01"))) { + l01 = 0b1010; // LUT_D0 - we propagate only + } + } + + if (cfg.at(ctx->id("LUT2_10"))==1) + l10 = swap_lut2_inputs(l10); + if (cfg.count(ctx->id("LUT2_00")) && (cfg.at(ctx->id("LUT2_00"))==1)) + l00 = swap_lut2_inputs(l00); + if (cfg.count(ctx->id("LUT2_01")) && (cfg.at(ctx->id("LUT2_01"))==1)) + l01 = swap_lut2_inputs(l01); - } else { //second LUT2 - l01 = 0b1010; // LUT_D0 - we propagate only - if (cfg.at(ctx->id("CPE.D0_01"))==1) { - l01 = swap_lut2_inputs(l01); - cell.second->renamePort(id_D0_10, id_IN4); - cell.second->renamePort(id_D1_10, id_IN3); - } else { - cell.second->renamePort(id_D0_10, id_IN3); - cell.second->renamePort(id_D1_10, id_IN4); - } - } } printf("updated\n=========\n"); printf("L00 %04b\n",l00); @@ -618,66 +612,31 @@ void GateMateImpl::postRoute() cell.second->params[id_INIT_L00] = Property(l00,4); cell.second->params[id_INIT_L01] = Property(l01,4); cell.second->params[id_INIT_L10] = Property(l10,4); - if (cfg.count(ctx->id("CPE.C_I1"))) - cell.second->renamePort(id_IN2, id_PINY1); - if (cfg.count(ctx->id("CPE.C_I2"))) - cell.second->renamePort(id_IN4, id_PINX); - if (cfg.count(ctx->id("CPE.C_I3"))) - cell.second->renamePort(id_IN2, id_PINY1); - if (cfg.count(ctx->id("CPE.C_I4"))) - cell.second->renamePort(id_IN4, id_CINX); - + + cell.second->renamePort(id_D0_10, port_mapping[id_D0_10]); + cell.second->renamePort(id_D1_10, port_mapping[id_D1_10]); } else { - if ((cfg.count(ctx->id("CPE.D0_00")) && cfg.at(ctx->id("CPE.D0_00"))==1) || - (cfg.count(ctx->id("CPE.D1_00")) && cfg.at(ctx->id("CPE.D1_00"))==1)) { + if (cfg.count(ctx->id("LUT2_00")) && cfg.at(ctx->id("LUT2_00"))==1) { l00 = swap_lut2_inputs(l00); - cell.second->renamePort(id_D0_00, id_IN2); - cell.second->renamePort(id_D1_00, id_IN1); - } else { - cell.second->renamePort(id_D0_00, id_IN1); - cell.second->renamePort(id_D1_00, id_IN2); - } - - - if ((cfg.count(ctx->id("CPE.D0_01")) && cfg.at(ctx->id("CPE.D0_01"))==1) || - (cfg.count(ctx->id("CPE.D1_01")) && cfg.at(ctx->id("CPE.D1_01"))==1)) { + } + if (cfg.count(ctx->id("LUT2_01")) && cfg.at(ctx->id("LUT2_01"))==1) { l01 = swap_lut2_inputs(l01); - cell.second->renamePort(id_D0_01, id_IN4); - cell.second->renamePort(id_D1_01, id_IN3); - } else { - cell.second->renamePort(id_D0_01, id_IN3); - cell.second->renamePort(id_D1_01, id_IN4); } - - if ((cfg.count(ctx->id("CPE.D0_02")) && cfg.at(ctx->id("CPE.D0_02"))==1) || - (cfg.count(ctx->id("CPE.D1_02")) && cfg.at(ctx->id("CPE.D1_02"))==1)) { + if (cfg.count(ctx->id("LUT2_02")) && cfg.at(ctx->id("LUT2_02"))==1) { l00 = swap_lut2_inputs(l00); - - cell.second->renamePort(id_D0_00, id_IN2); - cell.second->renamePort(id_D1_00, id_IN1); - } else { - cell.second->renamePort(id_D0_00, id_IN1); - cell.second->renamePort(id_D1_00, id_IN2); } - - if ((cfg.count(ctx->id("CPE.D0_03")) && cfg.at(ctx->id("CPE.D0_03"))==1) || - (cfg.count(ctx->id("CPE.D1_03")) && cfg.at(ctx->id("CPE.D1_03"))==1)) { + if (cfg.count(ctx->id("LUT2_03")) && cfg.at(ctx->id("LUT2_03"))==1) { l01 = swap_lut2_inputs(l01); - cell.second->renamePort(id_D0_01, id_IN4); - cell.second->renamePort(id_D1_01, id_IN3); - } else { - cell.second->renamePort(id_D0_01, id_IN3); - cell.second->renamePort(id_D1_01, id_IN4); } - if (cfg.count(ctx->id("CPE.C_I1"))) - cell.second->renamePort(id_IN2, id_PINY1); - if (cfg.count(ctx->id("CPE.C_I2"))) - cell.second->renamePort(id_IN4, id_PINX); - if (cfg.count(ctx->id("CPE.C_I3"))) - cell.second->renamePort(id_IN2, id_PINY1); - if (cfg.count(ctx->id("CPE.C_I4"))) - cell.second->renamePort(id_IN4, id_CINX); + cell.second->params[id_INIT_L00] = Property(l00,4); + cell.second->params[id_INIT_L01] = Property(l01,4); + cell.second->params[id_INIT_L10] = Property(l10,4); + + cell.second->renamePort(id_D0_00, port_mapping[id_D0_00]); + cell.second->renamePort(id_D1_00, port_mapping[id_D1_00]); + cell.second->renamePort(id_D0_01, port_mapping[id_D0_01]); + cell.second->renamePort(id_D1_01, port_mapping[id_D1_01]); } if (cfg.count(ctx->id("CPE.C_I1"))) cell.second->params[id_C_I1] = Property(1,1); diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index 9c99fa9a..52289e2d 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -131,8 +131,43 @@ void GateMatePacker::count_cell(CellInfo &ci) count++; } +inline int lut2_apply_constant_inputs(int init, int d0_const, int d1_const) +{ + int b0 = (init >> 0) & 1; + int b1 = (init >> 1) & 1; + int b2 = (init >> 2) & 1; + int b3 = (init >> 3) & 1; + + int out[4]; + + for (int i = 0; i < 4; i++) { + int D1 = (i >> 1) & 1; + int D0 = (i >> 0) & 1; + + // Apply constants if present + if (d0_const != -1) D0 = d0_const; + if (d1_const != -1) D1 = d1_const; + + int src = (D1 << 1) | D0; + out[i] = + (src == 0) ? b0 : + (src == 1) ? b1 : + (src == 2) ? b2 : + b3; + } + + return (out[3] << 3) | (out[2] << 2) | (out[1] << 1) | out[0]; +} + void GateMatePacker::optimize_lut() { + auto lut2_same_inputs = [&](int lut) -> int { + int b0 = lut & 1; // bit 0 + int b3 = (lut >> 3) & 1; // bit 3 + + return (b3 << 3) | (b3 << 2) | (b0 << 1) | b0; + }; + for (auto &cell : ctx->cells) { CellInfo &ci = *cell.second; if (!ci.type.in(id_CC_LUT1, id_CC_LUT2)) @@ -148,6 +183,23 @@ void GateMatePacker::optimize_lut() uint8_t val = int_or_default(ci.params, id_INIT, 0); if (ci.type == id_CC_LUT1) val = val << 2 | val; + else { + int d0_const = -1; + int d1_const = -1; + if (ci.getPort(id_I0) && ci.getPort(id_I0)==net_PACKER_GND) { d0_const = 0; ci.disconnectPort(id_I0); } + if (ci.getPort(id_I0) && ci.getPort(id_I0)==net_PACKER_VCC) { d0_const = 1; ci.disconnectPort(id_I0); } + if (ci.getPort(id_I1) && ci.getPort(id_I1)==net_PACKER_GND) { d1_const = 0; ci.disconnectPort(id_I1); } + if (ci.getPort(id_I1) && ci.getPort(id_I1)==net_PACKER_VCC) { d1_const = 1; ci.disconnectPort(id_I1); } + + val = lut2_apply_constant_inputs(val, d0_const, d1_const); + + if (ci.getPort(id_I0)==ci.getPort(id_I1)) { + printf("LUT2 with same inputs %s\n",ci.name.c_str(ctx)); + val = lut2_same_inputs(val); + ci.params[id_INIT] = Property(val,4); + ci.disconnectPort(id_I1); + } + } switch (val) { case LUT_ZERO: // constant 0 move_connections(o_net, net_PACKER_GND); diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index e54a55e0..a0315590 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -401,7 +401,7 @@ void GateMatePacker::pack_cpe() ci.disconnectPort(id_D); } else { lt->params[id_INIT_L10] = Property(LUT_D0, 4); - ci.movePortTo(id_D, lt, id_D0_00); + ci.movePortTo(id_D, lt, id_D0_10); } ci.type = (ci.type == id_CC_DLT) ? id_CPE_LATCH : id_CPE_FF; NetInfo *conn = ctx->createNet(ctx->idf("%s$di", ci.name.c_str(ctx)));