-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Multiple guards leads to less efficient HDL than single guard of conjunction #2842
Comments
This is what the generated Verilog looks like (renamed a bit so more things line up) for one of the
And the same for
|
It seems the big difference is that in |
OK this is huge: by changing my guard in |
liftA2
'd produces much larger circuit than signal function
So, what would it take for Clash to be able to merge these conjunctions? I guess the problem is that by Core, this:
is turned into
But it sure would be neat if Clash could recognize this pattern and turn it into |
It would also be neat if the downstream logic synthesis tools would recognize this opportunity. What happens when you tell Vivado to optimize for size instead of whatever its default is? |
We recently encountered this as well, with the following snippet being inefficient: outReady = _dcSize == 0 || (_dcSize == 1 && inReady)
st' = case fwdIn of
Just inp | outReady -> fromPacketStreamM2S inp
_ -> st { _dcBuf = _dcBuf'
, _dcSize = _dcSize'
} and the equivalent but less pretty version that reduced the muxes this: outReady = _dcSize == 0 || (_dcSize == 1 && inReady)
st'
| isJust fwdIn && outReady = fromPacketStreamM2S (fromJustX fwdIn)
| otherwise = st { _dcBuf = _dcBuf'
, _dcSize = _dcSize'
} The combined guard collapsed it down to a single mux. The inefficient version boiled down to case fwdIn of
Nothing ->
st { _dcBuf = _dcBuf'
, _dcSize = _dcSize'
}
Just inp ->
case (_dcSize == 0 || (_dcSize == 1 && inReady)) of
True -> fromPacketStreamM2S inp
False ->
st { _dcBuf = _dcBuf'
, _dcSize = _dcSize'
} in Core, duplicating the record update for the wild match in the original Haskell. This inefficiency was observed both with Yosys+nextpnr as well as ISE (Tim didn't have a Vivado at the ready). |
In the following program,
guess1
is written as a signal function, whereasguess2
is written as a pure function. lifted (viafmap unbundle . liftA2
) into a signal function. The Verilog generated forguess1
, when fed to Vivado, produces a much smaller circuit than the Verilog generated forguess2
.The text was updated successfully, but these errors were encountered: