lion-0.4.0.0: src/Lion/Alu.hs
{-|
Module : Lion.Alu
Description : Lion arithmetic logic unit
Copyright : (c) David Cox, 2021-2024
License : BSD-3-Clause
Maintainer : standardsemiconductor@gmail.com
Configurable alu, choose between soft and hard adders/subtractors
-}
module Lion.Alu where
import Clash.Prelude
import Data.Function ( on )
import Ice40.Mac (
Input(..),
Parameter(..),
defaultInput,
defaultParameter,
mac
)
import Lion.Instruction (Op(..))
-- | ALU configuration
data AluConfig = Hard -- ^ use hard adder and subtractor from iCE40 SB_MAC16
| Soft -- ^ use generic adder and subtractor: (+) and (-)
deriving stock (Generic, Show, Eq)
alu
:: HiddenClockResetEnable dom
=> AluConfig
-> Signal dom Op
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
alu = \case
Hard -> hardAlu
Soft -> softAlu
softAlu
:: HiddenClockResetEnable dom
=> Signal dom Op
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
softAlu op in1 = register 0 . liftA3 aluFunc op in1
where
aluFunc = \case
Add -> (+)
Sub -> (-)
Sll -> \x y -> x `shiftL` shamt y
Slt -> boolToBV ... (<) `on` sign
Sltu -> boolToBV ... (<)
Xor -> xor
Srl -> \x y -> x `shiftR` shamt y
Sra -> \x y -> pack $ sign x `shiftR` shamt y
Or -> (.|.)
And -> (.&.)
where
shamt = unpack . resize . slice d4 d0
sign = unpack :: BitVector 32 -> Signed 32
(...) = (.).(.)
hardAlu
:: HiddenClockResetEnable dom
=> Signal dom Op
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
hardAlu op in1 in2 = mux isAddSub adderSubtractor $ register 0 $ baseAlu op in1 in2
where
isAdd = (Add == ) <$> op
isSub = (Sub == ) <$> op
isAddSub = delay False $ isAdd .||. isSub
adderSubtractor = hardAddSub (boolToBit <$> isSub) in1 in2
baseAlu
:: Signal dom Op
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
baseAlu = liftA3 $ \case
Add -> \_ _ -> 0
Sub -> \_ _ -> 0
Sll -> \x y -> x `shiftL` shamt y
Slt -> boolToBV ... (<) `on` sign
Sltu -> boolToBV ... (<)
Xor -> xor
Srl -> \x y -> x `shiftR` shamt y
Sra -> \x y -> pack $ sign x `shiftR` shamt y
Or -> (.|.)
And -> (.&.)
where
shamt = unpack . resize . slice d4 d0
sign = unpack :: BitVector 32 -> Signed 32
(...) = (.).(.)
-- | addSub32PipelinedUnsigned
hardAddSub
:: HiddenClock dom
=> Signal dom Bit -- ^ 0 = Add, 1 = Sub
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
-> Signal dom (BitVector 32)
hardAddSub addSub x y = out
where
(out, _, _, _) = mac parameter input
input = defaultInput{ a = slice d31 d16 <$> y
, b = slice d15 d0 <$> y
, c = slice d31 d16 <$> x
, d = slice d15 d0 <$> x
, addsubtop = addSub
, addsubbot = addSub
}
parameter = defaultParameter{ topOutputSelect = 1
, topAddSubUpperInput = 1
, topAddSubCarrySelect = 2
, botOutputSelect = 1
, botAddSubUpperInput = 1
, mode8x8 = 1
}