Skip to content
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

Add boundary proofs to dfold and smap #2686

Merged
merged 1 commit into from
Feb 14, 2025
Merged

Add boundary proofs to dfold and smap #2686

merged 1 commit into from
Feb 14, 2025

Conversation

kleinreact
Copy link
Member

@kleinreact kleinreact commented Mar 1, 2024

The PR extends dfold with a boundary proof for the folded function and introduces smapWithBounds offering a boundary proof as well. smapWithBounds is introduced in addition to smap, as the served proof may lead to untouchable errors requiring additional type annotations. While this is fine for dfold, which requires advanced knowledge of the type system for usage anyway, smap should stay intuitive for beginners, which is why we introduce an additional version instead.

The PR also renames typenat variables l (small letter L) to n to make them better distinguishable from the constant 1.

@martijnbastiaan
Copy link
Member

I'm curious; what motivated you to implement this? Any concrete example where you need the boundary proof?

@kleinreact
Copy link
Member Author

kleinreact commented Mar 5, 2024

I would use it here, but the currently used workaround is also sufficient. It is required to use the Resize class in that case.

@rowanG077
Copy link
Member

rowanG077 commented Mar 14, 2024

I have ran into this a few times. And just now I ran into it again. I was trying to do some type magics to allow dynamic(As in type level configurable) multi lane CRC to work. I tried to do something like this:

data CRCLaneParams (crcWidth :: Nat) (dataWidth :: Nat) (lanes :: Nat) where
  CRCLane0
    :: CircuitCRCParams crcWidth dataWidth
    -> CRCLaneParams crcWidth dataWidth 0
  CRCLaneN
    :: 1 <= lanes
    => SNat lanes
    -> CircuitCRCParams crcWidth ((lanes + 1) * dataWidth)
    -> CRCLaneParams crcWidth dataWidth (lanes - 1)
    -> CRCLaneParams crcWidth dataWidth lanes

-- | Get the Circuit params for a given lane
getCircuitParams
  :: lane <= lanes
  => CRCLaneParams crcWidth dataWidth lanes
  -> SNat lane
  -> CircuitCRCParams crcWidth ((lane + 1) * dataWidth)
getCircuitParams = ...

-- | Create a CRC step function that takes a larger input of which a subset is ignored to make types match.
mkStep
  :: forall (crcWidth :: Nat)
            (dataWidth :: Nat)
            (dataWidthFull :: Nat)
   . SNat dataWidthFull
  -> CircuitCRCParams crcWidth dataWidth
  -> BitVector crcWidth
  -- ^ The current CRC state
  -> BitVector dataWidthFull
  -- ^ The input
  -> BitVector crcWidth
  -- ^ The next CRC state
mkStep = ...

-- | A multi-lane CRC engine
crcEngine
  :: forall (nLanes :: Nat)
            (dom :: Domain)
            (crcWidth :: Nat)
            (dataWidth :: Nat)
   . HiddenClockResetEnable dom
  => KnownNat nLanes
  => KnownNat crcWidth
  => KnownNat dataWidth
  => 1 <= nLanes
  => CRCLaneParams crcWidth dataWidth (nLanes - 1)
  -> Signal dom (Maybe (Vec nLanes (BitVector dataWidth)))
  -> Signal dom (Index nLanes)
  -> ( Signal dom (BitVector crcWidth)
     , Signal dom Bool
     )
crcEngine laneParams dataIn validLane = ...
  where
    -- Cannot satisfy: v <= nLanes - 1
    engines = smap (\v _ -> mkStep SNat $ getCircuitParams laneParams v) (repeat @nLanes ())
    engine :: Signal dom (BitVector crcWidth -> BitVector (dataWidth * nLanes) -> BitVector crcWidth)
    engine = fmap (\n -> engines !! n) validLane

Note that I'm not sure whether this is the way to go here it was just experimentation. But it came up naturally at least.

@kleinreact kleinreact marked this pull request as draft March 14, 2024 13:24
@kleinreact kleinreact force-pushed the smap-with-bounds branch 3 times, most recently from 41f0b7e to 15579b4 Compare March 19, 2024 13:05
@kleinreact kleinreact marked this pull request as ready for review March 19, 2024 14:58
@kleinreact kleinreact requested a review from christiaanb March 19, 2024 14:58
@martijnbastiaan
Copy link
Member

Could you write a changelog entry? See changelog/README.md for instructions.

Copy link
Member

@martijnbastiaan martijnbastiaan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did we change dfold, but introduced an additional function for smap?

Because the evaluator rules aren't easy to review: could you add a test for the evaluator (and primitive reduction?) of these functions? It's a bit cumbersome to write these functions as you'd:

  • Need to make sure GHC doesn't do any constant folding for you
  • Clash does do the constant folding (perhaps with -fclash-ultra)

You can do something similar to T2542.hs in terms of checking whether some constant ended up in the HDL.

I'm also not sure what the difference is between "primitive reduction" and "evaluating", maybe @christiaanb can comment on that / how to write a test for both.

@kleinreact
Copy link
Member Author

kleinreact commented Jun 30, 2024

Why did we change dfold, but introduced an additional function for smap?

The primary argument was that smap may be used by beginners, which may be overwhelmed by the extended type signature required for the proof. On the other hand, dfold is not beginner friendly in terms of the type signature anyway, which is why it shouldn't hurt to introduce the changes directly there.

@martijnbastiaan
Copy link
Member

Makes sense!

Co-authored-by: Christiaan Baaij <[email protected]>
@martijnbastiaan
Copy link
Member

@christiaanb Are you happy with the applied changes?

@kleinreact kleinreact merged commit a1e4e6c into master Feb 14, 2025
13 checks passed
@kleinreact kleinreact deleted the smap-with-bounds branch February 14, 2025 05:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants