diff options
Diffstat (limited to 'mistral')
-rw-r--r-- | mistral/base_bitstream.cc | 14 | ||||
-rw-r--r-- | mistral/bitstream.cc | 102 | ||||
-rw-r--r-- | mistral/family.cmake | 3 |
3 files changed, 118 insertions, 1 deletions
diff --git a/mistral/base_bitstream.cc b/mistral/base_bitstream.cc index bf85c6b9..759cdfeb 100644 --- a/mistral/base_bitstream.cc +++ b/mistral/base_bitstream.cc @@ -45,6 +45,18 @@ void default_sx120f(CycloneV *cv) // Default TERM config cv->bmux_b_set(CycloneV::TERM, CycloneV::xy2pos(89, 34), CycloneV::INTOSC_2_EN, 0, 0); + // TODO: what if these pins are used? where do these come from + for (int z = 0; z < 4; z++) { + cv->bmux_m_set(CycloneV::GPIO, CycloneV::xy2pos(89, 43), CycloneV::IOCSR_STD, z, CycloneV::NVR_LOW); + cv->bmux_m_set(CycloneV::GPIO, CycloneV::xy2pos(89, 66), CycloneV::IOCSR_STD, z, CycloneV::NVR_LOW); + } + for (int y : {38, 44, 51, 58, 65, 73, 79}) { + // TODO: Why only these upper DQS? is there a pattern? + cv->bmux_b_set(CycloneV::DQS16, CycloneV::xy2pos(89, y), CycloneV::RB_2X_CLK_DQS_INV, 0, 1); + cv->bmux_b_set(CycloneV::DQS16, CycloneV::xy2pos(89, y), CycloneV::RB_ACLR_LFIFO_EN, 0, 1); + cv->bmux_b_set(CycloneV::DQS16, CycloneV::xy2pos(89, y), CycloneV::RB_LFIFO_BYPASS, 0, 0); + } + // Discover these mux values using // grep 'i [_A-Z0-9.]* 1' empty.bt cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 12), 69), true); @@ -54,7 +66,7 @@ void default_sx120f(CycloneV *cv) cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 37), 31), true); cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 40), 43), true); cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 46), 69), true); - cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 47), 53), true); + cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 47), 43), true); cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 53), 69), true); cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 54), 4), true); cv->inv_set(CycloneV::rnode(CycloneV::GOUT, CycloneV::xy2pos(0, 73), 68), true); diff --git a/mistral/bitstream.cc b/mistral/bitstream.cc index 9ed3a161..2c612a73 100644 --- a/mistral/bitstream.cc +++ b/mistral/bitstream.cc @@ -46,6 +46,107 @@ struct MistralBitgen cv->opt_b_set(CycloneV::RELEASE_CLEARS_BEFORE_TRISTATES_DIS, true); cv->opt_b_set(CycloneV::RETRY_CONFIG_ON_ERROR_EN, true); cv->opt_r_set(CycloneV::START_UP_CLOCK, 0x3F); + // Default inversion + write_default_inv(); + } + + void write_default_inv() + { + // Some PNODEs are inverted by default. Set them up here. + for (const auto &pn2r : cv->get_all_p2r()) { + const auto &pn = pn2r.first; + auto pt = CycloneV::pn2pt(pn); + auto pi = CycloneV::pn2pi(pn); + + switch (CycloneV::pn2bt(pn)) { + case CycloneV::HMC: { + // HMC OE are inverted to set OE=0, i.e. unused pins floating + // TODO: handle the case when we are using the HMC or HMC bypass + std::string name(CycloneV::port_type_names[pt]); + if (name.compare(0, 5, "IOINT") != 0 || name.compare(name.size() - 2, 2, "OE") != 0) + continue; + cv->inv_set(pn2r.second, true); + break; + }; + // HPS IO - TODO: what about when we actually support the HPS primitives? + case CycloneV::HPS_BOOT: { + switch (pt) { + case CycloneV::CSEL_EN: + case CycloneV::BSEL_EN: + case CycloneV::BOOT_FROM_FPGA_READY: + case CycloneV::BOOT_FROM_FPGA_ON_FAILURE: + cv->inv_set(pn2r.second, true); + break; + case CycloneV::CSEL: + if (pi < 2) + cv->inv_set(pn2r.second, true); + break; + case CycloneV::BSEL: + if (pi < 3) + cv->inv_set(pn2r.second, true); + break; + default: + break; + }; + break; + }; + case CycloneV::HPS_CROSS_TRIGGER: { + if (pt == CycloneV::CLK_EN) + cv->inv_set(pn2r.second, true); + break; + }; + case CycloneV::HPS_TEST: { + if (pt == CycloneV::CFG_DFX_BYPASS_ENABLE) + cv->inv_set(pn2r.second, true); + break; + }; + case CycloneV::GPIO: { + // Ignore GPIO used by the design + BelId bel = ctx->bel_by_block_idx(CycloneV::pn2x(pn), CycloneV::pn2y(pn), id_MISTRAL_IO, + CycloneV::pn2bi(pn)); + if (bel != BelId() && ctx->getBoundBelCell(bel) != nullptr) + continue; + // Bonded IO invert OEIN.1 which disables the output buffer and floats the IO + // Unbonded IO invert OEIN.0 which enables the output buffer, and {DATAIN.[0123]} to drive a constant + // GND, presumably for power/EMI reasons + bool is_bonded = cv->pin_find_pnode(pn) != nullptr; + if (is_bonded && (pt != CycloneV::OEIN || pi != 1)) + continue; + if (!is_bonded && (pt != CycloneV::DATAIN) && (pt != CycloneV::OEIN || pi != 0)) + continue; + cv->inv_set(pn2r.second, true); + break; + }; + case CycloneV::FPLL: { + if (pt == CycloneV::EXTSWITCH || (pt == CycloneV::CLKEN && pi < 2)) + cv->inv_set(pn2r.second, true); + break; + }; + default: + break; + } + } + } + + void write_dqs() + { + for (auto pos : cv->dqs16_get_pos()) { + int x = CycloneV::pos2x(pos), y = CycloneV::pos2y(pos); + // DQS bypass for used output pins + for (int z = 0; z < 16; z++) { + int ioy = y + (z / 4) - 2; + if (ioy < 0 || ioy >= int(cv->get_tile_sy())) + continue; + BelId bel = ctx->bel_by_block_idx(x, ioy, id_MISTRAL_IO, z % 4); + if (bel == BelId()) + continue; + CellInfo *ci = ctx->getBoundBelCell(bel); + if (ci == nullptr || (ci->type != id_MISTRAL_IO && ci->type != id_MISTRAL_OB)) + continue; // not an output + cv->bmux_m_set(CycloneV::DQS16, pos, CycloneV::INPUT_REG4_SEL, z, CycloneV::SEL_LOCKED_DPA); + cv->bmux_r_set(CycloneV::DQS16, pos, CycloneV::RB_T9_SEL_EREG_CFF_DELAY, z, 0x1f); + } + } } void write_routing() @@ -71,6 +172,7 @@ struct MistralBitgen cv->clear(); init(); write_routing(); + write_dqs(); } }; } // namespace diff --git a/mistral/family.cmake b/mistral/family.cmake index 441d81db..79681ba8 100644 --- a/mistral/family.cmake +++ b/mistral/family.cmake @@ -2,10 +2,13 @@ set(MISTRAL_ROOT "" CACHE STRING "Mistral install path") aux_source_directory(${MISTRAL_ROOT}/lib MISTRAL_LIB_FILES) add_library(mistral STATIC ${MISTRAL_LIB_FILES}) +target_compile_options(mistral PRIVATE -Wno-maybe-uninitialized) find_package(LibLZMA REQUIRED) foreach(family_target ${family_targets}) target_include_directories(${family_target} PRIVATE ${MISTRAL_ROOT}/lib ${LIBLZMA_INCLUDE_DIRS}) target_link_libraries(${family_target} PRIVATE mistral ${LIBLZMA_LIBRARIES}) + # Currently required to avoid issues with mistral (LTO means the warnings can end up in nextpnr) + target_link_options(${family_target} PRIVATE -Wno-maybe-uninitialized) endforeach() |