Merge pull request #118 from daveshah1/dcu

Adding ECP5 DCU support
This commit is contained in:
David Shah 2018-11-16 09:58:34 +00:00 committed by GitHub
commit fe4f98f26f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 934 additions and 38 deletions

View File

@ -651,6 +651,16 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
return TMG_IGNORE; // FIXME return TMG_IGNORE; // FIXME
} else if (cell->type == id_EHXPLLL) { } else if (cell->type == id_EHXPLLL) {
return TMG_IGNORE; return TMG_IGNORE;
} else if (cell->type == id_DCUA || cell->type == id_EXTREFB || cell->type == id_PCSCLKDIV) {
if (port == id_CH0_FF_TXI_CLK || port == id_CH0_FF_RXI_CLK || port == id_CH1_FF_TXI_CLK ||
port == id_CH1_FF_RXI_CLK)
return TMG_CLOCK_INPUT;
std::string prefix = port.str(this).substr(0, 9);
if (prefix == "CH0_FF_TX" || prefix == "CH0_FF_RX" || prefix == "CH1_FF_TX" || prefix == "CH1_FF_RX") {
clockInfoCount = 1;
return (cell->ports.at(port).type == PORT_OUT) ? TMG_REGISTER_OUTPUT : TMG_REGISTER_INPUT;
}
return TMG_IGNORE;
} else { } else {
NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'"); NPNR_ASSERT_FALSE_STR("no timing data for cell type '" + cell->type.str(this) + "'");
} }
@ -706,6 +716,23 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
info.setup.delay = 100; info.setup.delay = 100;
info.hold.delay = 0; info.hold.delay = 0;
} }
} else if (cell->type == id_DCUA) {
std::string prefix = port.str(this).substr(0, 9);
info.edge = RISING_EDGE;
if (prefix == "CH0_FF_TX")
info.clock_port = id_CH0_FF_TXI_CLK;
else if (prefix == "CH0_FF_RX")
info.clock_port = id_CH0_FF_RXI_CLK;
else if (prefix == "CH1_FF_TX")
info.clock_port = id_CH1_FF_TXI_CLK;
else if (prefix == "CH1_FF_RX")
info.clock_port = id_CH1_FF_RXI_CLK;
if (cell->ports.at(port).type == PORT_OUT) {
info.clockToQ.delay = 660;
} else {
info.setup.delay = 1000;
info.hold.delay = 0;
}
} }
return info; return info;
} }

View File

@ -101,6 +101,8 @@ bool Arch::isValidBelForCell(CellInfo *cell, BelId bel) const
bel_cells.push_back(cell); bel_cells.push_back(cell);
return slicesCompatible(bel_cells); return slicesCompatible(bel_cells);
} else if (cell->type == id_DCUA || cell->type == id_EXTREFB || cell->type == id_PCSCLKDIV) {
return args.type != ArchArgs::LFE5U_25F && args.type != ArchArgs::LFE5U_45F && args.type != ArchArgs::LFE5U_85F;
} else { } else {
// other checks // other checks
return true; return true;

View File

@ -87,7 +87,10 @@ struct BelId
bool operator==(const BelId &other) const { return index == other.index && location == other.location; } bool operator==(const BelId &other) const { return index == other.index && location == other.location; }
bool operator!=(const BelId &other) const { return index != other.index || location != other.location; } bool operator!=(const BelId &other) const { return index != other.index || location != other.location; }
bool operator<(const BelId &other) const { return location == other.location ? index < other.index : location < other.location; } bool operator<(const BelId &other) const
{
return location == other.location ? index < other.index : location < other.location;
}
}; };
struct WireId struct WireId
@ -97,7 +100,10 @@ struct WireId
bool operator==(const WireId &other) const { return index == other.index && location == other.location; } bool operator==(const WireId &other) const { return index == other.index && location == other.location; }
bool operator!=(const WireId &other) const { return index != other.index || location != other.location; } bool operator!=(const WireId &other) const { return index != other.index || location != other.location; }
bool operator<(const WireId &other) const { return location == other.location ? index < other.index : location < other.location; } bool operator<(const WireId &other) const
{
return location == other.location ? index < other.index : location < other.location;
}
}; };
struct PipId struct PipId
@ -107,7 +113,10 @@ struct PipId
bool operator==(const PipId &other) const { return index == other.index && location == other.location; } bool operator==(const PipId &other) const { return index == other.index && location == other.location; }
bool operator!=(const PipId &other) const { return index != other.index || location != other.location; } bool operator!=(const PipId &other) const { return index != other.index || location != other.location; }
bool operator<(const PipId &other) const { return location == other.location ? index < other.index : location < other.location; } bool operator<(const PipId &other) const
{
return location == other.location ? index < other.index : location < other.location;
}
}; };
struct GroupId struct GroupId

View File

@ -24,7 +24,7 @@
#include <queue> #include <queue>
#include <regex> #include <regex>
#include <streambuf> #include <streambuf>
#include <boost/algorithm/string/predicate.hpp>
#include "config.h" #include "config.h"
#include "io.h" #include "io.h"
#include "log.h" #include "log.h"
@ -379,6 +379,16 @@ std::vector<std::string> get_dsp_tiles(Context *ctx, BelId bel)
return tiles; return tiles;
} }
// Get the list of tiles corresponding to a DCU
std::vector<std::string> get_dcu_tiles(Context *ctx, BelId bel)
{
std::vector<std::string> tiles;
Loc loc = ctx->getBelLocation(bel);
for (int i = 0; i < 9; i++)
tiles.push_back(ctx->getTileByTypeAndLocation(loc.y, loc.x + i, "DCU" + std::to_string(i)));
return tiles;
}
// Get the list of tiles corresponding to a PLL // Get the list of tiles corresponding to a PLL
std::vector<std::string> get_pll_tiles(Context *ctx, BelId bel) std::vector<std::string> get_pll_tiles(Context *ctx, BelId bel)
{ {
@ -408,28 +418,25 @@ std::vector<std::string> get_pll_tiles(Context *ctx, BelId bel)
void fix_tile_names(Context *ctx, ChipConfig &cc) void fix_tile_names(Context *ctx, ChipConfig &cc)
{ {
// Remove the V prefix/suffix on certain tiles if device is a SERDES variant // Remove the V prefix/suffix on certain tiles if device is a SERDES variant
if (ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM_45F || if (ctx->args.type == ArchArgs::LFE5U_25F || ctx->args.type == ArchArgs::LFE5U_45F ||
ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_25F || ctx->args.type == ArchArgs::LFE5U_85F) {
ctx->args.type == ArchArgs::LFE5UM5G_45F || ctx->args.type == ArchArgs::LFE5UM5G_85F) {
std::map<std::string, std::string> tiletype_xform; std::map<std::string, std::string> tiletype_xform;
for (const auto &tile : cc.tiles) { for (const auto &tile : cc.tiles) {
std::string newname = tile.first; std::string newname = tile.first;
auto vcib = tile.first.find("VCIB"); auto cibdcu = tile.first.find("CIB_DCU");
if (vcib != std::string::npos) { if (cibdcu != std::string::npos) {
// Remove the V // Add the V
newname.erase(vcib, 1); if (newname.at(cibdcu - 1) != 'V')
newname.insert(cibdcu, 1, 'V');
tiletype_xform[tile.first] = newname; tiletype_xform[tile.first] = newname;
} else if (tile.first.back() == 'V') { } else if (boost::ends_with(tile.first, "BMID_0H")) {
// BMID_0V or BMID_2V newname.back() = 'V';
if (tile.first.at(tile.first.size() - 2) == '0') {
newname.at(tile.first.size() - 1) = 'H';
tiletype_xform[tile.first] = newname; tiletype_xform[tile.first] = newname;
} else if (tile.first.at(tile.first.size() - 2) == '2') { } else if (boost::ends_with(tile.first, "BMID_2")) {
newname.pop_back(); newname.push_back('V');
tiletype_xform[tile.first] = newname; tiletype_xform[tile.first] = newname;
} }
} }
}
// Apply the name changes // Apply the name changes
for (auto xform : tiletype_xform) { for (auto xform : tiletype_xform) {
cc.tiles[xform.second] = cc.tiles.at(xform.first); cc.tiles[xform.second] = cc.tiles.at(xform.first);
@ -456,6 +463,20 @@ void tieoff_dsp_ports(Context *ctx, ChipConfig &cc, CellInfo *ci)
} }
} }
void tieoff_dcu_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).find("CLK") != std::string::npos ||
port.first.str(ctx).find("HDIN") != std::string::npos ||
port.first.str(ctx).find("HDOUT") != std::string::npos)
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);
}
}
}
static void set_pip(Context *ctx, ChipConfig &cc, PipId pip) static void set_pip(Context *ctx, ChipConfig &cc, PipId pip)
{ {
std::string tile = ctx->getPipTilename(pip); std::string tile = ctx->getPipTilename(pip);
@ -464,6 +485,46 @@ static void set_pip(Context *ctx, ChipConfig &cc, PipId pip)
cc.tiles[tile].add_arc(sink, source); cc.tiles[tile].add_arc(sink, source);
} }
static std::vector<bool> parse_config_str(std::string str, int length)
{
// For DCU config which might be bin, hex or dec using prefices accordingly
std::string base = str.substr(0, 2);
std::vector<bool> word;
word.resize(length, false);
if (base == "0b") {
for (int i = 0; i < int(str.length()) - 2; i++) {
char c = str.at((str.size() - 1) - i);
NPNR_ASSERT(c == '0' || c == '1');
word.at(i) = (c == '1');
}
} else if (base == "0x") {
for (int i = 0; i < int(str.length()) - 2; i++) {
char c = str.at((str.size() - i) - 1);
int nibble = chtohex(c);
word.at(i * 4) = nibble & 0x1;
if (i * 4 + 1 < length)
word.at(i * 4 + 1) = nibble & 0x2;
if (i * 4 + 2 < length)
word.at(i * 4 + 2) = nibble & 0x4;
if (i * 4 + 3 < length)
word.at(i * 4 + 3) = nibble & 0x8;
}
} else if (base == "0d") {
NPNR_ASSERT(length < 64);
unsigned long long value = std::stoull(str.substr(2));
for (int i = 0; i < length; i++)
if (value & (1 << i))
word.at(i) = true;
} else {
NPNR_ASSERT(length < 64);
unsigned long long value = std::stoull(str);
for (int i = 0; i < length; i++)
if (value & (1 << i))
word.at(i) = true;
}
return word;
}
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;
@ -481,6 +542,23 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
// TODO: .bit metadata // TODO: .bit metadata
} }
// Clear out DCU tieoffs in base config if DCU used
for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get();
if (ci->type == id_DCUA) {
Loc loc = ctx->getBelLocation(ci->bel);
for (int i = 0; i < 12; i++) {
auto tiles = ctx->getTilesAtLocation(loc.y - 1, loc.x + i);
for (const auto &tile : tiles) {
auto cc_tile = cc.tiles.find(tile.first);
if (cc_tile != cc.tiles.end()) {
cc_tile->second.cenums.clear();
cc_tile->second.cunknowns.clear();
}
}
}
}
}
// Add all set, configurable pips to the config // Add all set, configurable pips to the config
for (auto pip : ctx->getPips()) { for (auto pip : ctx->getPips()) {
if (ctx->getBoundPipNet(pip) != nullptr) { if (ctx->getBoundPipNet(pip) != nullptr) {
@ -1000,6 +1078,28 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_ENABLE_FILTEROPAMP"), 0), 1)); int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_ENABLE_FILTEROPAMP"), 0), 1));
cc.tilegroups.push_back(tg); cc.tilegroups.push_back(tg);
} else if (ci->type == id_DCUA) {
TileGroup tg;
tg.tiles = get_dcu_tiles(ctx, ci->bel);
tg.config.add_enum("DCU.MODE", "DCUA");
#include "dcu_bitstream.h"
cc.tilegroups.push_back(tg);
tieoff_dcu_ports(ctx, cc, ci);
} else if (ci->type == id_EXTREFB) {
TileGroup tg;
tg.tiles = get_dcu_tiles(ctx, ci->bel);
tg.config.add_word("EXTREF.REFCK_DCBIAS_EN",
parse_config_str(str_or_default(ci->params, ctx->id("REFCK_DCBIAS_EN"), "0"), 1));
tg.config.add_word("EXTREF.REFCK_RTERM",
parse_config_str(str_or_default(ci->params, ctx->id("REFCK_RTERM"), "0"), 1));
tg.config.add_word("EXTREF.REFCK_PWDNB",
parse_config_str(str_or_default(ci->params, ctx->id("REFCK_PWDNB"), "0"), 1));
cc.tilegroups.push_back(tg);
} else if (ci->type == id_PCSCLKDIV) {
Loc loc = ctx->getBelLocation(ci->bel);
std::string tname = ctx->getTileByTypeAndLocation(loc.y + 1, loc.x, "BMID_0H");
cc.tiles[tname].add_enum("PCSCLKDIV" + std::to_string(loc.z),
str_or_default(ci->params, ctx->id("GSR"), "ENABLED"));
} else { } else {
NPNR_ASSERT_FALSE("unsupported cell type"); NPNR_ASSERT_FALSE("unsupported cell type");
} }

View File

@ -810,3 +810,310 @@ X(LOCK)
X(INTLOCK) X(INTLOCK)
X(REFCLK) X(REFCLK)
X(CLKINTFB) X(CLKINTFB)
X(EXTREFB)
X(REFCLKP)
X(REFCLKN)
X(REFCLKO)
X(DCUA)
X(CH0_HDINP)
X(CH1_HDINP)
X(CH0_HDINN)
X(CH1_HDINN)
X(D_TXBIT_CLKP_FROM_ND)
X(D_TXBIT_CLKN_FROM_ND)
X(D_SYNC_ND)
X(D_TXPLL_LOL_FROM_ND)
X(CH0_RX_REFCLK)
X(CH1_RX_REFCLK)
X(CH0_FF_RXI_CLK)
X(CH1_FF_RXI_CLK)
X(CH0_FF_TXI_CLK)
X(CH1_FF_TXI_CLK)
X(CH0_FF_EBRD_CLK)
X(CH1_FF_EBRD_CLK)
X(CH0_FF_TX_D_0)
X(CH1_FF_TX_D_0)
X(CH0_FF_TX_D_1)
X(CH1_FF_TX_D_1)
X(CH0_FF_TX_D_2)
X(CH1_FF_TX_D_2)
X(CH0_FF_TX_D_3)
X(CH1_FF_TX_D_3)
X(CH0_FF_TX_D_4)
X(CH1_FF_TX_D_4)
X(CH0_FF_TX_D_5)
X(CH1_FF_TX_D_5)
X(CH0_FF_TX_D_6)
X(CH1_FF_TX_D_6)
X(CH0_FF_TX_D_7)
X(CH1_FF_TX_D_7)
X(CH0_FF_TX_D_8)
X(CH1_FF_TX_D_8)
X(CH0_FF_TX_D_9)
X(CH1_FF_TX_D_9)
X(CH0_FF_TX_D_10)
X(CH1_FF_TX_D_10)
X(CH0_FF_TX_D_11)
X(CH1_FF_TX_D_11)
X(CH0_FF_TX_D_12)
X(CH1_FF_TX_D_12)
X(CH0_FF_TX_D_13)
X(CH1_FF_TX_D_13)
X(CH0_FF_TX_D_14)
X(CH1_FF_TX_D_14)
X(CH0_FF_TX_D_15)
X(CH1_FF_TX_D_15)
X(CH0_FF_TX_D_16)
X(CH1_FF_TX_D_16)
X(CH0_FF_TX_D_17)
X(CH1_FF_TX_D_17)
X(CH0_FF_TX_D_18)
X(CH1_FF_TX_D_18)
X(CH0_FF_TX_D_19)
X(CH1_FF_TX_D_19)
X(CH0_FF_TX_D_20)
X(CH1_FF_TX_D_20)
X(CH0_FF_TX_D_21)
X(CH1_FF_TX_D_21)
X(CH0_FF_TX_D_22)
X(CH1_FF_TX_D_22)
X(CH0_FF_TX_D_23)
X(CH1_FF_TX_D_23)
X(CH0_FFC_EI_EN)
X(CH1_FFC_EI_EN)
X(CH0_FFC_PCIE_DET_EN)
X(CH1_FFC_PCIE_DET_EN)
X(CH0_FFC_PCIE_CT)
X(CH1_FFC_PCIE_CT)
X(CH0_FFC_SB_INV_RX)
X(CH1_FFC_SB_INV_RX)
X(CH0_FFC_ENABLE_CGALIGN)
X(CH1_FFC_ENABLE_CGALIGN)
X(CH0_FFC_SIGNAL_DETECT)
X(CH1_FFC_SIGNAL_DETECT)
X(CH0_FFC_FB_LOOPBACK)
X(CH1_FFC_FB_LOOPBACK)
X(CH0_FFC_SB_PFIFO_LP)
X(CH1_FFC_SB_PFIFO_LP)
X(CH0_FFC_PFIFO_CLR)
X(CH1_FFC_PFIFO_CLR)
X(CH0_FFC_RATE_MODE_RX)
X(CH1_FFC_RATE_MODE_RX)
X(CH0_FFC_RATE_MODE_TX)
X(CH1_FFC_RATE_MODE_TX)
X(CH0_FFC_DIV11_MODE_RX)
X(CH1_FFC_DIV11_MODE_RX)
X(CH0_FFC_RX_GEAR_MODE)
X(CH1_FFC_RX_GEAR_MODE)
X(CH0_FFC_TX_GEAR_MODE)
X(CH1_FFC_TX_GEAR_MODE)
X(CH0_FFC_DIV11_MODE_TX)
X(CH1_FFC_DIV11_MODE_TX)
X(CH0_FFC_LDR_CORE2TX_EN)
X(CH1_FFC_LDR_CORE2TX_EN)
X(CH0_FFC_LANE_TX_RST)
X(CH1_FFC_LANE_TX_RST)
X(CH0_FFC_LANE_RX_RST)
X(CH1_FFC_LANE_RX_RST)
X(CH0_FFC_RRST)
X(CH1_FFC_RRST)
X(CH0_FFC_TXPWDNB)
X(CH1_FFC_TXPWDNB)
X(CH0_FFC_RXPWDNB)
X(CH1_FFC_RXPWDNB)
X(CH0_LDR_CORE2TX)
X(CH1_LDR_CORE2TX)
X(D_SCIWDATA0)
X(D_SCIWDATA1)
X(D_SCIWDATA2)
X(D_SCIWDATA3)
X(D_SCIWDATA4)
X(D_SCIWDATA5)
X(D_SCIWDATA6)
X(D_SCIWDATA7)
X(D_SCIADDR0)
X(D_SCIADDR1)
X(D_SCIADDR2)
X(D_SCIADDR3)
X(D_SCIADDR4)
X(D_SCIADDR5)
X(D_SCIENAUX)
X(D_SCISELAUX)
X(CH0_SCIEN)
X(CH1_SCIEN)
X(CH0_SCISEL)
X(CH1_SCISEL)
X(D_SCIRD)
X(D_SCIWSTN)
X(D_CYAWSTN)
X(D_FFC_SYNC_TOGGLE)
X(D_FFC_DUAL_RST)
X(D_FFC_MACRO_RST)
X(D_FFC_MACROPDB)
X(D_FFC_TRST)
X(CH0_FFC_CDR_EN_BITSLIP)
X(CH1_FFC_CDR_EN_BITSLIP)
X(D_SCAN_ENABLE)
X(D_SCAN_IN_0)
X(D_SCAN_IN_1)
X(D_SCAN_IN_2)
X(D_SCAN_IN_3)
X(D_SCAN_IN_4)
X(D_SCAN_IN_5)
X(D_SCAN_IN_6)
X(D_SCAN_IN_7)
X(D_SCAN_MODE)
X(D_SCAN_RESET)
X(D_CIN0)
X(D_CIN1)
X(D_CIN2)
X(D_CIN3)
X(D_CIN4)
X(D_CIN5)
X(D_CIN6)
X(D_CIN7)
X(D_CIN8)
X(D_CIN9)
X(D_CIN10)
X(D_CIN11)
X(CH0_HDOUTP)
X(CH1_HDOUTP)
X(CH0_HDOUTN)
X(CH1_HDOUTN)
X(D_TXBIT_CLKP_TO_ND)
X(D_TXBIT_CLKN_TO_ND)
X(D_SYNC_PULSE2ND)
X(D_TXPLL_LOL_TO_ND)
X(CH0_FF_RX_F_CLK)
X(CH1_FF_RX_F_CLK)
X(CH0_FF_RX_H_CLK)
X(CH1_FF_RX_H_CLK)
X(CH0_FF_TX_F_CLK)
X(CH1_FF_TX_F_CLK)
X(CH0_FF_TX_H_CLK)
X(CH1_FF_TX_H_CLK)
X(CH0_FF_RX_PCLK)
X(CH1_FF_RX_PCLK)
X(CH0_FF_TX_PCLK)
X(CH1_FF_TX_PCLK)
X(CH0_FF_RX_D_0)
X(CH1_FF_RX_D_0)
X(CH0_FF_RX_D_1)
X(CH1_FF_RX_D_1)
X(CH0_FF_RX_D_2)
X(CH1_FF_RX_D_2)
X(CH0_FF_RX_D_3)
X(CH1_FF_RX_D_3)
X(CH0_FF_RX_D_4)
X(CH1_FF_RX_D_4)
X(CH0_FF_RX_D_5)
X(CH1_FF_RX_D_5)
X(CH0_FF_RX_D_6)
X(CH1_FF_RX_D_6)
X(CH0_FF_RX_D_7)
X(CH1_FF_RX_D_7)
X(CH0_FF_RX_D_8)
X(CH1_FF_RX_D_8)
X(CH0_FF_RX_D_9)
X(CH1_FF_RX_D_9)
X(CH0_FF_RX_D_10)
X(CH1_FF_RX_D_10)
X(CH0_FF_RX_D_11)
X(CH1_FF_RX_D_11)
X(CH0_FF_RX_D_12)
X(CH1_FF_RX_D_12)
X(CH0_FF_RX_D_13)
X(CH1_FF_RX_D_13)
X(CH0_FF_RX_D_14)
X(CH1_FF_RX_D_14)
X(CH0_FF_RX_D_15)
X(CH1_FF_RX_D_15)
X(CH0_FF_RX_D_16)
X(CH1_FF_RX_D_16)
X(CH0_FF_RX_D_17)
X(CH1_FF_RX_D_17)
X(CH0_FF_RX_D_18)
X(CH1_FF_RX_D_18)
X(CH0_FF_RX_D_19)
X(CH1_FF_RX_D_19)
X(CH0_FF_RX_D_20)
X(CH1_FF_RX_D_20)
X(CH0_FF_RX_D_21)
X(CH1_FF_RX_D_21)
X(CH0_FF_RX_D_22)
X(CH1_FF_RX_D_22)
X(CH0_FF_RX_D_23)
X(CH1_FF_RX_D_23)
X(CH0_FFS_PCIE_DONE)
X(CH1_FFS_PCIE_DONE)
X(CH0_FFS_PCIE_CON)
X(CH1_FFS_PCIE_CON)
X(CH0_FFS_RLOS)
X(CH1_FFS_RLOS)
X(CH0_FFS_LS_SYNC_STATUS)
X(CH1_FFS_LS_SYNC_STATUS)
X(CH0_FFS_CC_UNDERRUN)
X(CH1_FFS_CC_UNDERRUN)
X(CH0_FFS_CC_OVERRUN)
X(CH1_FFS_CC_OVERRUN)
X(CH0_FFS_RXFBFIFO_ERROR)
X(CH1_FFS_RXFBFIFO_ERROR)
X(CH0_FFS_TXFBFIFO_ERROR)
X(CH1_FFS_TXFBFIFO_ERROR)
X(CH0_FFS_RLOL)
X(CH1_FFS_RLOL)
X(CH0_FFS_SKP_ADDED)
X(CH1_FFS_SKP_ADDED)
X(CH0_FFS_SKP_DELETED)
X(CH1_FFS_SKP_DELETED)
X(CH0_LDR_RX2CORE)
X(CH1_LDR_RX2CORE)
X(D_SCIRDATA0)
X(D_SCIRDATA1)
X(D_SCIRDATA2)
X(D_SCIRDATA3)
X(D_SCIRDATA4)
X(D_SCIRDATA5)
X(D_SCIRDATA6)
X(D_SCIRDATA7)
X(D_SCIINT)
X(D_SCAN_OUT_0)
X(D_SCAN_OUT_1)
X(D_SCAN_OUT_2)
X(D_SCAN_OUT_3)
X(D_SCAN_OUT_4)
X(D_SCAN_OUT_5)
X(D_SCAN_OUT_6)
X(D_SCAN_OUT_7)
X(D_COUT0)
X(D_COUT1)
X(D_COUT2)
X(D_COUT3)
X(D_COUT4)
X(D_COUT5)
X(D_COUT6)
X(D_COUT7)
X(D_COUT8)
X(D_COUT9)
X(D_COUT10)
X(D_COUT11)
X(D_COUT12)
X(D_COUT13)
X(D_COUT14)
X(D_COUT15)
X(D_COUT16)
X(D_COUT17)
X(D_COUT18)
X(D_COUT19)
X(D_REFCLKI)
X(D_FFS_PLOL)
X(PCSCLKDIV)
X(SEL2)
X(SEL1)
X(SEL0)
X(CDIV1)
X(CDIVX)

254
ecp5/dcu_bitstream.h Normal file
View File

@ -0,0 +1,254 @@
tg.config.add_word("DCU.CH0_AUTO_CALIB_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_AUTO_CALIB_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_AUTO_FACQ_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_AUTO_FACQ_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_BAND_THRESHOLD", parse_config_str(str_or_default(ci->params, ctx->id("CH0_BAND_THRESHOLD"), "0"), 6));
tg.config.add_word("DCU.CH0_CALIB_CK_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CALIB_CK_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_CC_MATCH_1", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CC_MATCH_1"), "0"), 10));
tg.config.add_word("DCU.CH0_CC_MATCH_2", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CC_MATCH_2"), "0"), 10));
tg.config.add_word("DCU.CH0_CC_MATCH_3", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CC_MATCH_3"), "0"), 10));
tg.config.add_word("DCU.CH0_CC_MATCH_4", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CC_MATCH_4"), "0"), 10));
tg.config.add_word("DCU.CH0_CDR_CNT4SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CDR_CNT4SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_CDR_CNT8SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CDR_CNT8SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_CTC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_CTC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_DCOATDCFG", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOATDCFG"), "0"), 2));
tg.config.add_word("DCU.CH0_DCOATDDLY", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOATDDLY"), "0"), 2));
tg.config.add_word("DCU.CH0_DCOBYPSATD", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOBYPSATD"), "0"), 1));
tg.config.add_word("DCU.CH0_DCOCALDIV", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOCALDIV"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOCTLGI", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOCTLGI"), "0"), 3));
tg.config.add_word("DCU.CH0_DCODISBDAVOID", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCODISBDAVOID"), "0"), 1));
tg.config.add_word("DCU.CH0_DCOFLTDAC", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOFLTDAC"), "0"), 2));
tg.config.add_word("DCU.CH0_DCOFTNRG", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOFTNRG"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOIOSTUNE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOIOSTUNE"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOITUNE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOITUNE"), "0"), 2));
tg.config.add_word("DCU.CH0_DCOITUNE4LSB", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOITUNE4LSB"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOIUPDNX2", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOIUPDNX2"), "0"), 1));
tg.config.add_word("DCU.CH0_DCONUOFLSB", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCONUOFLSB"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOSCALEI", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOSCALEI"), "0"), 2));
tg.config.add_word("DCU.CH0_DCOSTARTVAL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOSTARTVAL"), "0"), 3));
tg.config.add_word("DCU.CH0_DCOSTEP", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DCOSTEP"), "0"), 2));
tg.config.add_word("DCU.CH0_DEC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_DEC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_ENABLE_CG_ALIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_ENABLE_CG_ALIGN"), "0"), 1));
tg.config.add_word("DCU.CH0_ENC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_ENC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_FF_RX_F_CLK_DIS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_FF_RX_F_CLK_DIS"), "0"), 1));
tg.config.add_word("DCU.CH0_FF_RX_H_CLK_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_FF_RX_H_CLK_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_FF_TX_F_CLK_DIS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_FF_TX_F_CLK_DIS"), "0"), 1));
tg.config.add_word("DCU.CH0_FF_TX_H_CLK_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_FF_TX_H_CLK_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_GE_AN_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_GE_AN_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH0_INVERT_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_INVERT_RX"), "0"), 1));
tg.config.add_word("DCU.CH0_INVERT_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_INVERT_TX"), "0"), 1));
tg.config.add_word("DCU.CH0_LDR_CORE2TX_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_LDR_CORE2TX_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_LDR_RX2CORE_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_LDR_RX2CORE_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_LEQ_OFFSET_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_LEQ_OFFSET_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_LEQ_OFFSET_TRIM", parse_config_str(str_or_default(ci->params, ctx->id("CH0_LEQ_OFFSET_TRIM"), "0"), 3));
tg.config.add_word("DCU.CH0_LSM_DISABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_LSM_DISABLE"), "0"), 1));
tg.config.add_word("DCU.CH0_MATCH_2_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_MATCH_2_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH0_MATCH_4_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_MATCH_4_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH0_MIN_IPG_CNT", parse_config_str(str_or_default(ci->params, ctx->id("CH0_MIN_IPG_CNT"), "0"), 2));
tg.config.add_word("DCU.CH0_PCIE_EI_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PCIE_EI_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_PCIE_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PCIE_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_PCS_DET_TIME_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PCS_DET_TIME_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_PDEN_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PDEN_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_PRBS_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PRBS_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH0_PRBS_LOCK", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PRBS_LOCK"), "0"), 1));
tg.config.add_word("DCU.CH0_PRBS_SELECTION", parse_config_str(str_or_default(ci->params, ctx->id("CH0_PRBS_SELECTION"), "0"), 1));
tg.config.add_word("DCU.CH0_RATE_MODE_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RATE_MODE_RX"), "0"), 1));
tg.config.add_word("DCU.CH0_RATE_MODE_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RATE_MODE_TX"), "0"), 1));
tg.config.add_word("DCU.CH0_RCV_DCC_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RCV_DCC_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_REG_BAND_OFFSET", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REG_BAND_OFFSET"), "0"), 4));
tg.config.add_word("DCU.CH0_REG_BAND_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REG_BAND_SEL"), "0"), 6));
tg.config.add_word("DCU.CH0_REG_IDAC_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REG_IDAC_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_REG_IDAC_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REG_IDAC_SEL"), "0"), 10));
tg.config.add_word("DCU.CH0_REQ_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REQ_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_REQ_LVL_SET", parse_config_str(str_or_default(ci->params, ctx->id("CH0_REQ_LVL_SET"), "0"), 2));
tg.config.add_word("DCU.CH0_RIO_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RIO_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_RLOS_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RLOS_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_RPWDNB", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RPWDNB"), "0"), 1));
tg.config.add_word("DCU.CH0_RTERM_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RTERM_RX"), "0"), 5));
tg.config.add_word("DCU.CH0_RTERM_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RTERM_TX"), "0"), 5));
tg.config.add_word("DCU.CH0_RXIN_CM", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RXIN_CM"), "0"), 2));
tg.config.add_word("DCU.CH0_RXTERM_CM", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RXTERM_CM"), "0"), 2));
tg.config.add_word("DCU.CH0_RX_DCO_CK_DIV", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_DCO_CK_DIV"), "0"), 3));
tg.config.add_word("DCU.CH0_RX_DIV11_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_DIV11_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_RX_GEAR_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_GEAR_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_RX_GEAR_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_GEAR_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_RX_LOS_CEQ", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_LOS_CEQ"), "0"), 2));
tg.config.add_word("DCU.CH0_RX_LOS_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_LOS_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_RX_LOS_HYST_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_LOS_HYST_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_RX_LOS_LVL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_LOS_LVL"), "0"), 3));
tg.config.add_word("DCU.CH0_RX_RATE_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_RATE_SEL"), "0"), 4));
tg.config.add_word("DCU.CH0_RX_SB_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_RX_SB_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_SB_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_SB_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_SEL_SD_RX_CLK", parse_config_str(str_or_default(ci->params, ctx->id("CH0_SEL_SD_RX_CLK"), "0"), 1));
tg.config.add_word("DCU.CH0_TDRV_DAT_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_DAT_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_POST_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_POST_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_TDRV_PRE_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_PRE_EN"), "0"), 1));
tg.config.add_word("DCU.CH0_TDRV_SLICE0_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE0_CUR"), "0"), 3));
tg.config.add_word("DCU.CH0_TDRV_SLICE0_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE0_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE1_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE1_CUR"), "0"), 3));
tg.config.add_word("DCU.CH0_TDRV_SLICE1_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE1_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE2_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE2_CUR"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE2_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE2_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE3_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE3_CUR"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE3_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE3_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE4_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE4_CUR"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE4_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE4_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE5_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE5_CUR"), "0"), 2));
tg.config.add_word("DCU.CH0_TDRV_SLICE5_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TDRV_SLICE5_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TPWDNB", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TPWDNB"), "0"), 1));
tg.config.add_word("DCU.CH0_TX_CM_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_CM_SEL"), "0"), 2));
tg.config.add_word("DCU.CH0_TX_DIV11_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_DIV11_SEL"), "0"), 1));
tg.config.add_word("DCU.CH0_TX_GEAR_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_GEAR_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_TX_GEAR_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_GEAR_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_TX_POST_SIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_POST_SIGN"), "0"), 1));
tg.config.add_word("DCU.CH0_TX_PRE_SIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH0_TX_PRE_SIGN"), "0"), 1));
tg.config.add_word("DCU.CH0_UC_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_UC_MODE"), "0"), 1));
tg.config.add_word("DCU.CH0_UDF_COMMA_A", parse_config_str(str_or_default(ci->params, ctx->id("CH0_UDF_COMMA_A"), "0"), 10));
tg.config.add_word("DCU.CH0_UDF_COMMA_B", parse_config_str(str_or_default(ci->params, ctx->id("CH0_UDF_COMMA_B"), "0"), 10));
tg.config.add_word("DCU.CH0_UDF_COMMA_MASK", parse_config_str(str_or_default(ci->params, ctx->id("CH0_UDF_COMMA_MASK"), "0"), 10));
tg.config.add_word("DCU.CH0_WA_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH0_WA_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH0_WA_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH0_WA_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_AUTO_CALIB_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_AUTO_CALIB_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_AUTO_FACQ_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_AUTO_FACQ_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_BAND_THRESHOLD", parse_config_str(str_or_default(ci->params, ctx->id("CH1_BAND_THRESHOLD"), "0"), 6));
tg.config.add_word("DCU.CH1_CALIB_CK_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CALIB_CK_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_CC_MATCH_1", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CC_MATCH_1"), "0"), 10));
tg.config.add_word("DCU.CH1_CC_MATCH_2", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CC_MATCH_2"), "0"), 10));
tg.config.add_word("DCU.CH1_CC_MATCH_3", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CC_MATCH_3"), "0"), 10));
tg.config.add_word("DCU.CH1_CC_MATCH_4", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CC_MATCH_4"), "0"), 10));
tg.config.add_word("DCU.CH1_CDR_CNT4SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CDR_CNT4SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_CDR_CNT8SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CDR_CNT8SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_CTC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_CTC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_DCOATDCFG", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOATDCFG"), "0"), 2));
tg.config.add_word("DCU.CH1_DCOATDDLY", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOATDDLY"), "0"), 2));
tg.config.add_word("DCU.CH1_DCOBYPSATD", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOBYPSATD"), "0"), 1));
tg.config.add_word("DCU.CH1_DCOCALDIV", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOCALDIV"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOCTLGI", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOCTLGI"), "0"), 3));
tg.config.add_word("DCU.CH1_DCODISBDAVOID", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCODISBDAVOID"), "0"), 1));
tg.config.add_word("DCU.CH1_DCOFLTDAC", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOFLTDAC"), "0"), 2));
tg.config.add_word("DCU.CH1_DCOFTNRG", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOFTNRG"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOIOSTUNE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOIOSTUNE"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOITUNE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOITUNE"), "0"), 2));
tg.config.add_word("DCU.CH1_DCOITUNE4LSB", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOITUNE4LSB"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOIUPDNX2", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOIUPDNX2"), "0"), 1));
tg.config.add_word("DCU.CH1_DCONUOFLSB", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCONUOFLSB"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOSCALEI", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOSCALEI"), "0"), 2));
tg.config.add_word("DCU.CH1_DCOSTARTVAL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOSTARTVAL"), "0"), 3));
tg.config.add_word("DCU.CH1_DCOSTEP", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DCOSTEP"), "0"), 2));
tg.config.add_word("DCU.CH1_DEC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_DEC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_ENABLE_CG_ALIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_ENABLE_CG_ALIGN"), "0"), 1));
tg.config.add_word("DCU.CH1_ENC_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_ENC_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_FF_RX_F_CLK_DIS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_FF_RX_F_CLK_DIS"), "0"), 1));
tg.config.add_word("DCU.CH1_FF_RX_H_CLK_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_FF_RX_H_CLK_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_FF_TX_F_CLK_DIS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_FF_TX_F_CLK_DIS"), "0"), 1));
tg.config.add_word("DCU.CH1_FF_TX_H_CLK_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_FF_TX_H_CLK_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_GE_AN_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_GE_AN_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH1_INVERT_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_INVERT_RX"), "0"), 1));
tg.config.add_word("DCU.CH1_INVERT_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_INVERT_TX"), "0"), 1));
tg.config.add_word("DCU.CH1_LDR_CORE2TX_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_LDR_CORE2TX_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_LDR_RX2CORE_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_LDR_RX2CORE_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_LEQ_OFFSET_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_LEQ_OFFSET_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_LEQ_OFFSET_TRIM", parse_config_str(str_or_default(ci->params, ctx->id("CH1_LEQ_OFFSET_TRIM"), "0"), 3));
tg.config.add_word("DCU.CH1_LSM_DISABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_LSM_DISABLE"), "0"), 1));
tg.config.add_word("DCU.CH1_MATCH_2_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_MATCH_2_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH1_MATCH_4_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_MATCH_4_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH1_MIN_IPG_CNT", parse_config_str(str_or_default(ci->params, ctx->id("CH1_MIN_IPG_CNT"), "0"), 2));
tg.config.add_word("DCU.CH1_PCIE_EI_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PCIE_EI_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_PCIE_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PCIE_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_PCS_DET_TIME_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PCS_DET_TIME_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_PDEN_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PDEN_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_PRBS_ENABLE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PRBS_ENABLE"), "0"), 1));
tg.config.add_word("DCU.CH1_PRBS_LOCK", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PRBS_LOCK"), "0"), 1));
tg.config.add_word("DCU.CH1_PRBS_SELECTION", parse_config_str(str_or_default(ci->params, ctx->id("CH1_PRBS_SELECTION"), "0"), 1));
tg.config.add_word("DCU.CH1_RATE_MODE_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RATE_MODE_RX"), "0"), 1));
tg.config.add_word("DCU.CH1_RATE_MODE_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RATE_MODE_TX"), "0"), 1));
tg.config.add_word("DCU.CH1_RCV_DCC_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RCV_DCC_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_REG_BAND_OFFSET", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REG_BAND_OFFSET"), "0"), 4));
tg.config.add_word("DCU.CH1_REG_BAND_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REG_BAND_SEL"), "0"), 6));
tg.config.add_word("DCU.CH1_REG_IDAC_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REG_IDAC_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_REG_IDAC_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REG_IDAC_SEL"), "0"), 10));
tg.config.add_word("DCU.CH1_REQ_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REQ_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_REQ_LVL_SET", parse_config_str(str_or_default(ci->params, ctx->id("CH1_REQ_LVL_SET"), "0"), 2));
tg.config.add_word("DCU.CH1_RIO_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RIO_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_RLOS_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RLOS_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_RPWDNB", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RPWDNB"), "0"), 1));
tg.config.add_word("DCU.CH1_RTERM_RX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RTERM_RX"), "0"), 5));
tg.config.add_word("DCU.CH1_RTERM_TX", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RTERM_TX"), "0"), 5));
tg.config.add_word("DCU.CH1_RXIN_CM", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RXIN_CM"), "0"), 2));
tg.config.add_word("DCU.CH1_RXTERM_CM", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RXTERM_CM"), "0"), 2));
tg.config.add_word("DCU.CH1_RX_DCO_CK_DIV", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_DCO_CK_DIV"), "0"), 3));
tg.config.add_word("DCU.CH1_RX_DIV11_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_DIV11_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_RX_GEAR_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_GEAR_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_RX_GEAR_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_GEAR_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_RX_LOS_CEQ", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_LOS_CEQ"), "0"), 2));
tg.config.add_word("DCU.CH1_RX_LOS_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_LOS_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_RX_LOS_HYST_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_LOS_HYST_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_RX_LOS_LVL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_LOS_LVL"), "0"), 3));
tg.config.add_word("DCU.CH1_RX_RATE_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_RATE_SEL"), "0"), 4));
tg.config.add_word("DCU.CH1_RX_SB_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_RX_SB_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_SB_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_SB_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_SEL_SD_RX_CLK", parse_config_str(str_or_default(ci->params, ctx->id("CH1_SEL_SD_RX_CLK"), "0"), 1));
tg.config.add_word("DCU.CH1_TDRV_DAT_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_DAT_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_POST_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_POST_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_TDRV_PRE_EN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_PRE_EN"), "0"), 1));
tg.config.add_word("DCU.CH1_TDRV_SLICE0_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE0_CUR"), "0"), 3));
tg.config.add_word("DCU.CH1_TDRV_SLICE0_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE0_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE1_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE1_CUR"), "0"), 3));
tg.config.add_word("DCU.CH1_TDRV_SLICE1_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE1_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE2_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE2_CUR"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE2_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE2_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE3_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE3_CUR"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE3_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE3_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE4_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE4_CUR"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE4_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE4_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE5_CUR", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE5_CUR"), "0"), 2));
tg.config.add_word("DCU.CH1_TDRV_SLICE5_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TDRV_SLICE5_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TPWDNB", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TPWDNB"), "0"), 1));
tg.config.add_word("DCU.CH1_TX_CM_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_CM_SEL"), "0"), 2));
tg.config.add_word("DCU.CH1_TX_DIV11_SEL", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_DIV11_SEL"), "0"), 1));
tg.config.add_word("DCU.CH1_TX_GEAR_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_GEAR_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_TX_GEAR_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_GEAR_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_TX_POST_SIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_POST_SIGN"), "0"), 1));
tg.config.add_word("DCU.CH1_TX_PRE_SIGN", parse_config_str(str_or_default(ci->params, ctx->id("CH1_TX_PRE_SIGN"), "0"), 1));
tg.config.add_word("DCU.CH1_UC_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_UC_MODE"), "0"), 1));
tg.config.add_word("DCU.CH1_UDF_COMMA_A", parse_config_str(str_or_default(ci->params, ctx->id("CH1_UDF_COMMA_A"), "0"), 10));
tg.config.add_word("DCU.CH1_UDF_COMMA_B", parse_config_str(str_or_default(ci->params, ctx->id("CH1_UDF_COMMA_B"), "0"), 10));
tg.config.add_word("DCU.CH1_UDF_COMMA_MASK", parse_config_str(str_or_default(ci->params, ctx->id("CH1_UDF_COMMA_MASK"), "0"), 10));
tg.config.add_word("DCU.CH1_WA_BYPASS", parse_config_str(str_or_default(ci->params, ctx->id("CH1_WA_BYPASS"), "0"), 1));
tg.config.add_word("DCU.CH1_WA_MODE", parse_config_str(str_or_default(ci->params, ctx->id("CH1_WA_MODE"), "0"), 1));
tg.config.add_word("DCU.D_BITCLK_FROM_ND_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_BITCLK_FROM_ND_EN"), "0"), 1));
tg.config.add_word("DCU.D_BITCLK_LOCAL_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_BITCLK_LOCAL_EN"), "0"), 1));
tg.config.add_word("DCU.D_BITCLK_ND_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_BITCLK_ND_EN"), "0"), 1));
tg.config.add_word("DCU.D_BUS8BIT_SEL", parse_config_str(str_or_default(ci->params, ctx->id("D_BUS8BIT_SEL"), "0"), 1));
tg.config.add_word("DCU.D_CDR_LOL_SET", parse_config_str(str_or_default(ci->params, ctx->id("D_CDR_LOL_SET"), "0"), 2));
tg.config.add_word("DCU.D_CMUSETBIASI", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETBIASI"), "0"), 2));
tg.config.add_word("DCU.D_CMUSETI4CPP", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETI4CPP"), "0"), 4));
tg.config.add_word("DCU.D_CMUSETI4CPZ", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETI4CPZ"), "0"), 4));
tg.config.add_word("DCU.D_CMUSETI4VCO", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETI4VCO"), "0"), 2));
tg.config.add_word("DCU.D_CMUSETICP4P", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETICP4P"), "0"), 2));
tg.config.add_word("DCU.D_CMUSETICP4Z", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETICP4Z"), "0"), 3));
tg.config.add_word("DCU.D_CMUSETINITVCT", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETINITVCT"), "0"), 2));
tg.config.add_word("DCU.D_CMUSETISCL4VCO", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETISCL4VCO"), "0"), 3));
tg.config.add_word("DCU.D_CMUSETP1GM", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETP1GM"), "0"), 3));
tg.config.add_word("DCU.D_CMUSETP2AGM", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETP2AGM"), "0"), 3));
tg.config.add_word("DCU.D_CMUSETZGM", parse_config_str(str_or_default(ci->params, ctx->id("D_CMUSETZGM"), "0"), 3));
tg.config.add_word("DCU.D_DCO_CALIB_TIME_SEL", parse_config_str(str_or_default(ci->params, ctx->id("D_DCO_CALIB_TIME_SEL"), "0"), 2));
tg.config.add_word("DCU.D_HIGH_MARK", parse_config_str(str_or_default(ci->params, ctx->id("D_HIGH_MARK"), "0"), 4));
tg.config.add_word("DCU.D_IB_PWDNB", parse_config_str(str_or_default(ci->params, ctx->id("D_IB_PWDNB"), "0"), 1));
tg.config.add_word("DCU.D_ISETLOS", parse_config_str(str_or_default(ci->params, ctx->id("D_ISETLOS"), "0"), 8));
tg.config.add_word("DCU.D_LOW_MARK", parse_config_str(str_or_default(ci->params, ctx->id("D_LOW_MARK"), "0"), 4));
tg.config.add_word("DCU.D_MACROPDB", parse_config_str(str_or_default(ci->params, ctx->id("D_MACROPDB"), "0"), 1));
tg.config.add_word("DCU.D_PD_ISET", parse_config_str(str_or_default(ci->params, ctx->id("D_PD_ISET"), "0"), 2));
tg.config.add_word("DCU.D_PLL_LOL_SET", parse_config_str(str_or_default(ci->params, ctx->id("D_PLL_LOL_SET"), "0"), 2));
tg.config.add_word("DCU.D_REFCK_MODE", parse_config_str(str_or_default(ci->params, ctx->id("D_REFCK_MODE"), "0"), 3));
tg.config.add_word("DCU.D_REQ_ISET", parse_config_str(str_or_default(ci->params, ctx->id("D_REQ_ISET"), "0"), 3));
tg.config.add_word("DCU.D_RG_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_RG_EN"), "0"), 1));
tg.config.add_word("DCU.D_RG_SET", parse_config_str(str_or_default(ci->params, ctx->id("D_RG_SET"), "0"), 2));
tg.config.add_word("DCU.D_SETICONST_AUX", parse_config_str(str_or_default(ci->params, ctx->id("D_SETICONST_AUX"), "0"), 2));
tg.config.add_word("DCU.D_SETICONST_CH", parse_config_str(str_or_default(ci->params, ctx->id("D_SETICONST_CH"), "0"), 2));
tg.config.add_word("DCU.D_SETIRPOLY_AUX", parse_config_str(str_or_default(ci->params, ctx->id("D_SETIRPOLY_AUX"), "0"), 2));
tg.config.add_word("DCU.D_SETIRPOLY_CH", parse_config_str(str_or_default(ci->params, ctx->id("D_SETIRPOLY_CH"), "0"), 2));
tg.config.add_word("DCU.D_SETPLLRC", parse_config_str(str_or_default(ci->params, ctx->id("D_SETPLLRC"), "0"), 6));
tg.config.add_word("DCU.D_SYNC_LOCAL_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_SYNC_LOCAL_EN"), "0"), 1));
tg.config.add_word("DCU.D_SYNC_ND_EN", parse_config_str(str_or_default(ci->params, ctx->id("D_SYNC_ND_EN"), "0"), 1));
tg.config.add_word("DCU.D_TXPLL_PWDNB", parse_config_str(str_or_default(ci->params, ctx->id("D_TXPLL_PWDNB"), "0"), 1));
tg.config.add_word("DCU.D_TX_VCO_CK_DIV", parse_config_str(str_or_default(ci->params, ctx->id("D_TX_VCO_CK_DIV"), "0"), 3));
tg.config.add_word("DCU.D_XGE_MODE", parse_config_str(str_or_default(ci->params, ctx->id("D_XGE_MODE"), "0"), 1));

View File

@ -55,6 +55,9 @@ class Ecp5GlobalRouter
{ {
if (user.cell->type == id_TRELLIS_SLICE && (user.port == id_CLK || user.port == id_WCK)) if (user.cell->type == id_TRELLIS_SLICE && (user.port == id_CLK || user.port == id_WCK))
return true; return true;
if (user.cell->type == id_DCUA && (user.port == id_CH0_FF_RXI_CLK || user.port == id_CH1_FF_RXI_CLK ||
user.port == id_CH0_FF_TXI_CLK || user.port == id_CH1_FF_TXI_CLK))
return true;
return false; return false;
} }
@ -65,8 +68,11 @@ class Ecp5GlobalRouter
NetInfo *ni = net.second.get(); NetInfo *ni = net.second.get();
clockCount[ni->name] = 0; clockCount[ni->name] = 0;
for (const auto &user : ni->users) { for (const auto &user : ni->users) {
if (is_clock_port(user)) if (is_clock_port(user)) {
clockCount[ni->name]++; clockCount[ni->name]++;
if (user.cell->type == id_DCUA)
clockCount[ni->name] += 100;
}
} }
// log_info("clkcount %s: %d\n", ni->name.c_str(ctx),clockCount[ni->name]); // log_info("clkcount %s: %d\n", ni->name.c_str(ctx),clockCount[ni->name]);
} }
@ -290,6 +296,10 @@ class Ecp5GlobalRouter
float tns; float tns;
return get_net_metric(ctx, clki, MetricType::WIRELENGTH, tns); return get_net_metric(ctx, clki, MetricType::WIRELENGTH, tns);
} else { } else {
// Check for dedicated routing
if (has_short_route(ctx->getBelPinWire(drv_bel, drv.port), ctx->getBelPinWire(dcc->bel, id_CLKI))) {
return 0;
}
// Driver is locked // Driver is locked
Loc dcc_loc = ctx->getBelLocation(dcc->bel); Loc dcc_loc = ctx->getBelLocation(dcc->bel);
Loc drv_loc = ctx->getBelLocation(drv_bel); Loc drv_loc = ctx->getBelLocation(drv_bel);
@ -297,6 +307,46 @@ class Ecp5GlobalRouter
} }
} }
// Return true if a short (<5) route exists between two wires
bool has_short_route(WireId src, WireId dst, int thresh = 5)
{
std::queue<WireId> visit;
std::unordered_map<WireId, PipId> backtrace;
visit.push(src);
WireId cursor;
while (true) {
if (visit.empty() || visit.size() > 1000) {
// log_info ("dist %s -> %s = inf\n", ctx->getWireName(src).c_str(ctx),
// ctx->getWireName(dst).c_str(ctx));
return false;
}
cursor = visit.front();
visit.pop();
if (cursor == dst)
break;
for (auto dh : ctx->getPipsDownhill(cursor)) {
WireId pipDst = ctx->getPipDstWire(dh);
if (backtrace.count(pipDst))
continue;
backtrace[pipDst] = dh;
visit.push(pipDst);
}
}
int length = 0;
while (true) {
auto fnd = backtrace.find(cursor);
if (fnd == backtrace.end())
break;
cursor = ctx->getPipSrcWire(fnd->second);
length++;
}
// log_info ("dist %s -> %s = %d\n", ctx->getWireName(src).c_str(ctx), ctx->getWireName(dst).c_str(ctx),
// length);
return length < thresh;
}
// Attempt to place a DCC // Attempt to place a DCC
void place_dcc(CellInfo *dcc) void place_dcc(CellInfo *dcc)
{ {
@ -335,6 +385,8 @@ class Ecp5GlobalRouter
for (auto user : net->users) { for (auto user : net->users) {
if (user.port == id_CLKFB) { if (user.port == id_CLKFB) {
keep_users.push_back(user); keep_users.push_back(user);
} else if (net->driver.cell->type == id_EXTREFB && user.cell->type == id_DCUA) {
keep_users.push_back(user);
} else { } else {
glbnet->users.push_back(user); glbnet->users.push_back(user);
user.cell->ports.at(user.port).net = glbnet.get(); user.cell->ports.at(user.port).net = glbnet.get();

View File

@ -235,6 +235,46 @@ class Ecp5Packer
} }
} }
// Return true if an port is a top level port that provides its own IOBUF
bool is_top_port(PortRef &port)
{
if (port.cell == nullptr)
return false;
if (port.cell->type == id_DCUA) {
return port.port == id_CH0_HDINP || port.port == id_CH0_HDINN || port.port == id_CH0_HDOUTP ||
port.port == id_CH0_HDOUTN || port.port == id_CH1_HDINP || port.port == id_CH1_HDINN ||
port.port == id_CH1_HDOUTP || port.port == id_CH1_HDOUTN;
} else if (port.cell->type == id_EXTREFB) {
return port.port == id_REFCLKP || port.port == id_REFCLKN;
} else {
return false;
}
}
// Return true if a net only drives a top port
bool drives_top_port(NetInfo *net, PortRef &tp)
{
if (net == nullptr)
return false;
for (auto user : net->users) {
if (is_top_port(user)) {
if (net->users.size() > 1)
log_error(" port %s.%s must be connected to (and only to) a top level pin\n",
user.cell->name.c_str(ctx), user.port.c_str(ctx));
tp = user;
return true;
}
}
if (net->driver.cell != nullptr && is_top_port(net->driver)) {
if (net->users.size() > 1)
log_error(" port %s.%s must be connected to (and only to) a top level pin\n",
net->driver.cell->name.c_str(ctx), net->driver.port.c_str(ctx));
tp = net->driver;
return true;
}
return false;
}
// Simple "packer" to remove nextpnr IOBUFs, this assumes IOBUFs are manually instantiated // Simple "packer" to remove nextpnr IOBUFs, this assumes IOBUFs are manually instantiated
void pack_io() void pack_io()
{ {
@ -244,10 +284,14 @@ class Ecp5Packer
CellInfo *ci = cell.second; CellInfo *ci = cell.second;
if (is_nextpnr_iob(ctx, ci)) { if (is_nextpnr_iob(ctx, ci)) {
CellInfo *trio = nullptr; CellInfo *trio = nullptr;
NetInfo *ionet = nullptr;
PortRef tp;
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
trio = net_only_drives(ctx, ci->ports.at(ctx->id("O")).net, is_trellis_io, ctx->id("B"), true, ci); ionet = ci->ports.at(ctx->id("O")).net;
trio = net_only_drives(ctx, ionet, is_trellis_io, ctx->id("B"), true, ci);
} else if (ci->type == ctx->id("$nextpnr_obuf")) { } else if (ci->type == ctx->id("$nextpnr_obuf")) {
ionet = ci->ports.at(ctx->id("I")).net;
trio = net_only_drives(ctx, ci->ports.at(ctx->id("I")).net, is_trellis_io, ctx->id("B"), true, ci); trio = net_only_drives(ctx, ci->ports.at(ctx->id("I")).net, is_trellis_io, ctx->id("B"), true, ci);
} }
if (trio != nullptr) { if (trio != nullptr) {
@ -266,6 +310,19 @@ class Ecp5Packer
ctx->nets.erase(net2->name); ctx->nets.erase(net2->name);
} }
} }
} else if (drives_top_port(ionet, tp)) {
log_info("%s feeds %s %s.%s, removing %s %s.\n", ci->name.c_str(ctx), tp.cell->type.c_str(ctx),
tp.cell->name.c_str(ctx), tp.port.c_str(ctx), ci->type.c_str(ctx), ci->name.c_str(ctx));
if (ionet != nullptr) {
ctx->nets.erase(ionet->name);
tp.cell->ports.at(tp.port).net = nullptr;
}
if (ci->type == ctx->id("$nextpnr_iobuf")) {
NetInfo *net2 = ci->ports.at(ctx->id("I")).net;
if (net2 != nullptr) {
ctx->nets.erase(net2->name);
}
}
} else { } else {
// Create a TRELLIS_IO buffer // Create a TRELLIS_IO buffer
std::unique_ptr<CellInfo> tr_cell = std::unique_ptr<CellInfo> tr_cell =
@ -276,6 +333,7 @@ class Ecp5Packer
} }
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
if (trio != nullptr) {
for (const auto &attr : ci->attrs) for (const auto &attr : ci->attrs)
trio->attrs[attr.first] = attr.second; trio->attrs[attr.first] = attr.second;
@ -294,6 +352,7 @@ class Ecp5Packer
} }
} }
} }
}
flush_cells(); flush_cells();
} }
@ -1033,12 +1092,93 @@ class Ecp5Packer
} }
} }
// "Pack" DCUs
void pack_dcus()
{
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_DCUA) {
if (ci->attrs.count(ctx->id("LOC"))) {
std::string loc = ci->attrs.at(ctx->id("LOC"));
if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_25F || ctx->args.type == ArchArgs::LFE5UM5G_25F))
ci->attrs[ctx->id("BEL")] = "X42/Y50/DCU";
else if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F))
ci->attrs[ctx->id("BEL")] = "X42/Y71/DCU";
else if (loc == "DCU1" &&
(ctx->args.type == ArchArgs::LFE5UM_45F || ctx->args.type == ArchArgs::LFE5UM5G_45F))
ci->attrs[ctx->id("BEL")] = "X69/Y71/DCU";
else if (loc == "DCU0" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F))
ci->attrs[ctx->id("BEL")] = "X46/Y95/DCU";
else if (loc == "DCU1" &&
(ctx->args.type == ArchArgs::LFE5UM_85F || ctx->args.type == ArchArgs::LFE5UM5G_85F))
ci->attrs[ctx->id("BEL")] = "X71/Y95/DCU";
else
log_error("no DCU location '%s' in device '%s'\n", loc.c_str(), ctx->getChipName().c_str());
}
if (!ci->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
// Empty port auto-creation to generate correct tie-downs
BelId exemplar_bel;
for (auto bel : ctx->getBels()) {
if (ctx->getBelType(bel) == id_DCUA) {
exemplar_bel = bel;
break;
}
}
NPNR_ASSERT(exemplar_bel != BelId());
for (auto pin : ctx->getBelPins(exemplar_bel))
if (ctx->getBelPinType(exemplar_bel, pin) == PORT_IN)
autocreate_empty_port(ci, pin);
}
}
for (auto cell : sorted(ctx->cells)) {
CellInfo *ci = cell.second;
if (ci->type == id_EXTREFB) {
const NetInfo *refo = net_or_nullptr(ci, id_REFCLKO);
CellInfo *dcu = nullptr;
if (refo == nullptr)
log_error("EXTREFB REFCLKO must not be unconnected\n");
for (auto user : refo->users) {
if (user.cell->type != id_DCUA)
continue;
if (dcu != nullptr && dcu != user.cell)
log_error("EXTREFB REFCLKO must only drive a single DCUA\n");
dcu = user.cell;
}
if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
std::string bel = dcu->attrs.at(ctx->id("BEL"));
NPNR_ASSERT(bel.substr(bel.length() - 3) == "DCU");
bel.replace(bel.length() - 3, 3, "EXTREF");
ci->attrs[ctx->id("BEL")] = bel;
} else if (ci->type == id_PCSCLKDIV) {
const NetInfo *clki = net_or_nullptr(ci, id_CLKI);
if (clki != nullptr && clki->driver.cell != nullptr && clki->driver.cell->type == id_DCUA) {
CellInfo *dcu = clki->driver.cell;
if (!dcu->attrs.count(ctx->id("BEL")))
log_error("DCU must be constrained to a Bel!\n");
BelId bel = ctx->getBelByName(ctx->id(dcu->attrs.at(ctx->id("BEL"))));
if (bel == BelId())
log_error("Invalid DCU bel '%s'\n", dcu->attrs.at(ctx->id("BEL")).c_str());
Loc loc = ctx->getBelLocation(bel);
// DCU0 -> CLKDIV z=0; DCU1 -> CLKDIV z=1
ci->constr_abs_z = true;
ci->constr_z = (loc.x >= 69) ? 1 : 0;
}
}
}
}
public: public:
void pack() void pack()
{ {
pack_io(); pack_io();
pack_ebr(); pack_ebr();
pack_dsps(); pack_dsps();
pack_dcus();
pack_constants(); pack_constants();
pack_dram(); pack_dram();
pack_carries(); pack_carries();

View File

@ -200,9 +200,14 @@ def write_database(dev_name, chip, ddrg, endianness):
write_loc(arc.sinkWire.rel, "dst") write_loc(arc.sinkWire.rel, "dst")
bba.u32(arc.srcWire.id, "src_idx") bba.u32(arc.srcWire.id, "src_idx")
bba.u32(arc.sinkWire.id, "dst_idx") bba.u32(arc.sinkWire.id, "dst_idx")
bba.u32(get_pip_delay(get_wire_name(idx, arc.srcWire.rel, arc.srcWire.id), get_wire_name(idx, arc.sinkWire.rel, arc.sinkWire.id)), "delay") # TODO:delay src_name = get_wire_name(idx, arc.srcWire.rel, arc.srcWire.id)
snk_name = get_wire_name(idx, arc.sinkWire.rel, arc.sinkWire.id)
bba.u32(get_pip_delay(src_name, snk_name), "delay") # TODO:delay
bba.u16(get_tiletype_index(ddrg.to_str(arc.tiletype)), "tile_type") bba.u16(get_tiletype_index(ddrg.to_str(arc.tiletype)), "tile_type")
bba.u8(int(arc.cls), "pip_type") cls = arc.cls
if cls == 1 and "PCS" in snk_name or "DCU" in snk_name or "DCU" in src_name:
cls = 2
bba.u8(cls, "pip_type")
bba.u8(0, "padding") bba.u8(0, "padding")
if len(loctype.wires) > 0: if len(loctype.wires) > 0:
for wire_idx in range(len(loctype.wires)): for wire_idx in range(len(loctype.wires)):
@ -340,7 +345,7 @@ def write_database(dev_name, chip, ddrg, endianness):
bba.pop() bba.pop()
return bba return bba
dev_names = {"25k": "LFE5U-25F", "45k": "LFE5U-45F", "85k": "LFE5U-85F"} dev_names = {"25k": "LFE5UM5G-25F", "45k": "LFE5UM5G-45F", "85k": "LFE5UM5G-85F"}
def main(): def main():
global max_row, max_col global max_row, max_col