refactor: Use constids instead of id("..")

Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
gatecat 2022-02-16 17:09:54 +00:00
parent 9ef0bc3d3a
commit 76683a1e3c
41 changed files with 2643 additions and 2094 deletions

View File

@ -202,25 +202,25 @@ std::string Arch::get_full_chip_name() const
IdString Arch::archArgsToId(ArchArgs args) const IdString Arch::archArgsToId(ArchArgs args) const
{ {
if (args.type == ArchArgs::LFE5U_12F) if (args.type == ArchArgs::LFE5U_12F)
return id("lfe5u_12f"); return id_lfe5u_12f;
if (args.type == ArchArgs::LFE5U_25F) if (args.type == ArchArgs::LFE5U_25F)
return id("lfe5u_25f"); return id_lfe5u_25f;
if (args.type == ArchArgs::LFE5U_45F) if (args.type == ArchArgs::LFE5U_45F)
return id("lfe5u_45f"); return id_lfe5u_45f;
if (args.type == ArchArgs::LFE5U_85F) if (args.type == ArchArgs::LFE5U_85F)
return id("lfe5u_85f"); return id_lfe5u_85f;
if (args.type == ArchArgs::LFE5UM_25F) if (args.type == ArchArgs::LFE5UM_25F)
return id("lfe5um_25f"); return id_lfe5um_25f;
if (args.type == ArchArgs::LFE5UM_45F) if (args.type == ArchArgs::LFE5UM_45F)
return id("lfe5um_45f"); return id_lfe5um_45f;
if (args.type == ArchArgs::LFE5UM_85F) if (args.type == ArchArgs::LFE5UM_85F)
return id("lfe5um_85f"); return id_lfe5um_85f;
if (args.type == ArchArgs::LFE5UM5G_25F) if (args.type == ArchArgs::LFE5UM5G_25F)
return id("lfe5um5g_25f"); return id_lfe5um5g_25f;
if (args.type == ArchArgs::LFE5UM5G_45F) if (args.type == ArchArgs::LFE5UM5G_45F)
return id("lfe5um5g_45f"); return id_lfe5um5g_45f;
if (args.type == ArchArgs::LFE5UM5G_85F) if (args.type == ArchArgs::LFE5UM5G_85F)
return id("lfe5um5g_85f"); return id_lfe5um5g_85f;
return IdString(); return IdString();
} }
@ -586,7 +586,7 @@ delay_t Arch::getRipupDelayPenalty() const { return 400; }
bool Arch::place() 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") { if (placer == "heap") {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
@ -612,7 +612,7 @@ bool Arch::place()
for (auto &cell : cells) for (auto &cell : cells)
cell.second->belStrength = STRENGTH_LOCKED; cell.second->belStrength = STRENGTH_LOCKED;
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
return true; return true;
@ -620,7 +620,7 @@ bool Arch::place()
bool Arch::route() 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); 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()); 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(); archInfoToAttributes();
return result; 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); 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) || } else if (port == id_DI0 || port == id_DI1 || port == id_CE || port == id_LSR || (sd0 == 0 && port == id_M0) ||
(sd1 == 0 && port == id_M1)) { (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; info.clock_port = id_CLK;
get_setuphold_from_tmg_db(id_SLOGICB, id_CLK, port, info.setup, info.hold); get_setuphold_from_tmg_db(id_SLOGICB, id_CLK, port, info.setup, info.hold);
} else { } 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; info.clock_port = id_CLK;
bool is_path = get_delay_from_tmg_db(id_SLOGICB, id_CLK, port, info.clockToQ); bool is_path = get_delay_from_tmg_db(id_SLOGICB, id_CLK, port, info.clockToQ);
NPNR_ASSERT(is_path); NPNR_ASSERT(is_path);
@ -1070,8 +1070,7 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
} else { } else {
info.clock_port = half_clock; info.clock_port = half_clock;
} }
info.edge = (str_or_default(cell->params, info.clock_port == id_CLKB ? id("CLKBMUX") : id("CLKAMUX"), "CLK") == info.edge = (str_or_default(cell->params, info.clock_port == id_CLKB ? id_CLKBMUX : id_CLKAMUX, "CLK") == "INV")
"INV")
? FALLING_EDGE ? FALLING_EDGE
: RISING_EDGE; : RISING_EDGE;
if (cell->ports.at(port).type == PORT_OUT) { 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; std::vector<std::pair<IdString, std::string>> ret;
auto &wi = loc_info(wire)->wire_data[wire.index]; 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; return ret;
} }

View File

@ -150,7 +150,7 @@ void Arch::permute_luts()
for (auto &cell : cells) { for (auto &cell : cells) {
CellInfo *ci = cell.second.get(); 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, 0);
proc_lut(ci, 1); proc_lut(ci, 1);
} }

View File

@ -723,10 +723,10 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); 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); int bank = ctx->get_pio_bel_bank(ci->bel);
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT"); std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
std::string iotype = str_or_default(ci->attrs, ctx->id("IO_TYPE"), "LVCMOS33"); std::string iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
if (dir != "INPUT" || is_referenced(ioType_from_str(iotype))) { if (dir != "INPUT" || is_referenced(ioType_from_str(iotype))) {
IOVoltage vcc = get_vccio(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)); log_warning("found unplaced cell '%s' during bitstream gen\n", ci->name.c_str(ctx));
} }
BelId bel = ci->bel; BelId bel = ci->bel;
if (ci->type == ctx->id("TRELLIS_SLICE")) { if (ci->type == id_TRELLIS_SLICE) {
pool<IdString> used_phys_pins; pool<IdString> used_phys_pins;
std::string tname = ctx->get_tile_by_type_loc(bel.location.y, bel.location.x, "PLC2"); 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(); 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 lut0_init = int_or_default(ci->params, id_LUT0_INITVAL);
int lut1_init = int_or_default(ci->params, ctx->id("LUT1_INITVAL")); int lut1_init = int_or_default(ci->params, id_LUT1_INITVAL);
cc.tiles[tname].add_word(slice + ".K0.INIT", cc.tiles[tname].add_word(slice + ".K0.INIT",
int_to_bitvector(permute_lut(ctx, ci, used_phys_pins, 0, lut0_init), 16)); int_to_bitvector(permute_lut(ctx, ci, used_phys_pins, 0, lut0_init), 16));
cc.tiles[tname].add_word(slice + ".K1.INIT", cc.tiles[tname].add_word(slice + ".K1.INIT",
int_to_bitvector(permute_lut(ctx, ci, used_phys_pins, 1, lut1_init), 16)); 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 + ".MODE", str_or_default(ci->params, 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 + ".GSR", str_or_default(ci->params, 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 + ".REG0.SD", intstr_or_default(ci->params, 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 + ".REG1.SD", intstr_or_default(ci->params, id_REG1_SD, "0"));
cc.tiles[tname].add_enum(slice + ".REG0.REGSET", cc.tiles[tname].add_enum(slice + ".REG0.REGSET", str_or_default(ci->params, id_REG0_REGSET, "RESET"));
str_or_default(ci->params, ctx->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 + ".REG1.REGSET", cc.tiles[tname].add_enum(slice + ".REG0.LSRMODE", str_or_default(ci->params, id_REG0_LSRMODE, "LSR"));
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET")); cc.tiles[tname].add_enum(slice + ".REG1.LSRMODE", str_or_default(ci->params, id_REG1_LSRMODE, "LSR"));
cc.tiles[tname].add_enum(slice + ".REG0.LSRMODE", cc.tiles[tname].add_enum(slice + ".CEMUX", str_or_default(ci->params, id_CEMUX, "1"));
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"));
if (ci->sliceInfo.using_dff) { if (ci->sliceInfo.using_dff) {
NetInfo *lsrnet = nullptr; NetInfo *lsrnet = nullptr;
if (ci->ports.find(ctx->id("LSR")) != ci->ports.end() && ci->ports.at(ctx->id("LSR")).net != nullptr) if (ci->ports.find(id_LSR) != ci->ports.end() && ci->ports.at(id_LSR).net != nullptr)
lsrnet = ci->ports.at(ctx->id("LSR")).net; lsrnet = ci->ports.at(id_LSR).net;
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR0")) == lsrnet) { if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR0")) == lsrnet) {
cc.tiles[tname].add_enum("LSR0.SRMODE", cc.tiles[tname].add_enum("LSR0.SRMODE", str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, id_LSRMUX, "LSR"));
cc.tiles[tname].add_enum("LSR0.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
} }
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR1")) == lsrnet) { if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "LSR1")) == lsrnet) {
cc.tiles[tname].add_enum("LSR1.SRMODE", cc.tiles[tname].add_enum("LSR1.SRMODE", str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, id_LSRMUX, "LSR"));
cc.tiles[tname].add_enum("LSR1.LSRMUX", str_or_default(ci->params, ctx->id("LSRMUX"), "LSR"));
} }
NetInfo *clknet = nullptr; NetInfo *clknet = nullptr;
if (ci->ports.find(ctx->id("CLK")) != ci->ports.end() && ci->ports.at(ctx->id("CLK")).net != nullptr) if (ci->ports.find(id_CLK) != ci->ports.end() && ci->ports.at(id_CLK).net != nullptr)
clknet = ci->ports.at(ctx->id("CLK")).net; clknet = ci->ports.at(id_CLK).net;
if (ctx->getBoundWireNet(ctx->get_wire_by_loc_basename(bel.location, "CLK0")) == clknet) { 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) { 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", 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", 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 { } else {
// Don't interfere with cascade mux wiring // 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_0", "_NONE_");
cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_1", "_NONE_"); cc.tiles[tname].add_enum(slice + ".CCU2.INJECT1_1", "_NONE_");
} }
if (str_or_default(ci->params, ctx->id("MODE"), "LOGIC") == "DPRAM" && slice == "SLICEA") { if (str_or_default(ci->params, id_MODE, "LOGIC") == "DPRAM" && slice == "SLICEA") {
cc.tiles[tname].add_enum(slice + ".WREMUX", str_or_default(ci->params, ctx->id("WREMUX"), "WRE")); 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; wckmux = (wckmux == "WCK") ? "CLK" : wckmux;
cc.tiles[tname].add_enum("CLK1.CLKMUX", 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 // 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 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 iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT"); std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
std::string pio_tile = get_pio_tile(ctx, bel); std::string pio_tile = get_pio_tile(ctx, bel);
std::string pic_tile = get_pic_tile(ctx, bel); std::string pic_tile = get_pic_tile(ctx, bel);
cc.tiles[pio_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); 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))) { } else if (is_referenced(ioType_from_str(iotype))) {
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE"); cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", "NONE");
} }
if (dir != "INPUT" && if (dir != "INPUT" && (ci->ports.find(id_T) == ci->ports.end() || ci->ports.at(id_T).net == nullptr) &&
(ci->ports.find(ctx->id("T")) == ci->ports.end() || ci->ports.at(ctx->id("T")).net == nullptr) && (ci->ports.find(id_IOLTO) == ci->ports.end() || ci->ports.at(id_IOLTO).net == nullptr)) {
(ci->ports.find(ctx->id("IOLTO")) == ci->ports.end() ||
ci->ports.at(ctx->id("IOLTO")).net == nullptr)) {
// Tie tristate low if unconnected for outputs or bidir // 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())); WireId jpt_wire = ctx->get_wire_by_loc_basename(bel.location, fmt_str("JPADDT" << pio.back()));
PipId jpt_pip = *ctx->getPipsUphill(jpt_wire).begin(); 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)) && if ((dir == "INPUT" || dir == "BIDIR") && !is_differential(ioType_from_str(iotype)) &&
!is_referenced(ioType_from_str(iotype))) { !is_referenced(ioType_from_str(iotype))) {
cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", cc.tiles[pio_tile].add_enum(pio + ".HYSTERESIS", str_or_default(ci->attrs, id_HYSTERESIS, "ON"));
str_or_default(ci->attrs, ctx->id("HYSTERESIS"), "ON"));
} }
if (ci->attrs.count(ctx->id("SLEWRATE")) && !is_referenced(ioType_from_str(iotype))) 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, ctx->id("SLEWRATE"), "SLOW")); cc.tiles[pio_tile].add_enum(pio + ".SLEWRATE", str_or_default(ci->attrs, id_SLEWRATE, "SLOW"));
if (ci->attrs.count(ctx->id("PULLMODE"))) if (ci->attrs.count(id_PULLMODE))
cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", str_or_default(ci->attrs, ctx->id("PULLMODE"), "NONE")); cc.tiles[pio_tile].add_enum(pio + ".PULLMODE", str_or_default(ci->attrs, id_PULLMODE, "NONE"));
if (ci->attrs.count(ctx->id("DIFFRESISTOR"))) if (ci->attrs.count(id_DIFFRESISTOR))
cc.tiles[pio_tile].add_enum(pio + ".DIFFRESISTOR", cc.tiles[pio_tile].add_enum(pio + ".DIFFRESISTOR", str_or_default(ci->attrs, id_DIFFRESISTOR, "OFF"));
str_or_default(ci->attrs, ctx->id("DIFFRESISTOR"), "OFF")); if (ci->attrs.count(id_CLAMP))
if (ci->attrs.count(ctx->id("CLAMP"))) cc.tiles[pio_tile].add_enum(pio + ".CLAMP", str_or_default(ci->attrs, id_CLAMP, "OFF"));
cc.tiles[pio_tile].add_enum(pio + ".CLAMP", str_or_default(ci->attrs, ctx->id("CLAMP"), "OFF"));
if (ci->attrs.count(ctx->id("DRIVE"))) { if (ci->attrs.count(id_DRIVE)) {
static bool drive_3v3_warning_done = false; static bool drive_3v3_warning_done = false;
if (iotype == "LVCMOS33") { 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") { } else if (iotype == "LVCMOS33D") {
if (bel.location.y == 0) { if (bel.location.y == 0) {
// Pseudo differential top IO // Pseudo differential top IO
NPNR_ASSERT(dir == "OUTPUT"); NPNR_ASSERT(dir == "OUTPUT");
NPNR_ASSERT(pio == "PIOA"); NPNR_ASSERT(pio == "PIOA");
std::string cpio_tile = get_comp_pio_tile(ctx, bel); 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[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, ctx->id("DRIVE"), "12")); cc.tiles[cpio_tile].add_enum("PIOB.DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
} else { } else {
std::string other; std::string other;
if (pio == "PIOA") if (pio == "PIOA")
@ -997,9 +987,8 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
other = "PIOD"; other = "PIOD";
else else
log_error("cannot set DRIVE on differential IO at location %s\n", pio.c_str()); 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(pio + ".DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
cc.tiles[pio_tile].add_enum(other + ".DRIVE", cc.tiles[pio_tile].add_enum(other + ".DRIVE", str_or_default(ci->attrs, id_DRIVE, "12"));
str_or_default(ci->attrs, ctx->id("DRIVE"), "12"));
} }
} else { } else {
if (!drive_3v3_warning_done) 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; 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)); auto vccio = get_vccio(ioType_from_str(iotype));
switch (vccio) { switch (vccio) {
case IOVoltage::VCC_1V8: case IOVoltage::VCC_1V8:
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_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; break;
case IOVoltage::VCC_1V5: case IOVoltage::VCC_1V5:
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_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; break;
case IOVoltage::VCC_1V35: case IOVoltage::VCC_1V35:
cc.tiles[pio_tile].add_enum(pio + ".TERMINATION_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; break;
default: default:
log_error("TERMINATION is not supported with Vcc = %s (on PIO %s)\n", log_error("TERMINATION is not supported with Vcc = %s (on PIO %s)\n",
iovoltage_to_str(vccio).c_str(), ci->name.c_str(ctx)); iovoltage_to_str(vccio).c_str(), ci->name.c_str(ctx));
} }
} }
if (ci->attrs.count(ctx->id("OPENDRAIN"))) { if (ci->attrs.count(id_OPENDRAIN)) {
cc.tiles[pio_tile].add_enum(pio + ".OPENDRAIN", str_or_default(ci->attrs, ctx->id("OPENDRAIN"), "OFF")); cc.tiles[pio_tile].add_enum(pio + ".OPENDRAIN", str_or_default(ci->attrs, id_OPENDRAIN, "OFF"));
if (is_differential(ioType_from_str(iotype))) { if (is_differential(ioType_from_str(iotype))) {
std::string other; std::string other;
if (pio == "PIOA") if (pio == "PIOA")
@ -1037,25 +1026,24 @@ void write_bitstream(Context *ctx, std::string base_config_file, std::string tex
other = "PIOD"; other = "PIOD";
else else
log_error("cannot set OPENDRAIN on differential IO at location %s\n", pio.c_str()); log_error("cannot set OPENDRAIN on differential IO at location %s\n", pio.c_str());
cc.tiles[pio_tile].add_enum(other + ".OPENDRAIN", cc.tiles[pio_tile].add_enum(other + ".OPENDRAIN", str_or_default(ci->attrs, id_OPENDRAIN, "OFF"));
str_or_default(ci->attrs, ctx->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") if (datamux_oddr != "PADDO")
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_ODDR", datamux_oddr); 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") if (datamux_oreg != "PADDO")
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_OREG", datamux_oreg); 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") if (datamux_mddr != "PADDO")
cc.tiles[pic_tile].add_enum(pio + ".DATAMUX_MDDR", datamux_mddr); 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") if (trimux_tsreg != "PADDT")
cc.tiles[pic_tile].add_enum(pio + ".TRIMUX_TSREG", trimux_tsreg); cc.tiles[pic_tile].add_enum(pio + ".TRIMUX_TSREG", trimux_tsreg);
} else if (ci->type == ctx->id("DCCA")) { } else if (ci->type == id_DCCA) {
const NetInfo *cen = get_net_or_empty(ci, ctx->id("CE")); const NetInfo *cen = get_net_or_empty(ci, id_CE);
if (cen != nullptr) { if (cen != nullptr) {
std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get(); std::string belname = ctx->loc_info(bel)->bel_data[bel.index].name.get();
Loc loc = ctx->getBelLocation(bel); 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"); tg.config.add_enum(std::string("DCC_") + belname[0] + belname.substr(4) + ".MODE", "DCCA");
cc.tilegroups.push_back(tg); 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::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 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(); 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")); cc.tiles[tile].add_enum(dcs + ".DCSMODE", str_or_default(ci->attrs, id_DCSMODE, "POS"));
} else if (ci->type == ctx->id("DP16KD")) { } else if (ci->type == id_DP16KD) {
TileGroup tg; TileGroup tg;
Loc loc = ctx->getBelLocation(ci->bel); Loc loc = ctx->getBelLocation(ci->bel);
tg.tiles = get_bram_tiles(ctx, 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) { if (ci->ramInfo.is_pdp) {
tg.config.add_enum(ebr + ".MODE", "PDPW16KD"); tg.config.add_enum(ebr + ".MODE", "PDPW16KD");
tg.config.add_enum(ebr + ".PDPW16KD.DATA_WIDTH_R", 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 { } else {
tg.config.add_enum(ebr + ".MODE", "DP16KD"); tg.config.add_enum(ebr + ".MODE", "DP16KD");
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_A", tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_A", intstr_or_default(ci->params, id_DATA_WIDTH_A, "18"));
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, id_DATA_WIDTH_B, "18"));
tg.config.add_enum(ebr + ".DP16KD.DATA_WIDTH_B", tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_A", str_or_default(ci->params, id_WRITEMODE_A, "NORMAL"));
intstr_or_default(ci->params, ctx->id("DATA_WIDTH_B"), "18")); tg.config.add_enum(ebr + ".DP16KD.WRITEMODE_B", str_or_default(ci->params, id_WRITEMODE_B, "NORMAL"));
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"));
} }
auto csd_a = str_to_bitvector(str_or_default(ci->params, ctx->id("CSDECODE_A"), "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, ctx->id("CSDECODE_B"), "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_A", str_or_default(ci->params, 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_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", tg.config.add_enum(ebr + ".ASYNC_RESET_RELEASE",
str_or_default(ci->params, ctx->id("ASYNC_RESET_RELEASE"), "SYNC")); str_or_default(ci->params, id_ASYNC_RESET_RELEASE, "SYNC"));
tg.config.add_enum(ebr + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "DISABLED")); tg.config.add_enum(ebr + ".GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
tg.config.add_word(ebr + ".WID", tg.config.add_word(ebr + ".WID", int_to_bitvector(bit_reverse(int_or_default(ci->attrs, id_WID, 0), 9), 9));
int_to_bitvector(bit_reverse(int_or_default(ci->attrs, ctx->id("WID"), 0), 9), 9));
// Tie signals as appropriate // Tie signals as appropriate
for (auto port : ci->ports) { 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 + ".CLKAMUX", str_or_default(ci->params, id_CLKAMUX, "CLKA"));
tg.config.add_enum(ebr + ".CLKBMUX", str_or_default(ci->params, ctx->id("CLKBMUX"), "CLKB")); 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 + ".RSTAMUX", str_or_default(ci->params, id_RSTAMUX, "RSTA"));
tg.config.add_enum(ebr + ".RSTBMUX", str_or_default(ci->params, ctx->id("RSTBMUX"), "RSTB")); tg.config.add_enum(ebr + ".RSTBMUX", str_or_default(ci->params, id_RSTBMUX, "RSTB"));
if (!ci->ramInfo.is_pdp) { 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 + ".WEAMUX", str_or_default(ci->params, id_WEAMUX, "WEA"));
tg.config.add_enum(ebr + ".WEBMUX", str_or_default(ci->params, ctx->id("WEBMUX"), "WEB")); 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 + ".CEAMUX", str_or_default(ci->params, id_CEAMUX, "CEA"));
tg.config.add_enum(ebr + ".CEBMUX", str_or_default(ci->params, ctx->id("CEBMUX"), "CEB")); 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, ctx->id("OCEAMUX"), "OCEA")); 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, ctx->id("OCEBMUX"), "OCEB")); 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_a.begin(), csd_a.end());
std::reverse(csd_b.begin(), csd_b.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)); NPNR_ASSERT(!cc.bram_data.count(wid));
cc.bram_data[wid] = init_data; cc.bram_data[wid] = init_data;
cc.tilegroups.push_back(tg); 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); Loc loc = ctx->getBelLocation(ci->bel);
tg.tiles = get_dsp_tiles(ctx, ci->bel); tg.tiles = get_dsp_tiles(ctx, ci->bel);
std::string dsp = "MULT18_" + std::to_string(loc.z); std::string dsp = "MULT18_" + std::to_string(loc.z);
tg.config.add_enum(dsp + ".REG_INPUTA_CLK", str_or_default(ci->params, ctx->id("REG_INPUTA_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, ctx->id("REG_INPUTA_CE"), "CE0")); 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, ctx->id("REG_INPUTA_RST"), "RST0")); 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, ctx->id("REG_INPUTB_CLK"), "NONE")); 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, ctx->id("REG_INPUTB_CE"), "CE0")); 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, ctx->id("REG_INPUTB_RST"), "RST0")); 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, ctx->id("REG_INPUTC_CLK"), "NONE")); 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", tg.config.add_enum(dsp + ".REG_PIPELINE_CLK", str_or_default(ci->params, id_REG_PIPELINE_CLK, "NONE"));
str_or_default(ci->params, ctx->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_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, id_REG_PIPELINE_RST, "RST0"));
tg.config.add_enum(dsp + ".REG_PIPELINE_RST", tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, id_REG_OUTPUT_CLK, "NONE"));
str_or_default(ci->params, ctx->id("REG_PIPELINE_RST"), "RST0"));
tg.config.add_enum(dsp + ".REG_OUTPUT_CLK", str_or_default(ci->params, ctx->id("REG_OUTPUT_CLK"), "NONE"));
if (dsp == "MULT18_0" || dsp == "MULT18_4") if (dsp == "MULT18_0" || dsp == "MULT18_4")
tg.config.add_enum(dsp + ".REG_OUTPUT_RST", tg.config.add_enum(dsp + ".REG_OUTPUT_RST", str_or_default(ci->params, id_REG_OUTPUT_RST, "RST0"));
str_or_default(ci->params, ctx->id("REG_OUTPUT_RST"), "RST0"));
tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, ctx->id("CLK0_DIV"), "ENABLED")); tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, 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 + ".CLK1_DIV", str_or_default(ci->params, 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 + ".CLK2_DIV", str_or_default(ci->params, 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 + ".CLK3_DIV", str_or_default(ci->params, id_CLK3_DIV, "ENABLED"));
tg.config.add_enum(dsp + ".GSR", str_or_default(ci->params, ctx->id("GSR"), "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, ctx->id("SOURCEB_MODE"), "B_SHIFT")); 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, ctx->id("RESETMODE"), "SYNC")); tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, id_RESETMODE, "SYNC"));
tg.config.add_enum(dsp + ".MODE", "MULT18X18D"); 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"); tg.config.add_enum(dsp + ".CIBOUT_BYP", "ON");
if (loc.z < 4) 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); Loc loc = ctx->getBelLocation(ci->bel);
tg.tiles = get_dsp_tiles(ctx, ci->bel); tg.tiles = get_dsp_tiles(ctx, ci->bel);
std::string dsp = "ALU54_" + std::to_string(loc.z); std::string dsp = "ALU54_" + std::to_string(loc.z);
tg.config.add_enum(dsp + ".REG_INPUTC0_CLK", tg.config.add_enum(dsp + ".REG_INPUTC0_CLK", str_or_default(ci->params, id_REG_INPUTC0_CLK, "NONE"));
str_or_default(ci->params, ctx->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_INPUTC1_CLK",
str_or_default(ci->params, ctx->id("REG_INPUTC1_CLK"), "NONE"));
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CLK", tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CLK",
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CLK"), "NONE")); str_or_default(ci->params, id_REG_OPCODEOP0_0_CLK, "NONE"));
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE", tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_CE", str_or_default(ci->params, id_REG_OPCODEOP0_0_CE, "CE0"));
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_0_CE"), "CE0"));
tg.config.add_enum(dsp + ".REG_OPCODEOP0_0_RST", 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", 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", 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", tg.config.add_enum(dsp + ".REG_OPCODEOP1_1_CLK",
str_or_default(ci->params, ctx->id("REG_OPCODEOP1_1_CLK"), "NONE")); str_or_default(ci->params, id_REG_OPCODEOP1_1_CLK, "NONE"));
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE", tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_CE", str_or_default(ci->params, id_REG_OPCODEOP0_1_CE, "CE0"));
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_CE"), "CE0"));
tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_RST", tg.config.add_enum(dsp + ".REG_OPCODEOP0_1_RST",
str_or_default(ci->params, ctx->id("REG_OPCODEOP0_1_RST"), "RST0")); str_or_default(ci->params, id_REG_OPCODEOP0_1_RST, "RST0"));
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK", tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CLK", str_or_default(ci->params, id_REG_OPCODEIN_0_CLK, "NONE"));
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, id_REG_OPCODEIN_0_CE, "CE0"));
tg.config.add_enum(dsp + ".REG_OPCODEIN_0_CE", tg.config.add_enum(dsp + ".REG_OPCODEIN_0_RST", str_or_default(ci->params, id_REG_OPCODEIN_0_RST, "RST0"));
str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_CE"), "CE0")); 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_0_RST", tg.config.add_enum(dsp + ".REG_OPCODEIN_1_CE", str_or_default(ci->params, id_REG_OPCODEIN_1_CE, "CE0"));
str_or_default(ci->params, ctx->id("REG_OPCODEIN_0_RST"), "RST0")); 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_OPCODEIN_1_CLK", tg.config.add_enum(dsp + ".REG_OUTPUT0_CLK", str_or_default(ci->params, id_REG_OUTPUT0_CLK, "NONE"));
str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_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_OPCODEIN_1_CE", tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, id_REG_FLAG_CLK, "NONE"));
str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_CE"), "CE0")); tg.config.add_enum(dsp + ".MCPAT_SOURCE", str_or_default(ci->params, id_MCPAT_SOURCE, "STATIC"));
tg.config.add_enum(dsp + ".REG_OPCODEIN_1_RST", tg.config.add_enum(dsp + ".MASKPAT_SOURCE", str_or_default(ci->params, id_MASKPAT_SOURCE, "STATIC"));
str_or_default(ci->params, ctx->id("REG_OPCODEIN_1_RST"), "RST0")); tg.config.add_word(
tg.config.add_enum(dsp + ".REG_OUTPUT0_CLK", dsp + ".MASK01",
str_or_default(ci->params, ctx->id("REG_OUTPUT0_CLK"), "NONE")); parse_init_str(str_or_default(ci->params, id_MASK01, "0x00000000000000"), 56, ci->name.c_str(ctx)));
tg.config.add_enum(dsp + ".REG_OUTPUT1_CLK", tg.config.add_enum(dsp + ".CLK0_DIV", str_or_default(ci->params, id_CLK0_DIV, "ENABLED"));
str_or_default(ci->params, ctx->id("REG_OUTPUT1_CLK"), "NONE")); tg.config.add_enum(dsp + ".CLK1_DIV", str_or_default(ci->params, id_CLK1_DIV, "ENABLED"));
tg.config.add_enum(dsp + ".REG_FLAG_CLK", str_or_default(ci->params, ctx->id("REG_FLAG_CLK"), "NONE")); tg.config.add_enum(dsp + ".CLK2_DIV", str_or_default(ci->params, id_CLK2_DIV, "ENABLED"));
tg.config.add_enum(dsp + ".MCPAT_SOURCE", str_or_default(ci->params, ctx->id("MCPAT_SOURCE"), "STATIC")); tg.config.add_enum(dsp + ".CLK3_DIV", str_or_default(ci->params, id_CLK3_DIV, "ENABLED"));
tg.config.add_enum(dsp + ".MASKPAT_SOURCE", tg.config.add_word(dsp + ".MCPAT", parse_init_str(str_or_default(ci->params, id_MCPAT, "0x00000000000000"),
str_or_default(ci->params, ctx->id("MASKPAT_SOURCE"), "STATIC")); 56, ci->name.c_str(ctx)));
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)));
tg.config.add_word(dsp + ".MASKPAT", 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))); ci->name.c_str(ctx)));
tg.config.add_word(dsp + ".RNDPAT", tg.config.add_word(
parse_init_str(str_or_default(ci->params, ctx->id("RNDPAT"), "0x00000000000000"), 56, dsp + ".RNDPAT",
ci->name.c_str(ctx))); 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, ctx->id("GSR"), "ENABLED")); 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, ctx->id("RESETMODE"), "SYNC")); tg.config.add_enum(dsp + ".RESETMODE", str_or_default(ci->params, id_RESETMODE, "SYNC"));
tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT", tg.config.add_enum(dsp + ".FORCE_ZERO_BARREL_SHIFT",
str_or_default(ci->params, ctx->id("FORCE_ZERO_BARREL_SHIFT"), "DISABLED")); str_or_default(ci->params, id_FORCE_ZERO_BARREL_SHIFT, "DISABLED"));
tg.config.add_enum(dsp + ".LEGACY", str_or_default(ci->params, ctx->id("LEGACY"), "DISABLED")); tg.config.add_enum(dsp + ".LEGACY", str_or_default(ci->params, id_LEGACY, "DISABLED"));
tg.config.add_enum(dsp + ".MODE", "ALU54B"); 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"); tg.config.add_enum("DSP_LEFT.CIBOUT", "ON");
else else
tg.config.add_enum("DSP_RIGHT.CIBOUT", "ON"); 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") { if (dsp == "ALU54_7") {
tg.config.add_enum("MULT18_5.CIBOUT_BYP", "ON"); tg.config.add_enum("MULT18_5.CIBOUT_BYP", "ON");
} else if (dsp == "ALU54_3") { } else if (dsp == "ALU54_3") {
tg.config.add_enum("MULT18_5.CIBOUT_BYP", "ON"); 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") { if (dsp == "ALU54_7") {
tg.config.add_enum("MULT18_4.CIBOUT_BYP", "ON"); tg.config.add_enum("MULT18_4.CIBOUT_BYP", "ON");
} else if (dsp == "ALU54_3") { } 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_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("CLKI_DIV", int_to_bitvector(int_or_default(ci->params, id_CLKI_DIV, 1) - 1, 7));
tg.config.add_word("CLKFB_DIV", tg.config.add_word("CLKFB_DIV", int_to_bitvector(int_or_default(ci->params, id_CLKFB_DIV, 1) - 1, 7));
int_to_bitvector(int_or_default(ci->params, ctx->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("CLKOP_ENABLE", str_or_default(ci->params, id_CLKOP_ENABLE, "ENABLED"));
tg.config.add_enum("CLKOS_ENABLE", str_or_default(ci->params, ctx->id("CLKOS_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, ctx->id("CLKOS2_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, ctx->id("CLKOS3_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"}) { for (std::string out : {"CLKOP", "CLKOS", "CLKOS2", "CLKOS3"}) {
tg.config.add_word(out + "_DIV", 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)); 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("FEEDBK_PATH", str_or_default(ci->params, 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("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")); 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")); 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")); 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")); get_net_or_empty(ci, id_CLKOP) ? "DIVD" : "REFCLK"));
tg.config.add_word("PLL_LOCK_MODE", tg.config.add_word("PLL_LOCK_MODE", int_to_bitvector(int_or_default(ci->params, id_PLL_LOCK_MODE, 0), 3));
int_to_bitvector(int_or_default(ci->params, ctx->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("STDBY_ENABLE", str_or_default(ci->params, id_STDBY_ENABLE, "DISABLED"));
tg.config.add_enum("REFIN_RESET", str_or_default(ci->params, ctx->id("REFIN_RESET"), "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, ctx->id("SYNC_ENABLE"), "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, ctx->id("INT_LOCK_STICKY"), "ENABLED")); 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, ctx->id("DPHASE_SOURCE"), "DISABLED")); 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, ctx->id("PLLRST_ENA"), "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, ctx->id("INTFB_WAKE"), "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("KVCO", int_to_bitvector(int_or_default(ci->attrs, id_KVCO, 0), 3));
tg.config.add_word("LPF_CAPACITOR", tg.config.add_word("LPF_CAPACITOR", int_to_bitvector(int_or_default(ci->attrs, id_LPF_CAPACITOR, 0), 2));
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, id_LPF_RESISTOR, 0), 7));
tg.config.add_word("LPF_RESISTOR", tg.config.add_word("ICP_CURRENT", int_to_bitvector(int_or_default(ci->attrs, id_ICP_CURRENT, 0), 5));
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("FREQ_LOCK_ACCURACY", 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", tg.config.add_word("MFG_GMC_GAIN", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_GAIN, 0), 3));
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, id_MFG_GMC_TEST, 14), 4));
tg.config.add_word("MFG_GMC_TEST", tg.config.add_word("MFG1_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG1_TEST, 0), 3));
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_TEST"), 14), 4)); tg.config.add_word("MFG2_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG2_TEST, 0), 3));
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_FORCE_VFILTER", tg.config.add_word("MFG_FORCE_VFILTER",
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_FORCE_VFILTER"), 0), 1)); int_to_bitvector(int_or_default(ci->attrs, id_MFG_FORCE_VFILTER, 0), 1));
tg.config.add_word("MFG_ICP_TEST", tg.config.add_word("MFG_ICP_TEST", int_to_bitvector(int_or_default(ci->attrs, id_MFG_ICP_TEST, 0), 1));
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, id_MFG_EN_UP, 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, id_MFG_FLOAT_ICP, 0), 1));
tg.config.add_word("MFG_FLOAT_ICP", tg.config.add_word("MFG_GMC_PRESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_PRESET, 0), 1));
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_FLOAT_ICP"), 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_PRESET", tg.config.add_word("MFG_GMC_RESET", int_to_bitvector(int_or_default(ci->attrs, id_MFG_GMC_RESET, 0), 1));
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_GMC_PRESET"), 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_PRESET", tg.config.add_word("MFG_LF_RESGRND", int_to_bitvector(int_or_default(ci->attrs, id_MFG_LF_RESGRND, 0), 1));
int_to_bitvector(int_or_default(ci->attrs, ctx->id("MFG_LF_PRESET"), 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_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));
tg.config.add_word("MFG_ENABLE_FILTEROPAMP", 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); cc.tilegroups.push_back(tg);
} else if (ci->type == id_IOLOGIC || ci->type == id_SIOLOGIC) { } 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) { } else if (ci->type == id_EXTREFB) {
TileGroup tg; TileGroup tg;
tg.tiles = get_dcu_tiles(ctx, ci->bel); tg.tiles = get_dcu_tiles(ctx, ci->bel);
tg.config.add_word( tg.config.add_word("EXTREF.REFCK_DCBIAS_EN",
"EXTREF.REFCK_DCBIAS_EN", parse_config_str(get_or_default(ci->params, id_REFCK_DCBIAS_EN, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("REFCK_DCBIAS_EN"), Property(0)), 1));
tg.config.add_word("EXTREF.REFCK_RTERM", 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", 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); cc.tilegroups.push_back(tg);
} else if (ci->type == id_PCSCLKDIV) { } else if (ci->type == id_PCSCLKDIV) {
Loc loc = ctx->getBelLocation(ci->bel); Loc loc = ctx->getBelLocation(ci->bel);
std::string tname = ctx->get_tile_by_type_loc(loc.y + 1, loc.x, "BMID_0H"); 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), 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) { } else if (ci->type == id_DTR) {
cc.tiles[ctx->get_tile_by_type("DTR")].add_enum("DTR.MODE", "DTR"); cc.tiles[ctx->get_tile_by_type("DTR")].add_enum("DTR.MODE", "DTR");
} else if (ci->type == id_OSCG) { } 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) if (div == 128)
div = 127; div = 127;
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("OSC.DIV", std::to_string(div)); 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"); 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"); cc.tiles[ctx->get_tile_by_type("EFB3_PICB1")].add_enum("CCLK.MODE", "USRMCLK");
} else if (ci->type == id_GSR) { } else if (ci->type == id_GSR) {
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum( cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("GSR.GSRMODE",
"GSR.GSRMODE", str_or_default(ci->params, ctx->id("MODE"), "ACTIVE_LOW")); str_or_default(ci->params, id_MODE, "ACTIVE_LOW"));
cc.tiles[ctx->get_tile_by_type("VIQ_BUF")].add_enum( cc.tiles[ctx->get_tile_by_type("VIQ_BUF")].add_enum("GSR.SYNCMODE",
"GSR.SYNCMODE", str_or_default(ci->params, ctx->id("SYNCMODE"), "ASYNC")); str_or_default(ci->params, id_SYNCMODE, "ASYNC"));
} else if (ci->type == id_JTAGG) { } else if (ci->type == id_JTAGG) {
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum( cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("JTAG.ER1",
"JTAG.ER1", str_or_default(ci->params, ctx->id("ER1"), "ENABLED")); str_or_default(ci->params, id_ER1, "ENABLED"));
cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum( cc.tiles[ctx->get_tile_by_type("EFB0_PICB0")].add_enum("JTAG.ER2",
"JTAG.ER2", str_or_default(ci->params, ctx->id("ER2"), "ENABLED")); str_or_default(ci->params, id_ER2, "ENABLED"));
} else if (ci->type == id_CLKDIVF) { } else if (ci->type == id_CLKDIVF) {
Loc loc = ctx->getBelLocation(ci->bel); Loc loc = ctx->getBelLocation(ci->bel);
bool r = loc.x > 5; bool r = loc.x > 5;
std::string clkdiv = std::string("CLKDIV_") + (r ? "R" : "L") + std::to_string(loc.z); 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")); 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 + ".DIV", str_or_default(ci->params, 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 + ".GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
} else if (ci->type == id_TRELLIS_ECLKBUF) { } else if (ci->type == id_TRELLIS_ECLKBUF) {
} else if (ci->type == id_DQSBUFM) { } else if (ci->type == id_DQSBUFM) {
Loc loc = ctx->getBelLocation(ci->bel); 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, loc.x, pic + "0_DQS2"));
tg.tiles.push_back(ctx->get_tile_by_type_loc(loc.y + 1, loc.x, pic + "1_DQS3")); 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.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_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, ctx->id("DQS_LO_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, ctx->id("DQS_LI_DEL_VAL"), 0); int li_del_value = int_or_default(ci->params, id_DQS_LI_DEL_VAL, 0);
if (str_or_default(ci->params, ctx->id("DQS_LI_DEL_ADJ"), "PLUS") == "MINUS") if (str_or_default(ci->params, id_DQS_LI_DEL_ADJ, "PLUS") == "MINUS")
li_del_value = (256 - li_del_value) & 0xFF; li_del_value = (256 - li_del_value) & 0xFF;
int lo_del_value = int_or_default(ci->params, ctx->id("DQS_LO_DEL_VAL"), 0); int lo_del_value = int_or_default(ci->params, id_DQS_LO_DEL_VAL, 0);
if (str_or_default(ci->params, ctx->id("DQS_LO_DEL_ADJ"), "PLUS") == "MINUS") if (str_or_default(ci->params, id_DQS_LO_DEL_ADJ, "PLUS") == "MINUS")
lo_del_value = (256 - lo_del_value) & 0xFF; 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_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)); 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" ? "YES"
: "NO"); : "NO");
tg.config.add_enum("DQS.DDRDEL", get_net_or_empty(ci, id_DDRDEL) != nullptr ? "DDRDEL" : "0"); 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); cc.tilegroups.push_back(tg);
} else if (ci->type == id_ECLKSYNCB) { } else if (ci->type == id_ECLKSYNCB) {
Loc loc = ctx->getBelLocation(ci->bel); 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"; tiletype += "A";
std::string tile = ctx->get_tile_by_type(tiletype); std::string tile = ctx->get_tile_by_type(tiletype);
cc.tiles[tile].add_enum("DDRDLL.MODE", "DDRDLLA"); 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.GSR", str_or_default(ci->params, id_GSR, "DISABLED"));
cc.tiles[tile].add_enum("DDRDLL.FORCE_MAX_DELAY", cc.tiles[tile].add_enum("DDRDLL.FORCE_MAX_DELAY", str_or_default(ci->params, id_FORCE_MAX_DELAY, "NO"));
str_or_default(ci->params, ctx->id("FORCE_MAX_DELAY"), "NO"));
} else { } else {
NPNR_ASSERT_FALSE("unsupported cell type"); NPNR_ASSERT_FALSE("unsupported cell type");
} }

View File

@ -47,129 +47,129 @@ std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::str
} }
}; };
if (type == ctx->id("TRELLIS_SLICE")) { if (type == id_TRELLIS_SLICE) {
new_cell->params[ctx->id("MODE")] = std::string("LOGIC"); new_cell->params[id_MODE] = std::string("LOGIC");
new_cell->params[ctx->id("GSR")] = std::string("DISABLED"); new_cell->params[id_GSR] = std::string("DISABLED");
new_cell->params[ctx->id("SRMODE")] = std::string("LSR_OVER_CE"); new_cell->params[id_SRMODE] = std::string("LSR_OVER_CE");
new_cell->params[ctx->id("CEMUX")] = std::string("1"); new_cell->params[id_CEMUX] = std::string("1");
new_cell->params[ctx->id("CLKMUX")] = std::string("CLK"); new_cell->params[id_CLKMUX] = std::string("CLK");
new_cell->params[ctx->id("LSRMUX")] = std::string("LSR"); new_cell->params[id_LSRMUX] = std::string("LSR");
new_cell->params[ctx->id("LUT0_INITVAL")] = Property(0, 16); new_cell->params[id_LUT0_INITVAL] = Property(0, 16);
new_cell->params[ctx->id("LUT1_INITVAL")] = Property(0, 16); new_cell->params[id_LUT1_INITVAL] = Property(0, 16);
new_cell->params[ctx->id("REG0_SD")] = std::string("0"); new_cell->params[id_REG0_SD] = std::string("0");
new_cell->params[ctx->id("REG1_SD")] = std::string("0"); new_cell->params[id_REG1_SD] = std::string("0");
new_cell->params[ctx->id("REG0_REGSET")] = std::string("RESET"); new_cell->params[id_REG0_REGSET] = std::string("RESET");
new_cell->params[ctx->id("REG1_REGSET")] = std::string("RESET"); new_cell->params[id_REG1_REGSET] = std::string("RESET");
new_cell->params[ctx->id("CCU2_INJECT1_0")] = std::string("NO"); new_cell->params[id_CCU2_INJECT1_0] = std::string("NO");
new_cell->params[ctx->id("CCU2_INJECT1_1")] = std::string("NO"); new_cell->params[id_CCU2_INJECT1_1] = std::string("NO");
new_cell->params[ctx->id("WREMUX")] = std::string("WRE"); new_cell->params[id_WREMUX] = std::string("WRE");
new_cell->addInput(ctx->id("A0")); new_cell->addInput(id_A0);
new_cell->addInput(ctx->id("B0")); new_cell->addInput(id_B0);
new_cell->addInput(ctx->id("C0")); new_cell->addInput(id_C0);
new_cell->addInput(ctx->id("D0")); new_cell->addInput(id_D0);
new_cell->addInput(ctx->id("A1")); new_cell->addInput(id_A1);
new_cell->addInput(ctx->id("B1")); new_cell->addInput(id_B1);
new_cell->addInput(ctx->id("C1")); new_cell->addInput(id_C1);
new_cell->addInput(ctx->id("D1")); new_cell->addInput(id_D1);
new_cell->addInput(ctx->id("M0")); new_cell->addInput(id_M0);
new_cell->addInput(ctx->id("M1")); new_cell->addInput(id_M1);
new_cell->addInput(ctx->id("FCI")); new_cell->addInput(id_FCI);
new_cell->addInput(ctx->id("FXA")); new_cell->addInput(id_FXA);
new_cell->addInput(ctx->id("FXB")); new_cell->addInput(id_FXB);
new_cell->addInput(ctx->id("CLK")); new_cell->addInput(id_CLK);
new_cell->addInput(ctx->id("LSR")); new_cell->addInput(id_LSR);
new_cell->addInput(ctx->id("CE")); new_cell->addInput(id_CE);
new_cell->addInput(ctx->id("DI0")); new_cell->addInput(id_DI0);
new_cell->addInput(ctx->id("DI1")); new_cell->addInput(id_DI1);
new_cell->addInput(ctx->id("WD0")); new_cell->addInput(id_WD0);
new_cell->addInput(ctx->id("WD1")); new_cell->addInput(id_WD1);
new_cell->addInput(ctx->id("WAD0")); new_cell->addInput(id_WAD0);
new_cell->addInput(ctx->id("WAD1")); new_cell->addInput(id_WAD1);
new_cell->addInput(ctx->id("WAD2")); new_cell->addInput(id_WAD2);
new_cell->addInput(ctx->id("WAD3")); new_cell->addInput(id_WAD3);
new_cell->addInput(ctx->id("WRE")); new_cell->addInput(id_WRE);
new_cell->addInput(ctx->id("WCK")); new_cell->addInput(id_WCK);
new_cell->addOutput(ctx->id("F0")); new_cell->addOutput(id_F0);
new_cell->addOutput(ctx->id("Q0")); new_cell->addOutput(id_Q0);
new_cell->addOutput(ctx->id("F1")); new_cell->addOutput(id_F1);
new_cell->addOutput(ctx->id("Q1")); new_cell->addOutput(id_Q1);
new_cell->addOutput(ctx->id("FCO")); new_cell->addOutput(id_FCO);
new_cell->addOutput(ctx->id("OFX0")); new_cell->addOutput(id_OFX0);
new_cell->addOutput(ctx->id("OFX1")); new_cell->addOutput(id_OFX1);
new_cell->addOutput(ctx->id("WDO0")); new_cell->addOutput(id_WDO0);
new_cell->addOutput(ctx->id("WDO1")); new_cell->addOutput(id_WDO1);
new_cell->addOutput(ctx->id("WDO2")); new_cell->addOutput(id_WDO2);
new_cell->addOutput(ctx->id("WDO3")); new_cell->addOutput(id_WDO3);
new_cell->addOutput(ctx->id("WADO0")); new_cell->addOutput(id_WADO0);
new_cell->addOutput(ctx->id("WADO1")); new_cell->addOutput(id_WADO1);
new_cell->addOutput(ctx->id("WADO2")); new_cell->addOutput(id_WADO2);
new_cell->addOutput(ctx->id("WADO3")); new_cell->addOutput(id_WADO3);
} else if (type == ctx->id("TRELLIS_IO")) { } else if (type == id_TRELLIS_IO) {
new_cell->params[ctx->id("DIR")] = std::string("INPUT"); 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->params[ctx->id("DATAMUX_ODDR")] = std::string("PADDO"); new_cell->params[id_DATAMUX_ODDR] = std::string("PADDO");
new_cell->params[ctx->id("DATAMUX_MDDR")] = std::string("PADDO"); new_cell->params[id_DATAMUX_MDDR] = std::string("PADDO");
new_cell->addInout(ctx->id("B")); new_cell->addInout(id_B);
new_cell->addInput(ctx->id("I")); new_cell->addInput(id_I);
new_cell->addInput(ctx->id("T")); new_cell->addInput(id_T);
new_cell->addOutput(ctx->id("O")); new_cell->addOutput(id_O);
new_cell->addInput(ctx->id("IOLDO")); new_cell->addInput(id_IOLDO);
new_cell->addInput(ctx->id("IOLTO")); new_cell->addInput(id_IOLTO);
} else if (type == ctx->id("LUT4")) { } else if (type == id_LUT4) {
new_cell->params[ctx->id("INIT")] = Property(0, 16); new_cell->params[id_INIT] = Property(0, 16);
new_cell->addInput(ctx->id("A")); new_cell->addInput(id_A);
new_cell->addInput(ctx->id("B")); new_cell->addInput(id_B);
new_cell->addInput(ctx->id("C")); new_cell->addInput(id_C);
new_cell->addInput(ctx->id("D")); new_cell->addInput(id_D);
new_cell->addOutput(ctx->id("Z")); new_cell->addOutput(id_Z);
} else if (type == ctx->id("CCU2C")) { } else if (type == id_CCU2C) {
new_cell->params[ctx->id("INIT0")] = Property(0, 16); new_cell->params[id_INIT0] = Property(0, 16);
new_cell->params[ctx->id("INIT1")] = Property(0, 16); new_cell->params[id_INIT1] = Property(0, 16);
new_cell->params[ctx->id("INJECT1_0")] = std::string("YES"); new_cell->params[id_INJECT1_0] = std::string("YES");
new_cell->params[ctx->id("INJECT1_1")] = 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(id_A0);
new_cell->addInput(ctx->id("B0")); new_cell->addInput(id_B0);
new_cell->addInput(ctx->id("C0")); new_cell->addInput(id_C0);
new_cell->addInput(ctx->id("D0")); new_cell->addInput(id_D0);
new_cell->addInput(ctx->id("A1")); new_cell->addInput(id_A1);
new_cell->addInput(ctx->id("B1")); new_cell->addInput(id_B1);
new_cell->addInput(ctx->id("C1")); new_cell->addInput(id_C1);
new_cell->addInput(ctx->id("D1")); new_cell->addInput(id_D1);
new_cell->addOutput(ctx->id("S0")); new_cell->addOutput(id_S0);
new_cell->addOutput(ctx->id("S1")); new_cell->addOutput(id_S1);
new_cell->addOutput(ctx->id("COUT")); new_cell->addOutput(id_COUT);
} else if (type == ctx->id("DCCA")) { } else if (type == id_DCCA) {
new_cell->addInput(ctx->id("CLKI")); new_cell->addInput(id_CLKI);
new_cell->addOutput(ctx->id("CLKO")); new_cell->addOutput(id_CLKO);
new_cell->addInput(ctx->id("CE")); new_cell->addInput(id_CE);
} else if (type == id_IOLOGIC || type == id_SIOLOGIC) { } else if (type == id_IOLOGIC || type == id_SIOLOGIC) {
new_cell->params[ctx->id("MODE")] = std::string("NONE"); new_cell->params[id_MODE] = std::string("NONE");
new_cell->params[ctx->id("GSR")] = std::string("DISABLED"); new_cell->params[id_GSR] = std::string("DISABLED");
new_cell->params[ctx->id("CLKIMUX")] = std::string("CLK"); new_cell->params[id_CLKIMUX] = std::string("CLK");
new_cell->params[ctx->id("CLKOMUX")] = std::string("CLK"); new_cell->params[id_CLKOMUX] = std::string("CLK");
new_cell->params[ctx->id("LSRIMUX")] = std::string("0"); new_cell->params[id_LSRIMUX] = std::string("0");
new_cell->params[ctx->id("LSROMUX")] = std::string("0"); new_cell->params[id_LSROMUX] = std::string("0");
new_cell->params[ctx->id("LSRMUX")] = std::string("LSR"); new_cell->params[id_LSRMUX] = std::string("LSR");
new_cell->params[ctx->id("DELAY.OUTDEL")] = std::string("DISABLED"); new_cell->params[ctx->id("DELAY.OUTDEL")] = std::string("DISABLED");
new_cell->params[ctx->id("DELAY.DEL_VALUE")] = Property(0, 7); 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("MODDRX.MODE")] = std::string("NONE");
new_cell->params[ctx->id("MTDDRX.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.DQSW_INVERT")] = std::string("DISABLED");
new_cell->params[ctx->id("MTDDRX.REGSET")] = std::string("RESET"); 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 // Just copy ports from the Bel
copy_bel_ports(); copy_bel_ports();
} else if (type == id_TRELLIS_ECLKBUF) { } else if (type == id_TRELLIS_ECLKBUF) {
new_cell->addInput(ctx->id("ECLKI")); new_cell->addInput(id_ECLKI);
new_cell->addOutput(ctx->id("ECLKO")); new_cell->addOutput(id_ECLKO);
} else { } else {
log_error("unable to create ECP5 cell of type %s", type.c_str(ctx)); 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()) if (lc->hierpath == IdString())
lc->hierpath = ff->hierpath; 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); 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, id_SRMODE, str_or_default(ff->params, 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, id_GSR, str_or_default(ff->params, 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, id_CEMUX, str_or_default(ff->params, 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, id_LSRMUX, str_or_default(ff->params, 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_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 + "_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 + "_REGSET")] = str_or_default(ff->params, id_REGSET, "RESET");
lc->params[ctx->id(reg + "_LSRMODE")] = str_or_default(ff->params, ctx->id("LSRMODE"), "LSR"); lc->params[ctx->id(reg + "_LSRMODE")] = str_or_default(ff->params, id_LSRMODE, "LSR");
replace_port_safe(has_ff, ff, ctx->id("CLK"), lc, ctx->id("CLK")); replace_port_safe(has_ff, ff, id_CLK, lc, id_CLK);
if (ff->ports.find(ctx->id("LSR")) != ff->ports.end()) if (ff->ports.find(id_LSR) != ff->ports.end())
replace_port_safe(has_ff, ff, ctx->id("LSR"), lc, ctx->id("LSR")); replace_port_safe(has_ff, ff, id_LSR, lc, id_LSR);
if (ff->ports.find(ctx->id("CE")) != ff->ports.end()) if (ff->ports.find(id_CE) != ff->ports.end())
replace_port_safe(has_ff, ff, ctx->id("CE"), lc, ctx->id("CE")); 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))); replace_port(ff, id_Q, lc, ctx->id("Q" + std::to_string(index)));
if (get_net_or_empty(ff, ctx->id("M")) != nullptr) { if (get_net_or_empty(ff, id_M) != nullptr) {
// PRLD FFs that use both M and DI // PRLD FFs that use both M and DI
NPNR_ASSERT(!driven_by_lut); NPNR_ASSERT(!driven_by_lut);
// As M is used; must route DI through a new 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(reg + "_SD")] = std::string("1");
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = Property(0xFF00, 16); 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, 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_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))); connect_ports(ctx, lc, ctx->id("F" + std::to_string(index)), lc, ctx->id("DI" + std::to_string(index)));
} else { } else {
if (driven_by_lut) { 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 { } 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()) if (lc->hierpath == IdString())
lc->hierpath = lut->hierpath; lc->hierpath = lut->hierpath;
lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] = lc->params[ctx->id("LUT" + std::to_string(index) + "_INITVAL")] =
get_or_default(lut->params, ctx->id("INIT"), Property(0, 16)); get_or_default(lut->params, id_INIT, Property(0, 16));
replace_port(lut, ctx->id("A"), lc, ctx->id("A" + std::to_string(index))); replace_port(lut, 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, 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, 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, id_D, lc, ctx->id("D" + std::to_string(index)));
replace_port(lut, ctx->id("Z"), lc, ctx->id("F" + 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) void ccu2c_to_slice(Context *ctx, CellInfo *ccu, CellInfo *lc)
{ {
if (lc->hierpath == IdString()) if (lc->hierpath == IdString())
lc->hierpath = ccu->hierpath; lc->hierpath = ccu->hierpath;
lc->params[ctx->id("MODE")] = std::string("CCU2"); lc->params[id_MODE] = std::string("CCU2");
lc->params[ctx->id("LUT0_INITVAL")] = get_or_default(ccu->params, ctx->id("INIT0"), Property(0, 16)); lc->params[id_LUT0_INITVAL] = get_or_default(ccu->params, 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_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[id_CCU2_INJECT1_0] = str_or_default(ccu->params, 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_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, id_A0, lc, id_A0);
replace_port(ccu, ctx->id("B0"), lc, ctx->id("B0")); replace_port(ccu, id_B0, lc, id_B0);
replace_port(ccu, ctx->id("C0"), lc, ctx->id("C0")); replace_port(ccu, id_C0, lc, id_C0);
replace_port(ccu, ctx->id("D0"), lc, ctx->id("D0")); replace_port(ccu, id_D0, lc, id_D0);
replace_port(ccu, ctx->id("A1"), lc, ctx->id("A1")); replace_port(ccu, id_A1, lc, id_A1);
replace_port(ccu, ctx->id("B1"), lc, ctx->id("B1")); replace_port(ccu, id_B1, lc, id_B1);
replace_port(ccu, ctx->id("C1"), lc, ctx->id("C1")); replace_port(ccu, id_C1, lc, id_C1);
replace_port(ccu, ctx->id("D1"), lc, ctx->id("D1")); replace_port(ccu, id_D1, lc, id_D1);
replace_port(ccu, ctx->id("S0"), lc, ctx->id("F0")); replace_port(ccu, id_S0, lc, id_F0);
replace_port(ccu, ctx->id("S1"), lc, ctx->id("F1")); 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) void dram_to_ramw(Context *ctx, CellInfo *ram, CellInfo *lc)
{ {
if (lc->hierpath == IdString()) if (lc->hierpath == IdString())
lc->hierpath = ram->hierpath; lc->hierpath = ram->hierpath;
lc->params[ctx->id("MODE")] = std::string("RAMW"); lc->params[id_MODE] = std::string("RAMW");
replace_port(ram, ctx->id("WAD[0]"), lc, ctx->id("D0")); replace_port(ram, ctx->id("WAD[0]"), lc, id_D0);
replace_port(ram, ctx->id("WAD[1]"), lc, ctx->id("B0")); replace_port(ram, ctx->id("WAD[1]"), lc, id_B0);
replace_port(ram, ctx->id("WAD[2]"), lc, ctx->id("C0")); replace_port(ram, ctx->id("WAD[2]"), lc, id_C0);
replace_port(ram, ctx->id("WAD[3]"), lc, ctx->id("A0")); 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[0]"), lc, id_C1);
replace_port(ram, ctx->id("DI[1]"), lc, ctx->id("A1")); replace_port(ram, ctx->id("DI[1]"), lc, id_A1);
replace_port(ram, ctx->id("DI[2]"), lc, ctx->id("D1")); replace_port(ram, ctx->id("DI[2]"), lc, id_D1);
replace_port(ram, ctx->id("DI[3]"), lc, ctx->id("B1")); replace_port(ram, ctx->id("DI[3]"), lc, id_B1);
} }
static unsigned get_dram_init(const Context *ctx, const CellInfo *ram, int bit) 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); NPNR_ASSERT(!init_prop.is_string);
const std::string &idata = init_prop.str; const std::string &idata = init_prop.str;
NPNR_ASSERT(idata.length() == 64); 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()) if (lc->hierpath == IdString())
lc->hierpath = ram->hierpath; lc->hierpath = ram->hierpath;
lc->params[ctx->id("MODE")] = std::string("DPRAM"); lc->params[id_MODE] = std::string("DPRAM");
lc->params[ctx->id("WREMUX")] = str_or_default(ram->params, ctx->id("WREMUX"), "WRE"); lc->params[id_WREMUX] = str_or_default(ram->params, id_WREMUX, "WRE");
lc->params[ctx->id("WCKMUX")] = str_or_default(ram->params, ctx->id("WCKMUX"), "WCK"); lc->params[id_WCKMUX] = str_or_default(ram->params, id_WCKMUX, "WCK");
unsigned permuted_init0 = 0, permuted_init1 = 0; 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); 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); permuted_init1 |= (1 << i);
} }
lc->params[ctx->id("LUT0_INITVAL")] = Property(permuted_init0, 16); lc->params[id_LUT0_INITVAL] = Property(permuted_init0, 16);
lc->params[ctx->id("LUT1_INITVAL")] = Property(permuted_init1, 16); lc->params[id_LUT1_INITVAL] = Property(permuted_init1, 16);
if (ram->ports.count(ctx->id("RAD[0]"))) { 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, 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_D1);
} }
if (ram->ports.count(ctx->id("RAD[1]"))) { 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, 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_B1);
} }
if (ram->ports.count(ctx->id("RAD[2]"))) { 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, 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_C1);
} }
if (ram->ports.count(ctx->id("RAD[3]"))) { 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, 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_A1);
} }
if (ram->ports.count(ctx->id("WRE"))) if (ram->ports.count(id_WRE))
connect_port(ctx, ram->ports.at(ctx->id("WRE")).net, lc, ctx->id("WRE")); connect_port(ctx, ram->ports.at(id_WRE).net, lc, id_WRE);
if (ram->ports.count(ctx->id("WCK"))) if (ram->ports.count(id_WCK))
connect_port(ctx, ram->ports.at(ctx->id("WCK")).net, lc, ctx->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_WADO0, lc, id_WAD0);
connect_ports(ctx, ramw, id_WADO1, lc, id_WAD1); 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) pool<IdString> &todelete_cells)
{ {
if (nxio->type == ctx->id("$nextpnr_ibuf")) { if (nxio->type == ctx->id("$nextpnr_ibuf")) {
trio->params[ctx->id("DIR")] = std::string("INPUT"); trio->params[id_DIR] = std::string("INPUT");
replace_port(nxio, ctx->id("O"), trio, ctx->id("O")); replace_port(nxio, id_O, trio, id_O);
} else if (nxio->type == ctx->id("$nextpnr_obuf")) { } else if (nxio->type == ctx->id("$nextpnr_obuf")) {
trio->params[ctx->id("DIR")] = std::string("OUTPUT"); trio->params[id_DIR] = std::string("OUTPUT");
replace_port(nxio, ctx->id("I"), trio, ctx->id("I")); replace_port(nxio, id_I, trio, id_I);
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) { } else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
// N.B. tristate will be dealt with below // 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) if (i == nullptr || i->driver.cell == nullptr)
trio->params[ctx->id("DIR")] = std::string("INPUT"); trio->params[id_DIR] = std::string("INPUT");
else { else {
log_info("%s: %s.%s\n", ctx->nameOf(i), ctx->nameOf(i->driver.cell), ctx->nameOf(i->driver.port)); 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, id_I, trio, id_I);
replace_port(nxio, ctx->id("O"), trio, ctx->id("O")); replace_port(nxio, id_O, trio, id_O);
} else { } else {
NPNR_ASSERT(false); 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 // Rename I/O nets to avoid conflicts
if (donet != nullptr && donet->name == nxio->name) 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); ctx->net_aliases.erase(tn_netname);
NetInfo *toplevel_net = ctx->createNet(tn_netname); NetInfo *toplevel_net = ctx->createNet(tn_netname);
toplevel_net->name = 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; ctx->ports[nxio->name].net = toplevel_net;
} }
CellInfo *tbuf = net_driven_by( CellInfo *tbuf = net_driven_by(
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); }, ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
ctx->id("Y")); id_Y);
if (tbuf) { 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 // 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"); std::unique_ptr<CellInfo> inv_lut = create_ecp5_cell(ctx, id_LUT4, trio->name.str(ctx) + "$invert_T");
replace_port(tbuf, ctx->id("E"), inv_lut.get(), ctx->id("A")); replace_port(tbuf, id_E, inv_lut.get(), id_A);
inv_lut->params[ctx->id("INIT")] = Property(21845, 16); inv_lut->params[id_INIT] = Property(21845, 16);
connect_ports(ctx, inv_lut.get(), ctx->id("Z"), trio, ctx->id("T")); connect_ports(ctx, inv_lut.get(), id_Z, trio, id_T);
created_cells.push_back(std::move(inv_lut)); created_cells.push_back(std::move(inv_lut));
if (donet->users.size() > 1) { if (donet->users.size() > 1) {

View File

@ -30,37 +30,36 @@ NEXTPNR_NAMESPACE_BEGIN
std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::string name = ""); std::unique_ptr<CellInfo> create_ecp5_cell(Context *ctx, IdString type, std::string name = "");
// Return true if a cell is a LUT // 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 // 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) 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") || return cell->type == id_IDDRX1F || cell->type == id_IDDRX2F || cell->type == id_IDDR71B ||
cell->type == ctx->id("IDDRX2DQA") || cell->type == id_IDDRX2DQA ||
(cell->type == ctx->id("TRELLIS_FF") && bool_or_default(cell->attrs, ctx->id("syn_useioff")) && (cell->type == id_TRELLIS_FF && bool_or_default(cell->attrs, id_syn_useioff) &&
(str_or_default(cell->attrs, ctx->id("ioff_dir"), "") != "output")); (str_or_default(cell->attrs, id_ioff_dir, "") != "output"));
} }
inline bool is_iologic_output_cell(const BaseCtx *ctx, const CellInfo *cell) 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") || return cell->type == id_ODDRX1F || cell->type == id_ODDRX2F || cell->type == id_ODDR71B ||
cell->type == ctx->id("ODDRX2DQA") || cell->type == ctx->id("ODDRX2DQSB") || cell->type == id_ODDRX2DQA || cell->type == id_ODDRX2DQSB || cell->type == id_OSHX2A ||
cell->type == ctx->id("OSHX2A") || (cell->type == id_TRELLIS_FF && bool_or_default(cell->attrs, id_syn_useioff) &&
(cell->type == ctx->id("TRELLIS_FF") && bool_or_default(cell->attrs, ctx->id("syn_useioff")) && (str_or_default(cell->attrs, id_ioff_dir, "") != "input"));
(str_or_default(cell->attrs, ctx->id("ioff_dir"), "") != "input"));
} }
void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut); void ff_to_slice(Context *ctx, CellInfo *ff, CellInfo *lc, int index, bool driven_by_lut);

View File

@ -1341,3 +1341,513 @@ X(IOLOGIC_MODE_TSREG)
X(DCSC) X(DCSC)
X(DCSOUT) X(DCSOUT)
X(MODESEL) 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)

View File

@ -1,504 +1,424 @@
tg.config.add_word("DCU.CH0_AUTO_CALIB_EN", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", tg.config.add_word("DCU.CH0_CTC_BYPASS",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_CTC_BYPASS"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH0_CTC_BYPASS, Property(0)), 1));
tg.config.add_word("DCU.CH0_DCOATDCFG", tg.config.add_word("DCU.CH0_DCOATDCFG", parse_config_str(get_or_default(ci->params, id_CH0_DCOATDCFG, Property(0)), 2));
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, id_CH0_DCOATDDLY, 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));
tg.config.add_word("DCU.CH0_DCOBYPSATD", tg.config.add_word("DCU.CH0_DCOBYPSATD",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOBYPSATD"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH0_DCOBYPSATD, Property(0)), 1));
tg.config.add_word("DCU.CH0_DCOCALDIV", tg.config.add_word("DCU.CH0_DCOCALDIV", parse_config_str(get_or_default(ci->params, id_CH0_DCOCALDIV, Property(0)), 3));
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, id_CH0_DCOCTLGI, 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));
tg.config.add_word("DCU.CH0_DCODISBDAVOID", tg.config.add_word("DCU.CH0_DCODISBDAVOID",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCODISBDAVOID"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH0_DCODISBDAVOID, Property(0)), 1));
tg.config.add_word("DCU.CH0_DCOFLTDAC", tg.config.add_word("DCU.CH0_DCOFLTDAC", parse_config_str(get_or_default(ci->params, id_CH0_DCOFLTDAC, Property(0)), 2));
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, id_CH0_DCOFTNRG, Property(0)), 3));
tg.config.add_word("DCU.CH0_DCOFTNRG",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOFTNRG"), Property(0)), 3));
tg.config.add_word("DCU.CH0_DCOIOSTUNE", tg.config.add_word("DCU.CH0_DCOIOSTUNE",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOIOSTUNE"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH0_DCOIOSTUNE, Property(0)), 3));
tg.config.add_word("DCU.CH0_DCOITUNE", tg.config.add_word("DCU.CH0_DCOITUNE", parse_config_str(get_or_default(ci->params, id_CH0_DCOITUNE, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOITUNE"), Property(0)), 2));
tg.config.add_word("DCU.CH0_DCOITUNE4LSB", 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", 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", tg.config.add_word("DCU.CH0_DCONUOFLSB",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCONUOFLSB"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH0_DCONUOFLSB, Property(0)), 3));
tg.config.add_word("DCU.CH0_DCOSCALEI", tg.config.add_word("DCU.CH0_DCOSCALEI", parse_config_str(get_or_default(ci->params, id_CH0_DCOSCALEI, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSCALEI"), Property(0)), 2));
tg.config.add_word("DCU.CH0_DCOSTARTVAL", tg.config.add_word("DCU.CH0_DCOSTARTVAL",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSTARTVAL"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH0_DCOSTARTVAL, Property(0)), 3));
tg.config.add_word("DCU.CH0_DCOSTEP", tg.config.add_word("DCU.CH0_DCOSTEP", parse_config_str(get_or_default(ci->params, id_CH0_DCOSTEP, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_DCOSTEP"), Property(0)), 2));
tg.config.add_word("DCU.CH0_DEC_BYPASS", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_GE_AN_ENABLE, Property(0)), 1));
tg.config.add_word("DCU.CH0_INVERT_RX", tg.config.add_word("DCU.CH0_INVERT_RX", parse_config_str(get_or_default(ci->params, id_CH0_INVERT_RX, Property(0)), 1));
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, id_CH0_INVERT_TX, 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));
tg.config.add_word("DCU.CH0_LDR_CORE2TX_SEL", 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", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_PCIE_EI_EN, Property(0)), 1));
tg.config.add_word("DCU.CH0_PCIE_MODE", tg.config.add_word("DCU.CH0_PCIE_MODE", parse_config_str(get_or_default(ci->params, id_CH0_PCIE_MODE, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PCIE_MODE"), Property(0)), 1));
tg.config.add_word("DCU.CH0_PCS_DET_TIME_SEL", 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)); 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", tg.config.add_word("DCU.CH0_PDEN_SEL", parse_config_str(get_or_default(ci->params, id_CH0_PDEN_SEL, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PDEN_SEL"), Property(0)), 1));
tg.config.add_word("DCU.CH0_PRBS_ENABLE", tg.config.add_word("DCU.CH0_PRBS_ENABLE",
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PRBS_ENABLE"), 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", tg.config.add_word("DCU.CH0_PRBS_LOCK", parse_config_str(get_or_default(ci->params, id_CH0_PRBS_LOCK, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_PRBS_LOCK"), Property(0)), 1));
tg.config.add_word("DCU.CH0_PRBS_SELECTION", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_REG_IDAC_SEL, Property(0)), 10));
tg.config.add_word("DCU.CH0_REQ_EN", tg.config.add_word("DCU.CH0_REQ_EN", parse_config_str(get_or_default(ci->params, id_CH0_REQ_EN, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_REQ_EN"), Property(0)), 1));
tg.config.add_word("DCU.CH0_REQ_LVL_SET", 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)); parse_config_str(get_or_default(ci->params, id_CH0_REQ_LVL_SET, Property(0)), 2));
tg.config.add_word("DCU.CH0_RIO_MODE", tg.config.add_word("DCU.CH0_RIO_MODE", parse_config_str(get_or_default(ci->params, id_CH0_RIO_MODE, Property(0)), 1));
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, id_CH0_RLOS_SEL, Property(0)), 1));
tg.config.add_word("DCU.CH0_RLOS_SEL", tg.config.add_word("DCU.CH0_RPWDNB", parse_config_str(get_or_default(ci->params, id_CH0_RPWDNB, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RLOS_SEL"), 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_RPWDNB", tg.config.add_word("DCU.CH0_RTERM_TX", parse_config_str(get_or_default(ci->params, id_CH0_RTERM_TX, Property(0)), 5));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RPWDNB"), Property(0)), 1)); 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_RTERM_RX", tg.config.add_word("DCU.CH0_RXTERM_CM", parse_config_str(get_or_default(ci->params, id_CH0_RXTERM_CM, Property(0)), 2));
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));
tg.config.add_word("DCU.CH0_RX_DCO_CK_DIV", 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", 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", 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", 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", 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)); 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", 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));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_RX_LOS_EN"), Property(0)), 1));
tg.config.add_word("DCU.CH0_RX_LOS_HYST_EN", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_RX_SB_BYPASS, Property(0)), 1));
tg.config.add_word("DCU.CH0_SB_BYPASS", tg.config.add_word("DCU.CH0_SB_BYPASS", parse_config_str(get_or_default(ci->params, id_CH0_SB_BYPASS, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_SB_BYPASS"), Property(0)), 1));
tg.config.add_word("DCU.CH0_SEL_SD_RX_CLK", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_TDRV_SLICE5_SEL, Property(0)), 2));
tg.config.add_word("DCU.CH0_TPWDNB", tg.config.add_word("DCU.CH0_TPWDNB", parse_config_str(get_or_default(ci->params, id_CH0_TPWDNB, Property(0)), 1));
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, id_CH0_TX_CM_SEL, Property(0)), 2));
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));
tg.config.add_word("DCU.CH0_TX_DIV11_SEL", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_TX_PRE_SIGN, Property(0)), 1));
tg.config.add_word("DCU.CH0_UC_MODE", tg.config.add_word("DCU.CH0_UC_MODE", parse_config_str(get_or_default(ci->params, id_CH0_UC_MODE, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH0_UC_MODE"), Property(0)), 1));
tg.config.add_word("DCU.CH0_UDF_COMMA_A", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH0_UDF_COMMA_MASK, Property(0)), 10));
tg.config.add_word("DCU.CH0_WA_BYPASS", tg.config.add_word("DCU.CH0_WA_BYPASS", parse_config_str(get_or_default(ci->params, id_CH0_WA_BYPASS, Property(0)), 1));
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, id_CH0_WA_MODE, 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));
tg.config.add_word("DCU.CH1_AUTO_CALIB_EN", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", tg.config.add_word("DCU.CH1_CTC_BYPASS",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_CTC_BYPASS"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH1_CTC_BYPASS, Property(0)), 1));
tg.config.add_word("DCU.CH1_DCOATDCFG", tg.config.add_word("DCU.CH1_DCOATDCFG", parse_config_str(get_or_default(ci->params, id_CH1_DCOATDCFG, Property(0)), 2));
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, id_CH1_DCOATDDLY, 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));
tg.config.add_word("DCU.CH1_DCOBYPSATD", tg.config.add_word("DCU.CH1_DCOBYPSATD",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOBYPSATD"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH1_DCOBYPSATD, Property(0)), 1));
tg.config.add_word("DCU.CH1_DCOCALDIV", tg.config.add_word("DCU.CH1_DCOCALDIV", parse_config_str(get_or_default(ci->params, id_CH1_DCOCALDIV, Property(0)), 3));
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, id_CH1_DCOCTLGI, 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));
tg.config.add_word("DCU.CH1_DCODISBDAVOID", tg.config.add_word("DCU.CH1_DCODISBDAVOID",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCODISBDAVOID"), Property(0)), 1)); parse_config_str(get_or_default(ci->params, id_CH1_DCODISBDAVOID, Property(0)), 1));
tg.config.add_word("DCU.CH1_DCOFLTDAC", tg.config.add_word("DCU.CH1_DCOFLTDAC", parse_config_str(get_or_default(ci->params, id_CH1_DCOFLTDAC, Property(0)), 2));
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, id_CH1_DCOFTNRG, Property(0)), 3));
tg.config.add_word("DCU.CH1_DCOFTNRG",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOFTNRG"), Property(0)), 3));
tg.config.add_word("DCU.CH1_DCOIOSTUNE", tg.config.add_word("DCU.CH1_DCOIOSTUNE",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOIOSTUNE"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH1_DCOIOSTUNE, Property(0)), 3));
tg.config.add_word("DCU.CH1_DCOITUNE", tg.config.add_word("DCU.CH1_DCOITUNE", parse_config_str(get_or_default(ci->params, id_CH1_DCOITUNE, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOITUNE"), Property(0)), 2));
tg.config.add_word("DCU.CH1_DCOITUNE4LSB", 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", 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", tg.config.add_word("DCU.CH1_DCONUOFLSB",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCONUOFLSB"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH1_DCONUOFLSB, Property(0)), 3));
tg.config.add_word("DCU.CH1_DCOSCALEI", tg.config.add_word("DCU.CH1_DCOSCALEI", parse_config_str(get_or_default(ci->params, id_CH1_DCOSCALEI, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSCALEI"), Property(0)), 2));
tg.config.add_word("DCU.CH1_DCOSTARTVAL", tg.config.add_word("DCU.CH1_DCOSTARTVAL",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSTARTVAL"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_CH1_DCOSTARTVAL, Property(0)), 3));
tg.config.add_word("DCU.CH1_DCOSTEP", tg.config.add_word("DCU.CH1_DCOSTEP", parse_config_str(get_or_default(ci->params, id_CH1_DCOSTEP, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_DCOSTEP"), Property(0)), 2));
tg.config.add_word("DCU.CH1_DEC_BYPASS", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_GE_AN_ENABLE, Property(0)), 1));
tg.config.add_word("DCU.CH1_INVERT_RX", tg.config.add_word("DCU.CH1_INVERT_RX", parse_config_str(get_or_default(ci->params, id_CH1_INVERT_RX, Property(0)), 1));
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, id_CH1_INVERT_TX, 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));
tg.config.add_word("DCU.CH1_LDR_CORE2TX_SEL", 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", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_PCIE_EI_EN, Property(0)), 1));
tg.config.add_word("DCU.CH1_PCIE_MODE", tg.config.add_word("DCU.CH1_PCIE_MODE", parse_config_str(get_or_default(ci->params, id_CH1_PCIE_MODE, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PCIE_MODE"), Property(0)), 1));
tg.config.add_word("DCU.CH1_PCS_DET_TIME_SEL", 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)); 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", tg.config.add_word("DCU.CH1_PDEN_SEL", parse_config_str(get_or_default(ci->params, id_CH1_PDEN_SEL, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PDEN_SEL"), Property(0)), 1));
tg.config.add_word("DCU.CH1_PRBS_ENABLE", tg.config.add_word("DCU.CH1_PRBS_ENABLE",
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PRBS_ENABLE"), 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", tg.config.add_word("DCU.CH1_PRBS_LOCK", parse_config_str(get_or_default(ci->params, id_CH1_PRBS_LOCK, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_PRBS_LOCK"), Property(0)), 1));
tg.config.add_word("DCU.CH1_PRBS_SELECTION", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_REG_IDAC_SEL, Property(0)), 10));
tg.config.add_word("DCU.CH1_REQ_EN", tg.config.add_word("DCU.CH1_REQ_EN", parse_config_str(get_or_default(ci->params, id_CH1_REQ_EN, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_REQ_EN"), Property(0)), 1));
tg.config.add_word("DCU.CH1_REQ_LVL_SET", 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)); parse_config_str(get_or_default(ci->params, id_CH1_REQ_LVL_SET, Property(0)), 2));
tg.config.add_word("DCU.CH1_RIO_MODE", tg.config.add_word("DCU.CH1_RIO_MODE", parse_config_str(get_or_default(ci->params, id_CH1_RIO_MODE, Property(0)), 1));
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, id_CH1_RLOS_SEL, Property(0)), 1));
tg.config.add_word("DCU.CH1_RLOS_SEL", tg.config.add_word("DCU.CH1_RPWDNB", parse_config_str(get_or_default(ci->params, id_CH1_RPWDNB, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RLOS_SEL"), 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_RPWDNB", tg.config.add_word("DCU.CH1_RTERM_TX", parse_config_str(get_or_default(ci->params, id_CH1_RTERM_TX, Property(0)), 5));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RPWDNB"), Property(0)), 1)); 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_RTERM_RX", tg.config.add_word("DCU.CH1_RXTERM_CM", parse_config_str(get_or_default(ci->params, id_CH1_RXTERM_CM, Property(0)), 2));
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));
tg.config.add_word("DCU.CH1_RX_DCO_CK_DIV", 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", 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", 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", 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", 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)); 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", 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));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_RX_LOS_EN"), Property(0)), 1));
tg.config.add_word("DCU.CH1_RX_LOS_HYST_EN", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_RX_SB_BYPASS, Property(0)), 1));
tg.config.add_word("DCU.CH1_SB_BYPASS", tg.config.add_word("DCU.CH1_SB_BYPASS", parse_config_str(get_or_default(ci->params, id_CH1_SB_BYPASS, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_SB_BYPASS"), Property(0)), 1));
tg.config.add_word("DCU.CH1_SEL_SD_RX_CLK", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_TDRV_SLICE5_SEL, Property(0)), 2));
tg.config.add_word("DCU.CH1_TPWDNB", tg.config.add_word("DCU.CH1_TPWDNB", parse_config_str(get_or_default(ci->params, id_CH1_TPWDNB, Property(0)), 1));
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, id_CH1_TX_CM_SEL, Property(0)), 2));
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));
tg.config.add_word("DCU.CH1_TX_DIV11_SEL", 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", 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", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_TX_PRE_SIGN, Property(0)), 1));
tg.config.add_word("DCU.CH1_UC_MODE", tg.config.add_word("DCU.CH1_UC_MODE", parse_config_str(get_or_default(ci->params, id_CH1_UC_MODE, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("CH1_UC_MODE"), Property(0)), 1));
tg.config.add_word("DCU.CH1_UDF_COMMA_A", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_CH1_UDF_COMMA_MASK, Property(0)), 10));
tg.config.add_word("DCU.CH1_WA_BYPASS", tg.config.add_word("DCU.CH1_WA_BYPASS", parse_config_str(get_or_default(ci->params, id_CH1_WA_BYPASS, Property(0)), 1));
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, id_CH1_WA_MODE, 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));
tg.config.add_word("DCU.D_BITCLK_FROM_ND_EN", 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", 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", 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)); parse_config_str(get_or_default(ci->params, id_D_BITCLK_ND_EN, Property(0)), 1));
tg.config.add_word("DCU.D_BUS8BIT_SEL", tg.config.add_word("DCU.D_BUS8BIT_SEL", parse_config_str(get_or_default(ci->params, id_D_BUS8BIT_SEL, Property(0)), 1));
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, id_D_CDR_LOL_SET, Property(0)), 2));
tg.config.add_word("DCU.D_CDR_LOL_SET", tg.config.add_word("DCU.D_CMUSETBIASI", parse_config_str(get_or_default(ci->params, id_D_CMUSETBIASI, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("D_CDR_LOL_SET"), 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_CMUSETBIASI", tg.config.add_word("DCU.D_CMUSETI4CPZ", parse_config_str(get_or_default(ci->params, id_D_CMUSETI4CPZ, Property(0)), 4));
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETBIASI"), Property(0)), 2)); 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_CMUSETI4CPP", tg.config.add_word("DCU.D_CMUSETICP4P", parse_config_str(get_or_default(ci->params, id_D_CMUSETICP4P, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETI4CPP"), Property(0)), 4)); 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_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));
tg.config.add_word("DCU.D_CMUSETINITVCT", 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", tg.config.add_word("DCU.D_CMUSETISCL4VCO",
parse_config_str(get_or_default(ci->params, ctx->id("D_CMUSETISCL4VCO"), Property(0)), 3)); parse_config_str(get_or_default(ci->params, id_D_CMUSETISCL4VCO, Property(0)), 3));
tg.config.add_word("DCU.D_CMUSETP1GM", tg.config.add_word("DCU.D_CMUSETP1GM", parse_config_str(get_or_default(ci->params, id_D_CMUSETP1GM, Property(0)), 3));
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, id_D_CMUSETP2AGM, Property(0)), 3));
tg.config.add_word("DCU.D_CMUSETP2AGM", tg.config.add_word("DCU.D_CMUSETZGM", parse_config_str(get_or_default(ci->params, id_D_CMUSETZGM, Property(0)), 3));
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));
tg.config.add_word("DCU.D_DCO_CALIB_TIME_SEL", 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)); 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", tg.config.add_word("DCU.D_HIGH_MARK", parse_config_str(get_or_default(ci->params, id_D_HIGH_MARK, Property(0)), 4));
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, id_D_IB_PWDNB, Property(0)), 1));
tg.config.add_word("DCU.D_IB_PWDNB", tg.config.add_word("DCU.D_ISETLOS", parse_config_str(get_or_default(ci->params, id_D_ISETLOS, Property(0)), 8));
parse_config_str(get_or_default(ci->params, ctx->id("D_IB_PWDNB"), Property(0)), 1)); 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_ISETLOS", parse_config_str(get_or_default(ci->params, ctx->id("D_ISETLOS"), Property(0)), 8)); 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_LOW_MARK", tg.config.add_word("DCU.D_PD_ISET", parse_config_str(get_or_default(ci->params, id_D_PD_ISET, Property(0)), 2));
parse_config_str(get_or_default(ci->params, ctx->id("D_LOW_MARK"), Property(0)), 4)); 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_MACROPDB", tg.config.add_word("DCU.D_REFCK_MODE", parse_config_str(get_or_default(ci->params, id_D_REFCK_MODE, Property(0)), 3));
parse_config_str(get_or_default(ci->params, ctx->id("D_MACROPDB"), Property(0)), 1)); 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_PD_ISET", parse_config_str(get_or_default(ci->params, ctx->id("D_PD_ISET"), Property(0)), 2)); 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_PLL_LOL_SET", tg.config.add_word("DCU.D_RG_SET", parse_config_str(get_or_default(ci->params, id_D_RG_SET, Property(0)), 2));
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));
tg.config.add_word("DCU.D_SETICONST_AUX", 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", 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", 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", tg.config.add_word("DCU.D_SETIRPOLY_CH",
parse_config_str(get_or_default(ci->params, ctx->id("D_SETIRPOLY_CH"), Property(0)), 2)); parse_config_str(get_or_default(ci->params, id_D_SETIRPOLY_CH, Property(0)), 2));
tg.config.add_word("DCU.D_SETPLLRC", tg.config.add_word("DCU.D_SETPLLRC", parse_config_str(get_or_default(ci->params, id_D_SETPLLRC, Property(0)), 6));
parse_config_str(get_or_default(ci->params, ctx->id("D_SETPLLRC"), Property(0)), 6));
tg.config.add_word("DCU.D_SYNC_LOCAL_EN", 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)); 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", 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));
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, id_D_TXPLL_PWDNB, 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));
tg.config.add_word("DCU.D_TX_VCO_CK_DIV", 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)); 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", tg.config.add_word("DCU.D_XGE_MODE", parse_config_str(get_or_default(ci->params, id_D_XGE_MODE, Property(0)), 1));
parse_config_str(get_or_default(ci->params, ctx->id("D_XGE_MODE"), Property(0)), 1));

View File

@ -299,8 +299,8 @@ class Ecp5GlobalRouter
dedicated_routing = false; dedicated_routing = false;
if (drv.cell == nullptr) { if (drv.cell == nullptr) {
return 0; return 0;
} else if (drv.cell->attrs.count(ctx->id("BEL"))) { } else if (drv.cell->attrs.count(id_BEL)) {
drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(ctx->id("BEL")).as_string()); drv_bel = ctx->getBelByNameStr(drv.cell->attrs.at(id_BEL).as_string());
} else { } else {
// Check if driver is a singleton // Check if driver is a singleton
BelId last_bel; BelId last_bel;
@ -399,7 +399,7 @@ class Ecp5GlobalRouter
{ {
BelId best_bel; BelId best_bel;
WireId best_bel_pclkcib; 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; wirelen_t best_wirelen = 9999999;
bool dedicated_routing = false; bool dedicated_routing = false;
for (auto bel : ctx->getBels()) { for (auto bel : ctx->getBels()) {
@ -492,8 +492,8 @@ class Ecp5GlobalRouter
dccptr = dcc.get(); dccptr = dcc.get();
ctx->cells[dcc->name] = std::move(dcc); ctx->cells[dcc->name] = std::move(dcc);
} }
glbptr->attrs[ctx->id("ECP5_IS_GLOBAL")] = 1; glbptr->attrs[id_ECP5_IS_GLOBAL] = 1;
if (str_or_default(dccptr->attrs, ctx->id("BEL"), "") == "") if (str_or_default(dccptr->attrs, id_BEL, "") == "")
place_dcc_dcs(dccptr); place_dcc_dcs(dccptr);
return glbptr; return glbptr;
} }
@ -514,8 +514,8 @@ class Ecp5GlobalRouter
log_info("Promoting globals...\n"); log_info("Promoting globals...\n");
auto clocks = get_clocks(); auto clocks = get_clocks();
for (auto clock : clocks) { for (auto clock : clocks) {
bool is_noglobal = bool_or_default(clock->attrs, ctx->id("noglobal"), false) || bool is_noglobal = bool_or_default(clock->attrs, id_noglobal, false) ||
bool_or_default(clock->attrs, ctx->id("ECP5_IS_GLOBAL"), false); bool_or_default(clock->attrs, id_ECP5_IS_GLOBAL, false);
if (is_noglobal) if (is_noglobal)
continue; continue;
log_info(" promoting clock net %s to global network\n", clock->name.c_str(ctx)); log_info(" promoting clock net %s to global network\n", clock->name.c_str(ctx));

View File

@ -134,7 +134,7 @@ bool Arch::apply_lpf(std::string filename, std::istream &in)
if (words.size() > 5) if (words.size() > 5)
log_error("unexpected input following LOCATE clause (on line %d)\n", lineno); log_error("unexpected input following LOCATE clause (on line %d)\n", lineno);
if (fnd_cell != cells.end()) { 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") { } else if (verb == "IOBUF") {
if (words.size() < 3) if (words.size() < 3)

View File

@ -277,7 +277,7 @@ void ECP5CommandHandler::customAfterLoad(Context *ctx)
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") || if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
ci->type == ctx->id("$nextpnr_iobuf")) { 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")) if (vm.count("lpf-allow-unconstrained"))
log_warning("IO '%s' is unconstrained in LPF and will be automatically placed\n", log_warning("IO '%s' is unconstrained in LPF and will be automatically placed\n",
cell.first.c_str(ctx)); cell.first.c_str(ctx));

File diff suppressed because it is too large Load Diff

View File

@ -688,7 +688,7 @@ void Arch::read_cst(std::istream &in)
insloc insloc
} cst_type; } cst_type;
settings.erase(id("cst")); settings.erase(id_cst);
while (!in.eof()) { while (!in.eof()) {
std::getline(in, line); std::getline(in, line);
cst_type = ioloc; 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 // Add all MUXes for the cell
@ -1455,13 +1455,13 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
bool Arch::place() 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; bool retVal;
if (placer == "heap") { if (placer == "heap") {
bool have_iobuf_or_constr = false; bool have_iobuf_or_constr = false;
for (auto &cell : cells) { for (auto &cell : cells) {
CellInfo *ci = cell.second.get(); 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; have_iobuf_or_constr = true;
break; break;
} }
@ -1472,15 +1472,15 @@ bool Arch::place()
retVal = placer1(getCtx(), Placer1Cfg(getCtx())); retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
} else { } else {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
cfg.ioBufTypes.insert(id("IOB")); cfg.ioBufTypes.insert(id_IOB);
cfg.beta = 0.5; cfg.beta = 0.5;
retVal = placer_heap(getCtx(), cfg); retVal = placer_heap(getCtx(), cfg);
} }
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
} else if (placer == "sa") { } else if (placer == "sa") {
retVal = placer1(getCtx(), Placer1Cfg(getCtx())); retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
return retVal; return retVal;
} else { } else {
@ -1497,7 +1497,7 @@ bool Arch::place()
bool Arch::route() 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; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(getCtx(), Router1Cfg(getCtx()));
@ -1507,7 +1507,7 @@ bool Arch::route()
} else { } else {
log_error("Gowin architecture does not support router '%s'\n", router.c_str()); 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(); archInfoToAttributes();
return result; return result;
} }
@ -1600,9 +1600,9 @@ void Arch::assignArchInfo()
ci->is_slice = true; ci->is_slice = true;
ci->ff_used = ci->params.at(id_FF_USED).as_bool(); ci->ff_used = ci->params.at(id_FF_USED).as_bool();
ci->ff_type = id(ci->params.at(id_FF_TYPE).as_string()); ci->ff_type = id(ci->params.at(id_FF_TYPE).as_string());
ci->slice_clk = get_net_or_empty(ci, id("CLK")); ci->slice_clk = get_net_or_empty(ci, id_CLK);
ci->slice_ce = get_net_or_empty(ci, id("CE")); ci->slice_ce = get_net_or_empty(ci, id_CE);
ci->slice_lsr = get_net_or_empty(ci, id("LSR")); ci->slice_lsr = get_net_or_empty(ci, id_LSR);
// add timing paths // add timing paths
addCellTimingClock(cname, id_CLK); addCellTimingClock(cname, id_CLK);

View File

@ -354,7 +354,7 @@ struct Arch : BaseArch<ArchRanges>
std::string getChipName() const override { return device; } std::string getChipName() const override { return device; }
ArchArgs archArgs() const override { return args; } 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 getGridDimX() const override { return gridDimX; }
int getGridDimY() const override { return gridDimY; } int getGridDimY() const override { return gridDimY; }

View File

@ -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)

View File

@ -114,7 +114,7 @@ static void pack_alus(Context *ctx)
int alu_idx = 1; int alu_idx = 1;
do { // go through the ALU chain 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()) { if (alu_bel != ci->attrs.end()) {
log_error("ALU %s placement restrictions are not supported.\n", ctx->nameOf(ci)); log_error("ALU %s placement restrictions are not supported.\n", ctx->nameOf(ci));
return; 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) 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 // find the muxed LUT
NetInfo *i1 = ci->ports.at(id_I1).net; 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 // XXX enable the placement constraints
auto mux_bel = ci->attrs.find(ctx->id("BEL")); auto mux_bel = ci->attrs.find(id_BEL);
auto lut1_bel = lut1->attrs.find(ctx->id("BEL")); auto lut1_bel = lut1->attrs.find(id_BEL);
if (lut1_bel != lut1->attrs.end() || mux_bel != ci->attrs.end()) { 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)); log_error("MUX2_LUT5 '%s' placement restrictions are not supported yet\n", ctx->nameOf(ci));
return; 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) { if (ctx->verbose) {
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get())); 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 // XXX enable the placement constraints
auto mux_bel = ci->attrs.find(ctx->id("BEL")); auto mux_bel = ci->attrs.find(id_BEL);
auto lut0_bel = lut0->attrs.find(ctx->id("BEL")); auto lut0_bel = lut0->attrs.find(id_BEL);
auto lut1_bel = lut1->attrs.find(ctx->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()) { 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)); log_error("MUX2_LUT5 '%s' placement restrictions are not supported yet\n", ctx->nameOf(ci));
return; 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) { if (ctx->verbose) {
log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get())); 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 // XXX enable the placement constraints
auto mux_bel = ci->attrs.find(ctx->id("BEL")); auto mux_bel = ci->attrs.find(id_BEL);
auto mux0_bel = mux0->attrs.find(ctx->id("BEL")); auto mux0_bel = mux0->attrs.find(id_BEL);
auto mux1_bel = mux1->attrs.find(ctx->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()) { 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)); log_error("MUX2_LUT%c '%s' placement restrictions are not supported yet\n", type_suffix, ctx->nameOf(ci));
return; return;
@ -512,7 +512,7 @@ static void pack_lut_lutffs(Context *ctx)
if (ctx->verbose) if (ctx->verbose)
log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx)); log_info("cell '%s' is of type '%s'\n", ctx->nameOf(ci), ci->type.c_str(ctx));
if (is_lut(ctx, ci)) { 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) for (auto &attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
packed_cells.insert(ci->name); 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())); log_info("packed cell %s into %s\n", ctx->nameOf(ci), ctx->nameOf(packed.get()));
// See if we can pack into a DFF // See if we can pack into a DFF
// TODO: LUT cascade // TODO: LUT cascade
NetInfo *o = ci->ports.at(ctx->id("F")).net; NetInfo *o = ci->ports.at(id_F).net;
CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("D"), true); CellInfo *dff = net_only_drives(ctx, o, is_ff, id_D, true);
auto lut_bel = ci->attrs.find(ctx->id("BEL")); auto lut_bel = ci->attrs.find(id_BEL);
bool packed_dff = false; bool packed_dff = false;
if (dff) { if (dff) {
if (ctx->verbose) if (ctx->verbose)
log_info("found attached dff %s\n", ctx->nameOf(dff)); 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) { if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack // Locations don't match, can't pack
} else { } else {
@ -535,7 +535,7 @@ static void pack_lut_lutffs(Context *ctx)
dff_to_lc(ctx, dff, packed.get(), false); dff_to_lc(ctx, dff, packed.get(), false);
ctx->nets.erase(o->name); ctx->nets.erase(o->name);
if (dff_bel != dff->attrs.end()) 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); packed_cells.insert(dff->name);
if (ctx->verbose) if (ctx->verbose)
log_info("packed cell %s into %s\n", ctx->nameOf(dff), ctx->nameOf(packed.get())); 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) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (is_ff(ctx, ci)) { 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) for (auto &attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
if (ctx->verbose) if (ctx->verbose)
@ -610,20 +610,20 @@ static void pack_constants(Context *ctx)
{ {
log_info("Packing constants..\n"); log_info("Packing constants..\n");
std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, ctx->id("SLICE"), "$PACKER_GND"); std::unique_ptr<CellInfo> gnd_cell = create_generic_cell(ctx, id_SLICE, "$PACKER_GND");
gnd_cell->params[ctx->id("INIT")] = Property(0, 1 << 4); gnd_cell->params[id_INIT] = Property(0, 1 << 4);
auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET")); auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET"));
gnd_net->driver.cell = gnd_cell.get(); gnd_net->driver.cell = gnd_cell.get();
gnd_net->driver.port = ctx->id("F"); gnd_net->driver.port = id_F;
gnd_cell->ports.at(ctx->id("F")).net = gnd_net.get(); 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 // 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")); auto vcc_net = std::make_unique<NetInfo>(ctx->id("$PACKER_VCC_NET"));
vcc_net->driver.cell = vcc_cell.get(); vcc_net->driver.cell = vcc_cell.get();
vcc_net->driver.port = ctx->id("F"); vcc_net->driver.port = id_F;
vcc_cell->ports.at(ctx->id("F")).net = vcc_net.get(); vcc_cell->ports.at(id_F).net = vcc_net.get();
std::vector<IdString> dead_nets; std::vector<IdString> dead_nets;
@ -631,13 +631,13 @@ static void pack_constants(Context *ctx)
for (auto &net : ctx->nets) { for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get(); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, gnd_net.get(), false); set_net_constant(ctx, ni, gnd_net.get(), false);
gnd_used = true; gnd_used = true;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
ctx->cells.erase(drv_cell); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, vcc_net.get(), true); set_net_constant(ctx, ni, vcc_net.get(), true);
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
@ -780,7 +780,7 @@ bool Arch::pack()
pack_alus(ctx); pack_alus(ctx);
pack_lut_lutffs(ctx); pack_lut_lutffs(ctx);
pack_nonlut_ffs(ctx); pack_nonlut_ffs(ctx);
ctx->settings[ctx->id("pack")] = 1; ctx->settings[id_pack] = 1;
ctx->assignArchInfo(); ctx->assignArchInfo();
log_info("Checksum: 0x%08x\n", ctx->checksum()); log_info("Checksum: 0x%08x\n", ctx->checksum());
return true; return true;

View File

@ -169,29 +169,29 @@ std::string Arch::getChipName() const
IdString Arch::archArgsToId(ArchArgs args) const IdString Arch::archArgsToId(ArchArgs args) const
{ {
if (args.type == ArchArgs::LP384) if (args.type == ArchArgs::LP384)
return id("lp384"); return id_lp384;
if (args.type == ArchArgs::LP1K) if (args.type == ArchArgs::LP1K)
return id("lp1k"); return id_lp1k;
if (args.type == ArchArgs::HX1K) if (args.type == ArchArgs::HX1K)
return id("hx1k"); return id_hx1k;
if (args.type == ArchArgs::UP3K) if (args.type == ArchArgs::UP3K)
return id("up3k"); return id_up3k;
if (args.type == ArchArgs::UP5K) if (args.type == ArchArgs::UP5K)
return id("up5k"); return id_up5k;
if (args.type == ArchArgs::U1K) if (args.type == ArchArgs::U1K)
return id("u1k"); return id_u1k;
if (args.type == ArchArgs::U2K) if (args.type == ArchArgs::U2K)
return id("u2k"); return id_u2k;
if (args.type == ArchArgs::U4K) if (args.type == ArchArgs::U4K)
return id("u4k"); return id_u4k;
if (args.type == ArchArgs::LP4K) if (args.type == ArchArgs::LP4K)
return id("lp4k"); return id_lp4k;
if (args.type == ArchArgs::LP8K) if (args.type == ArchArgs::LP8K)
return id("lp8k"); return id_lp8k;
if (args.type == ArchArgs::HX4K) if (args.type == ArchArgs::HX4K)
return id("hx4k"); return id_hx4k;
if (args.type == ArchArgs::HX8K) if (args.type == ArchArgs::HX8K)
return id("hx8k"); return id_hx8k;
return IdString(); 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; 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; return ret;
} }
@ -387,33 +387,33 @@ IdString Arch::getWireType(WireId wire) const
case WireInfoPOD::WIRE_TYPE_NONE: case WireInfoPOD::WIRE_TYPE_NONE:
return IdString(); return IdString();
case WireInfoPOD::WIRE_TYPE_GLB2LOCAL: case WireInfoPOD::WIRE_TYPE_GLB2LOCAL:
return id("GLB2LOCAL"); return id_GLB2LOCAL;
case WireInfoPOD::WIRE_TYPE_GLB_NETWK: case WireInfoPOD::WIRE_TYPE_GLB_NETWK:
return id("GLB_NETWK"); return id_GLB_NETWK;
case WireInfoPOD::WIRE_TYPE_LOCAL: case WireInfoPOD::WIRE_TYPE_LOCAL:
return id("LOCAL"); return id_LOCAL;
case WireInfoPOD::WIRE_TYPE_LUTFF_IN: case WireInfoPOD::WIRE_TYPE_LUTFF_IN:
return id("LUTFF_IN"); return id_LUTFF_IN;
case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT: case WireInfoPOD::WIRE_TYPE_LUTFF_IN_LUT:
return id("LUTFF_IN_LUT"); return id_LUTFF_IN_LUT;
case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT: case WireInfoPOD::WIRE_TYPE_LUTFF_LOUT:
return id("LUTFF_LOUT"); return id_LUTFF_LOUT;
case WireInfoPOD::WIRE_TYPE_LUTFF_OUT: case WireInfoPOD::WIRE_TYPE_LUTFF_OUT:
return id("LUTFF_OUT"); return id_LUTFF_OUT;
case WireInfoPOD::WIRE_TYPE_LUTFF_COUT: case WireInfoPOD::WIRE_TYPE_LUTFF_COUT:
return id("LUTFF_COUT"); return id_LUTFF_COUT;
case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL: case WireInfoPOD::WIRE_TYPE_LUTFF_GLOBAL:
return id("LUTFF_GLOBAL"); return id_LUTFF_GLOBAL;
case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX: case WireInfoPOD::WIRE_TYPE_CARRY_IN_MUX:
return id("CARRY_IN_MUX"); return id_CARRY_IN_MUX;
case WireInfoPOD::WIRE_TYPE_SP4_V: case WireInfoPOD::WIRE_TYPE_SP4_V:
return id("SP4_V"); return id_SP4_V;
case WireInfoPOD::WIRE_TYPE_SP4_H: case WireInfoPOD::WIRE_TYPE_SP4_H:
return id("SP4_H"); return id_SP4_H;
case WireInfoPOD::WIRE_TYPE_SP12_V: case WireInfoPOD::WIRE_TYPE_SP12_V:
return id("SP12_V"); return id_SP12_V;
case WireInfoPOD::WIRE_TYPE_SP12_H: case WireInfoPOD::WIRE_TYPE_SP12_H:
return id("SP12_H"); return id_SP12_H;
} }
return IdString(); 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; std::vector<std::pair<IdString, std::string>> ret;
auto &wi = chip_info->wire_data[wire.index]; 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_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_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_Z, stringf("%d", wi.z)));
return ret; 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; 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; return ret;
} }
@ -682,7 +682,7 @@ bool Arch::getBudgetOverride(const NetInfo *net_info, const PortRef &sink, delay
bool Arch::place() 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") { if (placer == "heap") {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
cfg.ioBufTypes.insert(id_SB_IO); 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()); log_error("iCE40 architecture does not support placer '%s'\n", placer.c_str());
} }
bool retVal = true; bool retVal = true;
if (bool_or_default(settings, id("opt_timing"), false)) { if (bool_or_default(settings, id_opt_timing, false)) {
TimingOptCfg tocfg(getCtx()); TimingOptCfg tocfg(getCtx());
tocfg.cellTypes.insert(id_ICESTORM_LC); tocfg.cellTypes.insert(id_ICESTORM_LC);
retVal = timing_opt(getCtx(), tocfg); retVal = timing_opt(getCtx(), tocfg);
} }
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
return retVal; return retVal;
} }
bool Arch::route() 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; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(getCtx(), Router1Cfg(getCtx()));
@ -717,7 +717,7 @@ bool Arch::route()
} else { } else {
log_error("iCE40 architecture does not support router '%s'\n", router.c_str()); 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(); archInfoToAttributes();
return result; return result;
} }
@ -1064,7 +1064,7 @@ TimingPortClass Arch::getPortTimingClass(const CellInfo *cell, IdString port, in
return TMG_CLOCK_INPUT; return TMG_CLOCK_INPUT;
return TMG_IGNORE; return TMG_IGNORE;
} else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) { } 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; return TMG_CLOCK_INPUT;
clockInfoCount = 1; clockInfoCount = 1;
@ -1108,10 +1108,10 @@ TimingClockingInfo Arch::getPortClockingInfo(const CellInfo *cell, IdString port
} else if (cell->type == id_ICESTORM_RAM) { } else if (cell->type == id_ICESTORM_RAM) {
if (port.str(this)[0] == 'R') { if (port.str(this)[0] == 'R') {
info.clock_port = id_RCLK; 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 { } else {
info.clock_port = id_WCLK; 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) { if (cell->ports.at(port).type == PORT_OUT) {
bool has_clktoq = get_cell_delay_internal(cell, info.clock_port, port, info.clockToQ); 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); info.hold = DelayPair(0);
} }
} else if (cell->type == id_SB_I2C || cell->type == id_SB_SPI) { } 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; info.edge = RISING_EDGE;
if (cell->ports.at(port).type == PORT_OUT) { if (cell->ports.at(port).type == PORT_OUT) {
/* Dummy number */ /* Dummy number */
@ -1233,12 +1233,12 @@ void Arch::assignCellInfo(CellInfo *cell)
cell->lcInfo.inputCount++; cell->lcInfo.inputCount++;
} else if (cell->type == id_SB_IO) { } 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.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.global = bool_or_default(cell->attrs, id_GLOBAL);
cell->ioInfo.pintype = int_or_default(cell->params, this->id("PIN_TYPE")); cell->ioInfo.pintype = int_or_default(cell->params, id_PIN_TYPE);
cell->ioInfo.negtrig = bool_or_default(cell->params, this->id("NEG_TRIGGER")); cell->ioInfo.negtrig = bool_or_default(cell->params, id_NEG_TRIGGER);
} else if (cell->type == id_SB_GB) { } 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);
} }
} }

View File

@ -120,7 +120,7 @@ bool Arch::isBelLocationValid(BelId bel) const
break; break;
// Are we perhaps a PAD INPUT Bel that can be placed here? // 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; return true;
// Conflict // Conflict

View File

@ -391,7 +391,7 @@ void write_asc(const Context *ctx, std::ostream &out)
pool<Loc> sb_io_used_by_pll_pad; pool<Loc> sb_io_used_by_pll_pad;
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
if (cell.second->type != ctx->id("ICESTORM_PLL")) if (cell.second->type != id_ICESTORM_PLL)
continue; continue;
// Collect all locations matching an PLL output port // 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; std::cout << "Found unplaced cell " << cell.first.str(ctx) << " while generating bitstream!" << std::endl;
continue; continue;
} }
if (cell.second->type == ctx->id("ICESTORM_LC")) { if (cell.second->type == id_ICESTORM_LC) {
const BelInfoPOD &beli = ci.bel_data[bel.index]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; int x = beli.x, y = beli.y, z = beli.z;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_LOGIC];
unsigned lut_init = get_param_or_def(ctx, cell.second.get(), ctx->id("LUT_INIT")); 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(), ctx->id("NEG_CLK")); 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(), ctx->id("DFF_ENABLE")); 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(), ctx->id("ASYNC_SR")); 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(), ctx->id("SET_NORESET")); 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(), ctx->id("CARRY_ENABLE")); bool carry_enable = get_param_or_def(ctx, cell.second.get(), id_CARRY_ENABLE);
std::vector<bool> lc(20, false); std::vector<bool> lc(20, false);
// Discover permutation // Discover permutation
@ -502,20 +502,20 @@ void write_asc(const Context *ctx, std::ostream &out)
if (dff_enable) if (dff_enable)
set_config(ti, config.at(y).at(x), "NegClk", neg_clk); 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_const = get_param_or_def(ctx, cell.second.get(), id_CIN_CONST);
bool carry_set = get_param_or_def(ctx, cell.second.get(), ctx->id("CIN_SET")); bool carry_set = get_param_or_def(ctx, cell.second.get(), id_CIN_SET);
if (carry_const) { if (carry_const) {
if (!ctx->force) if (!ctx->force)
NPNR_ASSERT(z == 0); NPNR_ASSERT(z == 0);
set_config(ti, config.at(y).at(x), "CarryInSet", carry_set); 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]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; int x = beli.x, y = beli.y, z = beli.z;
const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO]; const TileInfoPOD &ti = bi.tiles_nonrouting[TILE_IO];
unsigned pin_type = get_param_or_def(ctx, cell.second.get(), ctx->id("PIN_TYPE")); 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(), ctx->id("NEG_TRIGGER")); bool neg_trigger = get_param_or_def(ctx, cell.second.get(), id_NEG_TRIGGER);
bool pullup = get_param_or_def(ctx, cell.second.get(), ctx->id("PULLUP")); bool pullup = get_param_or_def(ctx, cell.second.get(), id_PULLUP);
bool lvds = cell.second->ioInfo.lvds; 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_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; 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) { if (ctx->args.type == ArchArgs::UP5K || ctx->args.type == ArchArgs::UP3K) {
std::string pullup_resistor = "100K"; std::string pullup_resistor = "100K";
if (cell.second->attrs.count(ctx->id("PULLUP_RESISTOR"))) if (cell.second->attrs.count(id_PULLUP_RESISTOR))
pullup_resistor = cell.second->attrs.at(ctx->id("PULLUP_RESISTOR")).as_string(); pullup_resistor = cell.second->attrs.at(id_PULLUP_RESISTOR).as_string();
NPNR_ASSERT(pullup_resistor == "100K" || pullup_resistor == "10K" || pullup_resistor == "6P8K" || NPNR_ASSERT(pullup_resistor == "100K" || pullup_resistor == "10K" || pullup_resistor == "6P8K" ||
pullup_resistor == "3P3K"); pullup_resistor == "3P3K");
if (iez == 0) { 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) { if (cell.second->gbInfo.forPadIn) {
Loc gb_loc = ctx->getBelLocation(bel); Loc gb_loc = ctx->getBelLocation(bel);
for (auto &glb : ci.global_network_info) { 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]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y; int x = beli.x, y = beli.y;
const TileInfoPOD &ti_ramt = bi.tiles_nonrouting[TILE_RAMT]; 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)) { if (!(ctx->args.type == ArchArgs::LP1K || ctx->args.type == ArchArgs::HX1K)) {
set_config(ti_ramb, config.at(y).at(x), "RamConfig.PowerUp", true); 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_r = get_param_or_def(ctx, cell.second.get(), id_NEG_CLK_R);
bool negclk_w = get_param_or_def(ctx, cell.second.get(), ctx->id("NEG_CLK_W")); 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(), ctx->id("WRITE_MODE")); 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(), ctx->id("READ_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_ramb, config.at(y).at(x), "NegClk", negclk_w);
set_config(ti_ramt, config.at(y + 1).at(x), "NegClk", negclk_r); 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_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_2", read_mode & 0x1);
set_config(ti_ramt, config.at(y + 1).at(x), "RamConfig.CBIT_3", read_mode & 0x2); 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, set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "LED_DRV_CUR_EN", true,
"IpConfig."); "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 = { const std::vector<std::pair<std::string, int>> rgb_params = {
{"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}};
configure_extra_cell(config, ctx, cell.second.get(), rgb_params, true, std::string("IpConfig.")); 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."); 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 = { const std::vector<std::pair<std::string, int>> rgba_params = {
{"CURRENT_MODE", 1}, {"RGB0_CURRENT", 6}, {"RGB1_CURRENT", 6}, {"RGB2_CURRENT", 6}}; {"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.")); 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."); 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") || } else if (cell.second->type == id_SB_WARMBOOT || cell.second->type == id_ICESTORM_LFOSC ||
cell.second->type == ctx->id("SB_LEDDA_IP")) { cell.second->type == id_SB_LEDDA_IP) {
// No config needed // No config needed
} else if (cell.second->type == ctx->id("SB_I2C")) { } else if (cell.second->type == id_SB_I2C) {
bool sda_in_dly = !cell.second->attrs.count(ctx->id("SDA_INPUT_DELAYED")) || bool sda_in_dly = !cell.second->attrs.count(id_SDA_INPUT_DELAYED) ||
cell.second->attrs[ctx->id("SDA_INPUT_DELAYED")].as_bool(); cell.second->attrs[id_SDA_INPUT_DELAYED].as_bool();
bool sda_out_dly = !cell.second->attrs.count(ctx->id("SDA_OUTPUT_DELAYED")) || bool sda_out_dly = !cell.second->attrs.count(id_SDA_OUTPUT_DELAYED) ||
cell.second->attrs[ctx->id("SDA_OUTPUT_DELAYED")].as_bool(); 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, set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SDA_INPUT_DELAYED", sda_in_dly,
"IpConfig."); "IpConfig.");
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SDA_OUTPUT_DELAYED", sda_out_dly, 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."); "IpConfig.");
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "I2C_ENABLE_1", true, set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "I2C_ENABLE_1", true,
"IpConfig."); "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, set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_0", true,
"IpConfig."); "IpConfig.");
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_1", true, 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."); "IpConfig.");
set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_3", true, set_ec_cbit(config, ctx, get_ec_config(ctx->chip_info, cell.second->bel), "SPI_ENABLE_3", true,
"IpConfig."); "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]; const BelInfoPOD &beli = ci.bel_data[bel.index];
int x = beli.x, y = beli.y, z = beli.z; int x = beli.x, y = beli.y, z = beli.z;
NPNR_ASSERT(ctx->args.type == ArchArgs::UP5K || ctx->args.type == ArchArgs::UP3K); 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); 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}, const std::vector<std::pair<std::string, int>> mac16_params = {{"C_REG", 1},
{"A_REG", 1}, {"A_REG", 1},
{"B_REG", 1}, {"B_REG", 1},
@ -709,13 +709,13 @@ void write_asc(const Context *ctx, std::ostream &out)
{"A_SIGNED", 1}, {"A_SIGNED", 1},
{"B_SIGNED", 1}}; {"B_SIGNED", 1}};
configure_extra_cell(config, ctx, cell.second.get(), mac16_params, false, std::string("IpConfig.")); 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}}; 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) 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)); 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.")); 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}, const std::vector<std::pair<std::string, int>> pll_params = {{"DELAY_ADJMODE_FB", 1},
{"DELAY_ADJMODE_REL", 1}, {"DELAY_ADJMODE_REL", 1},
{"DIVF", 7}, {"DIVF", 7},
@ -874,7 +874,7 @@ void write_asc(const Context *ctx, std::ostream &out)
// Write RAM init data // Write RAM init data
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
if (cell.second->bel != BelId()) { 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]; const BelInfoPOD &beli = ci.bel_data[cell.second->bel.index];
int x = beli.x, y = beli.y; int x = beli.x, y = beli.y;
out << ".ram_data " << x << " " << y << std::endl; out << ".ram_data " << x << " " << y << std::endl;
@ -1054,7 +1054,7 @@ bool read_asc(Context *ctx, std::istream &in)
isUsed |= carry_set; isUsed |= carry_set;
if (isUsed) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK);
@ -1074,7 +1074,7 @@ bool read_asc(Context *ctx, std::istream &in)
isUsed |= neg_trigger; isUsed |= neg_trigger;
if (isUsed) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(bel, ctx->cells[name].get(), STRENGTH_WEAK); 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->checkBelAvail(belpin.bel)) {
if (ctx->getBelType(belpin.bel) == id_ICESTORM_LC) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == id_SB_IO) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == id_SB_GB) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == id_SB_WARMBOOT) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);
// TODO: Add port mapping to nets // TODO: Add port mapping to nets
} }
if (ctx->getBelType(belpin.bel) == id_ICESTORM_LFOSC) { 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; IdString name = created->name;
ctx->cells[name] = std::move(created); ctx->cells[name] = std::move(created);
ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK); ctx->bindBel(belpin.bel, ctx->cells[name].get(), STRENGTH_WEAK);

View File

@ -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); 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); auto new_cell = std::make_unique<CellInfo>(ctx, name_id, type);
if (type == ctx->id("ICESTORM_LC")) { if (type == id_ICESTORM_LC) {
new_cell->params[ctx->id("LUT_INIT")] = Property(0, 16); new_cell->params[id_LUT_INIT] = Property(0, 16);
new_cell->params[ctx->id("NEG_CLK")] = Property::State::S0; new_cell->params[id_NEG_CLK] = Property::State::S0;
new_cell->params[ctx->id("CARRY_ENABLE")] = Property::State::S0; new_cell->params[id_CARRY_ENABLE] = Property::State::S0;
new_cell->params[ctx->id("DFF_ENABLE")] = Property::State::S0; new_cell->params[id_DFF_ENABLE] = Property::State::S0;
new_cell->params[ctx->id("SET_NORESET")] = Property::State::S0; new_cell->params[id_SET_NORESET] = Property::State::S0;
new_cell->params[ctx->id("ASYNC_SR")] = Property::State::S0; new_cell->params[id_ASYNC_SR] = Property::State::S0;
new_cell->params[ctx->id("CIN_CONST")] = Property::State::S0; new_cell->params[id_CIN_CONST] = Property::State::S0;
new_cell->params[ctx->id("CIN_SET")] = Property::State::S0; new_cell->params[id_CIN_SET] = Property::State::S0;
new_cell->addInput(ctx->id("I0")); new_cell->addInput(id_I0);
new_cell->addInput(ctx->id("I1")); new_cell->addInput(id_I1);
new_cell->addInput(ctx->id("I2")); new_cell->addInput(id_I2);
new_cell->addInput(ctx->id("I3")); new_cell->addInput(id_I3);
new_cell->addInput(ctx->id("CIN")); new_cell->addInput(id_CIN);
new_cell->addInput(ctx->id("CLK")); new_cell->addInput(id_CLK);
new_cell->addInput(ctx->id("CEN")); new_cell->addInput(id_CEN);
new_cell->addInput(ctx->id("SR")); new_cell->addInput(id_SR);
new_cell->addOutput(ctx->id("LO")); new_cell->addOutput(id_LO);
new_cell->addOutput(ctx->id("O")); new_cell->addOutput(id_O);
new_cell->addOutput(ctx->id("COUT")); new_cell->addOutput(id_COUT);
} else if (type == ctx->id("SB_IO")) { } else if (type == id_SB_IO) {
new_cell->params[ctx->id("PIN_TYPE")] = Property(0, 6); new_cell->params[id_PIN_TYPE] = Property(0, 6);
new_cell->params[ctx->id("PULLUP")] = Property::State::S0; new_cell->params[id_PULLUP] = Property::State::S0;
new_cell->params[ctx->id("NEG_TRIGGER")] = Property::State::S0; new_cell->params[id_NEG_TRIGGER] = Property::State::S0;
new_cell->params[ctx->id("IO_STANDARD")] = Property("SB_LVCMOS"); 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(id_LATCH_INPUT_VALUE);
new_cell->addInput(ctx->id("CLOCK_ENABLE")); new_cell->addInput(id_CLOCK_ENABLE);
new_cell->addInput(ctx->id("INPUT_CLK")); new_cell->addInput(id_INPUT_CLK);
new_cell->addInput(ctx->id("OUTPUT_CLK")); new_cell->addInput(id_OUTPUT_CLK);
new_cell->addInput(ctx->id("OUTPUT_ENABLE")); new_cell->addInput(id_OUTPUT_ENABLE);
new_cell->addInput(ctx->id("D_OUT_0")); new_cell->addInput(id_D_OUT_0);
new_cell->addInput(ctx->id("D_OUT_1")); new_cell->addInput(id_D_OUT_1);
new_cell->addOutput(ctx->id("D_IN_0")); new_cell->addOutput(id_D_IN_0);
new_cell->addOutput(ctx->id("D_IN_1")); new_cell->addOutput(id_D_IN_1);
} else if (type == ctx->id("ICESTORM_RAM")) { } else if (type == id_ICESTORM_RAM) {
new_cell->params[ctx->id("NEG_CLK_W")] = Property::State::S0; new_cell->params[id_NEG_CLK_W] = Property::State::S0;
new_cell->params[ctx->id("NEG_CLK_R")] = Property::State::S0; new_cell->params[id_NEG_CLK_R] = Property::State::S0;
new_cell->params[ctx->id("WRITE_MODE")] = Property::State::S0; new_cell->params[id_WRITE_MODE] = Property::State::S0;
new_cell->params[ctx->id("READ_MODE")] = Property::State::S0; new_cell->params[id_READ_MODE] = Property::State::S0;
new_cell->addInput(ctx->id("RCLK")); new_cell->addInput(id_RCLK);
new_cell->addInput(ctx->id("RCLKE")); new_cell->addInput(id_RCLKE);
new_cell->addInput(ctx->id("RE")); new_cell->addInput(id_RE);
new_cell->addInput(ctx->id("WCLK")); new_cell->addInput(id_WCLK);
new_cell->addInput(ctx->id("WCLKE")); new_cell->addInput(id_WCLKE);
new_cell->addInput(ctx->id("WE")); new_cell->addInput(id_WE);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
new_cell->addInput(ctx->id("WDATA_" + std::to_string(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("RADDR_" + std::to_string(i)));
new_cell->addInput(ctx->id("WADDR_" + std::to_string(i))); new_cell->addInput(ctx->id("WADDR_" + std::to_string(i)));
} }
} else if (type == ctx->id("ICESTORM_LFOSC")) { } else if (type == id_ICESTORM_LFOSC) {
new_cell->addInput(ctx->id("CLKLFEN")); new_cell->addInput(id_CLKLFEN);
new_cell->addInput(ctx->id("CLKLFPU")); new_cell->addInput(id_CLKLFPU);
new_cell->addOutput(ctx->id("CLKLF")); new_cell->addOutput(id_CLKLF);
new_cell->addOutput(ctx->id("CLKLF_FABRIC")); new_cell->addOutput(id_CLKLF_FABRIC);
} else if (type == ctx->id("ICESTORM_HFOSC")) { } else if (type == id_ICESTORM_HFOSC) {
new_cell->params[ctx->id("CLKHF_DIV")] = Property("0b00"); new_cell->params[id_CLKHF_DIV] = Property("0b00");
new_cell->params[ctx->id("TRIM_EN")] = Property("0b0"); new_cell->params[id_TRIM_EN] = Property("0b0");
new_cell->addInput(ctx->id("CLKHFEN")); new_cell->addInput(id_CLKHFEN);
new_cell->addInput(ctx->id("CLKHFPU")); new_cell->addInput(id_CLKHFPU);
new_cell->addOutput(ctx->id("CLKHF")); new_cell->addOutput(id_CLKHF);
new_cell->addOutput(ctx->id("CLKHF_FABRIC")); new_cell->addOutput(id_CLKHF_FABRIC);
for (int i = 0; i < 10; i++) for (int i = 0; i < 10; i++)
new_cell->addInput(ctx->id("TRIM" + std::to_string(i))); new_cell->addInput(ctx->id("TRIM" + std::to_string(i)));
} else if (type == ctx->id("SB_GB")) { } else if (type == id_SB_GB) {
new_cell->addInput(ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")); new_cell->addInput(id_USER_SIGNAL_TO_GLOBAL_BUFFER);
new_cell->addOutput(ctx->id("GLOBAL_BUFFER_OUTPUT")); new_cell->addOutput(id_GLOBAL_BUFFER_OUTPUT);
} else if (type == ctx->id("ICESTORM_SPRAM")) { } else if (type == id_ICESTORM_SPRAM) {
new_cell->addInput(ctx->id("WREN")); new_cell->addInput(id_WREN);
new_cell->addInput(ctx->id("CHIPSELECT")); new_cell->addInput(id_CHIPSELECT);
new_cell->addInput(ctx->id("CLOCK")); new_cell->addInput(id_CLOCK);
new_cell->addInput(ctx->id("STANDBY")); new_cell->addInput(id_STANDBY);
new_cell->addInput(ctx->id("SLEEP")); new_cell->addInput(id_SLEEP);
new_cell->addInput(ctx->id("POWEROFF")); new_cell->addInput(id_POWEROFF);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
new_cell->addInput(ctx->id("DATAIN_" + std::to_string(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++) { for (int i = 0; i < 4; i++) {
new_cell->addInput(ctx->id("MASKWREN_" + std::to_string(i))); new_cell->addInput(ctx->id("MASKWREN_" + std::to_string(i)));
} }
} else if (type == ctx->id("ICESTORM_DSP")) { } else if (type == id_ICESTORM_DSP) {
new_cell->params[ctx->id("NEG_TRIGGER")] = Property::State::S0; new_cell->params[id_NEG_TRIGGER] = Property::State::S0;
new_cell->params[ctx->id("C_REG")] = Property::State::S0; new_cell->params[id_C_REG] = Property::State::S0;
new_cell->params[ctx->id("A_REG")] = Property::State::S0; new_cell->params[id_A_REG] = Property::State::S0;
new_cell->params[ctx->id("B_REG")] = Property::State::S0; new_cell->params[id_B_REG] = Property::State::S0;
new_cell->params[ctx->id("D_REG")] = Property::State::S0; new_cell->params[id_D_REG] = Property::State::S0;
new_cell->params[ctx->id("TOP_8x8_MULT_REG")] = Property::State::S0; new_cell->params[id_TOP_8x8_MULT_REG] = Property::State::S0;
new_cell->params[ctx->id("BOT_8x8_MULT_REG")] = Property::State::S0; new_cell->params[id_BOT_8x8_MULT_REG] = Property::State::S0;
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG1")] = Property::State::S0; new_cell->params[id_PIPELINE_16x16_MULT_REG1] = Property::State::S0;
new_cell->params[ctx->id("PIPELINE_16x16_MULT_REG2")] = 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[id_TOPOUTPUT_SELECT] = Property(0, 2);
new_cell->params[ctx->id("TOPADDSUB_LOWERINPUT")] = Property(0, 2); new_cell->params[id_TOPADDSUB_LOWERINPUT] = Property(0, 2);
new_cell->params[ctx->id("TOPADDSUB_UPPERINPUT")] = Property::State::S0; new_cell->params[id_TOPADDSUB_UPPERINPUT] = Property::State::S0;
new_cell->params[ctx->id("TOPADDSUB_CARRYSELECT")] = Property(0, 2); new_cell->params[id_TOPADDSUB_CARRYSELECT] = Property(0, 2);
new_cell->params[ctx->id("BOTOUTPUT_SELECT")] = Property(0, 2); new_cell->params[id_BOTOUTPUT_SELECT] = Property(0, 2);
new_cell->params[ctx->id("BOTADDSUB_LOWERINPUT")] = Property(0, 2); new_cell->params[id_BOTADDSUB_LOWERINPUT] = Property(0, 2);
new_cell->params[ctx->id("BOTADDSUB_UPPERINPUT")] = Property::State::S0; new_cell->params[id_BOTADDSUB_UPPERINPUT] = Property::State::S0;
new_cell->params[ctx->id("BOTADDSUB_CARRYSELECT")] = Property(0, 2); new_cell->params[id_BOTADDSUB_CARRYSELECT] = Property(0, 2);
new_cell->params[ctx->id("MODE_8x8")] = Property::State::S0; new_cell->params[id_MODE_8x8] = Property::State::S0;
new_cell->params[ctx->id("A_SIGNED")] = Property::State::S0; new_cell->params[id_A_SIGNED] = Property::State::S0;
new_cell->params[ctx->id("B_SIGNED")] = Property::State::S0; new_cell->params[id_B_SIGNED] = Property::State::S0;
new_cell->addInput(ctx->id("CLK")); new_cell->addInput(id_CLK);
new_cell->addInput(ctx->id("CE")); new_cell->addInput(id_CE);
for (int i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
new_cell->addInput(ctx->id("C_" + std::to_string(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("A_" + std::to_string(i)));
new_cell->addInput(ctx->id("B_" + 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("D_" + std::to_string(i)));
} }
new_cell->addInput(ctx->id("AHOLD")); new_cell->addInput(id_AHOLD);
new_cell->addInput(ctx->id("BHOLD")); new_cell->addInput(id_BHOLD);
new_cell->addInput(ctx->id("CHOLD")); new_cell->addInput(id_CHOLD);
new_cell->addInput(ctx->id("DHOLD")); new_cell->addInput(id_DHOLD);
new_cell->addInput(ctx->id("IRSTTOP")); new_cell->addInput(id_IRSTTOP);
new_cell->addInput(ctx->id("IRSTBOT")); new_cell->addInput(id_IRSTBOT);
new_cell->addInput(ctx->id("ORSTTOP")); new_cell->addInput(id_ORSTTOP);
new_cell->addInput(ctx->id("ORSTBOT")); new_cell->addInput(id_ORSTBOT);
new_cell->addInput(ctx->id("OLOADTOP")); new_cell->addInput(id_OLOADTOP);
new_cell->addInput(ctx->id("OLOADBOT")); new_cell->addInput(id_OLOADBOT);
new_cell->addInput(ctx->id("ADDSUBTOP")); new_cell->addInput(id_ADDSUBTOP);
new_cell->addInput(ctx->id("ADDSUBBOT")); new_cell->addInput(id_ADDSUBBOT);
new_cell->addInput(ctx->id("OHOLDTOP")); new_cell->addInput(id_OHOLDTOP);
new_cell->addInput(ctx->id("OHOLDBOT")); new_cell->addInput(id_OHOLDBOT);
new_cell->addInput(ctx->id("CI")); new_cell->addInput(id_CI);
new_cell->addInput(ctx->id("ACCUMCI")); new_cell->addInput(id_ACCUMCI);
new_cell->addInput(ctx->id("SIGNEXTIN")); new_cell->addInput(id_SIGNEXTIN);
for (int i = 0; i < 32; i++) { for (int i = 0; i < 32; i++) {
new_cell->addOutput(ctx->id("O_" + std::to_string(i))); new_cell->addOutput(ctx->id("O_" + std::to_string(i)));
} }
new_cell->addOutput(ctx->id("CO")); new_cell->addOutput(id_CO);
new_cell->addOutput(ctx->id("ACCUMCO")); new_cell->addOutput(id_ACCUMCO);
new_cell->addOutput(ctx->id("SIGNEXTOUT")); new_cell->addOutput(id_SIGNEXTOUT);
} else if (type == ctx->id("ICESTORM_PLL")) { } else if (type == id_ICESTORM_PLL) {
new_cell->params[ctx->id("DELAY_ADJMODE_FB")] = Property::State::S0; new_cell->params[id_DELAY_ADJMODE_FB] = Property::State::S0;
new_cell->params[ctx->id("DELAY_ADJMODE_REL")] = 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[id_DIVF] = Property(0, 7);
new_cell->params[ctx->id("DIVQ")] = Property(0, 3); new_cell->params[id_DIVQ] = Property(0, 3);
new_cell->params[ctx->id("DIVR")] = Property(0, 4); new_cell->params[id_DIVR] = Property(0, 4);
new_cell->params[ctx->id("FDA_FEEDBACK")] = Property(0, 4); new_cell->params[id_FDA_FEEDBACK] = Property(0, 4);
new_cell->params[ctx->id("FDA_RELATIVE")] = Property(0, 4); new_cell->params[id_FDA_RELATIVE] = Property(0, 4);
new_cell->params[ctx->id("FEEDBACK_PATH")] = Property(1, 3); new_cell->params[id_FEEDBACK_PATH] = Property(1, 3);
new_cell->params[ctx->id("FILTER_RANGE")] = Property(0, 3); new_cell->params[id_FILTER_RANGE] = Property(0, 3);
new_cell->params[ctx->id("PLLOUT_SELECT_A")] = Property(0, 2); new_cell->params[id_PLLOUT_SELECT_A] = Property(0, 2);
new_cell->params[ctx->id("PLLOUT_SELECT_B")] = 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[id_PLLTYPE] = Property(0, 3);
new_cell->params[ctx->id("SHIFTREG_DIVMODE")] = Property::State::S0; new_cell->params[id_SHIFTREG_DIVMODE] = Property::State::S0;
new_cell->params[ctx->id("TEST_MODE")] = 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++) for (int i = 0; i < 8; i++)
new_cell->addInput(ctx->id("DYNAMICDELAY_" + std::to_string(i))); new_cell->addInput(ctx->id("DYNAMICDELAY_" + std::to_string(i)));
new_cell->addInput(ctx->id("EXTFEEDBACK")); new_cell->addInput(id_EXTFEEDBACK);
new_cell->addInput(ctx->id("LATCHINPUTVALUE")); new_cell->addInput(id_LATCHINPUTVALUE);
new_cell->addInput(ctx->id("REFERENCECLK")); new_cell->addInput(id_REFERENCECLK);
new_cell->addInput(ctx->id("RESETB")); new_cell->addInput(id_RESETB);
new_cell->addInput(ctx->id("SCLK")); new_cell->addInput(id_SCLK);
new_cell->addInput(ctx->id("SDI")); new_cell->addInput(id_SDI);
new_cell->addOutput(ctx->id("SDO")); new_cell->addOutput(id_SDO);
new_cell->addOutput(ctx->id("LOCK")); new_cell->addOutput(id_LOCK);
new_cell->addOutput(ctx->id("PLLOUT_A")); new_cell->addOutput(id_PLLOUT_A);
new_cell->addOutput(ctx->id("PLLOUT_B")); new_cell->addOutput(id_PLLOUT_B);
new_cell->addOutput(ctx->id("PLLOUT_A_GLOBAL")); new_cell->addOutput(id_PLLOUT_A_GLOBAL);
new_cell->addOutput(ctx->id("PLLOUT_B_GLOBAL")); new_cell->addOutput(id_PLLOUT_B_GLOBAL);
} else if (type == ctx->id("SB_RGBA_DRV")) { } else if (type == id_SB_RGBA_DRV) {
new_cell->params[ctx->id("CURRENT_MODE")] = std::string("0b0"); new_cell->params[id_CURRENT_MODE] = std::string("0b0");
new_cell->params[ctx->id("RGB0_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB0_CURRENT] = std::string("0b000000");
new_cell->params[ctx->id("RGB1_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB1_CURRENT] = std::string("0b000000");
new_cell->params[ctx->id("RGB2_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB2_CURRENT] = std::string("0b000000");
new_cell->addInput(ctx->id("CURREN")); new_cell->addInput(id_CURREN);
new_cell->addInput(ctx->id("RGBLEDEN")); new_cell->addInput(id_RGBLEDEN);
new_cell->addInput(ctx->id("RGB0PWM")); new_cell->addInput(id_RGB0PWM);
new_cell->addInput(ctx->id("RGB1PWM")); new_cell->addInput(id_RGB1PWM);
new_cell->addInput(ctx->id("RGB2PWM")); new_cell->addInput(id_RGB2PWM);
new_cell->addOutput(ctx->id("RGB0")); new_cell->addOutput(id_RGB0);
new_cell->addOutput(ctx->id("RGB1")); new_cell->addOutput(id_RGB1);
new_cell->addOutput(ctx->id("RGB2")); new_cell->addOutput(id_RGB2);
} else if (type == ctx->id("SB_LED_DRV_CUR")) { } else if (type == id_SB_LED_DRV_CUR) {
new_cell->addInput(ctx->id("EN")); new_cell->addInput(id_EN);
new_cell->addOutput(ctx->id("LEDPU")); new_cell->addOutput(id_LEDPU);
} else if (type == ctx->id("SB_RGB_DRV")) { } else if (type == id_SB_RGB_DRV) {
new_cell->params[ctx->id("RGB0_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB0_CURRENT] = std::string("0b000000");
new_cell->params[ctx->id("RGB1_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB1_CURRENT] = std::string("0b000000");
new_cell->params[ctx->id("RGB2_CURRENT")] = std::string("0b000000"); new_cell->params[id_RGB2_CURRENT] = std::string("0b000000");
new_cell->addInput(ctx->id("RGBPU")); new_cell->addInput(id_RGBPU);
new_cell->addInput(ctx->id("RGBLEDEN")); new_cell->addInput(id_RGBLEDEN);
new_cell->addInput(ctx->id("RGB0PWM")); new_cell->addInput(id_RGB0PWM);
new_cell->addInput(ctx->id("RGB1PWM")); new_cell->addInput(id_RGB1PWM);
new_cell->addInput(ctx->id("RGB2PWM")); new_cell->addInput(id_RGB2PWM);
new_cell->addOutput(ctx->id("RGB0")); new_cell->addOutput(id_RGB0);
new_cell->addOutput(ctx->id("RGB1")); new_cell->addOutput(id_RGB1);
new_cell->addOutput(ctx->id("RGB2")); new_cell->addOutput(id_RGB2);
} else if (type == ctx->id("SB_LEDDA_IP")) { } else if (type == id_SB_LEDDA_IP) {
new_cell->addInput(ctx->id("LEDDCS")); new_cell->addInput(id_LEDDCS);
new_cell->addInput(ctx->id("LEDDCLK")); new_cell->addInput(id_LEDDCLK);
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
new_cell->addInput(ctx->id("LEDDDAT" + std::to_string(i))); new_cell->addInput(ctx->id("LEDDDAT" + std::to_string(i)));
for (int i = 0; i < 3; i++) for (int i = 0; i < 3; i++)
new_cell->addInput(ctx->id("LEDDADDR" + std::to_string(i))); new_cell->addInput(ctx->id("LEDDADDR" + std::to_string(i)));
new_cell->addInput(ctx->id("LEDDDEN")); new_cell->addInput(id_LEDDDEN);
new_cell->addInput(ctx->id("LEDDEXE")); new_cell->addInput(id_LEDDEXE);
new_cell->addInput(ctx->id("LEDDRST")); // doesn't actually exist, for icecube code compatibility new_cell->addInput(id_LEDDRST); // doesn't actually exist, for icecube code compatibility
// only // only
new_cell->addOutput(ctx->id("PWMOUT0")); new_cell->addOutput(id_PWMOUT0);
new_cell->addOutput(ctx->id("PWMOUT1")); new_cell->addOutput(id_PWMOUT1);
new_cell->addOutput(ctx->id("PWMOUT2")); new_cell->addOutput(id_PWMOUT2);
new_cell->addOutput(ctx->id("LEDDON")); new_cell->addOutput(id_LEDDON);
} else if (type == ctx->id("SB_I2C")) { } else if (type == id_SB_I2C) {
new_cell->params[ctx->id("I2C_SLAVE_INIT_ADDR")] = std::string("0b1111100001"); new_cell->params[id_I2C_SLAVE_INIT_ADDR] = std::string("0b1111100001");
new_cell->params[ctx->id("BUS_ADDR74")] = std::string("0b0001"); new_cell->params[id_BUS_ADDR74] = std::string("0b0001");
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
new_cell->addInput(ctx->id("SBADRI" + std::to_string(i))); new_cell->addInput(ctx->id("SBADRI" + std::to_string(i)));
new_cell->addInput(ctx->id("SBDATI" + 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->addOutput(ctx->id("SBDATO" + std::to_string(i)));
} }
new_cell->addInput(ctx->id("SBCLKI")); new_cell->addInput(id_SBCLKI);
new_cell->addInput(ctx->id("SBRWI")); new_cell->addInput(id_SBRWI);
new_cell->addInput(ctx->id("SBSTBI")); new_cell->addInput(id_SBSTBI);
new_cell->addInput(ctx->id("SCLI")); new_cell->addInput(id_SCLI);
new_cell->addInput(ctx->id("SDAI")); new_cell->addInput(id_SDAI);
new_cell->addOutput(ctx->id("SBACKO")); new_cell->addOutput(id_SBACKO);
new_cell->addOutput(ctx->id("I2CIRQ")); new_cell->addOutput(id_I2CIRQ);
new_cell->addOutput(ctx->id("I2CWKUP")); new_cell->addOutput(id_I2CWKUP);
new_cell->addOutput(ctx->id("SCLO")); new_cell->addOutput(id_SCLO);
new_cell->addOutput(ctx->id("SCLOE")); new_cell->addOutput(id_SCLOE);
new_cell->addOutput(ctx->id("SDAO")); new_cell->addOutput(id_SDAO);
new_cell->addOutput(ctx->id("SDAOE")); new_cell->addOutput(id_SDAOE);
} else if (type == ctx->id("SB_SPI")) { } else if (type == id_SB_SPI) {
new_cell->params[ctx->id("BUS_ADDR74")] = std::string("0b0000"); new_cell->params[id_BUS_ADDR74] = std::string("0b0000");
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
new_cell->addInput(ctx->id("SBADRI" + std::to_string(i))); new_cell->addInput(ctx->id("SBADRI" + std::to_string(i)));
new_cell->addInput(ctx->id("SBDATI" + 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->addOutput(ctx->id("SBDATO" + std::to_string(i)));
} }
new_cell->addInput(ctx->id("SBCLKI")); new_cell->addInput(id_SBCLKI);
new_cell->addInput(ctx->id("SBRWI")); new_cell->addInput(id_SBRWI);
new_cell->addInput(ctx->id("SBSTBI")); new_cell->addInput(id_SBSTBI);
new_cell->addInput(ctx->id("MI")); new_cell->addInput(id_MI);
new_cell->addInput(ctx->id("SI")); new_cell->addInput(id_SI);
new_cell->addInput(ctx->id("SCKI")); new_cell->addInput(id_SCKI);
new_cell->addInput(ctx->id("SCSNI")); new_cell->addInput(id_SCSNI);
new_cell->addOutput(ctx->id("SBACKO")); new_cell->addOutput(id_SBACKO);
new_cell->addOutput(ctx->id("SPIIRQ")); new_cell->addOutput(id_SPIIRQ);
new_cell->addOutput(ctx->id("SPIWKUP")); new_cell->addOutput(id_SPIWKUP);
new_cell->addOutput(ctx->id("SO")); new_cell->addOutput(id_SO);
new_cell->addOutput(ctx->id("SOE")); new_cell->addOutput(id_SOE);
new_cell->addOutput(ctx->id("MO")); new_cell->addOutput(id_MO);
new_cell->addOutput(ctx->id("MOE")); new_cell->addOutput(id_MOE);
new_cell->addOutput(ctx->id("SCKO")); new_cell->addOutput(id_SCKO);
new_cell->addOutput(ctx->id("SCKOE")); new_cell->addOutput(id_SCKOE);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
new_cell->addOutput(ctx->id("MCSNO" + std::to_string(i))); new_cell->addOutput(ctx->id("MCSNO" + std::to_string(i)));
new_cell->addOutput(ctx->id("MCSNOE" + 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()) if (lc->hierpath == IdString())
lc->hierpath = lut->hierpath; lc->hierpath = lut->hierpath;
lc->params[ctx->id("LUT_INIT")] = lut->params[ctx->id("LUT_INIT")].extract(0, 16, Property::State::S0); lc->params[id_LUT_INIT] = lut->params[id_LUT_INIT].extract(0, 16, Property::State::S0);
replace_port(lut, ctx->id("I0"), lc, ctx->id("I0")); replace_port(lut, id_I0, lc, id_I0);
replace_port(lut, ctx->id("I1"), lc, ctx->id("I1")); replace_port(lut, id_I1, lc, id_I1);
replace_port(lut, ctx->id("I2"), lc, ctx->id("I2")); replace_port(lut, id_I2, lc, id_I2);
replace_port(lut, ctx->id("I3"), lc, ctx->id("I3")); replace_port(lut, id_I3, lc, id_I3);
if (no_dff) { if (no_dff) {
replace_port(lut, ctx->id("O"), lc, ctx->id("O")); replace_port(lut, id_O, lc, id_O);
lc->params[ctx->id("DFF_ENABLE")] = Property::State::S0; 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()) if (lc->hierpath == IdString())
lc->hierpath = dff->hierpath; 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); std::string config = dff->type.str(ctx).substr(6);
auto citer = config.begin(); 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') { if (citer != config.end() && *citer == 'N') {
lc->params[ctx->id("NEG_CLK")] = Property::State::S1; lc->params[id_NEG_CLK] = Property::State::S1;
++citer; ++citer;
} else { } else {
lc->params[ctx->id("NEG_CLK")] = Property::State::S0; lc->params[id_NEG_CLK] = Property::State::S0;
} }
if (citer != config.end() && *citer == 'E') { 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; ++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) { if ((config.end() - citer) >= 2) {
char c = *(citer++); char c = *(citer++);
NPNR_ASSERT(c == 'S'); NPNR_ASSERT(c == 'S');
lc->params[ctx->id("ASYNC_SR")] = Property::State::S0; lc->params[id_ASYNC_SR] = Property::State::S0;
} else { } else {
lc->params[ctx->id("ASYNC_SR")] = Property::State::S1; lc->params[id_ASYNC_SR] = Property::State::S1;
} }
if (*citer == 'S') { if (*citer == 'S') {
citer++; citer++;
replace_port(dff, ctx->id("S"), lc, ctx->id("SR")); replace_port(dff, id_S, lc, id_SR);
lc->params[ctx->id("SET_NORESET")] = Property::State::S1; lc->params[id_SET_NORESET] = Property::State::S1;
} else { } else {
NPNR_ASSERT(*citer == 'R'); NPNR_ASSERT(*citer == 'R');
citer++; citer++;
replace_port(dff, ctx->id("R"), lc, ctx->id("SR")); replace_port(dff, id_R, lc, id_SR);
lc->params[ctx->id("SET_NORESET")] = Property::State::S0; lc->params[id_SET_NORESET] = Property::State::S0;
} }
} }
NPNR_ASSERT(citer == config.end()); NPNR_ASSERT(citer == config.end());
if (pass_thru_lut) { if (pass_thru_lut) {
lc->params[ctx->id("LUT_INIT")] = Property(2, 16); lc->params[id_LUT_INIT] = Property(2, 16);
replace_port(dff, ctx->id("D"), lc, ctx->id("I0")); 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) void nxio_to_sb(Context *ctx, CellInfo *nxio, CellInfo *sbio, pool<IdString> &todelete_cells)
{ {
if (nxio->type == ctx->id("$nextpnr_ibuf")) { if (nxio->type == ctx->id("$nextpnr_ibuf")) {
sbio->params[ctx->id("PIN_TYPE")] = 1; sbio->params[id_PIN_TYPE] = 1;
auto pu_attr = nxio->attrs.find(ctx->id("PULLUP")); auto pu_attr = nxio->attrs.find(id_PULLUP);
if (pu_attr != nxio->attrs.end()) if (pu_attr != nxio->attrs.end())
sbio->params[ctx->id("PULLUP")] = pu_attr->second; sbio->params[id_PULLUP] = pu_attr->second;
replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0")); replace_port(nxio, id_O, sbio, id_D_IN_0);
} else if (nxio->type == ctx->id("$nextpnr_obuf")) { } else if (nxio->type == ctx->id("$nextpnr_obuf")) {
sbio->params[ctx->id("PIN_TYPE")] = 25; sbio->params[id_PIN_TYPE] = 25;
replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0")); replace_port(nxio, id_I, sbio, id_D_OUT_0);
} else if (nxio->type == ctx->id("$nextpnr_iobuf")) { } else if (nxio->type == ctx->id("$nextpnr_iobuf")) {
// N.B. tristate will be dealt with below // 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) if (i == nullptr || i->driver.cell == nullptr)
sbio->params[ctx->id("PIN_TYPE")] = 1; sbio->params[id_PIN_TYPE] = 1;
else else
sbio->params[ctx->id("PIN_TYPE")] = 25; sbio->params[id_PIN_TYPE] = 25;
auto pu_attr = nxio->attrs.find(ctx->id("PULLUP")); auto pu_attr = nxio->attrs.find(id_PULLUP);
if (pu_attr != nxio->attrs.end()) if (pu_attr != nxio->attrs.end())
sbio->params[ctx->id("PULLUP")] = pu_attr->second; sbio->params[id_PULLUP] = pu_attr->second;
replace_port(nxio, ctx->id("I"), sbio, ctx->id("D_OUT_0")); replace_port(nxio, id_I, sbio, id_D_OUT_0);
replace_port(nxio, ctx->id("O"), sbio, ctx->id("D_IN_0")); replace_port(nxio, id_O, sbio, id_D_IN_0);
} else { } else {
NPNR_ASSERT(false); 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 // Rename I/O nets to avoid conflicts
if (donet != nullptr && donet->name == nxio->name) 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)); NPNR_ASSERT(!ctx->nets.count(tn_netname));
ctx->net_aliases.erase(tn_netname); ctx->net_aliases.erase(tn_netname);
NetInfo *toplevel_net = ctx->createNet(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; ctx->ports[nxio->name].net = toplevel_net;
} }
CellInfo *tbuf = net_driven_by( CellInfo *tbuf = net_driven_by(
ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); }, ctx, donet, [](const Context *ctx, const CellInfo *cell) { return cell->type == ctx->id("$_TBUF_"); },
ctx->id("Y")); id_Y);
if (tbuf) { if (tbuf) {
sbio->params[ctx->id("PIN_TYPE")] = 41; sbio->params[id_PIN_TYPE] = 41;
replace_port(tbuf, ctx->id("A"), sbio, ctx->id("D_OUT_0")); replace_port(tbuf, id_A, sbio, id_D_OUT_0);
replace_port(tbuf, ctx->id("E"), sbio, ctx->id("OUTPUT_ENABLE")); replace_port(tbuf, id_E, sbio, id_OUTPUT_ENABLE);
if (donet->users.size() > 1) { if (donet->users.size() > 1) {
for (auto user : donet->users) 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) 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; return 2;
if (cell->type == ctx->id("SB_PLL40_2_PAD")) if (cell->type == id_SB_PLL40_2_PAD)
return 4; return 4;
if (cell->type == ctx->id("SB_PLL40_2F_PAD")) if (cell->type == id_SB_PLL40_2F_PAD)
return 6; return 6;
if (cell->type == ctx->id("SB_PLL40_CORE")) if (cell->type == id_SB_PLL40_CORE)
return 3; return 3;
if (cell->type == ctx->id("SB_PLL40_2F_CORE")) if (cell->type == id_SB_PLL40_2F_CORE)
return 7; return 7;
NPNR_ASSERT(0); NPNR_ASSERT(0);
} }
@ -495,15 +495,14 @@ bool is_clock_port(const BaseCtx *ctx, const PortRef &port)
if (port.cell == nullptr) if (port.cell == nullptr)
return false; return false;
if (is_ff(ctx, port.cell)) if (is_ff(ctx, port.cell))
return port.port == ctx->id("C"); return port.port == id_C;
if (port.cell->type == ctx->id("ICESTORM_LC")) if (port.cell->type == id_ICESTORM_LC)
return port.port == ctx->id("CLK"); return port.port == id_CLK;
if (is_ram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_RAM")) if (is_ram(ctx, port.cell) || port.cell->type == id_ICESTORM_RAM)
return port.port == ctx->id("RCLK") || port.port == ctx->id("WCLK") || port.port == ctx->id("RCLKN") || return port.port == id_RCLK || port.port == id_WCLK || port.port == id_RCLKN || port.port == id_WCLKN;
port.port == ctx->id("WCLKN"); if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) return port.port == id_CLK;
return port.port == ctx->id("CLK"); if (is_sb_spram(ctx, port.cell) || port.cell->type == id_ICESTORM_SPRAM)
if (is_sb_spram(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_SPRAM"))
return port.port == id_CLOCK; return port.port == id_CLOCK;
if (is_sb_io(ctx, port.cell)) if (is_sb_io(ctx, port.cell))
return port.port == id_INPUT_CLK || port.port == id_OUTPUT_CLK; 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) if (port.cell == nullptr)
return false; return false;
if (is_ff(ctx, port.cell)) if (is_ff(ctx, port.cell))
return port.port == ctx->id("R") || port.port == ctx->id("S"); return port.port == id_R || port.port == id_S;
if (port.cell->type == ctx->id("ICESTORM_LC")) if (port.cell->type == id_ICESTORM_LC)
return port.port == ctx->id("SR"); return port.port == id_SR;
if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
return port.port == ctx->id("IRSTTOP") || port.port == ctx->id("IRSTBOT") || port.port == ctx->id("ORSTTOP") || return port.port == id_IRSTTOP || port.port == id_IRSTBOT || port.port == id_ORSTTOP || port.port == id_ORSTBOT;
port.port == ctx->id("ORSTBOT");
return false; return false;
} }
@ -529,12 +527,12 @@ bool is_enable_port(const BaseCtx *ctx, const PortRef &port)
if (port.cell == nullptr) if (port.cell == nullptr)
return false; return false;
if (is_ff(ctx, port.cell)) if (is_ff(ctx, port.cell))
return port.port == ctx->id("E"); return port.port == id_E;
if (port.cell->type == ctx->id("ICESTORM_LC")) if (port.cell->type == id_ICESTORM_LC)
return port.port == ctx->id("CEN"); return port.port == id_CEN;
// FIXME // FIXME
// if (is_sb_mac16(ctx, port.cell) || port.cell->type == ctx->id("ICESTORM_DSP")) // if (is_sb_mac16(ctx, port.cell) || port.cell->type == id_ICESTORM_DSP)
// return port.port == ctx->id("CE"); // return port.port == id_CE;
return false; return false;
} }

View File

@ -30,90 +30,80 @@ NEXTPNR_NAMESPACE_BEGIN
std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = ""); std::unique_ptr<CellInfo> create_ice_cell(Context *ctx, IdString type, std::string name = "");
// Return true if a cell is a LUT // 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 // Return true if a cell is a flipflop
inline bool is_ff(const BaseCtx *ctx, const CellInfo *cell) 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") || return cell->type == id_SB_DFF || cell->type == id_SB_DFFE || cell->type == id_SB_DFFSR ||
cell->type == ctx->id("SB_DFFR") || cell->type == ctx->id("SB_DFFSS") || cell->type == ctx->id("SB_DFFS") || cell->type == id_SB_DFFR || cell->type == id_SB_DFFSS || cell->type == id_SB_DFFS ||
cell->type == ctx->id("SB_DFFESR") || cell->type == ctx->id("SB_DFFER") || cell->type == id_SB_DFFESR || cell->type == id_SB_DFFER || cell->type == id_SB_DFFESS ||
cell->type == ctx->id("SB_DFFESS") || cell->type == ctx->id("SB_DFFES") || cell->type == id_SB_DFFES || cell->type == id_SB_DFFN || cell->type == id_SB_DFFNE ||
cell->type == ctx->id("SB_DFFN") || cell->type == ctx->id("SB_DFFNE") || cell->type == id_SB_DFFNSR || cell->type == id_SB_DFFNR || cell->type == id_SB_DFFNSS ||
cell->type == ctx->id("SB_DFFNSR") || cell->type == ctx->id("SB_DFFNR") || cell->type == id_SB_DFFNS || cell->type == id_SB_DFFNESR || cell->type == id_SB_DFFNER ||
cell->type == ctx->id("SB_DFFNSS") || cell->type == ctx->id("SB_DFFNS") || cell->type == id_SB_DFFNESS || cell->type == id_SB_DFFNES;
cell->type == ctx->id("SB_DFFNESR") || cell->type == ctx->id("SB_DFFNER") ||
cell->type == ctx->id("SB_DFFNESS") || cell->type == ctx->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 // 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 // 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 // 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 // Return true if a cell is a RAM
inline bool is_ram(const BaseCtx *ctx, const CellInfo *cell) 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") || return cell->type == id_SB_RAM40_4K || cell->type == id_SB_RAM40_4KNR || cell->type == id_SB_RAM40_4KNW ||
cell->type == ctx->id("SB_RAM40_4KNW") || cell->type == ctx->id("SB_RAM40_4KNRNW"); 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) inline bool is_sb_led_drv_cur(const BaseCtx *ctx, const CellInfo *cell) { return cell->type == id_SB_LED_DRV_CUR; }
{
return cell->type == ctx->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) 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") || return cell->type == id_SB_PLL40_PAD || cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD ||
cell->type == ctx->id("SB_PLL40_2F_PAD") || cell->type == ctx->id("SB_PLL40_CORE") || cell->type == id_SB_PLL40_CORE || cell->type == id_SB_PLL40_2F_CORE;
cell->type == ctx->id("SB_PLL40_2F_CORE");
} }
inline bool is_sb_pll40_pad(const BaseCtx *ctx, const CellInfo *cell) 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") || return cell->type == id_SB_PLL40_PAD || cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD ||
cell->type == ctx->id("SB_PLL40_2F_PAD") || (cell->type == id_ICESTORM_PLL && (cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_PAD" ||
(cell->type == ctx->id("ICESTORM_PLL") && cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2_PAD" ||
(cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_PAD" || cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_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"));
} }
inline bool is_sb_pll40_dual(const BaseCtx *ctx, const CellInfo *cell) 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") || return cell->type == id_SB_PLL40_2_PAD || cell->type == id_SB_PLL40_2F_PAD || cell->type == id_SB_PLL40_2F_CORE ||
cell->type == ctx->id("SB_PLL40_2F_CORE") || (cell->type == id_ICESTORM_PLL && (cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2_PAD" ||
(cell->type == ctx->id("ICESTORM_PLL") && cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_PAD" ||
(cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2_PAD" || cell->attrs.at(id_TYPE).as_string() == "SB_PLL40_2F_CORE"));
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2F_PAD" ||
cell->attrs.at(ctx->id("TYPE")).as_string() == "SB_PLL40_2F_CORE"));
} }
uint8_t sb_pll40_type(const BaseCtx *ctx, const CellInfo *cell); uint8_t sb_pll40_type(const BaseCtx *ctx, const CellInfo *cell);

View File

@ -53,9 +53,9 @@ class ChainConstrainer
tile.clear(); tile.clear();
chains.emplace_back(); chains.emplace_back();
start_of_chain = false; 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 // 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); chains.back().cells.push_back(feedin);
tile.push_back(feedin); tile.push_back(feedin);
++feedio_lcs; ++feedio_lcs;
@ -66,18 +66,18 @@ class ChainConstrainer
bool split_chain = (!ctx->logic_cells_compatible(tile.data(), tile.size())) || bool split_chain = (!ctx->logic_cells_compatible(tile.data(), tile.size())) ||
(int(chains.back().cells.size()) > max_length); (int(chains.back().cells.size()) > max_length);
if (split_chain) { 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(); tile.pop_back();
chains.back().cells.back() = passout; chains.back().cells.back() = passout;
start_of_chain = true; start_of_chain = true;
} else { } 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); bool at_end = (curr_cell == carryc.cells.end() - 1);
if (carry_net != nullptr && (carry_net->users.size() > 1 || at_end)) { if (carry_net != nullptr && (carry_net->users.size() > 1 || at_end)) {
if (carry_net->users.size() > 2 || 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, id_I3, false) !=
net_only_drives(ctx, carry_net, is_lc, ctx->id("CIN"), false)) || net_only_drives(ctx, carry_net, is_lc, id_CIN, false)) ||
(at_end && !net_only_drives(ctx, carry_net, is_lc, ctx->id("I3"), true))) { (at_end && !net_only_drives(ctx, carry_net, is_lc, id_I3, true))) {
if (ctx->debug) if (ctx->debug)
log_info(" inserting feed-%s\n", at_end ? "out" : "out-in"); log_info(" inserting feed-%s\n", at_end ? "out" : "out-in");
CellInfo *passout; CellInfo *passout;
@ -89,10 +89,10 @@ class ChainConstrainer
tile.pop_back(); tile.pop_back();
if (split_chain_next) if (split_chain_next)
start_of_chain = true; 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)); split_chain_next ? nullptr : *(curr_cell + 1));
} else { } 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); chains.back().cells.push_back(passout);
@ -110,9 +110,9 @@ class ChainConstrainer
CellInfo *make_carry_pass_out(PortInfo &cout_port, CellInfo *cin_cell = nullptr) CellInfo *make_carry_pass_out(PortInfo &cout_port, CellInfo *cin_cell = nullptr)
{ {
NPNR_ASSERT(cout_port.net != nullptr); NPNR_ASSERT(cout_port.net != nullptr);
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, id_ICESTORM_LC);
lc->params[ctx->id("LUT_INIT")] = Property(65280, 16); // 0xff00: O = I3 lc->params[id_LUT_INIT] = Property(65280, 16); // 0xff00: O = I3
lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1; lc->params[id_CARRY_ENABLE] = Property::State::S1;
lc->ports.at(id_O).net = cout_port.net; lc->ports.at(id_O).net = cout_port.net;
NetInfo *co_i3_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$I3")); NetInfo *co_i3_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$I3"));
co_i3_net->driver = cout_port.net->driver; 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) CellInfo *make_carry_feed_in(CellInfo *cin_cell, PortInfo &cin_port)
{ {
NPNR_ASSERT(cin_port.net != nullptr); NPNR_ASSERT(cin_port.net != nullptr);
std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, ctx->id("ICESTORM_LC")); std::unique_ptr<CellInfo> lc = create_ice_cell(ctx, id_ICESTORM_LC);
lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1; lc->params[id_CARRY_ENABLE] = Property::State::S1;
lc->params[ctx->id("CIN_CONST")] = Property::State::S1; lc->params[id_CIN_CONST] = Property::State::S1;
lc->params[ctx->id("CIN_SET")] = Property::State::S1; lc->params[id_CIN_SET] = Property::State::S1;
lc->ports.at(ctx->id("I1")).net = cin_port.net; 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_port.net->users.erase(std::remove_if(cin_port.net->users.begin(), cin_port.net->users.end(),
[cin_cell, cin_port](const PortRef &usr) { [cin_cell, cin_port](const PortRef &usr) {
return usr.cell == cin_cell && usr.port == cin_port.name; return usr.cell == cin_cell && usr.port == cin_port.name;
@ -189,16 +189,16 @@ class ChainConstrainer
PortRef i1_ref; PortRef i1_ref;
i1_ref.cell = lc.get(); i1_ref.cell = lc.get();
i1_ref.port = ctx->id("I1"); i1_ref.port = id_I1;
lc->ports.at(ctx->id("I1")).net->users.push_back(i1_ref); lc->ports.at(id_I1).net->users.push_back(i1_ref);
NetInfo *out_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$O")); NetInfo *out_net = ctx->createNet(ctx->id(lc->name.str(ctx) + "$O"));
PortRef drv_ref; PortRef drv_ref;
drv_ref.port = ctx->id("COUT"); drv_ref.port = id_COUT;
drv_ref.cell = lc.get(); drv_ref.cell = lc.get();
out_net->driver = drv_ref; 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; PortRef usr_ref;
usr_ref.port = cin_port.name; usr_ref.port = cin_port.name;
@ -219,22 +219,19 @@ class ChainConstrainer
[](const Context *ctx, const [](const Context *ctx, const
CellInfo *cell) { CellInfo *cell) {
CellInfo *carry_prev = CellInfo *carry_prev = net_driven_by(ctx, cell->ports.at(id_CIN).net, is_lc, id_COUT);
net_driven_by(ctx, cell->ports.at(ctx->id("CIN")).net, is_lc, ctx->id("COUT"));
if (carry_prev != nullptr) if (carry_prev != nullptr)
return carry_prev; 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) if (i3_prev != nullptr)
return i3_prev; return i3_prev;
return (CellInfo *)nullptr; return (CellInfo *)nullptr;
}, },
[](const Context *ctx, const CellInfo *cell) { [](const Context *ctx, const CellInfo *cell) {
CellInfo *carry_next = CellInfo *carry_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_CIN, false);
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("CIN"), false);
if (carry_next != nullptr) if (carry_next != nullptr)
return carry_next; return carry_next;
CellInfo *i3_next = CellInfo *i3_next = net_only_drives(ctx, cell->ports.at(id_COUT).net, is_lc, id_I3, false);
net_only_drives(ctx, cell->ports.at(ctx->id("COUT")).net, is_lc, ctx->id("I3"), false);
if (i3_next != nullptr) if (i3_next != nullptr)
return i3_next; return i3_next;
return (CellInfo *)nullptr; return (CellInfo *)nullptr;
@ -249,7 +246,7 @@ class ChainConstrainer
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (chained.find(cell.first) == chained.end() && is_lc(ctx, ci) && 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; CellChain sChain;
sChain.cells.push_back(ci); sChain.cells.push_back(ci);
chained.insert(cell.first); chained.insert(cell.first);

View File

@ -448,4 +448,168 @@ X(SB_RGB_DRV)
X(DFF_ENABLE) X(DFF_ENABLE)
X(CARRY_ENABLE) X(CARRY_ENABLE)
X(NEG_CLK) X(NEG_CLK)
X(IO_STANDARD) 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)

View File

@ -265,13 +265,13 @@ std::unique_ptr<Context> Ice40CommandHandler::createContext(dict<std::string, Pr
ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package; ctx->settings[ctx->id("arch.package")] = ctx->archArgs().package;
if (vm.count("promote-logic")) 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")) 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")) 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")) 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; return ctx;
} }

View File

@ -41,7 +41,7 @@ static void pack_lut_lutffs(Context *ctx)
if (ctx->verbose) if (ctx->verbose)
log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx)); log_info("cell '%s' is of type '%s'\n", ci->name.c_str(ctx), ci->type.c_str(ctx));
if (is_lut(ctx, ci)) { 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) for (auto &attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
packed_cells.insert(ci->name); 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)); 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 // See if we can pack into a DFF
// TODO: LUT cascade // TODO: LUT cascade
NetInfo *o = ci->ports.at(ctx->id("O")).net; NetInfo *o = ci->ports.at(id_O).net;
CellInfo *dff = net_only_drives(ctx, o, is_ff, ctx->id("D"), true); CellInfo *dff = net_only_drives(ctx, o, is_ff, id_D, true);
auto lut_bel = ci->attrs.find(ctx->id("BEL")); auto lut_bel = ci->attrs.find(id_BEL);
bool packed_dff = false; bool packed_dff = false;
if (dff) { if (dff) {
if (ctx->verbose) if (ctx->verbose)
log_info("found attached dff %s\n", dff->name.c_str(ctx)); 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) { if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack // Locations don't match, can't pack
} else { } else {
@ -65,10 +65,10 @@ static void pack_lut_lutffs(Context *ctx)
++lut_and_ff; ++lut_and_ff;
ctx->nets.erase(o->name); ctx->nets.erase(o->name);
if (dff_bel != dff->attrs.end()) 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) { for (const auto &attr : dff->attrs) {
// BEL is dealt with specially // BEL is dealt with specially
if (attr.first != ctx->id("BEL")) if (attr.first != id_BEL)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
} }
packed_cells.insert(dff->name); packed_cells.insert(dff->name);
@ -106,8 +106,7 @@ static void pack_nonlut_ffs(Context *ctx)
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (is_ff(ctx, ci)) { if (is_ff(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LC, ci->name.str(ctx) + "_DFFLC");
create_ice_cell(ctx, ctx->id("ICESTORM_LC"), ci->name.str(ctx) + "_DFFLC");
for (auto &attr : ci->attrs) for (auto &attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
if (ctx->verbose) if (ctx->verbose)
@ -155,25 +154,25 @@ static void pack_carries(Context *ctx)
CellInfo *carry_ci_lc; CellInfo *carry_ci_lc;
bool ci_value; 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) { if (ci_const) {
carry_ci_lc = nullptr; carry_ci_lc = nullptr;
} else { } 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; std::set<IdString> i0_matches, i1_matches;
NetInfo *i0_net = ci->ports.at(ctx->id("I0")).net; NetInfo *i0_net = ci->ports.at(id_I0).net;
NetInfo *i1_net = ci->ports.at(ctx->id("I1")).net; NetInfo *i1_net = ci->ports.at(id_I1).net;
// Find logic cells connected to both I0 and I1 // Find logic cells connected to both I0 and I1
if (i0_net) { if (i0_net) {
for (auto usr : i0_net->users) { 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() && if (ctx->cells.find(usr.cell->name) != ctx->cells.end() &&
exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) { exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) {
// This clause stops us double-packing cells // This clause stops us double-packing cells
i0_matches.insert(usr.cell->name); 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 is don't care when disconnected, duplicate I0
i1_matches.insert(usr.cell->name); i1_matches.insert(usr.cell->name);
} }
@ -183,12 +182,12 @@ static void pack_carries(Context *ctx)
} }
if (i1_net) { if (i1_net) {
for (auto usr : i1_net->users) { 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() && if (ctx->cells.find(usr.cell->name) != ctx->cells.end() &&
exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) { exhausted_cells.find(usr.cell->name) == exhausted_cells.end()) {
// This clause stops us double-packing cells // This clause stops us double-packing cells
i1_matches.insert(usr.cell->name); 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 is don't care when disconnected, duplicate I1
i0_matches.insert(usr.cell->name); i0_matches.insert(usr.cell->name);
} }
@ -208,53 +207,53 @@ static void pack_carries(Context *ctx)
} else { } else {
// No LC to pack into matching I0/I1, insert a new one // No LC to pack into matching I0/I1, insert a new one
std::unique_ptr<CellInfo> created_lc = 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(); 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) { if (i0_net) {
PortRef pr; PortRef pr;
pr.cell = created_lc.get(); pr.cell = created_lc.get();
pr.port = ctx->id("I1"); pr.port = id_I1;
i0_net->users.push_back(pr); 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) { if (i1_net) {
PortRef pr; PortRef pr;
pr.cell = created_lc.get(); pr.cell = created_lc.get();
pr.port = ctx->id("I2"); pr.port = id_I2;
i1_net->users.push_back(pr); i1_net->users.push_back(pr);
} }
new_cells.push_back(std::move(created_lc)); new_cells.push_back(std::move(created_lc));
++carry_only; ++carry_only;
} }
carry_lc->params[ctx->id("CARRY_ENABLE")] = Property::State::S1; carry_lc->params[id_CARRY_ENABLE] = Property::State::S1;
replace_port(ci, ctx->id("CI"), carry_lc, ctx->id("CIN")); replace_port(ci, id_CI, carry_lc, id_CIN);
replace_port(ci, ctx->id("CO"), carry_lc, ctx->id("COUT")); replace_port(ci, id_CO, carry_lc, id_COUT);
if (i0_net) { if (i0_net) {
auto &i0_usrs = i0_net->users; auto &i0_usrs = i0_net->users;
i0_usrs.erase(std::remove_if(i0_usrs.begin(), i0_usrs.end(), [ci, ctx](const PortRef &pr) { 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) { if (i1_net) {
auto &i1_usrs = i1_net->users; auto &i1_usrs = i1_net->users;
i1_usrs.erase(std::remove_if(i1_usrs.begin(), i1_usrs.end(), [ci, ctx](const PortRef &pr) { 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 // Check for constant driver on CIN
if (carry_lc->ports.at(ctx->id("CIN")).net != nullptr) { if (carry_lc->ports.at(id_CIN).net != nullptr) {
IdString cin_net = carry_lc->ports.at(ctx->id("CIN")).net->name; 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")) { 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[id_CIN_CONST] = Property::State::S1;
carry_lc->params[ctx->id("CIN_SET")] = carry_lc->params[id_CIN_SET] =
cin_net == ctx->id("$PACKER_VCC_NET") ? Property::State::S1 : Property::State::S0; 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; auto &cin_users = ctx->nets.at(cin_net)->users;
cin_users.erase( cin_users.erase(
std::remove_if(cin_users.begin(), cin_users.end(), [carry_lc, ctx](const PortRef &pr) { 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) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (is_ram(ctx, ci)) { if (is_ram(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_RAM, ci->name.str(ctx) + "_RAM");
create_ice_cell(ctx, ctx->id("ICESTORM_RAM"), ci->name.str(ctx) + "_RAM");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
for (auto attr : ci->attrs) for (auto attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
for (auto param : ci->params) for (auto param : ci->params)
packed->params[param.first] = param.second; packed->params[param.first] = param.second;
packed->params[ctx->id("NEG_CLK_W")] = packed->params[id_NEG_CLK_W] = Property(ci->type == id_SB_RAM40_4KNW || ci->type == id_SB_RAM40_4KNRNW, 1);
Property(ci->type == ctx->id("SB_RAM40_4KNW") || ci->type == ctx->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->params[ctx->id("NEG_CLK_R")] = packed->type = id_ICESTORM_RAM;
Property(ci->type == ctx->id("SB_RAM40_4KNR") || ci->type == ctx->id("SB_RAM40_4KNRNW"), 1);
packed->type = ctx->id("ICESTORM_RAM");
for (auto port : ci->ports) { for (auto port : ci->ports) {
PortInfo &pi = port.second; PortInfo &pi = port.second;
std::string newname = pi.name.str(ctx); std::string newname = pi.name.str(ctx);
@ -300,9 +296,9 @@ static void pack_ram(Context *ctx)
if (bpos != std::string::npos) { if (bpos != std::string::npos) {
newname = newname.substr(0, bpos) + "_" + newname.substr(bpos + 1, (newname.size() - bpos) - 2); 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"; newname = "RCLK";
else if (pi.name == ctx->id("WCLKN")) else if (pi.name == id_WCLKN)
newname = "WCLK"; newname = "WCLK";
replace_port(ci, ctx->id(pi.name.c_str(ctx)), packed.get(), ctx->id(newname)); 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') && if ((is_lut(ctx, uc) || is_lc(ctx, uc) || is_carry(ctx, uc)) && (user.port.str(ctx).at(0) == 'I') &&
!constval) { !constval) {
uc->ports[user.port].net = nullptr; uc->ports[user.port].net = nullptr;
} else if ((is_sb_mac16(ctx, uc) || uc->type == ctx->id("ICESTORM_DSP")) && } else if ((is_sb_mac16(ctx, uc) || uc->type == id_ICESTORM_DSP) &&
(user.port != ctx->id("CLK") && (user.port != id_CLK &&
((constval && user.port == ctx->id("CE")) || (!constval && user.port != ctx->id("CE"))))) { ((constval && user.port == id_CE) || (!constval && user.port != id_CE)))) {
uc->ports[user.port].net = nullptr; uc->ports[user.port].net = nullptr;
} else if (is_ram(ctx, uc) && !constval && user.port != ctx->id("RCLK") && user.port != ctx->id("RCLKN") && } else if (is_ram(ctx, uc) && !constval && user.port != id_RCLK && user.port != id_RCLKN &&
user.port != ctx->id("WCLK") && user.port != ctx->id("WCLKN") && user.port != ctx->id("RCLKE") && user.port != id_WCLK && user.port != id_WCLKN && user.port != id_RCLKE &&
user.port != ctx->id("WCLKE")) { user.port != id_WCLKE) {
uc->ports[user.port].net = nullptr; uc->ports[user.port].net = nullptr;
} else { } else {
uc->ports[user.port].net = constnet; uc->ports[user.port].net = constnet;
@ -352,24 +348,24 @@ static void pack_constants(Context *ctx)
{ {
log_info("Packing constants..\n"); log_info("Packing constants..\n");
std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), "$PACKER_GND"); std::unique_ptr<CellInfo> gnd_cell = create_ice_cell(ctx, id_ICESTORM_LC, "$PACKER_GND");
gnd_cell->params[ctx->id("LUT_INIT")] = Property(0, 16); gnd_cell->params[id_LUT_INIT] = Property(0, 16);
auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET")); auto gnd_net = std::make_unique<NetInfo>(ctx->id("$PACKER_GND_NET"));
gnd_net->driver.cell = gnd_cell.get(); gnd_net->driver.cell = gnd_cell.get();
gnd_net->driver.port = ctx->id("O"); gnd_net->driver.port = id_O;
gnd_cell->ports.at(ctx->id("O")).net = gnd_net.get(); gnd_cell->ports.at(id_O).net = gnd_net.get();
NetInfo *gnd_net_info = gnd_net.get(); NetInfo *gnd_net_info = gnd_net.get();
if (ctx->nets.find(ctx->id("$PACKER_GND_NET")) != ctx->nets.end()) { 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(); 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"); std::unique_ptr<CellInfo> vcc_cell = create_ice_cell(ctx, id_ICESTORM_LC, "$PACKER_VCC");
vcc_cell->params[ctx->id("LUT_INIT")] = Property(1, 16); vcc_cell->params[id_LUT_INIT] = Property(1, 16);
auto vcc_net = std::make_unique<NetInfo>(ctx->id("$PACKER_VCC_NET")); auto vcc_net = std::make_unique<NetInfo>(ctx->id("$PACKER_VCC_NET"));
vcc_net->driver.cell = vcc_cell.get(); vcc_net->driver.cell = vcc_cell.get();
vcc_net->driver.port = ctx->id("O"); vcc_net->driver.port = id_O;
vcc_cell->ports.at(ctx->id("O")).net = vcc_net.get(); vcc_cell->ports.at(id_O).net = vcc_net.get();
NetInfo *vcc_net_info = vcc_net.get(); NetInfo *vcc_net_info = vcc_net.get();
if (ctx->nets.find(ctx->id("$PACKER_VCC_NET")) != ctx->nets.end()) { 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) { for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get(); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, gnd_net_info, false); set_net_constant(ctx, ni, gnd_net_info, false);
gnd_used = true; gnd_used = true;
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
ctx->cells.erase(drv_cell); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, vcc_net_info, true); set_net_constant(ctx, ni, vcc_net_info, true);
dead_nets.push_back(net.first); 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) std::string gbuf_name)
{ {
// Find the matching SB_GB BEL connected to the same global network // 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)); 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); BelId gb_bel = find_padin_gbuf(ctx, bel, port_name);
NPNR_ASSERT(gb_bel != BelId()); NPNR_ASSERT(gb_bel != BelId());
// Create a SB_GB Cell and lock it there // Create a SB_GB Cell and lock it there
std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, ctx->id("SB_GB"), gbuf_name); std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, id_SB_GB, gbuf_name);
gb->attrs[ctx->id("FOR_PAD_IN")] = Property::State::S1; gb->attrs[id_FOR_PAD_IN] = Property::State::S1;
gb->attrs[ctx->id("BEL")] = ctx->getBelName(gb_bel).str(ctx); gb->attrs[id_BEL] = ctx->getBelName(gb_bel).str(ctx);
// Reconnect the net to that port for easier identification it's a global net // 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); 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)) { if (is_nextpnr_iob(ctx, ci)) {
CellInfo *sb = nullptr, *rgb = nullptr; CellInfo *sb = nullptr, *rgb = nullptr;
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) { if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) {
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")) { } else if (ci->type == ctx->id("$nextpnr_obuf")) {
NetInfo *net = ci->ports.at(ctx->id("I")).net; NetInfo *net = ci->ports.at(id_I).net;
sb = net_only_drives(ctx, net, is_ice_iob, ctx->id("PACKAGE_PIN"), true, ci); sb = net_only_drives(ctx, net, is_ice_iob, id_PACKAGE_PIN, true, ci);
if (net && net->driver.cell && if (net && net->driver.cell &&
(is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell))) (is_sb_rgba_drv(ctx, net->driver.cell) || is_sb_rgb_drv(ctx, net->driver.cell)))
rgb = 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 // 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), 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)); 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")) && if (((ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_iobuf")) &&
net->users.size() > 1) || net->users.size() > 1) ||
(ci->type == ctx->id("$nextpnr_obuf") && (net->users.size() > 2 || net->driver.cell != nullptr))) (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) { } 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), 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)); rgb->name.c_str(ctx));
disconnect_port(ctx, ci, ctx->id("I")); disconnect_port(ctx, ci, id_I);
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
continue; continue;
} else { } else {
// Create a SB_IO buffer // Create a SB_IO buffer
std::unique_ptr<CellInfo> ice_cell = std::unique_ptr<CellInfo> ice_cell = create_ice_cell(ctx, id_SB_IO, ci->name.str(ctx) + "$sb_io");
create_ice_cell(ctx, ctx->id("SB_IO"), ci->name.str(ctx) + "$sb_io");
nxio_to_sb(ctx, ci, ice_cell.get(), packed_cells); nxio_to_sb(ctx, ci, ice_cell.get(), packed_cells);
new_cells.push_back(std::move(ice_cell)); new_cells.push_back(std::move(ice_cell));
sb = new_cells.back().get(); sb = new_cells.back().get();
@ -535,7 +530,7 @@ static void pack_io(Context *ctx)
for (auto &attr : ci->attrs) for (auto &attr : ci->attrs)
sb->attrs[attr.first] = attr.second; sb->attrs[attr.first] = attr.second;
} else if (is_sb_io(ctx, ci) || is_sb_gb_io(ctx, ci)) { } 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) || if ((net != nullptr) && ((net->users.size() > 2) ||
(net->driver.cell != nullptr && (net->driver.cell != nullptr &&
net->driver.cell->type == ctx->id("$nextpnr_obuf") && net->users.size() > 1))) 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)); new_cells.push_back(std::move(gb));
// Make it a normal SB_IO with global marker // Make it a normal SB_IO with global marker
ci->type = ctx->id("SB_IO"); ci->type = id_SB_IO;
ci->attrs[ctx->id("GLOBAL")] = Property::State::S1; ci->attrs[id_GLOBAL] = Property::State::S1;
} else if (is_sb_io(ctx, ci)) { } else if (is_sb_io(ctx, ci)) {
// Disconnect unused inputs // Disconnect unused inputs
NetInfo *net_in0 = ci->ports.count(id_D_IN_0) ? ci->ports[id_D_IN_0].net : nullptr; 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); 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::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); std::unique_ptr<CellInfo> gb = create_ice_cell(ctx, id_SB_GB, "$gbuf_" + glb_name);
gb->ports[ctx->id("USER_SIGNAL_TO_GLOBAL_BUFFER")].net = net; gb->ports[id_USER_SIGNAL_TO_GLOBAL_BUFFER].net = net;
PortRef pr; PortRef pr;
pr.cell = gb.get(); 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); net->users.push_back(pr);
pr.cell = gb.get(); 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)); NetInfo *glbnet = ctx->createNet(ctx->id(glb_name));
glbnet->driver = pr; 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; std::vector<PortRef> keep_users;
for (auto user : net->users) { for (auto user : net->users) {
if (is_clock_port(ctx, user) || (is_reset && is_reset_port(ctx, user)) || 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; --gbs_available;
/* And possibly limits what we can promote */ /* 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 */ /* 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); int glb_id = ctx->get_driven_glb_netwk(bel);
if ((glb_id % 2) == 0) if ((glb_id % 2) == 0)
resets_available--; 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 && 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_cen->second || prom_cens >= cens_available) &&
(global_logic->second > global_reset->second || prom_resets >= resets_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(); NetInfo *logicnet = ctx->nets[global_logic->first].get();
insert_global(ctx, logicnet, false, false, true, global_logic->second); insert_global(ctx, logicnet, false, false, true, global_logic->second);
++prom_globals; ++prom_globals;
@ -784,11 +779,11 @@ static void place_plls(Context *ctx)
continue; continue;
// If it's constrained already, add to already used list // If it's constrained already, add to already used list
if (ci->attrs.count(ctx->id("BEL"))) { if (ci->attrs.count(id_BEL)) {
BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[ctx->id("BEL")].as_string()); BelId bel_constrain = ctx->getBelByNameStr(ci->attrs[id_BEL].as_string());
if (pll_all_bels.count(bel_constrain) == 0) if (pll_all_bels.count(bel_constrain) == 0)
log_error("PLL '%s' is constrained to invalid BEL '%s'\n", ci->name.c_str(ctx), 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; pll_used_bels[bel_constrain] = ci;
} }
@ -802,10 +797,10 @@ static void place_plls(Context *ctx)
continue; continue;
// Check PACKAGEPIN connection // 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)); 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) 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)); 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)); ci->name.c_str(ctx), io_cell->type.c_str(ctx));
if (ni->users.size() != 1) 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)); 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), log_error("PLL '%s' PACKAGEPIN SB_IO '%s' is unconstrained\n", ci->name.c_str(ctx),
io_cell->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; BelId found_bel;
// Find the PLL BEL that would suit that connection // Find the PLL BEL that would suit that connection
@ -843,16 +838,16 @@ static void place_plls(Context *ctx)
} }
// Is it user constrained ? // Is it user constrained ?
if (ci->attrs.count(ctx->id("BEL"))) { if (ci->attrs.count(id_BEL)) {
// Yes. Check it actually matches ! // 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) 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 " log_error("PLL '%s' is user constrained to %s but can only be placed in %s based on its PACKAGEPIN "
"connection\n", "connection\n",
ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel)); ci->name.c_str(ctx), ctx->nameOfBel(bel_constrain), ctx->nameOfBel(found_bel));
} else { } else {
// No, we can constrain it ourselves // 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; pll_used_bels[found_bel] = ci;
} }
@ -867,15 +862,15 @@ static void place_plls(Context *ctx)
continue; continue;
// Only consider bound IO that are used as inputs // 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; continue;
if ((!io_ci->ports.count(id_D_IN_0) || (io_ci->ports[id_D_IN_0].net == nullptr)) && 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)) && (!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; continue;
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN) // 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) { for (auto placed_pll : pll_used_bels) {
BelPin pll_io_a, pll_io_b; BelPin pll_io_a, pll_io_b;
@ -905,11 +900,11 @@ static void place_plls(Context *ctx)
continue; continue;
// Only consider the bound ones // Only consider the bound ones
if (!gb_ci->attrs.count(ctx->id("BEL"))) if (!gb_ci->attrs.count(id_BEL))
continue; continue;
// Check all placed PLL (either forced by user, or forced by PACKAGEPIN) // 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) { for (auto placed_pll : pll_used_bels) {
CellInfo *ci = placed_pll.second; CellInfo *ci = placed_pll.second;
@ -967,8 +962,8 @@ static void place_plls(Context *ctx)
// Could this be a PAD PLL ? // Could this be a PAD PLL ?
bool could_be_pad = false; bool could_be_pad = false;
BelId pad_bel; BelId pad_bel;
if (ni->users.size() == 1 && is_sb_io(ctx, ni->driver.cell) && ni->driver.cell->attrs.count(ctx->id("BEL"))) 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[ctx->id("BEL")].as_string()); pad_bel = ctx->getBelByNameStr(ni->driver.cell->attrs[id_BEL].as_string());
// Find a BEL for it // Find a BEL for it
BelId found_bel; BelId found_bel;
@ -1002,7 +997,7 @@ static void place_plls(Context *ctx)
if (could_be_pad) if (could_be_pad)
log_info(" (given its connections, this PLL could have been a PAD PLL)\n"); 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; 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); NPNR_ASSERT(port.net != nullptr);
// Create pass-through LUT. // Create pass-through LUT.
std::unique_ptr<CellInfo> pt = create_ice_cell(ctx, ctx->id("ICESTORM_LC"), std::unique_ptr<CellInfo> pt =
ci->name.str(ctx) + "$nextpnr_" + portId.str(ctx) + "_lut_through"); create_ice_cell(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 pt->params[id_LUT_INIT] = Property(65280, 16); // output is always I3
// Create LUT output net. // Create LUT output net.
NetInfo *out_net = ctx->createNet(ctx->id(ci->name.str(ctx) + "$nextnr_" + portId.str(ctx) + "_lut_through_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.cell = pt.get();
out_net->driver.port = ctx->id("O"); out_net->driver.port = id_O;
pt->ports.at(ctx->id("O")).net = out_net; pt->ports.at(id_O).net = out_net;
// New users of the original cell's port // New users of the original cell's port
std::vector<PortRef> new_users; std::vector<PortRef> new_users;
for (const auto &user : port.net->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); new_users.push_back(user);
continue; continue;
} }
@ -1046,9 +1041,9 @@ static std::unique_ptr<CellInfo> spliceLUT(Context *ctx, CellInfo *ci, IdString
// Add LUT to new users. // Add LUT to new users.
PortRef pr; PortRef pr;
pr.cell = pt.get(); pr.cell = pt.get();
pr.port = ctx->id("I3"); pr.port = id_I3;
new_users.push_back(pr); 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. // Replace users of the original net.
port.net->users = new_users; port.net->users = new_users;
@ -1065,7 +1060,7 @@ static BelId cell_place_unique(Context *ctx, CellInfo *ci)
if (ctx->is_bel_locked(bel)) if (ctx->is_bel_locked(bel))
continue; continue;
IdStringList bel_name = ctx->getBelName(bel); 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)); log_info(" constrained %s '%s' to %s\n", ci->type.c_str(ctx), ci->name.c_str(ctx), ctx->nameOfBel(bel));
return bel; return bel;
} }
@ -1124,7 +1119,7 @@ static void pack_special(Context *ctx)
/* Force placement (no choices anyway) */ /* Force placement (no choices anyway) */
cell_place_unique(ctx, ci); 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) { for (auto &user : ledpu_net->users) {
if (!is_sb_rgb_drv(ctx, user.cell)) { 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"); 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; 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); ctx->nets.erase(ledpu_net->name);
} }
} }
for (auto &cell : ctx->cells) { for (auto &cell : ctx->cells) {
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (is_sb_lfosc(ctx, ci)) { if (is_sb_lfosc(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_LFOSC, ci->name.str(ctx) + "_OSC");
create_ice_cell(ctx, ctx->id("ICESTORM_LFOSC"), ci->name.str(ctx) + "_OSC");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
cell_place_unique(ctx, packed.get()); cell_place_unique(ctx, packed.get());
replace_port(ci, ctx->id("CLKLFEN"), packed.get(), ctx->id("CLKLFEN")); replace_port(ci, id_CLKLFEN, packed.get(), id_CLKLFEN);
replace_port(ci, ctx->id("CLKLFPU"), packed.get(), ctx->id("CLKLFPU")); replace_port(ci, id_CLKLFPU, packed.get(), id_CLKLFPU);
if (bool_or_default(ci->attrs, ctx->id("ROUTE_THROUGH_FABRIC"))) { if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
replace_port(ci, ctx->id("CLKLF"), packed.get(), ctx->id("CLKLF_FABRIC")); replace_port(ci, id_CLKLF, packed.get(), id_CLKLF_FABRIC);
set_period(ctx, packed.get(), ctx->id("CLKLF_FABRIC"), 100000000); // 10kHz set_period(ctx, packed.get(), id_CLKLF_FABRIC, 100000000); // 10kHz
} else { } 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 = 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 set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 100000000); // 10kHz
new_cells.push_back(std::move(gb)); new_cells.push_back(std::move(gb));
} }
new_cells.push_back(std::move(packed)); new_cells.push_back(std::move(packed));
} else if (is_sb_hfosc(ctx, ci)) { } else if (is_sb_hfosc(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_HFOSC, ci->name.str(ctx) + "_OSC");
create_ice_cell(ctx, ctx->id("ICESTORM_HFOSC"), ci->name.str(ctx) + "_OSC");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
cell_place_unique(ctx, packed.get()); cell_place_unique(ctx, packed.get());
packed->params[ctx->id("TRIM_EN")] = str_or_default(ci->params, ctx->id("TRIM_EN"), "0b0"); packed->params[id_TRIM_EN] = str_or_default(ci->params, id_TRIM_EN, "0b0");
packed->params[ctx->id("CLKHF_DIV")] = str_or_default(ci->params, ctx->id("CLKHF_DIV"), "0b00"); packed->params[id_CLKHF_DIV] = str_or_default(ci->params, id_CLKHF_DIV, "0b00");
replace_port(ci, ctx->id("CLKHFEN"), packed.get(), ctx->id("CLKHFEN")); replace_port(ci, id_CLKHFEN, packed.get(), id_CLKHFEN);
replace_port(ci, ctx->id("CLKHFPU"), packed.get(), ctx->id("CLKHFPU")); replace_port(ci, id_CLKHFPU, packed.get(), id_CLKHFPU);
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
auto port = ctx->id("TRIM" + std::to_string(i)); auto port = ctx->id("TRIM" + std::to_string(i));
replace_port(ci, port, packed.get(), port); 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; int frequency;
if (div == "0b00") if (div == "0b00")
frequency = 48; frequency = 48;
@ -1182,20 +1175,19 @@ static void pack_special(Context *ctx)
frequency = 6; frequency = 6;
else else
log_error("Invalid HFOSC divider value '%s' - expecting 0b00, 0b01, 0b10 or 0b11\n", div.c_str()); 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"))) { if (bool_or_default(ci->attrs, id_ROUTE_THROUGH_FABRIC)) {
replace_port(ci, ctx->id("CLKHF"), packed.get(), ctx->id("CLKHF_FABRIC")); replace_port(ci, id_CLKHF, packed.get(), id_CLKHF_FABRIC);
set_period(ctx, packed.get(), ctx->id("CLKHF_FABRIC"), 1000000 / frequency); set_period(ctx, packed.get(), id_CLKHF_FABRIC, 1000000 / frequency);
} else { } 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 = 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); set_period(ctx, gb.get(), id_GLOBAL_BUFFER_OUTPUT, 1000000 / frequency);
new_cells.push_back(std::move(gb)); new_cells.push_back(std::move(gb));
} }
new_cells.push_back(std::move(packed)); new_cells.push_back(std::move(packed));
} else if (is_sb_spram(ctx, ci)) { } else if (is_sb_spram(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_SPRAM, ci->name.str(ctx) + "_RAM");
create_ice_cell(ctx, ctx->id("ICESTORM_SPRAM"), ci->name.str(ctx) + "_RAM");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
for (auto attr : ci->attrs) for (auto attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
@ -1210,8 +1202,7 @@ static void pack_special(Context *ctx)
} }
new_cells.push_back(std::move(packed)); new_cells.push_back(std::move(packed));
} else if (is_sb_mac16(ctx, ci)) { } else if (is_sb_mac16(ctx, ci)) {
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_DSP, ci->name.str(ctx) + "_DSP");
create_ice_cell(ctx, ctx->id("ICESTORM_DSP"), ci->name.str(ctx) + "_DSP");
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
for (auto attr : ci->attrs) for (auto attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
@ -1241,7 +1232,7 @@ static void pack_special(Context *ctx)
if (net == nullptr) if (net == nullptr)
continue; 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; continue;
if (net->users.size() > 0) 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) 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"); 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(id_RGBPU);
ci->ports.erase(ctx->id("RGB0")); ci->ports.erase(id_RGB0);
ci->ports.erase(ctx->id("RGB1")); ci->ports.erase(id_RGB1);
ci->ports.erase(ctx->id("RGB2")); ci->ports.erase(id_RGB2);
} else if (is_sb_ledda_ip(ctx, ci)) { } else if (is_sb_ledda_ip(ctx, ci)) {
/* Force placement (no choices anyway) */ /* Force placement (no choices anyway) */
cell_place_unique(ctx, ci); 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::make_tuple(id_SB_I2C, "0b0011"), Loc(25, 31, 0)},
}; };
std::string bus_addr74 = 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()) 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), log_error("Invalid value for BUS_ADDR74 for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
ci->type.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), log_error("Unable to find placement for cell '%s' of type '%s'\n", ci->name.c_str(ctx),
ci->type.c_str(ctx)); ci->type.c_str(ctx));
IdStringList bel_name = ctx->getBelName(bel); 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)); 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_pad = is_sb_pll40_pad(ctx, ci);
bool is_core = !is_pad; bool is_core = !is_pad;
std::unique_ptr<CellInfo> packed = std::unique_ptr<CellInfo> packed = create_ice_cell(ctx, id_ICESTORM_PLL, ci->name.str(ctx) + "_PLL");
create_ice_cell(ctx, ctx->id("ICESTORM_PLL"), ci->name.str(ctx) + "_PLL"); packed->attrs[id_TYPE] = ci->type.str(ctx);
packed->attrs[ctx->id("TYPE")] = ci->type.str(ctx);
packed_cells.insert(ci->name); packed_cells.insert(ci->name);
if (!is_sb_pll40_dual(ctx, ci)) { if (!is_sb_pll40_dual(ctx, ci)) {
// Remove second output, so a buffer isn't created for it, for these // Remove second output, so a buffer isn't created for it, for these
// cell types with only one output // cell types with only one output
packed->ports.erase(ctx->id("PLLOUT_B")); packed->ports.erase(id_PLLOUT_B);
packed->ports.erase(ctx->id("PLLOUT_B_GLOBAL")); packed->ports.erase(id_PLLOUT_B_GLOBAL);
} }
for (auto attr : ci->attrs) for (auto attr : ci->attrs)
packed->attrs[attr.first] = attr.second; packed->attrs[attr.first] = attr.second;
@ -1319,9 +1309,9 @@ void pack_plls(Context *ctx)
packed->params[param.first] = param.second; packed->params[param.first] = param.second;
const std::map<IdString, IdString> pos_map_name = { const std::map<IdString, IdString> pos_map_name = {
{ctx->id("PLLOUT_SELECT"), ctx->id("PLLOUT_SELECT_A")}, {id_PLLOUT_SELECT, id_PLLOUT_SELECT_A},
{ctx->id("PLLOUT_SELECT_PORTA"), ctx->id("PLLOUT_SELECT_A")}, {id_PLLOUT_SELECT_PORTA, id_PLLOUT_SELECT_A},
{ctx->id("PLLOUT_SELECT_PORTB"), ctx->id("PLLOUT_SELECT_B")}, {id_PLLOUT_SELECT_PORTB, id_PLLOUT_SELECT_B},
}; };
const std::map<std::string, int> pos_map_val = { const std::map<std::string, int> pos_map_val = {
{"GENCLK", 0}, {"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()); 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 = { const std::map<IdString, std::pair<IdString, IdString>> delmodes = {
{ctx->id("DELAY_ADJUSTMENT_MODE_FEEDBACK"), {ctx->id("DELAY_ADJMODE_FB"), ctx->id("FDA_FEEDBACK")}}, {id_DELAY_ADJUSTMENT_MODE_FEEDBACK, {id_DELAY_ADJMODE_FB, id_FDA_FEEDBACK}},
{ctx->id("DELAY_ADJUSTMENT_MODE_RELATIVE"), {id_DELAY_ADJUSTMENT_MODE_RELATIVE, {id_DELAY_ADJMODE_REL, id_FDA_RELATIVE}},
{ctx->id("DELAY_ADJMODE_REL"), ctx->id("FDA_RELATIVE")}},
}; };
for (auto delmode : delmodes) { for (auto delmode : delmodes) {
if (ci->params.count(delmode.first)) { 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()); 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 auto feedback_path = packed->params[id_FEEDBACK_PATH].is_string
? packed->params[ctx->id("FEEDBACK_PATH")].as_string() ? packed->params[id_FEEDBACK_PATH].as_string()
: std::to_string(packed->params[ctx->id("FEEDBACK_PATH")].as_int64()); : std::to_string(packed->params[id_FEEDBACK_PATH].as_int64());
std::string fbp_value = feedback_path == "DELAY" ? "0" std::string fbp_value = feedback_path == "DELAY" ? "0"
: feedback_path == "SIMPLE" ? "1" : feedback_path == "SIMPLE" ? "1"
: feedback_path == "PHASE_AND_DELAY" ? "2" : 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)) 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), log_error("PLL '%s' has unsupported FEEDBACK_PATH value '%s'\n", ci->name.c_str(ctx),
feedback_path.c_str()); feedback_path.c_str());
packed->params[ctx->id("FEEDBACK_PATH")] = Property(std::stoi(fbp_value), 3); packed->params[id_FEEDBACK_PATH] = Property(std::stoi(fbp_value), 3);
packed->params[ctx->id("PLLTYPE")] = sb_pll40_type(ctx, ci); packed->params[id_PLLTYPE] = sb_pll40_type(ctx, ci);
NetInfo *pad_packagepin_net = nullptr; 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); 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"; newname = "PLLOUT_A";
if (pi.name == ctx->id("PLLOUTCOREB")) if (pi.name == id_PLLOUTCOREB)
newname = "PLLOUT_B"; 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"; newname = "PLLOUT_A_GLOBAL";
if (pi.name == ctx->id("PLLOUTGLOBALB")) if (pi.name == id_PLLOUTGLOBALB)
newname = "PLLOUT_B_GLOBAL"; newname = "PLLOUT_B_GLOBAL";
if (pi.name == ctx->id("PACKAGEPIN")) { if (pi.name == id_PACKAGEPIN) {
if (!is_pad) { if (!is_pad) {
log_error("PLL '%s' has a PACKAGEPIN but is not a PAD PLL\n", ci->name.c_str(ctx)); log_error("PLL '%s' has a PACKAGEPIN but is not a PAD PLL\n", ci->name.c_str(ctx));
} else { } else {
@ -1399,7 +1388,7 @@ void pack_plls(Context *ctx)
continue; continue;
} }
} }
if (pi.name == ctx->id("REFERENCECLK")) { if (pi.name == id_REFERENCECLK) {
if (!is_core) if (!is_core)
log_error("PLL '%s' has a REFERENCECLK but is not a CORE PLL\n", ci->name.c_str(ctx)); 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); 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), log_info(" Input frequency of PLL '%s' is constrained to %.1f MHz\n", ctx->nameOf(ci),
MHz(ctx, input_constr)); MHz(ctx, input_constr));
// Input divider (DIVR) // 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 vco_constr = 0;
delay_t outa_constr = 0, outb_constr = 0; delay_t outa_constr = 0, outb_constr = 0;
int sr_div = 4; int sr_div = 4;
@ -1452,7 +1441,7 @@ void pack_plls(Context *ctx)
}; };
// Lookup shiftreg divider // 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) { switch (sr_div_mode) {
case 0: case 0:
sr_div = 4; sr_div = 4;
@ -1470,8 +1459,8 @@ void pack_plls(Context *ctx)
} }
} }
// Determine dividers in VCO path // Determine dividers in VCO path
vco_constr = input_constr / (int_or_default(packed->params, ctx->id("DIVF"), 0) + 1); vco_constr = input_constr / (int_or_default(packed->params, id_DIVF, 0) + 1);
divq = 1 << (int_or_default(packed->params, ctx->id("DIVQ"), 0)); divq = 1 << (int_or_default(packed->params, id_DIVQ, 0));
if (fbp_value != "1") // anything other than SIMPLE - feedback after DIVQ if (fbp_value != "1") // anything other than SIMPLE - feedback after DIVQ
vco_constr /= divq; vco_constr /= divq;
if (fbp_value == "6") { // EXTERNAL 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), log_info(" VCO frequency of PLL '%s' is constrained to %.1f MHz\n", ctx->nameOf(ci),
MHz(ctx, vco_constr)); 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 outa_constr = input_constr; // 2_PAD variant passes through input to OUTPUT A
else else
outa_constr = process_output(ctx->id("PLLOUT_SELECT_A")); outa_constr = process_output(id_PLLOUT_SELECT_A);
outb_constr = process_output(ctx->id("PLLOUT_SELECT_B")); outb_constr = process_output(id_PLLOUT_SELECT_B);
set_period(ctx, packed.get(), ctx->id("PLLOUT_A"), outa_constr); set_period(ctx, packed.get(), id_PLLOUT_A, outa_constr);
set_period(ctx, packed.get(), ctx->id("PLLOUT_A_GLOBAL"), outa_constr); set_period(ctx, packed.get(), id_PLLOUT_A_GLOBAL, outa_constr);
set_period(ctx, packed.get(), ctx->id("PLLOUT_B"), outb_constr); set_period(ctx, packed.get(), id_PLLOUT_B, outb_constr);
set_period(ctx, packed.get(), ctx->id("PLLOUT_B_GLOBAL"), outb_constr); set_period(ctx, packed.get(), id_PLLOUT_B_GLOBAL, outb_constr);
} }
constr_fail: constr_fail:
// PLL must have been placed already in place_plls() // 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()); NPNR_ASSERT(pll_bel != BelId());
// Deal with PAD PLL peculiarities // Deal with PAD PLL peculiarities
@ -1505,10 +1494,10 @@ void pack_plls(Context *ctx)
auto pll_packagepin_driver = pad_packagepin_net->driver; auto pll_packagepin_driver = pad_packagepin_net->driver;
NPNR_ASSERT(pll_packagepin_driver.cell != nullptr); NPNR_ASSERT(pll_packagepin_driver.cell != nullptr);
auto packagepin_cell = pll_packagepin_driver.cell; 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. // 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) // Disconnect PACKAGEPIN (it's a physical HW link)
for (auto user : pad_packagepin_net->users) 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 // In practice, this means the LOCK signal can only directly reach LUT
// inputs. // inputs.
// If we have a net connected to LOCK, make sure it only drives LUTs. // 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) { if (port.net != nullptr) {
log_info(" PLL '%s' has LOCK output, need to pass all outputs via LUT\n", ci->name.c_str(ctx)); log_info(" PLL '%s' has LOCK output, need to pass all outputs via LUT\n", ci->name.c_str(ctx));
bool found_lut = false; bool found_lut = false;
@ -1531,8 +1520,8 @@ void pack_plls(Context *ctx)
unsigned int lut_count = 0; unsigned int lut_count = 0;
for (const auto &user : port.net->users) { for (const auto &user : port.net->users) {
NPNR_ASSERT(user.cell != nullptr); NPNR_ASSERT(user.cell != nullptr);
if (user.cell->type == ctx->id("ICESTORM_LC")) { if (user.cell->type == id_ICESTORM_LC) {
if (bool_or_default(user.cell->params, ctx->id("CARRY_ENABLE"), false)) { if (bool_or_default(user.cell->params, id_CARRY_ENABLE, false)) {
found_carry = true; found_carry = true;
all_luts = false; all_luts = false;
} else { } else {
@ -1569,14 +1558,14 @@ void pack_plls(Context *ctx)
int z = 0; int z = 0;
for (const auto &user : port.net->users) { for (const auto &user : port.net->users) {
NPNR_ASSERT(user.cell != nullptr); 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 // TODO(q3k): handle when the Bel might be already the
// target of another constraint. // target of another constraint.
NPNR_ASSERT(z < 8); NPNR_ASSERT(z < 8);
auto target_bel = ctx->getBelByLocation(Loc(x, y, z++)); auto target_bel = ctx->getBelByLocation(Loc(x, y, z++));
auto target_bel_name = ctx->getBelName(target_bel).str(ctx); 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()); 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; PortInfo &pi = port.second;
bool is_b_port; bool is_b_port;
if (pi.name == ctx->id("PLLOUT_A_GLOBAL")) if (pi.name == id_PLLOUT_A_GLOBAL)
is_b_port = false; 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; is_b_port = true;
else else
continue; continue;
@ -1635,13 +1624,13 @@ bool Arch::pack()
place_plls(ctx); place_plls(ctx);
pack_special(ctx); pack_special(ctx);
pack_plls(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); promote_globals(ctx);
ctx->assignArchInfo(); ctx->assignArchInfo();
constrain_chains(ctx); constrain_chains(ctx);
ctx->fixupHierarchy(); ctx->fixupHierarchy();
ctx->assignArchInfo(); ctx->assignArchInfo();
ctx->settings[ctx->id("pack")] = 1; ctx->settings[id_pack] = 1;
archInfoToAttributes(); archInfoToAttributes();
log_info("Checksum: 0x%08x\n", ctx->checksum()); log_info("Checksum: 0x%08x\n", ctx->checksum());
return true; return true;

View File

@ -57,9 +57,9 @@ bool apply_pcf(Context *ctx, std::string filename, std::istream &in)
if (setting == "-pullup") { if (setting == "-pullup") {
const auto &value = words.at(++args_end); const auto &value = words.at(++args_end);
if (value == "yes" || value == "1") 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") 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 else
log_error("Invalid value '%s' for -pullup (on line %d)\n", value.c_str(), lineno); log_error("Invalid value '%s' for -pullup (on line %d)\n", value.c_str(), lineno);
} else if (setting == "-pullup_resistor") { } 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); 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") 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); 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") { } else if (setting == "-nowarn") {
nowarn = true; nowarn = true;
} else if (setting == "--warn-no-port") { } 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); BelId pin_bel = ctx->get_package_pin_bel(pin);
if (pin_bel == BelId()) if (pin_bel == BelId())
log_error("package does not have a pin named '%s' (on line %d)\n", pin.c_str(), lineno); 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); 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(), 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) for (const auto &attr : extra_attrs)
fnd_cell->second->attrs[attr.first] = attr.second; 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(); CellInfo *ci = cell.second.get();
if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") || if (ci->type == ctx->id("$nextpnr_ibuf") || ci->type == ctx->id("$nextpnr_obuf") ||
ci->type == ctx->id("$nextpnr_iobuf")) { ci->type == ctx->id("$nextpnr_iobuf")) {
if (!ci->attrs.count(ctx->id("BEL"))) { if (!ci->attrs.count(id_BEL)) {
if (bool_or_default(ctx->settings, ctx->id("pcf_allow_unconstrained"))) if (bool_or_default(ctx->settings, id_pcf_allow_unconstrained))
log_warning("IO '%s' is unconstrained in PCF and will be automatically placed\n", log_warning("IO '%s' is unconstrained in PCF and will be automatically placed\n",
cell.first.c_str(ctx)); cell.first.c_str(ctx));
else else

View File

@ -171,17 +171,17 @@ std::string Arch::get_full_chip_name() const
IdString Arch::archArgsToId(ArchArgs args) const IdString Arch::archArgsToId(ArchArgs args) const
{ {
if (args.type == ArchArgs::LCMXO2_256HC) { if (args.type == ArchArgs::LCMXO2_256HC) {
return id("lcmxo2_256hc"); return id_lcmxo2_256hc;
} else if (args.type == ArchArgs::LCMXO2_640HC) { } else if (args.type == ArchArgs::LCMXO2_640HC) {
return id("lcmxo2_640hc"); return id_lcmxo2_640hc;
} else if (args.type == ArchArgs::LCMXO2_1200HC) { } else if (args.type == ArchArgs::LCMXO2_1200HC) {
return id("lcmxo2_1200hc"); return id_lcmxo2_1200hc;
} else if (args.type == ArchArgs::LCMXO2_2000HC) { } else if (args.type == ArchArgs::LCMXO2_2000HC) {
return id("lcmxo2_2000hc"); return id_lcmxo2_2000hc;
} else if (args.type == ArchArgs::LCMXO2_4000HC) { } else if (args.type == ArchArgs::LCMXO2_4000HC) {
return id("lcmxo2_4000hc"); return id_lcmxo2_4000hc;
} else if (args.type == ArchArgs::LCMXO2_7000HC) { } else if (args.type == ArchArgs::LCMXO2_7000HC) {
return id("lcmxo2_7000hc"); return id_lcmxo2_7000hc;
} }
return IdString(); return IdString();
@ -414,17 +414,17 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
bool Arch::place() 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") { if (placer == "sa") {
bool retVal = placer1(getCtx(), Placer1Cfg(getCtx())); bool retVal = placer1(getCtx(), Placer1Cfg(getCtx()));
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
return retVal; return retVal;
} else if (placer == "heap") { } else if (placer == "heap") {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
cfg.ioBufTypes.insert(id_FACADE_IO); cfg.ioBufTypes.insert(id_FACADE_IO);
bool retVal = placer_heap(getCtx(), cfg); bool retVal = placer_heap(getCtx(), cfg);
getCtx()->settings[getCtx()->id("place")] = 1; getCtx()->settings[id_place] = 1;
archInfoToAttributes(); archInfoToAttributes();
return retVal; return retVal;
} else { } else {
@ -434,7 +434,7 @@ bool Arch::place()
bool Arch::route() 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; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(getCtx(), Router1Cfg(getCtx()));
@ -444,7 +444,7 @@ bool Arch::route()
} else { } else {
log_error("MachXO2 architecture does not support router '%s'\n", router.c_str()); 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(); archInfoToAttributes();
return result; return result;
} }

View File

@ -435,7 +435,7 @@ struct Arch : BaseArch<ArchRanges>
// Extra helper // Extra helper
std::string get_full_chip_name() const; 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; } ArchArgs archArgs() const override { return args; }
IdString archArgsToId(ArchArgs args) const override; IdString archArgsToId(ArchArgs args) const override;

View File

@ -235,36 +235,34 @@ void write_bitstream(Context *ctx, std::string text_config_file)
int int_index = slice[5] - 'A'; int int_index = slice[5] - 'A';
NPNR_ASSERT(int_index >= 0 && int_index < 4); NPNR_ASSERT(int_index >= 0 && int_index < 4);
int lut0_init = int_or_default(ci->params, ctx->id("LUT0_INITVAL")); int lut0_init = int_or_default(ci->params, id_LUT0_INITVAL);
int lut1_init = int_or_default(ci->params, ctx->id("LUT1_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 + ".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_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 + ".MODE", str_or_default(ci->params, 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 + ".GSR", str_or_default(ci->params, id_GSR, "ENABLED"));
cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".SRMODE", cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".SRMODE",
str_or_default(ci->params, ctx->id("SRMODE"), "LSR_OVER_CE")); str_or_default(ci->params, id_SRMODE, "LSR_OVER_CE"));
cc.tiles[tname].add_enum(slice + ".CEMUX", intstr_or_default(ci->params, ctx->id("CEMUX"), "1")); 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", 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", 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", cc.tiles[tname].add_enum("LSR" + std::to_string(int_index) + ".LSRONMUX",
intstr_or_default(ci->params, ctx->id("LSRONMUX"), "LSRMUX")); intstr_or_default(ci->params, 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 + ".REGMODE", str_or_default(ci->params, 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 + ".REG0.SD", intstr_or_default(ci->params, 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 + ".REG1.SD", intstr_or_default(ci->params, id_REG1_SD, "0"));
cc.tiles[tname].add_enum(slice + ".REG0.REGSET", cc.tiles[tname].add_enum(slice + ".REG0.REGSET", str_or_default(ci->params, id_REG0_REGSET, "RESET"));
str_or_default(ci->params, ctx->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 + ".REG1.REGSET", } else if (ci->type == id_FACADE_IO) {
str_or_default(ci->params, ctx->id("REG1_REGSET"), "RESET"));
} else if (ci->type == ctx->id("FACADE_IO")) {
std::string pio = ctx->tile_info(bel)->bel_data[bel.index].name.get(); 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 iotype = str_or_default(ci->attrs, id_IO_TYPE, "LVCMOS33");
std::string dir = str_or_default(ci->params, ctx->id("DIR"), "INPUT"); std::string dir = str_or_default(ci->params, id_DIR, "INPUT");
std::string pic_tile = get_pic_tile(ctx, bel); std::string pic_tile = get_pic_tile(ctx, bel);
cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype); cc.tiles[pic_tile].add_enum(pio + ".BASE_TYPE", dir + "_" + iotype);
} else if (ci->type == ctx->id("OSCH")) { } else if (ci->type == id_OSCH) {
std::string freq = str_or_default(ci->params, ctx->id("NOM_FREQ"), "2.08"); 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.MODE", "OSCH");
cc.tiles[ctx->get_tile_by_type("CFG1")].add_enum("OSCH.NOM_FREQ", freq); cc.tiles[ctx->get_tile_by_type("CFG1")].add_enum("OSCH.NOM_FREQ", freq);
} }

View File

@ -103,12 +103,12 @@ std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::
new_cell->addOutput(id_WADO3); new_cell->addOutput(id_WADO3);
} else if (type == id_FACADE_IO) { } else if (type == id_FACADE_IO) {
new_cell->params[id_DIR] = std::string("INPUT"); 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->addInout(id_PAD);
new_cell->addInput(ctx->id("I")); new_cell->addInput(id_I);
new_cell->addInput(ctx->id("EN")); new_cell->addInput(id_EN);
new_cell->addOutput(ctx->id("O")); new_cell->addOutput(id_O);
} else if (type == id_LUT4) { } else if (type == id_LUT4) {
new_cell->params[id_INIT] = Property(0, 16); 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) 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"}) { for (std::string i : {"A", "B", "C", "D"}) {
IdString lut_port = ctx->id(i); 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, 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) 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. // 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, id_CLK, lc, id_CLK);
replace_port(dff, ctx->id("LSR"), lc, ctx->id("LSR")); replace_port(dff, id_LSR, lc, id_LSR);
replace_port(dff, ctx->id("Q"), lc, ctx->id("Q0")); replace_port(dff, id_Q, lc, id_Q0);
if (lut_type == LutType::PassThru) { if (lut_type == LutType::PassThru) {
// If a register's DI port is fed by a constant, options for placing are // If a register's DI port is fed by a constant, options for placing are
// limited. Use the LUT to get around this. // limited. Use the LUT to get around this.
// LUT output will go to F0, which will feed back to DI0 input. // LUT output will go to F0, which will feed back to DI0 input.
lc->params[ctx->id("LUT0_INITVAL")] = Property(0xAAAA, 16); lc->params[id_LUT0_INITVAL] = Property(0xAAAA, 16);
replace_port(dff, ctx->id("DI"), lc, ctx->id("A0")); replace_port(dff, id_DI, lc, id_A0);
connect_ports(ctx, lc, ctx->id("F0"), lc, ctx->id("DI0")); connect_ports(ctx, lc, id_F0, lc, id_DI0);
} else if (lut_type == LutType::None) { } else if (lut_type == LutType::None) {
// If there is no LUT, use the M0 input because DI0 requires // If there is no LUT, use the M0 input because DI0 requires
// going through the LUTs. // going through the LUTs.
lc->params[ctx->id("REG0_SD")] = std::string("0"); lc->params[id_REG0_SD] = std::string("0");
replace_port(dff, ctx->id("DI"), lc, ctx->id("M0")); replace_port(dff, id_DI, lc, id_M0);
} else { } else {
// Otherwise, there's a LUT being used in the slice and mapping DI to // Otherwise, there's a LUT being used in the slice and mapping DI to
// DI0 input is fine. // DI0 input is fine.
replace_port(dff, ctx->id("DI"), lc, ctx->id("DI0")); replace_port(dff, id_DI, lc, id_DI0);
} }
} }

View File

@ -40,12 +40,12 @@ enum class LutType
std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::string name = ""); std::unique_ptr<CellInfo> create_machxo2_cell(Context *ctx, IdString type, std::string name = "");
// Return true if a cell is a LUT // 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 // 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 // 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 // as needed. Set no_dff if a DFF is not being used, so that the output

View File

@ -116,3 +116,22 @@ X(CLK0)
X(CLK1) X(CLK1)
X(SEL) X(SEL)
X(DCMOUT) 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)

View File

@ -51,20 +51,20 @@ static void pack_lut_lutffs(Context *ctx)
// LUT4 drives more than one FF. // LUT4 drives more than one FF.
NetInfo *o = ci->ports.at(id_Z).net; NetInfo *o = ci->ports.at(id_Z).net;
CellInfo *dff = net_only_drives(ctx, o, is_ff, id_DI, false); 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; bool packed_dff = false;
if (dff) { if (dff) {
if (ctx->verbose) if (ctx->verbose)
log_info("found attached dff %s\n", dff->name.c_str(ctx)); 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) { if (lut_bel != ci->attrs.end() && dff_bel != dff->attrs.end() && lut_bel->second != dff_bel->second) {
// Locations don't match, can't pack // Locations don't match, can't pack
} else { } else {
lut_to_lc(ctx, ci, packed.get(), false); lut_to_lc(ctx, ci, packed.get(), false);
dff_to_lc(ctx, dff, packed.get(), LutType::Normal); dff_to_lc(ctx, dff, packed.get(), LutType::Normal);
if (dff_bel != dff->attrs.end()) 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); packed_cells.insert(dff->name);
if (ctx->verbose) if (ctx->verbose)
log_info("packed cell %s into %s\n", dff->name.c_str(ctx), packed->name.c_str(ctx)); 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) for (auto &attr : ci->attrs)
packed->attrs[attr.first] = attr.second; 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); dff_to_lc(ctx, ci, packed.get(), LutType::None);
if (dff_bel != ci->attrs.end()) 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); packed_cells.insert(ci->name);
if (ctx->verbose) if (ctx->verbose)
log_info("packed cell %s into %s\n", ci->name.c_str(ctx), packed->name.c_str(ctx)); 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) { for (auto &net : ctx->nets) {
NetInfo *ni = net.second.get(); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, gnd_net, false); set_net_constant(ctx, ni, gnd_net, false);
dead_nets.push_back(net.first); dead_nets.push_back(net.first);
ctx->cells.erase(drv_cell); 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; IdString drv_cell = ni->driver.cell->name;
set_net_constant(ctx, ni, vcc_net, true); set_net_constant(ctx, ni, vcc_net, true);
dead_nets.push_back(net.first); 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 // attribute already on a FACADE_IO is an error. Attributes on
// the pin attached to the PAD of FACADE_IO are ignored by this // the pin attached to the PAD of FACADE_IO are ignored by this
// packing phase. // packing phase.
auto loc_attr_cell = ci->attrs.find(ctx->id("LOC")); auto loc_attr_cell = ci->attrs.find(id_LOC);
auto bel_attr_cell = ci->attrs.find(ctx->id("BEL")); auto bel_attr_cell = ci->attrs.find(id_BEL);
if (loc_attr_cell != ci->attrs.end()) { if (loc_attr_cell != ci->attrs.end()) {
if (bel_attr_cell != ci->attrs.end()) { if (bel_attr_cell != ci->attrs.end()) {
@ -312,7 +312,7 @@ static void pack_io(Context *ctx)
} else { } else {
log_info("pin '%s' constrained to Bel '%s'.\n", ci->name.c_str(ctx), ctx->nameOfBel(pinBel)); 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_io(ctx);
pack_lut_lutffs(ctx); pack_lut_lutffs(ctx);
pack_remaining_ffs(ctx); pack_remaining_ffs(ctx);
ctx->settings[ctx->id("pack")] = 1; ctx->settings[id_pack] = 1;
ctx->assignArchInfo(); ctx->assignArchInfo();
log_info("Checksum: 0x%08x\n", ctx->checksum()); log_info("Checksum: 0x%08x\n", ctx->checksum());
return true; return true;

View File

@ -446,7 +446,7 @@ ArcBounds Arch::getRouteBoundingBox(WireId src, WireId dst) const
bool Arch::place() 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") { if (placer == "heap") {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
@ -468,7 +468,7 @@ bool Arch::place()
log_error("Mistral architecture does not support placer '%s'\n", placer.c_str()); 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(); archInfoToAttributes();
return true; return true;
} }
@ -479,7 +479,7 @@ bool Arch::route()
lab_pre_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; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(getCtx(), Router1Cfg(getCtx()));
@ -489,7 +489,7 @@ bool Arch::route()
} else { } else {
log_error("Mistral architecture does not support router '%s'\n", router.c_str()); 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(); archInfoToAttributes();
return result; return result;
} }

View File

@ -97,3 +97,11 @@ X(WE_INV)
X(cyclonev_oscillator) X(cyclonev_oscillator)
X(cyclonev_hps_interface_mpu_general_purpose) X(cyclonev_hps_interface_mpu_general_purpose)
X(clkout)
X(clkout1)
X(compress_rbf)
X(oscena)
X(placer)
X(router)
X(step)

View File

@ -58,9 +58,9 @@ void Arch::create_hps_mpu_general_purpose(int x, int y)
void Arch::create_control(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); 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_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_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_clkout1, PORT_OUT, get_port(CycloneV::CTRL, x, y, -1, CycloneV::CLK_OUT1, -1));
} }
NEXTPNR_NAMESPACE_END NEXTPNR_NAMESPACE_END

View File

@ -79,7 +79,7 @@ std::unique_ptr<Context> MistralCommandHandler::createContext(dict<std::string,
chipArgs.device = vm["device"].as<std::string>(); chipArgs.device = vm["device"].as<std::string>();
auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
if (vm.count("compress-rbf")) if (vm.count("compress-rbf"))
ctx->settings[ctx->id("compress_rbf")] = Property::State::S1; ctx->settings[id_compress_rbf] = Property::State::S1;
return ctx; return ctx;
} }

View File

@ -186,8 +186,8 @@ Arch::Arch(ArchArgs args) : args(args)
disabled_pips.insert(pip); disabled_pips.insert(pip);
} }
// TODO: find a better solution to disable these // TODO: find a better solution to disable these
WireId dcs_out = getWireByName( WireId dcs_out =
IdStringList(std::array<IdString, 3>{x_ids.at(37), y_ids.at(10), id("JDCSOUT_DCS_DCSIP")})); 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)) for (auto dcs_pip : getPipsUphill(dcs_out))
disabled_pips.insert(dcs_pip); disabled_pips.insert(dcs_pip);
NPNR_ASSERT(disabled_pips.size() == 6); 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; 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_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_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_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; 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; 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_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_GRID_Y, stringf("%d", wire.tile / chip_info->width));
ret.emplace_back(id("FLAGS"), stringf("%u", wire_data(wire).flags)); ret.emplace_back(id_FLAGS, stringf("%u", wire_data(wire).flags));
return ret; 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; 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_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_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_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_TO_TILE_WIRE, nameOf(IdString(loc_data(pip).wires[pip_data(pip).to_wire].name)));
return ret; return ret;
} }
@ -665,7 +665,7 @@ bool Arch::place()
if (getCtx()->settings.count(getCtx()->id("estimate-delay-mult"))) if (getCtx()->settings.count(getCtx()->id("estimate-delay-mult")))
estimate_delay_mult = getCtx()->setting<int>("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") { if (placer == "heap") {
PlacerHeapCfg cfg(getCtx()); PlacerHeapCfg cfg(getCtx());
@ -689,7 +689,7 @@ bool Arch::place()
post_place_opt(); post_place_opt();
getCtx()->attrs[getCtx()->id("step")] = std::string("place"); getCtx()->attrs[id_step] = std::string("place");
archInfoToAttributes(); archInfoToAttributes();
return true; return true;
} }
@ -740,7 +740,7 @@ bool Arch::route()
route_globals(); route_globals();
std::string router = str_or_default(settings, id("router"), defaultRouter); std::string router = str_or_default(settings, id_router, defaultRouter);
bool result; bool result;
if (router == "router1") { if (router == "router1") {
result = router1(getCtx(), Router1Cfg(getCtx())); result = router1(getCtx(), Router1Cfg(getCtx()));
@ -752,7 +752,7 @@ bool Arch::route()
} else { } else {
log_error("Nexus architecture does not support router '%s'\n", router.c_str()); 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(); archInfoToAttributes();
return result; return result;
} }

View File

@ -531,3 +531,24 @@ X(Q1)
X(SCLK) X(SCLK)
X(LOCAL_VCC) 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)

View File

@ -79,15 +79,15 @@ std::unique_ptr<Context> NexusCommandHandler::createContext(dict<std::string, Pr
chipArgs.device = vm["device"].as<std::string>(); chipArgs.device = vm["device"].as<std::string>();
auto ctx = std::unique_ptr<Context>(new Context(chipArgs)); auto ctx = std::unique_ptr<Context>(new Context(chipArgs));
if (vm.count("no-post-place-opt")) 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")) 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")) { if (vm.count("carry-lutff-ratio")) {
float ratio = vm["carry-lutff-ratio"].as<float>(); float ratio = vm["carry-lutff-ratio"].as<float>();
if (ratio < 0.0f || ratio > 1.0f) { if (ratio < 0.0f || ratio > 1.0f) {
log_error("Carry LUT+FF packing ration must be between 0.0 and 1.0"); 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")) if (vm.count("estimate-delay-mult"))
ctx->settings[ctx->id("estimate-delay-mult")] = vm["estimate-delay-mult"].as<int>(); ctx->settings[ctx->id("estimate-delay-mult")] = vm["estimate-delay-mult"].as<int>();

View File

@ -1132,7 +1132,7 @@ struct NexusPacker
CellInfo *ci = cell.second.get(); CellInfo *ci = cell.second.get();
if (ci->type != id_LRAM_CORE) if (ci->type != id_LRAM_CORE)
continue; 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; continue;
for (int i = 0; i < 0x80; i++) { for (int i = 0; i < 0x80; i++) {
// FIXME: document ECC and remove this DRC // FIXME: document ECC and remove this DRC
@ -1986,7 +1986,7 @@ struct NexusPacker
if (ci->type == id_DCC) { if (ci->type == id_DCC) {
copy_constraint(ci, id_CLKI, id_CLKO, 1); copy_constraint(ci, id_CLKI, id_CLKO, 1);
} else if (ci->type == id_OSC_CORE) { } 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. 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_HFCLKOUT, delay_t((1.0e6 / 450) * (div + 1) / tol));
set_period(ci, id_LFCLKOUT, delay_t((1.0e3 / 10) / tol)); set_period(ci, id_LFCLKOUT, delay_t((1.0e3 / 10) / tol));
@ -2177,26 +2177,26 @@ struct NexusPacker
// We have IDDR+ODDR // We have IDDR+ODDR
if (isODDR && isIDDR) { if (isODDR && isIDDR) {
if (!iob->attrs.count(ctx->id("GLITCHFILTER"))) { if (!iob->attrs.count(id_GLITCHFILTER)) {
iob->attrs[ctx->id("GLITCHFILTER")] = std::string("ON"); iob->attrs[id_GLITCHFILTER] = std::string("ON");
} }
if (!iob->attrs.count(ctx->id("CLAMP"))) { if (!iob->attrs.count(id_CLAMP)) {
iob->attrs[ctx->id("CLAMP")] = std::string("ON"); iob->attrs[id_CLAMP] = std::string("ON");
} }
if (!iob->attrs.count(ctx->id("PULLMODE"))) { if (!iob->attrs.count(id_PULLMODE)) {
iob->attrs[ctx->id("PULLMODE")] = std::string("DOWN"); iob->attrs[id_PULLMODE] = std::string("DOWN");
} }
} }
// We have ODDR only // We have ODDR only
else if (isODDR && !isIDDR) { else if (isODDR && !isIDDR) {
if (!iob->attrs.count(ctx->id("GLITCHFILTER"))) { if (!iob->attrs.count(id_GLITCHFILTER)) {
iob->attrs[ctx->id("GLITCHFILTER")] = std::string("OFF"); iob->attrs[id_GLITCHFILTER] = std::string("OFF");
} }
if (!iob->attrs.count(ctx->id("CLAMP"))) { if (!iob->attrs.count(id_CLAMP)) {
iob->attrs[ctx->id("CLAMP")] = std::string("OFF"); iob->attrs[id_CLAMP] = std::string("OFF");
} }
if (!iob->attrs.count(ctx->id("PULLMODE"))) { if (!iob->attrs.count(id_PULLMODE)) {
iob->attrs[ctx->id("PULLMODE")] = std::string("NONE"); 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 // Check if the net wants to use the T flip-flop in
// IOLOGIC // IOLOGIC
bool syn_useioff = false; bool syn_useioff = false;
if (iob_t->attrs.count(ctx->id("syn_useioff"))) { if (iob_t->attrs.count(id_syn_useioff)) {
syn_useioff = iob_t->attrs.at(ctx->id("syn_useioff")).as_bool(); syn_useioff = iob_t->attrs.at(id_syn_useioff).as_bool();
} }
// Check if the T input is driven by a flip-flop. Store // 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); iol->params[id_REGSET] = ff->params.at(id_REGSET);
// Enable the TSREG // 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("TSREG.REGSET")] = std::string("SET");
iol->params[ctx->id("IDDRX1_ODDRX1.TRISTATE")] = std::string("ENABLED"); iol->params[ctx->id("IDDRX1_ODDRX1.TRISTATE")] = std::string("ENABLED");
} }
@ -2328,7 +2328,7 @@ struct NexusPacker
log_info("Inferring LUT+FF pairs...\n"); log_info("Inferring LUT+FF pairs...\n");
float carry_ratio = 1.0f; 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"); carry_ratio = ctx->setting<float>("carry_lutff_ratio");
} }
@ -2487,7 +2487,7 @@ struct NexusPacker
pack_ip(); pack_ip();
handle_iologic(); 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(); pack_lutffs();
} }
@ -2500,7 +2500,7 @@ struct NexusPacker
bool Arch::pack() bool Arch::pack()
{ {
(NexusPacker(getCtx()))(); (NexusPacker(getCtx()))();
attrs[id("step")] = std::string("pack"); attrs[id_step] = std::string("pack");
archInfoToAttributes(); archInfoToAttributes();
assignArchInfo(); assignArchInfo();
return true; return true;

View File

@ -148,7 +148,7 @@ struct NexusPostPlaceOpt
void Arch::post_place_opt() 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; return;
log_info("Running post-place optimisations...\n"); log_info("Running post-place optimisations...\n");
NexusPostPlaceOpt opt(getCtx()); NexusPostPlaceOpt opt(getCtx());