package UBit ( UBit, mkUBitReg, uBitSelect, uBitUpdate -- in place of PrimSelectable ) where import ListReg import Vector import List -- The UBit type data UBit = UBit (List (Bit 1)) | UBitUnknownSize Integer -- | UBitMinBound -- | UBitMaxBound integerToUBit :: Integer -> Integer -> UBit integerToUBit sz i = UBit (errIntegerToBitList "integerToUBit" sz i) mkUBitReg :: (IsModule m c) => Integer -> UBit -> m (Reg UBit) mkUBitReg sz init_val = module let init_list = uBitToBitList "mkUBitreg" sz init_val reg :: Reg (List (Bit 1)) reg <- mkListReg init_list interface _read = bitListToUBit reg._read _write val = let bitlist = uBitToBitList "mkUBitReg: _write" sz val in reg._write bitlist getLists :: String -> UBit -> UBit -> Either (List (Bit 1), List (Bit 1)) (Integer, Integer) getLists name (UBit xs) (UBit ys) = Left (xs, ys) getLists name (UBit xs) (UBitUnknownSize i) = let ys = errIntegerToBitList name (length xs) i in Left (xs, ys) getLists name (UBitUnknownSize i) (UBit ys) = let xs = errIntegerToBitList name (length ys) i in Left (xs, ys) getLists name (UBitUnknownSize xi) (UBitUnknownSize yi) = Right (xi, yi) -- Instances: instance Literal UBit where fromInteger x = UBitUnknownSize x {- instance Bounded UBit where minBound = UBitMinBound maxBound = UBitMaxBound -} -- XXX What if the lists are of different size? instance Eq UBit where (==) x y = case (getLists "==" x y) of Left (xs,ys) -> xs == ys Right (xi,yi) -> xi == yi (/=) x y = case (getLists "/=" x y) of Left (xs,ys) -> xs /= ys Right (xi,yi) -> xi /= yi -- We have the option here of extending when necessary... sumBitList :: String -> (Bit 2 -> Bit 2 -> Bit 2) -> List (Bit 1) -> List (Bit 1) -> List (Bit 1) sumBitList name op xs ys = let addBit :: Bit 1 -> Bit 1 -> Bit 1 -> (Bit 1, Bit 1) addBit x y c = let twobitsum :: Bit 2 twobitsum = ((zeroExtend x) `op` (zeroExtend y)) `op` (zeroExtend c) in split twobitsum f (x,y) (rs,carrybit) = let (c,b) = addBit x y carrybit in (Cons b rs, c) in if ((length xs) /= (length ys)) then error ("UBit operation " +++ name +++ " failed because the bit sizes are not equal: " +++ integerToString (length xs) +++ " /= " +++ integerToString (length ys)) else (List.foldr f (Nil,0) (List.zip xs ys)).fst instance Arith UBit where (+) x y = case (getLists "+" x y) of Left (xs,ys) -> UBit (sumBitList "+" (+) xs ys) Right (xi,yi) -> UBitUnknownSize (xi + yi) (-) x y = case (getLists "+" x y) of Left (xs,ys) -> UBit (sumBitList "-" (-) xs ys) Right (xi,yi) -> UBitUnknownSize (xi - yi) negate x = error "UBit: negate not yet implemented" (*) x y = error "UBit: * not yet implemented" uBitSelect :: List a -> UBit -> a uBitSelect l (UBitUnknownSize i) = primSelectFn (getStringPosition "") l i uBitSelect l (UBit k) = let f p res = if (k == p.snd) then p.fst else res zeroBits = List.map (const 0) k in List.foldr f _ (numListBits l zeroBits) uBitUpdate :: List a -> UBit -> a -> List a uBitUpdate l (UBitUnknownSize i) x = primUpdateFn (getStringPosition "") l i x uBitUpdate l (UBit k) x = let f p = if (k == p.snd) then x else p.fst zeroBits = List.map (const 0) k in List.map f (numListBits l zeroBits) numListBits :: List a -> List (Bit 1) -> List (a, List (Bit 1)) numListBits Nil bs = Nil numListBits (Cons x xs) bs = Cons (x, bs) (numListBits xs (incrListBits bs)) incrListBits :: List (Bit 1) -> List (Bit 1) incrListBits bs = let addBit :: Bit 1 -> Bit 1 -> (Bit 1, Bit 1) addBit b c = let twobitsum :: Bit 2 twobitsum = (zeroExtend b) + (zeroExtend c) in split twobitsum f x (rs,carrybit) = let (c,b) = addBit x carrybit in (Cons b rs, c) in (List.foldr f (Nil,1) bs).fst {- -- This is not possible becase of fundeps on PrimSelectable: -- List already has an instance, so we can't define another instance PrimSelectable (List a) UBit a where primSelectFn = uBitSelect primUpdateFn = uBitUpdate -} -- Assumes that the size and the value are non-negative integerToBitList :: Integer -> Integer -> Maybe (List (Bit 1)) integerToBitList sz val = let f :: Integer -> Integer -> List (Bit 1) -> Maybe (List (Bit 1)) f sz val accum = if (sz == 0) then if (val > 0) then Invalid else Valid accum else let b = val `mod` 2 r = val `div` 2 in f (sz - 1) r (Cons (fromInteger b) accum) in f sz val Nil errIntegerToBitList :: String -> Integer -> Integer -> List (Bit 1) errIntegerToBitList fname sz val = let prefx = if (fname == "") then fname else fname +++ ": " in if (sz < 0) then error (prefx +++ "UBit must have non-negative size: given size " +++ integerToString sz) else if (val < 0) then error (prefx +++ "UBit must have non-negative value: given value " +++ integerToString val) else case (integerToBitList sz val) of Invalid -> error (prefx +++ "initial value " +++ integerToString val +++ " too large for vector of " +++ integerToString sz +++ " bits") Valid res -> res uBitToInteger :: UBit -> Integer uBitToInteger (UBitUnknownSize i) = i uBitToInteger (UBit xs) = let f :: (Bit 1) -> (Integer, Integer) -> (Integer, Integer) f bit (tot,fac) = let bi = if (bit == 1) then 1 else 0 in (tot + (bi * fac), fac * 2) in (List.foldr f (0,1) xs).fst bitListToUBit :: List (Bit 1) -> UBit bitListToUBit bs = UBit bs uBitToBitList :: String -> Integer -> UBit -> List (Bit 1) uBitToBitList _ _ (UBit bs) = bs uBitToBitList name sz (UBitUnknownSize i) = errIntegerToBitList name sz i