packages feed

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