module Data.SBV.Examples.CRC.CCITT_Unidir where
import Data.SBV
type SWord48 = (SWord32, SWord16)
extendData :: SWord48 -> SWord64
extendData (h, l) = h # l # 0
mkFrame :: SWord48 -> SWord64
mkFrame msg@(h, l) = h # l # crc msg
crc :: SWord48 -> SWord16
crc msg = res
where msg64, divisor :: SWord64
msg64 = extendData msg
divisor = polynomial [16, 12, 5, 0]
crc64 = pMod msg64 divisor
(_, res) = split (snd (split crc64))
diffCount :: [SBool] -> [SBool] -> SWord8
diffCount xs ys = count $ zipWith (.==) xs ys
where count [] = 0
count (b:bs) = let r = count bs in ite b r (1+r)
nonUnidir :: [SBool] -> [SBool] -> SBool
nonUnidir [] _ = false
nonUnidir _ [] = false
nonUnidir (a:as) (b:bs) = (bnot a &&& b) ||| nonUnidir as bs
crcUniGood :: SWord8 -> SWord48 -> SWord48 -> SBool
crcUniGood hd sent received =
sent ./= received ==> nonUnidir frameSent frameReceived ||| diffCount frameSent frameReceived .> hd
where frameSent = blastLE $ mkFrame sent
frameReceived = blastLE $ mkFrame received
ccitHDis3 :: IO ()
ccitHDis3 = print =<< prove (crcUniGood 3)
ccitHDis4 :: IO ()
ccitHDis4 = print =<< prove (crcUniGood 4)