mirror of https://github.com/YosysHQ/nextpnr.git
Update a passthru to use new primitives
This commit is contained in:
parent
998e3e1e6f
commit
b6c7f56a83
|
|
@ -266,6 +266,8 @@ struct BitstreamBackend
|
|||
break;
|
||||
case id_CPE_LT_L.index:
|
||||
case id_CPE_LT_U.index:
|
||||
case id_CPE_CPLINES.index:
|
||||
case id_CPE_COMP.index:
|
||||
case id_CPE_L2T4.index:
|
||||
case id_CPE_L2T5.index:
|
||||
case id_CPE_ADDF.index:
|
||||
|
|
|
|||
|
|
@ -41,7 +41,19 @@ CellInfo *GateMatePacker::create_cell_ptr(IdString type, IdString name)
|
|||
add_port(id_IN4, PORT_IN);
|
||||
add_port(id_OUT, PORT_OUT);
|
||||
if (type.in(id_CPE_LT_L, id_CPE_L2T5_L, id_CPE_CI)) {
|
||||
add_port(id_CINX, PORT_IN);
|
||||
add_port(id_PINX, PORT_IN);
|
||||
add_port(id_CINY1, PORT_IN);
|
||||
add_port(id_PINY1, PORT_IN);
|
||||
add_port(id_CINY2, PORT_IN);
|
||||
add_port(id_PINY2, PORT_IN);
|
||||
|
||||
add_port(id_COUTX, PORT_OUT);
|
||||
add_port(id_POUTX, PORT_OUT);
|
||||
add_port(id_COUTY1, PORT_OUT);
|
||||
add_port(id_POUTY1, PORT_OUT);
|
||||
add_port(id_COUTY2, PORT_OUT);
|
||||
add_port(id_POUTY2, PORT_OUT);
|
||||
}
|
||||
} else if (type.in(id_CLKIN)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
|
@ -69,6 +81,28 @@ CellInfo *GateMatePacker::create_cell_ptr(IdString type, IdString name)
|
|||
add_port(id_RAM_I, PORT_IN);
|
||||
add_port(id_RAM_O, PORT_OUT);
|
||||
add_port(id_OUT, PORT_OUT);
|
||||
} else if (type.in(id_CPE_COMP)) {
|
||||
add_port(id_COMB1, PORT_IN);
|
||||
add_port(id_COMB2, PORT_IN);
|
||||
add_port(id_COMPOUT, PORT_OUT);
|
||||
} else if (type.in(id_CPE_CPLINES)) {
|
||||
add_port(id_OUT1, PORT_IN);
|
||||
add_port(id_OUT2, PORT_IN);
|
||||
add_port(id_COMPOUT, PORT_IN);
|
||||
|
||||
add_port(id_CINX, PORT_IN);
|
||||
add_port(id_PINX, PORT_IN);
|
||||
add_port(id_CINY1, PORT_IN);
|
||||
add_port(id_PINY1, PORT_IN);
|
||||
add_port(id_CINY2, PORT_IN);
|
||||
add_port(id_PINY2, PORT_IN);
|
||||
|
||||
add_port(id_COUTX, PORT_OUT);
|
||||
add_port(id_POUTX, PORT_OUT);
|
||||
add_port(id_COUTY1, PORT_OUT);
|
||||
add_port(id_POUTY1, PORT_OUT);
|
||||
add_port(id_COUTY2, PORT_OUT);
|
||||
add_port(id_POUTY2, PORT_OUT);
|
||||
} else {
|
||||
log_error("Trying to create unknown cell type %s\n", type.c_str(ctx));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -940,8 +940,18 @@ X(CPE_LT_L)
|
|||
//X(OUT)
|
||||
//X(CPOUT)
|
||||
X(MUXOUT)
|
||||
X(CINX)
|
||||
X(PINX)
|
||||
X(CINY1)
|
||||
X(PINY1)
|
||||
X(CINY2)
|
||||
X(PINY2)
|
||||
X(COUTX)
|
||||
X(POUTX)
|
||||
X(COUTY1)
|
||||
X(POUTY1)
|
||||
X(COUTY2)
|
||||
X(POUTY2)
|
||||
|
||||
// hardware primitive CPE_FF_L
|
||||
X(CPE_FF_L)
|
||||
|
|
@ -976,24 +986,44 @@ X(OUT2)
|
|||
X(CPOUT1)
|
||||
X(CPOUT2)
|
||||
//X(MUXOUT)
|
||||
//X(CINX)
|
||||
//X(PINX)
|
||||
//X(CINY1)
|
||||
//X(PINY1)
|
||||
//X(CINY2)
|
||||
//X(PINY2)
|
||||
//X(COUTX)
|
||||
//X(POUTX)
|
||||
//X(COUTY1)
|
||||
//X(POUTY1)
|
||||
//X(COUTY2)
|
||||
//X(POUTY2)
|
||||
|
||||
// hardware primitive CPE_LINES
|
||||
X(CPE_LINES)
|
||||
// CPE_LINES pins
|
||||
X(CINX)
|
||||
X(PINX)
|
||||
// hardware primitive CPE_COMP
|
||||
X(CPE_COMP)
|
||||
// CPE_COMP pins
|
||||
X(COMB1)
|
||||
X(COMB2)
|
||||
X(COMPOUT)
|
||||
|
||||
// hardware primitive CPE_CPLINES
|
||||
X(CPE_CPLINES)
|
||||
// CPE_CPLINES pins
|
||||
//X(OUT1)
|
||||
//X(OUT2)
|
||||
//X(COMPOUT)
|
||||
//X(CINX)
|
||||
//X(PINX)
|
||||
//X(CINY1)
|
||||
X(PINY1)
|
||||
X(CINY2)
|
||||
X(PINY2)
|
||||
X(COUTX)
|
||||
X(POUTX)
|
||||
//X(PINY1)
|
||||
//X(CINY2)
|
||||
//X(PINY2)
|
||||
//X(COUTX)
|
||||
//X(POUTX)
|
||||
//X(COUTY1)
|
||||
X(POUTY1)
|
||||
X(COUTY2)
|
||||
X(POUTY2)
|
||||
//X(POUTY1)
|
||||
//X(COUTY2)
|
||||
//X(POUTY2)
|
||||
|
||||
// hardware primitive GPIO
|
||||
X(GPIO)
|
||||
|
|
|
|||
|
|
@ -93,8 +93,9 @@ enum CPE_Z
|
|||
CPE_FF_L_Z = 3,
|
||||
CPE_RAMIO_U_Z = 4,
|
||||
CPE_RAMIO_L_Z = 5,
|
||||
CPE_LINES_Z = 6,
|
||||
CPE_LT_FULL_Z = 7,
|
||||
CPE_COMP_Z = 6,
|
||||
CPE_CPLINES_Z = 7,
|
||||
CPE_LT_FULL_Z = 8,
|
||||
};
|
||||
|
||||
enum ClusterPlacement
|
||||
|
|
|
|||
|
|
@ -46,12 +46,14 @@ struct ZeroDriver
|
|||
// Propagate A0 through OUT1 and A1 through OUT2; zero COUTX and POUTX.
|
||||
struct APassThroughCell
|
||||
{
|
||||
APassThroughCell(CellInfo *lower, CellInfo *upper, IdString name);
|
||||
APassThroughCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name);
|
||||
|
||||
void clean_up(Context *ctx);
|
||||
|
||||
CellInfo *lower;
|
||||
CellInfo *upper;
|
||||
CellInfo *comp;
|
||||
CellInfo *cplines;
|
||||
};
|
||||
|
||||
// Propagate B0 through POUTY1 and B1 through COUTY1
|
||||
|
|
@ -152,25 +154,23 @@ ZeroDriver::ZeroDriver(CellInfo *lower, CellInfo *upper, IdString name) : lower{
|
|||
upper->params[id_INIT_L10] = Property(LUT_ZERO, 4); // (unused)
|
||||
}
|
||||
|
||||
APassThroughCell::APassThroughCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
|
||||
APassThroughCell::APassThroughCell(CellInfo *lower, CellInfo *upper, CellInfo *comp, CellInfo *cplines, IdString name)
|
||||
: lower{lower}, upper{upper}, comp{comp}, cplines{cplines}
|
||||
{
|
||||
lower->params[id_INIT_L02] = Property(LUT_D0, 4); // IN5
|
||||
lower->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L11] = Property(LUT_D0, 4); // L02
|
||||
lower->params[id_INIT_L20] = Property(LUT_D1, 4); // L11 -> COMB1OUT
|
||||
lower->params[id_INIT_L30] = Property(LUT_ONE, 4); // zero -> COMP_OUT (L30 is inverted)
|
||||
lower->params[id_INIT_L00] = Property(LUT_D0, 4); // IN5
|
||||
lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L10] = Property(LUT_D0, 4); // L02
|
||||
|
||||
comp->params[id_INIT_L30] = Property(LUT_ONE, 4); // zero -> COMP_OUT (L30 is inverted)
|
||||
|
||||
upper->params[id_INIT_L00] = Property(LUT_D0, 4); // IN1
|
||||
upper->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L10] = Property(LUT_D0, 4); // L00 -> COMB2OUT
|
||||
|
||||
upper->params[id_C_SEL_C] = Property(1, 1); // COMP_OUT -> CX_VAL
|
||||
upper->params[id_C_SEL_P] = Property(1, 1); // COMP_OUT -> PX_VAL
|
||||
upper->params[id_C_CX_I] = Property(1, 1); // CX_VAL -> COUTX
|
||||
upper->params[id_C_PX_I] = Property(1, 1); // PX_VAL -> POUTX
|
||||
|
||||
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
|
||||
upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2
|
||||
cplines->params[id_C_SEL_C] = Property(1, 1); // COMP_OUT -> CX_VAL
|
||||
cplines->params[id_C_SEL_P] = Property(1, 1); // COMP_OUT -> PX_VAL
|
||||
cplines->params[id_C_CX_I] = Property(1, 1); // CX_VAL -> COUTX
|
||||
cplines->params[id_C_PX_I] = Property(1, 1); // PX_VAL -> POUTX
|
||||
}
|
||||
|
||||
void APassThroughCell::clean_up(Context *ctx)
|
||||
|
|
@ -185,9 +185,8 @@ void APassThroughCell::clean_up(Context *ctx)
|
|||
bool net_is_gnd = lower_net->name == ctx->idf("$PACKER_GND");
|
||||
bool net_is_vcc = lower_net->name == ctx->idf("$PACKER_VCC");
|
||||
if (net_is_gnd || net_is_vcc) {
|
||||
lower->params[id_INIT_L02] = Property(LUT_ZERO, 4);
|
||||
lower->params[id_INIT_L11] = Property(LUT_ZERO, 4);
|
||||
lower->params[id_INIT_L20] = Property(net_is_vcc ? LUT_ONE : LUT_ZERO, 4);
|
||||
lower->params[id_INIT_L00] = Property(LUT_ZERO, 4);
|
||||
lower->params[id_INIT_L10] = Property(LUT_ZERO, 4);
|
||||
lower->disconnectPort(id_IN1);
|
||||
}
|
||||
}
|
||||
|
|
@ -402,9 +401,14 @@ void GateMatePacker::pack_mult()
|
|||
};
|
||||
|
||||
auto create_a_passthru = [&](IdString name) {
|
||||
auto *a_passthru_lower = create_cell_ptr(id_CPE_LT_L, ctx->idf("%s$a_passthru_lower", name.c_str(ctx)));
|
||||
auto *a_passthru_lower = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$a_passthru_lower", name.c_str(ctx)));
|
||||
auto *a_passthru_upper = create_cell_ptr(id_CPE_L2T4, ctx->idf("%s$a_passthru_upper", name.c_str(ctx)));
|
||||
return APassThroughCell{a_passthru_lower, a_passthru_upper, name};
|
||||
auto *a_passthru_comp = create_cell_ptr(id_CPE_COMP, ctx->idf("%s$a_passthru_comp", name.c_str(ctx)));
|
||||
auto *a_passthru_lines = create_cell_ptr(id_CPE_CPLINES, ctx->idf("%s$a_passthru_cplines", name.c_str(ctx)));
|
||||
NetInfo *comp_conn = ctx->createNet(ctx->idf("%s$compout", name.c_str(ctx)));
|
||||
a_passthru_comp->connectPort(id_COMPOUT, comp_conn);
|
||||
a_passthru_lines->connectPort(id_COMPOUT, comp_conn);
|
||||
return APassThroughCell{a_passthru_lower, a_passthru_upper, a_passthru_comp, a_passthru_lines, name};
|
||||
};
|
||||
|
||||
auto create_mult_col = [&](IdString name, int a_width, bool is_even_x, bool carry_enable_cinx,
|
||||
|
|
@ -511,38 +515,40 @@ void GateMatePacker::pack_mult()
|
|||
};
|
||||
|
||||
// Constrain zero driver.
|
||||
constrain_cell(m.zero.lower, -1, 3, 1);
|
||||
constrain_cell(m.zero.upper, -1, 3, 0);
|
||||
constrain_cell(m.zero.lower, -1, 3, CPE_LT_L_Z);
|
||||
constrain_cell(m.zero.upper, -1, 3, CPE_LT_U_Z);
|
||||
|
||||
// Constrain A passthrough cells.
|
||||
for (int a = 0; a < a_width / 2; a++) {
|
||||
auto &a_passthru = m.a_passthrus.at(a);
|
||||
constrain_cell(a_passthru.lower, -1, 4 + a, 1);
|
||||
constrain_cell(a_passthru.upper, -1, 4 + a, 0);
|
||||
constrain_cell(a_passthru.lower, -1, 4 + a, CPE_LT_L_Z);
|
||||
constrain_cell(a_passthru.upper, -1, 4 + a, CPE_LT_U_Z);
|
||||
constrain_cell(a_passthru.comp, -1, 4 + a, CPE_COMP_Z);
|
||||
constrain_cell(a_passthru.cplines,-1, 4 + a, CPE_CPLINES_Z);
|
||||
}
|
||||
|
||||
// Constrain multiplier columns.
|
||||
for (int b = 0; b < b_width / 2; b++) {
|
||||
auto &col = m.cols.at(b);
|
||||
constrain_cell(col.b_passthru.lower, b, b, 1);
|
||||
constrain_cell(col.b_passthru.upper, b, b, 0);
|
||||
constrain_cell(col.b_passthru.lower, b, b, CPE_LT_L_Z);
|
||||
constrain_cell(col.b_passthru.upper, b, b, CPE_LT_U_Z);
|
||||
|
||||
constrain_cell(col.carry.lower, b, b + 1, 1);
|
||||
constrain_cell(col.carry.upper, b, b + 1, 0);
|
||||
constrain_cell(col.carry.lower, b, b + 1, CPE_LT_L_Z);
|
||||
constrain_cell(col.carry.upper, b, b + 1, CPE_LT_U_Z);
|
||||
|
||||
constrain_cell(col.multfab.lower, b, b + 2, 1);
|
||||
constrain_cell(col.multfab.upper, b, b + 2, 0);
|
||||
constrain_cell(col.multfab.lower, b, b + 2, CPE_LT_L_Z);
|
||||
constrain_cell(col.multfab.upper, b, b + 2, CPE_LT_U_Z);
|
||||
|
||||
constrain_cell(col.f_route.lower, b, b + 3, 1);
|
||||
constrain_cell(col.f_route.upper, b, b + 3, 0);
|
||||
constrain_cell(col.f_route.lower, b, b + 3, CPE_LT_L_Z);
|
||||
constrain_cell(col.f_route.upper, b, b + 3, CPE_LT_U_Z);
|
||||
|
||||
for (size_t mult_idx = 0; mult_idx < col.mults.size(); mult_idx++) {
|
||||
constrain_cell(col.mults[mult_idx].lower, b, b + 4 + mult_idx, 1);
|
||||
constrain_cell(col.mults[mult_idx].upper, b, b + 4 + mult_idx, 0);
|
||||
constrain_cell(col.mults[mult_idx].lower, b, b + 4 + mult_idx, CPE_LT_L_Z);
|
||||
constrain_cell(col.mults[mult_idx].upper, b, b + 4 + mult_idx, CPE_LT_U_Z);
|
||||
}
|
||||
|
||||
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(), 0);
|
||||
constrain_cell(col.msb_route.lower, b, b + 4 + col.mults.size(), CPE_LT_L_Z);
|
||||
constrain_cell(col.msb_route.upper, b, b + 4 + col.mults.size(), CPE_LT_U_Z);
|
||||
}
|
||||
|
||||
// Step 3: connect them.
|
||||
|
|
@ -565,9 +571,20 @@ void GateMatePacker::pack_mult()
|
|||
cpe_half->connectPort(id_OUT, a_net);
|
||||
|
||||
// This may be GND/VCC; if so, clean it up.
|
||||
if (a % 2 == 1)
|
||||
if (a % 2 == 1) {
|
||||
a_passthru.clean_up(ctx);
|
||||
|
||||
auto &mult_row = m.cols.at(0).mults.at(a / 2);
|
||||
|
||||
auto *so1_net =ctx->createNet(ctx->idf("%s_so1", cpe_half->name.c_str(ctx)));
|
||||
a_passthru.cplines->connectPort(id_COUTX, so1_net);
|
||||
mult_row.lower->connectPort(id_CINX, so1_net);
|
||||
|
||||
auto *so2_net =ctx->createNet(ctx->idf("%s_so2", cpe_half->name.c_str(ctx)));
|
||||
a_passthru.cplines->connectPort(id_POUTX, so2_net);
|
||||
mult_row.lower->connectPort(id_PINX, so2_net);
|
||||
}
|
||||
|
||||
for (int b = 0; b < b_width / 2; b++) {
|
||||
{
|
||||
auto &mult_row = m.cols.at(b).mults.at(a / 2);
|
||||
|
|
|
|||
Loading…
Reference in New Issue