mirror of
https://github.com/YosysHQ/yosys
synced 2026-06-30 12:38:53 +00:00
[core] add rf techlibs
This commit is contained in:
parent
54f8505045
commit
d7cf53d86a
49 changed files with 34443 additions and 0 deletions
441
techlibs/rapidflex/src/rf_new_dsp.cc
Normal file
441
techlibs/rapidflex/src/rf_new_dsp.cc
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
#include "kernel/sigtools.h"
|
||||
#include "kernel/yosys.h"
|
||||
|
||||
USING_YOSYS_NAMESPACE
|
||||
PRIVATE_NAMESPACE_BEGIN
|
||||
|
||||
#include "pmgen/rf_new_dsp.h"
|
||||
|
||||
void swapinput(RTLIL::SigSpec &sigA, RTLIL::SigSpec &sigB) {
|
||||
if (GetSize(sigA) < GetSize(sigB)) {
|
||||
RTLIL::SigSpec sigC = sigB;
|
||||
sigB = sigA;
|
||||
sigA = sigC;
|
||||
}
|
||||
}
|
||||
|
||||
void rf_new_dsp(rf_new_dsp_pm &pm) {
|
||||
auto &st = pm.st_rf_new_dsp;
|
||||
|
||||
log("mul1: %s\n", log_id(st.mul1, "--"));
|
||||
log("mul2: %s\n", log_id(st.mul2, "--"));
|
||||
log("mul3: %s\n", log_id(st.mul3, "--"));
|
||||
log("mul4: %s\n", log_id(st.mul4, "--"));
|
||||
log("postAdd1: %s\n", log_id(st.postAdd1, "--"));
|
||||
log("postAdd2: %s\n", log_id(st.postAdd2, "--"));
|
||||
log("postAdd3: %s\n", log_id(st.postAdd3, "--"));
|
||||
log("postAdd4: %s\n", log_id(st.postAdd4, "--"));
|
||||
|
||||
RTLIL::SigSpec sigA, sigB, sigD, sigY;
|
||||
|
||||
// mode
|
||||
string mode;
|
||||
if (st.level == 4) {
|
||||
if (st.dinput)
|
||||
mode +=
|
||||
"1001"; // 4-level mac with d input: d + a1*b1 + a2*b2 + a3*b3 + a4*b4
|
||||
else
|
||||
mode +=
|
||||
"0000"; // 4-level mac without d input: a1*b1 + a2*b2 + a3*b3 + a4*b4
|
||||
}
|
||||
if (st.level == 3)
|
||||
mode += "1001"; // 3-level mac with d input: d + a1*b1 + a2*b2 + a3*b3
|
||||
if (st.level == 2) {
|
||||
if (st.dinput)
|
||||
mode += "0001"; // 2-level mac with d input: d + a1*b1 + a2*b2
|
||||
else
|
||||
mode += "0010"; // 2-level mac without d input: a1*b1 + a2*b2
|
||||
}
|
||||
if (st.level == 1) {
|
||||
if (st.dinput)
|
||||
mode += "0101"; // 1-level mac with d input: d + a1*b1
|
||||
else
|
||||
return;
|
||||
}
|
||||
|
||||
// input size
|
||||
int n_size = 0;
|
||||
int m_size = 0;
|
||||
int d_size = 0;
|
||||
|
||||
string cell_base_name = "mad";
|
||||
string cell_size_name = "";
|
||||
string cell_cfg_name = "";
|
||||
string cell_full_name = "";
|
||||
|
||||
if (st.mul1) {
|
||||
swapinput(st.sigA1, st.sigB1);
|
||||
n_size = n_size > GetSize(st.sigA1) ? n_size : GetSize(st.sigA1);
|
||||
m_size = m_size > GetSize(st.sigB1) ? m_size : GetSize(st.sigB1);
|
||||
}
|
||||
|
||||
if (st.mul2) {
|
||||
swapinput(st.sigA2, st.sigB2);
|
||||
n_size = n_size > GetSize(st.sigA2) ? n_size : GetSize(st.sigA2);
|
||||
m_size = m_size > GetSize(st.sigB2) ? m_size : GetSize(st.sigB2);
|
||||
}
|
||||
|
||||
if (st.mul3) {
|
||||
swapinput(st.sigA3, st.sigB3);
|
||||
n_size = n_size > GetSize(st.sigA3) ? n_size : GetSize(st.sigA3);
|
||||
m_size = m_size > GetSize(st.sigB3) ? m_size : GetSize(st.sigB3);
|
||||
}
|
||||
|
||||
if (st.mul4) {
|
||||
swapinput(st.sigA4, st.sigB4);
|
||||
n_size = n_size > GetSize(st.sigA4) ? n_size : GetSize(st.sigA4);
|
||||
m_size = m_size > GetSize(st.sigB4) ? m_size : GetSize(st.sigB4);
|
||||
}
|
||||
|
||||
if (st.dinput)
|
||||
d_size = GetSize(st.sigD);
|
||||
|
||||
if (mode == "0100") {
|
||||
n_size = (n_size + 1) / 2;
|
||||
m_size = (m_size + 1) / 2;
|
||||
}
|
||||
|
||||
if (n_size <= 2 && m_size <= 2 && d_size <= 4) {
|
||||
// Too narrow
|
||||
return;
|
||||
} else if (n_size <= 12 && m_size <= 10 && d_size <= 30) {
|
||||
cell_size_name = "12x10x22";
|
||||
n_size = 12;
|
||||
m_size = 10;
|
||||
d_size = 30;
|
||||
} else if (n_size <= 24 && m_size <= 20 && d_size <= 52) {
|
||||
cell_size_name = "24x20x44";
|
||||
n_size = 24;
|
||||
m_size = 20;
|
||||
d_size = 52;
|
||||
} else {
|
||||
// Too wide
|
||||
return;
|
||||
}
|
||||
|
||||
// cell
|
||||
cell_full_name = cell_base_name + cell_size_name + cell_cfg_name;
|
||||
|
||||
string cellname;
|
||||
cellname += "newdsp_" + RTLIL::unescape_id(st.mul1->name);
|
||||
RTLIL::Cell *cell = pm.module->addCell(RTLIL::escape_id(cellname),
|
||||
RTLIL::escape_id(cell_full_name));
|
||||
|
||||
// D input
|
||||
bool d_signed = false;
|
||||
if (st.dinput) {
|
||||
d_signed = st.postAdd1->getParam(ID(A_SIGNED)).as_bool();
|
||||
if (mode == "0001")
|
||||
sigD.extend_u0(d_size);
|
||||
sigD.append(st.sigD);
|
||||
}
|
||||
sigD.extend_u0(2 * d_size, d_signed);
|
||||
|
||||
// output
|
||||
if (st.multiout2 || st.multiout3) {
|
||||
auto *wire = pm.module->addWire(NEW_ID, d_size - GetSize(st.sigY2));
|
||||
sigY.append(st.sigY2);
|
||||
sigY.append(wire);
|
||||
sigY.append(st.sigY);
|
||||
} else if (mode == "0001" || (st.level == 4 && st.dinput)) {
|
||||
auto *wire = pm.module->addWire(NEW_ID, d_size);
|
||||
sigY.append(wire);
|
||||
sigY.append(st.sigY);
|
||||
} else
|
||||
sigY.append(st.sigY);
|
||||
auto *wire = pm.module->addWire(NEW_ID, 2 * d_size - GetSize(sigY));
|
||||
sigY.append(wire);
|
||||
|
||||
// input
|
||||
bool a_signed, b_signed;
|
||||
if (mode == "0001") {
|
||||
sigA.extend_u0(2 * n_size);
|
||||
sigB.extend_u0(2 * m_size);
|
||||
}
|
||||
if (st.mul1 && mode != "0100") {
|
||||
a_signed = st.mul1->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul1->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA1.extend_u0(n_size, a_signed);
|
||||
st.sigB1.extend_u0(m_size, b_signed);
|
||||
sigA.append(st.sigA1);
|
||||
sigB.append(st.sigB1);
|
||||
}
|
||||
if (mode == "0100") {
|
||||
a_signed = st.mul1->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul1->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA1.extend_u0(2 * n_size, a_signed);
|
||||
st.sigB1.extend_u0(2 * m_size, b_signed);
|
||||
sigA.append(st.sigA1);
|
||||
sigB.append(st.sigB1);
|
||||
}
|
||||
if (!st.dinput && st.mul4) {
|
||||
a_signed = st.mul4->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul4->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA4.extend_u0(n_size, a_signed);
|
||||
st.sigB4.extend_u0(m_size, b_signed);
|
||||
sigA.append(st.sigA4);
|
||||
sigB.append(st.sigB4);
|
||||
}
|
||||
if (st.mul2) {
|
||||
a_signed = st.mul2->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul2->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA2.extend_u0(n_size, a_signed);
|
||||
st.sigB2.extend_u0(m_size, b_signed);
|
||||
sigA.append(st.sigA2);
|
||||
sigB.append(st.sigB2);
|
||||
}
|
||||
if (st.mul3) {
|
||||
a_signed = st.mul3->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul3->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA3.extend_u0(n_size, a_signed);
|
||||
st.sigB3.extend_u0(m_size, b_signed);
|
||||
sigA.append(st.sigA3);
|
||||
sigB.append(st.sigB3);
|
||||
}
|
||||
if (st.dinput && st.mul4) {
|
||||
a_signed = st.mul4->getParam(ID(A_SIGNED)).as_bool();
|
||||
b_signed = st.mul4->getParam(ID(B_SIGNED)).as_bool();
|
||||
st.sigA4.extend_u0(n_size, a_signed);
|
||||
st.sigB4.extend_u0(m_size, b_signed);
|
||||
sigA.append(st.sigA4);
|
||||
sigB.append(st.sigB4);
|
||||
}
|
||||
sigA.extend_u0(4 * n_size);
|
||||
sigB.extend_u0(4 * m_size);
|
||||
|
||||
// reg
|
||||
mode = "00000" + mode + "0000";
|
||||
if (st.level == 1) {
|
||||
if (st.ffA1 && st.ffB1 && !(st.dinput && !st.ffD)) {
|
||||
mode[1] = mode[2] = '1';
|
||||
pm.autoremove(st.ffA1);
|
||||
pm.autoremove(st.ffB1);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffD);
|
||||
}
|
||||
if (st.ffM1 && st.ffD && st.postAdd1) {
|
||||
mode[11] = '1';
|
||||
pm.autoremove(st.ffM1);
|
||||
pm.autoremove(st.ffD);
|
||||
}
|
||||
if (st.ffY1 || (!st.postAdd1 && st.ffM1)) {
|
||||
mode[3] = mode[4] = '1';
|
||||
pm.autoremove(st.ffY1);
|
||||
pm.autoremove(st.ffM1);
|
||||
}
|
||||
}
|
||||
if (st.level == 2) {
|
||||
if (st.ffA1 && st.ffB1 && st.ffA2 && st.ffB2 && st.dinput &&
|
||||
st.ffD) // in reg
|
||||
{
|
||||
mode[1] = mode[2] = '1';
|
||||
pm.autoremove(st.ffA1);
|
||||
pm.autoremove(st.ffB1);
|
||||
pm.autoremove(st.ffA2);
|
||||
pm.autoremove(st.ffB2);
|
||||
pm.autoremove(st.ffD);
|
||||
}
|
||||
if (st.ffA1 && st.ffB1 && st.ffA4 && st.ffB4 && !st.dinput) // in reg
|
||||
{
|
||||
mode[1] = mode[2] = '1';
|
||||
pm.autoremove(st.ffA1);
|
||||
pm.autoremove(st.ffB1);
|
||||
pm.autoremove(st.ffA4);
|
||||
pm.autoremove(st.ffB4);
|
||||
}
|
||||
if (st.ffM1 && ((st.dinput && st.ffM2) || st.ffD)) // mul in reg
|
||||
{
|
||||
mode[11] = '1';
|
||||
pm.autoremove(st.ffM1);
|
||||
pm.autoremove(st.ffD);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffM2);
|
||||
}
|
||||
if (st.ffY1 && st.ffY2 && st.dinput) // mul out reg
|
||||
{
|
||||
mode[12] = '1';
|
||||
pm.autoremove(st.ffY1);
|
||||
pm.autoremove(st.ffY2);
|
||||
} else if (st.ffY1 || st.ffY2) // out reg
|
||||
{
|
||||
mode[3] = mode[4] = '1';
|
||||
pm.autoremove(st.ffY1);
|
||||
pm.autoremove(st.ffY2);
|
||||
}
|
||||
}
|
||||
if (st.ffA1 && st.ffB1 && st.ffA2 && st.ffB2 && st.dinput &&
|
||||
st.ffD) // in reg low
|
||||
{
|
||||
mode[2] = '1';
|
||||
pm.autoremove(st.ffA1);
|
||||
pm.autoremove(st.ffB1);
|
||||
pm.autoremove(st.ffA2);
|
||||
pm.autoremove(st.ffB2);
|
||||
pm.autoremove(st.ffD);
|
||||
}
|
||||
if (st.ffA1 && st.ffB1 && st.ffA4 && st.ffB4 && !st.dinput) // in reg low
|
||||
{
|
||||
mode[2] = '1';
|
||||
pm.autoremove(st.ffA1);
|
||||
pm.autoremove(st.ffB1);
|
||||
pm.autoremove(st.ffA4);
|
||||
pm.autoremove(st.ffB4);
|
||||
}
|
||||
if (st.level == 3) {
|
||||
if (st.ffA3 && st.ffB3 && st.dinput) // in reg high
|
||||
{
|
||||
mode[1] = '1';
|
||||
pm.autoremove(st.ffA3);
|
||||
pm.autoremove(st.ffB3);
|
||||
}
|
||||
if (st.ffA2 && st.ffB2 && !st.dinput) // in reg high
|
||||
{
|
||||
mode[1] = '1';
|
||||
pm.autoremove(st.ffA2);
|
||||
pm.autoremove(st.ffB2);
|
||||
}
|
||||
if (st.ffM1 && st.ffM2 && ((st.dinput && st.ffM3) || st.ffD)) // mul in reg
|
||||
{
|
||||
mode[11] = '1';
|
||||
pm.autoremove(st.ffM1);
|
||||
pm.autoremove(st.ffD);
|
||||
pm.autoremove(st.ffM2);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffM3);
|
||||
}
|
||||
if (st.ffY1 && st.ffY2 && !(st.dinput && !st.ffY3)) // mul out reg
|
||||
{
|
||||
mode[12] = '1';
|
||||
pm.autoremove(st.ffY1);
|
||||
pm.autoremove(st.ffY2);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffY3);
|
||||
} else if (st.ffY2 || st.ffY3) // out reg
|
||||
{
|
||||
mode[3] = mode[4] = '1';
|
||||
pm.autoremove(st.ffY2);
|
||||
pm.autoremove(st.ffY3);
|
||||
}
|
||||
}
|
||||
if (st.level == 4) {
|
||||
if (st.ffA3 && st.ffB3 && st.ffA4 && st.ffB4 && st.dinput) // in reg high
|
||||
{
|
||||
mode[1] = '1';
|
||||
pm.autoremove(st.ffA3);
|
||||
pm.autoremove(st.ffB3);
|
||||
pm.autoremove(st.ffA4);
|
||||
pm.autoremove(st.ffB4);
|
||||
}
|
||||
if (st.ffA2 && st.ffB2 && st.ffA3 && st.ffB3 && !st.dinput) // in reg high
|
||||
{
|
||||
mode[1] = '1';
|
||||
pm.autoremove(st.ffA2);
|
||||
pm.autoremove(st.ffB2);
|
||||
pm.autoremove(st.ffA3);
|
||||
pm.autoremove(st.ffB3);
|
||||
}
|
||||
if (st.ffM1 && st.ffM2 && st.ffM3 &&
|
||||
((st.dinput && st.ffM4) || st.ffD)) // mul in reg
|
||||
{
|
||||
mode[11] = '1';
|
||||
pm.autoremove(st.ffM1);
|
||||
pm.autoremove(st.ffD);
|
||||
pm.autoremove(st.ffM2);
|
||||
pm.autoremove(st.ffM3);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffM4);
|
||||
}
|
||||
if (st.ffY1 && st.ffY2 && st.ffY3 &&
|
||||
!(st.dinput && !st.ffY4)) // mul out reg
|
||||
{
|
||||
mode[12] = '1';
|
||||
pm.autoremove(st.ffY1);
|
||||
pm.autoremove(st.ffY2);
|
||||
pm.autoremove(st.ffY3);
|
||||
if (st.dinput)
|
||||
pm.autoremove(st.ffY4);
|
||||
} else if (st.ffY3 || st.ffY4) // out reg high
|
||||
{
|
||||
if (st.multiout2 || st.multiout3)
|
||||
mode[3] = '1';
|
||||
else
|
||||
mode[3] = mode[4] = '1';
|
||||
pm.autoremove(st.ffY3);
|
||||
pm.autoremove(st.ffY4);
|
||||
}
|
||||
if (st.ffMY) // out reg low
|
||||
{
|
||||
mode[4] = '1';
|
||||
pm.autoremove(st.ffMY);
|
||||
}
|
||||
}
|
||||
|
||||
cell->setPort(RTLIL::escape_id("a_i"), sigA);
|
||||
cell->setPort(RTLIL::escape_id("b_i"), sigB);
|
||||
cell->setPort(RTLIL::escape_id("d_i"), sigD);
|
||||
cell->setPort(RTLIL::escape_id("out_o"), sigY);
|
||||
cell->setPort(RTLIL::escape_id("mode_i"), Const::from_string(mode));
|
||||
if (st.clock != SigBit())
|
||||
cell->setPort(RTLIL::escape_id("clk_i"), st.clock);
|
||||
cell->setPort(RTLIL::escape_id("rst_acc"), RTLIL::SigSpec(0, 1));
|
||||
cell->setPort(RTLIL::escape_id("accsel"), RTLIL::SigSpec(0, 1));
|
||||
cell->setPort(RTLIL::escape_id("cas_g"), RTLIL::SigSpec(0, 1));
|
||||
|
||||
pm.autoremove(st.mul1);
|
||||
pm.autoremove(st.mul2);
|
||||
pm.autoremove(st.mul3);
|
||||
pm.autoremove(st.mul4);
|
||||
pm.autoremove(st.postAdd1);
|
||||
pm.autoremove(st.postAdd2);
|
||||
pm.autoremove(st.postAdd3);
|
||||
pm.autoremove(st.postAdd4);
|
||||
}
|
||||
|
||||
struct RfNewDSP : public Pass {
|
||||
bool show_help;
|
||||
|
||||
RfNewDSP()
|
||||
: Pass("rf_new_dsp",
|
||||
"Extract multiply-add operators and map to new_dsps") {}
|
||||
|
||||
void help() override {
|
||||
log("\n");
|
||||
log(" rf_new_dsp [options] [selection]\n");
|
||||
log("\n");
|
||||
log(" Extract multiply-add operators and map to new_dsps\n");
|
||||
log("\n");
|
||||
log(" -help: show help desk\n");
|
||||
log("\n");
|
||||
log(" -n_size: specify input n size\n");
|
||||
log("\n");
|
||||
log(" -m_size: specify input m size\n");
|
||||
log("\n");
|
||||
}
|
||||
|
||||
void clear_flags() override { show_help = false; }
|
||||
|
||||
void execute(std::vector<std::string> a_Args,
|
||||
RTLIL::Design *a_Design) override {
|
||||
log_header(a_Design, "Executing RF_NEW_DSP pass.\n");
|
||||
size_t argidx;
|
||||
for (argidx = 1; argidx < a_Args.size(); argidx++) {
|
||||
if (a_Args[argidx] == "-help") {
|
||||
show_help = true;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
extra_args(a_Args, argidx, a_Design);
|
||||
if (show_help) {
|
||||
help();
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto module : a_Design->selected_modules()) {
|
||||
rf_new_dsp_pm pm(module, module->selected_cells());
|
||||
pm.run_rf_new_dsp(rf_new_dsp);
|
||||
}
|
||||
}
|
||||
} RfNewDsp;
|
||||
|
||||
PRIVATE_NAMESPACE_END
|
||||
Loading…
Add table
Add a link
Reference in a new issue