diff --git a/himbaechel/uarch/gatemate/bitstream.cc b/himbaechel/uarch/gatemate/bitstream.cc index fa255989..5ee54f5d 100644 --- a/himbaechel/uarch/gatemate/bitstream.cc +++ b/himbaechel/uarch/gatemate/bitstream.cc @@ -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: diff --git a/himbaechel/uarch/gatemate/cells.cc b/himbaechel/uarch/gatemate/cells.cc index 93ea085f..5daf7116 100644 --- a/himbaechel/uarch/gatemate/cells.cc +++ b/himbaechel/uarch/gatemate/cells.cc @@ -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)); } diff --git a/himbaechel/uarch/gatemate/constids.inc b/himbaechel/uarch/gatemate/constids.inc index 66a7ac29..26fa847c 100644 --- a/himbaechel/uarch/gatemate/constids.inc +++ b/himbaechel/uarch/gatemate/constids.inc @@ -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) diff --git a/himbaechel/uarch/gatemate/extra_data.h b/himbaechel/uarch/gatemate/extra_data.h index c0df75e1..8ce126dc 100644 --- a/himbaechel/uarch/gatemate/extra_data.h +++ b/himbaechel/uarch/gatemate/extra_data.h @@ -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 diff --git a/himbaechel/uarch/gatemate/pack_mult.cc b/himbaechel/uarch/gatemate/pack_mult.cc index 9535c74c..fbb06794 100644 --- a/himbaechel/uarch/gatemate/pack_mult.cc +++ b/himbaechel/uarch/gatemate/pack_mult.cc @@ -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);