diff options
-rw-r--r-- | ecp5/arch.cc | 4 | ||||
-rw-r--r-- | ecp5/bitstream.cc | 278 | ||||
-rw-r--r-- | ecp5/constids.inc | 617 | ||||
-rw-r--r-- | ecp5/pack.cc | 55 |
4 files changed, 939 insertions, 15 deletions
diff --git a/ecp5/arch.cc b/ecp5/arch.cc index aa9506f9..ab3e15c0 100644 --- a/ecp5/arch.cc +++ b/ecp5/arch.cc @@ -647,6 +647,10 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, Id return (cell->ports.at(port).type == PORT_OUT) ? TMG_REGISTER_OUTPUT : TMG_REGISTER_INPUT; } NPNR_ASSERT_FALSE_STR("no timing type for RAM port '" + port.str(this) + "'"); + } else if (cell->type == id_MULT18X18D) { + return TMG_IGNORE; // FIXME + } else if (cell->type == id_ALU54B) { + return TMG_IGNORE; // FIXME } else { NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'"); } diff --git a/ecp5/bitstream.cc b/ecp5/bitstream.cc index 29b12c86..c7b5d562 100644 --- a/ecp5/bitstream.cc +++ b/ecp5/bitstream.cc @@ -21,6 +21,7 @@ #include <fstream> #include <iomanip> +#include <queue> #include <regex> #include <streambuf> @@ -81,17 +82,20 @@ static std::vector<bool> str_to_bitvector(std::string str, int size) static void tie_cib_signal(Context *ctx, ChipConfig &cc, WireId wire, bool value) { static const std::regex cib_re("J([A-D]|CE|LSR|CLK)[0-7]"); - WireId cibsig = wire; - std::string basename = ctx->getWireBasename(wire).str(ctx); - - while (!std::regex_match(basename, cib_re)) { - auto uphill = ctx->getPipsUphill(cibsig); - NPNR_ASSERT(uphill.begin() != uphill.end()); // At least one uphill pip - auto iter = uphill.begin(); - cibsig = ctx->getPipSrcWire(*iter); + std::queue<WireId> signals; + signals.push(wire); + WireId cibsig; + std::string basename; + while (true) { + NPNR_ASSERT(!signals.empty()); + NPNR_ASSERT(signals.size() < 100); + cibsig = signals.front(); basename = ctx->getWireBasename(cibsig).str(ctx); - ++iter; - NPNR_ASSERT(!(iter != uphill.end())); // Exactly one uphill pip + signals.pop(); + if (std::regex_match(basename, cib_re)) + break; + for (auto pip : ctx->getPipsUphill(cibsig)) + signals.push(ctx->getPipSrcWire(pip)); } bool out_value = value; @@ -132,9 +136,12 @@ std::vector<bool> parse_init_str(const std::string &str, int length) char c = str.at((str.size() - i) - 1); int nibble = chtohex(c); result.at(i * 4) = nibble & 0x1; - result.at(i * 4 + 1) = nibble & 0x2; - result.at(i * 4 + 2) = nibble & 0x4; - result.at(i * 4 + 3) = nibble & 0x8; + if (i * 4 + 1 < length) + result.at(i * 4 + 1) = nibble & 0x2; + if (i * 4 + 2 < length) + result.at(i * 4 + 2) = nibble & 0x4; + if (i * 4 + 3 < length) + result.at(i * 4 + 3) = nibble & 0x8; } } else { // Yosys style binary string @@ -279,6 +286,98 @@ std::vector<std::string> get_bram_tiles(Context *ctx, BelId bel) return tiles; } +// Get the list of tiles corresponding to a DSP +std::vector<std::string> get_dsp_tiles(Context *ctx, BelId bel) +{ + std::vector<std::string> tiles; + Loc loc = ctx->getBelLocation(bel); + + static const std::set<std::string> dsp8 = {"MIB_DSP8", "DSP_SPINE_UL0", "DSP_SPINE_UR0", "DSP_SPINE_UR1"}; + if (ctx->getBelType(bel) == id_MULT18X18D) { + switch (loc.z) { + case 0: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB2_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB2_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 4, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 4, "MIB2_DSP4")); + break; + case 1: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB2_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB2_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB2_DSP4")); + break; + case 4: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB2_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB2_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 4, dsp8)); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 4, "MIB2_DSP8")); + break; + case 5: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB2_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 2, "MIB2_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, dsp8)); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 3, "MIB2_DSP8")); + break; + default: + NPNR_ASSERT_FALSE("bad MULT z loc"); + } + } else if (ctx->getBelType(bel) == id_ALU54B) { + switch (loc.z) { + case 3: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 3, "MIB_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 3, "MIB2_DSP0")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 2, "MIB_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 2, "MIB2_DSP1")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB2_DSP2")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP3")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP4")); + break; + case 7: + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 3, "MIB_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 3, "MIB2_DSP4")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 2, "MIB_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 2, "MIB2_DSP5")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x - 1, "MIB2_DSP6")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x, "MIB2_DSP7")); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, dsp8)); + tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + 1, "MIB2_DSP8")); + break; + default: + NPNR_ASSERT_FALSE("bad ALU z loc"); + } + } + return tiles; +} void fix_tile_names(Context *ctx, ChipConfig &cc) { // Remove the V prefix/suffix on certain tiles if device is a SERDES variant @@ -312,6 +411,24 @@ void fix_tile_names(Context *ctx, ChipConfig &cc) } } +void tieoff_dsp_ports(Context *ctx, ChipConfig &cc, CellInfo *ci) +{ + for (auto port : ci->ports) { + if (port.second.net == nullptr && port.second.type == PORT_IN) { + if (port.first.str(ctx).substr(0, 3) == "CLK" || port.first.str(ctx).substr(0, 2) == "CE" || + port.first.str(ctx).substr(0, 3) == "RST" || port.first.str(ctx).substr(0, 3) == "SRO" || + port.first.str(ctx).substr(0, 3) == "SRI" || port.first.str(ctx).substr(0, 2) == "RO" || + port.first.str(ctx).substr(0, 2) == "MA" || port.first.str(ctx).substr(0, 2) == "MB" || + port.first.str(ctx).substr(0, 3) == "CFB" || port.first.str(ctx).substr(0, 3) == "CIN" || + port.first.str(ctx).substr(0, 6) == "SOURCE" || port.first.str(ctx).substr(0, 6) == "SIGNED" || + port.first.str(ctx).substr(0, 2) == "OP") + continue; + bool value = bool_or_default(ci->params, ctx->id(port.first.str(ctx) + "MUX"), false); + tie_cib_signal(ctx, cc, ctx->getBelPinWire(ci->bel, port.first), value); + } + } +} + void write_bitstream(Context *ctx, std::string base_config_file, std::string text_config_file) { ChipConfig cc; @@ -617,10 +734,145 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex NPNR_ASSERT(!cc.bram_data.count(wid)); cc.bram_data[wid] = init_data; cc.tilegroups.push_back(tg); + } else if (ci->type == id_MULT18X18D) { + TileGroup tg; + Loc loc = ctx->getBelLocation(ci->bel); + tg.tiles = get_dsp_tiles(ctx, ci->bel); + std::string dsp = "MULT18_" + std::to_string(loc.z); + tg.config.add_enum(dsp + ".REG_INPUTA_CLK", str_or_default(ci->params, ctx->id("REG_INPUTA_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_INPUTA_CE", str_or_default(ci->params, ctx->id("REG_INPUTA_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_INPUTA_RST", str_or_default(ci->params, ctx->id("REG_INPUTA_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_INPUTB_CLK", str_or_default(ci->params, ctx->id("REG_INPUTB_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_INPUTB_CE", str_or_default(ci->params, ctx->id("REG_INPUTB_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_INPUTB_RST", str_or_default(ci->params, ctx->id("REG_INPUTB_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_INPUTC_CLK", str_or_default(ci->params, ctx->id("REG_INPUTC_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_PIPELINE_CLK", + str_or_default(ci->params, ctx->id("REG_PIPELINE_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_PIPELINE_CE", str_or_default(ci->params, ctx->id("REG_PIPELINE_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_PIPELINE_RST", + str_or_default(ci->params, ctx->id("REG_PIPELINE_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, ctx->id("REG_OUTPUT_CLK"), "NONE")); + if (dsp == "MULT18_0" || dsp == "MULT18_4") + tg.config.add_enum(dsp + ".REG_OUTPUT_RST", + str_or_default(ci->params, ctx->id("REG_OUTPUT_RST"), "RST0")); + + tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, ctx->id("CLK1_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, ctx->id("CLK2_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, ctx->id("CLK3_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED")); + tg.config.add_enum(dsp + ".SOURCEB_MODE", str_or_default(ci->params, ctx->id("SOURCEB_MODE"), "B_SHIFT")); + tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC")); + + tg.config.add_enum(dsp + ".MODE", "MULT18X18D"); + if (str_or_default(ci->params, ctx->id("REG_OUTPUT_CLK"), "NONE") == "NONE") + tg.config.add_enum(dsp + ".CIBOUT_BYP", "ON"); + + if (loc.z < 4) + tg.config.add_enum("DSP_LEFT.CIBOUT", "ON"); + else + tg.config.add_enum("DSP_RIGHT.CIBOUT", "ON"); + + // Some muxes default to INV, make all pass-thru + for (auto port : {"CLK", "CE", "RST"}) { + for (int i = 0; i < 4; i++) { + std::string sig = port + std::to_string(i); + tg.config.add_enum(dsp + "." + sig + "MUX", sig); + } + } + + tieoff_dsp_ports(ctx, cc, ci); + cc.tilegroups.push_back(tg); + + } else if (ci->type == id_ALU54B) { + TileGroup tg; + Loc loc = ctx->getBelLocation(ci->bel); + tg.tiles = get_dsp_tiles(ctx, ci->bel); + std::string dsp = "ALU54_" + std::to_string(loc.z); + tg.config.add_enum(dsp + ".REG_INPUTC0_CLK", + str_or_default(ci->params, ctx->id("REG_INPUTC0_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_INPUTC1_CLK", + str_or_default(ci->params, ctx->id("REG_INPUTC1_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CLK", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_RST", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_OPCODEOP1_0_CLK", + str_or_default(ci->params, ctx->id("REG_OPCODEOP1_0_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CLK", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_RST", + str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CE", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_0_RST", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CLK", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CE", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_CE"), "CE0")); + tg.config.add_enum(dsp + ".REG_OPCODEIN_1_RST", + str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_RST"), "RST0")); + tg.config.add_enum(dsp + ".REG_OUTPUT0_CLK", + str_or_default(ci->params, ctx->id("REG_OUTPUT0_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_OUTPUT1_CLK", + str_or_default(ci->params, ctx->id("REG_OUTPUT1_CLK"), "NONE")); + tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, ctx->id("REG_FLAG_CLK"), "NONE")); + tg.config.add_enum(dsp + ".MCPAT_SOURCE", str_or_default(ci->params, ctx->id("MCPAT_SOURCE"), "STATIC")); + tg.config.add_enum(dsp + ".MASKPAT_SOURCE", + str_or_default(ci->params, ctx->id("MASKPAT_SOURCE"), "STATIC")); + tg.config.add_word(dsp + ".MASK01", + parse_init_str(str_or_default(ci->params, ctx->id("MASK01"), "0x00000000000000"), 56)); + tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, ctx->id("CLK1_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, ctx->id("CLK2_DIV"), "ENABLED")); + tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, ctx->id("CLK3_DIV"), "ENABLED")); + tg.config.add_word(dsp + ".MCPAT", + parse_init_str(str_or_default(ci->params, ctx->id("MCPAT"), "0x00000000000000"), 56)); + tg.config.add_word(dsp + ".MASKPAT", + parse_init_str(str_or_default(ci->params, ctx->id("MASKPAT"), "0x00000000000000"), 56)); + tg.config.add_word(dsp + ".RNDPAT", + parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 56)); + tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED")); + tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC")); + tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT", + str_or_default(ci->params, ctx->id("FORCE_ZERO_BARREL_SHIFT"), "DISABLED")); + tg.config.add_enum(dsp + ".LEGACY", str_or_default(ci->params, ctx->id("LEGACY"), "DISABLED")); + + tg.config.add_enum(dsp + ".MODE", "ALU54B"); + + if (loc.z < 4) + tg.config.add_enum("DSP_LEFT.CIBOUT", "ON"); + else + tg.config.add_enum("DSP_RIGHT.CIBOUT", "ON"); + if (str_or_default(ci->params, ctx->id("REG_FLAG_CLK"), "NONE") == "NONE") { + if (dsp == "ALU54_7") { + tg.config.add_enum("MULT18_5.CIBOUT_BYP", "ON"); + } else if (dsp == "ALU54_3") { + tg.config.add_enum("MULT18_5.CIBOUT_BYP", "ON"); + } + } + if (str_or_default(ci->params, ctx->id("REG_OUTPUT0_CLK"), "NONE") == "NONE") { + if (dsp == "ALU54_7") { + tg.config.add_enum("MULT18_4.CIBOUT_BYP", "ON"); + } else if (dsp == "ALU54_3") { + tg.config.add_enum("MULT18_0.CIBOUT_BYP", "ON"); + } + } + tieoff_dsp_ports(ctx, cc, ci); + cc.tilegroups.push_back(tg); + } else { NPNR_ASSERT_FALSE("unsupported cell type"); } } + // Fixup tile names fix_tile_names(ctx, cc); // Configure chip diff --git a/ecp5/constids.inc b/ecp5/constids.inc index 7880126b..e3bfec6e 100644 --- a/ecp5/constids.inc +++ b/ecp5/constids.inc @@ -171,4 +171,619 @@ X(DOB13) X(DOB14) X(DOB15) X(DOB16) -X(DOB17)
\ No newline at end of file +X(DOB17) + + +X(MULT18X18D) +X(A2) +X(A3) +X(A4) +X(A5) +X(A6) +X(A7) +X(A8) +X(A9) +X(A10) +X(A11) +X(A12) +X(A13) +X(A14) +X(A15) +X(A16) +X(A17) +X(B2) +X(B3) +X(B4) +X(B5) +X(B6) +X(B7) +X(B8) +X(B9) +X(B10) +X(B11) +X(B12) +X(B13) +X(B14) +X(B15) +X(B16) +X(B17) +X(C2) +X(C3) +X(C4) +X(C5) +X(C6) +X(C7) +X(C8) +X(C9) +X(C10) +X(C11) +X(C12) +X(C13) +X(C14) +X(C15) +X(C16) +X(C17) +X(SIGNEDA) +X(SIGNEDB) +X(SOURCEA) +X(SOURCEB) +X(CLK0) +X(CLK1) +X(CLK2) +X(CLK3) +X(CE0) +X(CE1) +X(CE2) +X(CE3) +X(RST0) +X(RST1) +X(RST2) +X(RST3) +X(SRIA0) +X(SRIA1) +X(SRIA2) +X(SRIA3) +X(SRIA4) +X(SRIA5) +X(SRIA6) +X(SRIA7) +X(SRIA8) +X(SRIA9) +X(SRIA10) +X(SRIA11) +X(SRIA12) +X(SRIA13) +X(SRIA14) +X(SRIA15) +X(SRIA16) +X(SRIA17) +X(SRIB0) +X(SRIB1) +X(SRIB2) +X(SRIB3) +X(SRIB4) +X(SRIB5) +X(SRIB6) +X(SRIB7) +X(SRIB8) +X(SRIB9) +X(SRIB10) +X(SRIB11) +X(SRIB12) +X(SRIB13) +X(SRIB14) +X(SRIB15) +X(SRIB16) +X(SRIB17) +X(SROA0) +X(SROA1) +X(SROA2) +X(SROA3) +X(SROA4) +X(SROA5) +X(SROA6) +X(SROA7) +X(SROA8) +X(SROA9) +X(SROA10) +X(SROA11) +X(SROA12) +X(SROA13) +X(SROA14) +X(SROA15) +X(SROA16) +X(SROA17) +X(SROB0) +X(SROB1) +X(SROB2) +X(SROB3) +X(SROB4) +X(SROB5) +X(SROB6) +X(SROB7) +X(SROB8) +X(SROB9) +X(SROB10) +X(SROB11) +X(SROB12) +X(SROB13) +X(SROB14) +X(SROB15) +X(SROB16) +X(SROB17) +X(ROA0) +X(ROA1) +X(ROA2) +X(ROA3) +X(ROA4) +X(ROA5) +X(ROA6) +X(ROA7) +X(ROA8) +X(ROA9) +X(ROA10) +X(ROA11) +X(ROA12) +X(ROA13) +X(ROA14) +X(ROA15) +X(ROA16) +X(ROA17) +X(ROB0) +X(ROB1) +X(ROB2) +X(ROB3) +X(ROB4) +X(ROB5) +X(ROB6) +X(ROB7) +X(ROB8) +X(ROB9) +X(ROB10) +X(ROB11) +X(ROB12) +X(ROB13) +X(ROB14) +X(ROB15) +X(ROB16) +X(ROB17) +X(ROC0) +X(ROC1) +X(ROC2) +X(ROC3) +X(ROC4) +X(ROC5) +X(ROC6) +X(ROC7) +X(ROC8) +X(ROC9) +X(ROC10) +X(ROC11) +X(ROC12) +X(ROC13) +X(ROC14) +X(ROC15) +X(ROC16) +X(ROC17) +X(P0) +X(P1) +X(P2) +X(P3) +X(P4) +X(P5) +X(P6) +X(P7) +X(P8) +X(P9) +X(P10) +X(P11) +X(P12) +X(P13) +X(P14) +X(P15) +X(P16) +X(P17) +X(P18) +X(P19) +X(P20) +X(P21) +X(P22) +X(P23) +X(P24) +X(P25) +X(P26) +X(P27) +X(P28) +X(P29) +X(P30) +X(P31) +X(P32) +X(P33) +X(P34) +X(P35) +X(SIGNEDP) + +X(ALU54B) +X(SIGNEDIA) +X(SIGNEDIB) +X(SIGNEDCIN) +X(A18) +X(A19) +X(A20) +X(A21) +X(A22) +X(A23) +X(A24) +X(A25) +X(A26) +X(A27) +X(A28) +X(A29) +X(A30) +X(A31) +X(A32) +X(A33) +X(A34) +X(A35) +X(B18) +X(B19) +X(B20) +X(B21) +X(B22) +X(B23) +X(B24) +X(B25) +X(B26) +X(B27) +X(B28) +X(B29) +X(B30) +X(B31) +X(B32) +X(B33) +X(B34) +X(B35) +X(C18) +X(C19) +X(C20) +X(C21) +X(C22) +X(C23) +X(C24) +X(C25) +X(C26) +X(C27) +X(C28) +X(C29) +X(C30) +X(C31) +X(C32) +X(C33) +X(C34) +X(C35) +X(C36) +X(C37) +X(C38) +X(C39) +X(C40) +X(C41) +X(C42) +X(C43) +X(C44) +X(C45) +X(C46) +X(C47) +X(C48) +X(C49) +X(C50) +X(C51) +X(C52) +X(C53) +X(CFB0) +X(CFB1) +X(CFB2) +X(CFB3) +X(CFB4) +X(CFB5) +X(CFB6) +X(CFB7) +X(CFB8) +X(CFB9) +X(CFB10) +X(CFB11) +X(CFB12) +X(CFB13) +X(CFB14) +X(CFB15) +X(CFB16) +X(CFB17) +X(CFB18) +X(CFB19) +X(CFB20) +X(CFB21) +X(CFB22) +X(CFB23) +X(CFB24) +X(CFB25) +X(CFB26) +X(CFB27) +X(CFB28) +X(CFB29) +X(CFB30) +X(CFB31) +X(CFB32) +X(CFB33) +X(CFB34) +X(CFB35) +X(CFB36) +X(CFB37) +X(CFB38) +X(CFB39) +X(CFB40) +X(CFB41) +X(CFB42) +X(CFB43) +X(CFB44) +X(CFB45) +X(CFB46) +X(CFB47) +X(CFB48) +X(CFB49) +X(CFB50) +X(CFB51) +X(CFB52) +X(CFB53) +X(MA0) +X(MA1) +X(MA2) +X(MA3) +X(MA4) +X(MA5) +X(MA6) +X(MA7) +X(MA8) +X(MA9) +X(MA10) +X(MA11) +X(MA12) +X(MA13) +X(MA14) +X(MA15) +X(MA16) +X(MA17) +X(MA18) +X(MA19) +X(MA20) +X(MA21) +X(MA22) +X(MA23) +X(MA24) +X(MA25) +X(MA26) +X(MA27) +X(MA28) +X(MA29) +X(MA30) +X(MA31) +X(MA32) +X(MA33) +X(MA34) +X(MA35) +X(MB0) +X(MB1) +X(MB2) +X(MB3) +X(MB4) +X(MB5) +X(MB6) +X(MB7) +X(MB8) +X(MB9) +X(MB10) +X(MB11) +X(MB12) +X(MB13) +X(MB14) +X(MB15) +X(MB16) +X(MB17) +X(MB18) +X(MB19) +X(MB20) +X(MB21) +X(MB22) +X(MB23) +X(MB24) +X(MB25) +X(MB26) +X(MB27) +X(MB28) +X(MB29) +X(MB30) +X(MB31) +X(MB32) +X(MB33) +X(MB34) +X(MB35) +X(CIN0) +X(CIN1) +X(CIN2) +X(CIN3) +X(CIN4) +X(CIN5) +X(CIN6) +X(CIN7) +X(CIN8) +X(CIN9) +X(CIN10) +X(CIN11) +X(CIN12) +X(CIN13) +X(CIN14) +X(CIN15) +X(CIN16) +X(CIN17) +X(CIN18) +X(CIN19) +X(CIN20) +X(CIN21) +X(CIN22) +X(CIN23) +X(CIN24) +X(CIN25) +X(CIN26) +X(CIN27) +X(CIN28) +X(CIN29) +X(CIN30) +X(CIN31) +X(CIN32) +X(CIN33) +X(CIN34) +X(CIN35) +X(CIN36) +X(CIN37) +X(CIN38) +X(CIN39) +X(CIN40) +X(CIN41) +X(CIN42) +X(CIN43) +X(CIN44) +X(CIN45) +X(CIN46) +X(CIN47) +X(CIN48) +X(CIN49) +X(CIN50) +X(CIN51) +X(CIN52) +X(CIN53) +X(OP0) +X(OP1) +X(OP2) +X(OP3) +X(OP4) +X(OP5) +X(OP6) +X(OP7) +X(OP8) +X(OP9) +X(OP10) +X(R0) +X(R1) +X(R2) +X(R3) +X(R4) +X(R5) +X(R6) +X(R7) +X(R8) +X(R9) +X(R10) +X(R11) +X(R12) +X(R13) +X(R14) +X(R15) +X(R16) +X(R17) +X(R18) +X(R19) +X(R20) +X(R21) +X(R22) +X(R23) +X(R24) +X(R25) +X(R26) +X(R27) +X(R28) +X(R29) +X(R30) +X(R31) +X(R32) +X(R33) +X(R34) +X(R35) +X(R36) +X(R37) +X(R38) +X(R39) +X(R40) +X(R41) +X(R42) +X(R43) +X(R44) +X(R45) +X(R46) +X(R47) +X(R48) +X(R49) +X(R50) +X(R51) +X(R52) +X(R53) +X(CO0) +X(CO1) +X(CO2) +X(CO3) +X(CO4) +X(CO5) +X(CO6) +X(CO7) +X(CO8) +X(CO9) +X(CO10) +X(CO11) +X(CO12) +X(CO13) +X(CO14) +X(CO15) +X(CO16) +X(CO17) +X(CO18) +X(CO19) +X(CO20) +X(CO21) +X(CO22) +X(CO23) +X(CO24) +X(CO25) +X(CO26) +X(CO27) +X(CO28) +X(CO29) +X(CO30) +X(CO31) +X(CO32) +X(CO33) +X(CO34) +X(CO35) +X(CO36) +X(CO37) +X(CO38) +X(CO39) +X(CO40) +X(CO41) +X(CO42) +X(CO43) +X(CO44) +X(CO45) +X(CO46) +X(CO47) +X(CO48) +X(CO49) +X(CO50) +X(CO51) +X(CO52) +X(CO53) +X(EQZ) +X(EQZM) +X(EQOM) +X(EQPAT) +X(EQPATB) +X(OVER) +X(UNDER) +X(OVERUNDER) +X(SIGNEDR) diff --git a/ecp5/pack.cc b/ecp5/pack.cc index ef65fd27..18debb74 100644 --- a/ecp5/pack.cc +++ b/ecp5/pack.cc @@ -856,7 +856,21 @@ class Ecp5Packer uc->params[ctx->id(user.port.str(ctx) + "MUX")] = constval ? "1" : "0"; } uc->ports[user.port].net = nullptr; - + } else if (uc->type == id_ALU54B || uc->type == id_MULT18X18D) { + if (user.port.str(ctx).substr(0, 3) == "CLK" || user.port.str(ctx).substr(0, 2) == "CE" || + user.port.str(ctx).substr(0, 3) == "RST" || user.port.str(ctx).substr(0, 3) == "SRO" || + user.port.str(ctx).substr(0, 3) == "SRI" || user.port.str(ctx).substr(0, 2) == "RO" || + user.port.str(ctx).substr(0, 2) == "MA" || user.port.str(ctx).substr(0, 2) == "MB" || + user.port.str(ctx).substr(0, 3) == "CFB" || user.port.str(ctx).substr(0, 3) == "CIN" || + user.port.str(ctx).substr(0, 6) == "SOURCE" || user.port.str(ctx).substr(0, 6) == "SIGNED" || + user.port.str(ctx).substr(0, 2) == "OP") { + uc->ports[user.port].net = constnet; + constnet->users.push_back(user); + } else { + // Connected to CIB ABCD. Default state is bitstream configurable + uc->params[ctx->id(user.port.str(ctx) + "MUX")] = constval ? "1" : "0"; + uc->ports[user.port].net = nullptr; + } } else { uc->ports[user.port].net = constnet; constnet->users.push_back(user); @@ -974,11 +988,50 @@ class Ecp5Packer } } + // Pack DSPs + void pack_dsps() + { + for (auto cell : sorted(ctx->cells)) { + CellInfo *ci = cell.second; + if (ci->type == id_MULT18X18D) { + // Add ports, even if disconnected, to ensure correct tie-offs + for (auto sig : {"CLK", "CE", "RST"}) + for (int i = 0; i < 4; i++) + autocreate_empty_port(ci, ctx->id(sig + std::to_string(i))); + for (auto sig : {"SIGNED", "SOURCE"}) + for (auto c : {"A", "B"}) + autocreate_empty_port(ci, ctx->id(sig + std::string(c))); + for (auto port : {"A", "B", "C"}) + for (int i = 0; i < 18; i++) + autocreate_empty_port(ci, ctx->id(port + std::to_string(i))); + for (auto port : {"SRIA", "SRIB"}) + for (int i = 0; i < 18; i++) + autocreate_empty_port(ci, ctx->id(port + std::to_string(i))); + } else if (ci->type == id_ALU54B) { + for (auto sig : {"CLK", "CE", "RST"}) + for (int i = 0; i < 4; i++) + autocreate_empty_port(ci, ctx->id(sig + std::to_string(i))); + autocreate_empty_port(ci, id_SIGNEDIA); + autocreate_empty_port(ci, id_SIGNEDIB); + autocreate_empty_port(ci, id_SIGNEDCIN); + for (auto port : {"A", "B", "MA", "MB"}) + for (int i = 0; i < 36; i++) + autocreate_empty_port(ci, ctx->id(port + std::to_string(i))); + for (auto port : {"C", "CFB", "CIN"}) + for (int i = 0; i < 54; i++) + autocreate_empty_port(ci, ctx->id(port + std::to_string(i))); + for (int i = 0; i < 11; i++) + autocreate_empty_port(ci, ctx->id("OP" + std::to_string(i))); + } + } + } + public: void pack() { pack_io(); pack_ebr(); + pack_dsps(); pack_constants(); pack_dram(); pack_carries(); |