mistral: Setting some more boilerplate bits
Signed-off-by: gatecat <gatecat@ds0.me>
This commit is contained in:
parent
27eb3be7da
commit
dea4c6f53f
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
Loading…
Reference in New Issue
Block a user