diff options
-rw-r--r-- | nexus/arch.h | 3 | ||||
-rw-r--r-- | nexus/fasm.cc | 161 | ||||
-rw-r--r-- | nexus/pack.cc | 40 |
3 files changed, 177 insertions, 27 deletions
diff --git a/nexus/arch.h b/nexus/arch.h index ea4e9f5b..323dcacd 100644 --- a/nexus/arch.h +++ b/nexus/arch.h @@ -1408,7 +1408,8 @@ struct Arch : BaseArch<ArchRanges> // ------------------------------------------------- // Parse a possibly-Lattice-style (C literal in Verilog string) style parameter - Property parse_lattice_param(const CellInfo *ci, IdString prop, int width, int64_t defval) const; + Property parse_lattice_param_from_cell(const CellInfo *ci, IdString prop, int width, int64_t defval) const; + Property parse_lattice_param(const Property &val, IdString prop, int width, const char* ci="") const; // ------------------------------------------------- diff --git a/nexus/fasm.cc b/nexus/fasm.cc index e2eb2305..a6e94d73 100644 --- a/nexus/fasm.cc +++ b/nexus/fasm.cc @@ -521,8 +521,10 @@ struct NexusFasmWriter write_enum(cell, "HFDIV_FABRIC_EN", "ENABLED"); write_enum(cell, "LF_FABRIC_EN"); write_enum(cell, "LF_OUTPUT_EN"); + write_enum(cell, "DTR_EN", "ENABLED"); write_enum(cell, "DEBUG_N", "DISABLED"); - write_int_vector(stringf("HF_CLK_DIV[7:0]"), ctx->parse_lattice_param(cell, id_HF_CLK_DIV, 8, 0).intval, 8); + write_int_vector(stringf("HF_CLK_DIV[7:0]"), ctx->parse_lattice_param_from_cell(cell, id_HF_CLK_DIV, 8, 0).intval, 8); + write_int_vector(stringf("HF_SED_SEC_DIV[7:0]"), 1, 8); write_cell_muxes(cell); pop(2); } @@ -681,6 +683,125 @@ struct NexusFasmWriter {"V2I_PP_ICTRL", 5}, }; + const dict<std::string, std::string> pll_default_params = { + {"BW_CTL_BIAS", "0b0101"}, + {"CLKOP_TRIM", "0b0000"}, + {"CLKOS_TRIM", "0b0000"}, + {"CLKOS2_TRIM", "0b0000"}, + {"CLKOS3_TRIM", "0b0000"}, + {"CLKOS4_TRIM", "0b0000"}, + {"CLKOS5_TRIM", "0b0000"}, + {"CRIPPLE", "5P"}, + {"CSET", "40P"}, + {"DELAY_CTRL", "200PS"}, + {"DELA", "0"}, + {"DELB", "0"}, + {"DELC", "0"}, + {"DELD", "0"}, + {"DELE", "0"}, + {"DELF", "0"}, + {"DIRECTION", "DISABLED"}, + {"DIVA", "0"}, + {"DIVB", "0"}, + {"DIVC", "0"}, + {"DIVD", "0"}, + {"DIVE", "0"}, + {"DIVF", "0"}, + {"DYN_SEL", "0b000"}, + {"DYN_SOURCE", "STATIC"}, + {"ENCLK_CLKOP", "DISABLED"}, + {"ENCLK_CLKOS", "DISABLED"}, + {"ENCLK_CLKOS2", "DISABLED"}, + {"ENCLK_CLKOS3", "DISABLED"}, + {"ENCLK_CLKOS4", "DISABLED"}, + {"ENCLK_CLKOS5", "DISABLED"}, + {"ENABLE_SYNC", "DISABLED"}, + {"FAST_LOCK_EN", "ENABLED"}, + {"V2I_1V_EN", "DISABLED"}, + {"FBK_CUR_BLE", "0b00000000"}, + {"FBK_EDGE_SEL", "POSITIVE"}, + {"FBK_IF_TIMING_CTL", "0b00"}, + {"FBK_INTEGER_MODE", "DISABLED"}, + {"FBK_MASK", "0b00001000"}, + {"FBK_MMD_DIG", "8"}, + {"FBK_MMD_PULS_CTL", "0b0000"}, + {"FBK_MODE", "0b00"}, + {"FBK_PI_BYPASS", "NOT_BYPASSED"}, + {"FBK_PI_RC", "0b1100"}, + {"FBK_PR_CC", "0b0000"}, + {"FBK_PR_IC", "0b1000"}, + {"FLOAT_CP", "DISABLED"}, + {"FLOCK_CTRL", "2X"}, + {"FLOCK_EN", "ENABLED"}, + {"FLOCK_SRC_SEL", "REFCLK"}, + {"FORCE_FILTER", "DISABLED"}, + {"I_CTRL", "10UA"}, + {"IPI_CMP", "0b1000"}, + {"IPI_CMPN", "0b0011"}, + {"IPI_COMP_EN", "DISABLED"}, + {"IPP_CTRL", "0b1000"}, + {"IPP_SEL", "0b1111"}, + {"KP_VCO", "0b11001"}, + {"LDT_INT_LOCK_STICKY", "DISABLED"}, + {"LDT_LOCK", "1536CYC"}, + {"LDT_LOCK_SEL", "U_FREQ"}, + {"LEGACY_ATT", "DISABLED"}, + {"LOAD_REG", "DISABLED"}, + {"OPENLOOP_EN", "DISABLED"}, + {"PHIA", "0"}, + {"PHIB", "0"}, + {"PHIC", "0"}, + {"PHID", "0"}, + {"PHIE", "0"}, + {"PHIF", "0"}, + {"PLLPDN_EN", "DISABLED"}, + {"PLLPD_N", "UNUSED"}, + {"PLLRESET_ENA", "DISABLED"}, + {"REF_INTEGER_MODE", "DISABLED"}, + {"REF_MASK", "0b00000000"}, + {"REF_MMD_DIG", "8"}, + {"REF_MMD_IN", "0b00001000"}, + {"REF_MMD_PULS_CTL", "0b0000"}, + {"REF_TIMING_CTL", "0b00"}, + {"REFIN_RESET", "SET"}, + {"RESET_LF", "DISABLED"}, + {"ROTATE", "DISABLED"}, + {"SEL_OUTA", "DISABLED"}, + {"SEL_OUTB", "DISABLED"}, + {"SEL_OUTC", "DISABLED"}, + {"SEL_OUTD", "DISABLED"}, + {"SEL_OUTE", "DISABLED"}, + {"SEL_OUTF", "DISABLED"}, + {"SLEEP", "DISABLED"}, + {"SSC_DELTA", "0b000000000000000"}, + {"SSC_DELTA_CTL", "0b00"}, + {"SSC_DITHER", "DISABLED"}, + {"SSC_EN_CENTER_IN", "DOWN_TRIANGLE"}, + {"SSC_EN_SDM", "DISABLED"}, + {"SSC_EN_SSC", "DISABLED"}, + {"SSC_F_CODE", "0b000000000000000"}, + {"SSC_N_CODE", "0b000010100"}, + {"SSC_ORDER", "SDM_ORDER2"}, + {"SSC_PI_BYPASS", "NOT_BYPASSED"}, + {"SSC_REG_WEIGHTING_SEL", "0b000"}, + {"SSC_SQUARE_MODE", "DISABLED"}, + {"SSC_STEP_IN", "0b0000000"}, + {"SSC_TBASE", "0b000000000000"}, + {"STDBY_ATT", "DISABLED"}, + {"TRIMOP_BYPASS_N", "BYPASSED"}, + {"TRIMOS_BYPASS_N", "BYPASSED"}, + {"TRIMOS2_BYPASS_N", "BYPASSED"}, + {"TRIMOS3_BYPASS_N", "BYPASSED"}, + {"TRIMOS4_BYPASS_N", "BYPASSED"}, + {"TRIMOS5_BYPASS_N", "BYPASSED"}, + {"V2I_KVCO_SEL", "85"}, + {"V2I_PP_ICTRL", "0b00110"}, + {"V2I_PP_RES", "10K"}, + {"CLKMUX_FB", "CMUX_CLKOP"}, + {"SEL_FBK", "DIVA"}, + {"DIV_DEL", "0b0000001"}, + }; + // Which MIPI params are 'word' values const dict<std::string, int> dphy_word_params = { {"CM", 8}, {"CN", 5}, {"CO", 3}, {"RSEL", 2}, {"RXCDRP", 2}, @@ -691,6 +812,14 @@ struct NexusFasmWriter }; /* clang-format on */ + static bool is_number(std::string s) { + for (auto c : s) { + if(!isdigit(c)) + return false; + } + return true; + } + // Write out config for some kind of PLL cell void write_pll(const CellInfo *cell) { @@ -701,17 +830,33 @@ struct NexusFasmWriter write_cell_muxes(cell); pop(); push(stringf("IP_%s", ctx->nameOf(IdString(ctx->bel_data(bel).name)))); - for (auto ¶m : cell->params) { - const std::string &name = param.first.str(ctx); + for (auto &value : pll_default_params) { + IdString n = IdString(ctx, value.first); + Property temp; + if (is_number(value.second)) + temp = Property(std::stoi(value.second), 32); + else + temp = Property::from_string(value.second); + const std::string &name = n.str(ctx); if (is_mux_param(name) || name == "CLKMUX_FB" || name == "SEL_FBK") continue; auto fnd_word = pll_word_params.find(name); if (fnd_word != pll_word_params.end()) { - write_int_vector(stringf("%s[%d:0]", name.c_str(), fnd_word->second - 1), - ctx->parse_lattice_param(cell, param.first, fnd_word->second, 0).as_int64(), - fnd_word->second); + if (cell->params.count(n)) { + write_int_vector(stringf("%s[%d:0]", name.c_str(), fnd_word->second - 1), + ctx->parse_lattice_param_from_cell(cell, n, fnd_word->second, 0).as_int64(), + fnd_word->second); + } else { + write_int_vector(stringf("%s[%d:0]", name.c_str(), fnd_word->second - 1), + ctx->parse_lattice_param(temp, n, fnd_word->second).as_int64(), + fnd_word->second); + } } else { - write_bit(stringf("%s.%s", name.c_str(), param.second.as_string().c_str())); + if (cell->params.count(n)) { + write_bit(stringf("%s.%s", name.c_str(), cell->params.at(n).as_string().c_str())); + } else { + write_bit(stringf("%s.%s", name.c_str(), temp.as_string().c_str())); + } } } pop(); @@ -729,7 +874,7 @@ struct NexusFasmWriter auto fnd_word = dphy_word_params.find(name); if (fnd_word != dphy_word_params.end()) { write_int_vector(stringf("%s[%d:0]", name.c_str(), fnd_word->second - 1), - ctx->parse_lattice_param(cell, param.first, fnd_word->second, 0).as_int64(), + ctx->parse_lattice_param_from_cell(cell, param.first, fnd_word->second, 0).as_int64(), fnd_word->second); } else { write_bit(stringf("%s.%s", name.c_str(), param.second.as_string().c_str())); diff --git a/nexus/pack.cc b/nexus/pack.cc index 26da3dc5..4eccc634 100644 --- a/nexus/pack.cc +++ b/nexus/pack.cc @@ -32,13 +32,17 @@ namespace { bool is_enabled(CellInfo *ci, IdString prop) { return str_or_default(ci->params, prop, "") == "ENABLED"; } } // namespace -// Parse a possibly-Lattice-style (C literal in Verilog string) style parameter -Property Arch::parse_lattice_param(const CellInfo *ci, IdString prop, int width, int64_t defval) const +Property Arch::parse_lattice_param_from_cell(const CellInfo *ci, IdString prop, int width, int64_t defval) const { auto fnd = ci->params.find(prop); if (fnd == ci->params.end()) return Property(defval, width); - const auto &val = fnd->second; + return this->parse_lattice_param(fnd->second, prop, width, nameOf(ci)); +} + +// Parse a possibly-Lattice-style (C literal in Verilog string) style parameter +Property Arch::parse_lattice_param(const Property &val, IdString prop, int width, const char* ci) const +{ if (val.is_string) { const std::string &s = val.str; Property temp; @@ -47,7 +51,7 @@ Property Arch::parse_lattice_param(const CellInfo *ci, IdString prop, int width, for (int i = int(s.length()) - 1; i >= 2; i--) { char c = s.at(i); if (c != '0' && c != '1' && c != 'x') - log_error("Invalid binary digit '%c' in property %s.%s\n", c, nameOf(ci), nameOf(prop)); + log_error("Invalid binary digit '%c' in property %s.%s\n", c, ci, nameOf(prop)); temp.str.push_back(c); } } else if (boost::starts_with(s, "0x")) { @@ -61,7 +65,7 @@ Property Arch::parse_lattice_param(const CellInfo *ci, IdString prop, int width, else if (c >= 'A' && c <= 'F') nibble = (c - 'A') + 10; else - log_error("Invalid hex digit '%c' in property %s.%s\n", c, nameOf(ci), nameOf(prop)); + log_error("Invalid hex digit '%c' in property %s.%s\n", c, ci, nameOf(prop)); for (int j = 0; j < 4; j++) temp.str.push_back(((nibble >> j) & 0x1) ? Property::S1 : Property::S0); } @@ -73,14 +77,14 @@ Property Arch::parse_lattice_param(const CellInfo *ci, IdString prop, int width, else ival = std::stoll(s); } catch (std::runtime_error &e) { - log_error("Invalid decimal value for property %s.%s", nameOf(ci), nameOf(prop)); + log_error("Invalid decimal value for property %s.%s", ci, nameOf(prop)); } temp = Property(ival); } for (auto b : temp.str.substr(width)) { if (b == Property::S1) - log_error("Found value for property %s.%s with width greater than %d\n", nameOf(ci), nameOf(prop), + log_error("Found value for property %s.%s with width greater than %d\n", ci, nameOf(prop), width); } temp.update_intval(); @@ -90,7 +94,7 @@ Property Arch::parse_lattice_param(const CellInfo *ci, IdString prop, int width, if (b == Property::S1) log_error("Found bitvector value for property %s.%s with width greater than %d - perhaps a string was " "converted to bits?\n", - nameOf(ci), nameOf(prop), width); + ci, nameOf(prop), width); } return val.extract(0, width); } @@ -170,7 +174,7 @@ struct NexusPacker int64_t def; for (const auto &p : rule.parse_params) { std::tie(old_param, new_param, width, def) = p; - ci->params[new_param] = ctx->parse_lattice_param(ci, old_param, width, def); + ci->params[new_param] = ctx->parse_lattice_param_from_cell(ci, old_param, width, def); } } @@ -953,7 +957,7 @@ struct NexusPacker ramw->connectPort(id_WCKO, int_wck); ramw->connectPort(id_WREO, int_wre); - uint64_t initval = ctx->parse_lattice_param(ci, id_INITVAL, 64, 0).as_int64(); + uint64_t initval = ctx->parse_lattice_param_from_cell(ci, id_INITVAL, 64, 0).as_int64(); // Rewiring - buses for (int i = 0; i < 4; i++) { @@ -1272,8 +1276,8 @@ struct NexusPacker combs[1]->connectPort(id_F, f1); combs[0]->connectPort(id_F1, f1); - combs[0]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT0, 16, 0); - combs[1]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT1, 16, 0); + combs[0]->params[id_INIT] = ctx->parse_lattice_param_from_cell(ci, id_INIT0, 16, 0); + combs[1]->params[id_INIT] = ctx->parse_lattice_param_from_cell(ci, id_INIT1, 16, 0); combs[1]->cluster = combs[0]->name; combs[1]->constr_x = 0; @@ -1329,8 +1333,8 @@ struct NexusPacker // Copy parameters if (ci->params.count(id_INJECT)) combs[0]->params[id_INJECT] = ci->params[id_INJECT]; - combs[0]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT0, 16, 0); - combs[1]->params[id_INIT] = ctx->parse_lattice_param(ci, id_INIT1, 16, 0); + combs[0]->params[id_INIT] = ctx->parse_lattice_param_from_cell(ci, id_INIT0, 16, 0); + combs[1]->params[id_INIT] = ctx->parse_lattice_param_from_cell(ci, id_INIT1, 16, 0); // Internal carry net between the two split COMB cells NetInfo *int_cy = ctx->createNet(ctx->id(stringf("%s$widefn_int_cy$", ctx->nameOf(ci)))); @@ -2026,9 +2030,9 @@ struct NexusPacker log_info(" Input frequency of PLL '%s' is constrained to %.1f MHz\n", ci->name.c_str(ctx), MHz(period_in)); - int input_div = ctx->parse_lattice_param(ci, id_REF_MMD_DIG, 8, 1).as_int64(); + int input_div = ctx->parse_lattice_param_from_cell(ci, id_REF_MMD_DIG, 8, 1).as_int64(); period_in *= input_div; - int feedback_div = ctx->parse_lattice_param(ci, id_REF_MMD_DIG, 8, 1).as_int64(); + int feedback_div = ctx->parse_lattice_param_from_cell(ci, id_REF_MMD_DIG, 8, 1).as_int64(); bool found_fbk = false; std::string clkmux_fb = str_or_default(ci->params, id_CLKMUX_FB, "CMUX_CLKOP"); for (int i = 0; i < 6; i++) { @@ -2036,7 +2040,7 @@ struct NexusPacker if (clkmux_fb != stringf("CMUX_%s", output[i].c_str(ctx))) continue; // Multiply feedback output divider with - feedback_div *= (ctx->parse_lattice_param(ci, div[i], 7, 0).as_int64() + 1); + feedback_div *= (ctx->parse_lattice_param_from_cell(ci, div[i], 7, 0).as_int64() + 1); found_fbk = true; } if (!found_fbk) { @@ -2050,7 +2054,7 @@ struct NexusPacker MHz(vco_period)); for (int i = 0; i < 6; i++) { set_period(ci, output[i], - (ctx->parse_lattice_param(ci, div[i], 7, 0).as_int64() + 1) * vco_period); + (ctx->parse_lattice_param_from_cell(ci, div[i], 7, 0).as_int64() + 1) * vco_period); } } } |