mirror of
https://github.com/YosysHQ/nextpnr.git
synced 2026-02-14 03:54:22 +00:00
current progress
This commit is contained in:
@@ -24,6 +24,26 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
enum CPELut
|
||||
{
|
||||
LUT_ZERO = 0b0000,
|
||||
LUT_NOR = 0b0001,
|
||||
LUT_AND_INV_D1 = 0b0010,
|
||||
LUT_INV_D1 = 0b0011,
|
||||
LUT_AND_INV_D0 = 0b0100,
|
||||
LUT_INV_D0 = 0b0101,
|
||||
LUT_XOR = 0b0110,
|
||||
LUT_NAND = 0b0111,
|
||||
LUT_AND = 0b1000,
|
||||
LUT_XNOR = 0b1001,
|
||||
LUT_D0 = 0b1010,
|
||||
LUT_NAND_INV_D0 = 0b1011,
|
||||
LUT_D1 = 0b1100,
|
||||
LUT_NAND_INV_D1 = 0b1101,
|
||||
LUT_OR = 0b1110,
|
||||
LUT_ONE = 0b1111
|
||||
};
|
||||
|
||||
struct GateMatePacker
|
||||
{
|
||||
GateMatePacker(Context *ctx, GateMateImpl *uarch) : ctx(ctx), uarch(uarch) { h.init(ctx); };
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "nextpnr_types.h"
|
||||
#include "pack.h"
|
||||
#include "property.h"
|
||||
#include "uarch/gatemate/extra_data.h"
|
||||
#include "util.h"
|
||||
|
||||
#define HIMBAECHEL_CONSTIDS "uarch/gatemate/constids.inc"
|
||||
@@ -30,25 +31,32 @@
|
||||
|
||||
NEXTPNR_NAMESPACE_BEGIN
|
||||
|
||||
// Propagate A0 through OUT1 and A1 through OUT2
|
||||
//
|
||||
// TODO: do we need this cell?
|
||||
// Propagate A0 through OUT1 and A1 through OUT2; zero COUTX and POUTX.
|
||||
struct APassThroughCell
|
||||
{
|
||||
APassThroughCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(0b0101, 4); // IN1
|
||||
lower->params[id_INIT_L01] = Property(0b0000, 4); // 0 (unused)
|
||||
lower->params[id_INIT_L10] = Property(0b0101, 4); // L00 -> OUT2
|
||||
lower->params[id_INIT_L00] = Property(LUT_D0, 4); // IN1
|
||||
lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L10] = Property(LUT_D0, 4); // L00 -> COMB2OUT
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(0b0101, 4); // IN5
|
||||
upper->params[id_INIT_L03] = Property(0b0000, 4); // 0 (unused)
|
||||
upper->params[id_INIT_L11] = Property(0b0101, 4); // L02
|
||||
upper->params[id_INIT_L20] = Property(0b0101, 4); // L11 -> OUT1
|
||||
upper->params[id_INIT_L02] = Property(LUT_D0, 4); // IN5
|
||||
upper->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L11] = Property(LUT_D0, 4); // L02
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4); // L11 -> COMB1OUT
|
||||
upper->params[id_INIT_L30] = Property(LUT_ONE, 4); // zero -> COMP_OUT (L30 is inverted)
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
PortRef a0() const { return PortRef{upper, id_IN1}; }
|
||||
@@ -68,22 +76,22 @@ struct BPassThroughCell
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(0b0101, 4); // IN1
|
||||
lower->params[id_INIT_L01] = Property(0b0000, 4); // 0 (unused)
|
||||
lower->params[id_INIT_L10] = Property(0b0101, 4); // L00 -> OUT2
|
||||
lower->params[id_INIT_L00] = Property(LUT_D0, 4); // IN1
|
||||
lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L10] = Property(LUT_D0, 4); // L00 -> COMB2OUT
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(0b0101, 4); // IN5
|
||||
upper->params[id_INIT_L03] = Property(0b0000, 4); // 0 (unused)
|
||||
upper->params[id_INIT_L11] = Property(0b0101, 4); // L02
|
||||
upper->params[id_INIT_L20] = Property(0b0101, 4); // L11 -> OUT1
|
||||
upper->params[id_INIT_L02] = Property(LUT_D0, 4); // IN5
|
||||
upper->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L11] = Property(LUT_D0, 4); // L02
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4); // L11 -> COMB1OUT
|
||||
|
||||
upper->params[id_C_SEL_C] = Property(0, 1); // OUT2 -> CY1_VAL
|
||||
upper->params[id_C_SEL_P] = Property(0, 1); // OUT1 -> PY_VAL
|
||||
upper->params[id_C_SELY1] = Property(0, 1); // OUT1 -> PY1_VAL; OUT2 -> CY1_VAL
|
||||
upper->params[id_C_CY1_I] = Property(1, 1); // CY1_VAL -> COUTY1
|
||||
upper->params[id_C_PY1_I] = Property(1, 1); // PY1_VAL -> POUTY1
|
||||
|
||||
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
|
||||
upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2
|
||||
}
|
||||
|
||||
PortRef b0() const { return PortRef{upper, id_IN1}; }
|
||||
@@ -93,6 +101,125 @@ struct BPassThroughCell
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// TODO: Micko points out this is an L2T4 CPE_HALF
|
||||
struct CarryGenCell
|
||||
{
|
||||
CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
|
||||
{
|
||||
// TODO: simplify AND with zero/OR with zero into something more sensical.
|
||||
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(LUT_D1, 4); // PINY1
|
||||
upper->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L11] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
|
||||
upper->params[id_INIT_L20] = Property(is_even_x ? LUT_AND : LUT_OR, 4);
|
||||
upper->params[id_INIT_L30] = Property(LUT_INV_D0, 4); // OUT1 -> COMP_OUT
|
||||
|
||||
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_FUNCTION] = Property(C_EN_CIN, 3);
|
||||
upper->params[id_C_PY1_I] = Property(0, 1); // PINY1 -> POUTY1
|
||||
upper->params[id_C_CY1_I] = Property(0, 1); // CINY1 -> COUTY1
|
||||
upper->params[id_C_CY2_I] = Property(1, 1); // CY2_VAL -> COUTY2
|
||||
upper->params[id_C_SEL_C] = Property(1, 1); // COMP_OUT -> CY2_VAL
|
||||
upper->params[id_C_SELY2] = Property(0, 1); // COMP_OUT -> CY2_VAL
|
||||
|
||||
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// This prepares B bits for multiplication.
|
||||
struct MultfabCell
|
||||
{
|
||||
MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
|
||||
{
|
||||
// TODO: perhaps C_I[1234] could be pips?
|
||||
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
|
||||
lower->params[id_INIT_L01] = Property(is_even_x ? LUT_ZERO : LUT_D1, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(LUT_XOR, 4); // XOR
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(LUT_D1, 4); // PINY1
|
||||
upper->params[id_INIT_L03] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L11] = Property(LUT_D0, 4); // L02
|
||||
upper->params[id_INIT_L20] = Property(is_even_x ? LUT_AND_INV_D0 : LUT_OR, 4); // L10 AND L11 -> OUT1
|
||||
upper->params[id_INIT_L30] = Property(LUT_INV_D1, 4); // L10 -> COMP_OUT
|
||||
|
||||
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_FUNCTION] = Property(C_ADDCIN, 3);
|
||||
upper->params[id_C_SELX] = Property(1, 1); // inverted CINY2 -> CX_VAL
|
||||
upper->params[id_C_SEL_C] = Property(1, 1); // inverted CINY2 -> CX_VAL; COMP_OUT -> CY1_VAL
|
||||
upper->params[id_C_Y12] = Property(1, 1); // inverted CINY2 -> CX_VAL
|
||||
upper->params[id_C_CX_I] = Property(1, 1); // CX_VAL -> COUTX
|
||||
upper->params[id_C_CY1_I] = Property(1, 1); // CY1_VAL -> COUTY1
|
||||
upper->params[id_C_PY1_I] = Property(1, 1); // PY1_VAL -> POUTY1
|
||||
upper->params[id_C_SEL_P] = Property(0, 1); // OUT1 -> PY1_VAL
|
||||
upper->params[id_C_SELY1] = Property(0, 1); // COMP_OUT -> CY1_VAL; OUT1 -> PY1_VAL
|
||||
|
||||
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// CITE: CPE_ges_f-routing-1.pdf
|
||||
// TODO:
|
||||
struct FRoutingCell
|
||||
{
|
||||
FRoutingCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
|
||||
{
|
||||
// TODO: simplify AND with zero/OR with zero into something more sensical.
|
||||
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
|
||||
lower->params[id_INIT_L01] = Property(LUT_ONE, 4); // (unused)
|
||||
lower->params[id_INIT_L10] = Property(LUT_AND, 4);
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(LUT_ZERO, 4); // (unused)
|
||||
upper->params[id_INIT_L03] = Property(LUT_ONE, 4); // (unused)
|
||||
upper->params[id_INIT_L11] = Property(LUT_AND, 4);
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4);
|
||||
upper->params[id_INIT_L30] = Property(is_even_x ? LUT_ONE : LUT_INV_D1, 4); // OUT1 -> COMP_OUT
|
||||
|
||||
upper->params[id_C_I1] = Property(1, 1); // PINY1 for L00
|
||||
upper->params[id_C_FUNCTION] = Property(C_ADDCIN, 3);
|
||||
upper->params[id_C_SELX] = Property(1, 1);
|
||||
upper->params[id_C_SEL_C] = Property(1, 1);
|
||||
upper->params[id_C_Y12] = Property(1, 1);
|
||||
upper->params[id_C_CX_I] = Property(1, 1);
|
||||
upper->params[id_C_CY1_I] = Property(is_even_x, 1);
|
||||
upper->params[id_C_CY2_I] = Property(1, 1);
|
||||
upper->params[id_C_PY1_I] = Property(1, 1);
|
||||
upper->params[id_C_PY2_I] = Property(1, 1);
|
||||
|
||||
upper->params[id_C_O1] = Property(0b11, 2); // COMB1OUT -> OUT1
|
||||
upper->params[id_C_O2] = Property(0b11, 2); // COMB2OUT -> OUT2
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// Multiply two bits of A with two bits of B.
|
||||
//
|
||||
// CITE: CPE_MULT.pdf
|
||||
@@ -102,132 +229,113 @@ struct MultCell
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(0b1000, 4); // AND
|
||||
lower->params[id_INIT_L01] = Property(0b1100, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(0b0110, 4); // XOR
|
||||
lower->params[id_INIT_L00] = Property(LUT_AND, 4);
|
||||
lower->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(LUT_XOR, 4);
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(0b1000, 4); // AND
|
||||
upper->params[id_INIT_L03] = Property(0b1100, 4); // PINX
|
||||
upper->params[id_INIT_L11] = Property(0b0110, 4); // XOR
|
||||
upper->params[id_INIT_L20] = Property(0b1100, 4); // L11
|
||||
upper->params[id_INIT_L02] = Property(LUT_AND, 4);
|
||||
upper->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX
|
||||
upper->params[id_INIT_L11] = Property(LUT_XOR, 4);
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
|
||||
|
||||
upper->params[id_C_FUNCTION] = Property(C_MULT, 3);
|
||||
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
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// This seems to prepare B bits for multiplication.
|
||||
//
|
||||
// CITE: CPE_MULTFab.pdf
|
||||
struct MultfabCell
|
||||
{
|
||||
MultfabCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(0b1100, 4); // PINY1
|
||||
lower->params[id_INIT_L01] = Property(0b1100, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(0b0110, 4); // XOR
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(0b1100, 4); // PINY1
|
||||
upper->params[id_INIT_L03] = Property(0b0000, 4); // 0 (unused)
|
||||
upper->params[id_INIT_L11] = Property(0b0101, 4); // L02
|
||||
if (is_even_x) {
|
||||
// TODO: the diagrams suggest that AND has L10 inverted? need to check.
|
||||
upper->params[id_INIT_L20] = Property(0b1000, 4); // L10 AND L11 -> OUT1
|
||||
} else {
|
||||
upper->params[id_INIT_L20] = Property(0b1110, 4); // L10 OR L11 -> OUT1
|
||||
}
|
||||
upper->params[id_INIT_L30] = Property(0b1100, 4); // L10 -> COMP_OUT
|
||||
|
||||
upper->params[id_C_FUNCTION] = Property(C_MULT, 3);
|
||||
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_CX_I] = Property(1, 1); // CX_VAL -> COUTX
|
||||
upper->params[id_C_CY1_I] = Property(1, 1); // CY1_VAL -> COUTY1
|
||||
upper->params[id_C_PY1_I] = Property(1, 1); // PY1_VAL -> POUTY1
|
||||
upper->params[id_C_SELX] = Property(1, 1); // inverted CINY2 -> CX_VAL
|
||||
upper->params[id_C_SELY1] = Property(0, 1); // COMP_OUT -> CY1_VAL; OUT1 -> PY1_VAL
|
||||
upper->params[id_C_Y12] = Property(1, 1); // inverted CINY2 -> CX_VAL
|
||||
upper->params[id_C_SEL_C] = Property(1, 1); // inverted CINY2 -> CX_VAL; COMP_OUT -> CY1_VAL
|
||||
upper->params[id_C_SEL_P] = Property(0, 1); // OUT1 -> PY1_VAL
|
||||
|
||||
upper->params[id_C_O1] = Property(0b10, 2); // CP_OUT1 -> OUT1
|
||||
upper->params[id_C_O2] = Property(0b10, 2); // CP_OUT2 -> OUT2
|
||||
}
|
||||
|
||||
PortRef a0() const { return PortRef{upper, id_IN4}; }
|
||||
PortRef a1() const { return PortRef{upper, id_IN1}; }
|
||||
PortRef a2() const { return PortRef{lower, id_IN1}; }
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// CITE: CPE_ges_carry-gen.pdf
|
||||
struct CarryGenCell
|
||||
struct MultMsbCell
|
||||
{
|
||||
CarryGenCell(CellInfo *lower, CellInfo *upper, IdString name, bool is_even_x) : lower{lower}, upper{upper}
|
||||
MultMsbCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(0b0000, 4); // 0 (unused)
|
||||
lower->params[id_INIT_L01] = Property(0b1100, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(0b1100, 4); // L01 -> OUT2
|
||||
lower->params[id_INIT_L00] = Property(LUT_AND, 4);
|
||||
lower->params[id_INIT_L01] = Property(LUT_D1, 4); // CINX
|
||||
lower->params[id_INIT_L10] = Property(LUT_XOR, 4);
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(0b1100, 4); // PINY1
|
||||
upper->params[id_INIT_L03] = Property(0b0000, 4); // 0 (unused)
|
||||
if (is_even_x) {
|
||||
upper->params[id_INIT_L11] = Property(0b1000, 4); // AND
|
||||
upper->params[id_INIT_L20] = Property(0b1000, 4); // AND
|
||||
} else {
|
||||
upper->params[id_INIT_L11] = Property(0b1110, 4); // OR
|
||||
upper->params[id_INIT_L20] = Property(0b1110, 4); // OR
|
||||
}
|
||||
upper->params[id_INIT_L30] = Property(0b0101, 4); // OUT1 -> COMP_OUT
|
||||
upper->params[id_INIT_L02] = Property(LUT_AND, 4);
|
||||
upper->params[id_INIT_L03] = Property(LUT_D1, 4); // PINX
|
||||
upper->params[id_INIT_L11] = Property(LUT_XOR, 4);
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
|
||||
|
||||
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
|
||||
// TODO: how do I get B1 through CIN??
|
||||
upper->params[id_C_PY1_I] = Property(0, 1); // PINY1 -> POUTY1
|
||||
upper->params[id_C_CY1_I] = Property(0, 1); // CINY1 -> COUTY1
|
||||
upper->params[id_C_CY2_I] = Property(1, 1); // CY2_VAL -> COUTY2
|
||||
upper->params[id_C_SEL_C] = Property(1, 1); // COMP_OUT -> CY2_VAL
|
||||
upper->params[id_C_SELY2] = Property(0, 1); // COMP_OUT -> CY2_VAL
|
||||
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
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// CITE: CPE_ges_f-routing-1.pdf
|
||||
// TODO:
|
||||
struct FRoutingCell
|
||||
{
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
// CITE: CPE_ges_MSB-routing.pdf
|
||||
struct MsbRoutingCell
|
||||
{
|
||||
MsbRoutingCell(CellInfo *lower, CellInfo *upper, IdString name) : lower{lower}, upper{upper}
|
||||
{
|
||||
lower->cluster = name;
|
||||
lower->constr_abs_z = false;
|
||||
lower->params[id_INIT_L00] = Property(LUT_D1, 4); // PINY1
|
||||
lower->params[id_INIT_L01] = Property(LUT_ZERO, 4); // (unused)
|
||||
lower->params[id_INIT_L10] = Property(LUT_OR, 4);
|
||||
|
||||
upper->cluster = name;
|
||||
upper->constr_abs_z = false;
|
||||
upper->params[id_INIT_L02] = Property(LUT_ONE, 4);
|
||||
upper->params[id_INIT_L03] = Property(LUT_ONE, 4);
|
||||
upper->params[id_INIT_L11] = Property(LUT_ZERO, 4);
|
||||
upper->params[id_INIT_L20] = Property(LUT_D1, 4); // L11
|
||||
upper->params[id_INIT_L30] = Property(LUT_ONE, 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);
|
||||
upper->params[id_C_PX_I] = Property(1, 1);
|
||||
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
|
||||
}
|
||||
|
||||
CellInfo *upper;
|
||||
CellInfo *lower;
|
||||
};
|
||||
|
||||
struct MultiplierColumn
|
||||
{
|
||||
MsbRoutingCell msb_route;
|
||||
std::vector<MultCell> mults;
|
||||
// the variables are in bottom-up physical order as a mnemonic.
|
||||
|
||||
BPassThroughCell b_passthru;
|
||||
CarryGenCell carry;
|
||||
MultfabCell multfab;
|
||||
FRoutingCell f_route;
|
||||
BPassThroughCell b_passthru;
|
||||
std::vector<MultCell> mults;
|
||||
MultMsbCell multmsb;
|
||||
MsbRoutingCell msb_route;
|
||||
};
|
||||
|
||||
// A GateMate multiplier is made up of columns of 2x2 multipliers.
|
||||
@@ -239,6 +347,9 @@ struct Multiplier
|
||||
|
||||
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_mult_cell = [&](IdString name) {
|
||||
// instantiate a full CPE by creating two halves.
|
||||
auto *lower = create_cell_ptr(id_CPE_HALF_L, ctx->idf("%s$lower", name.c_str(ctx)));
|
||||
|
||||
Reference in New Issue
Block a user