current progress

This commit is contained in:
Lofty 2025-06-24 01:29:40 +01:00
parent 35c6fab0d0
commit 091bc57eab
2 changed files with 63 additions and 5 deletions

View File

@ -23,6 +23,8 @@
#include "config.h"
#include "gatemate.h"
#include "gatemate_util.h"
#include "nextpnr_assertions.h"
#include "uarch/gatemate/extra_data.h"
#define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc"
#include "himbaechel_constids.h"
@ -246,13 +248,13 @@ struct BitstreamBackend
// Update configuration bits based on signal inversion
dict<IdString, Property> params = cell.second->params;
uint8_t func = int_or_default(cell.second->params, id_C_FUNCTION, 0);
if (cell.second->type.in(id_CPE_HALF_U) && func != C_MX4) {
if (cell.second->type.in(id_CPE_HALF_U) && func != C_MX4 && func != C_MULT) {
update_cpe_lt(cell.second.get(), id_IN1, id_INIT_L00, params);
update_cpe_lt(cell.second.get(), id_IN2, id_INIT_L00, params);
update_cpe_lt(cell.second.get(), id_IN3, id_INIT_L01, params);
update_cpe_lt(cell.second.get(), id_IN4, id_INIT_L01, params);
}
if (cell.second->type.in(id_CPE_HALF_L)) {
if (cell.second->type.in(id_CPE_HALF_L) && func != C_MULT) {
update_cpe_lt(cell.second.get(), id_IN1, id_INIT_L02, params);
update_cpe_lt(cell.second.get(), id_IN2, id_INIT_L02, params);
update_cpe_lt(cell.second.get(), id_IN3, id_INIT_L03, params);

View File

@ -31,6 +31,30 @@
NEXTPNR_NAMESPACE_BEGIN
// Constant zero.
struct ZeroDriver
{
ZeroDriver() : lower{nullptr}, upper{nullptr} {}
ZeroDriver(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
{
lower->params[id_INIT_L02] = Property(LUT_ZERO, 4); // (unused)
lower->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
lower->params[id_INIT_L11] = Property(LUT_ZERO, 4); // (unused)
lower->params[id_INIT_L20] = Property(LUT_ZERO, 4); // (unused)
upper->params[id_INIT_L00] = Property(LUT_ZERO, 4); // (unused)
upper->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
upper->params[id_INIT_L10] = Property(LUT_ZERO, 4); // (unused)
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2
}
CellInfo *lower;
CellInfo *upper;
};
// Propagate A0 through OUT1 and A1 through OUT2; zero COUTX and POUTX.
struct APassThroughCell
{
@ -157,6 +181,7 @@ struct CarryGenCell
lower->params[id_INIT_L11] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
lower->params[id_INIT_L20] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
lower->params[id_INIT_L30] = Property(LUT_INV_D0, 4); // OUT1 -> COMP_OUT
lower->params[id_C_FUNCTION] = Property(C_EN_CIN, 3);
upper->params[id_INIT_L00] = Property(LUT_ZERO, 4); // (unused)
upper->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
@ -192,6 +217,7 @@ struct MultfabCell
lower->params[id_INIT_L11] = Property(LUT_D0, 4); // L02
lower->params[id_INIT_L20] = Property(is_even_x ? LUT_AND_INV_D0 : LUT_OR, 4); // L10 AND L11 -> OUT1
lower->params[id_INIT_L30] = Property(LUT_INV_D1, 4); // L10 -> COMP_OUT
lower->params[id_C_FUNCTION] = Property(C_ADDCIN, 3);
upper->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
upper->params[id_INIT_L01] = Property(is_even_x ? LUT_ZERO : LUT_D1, 4); // CINX
@ -231,6 +257,7 @@ struct FRoutingCell
lower->params[id_INIT_L11] = Property(LUT_AND, 4);
lower->params[id_INIT_L20] = Property(LUT_D1, 4);
lower->params[id_INIT_L30] = Property(is_even_x ? LUT_ONE : LUT_INV_D1, 4); // OUT1 -> COMP_OUT
lower->params[id_C_FUNCTION] = Property(C_ADDCIN, 3);
upper->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
upper->params[id_INIT_L01] = Property(LUT_ONE, 4); // (unused)
@ -268,6 +295,7 @@ struct MultCell
lower->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX
lower->params[id_INIT_L11] = Property(LUT_XOR, 4);
lower->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
lower->params[id_C_FUNCTION] = Property(C_MULT, 3);
upper->params[id_INIT_L00] = Property(LUT_AND, 4);
upper->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
@ -297,6 +325,7 @@ struct MultMsbCell
lower->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX
lower->params[id_INIT_L11] = Property(LUT_XOR, 4);
lower->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
lower->params[id_C_FUNCTION] = Property(C_MULT, 3);
upper->params[id_INIT_L00] = Property(LUT_AND, 4);
upper->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
@ -329,6 +358,7 @@ struct MsbRoutingCell
lower->params[id_INIT_L11] = Property(LUT_ZERO, 4);
lower->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
lower->params[id_INIT_L30] = Property(LUT_ONE, 4);
lower->params[id_C_FUNCTION] = Property(C_MULT, 3);
upper->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
upper->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
@ -364,14 +394,15 @@ struct MultiplierColumn
// A GateMate multiplier is made up of columns of 2x2 multipliers.
struct Multiplier
{
ZeroDriver zero;
std::vector<APassThroughCell> a_passthrus;
std::vector<MultiplierColumn> cols;
size_t cpe_count() const
{
auto count = a_passthrus.size();
auto count = 1 /* (zero driver) */ + a_passthrus.size();
for (const auto &col : cols) {
count += 6 + col.mults.size();
count += 4 /* (b_passthru, carry, multfab, f_route) */ + col.mults.size() + 2 /* (mult_msb, msb_route* */;
}
return count;
}
@ -382,6 +413,12 @@ void GateMatePacker::pack_mult()
// note to self: use constr_children for recursive constraints
// fpga_generic.pas in p_r might have useful info
auto create_zero_driver = [&](IdString name) {
auto *zero_lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$zero_lower", name.c_str(ctx)));
auto *zero_upper = create_cell_ptr(id_CPE_HALF_U, ctx->idf("%s$zero_upper", name.c_str(ctx)));
return ZeroDriver{zero_lower, zero_upper, name};
};
auto create_a_passthru = [&](IdString name) {
auto *a_passthru_lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$a_passthru_lower", name.c_str(ctx)));
auto *a_passthru_upper = create_cell_ptr(id_CPE_HALF_U, ctx->idf("%s$a_passthru_upper", name.c_str(ctx)));
@ -470,6 +507,7 @@ void GateMatePacker::pack_mult()
auto m = Multiplier{};
// Step 1: instantiate all the CPEs.
m.zero = create_zero_driver(ctx->idf("%s$col0", mult->name.c_str(ctx)));
for (int a = 0; a < a_width / 2; a++)
m.a_passthrus.push_back(create_a_passthru(ctx->idf("%s$col0$row%d", mult->name.c_str(ctx), a)));
for (int b = 0; b < b_width / 2; b++)
@ -491,6 +529,10 @@ void GateMatePacker::pack_mult()
cell->constr_z = cell->type == id_CPE_HALF_L ? 1 : 0;
};
// Constrain zero driver.
constrain_cell(m.zero.lower, -1, 3);
constrain_cell(m.zero.upper, -1, 3);
// Constrain A passthrough cells.
for (int a = 0; a < a_width / 2; a++) {
auto &a_passthru = m.a_passthrus.at(a);
@ -529,6 +571,11 @@ void GateMatePacker::pack_mult()
// TODO: check this with odd bus widths.
// Zero driver.
auto *zero_net = ctx->createNet(m.zero.upper->name);
m.zero.upper->connectPort(id_OUT, zero_net);
// A input.
for (int a = 0; a < a_width; a++) {
auto &a_passthru = m.a_passthrus.at(a / 2);
auto *cpe_half = (a % 2 == 1) ? a_passthru.upper : a_passthru.lower;
@ -566,9 +613,18 @@ void GateMatePacker::pack_mult()
mult_cell.lower->connectPort(id_IN4, a_net); // IN8
}
}
// constant zero goes to LSB of multipliers.
if (a == 0) {
auto &mult_col = m.cols.at(b);
auto *mult_cell = mult_col.mults.at(0).lower;
mult_cell->connectPort(id_IN4, zero_net);
}
}
}
// B input.
for (int b = 0; b < b_width; b++) {
auto &b_passthru = m.cols[b / 2].b_passthru;
auto *cpe_half = (b % 2 == 1) ? b_passthru.upper : b_passthru.lower;
@ -585,7 +641,7 @@ void GateMatePacker::pack_mult()
mult->copyPortTo(ctx->idf("B[%d]", b_width - 1), b_passthru.lower, id_IN1);
}
// Connect P outputs.
// P output.
auto diagonal_p_width = std::min(b_width, p_width);
auto vertical_p_width = std::max(p_width - b_width, 0);