clash-lang / clash-prelude

CLaSH prelude library containing datatypes and functions for circuit design
http://www.clash-lang.org/
Other
31 stars 27 forks source link

Reading block RAM from undefined address breaks simulation? #69

Closed tomjaguarpaw closed 8 years ago

tomjaguarpaw commented 8 years ago

It seems that if I ever try to read from an undefined address then the block RAM simulation breaks.

> let br addr = blockRam (0 :> Nil) (pure 0) addr (pure False) (pure 0)
> Prelude.take 10 $ Prelude.drop 5 $ simulate (br . register (error "foo")) [0,0..]
[*** Exception: foo
tomjaguarpaw commented 8 years ago

Once the ST computation encounters an exception the whole computation is dead forever more.

tomjaguarpaw commented 8 years ago

Perhaps we could wrap it with this little beauty, which I believe you've mentioned before, @christiaanb

import Control.Exception
import System.IO.Unsafe

catchError :: a -> Maybe a
catchError x = unsafePerformIO $ catch (evaluate x >> return (Just x)) handle
  where handle :: ErrorCall -> IO (Maybe b)
        handle _ = return Nothing
christiaanb commented 8 years ago

You're right, reading at an undefined address should just return an undefined value once; not break the entire simulation.

On a related note, I wouldn't know what to do when you write to an undefined though. On the actual FPGA you would probably either write to some random address, or address zero. But I wouldn't know what the preferred simulation behaviour should be:

  1. Stop the entire computation (the current behaviour)
  2. Make all values of the blockram undefined
  3. Write to a random address
  4. Write to address zero

Thoughts?

tomjaguarpaw commented 8 years ago

The undefined writes question is a good one. I think stopping the entire computation is reasonable since it will probably invoke undefined, or at the very least very puzzling, behaviour on hardware.

tomjaguarpaw commented 8 years ago

I tried wrapping the read address in catchError as above and it seems to work fine.