mirror of https://github.com/YosysHQ/yosys.git
Pack partial-product adder DSP48E1 packing
This commit is contained in:
parent
a002eba14a
commit
0b5b56c1ec
|
@ -37,16 +37,26 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
|||
log("ffA: %s\n", log_id(st.ffA, "--"));
|
||||
log("ffB: %s\n", log_id(st.ffB, "--"));
|
||||
log("dsp: %s\n", log_id(st.dsp, "--"));
|
||||
log("addAB: %s\n", log_id(st.addAB, "--"));
|
||||
log("ffP: %s\n", log_id(st.ffP, "--"));
|
||||
//log("muxP: %s\n", log_id(st.muxP, "--"));
|
||||
log("sigPused: %s\n", log_signal(st.sigPused));
|
||||
log_module(pm.module);
|
||||
#endif
|
||||
|
||||
log("Analysing %s.%s for Xilinx DSP register packing.\n", log_id(pm.module), log_id(st.dsp));
|
||||
log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp));
|
||||
|
||||
Cell *cell = st.dsp;
|
||||
log_assert(cell);
|
||||
SigSpec P = st.sigP;
|
||||
|
||||
if (st.addAB) {
|
||||
log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
||||
cell->setPort("\\C", st.sigC.extend_u0(48, true));
|
||||
SigSpec &opmode = cell->connections_.at("\\OPMODE");
|
||||
opmode[6] = State::S0;
|
||||
opmode[5] = State::S1;
|
||||
opmode[4] = State::S1;
|
||||
pm.autoremove(st.addAB);
|
||||
}
|
||||
|
||||
if (st.clock != SigBit())
|
||||
{
|
||||
|
@ -79,7 +89,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
|||
else log_abort();
|
||||
}
|
||||
if (st.ffP) {
|
||||
SigSpec P = cell->getPort("\\P");
|
||||
SigSpec D;
|
||||
//if (st.muxP)
|
||||
// D = st.muxP->getPort("\\B");
|
||||
|
@ -87,7 +96,6 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
|||
D = st.ffP->getPort("\\D");
|
||||
SigSpec Q = st.ffP->getPort("\\Q");
|
||||
P.replace(pm.sigmap(D), Q);
|
||||
cell->setPort("\\P", P);
|
||||
cell->setParam("\\PREG", State::S1);
|
||||
if (st.ffP->type == "$dff")
|
||||
cell->setPort("\\CEP", State::S1);
|
||||
|
@ -112,6 +120,10 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
|||
log("\n");
|
||||
}
|
||||
|
||||
if (GetSize(P) < 48)
|
||||
P.append(pm.module->addWire(NEW_ID, 48-GetSize(P)));
|
||||
cell->setPort("\\P", P);
|
||||
|
||||
pm.blacklist(cell);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
pattern xilinx_dsp
|
||||
|
||||
state <SigBit> clock
|
||||
state <SigSpec> sigPused
|
||||
state <SigSpec> sigC sigP sigPused
|
||||
state <Cell*> addAB
|
||||
|
||||
match dsp
|
||||
select dsp->type.in(\DSP48E1)
|
||||
|
@ -43,13 +44,69 @@ code clock
|
|||
}
|
||||
endcode
|
||||
|
||||
code sigP
|
||||
sigP = port(dsp, \P);
|
||||
endcode
|
||||
|
||||
match addA
|
||||
select addA->type.in($add)
|
||||
select param(addA, \A_SIGNED).as_bool() && param(addA, \B_SIGNED).as_bool()
|
||||
select nusers(port(addA, \A)) == 2
|
||||
//index <SigSpec> port(addA, \A) === sigP.extract(0, param(addA, \A_WIDTH).as_int())
|
||||
filter GetSize(sigP) >= param(addA, \A_WIDTH).as_int()
|
||||
filter port(addA, \A) == sigP.extract(0, param(addA, \A_WIDTH).as_int())
|
||||
optional
|
||||
endmatch
|
||||
|
||||
match addB
|
||||
if !addA
|
||||
select addB->type.in($add, $sub)
|
||||
select param(addB, \A_SIGNED).as_bool() && param(addB, \B_SIGNED).as_bool()
|
||||
select nusers(port(addB, \B)) == 2
|
||||
//index <SigSpec> port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
||||
filter GetSize(sigP) >= param(addB, \B_WIDTH).as_int()
|
||||
filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
||||
optional
|
||||
endmatch
|
||||
|
||||
code addAB sigC sigP
|
||||
bool C_SIGNED = false;
|
||||
if (addA) {
|
||||
addAB = addA;
|
||||
sigC = port(addAB, \B);
|
||||
C_SIGNED = param(addAB, \B_SIGNED).as_bool();
|
||||
}
|
||||
if (addB) {
|
||||
addAB = addB;
|
||||
sigC = port(addAB, \A);
|
||||
C_SIGNED = param(addAB, \B_SIGNED).as_bool();
|
||||
}
|
||||
if (addAB) {
|
||||
// Ensure that adder is not used
|
||||
SigSpec opmodeZ = port(dsp, \OPMODE).extract(4,3);
|
||||
if (!opmodeZ.is_fully_zero())
|
||||
reject;
|
||||
|
||||
int natural_mul_width = GetSize(port(dsp, \A)) + GetSize(port(dsp, \B));
|
||||
int actual_mul_width = GetSize(sigP);
|
||||
int actual_acc_width = GetSize(sigC);
|
||||
|
||||
if ((actual_acc_width > actual_mul_width) && (natural_mul_width > actual_mul_width))
|
||||
reject;
|
||||
//if ((actual_acc_width != actual_mul_width) && (param(dsp, \A_SIGNED).as_bool() != param(addAB, \A_SIGNED).as_bool()))
|
||||
// reject;
|
||||
|
||||
sigP = port(addAB, \Y);
|
||||
sigC.extend_u0(32, C_SIGNED);
|
||||
}
|
||||
endcode
|
||||
|
||||
// Extract the bits of P that actually have a consumer
|
||||
// (as opposed to being a dummy)
|
||||
code sigPused
|
||||
SigSpec P = port(dsp, \P);
|
||||
for (int i = 0; i < GetSize(P); i++)
|
||||
if (P[i].wire && nusers(P[i]) > 1)
|
||||
sigPused.append(P[i]);
|
||||
for (int i = 0; i < GetSize(sigP); i++)
|
||||
if (sigP[i].wire && nusers(sigP[i]) > 1)
|
||||
sigPused.append(sigP[i]);
|
||||
endcode
|
||||
|
||||
match ffP
|
||||
|
|
|
@ -287,6 +287,8 @@ struct SynthXilinxPass : public ScriptPass
|
|||
if (!nodsp || help_mode) {
|
||||
// NB: Xilinx multipliers are signed only
|
||||
run("techmap -map +/mul2dsp.v -map +/xilinx/dsp_map.v -D DSP_A_MAXWIDTH=25 -D DSP_B_MAXWIDTH=18 -D DSP_SIGNEDONLY=1 -D DSP_NAME=$__MUL25X18", "(skip if '-nodsp')");
|
||||
run("opt_expr -fine", " (skip if '-nodsp')");
|
||||
run("wreduce", " (skip if '-nodsp')");
|
||||
run("xilinx_dsp", " (skip if '-nodsp')");
|
||||
run("chtype -set $mul t:$__soft_mul"," (skip if '-nodsp')");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue