3
0
Fork 0
mirror of https://github.com/YosysHQ/yosys synced 2026-02-13 20:33:04 +00:00

Add support for subtraction in preadder

This commit is contained in:
Jeppe Johansen 2022-08-24 18:31:45 +02:00 committed by Gus Smith
parent 6dbe03f0f5
commit 44afd4bbdd
2 changed files with 44 additions and 8 deletions

View file

@ -263,6 +263,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
log("Analysing %s.%s for Xilinx DSP packing.\n", log_id(pm.module), log_id(st.dsp));
log_debug("preAdd: %s\n", log_id(st.preAdd, "--"));
log_debug("preSub: %s\n", log_id(st.preSub, "--"));
log_debug("ffAD: %s\n", log_id(st.ffAD, "--"));
log_debug("ffA2: %s\n", log_id(st.ffA2, "--"));
log_debug("ffA1: %s\n", log_id(st.ffA1, "--"));
@ -278,17 +279,22 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
Cell *cell = st.dsp;
if (st.preAdd) {
log(" preadder %s (%s)\n", log_id(st.preAdd), log_id(st.preAdd->type));
bool A_SIGNED = st.preAdd->getParam(ID::A_SIGNED).as_bool();
bool D_SIGNED = st.preAdd->getParam(ID::B_SIGNED).as_bool();
if (st.sigA == st.preAdd->getPort(ID::B))
if (st.preAdd || st.preSub) {
Cell* preAdder = st.preAdd ? st.preAdd : st.preSub;
log(" preadder %s (%s)\n", log_id(preAdder), log_id(preAdder->type));
bool A_SIGNED = preAdder->getParam(ID::A_SIGNED).as_bool();
bool D_SIGNED = preAdder->getParam(ID::B_SIGNED).as_bool();
if (st.sigA == preAdder->getPort(ID::B))
std::swap(A_SIGNED, D_SIGNED);
st.sigA.extend_u0(30, A_SIGNED);
st.sigD.extend_u0(25, D_SIGNED);
cell->setPort(ID::A, st.sigA);
cell->setPort(ID::D, st.sigD);
cell->setPort(ID(INMODE), Const::from_string("00100"));
if (preAdder->type == ID($add))
cell->setPort(ID(INMODE), Const::from_string("00100"));
else
cell->setPort(ID(INMODE), Const::from_string("01100"));
if (st.ffAD) {
if (st.ffAD->type.in(ID($dffe), ID($sdffe))) {
@ -303,7 +309,7 @@ void xilinx_dsp_pack(xilinx_dsp_pm &pm)
cell->setParam(ID(USE_DPORT), Const("TRUE"));
pm.autoremove(st.preAdd);
pm.autoremove(preAdder);
}
if (st.postAdd) {
log(" postadder %s (%s)\n", log_id(st.postAdd), log_id(st.postAdd->type));

View file

@ -6,6 +6,8 @@
// If ADREG matched, treat 'A' input as input of ADREG
// ( 3) Match the driver of the 'A' and 'D' inputs for a possible $add cell
// (pre-adder)
// (3.1) Match the driver of the 'A' and 'D' inputs for a possible $sub cell
// (pre-adder)
// ( 4) If pre-adder was present, find match 'A' input for A2REG
// If pre-adder was not present, move ADREG to A2REG
// If A2REG, then match 'A' input for A1REG
@ -152,13 +154,41 @@ code sigA sigD
}
endcode
// (3.1) Match the driver of the 'A' and 'D' inputs for a possible $sub cell
// (pre-adder)
match preSub
if sigD.empty() || sigD.is_fully_zero()
// Ensure that preAdder not already used
if param(dsp, \USE_DPORT).decode_string() == "FALSE"
if port(dsp, \INMODE, Const(0, 5)).is_fully_zero()
select preSub->type.in($sub)
// Output has to be 25 bits or less
select GetSize(port(preSub, \Y)) <= 25
select nusers(port(preSub, \Y)) == 2
// D port has to be 25 bits or less
select GetSize(port(preSub, \A)) <= 25
// A port has to be 30 bits or less
select GetSize(port(preSub, \B)) <= 30
index <SigSpec> port(preSub, \Y) === sigA
optional
endmatch
code sigA sigD
if (preSub) {
sigD = port(preSub, \A);
sigA = port(preSub, \B);
}
endcode
// (4) If pre-adder was present, find match 'A' input for A2REG
// If pre-adder was not present, move ADREG to A2REG
// Then match 'A' input for A1REG
code argQ ffAD sigA clock ffA2 ffA1
// Only search for ffA2 if there was a pre-adder
// (otherwise ffA2 would have been matched as ffAD)
if (preAdd) {
if (preAdd || preSub) {
if (param(dsp, \AREG).as_int() == 0) {
argQ = sigA;
subpattern(in_dffe);