refactor: Use constids instead of id("..")
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
9ef0bc3d3a
commit
76683a1e3c
37
ecp5/arch.cc
37
ecp5/arch.cc
@ -202,25 +202,25 @@ std::string Arch::get_full_chip_name() const
|
||||
IdString Arch::archArgsToId(ArchArgs args) const
|
||||
{
|
||||
if (args.type == ArchArgs::LFE5U_12F)
|
||||
return id("lfe5u_12f");
|
||||
return id_lfe5u_12f;
|
||||
if (args.type == ArchArgs::LFE5U_25F)
|
||||
return id("lfe5u_25f");
|
||||
return id_lfe5u_25f;
|
||||
if (args.type == ArchArgs::LFE5U_45F)
|
||||
return id("lfe5u_45f");
|
||||
return id_lfe5u_45f;
|
||||
if (args.type == ArchArgs::LFE5U_85F)
|
||||
return id("lfe5u_85f");
|
||||
return id_lfe5u_85f;
|
||||
if (args.type == ArchArgs::LFE5UM_25F)
|
||||
return id("lfe5um_25f");
|
||||
return id_lfe5um_25f;
|
||||
if (args.type == ArchArgs::LFE5UM_45F)
|
||||
return id("lfe5um_45f");
|
||||
return id_lfe5um_45f;
|
||||
if (args.type == ArchArgs::LFE5UM_85F)
|
||||
return id("lfe5um_85f");
|
||||
return id_lfe5um_85f;
|
||||
if (args.type == ArchArgs::LFE5UM5G_25F)
|
||||
return id("lfe5um5g_25f");
|
||||
return id_lfe5um5g_25f;
|
||||
if (args.type == ArchArgs::LFE5UM5G_45F)
|
||||
return id("lfe5um5g_45f");
|
||||
return id_lfe5um5g_45f;
|
||||
if (args.type == ArchArgs::LFE5UM5G_85F)
|
||||
return id("lfe5um5g_85f");
|
||||
return id_lfe5um5g_85f;
|
||||
return IdString();
|
||||
}
|
||||
|
||||
@ -586,7 +586,7 @@ delay_t Arch::getRipupDelayPenalty() const { return 400; }
|
||||
|
||||
bool Arch::place()
|
||||
{
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
|
||||
if (placer == "heap") {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
@ -612,7 +612,7 @@ bool Arch::place()
|
||||
for (auto &cell : cells)
|
||||
cell.second->belStrength = STRENGTH_LOCKED;
|
||||
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
|
||||
archInfoToAttributes();
|
||||
return true;
|
||||
@ -620,7 +620,7 @@ bool Arch::place()
|
||||
|
||||
bool Arch::route()
|
||||
{
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
|
||||
disable_router_lutperm = getCtx()->setting<bool>("arch.disable_router_lutperm", false);
|
||||
|
||||
@ -639,7 +639,7 @@ bool Arch::route()
|
||||
log_error("ECP5 architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
|
||||
getCtx()->settings[getCtx()->id("route")] = 1;
|
||||
getCtx()->settings[id_route] = 1;
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
@ -1033,12 +1033,12 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
||||
get_setuphold_from_tmg_db(id_SDPRAME, id_WCK, port, info.setup, info.hold);
|
||||
} else if (port == id_DI0 || port == id_DI1 || port == id_CE || port == id_LSR || (sd0 == 0 && port == id_M0) ||
|
||||
(sd1 == 0 && port == id_M1)) {
|
||||
info.edge = cell->sliceInfo.clkmux == id("INV") ? FALLING_EDGE : RISING_EDGE;
|
||||
info.edge = cell->sliceInfo.clkmux == id_INV ? FALLING_EDGE : RISING_EDGE;
|
||||
info.clock_port = id_CLK;
|
||||
get_setuphold_from_tmg_db(id_SLOGICB, id_CLK, port, info.setup, info.hold);
|
||||
|
||||
} else {
|
||||
info.edge = cell->sliceInfo.clkmux == id("INV") ? FALLING_EDGE : RISING_EDGE;
|
||||
info.edge = cell->sliceInfo.clkmux == id_INV ? FALLING_EDGE : RISING_EDGE;
|
||||
info.clock_port = id_CLK;
|
||||
bool is_path = get_delay_from_tmg_db(id_SLOGICB, id_CLK, port, info.clockToQ);
|
||||
NPNR_ASSERT(is_path);
|
||||
@ -1070,8 +1070,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
||||
} else {
|
||||
info.clock_port = half_clock;
|
||||
}
|
||||
info.edge = (str_or_default(cell->params, info.clock_port == id_CLKB ? id("CLKBMUX") : id("CLKAMUX"), "CLK") ==
|
||||
"INV")
|
||||
info.edge = (str_or_default(cell->params, info.clock_port == id_CLKB ? id_CLKBMUX : id_CLKAMUX, "CLK") == "INV")
|
||||
? FALLING_EDGE
|
||||
: RISING_EDGE;
|
||||
if (cell->ports.at(port).type == PORT_OUT) {
|
||||
@ -1298,7 +1297,7 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
auto &wi = loc_info(wire)->wire_data[wire.index];
|
||||
|
||||
ret.push_back(std::make_pair(id("TILE_WIRE_ID"), stringf("%d", wi.tile_wire)));
|
||||
ret.push_back(std::make_pair(id_TILE_WIRE_ID, stringf("%d", wi.tile_wire)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ void Arch::permute_luts()
|
||||
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id("MODE"), "LOGIC") == "LOGIC") {
|
||||
if (ci->type == id_TRELLIS_SLICE && str_or_default(ci->params, id_MODE, "LOGIC") == "LOGIC") {
|
||||
proc_lut(ci, 0);
|
||||
proc_lut(ci, 1);
|
||||
}
|
||||
|
@ -723,10 +723,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->bel != BelId() && ci->type == ctx->id("TRELLIS_IO")) {
|
||||
if (ci->bel != BelId() && ci->type == id_TRELLIS_IO) {
|
||||
int bank = ctx->get_pio_bel_bank(ci->bel);
|
||||
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT");
|
||||
std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33");
|
||||
std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
|
||||
std::string iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
|
||||
|
||||
if (dir != "INPUT" || is_referenced(ioType_from_str(iotype))) {
|
||||
IOVoltage vcc = get_vccio(ioType_from_str(iotype));
|
||||
@ -835,71 +835,65 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
log_warning("found unplaced cell '%s' during bitstream gen\n", ci->name.c_str(ctx));
|
||||
}
|
||||
BelId bel = ci->bel;
|
||||
if (ci->type == ctx->id("TRELLIS_SLICE")) {
|
||||
if (ci->type == id_TRELLIS_SLICE) {
|
||||
pool<IdString> used_phys_pins;
|
||||
std::string tname = ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, "PLC2");
|
||||
std::string slice = ctx->loc_info(bel)->bel_data[bel.index].name.get();
|
||||
int lut0_init = int_or_default(ci->params, ctx->id("LUT0_INITVAL"));
|
||||
int lut1_init = int_or_default(ci->params, ctx->id("LUT1_INITVAL"));
|
||||
int lut0_init = int_or_default(ci->params, id_LUT0_INITVAL);
|
||||
int lut1_init = int_or_default(ci->params, id_LUT1_INITVAL);
|
||||
cc.tiles[tname].add_word(slice + ".K0.INIT",
|
||||
int_to_bitvector(permute_lut(ctx, ci, used_phys_pins, 0, lut0_init), 16));
|
||||
cc.tiles[tname].add_word(slice + ".K1.INIT",
|
||||
int_to_bitvector(permute_lut(ctx, ci, used_phys_pins, 1, lut1_init), 16));
|
||||
cc.tiles[tname].add_enum(slice + ".MODE", str_or_default(ci->params, ctx->id("MODE"), "LOGIC"));
|
||||
cc.tiles[tname].add_enum(slice + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.SD", intstr_or_default(ci->params, ctx->id("REG0_SD"), "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.SD", intstr_or_default(ci->params, ctx->id("REG1_SD"), "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.REGSET",
|
||||
str_or_default(ci->params, ctx->id("REG0_REGSET"), "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.REGSET",
|
||||
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.LSRMODE",
|
||||
str_or_default(ci->params, ctx->id("REG0_LSRMODE"), "LSR"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.LSRMODE",
|
||||
str_or_default(ci->params, ctx->id("REG1_LSRMODE"), "LSR"));
|
||||
cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, ctx->id("CEMUX"), "1"));
|
||||
cc.tiles[tname].add_enum(slice + ".MODE", str_or_default(ci->params, id_MODE, "LOGIC"));
|
||||
cc.tiles[tname].add_enum(slice + ".GSR", str_or_default(ci->params, id_GSR, "ENABLED"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.SD", intstr_or_default(ci->params, id_REG0_SD, "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.SD", intstr_or_default(ci->params, id_REG1_SD, "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.REGSET", str_or_default(ci->params, id_REG0_REGSET, "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.REGSET", str_or_default(ci->params, id_REG1_REGSET, "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.LSRMODE", str_or_default(ci->params, id_REG0_LSRMODE, "LSR"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.LSRMODE", str_or_default(ci->params, id_REG1_LSRMODE, "LSR"));
|
||||
cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, id_CEMUX, "1"));
|
||||
|
||||
if (ci->sliceInfo.using_dff) {
|
||||
NetInfo *lsrnet = nullptr;
|
||||
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr)
|
||||
lsrnet = ci->ports.at(ctx->id("LSR")).net;
|
||||
if (ci->ports.find(id_LSR) != ci->ports.end() && ci->ports.at(id_LSR).net != nullptr)
|
||||
lsrnet = ci->ports.at(id_LSR).net;
|
||||
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR0")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR0.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, id_LSRMUX, "LSR"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR1")) == lsrnet) {
|
||||
cc.tiles[tname].add_enum("LSR1.SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
cc.tiles[tname].add_enum("LSR1.SRMODE", str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, id_LSRMUX, "LSR"));
|
||||
}
|
||||
|
||||
NetInfo *clknet = nullptr;
|
||||
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr)
|
||||
clknet = ci->ports.at(ctx->id("CLK")).net;
|
||||
if (ci->ports.find(id_CLK) != ci->ports.end() && ci->ports.at(id_CLK).net != nullptr)
|
||||
clknet = ci->ports.at(id_CLK).net;
|
||||
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "CLK0")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
cc.tiles[tname].add_enum("CLK0.CLKMUX", str_or_default(ci->params, id_CLKMUX, "CLK"));
|
||||
}
|
||||
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "CLK1")) == clknet) {
|
||||
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, ctx->id("CLKMUX"), "CLK"));
|
||||
cc.tiles[tname].add_enum("CLK1.CLKMUX", str_or_default(ci->params, id_CLKMUX, "CLK"));
|
||||
}
|
||||
}
|
||||
|
||||
if (str_or_default(ci->params, ctx->id("MODE"), "LOGIC") == "CCU2") {
|
||||
if (str_or_default(ci->params, id_MODE, "LOGIC") == "CCU2") {
|
||||
cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_0",
|
||||
str_or_default(ci->params, ctx->id("CCU2_INJECT1_0"), "YES"));
|
||||
str_or_default(ci->params, id_CCU2_INJECT1_0, "YES"));
|
||||
cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_1",
|
||||
str_or_default(ci->params, ctx->id("CCU2_INJECT1_1"), "YES"));
|
||||
str_or_default(ci->params, id_CCU2_INJECT1_1, "YES"));
|
||||
} else {
|
||||
// Don't interfere with cascade mux wiring
|
||||
cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_0", "_NONE_");
|
||||
cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_1", "_NONE_");
|
||||
}
|
||||
|
||||
if (str_or_default(ci->params, ctx->id("MODE"), "LOGIC") == "DPRAM" && slice == "SLICEA") {
|
||||
cc.tiles[tname].add_enum(slice + ".WREMUX", str_or_default(ci->params, ctx->id("WREMUX"), "WRE"));
|
||||
if (str_or_default(ci->params, id_MODE, "LOGIC") == "DPRAM" && slice == "SLICEA") {
|
||||
cc.tiles[tname].add_enum(slice + ".WREMUX", str_or_default(ci->params, id_WREMUX, "WRE"));
|
||||
|
||||
std::string wckmux = str_or_default(ci->params, ctx->id("WCKMUX"), "WCK");
|
||||
std::string wckmux = str_or_default(ci->params, id_WCKMUX, "WCK");
|
||||
wckmux = (wckmux == "WCK") ? "CLK" : wckmux;
|
||||
cc.tiles[tname].add_enum("CLK1.CLKMUX", wckmux);
|
||||
}
|
||||
@ -912,10 +906,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
}
|
||||
|
||||
// TODO: CLKMUX
|
||||
} else if (ci->type == ctx->id("TRELLIS_IO")) {
|
||||
} else if (ci->type == id_TRELLIS_IO) {
|
||||
std::string pio = ctx->loc_info(bel)->bel_data[bel.index].name.get();
|
||||
std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33");
|
||||
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT");
|
||||
std::string iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
|
||||
std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
|
||||
std::string pio_tile = get_pio_tile(ctx, bel);
|
||||
std::string pic_tile = get_pic_tile(ctx, bel);
|
||||
cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
|
||||
@ -950,10 +944,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
} else if (is_referenced(ioType_from_str(iotype))) {
|
||||
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE");
|
||||
}
|
||||
if (dir != "INPUT" &&
|
||||
(ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr) &&
|
||||
(ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() ||
|
||||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
|
||||
if (dir != "INPUT" && (ci->ports.find(id_T) == ci->ports.end() || ci->ports.at(id_T).net == nullptr) &&
|
||||
(ci->ports.find(id_IOLTO) == ci->ports.end() || ci->ports.at(id_IOLTO).net == nullptr)) {
|
||||
// Tie tristate low if unconnected for outputs or bidir
|
||||
WireId jpt_wire = ctx->get_wire_by_loc_basename(bel.location, fmt_str("JPADDT" << pio.back()));
|
||||
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin();
|
||||
@ -964,31 +956,29 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
}
|
||||
if ((dir == "INPUT" || dir == "BIDIR") && !is_differential(ioType_from_str(iotype)) &&
|
||||
!is_referenced(ioType_from_str(iotype))) {
|
||||
cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS",
|
||||
str_or_default(ci->attrs, ctx->id("HYSTERESIS"), "ON"));
|
||||
cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", str_or_default(ci->attrs, id_HYSTERESIS, "ON"));
|
||||
}
|
||||
if (ci->attrs.count(ctx->id("SLEWRATE")) && !is_referenced(ioType_from_str(iotype)))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".SLEWRATE", str_or_default(ci->attrs, ctx->id("SLEWRATE"), "SLOW"));
|
||||
if (ci->attrs.count(ctx->id("PULLMODE")))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", str_or_default(ci->attrs, ctx->id("PULLMODE"), "NONE"));
|
||||
if (ci->attrs.count(ctx->id("DIFFRESISTOR")))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DIFFRESISTOR",
|
||||
str_or_default(ci->attrs, ctx->id("DIFFRESISTOR"), "OFF"));
|
||||
if (ci->attrs.count(ctx->id("CLAMP")))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".CLAMP", str_or_default(ci->attrs, ctx->id("CLAMP"), "OFF"));
|
||||
if (ci->attrs.count(id_SLEWRATE) && !is_referenced(ioType_from_str(iotype)))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".SLEWRATE", str_or_default(ci->attrs, id_SLEWRATE, "SLOW"));
|
||||
if (ci->attrs.count(id_PULLMODE))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", str_or_default(ci->attrs, id_PULLMODE, "NONE"));
|
||||
if (ci->attrs.count(id_DIFFRESISTOR))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DIFFRESISTOR", str_or_default(ci->attrs, id_DIFFRESISTOR, "OFF"));
|
||||
if (ci->attrs.count(id_CLAMP))
|
||||
cc.tiles[pio_tile].add_enum(pio + ".CLAMP", str_or_default(ci->attrs, id_CLAMP, "OFF"));
|
||||
|
||||
if (ci->attrs.count(ctx->id("DRIVE"))) {
|
||||
if (ci->attrs.count(id_DRIVE)) {
|
||||
static bool drive_3v3_warning_done = false;
|
||||
if (iotype == "LVCMOS33") {
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "8"));
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DRIVE", str_or_default(ci->attrs, id_DRIVE, "8"));
|
||||
} else if (iotype == "LVCMOS33D") {
|
||||
if (bel.location.y == 0) {
|
||||
// Pseudo differential top IO
|
||||
NPNR_ASSERT(dir == "OUTPUT");
|
||||
NPNR_ASSERT(pio == "PIOA");
|
||||
std::string cpio_tile = get_comp_pio_tile(ctx, bel);
|
||||
cc.tiles[pio_tile].add_enum("PIOA.DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "12"));
|
||||
cc.tiles[cpio_tile].add_enum("PIOB.DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "12"));
|
||||
cc.tiles[pio_tile].add_enum("PIOA.DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
|
||||
cc.tiles[cpio_tile].add_enum("PIOB.DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
|
||||
} else {
|
||||
std::string other;
|
||||
if (pio == "PIOA")
|
||||
@ -997,9 +987,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
other = "PIOD";
|
||||
else
|
||||
log_error("cannot set DRIVE on differential IO at location %s\n", pio.c_str());
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DRIVE", str_or_default(ci->attrs, ctx->id("DRIVE"), "12"));
|
||||
cc.tiles[pio_tile].add_enum(other + ".DRIVE",
|
||||
str_or_default(ci->attrs, ctx->id("DRIVE"), "12"));
|
||||
cc.tiles[pio_tile].add_enum(pio + ".DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
|
||||
cc.tiles[pio_tile].add_enum(other + ".DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
|
||||
}
|
||||
} else {
|
||||
if (!drive_3v3_warning_done)
|
||||
@ -1007,28 +996,28 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
drive_3v3_warning_done = true;
|
||||
}
|
||||
}
|
||||
if (ci->attrs.count(ctx->id("TERMINATION"))) {
|
||||
if (ci->attrs.count(id_TERMINATION)) {
|
||||
auto vccio = get_vccio(ioType_from_str(iotype));
|
||||
switch (vccio) {
|
||||
case IOVoltage::VCC_1V8:
|
||||
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_1V8",
|
||||
str_or_default(ci->attrs, ctx->id("TERMINATION"), "OFF"));
|
||||
str_or_default(ci->attrs, id_TERMINATION, "OFF"));
|
||||
break;
|
||||
case IOVoltage::VCC_1V5:
|
||||
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_1V5",
|
||||
str_or_default(ci->attrs, ctx->id("TERMINATION"), "OFF"));
|
||||
str_or_default(ci->attrs, id_TERMINATION, "OFF"));
|
||||
break;
|
||||
case IOVoltage::VCC_1V35:
|
||||
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_1V35",
|
||||
str_or_default(ci->attrs, ctx->id("TERMINATION"), "OFF"));
|
||||
str_or_default(ci->attrs, id_TERMINATION, "OFF"));
|
||||
break;
|
||||
default:
|
||||
log_error("TERMINATION is not supported with Vcc = %s (on PIO %s)\n",
|
||||
iovoltage_to_str(vccio).c_str(), ci->name.c_str(ctx));
|
||||
}
|
||||
}
|
||||
if (ci->attrs.count(ctx->id("OPENDRAIN"))) {
|
||||
cc.tiles[pio_tile].add_enum(pio + ".OPENDRAIN", str_or_default(ci->attrs, ctx->id("OPENDRAIN"), "OFF"));
|
||||
if (ci->attrs.count(id_OPENDRAIN)) {
|
||||
cc.tiles[pio_tile].add_enum(pio + ".OPENDRAIN", str_or_default(ci->attrs, id_OPENDRAIN, "OFF"));
|
||||
if (is_differential(ioType_from_str(iotype))) {
|
||||
std::string other;
|
||||
if (pio == "PIOA")
|
||||
@ -1037,25 +1026,24 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
other = "PIOD";
|
||||
else
|
||||
log_error("cannot set OPENDRAIN on differential IO at location %s\n", pio.c_str());
|
||||
cc.tiles[pio_tile].add_enum(other + ".OPENDRAIN",
|
||||
str_or_default(ci->attrs, ctx->id("OPENDRAIN"), "OFF"));
|
||||
cc.tiles[pio_tile].add_enum(other + ".OPENDRAIN", str_or_default(ci->attrs, id_OPENDRAIN, "OFF"));
|
||||
}
|
||||
}
|
||||
|
||||
std::string datamux_oddr = str_or_default(ci->params, ctx->id("DATAMUX_ODDR"), "PADDO");
|
||||
std::string datamux_oddr = str_or_default(ci->params, id_DATAMUX_ODDR, "PADDO");
|
||||
if (datamux_oddr != "PADDO")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_ODDR", datamux_oddr);
|
||||
std::string datamux_oreg = str_or_default(ci->params, ctx->id("DATAMUX_OREG"), "PADDO");
|
||||
std::string datamux_oreg = str_or_default(ci->params, id_DATAMUX_OREG, "PADDO");
|
||||
if (datamux_oreg != "PADDO")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_OREG", datamux_oreg);
|
||||
std::string datamux_mddr = str_or_default(ci->params, ctx->id("DATAMUX_MDDR"), "PADDO");
|
||||
std::string datamux_mddr = str_or_default(ci->params, id_DATAMUX_MDDR, "PADDO");
|
||||
if (datamux_mddr != "PADDO")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_MDDR", datamux_mddr);
|
||||
std::string trimux_tsreg = str_or_default(ci->params, ctx->id("TRIMUX_TSREG"), "PADDT");
|
||||
std::string trimux_tsreg = str_or_default(ci->params, id_TRIMUX_TSREG, "PADDT");
|
||||
if (trimux_tsreg != "PADDT")
|
||||
cc.tiles[pic_tile].add_enum(pio + ".TRIMUX_TSREG", trimux_tsreg);
|
||||
} else if (ci->type == ctx->id("DCCA")) {
|
||||
const NetInfo *cen = get_net_or_empty(ci, ctx->id("CE"));
|
||||
} else if (ci->type == id_DCCA) {
|
||||
const NetInfo *cen = get_net_or_empty(ci, id_CE);
|
||||
if (cen != nullptr) {
|
||||
std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get();
|
||||
Loc loc = ctx->getBelLocation(bel);
|
||||
@ -1084,12 +1072,12 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
tg.config.add_enum(std::string("DCC_") + belname[0] + belname.substr(4) + ".MODE", "DCCA");
|
||||
cc.tilegroups.push_back(tg);
|
||||
}
|
||||
} else if (ci->type == ctx->id("DCSC")) {
|
||||
} else if (ci->type == id_DCSC) {
|
||||
std::set<std::string> dcs_tiles{"EBR_CMUX_LL", "EBR_CMUX_UL", "EBR_CMUX_LL_25K", "DSP_CMUX_UL"};
|
||||
std::string tile = ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, dcs_tiles);
|
||||
std::string dcs = ctx->loc_info(bel)->bel_data[bel.index].name.get();
|
||||
cc.tiles[tile].add_enum(dcs + ".DCSMODE", str_or_default(ci->attrs, ctx->id("DCSMODE"), "POS"));
|
||||
} else if (ci->type == ctx->id("DP16KD")) {
|
||||
cc.tiles[tile].add_enum(dcs + ".DCSMODE", str_or_default(ci->attrs, id_DCSMODE, "POS"));
|
||||
} else if (ci->type == id_DP16KD) {
|
||||
TileGroup tg;
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
tg.tiles = get_bram_tiles(ctx, ci->bel);
|
||||
@ -1098,32 +1086,27 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
if (ci->ramInfo.is_pdp) {
|
||||
tg.config.add_enum(ebr + ".MODE", "PDPW16KD");
|
||||
tg.config.add_enum(ebr + ".PDPW16KD.DATA_WIDTH_R",
|
||||
intstr_or_default(ci->params, ctx->id("DATA_WIDTH_B"), "36"));
|
||||
intstr_or_default(ci->params, id_DATA_WIDTH_B, "36"));
|
||||
} else {
|
||||
tg.config.add_enum(ebr + ".MODE", "DP16KD");
|
||||
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_A",
|
||||
intstr_or_default(ci->params, ctx->id("DATA_WIDTH_A"), "18"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_B",
|
||||
intstr_or_default(ci->params, ctx->id("DATA_WIDTH_B"), "18"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_A",
|
||||
str_or_default(ci->params, ctx->id("WRITEMODE_A"), "NORMAL"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_B",
|
||||
str_or_default(ci->params, ctx->id("WRITEMODE_B"), "NORMAL"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_A", intstr_or_default(ci->params, id_DATA_WIDTH_A, "18"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_B", intstr_or_default(ci->params, id_DATA_WIDTH_B, "18"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_A", str_or_default(ci->params, id_WRITEMODE_A, "NORMAL"));
|
||||
tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_B", str_or_default(ci->params, id_WRITEMODE_B, "NORMAL"));
|
||||
}
|
||||
|
||||
auto csd_a = str_to_bitvector(str_or_default(ci->params, ctx->id("CSDECODE_A"), "0b000"), 3),
|
||||
csd_b = str_to_bitvector(str_or_default(ci->params, ctx->id("CSDECODE_B"), "0b000"), 3);
|
||||
auto csd_a = str_to_bitvector(str_or_default(ci->params, id_CSDECODE_A, "0b000"), 3),
|
||||
csd_b = str_to_bitvector(str_or_default(ci->params, id_CSDECODE_B, "0b000"), 3);
|
||||
|
||||
tg.config.add_enum(ebr + ".REGMODE_A", str_or_default(ci->params, ctx->id("REGMODE_A"), "NOREG"));
|
||||
tg.config.add_enum(ebr + ".REGMODE_B", str_or_default(ci->params, ctx->id("REGMODE_B"), "NOREG"));
|
||||
tg.config.add_enum(ebr + ".REGMODE_A", str_or_default(ci->params, id_REGMODE_A, "NOREG"));
|
||||
tg.config.add_enum(ebr + ".REGMODE_B", str_or_default(ci->params, id_REGMODE_B, "NOREG"));
|
||||
|
||||
tg.config.add_enum(ebr + ".RESETMODE", str_or_default(ci->params, ctx->id("RESETMODE"), "SYNC"));
|
||||
tg.config.add_enum(ebr + ".RESETMODE", str_or_default(ci->params, id_RESETMODE, "SYNC"));
|
||||
tg.config.add_enum(ebr + ".ASYNC_RESET_RELEASE",
|
||||
str_or_default(ci->params, ctx->id("ASYNC_RESET_RELEASE"), "SYNC"));
|
||||
tg.config.add_enum(ebr + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED"));
|
||||
str_or_default(ci->params, id_ASYNC_RESET_RELEASE, "SYNC"));
|
||||
tg.config.add_enum(ebr + ".GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
|
||||
|
||||
tg.config.add_word(ebr + ".WID",
|
||||
int_to_bitvector(bit_reverse(int_or_default(ci->attrs, ctx->id("WID"), 0), 9), 9));
|
||||
tg.config.add_word(ebr + ".WID", int_to_bitvector(bit_reverse(int_or_default(ci->attrs, id_WID, 0), 9), 9));
|
||||
|
||||
// Tie signals as appropriate
|
||||
for (auto port : ci->ports) {
|
||||
@ -1169,19 +1152,19 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
}
|
||||
}
|
||||
|
||||
tg.config.add_enum(ebr + ".CLKAMUX", str_or_default(ci->params, ctx->id("CLKAMUX"), "CLKA"));
|
||||
tg.config.add_enum(ebr + ".CLKBMUX", str_or_default(ci->params, ctx->id("CLKBMUX"), "CLKB"));
|
||||
tg.config.add_enum(ebr + ".CLKAMUX", str_or_default(ci->params, id_CLKAMUX, "CLKA"));
|
||||
tg.config.add_enum(ebr + ".CLKBMUX", str_or_default(ci->params, id_CLKBMUX, "CLKB"));
|
||||
|
||||
tg.config.add_enum(ebr + ".RSTAMUX", str_or_default(ci->params, ctx->id("RSTAMUX"), "RSTA"));
|
||||
tg.config.add_enum(ebr + ".RSTBMUX", str_or_default(ci->params, ctx->id("RSTBMUX"), "RSTB"));
|
||||
tg.config.add_enum(ebr + ".RSTAMUX", str_or_default(ci->params, id_RSTAMUX, "RSTA"));
|
||||
tg.config.add_enum(ebr + ".RSTBMUX", str_or_default(ci->params, id_RSTBMUX, "RSTB"));
|
||||
if (!ci->ramInfo.is_pdp) {
|
||||
tg.config.add_enum(ebr + ".WEAMUX", str_or_default(ci->params, ctx->id("WEAMUX"), "WEA"));
|
||||
tg.config.add_enum(ebr + ".WEBMUX", str_or_default(ci->params, ctx->id("WEBMUX"), "WEB"));
|
||||
tg.config.add_enum(ebr + ".WEAMUX", str_or_default(ci->params, id_WEAMUX, "WEA"));
|
||||
tg.config.add_enum(ebr + ".WEBMUX", str_or_default(ci->params, id_WEBMUX, "WEB"));
|
||||
}
|
||||
tg.config.add_enum(ebr + ".CEAMUX", str_or_default(ci->params, ctx->id("CEAMUX"), "CEA"));
|
||||
tg.config.add_enum(ebr + ".CEBMUX", str_or_default(ci->params, ctx->id("CEBMUX"), "CEB"));
|
||||
tg.config.add_enum(ebr + ".OCEAMUX", str_or_default(ci->params, ctx->id("OCEAMUX"), "OCEA"));
|
||||
tg.config.add_enum(ebr + ".OCEBMUX", str_or_default(ci->params, ctx->id("OCEBMUX"), "OCEB"));
|
||||
tg.config.add_enum(ebr + ".CEAMUX", str_or_default(ci->params, id_CEAMUX, "CEA"));
|
||||
tg.config.add_enum(ebr + ".CEBMUX", str_or_default(ci->params, id_CEBMUX, "CEB"));
|
||||
tg.config.add_enum(ebr + ".OCEAMUX", str_or_default(ci->params, id_OCEAMUX, "OCEA"));
|
||||
tg.config.add_enum(ebr + ".OCEBMUX", str_or_default(ci->params, id_OCEBMUX, "OCEB"));
|
||||
|
||||
std::reverse(csd_a.begin(), csd_a.end());
|
||||
std::reverse(csd_b.begin(), csd_b.end());
|
||||
@ -1205,7 +1188,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
}
|
||||
}
|
||||
}
|
||||
int wid = int_or_default(ci->attrs, ctx->id("WID"), 0);
|
||||
int wid = int_or_default(ci->attrs, id_WID, 0);
|
||||
NPNR_ASSERT(!cc.bram_data.count(wid));
|
||||
cc.bram_data[wid] = init_data;
|
||||
cc.tilegroups.push_back(tg);
|
||||
@ -1214,33 +1197,30 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
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"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTA_CLK", str_or_default(ci->params, id_REG_INPUTA_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTA_CE", str_or_default(ci->params, id_REG_INPUTA_CE, "CE0"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTA_RST", str_or_default(ci->params, id_REG_INPUTA_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTB_CLK", str_or_default(ci->params, id_REG_INPUTB_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTB_CE", str_or_default(ci->params, id_REG_INPUTB_CE, "CE0"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTB_RST", str_or_default(ci->params, id_REG_INPUTB_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTC_CLK", str_or_default(ci->params, id_REG_INPUTC_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_PIPELINE_CLK", str_or_default(ci->params, id_REG_PIPELINE_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_PIPELINE_CE", str_or_default(ci->params, id_REG_PIPELINE_CE, "CE0"));
|
||||
tg.config.add_enum(dsp + ".REG_PIPELINE_RST", str_or_default(ci->params, id_REG_PIPELINE_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, 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 + ".REG_OUTPUT_RST", str_or_default(ci->params, 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 + ".CLK0_DIV", str_or_default(ci->params, id_CLK0_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, id_CLK1_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, id_CLK2_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, id_CLK3_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, id_GSR, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".SOURCEB_MODE", str_or_default(ci->params, id_SOURCEB_MODE, "B_SHIFT"));
|
||||
tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, id_RESETMODE, "SYNC"));
|
||||
|
||||
tg.config.add_enum(dsp + ".MODE", "MULT18X18D");
|
||||
if (str_or_default(ci->params, ctx->id("REG_OUTPUT_CLK"), "NONE") == "NONE" && ci->cluster == ClusterId())
|
||||
if (str_or_default(ci->params, id_REG_OUTPUT_CLK, "NONE") == "NONE" && ci->cluster == ClusterId())
|
||||
tg.config.add_enum(dsp + ".CIBOUT_BYP", "ON");
|
||||
|
||||
if (loc.z < 4)
|
||||
@ -1264,67 +1244,53 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
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_INPUTC0_CLK", str_or_default(ci->params, id_REG_INPUTC0_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_INPUTC1_CLK", str_or_default(ci->params, 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"));
|
||||
str_or_default(ci->params, id_REG_OPCODEOP0_0_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE", str_or_default(ci->params, 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"));
|
||||
str_or_default(ci->params, 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"));
|
||||
str_or_default(ci->params, 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"));
|
||||
str_or_default(ci->params, id_REG_OPCODEOP0_1_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEOP1_1_CLK",
|
||||
str_or_default(ci->params, ctx->id("REG_OPCODEOP1_1_CLK"), "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE",
|
||||
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CE"), "CE0"));
|
||||
str_or_default(ci->params, id_REG_OPCODEOP1_1_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE", str_or_default(ci->params, 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,
|
||||
ci->name.c_str(ctx)));
|
||||
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,
|
||||
ci->name.c_str(ctx)));
|
||||
str_or_default(ci->params, id_REG_OPCODEOP0_1_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK", str_or_default(ci->params, id_REG_OPCODEIN_0_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CE", str_or_default(ci->params, id_REG_OPCODEIN_0_CE, "CE0"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_RST", str_or_default(ci->params, id_REG_OPCODEIN_0_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CLK", str_or_default(ci->params, id_REG_OPCODEIN_1_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CE", str_or_default(ci->params, id_REG_OPCODEIN_1_CE, "CE0"));
|
||||
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_RST", str_or_default(ci->params, id_REG_OPCODEIN_1_RST, "RST0"));
|
||||
tg.config.add_enum(dsp + ".REG_OUTPUT0_CLK", str_or_default(ci->params, id_REG_OUTPUT0_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_OUTPUT1_CLK", str_or_default(ci->params, id_REG_OUTPUT1_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, id_REG_FLAG_CLK, "NONE"));
|
||||
tg.config.add_enum(dsp + ".MCPAT_SOURCE", str_or_default(ci->params, id_MCPAT_SOURCE, "STATIC"));
|
||||
tg.config.add_enum(dsp + ".MASKPAT_SOURCE", str_or_default(ci->params, id_MASKPAT_SOURCE, "STATIC"));
|
||||
tg.config.add_word(
|
||||
dsp + ".MASK01",
|
||||
parse_init_str(str_or_default(ci->params, id_MASK01, "0x00000000000000"), 56, ci->name.c_str(ctx)));
|
||||
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, id_CLK0_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, id_CLK1_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, id_CLK2_DIV, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, id_CLK3_DIV, "ENABLED"));
|
||||
tg.config.add_word(dsp + ".MCPAT", parse_init_str(str_or_default(ci->params, id_MCPAT, "0x00000000000000"),
|
||||
56, ci->name.c_str(ctx)));
|
||||
tg.config.add_word(dsp + ".MASKPAT",
|
||||
parse_init_str(str_or_default(ci->params, ctx->id("MASKPAT"), "0x00000000000000"), 56,
|
||||
parse_init_str(str_or_default(ci->params, id_MASKPAT, "0x00000000000000"), 56,
|
||||
ci->name.c_str(ctx)));
|
||||
tg.config.add_word(dsp + ".RNDPAT",
|
||||
parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 56,
|
||||
ci->name.c_str(ctx)));
|
||||
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_word(
|
||||
dsp + ".RNDPAT",
|
||||
parse_init_str(str_or_default(ci->params, id_RNDPAT, "0x00000000000000"), 56, ci->name.c_str(ctx)));
|
||||
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, id_GSR, "ENABLED"));
|
||||
tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, 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"));
|
||||
str_or_default(ci->params, id_FORCE_ZERO_BARREL_SHIFT, "DISABLED"));
|
||||
tg.config.add_enum(dsp + ".LEGACY", str_or_default(ci->params, id_LEGACY, "DISABLED"));
|
||||
|
||||
tg.config.add_enum(dsp + ".MODE", "ALU54B");
|
||||
|
||||
@ -1332,14 +1298,14 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
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 (str_or_default(ci->params, 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 (str_or_default(ci->params, id_REG_OUTPUT0_CLK, "NONE") == "NONE") {
|
||||
if (dsp == "ALU54_7") {
|
||||
tg.config.add_enum("MULT18_4.CIBOUT_BYP", "ON");
|
||||
} else if (dsp == "ALU54_3") {
|
||||
@ -1354,14 +1320,13 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
|
||||
tg.config.add_enum("MODE", "EHXPLLL");
|
||||
|
||||
tg.config.add_word("CLKI_DIV", int_to_bitvector(int_or_default(ci->params, ctx->id("CLKI_DIV"), 1) - 1, 7));
|
||||
tg.config.add_word("CLKFB_DIV",
|
||||
int_to_bitvector(int_or_default(ci->params, ctx->id("CLKFB_DIV"), 1) - 1, 7));
|
||||
tg.config.add_word("CLKI_DIV", int_to_bitvector(int_or_default(ci->params, id_CLKI_DIV, 1) - 1, 7));
|
||||
tg.config.add_word("CLKFB_DIV", int_to_bitvector(int_or_default(ci->params, id_CLKFB_DIV, 1) - 1, 7));
|
||||
|
||||
tg.config.add_enum("CLKOP_ENABLE", str_or_default(ci->params, ctx->id("CLKOP_ENABLE"), "ENABLED"));
|
||||
tg.config.add_enum("CLKOS_ENABLE", str_or_default(ci->params, ctx->id("CLKOS_ENABLE"), "ENABLED"));
|
||||
tg.config.add_enum("CLKOS2_ENABLE", str_or_default(ci->params, ctx->id("CLKOS2_ENABLE"), "ENABLED"));
|
||||
tg.config.add_enum("CLKOS3_ENABLE", str_or_default(ci->params, ctx->id("CLKOS3_ENABLE"), "ENABLED"));
|
||||
tg.config.add_enum("CLKOP_ENABLE", str_or_default(ci->params, id_CLKOP_ENABLE, "ENABLED"));
|
||||
tg.config.add_enum("CLKOS_ENABLE", str_or_default(ci->params, id_CLKOS_ENABLE, "ENABLED"));
|
||||
tg.config.add_enum("CLKOS2_ENABLE", str_or_default(ci->params, id_CLKOS2_ENABLE, "ENABLED"));
|
||||
tg.config.add_enum("CLKOS3_ENABLE", str_or_default(ci->params, id_CLKOS3_ENABLE, "ENABLED"));
|
||||
|
||||
for (std::string out : {"CLKOP", "CLKOS", "CLKOS2", "CLKOS3"}) {
|
||||
tg.config.add_word(out + "_DIV",
|
||||
@ -1372,73 +1337,59 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
int_to_bitvector(int_or_default(ci->params, ctx->id(out + "_FPHASE"), 0), 3));
|
||||
}
|
||||
|
||||
tg.config.add_enum("FEEDBK_PATH", str_or_default(ci->params, ctx->id("FEEDBK_PATH"), "CLKOP"));
|
||||
tg.config.add_enum("CLKOP_TRIM_POL", str_or_default(ci->params, ctx->id("CLKOP_TRIM_POL"), "RISING"));
|
||||
tg.config.add_enum("FEEDBK_PATH", str_or_default(ci->params, id_FEEDBK_PATH, "CLKOP"));
|
||||
tg.config.add_enum("CLKOP_TRIM_POL", str_or_default(ci->params, id_CLKOP_TRIM_POL, "RISING"));
|
||||
|
||||
tg.config.add_enum("CLKOP_TRIM_DELAY", intstr_or_default(ci->params, ctx->id("CLKOP_TRIM_DELAY"), "0"));
|
||||
tg.config.add_enum("CLKOP_TRIM_DELAY", intstr_or_default(ci->params, id_CLKOP_TRIM_DELAY, "0"));
|
||||
|
||||
tg.config.add_enum("CLKOS_TRIM_POL", str_or_default(ci->params, ctx->id("CLKOS_TRIM_POL"), "RISING"));
|
||||
tg.config.add_enum("CLKOS_TRIM_POL", str_or_default(ci->params, id_CLKOS_TRIM_POL, "RISING"));
|
||||
|
||||
tg.config.add_enum("CLKOS_TRIM_DELAY", intstr_or_default(ci->params, ctx->id("CLKOS_TRIM_DELAY"), "0"));
|
||||
tg.config.add_enum("CLKOS_TRIM_DELAY", intstr_or_default(ci->params, id_CLKOS_TRIM_DELAY, "0"));
|
||||
|
||||
tg.config.add_enum("OUTDIVIDER_MUXA", str_or_default(ci->params, ctx->id("OUTDIVIDER_MUXA"),
|
||||
tg.config.add_enum("OUTDIVIDER_MUXA", str_or_default(ci->params, id_OUTDIVIDER_MUXA,
|
||||
get_net_or_empty(ci, id_CLKOP) ? "DIVA" : "REFCLK"));
|
||||
tg.config.add_enum("OUTDIVIDER_MUXB", str_or_default(ci->params, ctx->id("OUTDIVIDER_MUXB"),
|
||||
tg.config.add_enum("OUTDIVIDER_MUXB", str_or_default(ci->params, id_OUTDIVIDER_MUXB,
|
||||
get_net_or_empty(ci, id_CLKOP) ? "DIVB" : "REFCLK"));
|
||||
tg.config.add_enum("OUTDIVIDER_MUXC", str_or_default(ci->params, ctx->id("OUTDIVIDER_MUXC"),
|
||||
tg.config.add_enum("OUTDIVIDER_MUXC", str_or_default(ci->params, id_OUTDIVIDER_MUXC,
|
||||
get_net_or_empty(ci, id_CLKOP) ? "DIVC" : "REFCLK"));
|
||||
tg.config.add_enum("OUTDIVIDER_MUXD", str_or_default(ci->params, ctx->id("OUTDIVIDER_MUXD"),
|
||||
tg.config.add_enum("OUTDIVIDER_MUXD", str_or_default(ci->params, id_OUTDIVIDER_MUXD,
|
||||
get_net_or_empty(ci, id_CLKOP) ? "DIVD" : "REFCLK"));
|
||||
|
||||
tg.config.add_word("PLL_LOCK_MODE",
|
||||
int_to_bitvector(int_or_default(ci->params, ctx->id("PLL_LOCK_MODE"), 0), 3));
|
||||
tg.config.add_word("PLL_LOCK_MODE", int_to_bitvector(int_or_default(ci->params, id_PLL_LOCK_MODE, 0), 3));
|
||||
|
||||
tg.config.add_enum("STDBY_ENABLE", str_or_default(ci->params, ctx->id("STDBY_ENABLE"), "DISABLED"));
|
||||
tg.config.add_enum("REFIN_RESET", str_or_default(ci->params, ctx->id("REFIN_RESET"), "DISABLED"));
|
||||
tg.config.add_enum("SYNC_ENABLE", str_or_default(ci->params, ctx->id("SYNC_ENABLE"), "DISABLED"));
|
||||
tg.config.add_enum("INT_LOCK_STICKY", str_or_default(ci->params, ctx->id("INT_LOCK_STICKY"), "ENABLED"));
|
||||
tg.config.add_enum("DPHASE_SOURCE", str_or_default(ci->params, ctx->id("DPHASE_SOURCE"), "DISABLED"));
|
||||
tg.config.add_enum("PLLRST_ENA", str_or_default(ci->params, ctx->id("PLLRST_ENA"), "DISABLED"));
|
||||
tg.config.add_enum("INTFB_WAKE", str_or_default(ci->params, ctx->id("INTFB_WAKE"), "DISABLED"));
|
||||
tg.config.add_enum("STDBY_ENABLE", str_or_default(ci->params, id_STDBY_ENABLE, "DISABLED"));
|
||||
tg.config.add_enum("REFIN_RESET", str_or_default(ci->params, id_REFIN_RESET, "DISABLED"));
|
||||
tg.config.add_enum("SYNC_ENABLE", str_or_default(ci->params, id_SYNC_ENABLE, "DISABLED"));
|
||||
tg.config.add_enum("INT_LOCK_STICKY", str_or_default(ci->params, id_INT_LOCK_STICKY, "ENABLED"));
|
||||
tg.config.add_enum("DPHASE_SOURCE", str_or_default(ci->params, id_DPHASE_SOURCE, "DISABLED"));
|
||||
tg.config.add_enum("PLLRST_ENA", str_or_default(ci->params, id_PLLRST_ENA, "DISABLED"));
|
||||
tg.config.add_enum("INTFB_WAKE", str_or_default(ci->params, id_INTFB_WAKE, "DISABLED"));
|
||||
|
||||
tg.config.add_word("KVCO", int_to_bitvector(int_or_default(ci->attrs, ctx->id("KVCO"), 0), 3));
|
||||
tg.config.add_word("LPF_CAPACITOR",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("LPF_CAPACITOR"), 0), 2));
|
||||
tg.config.add_word("LPF_RESISTOR",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("LPF_RESISTOR"), 0), 7));
|
||||
tg.config.add_word("ICP_CURRENT",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("ICP_CURRENT"), 0), 5));
|
||||
tg.config.add_word("KVCO", int_to_bitvector(int_or_default(ci->attrs, id_KVCO, 0), 3));
|
||||
tg.config.add_word("LPF_CAPACITOR", int_to_bitvector(int_or_default(ci->attrs, id_LPF_CAPACITOR, 0), 2));
|
||||
tg.config.add_word("LPF_RESISTOR", int_to_bitvector(int_or_default(ci->attrs, id_LPF_RESISTOR, 0), 7));
|
||||
tg.config.add_word("ICP_CURRENT", int_to_bitvector(int_or_default(ci->attrs, id_ICP_CURRENT, 0), 5));
|
||||
tg.config.add_word("FREQ_LOCK_ACCURACY",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("FREQ_LOCK_ACCURACY"), 0), 2));
|
||||
int_to_bitvector(int_or_default(ci->attrs, id_FREQ_LOCK_ACCURACY, 0), 2));
|
||||
|
||||
tg.config.add_word("MFG_GMC_GAIN",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_GAIN"), 0), 3));
|
||||
tg.config.add_word("MFG_GMC_TEST",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_TEST"), 14), 4));
|
||||
tg.config.add_word("MFG1_TEST", int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG1_TEST"), 0), 3));
|
||||
tg.config.add_word("MFG2_TEST", int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG2_TEST"), 0), 3));
|
||||
tg.config.add_word("MFG_GMC_GAIN", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_GAIN, 0), 3));
|
||||
tg.config.add_word("MFG_GMC_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_TEST, 14), 4));
|
||||
tg.config.add_word("MFG1_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG1_TEST, 0), 3));
|
||||
tg.config.add_word("MFG2_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG2_TEST, 0), 3));
|
||||
|
||||
tg.config.add_word("MFG_FORCE_VFILTER",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_FORCE_VFILTER"), 0), 1));
|
||||
tg.config.add_word("MFG_ICP_TEST",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_ICP_TEST"), 0), 1));
|
||||
tg.config.add_word("MFG_EN_UP", int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_EN_UP"), 0), 1));
|
||||
tg.config.add_word("MFG_FLOAT_ICP",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_FLOAT_ICP"), 0), 1));
|
||||
tg.config.add_word("MFG_GMC_PRESET",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_PRESET"), 0), 1));
|
||||
tg.config.add_word("MFG_LF_PRESET",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_LF_PRESET"), 0), 1));
|
||||
tg.config.add_word("MFG_GMC_RESET",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_RESET"), 0), 1));
|
||||
tg.config.add_word("MFG_LF_RESET",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_LF_RESET"), 0), 1));
|
||||
tg.config.add_word("MFG_LF_RESGRND",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_LF_RESGRND"), 0), 1));
|
||||
tg.config.add_word("MFG_GMCREF_SEL",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMCREF_SEL"), 0), 2));
|
||||
int_to_bitvector(int_or_default(ci->attrs, id_MFG_FORCE_VFILTER, 0), 1));
|
||||
tg.config.add_word("MFG_ICP_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG_ICP_TEST, 0), 1));
|
||||
tg.config.add_word("MFG_EN_UP", int_to_bitvector(int_or_default(ci->attrs, id_MFG_EN_UP, 0), 1));
|
||||
tg.config.add_word("MFG_FLOAT_ICP", int_to_bitvector(int_or_default(ci->attrs, id_MFG_FLOAT_ICP, 0), 1));
|
||||
tg.config.add_word("MFG_GMC_PRESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_PRESET, 0), 1));
|
||||
tg.config.add_word("MFG_LF_PRESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_LF_PRESET, 0), 1));
|
||||
tg.config.add_word("MFG_GMC_RESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_RESET, 0), 1));
|
||||
tg.config.add_word("MFG_LF_RESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_LF_RESET, 0), 1));
|
||||
tg.config.add_word("MFG_LF_RESGRND", int_to_bitvector(int_or_default(ci->attrs, id_MFG_LF_RESGRND, 0), 1));
|
||||
tg.config.add_word("MFG_GMCREF_SEL", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMCREF_SEL, 0), 2));
|
||||
tg.config.add_word("MFG_ENABLE_FILTEROPAMP",
|
||||
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_ENABLE_FILTEROPAMP"), 0), 1));
|
||||
int_to_bitvector(int_or_default(ci->attrs, id_MFG_ENABLE_FILTEROPAMP, 0), 1));
|
||||
|
||||
cc.tilegroups.push_back(tg);
|
||||
} else if (ci->type == id_IOLOGIC || ci->type == id_SIOLOGIC) {
|
||||
@ -1466,23 +1417,22 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
} 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(get_or_default(ci->params, ctx->id("REFCK_DCBIAS_EN"), Property(0)), 1));
|
||||
tg.config.add_word("EXTREF.REFCK_DCBIAS_EN",
|
||||
parse_config_str(get_or_default(ci->params, id_REFCK_DCBIAS_EN, Property(0)), 1));
|
||||
tg.config.add_word("EXTREF.REFCK_RTERM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("REFCK_RTERM"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_REFCK_RTERM, Property(0)), 1));
|
||||
tg.config.add_word("EXTREF.REFCK_PWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("REFCK_PWDNB"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_REFCK_PWDNB, Property(0)), 1));
|
||||
cc.tilegroups.push_back(tg);
|
||||
} else if (ci->type == id_PCSCLKDIV) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
std::string tname = ctx->get_tile_by_type_loc(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"));
|
||||
str_or_default(ci->params, id_GSR, "ENABLED"));
|
||||
} else if (ci->type == id_DTR) {
|
||||
cc.tiles[ctx->get_tile_by_type("DTR")].add_enum("DTR.MODE", "DTR");
|
||||
} else if (ci->type == id_OSCG) {
|
||||
int div = int_or_default(ci->params, ctx->id("DIV"), 128);
|
||||
int div = int_or_default(ci->params, id_DIV, 128);
|
||||
if (div == 128)
|
||||
div = 127;
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("OSC.DIV", std::to_string(div));
|
||||
@ -1494,22 +1444,22 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
log_warning("USRMCLK will not function correctly when MASTER_SPI_PORT is set to ENABLE.\n");
|
||||
cc.tiles[ctx->get_tile_by_type("EFB3_PICB1")].add_enum("CCLK.MODE", "USRMCLK");
|
||||
} else if (ci->type == id_GSR) {
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum(
|
||||
"GSR.GSRMODE", str_or_default(ci->params, ctx->id("MODE"), "ACTIVE_LOW"));
|
||||
cc.tiles[ctx->get_tile_by_type("VIQ_BUF")].add_enum(
|
||||
"GSR.SYNCMODE", str_or_default(ci->params, ctx->id("SYNCMODE"), "ASYNC"));
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("GSR.GSRMODE",
|
||||
str_or_default(ci->params, id_MODE, "ACTIVE_LOW"));
|
||||
cc.tiles[ctx->get_tile_by_type("VIQ_BUF")].add_enum("GSR.SYNCMODE",
|
||||
str_or_default(ci->params, id_SYNCMODE, "ASYNC"));
|
||||
} else if (ci->type == id_JTAGG) {
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum(
|
||||
"JTAG.ER1", str_or_default(ci->params, ctx->id("ER1"), "ENABLED"));
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum(
|
||||
"JTAG.ER2", str_or_default(ci->params, ctx->id("ER2"), "ENABLED"));
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("JTAG.ER1",
|
||||
str_or_default(ci->params, id_ER1, "ENABLED"));
|
||||
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("JTAG.ER2",
|
||||
str_or_default(ci->params, id_ER2, "ENABLED"));
|
||||
} else if (ci->type == id_CLKDIVF) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
bool r = loc.x > 5;
|
||||
std::string clkdiv = std::string("CLKDIV_") + (r ? "R" : "L") + std::to_string(loc.z);
|
||||
std::string tile = ctx->get_tile_by_type(std::string("ECLK_") + (r ? "R" : "L"));
|
||||
cc.tiles[tile].add_enum(clkdiv + ".DIV", str_or_default(ci->params, ctx->id("DIV"), "2.0"));
|
||||
cc.tiles[tile].add_enum(clkdiv + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED"));
|
||||
cc.tiles[tile].add_enum(clkdiv + ".DIV", str_or_default(ci->params, id_DIV, "2.0"));
|
||||
cc.tiles[tile].add_enum(clkdiv + ".GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
|
||||
} else if (ci->type == id_TRELLIS_ECLKBUF) {
|
||||
} else if (ci->type == id_DQSBUFM) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
@ -1521,13 +1471,13 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
tg.tiles.push_back(ctx->get_tile_by_type_loc(loc.y, loc.x, pic + "0_DQS2"));
|
||||
tg.tiles.push_back(ctx->get_tile_by_type_loc(loc.y + 1, loc.x, pic + "1_DQS3"));
|
||||
tg.config.add_enum("DQS.MODE", "DQSBUFM");
|
||||
tg.config.add_enum("DQS.DQS_LI_DEL_ADJ", str_or_default(ci->params, ctx->id("DQS_LI_DEL_ADJ"), "PLUS"));
|
||||
tg.config.add_enum("DQS.DQS_LO_DEL_ADJ", str_or_default(ci->params, ctx->id("DQS_LO_DEL_ADJ"), "PLUS"));
|
||||
int li_del_value = int_or_default(ci->params, ctx->id("DQS_LI_DEL_VAL"), 0);
|
||||
if (str_or_default(ci->params, ctx->id("DQS_LI_DEL_ADJ"), "PLUS") == "MINUS")
|
||||
tg.config.add_enum("DQS.DQS_LI_DEL_ADJ", str_or_default(ci->params, id_DQS_LI_DEL_ADJ, "PLUS"));
|
||||
tg.config.add_enum("DQS.DQS_LO_DEL_ADJ", str_or_default(ci->params, id_DQS_LO_DEL_ADJ, "PLUS"));
|
||||
int li_del_value = int_or_default(ci->params, id_DQS_LI_DEL_VAL, 0);
|
||||
if (str_or_default(ci->params, id_DQS_LI_DEL_ADJ, "PLUS") == "MINUS")
|
||||
li_del_value = (256 - li_del_value) & 0xFF;
|
||||
int lo_del_value = int_or_default(ci->params, ctx->id("DQS_LO_DEL_VAL"), 0);
|
||||
if (str_or_default(ci->params, ctx->id("DQS_LO_DEL_ADJ"), "PLUS") == "MINUS")
|
||||
int lo_del_value = int_or_default(ci->params, id_DQS_LO_DEL_VAL, 0);
|
||||
if (str_or_default(ci->params, id_DQS_LO_DEL_ADJ, "PLUS") == "MINUS")
|
||||
lo_del_value = (256 - lo_del_value) & 0xFF;
|
||||
tg.config.add_word("DQS.DQS_LI_DEL_VAL", int_to_bitvector(li_del_value, 8));
|
||||
tg.config.add_word("DQS.DQS_LO_DEL_VAL", int_to_bitvector(lo_del_value, 8));
|
||||
@ -1539,7 +1489,7 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
? "YES"
|
||||
: "NO");
|
||||
tg.config.add_enum("DQS.DDRDEL", get_net_or_empty(ci, id_DDRDEL) != nullptr ? "DDRDEL" : "0");
|
||||
tg.config.add_enum("DQS.GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED"));
|
||||
tg.config.add_enum("DQS.GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
|
||||
cc.tilegroups.push_back(tg);
|
||||
} else if (ci->type == id_ECLKSYNCB) {
|
||||
Loc loc = ctx->getBelLocation(ci->bel);
|
||||
@ -1565,9 +1515,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
|
||||
tiletype += "A";
|
||||
std::string tile = ctx->get_tile_by_type(tiletype);
|
||||
cc.tiles[tile].add_enum("DDRDLL.MODE", "DDRDLLA");
|
||||
cc.tiles[tile].add_enum("DDRDLL.GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED"));
|
||||
cc.tiles[tile].add_enum("DDRDLL.FORCE_MAX_DELAY",
|
||||
str_or_default(ci->params, ctx->id("FORCE_MAX_DELAY"), "NO"));
|
||||
cc.tiles[tile].add_enum("DDRDLL.GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
|
||||
cc.tiles[tile].add_enum("DDRDLL.FORCE_MAX_DELAY", str_or_default(ci->params, id_FORCE_MAX_DELAY, "NO"));
|
||||
} else {
|
||||
NPNR_ASSERT_FALSE("unsupported cell type");
|
||||
}
|
||||
|
384
ecp5/cells.cc
384
ecp5/cells.cc
@ -47,129 +47,129 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
|
||||
}
|
||||
};
|
||||
|
||||
if (type == ctx->id("TRELLIS_SLICE")) {
|
||||
new_cell->params[ctx->id("MODE")] = std::string("LOGIC");
|
||||
new_cell->params[ctx->id("GSR")] = std::string("DISABLED");
|
||||
new_cell->params[ctx->id("SRMODE")] = std::string("LSR_OVER_CE");
|
||||
new_cell->params[ctx->id("CEMUX")] = std::string("1");
|
||||
new_cell->params[ctx->id("CLKMUX")] = std::string("CLK");
|
||||
new_cell->params[ctx->id("LSRMUX")] = std::string("LSR");
|
||||
new_cell->params[ctx->id("LUT0_INITVAL")] = Property(0, 16);
|
||||
new_cell->params[ctx->id("LUT1_INITVAL")] = Property(0, 16);
|
||||
new_cell->params[ctx->id("REG0_SD")] = std::string("0");
|
||||
new_cell->params[ctx->id("REG1_SD")] = std::string("0");
|
||||
new_cell->params[ctx->id("REG0_REGSET")] = std::string("RESET");
|
||||
new_cell->params[ctx->id("REG1_REGSET")] = std::string("RESET");
|
||||
new_cell->params[ctx->id("CCU2_INJECT1_0")] = std::string("NO");
|
||||
new_cell->params[ctx->id("CCU2_INJECT1_1")] = std::string("NO");
|
||||
new_cell->params[ctx->id("WREMUX")] = std::string("WRE");
|
||||
if (type == id_TRELLIS_SLICE) {
|
||||
new_cell->params[id_MODE] = std::string("LOGIC");
|
||||
new_cell->params[id_GSR] = std::string("DISABLED");
|
||||
new_cell->params[id_SRMODE] = std::string("LSR_OVER_CE");
|
||||
new_cell->params[id_CEMUX] = std::string("1");
|
||||
new_cell->params[id_CLKMUX] = std::string("CLK");
|
||||
new_cell->params[id_LSRMUX] = std::string("LSR");
|
||||
new_cell->params[id_LUT0_INITVAL] = Property(0, 16);
|
||||
new_cell->params[id_LUT1_INITVAL] = Property(0, 16);
|
||||
new_cell->params[id_REG0_SD] = std::string("0");
|
||||
new_cell->params[id_REG1_SD] = std::string("0");
|
||||
new_cell->params[id_REG0_REGSET] = std::string("RESET");
|
||||
new_cell->params[id_REG1_REGSET] = std::string("RESET");
|
||||
new_cell->params[id_CCU2_INJECT1_0] = std::string("NO");
|
||||
new_cell->params[id_CCU2_INJECT1_1] = std::string("NO");
|
||||
new_cell->params[id_WREMUX] = std::string("WRE");
|
||||
|
||||
new_cell->addInput(ctx->id("A0"));
|
||||
new_cell->addInput(ctx->id("B0"));
|
||||
new_cell->addInput(ctx->id("C0"));
|
||||
new_cell->addInput(ctx->id("D0"));
|
||||
new_cell->addInput(id_A0);
|
||||
new_cell->addInput(id_B0);
|
||||
new_cell->addInput(id_C0);
|
||||
new_cell->addInput(id_D0);
|
||||
|
||||
new_cell->addInput(ctx->id("A1"));
|
||||
new_cell->addInput(ctx->id("B1"));
|
||||
new_cell->addInput(ctx->id("C1"));
|
||||
new_cell->addInput(ctx->id("D1"));
|
||||
new_cell->addInput(id_A1);
|
||||
new_cell->addInput(id_B1);
|
||||
new_cell->addInput(id_C1);
|
||||
new_cell->addInput(id_D1);
|
||||
|
||||
new_cell->addInput(ctx->id("M0"));
|
||||
new_cell->addInput(ctx->id("M1"));
|
||||
new_cell->addInput(id_M0);
|
||||
new_cell->addInput(id_M1);
|
||||
|
||||
new_cell->addInput(ctx->id("FCI"));
|
||||
new_cell->addInput(ctx->id("FXA"));
|
||||
new_cell->addInput(ctx->id("FXB"));
|
||||
new_cell->addInput(id_FCI);
|
||||
new_cell->addInput(id_FXA);
|
||||
new_cell->addInput(id_FXB);
|
||||
|
||||
new_cell->addInput(ctx->id("CLK"));
|
||||
new_cell->addInput(ctx->id("LSR"));
|
||||
new_cell->addInput(ctx->id("CE"));
|
||||
new_cell->addInput(id_CLK);
|
||||
new_cell->addInput(id_LSR);
|
||||
new_cell->addInput(id_CE);
|
||||
|
||||
new_cell->addInput(ctx->id("DI0"));
|
||||
new_cell->addInput(ctx->id("DI1"));
|
||||
new_cell->addInput(id_DI0);
|
||||
new_cell->addInput(id_DI1);
|
||||
|
||||
new_cell->addInput(ctx->id("WD0"));
|
||||
new_cell->addInput(ctx->id("WD1"));
|
||||
new_cell->addInput(ctx->id("WAD0"));
|
||||
new_cell->addInput(ctx->id("WAD1"));
|
||||
new_cell->addInput(ctx->id("WAD2"));
|
||||
new_cell->addInput(ctx->id("WAD3"));
|
||||
new_cell->addInput(ctx->id("WRE"));
|
||||
new_cell->addInput(ctx->id("WCK"));
|
||||
new_cell->addInput(id_WD0);
|
||||
new_cell->addInput(id_WD1);
|
||||
new_cell->addInput(id_WAD0);
|
||||
new_cell->addInput(id_WAD1);
|
||||
new_cell->addInput(id_WAD2);
|
||||
new_cell->addInput(id_WAD3);
|
||||
new_cell->addInput(id_WRE);
|
||||
new_cell->addInput(id_WCK);
|
||||
|
||||
new_cell->addOutput(ctx->id("F0"));
|
||||
new_cell->addOutput(ctx->id("Q0"));
|
||||
new_cell->addOutput(ctx->id("F1"));
|
||||
new_cell->addOutput(ctx->id("Q1"));
|
||||
new_cell->addOutput(id_F0);
|
||||
new_cell->addOutput(id_Q0);
|
||||
new_cell->addOutput(id_F1);
|
||||
new_cell->addOutput(id_Q1);
|
||||
|
||||
new_cell->addOutput(ctx->id("FCO"));
|
||||
new_cell->addOutput(ctx->id("OFX0"));
|
||||
new_cell->addOutput(ctx->id("OFX1"));
|
||||
new_cell->addOutput(id_FCO);
|
||||
new_cell->addOutput(id_OFX0);
|
||||
new_cell->addOutput(id_OFX1);
|
||||
|
||||
new_cell->addOutput(ctx->id("WDO0"));
|
||||
new_cell->addOutput(ctx->id("WDO1"));
|
||||
new_cell->addOutput(ctx->id("WDO2"));
|
||||
new_cell->addOutput(ctx->id("WDO3"));
|
||||
new_cell->addOutput(ctx->id("WADO0"));
|
||||
new_cell->addOutput(ctx->id("WADO1"));
|
||||
new_cell->addOutput(ctx->id("WADO2"));
|
||||
new_cell->addOutput(ctx->id("WADO3"));
|
||||
} else if (type == ctx->id("TRELLIS_IO")) {
|
||||
new_cell->params[ctx->id("DIR")] = std::string("INPUT");
|
||||
new_cell->attrs[ctx->id("IO_TYPE")] = std::string("LVCMOS33");
|
||||
new_cell->params[ctx->id("DATAMUX_ODDR")] = std::string("PADDO");
|
||||
new_cell->params[ctx->id("DATAMUX_MDDR")] = std::string("PADDO");
|
||||
new_cell->addOutput(id_WDO0);
|
||||
new_cell->addOutput(id_WDO1);
|
||||
new_cell->addOutput(id_WDO2);
|
||||
new_cell->addOutput(id_WDO3);
|
||||
new_cell->addOutput(id_WADO0);
|
||||
new_cell->addOutput(id_WADO1);
|
||||
new_cell->addOutput(id_WADO2);
|
||||
new_cell->addOutput(id_WADO3);
|
||||
} else if (type == id_TRELLIS_IO) {
|
||||
new_cell->params[id_DIR] = std::string("INPUT");
|
||||
new_cell->attrs[id_IO_TYPE] = std::string("LVCMOS33");
|
||||
new_cell->params[id_DATAMUX_ODDR] = std::string("PADDO");
|
||||
new_cell->params[id_DATAMUX_MDDR] = std::string("PADDO");
|
||||
|
||||
new_cell->addInout(ctx->id("B"));
|
||||
new_cell->addInput(ctx->id("I"));
|
||||
new_cell->addInput(ctx->id("T"));
|
||||
new_cell->addOutput(ctx->id("O"));
|
||||
new_cell->addInout(id_B);
|
||||
new_cell->addInput(id_I);
|
||||
new_cell->addInput(id_T);
|
||||
new_cell->addOutput(id_O);
|
||||
|
||||
new_cell->addInput(ctx->id("IOLDO"));
|
||||
new_cell->addInput(ctx->id("IOLTO"));
|
||||
new_cell->addInput(id_IOLDO);
|
||||
new_cell->addInput(id_IOLTO);
|
||||
|
||||
} else if (type == ctx->id("LUT4")) {
|
||||
new_cell->params[ctx->id("INIT")] = Property(0, 16);
|
||||
} else if (type == id_LUT4) {
|
||||
new_cell->params[id_INIT] = Property(0, 16);
|
||||
|
||||
new_cell->addInput(ctx->id("A"));
|
||||
new_cell->addInput(ctx->id("B"));
|
||||
new_cell->addInput(ctx->id("C"));
|
||||
new_cell->addInput(ctx->id("D"));
|
||||
new_cell->addOutput(ctx->id("Z"));
|
||||
} else if (type == ctx->id("CCU2C")) {
|
||||
new_cell->params[ctx->id("INIT0")] = Property(0, 16);
|
||||
new_cell->params[ctx->id("INIT1")] = Property(0, 16);
|
||||
new_cell->params[ctx->id("INJECT1_0")] = std::string("YES");
|
||||
new_cell->params[ctx->id("INJECT1_1")] = std::string("YES");
|
||||
new_cell->addInput(id_A);
|
||||
new_cell->addInput(id_B);
|
||||
new_cell->addInput(id_C);
|
||||
new_cell->addInput(id_D);
|
||||
new_cell->addOutput(id_Z);
|
||||
} else if (type == id_CCU2C) {
|
||||
new_cell->params[id_INIT0] = Property(0, 16);
|
||||
new_cell->params[id_INIT1] = Property(0, 16);
|
||||
new_cell->params[id_INJECT1_0] = std::string("YES");
|
||||
new_cell->params[id_INJECT1_1] = std::string("YES");
|
||||
|
||||
new_cell->addInput(ctx->id("CIN"));
|
||||
new_cell->addInput(id_CIN);
|
||||
|
||||
new_cell->addInput(ctx->id("A0"));
|
||||
new_cell->addInput(ctx->id("B0"));
|
||||
new_cell->addInput(ctx->id("C0"));
|
||||
new_cell->addInput(ctx->id("D0"));
|
||||
new_cell->addInput(id_A0);
|
||||
new_cell->addInput(id_B0);
|
||||
new_cell->addInput(id_C0);
|
||||
new_cell->addInput(id_D0);
|
||||
|
||||
new_cell->addInput(ctx->id("A1"));
|
||||
new_cell->addInput(ctx->id("B1"));
|
||||
new_cell->addInput(ctx->id("C1"));
|
||||
new_cell->addInput(ctx->id("D1"));
|
||||
new_cell->addInput(id_A1);
|
||||
new_cell->addInput(id_B1);
|
||||
new_cell->addInput(id_C1);
|
||||
new_cell->addInput(id_D1);
|
||||
|
||||
new_cell->addOutput(ctx->id("S0"));
|
||||
new_cell->addOutput(ctx->id("S1"));
|
||||
new_cell->addOutput(ctx->id("COUT"));
|
||||
new_cell->addOutput(id_S0);
|
||||
new_cell->addOutput(id_S1);
|
||||
new_cell->addOutput(id_COUT);
|
||||
|
||||
} else if (type == ctx->id("DCCA")) {
|
||||
new_cell->addInput(ctx->id("CLKI"));
|
||||
new_cell->addOutput(ctx->id("CLKO"));
|
||||
new_cell->addInput(ctx->id("CE"));
|
||||
} else if (type == id_DCCA) {
|
||||
new_cell->addInput(id_CLKI);
|
||||
new_cell->addOutput(id_CLKO);
|
||||
new_cell->addInput(id_CE);
|
||||
} else if (type == id_IOLOGIC || type == id_SIOLOGIC) {
|
||||
new_cell->params[ctx->id("MODE")] = std::string("NONE");
|
||||
new_cell->params[ctx->id("GSR")] = std::string("DISABLED");
|
||||
new_cell->params[ctx->id("CLKIMUX")] = std::string("CLK");
|
||||
new_cell->params[ctx->id("CLKOMUX")] = std::string("CLK");
|
||||
new_cell->params[ctx->id("LSRIMUX")] = std::string("0");
|
||||
new_cell->params[ctx->id("LSROMUX")] = std::string("0");
|
||||
new_cell->params[ctx->id("LSRMUX")] = std::string("LSR");
|
||||
new_cell->params[id_MODE] = std::string("NONE");
|
||||
new_cell->params[id_GSR] = std::string("DISABLED");
|
||||
new_cell->params[id_CLKIMUX] = std::string("CLK");
|
||||
new_cell->params[id_CLKOMUX] = std::string("CLK");
|
||||
new_cell->params[id_LSRIMUX] = std::string("0");
|
||||
new_cell->params[id_LSROMUX] = std::string("0");
|
||||
new_cell->params[id_LSRMUX] = std::string("LSR");
|
||||
|
||||
new_cell->params[ctx->id("DELAY.OUTDEL")] = std::string("DISABLED");
|
||||
new_cell->params[ctx->id("DELAY.DEL_VALUE")] = Property(0, 7);
|
||||
@ -183,7 +183,7 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
|
||||
new_cell->params[ctx->id("MODDRX.MODE")] = std::string("NONE");
|
||||
new_cell->params[ctx->id("MTDDRX.MODE")] = std::string("NONE");
|
||||
|
||||
new_cell->params[ctx->id("IOLTOMUX")] = std::string("NONE");
|
||||
new_cell->params[id_IOLTOMUX] = std::string("NONE");
|
||||
new_cell->params[ctx->id("MTDDRX.DQSW_INVERT")] = std::string("DISABLED");
|
||||
new_cell->params[ctx->id("MTDDRX.REGSET")] = std::string("RESET");
|
||||
|
||||
@ -192,8 +192,8 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
|
||||
// Just copy ports from the Bel
|
||||
copy_bel_ports();
|
||||
} else if (type == id_TRELLIS_ECLKBUF) {
|
||||
new_cell->addInput(ctx->id("ECLKI"));
|
||||
new_cell->addOutput(ctx->id("ECLKO"));
|
||||
new_cell->addInput(id_ECLKI);
|
||||
new_cell->addOutput(id_ECLKO);
|
||||
} else {
|
||||
log_error("unable to create ECP5 cell of type %s", type.c_str(ctx));
|
||||
}
|
||||
@ -225,38 +225,38 @@ void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool drive
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = ff->hierpath;
|
||||
bool has_ff = lc->ports.at(ctx->id("Q0")).net != nullptr || lc->ports.at(ctx->id("Q1")).net != nullptr;
|
||||
bool has_ff = lc->ports.at(id_Q0).net != nullptr || lc->ports.at(id_Q1).net != nullptr;
|
||||
std::string reg = "REG" + std::to_string(index);
|
||||
set_param_safe(has_ff, lc, ctx->id("SRMODE"), str_or_default(ff->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
set_param_safe(has_ff, lc, ctx->id("GSR"), str_or_default(ff->params, ctx->id("GSR"), "DISABLED"));
|
||||
set_param_safe(has_ff, lc, ctx->id("CEMUX"), str_or_default(ff->params, ctx->id("CEMUX"), "1"));
|
||||
set_param_safe(has_ff, lc, ctx->id("LSRMUX"), str_or_default(ff->params, ctx->id("LSRMUX"), "LSR"));
|
||||
set_param_safe(has_ff, lc, ctx->id("CLKMUX"), str_or_default(ff->params, ctx->id("CLKMUX"), "CLK"));
|
||||
set_param_safe(has_ff, lc, id_SRMODE, str_or_default(ff->params, id_SRMODE, "LSR_OVER_CE"));
|
||||
set_param_safe(has_ff, lc, id_GSR, str_or_default(ff->params, id_GSR, "DISABLED"));
|
||||
set_param_safe(has_ff, lc, id_CEMUX, str_or_default(ff->params, id_CEMUX, "1"));
|
||||
set_param_safe(has_ff, lc, id_LSRMUX, str_or_default(ff->params, id_LSRMUX, "LSR"));
|
||||
set_param_safe(has_ff, lc, id_CLKMUX, str_or_default(ff->params, id_CLKMUX, "CLK"));
|
||||
|
||||
lc->params[ctx->id(reg + "_SD")] = std::string(driven_by_lut ? "1" : "0");
|
||||
lc->params[ctx->id(reg + "_REGSET")] = str_or_default(ff->params, ctx->id("REGSET"), "RESET");
|
||||
lc->params[ctx->id(reg + "_LSRMODE")] = str_or_default(ff->params, ctx->id("LSRMODE"), "LSR");
|
||||
replace_port_safe(has_ff, ff, ctx->id("CLK"), lc, ctx->id("CLK"));
|
||||
if (ff->ports.find(ctx->id("LSR")) != ff->ports.end())
|
||||
replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR"));
|
||||
if (ff->ports.find(ctx->id("CE")) != ff->ports.end())
|
||||
replace_port_safe(has_ff, ff, ctx->id("CE"), lc, ctx->id("CE"));
|
||||
lc->params[ctx->id(reg + "_REGSET")] = str_or_default(ff->params, id_REGSET, "RESET");
|
||||
lc->params[ctx->id(reg + "_LSRMODE")] = str_or_default(ff->params, id_LSRMODE, "LSR");
|
||||
replace_port_safe(has_ff, ff, id_CLK, lc, id_CLK);
|
||||
if (ff->ports.find(id_LSR) != ff->ports.end())
|
||||
replace_port_safe(has_ff, ff, id_LSR, lc, id_LSR);
|
||||
if (ff->ports.find(id_CE) != ff->ports.end())
|
||||
replace_port_safe(has_ff, ff, id_CE, lc, id_CE);
|
||||
|
||||
replace_port(ff, ctx->id("Q"), lc, ctx->id("Q" + std::to_string(index)));
|
||||
if (get_net_or_empty(ff, ctx->id("M")) != nullptr) {
|
||||
replace_port(ff, id_Q, lc, ctx->id("Q" + std::to_string(index)));
|
||||
if (get_net_or_empty(ff, id_M) != nullptr) {
|
||||
// PRLD FFs that use both M and DI
|
||||
NPNR_ASSERT(!driven_by_lut);
|
||||
// As M is used; must route DI through a new LUT
|
||||
lc->params[ctx->id(reg + "_SD")] = std::string("1");
|
||||
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = Property(0xFF00, 16);
|
||||
replace_port(ff, ctx->id("DI"), lc, ctx->id("D" + std::to_string(index)));
|
||||
replace_port(ff, ctx->id("M"), lc, ctx->id("M" + std::to_string(index)));
|
||||
replace_port(ff, id_DI, lc, ctx->id("D" + std::to_string(index)));
|
||||
replace_port(ff, id_M, lc, ctx->id("M" + std::to_string(index)));
|
||||
connect_ports(ctx, lc, ctx->id("F" + std::to_string(index)), lc, ctx->id("DI" + std::to_string(index)));
|
||||
} else {
|
||||
if (driven_by_lut) {
|
||||
replace_port(ff, ctx->id("DI"), lc, ctx->id("DI" + std::to_string(index)));
|
||||
replace_port(ff, id_DI, lc, ctx->id("DI" + std::to_string(index)));
|
||||
} else {
|
||||
replace_port(ff, ctx->id("DI"), lc, ctx->id("M" + std::to_string(index)));
|
||||
replace_port(ff, id_DI, lc, ctx->id("M" + std::to_string(index)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -266,62 +266,62 @@ void lut_to_slice(Context *ctx, CellInfo *lut, CellInfo *lc, int index)
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = lut->hierpath;
|
||||
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] =
|
||||
get_or_default(lut->params, ctx->id("INIT"), Property(0, 16));
|
||||
replace_port(lut, ctx->id("A"), lc, ctx->id("A" + std::to_string(index)));
|
||||
replace_port(lut, ctx->id("B"), lc, ctx->id("B" + std::to_string(index)));
|
||||
replace_port(lut, ctx->id("C"), lc, ctx->id("C" + std::to_string(index)));
|
||||
replace_port(lut, ctx->id("D"), lc, ctx->id("D" + std::to_string(index)));
|
||||
replace_port(lut, ctx->id("Z"), lc, ctx->id("F" + std::to_string(index)));
|
||||
get_or_default(lut->params, id_INIT, Property(0, 16));
|
||||
replace_port(lut, id_A, lc, ctx->id("A" + std::to_string(index)));
|
||||
replace_port(lut, id_B, lc, ctx->id("B" + std::to_string(index)));
|
||||
replace_port(lut, id_C, lc, ctx->id("C" + std::to_string(index)));
|
||||
replace_port(lut, id_D, lc, ctx->id("D" + std::to_string(index)));
|
||||
replace_port(lut, id_Z, lc, ctx->id("F" + std::to_string(index)));
|
||||
}
|
||||
|
||||
void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc)
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = ccu->hierpath;
|
||||
lc->params[ctx->id("MODE")] = std::string("CCU2");
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = get_or_default(ccu->params, ctx->id("INIT0"), Property(0, 16));
|
||||
lc->params[ctx->id("LUT1_INITVAL")] = get_or_default(ccu->params, ctx->id("INIT1"), Property(0, 16));
|
||||
lc->params[id_MODE] = std::string("CCU2");
|
||||
lc->params[id_LUT0_INITVAL] = get_or_default(ccu->params, id_INIT0, Property(0, 16));
|
||||
lc->params[id_LUT1_INITVAL] = get_or_default(ccu->params, id_INIT1, Property(0, 16));
|
||||
|
||||
lc->params[ctx->id("CCU2_INJECT1_0")] = str_or_default(ccu->params, ctx->id("INJECT1_0"), "YES");
|
||||
lc->params[ctx->id("CCU2_INJECT1_1")] = str_or_default(ccu->params, ctx->id("INJECT1_1"), "YES");
|
||||
lc->params[id_CCU2_INJECT1_0] = str_or_default(ccu->params, id_INJECT1_0, "YES");
|
||||
lc->params[id_CCU2_INJECT1_1] = str_or_default(ccu->params, id_INJECT1_1, "YES");
|
||||
|
||||
replace_port(ccu, ctx->id("CIN"), lc, ctx->id("FCI"));
|
||||
replace_port(ccu, id_CIN, lc, id_FCI);
|
||||
|
||||
replace_port(ccu, ctx->id("A0"), lc, ctx->id("A0"));
|
||||
replace_port(ccu, ctx->id("B0"), lc, ctx->id("B0"));
|
||||
replace_port(ccu, ctx->id("C0"), lc, ctx->id("C0"));
|
||||
replace_port(ccu, ctx->id("D0"), lc, ctx->id("D0"));
|
||||
replace_port(ccu, id_A0, lc, id_A0);
|
||||
replace_port(ccu, id_B0, lc, id_B0);
|
||||
replace_port(ccu, id_C0, lc, id_C0);
|
||||
replace_port(ccu, id_D0, lc, id_D0);
|
||||
|
||||
replace_port(ccu, ctx->id("A1"), lc, ctx->id("A1"));
|
||||
replace_port(ccu, ctx->id("B1"), lc, ctx->id("B1"));
|
||||
replace_port(ccu, ctx->id("C1"), lc, ctx->id("C1"));
|
||||
replace_port(ccu, ctx->id("D1"), lc, ctx->id("D1"));
|
||||
replace_port(ccu, id_A1, lc, id_A1);
|
||||
replace_port(ccu, id_B1, lc, id_B1);
|
||||
replace_port(ccu, id_C1, lc, id_C1);
|
||||
replace_port(ccu, id_D1, lc, id_D1);
|
||||
|
||||
replace_port(ccu, ctx->id("S0"), lc, ctx->id("F0"));
|
||||
replace_port(ccu, ctx->id("S1"), lc, ctx->id("F1"));
|
||||
replace_port(ccu, id_S0, lc, id_F0);
|
||||
replace_port(ccu, id_S1, lc, id_F1);
|
||||
|
||||
replace_port(ccu, ctx->id("COUT"), lc, ctx->id("FCO"));
|
||||
replace_port(ccu, id_COUT, lc, id_FCO);
|
||||
}
|
||||
|
||||
void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc)
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = ram->hierpath;
|
||||
lc->params[ctx->id("MODE")] = std::string("RAMW");
|
||||
replace_port(ram, ctx->id("WAD[0]"), lc, ctx->id("D0"));
|
||||
replace_port(ram, ctx->id("WAD[1]"), lc, ctx->id("B0"));
|
||||
replace_port(ram, ctx->id("WAD[2]"), lc, ctx->id("C0"));
|
||||
replace_port(ram, ctx->id("WAD[3]"), lc, ctx->id("A0"));
|
||||
lc->params[id_MODE] = std::string("RAMW");
|
||||
replace_port(ram, ctx->id("WAD[0]"), lc, id_D0);
|
||||
replace_port(ram, ctx->id("WAD[1]"), lc, id_B0);
|
||||
replace_port(ram, ctx->id("WAD[2]"), lc, id_C0);
|
||||
replace_port(ram, ctx->id("WAD[3]"), lc, id_A0);
|
||||
|
||||
replace_port(ram, ctx->id("DI[0]"), lc, ctx->id("C1"));
|
||||
replace_port(ram, ctx->id("DI[1]"), lc, ctx->id("A1"));
|
||||
replace_port(ram, ctx->id("DI[2]"), lc, ctx->id("D1"));
|
||||
replace_port(ram, ctx->id("DI[3]"), lc, ctx->id("B1"));
|
||||
replace_port(ram, ctx->id("DI[0]"), lc, id_C1);
|
||||
replace_port(ram, ctx->id("DI[1]"), lc, id_A1);
|
||||
replace_port(ram, ctx->id("DI[2]"), lc, id_D1);
|
||||
replace_port(ram, ctx->id("DI[3]"), lc, id_B1);
|
||||
}
|
||||
|
||||
static unsigned get_dram_init(const Context *ctx, const CellInfo *ram, int bit)
|
||||
{
|
||||
auto init_prop = get_or_default(ram->params, ctx->id("INITVAL"), Property(0, 64));
|
||||
auto init_prop = get_or_default(ram->params, id_INITVAL, Property(0, 64));
|
||||
NPNR_ASSERT(!init_prop.is_string);
|
||||
const std::string &idata = init_prop.str;
|
||||
NPNR_ASSERT(idata.length() == 64);
|
||||
@ -340,9 +340,9 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = ram->hierpath;
|
||||
lc->params[ctx->id("MODE")] = std::string("DPRAM");
|
||||
lc->params[ctx->id("WREMUX")] = str_or_default(ram->params, ctx->id("WREMUX"), "WRE");
|
||||
lc->params[ctx->id("WCKMUX")] = str_or_default(ram->params, ctx->id("WCKMUX"), "WCK");
|
||||
lc->params[id_MODE] = std::string("DPRAM");
|
||||
lc->params[id_WREMUX] = str_or_default(ram->params, id_WREMUX, "WRE");
|
||||
lc->params[id_WCKMUX] = str_or_default(ram->params, id_WCKMUX, "WCK");
|
||||
|
||||
unsigned permuted_init0 = 0, permuted_init1 = 0;
|
||||
unsigned init0 = get_dram_init(ctx, ram, index * 2), init1 = get_dram_init(ctx, ram, index * 2 + 1);
|
||||
@ -363,30 +363,30 @@ void dram_to_ram_slice(Context *ctx, CellInfo *ram, CellInfo *lc, CellInfo *ramw
|
||||
permuted_init1 |= (1 << i);
|
||||
}
|
||||
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = Property(permuted_init0, 16);
|
||||
lc->params[ctx->id("LUT1_INITVAL")] = Property(permuted_init1, 16);
|
||||
lc->params[id_LUT0_INITVAL] = Property(permuted_init0, 16);
|
||||
lc->params[id_LUT1_INITVAL] = Property(permuted_init1, 16);
|
||||
|
||||
if (ram->ports.count(ctx->id("RAD[0]"))) {
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, ctx->id("D0"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, ctx->id("D1"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, id_D0);
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[0]")).net, lc, id_D1);
|
||||
}
|
||||
if (ram->ports.count(ctx->id("RAD[1]"))) {
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, ctx->id("B0"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, ctx->id("B1"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, id_B0);
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[1]")).net, lc, id_B1);
|
||||
}
|
||||
if (ram->ports.count(ctx->id("RAD[2]"))) {
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, ctx->id("C0"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, ctx->id("C1"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, id_C0);
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[2]")).net, lc, id_C1);
|
||||
}
|
||||
if (ram->ports.count(ctx->id("RAD[3]"))) {
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, ctx->id("A0"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, ctx->id("A1"));
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, id_A0);
|
||||
connect_port(ctx, ram->ports.at(ctx->id("RAD[3]")).net, lc, id_A1);
|
||||
}
|
||||
|
||||
if (ram->ports.count(ctx->id("WRE")))
|
||||
connect_port(ctx, ram->ports.at(ctx->id("WRE")).net, lc, ctx->id("WRE"));
|
||||
if (ram->ports.count(ctx->id("WCK")))
|
||||
connect_port(ctx, ram->ports.at(ctx->id("WCK")).net, lc, ctx->id("WCK"));
|
||||
if (ram->ports.count(id_WRE))
|
||||
connect_port(ctx, ram->ports.at(id_WRE).net, lc, id_WRE);
|
||||
if (ram->ports.count(id_WCK))
|
||||
connect_port(ctx, ram->ports.at(id_WCK).net, lc, id_WCK);
|
||||
|
||||
connect_ports(ctx, ramw, id_WADO0, lc, id_WAD0);
|
||||
connect_ports(ctx, ramw, id_WADO1, lc, id_WAD1);
|
||||
@ -415,26 +415,26 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
|
||||
pool<IdString> &todelete_cells)
|
||||
{
|
||||
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
|
||||
trio->params[ctx->id("DIR")] = std::string("INPUT");
|
||||
replace_port(nxio, ctx->id("O"), trio, ctx->id("O"));
|
||||
trio->params[id_DIR] = std::string("INPUT");
|
||||
replace_port(nxio, id_O, trio, id_O);
|
||||
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
|
||||
trio->params[ctx->id("DIR")] = std::string("OUTPUT");
|
||||
replace_port(nxio, ctx->id("I"), trio, ctx->id("I"));
|
||||
trio->params[id_DIR] = std::string("OUTPUT");
|
||||
replace_port(nxio, id_I, trio, id_I);
|
||||
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
|
||||
// N.B. tristate will be dealt with below
|
||||
NetInfo *i = get_net_or_empty(nxio, ctx->id("I"));
|
||||
NetInfo *i = get_net_or_empty(nxio, id_I);
|
||||
if (i == nullptr || i->driver.cell == nullptr)
|
||||
trio->params[ctx->id("DIR")] = std::string("INPUT");
|
||||
trio->params[id_DIR] = std::string("INPUT");
|
||||
else {
|
||||
log_info("%s: %s.%s\n", ctx->nameOf(i), ctx->nameOf(i->driver.cell), ctx->nameOf(i->driver.port));
|
||||
trio->params[ctx->id("DIR")] = std::string("BIDIR");
|
||||
trio->params[id_DIR] = std::string("BIDIR");
|
||||
}
|
||||
replace_port(nxio, ctx->id("I"), trio, ctx->id("I"));
|
||||
replace_port(nxio, ctx->id("O"), trio, ctx->id("O"));
|
||||
replace_port(nxio, id_I, trio, id_I);
|
||||
replace_port(nxio, id_O, trio, id_O);
|
||||
} else {
|
||||
NPNR_ASSERT(false);
|
||||
}
|
||||
NetInfo *donet = trio->ports.at(ctx->id("I")).net, *dinet = trio->ports.at(ctx->id("O")).net;
|
||||
NetInfo *donet = trio->ports.at(id_I).net, *dinet = trio->ports.at(id_O).net;
|
||||
|
||||
// Rename I/O nets to avoid conflicts
|
||||
if (donet != nullptr && donet->name == nxio->name)
|
||||
@ -458,20 +458,20 @@ void nxio_to_tr(Context *ctx, CellInfo *nxio, CellInfo *trio, std::vector<std::u
|
||||
ctx->net_aliases.erase(tn_netname);
|
||||
NetInfo *toplevel_net = ctx->createNet(tn_netname);
|
||||
toplevel_net->name = tn_netname;
|
||||
connect_port(ctx, toplevel_net, trio, ctx->id("B"));
|
||||
connect_port(ctx, toplevel_net, trio, id_B);
|
||||
ctx->ports[nxio->name].net = toplevel_net;
|
||||
}
|
||||
|
||||
CellInfo *tbuf = net_driven_by(
|
||||
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
||||
ctx->id("Y"));
|
||||
id_Y);
|
||||
if (tbuf) {
|
||||
replace_port(tbuf, ctx->id("A"), trio, ctx->id("I"));
|
||||
replace_port(tbuf, id_A, trio, id_I);
|
||||
// Need to invert E to form T
|
||||
std::unique_ptr<CellInfo> inv_lut = create_ecp5_cell(ctx, ctx->id("LUT4"), trio->name.str(ctx) + "$invert_T");
|
||||
replace_port(tbuf, ctx->id("E"), inv_lut.get(), ctx->id("A"));
|
||||
inv_lut->params[ctx->id("INIT")] = Property(21845, 16);
|
||||
connect_ports(ctx, inv_lut.get(), ctx->id("Z"), trio, ctx->id("T"));
|
||||
std::unique_ptr<CellInfo> inv_lut = create_ecp5_cell(ctx, id_LUT4, trio->name.str(ctx) + "$invert_T");
|
||||
replace_port(tbuf, id_E, inv_lut.get(), id_A);
|
||||
inv_lut->params[id_INIT] = Property(21845, 16);
|
||||
connect_ports(ctx, inv_lut.get(), id_Z, trio, id_T);
|
||||
created_cells.push_back(std::move(inv_lut));
|
||||
|
||||
if (donet->users.size() > 1) {
|
||||
|
33
ecp5/cells.h
33
ecp5/cells.h
@ -30,37 +30,36 @@ NEXTPNR_NAMESPACE_BEGIN
|
||||
std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::string name = "");
|
||||
|
||||
// Return true if a cell is a LUT
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("LUT4"); }
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_LUT4; }
|
||||
|
||||
// Return true if a cell is a flipflop
|
||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("TRELLIS_FF"); }
|
||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_TRELLIS_FF; }
|
||||
|
||||
inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("CCU2C"); }
|
||||
inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_CCU2C; }
|
||||
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("TRELLIS_SLICE"); }
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_TRELLIS_SLICE; }
|
||||
|
||||
inline bool is_trellis_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("TRELLIS_IO"); }
|
||||
inline bool is_trellis_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_TRELLIS_IO; }
|
||||
|
||||
inline bool is_dpram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("TRELLIS_DPR16X4"); }
|
||||
inline bool is_dpram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_TRELLIS_DPR16X4; }
|
||||
|
||||
inline bool is_pfumx(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("PFUMX"); }
|
||||
inline bool is_pfumx(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_PFUMX; }
|
||||
|
||||
inline bool is_l6mux(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("L6MUX21"); }
|
||||
inline bool is_l6mux(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_L6MUX21; }
|
||||
|
||||
inline bool is_iologic_input_cell(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("IDDRX1F") || cell->type == ctx->id("IDDRX2F") || cell->type == ctx->id("IDDR71B") ||
|
||||
cell->type == ctx->id("IDDRX2DQA") ||
|
||||
(cell->type == ctx->id("TRELLIS_FF") && bool_or_default(cell->attrs, ctx->id("syn_useioff")) &&
|
||||
(str_or_default(cell->attrs, ctx->id("ioff_dir"), "") != "output"));
|
||||
return cell->type == id_IDDRX1F || cell->type == id_IDDRX2F || cell->type == id_IDDR71B ||
|
||||
cell->type == id_IDDRX2DQA ||
|
||||
(cell->type == id_TRELLIS_FF && bool_or_default(cell->attrs, id_syn_useioff) &&
|
||||
(str_or_default(cell->attrs, id_ioff_dir, "") != "output"));
|
||||
}
|
||||
inline bool is_iologic_output_cell(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("ODDRX1F") || cell->type == ctx->id("ODDRX2F") || cell->type == ctx->id("ODDR71B") ||
|
||||
cell->type == ctx->id("ODDRX2DQA") || cell->type == ctx->id("ODDRX2DQSB") ||
|
||||
cell->type == ctx->id("OSHX2A") ||
|
||||
(cell->type == ctx->id("TRELLIS_FF") && bool_or_default(cell->attrs, ctx->id("syn_useioff")) &&
|
||||
(str_or_default(cell->attrs, ctx->id("ioff_dir"), "") != "input"));
|
||||
return cell->type == id_ODDRX1F || cell->type == id_ODDRX2F || cell->type == id_ODDR71B ||
|
||||
cell->type == id_ODDRX2DQA || cell->type == id_ODDRX2DQSB || cell->type == id_OSHX2A ||
|
||||
(cell->type == id_TRELLIS_FF && bool_or_default(cell->attrs, id_syn_useioff) &&
|
||||
(str_or_default(cell->attrs, id_ioff_dir, "") != "input"));
|
||||
}
|
||||
|
||||
void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut);
|
||||
|
@ -1341,3 +1341,513 @@ X(IOLOGIC_MODE_TSREG)
|
||||
X(DCSC)
|
||||
X(DCSOUT)
|
||||
X(MODESEL)
|
||||
|
||||
X(ALUT)
|
||||
X(ASYNC_RESET_RELEASE)
|
||||
X(BEL)
|
||||
X(BLUT)
|
||||
X(C)
|
||||
X(CCU2C)
|
||||
X(CCU2_INJECT1_0)
|
||||
X(CCU2_INJECT1_1)
|
||||
X(CEAMUX)
|
||||
X(CEBMUX)
|
||||
X(CEIMUX)
|
||||
X(CEMUX)
|
||||
X(CEOMUX)
|
||||
X(CER)
|
||||
X(CEW)
|
||||
X(CH0_AUTO_CALIB_EN)
|
||||
X(CH0_AUTO_FACQ_EN)
|
||||
X(CH0_BAND_THRESHOLD)
|
||||
X(CH0_CALIB_CK_MODE)
|
||||
X(CH0_CC_MATCH_1)
|
||||
X(CH0_CC_MATCH_2)
|
||||
X(CH0_CC_MATCH_3)
|
||||
X(CH0_CC_MATCH_4)
|
||||
X(CH0_CDR_CNT4SEL)
|
||||
X(CH0_CDR_CNT8SEL)
|
||||
X(CH0_CTC_BYPASS)
|
||||
X(CH0_DCOATDCFG)
|
||||
X(CH0_DCOATDDLY)
|
||||
X(CH0_DCOBYPSATD)
|
||||
X(CH0_DCOCALDIV)
|
||||
X(CH0_DCOCTLGI)
|
||||
X(CH0_DCODISBDAVOID)
|
||||
X(CH0_DCOFLTDAC)
|
||||
X(CH0_DCOFTNRG)
|
||||
X(CH0_DCOIOSTUNE)
|
||||
X(CH0_DCOITUNE)
|
||||
X(CH0_DCOITUNE4LSB)
|
||||
X(CH0_DCOIUPDNX2)
|
||||
X(CH0_DCONUOFLSB)
|
||||
X(CH0_DCOSCALEI)
|
||||
X(CH0_DCOSTARTVAL)
|
||||
X(CH0_DCOSTEP)
|
||||
X(CH0_DEC_BYPASS)
|
||||
X(CH0_ENABLE_CG_ALIGN)
|
||||
X(CH0_ENC_BYPASS)
|
||||
X(CH0_FF_RX_F_CLK_DIS)
|
||||
X(CH0_FF_RX_H_CLK_EN)
|
||||
X(CH0_FF_TX_F_CLK_DIS)
|
||||
X(CH0_FF_TX_H_CLK_EN)
|
||||
X(CH0_GE_AN_ENABLE)
|
||||
X(CH0_INVERT_RX)
|
||||
X(CH0_INVERT_TX)
|
||||
X(CH0_LDR_CORE2TX_SEL)
|
||||
X(CH0_LDR_RX2CORE_SEL)
|
||||
X(CH0_LEQ_OFFSET_SEL)
|
||||
X(CH0_LEQ_OFFSET_TRIM)
|
||||
X(CH0_LSM_DISABLE)
|
||||
X(CH0_MATCH_2_ENABLE)
|
||||
X(CH0_MATCH_4_ENABLE)
|
||||
X(CH0_MIN_IPG_CNT)
|
||||
X(CH0_PCIE_EI_EN)
|
||||
X(CH0_PCIE_MODE)
|
||||
X(CH0_PCS_DET_TIME_SEL)
|
||||
X(CH0_PDEN_SEL)
|
||||
X(CH0_PRBS_ENABLE)
|
||||
X(CH0_PRBS_LOCK)
|
||||
X(CH0_PRBS_SELECTION)
|
||||
X(CH0_RATE_MODE_RX)
|
||||
X(CH0_RATE_MODE_TX)
|
||||
X(CH0_RCV_DCC_EN)
|
||||
X(CH0_REG_BAND_OFFSET)
|
||||
X(CH0_REG_BAND_SEL)
|
||||
X(CH0_REG_IDAC_EN)
|
||||
X(CH0_REG_IDAC_SEL)
|
||||
X(CH0_REQ_EN)
|
||||
X(CH0_REQ_LVL_SET)
|
||||
X(CH0_RIO_MODE)
|
||||
X(CH0_RLOS_SEL)
|
||||
X(CH0_RPWDNB)
|
||||
X(CH0_RTERM_RX)
|
||||
X(CH0_RTERM_TX)
|
||||
X(CH0_RXIN_CM)
|
||||
X(CH0_RXTERM_CM)
|
||||
X(CH0_RX_DCO_CK_DIV)
|
||||
X(CH0_RX_DIV11_SEL)
|
||||
X(CH0_RX_GEAR_BYPASS)
|
||||
X(CH0_RX_GEAR_MODE)
|
||||
X(CH0_RX_LOS_CEQ)
|
||||
X(CH0_RX_LOS_EN)
|
||||
X(CH0_RX_LOS_HYST_EN)
|
||||
X(CH0_RX_LOS_LVL)
|
||||
X(CH0_RX_RATE_SEL)
|
||||
X(CH0_RX_SB_BYPASS)
|
||||
X(CH0_SB_BYPASS)
|
||||
X(CH0_SEL_SD_RX_CLK)
|
||||
X(CH0_TDRV_DAT_SEL)
|
||||
X(CH0_TDRV_POST_EN)
|
||||
X(CH0_TDRV_PRE_EN)
|
||||
X(CH0_TDRV_SLICE0_CUR)
|
||||
X(CH0_TDRV_SLICE0_SEL)
|
||||
X(CH0_TDRV_SLICE1_CUR)
|
||||
X(CH0_TDRV_SLICE1_SEL)
|
||||
X(CH0_TDRV_SLICE2_CUR)
|
||||
X(CH0_TDRV_SLICE2_SEL)
|
||||
X(CH0_TDRV_SLICE3_CUR)
|
||||
X(CH0_TDRV_SLICE3_SEL)
|
||||
X(CH0_TDRV_SLICE4_CUR)
|
||||
X(CH0_TDRV_SLICE4_SEL)
|
||||
X(CH0_TDRV_SLICE5_CUR)
|
||||
X(CH0_TDRV_SLICE5_SEL)
|
||||
X(CH0_TPWDNB)
|
||||
X(CH0_TX_CM_SEL)
|
||||
X(CH0_TX_DIV11_SEL)
|
||||
X(CH0_TX_GEAR_BYPASS)
|
||||
X(CH0_TX_GEAR_MODE)
|
||||
X(CH0_TX_POST_SIGN)
|
||||
X(CH0_TX_PRE_SIGN)
|
||||
X(CH0_UC_MODE)
|
||||
X(CH0_UDF_COMMA_A)
|
||||
X(CH0_UDF_COMMA_B)
|
||||
X(CH0_UDF_COMMA_MASK)
|
||||
X(CH0_WA_BYPASS)
|
||||
X(CH0_WA_MODE)
|
||||
X(CH1_AUTO_CALIB_EN)
|
||||
X(CH1_AUTO_FACQ_EN)
|
||||
X(CH1_BAND_THRESHOLD)
|
||||
X(CH1_CALIB_CK_MODE)
|
||||
X(CH1_CC_MATCH_1)
|
||||
X(CH1_CC_MATCH_2)
|
||||
X(CH1_CC_MATCH_3)
|
||||
X(CH1_CC_MATCH_4)
|
||||
X(CH1_CDR_CNT4SEL)
|
||||
X(CH1_CDR_CNT8SEL)
|
||||
X(CH1_CTC_BYPASS)
|
||||
X(CH1_DCOATDCFG)
|
||||
X(CH1_DCOATDDLY)
|
||||
X(CH1_DCOBYPSATD)
|
||||
X(CH1_DCOCALDIV)
|
||||
X(CH1_DCOCTLGI)
|
||||
X(CH1_DCODISBDAVOID)
|
||||
X(CH1_DCOFLTDAC)
|
||||
X(CH1_DCOFTNRG)
|
||||
X(CH1_DCOIOSTUNE)
|
||||
X(CH1_DCOITUNE)
|
||||
X(CH1_DCOITUNE4LSB)
|
||||
X(CH1_DCOIUPDNX2)
|
||||
X(CH1_DCONUOFLSB)
|
||||
X(CH1_DCOSCALEI)
|
||||
X(CH1_DCOSTARTVAL)
|
||||
X(CH1_DCOSTEP)
|
||||
X(CH1_DEC_BYPASS)
|
||||
X(CH1_ENABLE_CG_ALIGN)
|
||||
X(CH1_ENC_BYPASS)
|
||||
X(CH1_FF_RX_F_CLK_DIS)
|
||||
X(CH1_FF_RX_H_CLK_EN)
|
||||
X(CH1_FF_TX_F_CLK_DIS)
|
||||
X(CH1_FF_TX_H_CLK_EN)
|
||||
X(CH1_GE_AN_ENABLE)
|
||||
X(CH1_INVERT_RX)
|
||||
X(CH1_INVERT_TX)
|
||||
X(CH1_LDR_CORE2TX_SEL)
|
||||
X(CH1_LDR_RX2CORE_SEL)
|
||||
X(CH1_LEQ_OFFSET_SEL)
|
||||
X(CH1_LEQ_OFFSET_TRIM)
|
||||
X(CH1_LSM_DISABLE)
|
||||
X(CH1_MATCH_2_ENABLE)
|
||||
X(CH1_MATCH_4_ENABLE)
|
||||
X(CH1_MIN_IPG_CNT)
|
||||
X(CH1_PCIE_EI_EN)
|
||||
X(CH1_PCIE_MODE)
|
||||
X(CH1_PCS_DET_TIME_SEL)
|
||||
X(CH1_PDEN_SEL)
|
||||
X(CH1_PRBS_ENABLE)
|
||||
X(CH1_PRBS_LOCK)
|
||||
X(CH1_PRBS_SELECTION)
|
||||
X(CH1_RATE_MODE_RX)
|
||||
X(CH1_RATE_MODE_TX)
|
||||
X(CH1_RCV_DCC_EN)
|
||||
X(CH1_REG_BAND_OFFSET)
|
||||
X(CH1_REG_BAND_SEL)
|
||||
X(CH1_REG_IDAC_EN)
|
||||
X(CH1_REG_IDAC_SEL)
|
||||
X(CH1_REQ_EN)
|
||||
X(CH1_REQ_LVL_SET)
|
||||
X(CH1_RIO_MODE)
|
||||
X(CH1_RLOS_SEL)
|
||||
X(CH1_RPWDNB)
|
||||
X(CH1_RTERM_RX)
|
||||
X(CH1_RTERM_TX)
|
||||
X(CH1_RXIN_CM)
|
||||
X(CH1_RXTERM_CM)
|
||||
X(CH1_RX_DCO_CK_DIV)
|
||||
X(CH1_RX_DIV11_SEL)
|
||||
X(CH1_RX_GEAR_BYPASS)
|
||||
X(CH1_RX_GEAR_MODE)
|
||||
X(CH1_RX_LOS_CEQ)
|
||||
X(CH1_RX_LOS_EN)
|
||||
X(CH1_RX_LOS_HYST_EN)
|
||||
X(CH1_RX_LOS_LVL)
|
||||
X(CH1_RX_RATE_SEL)
|
||||
X(CH1_RX_SB_BYPASS)
|
||||
X(CH1_SB_BYPASS)
|
||||
X(CH1_SEL_SD_RX_CLK)
|
||||
X(CH1_TDRV_DAT_SEL)
|
||||
X(CH1_TDRV_POST_EN)
|
||||
X(CH1_TDRV_PRE_EN)
|
||||
X(CH1_TDRV_SLICE0_CUR)
|
||||
X(CH1_TDRV_SLICE0_SEL)
|
||||
X(CH1_TDRV_SLICE1_CUR)
|
||||
X(CH1_TDRV_SLICE1_SEL)
|
||||
X(CH1_TDRV_SLICE2_CUR)
|
||||
X(CH1_TDRV_SLICE2_SEL)
|
||||
X(CH1_TDRV_SLICE3_CUR)
|
||||
X(CH1_TDRV_SLICE3_SEL)
|
||||
X(CH1_TDRV_SLICE4_CUR)
|
||||
X(CH1_TDRV_SLICE4_SEL)
|
||||
X(CH1_TDRV_SLICE5_CUR)
|
||||
X(CH1_TDRV_SLICE5_SEL)
|
||||
X(CH1_TPWDNB)
|
||||
X(CH1_TX_CM_SEL)
|
||||
X(CH1_TX_DIV11_SEL)
|
||||
X(CH1_TX_GEAR_BYPASS)
|
||||
X(CH1_TX_GEAR_MODE)
|
||||
X(CH1_TX_POST_SIGN)
|
||||
X(CH1_TX_PRE_SIGN)
|
||||
X(CH1_UC_MODE)
|
||||
X(CH1_UDF_COMMA_A)
|
||||
X(CH1_UDF_COMMA_B)
|
||||
X(CH1_UDF_COMMA_MASK)
|
||||
X(CH1_WA_BYPASS)
|
||||
X(CH1_WA_MODE)
|
||||
X(CIN)
|
||||
X(CLAMP)
|
||||
X(CLK0_DIV)
|
||||
X(CLK1_DIV)
|
||||
X(CLK2_DIV)
|
||||
X(CLK3_DIV)
|
||||
X(CLKAMUX)
|
||||
X(CLKBMUX)
|
||||
X(CLKFB_DIV)
|
||||
X(CLKIMUX)
|
||||
X(CLKI_DIV)
|
||||
X(CLKOMUX)
|
||||
X(CLKOP_DIV)
|
||||
X(CLKOP_ENABLE)
|
||||
X(CLKOP_TRIM_DELAY)
|
||||
X(CLKOP_TRIM_POL)
|
||||
X(CLKOS2_DIV)
|
||||
X(CLKOS2_ENABLE)
|
||||
X(CLKOS3_DIV)
|
||||
X(CLKOS3_ENABLE)
|
||||
X(CLKOS_DIV)
|
||||
X(CLKOS_ENABLE)
|
||||
X(CLKOS_TRIM_DELAY)
|
||||
X(CLKOS_TRIM_POL)
|
||||
X(CLKR)
|
||||
X(CLKW)
|
||||
X(COUT)
|
||||
X(CSDECODE_A)
|
||||
X(CSDECODE_B)
|
||||
X(D)
|
||||
X(D2)
|
||||
X(D3)
|
||||
X(D4)
|
||||
X(D5)
|
||||
X(D6)
|
||||
X(DATAMUX_MDDR)
|
||||
X(DATAMUX_ODDR)
|
||||
X(DATAMUX_OREG)
|
||||
X(DATA_WIDTH_A)
|
||||
X(DATA_WIDTH_B)
|
||||
X(DATA_WIDTH_W)
|
||||
X(DCSMODE)
|
||||
X(DDRDLLA)
|
||||
X(DELAYF)
|
||||
X(DELAYG)
|
||||
X(DEL_MODE)
|
||||
X(DEL_VALUE)
|
||||
X(DIFFRESISTOR)
|
||||
X(DIR)
|
||||
X(DIV)
|
||||
X(DPHASE_SOURCE)
|
||||
X(DQS_LI_DEL_ADJ)
|
||||
X(DQS_LI_DEL_VAL)
|
||||
X(DQS_LO_DEL_ADJ)
|
||||
X(DQS_LO_DEL_VAL)
|
||||
X(DRIVE)
|
||||
X(D_BITCLK_FROM_ND_EN)
|
||||
X(D_BITCLK_LOCAL_EN)
|
||||
X(D_BITCLK_ND_EN)
|
||||
X(D_BUS8BIT_SEL)
|
||||
X(D_CDR_LOL_SET)
|
||||
X(D_CMUSETBIASI)
|
||||
X(D_CMUSETI4CPP)
|
||||
X(D_CMUSETI4CPZ)
|
||||
X(D_CMUSETI4VCO)
|
||||
X(D_CMUSETICP4P)
|
||||
X(D_CMUSETICP4Z)
|
||||
X(D_CMUSETINITVCT)
|
||||
X(D_CMUSETISCL4VCO)
|
||||
X(D_CMUSETP1GM)
|
||||
X(D_CMUSETP2AGM)
|
||||
X(D_CMUSETZGM)
|
||||
X(D_DCO_CALIB_TIME_SEL)
|
||||
X(D_HIGH_MARK)
|
||||
X(D_IB_PWDNB)
|
||||
X(D_ISETLOS)
|
||||
X(D_LOW_MARK)
|
||||
X(D_MACROPDB)
|
||||
X(D_PD_ISET)
|
||||
X(D_PLL_LOL_SET)
|
||||
X(D_REFCK_MODE)
|
||||
X(D_REQ_ISET)
|
||||
X(D_RG_EN)
|
||||
X(D_RG_SET)
|
||||
X(D_SETICONST_AUX)
|
||||
X(D_SETICONST_CH)
|
||||
X(D_SETIRPOLY_AUX)
|
||||
X(D_SETIRPOLY_CH)
|
||||
X(D_SETPLLRC)
|
||||
X(D_SYNC_LOCAL_EN)
|
||||
X(D_SYNC_ND_EN)
|
||||
X(D_TXPLL_PWDNB)
|
||||
X(D_TX_VCO_CK_DIV)
|
||||
X(D_XGE_MODE)
|
||||
X(E)
|
||||
X(ECP5_IS_GLOBAL)
|
||||
X(ER1)
|
||||
X(ER2)
|
||||
X(FEEDBK_PATH)
|
||||
X(FORCE_MAX_DELAY)
|
||||
X(FORCE_ZERO_BARREL_SHIFT)
|
||||
X(FREQ_LOCK_ACCURACY)
|
||||
X(GND)
|
||||
X(HYSTERESIS)
|
||||
X(ICP_CURRENT)
|
||||
X(IDDR71B)
|
||||
X(IDDRX1F)
|
||||
X(IDDRX2DQA)
|
||||
X(IDDRX2F)
|
||||
X(INIT)
|
||||
X(INIT0)
|
||||
X(INIT1)
|
||||
X(INITVAL)
|
||||
X(INJECT1_0)
|
||||
X(INJECT1_1)
|
||||
X(INTFB_WAKE)
|
||||
X(INT_LOCK_STICKY)
|
||||
X(INV)
|
||||
X(IOLTOMUX)
|
||||
X(IO_TYPE)
|
||||
X(KVCO)
|
||||
X(L6MUX21)
|
||||
X(LEGACY)
|
||||
X(LOC)
|
||||
X(LPF_CAPACITOR)
|
||||
X(LPF_RESISTOR)
|
||||
X(LSRIMUX)
|
||||
X(LSRMODE)
|
||||
X(LSROMUX)
|
||||
X(LUT0_INITVAL)
|
||||
X(LUT1_INITVAL)
|
||||
X(LUT4)
|
||||
X(M)
|
||||
X(MASK01)
|
||||
X(MASKPAT)
|
||||
X(MASKPAT_SOURCE)
|
||||
X(MCPAT)
|
||||
X(MCPAT_SOURCE)
|
||||
X(MFG1_TEST)
|
||||
X(MFG2_TEST)
|
||||
X(MFG_ENABLE_FILTEROPAMP)
|
||||
X(MFG_EN_UP)
|
||||
X(MFG_FLOAT_ICP)
|
||||
X(MFG_FORCE_VFILTER)
|
||||
X(MFG_GMCREF_SEL)
|
||||
X(MFG_GMC_GAIN)
|
||||
X(MFG_GMC_PRESET)
|
||||
X(MFG_GMC_RESET)
|
||||
X(MFG_GMC_TEST)
|
||||
X(MFG_ICP_TEST)
|
||||
X(MFG_LF_PRESET)
|
||||
X(MFG_LF_RESET)
|
||||
X(MFG_LF_RESGRND)
|
||||
X(MODE)
|
||||
X(MULT_BYPASS)
|
||||
X(OCEAMUX)
|
||||
X(OCEBMUX)
|
||||
X(OCER)
|
||||
X(ODDR71B)
|
||||
X(ODDRX1F)
|
||||
X(ODDRX2DQA)
|
||||
X(ODDRX2DQSB)
|
||||
X(ODDRX2F)
|
||||
X(OPENDRAIN)
|
||||
X(OSHX2A)
|
||||
X(OUTDIVIDER_MUXA)
|
||||
X(OUTDIVIDER_MUXB)
|
||||
X(OUTDIVIDER_MUXC)
|
||||
X(OUTDIVIDER_MUXD)
|
||||
X(PDPW16KD)
|
||||
X(PFUMX)
|
||||
X(PLLRST_ENA)
|
||||
X(PLL_LOCK_MODE)
|
||||
X(PULLMODE)
|
||||
X(Q)
|
||||
X(Q2)
|
||||
X(Q3)
|
||||
X(Q4)
|
||||
X(Q5)
|
||||
X(Q6)
|
||||
X(QWL)
|
||||
X(REFCK_DCBIAS_EN)
|
||||
X(REFCK_PWDNB)
|
||||
X(REFCK_RTERM)
|
||||
X(REFIN_RESET)
|
||||
X(REG0_LSRMODE)
|
||||
X(REG0_REGSET)
|
||||
X(REG0_SD)
|
||||
X(REG1_LSRMODE)
|
||||
X(REG1_REGSET)
|
||||
X(REG1_SD)
|
||||
X(REGMODE)
|
||||
X(REGMODE_A)
|
||||
X(REGMODE_B)
|
||||
X(REGSET)
|
||||
X(REG_FLAG_CLK)
|
||||
X(REG_INPUTA_CE)
|
||||
X(REG_INPUTA_CLK)
|
||||
X(REG_INPUTA_RST)
|
||||
X(REG_INPUTB_CE)
|
||||
X(REG_INPUTB_CLK)
|
||||
X(REG_INPUTB_RST)
|
||||
X(REG_INPUTC0_CLK)
|
||||
X(REG_INPUTC1_CLK)
|
||||
X(REG_INPUTC_CLK)
|
||||
X(REG_OPCODEIN_0_CE)
|
||||
X(REG_OPCODEIN_0_CLK)
|
||||
X(REG_OPCODEIN_0_RST)
|
||||
X(REG_OPCODEIN_1_CE)
|
||||
X(REG_OPCODEIN_1_CLK)
|
||||
X(REG_OPCODEIN_1_RST)
|
||||
X(REG_OPCODEOP0_0_CE)
|
||||
X(REG_OPCODEOP0_0_CLK)
|
||||
X(REG_OPCODEOP0_0_RST)
|
||||
X(REG_OPCODEOP0_1_CE)
|
||||
X(REG_OPCODEOP0_1_CLK)
|
||||
X(REG_OPCODEOP0_1_RST)
|
||||
X(REG_OPCODEOP1_0_CLK)
|
||||
X(REG_OPCODEOP1_1_CLK)
|
||||
X(REG_OUTPUT0_CLK)
|
||||
X(REG_OUTPUT1_CLK)
|
||||
X(REG_OUTPUT_CLK)
|
||||
X(REG_OUTPUT_RST)
|
||||
X(REG_PIPELINE_CE)
|
||||
X(REG_PIPELINE_CLK)
|
||||
X(REG_PIPELINE_RST)
|
||||
X(RESETMODE)
|
||||
X(RNDPAT)
|
||||
X(RSTAMUX)
|
||||
X(RSTBMUX)
|
||||
X(S0)
|
||||
X(S1)
|
||||
X(SD)
|
||||
X(SGSR)
|
||||
X(SLEWRATE)
|
||||
X(SOURCEB_MODE)
|
||||
X(STDBY_ENABLE)
|
||||
X(SYNCMODE)
|
||||
X(SYNC_ENABLE)
|
||||
X(T0)
|
||||
X(T1)
|
||||
X(TERMINATION)
|
||||
X(TILE_WIRE_ID)
|
||||
X(TRELLIS_DPR16X4)
|
||||
X(TRELLIS_FF)
|
||||
X(TRIMUX_TSREG)
|
||||
X(TSHX2DQA)
|
||||
X(TSHX2DQSA)
|
||||
X(USRMCLKI)
|
||||
X(USRMCLKO)
|
||||
X(USRMCLKTS)
|
||||
X(VCC)
|
||||
X(WCKMUX)
|
||||
X(WEAMUX)
|
||||
X(WEBMUX)
|
||||
X(WID)
|
||||
X(WREMUX)
|
||||
X(WRITEMODE_A)
|
||||
X(WRITEMODE_B)
|
||||
X(Y)
|
||||
X(ioff_dir)
|
||||
X(lfe5u_12f)
|
||||
X(lfe5u_25f)
|
||||
X(lfe5u_45f)
|
||||
X(lfe5u_85f)
|
||||
X(lfe5um5g_25f)
|
||||
X(lfe5um5g_45f)
|
||||
X(lfe5um5g_85f)
|
||||
X(lfe5um_25f)
|
||||
X(lfe5um_45f)
|
||||
X(lfe5um_85f)
|
||||
X(noglobal)
|
||||
X(pack)
|
||||
X(place)
|
||||
X(placer)
|
||||
X(route)
|
||||
X(router)
|
||||
X(syn_useioff)
|
||||
|
@ -1,504 +1,424 @@
|
||||
tg.config.add_word("DCU.CH0_AUTO_CALIB_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_AUTO_CALIB_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_AUTO_CALIB_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_AUTO_FACQ_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_AUTO_FACQ_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_AUTO_FACQ_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_BAND_THRESHOLD",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_BAND_THRESHOLD"), Property(0)), 6));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_BAND_THRESHOLD, Property(0)), 6));
|
||||
tg.config.add_word("DCU.CH0_CALIB_CK_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CALIB_CK_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CALIB_CK_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_CC_MATCH_1",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CC_MATCH_1"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CC_MATCH_1, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_CC_MATCH_2",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CC_MATCH_2"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CC_MATCH_2, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_CC_MATCH_3",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CC_MATCH_3"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CC_MATCH_3, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_CC_MATCH_4",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CC_MATCH_4"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CC_MATCH_4, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_CDR_CNT4SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CDR_CNT4SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CDR_CNT4SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_CDR_CNT8SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CDR_CNT8SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CDR_CNT8SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_CTC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CTC_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOATDCFG",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOATDCFG"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOATDDLY",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOATDDLY"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_CTC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOATDCFG", parse_config_str(get_or_default(ci->params, id_CH0_DCOATDCFG, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOATDDLY", parse_config_str(get_or_default(ci->params, id_CH0_DCOATDDLY, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOBYPSATD",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOBYPSATD"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOCALDIV",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOCALDIV"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOCTLGI",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOCTLGI"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCOBYPSATD, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOCALDIV", parse_config_str(get_or_default(ci->params, id_CH0_DCOCALDIV, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOCTLGI", parse_config_str(get_or_default(ci->params, id_CH0_DCOCTLGI, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCODISBDAVOID",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCODISBDAVOID"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOFLTDAC",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOFLTDAC"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOFTNRG",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOFTNRG"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCODISBDAVOID, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCOFLTDAC", parse_config_str(get_or_default(ci->params, id_CH0_DCOFLTDAC, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOFTNRG", parse_config_str(get_or_default(ci->params, id_CH0_DCOFTNRG, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOIOSTUNE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOIOSTUNE"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOITUNE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOITUNE"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCOIOSTUNE, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOITUNE", parse_config_str(get_or_default(ci->params, id_CH0_DCOITUNE, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOITUNE4LSB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOITUNE4LSB"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCOITUNE4LSB, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOIUPDNX2",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOIUPDNX2"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCOIUPDNX2, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_DCONUOFLSB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCONUOFLSB"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOSCALEI",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSCALEI"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCONUOFLSB, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOSCALEI", parse_config_str(get_or_default(ci->params, id_CH0_DCOSCALEI, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DCOSTARTVAL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSTARTVAL"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOSTEP",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSTEP"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DCOSTARTVAL, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_DCOSTEP", parse_config_str(get_or_default(ci->params, id_CH0_DCOSTEP, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_DEC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DEC_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_DEC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_ENABLE_CG_ALIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_ENABLE_CG_ALIGN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_ENABLE_CG_ALIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_ENC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_ENC_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_ENC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_FF_RX_F_CLK_DIS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_FF_RX_F_CLK_DIS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_FF_RX_F_CLK_DIS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_FF_RX_H_CLK_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_FF_RX_H_CLK_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_FF_RX_H_CLK_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_FF_TX_F_CLK_DIS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_FF_TX_F_CLK_DIS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_FF_TX_F_CLK_DIS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_FF_TX_H_CLK_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_FF_TX_H_CLK_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_FF_TX_H_CLK_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_GE_AN_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_GE_AN_ENABLE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_INVERT_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_INVERT_RX"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_INVERT_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_INVERT_TX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_GE_AN_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_INVERT_RX", parse_config_str(get_or_default(ci->params, id_CH0_INVERT_RX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_INVERT_TX", parse_config_str(get_or_default(ci->params, id_CH0_INVERT_TX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_LDR_CORE2TX_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_LDR_CORE2TX_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_LDR_CORE2TX_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_LDR_RX2CORE_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_LDR_RX2CORE_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_LDR_RX2CORE_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_LEQ_OFFSET_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_LEQ_OFFSET_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_LEQ_OFFSET_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_LEQ_OFFSET_TRIM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_LEQ_OFFSET_TRIM"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_LEQ_OFFSET_TRIM, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_LSM_DISABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_LSM_DISABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_LSM_DISABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_MATCH_2_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_MATCH_2_ENABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_MATCH_2_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_MATCH_4_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_MATCH_4_ENABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_MATCH_4_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_MIN_IPG_CNT",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_MIN_IPG_CNT"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_MIN_IPG_CNT, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_PCIE_EI_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PCIE_EI_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PCIE_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PCIE_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_PCIE_EI_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PCIE_MODE", parse_config_str(get_or_default(ci->params, id_CH0_PCIE_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PCS_DET_TIME_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PCS_DET_TIME_SEL"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_PDEN_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PDEN_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_PCS_DET_TIME_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_PDEN_SEL", parse_config_str(get_or_default(ci->params, id_CH0_PDEN_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PRBS_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PRBS_ENABLE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PRBS_LOCK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PRBS_LOCK"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_PRBS_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PRBS_LOCK", parse_config_str(get_or_default(ci->params, id_CH0_PRBS_LOCK, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_PRBS_SELECTION",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PRBS_SELECTION"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_PRBS_SELECTION, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RATE_MODE_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RATE_MODE_RX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RATE_MODE_RX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RATE_MODE_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RATE_MODE_TX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RATE_MODE_TX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RCV_DCC_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RCV_DCC_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RCV_DCC_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_REG_BAND_OFFSET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REG_BAND_OFFSET"), Property(0)), 4));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_REG_BAND_OFFSET, Property(0)), 4));
|
||||
tg.config.add_word("DCU.CH0_REG_BAND_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REG_BAND_SEL"), Property(0)), 6));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_REG_BAND_SEL, Property(0)), 6));
|
||||
tg.config.add_word("DCU.CH0_REG_IDAC_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REG_IDAC_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_REG_IDAC_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_REG_IDAC_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REG_IDAC_SEL"), Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_REQ_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REQ_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_REG_IDAC_SEL, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_REQ_EN", parse_config_str(get_or_default(ci->params, id_CH0_REQ_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_REQ_LVL_SET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REQ_LVL_SET"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RIO_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RIO_MODE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RLOS_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RLOS_SEL"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RPWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RPWDNB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RTERM_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RTERM_RX"), Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH0_RTERM_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RTERM_TX"), Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH0_RXIN_CM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RXIN_CM"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RXTERM_CM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RXTERM_CM"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_REQ_LVL_SET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RIO_MODE", parse_config_str(get_or_default(ci->params, id_CH0_RIO_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RLOS_SEL", parse_config_str(get_or_default(ci->params, id_CH0_RLOS_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RPWDNB", parse_config_str(get_or_default(ci->params, id_CH0_RPWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RTERM_RX", parse_config_str(get_or_default(ci->params, id_CH0_RTERM_RX, Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH0_RTERM_TX", parse_config_str(get_or_default(ci->params, id_CH0_RTERM_TX, Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH0_RXIN_CM", parse_config_str(get_or_default(ci->params, id_CH0_RXIN_CM, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RXTERM_CM", parse_config_str(get_or_default(ci->params, id_CH0_RXTERM_CM, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RX_DCO_CK_DIV",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_DCO_CK_DIV"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_DCO_CK_DIV, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_RX_DIV11_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_DIV11_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_DIV11_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RX_GEAR_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_GEAR_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_GEAR_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RX_GEAR_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_GEAR_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_GEAR_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RX_LOS_CEQ",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_LOS_CEQ"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RX_LOS_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_LOS_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_LOS_CEQ, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_RX_LOS_EN", parse_config_str(get_or_default(ci->params, id_CH0_RX_LOS_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RX_LOS_HYST_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_LOS_HYST_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_LOS_HYST_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_RX_LOS_LVL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_LOS_LVL"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_LOS_LVL, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_RX_RATE_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_RATE_SEL"), Property(0)), 4));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_RATE_SEL, Property(0)), 4));
|
||||
tg.config.add_word("DCU.CH0_RX_SB_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_SB_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_SB_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_SB_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_RX_SB_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_SB_BYPASS", parse_config_str(get_or_default(ci->params, id_CH0_SB_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_SEL_SD_RX_CLK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_SEL_SD_RX_CLK"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_SEL_SD_RX_CLK, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TDRV_DAT_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_DAT_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_DAT_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_POST_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_POST_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_POST_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TDRV_PRE_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_PRE_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_PRE_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE0_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE0_CUR"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE0_CUR, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE0_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE0_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE0_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE1_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE1_CUR"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE1_CUR, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE1_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE1_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE1_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE2_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE2_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE2_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE2_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE2_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE2_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE3_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE3_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE3_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE3_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE3_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE3_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE4_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE4_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE4_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE4_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE4_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE4_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE5_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE5_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE5_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TDRV_SLICE5_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TDRV_SLICE5_SEL"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TPWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TPWDNB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_CM_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_CM_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE5_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TPWDNB", parse_config_str(get_or_default(ci->params, id_CH0_TPWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_CM_SEL", parse_config_str(get_or_default(ci->params, id_CH0_TX_CM_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH0_TX_DIV11_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_DIV11_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TX_DIV11_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_GEAR_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_GEAR_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TX_GEAR_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_GEAR_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_GEAR_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TX_GEAR_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_POST_SIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_POST_SIGN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TX_POST_SIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_TX_PRE_SIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_TX_PRE_SIGN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_UC_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_UC_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_TX_PRE_SIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_UC_MODE", parse_config_str(get_or_default(ci->params, id_CH0_UC_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_UDF_COMMA_A",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_UDF_COMMA_A"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_UDF_COMMA_A, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_UDF_COMMA_B",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_UDF_COMMA_B"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_UDF_COMMA_B, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_UDF_COMMA_MASK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_UDF_COMMA_MASK"), Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_WA_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_WA_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_WA_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH0_WA_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH0_UDF_COMMA_MASK, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH0_WA_BYPASS", parse_config_str(get_or_default(ci->params, id_CH0_WA_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH0_WA_MODE", parse_config_str(get_or_default(ci->params, id_CH0_WA_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_AUTO_CALIB_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_AUTO_CALIB_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_AUTO_CALIB_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_AUTO_FACQ_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_AUTO_FACQ_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_AUTO_FACQ_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_BAND_THRESHOLD",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_BAND_THRESHOLD"), Property(0)), 6));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_BAND_THRESHOLD, Property(0)), 6));
|
||||
tg.config.add_word("DCU.CH1_CALIB_CK_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CALIB_CK_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CALIB_CK_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_CC_MATCH_1",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CC_MATCH_1"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CC_MATCH_1, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_CC_MATCH_2",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CC_MATCH_2"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CC_MATCH_2, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_CC_MATCH_3",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CC_MATCH_3"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CC_MATCH_3, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_CC_MATCH_4",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CC_MATCH_4"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CC_MATCH_4, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_CDR_CNT4SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CDR_CNT4SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CDR_CNT4SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_CDR_CNT8SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CDR_CNT8SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CDR_CNT8SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_CTC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CTC_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOATDCFG",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOATDCFG"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOATDDLY",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOATDDLY"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_CTC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOATDCFG", parse_config_str(get_or_default(ci->params, id_CH1_DCOATDCFG, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOATDDLY", parse_config_str(get_or_default(ci->params, id_CH1_DCOATDDLY, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOBYPSATD",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOBYPSATD"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOCALDIV",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOCALDIV"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOCTLGI",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOCTLGI"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCOBYPSATD, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOCALDIV", parse_config_str(get_or_default(ci->params, id_CH1_DCOCALDIV, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOCTLGI", parse_config_str(get_or_default(ci->params, id_CH1_DCOCTLGI, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCODISBDAVOID",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCODISBDAVOID"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOFLTDAC",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOFLTDAC"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOFTNRG",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOFTNRG"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCODISBDAVOID, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCOFLTDAC", parse_config_str(get_or_default(ci->params, id_CH1_DCOFLTDAC, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOFTNRG", parse_config_str(get_or_default(ci->params, id_CH1_DCOFTNRG, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOIOSTUNE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOIOSTUNE"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOITUNE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOITUNE"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCOIOSTUNE, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOITUNE", parse_config_str(get_or_default(ci->params, id_CH1_DCOITUNE, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOITUNE4LSB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOITUNE4LSB"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCOITUNE4LSB, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOIUPDNX2",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOIUPDNX2"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCOIUPDNX2, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_DCONUOFLSB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCONUOFLSB"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOSCALEI",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSCALEI"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCONUOFLSB, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOSCALEI", parse_config_str(get_or_default(ci->params, id_CH1_DCOSCALEI, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DCOSTARTVAL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSTARTVAL"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOSTEP",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSTEP"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DCOSTARTVAL, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_DCOSTEP", parse_config_str(get_or_default(ci->params, id_CH1_DCOSTEP, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_DEC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DEC_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_DEC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_ENABLE_CG_ALIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_ENABLE_CG_ALIGN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_ENABLE_CG_ALIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_ENC_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_ENC_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_ENC_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_FF_RX_F_CLK_DIS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_FF_RX_F_CLK_DIS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_FF_RX_F_CLK_DIS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_FF_RX_H_CLK_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_FF_RX_H_CLK_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_FF_RX_H_CLK_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_FF_TX_F_CLK_DIS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_FF_TX_F_CLK_DIS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_FF_TX_F_CLK_DIS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_FF_TX_H_CLK_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_FF_TX_H_CLK_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_FF_TX_H_CLK_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_GE_AN_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_GE_AN_ENABLE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_INVERT_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_INVERT_RX"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_INVERT_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_INVERT_TX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_GE_AN_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_INVERT_RX", parse_config_str(get_or_default(ci->params, id_CH1_INVERT_RX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_INVERT_TX", parse_config_str(get_or_default(ci->params, id_CH1_INVERT_TX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_LDR_CORE2TX_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_LDR_CORE2TX_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_LDR_CORE2TX_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_LDR_RX2CORE_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_LDR_RX2CORE_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_LDR_RX2CORE_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_LEQ_OFFSET_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_LEQ_OFFSET_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_LEQ_OFFSET_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_LEQ_OFFSET_TRIM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_LEQ_OFFSET_TRIM"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_LEQ_OFFSET_TRIM, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_LSM_DISABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_LSM_DISABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_LSM_DISABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_MATCH_2_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_MATCH_2_ENABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_MATCH_2_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_MATCH_4_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_MATCH_4_ENABLE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_MATCH_4_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_MIN_IPG_CNT",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_MIN_IPG_CNT"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_MIN_IPG_CNT, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_PCIE_EI_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PCIE_EI_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PCIE_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PCIE_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_PCIE_EI_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PCIE_MODE", parse_config_str(get_or_default(ci->params, id_CH1_PCIE_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PCS_DET_TIME_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PCS_DET_TIME_SEL"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_PDEN_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PDEN_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_PCS_DET_TIME_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_PDEN_SEL", parse_config_str(get_or_default(ci->params, id_CH1_PDEN_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PRBS_ENABLE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PRBS_ENABLE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PRBS_LOCK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PRBS_LOCK"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_PRBS_ENABLE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PRBS_LOCK", parse_config_str(get_or_default(ci->params, id_CH1_PRBS_LOCK, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_PRBS_SELECTION",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PRBS_SELECTION"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_PRBS_SELECTION, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RATE_MODE_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RATE_MODE_RX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RATE_MODE_RX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RATE_MODE_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RATE_MODE_TX"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RATE_MODE_TX, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RCV_DCC_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RCV_DCC_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RCV_DCC_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_REG_BAND_OFFSET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REG_BAND_OFFSET"), Property(0)), 4));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_REG_BAND_OFFSET, Property(0)), 4));
|
||||
tg.config.add_word("DCU.CH1_REG_BAND_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REG_BAND_SEL"), Property(0)), 6));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_REG_BAND_SEL, Property(0)), 6));
|
||||
tg.config.add_word("DCU.CH1_REG_IDAC_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REG_IDAC_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_REG_IDAC_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_REG_IDAC_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REG_IDAC_SEL"), Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_REQ_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REQ_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_REG_IDAC_SEL, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_REQ_EN", parse_config_str(get_or_default(ci->params, id_CH1_REQ_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_REQ_LVL_SET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REQ_LVL_SET"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RIO_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RIO_MODE"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RLOS_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RLOS_SEL"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RPWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RPWDNB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RTERM_RX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RTERM_RX"), Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH1_RTERM_TX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RTERM_TX"), Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH1_RXIN_CM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RXIN_CM"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RXTERM_CM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RXTERM_CM"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_REQ_LVL_SET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RIO_MODE", parse_config_str(get_or_default(ci->params, id_CH1_RIO_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RLOS_SEL", parse_config_str(get_or_default(ci->params, id_CH1_RLOS_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RPWDNB", parse_config_str(get_or_default(ci->params, id_CH1_RPWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RTERM_RX", parse_config_str(get_or_default(ci->params, id_CH1_RTERM_RX, Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH1_RTERM_TX", parse_config_str(get_or_default(ci->params, id_CH1_RTERM_TX, Property(0)), 5));
|
||||
tg.config.add_word("DCU.CH1_RXIN_CM", parse_config_str(get_or_default(ci->params, id_CH1_RXIN_CM, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RXTERM_CM", parse_config_str(get_or_default(ci->params, id_CH1_RXTERM_CM, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RX_DCO_CK_DIV",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_DCO_CK_DIV"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_DCO_CK_DIV, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_RX_DIV11_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_DIV11_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_DIV11_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RX_GEAR_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_GEAR_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_GEAR_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RX_GEAR_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_GEAR_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_GEAR_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RX_LOS_CEQ",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_LOS_CEQ"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RX_LOS_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_LOS_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_LOS_CEQ, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_RX_LOS_EN", parse_config_str(get_or_default(ci->params, id_CH1_RX_LOS_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RX_LOS_HYST_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_LOS_HYST_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_LOS_HYST_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_RX_LOS_LVL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_LOS_LVL"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_LOS_LVL, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_RX_RATE_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_RATE_SEL"), Property(0)), 4));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_RATE_SEL, Property(0)), 4));
|
||||
tg.config.add_word("DCU.CH1_RX_SB_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_SB_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_SB_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_SB_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_RX_SB_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_SB_BYPASS", parse_config_str(get_or_default(ci->params, id_CH1_SB_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_SEL_SD_RX_CLK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_SEL_SD_RX_CLK"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_SEL_SD_RX_CLK, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TDRV_DAT_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_DAT_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_DAT_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_POST_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_POST_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_POST_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TDRV_PRE_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_PRE_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_PRE_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE0_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE0_CUR"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE0_CUR, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE0_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE0_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE0_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE1_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE1_CUR"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE1_CUR, Property(0)), 3));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE1_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE1_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE1_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE2_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE2_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE2_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE2_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE2_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE2_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE3_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE3_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE3_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE3_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE3_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE3_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE4_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE4_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE4_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE4_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE4_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE4_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE5_CUR",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE5_CUR"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE5_CUR, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TDRV_SLICE5_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TDRV_SLICE5_SEL"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TPWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TPWDNB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_CM_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_CM_SEL"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE5_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TPWDNB", parse_config_str(get_or_default(ci->params, id_CH1_TPWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_CM_SEL", parse_config_str(get_or_default(ci->params, id_CH1_TX_CM_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.CH1_TX_DIV11_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_DIV11_SEL"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TX_DIV11_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_GEAR_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_GEAR_BYPASS"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TX_GEAR_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_GEAR_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_GEAR_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TX_GEAR_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_POST_SIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_POST_SIGN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TX_POST_SIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_TX_PRE_SIGN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_TX_PRE_SIGN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_UC_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_UC_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_TX_PRE_SIGN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_UC_MODE", parse_config_str(get_or_default(ci->params, id_CH1_UC_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_UDF_COMMA_A",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_UDF_COMMA_A"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_UDF_COMMA_A, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_UDF_COMMA_B",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_UDF_COMMA_B"), Property(0)), 10));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_UDF_COMMA_B, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_UDF_COMMA_MASK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_UDF_COMMA_MASK"), Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_WA_BYPASS",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_WA_BYPASS"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_WA_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("CH1_WA_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_CH1_UDF_COMMA_MASK, Property(0)), 10));
|
||||
tg.config.add_word("DCU.CH1_WA_BYPASS", parse_config_str(get_or_default(ci->params, id_CH1_WA_BYPASS, Property(0)), 1));
|
||||
tg.config.add_word("DCU.CH1_WA_MODE", parse_config_str(get_or_default(ci->params, id_CH1_WA_MODE, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_BITCLK_FROM_ND_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_BITCLK_FROM_ND_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_D_BITCLK_FROM_ND_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_BITCLK_LOCAL_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_BITCLK_LOCAL_EN"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_D_BITCLK_LOCAL_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_BITCLK_ND_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_BITCLK_ND_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_BUS8BIT_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_BUS8BIT_SEL"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_CDR_LOL_SET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CDR_LOL_SET"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETBIASI",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETBIASI"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETI4CPP",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETI4CPP"), Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_CMUSETI4CPZ",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETI4CPZ"), Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_CMUSETI4VCO",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETI4VCO"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETICP4P",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETICP4P"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETICP4Z",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETICP4Z"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_D_BITCLK_ND_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_BUS8BIT_SEL", parse_config_str(get_or_default(ci->params, id_D_BUS8BIT_SEL, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_CDR_LOL_SET", parse_config_str(get_or_default(ci->params, id_D_CDR_LOL_SET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETBIASI", parse_config_str(get_or_default(ci->params, id_D_CMUSETBIASI, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETI4CPP", parse_config_str(get_or_default(ci->params, id_D_CMUSETI4CPP, Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_CMUSETI4CPZ", parse_config_str(get_or_default(ci->params, id_D_CMUSETI4CPZ, Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_CMUSETI4VCO", parse_config_str(get_or_default(ci->params, id_D_CMUSETI4VCO, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETICP4P", parse_config_str(get_or_default(ci->params, id_D_CMUSETICP4P, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETICP4Z", parse_config_str(get_or_default(ci->params, id_D_CMUSETICP4Z, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETINITVCT",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETINITVCT"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_D_CMUSETINITVCT, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_CMUSETISCL4VCO",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETISCL4VCO"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETP1GM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETP1GM"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETP2AGM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETP2AGM"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETZGM",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETZGM"), Property(0)), 3));
|
||||
parse_config_str(get_or_default(ci->params, id_D_CMUSETISCL4VCO, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETP1GM", parse_config_str(get_or_default(ci->params, id_D_CMUSETP1GM, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETP2AGM", parse_config_str(get_or_default(ci->params, id_D_CMUSETP2AGM, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_CMUSETZGM", parse_config_str(get_or_default(ci->params, id_D_CMUSETZGM, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_DCO_CALIB_TIME_SEL",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_DCO_CALIB_TIME_SEL"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_HIGH_MARK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_HIGH_MARK"), Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_IB_PWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_IB_PWDNB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_ISETLOS", parse_config_str(get_or_default(ci->params, ctx->id("D_ISETLOS"), Property(0)), 8));
|
||||
tg.config.add_word("DCU.D_LOW_MARK",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_LOW_MARK"), Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_MACROPDB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_MACROPDB"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_PD_ISET", parse_config_str(get_or_default(ci->params, ctx->id("D_PD_ISET"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_PLL_LOL_SET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_PLL_LOL_SET"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_REFCK_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_REFCK_MODE"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_REQ_ISET",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_REQ_ISET"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_RG_EN", parse_config_str(get_or_default(ci->params, ctx->id("D_RG_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_RG_SET", parse_config_str(get_or_default(ci->params, ctx->id("D_RG_SET"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_D_DCO_CALIB_TIME_SEL, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_HIGH_MARK", parse_config_str(get_or_default(ci->params, id_D_HIGH_MARK, Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_IB_PWDNB", parse_config_str(get_or_default(ci->params, id_D_IB_PWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_ISETLOS", parse_config_str(get_or_default(ci->params, id_D_ISETLOS, Property(0)), 8));
|
||||
tg.config.add_word("DCU.D_LOW_MARK", parse_config_str(get_or_default(ci->params, id_D_LOW_MARK, Property(0)), 4));
|
||||
tg.config.add_word("DCU.D_MACROPDB", parse_config_str(get_or_default(ci->params, id_D_MACROPDB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_PD_ISET", parse_config_str(get_or_default(ci->params, id_D_PD_ISET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_PLL_LOL_SET", parse_config_str(get_or_default(ci->params, id_D_PLL_LOL_SET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_REFCK_MODE", parse_config_str(get_or_default(ci->params, id_D_REFCK_MODE, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_REQ_ISET", parse_config_str(get_or_default(ci->params, id_D_REQ_ISET, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_RG_EN", parse_config_str(get_or_default(ci->params, id_D_RG_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_RG_SET", parse_config_str(get_or_default(ci->params, id_D_RG_SET, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETICONST_AUX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SETICONST_AUX"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_D_SETICONST_AUX, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETICONST_CH",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SETICONST_CH"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_D_SETICONST_CH, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETIRPOLY_AUX",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SETIRPOLY_AUX"), Property(0)), 2));
|
||||
parse_config_str(get_or_default(ci->params, id_D_SETIRPOLY_AUX, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETIRPOLY_CH",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SETIRPOLY_CH"), Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETPLLRC",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SETPLLRC"), Property(0)), 6));
|
||||
parse_config_str(get_or_default(ci->params, id_D_SETIRPOLY_CH, Property(0)), 2));
|
||||
tg.config.add_word("DCU.D_SETPLLRC", parse_config_str(get_or_default(ci->params, id_D_SETPLLRC, Property(0)), 6));
|
||||
tg.config.add_word("DCU.D_SYNC_LOCAL_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SYNC_LOCAL_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_SYNC_ND_EN",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_SYNC_ND_EN"), Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_TXPLL_PWDNB",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_TXPLL_PWDNB"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_D_SYNC_LOCAL_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_SYNC_ND_EN", parse_config_str(get_or_default(ci->params, id_D_SYNC_ND_EN, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_TXPLL_PWDNB", parse_config_str(get_or_default(ci->params, id_D_TXPLL_PWDNB, Property(0)), 1));
|
||||
tg.config.add_word("DCU.D_TX_VCO_CK_DIV",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_TX_VCO_CK_DIV"), Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_XGE_MODE",
|
||||
parse_config_str(get_or_default(ci->params, ctx->id("D_XGE_MODE"), Property(0)), 1));
|
||||
parse_config_str(get_or_default(ci->params, id_D_TX_VCO_CK_DIV, Property(0)), 3));
|
||||
tg.config.add_word("DCU.D_XGE_MODE", parse_config_str(get_or_default(ci->params, id_D_XGE_MODE, Property(0)), 1));
|
||||
|
@ -299,8 +299,8 @@ class Ecp5GlobalRouter
|
||||
dedicated_routing = false;
|
||||
if (drv.cell == nullptr) {
|
||||
return 0;
|
||||
} else if (drv.cell->attrs.count(ctx->id("BEL"))) {
|
||||
drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(ctx->id("BEL")).as_string());
|
||||
} else if (drv.cell->attrs.count(id_BEL)) {
|
||||
drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(id_BEL).as_string());
|
||||
} else {
|
||||
// Check if driver is a singleton
|
||||
BelId last_bel;
|
||||
@ -399,7 +399,7 @@ class Ecp5GlobalRouter
|
||||
{
|
||||
BelId best_bel;
|
||||
WireId best_bel_pclkcib;
|
||||
bool using_ce = get_net_or_empty(dcc, ctx->id("CE")) != nullptr;
|
||||
bool using_ce = get_net_or_empty(dcc, id_CE) != nullptr;
|
||||
wirelen_t best_wirelen = 9999999;
|
||||
bool dedicated_routing = false;
|
||||
for (auto bel : ctx->getBels()) {
|
||||
@ -492,8 +492,8 @@ class Ecp5GlobalRouter
|
||||
dccptr = dcc.get();
|
||||
ctx->cells[dcc->name] = std::move(dcc);
|
||||
}
|
||||
glbptr->attrs[ctx->id("ECP5_IS_GLOBAL")] = 1;
|
||||
if (str_or_default(dccptr->attrs, ctx->id("BEL"), "") == "")
|
||||
glbptr->attrs[id_ECP5_IS_GLOBAL] = 1;
|
||||
if (str_or_default(dccptr->attrs, id_BEL, "") == "")
|
||||
place_dcc_dcs(dccptr);
|
||||
return glbptr;
|
||||
}
|
||||
@ -514,8 +514,8 @@ class Ecp5GlobalRouter
|
||||
log_info("Promoting globals...\n");
|
||||
auto clocks = get_clocks();
|
||||
for (auto clock : clocks) {
|
||||
bool is_noglobal = bool_or_default(clock->attrs, ctx->id("noglobal"), false) ||
|
||||
bool_or_default(clock->attrs, ctx->id("ECP5_IS_GLOBAL"), false);
|
||||
bool is_noglobal = bool_or_default(clock->attrs, id_noglobal, false) ||
|
||||
bool_or_default(clock->attrs, id_ECP5_IS_GLOBAL, false);
|
||||
if (is_noglobal)
|
||||
continue;
|
||||
log_info(" promoting clock net %s to global network\n", clock->name.c_str(ctx));
|
||||
|
@ -134,7 +134,7 @@ bool Arch::apply_lpf(std::string filename, std::istream &in)
|
||||
if (words.size() > 5)
|
||||
log_error("unexpected input following LOCATE clause (on line %d)\n", lineno);
|
||||
if (fnd_cell != cells.end()) {
|
||||
fnd_cell->second->attrs[id("LOC")] = strip_quotes(words.at(4));
|
||||
fnd_cell->second->attrs[id_LOC] = strip_quotes(words.at(4));
|
||||
}
|
||||
} else if (verb == "IOBUF") {
|
||||
if (words.size() < 3)
|
||||
|
@ -277,7 +277,7 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx)
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
|
||||
ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
if (!ci->attrs.count(ctx->id("LOC"))) {
|
||||
if (!ci->attrs.count(id_LOC)) {
|
||||
if (vm.count("lpf-allow-unconstrained"))
|
||||
log_warning("IO '%s' is unconstrained in LPF and will be automatically placed\n",
|
||||
cell.first.c_str(ctx));
|
||||
|
883
ecp5/pack.cc
883
ecp5/pack.cc
File diff suppressed because it is too large
Load Diff
@ -688,7 +688,7 @@ void Arch::read_cst(std::istream &in)
|
||||
insloc
|
||||
} cst_type;
|
||||
|
||||
settings.erase(id("cst"));
|
||||
settings.erase(id_cst);
|
||||
while (!in.eof()) {
|
||||
std::getline(in, line);
|
||||
cst_type = ioloc;
|
||||
@ -756,7 +756,7 @@ void Arch::read_cst(std::istream &in)
|
||||
}
|
||||
}
|
||||
}
|
||||
settings[id("cst")] = 1;
|
||||
settings[id_cst] = 1;
|
||||
}
|
||||
|
||||
// Add all MUXes for the cell
|
||||
@ -1455,13 +1455,13 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
||||
|
||||
bool Arch::place()
|
||||
{
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
bool retVal;
|
||||
if (placer == "heap") {
|
||||
bool have_iobuf_or_constr = false;
|
||||
for (auto &cell : cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == id("IOB") || ci->bel != BelId() || ci->attrs.count(id("BEL"))) {
|
||||
if (ci->type == id_IOB || ci->bel != BelId() || ci->attrs.count(id_BEL)) {
|
||||
have_iobuf_or_constr = true;
|
||||
break;
|
||||
}
|
||||
@ -1472,15 +1472,15 @@ bool Arch::place()
|
||||
retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
|
||||
} else {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
cfg.ioBufTypes.insert(id("IOB"));
|
||||
cfg.ioBufTypes.insert(id_IOB);
|
||||
cfg.beta = 0.5;
|
||||
retVal = placer_heap(getCtx(), cfg);
|
||||
}
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
archInfoToAttributes();
|
||||
} else if (placer == "sa") {
|
||||
retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
archInfoToAttributes();
|
||||
return retVal;
|
||||
} else {
|
||||
@ -1497,7 +1497,7 @@ bool Arch::place()
|
||||
|
||||
bool Arch::route()
|
||||
{
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
bool result;
|
||||
if (router == "router1") {
|
||||
result = router1(getCtx(), Router1Cfg(getCtx()));
|
||||
@ -1507,7 +1507,7 @@ bool Arch::route()
|
||||
} else {
|
||||
log_error("Gowin architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
getCtx()->settings[getCtx()->id("route")] = 1;
|
||||
getCtx()->settings[id_route] = 1;
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
@ -1600,9 +1600,9 @@ void Arch::assignArchInfo()
|
||||
ci->is_slice = true;
|
||||
ci->ff_used = ci->params.at(id_FF_USED).as_bool();
|
||||
ci->ff_type = id(ci->params.at(id_FF_TYPE).as_string());
|
||||
ci->slice_clk = get_net_or_empty(ci, id("CLK"));
|
||||
ci->slice_ce = get_net_or_empty(ci, id("CE"));
|
||||
ci->slice_lsr = get_net_or_empty(ci, id("LSR"));
|
||||
ci->slice_clk = get_net_or_empty(ci, id_CLK);
|
||||
ci->slice_ce = get_net_or_empty(ci, id_CE);
|
||||
ci->slice_lsr = get_net_or_empty(ci, id_LSR);
|
||||
|
||||
// add timing paths
|
||||
addCellTimingClock(cname, id_CLK);
|
||||
|
@ -354,7 +354,7 @@ struct Arch : BaseArch<ArchRanges>
|
||||
std::string getChipName() const override { return device; }
|
||||
|
||||
ArchArgs archArgs() const override { return args; }
|
||||
IdString archArgsToId(ArchArgs args) const override { return id("none"); }
|
||||
IdString archArgsToId(ArchArgs args) const override { return id_none; }
|
||||
|
||||
int getGridDimX() const override { return gridDimX; }
|
||||
int getGridDimY() const override { return gridDimY; }
|
||||
|
@ -806,3 +806,12 @@ X(DECAL_ALU_ACTIVE)
|
||||
|
||||
|
||||
|
||||
|
||||
X(SINGLE_INPUT_MUX)
|
||||
X(cst)
|
||||
X(none)
|
||||
X(pack)
|
||||
X(place)
|
||||
X(placer)
|
||||
X(route)
|
||||
X(router)
|
||||
|
@ -114,7 +114,7 @@ static void pack_alus(Context *ctx)
|
||||
|
||||
int alu_idx = 1;
|
||||
do { // go through the ALU chain
|
||||
auto alu_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto alu_bel = ci->attrs.find(id_BEL);
|
||||
if (alu_bel != ci->attrs.end()) {
|
||||
log_error("ALU %s placement restrictions are not supported.\n", ctx->nameOf(ci));
|
||||
return;
|
||||
@ -243,7 +243,7 @@ static void pack_mux2_lut5(Context *ctx, CellInfo *ci, pool<IdString> &packed_ce
|
||||
std::vector<std::unique_ptr<CellInfo>> &new_cells)
|
||||
{
|
||||
|
||||
if (bool_or_default(ci->attrs, ctx->id("SINGLE_INPUT_MUX"))) {
|
||||
if (bool_or_default(ci->attrs, id_SINGLE_INPUT_MUX)) {
|
||||
// find the muxed LUT
|
||||
NetInfo *i1 = ci->ports.at(id_I1).net;
|
||||
|
||||
@ -257,14 +257,14 @@ static void pack_mux2_lut5(Context *ctx, CellInfo *ci, pool<IdString> &packed_ce
|
||||
}
|
||||
|
||||
// XXX enable the placement constraints
|
||||
auto mux_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto lut1_bel = lut1->attrs.find(ctx->id("BEL"));
|
||||
auto mux_bel = ci->attrs.find(id_BEL);
|
||||
auto lut1_bel = lut1->attrs.find(id_BEL);
|
||||
if (lut1_bel != lut1->attrs.end() || mux_bel != ci->attrs.end()) {
|
||||
log_error("MUX2_LUT5 '%s' placement restrictions are not supported yet\n", ctx->nameOf(ci));
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("GW_MUX2_LUT5"), ci->name.str(ctx) + "_LC");
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, id_GW_MUX2_LUT5, ci->name.str(ctx) + "_LC");
|
||||
if (ctx->verbose) {
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
|
||||
}
|
||||
@ -299,15 +299,15 @@ static void pack_mux2_lut5(Context *ctx, CellInfo *ci, pool<IdString> &packed_ce
|
||||
}
|
||||
|
||||
// XXX enable the placement constraints
|
||||
auto mux_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto lut0_bel = lut0->attrs.find(ctx->id("BEL"));
|
||||
auto lut1_bel = lut1->attrs.find(ctx->id("BEL"));
|
||||
auto mux_bel = ci->attrs.find(id_BEL);
|
||||
auto lut0_bel = lut0->attrs.find(id_BEL);
|
||||
auto lut1_bel = lut1->attrs.find(id_BEL);
|
||||
if (lut0_bel != lut0->attrs.end() || lut1_bel != lut1->attrs.end() || mux_bel != ci->attrs.end()) {
|
||||
log_error("MUX2_LUT5 '%s' placement restrictions are not supported yet\n", ctx->nameOf(ci));
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("GW_MUX2_LUT5"), ci->name.str(ctx) + "_LC");
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, id_GW_MUX2_LUT5, ci->name.str(ctx) + "_LC");
|
||||
if (ctx->verbose) {
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
|
||||
}
|
||||
@ -354,9 +354,9 @@ static void pack_mux2_lut(Context *ctx, CellInfo *ci, bool (*pred)(const BaseCtx
|
||||
}
|
||||
|
||||
// XXX enable the placement constraints
|
||||
auto mux_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto mux0_bel = mux0->attrs.find(ctx->id("BEL"));
|
||||
auto mux1_bel = mux1->attrs.find(ctx->id("BEL"));
|
||||
auto mux_bel = ci->attrs.find(id_BEL);
|
||||
auto mux0_bel = mux0->attrs.find(id_BEL);
|
||||
auto mux1_bel = mux1->attrs.find(id_BEL);
|
||||
if (mux0_bel != mux0->attrs.end() || mux1_bel != mux1->attrs.end() || mux_bel != ci->attrs.end()) {
|
||||
log_error("MUX2_LUT%c '%s' placement restrictions are not supported yet\n", type_suffix, ctx->nameOf(ci));
|
||||
return;
|
||||
@ -512,7 +512,7 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_LC");
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, id_SLICE, ci->name.str(ctx) + "_LC");
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
packed_cells.insert(ci->name);
|
||||
@ -520,14 +520,14 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
|
||||
// See if we can pack into a DFF
|
||||
// TODO: LUT cascade
|
||||
NetInfo *o = ci->ports.at(ctx->id("F")).net;
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("D"), true);
|
||||
auto lut_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
NetInfo *o = ci->ports.at(id_F).net;
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_ff, id_D, true);
|
||||
auto lut_bel = ci->attrs.find(id_BEL);
|
||||
bool packed_dff = false;
|
||||
if (dff) {
|
||||
if (ctx->verbose)
|
||||
log_info("found attached dff %s\n", ctx->nameOf(dff));
|
||||
auto dff_bel = dff->attrs.find(ctx->id("BEL"));
|
||||
auto dff_bel = dff->attrs.find(id_BEL);
|
||||
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
|
||||
// Locations don't match, can't pack
|
||||
} else {
|
||||
@ -535,7 +535,7 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
dff_to_lc(ctx, dff, packed.get(), false);
|
||||
ctx->nets.erase(o->name);
|
||||
if (dff_bel != dff->attrs.end())
|
||||
packed->attrs[ctx->id("BEL")] = dff_bel->second;
|
||||
packed->attrs[id_BEL] = dff_bel->second;
|
||||
packed_cells.insert(dff->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ctx->nameOf(dff), ctx->nameOf(packed.get()));
|
||||
@ -567,7 +567,7 @@ static void pack_nonlut_ffs(Context *ctx)
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, ctx->id("SLICE"), ci->name.str(ctx) + "_DFFLC");
|
||||
std::unique_ptr<CellInfo> packed = create_generic_cell(ctx, id_SLICE, ci->name.str(ctx) + "_DFFLC");
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
if (ctx->verbose)
|
||||
@ -610,20 +610,20 @@ static void pack_constants(Context *ctx)
|
||||
{
|
||||
log_info("Packing constants..\n");
|
||||
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, ctx->id("SLICE"), "$PACKER_GND");
|
||||
gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << 4);
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, id_SLICE, "$PACKER_GND");
|
||||
gnd_cell->params[id_INIT] = Property(0, 1 << 4);
|
||||
auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET"));
|
||||
gnd_net->driver.cell = gnd_cell.get();
|
||||
gnd_net->driver.port = ctx->id("F");
|
||||
gnd_cell->ports.at(ctx->id("F")).net = gnd_net.get();
|
||||
gnd_net->driver.port = id_F;
|
||||
gnd_cell->ports.at(id_F).net = gnd_net.get();
|
||||
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_generic_cell(ctx, ctx->id("SLICE"), "$PACKER_VCC");
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_generic_cell(ctx, id_SLICE, "$PACKER_VCC");
|
||||
// Fill with 1s
|
||||
vcc_cell->params[ctx->id("INIT")] = Property(Property::S1).extract(0, (1 << 4), Property::S1);
|
||||
vcc_cell->params[id_INIT] = Property(Property::S1).extract(0, (1 << 4), Property::S1);
|
||||
auto vcc_net = std::make_unique<NetInfo>(ctx->id("$PACKER_VCC_NET"));
|
||||
vcc_net->driver.cell = vcc_cell.get();
|
||||
vcc_net->driver.port = ctx->id("F");
|
||||
vcc_cell->ports.at(ctx->id("F")).net = vcc_net.get();
|
||||
vcc_net->driver.port = id_F;
|
||||
vcc_cell->ports.at(id_F).net = vcc_net.get();
|
||||
|
||||
std::vector<IdString> dead_nets;
|
||||
|
||||
@ -631,13 +631,13 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == id_GND) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net.get(), false);
|
||||
gnd_used = true;
|
||||
dead_nets.push_back(net.first);
|
||||
ctx->cells.erase(drv_cell);
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) {
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == id_VCC) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, vcc_net.get(), true);
|
||||
dead_nets.push_back(net.first);
|
||||
@ -780,7 +780,7 @@ bool Arch::pack()
|
||||
pack_alus(ctx);
|
||||
pack_lut_lutffs(ctx);
|
||||
pack_nonlut_ffs(ctx);
|
||||
ctx->settings[ctx->id("pack")] = 1;
|
||||
ctx->settings[id_pack] = 1;
|
||||
ctx->assignArchInfo();
|
||||
log_info("Checksum: 0x%08x\n", ctx->checksum());
|
||||
return true;
|
||||
|
@ -169,29 +169,29 @@ std::string Arch::getChipName() const
|
||||
IdString Arch::archArgsToId(ArchArgs args) const
|
||||
{
|
||||
if (args.type == ArchArgs::LP384)
|
||||
return id("lp384");
|
||||
return id_lp384;
|
||||
if (args.type == ArchArgs::LP1K)
|
||||
return id("lp1k");
|
||||
return id_lp1k;
|
||||
if (args.type == ArchArgs::HX1K)
|
||||
return id("hx1k");
|
||||
return id_hx1k;
|
||||
if (args.type == ArchArgs::UP3K)
|
||||
return id("up3k");
|
||||
return id_up3k;
|
||||
if (args.type == ArchArgs::UP5K)
|
||||
return id("up5k");
|
||||
return id_up5k;
|
||||
if (args.type == ArchArgs::U1K)
|
||||
return id("u1k");
|
||||
return id_u1k;
|
||||
if (args.type == ArchArgs::U2K)
|
||||
return id("u2k");
|
||||
return id_u2k;
|
||||
if (args.type == ArchArgs::U4K)
|
||||
return id("u4k");
|
||||
return id_u4k;
|
||||
if (args.type == ArchArgs::LP4K)
|
||||
return id("lp4k");
|
||||
return id_lp4k;
|
||||
if (args.type == ArchArgs::LP8K)
|
||||
return id("lp8k");
|
||||
return id_lp8k;
|
||||
if (args.type == ArchArgs::HX4K)
|
||||
return id("hx4k");
|
||||
return id_hx4k;
|
||||
if (args.type == ArchArgs::HX8K)
|
||||
return id("hx8k");
|
||||
return id_hx8k;
|
||||
return IdString();
|
||||
}
|
||||
|
||||
@ -289,7 +289,7 @@ std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
|
||||
ret.push_back(std::make_pair(id("INDEX"), stringf("%d", bel.index)));
|
||||
ret.push_back(std::make_pair(id_INDEX, stringf("%d", bel.index)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -387,33 +387,33 @@ IdString Arch::getWireType(WireId wire) const
|
||||
case WireInfoPOD::WIRE_TYPE_NONE:
|
||||
return IdString();
|
||||
case WireInfoPOD::WIRE_TYPE_GLB2LOCAL:
|
||||
return id("GLB2LOCAL");
|
||||
return id_GLB2LOCAL;
|
||||
case WireInfoPOD::WIRE_TYPE_GLB_NETWK:
|
||||
return id("GLB_NETWK");
|
||||
return id_GLB_NETWK;
|
||||
case WireInfoPOD::WIRE_TYPE_LOCAL:
|
||||
return id("LOCAL");
|
||||
return id_LOCAL;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_IN:
|
||||
return id("LUTFF_IN");
|
||||
return id_LUTFF_IN;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT:
|
||||
return id("LUTFF_IN_LUT");
|
||||
return id_LUTFF_IN_LUT;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT:
|
||||
return id("LUTFF_LOUT");
|
||||
return id_LUTFF_LOUT;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_OUT:
|
||||
return id("LUTFF_OUT");
|
||||
return id_LUTFF_OUT;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_COUT:
|
||||
return id("LUTFF_COUT");
|
||||
return id_LUTFF_COUT;
|
||||
case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL:
|
||||
return id("LUTFF_GLOBAL");
|
||||
return id_LUTFF_GLOBAL;
|
||||
case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX:
|
||||
return id("CARRY_IN_MUX");
|
||||
return id_CARRY_IN_MUX;
|
||||
case WireInfoPOD::WIRE_TYPE_SP4_V:
|
||||
return id("SP4_V");
|
||||
return id_SP4_V;
|
||||
case WireInfoPOD::WIRE_TYPE_SP4_H:
|
||||
return id("SP4_H");
|
||||
return id_SP4_H;
|
||||
case WireInfoPOD::WIRE_TYPE_SP12_V:
|
||||
return id("SP12_V");
|
||||
return id_SP12_V;
|
||||
case WireInfoPOD::WIRE_TYPE_SP12_H:
|
||||
return id("SP12_H");
|
||||
return id_SP12_H;
|
||||
}
|
||||
return IdString();
|
||||
}
|
||||
@ -423,11 +423,11 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
auto &wi = chip_info->wire_data[wire.index];
|
||||
|
||||
ret.push_back(std::make_pair(id("INDEX"), stringf("%d", wire.index)));
|
||||
ret.push_back(std::make_pair(id_INDEX, stringf("%d", wire.index)));
|
||||
|
||||
ret.push_back(std::make_pair(id("GRID_X"), stringf("%d", wi.x)));
|
||||
ret.push_back(std::make_pair(id("GRID_Y"), stringf("%d", wi.y)));
|
||||
ret.push_back(std::make_pair(id("GRID_Z"), stringf("%d", wi.z)));
|
||||
ret.push_back(std::make_pair(id_GRID_X, stringf("%d", wi.x)));
|
||||
ret.push_back(std::make_pair(id_GRID_Y, stringf("%d", wi.y)));
|
||||
ret.push_back(std::make_pair(id_GRID_Z, stringf("%d", wi.z)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -476,7 +476,7 @@ std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId pip) const
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
|
||||
ret.push_back(std::make_pair(id("INDEX"), stringf("%d", pip.index)));
|
||||
ret.push_back(std::make_pair(id_INDEX, stringf("%d", pip.index)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -682,7 +682,7 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
|
||||
|
||||
bool Arch::place()
|
||||
{
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
if (placer == "heap") {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
cfg.ioBufTypes.insert(id_SB_IO);
|
||||
@ -695,19 +695,19 @@ bool Arch::place()
|
||||
log_error("iCE40 architecture does not support placer '%s'\n", placer.c_str());
|
||||
}
|
||||
bool retVal = true;
|
||||
if (bool_or_default(settings, id("opt_timing"), false)) {
|
||||
if (bool_or_default(settings, id_opt_timing, false)) {
|
||||
TimingOptCfg tocfg(getCtx());
|
||||
tocfg.cellTypes.insert(id_ICESTORM_LC);
|
||||
retVal = timing_opt(getCtx(), tocfg);
|
||||
}
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
archInfoToAttributes();
|
||||
return retVal;
|
||||
}
|
||||
|
||||
bool Arch::route()
|
||||
{
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
bool result;
|
||||
if (router == "router1") {
|
||||
result = router1(getCtx(), Router1Cfg(getCtx()));
|
||||
@ -717,7 +717,7 @@ bool Arch::route()
|
||||
} else {
|
||||
log_error("iCE40 architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
getCtx()->settings[getCtx()->id("route")] = 1;
|
||||
getCtx()->settings[id_route] = 1;
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
@ -1064,7 +1064,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
|
||||
return TMG_CLOCK_INPUT;
|
||||
return TMG_IGNORE;
|
||||
} else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) {
|
||||
if (port == this->id("SBCLKI"))
|
||||
if (port == id_SBCLKI)
|
||||
return TMG_CLOCK_INPUT;
|
||||
|
||||
clockInfoCount = 1;
|
||||
@ -1108,10 +1108,10 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
||||
} else if (cell->type == id_ICESTORM_RAM) {
|
||||
if (port.str(this)[0] == 'R') {
|
||||
info.clock_port = id_RCLK;
|
||||
info.edge = bool_or_default(cell->params, id("NEG_CLK_R")) ? FALLING_EDGE : RISING_EDGE;
|
||||
info.edge = bool_or_default(cell->params, id_NEG_CLK_R) ? FALLING_EDGE : RISING_EDGE;
|
||||
} else {
|
||||
info.clock_port = id_WCLK;
|
||||
info.edge = bool_or_default(cell->params, id("NEG_CLK_W")) ? FALLING_EDGE : RISING_EDGE;
|
||||
info.edge = bool_or_default(cell->params, id_NEG_CLK_W) ? FALLING_EDGE : RISING_EDGE;
|
||||
}
|
||||
if (cell->ports.at(port).type == PORT_OUT) {
|
||||
bool has_clktoq = get_cell_delay_internal(cell, info.clock_port, port, info.clockToQ);
|
||||
@ -1168,7 +1168,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
|
||||
info.hold = DelayPair(0);
|
||||
}
|
||||
} else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) {
|
||||
info.clock_port = this->id("SBCLKI");
|
||||
info.clock_port = id_SBCLKI;
|
||||
info.edge = RISING_EDGE;
|
||||
if (cell->ports.at(port).type == PORT_OUT) {
|
||||
/* Dummy number */
|
||||
@ -1233,12 +1233,12 @@ void Arch::assignCellInfo(CellInfo *cell)
|
||||
cell->lcInfo.inputCount++;
|
||||
} else if (cell->type == id_SB_IO) {
|
||||
cell->ioInfo.lvds = str_or_default(cell->params, id_IO_STANDARD, "SB_LVCMOS") == "SB_LVDS_INPUT";
|
||||
cell->ioInfo.global = bool_or_default(cell->attrs, this->id("GLOBAL"));
|
||||
cell->ioInfo.pintype = int_or_default(cell->params, this->id("PIN_TYPE"));
|
||||
cell->ioInfo.negtrig = bool_or_default(cell->params, this->id("NEG_TRIGGER"));
|
||||
cell->ioInfo.global = bool_or_default(cell->attrs, id_GLOBAL);
|
||||
cell->ioInfo.pintype = int_or_default(cell->params, id_PIN_TYPE);
|
||||
cell->ioInfo.negtrig = bool_or_default(cell->params, id_NEG_TRIGGER);
|
||||
|
||||
} else if (cell->type == id_SB_GB) {
|
||||
cell->gbInfo.forPadIn = bool_or_default(cell->attrs, this->id("FOR_PAD_IN"));
|
||||
cell->gbInfo.forPadIn = bool_or_default(cell->attrs, id_FOR_PAD_IN);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +120,7 @@ bool Arch::isBelLocationValid(BelId bel) const
|
||||
break;
|
||||
|
||||
// Are we perhaps a PAD INPUT Bel that can be placed here?
|
||||
if (pll_cell->attrs[id("BEL_PAD_INPUT")] == getBelName(bel).str(getCtx()))
|
||||
if (pll_cell->attrs[id_BEL_PAD_INPUT] == getBelName(bel).str(getCtx()))
|
||||
return true;
|
||||
|
||||
// Conflict
|
||||
|
@ -391,7 +391,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
pool<Loc> sb_io_used_by_pll_pad;
|
||||
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (cell.second->type != ctx->id("ICESTORM_PLL"))
|
||||
if (cell.second->type != id_ICESTORM_PLL)
|
||||
continue;
|
||||
|
||||
// Collect all locations matching an PLL output port
|
||||
@ -434,16 +434,16 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
std::cout << "Found unplaced cell " << cell.first.str(ctx) << " while generating bitstream!" << std::endl;
|
||||
continue;
|
||||
}
|
||||
if (cell.second->type == ctx->id("ICESTORM_LC")) {
|
||||
if (cell.second->type == id_ICESTORM_LC) {
|
||||
const BelInfoPOD &beli = ci.bel_data[bel.index];
|
||||
int x = beli.x, y = beli.y, z = beli.z;
|
||||
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
|
||||
unsigned lut_init = get_param_or_def(ctx, cell.second.get(), ctx->id("LUT_INIT"));
|
||||
bool neg_clk = get_param_or_def(ctx, cell.second.get(), ctx->id("NEG_CLK"));
|
||||
bool dff_enable = get_param_or_def(ctx, cell.second.get(), ctx->id("DFF_ENABLE"));
|
||||
bool async_sr = get_param_or_def(ctx, cell.second.get(), ctx->id("ASYNC_SR"));
|
||||
bool set_noreset = get_param_or_def(ctx, cell.second.get(), ctx->id("SET_NORESET"));
|
||||
bool carry_enable = get_param_or_def(ctx, cell.second.get(), ctx->id("CARRY_ENABLE"));
|
||||
unsigned lut_init = get_param_or_def(ctx, cell.second.get(), id_LUT_INIT);
|
||||
bool neg_clk = get_param_or_def(ctx, cell.second.get(), id_NEG_CLK);
|
||||
bool dff_enable = get_param_or_def(ctx, cell.second.get(), id_DFF_ENABLE);
|
||||
bool async_sr = get_param_or_def(ctx, cell.second.get(), id_ASYNC_SR);
|
||||
bool set_noreset = get_param_or_def(ctx, cell.second.get(), id_SET_NORESET);
|
||||
bool carry_enable = get_param_or_def(ctx, cell.second.get(), id_CARRY_ENABLE);
|
||||
std::vector<bool> lc(20, false);
|
||||
|
||||
// Discover permutation
|
||||
@ -502,20 +502,20 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
if (dff_enable)
|
||||
set_config(ti, config.at(y).at(x), "NegClk", neg_clk);
|
||||
|
||||
bool carry_const = get_param_or_def(ctx, cell.second.get(), ctx->id("CIN_CONST"));
|
||||
bool carry_set = get_param_or_def(ctx, cell.second.get(), ctx->id("CIN_SET"));
|
||||
bool carry_const = get_param_or_def(ctx, cell.second.get(), id_CIN_CONST);
|
||||
bool carry_set = get_param_or_def(ctx, cell.second.get(), id_CIN_SET);
|
||||
if (carry_const) {
|
||||
if (!ctx->force)
|
||||
NPNR_ASSERT(z == 0);
|
||||
set_config(ti, config.at(y).at(x), "CarryInSet", carry_set);
|
||||
}
|
||||
} else if (cell.second->type == ctx->id("SB_IO")) {
|
||||
} else if (cell.second->type == id_SB_IO) {
|
||||
const BelInfoPOD &beli = ci.bel_data[bel.index];
|
||||
int x = beli.x, y = beli.y, z = beli.z;
|
||||
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
|
||||
unsigned pin_type = get_param_or_def(ctx, cell.second.get(), ctx->id("PIN_TYPE"));
|
||||
bool neg_trigger = get_param_or_def(ctx, cell.second.get(), ctx->id("NEG_TRIGGER"));
|
||||
bool pullup = get_param_or_def(ctx, cell.second.get(), ctx->id("PULLUP"));
|
||||
unsigned pin_type = get_param_or_def(ctx, cell.second.get(), id_PIN_TYPE);
|
||||
bool neg_trigger = get_param_or_def(ctx, cell.second.get(), id_NEG_TRIGGER);
|
||||
bool pullup = get_param_or_def(ctx, cell.second.get(), id_PULLUP);
|
||||
bool lvds = cell.second->ioInfo.lvds;
|
||||
bool used_by_pll_out = sb_io_used_by_pll_out.count(Loc(x, y, z)) > 0;
|
||||
bool used_by_pll_pad = sb_io_used_by_pll_pad.count(Loc(x, y, z)) > 0;
|
||||
@ -550,8 +550,8 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
|
||||
if (ctx->args.type == ArchArgs::UP5K || ctx->args.type == ArchArgs::UP3K) {
|
||||
std::string pullup_resistor = "100K";
|
||||
if (cell.second->attrs.count(ctx->id("PULLUP_RESISTOR")))
|
||||
pullup_resistor = cell.second->attrs.at(ctx->id("PULLUP_RESISTOR")).as_string();
|
||||
if (cell.second->attrs.count(id_PULLUP_RESISTOR))
|
||||
pullup_resistor = cell.second->attrs.at(id_PULLUP_RESISTOR).as_string();
|
||||
NPNR_ASSERT(pullup_resistor == "100K" || pullup_resistor == "10K" || pullup_resistor == "6P8K" ||
|
||||
pullup_resistor == "3P3K");
|
||||
if (iez == 0) {
|
||||
@ -599,7 +599,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cell.second->type == ctx->id("SB_GB")) {
|
||||
} else if (cell.second->type == id_SB_GB) {
|
||||
if (cell.second->gbInfo.forPadIn) {
|
||||
Loc gb_loc = ctx->getBelLocation(bel);
|
||||
for (auto &glb : ci.global_network_info) {
|
||||
@ -608,7 +608,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (cell.second->type == ctx->id("ICESTORM_RAM")) {
|
||||
} else if (cell.second->type == id_ICESTORM_RAM) {
|
||||
const BelInfoPOD &beli = ci.bel_data[bel.index];
|
||||
int x = beli.x, y = beli.y;
|
||||
const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT];
|
||||
@ -616,10 +616,10 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
if (!(ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) {
|
||||
set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true);
|
||||
}
|
||||
bool negclk_r = get_param_or_def(ctx, cell.second.get(), ctx->id("NEG_CLK_R"));
|
||||
bool negclk_w = get_param_or_def(ctx, cell.second.get(), ctx->id("NEG_CLK_W"));
|
||||
int write_mode = get_param_or_def(ctx, cell.second.get(), ctx->id("WRITE_MODE"));
|
||||
int read_mode = get_param_or_def(ctx, cell.second.get(), ctx->id("READ_MODE"));
|
||||
bool negclk_r = get_param_or_def(ctx, cell.second.get(), id_NEG_CLK_R);
|
||||
bool negclk_w = get_param_or_def(ctx, cell.second.get(), id_NEG_CLK_W);
|
||||
int write_mode = get_param_or_def(ctx, cell.second.get(), id_WRITE_MODE);
|
||||
int read_mode = get_param_or_def(ctx, cell.second.get(), id_READ_MODE);
|
||||
set_config(ti_ramb, config.at(y).at(x), "NegClk", negclk_w);
|
||||
set_config(ti_ramt, config.at(y + 1).at(x), "NegClk", negclk_r);
|
||||
|
||||
@ -627,27 +627,27 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_1", write_mode & 0x2);
|
||||
set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_2", read_mode & 0x1);
|
||||
set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2);
|
||||
} else if (cell.second->type == ctx->id("SB_LED_DRV_CUR")) {
|
||||
} else if (cell.second->type == id_SB_LED_DRV_CUR) {
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "LED_DRV_CUR_EN", true,
|
||||
"IpConfig.");
|
||||
} else if (cell.second->type == ctx->id("SB_RGB_DRV")) {
|
||||
} else if (cell.second->type == id_SB_RGB_DRV) {
|
||||
const std::vector<std::pair<std::string, int>> rgb_params = {
|
||||
{"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}};
|
||||
configure_extra_cell(config, ctx, cell.second.get(), rgb_params, true, std::string("IpConfig."));
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "RGB_DRV_EN", true, "IpConfig.");
|
||||
} else if (cell.second->type == ctx->id("SB_RGBA_DRV")) {
|
||||
} else if (cell.second->type == id_SB_RGBA_DRV) {
|
||||
const std::vector<std::pair<std::string, int>> rgba_params = {
|
||||
{"CURRENT_MODE", 1}, {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}};
|
||||
configure_extra_cell(config, ctx, cell.second.get(), rgba_params, true, std::string("IpConfig."));
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "RGBA_DRV_EN", true, "IpConfig.");
|
||||
} else if (cell.second->type == ctx->id("SB_WARMBOOT") || cell.second->type == ctx->id("ICESTORM_LFOSC") ||
|
||||
cell.second->type == ctx->id("SB_LEDDA_IP")) {
|
||||
} else if (cell.second->type == id_SB_WARMBOOT || cell.second->type == id_ICESTORM_LFOSC ||
|
||||
cell.second->type == id_SB_LEDDA_IP) {
|
||||
// No config needed
|
||||
} else if (cell.second->type == ctx->id("SB_I2C")) {
|
||||
bool sda_in_dly = !cell.second->attrs.count(ctx->id("SDA_INPUT_DELAYED")) ||
|
||||
cell.second->attrs[ctx->id("SDA_INPUT_DELAYED")].as_bool();
|
||||
bool sda_out_dly = !cell.second->attrs.count(ctx->id("SDA_OUTPUT_DELAYED")) ||
|
||||
cell.second->attrs[ctx->id("SDA_OUTPUT_DELAYED")].as_bool();
|
||||
} else if (cell.second->type == id_SB_I2C) {
|
||||
bool sda_in_dly = !cell.second->attrs.count(id_SDA_INPUT_DELAYED) ||
|
||||
cell.second->attrs[id_SDA_INPUT_DELAYED].as_bool();
|
||||
bool sda_out_dly = !cell.second->attrs.count(id_SDA_OUTPUT_DELAYED) ||
|
||||
cell.second->attrs[id_SDA_OUTPUT_DELAYED].as_bool();
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SDA_INPUT_DELAYED", sda_in_dly,
|
||||
"IpConfig.");
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SDA_OUTPUT_DELAYED", sda_out_dly,
|
||||
@ -656,7 +656,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
"IpConfig.");
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "I2C_ENABLE_1", true,
|
||||
"IpConfig.");
|
||||
} else if (cell.second->type == ctx->id("SB_SPI")) {
|
||||
} else if (cell.second->type == id_SB_SPI) {
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_0", true,
|
||||
"IpConfig.");
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_1", true,
|
||||
@ -665,7 +665,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
"IpConfig.");
|
||||
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_3", true,
|
||||
"IpConfig.");
|
||||
} else if (cell.second->type == ctx->id("ICESTORM_SPRAM")) {
|
||||
} else if (cell.second->type == id_ICESTORM_SPRAM) {
|
||||
const BelInfoPOD &beli = ci.bel_data[bel.index];
|
||||
int x = beli.x, y = beli.y, z = beli.z;
|
||||
NPNR_ASSERT(ctx->args.type == ArchArgs::UP5K || ctx->args.type == ArchArgs::UP3K);
|
||||
@ -688,7 +688,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
NPNR_ASSERT(false);
|
||||
}
|
||||
}
|
||||
} else if (cell.second->type == ctx->id("ICESTORM_DSP")) {
|
||||
} else if (cell.second->type == id_ICESTORM_DSP) {
|
||||
const std::vector<std::pair<std::string, int>> mac16_params = {{"C_REG", 1},
|
||||
{"A_REG", 1},
|
||||
{"B_REG", 1},
|
||||
@ -709,13 +709,13 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
{"A_SIGNED", 1},
|
||||
{"B_SIGNED", 1}};
|
||||
configure_extra_cell(config, ctx, cell.second.get(), mac16_params, false, std::string("IpConfig."));
|
||||
} else if (cell.second->type == ctx->id("ICESTORM_HFOSC")) {
|
||||
} else if (cell.second->type == id_ICESTORM_HFOSC) {
|
||||
std::vector<std::pair<std::string, int>> hfosc_params = {{"CLKHF_DIV", 2}};
|
||||
if (ctx->args.type != ArchArgs::U4K && ctx->args.type != ArchArgs::U1K && ctx->args.type != ArchArgs::U2K)
|
||||
hfosc_params.push_back(std::pair<std::string, int>("TRIM_EN", 1));
|
||||
configure_extra_cell(config, ctx, cell.second.get(), hfosc_params, true, std::string("IpConfig."));
|
||||
|
||||
} else if (cell.second->type == ctx->id("ICESTORM_PLL")) {
|
||||
} else if (cell.second->type == id_ICESTORM_PLL) {
|
||||
const std::vector<std::pair<std::string, int>> pll_params = {{"DELAY_ADJMODE_FB", 1},
|
||||
{"DELAY_ADJMODE_REL", 1},
|
||||
{"DIVF", 7},
|
||||
@ -874,7 +874,7 @@ void write_asc(const Context *ctx, std::ostream &out)
|
||||
// Write RAM init data
|
||||
for (auto &cell : ctx->cells) {
|
||||
if (cell.second->bel != BelId()) {
|
||||
if (cell.second->type == ctx->id("ICESTORM_RAM")) {
|
||||
if (cell.second->type == id_ICESTORM_RAM) {
|
||||
const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index];
|
||||
int x = beli.x, y = beli.y;
|
||||
out << ".ram_data " << x << " " << y << std::endl;
|
||||
@ -1054,7 +1054,7 @@ bool read_asc(Context *ctx, std::istream &in)
|
||||
isUsed |= carry_set;
|
||||
|
||||
if (isUsed) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_ICESTORM_LC);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
@ -1074,7 +1074,7 @@ bool read_asc(Context *ctx, std::istream &in)
|
||||
isUsed |= neg_trigger;
|
||||
|
||||
if (isUsed) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_SB_IO);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
@ -1091,35 +1091,35 @@ bool read_asc(Context *ctx, std::istream &in)
|
||||
|
||||
if (ctx->checkBelAvail(belpin.bel)) {
|
||||
if (ctx->getBelType(belpin.bel) == id_ICESTORM_LC) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_ICESTORM_LC);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
// TODO: Add port mapping to nets
|
||||
}
|
||||
if (ctx->getBelType(belpin.bel) == id_SB_IO) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_IO"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_SB_IO);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
// TODO: Add port mapping to nets
|
||||
}
|
||||
if (ctx->getBelType(belpin.bel) == id_SB_GB) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_GB"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_SB_GB);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
// TODO: Add port mapping to nets
|
||||
}
|
||||
if (ctx->getBelType(belpin.bel) == id_SB_WARMBOOT) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("SB_WARMBOOT"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_SB_WARMBOOT);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
// TODO: Add port mapping to nets
|
||||
}
|
||||
if (ctx->getBelType(belpin.bel) == id_ICESTORM_LFOSC) {
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"));
|
||||
std::unique_ptr<CellInfo> created = create_ice_cell(ctx, id_ICESTORM_LFOSC);
|
||||
IdString name = created->name;
|
||||
ctx->cells[name] = std::move(created);
|
||||
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
|
||||
|
550
ice40/cells.cc
550
ice40/cells.cc
@ -33,61 +33,61 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
||||
name.empty() ? ctx->id("$nextpnr_" + type.str(ctx) + "_" + std::to_string(auto_idx++)) : ctx->id(name);
|
||||
auto new_cell = std::make_unique<CellInfo>(ctx, name_id, type);
|
||||
|
||||
if (type == ctx->id("ICESTORM_LC")) {
|
||||
new_cell->params[ctx->id("LUT_INIT")] = Property(0, 16);
|
||||
new_cell->params[ctx->id("NEG_CLK")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("CARRY_ENABLE")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("DFF_ENABLE")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("SET_NORESET")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("ASYNC_SR")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("CIN_CONST")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("CIN_SET")] = Property::State::S0;
|
||||
if (type == id_ICESTORM_LC) {
|
||||
new_cell->params[id_LUT_INIT] = Property(0, 16);
|
||||
new_cell->params[id_NEG_CLK] = Property::State::S0;
|
||||
new_cell->params[id_CARRY_ENABLE] = Property::State::S0;
|
||||
new_cell->params[id_DFF_ENABLE] = Property::State::S0;
|
||||
new_cell->params[id_SET_NORESET] = Property::State::S0;
|
||||
new_cell->params[id_ASYNC_SR] = Property::State::S0;
|
||||
new_cell->params[id_CIN_CONST] = Property::State::S0;
|
||||
new_cell->params[id_CIN_SET] = Property::State::S0;
|
||||
|
||||
new_cell->addInput(ctx->id("I0"));
|
||||
new_cell->addInput(ctx->id("I1"));
|
||||
new_cell->addInput(ctx->id("I2"));
|
||||
new_cell->addInput(ctx->id("I3"));
|
||||
new_cell->addInput(ctx->id("CIN"));
|
||||
new_cell->addInput(id_I0);
|
||||
new_cell->addInput(id_I1);
|
||||
new_cell->addInput(id_I2);
|
||||
new_cell->addInput(id_I3);
|
||||
new_cell->addInput(id_CIN);
|
||||
|
||||
new_cell->addInput(ctx->id("CLK"));
|
||||
new_cell->addInput(ctx->id("CEN"));
|
||||
new_cell->addInput(ctx->id("SR"));
|
||||
new_cell->addInput(id_CLK);
|
||||
new_cell->addInput(id_CEN);
|
||||
new_cell->addInput(id_SR);
|
||||
|
||||
new_cell->addOutput(ctx->id("LO"));
|
||||
new_cell->addOutput(ctx->id("O"));
|
||||
new_cell->addOutput(ctx->id("COUT"));
|
||||
} else if (type == ctx->id("SB_IO")) {
|
||||
new_cell->params[ctx->id("PIN_TYPE")] = Property(0, 6);
|
||||
new_cell->params[ctx->id("PULLUP")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("NEG_TRIGGER")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("IO_STANDARD")] = Property("SB_LVCMOS");
|
||||
new_cell->addOutput(id_LO);
|
||||
new_cell->addOutput(id_O);
|
||||
new_cell->addOutput(id_COUT);
|
||||
} else if (type == id_SB_IO) {
|
||||
new_cell->params[id_PIN_TYPE] = Property(0, 6);
|
||||
new_cell->params[id_PULLUP] = Property::State::S0;
|
||||
new_cell->params[id_NEG_TRIGGER] = Property::State::S0;
|
||||
new_cell->params[id_IO_STANDARD] = Property("SB_LVCMOS");
|
||||
|
||||
new_cell->addInout(ctx->id("PACKAGE_PIN"));
|
||||
new_cell->addInout(id_PACKAGE_PIN);
|
||||
|
||||
new_cell->addInput(ctx->id("LATCH_INPUT_VALUE"));
|
||||
new_cell->addInput(ctx->id("CLOCK_ENABLE"));
|
||||
new_cell->addInput(ctx->id("INPUT_CLK"));
|
||||
new_cell->addInput(ctx->id("OUTPUT_CLK"));
|
||||
new_cell->addInput(id_LATCH_INPUT_VALUE);
|
||||
new_cell->addInput(id_CLOCK_ENABLE);
|
||||
new_cell->addInput(id_INPUT_CLK);
|
||||
new_cell->addInput(id_OUTPUT_CLK);
|
||||
|
||||
new_cell->addInput(ctx->id("OUTPUT_ENABLE"));
|
||||
new_cell->addInput(ctx->id("D_OUT_0"));
|
||||
new_cell->addInput(ctx->id("D_OUT_1"));
|
||||
new_cell->addInput(id_OUTPUT_ENABLE);
|
||||
new_cell->addInput(id_D_OUT_0);
|
||||
new_cell->addInput(id_D_OUT_1);
|
||||
|
||||
new_cell->addOutput(ctx->id("D_IN_0"));
|
||||
new_cell->addOutput(ctx->id("D_IN_1"));
|
||||
} else if (type == ctx->id("ICESTORM_RAM")) {
|
||||
new_cell->params[ctx->id("NEG_CLK_W")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("NEG_CLK_R")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("WRITE_MODE")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("READ_MODE")] = Property::State::S0;
|
||||
new_cell->addOutput(id_D_IN_0);
|
||||
new_cell->addOutput(id_D_IN_1);
|
||||
} else if (type == id_ICESTORM_RAM) {
|
||||
new_cell->params[id_NEG_CLK_W] = Property::State::S0;
|
||||
new_cell->params[id_NEG_CLK_R] = Property::State::S0;
|
||||
new_cell->params[id_WRITE_MODE] = Property::State::S0;
|
||||
new_cell->params[id_READ_MODE] = Property::State::S0;
|
||||
|
||||
new_cell->addInput(ctx->id("RCLK"));
|
||||
new_cell->addInput(ctx->id("RCLKE"));
|
||||
new_cell->addInput(ctx->id("RE"));
|
||||
new_cell->addInput(id_RCLK);
|
||||
new_cell->addInput(id_RCLKE);
|
||||
new_cell->addInput(id_RE);
|
||||
|
||||
new_cell->addInput(ctx->id("WCLK"));
|
||||
new_cell->addInput(ctx->id("WCLKE"));
|
||||
new_cell->addInput(ctx->id("WE"));
|
||||
new_cell->addInput(id_WCLK);
|
||||
new_cell->addInput(id_WCLKE);
|
||||
new_cell->addInput(id_WE);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
new_cell->addInput(ctx->id("WDATA_" + std::to_string(i)));
|
||||
@ -99,31 +99,31 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
||||
new_cell->addInput(ctx->id("RADDR_" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("WADDR_" + std::to_string(i)));
|
||||
}
|
||||
} else if (type == ctx->id("ICESTORM_LFOSC")) {
|
||||
new_cell->addInput(ctx->id("CLKLFEN"));
|
||||
new_cell->addInput(ctx->id("CLKLFPU"));
|
||||
new_cell->addOutput(ctx->id("CLKLF"));
|
||||
new_cell->addOutput(ctx->id("CLKLF_FABRIC"));
|
||||
} else if (type == ctx->id("ICESTORM_HFOSC")) {
|
||||
new_cell->params[ctx->id("CLKHF_DIV")] = Property("0b00");
|
||||
new_cell->params[ctx->id("TRIM_EN")] = Property("0b0");
|
||||
} else if (type == id_ICESTORM_LFOSC) {
|
||||
new_cell->addInput(id_CLKLFEN);
|
||||
new_cell->addInput(id_CLKLFPU);
|
||||
new_cell->addOutput(id_CLKLF);
|
||||
new_cell->addOutput(id_CLKLF_FABRIC);
|
||||
} else if (type == id_ICESTORM_HFOSC) {
|
||||
new_cell->params[id_CLKHF_DIV] = Property("0b00");
|
||||
new_cell->params[id_TRIM_EN] = Property("0b0");
|
||||
|
||||
new_cell->addInput(ctx->id("CLKHFEN"));
|
||||
new_cell->addInput(ctx->id("CLKHFPU"));
|
||||
new_cell->addOutput(ctx->id("CLKHF"));
|
||||
new_cell->addOutput(ctx->id("CLKHF_FABRIC"));
|
||||
new_cell->addInput(id_CLKHFEN);
|
||||
new_cell->addInput(id_CLKHFPU);
|
||||
new_cell->addOutput(id_CLKHF);
|
||||
new_cell->addOutput(id_CLKHF_FABRIC);
|
||||
for (int i = 0; i < 10; i++)
|
||||
new_cell->addInput(ctx->id("TRIM" + std::to_string(i)));
|
||||
} else if (type == ctx->id("SB_GB")) {
|
||||
new_cell->addInput(ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER"));
|
||||
new_cell->addOutput(ctx->id("GLOBAL_BUFFER_OUTPUT"));
|
||||
} else if (type == ctx->id("ICESTORM_SPRAM")) {
|
||||
new_cell->addInput(ctx->id("WREN"));
|
||||
new_cell->addInput(ctx->id("CHIPSELECT"));
|
||||
new_cell->addInput(ctx->id("CLOCK"));
|
||||
new_cell->addInput(ctx->id("STANDBY"));
|
||||
new_cell->addInput(ctx->id("SLEEP"));
|
||||
new_cell->addInput(ctx->id("POWEROFF"));
|
||||
} else if (type == id_SB_GB) {
|
||||
new_cell->addInput(id_USER_SIGNAL_TO_GLOBAL_BUFFER);
|
||||
new_cell->addOutput(id_GLOBAL_BUFFER_OUTPUT);
|
||||
} else if (type == id_ICESTORM_SPRAM) {
|
||||
new_cell->addInput(id_WREN);
|
||||
new_cell->addInput(id_CHIPSELECT);
|
||||
new_cell->addInput(id_CLOCK);
|
||||
new_cell->addInput(id_STANDBY);
|
||||
new_cell->addInput(id_SLEEP);
|
||||
new_cell->addInput(id_POWEROFF);
|
||||
|
||||
for (int i = 0; i < 16; i++) {
|
||||
new_cell->addInput(ctx->id("DATAIN_" + std::to_string(i)));
|
||||
@ -135,196 +135,196 @@ std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::stri
|
||||
for (int i = 0; i < 4; i++) {
|
||||
new_cell->addInput(ctx->id("MASKWREN_" + std::to_string(i)));
|
||||
}
|
||||
} else if (type == ctx->id("ICESTORM_DSP")) {
|
||||
new_cell->params[ctx->id("NEG_TRIGGER")] = Property::State::S0;
|
||||
} else if (type == id_ICESTORM_DSP) {
|
||||
new_cell->params[id_NEG_TRIGGER] = Property::State::S0;
|
||||
|
||||
new_cell->params[ctx->id("C_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("A_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("B_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("D_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = Property::State::S0;
|
||||
new_cell->params[id_C_REG] = Property::State::S0;
|
||||
new_cell->params[id_A_REG] = Property::State::S0;
|
||||
new_cell->params[id_B_REG] = Property::State::S0;
|
||||
new_cell->params[id_D_REG] = Property::State::S0;
|
||||
new_cell->params[id_TOP_8x8_MULT_REG] = Property::State::S0;
|
||||
new_cell->params[id_BOT_8x8_MULT_REG] = Property::State::S0;
|
||||
new_cell->params[id_PIPELINE_16x16_MULT_REG1] = Property::State::S0;
|
||||
new_cell->params[id_PIPELINE_16x16_MULT_REG2] = Property::State::S0;
|
||||
|
||||
new_cell->params[ctx->id("TOPOUTPUT_SELECT")] = Property(0, 2);
|
||||
new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = Property(0, 2);
|
||||
new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = Property(0, 2);
|
||||
new_cell->params[id_TOPOUTPUT_SELECT] = Property(0, 2);
|
||||
new_cell->params[id_TOPADDSUB_LOWERINPUT] = Property(0, 2);
|
||||
new_cell->params[id_TOPADDSUB_UPPERINPUT] = Property::State::S0;
|
||||
new_cell->params[id_TOPADDSUB_CARRYSELECT] = Property(0, 2);
|
||||
|
||||
new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = Property(0, 2);
|
||||
new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = Property(0, 2);
|
||||
new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = Property(0, 2);
|
||||
new_cell->params[id_BOTOUTPUT_SELECT] = Property(0, 2);
|
||||
new_cell->params[id_BOTADDSUB_LOWERINPUT] = Property(0, 2);
|
||||
new_cell->params[id_BOTADDSUB_UPPERINPUT] = Property::State::S0;
|
||||
new_cell->params[id_BOTADDSUB_CARRYSELECT] = Property(0, 2);
|
||||
|
||||
new_cell->params[ctx->id("MODE_8x8")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("A_SIGNED")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("B_SIGNED")] = Property::State::S0;
|
||||
new_cell->params[id_MODE_8x8] = Property::State::S0;
|
||||
new_cell->params[id_A_SIGNED] = Property::State::S0;
|
||||
new_cell->params[id_B_SIGNED] = Property::State::S0;
|
||||
|
||||
new_cell->addInput(ctx->id("CLK"));
|
||||
new_cell->addInput(ctx->id("CE"));
|
||||
new_cell->addInput(id_CLK);
|
||||
new_cell->addInput(id_CE);
|
||||
for (int i = 0; i < 16; i++) {
|
||||
new_cell->addInput(ctx->id("C_" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("A_" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("B_" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("D_" + std::to_string(i)));
|
||||
}
|
||||
new_cell->addInput(ctx->id("AHOLD"));
|
||||
new_cell->addInput(ctx->id("BHOLD"));
|
||||
new_cell->addInput(ctx->id("CHOLD"));
|
||||
new_cell->addInput(ctx->id("DHOLD"));
|
||||
new_cell->addInput(id_AHOLD);
|
||||
new_cell->addInput(id_BHOLD);
|
||||
new_cell->addInput(id_CHOLD);
|
||||
new_cell->addInput(id_DHOLD);
|
||||
|
||||
new_cell->addInput(ctx->id("IRSTTOP"));
|
||||
new_cell->addInput(ctx->id("IRSTBOT"));
|
||||
new_cell->addInput(ctx->id("ORSTTOP"));
|
||||
new_cell->addInput(ctx->id("ORSTBOT"));
|
||||
new_cell->addInput(id_IRSTTOP);
|
||||
new_cell->addInput(id_IRSTBOT);
|
||||
new_cell->addInput(id_ORSTTOP);
|
||||
new_cell->addInput(id_ORSTBOT);
|
||||
|
||||
new_cell->addInput(ctx->id("OLOADTOP"));
|
||||
new_cell->addInput(ctx->id("OLOADBOT"));
|
||||
new_cell->addInput(id_OLOADTOP);
|
||||
new_cell->addInput(id_OLOADBOT);
|
||||
|
||||
new_cell->addInput(ctx->id("ADDSUBTOP"));
|
||||
new_cell->addInput(ctx->id("ADDSUBBOT"));
|
||||
new_cell->addInput(id_ADDSUBTOP);
|
||||
new_cell->addInput(id_ADDSUBBOT);
|
||||
|
||||
new_cell->addInput(ctx->id("OHOLDTOP"));
|
||||
new_cell->addInput(ctx->id("OHOLDBOT"));
|
||||
new_cell->addInput(id_OHOLDTOP);
|
||||
new_cell->addInput(id_OHOLDBOT);
|
||||
|
||||
new_cell->addInput(ctx->id("CI"));
|
||||
new_cell->addInput(ctx->id("ACCUMCI"));
|
||||
new_cell->addInput(ctx->id("SIGNEXTIN"));
|
||||
new_cell->addInput(id_CI);
|
||||
new_cell->addInput(id_ACCUMCI);
|
||||
new_cell->addInput(id_SIGNEXTIN);
|
||||
|
||||
for (int i = 0; i < 32; i++) {
|
||||
new_cell->addOutput(ctx->id("O_" + std::to_string(i)));
|
||||
}
|
||||
|
||||
new_cell->addOutput(ctx->id("CO"));
|
||||
new_cell->addOutput(ctx->id("ACCUMCO"));
|
||||
new_cell->addOutput(ctx->id("SIGNEXTOUT"));
|
||||
new_cell->addOutput(id_CO);
|
||||
new_cell->addOutput(id_ACCUMCO);
|
||||
new_cell->addOutput(id_SIGNEXTOUT);
|
||||
|
||||
} else if (type == ctx->id("ICESTORM_PLL")) {
|
||||
new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = Property::State::S0;
|
||||
} else if (type == id_ICESTORM_PLL) {
|
||||
new_cell->params[id_DELAY_ADJMODE_FB] = Property::State::S0;
|
||||
new_cell->params[id_DELAY_ADJMODE_REL] = Property::State::S0;
|
||||
|
||||
new_cell->params[ctx->id("DIVF")] = Property(0, 7);
|
||||
new_cell->params[ctx->id("DIVQ")] = Property(0, 3);
|
||||
new_cell->params[ctx->id("DIVR")] = Property(0, 4);
|
||||
new_cell->params[id_DIVF] = Property(0, 7);
|
||||
new_cell->params[id_DIVQ] = Property(0, 3);
|
||||
new_cell->params[id_DIVR] = Property(0, 4);
|
||||
|
||||
new_cell->params[ctx->id("FDA_FEEDBACK")] = Property(0, 4);
|
||||
new_cell->params[ctx->id("FDA_RELATIVE")] = Property(0, 4);
|
||||
new_cell->params[ctx->id("FEEDBACK_PATH")] = Property(1, 3);
|
||||
new_cell->params[ctx->id("FILTER_RANGE")] = Property(0, 3);
|
||||
new_cell->params[id_FDA_FEEDBACK] = Property(0, 4);
|
||||
new_cell->params[id_FDA_RELATIVE] = Property(0, 4);
|
||||
new_cell->params[id_FEEDBACK_PATH] = Property(1, 3);
|
||||
new_cell->params[id_FILTER_RANGE] = Property(0, 3);
|
||||
|
||||
new_cell->params[ctx->id("PLLOUT_SELECT_A")] = Property(0, 2);
|
||||
new_cell->params[ctx->id("PLLOUT_SELECT_B")] = Property(0, 2);
|
||||
new_cell->params[id_PLLOUT_SELECT_A] = Property(0, 2);
|
||||
new_cell->params[id_PLLOUT_SELECT_B] = Property(0, 2);
|
||||
|
||||
new_cell->params[ctx->id("PLLTYPE")] = Property(0, 3);
|
||||
new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = Property::State::S0;
|
||||
new_cell->params[ctx->id("TEST_MODE")] = Property::State::S0;
|
||||
new_cell->params[id_PLLTYPE] = Property(0, 3);
|
||||
new_cell->params[id_SHIFTREG_DIVMODE] = Property::State::S0;
|
||||
new_cell->params[id_TEST_MODE] = Property::State::S0;
|
||||
|
||||
new_cell->addInput(ctx->id("BYPASS"));
|
||||
new_cell->addInput(id_BYPASS);
|
||||
for (int i = 0; i < 8; i++)
|
||||
new_cell->addInput(ctx->id("DYNAMICDELAY_" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("EXTFEEDBACK"));
|
||||
new_cell->addInput(ctx->id("LATCHINPUTVALUE"));
|
||||
new_cell->addInput(ctx->id("REFERENCECLK"));
|
||||
new_cell->addInput(ctx->id("RESETB"));
|
||||
new_cell->addInput(id_EXTFEEDBACK);
|
||||
new_cell->addInput(id_LATCHINPUTVALUE);
|
||||
new_cell->addInput(id_REFERENCECLK);
|
||||
new_cell->addInput(id_RESETB);
|
||||
|
||||
new_cell->addInput(ctx->id("SCLK"));
|
||||
new_cell->addInput(ctx->id("SDI"));
|
||||
new_cell->addOutput(ctx->id("SDO"));
|
||||
new_cell->addInput(id_SCLK);
|
||||
new_cell->addInput(id_SDI);
|
||||
new_cell->addOutput(id_SDO);
|
||||
|
||||
new_cell->addOutput(ctx->id("LOCK"));
|
||||
new_cell->addOutput(ctx->id("PLLOUT_A"));
|
||||
new_cell->addOutput(ctx->id("PLLOUT_B"));
|
||||
new_cell->addOutput(ctx->id("PLLOUT_A_GLOBAL"));
|
||||
new_cell->addOutput(ctx->id("PLLOUT_B_GLOBAL"));
|
||||
} else if (type == ctx->id("SB_RGBA_DRV")) {
|
||||
new_cell->params[ctx->id("CURRENT_MODE")] = std::string("0b0");
|
||||
new_cell->params[ctx->id("RGB0_CURRENT")] = std::string("0b000000");
|
||||
new_cell->params[ctx->id("RGB1_CURRENT")] = std::string("0b000000");
|
||||
new_cell->params[ctx->id("RGB2_CURRENT")] = std::string("0b000000");
|
||||
new_cell->addOutput(id_LOCK);
|
||||
new_cell->addOutput(id_PLLOUT_A);
|
||||
new_cell->addOutput(id_PLLOUT_B);
|
||||
new_cell->addOutput(id_PLLOUT_A_GLOBAL);
|
||||
new_cell->addOutput(id_PLLOUT_B_GLOBAL);
|
||||
} else if (type == id_SB_RGBA_DRV) {
|
||||
new_cell->params[id_CURRENT_MODE] = std::string("0b0");
|
||||
new_cell->params[id_RGB0_CURRENT] = std::string("0b000000");
|
||||
new_cell->params[id_RGB1_CURRENT] = std::string("0b000000");
|
||||
new_cell->params[id_RGB2_CURRENT] = std::string("0b000000");
|
||||
|
||||
new_cell->addInput(ctx->id("CURREN"));
|
||||
new_cell->addInput(ctx->id("RGBLEDEN"));
|
||||
new_cell->addInput(ctx->id("RGB0PWM"));
|
||||
new_cell->addInput(ctx->id("RGB1PWM"));
|
||||
new_cell->addInput(ctx->id("RGB2PWM"));
|
||||
new_cell->addOutput(ctx->id("RGB0"));
|
||||
new_cell->addOutput(ctx->id("RGB1"));
|
||||
new_cell->addOutput(ctx->id("RGB2"));
|
||||
} else if (type == ctx->id("SB_LED_DRV_CUR")) {
|
||||
new_cell->addInput(ctx->id("EN"));
|
||||
new_cell->addOutput(ctx->id("LEDPU"));
|
||||
} else if (type == ctx->id("SB_RGB_DRV")) {
|
||||
new_cell->params[ctx->id("RGB0_CURRENT")] = std::string("0b000000");
|
||||
new_cell->params[ctx->id("RGB1_CURRENT")] = std::string("0b000000");
|
||||
new_cell->params[ctx->id("RGB2_CURRENT")] = std::string("0b000000");
|
||||
new_cell->addInput(id_CURREN);
|
||||
new_cell->addInput(id_RGBLEDEN);
|
||||
new_cell->addInput(id_RGB0PWM);
|
||||
new_cell->addInput(id_RGB1PWM);
|
||||
new_cell->addInput(id_RGB2PWM);
|
||||
new_cell->addOutput(id_RGB0);
|
||||
new_cell->addOutput(id_RGB1);
|
||||
new_cell->addOutput(id_RGB2);
|
||||
} else if (type == id_SB_LED_DRV_CUR) {
|
||||
new_cell->addInput(id_EN);
|
||||
new_cell->addOutput(id_LEDPU);
|
||||
} else if (type == id_SB_RGB_DRV) {
|
||||
new_cell->params[id_RGB0_CURRENT] = std::string("0b000000");
|
||||
new_cell->params[id_RGB1_CURRENT] = std::string("0b000000");
|
||||
new_cell->params[id_RGB2_CURRENT] = std::string("0b000000");
|
||||
|
||||
new_cell->addInput(ctx->id("RGBPU"));
|
||||
new_cell->addInput(ctx->id("RGBLEDEN"));
|
||||
new_cell->addInput(ctx->id("RGB0PWM"));
|
||||
new_cell->addInput(ctx->id("RGB1PWM"));
|
||||
new_cell->addInput(ctx->id("RGB2PWM"));
|
||||
new_cell->addOutput(ctx->id("RGB0"));
|
||||
new_cell->addOutput(ctx->id("RGB1"));
|
||||
new_cell->addOutput(ctx->id("RGB2"));
|
||||
} else if (type == ctx->id("SB_LEDDA_IP")) {
|
||||
new_cell->addInput(ctx->id("LEDDCS"));
|
||||
new_cell->addInput(ctx->id("LEDDCLK"));
|
||||
new_cell->addInput(id_RGBPU);
|
||||
new_cell->addInput(id_RGBLEDEN);
|
||||
new_cell->addInput(id_RGB0PWM);
|
||||
new_cell->addInput(id_RGB1PWM);
|
||||
new_cell->addInput(id_RGB2PWM);
|
||||
new_cell->addOutput(id_RGB0);
|
||||
new_cell->addOutput(id_RGB1);
|
||||
new_cell->addOutput(id_RGB2);
|
||||
} else if (type == id_SB_LEDDA_IP) {
|
||||
new_cell->addInput(id_LEDDCS);
|
||||
new_cell->addInput(id_LEDDCLK);
|
||||
for (int i = 0; i < 8; i++)
|
||||
new_cell->addInput(ctx->id("LEDDDAT" + std::to_string(i)));
|
||||
for (int i = 0; i < 3; i++)
|
||||
new_cell->addInput(ctx->id("LEDDADDR" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("LEDDDEN"));
|
||||
new_cell->addInput(ctx->id("LEDDEXE"));
|
||||
new_cell->addInput(ctx->id("LEDDRST")); // doesn't actually exist, for icecube code compatibility
|
||||
// only
|
||||
new_cell->addOutput(ctx->id("PWMOUT0"));
|
||||
new_cell->addOutput(ctx->id("PWMOUT1"));
|
||||
new_cell->addOutput(ctx->id("PWMOUT2"));
|
||||
new_cell->addOutput(ctx->id("LEDDON"));
|
||||
} else if (type == ctx->id("SB_I2C")) {
|
||||
new_cell->params[ctx->id("I2C_SLAVE_INIT_ADDR")] = std::string("0b1111100001");
|
||||
new_cell->params[ctx->id("BUS_ADDR74")] = std::string("0b0001");
|
||||
new_cell->addInput(id_LEDDDEN);
|
||||
new_cell->addInput(id_LEDDEXE);
|
||||
new_cell->addInput(id_LEDDRST); // doesn't actually exist, for icecube code compatibility
|
||||
// only
|
||||
new_cell->addOutput(id_PWMOUT0);
|
||||
new_cell->addOutput(id_PWMOUT1);
|
||||
new_cell->addOutput(id_PWMOUT2);
|
||||
new_cell->addOutput(id_LEDDON);
|
||||
} else if (type == id_SB_I2C) {
|
||||
new_cell->params[id_I2C_SLAVE_INIT_ADDR] = std::string("0b1111100001");
|
||||
new_cell->params[id_BUS_ADDR74] = std::string("0b0001");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
new_cell->addInput(ctx->id("SBADRI" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("SBDATI" + std::to_string(i)));
|
||||
new_cell->addOutput(ctx->id("SBDATO" + std::to_string(i)));
|
||||
}
|
||||
new_cell->addInput(ctx->id("SBCLKI"));
|
||||
new_cell->addInput(ctx->id("SBRWI"));
|
||||
new_cell->addInput(ctx->id("SBSTBI"));
|
||||
new_cell->addInput(ctx->id("SCLI"));
|
||||
new_cell->addInput(ctx->id("SDAI"));
|
||||
new_cell->addOutput(ctx->id("SBACKO"));
|
||||
new_cell->addOutput(ctx->id("I2CIRQ"));
|
||||
new_cell->addOutput(ctx->id("I2CWKUP"));
|
||||
new_cell->addOutput(ctx->id("SCLO"));
|
||||
new_cell->addOutput(ctx->id("SCLOE"));
|
||||
new_cell->addOutput(ctx->id("SDAO"));
|
||||
new_cell->addOutput(ctx->id("SDAOE"));
|
||||
} else if (type == ctx->id("SB_SPI")) {
|
||||
new_cell->params[ctx->id("BUS_ADDR74")] = std::string("0b0000");
|
||||
new_cell->addInput(id_SBCLKI);
|
||||
new_cell->addInput(id_SBRWI);
|
||||
new_cell->addInput(id_SBSTBI);
|
||||
new_cell->addInput(id_SCLI);
|
||||
new_cell->addInput(id_SDAI);
|
||||
new_cell->addOutput(id_SBACKO);
|
||||
new_cell->addOutput(id_I2CIRQ);
|
||||
new_cell->addOutput(id_I2CWKUP);
|
||||
new_cell->addOutput(id_SCLO);
|
||||
new_cell->addOutput(id_SCLOE);
|
||||
new_cell->addOutput(id_SDAO);
|
||||
new_cell->addOutput(id_SDAOE);
|
||||
} else if (type == id_SB_SPI) {
|
||||
new_cell->params[id_BUS_ADDR74] = std::string("0b0000");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
new_cell->addInput(ctx->id("SBADRI" + std::to_string(i)));
|
||||
new_cell->addInput(ctx->id("SBDATI" + std::to_string(i)));
|
||||
new_cell->addOutput(ctx->id("SBDATO" + std::to_string(i)));
|
||||
}
|
||||
new_cell->addInput(ctx->id("SBCLKI"));
|
||||
new_cell->addInput(ctx->id("SBRWI"));
|
||||
new_cell->addInput(ctx->id("SBSTBI"));
|
||||
new_cell->addInput(ctx->id("MI"));
|
||||
new_cell->addInput(ctx->id("SI"));
|
||||
new_cell->addInput(ctx->id("SCKI"));
|
||||
new_cell->addInput(ctx->id("SCSNI"));
|
||||
new_cell->addOutput(ctx->id("SBACKO"));
|
||||
new_cell->addOutput(ctx->id("SPIIRQ"));
|
||||
new_cell->addOutput(ctx->id("SPIWKUP"));
|
||||
new_cell->addOutput(ctx->id("SO"));
|
||||
new_cell->addOutput(ctx->id("SOE"));
|
||||
new_cell->addOutput(ctx->id("MO"));
|
||||
new_cell->addOutput(ctx->id("MOE"));
|
||||
new_cell->addOutput(ctx->id("SCKO"));
|
||||
new_cell->addOutput(ctx->id("SCKOE"));
|
||||
new_cell->addInput(id_SBCLKI);
|
||||
new_cell->addInput(id_SBRWI);
|
||||
new_cell->addInput(id_SBSTBI);
|
||||
new_cell->addInput(id_MI);
|
||||
new_cell->addInput(id_SI);
|
||||
new_cell->addInput(id_SCKI);
|
||||
new_cell->addInput(id_SCSNI);
|
||||
new_cell->addOutput(id_SBACKO);
|
||||
new_cell->addOutput(id_SPIIRQ);
|
||||
new_cell->addOutput(id_SPIWKUP);
|
||||
new_cell->addOutput(id_SO);
|
||||
new_cell->addOutput(id_SOE);
|
||||
new_cell->addOutput(id_MO);
|
||||
new_cell->addOutput(id_MOE);
|
||||
new_cell->addOutput(id_SCKO);
|
||||
new_cell->addOutput(id_SCKOE);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
new_cell->addOutput(ctx->id("MCSNO" + std::to_string(i)));
|
||||
new_cell->addOutput(ctx->id("MCSNOE" + std::to_string(i)));
|
||||
@ -339,14 +339,14 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = lut->hierpath;
|
||||
lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")].extract(0, 16, Property::State::S0);
|
||||
replace_port(lut, ctx->id("I0"), lc, ctx->id("I0"));
|
||||
replace_port(lut, ctx->id("I1"), lc, ctx->id("I1"));
|
||||
replace_port(lut, ctx->id("I2"), lc, ctx->id("I2"));
|
||||
replace_port(lut, ctx->id("I3"), lc, ctx->id("I3"));
|
||||
lc->params[id_LUT_INIT] = lut->params[id_LUT_INIT].extract(0, 16, Property::State::S0);
|
||||
replace_port(lut, id_I0, lc, id_I0);
|
||||
replace_port(lut, id_I1, lc, id_I1);
|
||||
replace_port(lut, id_I2, lc, id_I2);
|
||||
replace_port(lut, id_I3, lc, id_I3);
|
||||
if (no_dff) {
|
||||
replace_port(lut, ctx->id("O"), lc, ctx->id("O"));
|
||||
lc->params[ctx->id("DFF_ENABLE")] = Property::State::S0;
|
||||
replace_port(lut, id_O, lc, id_O);
|
||||
lc->params[id_DFF_ENABLE] = Property::State::S0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -354,20 +354,20 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
|
||||
{
|
||||
if (lc->hierpath == IdString())
|
||||
lc->hierpath = dff->hierpath;
|
||||
lc->params[ctx->id("DFF_ENABLE")] = Property::State::S1;
|
||||
lc->params[id_DFF_ENABLE] = Property::State::S1;
|
||||
std::string config = dff->type.str(ctx).substr(6);
|
||||
auto citer = config.begin();
|
||||
replace_port(dff, ctx->id("C"), lc, ctx->id("CLK"));
|
||||
replace_port(dff, id_C, lc, id_CLK);
|
||||
|
||||
if (citer != config.end() && *citer == 'N') {
|
||||
lc->params[ctx->id("NEG_CLK")] = Property::State::S1;
|
||||
lc->params[id_NEG_CLK] = Property::State::S1;
|
||||
++citer;
|
||||
} else {
|
||||
lc->params[ctx->id("NEG_CLK")] = Property::State::S0;
|
||||
lc->params[id_NEG_CLK] = Property::State::S0;
|
||||
}
|
||||
|
||||
if (citer != config.end() && *citer == 'E') {
|
||||
replace_port(dff, ctx->id("E"), lc, ctx->id("CEN"));
|
||||
replace_port(dff, id_E, lc, id_CEN);
|
||||
++citer;
|
||||
}
|
||||
|
||||
@ -375,60 +375,60 @@ void dff_to_lc(const Context *ctx, CellInfo *dff, CellInfo *lc, bool pass_thru_l
|
||||
if ((config.end() - citer) >= 2) {
|
||||
char c = *(citer++);
|
||||
NPNR_ASSERT(c == 'S');
|
||||
lc->params[ctx->id("ASYNC_SR")] = Property::State::S0;
|
||||
lc->params[id_ASYNC_SR] = Property::State::S0;
|
||||
} else {
|
||||
lc->params[ctx->id("ASYNC_SR")] = Property::State::S1;
|
||||
lc->params[id_ASYNC_SR] = Property::State::S1;
|
||||
}
|
||||
|
||||
if (*citer == 'S') {
|
||||
citer++;
|
||||
replace_port(dff, ctx->id("S"), lc, ctx->id("SR"));
|
||||
lc->params[ctx->id("SET_NORESET")] = Property::State::S1;
|
||||
replace_port(dff, id_S, lc, id_SR);
|
||||
lc->params[id_SET_NORESET] = Property::State::S1;
|
||||
} else {
|
||||
NPNR_ASSERT(*citer == 'R');
|
||||
citer++;
|
||||
replace_port(dff, ctx->id("R"), lc, ctx->id("SR"));
|
||||
lc->params[ctx->id("SET_NORESET")] = Property::State::S0;
|
||||
replace_port(dff, id_R, lc, id_SR);
|
||||
lc->params[id_SET_NORESET] = Property::State::S0;
|
||||
}
|
||||
}
|
||||
|
||||
NPNR_ASSERT(citer == config.end());
|
||||
|
||||
if (pass_thru_lut) {
|
||||
lc->params[ctx->id("LUT_INIT")] = Property(2, 16);
|
||||
replace_port(dff, ctx->id("D"), lc, ctx->id("I0"));
|
||||
lc->params[id_LUT_INIT] = Property(2, 16);
|
||||
replace_port(dff, id_D, lc, id_I0);
|
||||
}
|
||||
|
||||
replace_port(dff, ctx->id("Q"), lc, ctx->id("O"));
|
||||
replace_port(dff, id_Q, lc, id_O);
|
||||
}
|
||||
|
||||
void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells)
|
||||
{
|
||||
if (nxio->type == ctx->id("$nextpnr_ibuf")) {
|
||||
sbio->params[ctx->id("PIN_TYPE")] = 1;
|
||||
auto pu_attr = nxio->attrs.find(ctx->id("PULLUP"));
|
||||
sbio->params[id_PIN_TYPE] = 1;
|
||||
auto pu_attr = nxio->attrs.find(id_PULLUP);
|
||||
if (pu_attr != nxio->attrs.end())
|
||||
sbio->params[ctx->id("PULLUP")] = pu_attr->second;
|
||||
replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
|
||||
sbio->params[id_PULLUP] = pu_attr->second;
|
||||
replace_port(nxio, id_O, sbio, id_D_IN_0);
|
||||
} else if (nxio->type == ctx->id("$nextpnr_obuf")) {
|
||||
sbio->params[ctx->id("PIN_TYPE")] = 25;
|
||||
replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
|
||||
sbio->params[id_PIN_TYPE] = 25;
|
||||
replace_port(nxio, id_I, sbio, id_D_OUT_0);
|
||||
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
|
||||
// N.B. tristate will be dealt with below
|
||||
NetInfo *i = get_net_or_empty(nxio, ctx->id("I"));
|
||||
NetInfo *i = get_net_or_empty(nxio, id_I);
|
||||
if (i == nullptr || i->driver.cell == nullptr)
|
||||
sbio->params[ctx->id("PIN_TYPE")] = 1;
|
||||
sbio->params[id_PIN_TYPE] = 1;
|
||||
else
|
||||
sbio->params[ctx->id("PIN_TYPE")] = 25;
|
||||
auto pu_attr = nxio->attrs.find(ctx->id("PULLUP"));
|
||||
sbio->params[id_PIN_TYPE] = 25;
|
||||
auto pu_attr = nxio->attrs.find(id_PULLUP);
|
||||
if (pu_attr != nxio->attrs.end())
|
||||
sbio->params[ctx->id("PULLUP")] = pu_attr->second;
|
||||
replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0"));
|
||||
replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0"));
|
||||
sbio->params[id_PULLUP] = pu_attr->second;
|
||||
replace_port(nxio, id_I, sbio, id_D_OUT_0);
|
||||
replace_port(nxio, id_O, sbio, id_D_IN_0);
|
||||
} else {
|
||||
NPNR_ASSERT(false);
|
||||
}
|
||||
NetInfo *donet = sbio->ports.at(ctx->id("D_OUT_0")).net, *dinet = sbio->ports.at(ctx->id("D_IN_0")).net;
|
||||
NetInfo *donet = sbio->ports.at(id_D_OUT_0).net, *dinet = sbio->ports.at(id_D_IN_0).net;
|
||||
|
||||
// Rename I/O nets to avoid conflicts
|
||||
if (donet != nullptr && donet->name == nxio->name)
|
||||
@ -451,17 +451,17 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
|
||||
NPNR_ASSERT(!ctx->nets.count(tn_netname));
|
||||
ctx->net_aliases.erase(tn_netname);
|
||||
NetInfo *toplevel_net = ctx->createNet(tn_netname);
|
||||
connect_port(ctx, toplevel_net, sbio, ctx->id("PACKAGE_PIN"));
|
||||
connect_port(ctx, toplevel_net, sbio, id_PACKAGE_PIN);
|
||||
ctx->ports[nxio->name].net = toplevel_net;
|
||||
}
|
||||
|
||||
CellInfo *tbuf = net_driven_by(
|
||||
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
|
||||
ctx->id("Y"));
|
||||
id_Y);
|
||||
if (tbuf) {
|
||||
sbio->params[ctx->id("PIN_TYPE")] = 41;
|
||||
replace_port(tbuf, ctx->id("A"), sbio, ctx->id("D_OUT_0"));
|
||||
replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE"));
|
||||
sbio->params[id_PIN_TYPE] = 41;
|
||||
replace_port(tbuf, id_A, sbio, id_D_OUT_0);
|
||||
replace_port(tbuf, id_E, sbio, id_OUTPUT_ENABLE);
|
||||
|
||||
if (donet->users.size() > 1) {
|
||||
for (auto user : donet->users)
|
||||
@ -477,15 +477,15 @@ void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &to
|
||||
|
||||
uint8_t sb_pll40_type(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
if (cell->type == ctx->id("SB_PLL40_PAD"))
|
||||
if (cell->type == id_SB_PLL40_PAD)
|
||||
return 2;
|
||||
if (cell->type == ctx->id("SB_PLL40_2_PAD"))
|
||||
if (cell->type == id_SB_PLL40_2_PAD)
|
||||
return 4;
|
||||
if (cell->type == ctx->id("SB_PLL40_2F_PAD"))
|
||||
if (cell->type == id_SB_PLL40_2F_PAD)
|
||||
return 6;
|
||||
if (cell->type == ctx->id("SB_PLL40_CORE"))
|
||||
if (cell->type == id_SB_PLL40_CORE)
|
||||
return 3;
|
||||
if (cell->type == ctx->id("SB_PLL40_2F_CORE"))
|
||||
if (cell->type == id_SB_PLL40_2F_CORE)
|
||||
return 7;
|
||||
NPNR_ASSERT(0);
|
||||
}
|
||||
@ -495,15 +495,14 @@ bool is_clock_port(const BaseCtx *ctx, const PortRef &port)
|
||||
if (port.cell == nullptr)
|
||||
return false;
|
||||
if (is_ff(ctx, port.cell))
|
||||
return port.port == ctx->id("C");
|
||||
if (port.cell->type == ctx->id("ICESTORM_LC"))
|
||||
return port.port == ctx->id("CLK");
|
||||
if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM"))
|
||||
return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK") || port.port == ctx->id("RCLKN") ||
|
||||
port.port == ctx->id("WCLKN");
|
||||
if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP"))
|
||||
return port.port == ctx->id("CLK");
|
||||
if (is_sb_spram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_SPRAM"))
|
||||
return port.port == id_C;
|
||||
if (port.cell->type == id_ICESTORM_LC)
|
||||
return port.port == id_CLK;
|
||||
if (is_ram(ctx, port.cell) || port.cell->type == id_ICESTORM_RAM)
|
||||
return port.port == id_RCLK || port.port == id_WCLK || port.port == id_RCLKN || port.port == id_WCLKN;
|
||||
if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
|
||||
return port.port == id_CLK;
|
||||
if (is_sb_spram(ctx, port.cell) || port.cell->type == id_ICESTORM_SPRAM)
|
||||
return port.port == id_CLOCK;
|
||||
if (is_sb_io(ctx, port.cell))
|
||||
return port.port == id_INPUT_CLK || port.port == id_OUTPUT_CLK;
|
||||
@ -515,12 +514,11 @@ bool is_reset_port(const BaseCtx *ctx, const PortRef &port)
|
||||
if (port.cell == nullptr)
|
||||
return false;
|
||||
if (is_ff(ctx, port.cell))
|
||||
return port.port == ctx->id("R") || port.port == ctx->id("S");
|
||||
if (port.cell->type == ctx->id("ICESTORM_LC"))
|
||||
return port.port == ctx->id("SR");
|
||||
if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP"))
|
||||
return port.port == ctx->id("IRSTTOP") || port.port == ctx->id("IRSTBOT") || port.port == ctx->id("ORSTTOP") ||
|
||||
port.port == ctx->id("ORSTBOT");
|
||||
return port.port == id_R || port.port == id_S;
|
||||
if (port.cell->type == id_ICESTORM_LC)
|
||||
return port.port == id_SR;
|
||||
if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
|
||||
return port.port == id_IRSTTOP || port.port == id_IRSTBOT || port.port == id_ORSTTOP || port.port == id_ORSTBOT;
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -529,12 +527,12 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
|
||||
if (port.cell == nullptr)
|
||||
return false;
|
||||
if (is_ff(ctx, port.cell))
|
||||
return port.port == ctx->id("E");
|
||||
if (port.cell->type == ctx->id("ICESTORM_LC"))
|
||||
return port.port == ctx->id("CEN");
|
||||
return port.port == id_E;
|
||||
if (port.cell->type == id_ICESTORM_LC)
|
||||
return port.port == id_CEN;
|
||||
// FIXME
|
||||
// if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP"))
|
||||
// return port.port == ctx->id("CE");
|
||||
// if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
|
||||
// return port.port == id_CE;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -30,90 +30,80 @@ NEXTPNR_NAMESPACE_BEGIN
|
||||
std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = "");
|
||||
|
||||
// Return true if a cell is a LUT
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LUT4"); }
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_LUT4; }
|
||||
|
||||
// Return true if a cell is a flipflop
|
||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_DFF") || cell->type == ctx->id("SB_DFFE") || cell->type == ctx->id("SB_DFFSR") ||
|
||||
cell->type == ctx->id("SB_DFFR") || cell->type == ctx->id("SB_DFFSS") || cell->type == ctx->id("SB_DFFS") ||
|
||||
cell->type == ctx->id("SB_DFFESR") || cell->type == ctx->id("SB_DFFER") ||
|
||||
cell->type == ctx->id("SB_DFFESS") || cell->type == ctx->id("SB_DFFES") ||
|
||||
cell->type == ctx->id("SB_DFFN") || cell->type == ctx->id("SB_DFFNE") ||
|
||||
cell->type == ctx->id("SB_DFFNSR") || cell->type == ctx->id("SB_DFFNR") ||
|
||||
cell->type == ctx->id("SB_DFFNSS") || cell->type == ctx->id("SB_DFFNS") ||
|
||||
cell->type == ctx->id("SB_DFFNESR") || cell->type == ctx->id("SB_DFFNER") ||
|
||||
cell->type == ctx->id("SB_DFFNESS") || cell->type == ctx->id("SB_DFFNES");
|
||||
return cell->type == id_SB_DFF || cell->type == id_SB_DFFE || cell->type == id_SB_DFFSR ||
|
||||
cell->type == id_SB_DFFR || cell->type == id_SB_DFFSS || cell->type == id_SB_DFFS ||
|
||||
cell->type == id_SB_DFFESR || cell->type == id_SB_DFFER || cell->type == id_SB_DFFESS ||
|
||||
cell->type == id_SB_DFFES || cell->type == id_SB_DFFN || cell->type == id_SB_DFFNE ||
|
||||
cell->type == id_SB_DFFNSR || cell->type == id_SB_DFFNR || cell->type == id_SB_DFFNSS ||
|
||||
cell->type == id_SB_DFFNS || cell->type == id_SB_DFFNESR || cell->type == id_SB_DFFNER ||
|
||||
cell->type == id_SB_DFFNESS || cell->type == id_SB_DFFNES;
|
||||
}
|
||||
|
||||
inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_CARRY"); }
|
||||
inline bool is_carry(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_CARRY; }
|
||||
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("ICESTORM_LC"); }
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_ICESTORM_LC; }
|
||||
|
||||
// Return true if a cell is a SB_IO
|
||||
inline bool is_sb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_IO"); }
|
||||
inline bool is_sb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_IO; }
|
||||
|
||||
// Return true if a cell is a SB_GB_IO
|
||||
inline bool is_sb_gb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_GB_IO"); }
|
||||
inline bool is_sb_gb_io(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_GB_IO; }
|
||||
|
||||
// Return true if a cell is a global buffer
|
||||
inline bool is_gbuf(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_GB"); }
|
||||
inline bool is_gbuf(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_GB; }
|
||||
|
||||
// Return true if a cell is a RAM
|
||||
inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_RAM40_4K") || cell->type == ctx->id("SB_RAM40_4KNR") ||
|
||||
cell->type == ctx->id("SB_RAM40_4KNW") || cell->type == ctx->id("SB_RAM40_4KNRNW");
|
||||
return cell->type == id_SB_RAM40_4K || cell->type == id_SB_RAM40_4KNR || cell->type == id_SB_RAM40_4KNW ||
|
||||
cell->type == id_SB_RAM40_4KNRNW;
|
||||
}
|
||||
|
||||
inline bool is_sb_lfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LFOSC"); }
|
||||
inline bool is_sb_lfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_LFOSC; }
|
||||
|
||||
inline bool is_sb_hfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_HFOSC"); }
|
||||
inline bool is_sb_hfosc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_HFOSC; }
|
||||
|
||||
inline bool is_sb_spram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_SPRAM256KA"); }
|
||||
inline bool is_sb_spram(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_SPRAM256KA; }
|
||||
|
||||
inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_MAC16"); }
|
||||
inline bool is_sb_mac16(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_MAC16; }
|
||||
|
||||
inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGBA_DRV"); }
|
||||
inline bool is_sb_rgba_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_RGBA_DRV; }
|
||||
|
||||
inline bool is_sb_rgb_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_RGB_DRV"); }
|
||||
inline bool is_sb_rgb_drv(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_RGB_DRV; }
|
||||
|
||||
inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_LED_DRV_CUR");
|
||||
}
|
||||
inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_LED_DRV_CUR; }
|
||||
|
||||
inline bool is_sb_ledda_ip(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_LEDDA_IP"); }
|
||||
inline bool is_sb_ledda_ip(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_LEDDA_IP; }
|
||||
|
||||
inline bool is_sb_i2c(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_I2C"); }
|
||||
inline bool is_sb_i2c(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_I2C; }
|
||||
|
||||
inline bool is_sb_spi(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("SB_SPI"); }
|
||||
inline bool is_sb_spi(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_SPI; }
|
||||
|
||||
inline bool is_sb_pll40(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_PLL40_PAD") || cell->type == ctx->id("SB_PLL40_2_PAD") ||
|
||||
cell->type == ctx->id("SB_PLL40_2F_PAD") || cell->type == ctx->id("SB_PLL40_CORE") ||
|
||||
cell->type == ctx->id("SB_PLL40_2F_CORE");
|
||||
return cell->type == id_SB_PLL40_PAD || cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD ||
|
||||
cell->type == id_SB_PLL40_CORE || cell->type == id_SB_PLL40_2F_CORE;
|
||||
}
|
||||
|
||||
inline bool is_sb_pll40_pad(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_PLL40_PAD") || cell->type == ctx->id("SB_PLL40_2_PAD") ||
|
||||
cell->type == ctx->id("SB_PLL40_2F_PAD") ||
|
||||
(cell->type == ctx->id("ICESTORM_PLL") &&
|
||||
(cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_PAD" ||
|
||||
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2_PAD" ||
|
||||
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2F_PAD"));
|
||||
return cell->type == id_SB_PLL40_PAD || cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD ||
|
||||
(cell->type == id_ICESTORM_PLL && (cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_PAD" ||
|
||||
cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2_PAD" ||
|
||||
cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_PAD"));
|
||||
}
|
||||
|
||||
inline bool is_sb_pll40_dual(const BaseCtx *ctx, const CellInfo *cell)
|
||||
{
|
||||
return cell->type == ctx->id("SB_PLL40_2_PAD") || cell->type == ctx->id("SB_PLL40_2F_PAD") ||
|
||||
cell->type == ctx->id("SB_PLL40_2F_CORE") ||
|
||||
(cell->type == ctx->id("ICESTORM_PLL") &&
|
||||
(cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2_PAD" ||
|
||||
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2F_PAD" ||
|
||||
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2F_CORE"));
|
||||
return cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD || cell->type == id_SB_PLL40_2F_CORE ||
|
||||
(cell->type == id_ICESTORM_PLL && (cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2_PAD" ||
|
||||
cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_PAD" ||
|
||||
cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_CORE"));
|
||||
}
|
||||
|
||||
uint8_t sb_pll40_type(const BaseCtx *ctx, const CellInfo *cell);
|
||||
|
@ -53,9 +53,9 @@ class ChainConstrainer
|
||||
tile.clear();
|
||||
chains.emplace_back();
|
||||
start_of_chain = false;
|
||||
if (cell->ports.at(ctx->id("CIN")).net) {
|
||||
if (cell->ports.at(id_CIN).net) {
|
||||
// CIN is not constant and not part of a chain. Must feed in from fabric
|
||||
CellInfo *feedin = make_carry_feed_in(cell, cell->ports.at(ctx->id("CIN")));
|
||||
CellInfo *feedin = make_carry_feed_in(cell, cell->ports.at(id_CIN));
|
||||
chains.back().cells.push_back(feedin);
|
||||
tile.push_back(feedin);
|
||||
++feedio_lcs;
|
||||
@ -66,18 +66,18 @@ class ChainConstrainer
|
||||
bool split_chain = (!ctx->logic_cells_compatible(tile.data(), tile.size())) ||
|
||||
(int(chains.back().cells.size()) > max_length);
|
||||
if (split_chain) {
|
||||
CellInfo *passout = make_carry_pass_out((*(curr_cell - 1))->ports.at(ctx->id("COUT")));
|
||||
CellInfo *passout = make_carry_pass_out((*(curr_cell - 1))->ports.at(id_COUT));
|
||||
tile.pop_back();
|
||||
chains.back().cells.back() = passout;
|
||||
start_of_chain = true;
|
||||
} else {
|
||||
NetInfo *carry_net = cell->ports.at(ctx->id("COUT")).net;
|
||||
NetInfo *carry_net = cell->ports.at(id_COUT).net;
|
||||
bool at_end = (curr_cell == carryc.cells.end() - 1);
|
||||
if (carry_net != nullptr && (carry_net->users.size() > 1 || at_end)) {
|
||||
if (carry_net->users.size() > 2 ||
|
||||
(net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), false) !=
|
||||
net_only_drives(ctx, carry_net, is_lc, ctx->id("CIN"), false)) ||
|
||||
(at_end && !net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), true))) {
|
||||
(net_only_drives(ctx, carry_net, is_lc, id_I3, false) !=
|
||||
net_only_drives(ctx, carry_net, is_lc, id_CIN, false)) ||
|
||||
(at_end && !net_only_drives(ctx, carry_net, is_lc, id_I3, true))) {
|
||||
if (ctx->debug)
|
||||
log_info(" inserting feed-%s\n", at_end ? "out" : "out-in");
|
||||
CellInfo *passout;
|
||||
@ -89,10 +89,10 @@ class ChainConstrainer
|
||||
tile.pop_back();
|
||||
if (split_chain_next)
|
||||
start_of_chain = true;
|
||||
passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")),
|
||||
passout = make_carry_pass_out(cell->ports.at(id_COUT),
|
||||
split_chain_next ? nullptr : *(curr_cell + 1));
|
||||
} else {
|
||||
passout = make_carry_pass_out(cell->ports.at(ctx->id("COUT")), nullptr);
|
||||
passout = make_carry_pass_out(cell->ports.at(id_COUT), nullptr);
|
||||
}
|
||||
|
||||
chains.back().cells.push_back(passout);
|
||||
@ -110,9 +110,9 @@ class ChainConstrainer
|
||||
CellInfo *make_carry_pass_out(PortInfo &cout_port, CellInfo *cin_cell = nullptr)
|
||||
{
|
||||
NPNR_ASSERT(cout_port.net != nullptr);
|
||||
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
|
||||
lc->params[ctx->id("LUT_INIT")] = Property(65280, 16); // 0xff00: O = I3
|
||||
lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1;
|
||||
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, id_ICESTORM_LC);
|
||||
lc->params[id_LUT_INIT] = Property(65280, 16); // 0xff00: O = I3
|
||||
lc->params[id_CARRY_ENABLE] = Property::State::S1;
|
||||
lc->ports.at(id_O).net = cout_port.net;
|
||||
NetInfo *co_i3_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$I3"));
|
||||
co_i3_net->driver = cout_port.net->driver;
|
||||
@ -177,11 +177,11 @@ class ChainConstrainer
|
||||
CellInfo *make_carry_feed_in(CellInfo *cin_cell, PortInfo &cin_port)
|
||||
{
|
||||
NPNR_ASSERT(cin_port.net != nullptr);
|
||||
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, ctx->id("ICESTORM_LC"));
|
||||
lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1;
|
||||
lc->params[ctx->id("CIN_CONST")] = Property::State::S1;
|
||||
lc->params[ctx->id("CIN_SET")] = Property::State::S1;
|
||||
lc->ports.at(ctx->id("I1")).net = cin_port.net;
|
||||
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, id_ICESTORM_LC);
|
||||
lc->params[id_CARRY_ENABLE] = Property::State::S1;
|
||||
lc->params[id_CIN_CONST] = Property::State::S1;
|
||||
lc->params[id_CIN_SET] = Property::State::S1;
|
||||
lc->ports.at(id_I1).net = cin_port.net;
|
||||
cin_port.net->users.erase(std::remove_if(cin_port.net->users.begin(), cin_port.net->users.end(),
|
||||
[cin_cell, cin_port](const PortRef &usr) {
|
||||
return usr.cell == cin_cell && usr.port == cin_port.name;
|
||||
@ -189,16 +189,16 @@ class ChainConstrainer
|
||||
|
||||
PortRef i1_ref;
|
||||
i1_ref.cell = lc.get();
|
||||
i1_ref.port = ctx->id("I1");
|
||||
lc->ports.at(ctx->id("I1")).net->users.push_back(i1_ref);
|
||||
i1_ref.port = id_I1;
|
||||
lc->ports.at(id_I1).net->users.push_back(i1_ref);
|
||||
|
||||
NetInfo *out_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$O"));
|
||||
|
||||
PortRef drv_ref;
|
||||
drv_ref.port = ctx->id("COUT");
|
||||
drv_ref.port = id_COUT;
|
||||
drv_ref.cell = lc.get();
|
||||
out_net->driver = drv_ref;
|
||||
lc->ports.at(ctx->id("COUT")).net = out_net;
|
||||
lc->ports.at(id_COUT).net = out_net;
|
||||
|
||||
PortRef usr_ref;
|
||||
usr_ref.port = cin_port.name;
|
||||
@ -219,22 +219,19 @@ class ChainConstrainer
|
||||
[](const Context *ctx, const
|
||||
|
||||
CellInfo *cell) {
|
||||
CellInfo *carry_prev =
|
||||
net_driven_by(ctx, cell->ports.at(ctx->id("CIN")).net, is_lc, ctx->id("COUT"));
|
||||
CellInfo *carry_prev = net_driven_by(ctx, cell->ports.at(id_CIN).net, is_lc, id_COUT);
|
||||
if (carry_prev != nullptr)
|
||||
return carry_prev;
|
||||
CellInfo *i3_prev = net_driven_by(ctx, cell->ports.at(ctx->id("I3")).net, is_lc, ctx->id("COUT"));
|
||||
CellInfo *i3_prev = net_driven_by(ctx, cell->ports.at(id_I3).net, is_lc, id_COUT);
|
||||
if (i3_prev != nullptr)
|
||||
return i3_prev;
|
||||
return (CellInfo *)nullptr;
|
||||
},
|
||||
[](const Context *ctx, const CellInfo *cell) {
|
||||
CellInfo *carry_next =
|
||||
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("CIN"), false);
|
||||
CellInfo *carry_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_CIN, false);
|
||||
if (carry_next != nullptr)
|
||||
return carry_next;
|
||||
CellInfo *i3_next =
|
||||
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("I3"), false);
|
||||
CellInfo *i3_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_I3, false);
|
||||
if (i3_next != nullptr)
|
||||
return i3_next;
|
||||
return (CellInfo *)nullptr;
|
||||
@ -249,7 +246,7 @@ class ChainConstrainer
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) &&
|
||||
bool_or_default(ci->params, ctx->id("CARRY_ENABLE"))) {
|
||||
bool_or_default(ci->params, id_CARRY_ENABLE)) {
|
||||
CellChain sChain;
|
||||
sChain.cells.push_back(ci);
|
||||
chained.insert(cell.first);
|
||||
|
@ -449,3 +449,167 @@ X(DFF_ENABLE)
|
||||
X(CARRY_ENABLE)
|
||||
X(NEG_CLK)
|
||||
X(IO_STANDARD)
|
||||
X(A)
|
||||
X(ASYNC_SR)
|
||||
X(A_REG)
|
||||
X(A_SIGNED)
|
||||
X(BEL)
|
||||
X(BEL_PAD_INPUT)
|
||||
X(BOTADDSUB_CARRYSELECT)
|
||||
X(BOTADDSUB_LOWERINPUT)
|
||||
X(BOTADDSUB_UPPERINPUT)
|
||||
X(BOTOUTPUT_SELECT)
|
||||
X(BOT_8x8_MULT_REG)
|
||||
X(BUS_ADDR74)
|
||||
X(B_REG)
|
||||
X(B_SIGNED)
|
||||
X(C)
|
||||
X(CARRY_IN_MUX)
|
||||
X(CIN_CONST)
|
||||
X(CIN_SET)
|
||||
X(CLKHF_DIV)
|
||||
X(CURRENT_MODE)
|
||||
X(C_REG)
|
||||
X(D)
|
||||
X(DELAY_ADJMODE_FB)
|
||||
X(DELAY_ADJMODE_REL)
|
||||
X(DELAY_ADJUSTMENT_MODE_FEEDBACK)
|
||||
X(DELAY_ADJUSTMENT_MODE_RELATIVE)
|
||||
X(DIVF)
|
||||
X(DIVQ)
|
||||
X(DIVR)
|
||||
X(D_REG)
|
||||
X(E)
|
||||
X(FDA_FEEDBACK)
|
||||
X(FDA_RELATIVE)
|
||||
X(FEEDBACK_PATH)
|
||||
X(FILTER_RANGE)
|
||||
X(FOR_PAD_IN)
|
||||
X(GLB2LOCAL)
|
||||
X(GLB_NETWK)
|
||||
X(GLOBAL)
|
||||
X(GND)
|
||||
X(GRID_X)
|
||||
X(GRID_Y)
|
||||
X(GRID_Z)
|
||||
X(I)
|
||||
X(I2C_SLAVE_INIT_ADDR)
|
||||
X(INDEX)
|
||||
X(LEDDRST)
|
||||
X(LOCAL)
|
||||
X(LUTFF_COUT)
|
||||
X(LUTFF_GLOBAL)
|
||||
X(LUTFF_IN)
|
||||
X(LUTFF_IN_LUT)
|
||||
X(LUTFF_LOUT)
|
||||
X(LUTFF_OUT)
|
||||
X(LUT_INIT)
|
||||
X(MODE_8x8)
|
||||
X(NEG_CLK_R)
|
||||
X(NEG_CLK_W)
|
||||
X(NEG_TRIGGER)
|
||||
X(PACKAGEPIN)
|
||||
X(PIN_TYPE)
|
||||
X(PIPELINE_16x16_MULT_REG1)
|
||||
X(PIPELINE_16x16_MULT_REG2)
|
||||
X(PLLOUTCORE)
|
||||
X(PLLOUTCOREA)
|
||||
X(PLLOUTCOREB)
|
||||
X(PLLOUTGLOBAL)
|
||||
X(PLLOUTGLOBALA)
|
||||
X(PLLOUTGLOBALB)
|
||||
X(PLLOUT_SELECT)
|
||||
X(PLLOUT_SELECT_A)
|
||||
X(PLLOUT_SELECT_B)
|
||||
X(PLLOUT_SELECT_PORTA)
|
||||
X(PLLOUT_SELECT_PORTB)
|
||||
X(PLLTYPE)
|
||||
X(PULLUP)
|
||||
X(PULLUP_RESISTOR)
|
||||
X(Q)
|
||||
X(R)
|
||||
X(RCLKN)
|
||||
X(READ_MODE)
|
||||
X(RGB0_CURRENT)
|
||||
X(RGB1_CURRENT)
|
||||
X(RGB2_CURRENT)
|
||||
X(ROUTE_THROUGH_FABRIC)
|
||||
X(S)
|
||||
X(SB_CARRY)
|
||||
X(SB_DFF)
|
||||
X(SB_DFFE)
|
||||
X(SB_DFFER)
|
||||
X(SB_DFFES)
|
||||
X(SB_DFFESR)
|
||||
X(SB_DFFESS)
|
||||
X(SB_DFFN)
|
||||
X(SB_DFFNE)
|
||||
X(SB_DFFNER)
|
||||
X(SB_DFFNES)
|
||||
X(SB_DFFNESR)
|
||||
X(SB_DFFNESS)
|
||||
X(SB_DFFNR)
|
||||
X(SB_DFFNS)
|
||||
X(SB_DFFNSR)
|
||||
X(SB_DFFNSS)
|
||||
X(SB_DFFR)
|
||||
X(SB_DFFS)
|
||||
X(SB_DFFSR)
|
||||
X(SB_DFFSS)
|
||||
X(SB_GB_IO)
|
||||
X(SB_HFOSC)
|
||||
X(SB_LFOSC)
|
||||
X(SB_LUT4)
|
||||
X(SB_MAC16)
|
||||
X(SB_PLL40_2F_CORE)
|
||||
X(SB_PLL40_2F_PAD)
|
||||
X(SB_PLL40_2_PAD)
|
||||
X(SB_PLL40_CORE)
|
||||
X(SB_PLL40_PAD)
|
||||
X(SB_RAM40_4K)
|
||||
X(SB_RAM40_4KNR)
|
||||
X(SB_RAM40_4KNRNW)
|
||||
X(SB_RAM40_4KNW)
|
||||
X(SB_SPRAM256KA)
|
||||
X(SDA_INPUT_DELAYED)
|
||||
X(SDA_OUTPUT_DELAYED)
|
||||
X(SET_NORESET)
|
||||
X(SHIFTREG_DIVMODE)
|
||||
X(SHIFTREG_DIV_MODE)
|
||||
X(SP12_H)
|
||||
X(SP12_V)
|
||||
X(SP4_H)
|
||||
X(SP4_V)
|
||||
X(TEST_MODE)
|
||||
X(TOPADDSUB_CARRYSELECT)
|
||||
X(TOPADDSUB_LOWERINPUT)
|
||||
X(TOPADDSUB_UPPERINPUT)
|
||||
X(TOPOUTPUT_SELECT)
|
||||
X(TOP_8x8_MULT_REG)
|
||||
X(TRIM_EN)
|
||||
X(TYPE)
|
||||
X(VCC)
|
||||
X(WCLKN)
|
||||
X(WRITE_MODE)
|
||||
X(Y)
|
||||
X(hx1k)
|
||||
X(hx4k)
|
||||
X(hx8k)
|
||||
X(lp1k)
|
||||
X(lp384)
|
||||
X(lp4k)
|
||||
X(lp8k)
|
||||
X(no_promote_globals)
|
||||
X(opt_timing)
|
||||
X(pack)
|
||||
X(pcf_allow_unconstrained)
|
||||
X(place)
|
||||
X(placer)
|
||||
X(promote_logic)
|
||||
X(route)
|
||||
X(router)
|
||||
X(u1k)
|
||||
X(u2k)
|
||||
X(u4k)
|
||||
X(up3k)
|
||||
X(up5k)
|
||||
|
@ -265,13 +265,13 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext(dict<std::string, Pr
|
||||
|
||||
ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package;
|
||||
if (vm.count("promote-logic"))
|
||||
ctx->settings[ctx->id("promote_logic")] = Property::State::S1;
|
||||
ctx->settings[id_promote_logic] = Property::State::S1;
|
||||
if (vm.count("no-promote-globals"))
|
||||
ctx->settings[ctx->id("no_promote_globals")] = Property::State::S1;
|
||||
ctx->settings[id_no_promote_globals] = Property::State::S1;
|
||||
if (vm.count("opt-timing"))
|
||||
ctx->settings[ctx->id("opt_timing")] = Property::State::S1;
|
||||
ctx->settings[id_opt_timing] = Property::State::S1;
|
||||
if (vm.count("pcf-allow-unconstrained"))
|
||||
ctx->settings[ctx->id("pcf_allow_unconstrained")] = Property::State::S1;
|
||||
ctx->settings[id_pcf_allow_unconstrained] = Property::State::S1;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
363
ice40/pack.cc
363
ice40/pack.cc
@ -41,7 +41,7 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
if (ctx->verbose)
|
||||
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
|
||||
if (is_lut(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_LC");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LC, ci->name.str(ctx) + "_LC");
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
packed_cells.insert(ci->name);
|
||||
@ -49,14 +49,14 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
// See if we can pack into a DFF
|
||||
// TODO: LUT cascade
|
||||
NetInfo *o = ci->ports.at(ctx->id("O")).net;
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("D"), true);
|
||||
auto lut_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
NetInfo *o = ci->ports.at(id_O).net;
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_ff, id_D, true);
|
||||
auto lut_bel = ci->attrs.find(id_BEL);
|
||||
bool packed_dff = false;
|
||||
if (dff) {
|
||||
if (ctx->verbose)
|
||||
log_info("found attached dff %s\n", dff->name.c_str(ctx));
|
||||
auto dff_bel = dff->attrs.find(ctx->id("BEL"));
|
||||
auto dff_bel = dff->attrs.find(id_BEL);
|
||||
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
|
||||
// Locations don't match, can't pack
|
||||
} else {
|
||||
@ -65,10 +65,10 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
++lut_and_ff;
|
||||
ctx->nets.erase(o->name);
|
||||
if (dff_bel != dff->attrs.end())
|
||||
packed->attrs[ctx->id("BEL")] = dff_bel->second;
|
||||
packed->attrs[id_BEL] = dff_bel->second;
|
||||
for (const auto &attr : dff->attrs) {
|
||||
// BEL is dealt with specially
|
||||
if (attr.first != ctx->id("BEL"))
|
||||
if (attr.first != id_BEL)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
}
|
||||
packed_cells.insert(dff->name);
|
||||
@ -106,8 +106,7 @@ static void pack_nonlut_ffs(Context *ctx)
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ff(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LC, ci->name.str(ctx) + "_DFFLC");
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
if (ctx->verbose)
|
||||
@ -155,25 +154,25 @@ static void pack_carries(Context *ctx)
|
||||
|
||||
CellInfo *carry_ci_lc;
|
||||
bool ci_value;
|
||||
bool ci_const = net_is_constant(ctx, ci->ports.at(ctx->id("CI")).net, ci_value);
|
||||
bool ci_const = net_is_constant(ctx, ci->ports.at(id_CI).net, ci_value);
|
||||
if (ci_const) {
|
||||
carry_ci_lc = nullptr;
|
||||
} else {
|
||||
carry_ci_lc = net_only_drives(ctx, ci->ports.at(ctx->id("CI")).net, is_lc, ctx->id("I3"), false);
|
||||
carry_ci_lc = net_only_drives(ctx, ci->ports.at(id_CI).net, is_lc, id_I3, false);
|
||||
}
|
||||
|
||||
std::set<IdString> i0_matches, i1_matches;
|
||||
NetInfo *i0_net = ci->ports.at(ctx->id("I0")).net;
|
||||
NetInfo *i1_net = ci->ports.at(ctx->id("I1")).net;
|
||||
NetInfo *i0_net = ci->ports.at(id_I0).net;
|
||||
NetInfo *i1_net = ci->ports.at(id_I1).net;
|
||||
// Find logic cells connected to both I0 and I1
|
||||
if (i0_net) {
|
||||
for (auto usr : i0_net->users) {
|
||||
if (is_lc(ctx, usr.cell) && usr.port == ctx->id("I1")) {
|
||||
if (is_lc(ctx, usr.cell) && usr.port == id_I1) {
|
||||
if (ctx->cells.find(usr.cell->name) != ctx->cells.end() &&
|
||||
exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) {
|
||||
// This clause stops us double-packing cells
|
||||
i0_matches.insert(usr.cell->name);
|
||||
if (!i1_net && !usr.cell->ports.at(ctx->id("I2")).net) {
|
||||
if (!i1_net && !usr.cell->ports.at(id_I2).net) {
|
||||
// I1 is don't care when disconnected, duplicate I0
|
||||
i1_matches.insert(usr.cell->name);
|
||||
}
|
||||
@ -183,12 +182,12 @@ static void pack_carries(Context *ctx)
|
||||
}
|
||||
if (i1_net) {
|
||||
for (auto usr : i1_net->users) {
|
||||
if (is_lc(ctx, usr.cell) && usr.port == ctx->id("I2")) {
|
||||
if (is_lc(ctx, usr.cell) && usr.port == id_I2) {
|
||||
if (ctx->cells.find(usr.cell->name) != ctx->cells.end() &&
|
||||
exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) {
|
||||
// This clause stops us double-packing cells
|
||||
i1_matches.insert(usr.cell->name);
|
||||
if (!i0_net && !usr.cell->ports.at(ctx->id("I1")).net) {
|
||||
if (!i0_net && !usr.cell->ports.at(id_I1).net) {
|
||||
// I0 is don't care when disconnected, duplicate I1
|
||||
i0_matches.insert(usr.cell->name);
|
||||
}
|
||||
@ -208,53 +207,53 @@ static void pack_carries(Context *ctx)
|
||||
} else {
|
||||
// No LC to pack into matching I0/I1, insert a new one
|
||||
std::unique_ptr<CellInfo> created_lc =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), cell.first.str(ctx) + "$CARRY");
|
||||
create_ice_cell(ctx, id_ICESTORM_LC, cell.first.str(ctx) + "$CARRY");
|
||||
carry_lc = created_lc.get();
|
||||
created_lc->ports.at(ctx->id("I1")).net = i0_net;
|
||||
created_lc->ports.at(id_I1).net = i0_net;
|
||||
if (i0_net) {
|
||||
PortRef pr;
|
||||
pr.cell = created_lc.get();
|
||||
pr.port = ctx->id("I1");
|
||||
pr.port = id_I1;
|
||||
i0_net->users.push_back(pr);
|
||||
}
|
||||
created_lc->ports.at(ctx->id("I2")).net = i1_net;
|
||||
created_lc->ports.at(id_I2).net = i1_net;
|
||||
if (i1_net) {
|
||||
PortRef pr;
|
||||
pr.cell = created_lc.get();
|
||||
pr.port = ctx->id("I2");
|
||||
pr.port = id_I2;
|
||||
i1_net->users.push_back(pr);
|
||||
}
|
||||
new_cells.push_back(std::move(created_lc));
|
||||
++carry_only;
|
||||
}
|
||||
carry_lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1;
|
||||
replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN"));
|
||||
replace_port(ci, ctx->id("CO"), carry_lc, ctx->id("COUT"));
|
||||
carry_lc->params[id_CARRY_ENABLE] = Property::State::S1;
|
||||
replace_port(ci, id_CI, carry_lc, id_CIN);
|
||||
replace_port(ci, id_CO, carry_lc, id_COUT);
|
||||
if (i0_net) {
|
||||
auto &i0_usrs = i0_net->users;
|
||||
i0_usrs.erase(std::remove_if(i0_usrs.begin(), i0_usrs.end(), [ci, ctx](const PortRef &pr) {
|
||||
return pr.cell == ci && pr.port == ctx->id("I0");
|
||||
return pr.cell == ci && pr.port == id_I0;
|
||||
}));
|
||||
}
|
||||
if (i1_net) {
|
||||
auto &i1_usrs = i1_net->users;
|
||||
i1_usrs.erase(std::remove_if(i1_usrs.begin(), i1_usrs.end(), [ci, ctx](const PortRef &pr) {
|
||||
return pr.cell == ci && pr.port == ctx->id("I1");
|
||||
return pr.cell == ci && pr.port == id_I1;
|
||||
}));
|
||||
}
|
||||
|
||||
// Check for constant driver on CIN
|
||||
if (carry_lc->ports.at(ctx->id("CIN")).net != nullptr) {
|
||||
IdString cin_net = carry_lc->ports.at(ctx->id("CIN")).net->name;
|
||||
if (carry_lc->ports.at(id_CIN).net != nullptr) {
|
||||
IdString cin_net = carry_lc->ports.at(id_CIN).net->name;
|
||||
if (cin_net == ctx->id("$PACKER_GND_NET") || cin_net == ctx->id("$PACKER_VCC_NET")) {
|
||||
carry_lc->params[ctx->id("CIN_CONST")] = Property::State::S1;
|
||||
carry_lc->params[ctx->id("CIN_SET")] =
|
||||
carry_lc->params[id_CIN_CONST] = Property::State::S1;
|
||||
carry_lc->params[id_CIN_SET] =
|
||||
cin_net == ctx->id("$PACKER_VCC_NET") ? Property::State::S1 : Property::State::S0;
|
||||
carry_lc->ports.at(ctx->id("CIN")).net = nullptr;
|
||||
carry_lc->ports.at(id_CIN).net = nullptr;
|
||||
auto &cin_users = ctx->nets.at(cin_net)->users;
|
||||
cin_users.erase(
|
||||
std::remove_if(cin_users.begin(), cin_users.end(), [carry_lc, ctx](const PortRef &pr) {
|
||||
return pr.cell == carry_lc && pr.port == ctx->id("CIN");
|
||||
return pr.cell == carry_lc && pr.port == id_CIN;
|
||||
}));
|
||||
}
|
||||
}
|
||||
@ -281,18 +280,15 @@ static void pack_ram(Context *ctx)
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_ram(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_RAM, ci->name.str(ctx) + "_RAM");
|
||||
packed_cells.insert(ci->name);
|
||||
for (auto attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
for (auto param : ci->params)
|
||||
packed->params[param.first] = param.second;
|
||||
packed->params[ctx->id("NEG_CLK_W")] =
|
||||
Property(ci->type == ctx->id("SB_RAM40_4KNW") || ci->type == ctx->id("SB_RAM40_4KNRNW"), 1);
|
||||
packed->params[ctx->id("NEG_CLK_R")] =
|
||||
Property(ci->type == ctx->id("SB_RAM40_4KNR") || ci->type == ctx->id("SB_RAM40_4KNRNW"), 1);
|
||||
packed->type = ctx->id("ICESTORM_RAM");
|
||||
packed->params[id_NEG_CLK_W] = Property(ci->type == id_SB_RAM40_4KNW || ci->type == id_SB_RAM40_4KNRNW, 1);
|
||||
packed->params[id_NEG_CLK_R] = Property(ci->type == id_SB_RAM40_4KNR || ci->type == id_SB_RAM40_4KNRNW, 1);
|
||||
packed->type = id_ICESTORM_RAM;
|
||||
for (auto port : ci->ports) {
|
||||
PortInfo &pi = port.second;
|
||||
std::string newname = pi.name.str(ctx);
|
||||
@ -300,9 +296,9 @@ static void pack_ram(Context *ctx)
|
||||
if (bpos != std::string::npos) {
|
||||
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
|
||||
}
|
||||
if (pi.name == ctx->id("RCLKN"))
|
||||
if (pi.name == id_RCLKN)
|
||||
newname = "RCLK";
|
||||
else if (pi.name == ctx->id("WCLKN"))
|
||||
else if (pi.name == id_WCLKN)
|
||||
newname = "WCLK";
|
||||
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname));
|
||||
}
|
||||
@ -330,13 +326,13 @@ static void set_net_constant(const Context *ctx, NetInfo *orig, NetInfo *constne
|
||||
if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') &&
|
||||
!constval) {
|
||||
uc->ports[user.port].net = nullptr;
|
||||
} else if ((is_sb_mac16(ctx, uc) || uc->type == ctx->id("ICESTORM_DSP")) &&
|
||||
(user.port != ctx->id("CLK") &&
|
||||
((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) {
|
||||
} else if ((is_sb_mac16(ctx, uc) || uc->type == id_ICESTORM_DSP) &&
|
||||
(user.port != id_CLK &&
|
||||
((constval && user.port == id_CE) || (!constval && user.port != id_CE)))) {
|
||||
uc->ports[user.port].net = nullptr;
|
||||
} else if (is_ram(ctx, uc) && !constval && user.port != ctx->id("RCLK") && user.port != ctx->id("RCLKN") &&
|
||||
user.port != ctx->id("WCLK") && user.port != ctx->id("WCLKN") && user.port != ctx->id("RCLKE") &&
|
||||
user.port != ctx->id("WCLKE")) {
|
||||
} else if (is_ram(ctx, uc) && !constval && user.port != id_RCLK && user.port != id_RCLKN &&
|
||||
user.port != id_WCLK && user.port != id_WCLKN && user.port != id_RCLKE &&
|
||||
user.port != id_WCLKE) {
|
||||
uc->ports[user.port].net = nullptr;
|
||||
} else {
|
||||
uc->ports[user.port].net = constnet;
|
||||
@ -352,24 +348,24 @@ static void pack_constants(Context *ctx)
|
||||
{
|
||||
log_info("Packing constants..\n");
|
||||
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND");
|
||||
gnd_cell->params[ctx->id("LUT_INIT")] = Property(0, 16);
|
||||
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, id_ICESTORM_LC, "$PACKER_GND");
|
||||
gnd_cell->params[id_LUT_INIT] = Property(0, 16);
|
||||
auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET"));
|
||||
gnd_net->driver.cell = gnd_cell.get();
|
||||
gnd_net->driver.port = ctx->id("O");
|
||||
gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get();
|
||||
gnd_net->driver.port = id_O;
|
||||
gnd_cell->ports.at(id_O).net = gnd_net.get();
|
||||
|
||||
NetInfo *gnd_net_info = gnd_net.get();
|
||||
if (ctx->nets.find(ctx->id("$PACKER_GND_NET")) != ctx->nets.end()) {
|
||||
gnd_net_info = ctx->nets.find(ctx->id("$PACKER_GND_NET"))->second.get();
|
||||
}
|
||||
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_VCC");
|
||||
vcc_cell->params[ctx->id("LUT_INIT")] = Property(1, 16);
|
||||
std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, id_ICESTORM_LC, "$PACKER_VCC");
|
||||
vcc_cell->params[id_LUT_INIT] = Property(1, 16);
|
||||
auto vcc_net = std::make_unique<NetInfo>(ctx->id("$PACKER_VCC_NET"));
|
||||
vcc_net->driver.cell = vcc_cell.get();
|
||||
vcc_net->driver.port = ctx->id("O");
|
||||
vcc_cell->ports.at(ctx->id("O")).net = vcc_net.get();
|
||||
vcc_net->driver.port = id_O;
|
||||
vcc_cell->ports.at(id_O).net = vcc_net.get();
|
||||
|
||||
NetInfo *vcc_net_info = vcc_net.get();
|
||||
if (ctx->nets.find(ctx->id("$PACKER_VCC_NET")) != ctx->nets.end()) {
|
||||
@ -382,13 +378,13 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == id_GND) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net_info, false);
|
||||
gnd_used = true;
|
||||
dead_nets.push_back(net.first);
|
||||
ctx->cells.erase(drv_cell);
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) {
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == id_VCC) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, vcc_net_info, true);
|
||||
dead_nets.push_back(net.first);
|
||||
@ -434,16 +430,16 @@ static std::unique_ptr<CellInfo> create_padin_gbuf(Context *ctx, CellInfo *cell,
|
||||
std::string gbuf_name)
|
||||
{
|
||||
// Find the matching SB_GB BEL connected to the same global network
|
||||
if (!cell->attrs.count(ctx->id("BEL")))
|
||||
if (!cell->attrs.count(id_BEL))
|
||||
log_error("Unconstrained SB_GB_IO %s is not supported.\n", ctx->nameOf(cell));
|
||||
BelId bel = ctx->getBelByNameStr(cell->attrs[ctx->id("BEL")].as_string());
|
||||
BelId bel = ctx->getBelByNameStr(cell->attrs[id_BEL].as_string());
|
||||
BelId gb_bel = find_padin_gbuf(ctx, bel, port_name);
|
||||
NPNR_ASSERT(gb_bel != BelId());
|
||||
|
||||
// Create a SB_GB Cell and lock it there
|
||||
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, ctx->id("SB_GB"), gbuf_name);
|
||||
gb->attrs[ctx->id("FOR_PAD_IN")] = Property::State::S1;
|
||||
gb->attrs[ctx->id("BEL")] = ctx->getBelName(gb_bel).str(ctx);
|
||||
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, id_SB_GB, gbuf_name);
|
||||
gb->attrs[id_FOR_PAD_IN] = Property::State::S1;
|
||||
gb->attrs[id_BEL] = ctx->getBelName(gb_bel).str(ctx);
|
||||
|
||||
// Reconnect the net to that port for easier identification it's a global net
|
||||
replace_port(cell, port_name, gb.get(), id_GLOBAL_BUFFER_OUTPUT);
|
||||
@ -475,11 +471,11 @@ static void pack_io(Context *ctx)
|
||||
if (is_nextpnr_iob(ctx, ci)) {
|
||||
CellInfo *sb = nullptr, *rgb = nullptr;
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
sb = net_only_drives(ctx, ci->ports.at(ctx->id("O")).net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci);
|
||||
sb = net_only_drives(ctx, ci->ports.at(id_O).net, is_ice_iob, id_PACKAGE_PIN, true, ci);
|
||||
|
||||
} else if (ci->type == ctx->id("$nextpnr_obuf")) {
|
||||
NetInfo *net = ci->ports.at(ctx->id("I")).net;
|
||||
sb = net_only_drives(ctx, net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci);
|
||||
NetInfo *net = ci->ports.at(id_I).net;
|
||||
sb = net_only_drives(ctx, net, is_ice_iob, id_PACKAGE_PIN, true, ci);
|
||||
if (net && net->driver.cell &&
|
||||
(is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell)))
|
||||
rgb = net->driver.cell;
|
||||
@ -488,7 +484,7 @@ static void pack_io(Context *ctx)
|
||||
// Trivial case, SB_IO used. Just destroy the iobuf
|
||||
log_info("%s feeds SB_IO %s, removing %s %s.\n", ci->name.c_str(ctx), sb->name.c_str(ctx),
|
||||
ci->type.c_str(ctx), ci->name.c_str(ctx));
|
||||
NetInfo *net = sb->ports.at(ctx->id("PACKAGE_PIN")).net;
|
||||
NetInfo *net = sb->ports.at(id_PACKAGE_PIN).net;
|
||||
if (((ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) &&
|
||||
net->users.size() > 1) ||
|
||||
(ci->type == ctx->id("$nextpnr_obuf") && (net->users.size() > 2 || net->driver.cell != nullptr)))
|
||||
@ -518,13 +514,12 @@ static void pack_io(Context *ctx)
|
||||
} else if (rgb != nullptr) {
|
||||
log_info("%s use by SB_RGBA_DRV/SB_RGB_DRV %s, not creating SB_IO\n", ci->name.c_str(ctx),
|
||||
rgb->name.c_str(ctx));
|
||||
disconnect_port(ctx, ci, ctx->id("I"));
|
||||
disconnect_port(ctx, ci, id_I);
|
||||
packed_cells.insert(ci->name);
|
||||
continue;
|
||||
} else {
|
||||
// Create a SB_IO buffer
|
||||
std::unique_ptr<CellInfo> ice_cell =
|
||||
create_ice_cell(ctx, ctx->id("SB_IO"), ci->name.str(ctx) + "$sb_io");
|
||||
std::unique_ptr<CellInfo> ice_cell = create_ice_cell(ctx, id_SB_IO, ci->name.str(ctx) + "$sb_io");
|
||||
nxio_to_sb(ctx, ci, ice_cell.get(), packed_cells);
|
||||
new_cells.push_back(std::move(ice_cell));
|
||||
sb = new_cells.back().get();
|
||||
@ -535,7 +530,7 @@ static void pack_io(Context *ctx)
|
||||
for (auto &attr : ci->attrs)
|
||||
sb->attrs[attr.first] = attr.second;
|
||||
} else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) {
|
||||
NetInfo *net = ci->ports.at(ctx->id("PACKAGE_PIN")).net;
|
||||
NetInfo *net = ci->ports.at(id_PACKAGE_PIN).net;
|
||||
if ((net != nullptr) && ((net->users.size() > 2) ||
|
||||
(net->driver.cell != nullptr &&
|
||||
net->driver.cell->type == ctx->id("$nextpnr_obuf") && net->users.size() > 1)))
|
||||
@ -552,8 +547,8 @@ static void pack_io(Context *ctx)
|
||||
new_cells.push_back(std::move(gb));
|
||||
|
||||
// Make it a normal SB_IO with global marker
|
||||
ci->type = ctx->id("SB_IO");
|
||||
ci->attrs[ctx->id("GLOBAL")] = Property::State::S1;
|
||||
ci->type = id_SB_IO;
|
||||
ci->attrs[id_GLOBAL] = Property::State::S1;
|
||||
} else if (is_sb_io(ctx, ci)) {
|
||||
// Disconnect unused inputs
|
||||
NetInfo *net_in0 = ci->ports.count(id_D_IN_0) ? ci->ports[id_D_IN_0].net : nullptr;
|
||||
@ -595,18 +590,18 @@ static void insert_global(Context *ctx, NetInfo *net, bool is_reset, bool is_cen
|
||||
is_cen ? " [cen]" : "", is_logic ? " [logic]" : "", fanout);
|
||||
|
||||
std::string glb_name = net->name.str(ctx) + std::string("_$glb_") + (is_reset ? "sr" : (is_cen ? "ce" : "clk"));
|
||||
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, ctx->id("SB_GB"), "$gbuf_" + glb_name);
|
||||
gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net;
|
||||
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, id_SB_GB, "$gbuf_" + glb_name);
|
||||
gb->ports[id_USER_SIGNAL_TO_GLOBAL_BUFFER].net = net;
|
||||
PortRef pr;
|
||||
pr.cell = gb.get();
|
||||
pr.port = ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER");
|
||||
pr.port = id_USER_SIGNAL_TO_GLOBAL_BUFFER;
|
||||
net->users.push_back(pr);
|
||||
|
||||
pr.cell = gb.get();
|
||||
pr.port = ctx->id("GLOBAL_BUFFER_OUTPUT");
|
||||
pr.port = id_GLOBAL_BUFFER_OUTPUT;
|
||||
NetInfo *glbnet = ctx->createNet(ctx->id(glb_name));
|
||||
glbnet->driver = pr;
|
||||
gb->ports[ctx->id("GLOBAL_BUFFER_OUTPUT")].net = glbnet;
|
||||
gb->ports[id_GLOBAL_BUFFER_OUTPUT].net = glbnet;
|
||||
std::vector<PortRef> keep_users;
|
||||
for (auto user : net->users) {
|
||||
if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) ||
|
||||
@ -664,9 +659,9 @@ static void promote_globals(Context *ctx)
|
||||
--gbs_available;
|
||||
|
||||
/* And possibly limits what we can promote */
|
||||
if (cell.second->attrs.find(ctx->id("BEL")) != cell.second->attrs.end()) {
|
||||
if (cell.second->attrs.find(id_BEL) != cell.second->attrs.end()) {
|
||||
/* If the SB_GB is locked, doesn't matter what it drives */
|
||||
BelId bel = ctx->getBelByNameStr(cell.second->attrs[ctx->id("BEL")].as_string());
|
||||
BelId bel = ctx->getBelByNameStr(cell.second->attrs[id_BEL].as_string());
|
||||
int glb_id = ctx->get_driven_glb_netwk(bel);
|
||||
if ((glb_id % 2) == 0)
|
||||
resets_available--;
|
||||
@ -708,7 +703,7 @@ static void promote_globals(Context *ctx)
|
||||
if (global_clock->second == 0 && prom_logics < 4 && global_logic->second > logic_fanout_thresh &&
|
||||
(global_logic->second > global_cen->second || prom_cens >= cens_available) &&
|
||||
(global_logic->second > global_reset->second || prom_resets >= resets_available) &&
|
||||
bool_or_default(ctx->settings, ctx->id("promote_logic"), false)) {
|
||||
bool_or_default(ctx->settings, id_promote_logic, false)) {
|
||||
NetInfo *logicnet = ctx->nets[global_logic->first].get();
|
||||
insert_global(ctx, logicnet, false, false, true, global_logic->second);
|
||||
++prom_globals;
|
||||
@ -784,11 +779,11 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// If it's constrained already, add to already used list
|
||||
if (ci->attrs.count(ctx->id("BEL"))) {
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string());
|
||||
if (ci->attrs.count(id_BEL)) {
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[id_BEL].as_string());
|
||||
if (pll_all_bels.count(bel_constrain) == 0)
|
||||
log_error("PLL '%s' is constrained to invalid BEL '%s'\n", ci->name.c_str(ctx),
|
||||
ci->attrs[ctx->id("BEL")].as_string().c_str());
|
||||
ci->attrs[id_BEL].as_string().c_str());
|
||||
pll_used_bels[bel_constrain] = ci;
|
||||
}
|
||||
|
||||
@ -802,10 +797,10 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// Check PACKAGEPIN connection
|
||||
if (!ci->ports.count(ctx->id("PACKAGEPIN")))
|
||||
if (!ci->ports.count(id_PACKAGEPIN))
|
||||
log_error("PLL '%s' is of PAD type but doesn't have a PACKAGEPIN port\n", ci->name.c_str(ctx));
|
||||
|
||||
NetInfo *ni = ci->ports.at(ctx->id("PACKAGEPIN")).net;
|
||||
NetInfo *ni = ci->ports.at(id_PACKAGEPIN).net;
|
||||
if (ni == nullptr || ni->driver.cell == nullptr)
|
||||
log_error("PLL '%s' is of PAD type but doesn't have a valid PACKAGEPIN connection\n", ci->name.c_str(ctx));
|
||||
|
||||
@ -816,11 +811,11 @@ static void place_plls(Context *ctx)
|
||||
ci->name.c_str(ctx), io_cell->type.c_str(ctx));
|
||||
if (ni->users.size() != 1)
|
||||
log_error("PLL '%s' clock input '%s' can only drive PLL\n", ci->name.c_str(ctx), ni->name.c_str(ctx));
|
||||
if (!io_cell->attrs.count(ctx->id("BEL")))
|
||||
if (!io_cell->attrs.count(id_BEL))
|
||||
log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx),
|
||||
io_cell->name.c_str(ctx));
|
||||
|
||||
BelId io_bel = ctx->getBelByNameStr(io_cell->attrs.at(ctx->id("BEL")).as_string());
|
||||
BelId io_bel = ctx->getBelByNameStr(io_cell->attrs.at(id_BEL).as_string());
|
||||
BelId found_bel;
|
||||
|
||||
// Find the PLL BEL that would suit that connection
|
||||
@ -843,16 +838,16 @@ static void place_plls(Context *ctx)
|
||||
}
|
||||
|
||||
// Is it user constrained ?
|
||||
if (ci->attrs.count(ctx->id("BEL"))) {
|
||||
if (ci->attrs.count(id_BEL)) {
|
||||
// Yes. Check it actually matches !
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string());
|
||||
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[id_BEL].as_string());
|
||||
if (bel_constrain != found_bel)
|
||||
log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN "
|
||||
"connection\n",
|
||||
ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel));
|
||||
} else {
|
||||
// No, we can constrain it ourselves
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx);
|
||||
ci->attrs[id_BEL] = ctx->getBelName(found_bel).str(ctx);
|
||||
pll_used_bels[found_bel] = ci;
|
||||
}
|
||||
|
||||
@ -867,15 +862,15 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// Only consider bound IO that are used as inputs
|
||||
if (!io_ci->attrs.count(ctx->id("BEL")))
|
||||
if (!io_ci->attrs.count(id_BEL))
|
||||
continue;
|
||||
if ((!io_ci->ports.count(id_D_IN_0) || (io_ci->ports[id_D_IN_0].net == nullptr)) &&
|
||||
(!io_ci->ports.count(id_D_IN_1) || (io_ci->ports[id_D_IN_1].net == nullptr)) &&
|
||||
!bool_or_default(io_ci->attrs, ctx->id("GLOBAL")))
|
||||
!bool_or_default(io_ci->attrs, id_GLOBAL))
|
||||
continue;
|
||||
|
||||
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN)
|
||||
BelId io_bel = ctx->getBelByNameStr(io_ci->attrs[ctx->id("BEL")].as_string());
|
||||
BelId io_bel = ctx->getBelByNameStr(io_ci->attrs[id_BEL].as_string());
|
||||
|
||||
for (auto placed_pll : pll_used_bels) {
|
||||
BelPin pll_io_a, pll_io_b;
|
||||
@ -905,11 +900,11 @@ static void place_plls(Context *ctx)
|
||||
continue;
|
||||
|
||||
// Only consider the bound ones
|
||||
if (!gb_ci->attrs.count(ctx->id("BEL")))
|
||||
if (!gb_ci->attrs.count(id_BEL))
|
||||
continue;
|
||||
|
||||
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN)
|
||||
BelId gb_bel = ctx->getBelByNameStr(gb_ci->attrs[ctx->id("BEL")].as_string());
|
||||
BelId gb_bel = ctx->getBelByNameStr(gb_ci->attrs[id_BEL].as_string());
|
||||
|
||||
for (auto placed_pll : pll_used_bels) {
|
||||
CellInfo *ci = placed_pll.second;
|
||||
@ -967,8 +962,8 @@ static void place_plls(Context *ctx)
|
||||
// Could this be a PAD PLL ?
|
||||
bool could_be_pad = false;
|
||||
BelId pad_bel;
|
||||
if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(ctx->id("BEL")))
|
||||
pad_bel = ctx->getBelByNameStr(ni->driver.cell->attrs[ctx->id("BEL")].as_string());
|
||||
if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(id_BEL))
|
||||
pad_bel = ctx->getBelByNameStr(ni->driver.cell->attrs[id_BEL].as_string());
|
||||
|
||||
// Find a BEL for it
|
||||
BelId found_bel;
|
||||
@ -1002,7 +997,7 @@ static void place_plls(Context *ctx)
|
||||
if (could_be_pad)
|
||||
log_info(" (given its connections, this PLL could have been a PAD PLL)\n");
|
||||
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(found_bel).str(ctx);
|
||||
ci->attrs[id_BEL] = ctx->getBelName(found_bel).str(ctx);
|
||||
pll_used_bels[found_bel] = ci;
|
||||
}
|
||||
}
|
||||
@ -1017,20 +1012,20 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
|
||||
NPNR_ASSERT(port.net != nullptr);
|
||||
|
||||
// Create pass-through LUT.
|
||||
std::unique_ptr<CellInfo> pt = create_ice_cell(ctx, ctx->id("ICESTORM_LC"),
|
||||
ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through");
|
||||
pt->params[ctx->id("LUT_INIT")] = Property(65280, 16); // output is always I3
|
||||
std::unique_ptr<CellInfo> pt =
|
||||
create_ice_cell(ctx, id_ICESTORM_LC, ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through");
|
||||
pt->params[id_LUT_INIT] = Property(65280, 16); // output is always I3
|
||||
|
||||
// Create LUT output net.
|
||||
NetInfo *out_net = ctx->createNet(ctx->id(ci->name.str(ctx) + "$nextnr_" + portId.str(ctx) + "_lut_through_net"));
|
||||
out_net->driver.cell = pt.get();
|
||||
out_net->driver.port = ctx->id("O");
|
||||
pt->ports.at(ctx->id("O")).net = out_net;
|
||||
out_net->driver.port = id_O;
|
||||
pt->ports.at(id_O).net = out_net;
|
||||
|
||||
// New users of the original cell's port
|
||||
std::vector<PortRef> new_users;
|
||||
for (const auto &user : port.net->users) {
|
||||
if (onlyNonLUTs && user.cell->type == ctx->id("ICESTORM_LC")) {
|
||||
if (onlyNonLUTs && user.cell->type == id_ICESTORM_LC) {
|
||||
new_users.push_back(user);
|
||||
continue;
|
||||
}
|
||||
@ -1046,9 +1041,9 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
|
||||
// Add LUT to new users.
|
||||
PortRef pr;
|
||||
pr.cell = pt.get();
|
||||
pr.port = ctx->id("I3");
|
||||
pr.port = id_I3;
|
||||
new_users.push_back(pr);
|
||||
pt->ports.at(ctx->id("I3")).net = port.net;
|
||||
pt->ports.at(id_I3).net = port.net;
|
||||
|
||||
// Replace users of the original net.
|
||||
port.net->users = new_users;
|
||||
@ -1065,7 +1060,7 @@ static BelId cell_place_unique(Context *ctx, CellInfo *ci)
|
||||
if (ctx->is_bel_locked(bel))
|
||||
continue;
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
ci->attrs[ctx->id("BEL")] = bel_name.str(ctx);
|
||||
ci->attrs[id_BEL] = bel_name.str(ctx);
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||
return bel;
|
||||
}
|
||||
@ -1124,7 +1119,7 @@ static void pack_special(Context *ctx)
|
||||
/* Force placement (no choices anyway) */
|
||||
cell_place_unique(ctx, ci);
|
||||
|
||||
NetInfo *ledpu_net = ci->ports.at(ctx->id("LEDPU")).net;
|
||||
NetInfo *ledpu_net = ci->ports.at(id_LEDPU).net;
|
||||
for (auto &user : ledpu_net->users) {
|
||||
if (!is_sb_rgb_drv(ctx, user.cell)) {
|
||||
log_error("SB_LED_DRV_CUR LEDPU port can only be connected to SB_RGB_DRV!\n");
|
||||
@ -1133,44 +1128,42 @@ static void pack_special(Context *ctx)
|
||||
user.cell->ports.at(user.port).net = nullptr;
|
||||
}
|
||||
}
|
||||
ci->ports.erase(ctx->id("LEDPU"));
|
||||
ci->ports.erase(id_LEDPU);
|
||||
ctx->nets.erase(ledpu_net->name);
|
||||
}
|
||||
}
|
||||
for (auto &cell : ctx->cells) {
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (is_sb_lfosc(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LFOSC, ci->name.str(ctx) + "_OSC");
|
||||
packed_cells.insert(ci->name);
|
||||
cell_place_unique(ctx, packed.get());
|
||||
replace_port(ci, ctx->id("CLKLFEN"), packed.get(), ctx->id("CLKLFEN"));
|
||||
replace_port(ci, ctx->id("CLKLFPU"), packed.get(), ctx->id("CLKLFPU"));
|
||||
if (bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))) {
|
||||
replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF_FABRIC"));
|
||||
set_period(ctx, packed.get(), ctx->id("CLKLF_FABRIC"), 100000000); // 10kHz
|
||||
replace_port(ci, id_CLKLFEN, packed.get(), id_CLKLFEN);
|
||||
replace_port(ci, id_CLKLFPU, packed.get(), id_CLKLFPU);
|
||||
if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
|
||||
replace_port(ci, id_CLKLF, packed.get(), id_CLKLF_FABRIC);
|
||||
set_period(ctx, packed.get(), id_CLKLF_FABRIC, 100000000); // 10kHz
|
||||
} else {
|
||||
replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF"));
|
||||
replace_port(ci, id_CLKLF, packed.get(), id_CLKLF);
|
||||
std::unique_ptr<CellInfo> gb =
|
||||
create_padin_gbuf(ctx, packed.get(), ctx->id("CLKLF"), "$gbuf_" + ci->name.str(ctx) + "_lfosc");
|
||||
create_padin_gbuf(ctx, packed.get(), id_CLKLF, "$gbuf_" + ci->name.str(ctx) + "_lfosc");
|
||||
set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 100000000); // 10kHz
|
||||
new_cells.push_back(std::move(gb));
|
||||
}
|
||||
new_cells.push_back(std::move(packed));
|
||||
} else if (is_sb_hfosc(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_HFOSC"), ci->name.str(ctx) + "_OSC");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_HFOSC, ci->name.str(ctx) + "_OSC");
|
||||
packed_cells.insert(ci->name);
|
||||
cell_place_unique(ctx, packed.get());
|
||||
packed->params[ctx->id("TRIM_EN")] = str_or_default(ci->params, ctx->id("TRIM_EN"), "0b0");
|
||||
packed->params[ctx->id("CLKHF_DIV")] = str_or_default(ci->params, ctx->id("CLKHF_DIV"), "0b00");
|
||||
replace_port(ci, ctx->id("CLKHFEN"), packed.get(), ctx->id("CLKHFEN"));
|
||||
replace_port(ci, ctx->id("CLKHFPU"), packed.get(), ctx->id("CLKHFPU"));
|
||||
packed->params[id_TRIM_EN] = str_or_default(ci->params, id_TRIM_EN, "0b0");
|
||||
packed->params[id_CLKHF_DIV] = str_or_default(ci->params, id_CLKHF_DIV, "0b00");
|
||||
replace_port(ci, id_CLKHFEN, packed.get(), id_CLKHFEN);
|
||||
replace_port(ci, id_CLKHFPU, packed.get(), id_CLKHFPU);
|
||||
for (int i = 0; i < 10; i++) {
|
||||
auto port = ctx->id("TRIM" + std::to_string(i));
|
||||
replace_port(ci, port, packed.get(), port);
|
||||
}
|
||||
std::string div = packed->params[ctx->id("CLKHF_DIV")].as_string();
|
||||
std::string div = packed->params[id_CLKHF_DIV].as_string();
|
||||
int frequency;
|
||||
if (div == "0b00")
|
||||
frequency = 48;
|
||||
@ -1182,20 +1175,19 @@ static void pack_special(Context *ctx)
|
||||
frequency = 6;
|
||||
else
|
||||
log_error("Invalid HFOSC divider value '%s' - expecting 0b00, 0b01, 0b10 or 0b11\n", div.c_str());
|
||||
if (bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))) {
|
||||
replace_port(ci, ctx->id("CLKHF"), packed.get(), ctx->id("CLKHF_FABRIC"));
|
||||
set_period(ctx, packed.get(), ctx->id("CLKHF_FABRIC"), 1000000 / frequency);
|
||||
if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
|
||||
replace_port(ci, id_CLKHF, packed.get(), id_CLKHF_FABRIC);
|
||||
set_period(ctx, packed.get(), id_CLKHF_FABRIC, 1000000 / frequency);
|
||||
} else {
|
||||
replace_port(ci, ctx->id("CLKHF"), packed.get(), ctx->id("CLKHF"));
|
||||
replace_port(ci, id_CLKHF, packed.get(), id_CLKHF);
|
||||
std::unique_ptr<CellInfo> gb =
|
||||
create_padin_gbuf(ctx, packed.get(), ctx->id("CLKHF"), "$gbuf_" + ci->name.str(ctx) + "_hfosc");
|
||||
create_padin_gbuf(ctx, packed.get(), id_CLKHF, "$gbuf_" + ci->name.str(ctx) + "_hfosc");
|
||||
set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 1000000 / frequency);
|
||||
new_cells.push_back(std::move(gb));
|
||||
}
|
||||
new_cells.push_back(std::move(packed));
|
||||
} else if (is_sb_spram(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_SPRAM"), ci->name.str(ctx) + "_RAM");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_SPRAM, ci->name.str(ctx) + "_RAM");
|
||||
packed_cells.insert(ci->name);
|
||||
for (auto attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
@ -1210,8 +1202,7 @@ static void pack_special(Context *ctx)
|
||||
}
|
||||
new_cells.push_back(std::move(packed));
|
||||
} else if (is_sb_mac16(ctx, ci)) {
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_DSP"), ci->name.str(ctx) + "_DSP");
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_DSP, ci->name.str(ctx) + "_DSP");
|
||||
packed_cells.insert(ci->name);
|
||||
for (auto attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
@ -1241,7 +1232,7 @@ static void pack_special(Context *ctx)
|
||||
if (net == nullptr)
|
||||
continue;
|
||||
|
||||
if ((pi.name != ctx->id("RGB0")) && (pi.name != ctx->id("RGB1")) && (pi.name != ctx->id("RGB2")))
|
||||
if ((pi.name != id_RGB0) && (pi.name != id_RGB1) && (pi.name != id_RGB2))
|
||||
continue;
|
||||
|
||||
if (net->users.size() > 0)
|
||||
@ -1253,10 +1244,10 @@ static void pack_special(Context *ctx)
|
||||
if (is_sb_rgb_drv(ctx, ci) && !ci->ledInfo.ledCurConnected)
|
||||
log_error("Port RGBPU of SB_RGB_DRV should be driven by port LEDPU of SB_LED_DRV_CUR!\n");
|
||||
|
||||
ci->ports.erase(ctx->id("RGBPU"));
|
||||
ci->ports.erase(ctx->id("RGB0"));
|
||||
ci->ports.erase(ctx->id("RGB1"));
|
||||
ci->ports.erase(ctx->id("RGB2"));
|
||||
ci->ports.erase(id_RGBPU);
|
||||
ci->ports.erase(id_RGB0);
|
||||
ci->ports.erase(id_RGB1);
|
||||
ci->ports.erase(id_RGB2);
|
||||
} else if (is_sb_ledda_ip(ctx, ci)) {
|
||||
/* Force placement (no choices anyway) */
|
||||
cell_place_unique(ctx, ci);
|
||||
@ -1268,7 +1259,7 @@ static void pack_special(Context *ctx)
|
||||
{std::make_tuple(id_SB_I2C, "0b0011"), Loc(25, 31, 0)},
|
||||
};
|
||||
std::string bus_addr74 =
|
||||
str_or_default(ci->params, ctx->id("BUS_ADDR74"), is_sb_i2c(ctx, ci) ? "0b0001" : "0b0000");
|
||||
str_or_default(ci->params, id_BUS_ADDR74, is_sb_i2c(ctx, ci) ? "0b0001" : "0b0000");
|
||||
if (map_ba74.find(std::make_tuple(ci->type, bus_addr74)) == map_ba74.end())
|
||||
log_error("Invalid value for BUS_ADDR74 for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
|
||||
ci->type.c_str(ctx));
|
||||
@ -1278,7 +1269,7 @@ static void pack_special(Context *ctx)
|
||||
log_error("Unable to find placement for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
|
||||
ci->type.c_str(ctx));
|
||||
IdStringList bel_name = ctx->getBelName(bel);
|
||||
ci->attrs[ctx->id("BEL")] = bel_name.str(ctx);
|
||||
ci->attrs[id_BEL] = bel_name.str(ctx);
|
||||
log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel));
|
||||
}
|
||||
}
|
||||
@ -1303,15 +1294,14 @@ void pack_plls(Context *ctx)
|
||||
bool is_pad = is_sb_pll40_pad(ctx, ci);
|
||||
bool is_core = !is_pad;
|
||||
|
||||
std::unique_ptr<CellInfo> packed =
|
||||
create_ice_cell(ctx, ctx->id("ICESTORM_PLL"), ci->name.str(ctx) + "_PLL");
|
||||
packed->attrs[ctx->id("TYPE")] = ci->type.str(ctx);
|
||||
std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_PLL, ci->name.str(ctx) + "_PLL");
|
||||
packed->attrs[id_TYPE] = ci->type.str(ctx);
|
||||
packed_cells.insert(ci->name);
|
||||
if (!is_sb_pll40_dual(ctx, ci)) {
|
||||
// Remove second output, so a buffer isn't created for it, for these
|
||||
// cell types with only one output
|
||||
packed->ports.erase(ctx->id("PLLOUT_B"));
|
||||
packed->ports.erase(ctx->id("PLLOUT_B_GLOBAL"));
|
||||
packed->ports.erase(id_PLLOUT_B);
|
||||
packed->ports.erase(id_PLLOUT_B_GLOBAL);
|
||||
}
|
||||
for (auto attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
@ -1319,9 +1309,9 @@ void pack_plls(Context *ctx)
|
||||
packed->params[param.first] = param.second;
|
||||
|
||||
const std::map<IdString, IdString> pos_map_name = {
|
||||
{ctx->id("PLLOUT_SELECT"), ctx->id("PLLOUT_SELECT_A")},
|
||||
{ctx->id("PLLOUT_SELECT_PORTA"), ctx->id("PLLOUT_SELECT_A")},
|
||||
{ctx->id("PLLOUT_SELECT_PORTB"), ctx->id("PLLOUT_SELECT_B")},
|
||||
{id_PLLOUT_SELECT, id_PLLOUT_SELECT_A},
|
||||
{id_PLLOUT_SELECT_PORTA, id_PLLOUT_SELECT_A},
|
||||
{id_PLLOUT_SELECT_PORTB, id_PLLOUT_SELECT_B},
|
||||
};
|
||||
const std::map<std::string, int> pos_map_val = {
|
||||
{"GENCLK", 0},
|
||||
@ -1336,9 +1326,8 @@ void pack_plls(Context *ctx)
|
||||
packed->params[pos_map_name.at(param.first)] = pos_map_val.at(param.second.as_string());
|
||||
}
|
||||
const std::map<IdString, std::pair<IdString, IdString>> delmodes = {
|
||||
{ctx->id("DELAY_ADJUSTMENT_MODE_FEEDBACK"), {ctx->id("DELAY_ADJMODE_FB"), ctx->id("FDA_FEEDBACK")}},
|
||||
{ctx->id("DELAY_ADJUSTMENT_MODE_RELATIVE"),
|
||||
{ctx->id("DELAY_ADJMODE_REL"), ctx->id("FDA_RELATIVE")}},
|
||||
{id_DELAY_ADJUSTMENT_MODE_FEEDBACK, {id_DELAY_ADJMODE_FB, id_FDA_FEEDBACK}},
|
||||
{id_DELAY_ADJUSTMENT_MODE_RELATIVE, {id_DELAY_ADJMODE_REL, id_FDA_RELATIVE}},
|
||||
};
|
||||
for (auto delmode : delmodes) {
|
||||
if (ci->params.count(delmode.first)) {
|
||||
@ -1352,9 +1341,9 @@ void pack_plls(Context *ctx)
|
||||
log_error("Invalid PLL %s selection '%s'\n", delmode.first.c_str(ctx), value.c_str());
|
||||
}
|
||||
}
|
||||
auto feedback_path = packed->params[ctx->id("FEEDBACK_PATH")].is_string
|
||||
? packed->params[ctx->id("FEEDBACK_PATH")].as_string()
|
||||
: std::to_string(packed->params[ctx->id("FEEDBACK_PATH")].as_int64());
|
||||
auto feedback_path = packed->params[id_FEEDBACK_PATH].is_string
|
||||
? packed->params[id_FEEDBACK_PATH].as_string()
|
||||
: std::to_string(packed->params[id_FEEDBACK_PATH].as_int64());
|
||||
std::string fbp_value = feedback_path == "DELAY" ? "0"
|
||||
: feedback_path == "SIMPLE" ? "1"
|
||||
: feedback_path == "PHASE_AND_DELAY" ? "2"
|
||||
@ -1363,8 +1352,8 @@ void pack_plls(Context *ctx)
|
||||
if (!std::all_of(fbp_value.begin(), fbp_value.end(), isdigit))
|
||||
log_error("PLL '%s' has unsupported FEEDBACK_PATH value '%s'\n", ci->name.c_str(ctx),
|
||||
feedback_path.c_str());
|
||||
packed->params[ctx->id("FEEDBACK_PATH")] = Property(std::stoi(fbp_value), 3);
|
||||
packed->params[ctx->id("PLLTYPE")] = sb_pll40_type(ctx, ci);
|
||||
packed->params[id_FEEDBACK_PATH] = Property(std::stoi(fbp_value), 3);
|
||||
packed->params[id_PLLTYPE] = sb_pll40_type(ctx, ci);
|
||||
|
||||
NetInfo *pad_packagepin_net = nullptr;
|
||||
|
||||
@ -1379,16 +1368,16 @@ void pack_plls(Context *ctx)
|
||||
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2);
|
||||
}
|
||||
|
||||
if (pi.name == ctx->id("PLLOUTCOREA") || pi.name == ctx->id("PLLOUTCORE"))
|
||||
if (pi.name == id_PLLOUTCOREA || pi.name == id_PLLOUTCORE)
|
||||
newname = "PLLOUT_A";
|
||||
if (pi.name == ctx->id("PLLOUTCOREB"))
|
||||
if (pi.name == id_PLLOUTCOREB)
|
||||
newname = "PLLOUT_B";
|
||||
if (pi.name == ctx->id("PLLOUTGLOBALA") || pi.name == ctx->id("PLLOUTGLOBAL"))
|
||||
if (pi.name == id_PLLOUTGLOBALA || pi.name == id_PLLOUTGLOBAL)
|
||||
newname = "PLLOUT_A_GLOBAL";
|
||||
if (pi.name == ctx->id("PLLOUTGLOBALB"))
|
||||
if (pi.name == id_PLLOUTGLOBALB)
|
||||
newname = "PLLOUT_B_GLOBAL";
|
||||
|
||||
if (pi.name == ctx->id("PACKAGEPIN")) {
|
||||
if (pi.name == id_PACKAGEPIN) {
|
||||
if (!is_pad) {
|
||||
log_error("PLL '%s' has a PACKAGEPIN but is not a PAD PLL\n", ci->name.c_str(ctx));
|
||||
} else {
|
||||
@ -1399,7 +1388,7 @@ void pack_plls(Context *ctx)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (pi.name == ctx->id("REFERENCECLK")) {
|
||||
if (pi.name == id_REFERENCECLK) {
|
||||
if (!is_core)
|
||||
log_error("PLL '%s' has a REFERENCECLK but is not a CORE PLL\n", ci->name.c_str(ctx));
|
||||
got_input_constr = get_period(ctx, ci, pi.name, input_constr);
|
||||
@ -1429,7 +1418,7 @@ void pack_plls(Context *ctx)
|
||||
log_info(" Input frequency of PLL '%s' is constrained to %.1f MHz\n", ctx->nameOf(ci),
|
||||
MHz(ctx, input_constr));
|
||||
// Input divider (DIVR)
|
||||
input_constr *= (int_or_default(packed->params, ctx->id("DIVR"), 0) + 1);
|
||||
input_constr *= (int_or_default(packed->params, id_DIVR, 0) + 1);
|
||||
delay_t vco_constr = 0;
|
||||
delay_t outa_constr = 0, outb_constr = 0;
|
||||
int sr_div = 4;
|
||||
@ -1452,7 +1441,7 @@ void pack_plls(Context *ctx)
|
||||
};
|
||||
|
||||
// Lookup shiftreg divider
|
||||
int sr_div_mode = int_or_default(packed->params, ctx->id("SHIFTREG_DIV_MODE"), 0);
|
||||
int sr_div_mode = int_or_default(packed->params, id_SHIFTREG_DIV_MODE, 0);
|
||||
switch (sr_div_mode) {
|
||||
case 0:
|
||||
sr_div = 4;
|
||||
@ -1470,8 +1459,8 @@ void pack_plls(Context *ctx)
|
||||
}
|
||||
}
|
||||
// Determine dividers in VCO path
|
||||
vco_constr = input_constr / (int_or_default(packed->params, ctx->id("DIVF"), 0) + 1);
|
||||
divq = 1 << (int_or_default(packed->params, ctx->id("DIVQ"), 0));
|
||||
vco_constr = input_constr / (int_or_default(packed->params, id_DIVF, 0) + 1);
|
||||
divq = 1 << (int_or_default(packed->params, id_DIVQ, 0));
|
||||
if (fbp_value != "1") // anything other than SIMPLE - feedback after DIVQ
|
||||
vco_constr /= divq;
|
||||
if (fbp_value == "6") { // EXTERNAL
|
||||
@ -1484,19 +1473,19 @@ void pack_plls(Context *ctx)
|
||||
}
|
||||
log_info(" VCO frequency of PLL '%s' is constrained to %.1f MHz\n", ctx->nameOf(ci),
|
||||
MHz(ctx, vco_constr));
|
||||
if (ci->type == ctx->id("SB_PLL40_2_PAD"))
|
||||
if (ci->type == id_SB_PLL40_2_PAD)
|
||||
outa_constr = input_constr; // 2_PAD variant passes through input to OUTPUT A
|
||||
else
|
||||
outa_constr = process_output(ctx->id("PLLOUT_SELECT_A"));
|
||||
outb_constr = process_output(ctx->id("PLLOUT_SELECT_B"));
|
||||
set_period(ctx, packed.get(), ctx->id("PLLOUT_A"), outa_constr);
|
||||
set_period(ctx, packed.get(), ctx->id("PLLOUT_A_GLOBAL"), outa_constr);
|
||||
set_period(ctx, packed.get(), ctx->id("PLLOUT_B"), outb_constr);
|
||||
set_period(ctx, packed.get(), ctx->id("PLLOUT_B_GLOBAL"), outb_constr);
|
||||
outa_constr = process_output(id_PLLOUT_SELECT_A);
|
||||
outb_constr = process_output(id_PLLOUT_SELECT_B);
|
||||
set_period(ctx, packed.get(), id_PLLOUT_A, outa_constr);
|
||||
set_period(ctx, packed.get(), id_PLLOUT_A_GLOBAL, outa_constr);
|
||||
set_period(ctx, packed.get(), id_PLLOUT_B, outb_constr);
|
||||
set_period(ctx, packed.get(), id_PLLOUT_B_GLOBAL, outb_constr);
|
||||
}
|
||||
constr_fail:
|
||||
// PLL must have been placed already in place_plls()
|
||||
BelId pll_bel = ctx->getBelByNameStr(packed->attrs[ctx->id("BEL")].as_string());
|
||||
BelId pll_bel = ctx->getBelByNameStr(packed->attrs[id_BEL].as_string());
|
||||
NPNR_ASSERT(pll_bel != BelId());
|
||||
|
||||
// Deal with PAD PLL peculiarities
|
||||
@ -1505,10 +1494,10 @@ void pack_plls(Context *ctx)
|
||||
auto pll_packagepin_driver = pad_packagepin_net->driver;
|
||||
NPNR_ASSERT(pll_packagepin_driver.cell != nullptr);
|
||||
auto packagepin_cell = pll_packagepin_driver.cell;
|
||||
auto packagepin_bel_name = packagepin_cell->attrs.find(ctx->id("BEL"));
|
||||
auto packagepin_bel_name = packagepin_cell->attrs.find(id_BEL);
|
||||
|
||||
// Set an attribute about this PLL's PAD SB_IO.
|
||||
packed->attrs[ctx->id("BEL_PAD_INPUT")] = packagepin_bel_name->second;
|
||||
packed->attrs[id_BEL_PAD_INPUT] = packagepin_bel_name->second;
|
||||
|
||||
// Disconnect PACKAGEPIN (it's a physical HW link)
|
||||
for (auto user : pad_packagepin_net->users)
|
||||
@ -1522,7 +1511,7 @@ void pack_plls(Context *ctx)
|
||||
// In practice, this means the LOCK signal can only directly reach LUT
|
||||
// inputs.
|
||||
// If we have a net connected to LOCK, make sure it only drives LUTs.
|
||||
auto port = packed->ports[ctx->id("LOCK")];
|
||||
auto port = packed->ports[id_LOCK];
|
||||
if (port.net != nullptr) {
|
||||
log_info(" PLL '%s' has LOCK output, need to pass all outputs via LUT\n", ci->name.c_str(ctx));
|
||||
bool found_lut = false;
|
||||
@ -1531,8 +1520,8 @@ void pack_plls(Context *ctx)
|
||||
unsigned int lut_count = 0;
|
||||
for (const auto &user : port.net->users) {
|
||||
NPNR_ASSERT(user.cell != nullptr);
|
||||
if (user.cell->type == ctx->id("ICESTORM_LC")) {
|
||||
if (bool_or_default(user.cell->params, ctx->id("CARRY_ENABLE"), false)) {
|
||||
if (user.cell->type == id_ICESTORM_LC) {
|
||||
if (bool_or_default(user.cell->params, id_CARRY_ENABLE, false)) {
|
||||
found_carry = true;
|
||||
all_luts = false;
|
||||
} else {
|
||||
@ -1569,14 +1558,14 @@ void pack_plls(Context *ctx)
|
||||
int z = 0;
|
||||
for (const auto &user : port.net->users) {
|
||||
NPNR_ASSERT(user.cell != nullptr);
|
||||
NPNR_ASSERT(user.cell->type == ctx->id("ICESTORM_LC"));
|
||||
NPNR_ASSERT(user.cell->type == id_ICESTORM_LC);
|
||||
|
||||
// TODO(q3k): handle when the Bel might be already the
|
||||
// target of another constraint.
|
||||
NPNR_ASSERT(z < 8);
|
||||
auto target_bel = ctx->getBelByLocation(Loc(x, y, z++));
|
||||
auto target_bel_name = ctx->getBelName(target_bel).str(ctx);
|
||||
user.cell->attrs[ctx->id("BEL")] = target_bel_name;
|
||||
user.cell->attrs[id_BEL] = target_bel_name;
|
||||
log_info(" constrained '%s' to %s\n", user.cell->name.c_str(ctx), target_bel_name.c_str());
|
||||
}
|
||||
}
|
||||
@ -1586,9 +1575,9 @@ void pack_plls(Context *ctx)
|
||||
PortInfo &pi = port.second;
|
||||
bool is_b_port;
|
||||
|
||||
if (pi.name == ctx->id("PLLOUT_A_GLOBAL"))
|
||||
if (pi.name == id_PLLOUT_A_GLOBAL)
|
||||
is_b_port = false;
|
||||
else if (pi.name == ctx->id("PLLOUT_B_GLOBAL"))
|
||||
else if (pi.name == id_PLLOUT_B_GLOBAL)
|
||||
is_b_port = true;
|
||||
else
|
||||
continue;
|
||||
@ -1635,13 +1624,13 @@ bool Arch::pack()
|
||||
place_plls(ctx);
|
||||
pack_special(ctx);
|
||||
pack_plls(ctx);
|
||||
if (!bool_or_default(ctx->settings, ctx->id("no_promote_globals"), false))
|
||||
if (!bool_or_default(ctx->settings, id_no_promote_globals, false))
|
||||
promote_globals(ctx);
|
||||
ctx->assignArchInfo();
|
||||
constrain_chains(ctx);
|
||||
ctx->fixupHierarchy();
|
||||
ctx->assignArchInfo();
|
||||
ctx->settings[ctx->id("pack")] = 1;
|
||||
ctx->settings[id_pack] = 1;
|
||||
archInfoToAttributes();
|
||||
log_info("Checksum: 0x%08x\n", ctx->checksum());
|
||||
return true;
|
||||
|
16
ice40/pcf.cc
16
ice40/pcf.cc
@ -57,9 +57,9 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
|
||||
if (setting == "-pullup") {
|
||||
const auto &value = words.at(++args_end);
|
||||
if (value == "yes" || value == "1")
|
||||
extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP"), Property::State::S1));
|
||||
extra_attrs.emplace_back(std::make_pair(id_PULLUP, Property::State::S1));
|
||||
else if (value == "no" || value == "0")
|
||||
extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP"), Property::State::S0));
|
||||
extra_attrs.emplace_back(std::make_pair(id_PULLUP, Property::State::S0));
|
||||
else
|
||||
log_error("Invalid value '%s' for -pullup (on line %d)\n", value.c_str(), lineno);
|
||||
} else if (setting == "-pullup_resistor") {
|
||||
@ -68,7 +68,7 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
|
||||
log_error("Pullup resistance can only be set on UP5K/UP3K (on line %d)\n", lineno);
|
||||
if (value != "3P3K" && value != "6P8K" && value != "10K" && value != "100K")
|
||||
log_error("Invalid value '%s' for -pullup_resistor (on line %d)\n", value.c_str(), lineno);
|
||||
extra_attrs.emplace_back(std::make_pair(ctx->id("PULLUP_RESISTOR"), value));
|
||||
extra_attrs.emplace_back(std::make_pair(id_PULLUP_RESISTOR, value));
|
||||
} else if (setting == "-nowarn") {
|
||||
nowarn = true;
|
||||
} else if (setting == "--warn-no-port") {
|
||||
@ -92,11 +92,11 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
|
||||
BelId pin_bel = ctx->get_package_pin_bel(pin);
|
||||
if (pin_bel == BelId())
|
||||
log_error("package does not have a pin named '%s' (on line %d)\n", pin.c_str(), lineno);
|
||||
if (fnd_cell->second->attrs.count(ctx->id("BEL")))
|
||||
if (fnd_cell->second->attrs.count(id_BEL))
|
||||
log_error("duplicate pin constraint on '%s' (on line %d)\n", cell.c_str(), lineno);
|
||||
fnd_cell->second->attrs[ctx->id("BEL")] = ctx->getBelName(pin_bel).str(ctx);
|
||||
fnd_cell->second->attrs[id_BEL] = ctx->getBelName(pin_bel).str(ctx);
|
||||
log_info("constrained '%s' to bel '%s'\n", cell.c_str(),
|
||||
fnd_cell->second->attrs[ctx->id("BEL")].as_string().c_str());
|
||||
fnd_cell->second->attrs[id_BEL].as_string().c_str());
|
||||
for (const auto &attr : extra_attrs)
|
||||
fnd_cell->second->attrs[attr.first] = attr.second;
|
||||
}
|
||||
@ -112,8 +112,8 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
|
||||
ci->type == ctx->id("$nextpnr_iobuf")) {
|
||||
if (!ci->attrs.count(ctx->id("BEL"))) {
|
||||
if (bool_or_default(ctx->settings, ctx->id("pcf_allow_unconstrained")))
|
||||
if (!ci->attrs.count(id_BEL)) {
|
||||
if (bool_or_default(ctx->settings, id_pcf_allow_unconstrained))
|
||||
log_warning("IO '%s' is unconstrained in PCF and will be automatically placed\n",
|
||||
cell.first.c_str(ctx));
|
||||
else
|
||||
|
@ -171,17 +171,17 @@ std::string Arch::get_full_chip_name() const
|
||||
IdString Arch::archArgsToId(ArchArgs args) const
|
||||
{
|
||||
if (args.type == ArchArgs::LCMXO2_256HC) {
|
||||
return id("lcmxo2_256hc");
|
||||
return id_lcmxo2_256hc;
|
||||
} else if (args.type == ArchArgs::LCMXO2_640HC) {
|
||||
return id("lcmxo2_640hc");
|
||||
return id_lcmxo2_640hc;
|
||||
} else if (args.type == ArchArgs::LCMXO2_1200HC) {
|
||||
return id("lcmxo2_1200hc");
|
||||
return id_lcmxo2_1200hc;
|
||||
} else if (args.type == ArchArgs::LCMXO2_2000HC) {
|
||||
return id("lcmxo2_2000hc");
|
||||
return id_lcmxo2_2000hc;
|
||||
} else if (args.type == ArchArgs::LCMXO2_4000HC) {
|
||||
return id("lcmxo2_4000hc");
|
||||
return id_lcmxo2_4000hc;
|
||||
} else if (args.type == ArchArgs::LCMXO2_7000HC) {
|
||||
return id("lcmxo2_7000hc");
|
||||
return id_lcmxo2_7000hc;
|
||||
}
|
||||
|
||||
return IdString();
|
||||
@ -414,17 +414,17 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
||||
|
||||
bool Arch::place()
|
||||
{
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
if (placer == "sa") {
|
||||
bool retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
archInfoToAttributes();
|
||||
return retVal;
|
||||
} else if (placer == "heap") {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
cfg.ioBufTypes.insert(id_FACADE_IO);
|
||||
bool retVal = placer_heap(getCtx(), cfg);
|
||||
getCtx()->settings[getCtx()->id("place")] = 1;
|
||||
getCtx()->settings[id_place] = 1;
|
||||
archInfoToAttributes();
|
||||
return retVal;
|
||||
} else {
|
||||
@ -434,7 +434,7 @@ bool Arch::place()
|
||||
|
||||
bool Arch::route()
|
||||
{
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
bool result;
|
||||
if (router == "router1") {
|
||||
result = router1(getCtx(), Router1Cfg(getCtx()));
|
||||
@ -444,7 +444,7 @@ bool Arch::route()
|
||||
} else {
|
||||
log_error("MachXO2 architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
getCtx()->settings[getCtx()->id("route")] = 1;
|
||||
getCtx()->settings[id_route] = 1;
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
|
@ -435,7 +435,7 @@ struct Arch : BaseArch<ArchRanges>
|
||||
// Extra helper
|
||||
std::string get_full_chip_name() const;
|
||||
|
||||
IdString archId() const override { return id("machxo2"); }
|
||||
IdString archId() const override { return id_machxo2; }
|
||||
ArchArgs archArgs() const override { return args; }
|
||||
IdString archArgsToId(ArchArgs args) const override;
|
||||
|
||||
|
@ -235,36 +235,34 @@ void write_bitstream(Context *ctx, std::string text_config_file)
|
||||
int int_index = slice[5] - 'A';
|
||||
NPNR_ASSERT(int_index >= 0 && int_index < 4);
|
||||
|
||||
int lut0_init = int_or_default(ci->params, ctx->id("LUT0_INITVAL"));
|
||||
int lut1_init = int_or_default(ci->params, ctx->id("LUT1_INITVAL"));
|
||||
int lut0_init = int_or_default(ci->params, id_LUT0_INITVAL);
|
||||
int lut1_init = int_or_default(ci->params, id_LUT1_INITVAL);
|
||||
cc.tiles[tname].add_word(slice + ".K0.INIT", int_to_bitvector(lut0_init, 16));
|
||||
cc.tiles[tname].add_word(slice + ".K1.INIT", int_to_bitvector(lut1_init, 16));
|
||||
cc.tiles[tname].add_enum(slice + ".MODE", str_or_default(ci->params, ctx->id("MODE"), "LOGIC"));
|
||||
cc.tiles[tname].add_enum(slice + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "ENABLED"));
|
||||
cc.tiles[tname].add_enum(slice + ".MODE", str_or_default(ci->params, id_MODE, "LOGIC"));
|
||||
cc.tiles[tname].add_enum(slice + ".GSR", str_or_default(ci->params, id_GSR, "ENABLED"));
|
||||
cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".SRMODE",
|
||||
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum(slice + ".CEMUX", intstr_or_default(ci->params, ctx->id("CEMUX"), "1"));
|
||||
str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
|
||||
cc.tiles[tname].add_enum(slice + ".CEMUX", intstr_or_default(ci->params, id_CEMUX, "1"));
|
||||
cc.tiles[tname].add_enum("CLK" + std::to_string(int_index) + ".CLKMUX",
|
||||
intstr_or_default(ci->params, ctx->id("CLKMUX"), "0"));
|
||||
intstr_or_default(ci->params, id_CLKMUX, "0"));
|
||||
cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".LSRMUX",
|
||||
str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
|
||||
str_or_default(ci->params, id_LSRMUX, "LSR"));
|
||||
cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".LSRONMUX",
|
||||
intstr_or_default(ci->params, ctx->id("LSRONMUX"), "LSRMUX"));
|
||||
cc.tiles[tname].add_enum(slice + ".REGMODE", str_or_default(ci->params, ctx->id("REGMODE"), "FF"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.SD", intstr_or_default(ci->params, ctx->id("REG0_SD"), "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.SD", intstr_or_default(ci->params, ctx->id("REG1_SD"), "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.REGSET",
|
||||
str_or_default(ci->params, ctx->id("REG0_REGSET"), "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.REGSET",
|
||||
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET"));
|
||||
} else if (ci->type == ctx->id("FACADE_IO")) {
|
||||
intstr_or_default(ci->params, id_LSRONMUX, "LSRMUX"));
|
||||
cc.tiles[tname].add_enum(slice + ".REGMODE", str_or_default(ci->params, id_REGMODE, "FF"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.SD", intstr_or_default(ci->params, id_REG0_SD, "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.SD", intstr_or_default(ci->params, id_REG1_SD, "0"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG0.REGSET", str_or_default(ci->params, id_REG0_REGSET, "RESET"));
|
||||
cc.tiles[tname].add_enum(slice + ".REG1.REGSET", str_or_default(ci->params, id_REG1_REGSET, "RESET"));
|
||||
} else if (ci->type == id_FACADE_IO) {
|
||||
std::string pio = ctx->tile_info(bel)->bel_data[bel.index].name.get();
|
||||
std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33");
|
||||
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT");
|
||||
std::string iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
|
||||
std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
|
||||
std::string pic_tile = get_pic_tile(ctx, bel);
|
||||
cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
|
||||
} else if (ci->type == ctx->id("OSCH")) {
|
||||
std::string freq = str_or_default(ci->params, ctx->id("NOM_FREQ"), "2.08");
|
||||
} else if (ci->type == id_OSCH) {
|
||||
std::string freq = str_or_default(ci->params, id_NOM_FREQ, "2.08");
|
||||
cc.tiles[ctx->get_tile_by_type("CFG1")].add_enum("OSCH.MODE", "OSCH");
|
||||
cc.tiles[ctx->get_tile_by_type("CFG1")].add_enum("OSCH.NOM_FREQ", freq);
|
||||
}
|
||||
|
@ -103,12 +103,12 @@ std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::
|
||||
new_cell->addOutput(id_WADO3);
|
||||
} else if (type == id_FACADE_IO) {
|
||||
new_cell->params[id_DIR] = std::string("INPUT");
|
||||
new_cell->attrs[ctx->id("IO_TYPE")] = std::string("LVCMOS33");
|
||||
new_cell->attrs[id_IO_TYPE] = std::string("LVCMOS33");
|
||||
|
||||
new_cell->addInout(ctx->id("PAD"));
|
||||
new_cell->addInput(ctx->id("I"));
|
||||
new_cell->addInput(ctx->id("EN"));
|
||||
new_cell->addOutput(ctx->id("O"));
|
||||
new_cell->addInout(id_PAD);
|
||||
new_cell->addInput(id_I);
|
||||
new_cell->addInput(id_EN);
|
||||
new_cell->addOutput(id_O);
|
||||
} else if (type == id_LUT4) {
|
||||
new_cell->params[id_INIT] = Property(0, 16);
|
||||
|
||||
@ -126,7 +126,7 @@ std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::
|
||||
|
||||
void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
|
||||
{
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = lut->params[ctx->id("INIT")];
|
||||
lc->params[id_LUT0_INITVAL] = lut->params[id_INIT];
|
||||
|
||||
for (std::string i : {"A", "B", "C", "D"}) {
|
||||
IdString lut_port = ctx->id(i);
|
||||
@ -134,34 +134,34 @@ void lut_to_lc(const Context *ctx, CellInfo *lut, CellInfo *lc, bool no_dff)
|
||||
replace_port(lut, lut_port, lc, lc_port);
|
||||
}
|
||||
|
||||
replace_port(lut, ctx->id("Z"), lc, ctx->id("F0"));
|
||||
replace_port(lut, id_Z, lc, id_F0);
|
||||
}
|
||||
|
||||
void dff_to_lc(Context *ctx, CellInfo *dff, CellInfo *lc, LutType lut_type)
|
||||
{
|
||||
// FIXME: This will have to change once we support FFs with reset value of 1.
|
||||
lc->params[ctx->id("REG0_REGSET")] = std::string("RESET");
|
||||
lc->params[id_REG0_REGSET] = std::string("RESET");
|
||||
|
||||
replace_port(dff, ctx->id("CLK"), lc, ctx->id("CLK"));
|
||||
replace_port(dff, ctx->id("LSR"), lc, ctx->id("LSR"));
|
||||
replace_port(dff, ctx->id("Q"), lc, ctx->id("Q0"));
|
||||
replace_port(dff, id_CLK, lc, id_CLK);
|
||||
replace_port(dff, id_LSR, lc, id_LSR);
|
||||
replace_port(dff, id_Q, lc, id_Q0);
|
||||
|
||||
if (lut_type == LutType::PassThru) {
|
||||
// If a register's DI port is fed by a constant, options for placing are
|
||||
// limited. Use the LUT to get around this.
|
||||
// LUT output will go to F0, which will feed back to DI0 input.
|
||||
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16);
|
||||
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0"));
|
||||
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0"));
|
||||
lc->params[id_LUT0_INITVAL] = Property(0xAAAA, 16);
|
||||
replace_port(dff, id_DI, lc, id_A0);
|
||||
connect_ports(ctx, lc, id_F0, lc, id_DI0);
|
||||
} else if (lut_type == LutType::None) {
|
||||
// If there is no LUT, use the M0 input because DI0 requires
|
||||
// going through the LUTs.
|
||||
lc->params[ctx->id("REG0_SD")] = std::string("0");
|
||||
replace_port(dff, ctx->id("DI"), lc, ctx->id("M0"));
|
||||
lc->params[id_REG0_SD] = std::string("0");
|
||||
replace_port(dff, id_DI, lc, id_M0);
|
||||
} else {
|
||||
// Otherwise, there's a LUT being used in the slice and mapping DI to
|
||||
// DI0 input is fine.
|
||||
replace_port(dff, ctx->id("DI"), lc, ctx->id("DI0"));
|
||||
replace_port(dff, id_DI, lc, id_DI0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,12 +40,12 @@ enum class LutType
|
||||
std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::string name = "");
|
||||
|
||||
// Return true if a cell is a LUT
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("LUT4"); }
|
||||
inline bool is_lut(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_LUT4; }
|
||||
|
||||
// Return true if a cell is a flipflop
|
||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("FACADE_FF"); }
|
||||
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_FACADE_FF; }
|
||||
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == ctx->id("FACADE_SLICE"); }
|
||||
inline bool is_lc(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_FACADE_SLICE; }
|
||||
|
||||
// Convert a LUT primitive to (part of) an GENERIC_SLICE, swapping ports
|
||||
// as needed. Set no_dff if a DFF is not being used, so that the output
|
||||
|
@ -116,3 +116,22 @@ X(CLK0)
|
||||
X(CLK1)
|
||||
X(SEL)
|
||||
X(DCMOUT)
|
||||
|
||||
X(BEL)
|
||||
X(GND)
|
||||
X(IO_TYPE)
|
||||
X(LOC)
|
||||
X(NOM_FREQ)
|
||||
X(VCC)
|
||||
X(lcmxo2_1200hc)
|
||||
X(lcmxo2_2000hc)
|
||||
X(lcmxo2_256hc)
|
||||
X(lcmxo2_4000hc)
|
||||
X(lcmxo2_640hc)
|
||||
X(lcmxo2_7000hc)
|
||||
X(machxo2)
|
||||
X(pack)
|
||||
X(place)
|
||||
X(placer)
|
||||
X(route)
|
||||
X(router)
|
||||
|
@ -51,20 +51,20 @@ static void pack_lut_lutffs(Context *ctx)
|
||||
// LUT4 drives more than one FF.
|
||||
NetInfo *o = ci->ports.at(id_Z).net;
|
||||
CellInfo *dff = net_only_drives(ctx, o, is_ff, id_DI, false);
|
||||
auto lut_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto lut_bel = ci->attrs.find(id_BEL);
|
||||
bool packed_dff = false;
|
||||
|
||||
if (dff) {
|
||||
if (ctx->verbose)
|
||||
log_info("found attached dff %s\n", dff->name.c_str(ctx));
|
||||
auto dff_bel = dff->attrs.find(ctx->id("BEL"));
|
||||
auto dff_bel = dff->attrs.find(id_BEL);
|
||||
if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
|
||||
// Locations don't match, can't pack
|
||||
} else {
|
||||
lut_to_lc(ctx, ci, packed.get(), false);
|
||||
dff_to_lc(ctx, dff, packed.get(), LutType::Normal);
|
||||
if (dff_bel != dff->attrs.end())
|
||||
packed->attrs[ctx->id("BEL")] = dff_bel->second;
|
||||
packed->attrs[id_BEL] = dff_bel->second;
|
||||
packed_cells.insert(dff->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", dff->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
@ -104,12 +104,12 @@ static void pack_remaining_ffs(Context *ctx)
|
||||
for (auto &attr : ci->attrs)
|
||||
packed->attrs[attr.first] = attr.second;
|
||||
|
||||
auto dff_bel = ci->attrs.find(ctx->id("BEL"));
|
||||
auto dff_bel = ci->attrs.find(id_BEL);
|
||||
|
||||
dff_to_lc(ctx, ci, packed.get(), LutType::None);
|
||||
|
||||
if (dff_bel != ci->attrs.end())
|
||||
packed->attrs[ctx->id("BEL")] = dff_bel->second;
|
||||
packed->attrs[id_BEL] = dff_bel->second;
|
||||
packed_cells.insert(ci->name);
|
||||
if (ctx->verbose)
|
||||
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx));
|
||||
@ -198,12 +198,12 @@ static void pack_constants(Context *ctx)
|
||||
|
||||
for (auto &net : ctx->nets) {
|
||||
NetInfo *ni = net.second.get();
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("GND")) {
|
||||
if (ni->driver.cell != nullptr && ni->driver.cell->type == id_GND) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, gnd_net, false);
|
||||
dead_nets.push_back(net.first);
|
||||
ctx->cells.erase(drv_cell);
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == ctx->id("VCC")) {
|
||||
} else if (ni->driver.cell != nullptr && ni->driver.cell->type == id_VCC) {
|
||||
IdString drv_cell = ni->driver.cell->name;
|
||||
set_net_constant(ctx, ni, vcc_net, true);
|
||||
dead_nets.push_back(net.first);
|
||||
@ -294,8 +294,8 @@ static void pack_io(Context *ctx)
|
||||
// attribute already on a FACADE_IO is an error. Attributes on
|
||||
// the pin attached to the PAD of FACADE_IO are ignored by this
|
||||
// packing phase.
|
||||
auto loc_attr_cell = ci->attrs.find(ctx->id("LOC"));
|
||||
auto bel_attr_cell = ci->attrs.find(ctx->id("BEL"));
|
||||
auto loc_attr_cell = ci->attrs.find(id_LOC);
|
||||
auto bel_attr_cell = ci->attrs.find(id_BEL);
|
||||
|
||||
if (loc_attr_cell != ci->attrs.end()) {
|
||||
if (bel_attr_cell != ci->attrs.end()) {
|
||||
@ -312,7 +312,7 @@ static void pack_io(Context *ctx)
|
||||
} else {
|
||||
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx), ctx->nameOfBel(pinBel));
|
||||
}
|
||||
ci->attrs[ctx->id("BEL")] = ctx->getBelName(pinBel).str(ctx);
|
||||
ci->attrs[id_BEL] = ctx->getBelName(pinBel).str(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -332,7 +332,7 @@ bool Arch::pack()
|
||||
pack_io(ctx);
|
||||
pack_lut_lutffs(ctx);
|
||||
pack_remaining_ffs(ctx);
|
||||
ctx->settings[ctx->id("pack")] = 1;
|
||||
ctx->settings[id_pack] = 1;
|
||||
ctx->assignArchInfo();
|
||||
log_info("Checksum: 0x%08x\n", ctx->checksum());
|
||||
return true;
|
||||
|
@ -446,7 +446,7 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
|
||||
|
||||
bool Arch::place()
|
||||
{
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
|
||||
if (placer == "heap") {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
@ -468,7 +468,7 @@ bool Arch::place()
|
||||
log_error("Mistral architecture does not support placer '%s'\n", placer.c_str());
|
||||
}
|
||||
|
||||
getCtx()->attrs[getCtx()->id("step")] = std::string("place");
|
||||
getCtx()->attrs[id_step] = std::string("place");
|
||||
archInfoToAttributes();
|
||||
return true;
|
||||
}
|
||||
@ -479,7 +479,7 @@ bool Arch::route()
|
||||
|
||||
lab_pre_route();
|
||||
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
bool result;
|
||||
if (router == "router1") {
|
||||
result = router1(getCtx(), Router1Cfg(getCtx()));
|
||||
@ -489,7 +489,7 @@ bool Arch::route()
|
||||
} else {
|
||||
log_error("Mistral architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
getCtx()->attrs[getCtx()->id("step")] = std::string("route");
|
||||
getCtx()->attrs[id_step] = std::string("route");
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
|
@ -97,3 +97,11 @@ X(WE_INV)
|
||||
|
||||
X(cyclonev_oscillator)
|
||||
X(cyclonev_hps_interface_mpu_general_purpose)
|
||||
|
||||
X(clkout)
|
||||
X(clkout1)
|
||||
X(compress_rbf)
|
||||
X(oscena)
|
||||
X(placer)
|
||||
X(router)
|
||||
X(step)
|
||||
|
@ -58,9 +58,9 @@ void Arch::create_hps_mpu_general_purpose(int x, int y)
|
||||
void Arch::create_control(int x, int y)
|
||||
{
|
||||
BelId oscillator_bel = add_bel(x, y, id_cyclonev_oscillator, id_cyclonev_oscillator);
|
||||
add_bel_pin(oscillator_bel, id("oscena"), PORT_IN, get_port(CycloneV::CTRL, x, y, -1, CycloneV::OSC_ENA, -1));
|
||||
add_bel_pin(oscillator_bel, id("clkout"), PORT_OUT, get_port(CycloneV::CTRL, x, y, -1, CycloneV::CLK_OUT, -1));
|
||||
add_bel_pin(oscillator_bel, id("clkout1"), PORT_OUT, get_port(CycloneV::CTRL, x, y, -1, CycloneV::CLK_OUT1, -1));
|
||||
add_bel_pin(oscillator_bel, id_oscena, PORT_IN, get_port(CycloneV::CTRL, x, y, -1, CycloneV::OSC_ENA, -1));
|
||||
add_bel_pin(oscillator_bel, id_clkout, PORT_OUT, get_port(CycloneV::CTRL, x, y, -1, CycloneV::CLK_OUT, -1));
|
||||
add_bel_pin(oscillator_bel, id_clkout1, PORT_OUT, get_port(CycloneV::CTRL, x, y, -1, CycloneV::CLK_OUT1, -1));
|
||||
}
|
||||
|
||||
NEXTPNR_NAMESPACE_END
|
||||
|
@ -79,7 +79,7 @@ std::unique_ptr<Context> MistralCommandHandler::createContext(dict<std::string,
|
||||
chipArgs.device = vm["device"].as<std::string>();
|
||||
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||
if (vm.count("compress-rbf"))
|
||||
ctx->settings[ctx->id("compress_rbf")] = Property::State::S1;
|
||||
ctx->settings[id_compress_rbf] = Property::State::S1;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
|
@ -186,8 +186,8 @@ Arch::Arch(ArchArgs args) : args(args)
|
||||
disabled_pips.insert(pip);
|
||||
}
|
||||
// TODO: find a better solution to disable these
|
||||
WireId dcs_out = getWireByName(
|
||||
IdStringList(std::array<IdString, 3>{x_ids.at(37), y_ids.at(10), id("JDCSOUT_DCS_DCSIP")}));
|
||||
WireId dcs_out =
|
||||
getWireByName(IdStringList(std::array<IdString, 3>{x_ids.at(37), y_ids.at(10), id_JDCSOUT_DCS_DCSIP}));
|
||||
for (auto dcs_pip : getPipsUphill(dcs_out))
|
||||
disabled_pips.insert(dcs_pip);
|
||||
NPNR_ASSERT(disabled_pips.size() == 6);
|
||||
@ -300,13 +300,13 @@ std::vector<std::pair<IdString, std::string>> Arch::getBelAttrs(BelId bel) const
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
|
||||
ret.emplace_back(id("INDEX"), stringf("%d", bel.index));
|
||||
ret.emplace_back(id_INDEX, stringf("%d", bel.index));
|
||||
|
||||
ret.emplace_back(id("GRID_X"), stringf("%d", bel.tile % chip_info->width));
|
||||
ret.emplace_back(id("GRID_Y"), stringf("%d", bel.tile / chip_info->width));
|
||||
ret.emplace_back(id("BEL_Z"), stringf("%d", bel_data(bel).z));
|
||||
ret.emplace_back(id_GRID_X, stringf("%d", bel.tile % chip_info->width));
|
||||
ret.emplace_back(id_GRID_Y, stringf("%d", bel.tile / chip_info->width));
|
||||
ret.emplace_back(id_BEL_Z, stringf("%d", bel_data(bel).z));
|
||||
|
||||
ret.emplace_back(id("BEL_TYPE"), nameOf(getBelType(bel)));
|
||||
ret.emplace_back(id_BEL_TYPE, nameOf(getBelType(bel)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -337,11 +337,11 @@ std::vector<std::pair<IdString, std::string>> Arch::getWireAttrs(WireId wire) co
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
|
||||
ret.emplace_back(id("INDEX"), stringf("%d", wire.index));
|
||||
ret.emplace_back(id_INDEX, stringf("%d", wire.index));
|
||||
|
||||
ret.emplace_back(id("GRID_X"), stringf("%d", wire.tile % chip_info->width));
|
||||
ret.emplace_back(id("GRID_Y"), stringf("%d", wire.tile / chip_info->width));
|
||||
ret.emplace_back(id("FLAGS"), stringf("%u", wire_data(wire).flags));
|
||||
ret.emplace_back(id_GRID_X, stringf("%d", wire.tile % chip_info->width));
|
||||
ret.emplace_back(id_GRID_Y, stringf("%d", wire.tile / chip_info->width));
|
||||
ret.emplace_back(id_FLAGS, stringf("%u", wire_data(wire).flags));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -388,13 +388,13 @@ std::vector<std::pair<IdString, std::string>> Arch::getPipAttrs(PipId pip) const
|
||||
{
|
||||
std::vector<std::pair<IdString, std::string>> ret;
|
||||
|
||||
ret.emplace_back(id("INDEX"), stringf("%d", pip.index));
|
||||
ret.emplace_back(id_INDEX, stringf("%d", pip.index));
|
||||
|
||||
ret.emplace_back(id("GRID_X"), stringf("%d", pip.tile % chip_info->width));
|
||||
ret.emplace_back(id("GRID_Y"), stringf("%d", pip.tile / chip_info->width));
|
||||
ret.emplace_back(id_GRID_X, stringf("%d", pip.tile % chip_info->width));
|
||||
ret.emplace_back(id_GRID_Y, stringf("%d", pip.tile / chip_info->width));
|
||||
|
||||
ret.emplace_back(id("FROM_TILE_WIRE"), nameOf(IdString(loc_data(pip).wires[pip_data(pip).from_wire].name)));
|
||||
ret.emplace_back(id("TO_TILE_WIRE"), nameOf(IdString(loc_data(pip).wires[pip_data(pip).to_wire].name)));
|
||||
ret.emplace_back(id_FROM_TILE_WIRE, nameOf(IdString(loc_data(pip).wires[pip_data(pip).from_wire].name)));
|
||||
ret.emplace_back(id_TO_TILE_WIRE, nameOf(IdString(loc_data(pip).wires[pip_data(pip).to_wire].name)));
|
||||
|
||||
return ret;
|
||||
}
|
||||
@ -665,7 +665,7 @@ bool Arch::place()
|
||||
if (getCtx()->settings.count(getCtx()->id("estimate-delay-mult")))
|
||||
estimate_delay_mult = getCtx()->setting<int>("estimate-delay-mult");
|
||||
|
||||
std::string placer = str_or_default(settings, id("placer"), defaultPlacer);
|
||||
std::string placer = str_or_default(settings, id_placer, defaultPlacer);
|
||||
|
||||
if (placer == "heap") {
|
||||
PlacerHeapCfg cfg(getCtx());
|
||||
@ -689,7 +689,7 @@ bool Arch::place()
|
||||
|
||||
post_place_opt();
|
||||
|
||||
getCtx()->attrs[getCtx()->id("step")] = std::string("place");
|
||||
getCtx()->attrs[id_step] = std::string("place");
|
||||
archInfoToAttributes();
|
||||
return true;
|
||||
}
|
||||
@ -740,7 +740,7 @@ bool Arch::route()
|
||||
|
||||
route_globals();
|
||||
|
||||
std::string router = str_or_default(settings, id("router"), defaultRouter);
|
||||
std::string router = str_or_default(settings, id_router, defaultRouter);
|
||||
bool result;
|
||||
if (router == "router1") {
|
||||
result = router1(getCtx(), Router1Cfg(getCtx()));
|
||||
@ -752,7 +752,7 @@ bool Arch::route()
|
||||
} else {
|
||||
log_error("Nexus architecture does not support router '%s'\n", router.c_str());
|
||||
}
|
||||
getCtx()->attrs[getCtx()->id("step")] = std::string("route");
|
||||
getCtx()->attrs[id_step] = std::string("route");
|
||||
archInfoToAttributes();
|
||||
return result;
|
||||
}
|
||||
|
@ -531,3 +531,24 @@ X(Q1)
|
||||
X(SCLK)
|
||||
|
||||
X(LOCAL_VCC)
|
||||
|
||||
X(BEL_TYPE)
|
||||
X(BEL_Z)
|
||||
X(CEOUTMUX)
|
||||
X(CLAMP)
|
||||
X(FLAGS)
|
||||
X(FROM_TILE_WIRE)
|
||||
X(GLITCHFILTER)
|
||||
X(GRID_X)
|
||||
X(GRID_Y)
|
||||
X(INDEX)
|
||||
X(JDCSOUT_DCS_DCSIP)
|
||||
X(PULLMODE)
|
||||
X(TO_TILE_WIRE)
|
||||
X(carry_lutff_ratio)
|
||||
X(no_pack_lutff)
|
||||
X(no_post_place_opt)
|
||||
X(placer)
|
||||
X(router)
|
||||
X(step)
|
||||
X(syn_useioff)
|
||||
|
@ -79,15 +79,15 @@ std::unique_ptr<Context> NexusCommandHandler::createContext(dict<std::string, Pr
|
||||
chipArgs.device = vm["device"].as<std::string>();
|
||||
auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
|
||||
if (vm.count("no-post-place-opt"))
|
||||
ctx->settings[ctx->id("no_post_place_opt")] = Property::State::S1;
|
||||
ctx->settings[id_no_post_place_opt] = Property::State::S1;
|
||||
if (vm.count("no-pack-lutff"))
|
||||
ctx->settings[ctx->id("no_pack_lutff")] = Property::State::S1;
|
||||
ctx->settings[id_no_pack_lutff] = Property::State::S1;
|
||||
if (vm.count("carry-lutff-ratio")) {
|
||||
float ratio = vm["carry-lutff-ratio"].as<float>();
|
||||
if (ratio < 0.0f || ratio > 1.0f) {
|
||||
log_error("Carry LUT+FF packing ration must be between 0.0 and 1.0");
|
||||
}
|
||||
ctx->settings[ctx->id("carry_lutff_ratio")] = ratio;
|
||||
ctx->settings[id_carry_lutff_ratio] = ratio;
|
||||
}
|
||||
if (vm.count("estimate-delay-mult"))
|
||||
ctx->settings[ctx->id("estimate-delay-mult")] = vm["estimate-delay-mult"].as<int>();
|
||||
|
@ -1132,7 +1132,7 @@ struct NexusPacker
|
||||
CellInfo *ci = cell.second.get();
|
||||
if (ci->type != id_LRAM_CORE)
|
||||
continue;
|
||||
if (str_or_default(ci->params, ctx->id("ECC_BYTE_SEL"), "BYTE_EN") == "BYTE_EN")
|
||||
if (str_or_default(ci->params, id_ECC_BYTE_SEL, "BYTE_EN") == "BYTE_EN")
|
||||
continue;
|
||||
for (int i = 0; i < 0x80; i++) {
|
||||
// FIXME: document ECC and remove this DRC
|
||||
@ -1986,7 +1986,7 @@ struct NexusPacker
|
||||
if (ci->type == id_DCC) {
|
||||
copy_constraint(ci, id_CLKI, id_CLKO, 1);
|
||||
} else if (ci->type == id_OSC_CORE) {
|
||||
int div = int_or_default(ci->params, ctx->id("HF_CLK_DIV"), 128);
|
||||
int div = int_or_default(ci->params, id_HF_CLK_DIV, 128);
|
||||
const float tol = 1.07f; // OSCA has +/-7% frequency tolerance, assume the worst case.
|
||||
set_period(ci, id_HFCLKOUT, delay_t((1.0e6 / 450) * (div + 1) / tol));
|
||||
set_period(ci, id_LFCLKOUT, delay_t((1.0e3 / 10) / tol));
|
||||
@ -2177,26 +2177,26 @@ struct NexusPacker
|
||||
|
||||
// We have IDDR+ODDR
|
||||
if (isODDR && isIDDR) {
|
||||
if (!iob->attrs.count(ctx->id("GLITCHFILTER"))) {
|
||||
iob->attrs[ctx->id("GLITCHFILTER")] = std::string("ON");
|
||||
if (!iob->attrs.count(id_GLITCHFILTER)) {
|
||||
iob->attrs[id_GLITCHFILTER] = std::string("ON");
|
||||
}
|
||||
if (!iob->attrs.count(ctx->id("CLAMP"))) {
|
||||
iob->attrs[ctx->id("CLAMP")] = std::string("ON");
|
||||
if (!iob->attrs.count(id_CLAMP)) {
|
||||
iob->attrs[id_CLAMP] = std::string("ON");
|
||||
}
|
||||
if (!iob->attrs.count(ctx->id("PULLMODE"))) {
|
||||
iob->attrs[ctx->id("PULLMODE")] = std::string("DOWN");
|
||||
if (!iob->attrs.count(id_PULLMODE)) {
|
||||
iob->attrs[id_PULLMODE] = std::string("DOWN");
|
||||
}
|
||||
}
|
||||
// We have ODDR only
|
||||
else if (isODDR && !isIDDR) {
|
||||
if (!iob->attrs.count(ctx->id("GLITCHFILTER"))) {
|
||||
iob->attrs[ctx->id("GLITCHFILTER")] = std::string("OFF");
|
||||
if (!iob->attrs.count(id_GLITCHFILTER)) {
|
||||
iob->attrs[id_GLITCHFILTER] = std::string("OFF");
|
||||
}
|
||||
if (!iob->attrs.count(ctx->id("CLAMP"))) {
|
||||
iob->attrs[ctx->id("CLAMP")] = std::string("OFF");
|
||||
if (!iob->attrs.count(id_CLAMP)) {
|
||||
iob->attrs[id_CLAMP] = std::string("OFF");
|
||||
}
|
||||
if (!iob->attrs.count(ctx->id("PULLMODE"))) {
|
||||
iob->attrs[ctx->id("PULLMODE")] = std::string("NONE");
|
||||
if (!iob->attrs.count(id_PULLMODE)) {
|
||||
iob->attrs[id_PULLMODE] = std::string("NONE");
|
||||
}
|
||||
}
|
||||
|
||||
@ -2237,8 +2237,8 @@ struct NexusPacker
|
||||
// Check if the net wants to use the T flip-flop in
|
||||
// IOLOGIC
|
||||
bool syn_useioff = false;
|
||||
if (iob_t->attrs.count(ctx->id("syn_useioff"))) {
|
||||
syn_useioff = iob_t->attrs.at(ctx->id("syn_useioff")).as_bool();
|
||||
if (iob_t->attrs.count(id_syn_useioff)) {
|
||||
syn_useioff = iob_t->attrs.at(id_syn_useioff).as_bool();
|
||||
}
|
||||
|
||||
// Check if the T input is driven by a flip-flop. Store
|
||||
@ -2281,7 +2281,7 @@ struct NexusPacker
|
||||
iol->params[id_REGSET] = ff->params.at(id_REGSET);
|
||||
|
||||
// Enable the TSREG
|
||||
iol->params[ctx->id("CEOUTMUX")] = std::string("1");
|
||||
iol->params[id_CEOUTMUX] = std::string("1");
|
||||
iol->params[ctx->id("TSREG.REGSET")] = std::string("SET");
|
||||
iol->params[ctx->id("IDDRX1_ODDRX1.TRISTATE")] = std::string("ENABLED");
|
||||
}
|
||||
@ -2328,7 +2328,7 @@ struct NexusPacker
|
||||
log_info("Inferring LUT+FF pairs...\n");
|
||||
|
||||
float carry_ratio = 1.0f;
|
||||
if (ctx->settings.find(ctx->id("carry_lutff_ratio")) != ctx->settings.end()) {
|
||||
if (ctx->settings.find(id_carry_lutff_ratio) != ctx->settings.end()) {
|
||||
carry_ratio = ctx->setting<float>("carry_lutff_ratio");
|
||||
}
|
||||
|
||||
@ -2487,7 +2487,7 @@ struct NexusPacker
|
||||
pack_ip();
|
||||
handle_iologic();
|
||||
|
||||
if (!bool_or_default(ctx->settings, ctx->id("no_pack_lutff"))) {
|
||||
if (!bool_or_default(ctx->settings, id_no_pack_lutff)) {
|
||||
pack_lutffs();
|
||||
}
|
||||
|
||||
@ -2500,7 +2500,7 @@ struct NexusPacker
|
||||
bool Arch::pack()
|
||||
{
|
||||
(NexusPacker(getCtx()))();
|
||||
attrs[id("step")] = std::string("pack");
|
||||
attrs[id_step] = std::string("pack");
|
||||
archInfoToAttributes();
|
||||
assignArchInfo();
|
||||
return true;
|
||||
|
@ -148,7 +148,7 @@ struct NexusPostPlaceOpt
|
||||
|
||||
void Arch::post_place_opt()
|
||||
{
|
||||
if (bool_or_default(settings, id("no_post_place_opt")))
|
||||
if (bool_or_default(settings, id_no_post_place_opt))
|
||||
return;
|
||||
log_info("Running post-place optimisations...\n");
|
||||
NexusPostPlaceOpt opt(getCtx());
|
||||
|
Loading…
Reference in New Issue
Block a user