mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Perform C -> PCIN optimisation after pattern matcher
This commit is contained in:
parent
1b0e68db94
commit
2f04beeeb5
|
@ -23,22 +23,23 @@
|
||||||
USING_YOSYS_NAMESPACE
|
USING_YOSYS_NAMESPACE
|
||||||
PRIVATE_NAMESPACE_BEGIN
|
PRIVATE_NAMESPACE_BEGIN
|
||||||
|
|
||||||
template<class T> bool includes(const T &lhs, const T &rhs) {
|
template<class T> inline bool includes(const T &lhs, const T &rhs) {
|
||||||
return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
return std::includes(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());
|
||||||
}
|
}
|
||||||
|
#include <set>
|
||||||
#include "passes/pmgen/xilinx_dsp_pm.h"
|
#include "passes/pmgen/xilinx_dsp_pm.h"
|
||||||
|
|
||||||
void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
void pack_xilinx_dsp(dict<SigBit, Cell*> &bit_to_driver, xilinx_dsp_pm &pm)
|
||||||
{
|
{
|
||||||
auto &st = pm.st_xilinx_dsp;
|
auto &st = pm.st_xilinx_dsp;
|
||||||
|
|
||||||
#if 1
|
#if 1
|
||||||
log("\n");
|
log("\n");
|
||||||
log("ffA: %s\n", log_id(st.ffA, "--"));
|
log("ffA: %s\n", log_id(st.ffA, "--"));
|
||||||
log("ffB: %s\n", log_id(st.ffB, "--"));
|
log("ffB: %s\n", log_id(st.ffB, "--"));
|
||||||
log("dsp: %s\n", log_id(st.dsp, "--"));
|
log("dsp: %s\n", log_id(st.dsp, "--"));
|
||||||
log("addAB: %s\n", log_id(st.addAB, "--"));
|
log("addAB: %s\n", log_id(st.addAB, "--"));
|
||||||
log("ffP: %s\n", log_id(st.ffP, "--"));
|
log("ffP: %s\n", log_id(st.ffP, "--"));
|
||||||
//log("muxP: %s\n", log_id(st.muxP, "--"));
|
//log("muxP: %s\n", log_id(st.muxP, "--"));
|
||||||
log("sigPused: %s\n", log_signal(st.sigPused));
|
log("sigPused: %s\n", log_signal(st.sigPused));
|
||||||
#endif
|
#endif
|
||||||
|
@ -46,11 +47,17 @@ void pack_xilinx_dsp(xilinx_dsp_pm &pm)
|
||||||
log("Analysing %s.%s for Xilinx DSP 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;
|
Cell *cell = st.dsp;
|
||||||
|
bit_to_driver.insert(std::make_pair(cell->getPort("\\P")[17], cell));
|
||||||
SigSpec P = st.sigP;
|
SigSpec P = st.sigP;
|
||||||
|
|
||||||
if (st.addAB) {
|
if (st.addAB) {
|
||||||
|
log_assert(st.addAB->getParam("\\A_SIGNED").as_bool());
|
||||||
|
log_assert(st.addAB->getParam("\\B_SIGNED").as_bool());
|
||||||
log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
log(" adder %s (%s)\n", log_id(st.addAB), log_id(st.addAB->type));
|
||||||
cell->setPort("\\C", st.sigC.extend_u0(48, true));
|
|
||||||
|
SigSpec C = st.sigC;
|
||||||
|
C.extend_u0(48, true);
|
||||||
|
cell->setPort("\\C", C);
|
||||||
SigSpec &opmode = cell->connections_.at("\\OPMODE");
|
SigSpec &opmode = cell->connections_.at("\\OPMODE");
|
||||||
opmode[6] = State::S0;
|
opmode[6] = State::S0;
|
||||||
opmode[5] = State::S1;
|
opmode[5] = State::S1;
|
||||||
|
@ -153,8 +160,48 @@ struct XilinxDspPass : public Pass {
|
||||||
}
|
}
|
||||||
extra_args(args, argidx, design);
|
extra_args(args, argidx, design);
|
||||||
|
|
||||||
for (auto module : design->selected_modules())
|
for (auto module : design->selected_modules()) {
|
||||||
xilinx_dsp_pm(module, module->selected_cells()).run_xilinx_dsp(pack_xilinx_dsp);
|
xilinx_dsp_pm pm(module, module->selected_cells());
|
||||||
|
dict<SigBit, Cell*> bit_to_driver;
|
||||||
|
auto f = [&bit_to_driver](xilinx_dsp_pm &pm){ pack_xilinx_dsp(bit_to_driver, pm); };
|
||||||
|
pm.run_xilinx_dsp(f);
|
||||||
|
|
||||||
|
// Look for ability to convert C input from another DSP into PCIN
|
||||||
|
// NB: Needs to be done after pattern matcher has folded all
|
||||||
|
// $add cells into the DSP
|
||||||
|
for (auto cell : module->cells()) {
|
||||||
|
if (cell->type != "\\DSP48E1")
|
||||||
|
continue;
|
||||||
|
SigSpec &opmode = cell->connections_.at("\\OPMODE");
|
||||||
|
if (opmode.extract(4,3) != Const::from_string("011"))
|
||||||
|
continue;
|
||||||
|
SigSpec C = pm.sigmap(cell->getPort("\\C"));
|
||||||
|
if (C.has_const())
|
||||||
|
continue;
|
||||||
|
auto it = bit_to_driver.find(C[0]);
|
||||||
|
if (it == bit_to_driver.end())
|
||||||
|
continue;
|
||||||
|
auto driver = it->second;
|
||||||
|
|
||||||
|
// Unextend C
|
||||||
|
int i;
|
||||||
|
for (i = GetSize(C)-1; i > 0; i--)
|
||||||
|
if (C[i] != C[i-1])
|
||||||
|
break;
|
||||||
|
if (i > 48-17)
|
||||||
|
continue;
|
||||||
|
if (driver->getPort("\\P").extract(17, i) == C.extract(0, i)) {
|
||||||
|
cell->setPort("\\C", Const(0, 48));
|
||||||
|
Wire *cascade = module->addWire(NEW_ID, 48);
|
||||||
|
driver->setPort("\\PCOUT", cascade);
|
||||||
|
cell->setPort("\\PCIN", cascade);
|
||||||
|
opmode[6] = State::S1;
|
||||||
|
opmode[5] = State::S0;
|
||||||
|
opmode[4] = State::S1;
|
||||||
|
bit_to_driver.erase(it);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} XilinxDspPass;
|
} XilinxDspPass;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
pattern xilinx_dsp
|
pattern xilinx_dsp
|
||||||
|
|
||||||
state <SigBit> clock
|
state <SigBit> clock
|
||||||
|
state <std::set<SigBit>> sigAset sigBset
|
||||||
state <SigSpec> sigC sigP sigPused
|
state <SigSpec> sigC sigP sigPused
|
||||||
state <Cell*> addAB
|
state <Cell*> addAB
|
||||||
|
|
||||||
|
@ -8,13 +9,22 @@ match dsp
|
||||||
select dsp->type.in(\DSP48E1)
|
select dsp->type.in(\DSP48E1)
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
|
code sigAset sigBset
|
||||||
|
SigSpec A = port(dsp, \A);
|
||||||
|
A.remove_const();
|
||||||
|
sigAset = A.to_sigbit_set();
|
||||||
|
SigSpec B = port(dsp, \B);
|
||||||
|
B.remove_const();
|
||||||
|
sigBset = B.to_sigbit_set();
|
||||||
|
endcode
|
||||||
|
|
||||||
match ffA
|
match ffA
|
||||||
if param(dsp, \AREG).as_int() == 0
|
if param(dsp, \AREG).as_int() == 0
|
||||||
if !port(dsp, \A).remove_const().empty()
|
if !sigAset.empty()
|
||||||
select ffA->type.in($dff)
|
select ffA->type.in($dff)
|
||||||
// DSP48E1 does not support clock inversion
|
// DSP48E1 does not support clock inversion
|
||||||
select param(ffA, \CLK_POLARITY).as_bool()
|
select param(ffA, \CLK_POLARITY).as_bool()
|
||||||
filter includes(port(ffA, \Q).to_sigbit_set(), port(dsp, \A).remove_const().to_sigbit_set())
|
filter includes(port(ffA, \Q).to_sigbit_set(), sigAset)
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
|
@ -25,11 +35,11 @@ endcode
|
||||||
|
|
||||||
match ffB
|
match ffB
|
||||||
if param(dsp, \BREG).as_int() == 0
|
if param(dsp, \BREG).as_int() == 0
|
||||||
if !port(dsp, \B).remove_const().empty()
|
if !sigBset.empty()
|
||||||
select ffB->type.in($dff)
|
select ffB->type.in($dff)
|
||||||
// DSP48E1 does not support clock inversion
|
// DSP48E1 does not support clock inversion
|
||||||
select param(ffB, \CLK_POLARITY).as_bool()
|
select param(ffB, \CLK_POLARITY).as_bool()
|
||||||
filter includes(port(ffB, \Q).to_sigbit_set(), port(dsp, \B).remove_const().to_sigbit_set())
|
filter includes(port(ffB, \Q).to_sigbit_set(), sigBset)
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
|
@ -65,21 +75,18 @@ match addB
|
||||||
index <int> nusers(port(addB, \B)) === 2
|
index <int> nusers(port(addB, \B)) === 2
|
||||||
//index <SigSpec> port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
//index <SigSpec> port(addB, \B) === sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
||||||
filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP)
|
filter param(addB, \B_WIDTH).as_int() <= GetSize(sigP)
|
||||||
filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
filter port(addB, \B) == sigP.extract(0, param(addB, \B_WIDTH).as_int())
|
||||||
optional
|
optional
|
||||||
endmatch
|
endmatch
|
||||||
|
|
||||||
code addAB sigC sigP
|
code addAB sigC sigP
|
||||||
bool C_SIGNED = false;
|
|
||||||
if (addA) {
|
if (addA) {
|
||||||
addAB = addA;
|
addAB = addA;
|
||||||
sigC = port(addAB, \B);
|
sigC = port(addAB, \B);
|
||||||
C_SIGNED = param(addAB, \B_SIGNED).as_bool();
|
|
||||||
}
|
}
|
||||||
if (addB) {
|
if (addB) {
|
||||||
addAB = addB;
|
addAB = addB;
|
||||||
sigC = port(addAB, \A);
|
sigC = port(addAB, \A);
|
||||||
C_SIGNED = param(addAB, \B_SIGNED).as_bool();
|
|
||||||
}
|
}
|
||||||
if (addAB) {
|
if (addAB) {
|
||||||
// Ensure that adder is not used
|
// Ensure that adder is not used
|
||||||
|
@ -97,7 +104,6 @@ code addAB sigC sigP
|
||||||
// reject;
|
// reject;
|
||||||
|
|
||||||
sigP = port(addAB, \Y);
|
sigP = port(addAB, \Y);
|
||||||
sigC.extend_u0(32, C_SIGNED);
|
|
||||||
}
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue