mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Refactor MREG and PREG to out_dffe subpattern
This commit is contained in:
parent
e64e650f9c
commit
8b8a68b38a
|
@ -7,12 +7,12 @@ state <IdString> postAddAB postAddMuxAB
|
||||||
state <bool> ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol
|
state <bool> ffAenpol ffADenpol ffBenpol ffCenpol ffDenpol ffMenpol ffPenpol
|
||||||
state <int> ffPoffset
|
state <int> ffPoffset
|
||||||
|
|
||||||
state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux
|
state <Cell*> ffAD ffADmux ffA ffAmux ffB ffBmux ffC ffCmux ffD ffDmux ffM ffMmux ffP ffPmux
|
||||||
|
|
||||||
// subpattern
|
// subpattern
|
||||||
state <SigSpec> argQ
|
state <SigSpec> argQ argD
|
||||||
state <bool> ffenpol
|
state <bool> ffenpol
|
||||||
udata <SigSpec> dffD
|
udata <SigSpec> dffD dffQ
|
||||||
udata <SigBit> dffclock
|
udata <SigBit> dffclock
|
||||||
udata <Cell*> dff dffmux
|
udata <Cell*> dff dffmux
|
||||||
udata <bool> dffenpol
|
udata <bool> dffenpol
|
||||||
|
@ -159,76 +159,20 @@ code argQ ffD ffDmux ffDenpol sigD clock
|
||||||
}
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match ffMmux
|
code argD ffM ffMmux ffMenpol sigM sigP clock
|
||||||
if param(dsp, \MREG).as_int() == 0
|
if (param(dsp, \MREG).as_int() == 0 && nusers(sigM) == 2) {
|
||||||
if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY"
|
argD = sigM;
|
||||||
if nusers(sigM) == 2
|
subpattern(out_dffe);
|
||||||
select ffMmux->type.in($mux)
|
if (dff) {
|
||||||
choice <IdString> BA {\B, \A}
|
ffM = dff;
|
||||||
// new-value net must have exactly two users: dsp and ffMmux
|
clock = dffclock;
|
||||||
select nusers(port(ffMmux, BA)) == 2
|
if (dffmux) {
|
||||||
define <IdString> AB (BA == \B ? \A : \B)
|
ffMmux = dffmux;
|
||||||
// keep-last-value net must have at least three users: ffMmux, ffM, downstream sink(s)
|
ffMenpol = dffenpol;
|
||||||
select nusers(port(ffMmux, AB)) >= 3
|
}
|
||||||
// ffMmux output must have two users: ffMmux and ffM.D
|
sigM = dffQ;
|
||||||
select nusers(port(ffMmux, \Y)) == 2
|
}
|
||||||
filter GetSize(unextend(port(ffMmux, BA))) <= GetSize(sigM)
|
|
||||||
filter unextend(port(ffMmux, BA)) == sigM.extract(0, GetSize(unextend(port(ffMmux, BA))))
|
|
||||||
// Remaining bits on sigM must not have any other users
|
|
||||||
filter nusers(sigM.extract_end(GetSize(unextend(port(ffMmux, BA))))) <= 1
|
|
||||||
define <bool> pol (AB == \A)
|
|
||||||
set ffMenpol pol
|
|
||||||
optional
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
code sigM
|
|
||||||
if (ffMmux)
|
|
||||||
sigM = port(ffMmux, \Y);
|
|
||||||
endcode
|
|
||||||
|
|
||||||
match ffM_enable
|
|
||||||
if ffMmux
|
|
||||||
if nusers(sigM) == 2
|
|
||||||
select ffM_enable->type.in($dff)
|
|
||||||
// DSP48E1 does not support clock inversion
|
|
||||||
select param(ffM_enable, \CLK_POLARITY).as_bool()
|
|
||||||
index <SigSpec> port(ffM_enable, \D) === sigM
|
|
||||||
index <SigSpec> port(ffM_enable, \Q) === port(ffMmux, ffMenpol ? \A : \B)
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match ffM
|
|
||||||
if dsp->parameters.at(\USE_MULT, Const("MULTIPLY")).decode_string() == "MULTIPLY"
|
|
||||||
if !ffM_enable
|
|
||||||
if param(dsp, \MREG).as_int() == 0
|
|
||||||
if nusers(sigM) == 2
|
|
||||||
select ffM->type.in($dff)
|
|
||||||
// DSP48E1 does not support clock inversion
|
|
||||||
select param(ffM, \CLK_POLARITY).as_bool()
|
|
||||||
index <SigSpec> port(ffM, \D) === sigM
|
|
||||||
optional
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
code ffM clock sigM sigP
|
|
||||||
if (ffM_enable) {
|
|
||||||
log_assert(!ffM);
|
|
||||||
ffM = ffM_enable;
|
|
||||||
}
|
}
|
||||||
if (ffM) {
|
|
||||||
sigM = port(ffM, \Q);
|
|
||||||
|
|
||||||
for (auto b : sigM)
|
|
||||||
if (b.wire->get_bool_attribute(\keep))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
SigBit c = port(ffM, \CLK).as_bit();
|
|
||||||
if (clock != SigBit() && c != clock)
|
|
||||||
reject;
|
|
||||||
clock = c;
|
|
||||||
}
|
|
||||||
// No enable mux possible without flop
|
|
||||||
else if (ffMmux)
|
|
||||||
reject;
|
|
||||||
|
|
||||||
sigP = sigM;
|
sigP = sigM;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
@ -268,90 +212,25 @@ code sigC sigP
|
||||||
}
|
}
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match ffPmux
|
code argD ffP ffPmux ffPenpol sigP clock
|
||||||
if param(dsp, \PREG).as_int() == 0
|
if (param(dsp, \PREG).as_int() == 0) {
|
||||||
// If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux
|
// If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux
|
||||||
if !ffMmux || postAdd || nusers(sigP) == 3
|
if ((ffMmux && !postAdd && nusers(sigP) == 3) ||
|
||||||
// Otherwise new-value net must have exactly two users: dsp and ffPmux
|
// Otherwise new-value net must have exactly two users: dsp and ffPmux
|
||||||
if (ffMmux && !postAdd) || nusers(sigP) == 2
|
((!ffMmux || postAdd) && nusers(sigP) == 2)) {
|
||||||
|
argD = sigP;
|
||||||
select ffPmux->type.in($mux)
|
subpattern(out_dffe);
|
||||||
// ffPmux output must have two users: ffPmux and ffP.D
|
if (dff) {
|
||||||
select nusers(port(ffPmux, \Y)) == 2
|
ffP = dff;
|
||||||
filter GetSize(port(ffPmux, \Y)) >= GetSize(sigP)
|
clock = dffclock;
|
||||||
|
if (dffmux) {
|
||||||
slice offset GetSize(port(ffPmux, \Y))
|
ffPmux = dffmux;
|
||||||
filter offset+GetSize(sigP) <= GetSize(port(ffPmux, \Y))
|
ffPenpol = dffenpol;
|
||||||
choice <IdString> BA {\B, \A}
|
}
|
||||||
filter port(ffPmux, BA).extract(offset, GetSize(sigP)) == sigP
|
sigP = dffQ;
|
||||||
|
}
|
||||||
define <IdString> AB (BA == \B ? \A : \B)
|
}
|
||||||
// keep-last-value net must have at least three users: ffPmux, ffP, downstream sink(s)
|
|
||||||
filter nusers(port(ffPmux, AB)) >= 3
|
|
||||||
define <bool> pol (AB == \A)
|
|
||||||
set ffPenpol pol
|
|
||||||
set ffPoffset offset
|
|
||||||
optional
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
code sigP
|
|
||||||
if (ffPmux)
|
|
||||||
sigP.replace(port(ffPmux, ffPenpol ? \B : \A), port(ffPmux, \Y));
|
|
||||||
endcode
|
|
||||||
|
|
||||||
match ffP_enable
|
|
||||||
if ffPmux
|
|
||||||
if nusers(sigP) == 2
|
|
||||||
select ffP_enable->type.in($dff)
|
|
||||||
// DSP48E1 does not support clock inversion
|
|
||||||
select param(ffP_enable, \CLK_POLARITY).as_bool()
|
|
||||||
index <SigSpec> port(ffP_enable, \D) === port(ffPmux, \Y)
|
|
||||||
index <SigSpec> port(ffP_enable, \Q) === port(ffPmux, ffPenpol ? \A : \B)
|
|
||||||
filter GetSize(port(ffP_enable, \D)) >= GetSize(sigP)
|
|
||||||
filter ffPoffset+GetSize(sigP) <= GetSize(port(ffP_enable, \D))
|
|
||||||
filter port(ffP_enable, \D).extract(ffPoffset, GetSize(sigP)) == sigP
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
match ffP
|
|
||||||
if !ffP_enable
|
|
||||||
if param(dsp, \PREG).as_int() == 0
|
|
||||||
// If ffMmux and no postAdd new-value net must have exactly three users: ffMmux, ffM and ffPmux
|
|
||||||
if !ffMmux || postAdd || nusers(sigP) == 3
|
|
||||||
// Otherwise new-value net must have exactly two users: dsp and ffPmux
|
|
||||||
if (ffMmux && !postAdd) || nusers(sigP) == 2
|
|
||||||
|
|
||||||
select ffP->type.in($dff)
|
|
||||||
// DSP48E1 does not support clock inversion
|
|
||||||
select param(ffP, \CLK_POLARITY).as_bool()
|
|
||||||
filter GetSize(port(ffP, \D)) >= GetSize(sigP)
|
|
||||||
slice offset GetSize(port(ffP, \D))
|
|
||||||
filter offset+GetSize(sigP) <= GetSize(port(ffP, \D))
|
|
||||||
filter port(ffP, \D).extract(offset, GetSize(sigP)) == sigP
|
|
||||||
optional
|
|
||||||
endmatch
|
|
||||||
|
|
||||||
code ffP sigP clock
|
|
||||||
if (ffP_enable) {
|
|
||||||
log_assert(!ffP);
|
|
||||||
ffP = ffP_enable;
|
|
||||||
}
|
}
|
||||||
if (ffP) {
|
|
||||||
for (auto b : port(ffP, \Q))
|
|
||||||
if (b.wire->get_bool_attribute(\keep))
|
|
||||||
reject;
|
|
||||||
|
|
||||||
SigBit c = port(ffP, \CLK).as_bit();
|
|
||||||
|
|
||||||
if (clock != SigBit() && c != clock)
|
|
||||||
reject;
|
|
||||||
|
|
||||||
clock = c;
|
|
||||||
|
|
||||||
sigP.replace(port(ffP, \D), port(ffP, \Q));
|
|
||||||
}
|
|
||||||
// No enable mux possible without flop
|
|
||||||
else if (ffPmux)
|
|
||||||
reject;
|
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
match postAddMux
|
match postAddMux
|
||||||
|
@ -391,6 +270,8 @@ code
|
||||||
accept;
|
accept;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
// #######################
|
||||||
|
|
||||||
subpattern in_dffe
|
subpattern in_dffe
|
||||||
arg argQ clock ffenpol
|
arg argQ clock ffenpol
|
||||||
|
|
||||||
|
@ -457,3 +338,89 @@ code
|
||||||
else
|
else
|
||||||
dffmux = nullptr;
|
dffmux = nullptr;
|
||||||
endcode
|
endcode
|
||||||
|
|
||||||
|
// #######################
|
||||||
|
|
||||||
|
subpattern out_dffe
|
||||||
|
arg argD clock ffenpol
|
||||||
|
arg unextend
|
||||||
|
|
||||||
|
match ffmux
|
||||||
|
select ffmux->type.in($mux)
|
||||||
|
// ffmux output must have two users: ffmux and ff.D
|
||||||
|
select nusers(port(ffmux, \Y)) == 2
|
||||||
|
filter GetSize(port(ffmux, \Y)) >= GetSize(argD)
|
||||||
|
|
||||||
|
choice <IdString> BA {\B, \A}
|
||||||
|
// new-value net must have exactly two users: (upstream) and ffmux
|
||||||
|
select nusers(port(ffmux, BA)) == 2
|
||||||
|
|
||||||
|
slice offset GetSize(port(ffmux, \Y))
|
||||||
|
filter offset+GetSize(argD) <= GetSize(port(ffmux, \Y))
|
||||||
|
filter port(ffmux, BA).extract(offset, GetSize(argD)) == argD
|
||||||
|
|
||||||
|
define <IdString> AB (BA == \B ? \A : \B)
|
||||||
|
// keep-last-value net must have at least three users: ffmux, ff, downstream sink(s)
|
||||||
|
select nusers(port(ffmux, AB)) >= 3
|
||||||
|
|
||||||
|
filter GetSize(unextend(port(ffmux, BA))) <= GetSize(argD)
|
||||||
|
filter unextend(port(ffmux, BA)) == argD.extract(0, GetSize(unextend(port(ffmux, BA))))
|
||||||
|
// Remaining bits on argD must not have any other users
|
||||||
|
filter nusers(argD.extract_end(GetSize(unextend(port(ffmux, BA))))) <= 1
|
||||||
|
|
||||||
|
define <bool> pol (AB == \A)
|
||||||
|
set ffenpol pol
|
||||||
|
semioptional
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code argD
|
||||||
|
if (ffmux) {
|
||||||
|
dffmux = ffmux;
|
||||||
|
dffenpol = ffenpol;
|
||||||
|
argD = port(ffmux, \Y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
dffmux = nullptr;
|
||||||
|
endcode
|
||||||
|
|
||||||
|
match ff_enable
|
||||||
|
if ffmux
|
||||||
|
select ff_enable->type.in($dff)
|
||||||
|
// DSP48E1 does not support clock inversion
|
||||||
|
select param(ff_enable, \CLK_POLARITY).as_bool()
|
||||||
|
index <SigSpec> port(ff_enable, \D) === argD
|
||||||
|
index <SigSpec> port(ff_enable, \Q) === port(ffmux, ffenpol ? \A : \B)
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
match ff
|
||||||
|
if !ff_enable
|
||||||
|
select ff->type.in($dff)
|
||||||
|
// DSP48E1 does not support clock inversion
|
||||||
|
select param(ff, \CLK_POLARITY).as_bool()
|
||||||
|
index <SigSpec> port(ff, \D) === argD
|
||||||
|
semioptional
|
||||||
|
endmatch
|
||||||
|
|
||||||
|
code
|
||||||
|
if (ff_enable)
|
||||||
|
dff = ff_enable;
|
||||||
|
else
|
||||||
|
dff = ff;
|
||||||
|
log_dump("ffM", dff, dffmux);
|
||||||
|
if (dff) {
|
||||||
|
dffQ = port(dff, \Q);
|
||||||
|
|
||||||
|
for (auto b : dffQ)
|
||||||
|
if (b.wire->get_bool_attribute(\keep))
|
||||||
|
reject;
|
||||||
|
|
||||||
|
if (clock != SigBit()) {
|
||||||
|
if (port(dff, \CLK) != clock)
|
||||||
|
reject;
|
||||||
|
}
|
||||||
|
dffclock = port(dff, \CLK);
|
||||||
|
}
|
||||||
|
// No enable mux possible without flop
|
||||||
|
else if (ffmux)
|
||||||
|
reject;
|
||||||
|
endcode
|
||||||
|
|
Loading…
Reference in a new issue