diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index c8a484a6..87b694b1 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -906,6 +906,12 @@ X(USR_RSTN) // hardware primitive CPE_LT_U X(CPE_LT_U) // CPE_LT_U pins +X(D0_00) +X(D1_00) +X(D0_01) +X(D1_01) +X(D0_10) +X(D1_10) X(IN1) X(IN2) X(IN3) @@ -935,11 +941,17 @@ X(RAM_O) // hardware primitive CPE_LT_L X(CPE_LT_L) // CPE_LT_L pins +//X(D0_00) +//X(D1_00) +//X(D0_01) +//X(D1_01) +//X(D0_10) +//X(D1_10) +X(COMBIN) //X(IN1) //X(IN2) //X(IN3) //X(IN4) -X(COMBIN) //X(OUT) //X(CPOUT) //X(CINX) @@ -988,6 +1000,18 @@ X(MUXOUT) // hardware primitive CPE_LT_FULL X(CPE_LT_FULL) // CPE_LT_FULL pins +//X(D0_00) +//X(D1_00) +//X(D0_01) +//X(D1_01) +X(D0_02) +X(D1_02) +X(D0_03) +X(D1_03) +//X(D0_10) +//X(D1_10) +X(D0_11) +X(D1_11) //X(IN1) //X(IN2) //X(IN3) @@ -2476,6 +2500,14 @@ X(2B) X(DIE) X(GATEMATE_DIE) +// LUT permutation +X(LUT2_00) +X(LUT2_01) +X(LUT2_02) +X(LUT2_03) +X(LUT2_10) +X(LUT2_11) + // Timing X(timing_ADDF2x_IN5_8_comb2) X(timing_CIN_C_CINI) diff --git a/himbaechel/uarch/gatemate/delay.cc b/himbaechel/uarch/gatemate/delay.cc index 3a7a563b..c61168d3 100644 --- a/himbaechel/uarch/gatemate/delay.cc +++ b/himbaechel/uarch/gatemate/delay.cc @@ -90,14 +90,20 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin { delay = DelayQuad{0}; static dict map_upper = { - {id_OUT, id_OUT2}, - {id_RAM_O, id_RAM_O2}, - {id_RAM_I, id_RAM_I2}, - {id_CPOUT, id_CPOUT2}, + {id_D0_00, id_IN1}, {id_D1_00, id_IN2}, {id_D0_01, id_IN3}, {id_D1_01, id_IN4}, {id_D0_10, id_IN1}, + {id_D1_10, id_IN3}, {id_OUT, id_OUT2}, {id_RAM_O, id_RAM_O2}, {id_RAM_I, id_RAM_I2}, {id_CPOUT, id_CPOUT2}, }; static dict map_lower = { - {id_OUT, id_OUT1}, {id_RAM_O, id_RAM_O1}, {id_RAM_I, id_RAM_I1}, {id_CPOUT, id_CPOUT1}, - {id_IN1, id_IN5}, {id_IN2, id_IN6}, {id_IN3, id_IN7}, {id_IN4, id_IN8}, + {id_D0_00, id_IN5}, {id_D1_00, id_IN6}, {id_D0_01, id_IN7}, {id_D1_01, id_IN8}, {id_D0_10, id_IN5}, + {id_D1_10, id_IN7}, {id_D0_02, id_IN5}, {id_D1_02, id_IN6}, {id_D0_03, id_IN7}, {id_D1_03, id_IN8}, + {id_D0_11, id_IN5}, {id_D1_11, id_IN7}, {id_OUT, id_OUT1}, {id_RAM_O, id_RAM_O1}, {id_RAM_I, id_RAM_I1}, + {id_CPOUT, id_CPOUT1}, {id_IN1, id_IN5}, {id_IN2, id_IN6}, {id_IN3, id_IN7}, {id_IN4, id_IN8}, + }; + + static dict map_both = { + {id_D0_00, id_IN1}, {id_D1_00, id_IN2}, {id_D0_01, id_IN3}, {id_D1_01, id_IN4}, + {id_D0_10, id_IN1}, {id_D1_10, id_IN3}, {id_D0_02, id_IN5}, {id_D1_02, id_IN6}, + {id_D0_03, id_IN7}, {id_D1_03, id_IN8}, {id_D0_11, id_IN5}, {id_D1_11, id_IN7}, }; int z = (cell->bel != BelId()) ? (ctx->getBelLocation(cell->bel).z % 2) : 0; @@ -116,9 +122,19 @@ bool GateMateImpl::getCellDelay(const CellInfo *cell, IdString fromPort, IdStrin } return get_delay_from_tmg_db(ctx->idf("timing__ARBLUT_%s_%s", fp.c_str(ctx), tp.c_str(ctx)), delay); } else if (cell->type.in(id_CPE_ADDF, id_CPE_ADDF2)) { - return get_delay_from_tmg_db(ctx->idf("timing__ADDF2Y1_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + IdString fp = fromPort, tp = toPort; + if (map_both.count(fp)) + fp = map_both[fp]; + if (map_both.count(tp)) + tp = map_both[tp]; + return get_delay_from_tmg_db(ctx->idf("timing__ADDF2Y1_%s_%s", fp.c_str(ctx), tp.c_str(ctx)), delay); } else if (cell->type.in(id_CPE_MX4)) { - return get_delay_from_tmg_db(ctx->idf("timing__MX4A_%s_%s", fromPort.c_str(ctx), toPort.c_str(ctx)), delay); + IdString fp = fromPort, tp = toPort; + if (map_both.count(fp)) + fp = map_both[fp]; + if (map_both.count(tp)) + tp = map_both[tp]; + return get_delay_from_tmg_db(ctx->idf("timing__MX4A_%s_%s", fp.c_str(ctx), tp.c_str(ctx)), delay); } else if (cell->type.in(id_CPE_MULT)) { if (toPort == id_CPOUT1) return get_delay_from_tmg_db(ctx->id("timing_cpout_OUT1"), delay); @@ -187,22 +203,29 @@ TimingPortClass GateMateImpl::getPortTimingClass(const CellInfo *cell, IdString auto disconnected = [cell](IdString p) { return !cell->ports.count(p) || cell->ports.at(p).net == nullptr; }; clockInfoCount = 0; if (cell->type.in(id_CPE_L2T4, id_CPE_LT_L, id_CPE_LT_U)) { - if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_COMBIN, id_CINY1, id_CINY2, id_CINX, id_PINX)) + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_COMBIN, id_CINY1, id_CINY2, id_CINX, id_PINX, id_D0_00, id_D1_00, + id_D0_01, id_D1_01, id_D0_10, id_D1_10, id_D0_02, id_D1_02, id_D0_03, id_D1_03, id_D0_11, id_D1_11)) return TMG_COMB_INPUT; if (port == id_OUT && disconnected(id_IN1) && disconnected(id_IN2) && disconnected(id_IN3) && - disconnected(id_IN4)) + disconnected(id_IN4) && disconnected(id_D0_00) && disconnected(id_D1_00) && disconnected(id_D0_01) && + disconnected(id_D1_01) && disconnected(id_D0_10) && disconnected(id_D1_10) && disconnected(id_D0_02) && + disconnected(id_D1_02) && disconnected(id_D0_03) && disconnected(id_D1_03) && disconnected(id_D0_11) && + disconnected(id_D1_11)) return TMG_IGNORE; // LUT with no inputs is a constant if (port.in(id_OUT)) return TMG_COMB_OUTPUT; return TMG_IGNORE; } else if (cell->type.in(id_CPE_ADDF, id_CPE_ADDF2)) { - if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8, id_CINX, id_CINY1)) + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8, id_CINX, id_CINY1, id_D0_00, + id_D1_00, id_D0_01, id_D1_01, id_D0_10, id_D1_10, id_D0_02, id_D1_02, id_D0_03, id_D1_03, id_D0_11, + id_D1_11)) return TMG_COMB_INPUT; if (port.in(id_OUT1, id_OUT2, id_COUTY1)) return TMG_COMB_OUTPUT; return TMG_IGNORE; } else if (cell->type.in(id_CPE_MX4)) { - if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8)) + if (port.in(id_IN1, id_IN2, id_IN3, id_IN4, id_IN5, id_IN6, id_IN7, id_IN8, id_D0_00, id_D1_00, id_D0_01, + id_D1_01, id_D0_10, id_D1_10, id_D0_02, id_D1_02, id_D0_03, id_D1_03, id_D0_11, id_D1_11)) return TMG_COMB_INPUT; if (port.in(id_OUT1)) return TMG_COMB_OUTPUT; diff --git a/himbaechel/uarch/gatemate/gatemate.cc b/himbaechel/uarch/gatemate/gatemate.cc index f818550a..2c2e99e2 100644 --- a/himbaechel/uarch/gatemate/gatemate.cc +++ b/himbaechel/uarch/gatemate/gatemate.cc @@ -447,6 +447,201 @@ void GateMateImpl::postRoute() } } + dict cfg; + dict port_mapping; + auto add_input = [&](IdString orig_port, IdString port, bool merged) -> bool { + 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}}; + static dict convert_port_merged = { + {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_IN5}, {ctx->id("CPE.IN6"), id_IN6}, + {ctx->id("CPE.IN7"), id_IN7}, {ctx->id("CPE.IN8"), id_IN8}, {ctx->id("CPE.PINY1"), id_PINY1}, + {ctx->id("CPE.CINX"), id_CINX}, {ctx->id("CPE.PINX"), id_PINX}}; + if (convert_port.count(port)) { + port_mapping.emplace(orig_port, merged ? convert_port_merged[port] : convert_port[port]); + return true; + }; + return false; + }; + auto check_input = [&](CellInfo *cell, IdString port, bool merged) { + if (cell->getPort(port)) { + NetInfo *net = cell->getPort(port); + WireId src = ctx->getBelPinWire(cell->bel, port); + // In current chip db real CPE input is max 4 pips away + for (int i = 0; i < 4; i++) { + if (net->wires.count(src)) { + auto &p = net->wires.at(src); + src = ctx->getPipSrcWire(p.pip); + const auto &extra_data = *pip_extra_data(p.pip); + if (extra_data.type == PipExtra::PIP_EXTRA_MUX) { + cfg.emplace(IdString(extra_data.name), extra_data.value); + if (add_input(port, ctx->getWireName(src)[1], merged)) + break; + } + } + } + } + }; + auto swap_lut2_inputs = [&](int lut) -> int { + // bit permutation: [3,1,2,0] + return ((lut & 0b1000)) | // b3 -> bit 3 + ((lut & 0b0010) << 1) | // b1 -> bit 2 + ((lut & 0b0100) >> 1) | // b2 -> bit 1 + ((lut & 0b0001)); // b0 -> bit 0 + }; + + log_info("Update configuration based on routing..\n"); + for (auto &cell : ctx->cells) { + if (cell.second->type.in(id_CPE_L2T4)) { + cfg.clear(); + port_mapping.clear(); + + int l00 = int_or_default(cell.second->params, id_INIT_L00, 0); + int l01 = int_or_default(cell.second->params, id_INIT_L01, 0); + int l10 = int_or_default(cell.second->params, id_INIT_L10, 0); + + check_input(cell.second.get(), id_D0_00, false); + check_input(cell.second.get(), id_D1_00, false); + check_input(cell.second.get(), id_D0_01, false); + check_input(cell.second.get(), id_D1_01, false); + check_input(cell.second.get(), id_D0_10, false); + check_input(cell.second.get(), id_D1_10, false); + if (cfg.count(id_LUT2_11) || cfg.count(id_LUT2_10)) { + if (cfg.count(id_LUT2_11)) { // lower + if (cfg.count(id_LUT2_02) && !cfg.count(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(id_LUT2_02) && cfg.count(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(id_LUT2_02)) + l00 = 0b1010; // LUT_D0 - we propagate only + if (cfg.count(id_LUT2_03)) + l01 = 0b1010; // LUT_D0 - we propagate only + } + + if (cfg.at(id_LUT2_11) == 1) + l10 = swap_lut2_inputs(l10); + if (cfg.count(id_LUT2_02) && (cfg.at(id_LUT2_02) == 1)) + l00 = swap_lut2_inputs(l00); + if (cfg.count(id_LUT2_03) && (cfg.at(id_LUT2_03) == 1)) + l01 = swap_lut2_inputs(l01); + } else { // upper part + if (cfg.count(id_LUT2_00) && !cfg.count(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(id_LUT2_00) && cfg.count(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(id_LUT2_00)) + l00 = 0b1010; // LUT_D0 - we propagate only + if (cfg.count(id_LUT2_01)) + l01 = 0b1010; // LUT_D0 - we propagate only + } + + if (cfg.at(id_LUT2_10) == 1) + l10 = swap_lut2_inputs(l10); + if (cfg.count(id_LUT2_00) && (cfg.at(id_LUT2_00) == 1)) + l00 = swap_lut2_inputs(l00); + if (cfg.count(id_LUT2_01) && (cfg.at(id_LUT2_01) == 1)) + l01 = swap_lut2_inputs(l01); + } + 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_10, port_mapping[id_D0_10]); + cell.second->renamePort(id_D1_10, port_mapping[id_D1_10]); + } else { + if (cfg.count(id_LUT2_00) && cfg.at(id_LUT2_00) == 1) + l00 = swap_lut2_inputs(l00); + if (cfg.count(id_LUT2_01) && cfg.at(id_LUT2_01) == 1) + l01 = swap_lut2_inputs(l01); + if (cfg.count(id_LUT2_02) && cfg.at(id_LUT2_02) == 1) + l00 = swap_lut2_inputs(l00); + if (cfg.count(id_LUT2_03) && cfg.at(id_LUT2_03) == 1) + l01 = swap_lut2_inputs(l01); + + 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(id_C_I1) && cfg.at(id_C_I1) == 1) + cell.second->params[id_C_I1] = Property(1, 1); + if (cfg.count(id_C_I2) && cfg.at(id_C_I2) == 1) + cell.second->params[id_C_I2] = Property(1, 1); + if (cfg.count(id_C_I3) && cfg.at(id_C_I3) == 1) + cell.second->params[id_C_I3] = Property(1, 1); + if (cfg.count(id_C_I4) && cfg.at(id_C_I4) == 1) + cell.second->params[id_C_I4] = Property(1, 1); + } + if (cell.second->type.in(id_CPE_MX4, id_CPE_ADDF, id_CPE_ADDF2)) { + cfg.clear(); + port_mapping.clear(); + + int l00 = int_or_default(cell.second->params, id_INIT_L00, 0); + int l01 = int_or_default(cell.second->params, id_INIT_L01, 0); + int l02 = int_or_default(cell.second->params, id_INIT_L02, 0); + int l03 = int_or_default(cell.second->params, id_INIT_L03, 0); + + check_input(cell.second.get(), id_D0_00, true); + check_input(cell.second.get(), id_D1_00, true); + check_input(cell.second.get(), id_D0_01, true); + check_input(cell.second.get(), id_D1_01, true); + check_input(cell.second.get(), id_D0_02, true); + check_input(cell.second.get(), id_D1_02, true); + check_input(cell.second.get(), id_D0_03, true); + check_input(cell.second.get(), id_D1_03, true); + + if (cfg.count(id_LUT2_00) && cfg.at(id_LUT2_00) == 1) + l00 = swap_lut2_inputs(l00); + if (cfg.count(id_LUT2_01) && cfg.at(id_LUT2_01) == 1) + l01 = swap_lut2_inputs(l01); + if (cfg.count(id_LUT2_02) && cfg.at(id_LUT2_02) == 1) + l02 = swap_lut2_inputs(l02); + if (cfg.count(id_LUT2_03) && cfg.at(id_LUT2_03) == 1) + l03 = swap_lut2_inputs(l03); + + cell.second->params[id_INIT_L00] = Property(l00, 4); + cell.second->params[id_INIT_L01] = Property(l01, 4); + cell.second->params[id_INIT_L02] = Property(l02, 4); + cell.second->params[id_INIT_L03] = Property(l03, 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]); + cell.second->renamePort(id_D0_02, port_mapping[id_D0_02]); + cell.second->renamePort(id_D1_02, port_mapping[id_D1_02]); + cell.second->renamePort(id_D0_03, port_mapping[id_D0_03]); + cell.second->renamePort(id_D1_03, port_mapping[id_D1_03]); + + if (cfg.count(id_C_I1) && cfg.at(id_C_I1) == 1) + cell.second->params[id_C_I1] = Property(1, 1); + if (cfg.count(id_C_I2) && cfg.at(id_C_I2) == 1) + cell.second->params[id_C_I2] = Property(1, 1); + if (cfg.count(id_C_I3) && cfg.at(id_C_I3) == 1) + cell.second->params[id_C_I3] = Property(1, 1); + if (cfg.count(id_C_I4) && cfg.at(id_C_I4) == 1) + cell.second->params[id_C_I4] = Property(1, 1); + } + } ctx->assignArchInfo(); const ArchArgs &args = ctx->args; diff --git a/himbaechel/uarch/gatemate/gen/arch_gen.py b/himbaechel/uarch/gatemate/gen/arch_gen.py index bc0c2853..1e5b6a32 100644 --- a/himbaechel/uarch/gatemate/gen/arch_gen.py +++ b/himbaechel/uarch/gatemate/gen/arch_gen.py @@ -224,7 +224,7 @@ def set_timings(ch): assert k in timing, f"pip class {k} not found in timing data" tmg.set_pip_class(grade=speed, name=k, delay=convert_timing(timing[k])) -EXPECTED_VERSION = 1.10 +EXPECTED_VERSION = 1.11 def main(): # Range needs to be +1, but we are adding +2 more to coordinates, since diff --git a/himbaechel/uarch/gatemate/pack.cc b/himbaechel/uarch/gatemate/pack.cc index f7c61375..cac93631 100644 --- a/himbaechel/uarch/gatemate/pack.cc +++ b/himbaechel/uarch/gatemate/pack.cc @@ -131,10 +131,83 @@ 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_lut2(CellInfo &ci, IdString i0, IdString i1, IdString init) +{ + 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; + }; + + uint8_t val = int_or_default(ci.params, init, 0); + int d0_const = -1; + int d1_const = -1; + if (ci.getPort(i0) && ci.getPort(i0) == net_PACKER_GND) { + d0_const = 0; + ci.disconnectPort(i0); + } + if (ci.getPort(i0) && ci.getPort(i0) == net_PACKER_VCC) { + d0_const = 1; + ci.disconnectPort(i0); + } + if (ci.getPort(i1) && ci.getPort(i1) == net_PACKER_GND) { + d1_const = 0; + ci.disconnectPort(i1); + } + if (ci.getPort(i1) && ci.getPort(i1) == net_PACKER_VCC) { + d1_const = 1; + ci.disconnectPort(i1); + } + + val = lut2_apply_constant_inputs(val, d0_const, d1_const); + + if (ci.getPort(i0) == ci.getPort(i1)) { + val = lut2_same_inputs(val); + ci.params[init] = Property(val, 4); + ci.disconnectPort(i1); + } +} + void GateMatePacker::optimize_lut() { for (auto &cell : ctx->cells) { CellInfo &ci = *cell.second; + if (ci.type == id_CC_LUT2) { + optimize_lut2(ci, id_I0, id_I1, id_INIT); + } else if (ci.type == id_CC_L2T4) { + optimize_lut2(ci, id_I0, id_I1, id_INIT_L00); + optimize_lut2(ci, id_I2, id_I3, id_INIT_L01); + } else if (ci.type == id_CC_L2T5) { + optimize_lut2(ci, id_I0, id_I1, id_INIT_L02); + optimize_lut2(ci, id_I2, id_I3, id_INIT_L03); + } if (!ci.type.in(id_CC_LUT1, id_CC_LUT2)) continue; if (ci.attrs.count(ctx->id("keep"))) @@ -308,6 +381,8 @@ void GateMatePacker::repack_cpe() if (l.z == CPE_LT_L_Z) { if (!cell.second->params.count(id_INIT_L20)) cell.second->params[id_INIT_L20] = Property(LUT_D1, 4); + if (cell.second->getPort(id_D0_10)) { + } } cell.second->params[id_L2T4_UPPER] = Property((l.z == CPE_LT_U_Z) ? 1 : 0, 1); } else if (cell.second->type.in(id_CPE_LT_L)) { @@ -318,6 +393,13 @@ void GateMatePacker::repack_cpe() loc.z = CPE_LT_FULL_Z; ctx->unbindBel(bel); ctx->bindBel(ctx->getBelByLocation(loc), cell.second.get(), strength); + cell.second->renamePort(id_D0_00, id_D0_02); + cell.second->renamePort(id_D1_00, id_D1_02); + cell.second->renamePort(id_D0_01, id_D0_03); + cell.second->renamePort(id_D1_01, id_D1_03); + cell.second->renamePort(id_D0_10, id_D0_11); + cell.second->renamePort(id_D1_10, id_D1_11); + cell.second->renamePort(id_IN1, id_IN5); cell.second->renamePort(id_IN2, id_IN6); cell.second->renamePort(id_IN3, id_IN7); @@ -368,6 +450,14 @@ void GateMatePacker::repack_cpe() cell.second->params[id_C_I1] = Property(int_or_default(upper->params, id_C_I1, 0), 1); if (upper->params.count(id_C_I2)) cell.second->params[id_C_I2] = Property(int_or_default(upper->params, id_C_I2, 0), 1); + + upper->movePortTo(id_D0_00, cell.second.get(), id_D0_00); + upper->movePortTo(id_D1_00, cell.second.get(), id_D1_00); + upper->movePortTo(id_D0_01, cell.second.get(), id_D0_01); + upper->movePortTo(id_D1_01, cell.second.get(), id_D1_01); + upper->movePortTo(id_D0_10, cell.second.get(), id_D0_10); + upper->movePortTo(id_D1_10, cell.second.get(), id_D1_10); + upper->movePortTo(id_IN1, cell.second.get(), id_IN1); upper->movePortTo(id_IN2, cell.second.get(), id_IN2); upper->movePortTo(id_IN3, cell.second.get(), id_IN3); diff --git a/himbaechel/uarch/gatemate/pack.h b/himbaechel/uarch/gatemate/pack.h index d7bae92d..533fa7bb 100644 --- a/himbaechel/uarch/gatemate/pack.h +++ b/himbaechel/uarch/gatemate/pack.h @@ -85,6 +85,7 @@ struct GateMatePacker void disconnect_not_used(); void optimize_lut(); + void optimize_lut2(CellInfo &ci, IdString i0, IdString i1, IdString init); void optimize_mx(); void optimize_ff(); void count_cell(CellInfo &ci); diff --git a/himbaechel/uarch/gatemate/pack_cpe.cc b/himbaechel/uarch/gatemate/pack_cpe.cc index dbc62492..5ea2868e 100644 --- a/himbaechel/uarch/gatemate/pack_cpe.cc +++ b/himbaechel/uarch/gatemate/pack_cpe.cc @@ -202,10 +202,10 @@ void GateMatePacker::pack_cpe() bool is_l2t5 = false; if (ci.type == id_CC_L2T5) { l2t5_list.push_back(&ci); - ci.renamePort(id_I0, id_IN1); - ci.renamePort(id_I1, id_IN2); - ci.renamePort(id_I2, id_IN3); - ci.renamePort(id_I3, id_IN4); + ci.renamePort(id_I0, id_D0_00); + ci.renamePort(id_I1, id_D1_00); + ci.renamePort(id_I2, id_D0_01); + ci.renamePort(id_I3, id_D1_01); ci.renamePort(id_O, id_OUT); rename_param(&ci, id_INIT_L02, id_INIT_L00, 4); @@ -217,12 +217,12 @@ void GateMatePacker::pack_cpe() ci.type = id_CPE_L2T4; is_l2t5 = true; } else if (ci.type == id_CC_MX2) { - ci.renamePort(id_D1, id_IN1); + ci.renamePort(id_D1, id_D0_00); NetInfo *sel = ci.getPort(id_S0); - ci.renamePort(id_S0, id_IN2); - ci.addInput(id_IN3); - ci.connectPort(id_IN3, sel); - ci.renamePort(id_D0, id_IN4); + ci.renamePort(id_S0, id_D1_00); + ci.addInput(id_D0_01); + ci.connectPort(id_D0_01, sel); + ci.renamePort(id_D0, id_D1_01); ci.disconnectPort(id_D1); ci.params[id_INIT_L00] = Property(LUT_AND, 4); ci.params[id_INIT_L01] = Property(LUT_AND_INV_D0, 4); @@ -230,18 +230,20 @@ void GateMatePacker::pack_cpe() ci.renamePort(id_Y, id_OUT); ci.type = id_CPE_L2T4; } else { - ci.renamePort(id_I0, id_IN1); - ci.renamePort(id_I1, id_IN2); - ci.renamePort(id_I2, id_IN3); - ci.renamePort(id_I3, id_IN4); ci.renamePort(id_O, id_OUT); if (ci.type.in(id_CC_LUT1, id_CC_LUT2)) { + ci.renamePort(id_I0, id_D0_10); + ci.renamePort(id_I1, id_D1_10); uint8_t val = int_or_default(ci.params, id_INIT, 0); if (ci.type == id_CC_LUT1) val = val << 2 | val; - ci.params[id_INIT_L00] = Property(val, 4); + ci.params[id_INIT_L10] = Property(val, 4); ci.unsetParam(id_INIT); - ci.params[id_INIT_L10] = Property(LUT_D0, 4); + } else { + ci.renamePort(id_I0, id_D0_00); + ci.renamePort(id_I1, id_D1_00); + ci.renamePort(id_I2, id_D0_01); + ci.renamePort(id_I3, id_D1_01); } ci.type = id_CPE_L2T4; } @@ -297,8 +299,7 @@ void GateMatePacker::pack_cpe() upper->region = ci->region; upper->constr_abs_z = true; upper->constr_z = CPE_LT_U_Z; - ci->movePortTo(id_I4, upper, id_IN1); - upper->params[id_INIT_L00] = Property(LUT_D0, 4); + ci->movePortTo(id_I4, upper, id_D0_10); upper->params[id_INIT_L10] = Property(LUT_D0, 4); ci->constr_children.push_back(upper); @@ -322,8 +323,8 @@ void GateMatePacker::pack_cpe() ci.cluster = ci.name; ci.renamePort(id_Y, id_OUT); - ci.renamePort(id_S0, id_IN2); // IN6 - ci.renamePort(id_S1, id_IN4); // IN8 + ci.renamePort(id_S0, id_D0_00); // IN5 + ci.renamePort(id_S1, id_D0_01); // IN7 uint8_t select = 0; uint8_t invert = 0; @@ -341,8 +342,8 @@ void GateMatePacker::pack_cpe() } } ci.params[id_C_FUNCTION] = Property(C_MX4, 3); - ci.params[id_INIT_L02] = Property(LUT_D1, 4); // IN6 - ci.params[id_INIT_L03] = Property(LUT_D1, 4); // IN8 + ci.params[id_INIT_L02] = Property(LUT_D0, 4); // IN5 + ci.params[id_INIT_L03] = Property(LUT_D0, 4); // IN7 ci.params[id_INIT_L11] = Property(invert, 4); // Inversion bits ci.params[id_INIT_L20] = Property(LUT_D1, 4); // Always D1 ci.type = id_CPE_LT_L; @@ -389,16 +390,15 @@ void GateMatePacker::pack_cpe() ci.renamePort(id_Q, id_DOUT); NetInfo *d_net = ci.getPort(id_D); if (d_net == net_PACKER_GND) { - lt->params[id_INIT_L00] = Property(LUT_ZERO, 4); + lt->params[id_INIT_L10] = Property(LUT_ZERO, 4); ci.disconnectPort(id_D); } else if (d_net == net_PACKER_VCC) { - lt->params[id_INIT_L00] = Property(LUT_ONE, 4); + lt->params[id_INIT_L10] = Property(LUT_ONE, 4); ci.disconnectPort(id_D); } else { - lt->params[id_INIT_L00] = Property(LUT_D0, 4); + lt->params[id_INIT_L10] = Property(LUT_D0, 4); + ci.movePortTo(id_D, lt, id_D0_10); } - lt->params[id_INIT_L10] = Property(LUT_D0, 4); - ci.movePortTo(id_D, lt, id_IN1); 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))); lt->connectPort(id_OUT, conn); @@ -610,8 +610,8 @@ void GateMatePacker::pack_addf() bool merged = cy->type != id_CC_ADDF; if (merged) { - merge_input(cy, cy, id_A2, id_INIT_L02, id_IN1, id_IN2); // IN5,IN6 - merge_input(cy, cy, id_B2, id_INIT_L03, id_IN3, id_IN4); // IN7,IN8 + merge_input(cy, cy, id_A2, id_INIT_L02, id_D0_02, id_D1_02); // IN5,IN6 + merge_input(cy, cy, id_B2, id_INIT_L03, id_D0_03, id_D1_03); // IN7,IN8 cy->params[id_INIT_L11] = Property(LUT_XOR, 4); } else { cy->params[id_INIT_L02] = Property(LUT_ZERO, 4); @@ -638,8 +638,8 @@ void GateMatePacker::pack_addf() cy->renamePort(id_S, id_OUT); } merge_dff(cy, id_OUT, other_dff); - merge_input(cy, upper, id_A, id_INIT_L00, id_IN1, id_IN2); - merge_input(cy, upper, id_B, id_INIT_L01, id_IN3, id_IN4); + merge_input(cy, upper, id_A, id_INIT_L00, id_D0_00, id_D1_00); + merge_input(cy, upper, id_B, id_INIT_L01, id_D0_01, id_D1_01); upper->params[id_INIT_L10] = Property(LUT_XOR, 4); upper->params[id_C_FUNCTION] = Property(merged ? C_ADDF2 : C_ADDF, 3); @@ -804,16 +804,15 @@ std::pair GateMatePacker::move_ram_o(CellInfo *cell, IdS ctx->bindBel(b, cpe_half, PlaceStrength::STRENGTH_FIXED); } if (net == net_PACKER_GND) { - cpe_half->params[id_INIT_L00] = Property(LUT_ZERO, 4); + cpe_half->params[id_INIT_L10] = Property(LUT_ZERO, 4); cell->disconnectPort(origPort); } else if (net == net_PACKER_VCC) { - cpe_half->params[id_INIT_L00] = Property(LUT_ONE, 4); + cpe_half->params[id_INIT_L10] = Property(LUT_ONE, 4); cell->disconnectPort(origPort); } else { - cpe_half->params[id_INIT_L00] = Property(LUT_D0, 4); - cell->movePortTo(origPort, cpe_half, id_IN1); + cpe_half->params[id_INIT_L10] = Property(LUT_D0, 4); + cell->movePortTo(origPort, cpe_half, id_D0_10); } - cpe_half->params[id_INIT_L10] = Property(LUT_D0, 4); cpe_ramio->params[id_C_RAM_O] = Property(1, 1); NetInfo *ram_o = ctx->createNet(ctx->idf("%s$ram_o", cpe_half->name.c_str(ctx))); @@ -867,16 +866,15 @@ std::pair GateMatePacker::move_ram_io(CellInfo *cell, Id if (o_net) { if (o_net == net_PACKER_GND) { - cpe_half->params[id_INIT_L00] = Property(LUT_ZERO, 4); + cpe_half->params[id_INIT_L10] = Property(LUT_ZERO, 4); cell->disconnectPort(oPort); } else if (o_net == net_PACKER_VCC) { - cpe_half->params[id_INIT_L00] = Property(LUT_ONE, 4); + cpe_half->params[id_INIT_L10] = Property(LUT_ONE, 4); cell->disconnectPort(oPort); } else { - cpe_half->params[id_INIT_L00] = Property(LUT_D0, 4); - cell->movePortTo(oPort, cpe_half, id_IN1); + cpe_half->params[id_INIT_L10] = Property(LUT_D0, 4); + cell->movePortTo(oPort, cpe_half, id_D0_10); } - cpe_half->params[id_INIT_L10] = Property(LUT_D0, 4); cpe_ramio->params[id_C_RAM_O] = Property(1, 1); NetInfo *ram_o = ctx->createNet(ctx->idf("%s$ram_o", cpe_half->name.c_str(ctx))); diff --git a/himbaechel/uarch/gatemate/pack_io.cc b/himbaechel/uarch/gatemate/pack_io.cc index 438e9a63..5c913295 100644 --- a/himbaechel/uarch/gatemate/pack_io.cc +++ b/himbaechel/uarch/gatemate/pack_io.cc @@ -560,7 +560,7 @@ void GateMatePacker::pack_io_sel() int die = uarch->tile_extra_data(ci.bel.tile)->die; auto [cpe_half, cpe_ramio] = ddr[die][pad->pad_bank]; if (cpe_half) { - if (cpe_half->getPort(id_IN1) != oddr->getPort(id_DDR)) + if (cpe_half->getPort(id_D0_10) != oddr->getPort(id_DDR)) log_error("DDR port use signal different than already occupied DDR source.\n"); ci.addInput(id_DDR); ci.connectPort(id_DDR, cpe_ramio->getPort(id_RAM_O)); @@ -568,7 +568,7 @@ void GateMatePacker::pack_io_sel() auto l = reinterpret_cast(pad->extra_data.get()); oddr->movePortTo(id_DDR, &ci, id_DDR); ddr[die][pad->pad_bank] = move_ram_o(&ci, id_DDR, false, Loc(l->x, l->y, l->z)); - uarch->ddr_nets.insert(ddr[die][pad->pad_bank].first->getPort(id_IN1)->name); + uarch->ddr_nets.insert(ddr[die][pad->pad_bank].first->getPort(id_D0_10)->name); } use_custom_clock = set_out_clk(oddr, &ci); bool invert = bool_or_default(oddr->params, id_CLK_INV, 0);