log("postAdd: %s\n", log_id(st.postAdd, "--"));
log("postAddMux: %s\n", log_id(st.postAddMux, "--"));
log("ffP: %s %s %s\n", log_id(st.ffP, "--"), log_id(st.ffPcemux, "--"), log_id(st.ffPrstmux, "--"));
+ log("overflow: %s\n", log_id(st.overflow, "--"));
#endif
log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp));
pm.autoremove(st.postAdd);
}
+ if (st.overflow) {
+ log(" overflow %s (%s)\n", log_id(st.overflow), log_id(st.overflow->type));
+ cell->setParam("\\USE_PATTERN_DETECT", Const("PATDET"));
+ cell->setParam("\\SEL_PATTERN", Const("PATTERN"));
+ cell->setParam("\\SEL_MASK", Const("MASK"));
+
+ if (st.overflow->type == "$ge") {
+ int B = st.overflow->getPort("\\B").as_int();
+ log_assert((B & (B-1)) == 0); // Exact power of 2
+
+ cell->setParam("\\MASK", Const(B-1, 48));
+ cell->setParam("\\PATTERN", Const(0, 48));
+ cell->setPort("\\OVERFLOW", st.overflow->getPort("\\Y"));
+ }
+ else log_abort();
+
+ pm.autoremove(st.overflow);
+ }
if (st.clock != SigBit())
{
select postAdd->type.in($add)
select GetSize(port(postAdd, \Y)) <= 48
- select nusers(port(postAdd, \Y)) == 2
choice <IdString> AB {\A, \B}
select nusers(port(postAdd, AB)) <= 3
filter ffMcemux || nusers(port(postAdd, AB)) == 2
}
endcode
+match overflow
+ if ffP
+ if dsp->parameters.at(\USE_PATTERN_DETECT, Const("NO_PATDET")).decode_string() == "NO_PATDET"
+ select overflow->type.in($ge)
+ select GetSize(port(overflow, \Y)) <= 48
+ select port(overflow, \B).is_fully_const()
+ // Check is exact power of 2
+ select (port(overflow, \B).as_int() & (port(overflow, \B).as_int()-1)) == 0
+ index <SigSpec> port(overflow, \A) === sigP
+ optional
+endmatch
+
code
accept;
endcode