-- |BitRepr.hs -- Bit representation. {-# LANGUAGE RankNTypes, GADTs, TypeFamilies, TypeOperators, TemplateHaskell #-} {-# LANGUAGE FlexibleInstances, FlexibleContexts, UndecidableInstances #-} {-# LANGUAGE MultiParamTypeClasses, OverlappingInstances #-} module Hardware.HHDL.BitRepr where import Data.Bits import Hardware.HHDL.TyLeA ------------------------------------------------------------------------------- -- Main class. class Nat (BitVectorSize a) => BitRepr a where type BitVectorSize a -- |Convert value to an integer. toBitVector :: a -> Integer -- |Convert integer to value. Conversion should ignore any bits above -- "bitVectorSize result". fromBitVector :: Integer -> a -- |Size of value in bits. bitVectorSize :: a -> Int bitVectorSize a = i where getSize :: a -> BitVectorSize a getSize a = undefined i = fromNat (getSize a) -- |Mask for value's significant bits. -- In usual bit vectors they are all significant (default variant below). -- In algebraic types they aren't: data T = B Bool | W Word64. -- The mask for B x could ignore significant bits from Word64 in W. -- Right now it is not widely used, so it is safe to leave it as it is. bitMask :: a -> Integer bitMask a = shiftL 1 (bitVectorSize a) - 1 ------------------------------------------------------------------------------- -- Support definitions and type functions for algebraic types. -- instances are generated by calling generateMakeMatches from TH.hs. -- |How much bits do we need to pass arguments for any constructor? type family ArgsBusSize a -- |How much bits do we need for constructor selector? type family SelectorBusSize a -- Utility conversion function. -- USed for toBitVector/fromBitVector implementations. _toArgsBusSize :: a -> ArgsBusSize a _toArgsBusSize = undefined _toArgsBusSizeInt :: Nat (ArgsBusSize a) => a -> Int _toArgsBusSizeInt = fromNat . _toArgsBusSize _toSelBusSize :: a -> SelectorBusSize a _toSelBusSize = undefined _toSelBusSizeInt :: Nat (SelectorBusSize a) => a -> Int _toSelBusSizeInt = fromNat . _toSelBusSize _combineConstructorIndexArgs :: Integer -> Int -> Integer -> Integer _combineConstructorIndexArgs argsVector shift ci = shiftL ci shift .|. argsVector -- |Helper class that breaks some type checking dependencies and -- allow for faster compilation. class (Nat (ArgsBusSize a), Nat (SelectorBusSize a)) => AlgTypeBitEnc a where algTypeArgsBusSize :: a -> Int algTypeArgsBusSize a = fromNat (_toArgsBusSize a) algTypeArgsBusMask :: a -> Integer algTypeArgsBusMask a = shiftL 1 (algTypeArgsBusSize a) - 1 algTypeSelectorBusSize :: a -> Int algTypeSelectorBusSize = _toSelBusSizeInt algTypeSelectorBusMask :: a -> Integer algTypeSelectorBusMask a = shiftL 1 (_toSelBusSizeInt a) - 1