Skip to content

Commit

Permalink
Merge pull request #9 from mrLSD/rv-extention-M-test
Browse files Browse the repository at this point in the history
RV64M extension tests
  • Loading branch information
mrLSD authored Dec 9, 2019
2 parents f747d4e + 5753aae commit cd0d90a
Show file tree
Hide file tree
Showing 14 changed files with 526 additions and 58 deletions.
25 changes: 1 addition & 24 deletions DecodeM.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,6 @@ type InstructionM =
| REM of {| rd: Register; rs1: Register; rs2: Register |}
| REMU of {| rd: Register; rs1: Register; rs2: Register |}

// Only x64
| MULW of {| rd: Register; rs1: Register; rs2: Register |}
| DIVW of {| rd: Register; rs1: Register; rs2: Register |}
| DIVUW of {| rd: Register; rs1: Register; rs2: Register |}
| REMW of {| rd: Register; rs1: Register; rs2: Register |}
| REMUW of {| rd: Register; rs1: Register; rs2: Register |}

| None // Instruction not found

/// Decode 'M' instructions
Expand Down Expand Up @@ -56,21 +49,6 @@ let Decode (mstate : MachineState) (instr: InstrField) : InstructionM =
| _ -> None
| _ -> None

// RV64M Standard Extension (in addition to RV32M)
| 0b0111011 when mstate.Arch.archBits = RV64 ->
match funct7 with
| 0b0000001 ->
match funct3 with
// Multiplication Operations
| 0b000 -> MULW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
// Division Operations
| 0b100 -> DIVW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101 -> DIVUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b110 -> REMW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b111 -> REMUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| _ -> None
| _ -> None

| _ -> None

// Current ISA print log message for current instruction step
Expand All @@ -79,8 +57,7 @@ let verbosityMessage (instr : InstrField) (decodedInstr : InstructionM) (mstate
let instrMsg =
match (decodedInstr) with
| MUL x | MULH x | MULHSU x | MULHU x | DIV x
| DIVU x | REM x | REMU x | MULW x | DIVW x
| DIVUW x | REMW x | REMUW x -> sprintf "x%d, x%d, x%d" x.rd x.rs1 x.rs2
| DIVU x | REM x | REMU 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
Expand Down
59 changes: 59 additions & 0 deletions DecodeM64.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
module ISA.RISCV.Decode.M64

open System
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 |}
| DIVW of {| rd: Register; rs1: Register; rs2: Register |}
| DIVUW of {| rd: Register; rs1: Register; rs2: Register |}
| REMW of {| rd: Register; rs1: Register; rs2: Register |}
| REMUW of {| rd: Register; rs1: Register; rs2: Register |}

| None // Instruction not found

/// Decode 'M64' instructions
let Decode (mstate : MachineState) (instr: InstrField) : InstructionM64 =
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 25

match (opcode) with
// RV64M Standard Extension (in addition to RV32M)
| 0b0111011 when mstate.Arch.archBits = RV64 ->
match funct7 with
| 0b0000001 ->
match funct3 with
// Multiplication Operations
| 0b000 -> MULW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
// Division Operations
| 0b100 -> DIVW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b101 -> DIVUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b110 -> REMW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| 0b111 -> REMUW {| rd = rd; rs1 = rs1; rs2 = rs2 |}
| _ -> None
| _ -> None

| _ -> None

// Current ISA print log message for current instruction step
let verbosityMessage (instr : InstrField) (decodedInstr : InstructionM64) (mstate : MachineState) =
let typeName = decodedInstr.GetType().Name
let instrMsg =
match (decodedInstr) with
MULW x | DIVW x | DIVUW x |
REMW x | REMUW 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))
7 changes: 5 additions & 2 deletions Decoder.fs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
let decI32 = I.Decode mstate instr
let decI64 = I64.Decode instr
let decM = M.Decode mstate instr
let decM64 = M64.Decode mstate instr

// Check is instruction should be executed
let execI32 =
match mstate.Arch with
Expand All @@ -30,8 +32,9 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
| _ -> false
let execM64 =
match mstate.Arch with
| RV64im when decM <> M.InstructionM.None -> true
| RV64im when decM64 <> M64.InstructionM64.None -> true
| _ -> false

// Decoded instruction and execute ISA function
if execI32 then
Some(I.Execute decI32)
Expand All @@ -40,6 +43,6 @@ let Decode (mstate : MachineState) (instr: InstrField) : execFunc option =
else if execM32 then
Some(M.Execute decM)
else if execM64 then
Some(M64.Execute decM)
Some(M64.Execute decM64)
else
None
61 changes: 51 additions & 10 deletions ExecuteM.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,36 @@ open ISA.RISCV.Arch
open ISA.RISCV.MachineState
open ISA.RISCV.Utils.Bits

let mulhu (x : uint64, y : uint64) : uint64 =
let x0 = uint64(uint32 x)
let y0 = uint64(uint32 y)
let x1 = x >>> 32
let y1 = y >>> 32

let t = x1 * y0 + ((x0 * y0) >>> 32)
let y2 = uint64(uint32 t)
let y3 = t >>> 32
let y4 = x0 * y1 + y2
let t = x1 * y1 + y3 + (y4 >>> 32)
let y5 = uint64(uint32 t)
let y6 = (t >>> 32) <<< 32
y6 ||| y5

let mulh (x : int64, y : int64) : int64 =
let neg = (x < 0L) <> (y < 0L)
let x1 = uint64(if x < 0L then -x else x)
let y1 = uint64(if y < 0L then -y else y)
let res = mulhu(x1, y1)
let resd = if (x * y) = 0L then 1L else 0L
if neg then int64(~~~res) + resd else int64 res

let mulhsu (x : int64, y : uint64) : int64 =
let neg = x < 0L
let x1 = uint64(if x < 0L then -x else x)
let res = mulhu(x1, y)
let resd = if (x * int64 y) = 0L then 1L else 0L
if neg then int64(~~~res) + resd else int64 res

//=================================================
// MUL - Multiplication operation - sign * sign
let execMUL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
Expand All @@ -15,8 +45,15 @@ let execMUL (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineS
//=================================================
// MULH - Multiplication operation - sign * sign and return high 32 bits
let execMULH (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
let hRes = rdVal.bitSlice 63 32
let hRes =
match mstate.Arch.archBits with
| RV32 ->
let rdVal = (mstate.getRegister rs1) * (mstate.getRegister rs2)
rdVal.bitSlice 63 32
| _ ->
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
mulh(rs1Val, rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC

Expand All @@ -25,11 +62,13 @@ let execMULH (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machine
let execMULHSU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let rdVal =
let hRes =
match mstate.Arch.archBits with
| RV32 -> rs1Val * int64(uint32 rs2Val)
| _ -> rs1Val * int64(uint64 rs2Val)
let hRes = rdVal.bitSlice 63 32
| RV32 ->
let rdVal = rs1Val * int64(uint32 rs2Val)
rdVal.bitSlice 63 32
| _ ->
mulhsu(rs1Val, uint64 rs2Val)
let mstate = mstate.setRegister rd hRes
mstate.incPC

Expand All @@ -38,11 +77,13 @@ let execMULHSU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machi
let execMULHU (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let rdVal =
let hRes =
match mstate.Arch.archBits with
| RV32 -> int64(uint32 rs1Val) * int64(uint32 rs2Val)
| _ -> int64(uint64 rs1Val) * int64(uint64 rs2Val)
let hRes = rdVal.bitSlice 63 32
| RV32 ->
let rdVal = int64(uint32 rs1Val) * int64(uint32 rs2Val)
rdVal.bitSlice 63 32
| _ ->
int64(mulhu(uint64 rs1Val, uint64 rs2Val))
let mstate = mstate.setRegister rd hRes
mstate.incPC

Expand Down
30 changes: 15 additions & 15 deletions ExecuteM64.fs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
module ISA.RISCV.Execute.M64

open ISA.RISCV.Arch
open ISA.RISCV.Decode.M
open ISA.RISCV.Decode.M64
open ISA.RISCV.MachineState

//=================================================
Expand All @@ -15,16 +15,16 @@ let execMULW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machine
//=================================================
// DIVW - Division Word operation - sign * sign
let execDIVW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let minSigned = 0x8000000000000000L
let rs1Val = int32(mstate.getRegister rs1)
let rs2Val = int32(mstate.getRegister rs2)
let minSigned = 0x80000000
let rdVal =
if rs2Val = 0L then
if rs2Val = 0 then
-1
else if rs1Val = minSigned && rs2Val = -1L then
int32 rs1Val
else if rs1Val = minSigned && rs2Val = -1 then
rs1Val
else
int32 rs1Val / int32 rs2Val
rs1Val / rs2Val
let mstate = mstate.setRegister rd (int64 rdVal)
mstate.incPC

Expand All @@ -45,16 +45,16 @@ let execDIVUW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machin
//=================================================
// REMW - Division Unsign Word operation - sign * sign
let execREMW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : MachineState) =
let rs1Val = mstate.getRegister rs1
let rs2Val = mstate.getRegister rs2
let minSigned = 0x8000000000000000L
let rs1Val = int32(mstate.getRegister rs1)
let rs2Val = int32(mstate.getRegister rs2)
let minSigned = 0x80000000
let rdVal =
if rs2Val = 0L then
if rs2Val = 0 then
int32 rs1Val
else if rs1Val = minSigned && rs2Val = -1L then
else if rs1Val = minSigned && rs2Val = -1 then
0
else
int32 rs1Val % int32 rs2Val
rs1Val % rs2Val
let mstate = mstate.setRegister rd (int64 rdVal)
mstate.incPC

Expand All @@ -72,7 +72,7 @@ let execREMUW (rd : Register) (rs1 : Register) (rs2 : Register) (mstate : Machin
mstate.incPC

// Execute M64-instructions
let Execute (instr : InstructionM) (mstate : MachineState) =
let Execute (instr : InstructionM64) (mstate : MachineState) =
match instr with
| MULW i ->
execMULW i.rd i.rs1 i.rs2 mstate
Expand Down
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,11 @@ Technical Group constituted by The RISC-V Foundation
- [x] Tests RV32I
- [x] Base instruction set: RV64I
- [x] Tests RV64I
- [ ] Standard extension M (integer multiply/divide)
- [ ] Tests for Standard extension M RV32/RV64
- [x] Standard extension M (integer multiply/divide)
- [x] Tests for Standard extension M RV32/RV64
- [ ] Standard extension A (atomic memory ops)
- [ ] Tests for Standard extension A RV32/RV64
* Features under development
* Standard extension A (atomic memory ops)
* Standard extension C (Compressed 16-bit instructions)
* Standard extension F (Single-precision floating point)
* Standard extension D (Double-precision floating point)
Expand Down
3 changes: 3 additions & 0 deletions Tests/Tests.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@
<Compile Include="rv64i\j.fs" />
<Compile Include="rv64i\br.fs" />
<Compile Include="rv64i\mem.fs" />

<Compile Include="rv32m\alu.fs" />
<Compile Include="rv64m\alu.fs" />

<Compile Include="Program.fs" />
</ItemGroup>
Expand Down
2 changes: 1 addition & 1 deletion Tests/asm/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ $(BUILDDIR)/%32: $(SRCDIR)/%.S init32.o mmio.ld

$(BUILDDIR)/%64: $(SRCDIR)/%.S init64.o mmio.ld
mkdir -p $(BUILDDIR)
$(RISCVCC64) -c $(SRCDIR)/$*.S -o intermediate64.o
$(RISCVCC64) -c $(SRCDIR)/$*.S -o intermediate64.o -D x64
$(RISCVCC64) -o $(BUILDDIR)/$*64 -Tmmio.ld intermediate64.o init64.o
rm intermediate64.o

Expand Down
22 changes: 21 additions & 1 deletion Tests/asm/src/alu.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,30 @@ main:
sra x3, x2, x1
or x3, x2, x1
and x3, x2, x1
# x64
#ifdef x64
addw x3, x2, x1
subw x3, x2, x1
sllw x3, x2, x1
srlw x3, x2, x1
sraw x3, x2, x1
#endif

# M-extension
mul x3, x2, x1
mulh x3, x2, x1
mulhu x3, x2, x1
mulhsu x3, x2, x1

div x3, x2, x1
divu x3, x2, x1
rem x3, x2, x1
remu x3, x2, x1

#ifdef x64
mulw x3, x2, x1
divw x3, x2, x1
divuw x3, x2, x1
remw x3, x2, x1
remuw x3, x2, x1
#endif
ret
3 changes: 2 additions & 1 deletion Tests/asm/src/alui.S
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@ main:
slli x3, x2, 5
srli x3, x2, 5
srai x3, x2, 5
# x64 only
#ifdef x64
addiw x3, x2, 5
slliw x3, x2, 5
srliw x3, x2, 5
sraiw x3, x2, 5
#endif
ret
7 changes: 6 additions & 1 deletion Tests/asm/src/mem.S
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@ main:
lh x3, -10(x2)
lw x3, 10(x2)
lw x3, -10(x2)
#ifdef x64
ld x3, 10(x2)
ld x3, -10(x2)
#endif

lbu x3, 10(x2)
lbu x3, -10(x2)
lhu x3, 10(x2)
lhu x3, -10(x2)
#ifdef x64
lwu x3, 10(x2)
lwu x3, -10(x2)
#endif

sb x3, 10(x2)
sb x3, -10(x2)
sh x3, 10(x2)
sh x3, -10(x2)
sw x3, 10(x2)
sw x3, -10(x2)
# x64
#ifdef x64
sd x3, 10(x2)
sd x3, -10(x2)
#endif
ret
Loading

0 comments on commit cd0d90a

Please sign in to comment.