Skip to content

Commit

Permalink
Merge pull request #6 from mrLSD/rv64i
Browse files Browse the repository at this point in the history
RV64i
  • Loading branch information
mrLSD authored Nov 9, 2019
2 parents bc15bde + 17c1627 commit ba15cab
Show file tree
Hide file tree
Showing 29 changed files with 1,244 additions and 267 deletions.
6 changes: 5 additions & 1 deletion Arch.fs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
module ISA.RISCV.Arch

// Basic Machine Int representation - include x32
type MachineInt = int64
// Basic registers: 0-32
type Register = int32
// Value of Register
type RegisterVal = MachineInt
type Opcode = MachineInt
type InstrField = MachineInt
type InstrField = int32

// Available RISC-V architectures
type Architecture =
Expand All @@ -26,6 +29,7 @@ type Architecture =
type TrapErrors =
| InstructionFetch of MachineInt
| InstructionDecode
| InstructionExecute
| JumpAddress
| BreakAddress
| ECall
Expand Down
27 changes: 16 additions & 11 deletions Bits.fs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,11 @@ type System.Int64 with
(x ^^^ (x >>> 31)) - (x >>> 31)

type System.Int32 with
member x.bitSlice endBit startBit = // get Bit slice from range
(x >>> startBit) &&& ~~~(-1 <<< (endBit - startBit + 1))
member x.signExtend n = // Sign extend bits for x32
let bitOffset = 32 - n
(x <<< bitOffset) >>> bitOffset
member x.align = // get x32 mask with all `1` bits
x &&& (-1)

Expand All @@ -70,27 +75,27 @@ let loadHalfWord (mem : Map<int64, byte>) (addr : int64) : int16 option =
None

// Load from Memory 4 bytes
let loadWord (mem : Map<int64, byte>) (addr : int64) : int64 option =
let loadWord (mem : Map<int64, byte>) (addr : int64) : int32 option =
if Map.containsKey addr mem &&
Map.containsKey (addr+1L) mem &&
Map.containsKey (addr+2L) mem &&
Map.containsKey (addr+3L) mem then
let word = [| mem.[addr]; mem.[addr+1L]; mem.[addr+2L]; mem.[addr+3L] |]
Some(int64(combineBytes word))
Some(int32(combineBytes word))
else
None

// Load from Memory 8 bytes
let loadDouble (mem : Map<uint32, byte>) (addr : uint32) : int64 option =
let loadDouble (mem : Map<int64, byte>) (addr : int64) : int64 option =
if Map.containsKey addr mem &&
Map.containsKey (addr+1u) mem &&
Map.containsKey (addr+2u) mem &&
Map.containsKey (addr+3u) mem &&
Map.containsKey (addr+4u) mem &&
Map.containsKey (addr+5u) mem &&
Map.containsKey (addr+6u) mem &&
Map.containsKey (addr+7u) mem then
let dWord = [| mem.[addr]; mem.[addr+1u]; mem.[addr+2u]; mem.[addr+3u]; mem.[addr+4u]; mem.[addr+5u]; mem.[addr+6u]; mem.[addr+7u] |]
Map.containsKey (addr+1L) mem &&
Map.containsKey (addr+2L) mem &&
Map.containsKey (addr+3L) mem &&
Map.containsKey (addr+4L) mem &&
Map.containsKey (addr+5L) mem &&
Map.containsKey (addr+6L) mem &&
Map.containsKey (addr+7L) mem then
let dWord = [| mem.[addr]; mem.[addr+1L]; mem.[addr+2L]; mem.[addr+3L]; mem.[addr+4L]; mem.[addr+5L]; mem.[addr+6L]; mem.[addr+7L] |]
Some(int64(combineBytes dWord))
else
None
224 changes: 114 additions & 110 deletions DecodeI.fs
Original file line number Diff line number Diff line change
@@ -1,44 +1,46 @@
module ISA.RISCV.Decode.I

open System
open ISA.RISCV.Utils.Bits
open ISA.RISCV.Arch
open ISA.RISCV.MachineState

//================================================================ -- \begin_latex{Major_Opcodes}
// 'I' (Base instruction set)
// 'I' (Integer x32 instruction set)
type InstructionI =
| LUI of {| rd: Register; imm20: MachineInt |}
| AUIPC of {| rd: Register; imm20: MachineInt |}

| JALR of {| rd: Register; rs1: Register; imm12: MachineInt |}
| JAL of {| rd: Register; imm20: MachineInt |}

| BEQ of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| BNE of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| BLT of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| BGE of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| BLTU of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| BGEU of {| rs1: Register; rs2: Register; imm12: MachineInt |}

| LB of {| rd: Register; rs1: Register; imm12: MachineInt |}
| LH of {| rd: Register; rs1: Register; imm12: MachineInt |}
| LW of {| rd: Register; rs1: Register; imm12: MachineInt |}
| LBU of {| rd: Register; rs1: Register; imm12: MachineInt |}
| LHU of {| rd: Register; rs1: Register; imm12: MachineInt |}

| SB of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| SH of {| rs1: Register; rs2: Register; imm12: MachineInt |}
| SW of {| rs1: Register; rs2: Register; imm12: MachineInt |}

| ADDI of {| rd: Register; rs1: Register; imm12: MachineInt |}
| SLTI of {| rd: Register; rs1: Register; imm12: MachineInt |}
| SLTIU of {| rd: Register; rs1: Register; imm12: MachineInt |}
| XORI of {| rd: Register; rs1: Register; imm12: MachineInt |}
| ORI of {| rd: Register; rs1: Register; imm12: MachineInt |}
| ANDI of {| rd: Register; rs1: Register; imm12: MachineInt |}

| SLLI of {| rd: Register; rs1: Register; shamt: MachineInt |}
| SRLI of {| rd: Register; rs1: Register; shamt: MachineInt |}
| SRAI of {| rd: Register; rs1: Register; shamt: MachineInt |}
| LUI of {| rd: Register; imm20: InstrField |}
| AUIPC of {| rd: Register; imm20: InstrField |}

| JALR of {| rd: Register; rs1: Register; imm12: InstrField |}
| JAL of {| rd: Register; imm20: InstrField |}

| BEQ of {| rs1: Register; rs2: Register; imm12: InstrField |}
| BNE of {| rs1: Register; rs2: Register; imm12: InstrField |}
| BLT of {| rs1: Register; rs2: Register; imm12: InstrField |}
| BGE of {| rs1: Register; rs2: Register; imm12: InstrField |}
| BLTU of {| rs1: Register; rs2: Register; imm12: InstrField |}
| BGEU of {| rs1: Register; rs2: Register; imm12: InstrField |}

| LB of {| rd: Register; rs1: Register; imm12: InstrField |}
| LH of {| rd: Register; rs1: Register; imm12: InstrField |}
| LW of {| rd: Register; rs1: Register; imm12: InstrField |}
| LBU of {| rd: Register; rs1: Register; imm12: InstrField |}
| LHU of {| rd: Register; rs1: Register; imm12: InstrField |}

| SB of {| rs1: Register; rs2: Register; imm12: InstrField |}
| SH of {| rs1: Register; rs2: Register; imm12: InstrField |}
| SW of {| rs1: Register; rs2: Register; imm12: InstrField |}

| ADDI of {| rd: Register; rs1: Register; imm12: InstrField |}
| SLTI of {| rd: Register; rs1: Register; imm12: InstrField |}
| SLTIU of {| rd: Register; rs1: Register; imm12: InstrField |}
| XORI of {| rd: Register; rs1: Register; imm12: InstrField |}
| ORI of {| rd: Register; rs1: Register; imm12: InstrField |}
| ANDI of {| rd: Register; rs1: Register; imm12: InstrField |}

| SLLI of {| rd: Register; rs1: Register; shamt: InstrField |}
| SRLI of {| rd: Register; rs1: Register; shamt: InstrField |}
| SRAI of {| rd: Register; rs1: Register; shamt: InstrField |}

| ADD of {| rd: Register; rs1: Register; rs2: Register |}
| SUB of {| rd: Register; rs1: Register; rs2: Register |}
Expand All @@ -51,50 +53,33 @@ type InstructionI =
| OR of {| rd: Register; rs1: Register; rs2: Register |}
| AND of {| rd: Register; rs1: Register; rs2: Register |}

| FENCE of {| pred: MachineInt; succ: MachineInt; fm: MachineInt |}
| FENCE of {| pred: InstrField; succ: InstrField; fm: InstrField |}
| ECALL
| EBREAK

| None // Instruction not found

//================================================================ -- \begin_latex{Major_Opcodes}
// Major Opcodes
let opcode_OP = 0b0110011L

//================================================================
// Sub-opcodes for 'I' instructions

// opcode_JALR sub-opcodes
let funct3_JALR = 0b000L

// Sub opcode_OP_IMM.SLLI/SRLI/SRAI - 32 & 64 bit
let msbs6_SLLI = 0b0000000L
let msbs6_SRLI = 0b0000000L
let msbs6_SRAI = 0b0100000L

// opcode_MISC_MEM sub-opcodes
let funct3_FENCE = 0b000L

// opcode_SYSTEM sub-opcodes
let funct3_PRIV = 0b000L
let funct12_ECALL = 0b000000000000L
let funct12_EBREAK = 0b000000000001L

/// Decode 'I' instructions
let DecodeI (instr: InstrField) : InstructionI =
let Decode (mstate : MachineState) (instr: InstrField) : InstructionI =
let opcode = instr.bitSlice 6 0
// Register number can be: 0-32
let rd = int32(instr.bitSlice 11 7)
let funct3 = instr.bitSlice 14 12
let rs1 = int32(instr.bitSlice 19 15)
let rs2 = int32(instr.bitSlice 24 20)

let funct3 = instr.bitSlice 14 12
let funct7 = instr.bitSlice 31 25

// Shamt funcs
let shamt = instr.bitSlice 24 20
let shamt5 = instr.bitSlice 24 20
let shamt6 = instr.bitSlice 25 20
// TODO: x32/64 check for Shamt
let shamt_ok = true
let shamt =
if mstate.Arch.archBits = RV32 then
instr.bitSlice 24 20
else
instr.bitSlice 24 20
let funct6 = instr.bitSlice 31 26
let shamt_ok =
((instr.bitSlice 25 25) = 0) ||
(mstate.Arch.archBits = RV64)

let imm12_I = (instr.bitSlice 31 20).signExtend 12
let imm20_U = ((instr.bitSlice 31 12) <<< 12).signExtend 32
Expand Down Expand Up @@ -128,78 +113,97 @@ let DecodeI (instr: InstrField) : InstructionI =

match (opcode) with
// Upper Immediate Opcodes
| 0b0110111L -> LUI {| rd = rd; imm20 = imm20_U |}
| 0b0010111L -> AUIPC {| rd = rd; imm20 = imm20_U |}
| 0b0110111 -> LUI {| rd = rd; imm20 = imm20_U |}
| 0b0010111 -> AUIPC {| rd = rd; imm20 = imm20_U |}

// Jump Opcodes
| 0b1100111L -> JALR {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b1101111L -> JAL {| rd = rd; imm20 = imm20_J |}
| 0b1100111 -> JALR {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b1101111 -> JAL {| rd = rd; imm20 = imm20_J |}

// Branch Opcodes
| 0b1100011L ->
| 0b1100011 ->
match funct3 with
| 0b000L -> BEQ {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b001L -> BNE {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b100L -> BLT {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b101L -> BGE {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b110L -> BLTU {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b111L -> BGEU {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b000 -> BEQ {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b001 -> BNE {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b100 -> BLT {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b101 -> BGE {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b110 -> BLTU {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| 0b111 -> BGEU {| rs1 = rs1; rs2 = rs2; imm12 = imm12_B |}
| _ -> None

// Load Opcodes
| 0b0000011L ->
| 0b0000011 ->
match funct3 with
| 0b000L -> LB {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b001L -> LH {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b010L -> LW {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b100L -> LBU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b101L -> LHU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b000 -> LB {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b001 -> LH {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b010 -> LW {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b100 -> LBU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b101 -> LHU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| _ -> None

// Store opcodes
| 0b0100011L ->
| 0b0100011 ->
match funct3 with
| 0b000L -> SB {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| 0b001L -> SH {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| 0b010L -> SW {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| 0b000 -> SB {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| 0b001 -> SH {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| 0b010 -> SW {| rs1 = rs1; rs2 = rs2; imm12 = imm11_S |}
| _ -> None

// Immediate Opcodes
| 0b0010011L ->
| 0b0010011 ->
match funct3 with
| 0b000L -> ADDI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b010L -> SLTI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b011L -> SLTIU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b100L -> XORI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b110L -> ORI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b111L -> ANDI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b000 -> ADDI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b010 -> SLTI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b011 -> SLTIU {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b100 -> XORI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b110 -> ORI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}
| 0b111 -> ANDI {| rd = rd; rs1 = rs1; imm12 = imm12_I |}

// Shift Immediate Opcodes
| 0b001L when funct7 = msbs6_SLLI -> SLLI {| rd = rd; rs1 = rs1; shamt = shamt |}
| 0b101L when funct7 = msbs6_SRLI -> SRLI {| rd = rd; rs1 = rs1; shamt = shamt |}
| 0b101L when funct7 = msbs6_SRAI -> SRAI {| rd = rd; rs1 = rs1; shamt = shamt |}
| 0b001 when funct6 = 0b000000 && shamt_ok -> SLLI {| rd = rd; rs1 = rs1; shamt = shamt |}
| 0b101 when funct6 = 0b000000 && shamt_ok -> SRLI {| rd = rd; rs1 = rs1; shamt = shamt |}
| 0b101 when funct6 = 0b010000 && shamt_ok -> SRAI {| rd = rd; rs1 = rs1; shamt = shamt |}
| _ -> None

// ALU Opcodes
| 0b0110011L ->
| 0b0110011 ->
match funct3 with
| 0b000L when funct7 = 0b0000000L -> ADD {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b000L when funct7 = 0b0100000L -> SUB {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b001L when funct7 = 0b0000000L -> SLL {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b010L when funct7 = 0b0000000L -> SLT {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b011L when funct7 = 0b0000000L -> SLTU {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b100L when funct7 = 0b0000000L -> XOR {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101L when funct7 = 0b0000000L -> SRL {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101L when funct7 = 0b0100000L -> SRA {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b110L when funct7 = 0b0000000L -> OR {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b111L when funct7 = 0b0000000L -> AND {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b000 when funct7 = 0b0000000 -> ADD {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b000 when funct7 = 0b0100000 -> SUB {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b001 when funct7 = 0b0000000 -> SLL {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b010 when funct7 = 0b0000000 -> SLT {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b011 when funct7 = 0b0000000 -> SLTU {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b100 when funct7 = 0b0000000 -> XOR {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101 when funct7 = 0b0000000 -> SRL {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101 when funct7 = 0b0100000 -> SRA {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b110 when funct7 = 0b0000000 -> OR {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b111 when funct7 = 0b0000000 -> AND {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| _ -> None

// Fence Opcode
| 0b0001111L when rd = 0 && rs1 = 0 && funct3 = funct3_FENCE -> FENCE {| fm = fm; pred = pred; succ = succ |}
| 0b0001111 when rd = 0 && rs1 = 0 && funct3 = 0b000 -> FENCE {| fm = fm; pred = pred; succ = succ |}

// System opcodes
| 0b1110011L when rd = 0 && rs1 = 0 && funct3 = funct3_PRIV && imm12_I = funct12_ECALL -> ECALL
| 0b1110011L when rd = 0 && rs1 = 0 && funct3 = funct3_PRIV && imm12_I = funct12_EBREAK -> EBREAK
| 0b1110011 when rd = 0 && rs1 = 0 && funct3 = 0b000 && imm12_I = 0b000000000000 -> ECALL
| 0b1110011 when rd = 0 && rs1 = 0 && funct3 = 0b000 && imm12_I = 0b000000000001 -> EBREAK

| _ -> None

// Current ISA print log message for current instruction step
let verbosityMessage (instr : InstrField) (decodedInstr : InstructionI) (mstate : MachineState) =
let typeName = decodedInstr.GetType().Name
let instrMsg =
match (decodedInstr) with
| LUI x | AUIPC x -> sprintf "x%d, 0x%08x" x.rd x.imm20
| JAL x -> sprintf "x%d, 0x%08x\n" x.rd x.imm20
| JALR x -> sprintf "x%d, x%d, 0x%08x\n" x.rd x.rs1 x.imm12
| LB x | LH x | LW x | LBU x | LHU x | LB x | ADDI x | SLTI x | XORI x | ORI x | ANDI x -> sprintf "x%d, x%d, %d" x.rd x.rs1 x.imm12
| BEQ x | BNE x | BLT x | BGE x | BLTU x | BGEU x | SB x | SH x | SW x -> sprintf "x%d, x%d, 0x%08x" x.rs1 x.rs2 x.imm12
| SLLI x | SRLI x | SRAI x -> sprintf "x%d, x%d, %d" x.rd x.rs1 x.shamt
| ADD x | SUB x | SLL x | SLT x | SLTU x | XOR x | SRL x | SRA x | OR x | AND x -> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
| FENCE _ | EBREAK | ECALL -> ""
| _ -> "Undef"
let pc = sprintf "%08x:" mstate.PC
let instr = sprintf "%08x" instr
let instrMsg = String.Format("{0,-7}{1}", typeName, instrMsg)
printfn "%s" (String.Format("{0,-12}{1,-12}{2}", pc, instr, instrMsg))
Loading

0 comments on commit ba15cab

Please sign in to comment.