current progress (013 seems to work?)

This commit is contained in:
Lofty 2025-06-28 18:47:30 +01:00
parent bdf235721e
commit 2d81d34991
4 changed files with 126 additions and 86 deletions

View File

@ -51,7 +51,8 @@ static std::string clock_event_name(const Context *ctx, const ClockEvent &e)
return value;
};
static std::vector<std::string> net_sources(const NetInfo *net, const Context *ctx) {
static std::vector<std::string> net_sources(const NetInfo *net, const Context *ctx)
{
auto sources = net->attrs.find(ctx->id("src"));
std::vector<std::string> source_entries;
if (sources != net->attrs.end()) {

View File

@ -215,6 +215,91 @@ void GateMateImpl::postPlace()
}
}
}
auto print_config = [&](CellInfo *cell, dict<IdString, Property> &params) {
uint32_t word1 = 0;
uint32_t word2 = 0;
uint32_t word3 = 0;
word1 |= int_or_default(params, id_INIT_L00, 0);
word1 |= int_or_default(params, id_INIT_L01, 0) << 4;
word1 |= int_or_default(params, id_INIT_L02, 0) << 8;
word1 |= int_or_default(params, id_INIT_L03, 0) << 12;
word1 |= int_or_default(params, id_INIT_L10, 0) << 16;
word1 |= int_or_default(params, id_INIT_L11, 0) << 20;
word1 |= int_or_default(params, id_INIT_L20, 0) << 24;
word1 |= int_or_default(params, id_INIT_L30, 0) << 28;
word2 |= int_or_default(params, id_C_I1, 0) << (32 - 32);
word2 |= int_or_default(params, id_C_I2, 0) << (33 - 32);
word2 |= int_or_default(params, id_C_I3, 0) << (34 - 32);
word2 |= int_or_default(params, id_C_I4, 0) << (35 - 32);
word2 |= int_or_default(params, id_C_FUNCTION, 0) << (36 - 32);
word2 |= int_or_default(params, id_C_COMP, 0) << (39 - 32);
word2 |= int_or_default(params, id_C_COMP_I, 0) << (40 - 32);
word2 |= int_or_default(params, id_C_HORIZ, 0) << (41 - 32);
word2 |= int_or_default(params, id_C_SELX, 0) << (42 - 32);
word2 |= int_or_default(params, id_C_SELY1, 0) << (43 - 32);
word2 |= int_or_default(params, id_C_SELY2, 0) << (44 - 32);
word2 |= int_or_default(params, id_C_SEL_C, 0) << (45 - 32);
word2 |= int_or_default(params, id_C_SEL_P, 0) << (46 - 32);
word2 |= int_or_default(params, id_C_Y12, 0) << (47 - 32);
word2 |= int_or_default(params, id_C_CX_I, 0) << (48 - 32);
word2 |= int_or_default(params, id_C_CY1_I, 0) << (49 - 32);
word2 |= int_or_default(params, id_C_CY2_I, 0) << (50 - 32);
word2 |= int_or_default(params, id_C_PX_I, 0) << (51 - 32);
word2 |= int_or_default(params, id_C_PY1_I, 0) << (52 - 32);
word2 |= int_or_default(params, id_C_PY2_I, 0) << (53 - 32);
word2 |= int_or_default(params, id_C_C_P, 0) << (54 - 32);
word2 |= int_or_default(params, id_C_2D_IN, 0) << (55 - 32);
word2 |= int_or_default(params, id_C_SN, 0) << (56 - 32);
word2 |= int_or_default(params, id_C_O1, 0) << (59 - 32);
word2 |= int_or_default(params, id_C_O2, 0) << (61 - 32);
word2 |= int_or_default(params, id_C_BR, 0) << (63 - 32);
word3 |= int_or_default(params, id_C_CPE_CLK, 0) << (64 - 64);
word3 |= int_or_default(params, id_C_CPE_EN, 0) << (66 - 64);
word3 |= int_or_default(params, id_C_CPE_RES, 0) << (68 - 64);
word3 |= int_or_default(params, id_C_CPE_SET, 0) << (70 - 64);
word3 |= int_or_default(params, id_C_RAM_I1, 0) << (72 - 64);
word3 |= int_or_default(params, id_C_RAM_I2, 0) << (73 - 64);
word3 |= int_or_default(params, id_C_RAM_O1, 0) << (74 - 64);
word3 |= int_or_default(params, id_C_RAM_O2, 0) << (75 - 64);
word3 |= int_or_default(params, id_C_L_D, 0) << (76 - 64);
word3 |= int_or_default(params, id_C_EN_SR, 0) << (77 - 64);
word3 |= int_or_default(params, id_C_CLKSEL, 0) << (78 - 64);
word3 |= int_or_default(params, id_C_ENSEL, 0) << (79 - 64);
auto loc = ctx->getBelLocation(cell->bel);
printf("(%d, %d): %s %02x_%02x%02x_%02x_%04x_%04x_%04x\n", loc.x, loc.y, cell->name.c_str(ctx), word3 >> 8,
word3 & 0xFF, word2 >> 24, (word2 >> 16) & 0xFF, word2 & 0xFFFF, word1 >> 16, word1 & 0xFFFF);
};
if (ctx->debug) {
std::set<CellInfo *> done;
printf("=====================\n");
for (auto &cell : ctx->cells) {
if (cell.second->type.in(id_CPE_HALF_L)) {
Loc l = ctx->getBelLocation(cell.second->bel);
dict<IdString, Property> params = cell.second->params;
CellInfo *upper = ctx->getBoundBelCell(ctx->getBelByLocation(Loc(l.x, l.y, l.z == 1 ? 0 : 1)));
if (upper) {
for (auto &p : upper->params) {
params.emplace(p.first, p.second);
}
done.emplace(upper);
}
print_config(cell.second.get(), params);
}
}
for (auto &cell : ctx->cells) {
if (cell.second->type.in(id_CPE_HALF_U) && done.count(cell.second.get()) == 0) {
print_config(cell.second.get(), cell.second->params);
}
}
printf("=====================\n");
}
}
void GateMateImpl::preRoute() { route_clock(); }

View File

@ -68,7 +68,7 @@ struct BPassThroughCell
struct CarryGenCell
{
CarryGenCell() : lower{nullptr}, upper{nullptr} {}
CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x);
CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x, bool enable_cinx);
CellInfo *lower;
CellInfo *upper;
@ -78,7 +78,7 @@ struct CarryGenCell
struct MultfabCell
{
MultfabCell() : lower{nullptr}, upper{nullptr} {}
MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x);
MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x, bool enable_cinx);
CellInfo *lower;
CellInfo *upper;
@ -100,16 +100,7 @@ struct FRoutingCell
struct MultCell
{
MultCell() : lower{nullptr}, upper{nullptr} {}
MultCell(CellInfo *lower, CellInfo *upper, IdString name);
CellInfo *lower;
CellInfo *upper;
};
struct MultMsbCell
{
MultMsbCell() : lower{nullptr}, upper{nullptr} {}
MultMsbCell(CellInfo *lower, CellInfo *upper, IdString name);
MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb);
CellInfo *lower;
CellInfo *upper;
@ -132,7 +123,6 @@ struct MultiplierColumn
MultfabCell multfab;
FRoutingCell f_route;
std::vector<MultCell> mults;
MultMsbCell mult_msb;
MsbRoutingCell msb_route;
};

View File

@ -153,7 +153,8 @@ void BPassThroughCell::clean_up(Context *ctx)
}
}
CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x, bool enable_cinx)
: lower{lower}, upper{upper}
{
// TODO: simplify AND with zero/OR with zero into something more sensical.
@ -164,8 +165,8 @@ CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool
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
upper->params[id_INIT_L00] = Property(enable_cinx ? LUT_ONE : LUT_ZERO, 4); // ???
upper->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
upper->params[id_INIT_L10] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
upper->params[id_C_I2] = Property(1, 1); // CINX for L01
@ -180,7 +181,8 @@ CarryGenCell::CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
}
MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x, bool enable_cinx)
: lower{lower}, upper{upper}
{
// TODO: perhaps C_I[1234] could be pips?
@ -191,9 +193,9 @@ MultfabCell::MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool i
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
upper->params[id_INIT_L10] = Property(LUT_XOR, 4); // XOR
upper->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
upper->params[id_INIT_L01] = Property(enable_cinx ? LUT_D1 : LUT_ZERO, 4); // CINX
upper->params[id_INIT_L10] = Property(LUT_XOR, 4); // XOR
upper->params[id_C_I1] = Property(1, 1); // PINY1 for L00
upper->params[id_C_I2] = Property(1, 1); // CINX for L01
@ -241,7 +243,7 @@ FRoutingCell::FRoutingCell(CellInfo *lower, CellInfo *upper, IdString name, bool
upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2
}
MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_msb) : lower{lower}, upper{upper}
{
lower->params[id_INIT_L02] = Property(LUT_AND, 4);
lower->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX
@ -259,33 +261,15 @@ MultCell::MultCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lowe
upper->params[id_C_I4] = Property(1, 1); // PINX for L03
upper->params[id_C_FUNCTION] = Property(C_MULT, 3);
if (is_msb) {
upper->params[id_C_PY1_I] = Property(1, 1);
upper->params[id_C_C_P] = Property(1, 1);
}
upper->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1
upper->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2
}
MultMsbCell::MultMsbCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
{
lower->params[id_INIT_L02] = Property(LUT_AND, 4);
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
upper->params[id_INIT_L10] = Property(LUT_XOR, 4);
upper->params[id_C_I1] = Property(1, 1); // PINY1 for L00
upper->params[id_C_I2] = Property(1, 1); // CINX for L01
upper->params[id_C_I3] = Property(1, 1); // PINY1 for L02
upper->params[id_C_I4] = Property(1, 1); // PINX for L03
upper->params[id_C_FUNCTION] = Property(C_MULT, 3);
upper->params[id_C_PY1_I] = Property(1, 1);
upper->params[id_C_C_P] = Property(1, 1);
upper->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1
}
MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
{
lower->params[id_INIT_L02] = Property(LUT_ONE, 4);
@ -293,14 +277,12 @@ MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, IdString name)
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)
upper->params[id_INIT_L10] = Property(LUT_OR, 4);
upper->params[id_C_I1] = Property(1, 1); // PINY1 for L00
upper->params[id_C_FUNCTION] = Property(C_MULT, 3);
upper->params[id_C_SELX] = Property(1, 1);
upper->params[id_C_SEL_P] = Property(1, 1);
upper->params[id_C_CX_I] = Property(1, 1);
@ -308,7 +290,7 @@ MsbRoutingCell::MsbRoutingCell(CellInfo *lower, CellInfo *upper, IdString name)
upper->params[id_C_PY1_I] = Property(1, 1);
upper->params[id_C_PY2_I] = Property(1, 1);
upper->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2
upper->params[id_C_O2] = Property(0b11, 2); // COMB2 -> OUT2
}
void GateMatePacker::pack_mult()
@ -328,7 +310,8 @@ void GateMatePacker::pack_mult()
return APassThroughCell{a_passthru_lower, a_passthru_upper, name, inverted};
};
auto create_mult_col = [&](IdString name, int a_width, bool is_even_x) {
auto create_mult_col = [&](IdString name, int a_width, bool is_even_x, bool carry_enable_cinx,
bool multfab_enable_cinx) {
// Ideally this would be the MultiplierColumn constructor, but we need create_cell_ptr here.
auto col = MultiplierColumn{};
@ -341,7 +324,7 @@ void GateMatePacker::pack_mult()
{
auto *carry_lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$carry_lower", name.c_str(ctx)));
auto *carry_upper = create_cell_ptr(id_CPE_HALF_U, ctx->idf("%s$carry_upper", name.c_str(ctx)));
col.carry = CarryGenCell{carry_lower, carry_upper, name, is_even_x};
col.carry = CarryGenCell{carry_lower, carry_upper, name, is_even_x, carry_enable_cinx};
}
{
@ -349,7 +332,7 @@ void GateMatePacker::pack_mult()
ctx->idf("%s$multf%c_lower", name.c_str(ctx), is_even_x ? 'a' : 'b'));
auto *multfab_upper = create_cell_ptr(id_CPE_HALF_U,
ctx->idf("%s$multf%c_upper", name.c_str(ctx), is_even_x ? 'a' : 'b'));
col.multfab = MultfabCell{multfab_lower, multfab_upper, name, is_even_x};
col.multfab = MultfabCell{multfab_lower, multfab_upper, name, is_even_x, multfab_enable_cinx};
}
{
@ -358,16 +341,10 @@ void GateMatePacker::pack_mult()
col.f_route = FRoutingCell{f_route_lower, f_route_upper, name, is_even_x};
}
for (int i = 0; i < a_width / 2; i++) {
for (int i = 0; i < (a_width / 2); i++) {
auto *mult_lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$row%d$mult_lower", name.c_str(ctx), i));
auto *mult_upper = create_cell_ptr(id_CPE_HALF_U, ctx->idf("%s$row%d$mult_upper", name.c_str(ctx), i));
col.mults.push_back(MultCell{mult_lower, mult_upper, name});
}
{
auto *mult_msb_lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$mult_msb_lower", name.c_str(ctx)));
auto *mult_msb_upper = create_cell_ptr(id_CPE_HALF_U, ctx->idf("%s$mult_msb_upper", name.c_str(ctx)));
col.mult_msb = MultMsbCell{mult_msb_lower, mult_msb_upper, name};
col.mults.push_back(MultCell{mult_lower, mult_upper, name, i == ((a_width / 2) - 1)});
}
{
@ -425,13 +402,11 @@ void GateMatePacker::pack_mult()
// 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++) {
bool inverted = false;
log_info("row %d inverted? %d\n", a, inverted);
m.a_passthrus.push_back(create_a_passthru(ctx->idf("%s$col0$row%d", mult->name.c_str(ctx), a), inverted));
}
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), false));
for (int b = 0; b < b_width / 2; b++)
m.cols.push_back(create_mult_col(ctx->idf("%s$col%d", mult->name.c_str(ctx), b + 1), a_width, b % 2 == 0));
m.cols.push_back(create_mult_col(ctx->idf("%s$col%d", mult->name.c_str(ctx), b + 1), a_width, b % 2 == 0,
b == 2 /* ??? */, b > 0 /* ??? */));
// Step 2: constrain them together.
// We define (0, 0) to be the B passthrough cell of column 1.
@ -480,11 +455,8 @@ void GateMatePacker::pack_mult()
constrain_cell(col.mults[mult_idx].upper, b, b + 4 + mult_idx);
}
constrain_cell(col.mult_msb.lower, b, b + 4 + col.mults.size());
constrain_cell(col.mult_msb.upper, b, b + 4 + col.mults.size());
constrain_cell(col.msb_route.lower, b, b + 4 + col.mults.size() + 1);
constrain_cell(col.msb_route.upper, b, b + 4 + col.mults.size() + 1);
constrain_cell(col.msb_route.lower, b, b + 4 + col.mults.size());
constrain_cell(col.msb_route.upper, b, b + 4 + col.mults.size());
}
// Step 3: connect them.
@ -501,14 +473,15 @@ void GateMatePacker::pack_mult()
// Connect A input passthrough cell.
mult->movePortTo(ctx->idf("A[%d]", a), cpe_half, id_IN1);
// Connect A passthrough output to multiplier inputs.
auto *a_net =
ctx->createNet(ctx->idf("%s$a%d_passthru", cpe_half->ports.at(id_IN1).net->name.c_str(ctx), a));
cpe_half->connectPort(id_OUT, a_net);
// This may be GND/VCC; if so, clean it up.
if (a % 2 == 1)
a_passthru.clean_up(ctx);
// Connect A passthrough output to multiplier inputs.
auto *a_net = ctx->createNet(cpe_half->name);
cpe_half->connectPort(id_OUT, a_net);
for (int b = 0; b < b_width / 2; b++) {
{
auto &mult_row = m.cols.at(b).mults.at(a / 2);
@ -518,19 +491,10 @@ void GateMatePacker::pack_mult()
}
// A upper out signals must also go to the CPE above.
if ((a % 2) == 1) {
if ((a % 2) == 1 && (a / 2) + 1 < (a_width / 2)) {
auto &mult_col = m.cols.at(b);
if ((a / 2 + 1) < (a_width / 2)) {
auto *mult_cell = mult_col.mults.at(a / 2 + 1).lower;
mult_cell->connectPort(id_IN4, a_net); // IN8
} else {
auto &mult_cell = mult_col.mult_msb;
mult_cell.upper->connectPort(id_IN1, a_net); // IN1
mult_cell.lower->connectPort(id_IN1, a_net); // IN5
mult_cell.lower->connectPort(id_IN4, a_net); // IN8
}
auto *mult_cell = mult_col.mults.at((a / 2) + 1).lower;
mult_cell->connectPort(id_IN4, a_net); // IN8
}
// constant zero goes to LSB of multipliers.