lion-0.2.0.0: src/Lion/Instruction.hs
{-|
Module : Lion.Instruction
Description : RISC-V ISA
Copyright : (c) David Cox, 2021
License : BSD-3-Clause
Maintainer : standardsemiconductor@gmail.com
-}
module Lion.Instruction where
import Clash.Prelude
import Data.Function ( on )
data Exception = IllegalInstruction
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Writeback pipeline instruction
data WbInstr = WbRegWr (Unsigned 5) (BitVector 32)
| WbLoad Load (Unsigned 5) (BitVector 4)
| WbStore
| WbNop
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Memory pipeline instruction
data MeInstr = MeRegWr (Unsigned 5)
| MeJump (Unsigned 5) (BitVector 32)
| MeBranch
| MeStore (BitVector 32) (BitVector 4) (BitVector 32)
| MeLoad Load (Unsigned 5) (BitVector 32) (BitVector 4)
| MeNop
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Execute pipeline instruction
data ExInstr = Ex ExOp (Unsigned 5) (BitVector 32)
| ExJump Jump (Unsigned 5) (BitVector 32)
| ExBranch Branch (BitVector 32)
| ExStore Store (BitVector 32)
| ExLoad Load (Unsigned 5) (BitVector 32)
| ExAlu Op (Unsigned 5)
| ExAluImm Op (Unsigned 5) (BitVector 32)
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | ALU operation
data Op = Add
| Sub
| Sll
| Slt
| Sltu
| Xor
| Srl
| Sra
| Or
| And
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Branch operation
data Branch = Beq
| Bne
| Blt
| Bge
| Bltu
| Bgeu
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | branch calculation
branch :: Branch -> BitVector 32 -> BitVector 32 -> Bool
branch = \case
Beq -> not ... (/=)
Bne -> (/=)
Bge -> not ... (<) `on` sign
Bgeu -> not ... (<)
Blt -> (<) `on` sign
Bltu -> (<)
where
(...) = (.).(.)
sign :: BitVector 32 -> Signed 32
sign = unpack
data ExOp = Lui
| Auipc
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
data Jump = Jal | Jalr
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Store operation
data Store = Sb
| Sh
| Sw
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
-- | Load operation
data Load = Lb
| Lh
| Lw
| Lbu
| Lhu
deriving stock (Generic, Show, Eq)
deriving anyclass NFDataX
parseInstr :: BitVector 32 -> Either Exception ExInstr
parseInstr i = case i of
$(bitPattern ".........................0110111") -> Right $ Ex Lui rd immU -- lui
$(bitPattern ".........................0010111") -> Right $ Ex Auipc rd immU -- auipc
$(bitPattern ".........................1101111") -> Right $ ExJump Jal rd immJ -- jal
$(bitPattern ".................000.....1100111") -> Right $ ExJump Jalr rd immI -- jalr
$(bitPattern ".................000.....1100011") -> Right $ ExBranch Beq immB -- beq
$(bitPattern ".................001.....1100011") -> Right $ ExBranch Bne immB -- bne
$(bitPattern ".................100.....1100011") -> Right $ ExBranch Blt immB -- blt
$(bitPattern ".................101.....1100011") -> Right $ ExBranch Bge immB -- bge
$(bitPattern ".................110.....1100011") -> Right $ ExBranch Bltu immB -- bltu
$(bitPattern ".................111.....1100011") -> Right $ ExBranch Bgeu immB -- bgeu
$(bitPattern ".................000.....0000011") -> Right $ ExLoad Lb rd immI -- lb
$(bitPattern ".................001.....0000011") -> Right $ ExLoad Lh rd immI -- lh
$(bitPattern ".................010.....0000011") -> Right $ ExLoad Lw rd immI -- lw
$(bitPattern ".................100.....0000011") -> Right $ ExLoad Lbu rd immI -- lbu
$(bitPattern ".................101.....0000011") -> Right $ ExLoad Lhu rd immI -- lhu
$(bitPattern ".................000.....0100011") -> Right $ ExStore Sb immS -- sb
$(bitPattern ".................001.....0100011") -> Right $ ExStore Sh immS -- sh
$(bitPattern ".................010.....0100011") -> Right $ ExStore Sw immS -- sw
$(bitPattern ".................000.....0010011") -> Right $ ExAluImm Add rd immI -- addi
$(bitPattern ".................010.....0010011") -> Right $ ExAluImm Slt rd immI -- slti
$(bitPattern ".................011.....0010011") -> Right $ ExAluImm Sltu rd immI -- sltiu
$(bitPattern ".................100.....0010011") -> Right $ ExAluImm Xor rd immI -- xori
$(bitPattern ".................110.....0010011") -> Right $ ExAluImm Or rd immI -- ori
$(bitPattern ".................111.....0010011") -> Right $ ExAluImm And rd immI -- andi
$(bitPattern "0000000..........001.....0010011") -> Right $ ExAluImm Sll rd immI -- slli
$(bitPattern "0000000..........101.....0010011") -> Right $ ExAluImm Srl rd immI -- srli
$(bitPattern "0100000..........101.....0010011") -> Right $ ExAluImm Sra rd immI -- srai
$(bitPattern "0000000..........000.....0110011") -> Right $ ExAlu Add rd -- add
$(bitPattern "0100000..........000.....0110011") -> Right $ ExAlu Sub rd -- sub
$(bitPattern "0000000..........001.....0110011") -> Right $ ExAlu Sll rd -- sll
$(bitPattern "0000000..........010.....0110011") -> Right $ ExAlu Slt rd -- slt
$(bitPattern "0000000..........011.....0110011") -> Right $ ExAlu Sltu rd -- sltu
$(bitPattern "0000000..........100.....0110011") -> Right $ ExAlu Xor rd -- xor
$(bitPattern "0000000..........101.....0110011") -> Right $ ExAlu Srl rd -- srl
$(bitPattern "0100000..........101.....0110011") -> Right $ ExAlu Sra rd -- sra
$(bitPattern "0000000..........110.....0110011") -> Right $ ExAlu Or rd -- or
$(bitPattern "0000000..........111.....0110011") -> Right $ ExAlu And rd -- and
_ -> Left IllegalInstruction
where
-- npcB = immB + pc
-- npcJ = immJ + pc
rd = sliceRd i
immI :: BitVector 32
immI = signExtend $ slice d31 d20 i
immS :: BitVector 32
immS = signExtend $ slice d31 d25 i ++# slice d11 d7 i
immB :: BitVector 32
immB = signExtend (slice d31 d31 i ++# slice d7 d7 i ++# slice d30 d25 i ++# slice d11 d8 i) `shiftL` 1
immU :: BitVector 32
immU = slice d31 d12 i ++# 0
immJ :: BitVector 32
immJ = signExtend (slice d31 d31 i ++# slice d19 d12 i ++# slice d20 d20 i ++# slice d30 d25 i ++# slice d24 d21 i) `shiftL` 1
sliceRd :: BitVector 32 -> Unsigned 5
sliceRd = unpack . slice d11 d7
sliceRs1 :: BitVector 32 -> Unsigned 5
sliceRs1 = unpack . slice d19 d15
sliceRs2 :: BitVector 32 -> Unsigned 5
sliceRs2 = unpack . slice d24 d20
sliceOpcode :: BitVector 32 -> BitVector 7
sliceOpcode = slice d6 d0
sliceFunct3 :: BitVector 32 -> BitVector 3
sliceFunct3 = slice d14 d12
sliceFunct7 :: BitVector 32 -> BitVector 7
sliceFunct7 = slice d31 d25