Closed leonschoorl closed 1 year ago
I've had a look at the core that clash gets from GHC.
When mapping with vioProbe
, GHC seems to do some case transformation where it puts the vioProbe inside of the projection case of the result of the clockWizard:
map
(case (clockWizard ... clkIn[LocalId] rst[LocalId]) of
(,) clk ds ->
vioProbe ... clk[LocalId])
inp[LocalId]
But when mapping with register
for some reason doesn't do that and just maps with let expression for clk
with just the straight projection, making it easier for clash to pull it out of the map:
map
(let
clk
= case clockWizard ... clkIn[LocalId] rst[LocalId] of
(,) clk1 ds ->
clk1[LocalId]
in let
initial
= fromInteger## 0## 0
in λi ->
register# ... clk[LocalId] ...)
inp[LocalId]
duplicates the
clockWizard
inside of the map loop:This is might not specify to
clockWizard
, but I noticed it there because Vivado failed to synthesize this, because it couldn't route one clock port to multiple MMCMs. But even if Vivado were to allow it, MMCMs are a limited resource. And in general clash shouldn't be duplicating things that do work.If we change the
vioProbe
for something simpler like aregister
then clash is able to pull theclockWizard
out of the map loop.I've tried adding
Clash.Magic.deDup
both aroundclockWizard
and at the usage site ofclk
, but that doesn't have an effect.