mirror of https://github.com/YosysHQ/nextpnr.git
current progress (013 seems to work?)
This commit is contained in:
parent
bdf235721e
commit
2d81d34991
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -215,6 +215,91 @@ void GateMateImpl::postPlace()
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto print_config = [&](CellInfo *cell, dict<IdString, Property> ¶ms) {
|
||||
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(); }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
Loading…
Reference in New Issue