module Lava.Arithmetic where

import Lava
import Lava.Patterns

----------------------------------------------------------------
-- Basic Components

halfAdd :: (Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool)
halfAdd (a :: Signal Bool
a, b :: Signal Bool
b) = (Signal Bool
sum, Signal Bool
carry)
  where
    sum :: Signal Bool
sum   = (Signal Bool, Signal Bool) -> Signal Bool
xor2 (Signal Bool
a, Signal Bool
b)
    carry :: Signal Bool
carry = (Signal Bool, Signal Bool) -> Signal Bool
and2 (Signal Bool
a, Signal Bool
b)

fullAdd :: (Signal Bool, (Signal Bool, Signal Bool))
-> (Signal Bool, Signal Bool)
fullAdd (carryIn :: Signal Bool
carryIn, (a :: Signal Bool
a, b :: Signal Bool
b)) = (Signal Bool
sum, Signal Bool
carryOut)
  where
    (sum1 :: Signal Bool
sum1, carry1 :: Signal Bool
carry1) = (Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool)
halfAdd (Signal Bool
a, Signal Bool
b)
    (sum :: Signal Bool
sum, carry2 :: Signal Bool
carry2)  = (Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool)
halfAdd (Signal Bool
carryIn, Signal Bool
sum1)
    carryOut :: Signal Bool
carryOut       = (Signal Bool, Signal Bool) -> Signal Bool
xor2 (Signal Bool
carry1, Signal Bool
carry2)

bitAdder :: (Signal Bool, [Signal Bool]) -> ([Signal Bool], Signal Bool)
bitAdder = ((Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool))
-> (Signal Bool, [Signal Bool]) -> ([Signal Bool], Signal Bool)
forall b a1 a2. ((b, a1) -> (a2, b)) -> (b, [a1]) -> ([a2], b)
row (Signal Bool, Signal Bool) -> (Signal Bool, Signal Bool)
halfAdd

adder :: (Signal Bool, ([Signal Bool], [Signal Bool]))
-> ([Signal Bool], Signal Bool)
adder (carryIn :: Signal Bool
carryIn, ([],   []))   = ([], Signal Bool
carryIn)
adder (carryIn :: Signal Bool
carryIn, (as :: [Signal Bool]
as,   []))   = (Signal Bool, [Signal Bool]) -> ([Signal Bool], Signal Bool)
bitAdder (Signal Bool
carryIn, [Signal Bool]
as)
adder (carryIn :: Signal Bool
carryIn, ([],   bs :: [Signal Bool]
bs))   = (Signal Bool, [Signal Bool]) -> ([Signal Bool], Signal Bool)
bitAdder (Signal Bool
carryIn, [Signal Bool]
bs)
adder (carryIn :: Signal Bool
carryIn, (a :: Signal Bool
a:as :: [Signal Bool]
as, b :: Signal Bool
b:bs :: [Signal Bool]
bs)) = (Signal Bool
sSignal Bool -> [Signal Bool] -> [Signal Bool]
forall a. a -> [a] -> [a]
:[Signal Bool]
ss, Signal Bool
carryOut)
  where
    (s :: Signal Bool
s, carry :: Signal Bool
carry)     = (Signal Bool, (Signal Bool, Signal Bool))
-> (Signal Bool, Signal Bool)
fullAdd (Signal Bool
carryIn, (Signal Bool
a, Signal Bool
b))
    (ss :: [Signal Bool]
ss, carryOut :: Signal Bool
carryOut) = (Signal Bool, ([Signal Bool], [Signal Bool]))
-> ([Signal Bool], Signal Bool)
adder (Signal Bool
carry, ([Signal Bool]
as, [Signal Bool]
bs))

binAdder :: ([Signal Bool], [Signal Bool]) -> [Signal Bool]
binAdder (as :: [Signal Bool]
as, bs :: [Signal Bool]
bs) = [Signal Bool]
sum [Signal Bool] -> [Signal Bool] -> [Signal Bool]
forall a. [a] -> [a] -> [a]
++ [Signal Bool
carryOut]
  where
    (sum :: [Signal Bool]
sum, carryOut :: Signal Bool
carryOut) = (Signal Bool, ([Signal Bool], [Signal Bool]))
-> ([Signal Bool], Signal Bool)
adder (Signal Bool
low, ([Signal Bool]
as, [Signal Bool]
bs))

bitMulti :: (Signal Bool, [Signal Bool]) -> [Signal Bool]
bitMulti (a :: Signal Bool
a, bs :: [Signal Bool]
bs) = [ (Signal Bool, Signal Bool) -> Signal Bool
and2 (Signal Bool
a, Signal Bool
b) | Signal Bool
b <- [Signal Bool]
bs ]

multi :: ([Signal Bool], [Signal Bool]) -> [Signal Bool]
multi ([],   []) = []
multi (as :: [Signal Bool]
as,   []) = Int -> Signal Bool -> [Signal Bool]
forall a. Int -> a -> [a]
replicate ([Signal Bool] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Signal Bool]
as) Signal Bool
low
multi ([],   bs :: [Signal Bool]
bs) = Int -> Signal Bool -> [Signal Bool]
forall a. Int -> a -> [a]
replicate ([Signal Bool] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Signal Bool]
bs) Signal Bool
low
multi (a :: Signal Bool
a:as :: [Signal Bool]
as, bs :: [Signal Bool]
bs) = Signal Bool
m Signal Bool -> [Signal Bool] -> [Signal Bool]
forall a. a -> [a] -> [a]
: [Signal Bool]
ms
  where
    (m :: Signal Bool
m:abs :: [Signal Bool]
abs) = (Signal Bool, [Signal Bool]) -> [Signal Bool]
bitMulti (Signal Bool
a, [Signal Bool]
bs)
    asbs :: [Signal Bool]
asbs    = ([Signal Bool], [Signal Bool]) -> [Signal Bool]
multi ([Signal Bool]
as, [Signal Bool]
bs)
    (ms :: [Signal Bool]
ms,_)  = (Signal Bool, ([Signal Bool], [Signal Bool]))
-> ([Signal Bool], Signal Bool)
adder (Signal Bool
low, ([Signal Bool]
abs, [Signal Bool]
asbs))

numBreak :: Signal Int -> (Signal Bool, Signal Int)
numBreak num :: Signal Int
num = (Signal Bool
bit, Signal Int
num')
  where
    digit :: Signal Int
digit = (Signal Int, Signal Int) -> Signal Int
imod (Signal Int
num, 2)
    bit :: Signal Bool
bit   = Signal Int -> Signal Bool
int2bit Signal Int
digit
    num' :: Signal Int
num'  = (Signal Int, Signal Int) -> Signal Int
idiv (Signal Int
num, 2)

int2bin :: a -> Signal Int -> [Signal Bool]
int2bin 0 num :: Signal Int
num = []
int2bin n :: a
n num :: Signal Int
num = (Signal Bool
bitSignal Bool -> [Signal Bool] -> [Signal Bool]
forall a. a -> [a] -> [a]
:[Signal Bool]
bits)
  where
    (bit :: Signal Bool
bit,num' :: Signal Int
num') = Signal Int -> (Signal Bool, Signal Int)
numBreak Signal Int
num
    bits :: [Signal Bool]
bits       = a -> Signal Int -> [Signal Bool]
int2bin (a
na -> a -> a
forall a. Num a => a -> a -> a
-1) Signal Int
num'

bin2int :: [Signal Bool] -> Signal Int
bin2int []     = 0
bin2int (b :: Signal Bool
b:bs :: [Signal Bool]
bs) = Signal Int
num
  where
    num' :: Signal Int
num' = [Signal Bool] -> Signal Int
bin2int [Signal Bool]
bs
    num :: Signal Int
num  = Signal Bool -> Signal Int
bit2int Signal Bool
b Signal Int -> Signal Int -> Signal Int
forall a. Num a => a -> a -> a
+ 2 Signal Int -> Signal Int -> Signal Int
forall a. Num a => a -> a -> a
* Signal Int
num'

----------------------------------------------------------------
-- the end.