ecp5: Working on DSPs
Signed-off-by: David Shah <davey1576@gmail.com>
This commit is contained in:
parent
1a06f4b2bd
commit
535a6f625a
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
#include <queue>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <streambuf>
|
#include <streambuf>
|
||||||
|
|
||||||
@ -81,17 +82,23 @@ 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 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]");
|
static const std::regex cib_re("J([A-D]|CE|LSR|CLK)[0-7]");
|
||||||
WireId cibsig = wire;
|
std::queue<WireId> signals;
|
||||||
std::string basename = ctx->getWireBasename(wire).str(ctx);
|
signals.push(wire);
|
||||||
|
WireId cibsig;
|
||||||
while (!std::regex_match(basename, cib_re)) {
|
std::string basename;
|
||||||
auto uphill = ctx->getPipsUphill(cibsig);
|
log_info("wire %s\n", ctx->getWireName(wire).c_str(ctx));
|
||||||
NPNR_ASSERT(uphill.begin() != uphill.end()); // At least one uphill pip
|
while (true) {
|
||||||
auto iter = uphill.begin();
|
NPNR_ASSERT(!signals.empty());
|
||||||
cibsig = ctx->getPipSrcWire(*iter);
|
NPNR_ASSERT(signals.size() < 100);
|
||||||
|
cibsig = signals.front();
|
||||||
basename = ctx->getWireBasename(cibsig).str(ctx);
|
basename = ctx->getWireBasename(cibsig).str(ctx);
|
||||||
++iter;
|
log_info(" wire %s\n", ctx->getWireName(cibsig).c_str(ctx));
|
||||||
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;
|
bool out_value = value;
|
||||||
@ -285,7 +292,7 @@ std::vector<std::string> get_dsp_tiles(Context *ctx, BelId bel)
|
|||||||
std::vector<std::string> tiles;
|
std::vector<std::string> tiles;
|
||||||
Loc loc = ctx->getBelLocation(bel);
|
Loc loc = ctx->getBelLocation(bel);
|
||||||
|
|
||||||
static const std::set<std::string> dsp8 = {"MIB_DSP8", "DSP_SPINE_UL0", "DSP_SPINE_UR0", "DSP_SPINE_UR1", ""};
|
static const std::set<std::string> dsp8 = {"MIB_DSP8", "DSP_SPINE_UL0", "DSP_SPINE_UR0", "DSP_SPINE_UR1"};
|
||||||
if (ctx->getBelType(bel) == id_MULT18X18D) {
|
if (ctx->getBelType(bel) == id_MULT18X18D) {
|
||||||
switch (loc.z) {
|
switch (loc.z) {
|
||||||
case 0:
|
case 0:
|
||||||
@ -404,6 +411,23 @@ 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")
|
||||||
|
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)
|
void write_bitstream(Context *ctx, std::string base_config_file, std::string text_config_file)
|
||||||
{
|
{
|
||||||
ChipConfig cc;
|
ChipConfig cc;
|
||||||
@ -714,87 +738,129 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
|||||||
Loc loc = ctx->getBelLocation(ci->bel);
|
Loc loc = ctx->getBelLocation(ci->bel);
|
||||||
tg.tiles = get_dsp_tiles(ctx, ci->bel);
|
tg.tiles = get_dsp_tiles(ctx, ci->bel);
|
||||||
std::string dsp = "MULT18_" + std::to_string(loc.z);
|
std::string dsp = "MULT18_" + std::to_string(loc.z);
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTA_CLK", str_or_default(ci->params, "REG_INPUTA_CLK", "NONE"));
|
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, "REG_INPUTA_CE", "CE0"));
|
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, "REG_INPUTA_RST", "RST0"));
|
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, "REG_INPUTB_CLK", "NONE"));
|
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, "REG_INPUTB_CE", "CE0"));
|
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, "REG_INPUTB_RST", "RST0"));
|
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, "REG_INPUTC_CLK", "NONE"));
|
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_INPUTC_CE", str_or_default(ci->params, "REG_INPUTC_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_PIPELINE_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC_RST", str_or_default(ci->params, "REG_INPUTC_RST", "RST0"));
|
str_or_default(ci->params, ctx->id("REG_PIPELINE_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_PIPELINE_CLK", str_or_default(ci->params, "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_CE", str_or_default(ci->params, "REG_PIPELINE_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_PIPELINE_RST",
|
||||||
tg.config.add_enum(dsp + ".REG_PIPELINE_RST", str_or_default(ci->params, "REG_PIPELINE_RST", "RST0"));
|
str_or_default(ci->params, ctx->id("REG_PIPELINE_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, "REG_OUTPUT_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, ctx->id("REG_OUTPUT_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT_CE", str_or_default(ci->params, "REG_OUTPUT_CE", "CE0"));
|
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT_RST", str_or_default(ci->params, "REG_OUTPUT_RST", "RST0"));
|
tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, ctx->id("CLK1_DIV"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, "CLK0_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, ctx->id("CLK2_DIV"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, "CLK1_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, ctx->id("CLK3_DIV"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, "CLK2_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, "CLK3_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".SOURCEB_MODE", str_or_default(ci->params, ctx->id("SOURCEB_MODE"), "B_SHIFT"));
|
||||||
tg.config.add_enum(dsp + ".HIGHSPEED_CLK", str_or_default(ci->params, "HIGHSPEED_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC"));
|
||||||
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, "GSR", "ENABLED"));
|
|
||||||
tg.config.add_enum(dsp + ".CAS_MATCH_REG", str_or_default(ci->params, "CAS_MATCH_REG", "FALSE"));
|
tg.config.add_enum(dsp + ".MODE", "MULT18X18D");
|
||||||
tg.config.add_enum(dsp + ".SOURCEB_MODE", str_or_default(ci->params, "SOURCEB_MODE", "B_SHIFT"));
|
|
||||||
tg.config.add_enum(dsp + ".MULT_BYPASS", str_or_default(ci->params, "MULT_BYPASS", "DISABLED"));
|
if (loc.z < 4)
|
||||||
tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, "RESETMODE", "SYNC"));
|
tg.config.add_enum("DSP_LEFT.CIBOUT", "ON");
|
||||||
|
else
|
||||||
|
tg.config.add_enum("DSP_RIGHT.CIBOUT", "ON");
|
||||||
|
|
||||||
|
|
||||||
|
tieoff_dsp_ports(ctx, cc, ci);
|
||||||
|
cc.tilegroups.push_back(tg);
|
||||||
|
|
||||||
} else if (ci->type == id_ALU54B) {
|
} else if (ci->type == id_ALU54B) {
|
||||||
TileGroup tg;
|
TileGroup tg;
|
||||||
Loc loc = ctx->getBelLocation(ci->bel);
|
Loc loc = ctx->getBelLocation(ci->bel);
|
||||||
tg.tiles = get_dsp_tiles(ctx, ci->bel);
|
tg.tiles = get_dsp_tiles(ctx, ci->bel);
|
||||||
std::string dsp = "ALU54_" + std::to_string(loc.z);
|
std::string dsp = "ALU54_" + std::to_string(loc.z);
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC0_CLK", str_or_default(ci->params, "REG_INPUTC0_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_INPUTC0_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC0_CE", str_or_default(ci->params, "REG_INPUTC0_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_INPUTC0_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC0_RST", str_or_default(ci->params, "REG_INPUTC0_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_INPUTC0_CE", str_or_default(ci->params, ctx->id("REG_INPUTC0_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC1_CLK", str_or_default(ci->params, "REG_INPUTC1_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_INPUTC0_RST",
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC1_CE", str_or_default(ci->params, "REG_INPUTC1_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_INPUTC0_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTC1_RST", str_or_default(ci->params, "REG_INPUTC1_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_INPUTC1_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CLK", str_or_default(ci->params, "REG_OPCODEOP0_0_CLK", "NONE"));
|
str_or_default(ci->params, ctx->id("REG_INPUTC1_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE", str_or_default(ci->params, "REG_OPCODEOP0_0_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_INPUTC1_CE", str_or_default(ci->params, ctx->id("REG_INPUTC1_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_RST", str_or_default(ci->params, "REG_OPCODEOP0_0_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_INPUTC1_RST",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP1_0_CLK", str_or_default(ci->params, "REG_OPCODEOP1_0_CLK", "NONE"));
|
str_or_default(ci->params, ctx->id("REG_INPUTC1_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CLK", str_or_default(ci->params, "REG_OPCODEOP0_1_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE", str_or_default(ci->params, "REG_OPCODEOP0_1_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_RST", str_or_default(ci->params, "REG_OPCODEOP0_1_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK", str_or_default(ci->params, "REG_OPCODEIN_0_CLK", "NONE"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CE", str_or_default(ci->params, "REG_OPCODEIN_0_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_RST",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_RST", str_or_default(ci->params, "REG_OPCODEIN_0_RST", "RST0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CLK", str_or_default(ci->params, "REG_OPCODEIN_1_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP1_0_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CE", str_or_default(ci->params, "REG_OPCODEIN_1_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP1_0_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_RST", str_or_default(ci->params, "REG_OPCODEIN_1_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT0_CLK", str_or_default(ci->params, "REG_OUTPUT0_CLK", "NONE"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT0_CE", str_or_default(ci->params, "REG_OUTPUT0_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE",
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT0_RST", str_or_default(ci->params, "REG_OUTPUT0_RST", "RST0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT1_CLK", str_or_default(ci->params, "REG_OUTPUT1_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_RST",
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT1_CE", str_or_default(ci->params, "REG_OUTPUT1_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".REG_OUTPUT1_RST", str_or_default(ci->params, "REG_OUTPUT1_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, "REG_FLAG_CLK", "NONE"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_FLAG_CE", str_or_default(ci->params, "REG_FLAG_CE", "CE0"));
|
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CE",
|
||||||
tg.config.add_enum(dsp + ".REG_FLAG_RST", str_or_default(ci->params, "REG_FLAG_RST", "RST0"));
|
str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".MCPAT_SOURCE", str_or_default(ci->params, "MCPAT_SOURCE", "STATIC"));
|
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_RST",
|
||||||
tg.config.add_enum(dsp + ".MASKPAT_SOURCE", str_or_default(ci->params, "MASKPAT_SOURCE", "STATIC"));
|
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_OUTPUT0_CE", str_or_default(ci->params, ctx->id("REG_OUTPUT0_CE"), "CE0"));
|
||||||
|
tg.config.add_enum(dsp + ".REG_OUTPUT0_RST",
|
||||||
|
str_or_default(ci->params, ctx->id("REG_OUTPUT0_RST"), "RST0"));
|
||||||
|
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_OUTPUT1_CE", str_or_default(ci->params, ctx->id("REG_OUTPUT1_CE"), "CE0"));
|
||||||
|
tg.config.add_enum(dsp + ".REG_OUTPUT1_RST",
|
||||||
|
str_or_default(ci->params, ctx->id("REG_OUTPUT1_RST"), "RST0"));
|
||||||
|
tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, ctx->id("REG_FLAG_CLK"), "NONE"));
|
||||||
|
tg.config.add_enum(dsp + ".REG_FLAG_CE", str_or_default(ci->params, ctx->id("REG_FLAG_CE"), "CE0"));
|
||||||
|
tg.config.add_enum(dsp + ".REG_FLAG_RST", str_or_default(ci->params, ctx->id("REG_FLAG_RST"), "RST0"));
|
||||||
|
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",
|
tg.config.add_word(dsp + ".MASK01",
|
||||||
parse_init_str(str_or_default(ci->params, "MASK01", "0x00000000000000"), 54));
|
parse_init_str(str_or_default(ci->params, ctx->id("MASK01"), "0x00000000000000"), 54));
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTCFB_CLK", str_or_default(ci->params, "REG_INPUTCFB_CLK", "NONE"));
|
tg.config.add_enum(dsp + ".REG_INPUTCFB_CLK",
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTCFB_CE", str_or_default(ci->params, "REG_INPUTCFB_CE", "CE0"));
|
str_or_default(ci->params, ctx->id("REG_INPUTCFB_CLK"), "NONE"));
|
||||||
tg.config.add_enum(dsp + ".REG_INPUTCFB_RST", str_or_default(ci->params, "REG_INPUTCFB_RST", "RST0"));
|
tg.config.add_enum(dsp + ".REG_INPUTCFB_CE", str_or_default(ci->params, ctx->id("REG_INPUTCFB_CE"), "CE0"));
|
||||||
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, "CLK0_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".REG_INPUTCFB_RST",
|
||||||
tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, "CLK1_DIV", "ENABLED"));
|
str_or_default(ci->params, ctx->id("REG_INPUTCFB_RST"), "RST0"));
|
||||||
tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, "CLK2_DIV", "ENABLED"));
|
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED"));
|
||||||
tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, "CLK3_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",
|
tg.config.add_word(dsp + ".MCPAT",
|
||||||
parse_init_str(str_or_default(ci->params, "MCPAT", "0x00000000000000"), 54));
|
parse_init_str(str_or_default(ci->params, ctx->id("MCPAT"), "0x00000000000000"), 54));
|
||||||
tg.config.add_word(dsp + ".MASKPAT",
|
tg.config.add_word(dsp + ".MASKPAT",
|
||||||
parse_init_str(str_or_default(ci->params, "MASKPAT", "0x00000000000000"), 54));
|
parse_init_str(str_or_default(ci->params, ctx->id("MASKPAT"), "0x00000000000000"), 54));
|
||||||
tg.config.add_word(dsp + ".RNDPAT",
|
tg.config.add_word(dsp + ".RNDPAT",
|
||||||
parse_init_str(str_or_default(ci->params, "RNDPAT", "0x00000000000000"), 54));
|
parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 54));
|
||||||
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, "GSR", "ENABLED"));
|
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, "RESETMODE", "SYNC"));
|
tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC"));
|
||||||
tg.config.add_enum(dsp + ".MULT9_MODE", str_or_default(ci->params, "MULT9_MODE", "DISABLED"));
|
tg.config.add_enum(dsp + ".MULT9_MODE", str_or_default(ci->params, ctx->id("MULT9_MODE"), "DISABLED"));
|
||||||
tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT",
|
tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT",
|
||||||
str_or_default(ci->params, "FORCE_ZERO_BARREL_SHIFT", "DISABLED"));
|
str_or_default(ci->params, ctx->id("FORCE_ZERO_BARREL_SHIFT"), "DISABLED"));
|
||||||
tg.config.add_enum(dsp + ".LEGACY", str_or_default(ci->params, "LEGACY", "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");
|
||||||
|
|
||||||
|
tieoff_dsp_ports(ctx, cc, ci);
|
||||||
|
cc.tilegroups.push_back(tg);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
NPNR_ASSERT_FALSE("unsupported cell type");
|
NPNR_ASSERT_FALSE("unsupported cell type");
|
||||||
}
|
}
|
||||||
|
53
ecp5/pack.cc
53
ecp5/pack.cc
@ -856,7 +856,19 @@ class Ecp5Packer
|
|||||||
uc->params[ctx->id(user.port.str(ctx) + "MUX")] = constval ? "1" : "0";
|
uc->params[ctx->id(user.port.str(ctx) + "MUX")] = constval ? "1" : "0";
|
||||||
}
|
}
|
||||||
uc->ports[user.port].net = nullptr;
|
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") {
|
||||||
|
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";
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
uc->ports[user.port].net = constnet;
|
uc->ports[user.port].net = constnet;
|
||||||
constnet->users.push_back(user);
|
constnet->users.push_back(user);
|
||||||
@ -974,11 +986,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:
|
public:
|
||||||
void pack()
|
void pack()
|
||||||
{
|
{
|
||||||
pack_io();
|
pack_io();
|
||||||
pack_ebr();
|
pack_ebr();
|
||||||
|
pack_dsps();
|
||||||
pack_constants();
|
pack_constants();
|
||||||
pack_dram();
|
pack_dram();
|
||||||
pack_carries();
|
pack_carries();
|
||||||
|
Loading…
Reference in New Issue
Block a user