packages feed

clash-prelude-1.6.0: tests/Clash/Tests/AsyncFIFOSynchronizer.hs

{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-orphans #-}
{-# OPTIONS_GHC -Wno-unused-top-binds #-}

module Clash.Tests.AsyncFIFOSynchronizer (tests) where

import qualified Prelude as P

import Test.Tasty
import Test.Tasty.HUnit

import Clash.Explicit.Prelude

createDomain vSystem{vName = "Slow", vPeriod = 2 * vPeriod vSystem}

sync12RW
  :: ( KnownDomain dom1
     , KnownDomain dom2
     )
  => Int
  -> Int
  -> Int
  -> ( Signal dom1 (Bool, (Int, Bool))
     , Signal dom2 (Maybe Int, Bool)
     )
sync12RW w1 w2 w3 =
  ( bundle (inputRInc, bundle (rdata, rempty))
  , bundle (inputWDataM, wfull)
  )
 where
  (rdata, rempty, wfull) =
    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen
      enableGen inputRInc inputWDataM
  inputRInc = fromList $ P.replicate w1 False <> P.replicate 4 True <>
                P.replicate w2 False <> P.replicate 4 True <> P.repeat False
  inputWDataM = fromList $ Nothing : P.map Just [1 .. 4] <>
                  P.replicate w3 Nothing <> P.map Just [5 .. 8] <>
                  P.repeat Nothing

-- Test n.1:
--  - Write 4
--  - Empty as soon as we can stream all in a row
--  - Stay empty for a moment
--  - Write another 4
--  - Empty as soon as we can stream all in a row

sync1R1 :: Signal Slow (Bool, (Int, Bool))
sync1W1 :: Signal System (Maybe Int, Bool)
(sync1R1, sync1W1) = sync12RW 4 2 7

sync2R1 :: Signal System (Bool, (Int, Bool))
sync2W1 :: Signal Slow (Maybe Int, Bool)
(sync2R1, sync2W1) = sync12RW 9 6 1

-- Test n.2:
--  - Write 4
--  - Don't start immediately, but then empty all in a row
--  - Stay empty for a moment
--  - Write another 4
--  - Empty as soon as we can stream all in a row

sync1R2 :: Signal Slow (Bool, (Int, Bool))
sync1W2 :: Signal System (Maybe Int, Bool)
(sync1R2, sync1W2) = sync12RW 5 2 8

sync2R2 :: Signal System (Bool, (Int, Bool))
sync2W2 :: Signal Slow (Maybe Int, Bool)
(sync2R2, sync2W2) = sync12RW 10 10 1

-- Test n.3:
--  - Write 4
--  - Empty as soon as we can stream all in a row
--  - Stay empty for a moment
--  - Write another 4
--  - Don't start immediately, but then empty all in a row

sync1R3 :: Signal Slow (Bool, (Int, Bool))
sync1W3 :: Signal System (Maybe Int, Bool)
(sync1R3, sync1W3) = sync12RW 4 4 7

sync2R3 :: Signal System (Bool, (Int, Bool))
sync2W3 :: Signal Slow (Maybe Int, Bool)
(sync2R3, sync2W3) = sync12RW 9 8 1

-- Test n.4:
--  - Write 4
--  - Don't start immediately, but then empty all in a row
--  - Stay empty for a moment
--  - Write another 4
--  - Don't start immediately, but then empty all in a row

sync1R4 :: Signal Slow (Bool, (Int, Bool))
sync1W4 :: Signal System (Maybe Int, Bool)
(sync1R4, sync1W4) = sync12RW 5 3 8

sync2R4 :: Signal System (Bool, (Int, Bool))
sync2W4 :: Signal Slow (Maybe Int, Bool)
(sync2R4, sync2W4) = sync12RW 10 12 1

sync34RW
  :: ( KnownDomain dom1
     , KnownDomain dom2
     )
  => Int
  -> Int
  -> Int
  -> Int
  -> ( Signal dom1 (Bool, (Int, Bool))
     , Signal dom2 (Maybe Int, Bool)
     )
sync34RW w1 n1 w2 w3 =
  ( bundle (inputRInc, bundle (rdata, rempty))
  , bundle (inputWDataM, wfull)
  )
 where
  (rdata, rempty, wfull) =
    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen
      enableGen inputRInc inputWDataM
  inputRInc = fromList $ P.replicate w1 False <> P.replicate n1 True <>
                P.replicate w2 False <> P.replicate 16 True <> P.repeat False
  inputWDataM = fromList $ Nothing : P.map Just [1 .. n1] <>
                  P.replicate w3 Nothing <> P.map Just [n1 + 1 .. n1 + 16] <>
                  P.repeat Nothing

-- Test n.5: Fully fill the FIFO, then empty it again

sync3R5 :: Signal Slow (Bool, (Int, Bool))
sync3W5 :: Signal System (Maybe Int, Bool)
(sync3R5, sync3W5) = sync34RW 0 0 7 0

sync4R5 :: Signal System (Bool, (Int, Bool))
sync4W5 :: Signal Slow (Maybe Int, Bool)
(sync4R5, sync4W5) = sync34RW 0 0 28 0

-- Test n.6: Transfer 3 elements (so pointers are not zero), then fully fill
-- the FIFO, then empty it again

sync3R6 :: Signal Slow (Bool, (Int, Bool))
sync3W6 :: Signal System (Maybe Int, Bool)
(sync3R6, sync3W6) = sync34RW 4 3 4 4

sync4R6 :: Signal System (Bool, (Int, Bool))
sync4W6 :: Signal Slow (Maybe Int, Bool)
(sync4R6, sync4W6) = sync34RW 8 3 25 1

sync56RW
  :: ( KnownDomain dom1
     , KnownDomain dom2
     )
  => ( Signal dom1 (Bool, (Int, Bool))
     , Signal dom2 (Maybe Int, Bool)
     )
sync56RW =
  ( bundle (inputRInc, bundle (rdata, rempty))
  , bundle (inputWDataM, wfull)
  )
 where
  (rdata, rempty, wfull) =
    asyncFIFOSynchronizer d4 clockGen clockGen resetGen resetGen enableGen
      enableGen inputRInc inputWDataM
  inputRInc = not <$> rempty
  inputWDataM = fromList $ Nothing : P.map Just [1 .. 17] <> P.repeat Nothing

-- Test n.7: Read data as quickly as it comes, all through the memory and one
--           beyond the wrap of the circular buffer

sync5R7 :: Signal Slow (Bool, (Int, Bool))
sync5W7 :: Signal System (Maybe Int, Bool)
(sync5R7, sync5W7) = sync56RW

sync6R7 :: Signal System (Bool, (Int, Bool))
sync6W7 :: Signal Slow (Maybe Int, Bool)
(sync6R7, sync6W7) = sync56RW

-- For use with syncXRY syncXWY.
-- It prints (sample number, (input, output))
printTest
  :: (Foldable f, NFDataX a, ShowX a)
  => f a
  -> IO ()
printTest t = P.mapM_ (putStrLn . showX) $ P.zip [1 :: Int ..] $ sampleN 60 t

sampleR
  :: Foldable f
  => Int
  -> f (Bool, (Int, Bool))
  -> [(Bool, (Maybe Int, Bool))]
sampleR n r =
  P.map (\(inputRInc, (rdata, rempty)) -> (inputRInc, (maybeIsX rdata, rempty)))
    (sampleN n r)

-- For creating the expected constants below
printR
  :: Foldable f
  => f (Bool, (Int, Bool))
  -> IO ()
printR r = do
  let (first:rest) = P.map show $ sampleR 60 r
  putStrLn $ (P.foldl (\b a -> b <> "  , " <> a <> "\n")
                ("  [ " <> first <> "\n") rest) <> "  ]"

printW
  :: (Foldable f, NFDataX a, Show a)
  => f a
  -> IO ()
printW w = do
  let (first:rest) = P.map show $ sampleN 60 w
  putStrLn $ (P.foldl (\b a -> b <> "  , " <> a <> "\n")
                ("  [ " <> first <> "\n") rest) <> "  ]"

testR
  :: Foldable f
  => f (Bool, (Int, Bool))
  -> [(Bool, (Maybe Int, Bool))]
  -> Assertion
testR r expected = sampleR (P.length expected) r @?= expected

testW
  :: (Foldable f, NFDataX a, Eq a, Show a)
  => f a
  -> [a]
  -> Assertion
testW w expected = sampleN (P.length expected) w @?= expected


test1R1 :: Assertion
test1R1 = testR sync1R1
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Just 5,True))
  , (False,(Just 5,True))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test1W1 :: Assertion
test1W1 = testW sync1W1
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test2R1 :: Assertion
test2R1 = testR sync2R1
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test2W1 :: Assertion
test2W1 = testW sync2W1
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test1R2 :: Assertion
test1R2 = testR sync1R2
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test1W2 :: Assertion
test1W2 = testW sync1W2
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test2R2 :: Assertion
test2R2 = testR sync2R2
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Nothing,True))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test2W2 :: Assertion
test2W2 = testW sync2W2
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test1R3 :: Assertion
test1R3 = testR sync1R3
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Just 5,True))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test1W3 :: Assertion
test1W3 = testW sync1W3
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test2R3 :: Assertion
test2R3 = testR sync2R3
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test2W3 :: Assertion
test2W3 = testW sync2W3
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test1R4 :: Assertion
test1R4 = testR sync1R4
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test1W4 :: Assertion
test1W4 = testW sync1W4
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test2R4 :: Assertion
test2R4 = testR sync2R4
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (False,(Nothing,True))
  , (False,(Just 5,True))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (False,(Just 5,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (False,(Nothing,True))
  ]

test2W4 :: Assertion
test2W4 = testW sync2W4
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Nothing,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Nothing,False)
  ]

test3R5 :: Assertion
test3R5 = testR sync3R5
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (True,(Just 9,False))
  , (True,(Just 10,False))
  , (True,(Just 11,False))
  , (True,(Just 12,False))
  , (True,(Just 13,False))
  , (True,(Just 14,False))
  , (True,(Just 15,False))
  , (True,(Just 16,False))
  , (False,(Just 1,True))
  ]

test3W5 :: Assertion
test3W5 = testW sync3W5
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Nothing,True)
  , (Nothing,False)
  ]

test4R5 :: Assertion
test4R5 = testR sync4R5
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (True,(Just 9,False))
  , (True,(Just 10,False))
  , (True,(Just 11,False))
  , (True,(Just 12,False))
  , (True,(Just 13,False))
  , (True,(Just 14,False))
  , (True,(Just 15,False))
  , (True,(Just 16,False))
  , (False,(Just 1,True))
  ]

test4W5 :: Assertion
test4W5 = testW sync4W5
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Nothing,True)
  , (Nothing,False)
  ]

test3R6 :: Assertion
test3R6 = testR sync3R6
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (False,(Just 4,True))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (True,(Just 4,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (True,(Just 9,False))
  , (True,(Just 10,False))
  , (True,(Just 11,False))
  , (True,(Just 12,False))
  , (True,(Just 13,False))
  , (True,(Just 14,False))
  , (True,(Just 15,False))
  , (True,(Just 16,False))
  , (True,(Just 17,False))
  , (True,(Just 18,False))
  , (True,(Just 19,False))
  , (False,(Just 4,True))
  ]

test3W6 :: Assertion
test3W6 = testW sync3W6
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Nothing,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Just 17,False)
  , (Just 18,False)
  , (Just 19,False)
  , (Nothing,True)
  , (Nothing,True)
  , (Nothing,False)
  ]

test4R6 :: Assertion
test4R6 = testR sync4R6
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,False))
  , (False,(Just 1,False))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 4,True))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (False,(Just 4,False))
  , (True,(Just 4,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (True,(Just 9,False))
  , (True,(Just 10,False))
  , (True,(Just 11,False))
  , (True,(Just 12,False))
  , (True,(Just 13,False))
  , (True,(Just 14,False))
  , (True,(Just 15,False))
  , (True,(Just 16,False))
  , (True,(Just 17,False))
  , (True,(Just 18,False))
  , (True,(Just 19,False))
  , (False,(Just 4,True))
  ]

test4W6 :: Assertion
test4W6 = testW sync4W6
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Nothing,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Just 17,False)
  , (Just 18,False)
  , (Just 19,False)
  , (Nothing,True)
  , (Nothing,False)
  ]

test5R7 :: Assertion
test5R7 = testR sync5R7
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (False,(Just 1,True))
  , (True,(Just 1,False))
  , (True,(Just 2,False))
  , (True,(Just 3,False))
  , (True,(Just 4,False))
  , (True,(Just 5,False))
  , (True,(Just 6,False))
  , (True,(Just 7,False))
  , (True,(Just 8,False))
  , (True,(Just 9,False))
  , (True,(Just 10,False))
  , (True,(Just 11,False))
  , (True,(Just 12,False))
  , (True,(Just 13,False))
  , (True,(Just 14,False))
  , (True,(Just 15,False))
  , (True,(Just 16,False))
  , (True,(Just 17,False))
  , (False,(Just 2,True))
  ]

test5W7 :: Assertion
test5W7 = testW sync5W7
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Just 17,False)
  , (Nothing,False)
  ]

test6R7 :: Assertion
test6R7 = testR sync6R7
  [ (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Nothing,True))
  , (False,(Just 1,True))
  , (True,(Just 1,False))
  , (False,(Just 2,True))
  , (True,(Just 2,False))
  , (False,(Just 3,True))
  , (True,(Just 3,False))
  , (False,(Just 4,True))
  , (True,(Just 4,False))
  , (False,(Just 5,True))
  , (True,(Just 5,False))
  , (False,(Just 6,True))
  , (True,(Just 6,False))
  , (False,(Just 7,True))
  , (True,(Just 7,False))
  , (False,(Just 8,True))
  , (True,(Just 8,False))
  , (False,(Just 9,True))
  , (True,(Just 9,False))
  , (False,(Just 10,True))
  , (True,(Just 10,False))
  , (False,(Just 11,True))
  , (True,(Just 11,False))
  , (False,(Just 12,True))
  , (True,(Just 12,False))
  , (False,(Just 13,True))
  , (True,(Just 13,False))
  , (False,(Just 14,True))
  , (True,(Just 14,False))
  , (False,(Just 15,True))
  , (True,(Just 15,False))
  , (False,(Just 16,True))
  , (True,(Just 16,False))
  , (False,(Just 17,True))
  , (True,(Just 17,False))
  , (False,(Just 2,True))
  ]

test6W7 :: Assertion
test6W7 = testW sync6W7
  [ (Nothing,False)
  , (Just 1,False)
  , (Just 2,False)
  , (Just 3,False)
  , (Just 4,False)
  , (Just 5,False)
  , (Just 6,False)
  , (Just 7,False)
  , (Just 8,False)
  , (Just 9,False)
  , (Just 10,False)
  , (Just 11,False)
  , (Just 12,False)
  , (Just 13,False)
  , (Just 14,False)
  , (Just 15,False)
  , (Just 16,False)
  , (Just 17,False)
  , (Nothing,False)
  ]

tests :: TestTree
tests = testGroup "asyncFIFOSynchronizer"
  [ testCase "Test 1.1 Read" test1R1
  , testCase "Test 1.1 Write" test1W1
  , testCase "Test 2.1 Read" test2R1
  , testCase "Test 2.1 Write" test2W1
  , testCase "Test 1.2 Read" test1R2
  , testCase "Test 1.2 Write" test1W2
  , testCase "Test 2.2 Read" test2R2
  , testCase "Test 2.2 Write" test2W2
  , testCase "Test 1.3 Read" test1R3
  , testCase "Test 1.3 Write" test1W3
  , testCase "Test 2.3 Read" test2R3
  , testCase "Test 2.3 Write" test2W3
  , testCase "Test 1.4 Read" test1R4
  , testCase "Test 1.4 Write" test1W4
  , testCase "Test 2.4 Read" test2R4
  , testCase "Test 2.4 Write" test2W4
  , testCase "Test 3.5 Read" test3R5
  , testCase "Test 3.5 Write" test3W5
  , testCase "Test 4.5 Read" test4R5
  , testCase "Test 4.5 Write" test4W5
  , testCase "Test 3.6 Read" test3R6
  , testCase "Test 3.6 Write" test3W6
  , testCase "Test 4.6 Read" test4R6
  , testCase "Test 4.6 Write" test4W6
  , testCase "Test 5.7 Read" test5R7
  , testCase "Test 5.7 Write" test5W7
  , testCase "Test 6.7 Read" test6R7
  , testCase "Test 6.7 Write" test6W7
  ]