Skip to content

Commit

Permalink
Merge pull request #10 from mrLSD/rv-extension-A
Browse files Browse the repository at this point in the history
RV32/64A Standard Extension
  • Loading branch information
mrLSD authored Feb 15, 2020
2 parents cd0d90a + 0354fad commit a5ba8f9
Show file tree
Hide file tree
Showing 16 changed files with 630 additions and 27 deletions.
12 changes: 10 additions & 2 deletions Arch.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,26 @@ type Architecture =
| RV64i
| RV32im
| RV64im
| RV32ia
| RV64ia
| RV32ima
| RV64ima
static member fromString (x : string) =
match x with
| "rv32i" -> Some(RV32i)
| "rv64i" -> Some(RV64i)
| "rv32im" -> Some(RV32im)
| "rv64im" -> Some(RV64im)
| "rv32ia" -> Some(RV32ia)
| "rv64ia" -> Some(RV64ia)
| "rv32ima" -> Some(RV32ima)
| "rv64ima" -> Some(RV64ima)
| _ -> None

member x.archBits = // Get architecture bits
match x with
| RV32 | RV32i | RV32im -> RV32
| RV64 | RV64i | RV64im -> RV64
| RV32 | RV32i | RV32im | RV32ia | RV32ima -> RV32
| RV64 | RV64i | RV64im | RV64ia | RV64ima -> RV64

type TrapErrors =
| InstructionFetch of MachineInt
Expand Down
6 changes: 3 additions & 3 deletions CLI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module ISA.RISCV.CLI

open System

let version = "v0.1.0"
let version = "v0.4.0"
let author = "(c) 20019 by Evgeny Ukhanov"
let about = sprintf "RISC-V Simulator for Formal RISC-V ISA implementation\n%s %s" version author

Expand Down Expand Up @@ -61,7 +61,7 @@ type CliOptions = {
else if x.LongKey.IsSome then
sprintf "--%s\t" x.LongKey.Value
else if x.Value.IsSome then
sprintf "<%s>\t" x.Value.Value
sprintf "<%s>" x.Value.Value
else
""
printfn "%s" (String.Format("{0,-5}{1,-20} {2}", "", msg, x.HelpMessage))
Expand Down Expand Up @@ -181,7 +181,7 @@ let rec InitCLI =
Key = Some("A");
LongKey = Some("arch");
Value = Some("ARCH")
HelpMessage = "RISC-V architecture. Available: rv32i, rv32im, rv64i, rv64im. Default: rv32i"
HelpMessage = "RISC-V architecture. Available: rv32i, rv32im, rv32ia, rv32ima, rv64i, rv64im, rv64ia, rv64ima. Default: rv32i"
Handler =
fun arg cfg ->
{ cfg with
Expand Down
70 changes: 70 additions & 0 deletions DecodeA.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module ISA.RISCV.Decode.A

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

//================================================================
// 'A32' (Atomic Memory Operations 'A' Standard Extension)
type InstructionA =
| LR_W of {| rd: Register; rs1: Register; aq: InstrField; rl: InstrField |}
| SC_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}

| AMOSWAP_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOADD_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOXOR_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOAND_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOOR_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMIN_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMAX_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMINU_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMAXU_W of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}

| None // Instruction not found

/// Decode 'A' instructions
let Decode (instr: InstrField) : InstructionA =
let opcode = instr.bitSlice 6 0
// Register number can be: 0-32
let rd = int32(instr.bitSlice 11 7)
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 27

let rl = instr.bitSlice 25 25
let aq = instr.bitSlice 26 26

match (opcode) with
| 0b0101111 when funct3 = 0b010 ->
match funct7 with
| 00010 -> LR_W {| rd = rd; rs1 = rs1; aq = aq; rl = rl |}
| 00011 -> SC_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 00001 -> AMOSWAP_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 00000 -> AMOADD_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 00100 -> AMOXOR_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 01100 -> AMOAND_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 01000 -> AMOOR_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 10000 -> AMOMIN_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 10100 -> AMOMAX_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 11000 -> AMOMINU_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| 11100 -> AMOMAXU_W {| rd = rd; rs1 = rs1; rs2 = rs2; aq = aq; rl = rl |}
| _ -> None

| _ -> None

let verbosityMessage (instr : InstrField) (decodedInstr : InstructionA) (mstate : MachineState) =
let typeName = decodedInstr.GetType().Name
let instrMsg =
match (decodedInstr) with
| LR_W x -> sprintf "x%d, x%d" x.rd x.rs1
| SC_W x | AMOSWAP_W x | AMOADD_W x | AMOXOR_W x
| AMOAND_W x | AMOOR_W x | AMOMIN_W x
| AMOMAX_W x | AMOMINU_W x | AMOMAXU_W x-> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
| _ -> "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))
70 changes: 70 additions & 0 deletions DecodeA64.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
module ISA.RISCV.Decode.A64

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

//================================================================
// 'A64' (Atomic Memory Operations 'A' Standard Extension)
type InstructionA64 =
| LR_D of {| rd: Register; rs1: Register; aq: InstrField; rl: InstrField |}
| SC_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}

| AMOSWAP_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOADD_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOXOR_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOAND_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOOR_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMIN_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMAX_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMINU_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}
| AMOMAXU_D of {| rd: Register; rs1: Register; rs2: Register; aq: InstrField; rl: InstrField |}

| None // Instruction not found

/// Decode 'A64' instructions
let Decode (instr: InstrField) : InstructionA64 =
let opcode = instr.bitSlice 6 0
// Register number can be: 0-32
let rd = int32(instr.bitSlice 11 7)
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 27

let rl = instr.bitSlice 25 25
let aq = instr.bitSlice 26 26

match (opcode) with
| 0b0101111 when funct3 = 0b011 ->
match funct7 with
| 00010 -> LR_D {| rd = rd; rs1 = rs1; aq = aq; rl = rl |}
| 00011 -> SC_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 00001 -> AMOSWAP_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 00000 -> AMOADD_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 00100 -> AMOXOR_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 01100 -> AMOAND_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 01000 -> AMOOR_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 10000 -> AMOMIN_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 10100 -> AMOMAX_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 11000 -> AMOMINU_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| 11100 -> AMOMAXU_D {| rd = rd; rs1 = rs1; rs2 = rs1; aq = aq; rl = rl |}
| _ -> None

| _ -> None

let verbosityMessage (instr : InstrField) (decodedInstr : InstructionA64) (mstate : MachineState) =
let typeName = decodedInstr.GetType().Name
let instrMsg =
match (decodedInstr) with
| LR_D x -> sprintf "x%d, x%d" x.rd x.rs1
| SC_D x | AMOSWAP_D x | AMOADD_D x | AMOXOR_D x
| AMOAND_D x | AMOOR_D x | AMOMIN_D x
| AMOMAX_D x | AMOMINU_D x | AMOMAXU_D x-> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
| _ -> "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))
2 changes: 1 addition & 1 deletion DecodeI.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open ISA.RISCV.Utils.Bits
open ISA.RISCV.Arch
open ISA.RISCV.MachineState

//================================================================ -- \begin_latex{Major_Opcodes}
//================================================================
// 'I' (Integer x32 instruction set)
type InstructionI =
| LUI of {| rd: Register; imm20: InstrField |}
Expand Down
2 changes: 1 addition & 1 deletion DecodeI64.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open ISA.RISCV.Utils.Bits
open ISA.RISCV.Arch
open ISA.RISCV.MachineState

//================================================================ -- \begin_latex{Major_Opcodes}
//================================================================
// 'I64' (Integer x64 instruction set)
type InstructionI64 =
| LWU of {| rd: Register; rs1: Register; imm12: InstrField |}
Expand Down
2 changes: 1 addition & 1 deletion DecodeM.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open ISA.RISCV.Utils.Bits
open ISA.RISCV.Arch
open ISA.RISCV.MachineState

//================================================================ -- \begin_latex{Major_Opcodes}
//================================================================
// 'M' (Integer Multiplication and Division 'M' Standard Extension)
type InstructionM =
| MUL of {| rd: Register; rs1: Register; rs2: Register |}
Expand Down
2 changes: 1 addition & 1 deletion DecodeM64.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ open ISA.RISCV.Utils.Bits
open ISA.RISCV.Arch
open ISA.RISCV.MachineState

//================================================================ -- \begin_latex{Major_Opcodes}
//================================================================
// 'M64' (Integer Multiplication and Division 'M' Standard Extension)
type InstructionM64 =
| MULW of {| rd: Register; rs1: Register; rs2: Register |}
Expand Down
25 changes: 20 additions & 5 deletions Decoder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,36 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
let decI64 = I64.Decode instr
let decM = M.Decode mstate instr
let decM64 = M64.Decode mstate instr
let decA = A.Decode instr
let decA64 = A64.Decode instr

// Check is instruction should be executed
let execI32 =
match mstate.Arch with
| RV32i | RV64i | RV32im | RV64im when decI32 <> I.InstructionI.None -> true
| RV32i | RV32im | RV32ia | RV32ima
| RV64i | RV64im | RV64ia | RV64ima when decI32 <> I.InstructionI.None -> true
| _ -> false
let execI64 =
match mstate.Arch with
| RV64i | RV64im when decI64 <> I64.InstructionI64.None -> true
| RV64i | RV64im | RV64ia | RV64ima when decI64 <> I64.InstructionI64.None -> true
| _ -> false
let execM32 =
match mstate.Arch with
| RV32im | RV64im when decM <> M.InstructionM.None -> true
| RV32im | RV64im | RV32ima | RV64ima when decM <> M.InstructionM.None -> true
| _ -> false
let execM64 =
match mstate.Arch with
| RV64im when decM64 <> M64.InstructionM64.None -> true
| RV64im | RV64ima when decM64 <> M64.InstructionM64.None -> true
| _ -> false

let execA32 =
match mstate.Arch with
| RV32ia | RV64ia | RV32ima | RV64ima when decA <> A.InstructionA.None -> true
| _ -> false
let execA64 =
match mstate.Arch with
| RV64ia | RV64ima when decA64 <> A64.InstructionA64.None -> true
| _ -> false

// Decoded instruction and execute ISA function
if execI32 then
Some(I.Execute decI32)
Expand All @@ -44,5 +55,9 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
Some(M.Execute decM)
else if execM64 then
Some(M64.Execute decM64)
else if execA32 then
Some(A.Execute decA)
else if execA64 then
Some(A64.Execute decA64)
else
None
Loading

0 comments on commit a5ba8f9

Please sign in to comment.