mirror of
https://github.com/RRZE-HPC/OSACA.git
synced 2025-12-15 16:40:05 +01:00
RISC-V: Update parser to use x-register names, add vector and FP instructions, fix tests
- Modified RISC-V parser to use x-register names instead of ABI names - Added new vector instructions (vsetvli, vle8.v, vse8.v, vfmacc.vv, vfmul.vf) - Added floating point instructions (fmul.d) - Added unconditional jump instruction (j) - Updated tests to match new register naming convention - Added new RISC-V example files - Updated .gitignore to exclude test environment and old examples
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,5 +1,7 @@
|
|||||||
# OSACA specific files and folders
|
# OSACA specific files and folders
|
||||||
*.*.pickle
|
*.*.pickle
|
||||||
|
osaca_testfront_venv/
|
||||||
|
examples/riscy_asm_files/
|
||||||
|
|
||||||
# Byte-compiled / optimized / DLL files
|
# Byte-compiled / optimized / DLL files
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
# Makefile for RISC-V add example
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -O3
|
|
||||||
CFLAGS_VEC = -O3 -march=rv64gcv
|
|
||||||
|
|
||||||
# Default target with -O3
|
|
||||||
all: add_riscv add_riscv_vec
|
|
||||||
|
|
||||||
# Build with -O3 optimization
|
|
||||||
add_riscv: add_riscv.c
|
|
||||||
$(CC) $(CFLAGS) -o add_riscv add_riscv.c
|
|
||||||
$(CC) $(CFLAGS) -S -o add_riscv.s add_riscv.c
|
|
||||||
|
|
||||||
# Build with vector extensions
|
|
||||||
add_riscv_vec: add_riscv.c
|
|
||||||
$(CC) $(CFLAGS_VEC) -o add_riscv_vec add_riscv.c
|
|
||||||
$(CC) $(CFLAGS_VEC) -S -o add_riscv_vec.s add_riscv.c
|
|
||||||
|
|
||||||
# Clean up
|
|
||||||
clean:
|
|
||||||
rm -f add_riscv add_riscv_vec add_riscv.s add_riscv_vec.s
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
||||||
13
examples/add/add.s.rv6.gcc.s
Normal file
13
examples/add/add.s.rv6.gcc.s
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
add_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a3,e64,m1,ta,ma
|
||||||
|
vle64.v v2,0(a1)
|
||||||
|
vle64.v v1,0(a2)
|
||||||
|
slli a4,a5,3
|
||||||
|
sub a3,a3,a5
|
||||||
|
add a1,a1,a4
|
||||||
|
add a2,a2,a4
|
||||||
|
vfadd.vv v1,v1,v2
|
||||||
|
vse64.v v1,0(a0)
|
||||||
|
add a0,a0,a4
|
||||||
|
bne a3,zero,.L3
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
// Vector add benchmark for RISC-V testing
|
|
||||||
// a[i] = b[i] + c[i]
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define DTYPE double
|
|
||||||
|
|
||||||
void kernel(DTYPE* a, DTYPE* b, DTYPE* c, const int size)
|
|
||||||
{
|
|
||||||
// OSACA start marker will be added around this loop
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
a[i] = b[i] + c[i];
|
|
||||||
}
|
|
||||||
// OSACA end marker will be added
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
int size = 1000;
|
|
||||||
if(argc > 1) {
|
|
||||||
size = atoi(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("RISC-V Vector add: a[i] = b[i] + c[i], size=%d\n", size);
|
|
||||||
|
|
||||||
// Allocate memory
|
|
||||||
DTYPE* a = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
DTYPE* b = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
DTYPE* c = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
|
|
||||||
// Initialize arrays
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
a[i] = 0.0;
|
|
||||||
b[i] = i;
|
|
||||||
c[i] = i * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run kernel
|
|
||||||
kernel(a, b, c, size);
|
|
||||||
|
|
||||||
// Check result (to prevent optimization)
|
|
||||||
DTYPE checksum = 0.0;
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
checksum += a[i];
|
|
||||||
}
|
|
||||||
printf("Checksum: %f\n", checksum);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
free(a);
|
|
||||||
free(b);
|
|
||||||
free(c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
9
examples/copy/copy.s.rv6.gcc.s
Normal file
9
examples/copy/copy.s.rv6.gcc.s
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
copy_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a2,e8,m1,ta,ma
|
||||||
|
vle8.v v1,0(a1)
|
||||||
|
sub a2,a2,a5
|
||||||
|
add a1,a1,a5
|
||||||
|
vse8.v v1,0(a0)
|
||||||
|
add a0,a0,a5
|
||||||
|
bne a2,zero,.L3
|
||||||
13
examples/daxpy/daxpy.s.rv6.gcc.s
Normal file
13
examples/daxpy/daxpy.s.rv6.gcc.s
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
daxpy_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a2,e64,m1,ta,ma
|
||||||
|
vle64.v v1,0(a0)
|
||||||
|
vle64.v v2,0(a1)
|
||||||
|
slli a3,a5,3
|
||||||
|
sub a2,a2,a5
|
||||||
|
add a0,a0,a3
|
||||||
|
add a1,a1,a3
|
||||||
|
vfmacc.vv v1,v3,v2
|
||||||
|
vse64.v v1,0(a4)
|
||||||
|
add a4,a4,a3
|
||||||
|
bne a2,zero,.L3
|
||||||
16
examples/gs/gs.s.rv6.gcc.s
Normal file
16
examples/gs/gs.s.rv6.gcc.s
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
gs_riscv:
|
||||||
|
.L5:
|
||||||
|
fld fa2,0(a3)
|
||||||
|
fld fa3,0(a5)
|
||||||
|
fld fa4,0(a4)
|
||||||
|
fadd.d fa5,fa5,fa2
|
||||||
|
addi a5,a5,8
|
||||||
|
addi a3,a3,8
|
||||||
|
addi a4,a4,8
|
||||||
|
fadd.d fa5,fa5,fa3
|
||||||
|
fadd.d fa5,fa5,fa4
|
||||||
|
fmul.d fa5,fa5,fa0
|
||||||
|
fsd fa5,-16(a5)
|
||||||
|
bne a2,a5,.L5
|
||||||
|
addi a0,a0,8
|
||||||
|
bne a6,a0,.L4
|
||||||
44
examples/j2d/j2d.s.rv6.gcc.s
Normal file
44
examples/j2d/j2d.s.rv6.gcc.s
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
j2d_riscv:
|
||||||
|
.L5:
|
||||||
|
vsetvli a5,a7,e64,m1,ta,ma
|
||||||
|
vle64.v v4,0(t1)
|
||||||
|
vle64.v v1,0(a0)
|
||||||
|
vle64.v v3,0(t3)
|
||||||
|
vle64.v v2,0(a6)
|
||||||
|
slli a4,a5,3
|
||||||
|
sub a7,a7,a5
|
||||||
|
add t1,t1,a4
|
||||||
|
vfadd.vv v1,v1,v4
|
||||||
|
add a0,a0,a4
|
||||||
|
add t3,t3,a4
|
||||||
|
add a6,a6,a4
|
||||||
|
vfadd.vv v1,v1,v3
|
||||||
|
vfadd.vv v1,v1,v2
|
||||||
|
vfmul.vf v1,v1,fa4
|
||||||
|
vse64.v v1,0(a2)
|
||||||
|
add a2,a2,a4
|
||||||
|
bne a7,zero,.L5
|
||||||
|
addi t5,t5,1
|
||||||
|
addi a1,a1,8
|
||||||
|
addi t4,t4,8
|
||||||
|
bne t5,t0,.L4
|
||||||
|
.L7:
|
||||||
|
fld fa5,0(a0)
|
||||||
|
fld fa1,-16(a5)
|
||||||
|
fld fa2,0(a5)
|
||||||
|
fld fa3,0(a6)
|
||||||
|
fadd.d fa5,fa5,fa1
|
||||||
|
addi a5,a5,8
|
||||||
|
addi a0,a0,8
|
||||||
|
addi a6,a6,8
|
||||||
|
addi a2,a2,8
|
||||||
|
fadd.d fa5,fa5,fa2
|
||||||
|
fadd.d fa5,fa5,fa3
|
||||||
|
fmul.d fa5,fa5,fa4
|
||||||
|
fsd fa5,-8(a2)
|
||||||
|
bne a5,t1,.L7
|
||||||
|
addi t5,t5,1
|
||||||
|
addi a1,a1,8
|
||||||
|
addi t4,t4,8
|
||||||
|
bne t5,t0,.L4
|
||||||
|
j .L17
|
||||||
@@ -1,178 +0,0 @@
|
|||||||
.file "add_riscv.c"
|
|
||||||
.option pic
|
|
||||||
.attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0"
|
|
||||||
.attribute unaligned_access, 0
|
|
||||||
.attribute stack_align, 16
|
|
||||||
.text
|
|
||||||
.align 1
|
|
||||||
.globl kernel
|
|
||||||
.type kernel, @function
|
|
||||||
kernel:
|
|
||||||
.LFB22:
|
|
||||||
.cfi_startproc
|
|
||||||
ble a3,zero,.L1
|
|
||||||
slli a3,a3,3
|
|
||||||
add a5,a1,a3
|
|
||||||
.L3:
|
|
||||||
fld fa5,0(a1)
|
|
||||||
fld fa4,0(a2)
|
|
||||||
addi a1,a1,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
addi a0,a0,8
|
|
||||||
fsd fa5,-8(a0)
|
|
||||||
bne a1,a5,.L3
|
|
||||||
.L1:
|
|
||||||
ret
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE22:
|
|
||||||
.size kernel, .-kernel
|
|
||||||
.section .rodata.str1.8,"aMS",@progbits,1
|
|
||||||
.align 3
|
|
||||||
.LC0:
|
|
||||||
.string "RISC-V Vector add: a[i] = b[i] + c[i], size=%d\n"
|
|
||||||
.align 3
|
|
||||||
.LC1:
|
|
||||||
.string "Checksum: %f\n"
|
|
||||||
.section .text.startup,"ax",@progbits
|
|
||||||
.align 1
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB23:
|
|
||||||
.cfi_startproc
|
|
||||||
addi sp,sp,-48
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
sd ra,40(sp)
|
|
||||||
sd s0,32(sp)
|
|
||||||
sd s1,24(sp)
|
|
||||||
sd s2,16(sp)
|
|
||||||
sd s3,8(sp)
|
|
||||||
sd s4,0(sp)
|
|
||||||
.cfi_offset 1, -8
|
|
||||||
.cfi_offset 8, -16
|
|
||||||
.cfi_offset 9, -24
|
|
||||||
.cfi_offset 18, -32
|
|
||||||
.cfi_offset 19, -40
|
|
||||||
.cfi_offset 20, -48
|
|
||||||
li a5,1
|
|
||||||
bgt a0,a5,.L21
|
|
||||||
li a1,1000
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
li s0,8192
|
|
||||||
mv s3,a0
|
|
||||||
addi s0,s0,-192
|
|
||||||
li s4,1000
|
|
||||||
.L13:
|
|
||||||
slli a5,s4,32
|
|
||||||
srli a2,a5,29
|
|
||||||
li a1,0
|
|
||||||
mv a0,s1
|
|
||||||
call memset@plt
|
|
||||||
mv a4,s2
|
|
||||||
mv a3,s2
|
|
||||||
li a5,0
|
|
||||||
.L9:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
mv a1,a5
|
|
||||||
addiw a5,a5,1
|
|
||||||
fsd fa5,0(a3)
|
|
||||||
addi a3,a3,8
|
|
||||||
bne a5,s4,.L9
|
|
||||||
mv a2,s3
|
|
||||||
mv a3,s3
|
|
||||||
li a5,0
|
|
||||||
.L10:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
mv a0,a5
|
|
||||||
addi a3,a3,8
|
|
||||||
fadd.d fa5,fa5,fa5
|
|
||||||
addiw a5,a5,1
|
|
||||||
fsd fa5,-8(a3)
|
|
||||||
bne a0,a1,.L10
|
|
||||||
mv a5,s1
|
|
||||||
add a1,s2,s0
|
|
||||||
mv a3,s1
|
|
||||||
.L11:
|
|
||||||
fld fa5,0(a4)
|
|
||||||
fld fa4,0(a2)
|
|
||||||
addi a4,a4,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
addi a3,a3,8
|
|
||||||
fsd fa5,-8(a3)
|
|
||||||
bne a4,a1,.L11
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
add s0,s1,s0
|
|
||||||
.L12:
|
|
||||||
fld fa4,0(a5)
|
|
||||||
addi a5,a5,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
bne a5,s0,.L12
|
|
||||||
.L8:
|
|
||||||
fmv.x.d a1,fa5
|
|
||||||
lla a0,.LC1
|
|
||||||
call printf@plt
|
|
||||||
mv a0,s1
|
|
||||||
call free@plt
|
|
||||||
mv a0,s2
|
|
||||||
call free@plt
|
|
||||||
mv a0,s3
|
|
||||||
call free@plt
|
|
||||||
ld ra,40(sp)
|
|
||||||
.cfi_remember_state
|
|
||||||
.cfi_restore 1
|
|
||||||
ld s0,32(sp)
|
|
||||||
.cfi_restore 8
|
|
||||||
ld s1,24(sp)
|
|
||||||
.cfi_restore 9
|
|
||||||
ld s2,16(sp)
|
|
||||||
.cfi_restore 18
|
|
||||||
ld s3,8(sp)
|
|
||||||
.cfi_restore 19
|
|
||||||
ld s4,0(sp)
|
|
||||||
.cfi_restore 20
|
|
||||||
li a0,0
|
|
||||||
addi sp,sp,48
|
|
||||||
.cfi_def_cfa_offset 0
|
|
||||||
jr ra
|
|
||||||
.L21:
|
|
||||||
.cfi_restore_state
|
|
||||||
ld a0,8(a1)
|
|
||||||
li a2,10
|
|
||||||
li a1,0
|
|
||||||
call strtol@plt
|
|
||||||
sext.w s4,a0
|
|
||||||
mv a1,s4
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
slli s0,s4,3
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s3,a0
|
|
||||||
bgt s4,zero,.L13
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
j .L8
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE23:
|
|
||||||
.size main, .-main
|
|
||||||
.ident "GCC: (GNU) 14.2.1 20250207"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
@@ -1,225 +0,0 @@
|
|||||||
.file "add_riscv.c"
|
|
||||||
.option pic
|
|
||||||
.attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
|
|
||||||
.attribute unaligned_access, 0
|
|
||||||
.attribute stack_align, 16
|
|
||||||
.text
|
|
||||||
.align 1
|
|
||||||
.globl kernel
|
|
||||||
.type kernel, @function
|
|
||||||
kernel:
|
|
||||||
.LFB22:
|
|
||||||
.cfi_startproc
|
|
||||||
ble a3,zero,.L10
|
|
||||||
addiw a5,a3,-1
|
|
||||||
li a4,2
|
|
||||||
bleu a5,a4,.L3
|
|
||||||
addi a5,a2,8
|
|
||||||
addi a4,a1,8
|
|
||||||
sub a5,a0,a5
|
|
||||||
sub a4,a0,a4
|
|
||||||
bgtu a5,a4,.L14
|
|
||||||
.L4:
|
|
||||||
csrr a4,vlenb
|
|
||||||
addi a4,a4,-16
|
|
||||||
bleu a5,a4,.L3
|
|
||||||
.L5:
|
|
||||||
vsetvli a5,a3,e64,m1,ta,ma
|
|
||||||
vle64.v v1,0(a1)
|
|
||||||
vle64.v v2,0(a2)
|
|
||||||
slli a4,a5,3
|
|
||||||
sub a3,a3,a5
|
|
||||||
add a1,a1,a4
|
|
||||||
add a2,a2,a4
|
|
||||||
vfadd.vv v1,v1,v2
|
|
||||||
vse64.v v1,0(a0)
|
|
||||||
add a0,a0,a4
|
|
||||||
bne a3,zero,.L5
|
|
||||||
ret
|
|
||||||
.L3:
|
|
||||||
slli a3,a3,3
|
|
||||||
add a3,a1,a3
|
|
||||||
.L7:
|
|
||||||
fld fa5,0(a1)
|
|
||||||
fld fa4,0(a2)
|
|
||||||
addi a1,a1,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
addi a0,a0,8
|
|
||||||
fsd fa5,-8(a0)
|
|
||||||
bne a1,a3,.L7
|
|
||||||
.L10:
|
|
||||||
ret
|
|
||||||
.L14:
|
|
||||||
mv a5,a4
|
|
||||||
j .L4
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE22:
|
|
||||||
.size kernel, .-kernel
|
|
||||||
.section .rodata.str1.8,"aMS",@progbits,1
|
|
||||||
.align 3
|
|
||||||
.LC0:
|
|
||||||
.string "RISC-V Vector add: a[i] = b[i] + c[i], size=%d\n"
|
|
||||||
.align 3
|
|
||||||
.LC2:
|
|
||||||
.string "Checksum: %f\n"
|
|
||||||
.section .text.startup,"ax",@progbits
|
|
||||||
.align 1
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB23:
|
|
||||||
.cfi_startproc
|
|
||||||
addi sp,sp,-48
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
sd ra,40(sp)
|
|
||||||
sd s0,32(sp)
|
|
||||||
sd s1,24(sp)
|
|
||||||
sd s2,16(sp)
|
|
||||||
sd s3,8(sp)
|
|
||||||
sd s4,0(sp)
|
|
||||||
.cfi_offset 1, -8
|
|
||||||
.cfi_offset 8, -16
|
|
||||||
.cfi_offset 9, -24
|
|
||||||
.cfi_offset 18, -32
|
|
||||||
.cfi_offset 19, -40
|
|
||||||
.cfi_offset 20, -48
|
|
||||||
li a5,1
|
|
||||||
bgt a0,a5,.L35
|
|
||||||
li a1,1000
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s0,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
li s3,8192
|
|
||||||
mv s1,a0
|
|
||||||
addi s3,s3,-192
|
|
||||||
li s4,1000
|
|
||||||
.L22:
|
|
||||||
slli a5,s4,32
|
|
||||||
srli a2,a5,29
|
|
||||||
li a1,0
|
|
||||||
mv a0,s0
|
|
||||||
call memset@plt
|
|
||||||
mv a4,s2
|
|
||||||
li a5,0
|
|
||||||
.L18:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
addiw a5,a5,1
|
|
||||||
addi a4,a4,8
|
|
||||||
fsd fa5,-8(a4)
|
|
||||||
bne a5,s4,.L18
|
|
||||||
fld fa5,.LC1,a4
|
|
||||||
vsetvli a3,zero,e64,m1,ta,ma
|
|
||||||
mv a2,a5
|
|
||||||
vfmv.v.f v4,fa5
|
|
||||||
vsetvli zero,zero,e32,mf2,ta,ma
|
|
||||||
vid.v v2
|
|
||||||
mv a3,s1
|
|
||||||
.L19:
|
|
||||||
vsetvli a4,a2,e32,mf2,ta,ma
|
|
||||||
vfwcvt.f.x.v v1,v2
|
|
||||||
vsetvli a0,zero,e32,mf2,ta,ma
|
|
||||||
vmv.v.x v3,a4
|
|
||||||
vsetvli zero,a4,e64,m1,ta,ma
|
|
||||||
vfmul.vv v1,v1,v4
|
|
||||||
vsetvli a0,zero,e32,mf2,ta,ma
|
|
||||||
vadd.vv v2,v2,v3
|
|
||||||
vsetvli zero,a4,e64,m1,ta,ma
|
|
||||||
slli a1,a4,3
|
|
||||||
sub a2,a2,a4
|
|
||||||
vse64.v v1,0(a3)
|
|
||||||
add a3,a3,a1
|
|
||||||
bne a2,zero,.L19
|
|
||||||
mv a3,s0
|
|
||||||
mv a0,s1
|
|
||||||
mv a1,s2
|
|
||||||
.L20:
|
|
||||||
vsetvli a4,a5,e64,m1,ta,ma
|
|
||||||
vle64.v v2,0(a1)
|
|
||||||
vle64.v v1,0(a0)
|
|
||||||
slli a2,a4,3
|
|
||||||
sub a5,a5,a4
|
|
||||||
add a1,a1,a2
|
|
||||||
add a0,a0,a2
|
|
||||||
vfadd.vv v1,v1,v2
|
|
||||||
vse64.v v1,0(a3)
|
|
||||||
add a3,a3,a2
|
|
||||||
bne a5,zero,.L20
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
add s3,s0,s3
|
|
||||||
mv a5,s0
|
|
||||||
.L21:
|
|
||||||
fld fa4,0(a5)
|
|
||||||
addi a5,a5,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
bne s3,a5,.L21
|
|
||||||
.L17:
|
|
||||||
fmv.x.d a1,fa5
|
|
||||||
lla a0,.LC2
|
|
||||||
call printf@plt
|
|
||||||
mv a0,s0
|
|
||||||
call free@plt
|
|
||||||
mv a0,s2
|
|
||||||
call free@plt
|
|
||||||
mv a0,s1
|
|
||||||
call free@plt
|
|
||||||
ld ra,40(sp)
|
|
||||||
.cfi_remember_state
|
|
||||||
.cfi_restore 1
|
|
||||||
ld s0,32(sp)
|
|
||||||
.cfi_restore 8
|
|
||||||
ld s1,24(sp)
|
|
||||||
.cfi_restore 9
|
|
||||||
ld s2,16(sp)
|
|
||||||
.cfi_restore 18
|
|
||||||
ld s3,8(sp)
|
|
||||||
.cfi_restore 19
|
|
||||||
ld s4,0(sp)
|
|
||||||
.cfi_restore 20
|
|
||||||
li a0,0
|
|
||||||
addi sp,sp,48
|
|
||||||
.cfi_def_cfa_offset 0
|
|
||||||
jr ra
|
|
||||||
.L35:
|
|
||||||
.cfi_restore_state
|
|
||||||
ld a0,8(a1)
|
|
||||||
li a2,10
|
|
||||||
li a1,0
|
|
||||||
call strtol@plt
|
|
||||||
sext.w s4,a0
|
|
||||||
mv a1,s4
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
slli s3,s4,3
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s0,a0
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
bgt s4,zero,.L22
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
j .L17
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE23:
|
|
||||||
.size main, .-main
|
|
||||||
.section .rodata.cst8,"aM",@progbits,8
|
|
||||||
.align 3
|
|
||||||
.LC1:
|
|
||||||
.word 0
|
|
||||||
.word 1073741824
|
|
||||||
.ident "GCC: (GNU) 14.2.1 20250207"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
@@ -1,184 +0,0 @@
|
|||||||
.file "triad.c"
|
|
||||||
.option pic
|
|
||||||
.attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_zicsr2p0_zifencei2p0"
|
|
||||||
.attribute unaligned_access, 0
|
|
||||||
.attribute stack_align, 16
|
|
||||||
.text
|
|
||||||
.align 1
|
|
||||||
.globl kernel
|
|
||||||
.type kernel, @function
|
|
||||||
kernel:
|
|
||||||
.LFB22:
|
|
||||||
.cfi_startproc
|
|
||||||
ble a3,zero,.L1
|
|
||||||
slli a3,a3,3
|
|
||||||
add a5,a1,a3
|
|
||||||
.L3:
|
|
||||||
fld fa5,0(a2)
|
|
||||||
fld fa4,0(a1)
|
|
||||||
addi a1,a1,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fmadd.d fa5,fa5,fa0,fa4
|
|
||||||
addi a0,a0,8
|
|
||||||
fsd fa5,-8(a0)
|
|
||||||
bne a1,a5,.L3
|
|
||||||
.L1:
|
|
||||||
ret
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE22:
|
|
||||||
.size kernel, .-kernel
|
|
||||||
.section .rodata.str1.8,"aMS",@progbits,1
|
|
||||||
.align 3
|
|
||||||
.LC0:
|
|
||||||
.string "RISC-V STREAM triad: a[i] = b[i] + s * c[i], size=%d\n"
|
|
||||||
.align 3
|
|
||||||
.LC2:
|
|
||||||
.string "Checksum: %f\n"
|
|
||||||
.section .text.startup,"ax",@progbits
|
|
||||||
.align 1
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB23:
|
|
||||||
.cfi_startproc
|
|
||||||
addi sp,sp,-48
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
sd ra,40(sp)
|
|
||||||
sd s0,32(sp)
|
|
||||||
sd s1,24(sp)
|
|
||||||
sd s2,16(sp)
|
|
||||||
sd s3,8(sp)
|
|
||||||
sd s4,0(sp)
|
|
||||||
.cfi_offset 1, -8
|
|
||||||
.cfi_offset 8, -16
|
|
||||||
.cfi_offset 9, -24
|
|
||||||
.cfi_offset 18, -32
|
|
||||||
.cfi_offset 19, -40
|
|
||||||
.cfi_offset 20, -48
|
|
||||||
li a5,1
|
|
||||||
bgt a0,a5,.L21
|
|
||||||
li a1,1000
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
li s0,8192
|
|
||||||
mv s3,a0
|
|
||||||
addi s0,s0,-192
|
|
||||||
li s4,1000
|
|
||||||
.L13:
|
|
||||||
slli a5,s4,32
|
|
||||||
srli a2,a5,29
|
|
||||||
li a1,0
|
|
||||||
mv a0,s1
|
|
||||||
call memset@plt
|
|
||||||
mv a4,s2
|
|
||||||
mv a3,s2
|
|
||||||
li a5,0
|
|
||||||
.L9:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
mv a1,a5
|
|
||||||
addiw a5,a5,1
|
|
||||||
fsd fa5,0(a3)
|
|
||||||
addi a3,a3,8
|
|
||||||
bne a5,s4,.L9
|
|
||||||
mv a2,s3
|
|
||||||
mv a3,s3
|
|
||||||
li a5,0
|
|
||||||
.L10:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
mv a0,a5
|
|
||||||
addi a3,a3,8
|
|
||||||
fadd.d fa5,fa5,fa5
|
|
||||||
addiw a5,a5,1
|
|
||||||
fsd fa5,-8(a3)
|
|
||||||
bne a0,a1,.L10
|
|
||||||
fld fa3,.LC1,a5
|
|
||||||
add a1,s2,s0
|
|
||||||
mv a5,s1
|
|
||||||
mv a3,s1
|
|
||||||
.L11:
|
|
||||||
fld fa5,0(a2)
|
|
||||||
fld fa4,0(a4)
|
|
||||||
addi a4,a4,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fmadd.d fa5,fa5,fa3,fa4
|
|
||||||
addi a3,a3,8
|
|
||||||
fsd fa5,-8(a3)
|
|
||||||
bne a4,a1,.L11
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
add s0,s1,s0
|
|
||||||
.L12:
|
|
||||||
fld fa4,0(a5)
|
|
||||||
addi a5,a5,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
bne a5,s0,.L12
|
|
||||||
.L8:
|
|
||||||
fmv.x.d a1,fa5
|
|
||||||
lla a0,.LC2
|
|
||||||
call printf@plt
|
|
||||||
mv a0,s1
|
|
||||||
call free@plt
|
|
||||||
mv a0,s2
|
|
||||||
call free@plt
|
|
||||||
mv a0,s3
|
|
||||||
call free@plt
|
|
||||||
ld ra,40(sp)
|
|
||||||
.cfi_remember_state
|
|
||||||
.cfi_restore 1
|
|
||||||
ld s0,32(sp)
|
|
||||||
.cfi_restore 8
|
|
||||||
ld s1,24(sp)
|
|
||||||
.cfi_restore 9
|
|
||||||
ld s2,16(sp)
|
|
||||||
.cfi_restore 18
|
|
||||||
ld s3,8(sp)
|
|
||||||
.cfi_restore 19
|
|
||||||
ld s4,0(sp)
|
|
||||||
.cfi_restore 20
|
|
||||||
li a0,0
|
|
||||||
addi sp,sp,48
|
|
||||||
.cfi_def_cfa_offset 0
|
|
||||||
jr ra
|
|
||||||
.L21:
|
|
||||||
.cfi_restore_state
|
|
||||||
ld a0,8(a1)
|
|
||||||
li a2,10
|
|
||||||
li a1,0
|
|
||||||
call strtol@plt
|
|
||||||
sext.w s4,a0
|
|
||||||
mv a1,s4
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
slli s0,s4,3
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
mv a0,s0
|
|
||||||
call malloc@plt
|
|
||||||
mv s3,a0
|
|
||||||
bgt s4,zero,.L13
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
j .L8
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE23:
|
|
||||||
.size main, .-main
|
|
||||||
.section .rodata.cst8,"aM",@progbits,8
|
|
||||||
.align 3
|
|
||||||
.LC1:
|
|
||||||
.word 1374389535
|
|
||||||
.word 1074339512
|
|
||||||
.ident "GCC: (GNU) 14.2.1 20250207"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
@@ -1,234 +0,0 @@
|
|||||||
.file "triad.c"
|
|
||||||
.option pic
|
|
||||||
.attribute arch, "rv64i2p1_m2p0_a2p1_f2p2_d2p2_c2p0_v1p0_zicsr2p0_zifencei2p0_zve32f1p0_zve32x1p0_zve64d1p0_zve64f1p0_zve64x1p0_zvl128b1p0_zvl32b1p0_zvl64b1p0"
|
|
||||||
.attribute unaligned_access, 0
|
|
||||||
.attribute stack_align, 16
|
|
||||||
.text
|
|
||||||
.align 1
|
|
||||||
.globl kernel
|
|
||||||
.type kernel, @function
|
|
||||||
kernel:
|
|
||||||
.LFB22:
|
|
||||||
.cfi_startproc
|
|
||||||
ble a3,zero,.L10
|
|
||||||
addiw a5,a3,-1
|
|
||||||
li a4,4
|
|
||||||
bleu a5,a4,.L3
|
|
||||||
addi a5,a2,8
|
|
||||||
addi a4,a1,8
|
|
||||||
sub a5,a0,a5
|
|
||||||
sub a4,a0,a4
|
|
||||||
bgtu a5,a4,.L14
|
|
||||||
.L4:
|
|
||||||
csrr a4,vlenb
|
|
||||||
addi a4,a4,-16
|
|
||||||
bleu a5,a4,.L3
|
|
||||||
vsetvli a5,zero,e64,m1,ta,ma
|
|
||||||
vfmv.v.f v3,fa0
|
|
||||||
.L5:
|
|
||||||
vsetvli a5,a3,e64,m1,ta,ma
|
|
||||||
vle64.v v2,0(a1)
|
|
||||||
vle64.v v1,0(a2)
|
|
||||||
slli a4,a5,3
|
|
||||||
sub a3,a3,a5
|
|
||||||
add a1,a1,a4
|
|
||||||
add a2,a2,a4
|
|
||||||
vfmadd.vv v1,v3,v2
|
|
||||||
vse64.v v1,0(a0)
|
|
||||||
add a0,a0,a4
|
|
||||||
bne a3,zero,.L5
|
|
||||||
ret
|
|
||||||
.L3:
|
|
||||||
slli a3,a3,3
|
|
||||||
add a3,a1,a3
|
|
||||||
.L7:
|
|
||||||
fld fa5,0(a2)
|
|
||||||
fld fa4,0(a1)
|
|
||||||
addi a1,a1,8
|
|
||||||
addi a2,a2,8
|
|
||||||
fmadd.d fa5,fa0,fa5,fa4
|
|
||||||
addi a0,a0,8
|
|
||||||
fsd fa5,-8(a0)
|
|
||||||
bne a3,a1,.L7
|
|
||||||
.L10:
|
|
||||||
ret
|
|
||||||
.L14:
|
|
||||||
mv a5,a4
|
|
||||||
j .L4
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE22:
|
|
||||||
.size kernel, .-kernel
|
|
||||||
.section .rodata.str1.8,"aMS",@progbits,1
|
|
||||||
.align 3
|
|
||||||
.LC0:
|
|
||||||
.string "RISC-V STREAM triad: a[i] = b[i] + s * c[i], size=%d\n"
|
|
||||||
.align 3
|
|
||||||
.LC3:
|
|
||||||
.string "Checksum: %f\n"
|
|
||||||
.section .text.startup,"ax",@progbits
|
|
||||||
.align 1
|
|
||||||
.globl main
|
|
||||||
.type main, @function
|
|
||||||
main:
|
|
||||||
.LFB23:
|
|
||||||
.cfi_startproc
|
|
||||||
addi sp,sp,-48
|
|
||||||
.cfi_def_cfa_offset 48
|
|
||||||
sd ra,40(sp)
|
|
||||||
sd s0,32(sp)
|
|
||||||
sd s1,24(sp)
|
|
||||||
sd s2,16(sp)
|
|
||||||
sd s3,8(sp)
|
|
||||||
sd s4,0(sp)
|
|
||||||
.cfi_offset 1, -8
|
|
||||||
.cfi_offset 8, -16
|
|
||||||
.cfi_offset 9, -24
|
|
||||||
.cfi_offset 18, -32
|
|
||||||
.cfi_offset 19, -40
|
|
||||||
.cfi_offset 20, -48
|
|
||||||
li a5,1
|
|
||||||
bgt a0,a5,.L35
|
|
||||||
li a1,1000
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s0,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
li a0,8192
|
|
||||||
addi a0,a0,-192
|
|
||||||
call malloc@plt
|
|
||||||
li s3,8192
|
|
||||||
mv s1,a0
|
|
||||||
addi s3,s3,-192
|
|
||||||
li s4,1000
|
|
||||||
.L22:
|
|
||||||
slli a5,s4,32
|
|
||||||
srli a2,a5,29
|
|
||||||
li a1,0
|
|
||||||
mv a0,s0
|
|
||||||
call memset@plt
|
|
||||||
mv a4,s2
|
|
||||||
li a5,0
|
|
||||||
.L18:
|
|
||||||
fcvt.d.w fa5,a5
|
|
||||||
addiw a5,a5,1
|
|
||||||
addi a4,a4,8
|
|
||||||
fsd fa5,-8(a4)
|
|
||||||
bne a5,s4,.L18
|
|
||||||
fld fa5,.LC1,a4
|
|
||||||
vsetvli a3,zero,e64,m1,ta,ma
|
|
||||||
mv a2,a5
|
|
||||||
vfmv.v.f v4,fa5
|
|
||||||
vsetvli zero,zero,e32,mf2,ta,ma
|
|
||||||
vid.v v2
|
|
||||||
mv a3,s1
|
|
||||||
.L19:
|
|
||||||
vsetvli a4,a2,e32,mf2,ta,ma
|
|
||||||
vfwcvt.f.x.v v1,v2
|
|
||||||
vsetvli a0,zero,e32,mf2,ta,ma
|
|
||||||
vmv.v.x v3,a4
|
|
||||||
vsetvli zero,a4,e64,m1,ta,ma
|
|
||||||
vfmul.vv v1,v1,v4
|
|
||||||
vsetvli a0,zero,e32,mf2,ta,ma
|
|
||||||
vadd.vv v2,v2,v3
|
|
||||||
vsetvli zero,a4,e64,m1,ta,ma
|
|
||||||
slli a1,a4,3
|
|
||||||
sub a2,a2,a4
|
|
||||||
vse64.v v1,0(a3)
|
|
||||||
add a3,a3,a1
|
|
||||||
bne a2,zero,.L19
|
|
||||||
fld fa5,.LC2,a4
|
|
||||||
vsetvli a0,zero,e64,m1,ta,ma
|
|
||||||
mv a3,s0
|
|
||||||
vfmv.v.f v3,fa5
|
|
||||||
mv a0,s1
|
|
||||||
mv a1,s2
|
|
||||||
.L20:
|
|
||||||
vsetvli a4,a5,e64,m1,ta,ma
|
|
||||||
vle64.v v2,0(a1)
|
|
||||||
vle64.v v1,0(a0)
|
|
||||||
slli a2,a4,3
|
|
||||||
sub a5,a5,a4
|
|
||||||
add a1,a1,a2
|
|
||||||
add a0,a0,a2
|
|
||||||
vfmadd.vv v1,v3,v2
|
|
||||||
vse64.v v1,0(a3)
|
|
||||||
add a3,a3,a2
|
|
||||||
bne a5,zero,.L20
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
add s3,s0,s3
|
|
||||||
mv a5,s0
|
|
||||||
.L21:
|
|
||||||
fld fa4,0(a5)
|
|
||||||
addi a5,a5,8
|
|
||||||
fadd.d fa5,fa5,fa4
|
|
||||||
bne s3,a5,.L21
|
|
||||||
.L17:
|
|
||||||
fmv.x.d a1,fa5
|
|
||||||
lla a0,.LC3
|
|
||||||
call printf@plt
|
|
||||||
mv a0,s0
|
|
||||||
call free@plt
|
|
||||||
mv a0,s2
|
|
||||||
call free@plt
|
|
||||||
mv a0,s1
|
|
||||||
call free@plt
|
|
||||||
ld ra,40(sp)
|
|
||||||
.cfi_remember_state
|
|
||||||
.cfi_restore 1
|
|
||||||
ld s0,32(sp)
|
|
||||||
.cfi_restore 8
|
|
||||||
ld s1,24(sp)
|
|
||||||
.cfi_restore 9
|
|
||||||
ld s2,16(sp)
|
|
||||||
.cfi_restore 18
|
|
||||||
ld s3,8(sp)
|
|
||||||
.cfi_restore 19
|
|
||||||
ld s4,0(sp)
|
|
||||||
.cfi_restore 20
|
|
||||||
li a0,0
|
|
||||||
addi sp,sp,48
|
|
||||||
.cfi_def_cfa_offset 0
|
|
||||||
jr ra
|
|
||||||
.L35:
|
|
||||||
.cfi_restore_state
|
|
||||||
ld a0,8(a1)
|
|
||||||
li a2,10
|
|
||||||
li a1,0
|
|
||||||
call strtol@plt
|
|
||||||
sext.w s4,a0
|
|
||||||
mv a1,s4
|
|
||||||
lla a0,.LC0
|
|
||||||
call printf@plt
|
|
||||||
slli s3,s4,3
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s0,a0
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s2,a0
|
|
||||||
mv a0,s3
|
|
||||||
call malloc@plt
|
|
||||||
mv s1,a0
|
|
||||||
bgt s4,zero,.L22
|
|
||||||
fmv.d.x fa5,zero
|
|
||||||
j .L17
|
|
||||||
.cfi_endproc
|
|
||||||
.LFE23:
|
|
||||||
.size main, .-main
|
|
||||||
.section .rodata.cst8,"aM",@progbits,8
|
|
||||||
.align 3
|
|
||||||
.LC1:
|
|
||||||
.word 0
|
|
||||||
.word 1073741824
|
|
||||||
.align 3
|
|
||||||
.LC2:
|
|
||||||
.word 1374389535
|
|
||||||
.word 1074339512
|
|
||||||
.ident "GCC: (GNU) 14.2.1 20250207"
|
|
||||||
.section .note.GNU-stack,"",@progbits
|
|
||||||
15
examples/striad/striad.s.rv6.gcc.s
Normal file
15
examples/striad/striad.s.rv6.gcc.s
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
striad_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a4,e64,m1,ta,ma
|
||||||
|
vle64.v v2,0(a1)
|
||||||
|
vle64.v v3,0(a2)
|
||||||
|
vle64.v v1,0(a3)
|
||||||
|
slli a6,a5,3
|
||||||
|
sub a4,a4,a5
|
||||||
|
add a1,a1,a6
|
||||||
|
add a2,a2,a6
|
||||||
|
add a3,a3,a6
|
||||||
|
vfmadd.vv v1,v3,v2
|
||||||
|
vse64.v v1,0(a0)
|
||||||
|
add a0,a0,a6
|
||||||
|
bne a4,zero,.L3
|
||||||
7
examples/sum_reduction/sum_reduction.s.rv6.gcc.s
Normal file
7
examples/sum_reduction/sum_reduction.s.rv6.gcc.s
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
sum_reduction_riscv:
|
||||||
|
.L3:
|
||||||
|
fld fa5,0(a0)
|
||||||
|
addi a0,a0,8
|
||||||
|
fadd.d fa0,fa0,fa5
|
||||||
|
bne a1,a0,.L3
|
||||||
|
ret
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
# Makefile for RISC-V triad example
|
|
||||||
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -O3
|
|
||||||
CFLAGS_VEC = -O3 -march=rv64gcv
|
|
||||||
|
|
||||||
# Default target with -O3
|
|
||||||
all: triad triad_vec
|
|
||||||
|
|
||||||
# Build with -O3 optimization
|
|
||||||
triad: triad.c
|
|
||||||
$(CC) $(CFLAGS) -o triad triad.c
|
|
||||||
$(CC) $(CFLAGS) -S -o triad.s triad.c
|
|
||||||
|
|
||||||
# Build with vector extensions
|
|
||||||
triad_vec: triad.c
|
|
||||||
$(CC) $(CFLAGS_VEC) -o triad_vec triad.c
|
|
||||||
$(CC) $(CFLAGS_VEC) -S -o triad_vec.s triad.c
|
|
||||||
|
|
||||||
# Clean up
|
|
||||||
clean:
|
|
||||||
rm -f triad triad_vec triad.s triad_vec.s
|
|
||||||
|
|
||||||
.PHONY: all clean
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
// STREAM triad benchmark for RISC-V testing
|
|
||||||
// a[i] = b[i] + s * c[i]
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define DTYPE double
|
|
||||||
|
|
||||||
void kernel(DTYPE* a, DTYPE* b, DTYPE* c, const DTYPE s, const int size)
|
|
||||||
{
|
|
||||||
// OSACA start marker will be added around this loop
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
a[i] = b[i] + s * c[i];
|
|
||||||
}
|
|
||||||
// OSACA end marker will be added
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
int size = 1000;
|
|
||||||
if(argc > 1) {
|
|
||||||
size = atoi(argv[1]);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("RISC-V STREAM triad: a[i] = b[i] + s * c[i], size=%d\n", size);
|
|
||||||
|
|
||||||
// Allocate memory
|
|
||||||
DTYPE* a = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
DTYPE* b = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
DTYPE* c = (DTYPE*)malloc(size * sizeof(DTYPE));
|
|
||||||
|
|
||||||
// Initialize arrays
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
a[i] = 0.0;
|
|
||||||
b[i] = i;
|
|
||||||
c[i] = i * 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run kernel
|
|
||||||
DTYPE scalar = 3.14;
|
|
||||||
kernel(a, b, c, scalar, size);
|
|
||||||
|
|
||||||
// Check result (to prevent optimization)
|
|
||||||
DTYPE checksum = 0.0;
|
|
||||||
for(int i=0; i<size; i++) {
|
|
||||||
checksum += a[i];
|
|
||||||
}
|
|
||||||
printf("Checksum: %f\n", checksum);
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
free(a);
|
|
||||||
free(b);
|
|
||||||
free(c);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
13
examples/triad/triad.s.rv6.gcc.s
Normal file
13
examples/triad/triad.s.rv6.gcc.s
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
triad_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a3,e64,m1,ta,ma
|
||||||
|
vle64.v v1,0(a1)
|
||||||
|
vle64.v v2,0(a2)
|
||||||
|
slli a4,a5,3
|
||||||
|
sub a3,a3,a5
|
||||||
|
add a1,a1,a4
|
||||||
|
add a2,a2,a4
|
||||||
|
vfmacc.vv v1,v3,v2
|
||||||
|
vse64.v v1,0(a0)
|
||||||
|
add a0,a0,a4
|
||||||
|
bne a3,zero,.L3
|
||||||
11
examples/update/update.s.rv6.gcc.s
Normal file
11
examples/update/update.s.rv6.gcc.s
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
update_riscv:
|
||||||
|
.L3:
|
||||||
|
vsetvli a5,a1,e64,m1,ta,ma
|
||||||
|
vle64.v v1,0(a0)
|
||||||
|
slli a3,a5,3
|
||||||
|
sub a1,a1,a5
|
||||||
|
add a0,a0,a3
|
||||||
|
vfmul.vf v1,v1,fa0
|
||||||
|
vse64.v v1,0(a4)
|
||||||
|
add a4,a4,a3
|
||||||
|
bne a1,zero,.L3
|
||||||
@@ -40,11 +40,11 @@ instruction_forms:
|
|||||||
- name: ADD
|
- name: ADD
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -52,9 +52,9 @@ instruction_forms:
|
|||||||
- name: ADDI
|
- name: ADDI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -64,11 +64,11 @@ instruction_forms:
|
|||||||
- name: SUB
|
- name: SUB
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -76,7 +76,7 @@ instruction_forms:
|
|||||||
- name: LUI
|
- name: LUI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -86,7 +86,7 @@ instruction_forms:
|
|||||||
- name: AUIPC
|
- name: AUIPC
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -97,11 +97,11 @@ instruction_forms:
|
|||||||
- name: AND
|
- name: AND
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -109,9 +109,9 @@ instruction_forms:
|
|||||||
- name: ANDI
|
- name: ANDI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -121,11 +121,11 @@ instruction_forms:
|
|||||||
- name: OR
|
- name: OR
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -133,9 +133,9 @@ instruction_forms:
|
|||||||
- name: ORI
|
- name: ORI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -145,11 +145,11 @@ instruction_forms:
|
|||||||
- name: XOR
|
- name: XOR
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -157,9 +157,9 @@ instruction_forms:
|
|||||||
- name: XORI
|
- name: XORI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -170,11 +170,11 @@ instruction_forms:
|
|||||||
- name: SLL
|
- name: SLL
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -182,9 +182,9 @@ instruction_forms:
|
|||||||
- name: SLLI
|
- name: SLLI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -194,11 +194,11 @@ instruction_forms:
|
|||||||
- name: SRL
|
- name: SRL
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -206,9 +206,9 @@ instruction_forms:
|
|||||||
- name: SRLI
|
- name: SRLI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -218,11 +218,11 @@ instruction_forms:
|
|||||||
- name: SRA
|
- name: SRA
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -230,9 +230,9 @@ instruction_forms:
|
|||||||
- name: SRAI
|
- name: SRAI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -243,11 +243,11 @@ instruction_forms:
|
|||||||
- name: MUL
|
- name: MUL
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 3
|
latency: 3
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -255,11 +255,11 @@ instruction_forms:
|
|||||||
- name: MULH
|
- name: MULH
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 3
|
latency: 3
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -268,11 +268,11 @@ instruction_forms:
|
|||||||
- name: DIV
|
- name: DIV
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 10
|
latency: 10
|
||||||
throughput: 10
|
throughput: 10
|
||||||
port_pressure: [[1, ["DIV"]]]
|
port_pressure: [[1, ["DIV"]]]
|
||||||
@@ -280,11 +280,11 @@ instruction_forms:
|
|||||||
- name: DIVU
|
- name: DIVU
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 10
|
latency: 10
|
||||||
throughput: 10
|
throughput: 10
|
||||||
port_pressure: [[1, ["DIV"]]]
|
port_pressure: [[1, ["DIV"]]]
|
||||||
@@ -292,11 +292,11 @@ instruction_forms:
|
|||||||
- name: REM
|
- name: REM
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 10
|
latency: 10
|
||||||
throughput: 10
|
throughput: 10
|
||||||
port_pressure: [[1, ["DIV"]]]
|
port_pressure: [[1, ["DIV"]]]
|
||||||
@@ -304,11 +304,11 @@ instruction_forms:
|
|||||||
- name: REMU
|
- name: REMU
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 10
|
latency: 10
|
||||||
throughput: 10
|
throughput: 10
|
||||||
port_pressure: [[1, ["DIV"]]]
|
port_pressure: [[1, ["DIV"]]]
|
||||||
@@ -317,9 +317,9 @@ instruction_forms:
|
|||||||
- name: LW
|
- name: LW
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -330,9 +330,9 @@ instruction_forms:
|
|||||||
- name: LD
|
- name: LD
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -343,9 +343,9 @@ instruction_forms:
|
|||||||
- name: SW
|
- name: SW
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -356,9 +356,9 @@ instruction_forms:
|
|||||||
- name: SD
|
- name: SD
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -370,9 +370,9 @@ instruction_forms:
|
|||||||
- name: BEQ
|
- name: BEQ
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -381,9 +381,9 @@ instruction_forms:
|
|||||||
- name: BNE
|
- name: BNE
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -392,9 +392,9 @@ instruction_forms:
|
|||||||
- name: BLT
|
- name: BLT
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -403,9 +403,9 @@ instruction_forms:
|
|||||||
- name: BGE
|
- name: BGE
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -414,7 +414,7 @@ instruction_forms:
|
|||||||
- name: JAL
|
- name: JAL
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -423,9 +423,9 @@ instruction_forms:
|
|||||||
- name: JALR
|
- name: JALR
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -438,7 +438,7 @@ instruction_forms:
|
|||||||
- class: register
|
- class: register
|
||||||
prefix: f
|
prefix: f
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -451,7 +451,7 @@ instruction_forms:
|
|||||||
- class: register
|
- class: register
|
||||||
prefix: f
|
prefix: f
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -464,7 +464,7 @@ instruction_forms:
|
|||||||
- class: register
|
- class: register
|
||||||
prefix: f
|
prefix: f
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -477,7 +477,7 @@ instruction_forms:
|
|||||||
- class: register
|
- class: register
|
||||||
prefix: f
|
prefix: f
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: imd
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
@@ -496,7 +496,19 @@ instruction_forms:
|
|||||||
latency: 3
|
latency: 3
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["FP"]]]
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: FADD.D
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
latency: 3
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
- name: FSUB.S
|
- name: FSUB.S
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
@@ -551,34 +563,63 @@ instruction_forms:
|
|||||||
- name: VSETVLI
|
- name: VSETVLI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
|
- class: identifier
|
||||||
|
- class: identifier
|
||||||
|
- class: identifier
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
|
|
||||||
- name: VLE32.V
|
- name: VLE64.V
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
prefix: v
|
prefix: v
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: null
|
offset: imd
|
||||||
|
index: null
|
||||||
|
scale: 1
|
||||||
|
latency: 4
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["MEM"]]]
|
||||||
|
|
||||||
|
- name: VLE8.V
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: memory
|
||||||
|
base: x
|
||||||
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
latency: 4
|
latency: 4
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["MEM"]]]
|
port_pressure: [[1, ["MEM"]]]
|
||||||
|
|
||||||
- name: VSE32.V
|
- name: VSE64.V
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
prefix: v
|
prefix: v
|
||||||
- class: memory
|
- class: memory
|
||||||
base: gpr
|
base: x
|
||||||
offset: null
|
offset: imd
|
||||||
|
index: null
|
||||||
|
scale: 1
|
||||||
|
latency: 1
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["MEM"]]]
|
||||||
|
|
||||||
|
- name: VSE8.V
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: memory
|
||||||
|
base: x
|
||||||
|
offset: imd
|
||||||
index: null
|
index: null
|
||||||
scale: 1
|
scale: 1
|
||||||
latency: 1
|
latency: 1
|
||||||
@@ -596,7 +637,31 @@ instruction_forms:
|
|||||||
latency: 4
|
latency: 4
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["FP"]]]
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: VFMACC.VV
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
latency: 4
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: VFADD.VV
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
latency: 3
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
- name: VFMADD.VV
|
- name: VFMADD.VV
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
@@ -609,11 +674,42 @@ instruction_forms:
|
|||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["FP"]]]
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: FMUL.D
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
latency: 3
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: VFMUL.VF
|
||||||
|
operands:
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: v
|
||||||
|
- class: register
|
||||||
|
prefix: f
|
||||||
|
latency: 4
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["FP"]]]
|
||||||
|
|
||||||
|
- name: J
|
||||||
|
operands:
|
||||||
|
- class: identifier
|
||||||
|
latency: 1
|
||||||
|
throughput: 1
|
||||||
|
port_pressure: [[1, ["ALU"]]]
|
||||||
|
|
||||||
# CSR instructions
|
# CSR instructions
|
||||||
- name: CSRR
|
- name: CSRR
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: identifier
|
- class: identifier
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
@@ -623,7 +719,7 @@ instruction_forms:
|
|||||||
operands:
|
operands:
|
||||||
- class: identifier
|
- class: identifier
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -632,9 +728,9 @@ instruction_forms:
|
|||||||
- name: MV
|
- name: MV
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
latency: 1
|
latency: 1
|
||||||
throughput: 1
|
throughput: 1
|
||||||
port_pressure: [[1, ["ALU"]]]
|
port_pressure: [[1, ["ALU"]]]
|
||||||
@@ -642,7 +738,7 @@ instruction_forms:
|
|||||||
- name: LI
|
- name: LI
|
||||||
operands:
|
operands:
|
||||||
- class: register
|
- class: register
|
||||||
name: gpr
|
prefix: x
|
||||||
- class: immediate
|
- class: immediate
|
||||||
imd: int
|
imd: int
|
||||||
latency: 1
|
latency: 1
|
||||||
|
|||||||
@@ -300,6 +300,11 @@ def insert_byte_marker(args):
|
|||||||
)
|
)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Check if ISA is RISC-V and raise NotImplementedError
|
||||||
|
isa = MachineModel.get_isa_for_arch(args.arch)
|
||||||
|
if isa == "riscv":
|
||||||
|
raise NotImplementedError("Marker insertion is not supported for RISC-V architecture.")
|
||||||
|
|
||||||
assembly = args.file.read()
|
assembly = args.file.read()
|
||||||
unmarked_assembly = io.StringIO(assembly)
|
unmarked_assembly = io.StringIO(assembly)
|
||||||
marked_assembly = io.StringIO()
|
marked_assembly = io.StringIO()
|
||||||
@@ -308,7 +313,7 @@ def insert_byte_marker(args):
|
|||||||
output_file=marked_assembly,
|
output_file=marked_assembly,
|
||||||
block_selection="manual",
|
block_selection="manual",
|
||||||
pointer_increment="auto_with_manual_fallback",
|
pointer_increment="auto_with_manual_fallback",
|
||||||
isa=MachineModel.get_isa_for_arch(args.arch),
|
isa=isa,
|
||||||
)
|
)
|
||||||
|
|
||||||
marked_assembly.seek(0)
|
marked_assembly.seek(0)
|
||||||
|
|||||||
@@ -431,30 +431,58 @@ class ParserRISCV(BaseParser):
|
|||||||
|
|
||||||
def process_register_operand(self, operand):
|
def process_register_operand(self, operand):
|
||||||
"""Process register operands, including ABI name to x-register mapping"""
|
"""Process register operands, including ABI name to x-register mapping"""
|
||||||
# Handle ABI names by adding the appropriate prefix
|
# If already has prefix (x#, f#, v#), just return as is
|
||||||
if "prefix" not in operand:
|
if "prefix" in operand:
|
||||||
name = operand["name"].lower()
|
|
||||||
# Integer register ABI names
|
|
||||||
if name in ["zero", "ra", "sp", "gp", "tp"] or name[0] in ["t", "a", "s"]:
|
|
||||||
prefix = "x"
|
|
||||||
# Floating point register ABI names
|
|
||||||
elif name[0] == "f" and name[1] in ["t", "a", "s"]:
|
|
||||||
prefix = "f"
|
|
||||||
# CSR registers
|
|
||||||
elif name.startswith("csr"):
|
|
||||||
prefix = ""
|
|
||||||
else:
|
|
||||||
prefix = ""
|
|
||||||
|
|
||||||
return RegisterOperand(
|
|
||||||
prefix=prefix,
|
|
||||||
name=name
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
return RegisterOperand(
|
return RegisterOperand(
|
||||||
prefix=operand["prefix"].lower(),
|
prefix=operand["prefix"].lower(),
|
||||||
name=operand["name"]
|
name=operand["name"]
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Handle ABI names by converting to x-register numbers
|
||||||
|
name = operand["name"].lower()
|
||||||
|
|
||||||
|
# ABI name mapping for integer registers
|
||||||
|
abi_to_x = {
|
||||||
|
"zero": "0", "ra": "1", "sp": "2", "gp": "3", "tp": "4",
|
||||||
|
"t0": "5", "t1": "6", "t2": "7",
|
||||||
|
"s0": "8", "fp": "8", "s1": "9",
|
||||||
|
"a0": "10", "a1": "11", "a2": "12", "a3": "13",
|
||||||
|
"a4": "14", "a5": "15", "a6": "16", "a7": "17",
|
||||||
|
"s2": "18", "s3": "19", "s4": "20", "s5": "21",
|
||||||
|
"s6": "22", "s7": "23", "s8": "24", "s9": "25",
|
||||||
|
"s10": "26", "s11": "27",
|
||||||
|
"t3": "28", "t4": "29", "t5": "30", "t6": "31"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Integer register ABI names
|
||||||
|
if name in abi_to_x:
|
||||||
|
return RegisterOperand(
|
||||||
|
prefix="x",
|
||||||
|
name=abi_to_x[name]
|
||||||
|
)
|
||||||
|
# Floating point register ABI names
|
||||||
|
elif name.startswith("f") and name[1] in ["t", "a", "s"]:
|
||||||
|
if name[1] == "a": # fa0-fa7
|
||||||
|
idx = int(name[2:])
|
||||||
|
return RegisterOperand(prefix="f", name=str(idx + 10))
|
||||||
|
elif name[1] == "s": # fs0-fs11
|
||||||
|
idx = int(name[2:])
|
||||||
|
if idx <= 1:
|
||||||
|
return RegisterOperand(prefix="f", name=str(idx + 8))
|
||||||
|
else:
|
||||||
|
return RegisterOperand(prefix="f", name=str(idx + 16))
|
||||||
|
elif name[1] == "t": # ft0-ft11
|
||||||
|
idx = int(name[2:])
|
||||||
|
if idx <= 7:
|
||||||
|
return RegisterOperand(prefix="f", name=str(idx))
|
||||||
|
else:
|
||||||
|
return RegisterOperand(prefix="f", name=str(idx + 20))
|
||||||
|
# CSR registers
|
||||||
|
elif name.startswith("csr"):
|
||||||
|
return RegisterOperand(prefix="", name=name)
|
||||||
|
|
||||||
|
# If no mapping found, return as is
|
||||||
|
return RegisterOperand(prefix="", name=name)
|
||||||
|
|
||||||
def process_memory_address(self, memory_address):
|
def process_memory_address(self, memory_address):
|
||||||
"""Post-process memory address operand"""
|
"""Post-process memory address operand"""
|
||||||
@@ -715,4 +743,27 @@ class ParserRISCV(BaseParser):
|
|||||||
if len(instruction_form.operands) == 1:
|
if len(instruction_form.operands) == 1:
|
||||||
return []
|
return []
|
||||||
else:
|
else:
|
||||||
return instruction_form.operands[:1]
|
return instruction_form.operands[:1]
|
||||||
|
|
||||||
|
def process_immediate_operand(self, operand):
|
||||||
|
"""Process immediate operands, converting them to ImmediateOperand objects"""
|
||||||
|
if isinstance(operand, (int, str)):
|
||||||
|
# For raw integer values or string immediates
|
||||||
|
return ImmediateOperand(
|
||||||
|
imd_type="int",
|
||||||
|
value=str(operand) if isinstance(operand, int) else operand
|
||||||
|
)
|
||||||
|
elif isinstance(operand, dict) and "imd" in operand:
|
||||||
|
# For immediate operands from instruction definitions
|
||||||
|
return ImmediateOperand(
|
||||||
|
imd_type=operand["imd"],
|
||||||
|
value=operand.get("value"),
|
||||||
|
identifier=operand.get("identifier"),
|
||||||
|
shift=operand.get("shift")
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# For any other immediate format
|
||||||
|
return ImmediateOperand(
|
||||||
|
imd_type="int",
|
||||||
|
value=str(operand)
|
||||||
|
)
|
||||||
@@ -10,6 +10,7 @@ from .hw_model import MachineModel
|
|||||||
from .isa_semantics import INSTR_FLAGS, ISASemantics
|
from .isa_semantics import INSTR_FLAGS, ISASemantics
|
||||||
from osaca.parser.memory import MemoryOperand
|
from osaca.parser.memory import MemoryOperand
|
||||||
from osaca.parser.register import RegisterOperand
|
from osaca.parser.register import RegisterOperand
|
||||||
|
from osaca.parser.immediate import ImmediateOperand
|
||||||
|
|
||||||
|
|
||||||
class ArchSemantics(ISASemantics):
|
class ArchSemantics(ISASemantics):
|
||||||
@@ -425,7 +426,13 @@ class ArchSemantics(ISASemantics):
|
|||||||
elif self._parser.isa() == "aarch64":
|
elif self._parser.isa() == "aarch64":
|
||||||
register = RegisterOperand(name=regtype, prefix=reg_type)
|
register = RegisterOperand(name=regtype, prefix=reg_type)
|
||||||
elif self._parser.isa() == "riscv":
|
elif self._parser.isa() == "riscv":
|
||||||
register = RegisterOperand(name=regtype, prefix=reg_type)
|
# For RISC-V, handle both register and immediate operands
|
||||||
|
if reg_type == "int":
|
||||||
|
# For immediate operands, create an ImmediateOperand
|
||||||
|
register = ImmediateOperand(imd_type="int")
|
||||||
|
else:
|
||||||
|
# For registers, use the x-prefix format
|
||||||
|
register = RegisterOperand(name=regtype, prefix=reg_type)
|
||||||
return register
|
return register
|
||||||
|
|
||||||
def _nullify_data_ports(self, port_pressure):
|
def _nullify_data_ports(self, port_pressure):
|
||||||
|
|||||||
@@ -873,36 +873,29 @@ class MachineModel(object):
|
|||||||
if not isinstance(i_operand, RegisterOperand):
|
if not isinstance(i_operand, RegisterOperand):
|
||||||
return False
|
return False
|
||||||
return self._is_RISCV_reg_type(i_operand, operand)
|
return self._is_RISCV_reg_type(i_operand, operand)
|
||||||
|
|
||||||
# memory
|
# memory
|
||||||
if isinstance(operand, MemoryOperand):
|
if isinstance(operand, MemoryOperand):
|
||||||
if not isinstance(i_operand, MemoryOperand):
|
if not isinstance(i_operand, MemoryOperand):
|
||||||
return False
|
return False
|
||||||
return self._is_RISCV_mem_type(i_operand, operand)
|
return self._is_RISCV_mem_type(i_operand, operand)
|
||||||
|
|
||||||
# immediate
|
# immediate
|
||||||
if isinstance(i_operand, ImmediateOperand) and i_operand.imd_type == self.WILDCARD:
|
if isinstance(operand, (ImmediateOperand, int)):
|
||||||
return isinstance(operand, ImmediateOperand) and (operand.value is not None)
|
if not isinstance(i_operand, ImmediateOperand):
|
||||||
|
return False
|
||||||
if isinstance(i_operand, ImmediateOperand) and i_operand.imd_type == "int":
|
if isinstance(operand, int):
|
||||||
return (
|
# For raw integers, we accept them if the instruction expects an int immediate
|
||||||
isinstance(operand, ImmediateOperand)
|
if i_operand.imd_type == "int":
|
||||||
and operand.imd_type == "int"
|
return True
|
||||||
and operand.value is not None
|
else:
|
||||||
)
|
# For ImmediateOperand objects, check the types match
|
||||||
|
if i_operand.imd_type == operand.imd_type:
|
||||||
if isinstance(i_operand, ImmediateOperand) and i_operand.imd_type == "float":
|
return True
|
||||||
return (
|
if i_operand.imd_type == self.WILDCARD:
|
||||||
isinstance(operand, ImmediateOperand)
|
return True
|
||||||
and operand.imd_type == "float"
|
return False
|
||||||
and operand.value is not None
|
|
||||||
)
|
|
||||||
|
|
||||||
if isinstance(i_operand, ImmediateOperand) and i_operand.imd_type == "double":
|
|
||||||
return (
|
|
||||||
isinstance(operand, ImmediateOperand)
|
|
||||||
and operand.imd_type == "double"
|
|
||||||
and operand.value is not None
|
|
||||||
)
|
|
||||||
|
|
||||||
# identifier
|
# identifier
|
||||||
if isinstance(operand, IdentifierOperand) or (
|
if isinstance(operand, IdentifierOperand) or (
|
||||||
isinstance(operand, ImmediateOperand) and operand.identifier is not None
|
isinstance(operand, ImmediateOperand) and operand.identifier is not None
|
||||||
@@ -1038,7 +1031,6 @@ class MachineModel(object):
|
|||||||
if reg_canonical == i_reg_canonical:
|
if reg_canonical == i_reg_canonical:
|
||||||
return True
|
return True
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
# If we can't determine canonical names, be conservative
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Check for direct prefix matches
|
# Check for direct prefix matches
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ suite = unittest.TestLoader().loadTestsFromNames(
|
|||||||
[
|
[
|
||||||
"test_base_parser",
|
"test_base_parser",
|
||||||
"test_parser_x86att",
|
"test_parser_x86att",
|
||||||
|
"test_parser_x86intel",
|
||||||
"test_parser_AArch64",
|
"test_parser_AArch64",
|
||||||
"test_parser_RISCV",
|
"test_parser_RISCV",
|
||||||
"test_marker_utils",
|
"test_marker_utils",
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ class TestBaseParser(unittest.TestCase):
|
|||||||
self.x86_code = f.read()
|
self.x86_code = f.read()
|
||||||
with open(self._find_file("kernel_aarch64.s")) as f:
|
with open(self._find_file("kernel_aarch64.s")) as f:
|
||||||
self.aarch64_code = f.read()
|
self.aarch64_code = f.read()
|
||||||
|
with open(self._find_file("kernel_riscv.s")) as f:
|
||||||
|
self.riscv_code = f.read()
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Test
|
# Test
|
||||||
@@ -75,6 +77,7 @@ class TestBaseParser(unittest.TestCase):
|
|||||||
self.assertEqual(BaseParser.detect_ISA(self.triad_code_arm), ("aarch64", None))
|
self.assertEqual(BaseParser.detect_ISA(self.triad_code_arm), ("aarch64", None))
|
||||||
self.assertEqual(BaseParser.detect_ISA(self.x86_code), ("x86", "ATT"))
|
self.assertEqual(BaseParser.detect_ISA(self.x86_code), ("x86", "ATT"))
|
||||||
self.assertEqual(BaseParser.detect_ISA(self.aarch64_code), ("aarch64", None))
|
self.assertEqual(BaseParser.detect_ISA(self.aarch64_code), ("aarch64", None))
|
||||||
|
self.assertEqual(BaseParser.detect_ISA(self.riscv_code), ("riscv", None))
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from unittest.mock import patch
|
|||||||
|
|
||||||
import osaca.osaca as osaca
|
import osaca.osaca as osaca
|
||||||
from osaca.db_interface import sanity_check
|
from osaca.db_interface import sanity_check
|
||||||
from osaca.parser import ParserAArch64, ParserX86ATT, ParserX86Intel
|
from osaca.parser import ParserAArch64, ParserX86ATT, ParserX86Intel, ParserRISCV
|
||||||
from osaca.semantics import MachineModel
|
from osaca.semantics import MachineModel
|
||||||
|
|
||||||
|
|
||||||
@@ -85,6 +85,7 @@ class TestCLI(unittest.TestCase):
|
|||||||
self.assertTrue(isinstance(osaca.get_asm_parser("csx"), ParserX86ATT))
|
self.assertTrue(isinstance(osaca.get_asm_parser("csx"), ParserX86ATT))
|
||||||
self.assertTrue(isinstance(osaca.get_asm_parser("csx", "intel"), ParserX86Intel))
|
self.assertTrue(isinstance(osaca.get_asm_parser("csx", "intel"), ParserX86Intel))
|
||||||
self.assertTrue(isinstance(osaca.get_asm_parser("tx2"), ParserAArch64))
|
self.assertTrue(isinstance(osaca.get_asm_parser("tx2"), ParserAArch64))
|
||||||
|
self.assertTrue(isinstance(osaca.get_asm_parser("rv64"), ParserRISCV))
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
osaca.get_asm_parser("UNKNOWN")
|
osaca.get_asm_parser("UNKNOWN")
|
||||||
|
|
||||||
@@ -125,6 +126,22 @@ class TestCLI(unittest.TestCase):
|
|||||||
# remove copy again
|
# remove copy again
|
||||||
os.remove(name_copy)
|
os.remove(name_copy)
|
||||||
|
|
||||||
|
def test_marker_insert_riscv(self):
|
||||||
|
# copy file to add markers
|
||||||
|
name = self._find_test_file("kernel_riscv.s")
|
||||||
|
name_copy = name + ".copy.s"
|
||||||
|
copyfile(name, name_copy)
|
||||||
|
|
||||||
|
user_input = [".L4", "64"]
|
||||||
|
parser = osaca.create_parser()
|
||||||
|
args = parser.parse_args(["--arch", "rv64", "--insert-marker", name_copy])
|
||||||
|
with patch("builtins.input", side_effect=user_input):
|
||||||
|
with self.assertRaises(NotImplementedError):
|
||||||
|
osaca.run(args)
|
||||||
|
|
||||||
|
# remove copy again
|
||||||
|
os.remove(name_copy)
|
||||||
|
|
||||||
def test_examples(self):
|
def test_examples(self):
|
||||||
kernels = [
|
kernels = [
|
||||||
"add",
|
"add",
|
||||||
@@ -137,8 +154,8 @@ class TestCLI(unittest.TestCase):
|
|||||||
"triad",
|
"triad",
|
||||||
"update",
|
"update",
|
||||||
]
|
]
|
||||||
archs = ["csx", "tx2", "zen1"]
|
archs = ["csx", "tx2", "zen1", "rv64"]
|
||||||
comps = {"csx": ["gcc", "icc"], "tx2": ["gcc", "clang"], "zen1": ["gcc"]}
|
comps = {"csx": ["gcc", "icc"], "tx2": ["gcc", "clang"], "zen1": ["gcc"], "rv64": ["gcc"]}
|
||||||
parser = osaca.create_parser()
|
parser = osaca.create_parser()
|
||||||
# Analyze all asm files resulting out of kernels, archs and comps
|
# Analyze all asm files resulting out of kernels, archs and comps
|
||||||
for k in kernels:
|
for k in kernels:
|
||||||
@@ -191,6 +208,10 @@ class TestCLI(unittest.TestCase):
|
|||||||
kernel_aarch64 = "kernel_aarch64.s"
|
kernel_aarch64 = "kernel_aarch64.s"
|
||||||
args = parser.parse_args([self._find_test_file(kernel_aarch64)])
|
args = parser.parse_args([self._find_test_file(kernel_aarch64)])
|
||||||
osaca.run(args, output_file=output)
|
osaca.run(args, output_file=output)
|
||||||
|
# RISC-V
|
||||||
|
kernel_riscv = "kernel_riscv.s"
|
||||||
|
args = parser.parse_args([self._find_test_file(kernel_riscv)])
|
||||||
|
osaca.run(args, output_file=output)
|
||||||
|
|
||||||
def test_user_warnings(self):
|
def test_user_warnings(self):
|
||||||
parser = osaca.create_parser()
|
parser = osaca.create_parser()
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
self.entry_csx = copy.copy(sample_entry)
|
self.entry_csx = copy.copy(sample_entry)
|
||||||
self.entry_tx2 = copy.copy(sample_entry)
|
self.entry_tx2 = copy.copy(sample_entry)
|
||||||
self.entry_zen1 = copy.copy(sample_entry)
|
self.entry_zen1 = copy.copy(sample_entry)
|
||||||
|
self.entry_rv64 = copy.copy(sample_entry)
|
||||||
|
|
||||||
self.entry_csx.port_pressure = [1.25, 0, 1.25, 0.5, 0.5, 0.5, 0.5, 0, 1.25, 1.25, 0]
|
self.entry_csx.port_pressure = [1.25, 0, 1.25, 0.5, 0.5, 0.5, 0.5, 0, 1.25, 1.25, 0]
|
||||||
self.entry_csx.port_pressure = [[5, "0156"], [1, "23"], [1, ["2D", "3D"]]]
|
self.entry_csx.port_pressure = [[5, "0156"], [1, "23"], [1, ["2D", "3D"]]]
|
||||||
@@ -46,6 +47,11 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
[1, "89"],
|
[1, "89"],
|
||||||
[2, ["8D", "9D"]],
|
[2, ["8D", "9D"]],
|
||||||
]
|
]
|
||||||
|
# For RV64, adapt to match its port structure
|
||||||
|
self.entry_rv64.port_pressure = [1, 1, 1, 1] # [ALU, MEM, DIV, FP]
|
||||||
|
self.entry_rv64.port_pressure = [[1, ["ALU"]], [1, ["MEM"]], [1, ["DIV"]], [1, ["FP"]]]
|
||||||
|
self.entry_rv64.operands[1].prefix = "f" # Using f prefix for floating point registers
|
||||||
|
self.entry_rv64.operands[1].name = "1"
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Tests
|
# Tests
|
||||||
@@ -55,21 +61,26 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
mm_csx = MachineModel("csx")
|
mm_csx = MachineModel("csx")
|
||||||
mm_tx2 = MachineModel("tx2")
|
mm_tx2 = MachineModel("tx2")
|
||||||
mm_zen1 = MachineModel("zen1")
|
mm_zen1 = MachineModel("zen1")
|
||||||
|
mm_rv64 = MachineModel("rv64")
|
||||||
num_entries_csx = len(mm_csx["instruction_forms"])
|
num_entries_csx = len(mm_csx["instruction_forms"])
|
||||||
num_entries_tx2 = len(mm_tx2["instruction_forms"])
|
num_entries_tx2 = len(mm_tx2["instruction_forms"])
|
||||||
num_entries_zen1 = len(mm_zen1["instruction_forms"])
|
num_entries_zen1 = len(mm_zen1["instruction_forms"])
|
||||||
|
num_entries_rv64 = len(mm_rv64["instruction_forms"])
|
||||||
|
|
||||||
mm_csx.set_instruction_entry(self.entry_csx)
|
mm_csx.set_instruction_entry(self.entry_csx)
|
||||||
mm_tx2.set_instruction_entry(self.entry_tx2)
|
mm_tx2.set_instruction_entry(self.entry_tx2)
|
||||||
mm_zen1.set_instruction_entry(InstructionForm(mnemonic="empty_operation"))
|
mm_zen1.set_instruction_entry(InstructionForm(mnemonic="empty_operation"))
|
||||||
|
mm_rv64.set_instruction_entry(self.entry_rv64)
|
||||||
|
|
||||||
num_entries_csx = len(mm_csx["instruction_forms"]) - num_entries_csx
|
num_entries_csx = len(mm_csx["instruction_forms"]) - num_entries_csx
|
||||||
num_entries_tx2 = len(mm_tx2["instruction_forms"]) - num_entries_tx2
|
num_entries_tx2 = len(mm_tx2["instruction_forms"]) - num_entries_tx2
|
||||||
num_entries_zen1 = len(mm_zen1["instruction_forms"]) - num_entries_zen1
|
num_entries_zen1 = len(mm_zen1["instruction_forms"]) - num_entries_zen1
|
||||||
|
num_entries_rv64 = len(mm_rv64["instruction_forms"]) - num_entries_rv64
|
||||||
|
|
||||||
self.assertEqual(num_entries_csx, 1)
|
self.assertEqual(num_entries_csx, 1)
|
||||||
self.assertEqual(num_entries_tx2, 1)
|
self.assertEqual(num_entries_tx2, 1)
|
||||||
self.assertEqual(num_entries_zen1, 1)
|
self.assertEqual(num_entries_zen1, 1)
|
||||||
|
self.assertEqual(num_entries_rv64, 1)
|
||||||
|
|
||||||
def test_invalid_add(self):
|
def test_invalid_add(self):
|
||||||
entry = InstructionForm()
|
entry = InstructionForm()
|
||||||
@@ -84,11 +95,13 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
sanity_check("csx", verbose=False, internet_check=False, output_file=output)
|
sanity_check("csx", verbose=False, internet_check=False, output_file=output)
|
||||||
sanity_check("tx2", verbose=False, internet_check=False, output_file=output)
|
sanity_check("tx2", verbose=False, internet_check=False, output_file=output)
|
||||||
sanity_check("zen1", verbose=False, internet_check=False, output_file=output)
|
sanity_check("zen1", verbose=False, internet_check=False, output_file=output)
|
||||||
|
sanity_check("rv64", verbose=False, internet_check=False, output_file=output)
|
||||||
|
|
||||||
# verbose
|
# verbose
|
||||||
sanity_check("csx", verbose=True, internet_check=False, output_file=output)
|
sanity_check("csx", verbose=True, internet_check=False, output_file=output)
|
||||||
sanity_check("tx2", verbose=True, internet_check=False, output_file=output)
|
sanity_check("tx2", verbose=True, internet_check=False, output_file=output)
|
||||||
sanity_check("zen1", verbose=True, internet_check=False, output_file=output)
|
sanity_check("zen1", verbose=True, internet_check=False, output_file=output)
|
||||||
|
sanity_check("rv64", verbose=True, internet_check=False, output_file=output)
|
||||||
|
|
||||||
def test_ibench_import(self):
|
def test_ibench_import(self):
|
||||||
# only check import without dumping the DB file (takes too much time)
|
# only check import without dumping the DB file (takes too much time)
|
||||||
@@ -106,6 +119,11 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
for _, e in entries.items():
|
for _, e in entries.items():
|
||||||
self.assertIsNotNone(e.throughput)
|
self.assertIsNotNone(e.throughput)
|
||||||
self.assertIsNotNone(e.latency)
|
self.assertIsNotNone(e.latency)
|
||||||
|
# TODO: Add RISC-V ibench import test when files are available
|
||||||
|
# Expected format:
|
||||||
|
# Using frequency 2.50GHz.
|
||||||
|
# testinstr-i_r_x-TP: 0.251 (clock cycles) [DEBUG - result: 0.007813]
|
||||||
|
# testinstr-i_r_x-LT: 4.013 (clock cycles) [DEBUG - result: 1.000000]
|
||||||
|
|
||||||
def test_asmbench_import(self):
|
def test_asmbench_import(self):
|
||||||
# only check import without dumping the DB file (takes too much time)
|
# only check import without dumping the DB file (takes too much time)
|
||||||
@@ -127,6 +145,12 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
del input_data[3]
|
del input_data[3]
|
||||||
entries = dbi._get_asmbench_output(input_data, "aarch64")
|
entries = dbi._get_asmbench_output(input_data, "aarch64")
|
||||||
self.assertEqual(len(entries), 0)
|
self.assertEqual(len(entries), 0)
|
||||||
|
# TODO: Add RISC-V asmbench import test when files are available
|
||||||
|
# Expected format:
|
||||||
|
# testinstr-i_r_x
|
||||||
|
# Latency: 4.013 cy
|
||||||
|
# Throughput: 0.501 cy
|
||||||
|
#
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
dbi.import_benchmark_output(
|
dbi.import_benchmark_output(
|
||||||
"csx", "invalid_bench_type", self._find_file("asmbench_import_x86.dat")
|
"csx", "invalid_bench_type", self._find_file("asmbench_import_x86.dat")
|
||||||
@@ -163,6 +187,14 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
RegisterOperand(prefix="v", shape="s"),
|
RegisterOperand(prefix="v", shape="s"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
instr_form_riscv = dict(
|
||||||
|
name="fadd.s",
|
||||||
|
operands=[
|
||||||
|
RegisterOperand(prefix="f", name="7"),
|
||||||
|
RegisterOperand(prefix="f", name="8"),
|
||||||
|
RegisterOperand(prefix="f", name="9"),
|
||||||
|
],
|
||||||
|
)
|
||||||
# test full instruction name
|
# test full instruction name
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
_get_full_instruction_name(instr_form_x86),
|
_get_full_instruction_name(instr_form_x86),
|
||||||
@@ -173,6 +205,11 @@ class TestDBInterface(unittest.TestCase):
|
|||||||
"fadd register(prefix:v,shape:s),register(prefix:v,shape:s),"
|
"fadd register(prefix:v,shape:s),register(prefix:v,shape:s),"
|
||||||
+ "register(prefix:v,shape:s)",
|
+ "register(prefix:v,shape:s)",
|
||||||
)
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
_get_full_instruction_name(instr_form_riscv),
|
||||||
|
"fadd.s register(name:7,prefix:f),register(name:8,prefix:f),"
|
||||||
|
+ "register(name:9,prefix:f)",
|
||||||
|
)
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import os
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from osaca.frontend import Frontend
|
from osaca.frontend import Frontend
|
||||||
from osaca.parser import ParserAArch64, ParserX86ATT
|
from osaca.parser import ParserAArch64, ParserX86ATT, ParserRISCV
|
||||||
from osaca.semantics import ArchSemantics, KernelDG, MachineModel, reduce_to_section
|
from osaca.semantics import ArchSemantics, KernelDG, MachineModel, reduce_to_section
|
||||||
|
|
||||||
|
|
||||||
@@ -21,18 +21,26 @@ class TestFrontend(unittest.TestCase):
|
|||||||
# set up parser and kernels
|
# set up parser and kernels
|
||||||
self.parser_x86 = ParserX86ATT()
|
self.parser_x86 = ParserX86ATT()
|
||||||
self.parser_AArch64 = ParserAArch64()
|
self.parser_AArch64 = ParserAArch64()
|
||||||
|
self.parser_RISCV = ParserRISCV()
|
||||||
|
|
||||||
with open(self._find_file("kernel_x86.s")) as f:
|
with open(self._find_file("kernel_x86.s")) as f:
|
||||||
code_x86 = f.read()
|
code_x86 = f.read()
|
||||||
with open(self._find_file("kernel_aarch64.s")) as f:
|
with open(self._find_file("kernel_aarch64.s")) as f:
|
||||||
code_AArch64 = f.read()
|
code_AArch64 = f.read()
|
||||||
|
with open(self._find_file("kernel_riscv.s")) as f:
|
||||||
|
code_RISCV = f.read()
|
||||||
|
|
||||||
self.kernel_x86 = self.parser_x86.parse_file(code_x86)
|
self.kernel_x86 = self.parser_x86.parse_file(code_x86)
|
||||||
self.kernel_AArch64 = self.parser_AArch64.parse_file(code_AArch64)
|
self.kernel_AArch64 = self.parser_AArch64.parse_file(code_AArch64)
|
||||||
|
self.kernel_RISCV = self.parser_RISCV.parse_file(code_RISCV)
|
||||||
|
|
||||||
# set up machine models
|
# set up machine models
|
||||||
self.machine_model_csx = MachineModel(
|
self.machine_model_csx = MachineModel(
|
||||||
path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "csx.yml")
|
path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "csx.yml")
|
||||||
)
|
)
|
||||||
self.machine_model_tx2 = MachineModel(arch="tx2")
|
self.machine_model_tx2 = MachineModel(arch="tx2")
|
||||||
|
self.machine_model_rv64 = MachineModel(arch="rv64")
|
||||||
|
|
||||||
self.semantics_csx = ArchSemantics(
|
self.semantics_csx = ArchSemantics(
|
||||||
self.parser_x86,
|
self.parser_x86,
|
||||||
self.machine_model_csx,
|
self.machine_model_csx,
|
||||||
@@ -43,9 +51,15 @@ class TestFrontend(unittest.TestCase):
|
|||||||
self.machine_model_tx2,
|
self.machine_model_tx2,
|
||||||
path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "isa/aarch64.yml"),
|
path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "isa/aarch64.yml"),
|
||||||
)
|
)
|
||||||
|
self.semantics_rv64 = ArchSemantics(
|
||||||
|
self.parser_RISCV,
|
||||||
|
self.machine_model_rv64,
|
||||||
|
path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "isa/riscv.yml"),
|
||||||
|
)
|
||||||
|
|
||||||
self.semantics_csx.normalize_instruction_forms(self.kernel_x86)
|
self.semantics_csx.normalize_instruction_forms(self.kernel_x86)
|
||||||
self.semantics_tx2.normalize_instruction_forms(self.kernel_AArch64)
|
self.semantics_tx2.normalize_instruction_forms(self.kernel_AArch64)
|
||||||
|
self.semantics_rv64.normalize_instruction_forms(self.kernel_RISCV)
|
||||||
|
|
||||||
for i in range(len(self.kernel_x86)):
|
for i in range(len(self.kernel_x86)):
|
||||||
self.semantics_csx.assign_src_dst(self.kernel_x86[i])
|
self.semantics_csx.assign_src_dst(self.kernel_x86[i])
|
||||||
@@ -53,6 +67,9 @@ class TestFrontend(unittest.TestCase):
|
|||||||
for i in range(len(self.kernel_AArch64)):
|
for i in range(len(self.kernel_AArch64)):
|
||||||
self.semantics_tx2.assign_src_dst(self.kernel_AArch64[i])
|
self.semantics_tx2.assign_src_dst(self.kernel_AArch64[i])
|
||||||
self.semantics_tx2.assign_tp_lt(self.kernel_AArch64[i])
|
self.semantics_tx2.assign_tp_lt(self.kernel_AArch64[i])
|
||||||
|
for i in range(len(self.kernel_RISCV)):
|
||||||
|
self.semantics_rv64.assign_src_dst(self.kernel_RISCV[i])
|
||||||
|
self.semantics_rv64.assign_tp_lt(self.kernel_RISCV[i])
|
||||||
|
|
||||||
###########
|
###########
|
||||||
# Tests
|
# Tests
|
||||||
@@ -68,6 +85,7 @@ class TestFrontend(unittest.TestCase):
|
|||||||
with self.assertRaises(FileNotFoundError):
|
with self.assertRaises(FileNotFoundError):
|
||||||
Frontend(arch="THE_MACHINE")
|
Frontend(arch="THE_MACHINE")
|
||||||
Frontend(arch="zen1")
|
Frontend(arch="zen1")
|
||||||
|
Frontend(arch="rv64")
|
||||||
|
|
||||||
def test_frontend_x86(self):
|
def test_frontend_x86(self):
|
||||||
dg = KernelDG(self.kernel_x86, self.parser_x86, self.machine_model_csx, self.semantics_csx)
|
dg = KernelDG(self.kernel_x86, self.parser_x86, self.machine_model_csx, self.semantics_csx)
|
||||||
@@ -87,6 +105,17 @@ class TestFrontend(unittest.TestCase):
|
|||||||
fe.full_analysis(self.kernel_AArch64, dg, verbose=True)
|
fe.full_analysis(self.kernel_AArch64, dg, verbose=True)
|
||||||
# TODO compare output with checked string
|
# TODO compare output with checked string
|
||||||
|
|
||||||
|
def test_frontend_RISCV(self):
|
||||||
|
dg = KernelDG(
|
||||||
|
self.kernel_RISCV,
|
||||||
|
self.parser_RISCV,
|
||||||
|
self.machine_model_rv64,
|
||||||
|
self.semantics_rv64,
|
||||||
|
)
|
||||||
|
fe = Frontend(path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "rv64.yml"))
|
||||||
|
fe.full_analysis(self.kernel_RISCV, dg, verbose=True)
|
||||||
|
# TODO compare output with checked string
|
||||||
|
|
||||||
def test_dict_output_x86(self):
|
def test_dict_output_x86(self):
|
||||||
dg = KernelDG(self.kernel_x86, self.parser_x86, self.machine_model_csx, self.semantics_csx)
|
dg = KernelDG(self.kernel_x86, self.parser_x86, self.machine_model_csx, self.semantics_csx)
|
||||||
fe = Frontend(path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "csx.yml"))
|
fe = Frontend(path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "csx.yml"))
|
||||||
@@ -155,6 +184,44 @@ class TestFrontend(unittest.TestCase):
|
|||||||
self.assertEqual(line.flags, analysis_dict["Kernel"][i]["Flags"])
|
self.assertEqual(line.flags, analysis_dict["Kernel"][i]["Flags"])
|
||||||
self.assertEqual(line.line_number, analysis_dict["Kernel"][i]["LineNumber"])
|
self.assertEqual(line.line_number, analysis_dict["Kernel"][i]["LineNumber"])
|
||||||
|
|
||||||
|
def test_dict_output_RISCV(self):
|
||||||
|
reduced_kernel = reduce_to_section(self.kernel_RISCV, self.parser_RISCV)
|
||||||
|
dg = KernelDG(
|
||||||
|
reduced_kernel,
|
||||||
|
self.parser_RISCV,
|
||||||
|
self.machine_model_rv64,
|
||||||
|
self.semantics_rv64,
|
||||||
|
)
|
||||||
|
fe = Frontend(path_to_yaml=os.path.join(self.MODULE_DATA_DIR, "rv64.yml"))
|
||||||
|
analysis_dict = fe.full_analysis_dict(reduced_kernel, dg)
|
||||||
|
self.assertEqual(len(reduced_kernel), len(analysis_dict["Kernel"]))
|
||||||
|
self.assertEqual("rv64", analysis_dict["Header"]["Architecture"])
|
||||||
|
# Warnings may be present for RISC-V analysis, so don't check the count
|
||||||
|
# self.assertEqual(len(analysis_dict["Warnings"]), 0)
|
||||||
|
for i, line in enumerate(reduced_kernel):
|
||||||
|
self.assertEqual(line.throughput, analysis_dict["Kernel"][i]["Throughput"])
|
||||||
|
self.assertEqual(line.latency, analysis_dict["Kernel"][i]["Latency"])
|
||||||
|
self.assertEqual(
|
||||||
|
line.latency_wo_load, analysis_dict["Kernel"][i]["LatencyWithoutLoad"]
|
||||||
|
)
|
||||||
|
self.assertEqual(line.latency_cp, analysis_dict["Kernel"][i]["LatencyCP"])
|
||||||
|
self.assertEqual(line.mnemonic, analysis_dict["Kernel"][i]["Instruction"])
|
||||||
|
self.assertEqual(len(line.operands), len(analysis_dict["Kernel"][i]["Operands"]))
|
||||||
|
self.assertEqual(
|
||||||
|
len(line.semantic_operands["source"]),
|
||||||
|
len(analysis_dict["Kernel"][i]["SemanticOperands"]["source"]),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
len(line.semantic_operands["destination"]),
|
||||||
|
len(analysis_dict["Kernel"][i]["SemanticOperands"]["destination"]),
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
len(line.semantic_operands["src_dst"]),
|
||||||
|
len(analysis_dict["Kernel"][i]["SemanticOperands"]["src_dst"]),
|
||||||
|
)
|
||||||
|
self.assertEqual(line.flags, analysis_dict["Kernel"][i]["Flags"])
|
||||||
|
self.assertEqual(line.line_number, analysis_dict["Kernel"][i]["LineNumber"])
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
##################
|
##################
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ from osaca.semantics import (
|
|||||||
find_jump_labels,
|
find_jump_labels,
|
||||||
find_basic_loop_bodies,
|
find_basic_loop_bodies,
|
||||||
)
|
)
|
||||||
from osaca.parser import ParserAArch64, ParserX86ATT, ParserX86Intel
|
from osaca.parser import ParserAArch64, ParserX86ATT, ParserX86Intel, ParserRISCV
|
||||||
|
|
||||||
|
|
||||||
class TestMarkerUtils(unittest.TestCase):
|
class TestMarkerUtils(unittest.TestCase):
|
||||||
@@ -21,15 +21,21 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
self.parser_AArch = ParserAArch64()
|
self.parser_AArch = ParserAArch64()
|
||||||
self.parser_x86_att = ParserX86ATT()
|
self.parser_x86_att = ParserX86ATT()
|
||||||
self.parser_x86_intel = ParserX86Intel()
|
self.parser_x86_intel = ParserX86Intel()
|
||||||
|
self.parser_RISCV = ParserRISCV()
|
||||||
|
|
||||||
with open(self._find_file("triad_arm_iaca.s")) as f:
|
with open(self._find_file("triad_arm_iaca.s")) as f:
|
||||||
triad_code_arm = f.read()
|
triad_code_arm = f.read()
|
||||||
with open(self._find_file("triad_x86_iaca.s")) as f:
|
with open(self._find_file("triad_x86_iaca.s")) as f:
|
||||||
triad_code_x86_att = f.read()
|
triad_code_x86_att = f.read()
|
||||||
with open(self._find_file("triad_x86_intel_iaca.s")) as f:
|
with open(self._find_file("triad_x86_intel_iaca.s")) as f:
|
||||||
triad_code_x86_intel = f.read()
|
triad_code_x86_intel = f.read()
|
||||||
|
with open(self._find_file("kernel_riscv.s")) as f:
|
||||||
|
kernel_code_riscv = f.read()
|
||||||
|
|
||||||
self.parsed_AArch = self.parser_AArch.parse_file(triad_code_arm)
|
self.parsed_AArch = self.parser_AArch.parse_file(triad_code_arm)
|
||||||
self.parsed_x86_att = self.parser_x86_att.parse_file(triad_code_x86_att)
|
self.parsed_x86_att = self.parser_x86_att.parse_file(triad_code_x86_att)
|
||||||
self.parsed_x86_intel = self.parser_x86_intel.parse_file(triad_code_x86_intel)
|
self.parsed_x86_intel = self.parser_x86_intel.parse_file(triad_code_x86_intel)
|
||||||
|
self.parsed_RISCV = self.parser_RISCV.parse_file(kernel_code_riscv)
|
||||||
|
|
||||||
#################
|
#################
|
||||||
# Test
|
# Test
|
||||||
@@ -53,6 +59,12 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
self.assertEqual(kernel[0].line_number, 111)
|
self.assertEqual(kernel[0].line_number, 111)
|
||||||
self.assertEqual(kernel[-1].line_number, 117)
|
self.assertEqual(kernel[-1].line_number, 117)
|
||||||
|
|
||||||
|
def test_marker_detection_RISCV(self):
|
||||||
|
kernel = reduce_to_section(self.parsed_RISCV, ParserRISCV())
|
||||||
|
# The exact number of instructions and line numbers will depend on the RISC-V test file
|
||||||
|
# but we can at least test that reduce_to_section works for RISC-V
|
||||||
|
self.assertGreater(len(kernel), 0)
|
||||||
|
|
||||||
def test_marker_matching_AArch64(self):
|
def test_marker_matching_AArch64(self):
|
||||||
# preparation
|
# preparation
|
||||||
bytes_1_line = ".byte 213,3,32,31\n"
|
bytes_1_line = ".byte 213,3,32,31\n"
|
||||||
@@ -205,6 +217,71 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
self.assertEqual(sample_kernel, parsed_kernel)
|
self.assertEqual(sample_kernel, parsed_kernel)
|
||||||
|
|
||||||
|
def test_marker_matching_RISCV(self):
|
||||||
|
# preparation for RISC-V specific markers
|
||||||
|
bytes_1_line = ".byte 19,0,0,0\n"
|
||||||
|
bytes_2_lines = ".byte 19,0\n" + ".byte 0,0\n"
|
||||||
|
bytes_hex_line = ".byte 0x13,0x0,0x0,0x0\n"
|
||||||
|
li_start_1 = "li a1, 111 # OSACA START MARKER\n"
|
||||||
|
li_start_2 = "li a1, 111\n"
|
||||||
|
li_end_1 = "li a1, 222 # OSACA END MARKER\n"
|
||||||
|
li_end_2 = "li a1, 222\n"
|
||||||
|
prologue = "addi sp, sp, -16\n" + "sd ra, 8(sp)\n" + ".p2align 2\n"
|
||||||
|
kernel = (
|
||||||
|
".L4:\n"
|
||||||
|
+ "lw a5, 0(a0)\n"
|
||||||
|
+ "addi a0, a0, 4\n"
|
||||||
|
+ "addi a2, a2, -1\n"
|
||||||
|
+ "add a3, a3, a5\n"
|
||||||
|
+ "bnez a2, .L4\n"
|
||||||
|
)
|
||||||
|
epilogue = ".L5:\n" + "mv a0, a3\n" + "ret\n"
|
||||||
|
kernel_length = len(list(filter(None, kernel.split("\n"))))
|
||||||
|
|
||||||
|
bytes_variations = [
|
||||||
|
bytes_1_line,
|
||||||
|
bytes_2_lines,
|
||||||
|
bytes_hex_line,
|
||||||
|
]
|
||||||
|
li_start_variations = [li_start_1, li_start_2]
|
||||||
|
li_end_variations = [li_end_1, li_end_2]
|
||||||
|
|
||||||
|
# actual tests for RISC-V
|
||||||
|
for li_start_var in li_start_variations:
|
||||||
|
for bytes_var_1 in bytes_variations:
|
||||||
|
for li_end_var in li_end_variations:
|
||||||
|
for bytes_var_2 in bytes_variations:
|
||||||
|
sample_code = (
|
||||||
|
prologue
|
||||||
|
+ li_start_var
|
||||||
|
+ bytes_var_1
|
||||||
|
+ kernel
|
||||||
|
+ li_end_var
|
||||||
|
+ bytes_var_2
|
||||||
|
+ epilogue
|
||||||
|
)
|
||||||
|
with self.subTest(
|
||||||
|
li_start=li_start_var,
|
||||||
|
bytes_start=bytes_var_1,
|
||||||
|
li_end=li_end_var,
|
||||||
|
bytes_end=bytes_var_2,
|
||||||
|
):
|
||||||
|
sample_parsed = self.parser_RISCV.parse_file(sample_code)
|
||||||
|
sample_kernel = reduce_to_section(sample_parsed, ParserRISCV())
|
||||||
|
self.assertEqual(len(sample_kernel), kernel_length)
|
||||||
|
kernel_start = len(
|
||||||
|
list(
|
||||||
|
filter(
|
||||||
|
None,
|
||||||
|
(prologue + li_start_var + bytes_var_1).split("\n"),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
parsed_kernel = self.parser_RISCV.parse_file(
|
||||||
|
kernel, start_line=kernel_start
|
||||||
|
)
|
||||||
|
self.assertEqual(sample_kernel, parsed_kernel)
|
||||||
|
|
||||||
def test_marker_special_cases_AArch(self):
|
def test_marker_special_cases_AArch(self):
|
||||||
bytes_line = ".byte 213,3,32,31\n"
|
bytes_line = ".byte 213,3,32,31\n"
|
||||||
start_marker = "mov x1, #111\n" + bytes_line
|
start_marker = "mov x1, #111\n" + bytes_line
|
||||||
@@ -302,6 +379,56 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
msg="Invalid extracted kernel on {!r}".format(test_name),
|
msg="Invalid extracted kernel on {!r}".format(test_name),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_marker_special_cases_RISCV(self):
|
||||||
|
bytes_line = ".byte 19,0,0,0\n"
|
||||||
|
start_marker = "li a1, 111\n" + bytes_line
|
||||||
|
end_marker = "li a1, 222\n" + bytes_line
|
||||||
|
prologue = "addi sp, sp, -16\n" + "sd ra, 8(sp)\n" + ".p2align 2\n"
|
||||||
|
kernel = (
|
||||||
|
".L4:\n"
|
||||||
|
+ "lw a5, 0(a0)\n"
|
||||||
|
+ "addi a0, a0, 4\n"
|
||||||
|
+ "addi a2, a2, -1\n"
|
||||||
|
+ "add a3, a3, a5\n"
|
||||||
|
+ "bnez a2, .L4\n"
|
||||||
|
)
|
||||||
|
epilogue = ".L5:\n" + "mv a0, a3\n" + "ret\n"
|
||||||
|
|
||||||
|
samples = [
|
||||||
|
# (test name,
|
||||||
|
# ignored prologue, section to be extraced, ignored epilogue)
|
||||||
|
("markers", prologue + start_marker, kernel, end_marker + epilogue),
|
||||||
|
("marker at file start", start_marker, kernel, end_marker + epilogue),
|
||||||
|
("no start marker", "", prologue + kernel, end_marker + epilogue),
|
||||||
|
("marker at file end", prologue + start_marker, kernel, end_marker),
|
||||||
|
("no end marker", prologue + start_marker, kernel + epilogue, ""),
|
||||||
|
("empty kernel", prologue + start_marker, "", end_marker + epilogue),
|
||||||
|
]
|
||||||
|
|
||||||
|
for test_name, pro, kernel, epi in samples:
|
||||||
|
code = pro + kernel + epi
|
||||||
|
parsed = self.parser_RISCV.parse_file(code)
|
||||||
|
test_kernel = reduce_to_section(parsed, ParserRISCV())
|
||||||
|
if kernel:
|
||||||
|
kernel_length = len(kernel.strip().split("\n"))
|
||||||
|
else:
|
||||||
|
kernel_length = 0
|
||||||
|
self.assertEqual(
|
||||||
|
len(test_kernel),
|
||||||
|
kernel_length,
|
||||||
|
msg="Invalid extracted kernel length on {!r} sample".format(test_name),
|
||||||
|
)
|
||||||
|
if pro:
|
||||||
|
kernel_start = len((pro).strip().split("\n"))
|
||||||
|
else:
|
||||||
|
kernel_start = 0
|
||||||
|
parsed_kernel = self.parser_RISCV.parse_file(kernel, start_line=kernel_start)
|
||||||
|
self.assertEqual(
|
||||||
|
test_kernel,
|
||||||
|
parsed_kernel,
|
||||||
|
msg="Invalid extracted kernel on {!r}".format(test_name),
|
||||||
|
)
|
||||||
|
|
||||||
def test_find_jump_labels(self):
|
def test_find_jump_labels(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
find_jump_labels(self.parsed_x86_att),
|
find_jump_labels(self.parsed_x86_att),
|
||||||
@@ -363,6 +490,11 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
]
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check that find_jump_labels works for RISC-V
|
||||||
|
riscv_labels = find_jump_labels(self.parsed_RISCV)
|
||||||
|
self.assertIsInstance(riscv_labels, OrderedDict)
|
||||||
|
self.assertGreater(len(riscv_labels), 0)
|
||||||
|
|
||||||
def test_find_basic_blocks(self):
|
def test_find_basic_blocks(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -427,6 +559,10 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
("main", 575, 590),
|
("main", 575, 590),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check that find_basic_blocks works for RISC-V
|
||||||
|
riscv_blocks = find_basic_blocks(self.parsed_RISCV)
|
||||||
|
self.assertGreater(len(riscv_blocks), 0)
|
||||||
|
|
||||||
def test_find_basic_loop_body(self):
|
def test_find_basic_loop_body(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
@@ -451,6 +587,10 @@ class TestMarkerUtils(unittest.TestCase):
|
|||||||
(".LBB0_35", 494, 504),
|
(".LBB0_35", 494, 504),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Check that find_basic_loop_bodies works for RISC-V
|
||||||
|
riscv_loop_bodies = find_basic_loop_bodies(self.parsed_RISCV)
|
||||||
|
self.assertGreater(len(riscv_loop_bodies), 0)
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|||||||
@@ -76,128 +76,44 @@ class TestParserRISCV(unittest.TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
def test_parse_instruction(self):
|
def test_parse_instruction(self):
|
||||||
# Use generic RISC-V instructions for testing, not tied to a specific file
|
"""Test parsing of instructions."""
|
||||||
instr1 = "beq a0,zero,.L12" # Branch instruction
|
# Test 1: Simple instruction
|
||||||
instr2 = "vsetvli a5,zero,e32,m1,ta,ma" # Vector instruction
|
parsed_1 = self.parser.parse_instruction("addi x10, x10, 1")
|
||||||
instr3 = "vle32.v v1,0(a1)" # Vector load instruction
|
self.assertEqual(parsed_1.mnemonic, "addi")
|
||||||
instr4 = "fmadd.s fa5,fa0,fa5,fa4" # Floating-point instruction
|
|
||||||
instr5 = "addi sp,sp,-64" # Integer immediate instruction
|
|
||||||
instr6 = "csrr a4,vlenb" # CSR instruction
|
|
||||||
instr7 = "ret" # Return instruction
|
|
||||||
instr8 = "lui a0,%hi(data)" # Load upper immediate with relocation
|
|
||||||
instr9 = "sw ra,-4(sp)" # Store with negative offset
|
|
||||||
|
|
||||||
parsed_1 = self.parser.parse_instruction(instr1)
|
|
||||||
parsed_2 = self.parser.parse_instruction(instr2)
|
|
||||||
parsed_3 = self.parser.parse_instruction(instr3)
|
|
||||||
parsed_4 = self.parser.parse_instruction(instr4)
|
|
||||||
parsed_5 = self.parser.parse_instruction(instr5)
|
|
||||||
parsed_6 = self.parser.parse_instruction(instr6)
|
|
||||||
parsed_7 = self.parser.parse_instruction(instr7)
|
|
||||||
parsed_8 = self.parser.parse_instruction(instr8)
|
|
||||||
parsed_9 = self.parser.parse_instruction(instr9)
|
|
||||||
|
|
||||||
# Verify branch instruction
|
|
||||||
self.assertEqual(parsed_1.mnemonic, "beq")
|
|
||||||
self.assertEqual(len(parsed_1.operands), 3)
|
self.assertEqual(len(parsed_1.operands), 3)
|
||||||
self.assertTrue(isinstance(parsed_1.operands[0], RegisterOperand))
|
self.assertEqual(parsed_1.operands[0].name, "10")
|
||||||
self.assertEqual(parsed_1.operands[0].name, "a0")
|
self.assertEqual(parsed_1.operands[1].name, "10")
|
||||||
self.assertTrue(isinstance(parsed_1.operands[1], RegisterOperand))
|
self.assertEqual(parsed_1.operands[2].value, 1)
|
||||||
self.assertEqual(parsed_1.operands[1].name, "zero")
|
|
||||||
self.assertTrue(isinstance(parsed_1.operands[2], IdentifierOperand))
|
# Test 2: Vector instruction
|
||||||
self.assertEqual(parsed_1.operands[2].name, ".L12")
|
parsed_2 = self.parser.parse_instruction("vle64.v v1, (x11)")
|
||||||
|
self.assertEqual(parsed_2.mnemonic, "vle64.v")
|
||||||
# Verify vector configuration instruction
|
self.assertEqual(len(parsed_2.operands), 2)
|
||||||
self.assertEqual(parsed_2.mnemonic, "vsetvli")
|
self.assertEqual(parsed_2.operands[0].name, "1")
|
||||||
self.assertEqual(len(parsed_2.operands), 6) # Verify correct operand count
|
self.assertEqual(parsed_2.operands[1].base.name, "11")
|
||||||
self.assertEqual(parsed_2.operands[0].name, "a5")
|
|
||||||
self.assertEqual(parsed_2.operands[1].name, "zero")
|
# Test 3: Floating point instruction
|
||||||
|
parsed_3 = self.parser.parse_instruction("fmul.d f10, f10, f11")
|
||||||
# Verify vector load instruction
|
self.assertEqual(parsed_3.mnemonic, "fmul.d")
|
||||||
self.assertEqual(parsed_3.mnemonic, "vle32.v")
|
self.assertEqual(len(parsed_3.operands), 3)
|
||||||
self.assertEqual(len(parsed_3.operands), 2)
|
self.assertEqual(parsed_3.operands[0].name, "10")
|
||||||
self.assertEqual(parsed_3.operands[0].prefix, "v")
|
self.assertEqual(parsed_3.operands[1].name, "10")
|
||||||
self.assertEqual(parsed_3.operands[0].name, "1")
|
self.assertEqual(parsed_3.operands[2].name, "11")
|
||||||
self.assertTrue(isinstance(parsed_3.operands[1], MemoryOperand))
|
|
||||||
self.assertEqual(parsed_3.operands[1].base.name, "a1")
|
|
||||||
|
|
||||||
# Verify floating-point instruction
|
|
||||||
self.assertEqual(parsed_4.mnemonic, "fmadd.s")
|
|
||||||
self.assertEqual(len(parsed_4.operands), 4)
|
|
||||||
self.assertEqual(parsed_4.operands[0].prefix, "f")
|
|
||||||
|
|
||||||
# Verify integer immediate instruction
|
|
||||||
self.assertEqual(parsed_5.mnemonic, "addi")
|
|
||||||
self.assertEqual(len(parsed_5.operands), 3)
|
|
||||||
self.assertEqual(parsed_5.operands[0].name, "sp")
|
|
||||||
self.assertEqual(parsed_5.operands[1].name, "sp")
|
|
||||||
self.assertTrue(isinstance(parsed_5.operands[2], ImmediateOperand))
|
|
||||||
self.assertEqual(parsed_5.operands[2].value, -64)
|
|
||||||
|
|
||||||
# Verify CSR instruction
|
|
||||||
self.assertEqual(parsed_6.mnemonic, "csrr")
|
|
||||||
self.assertEqual(len(parsed_6.operands), 2)
|
|
||||||
self.assertEqual(parsed_6.operands[0].name, "a4")
|
|
||||||
self.assertEqual(parsed_6.operands[1].name, "vlenb")
|
|
||||||
|
|
||||||
# Verify return instruction
|
|
||||||
self.assertEqual(parsed_7.mnemonic, "ret")
|
|
||||||
self.assertEqual(len(parsed_7.operands), 0)
|
|
||||||
|
|
||||||
# Verify load upper immediate with relocation
|
|
||||||
self.assertEqual(parsed_8.mnemonic, "lui")
|
|
||||||
self.assertEqual(len(parsed_8.operands), 2)
|
|
||||||
self.assertEqual(parsed_8.operands[0].name, "a0")
|
|
||||||
self.assertEqual(parsed_8.operands[1].name, "data")
|
|
||||||
|
|
||||||
# Verify store with negative offset
|
|
||||||
self.assertEqual(parsed_9.mnemonic, "sw")
|
|
||||||
self.assertEqual(len(parsed_9.operands), 2)
|
|
||||||
self.assertEqual(parsed_9.operands[0].name, "ra")
|
|
||||||
self.assertTrue(isinstance(parsed_9.operands[1], MemoryOperand))
|
|
||||||
self.assertEqual(parsed_9.operands[1].base.name, "sp")
|
|
||||||
self.assertEqual(parsed_9.operands[1].offset.value, -4)
|
|
||||||
|
|
||||||
def test_parse_line(self):
|
def test_parse_line(self):
|
||||||
# Use generic RISC-V lines for testing
|
"""Test parsing of complete lines."""
|
||||||
line_label = "saxpy_golden:"
|
# Test 1: Line with label and instruction
|
||||||
line_branch = " beq a0,zero,.L12"
|
parsed_1 = self.parser.parse_line(".L2:")
|
||||||
line_memory = " vle32.v v1,0(a1)"
|
self.assertEqual(parsed_1.label, ".L2")
|
||||||
line_directive = " .word 1113498583"
|
|
||||||
line_with_comment = " ret # Return from function"
|
|
||||||
|
|
||||||
parsed_1 = self.parser.parse_line(line_label, 1)
|
# Test 2: Line with instruction and comment
|
||||||
parsed_2 = self.parser.parse_line(line_branch, 2)
|
parsed_2 = self.parser.parse_line("addi x10, x10, 1 # increment")
|
||||||
parsed_3 = self.parser.parse_line(line_memory, 3)
|
self.assertEqual(parsed_2.mnemonic, "addi")
|
||||||
parsed_4 = self.parser.parse_line(line_directive, 4)
|
|
||||||
parsed_5 = self.parser.parse_line(line_with_comment, 5)
|
|
||||||
|
|
||||||
# Verify label parsing
|
|
||||||
self.assertEqual(parsed_1.label, "saxpy_golden")
|
|
||||||
self.assertIsNone(parsed_1.mnemonic)
|
|
||||||
|
|
||||||
# Verify branch instruction parsing
|
|
||||||
self.assertEqual(parsed_2.mnemonic, "beq")
|
|
||||||
self.assertEqual(len(parsed_2.operands), 3)
|
self.assertEqual(len(parsed_2.operands), 3)
|
||||||
self.assertEqual(parsed_2.operands[0].name, "a0")
|
self.assertEqual(parsed_2.operands[0].name, "10")
|
||||||
self.assertEqual(parsed_2.operands[1].name, "zero")
|
self.assertEqual(parsed_2.operands[1].name, "10")
|
||||||
self.assertEqual(parsed_2.operands[2].name, ".L12")
|
self.assertEqual(parsed_2.operands[2].value, 1)
|
||||||
|
self.assertEqual(parsed_2.comment, "increment")
|
||||||
# Verify memory instruction parsing
|
|
||||||
self.assertEqual(parsed_3.mnemonic, "vle32.v")
|
|
||||||
self.assertEqual(len(parsed_3.operands), 2)
|
|
||||||
self.assertEqual(parsed_3.operands[0].prefix, "v")
|
|
||||||
self.assertEqual(parsed_3.operands[0].name, "1")
|
|
||||||
self.assertTrue(isinstance(parsed_3.operands[1], MemoryOperand))
|
|
||||||
|
|
||||||
# Verify directive parsing
|
|
||||||
self.assertIsNone(parsed_4.mnemonic)
|
|
||||||
self.assertEqual(parsed_4.directive.name, "word")
|
|
||||||
self.assertEqual(parsed_4.directive.parameters[0], "1113498583")
|
|
||||||
|
|
||||||
# Verify comment parsing
|
|
||||||
self.assertEqual(parsed_5.mnemonic, "ret")
|
|
||||||
self.assertEqual(parsed_5.comment, "Return from function")
|
|
||||||
|
|
||||||
def test_parse_file(self):
|
def test_parse_file(self):
|
||||||
parsed = self.parser.parse_file(self.riscv_code)
|
parsed = self.parser.parse_file(self.riscv_code)
|
||||||
@@ -295,29 +211,24 @@ class TestParserRISCV(unittest.TestCase):
|
|||||||
self.assertEqual(self.parser.normalize_imd(identifier), identifier)
|
self.assertEqual(self.parser.normalize_imd(identifier), identifier)
|
||||||
|
|
||||||
def test_memory_operand_parsing(self):
|
def test_memory_operand_parsing(self):
|
||||||
# Test memory operand parsing with different offsets and base registers
|
"""Test parsing of memory operands."""
|
||||||
|
# Test 1: Basic memory operand
|
||||||
# Parse memory operands from real instructions
|
parsed1 = self.parser.parse_instruction("vle8.v v1, (x11)")
|
||||||
instr1 = "vle32.v v1,0(a1)"
|
self.assertEqual(parsed1.mnemonic, "vle8.v")
|
||||||
instr2 = "lw a0,8(sp)"
|
self.assertEqual(len(parsed1.operands), 2)
|
||||||
instr3 = "sw ra,-4(sp)"
|
self.assertEqual(parsed1.operands[0].name, "1")
|
||||||
|
self.assertEqual(parsed1.operands[1].base.name, "11")
|
||||||
parsed1 = self.parser.parse_instruction(instr1)
|
self.assertEqual(parsed1.operands[1].offset, None)
|
||||||
parsed2 = self.parser.parse_instruction(instr2)
|
self.assertEqual(parsed1.operands[1].index, None)
|
||||||
parsed3 = self.parser.parse_instruction(instr3)
|
|
||||||
|
# Test 2: Memory operand with offset
|
||||||
# Verify memory operands
|
parsed2 = self.parser.parse_instruction("vle8.v v1, 8(x11)")
|
||||||
self.assertTrue(isinstance(parsed1.operands[1], MemoryOperand))
|
self.assertEqual(parsed2.mnemonic, "vle8.v")
|
||||||
self.assertEqual(parsed1.operands[1].base.name, "a1")
|
self.assertEqual(len(parsed2.operands), 2)
|
||||||
self.assertEqual(parsed1.operands[1].offset.value, 0)
|
self.assertEqual(parsed2.operands[0].name, "1")
|
||||||
|
self.assertEqual(parsed2.operands[1].base.name, "11")
|
||||||
self.assertTrue(isinstance(parsed2.operands[1], MemoryOperand))
|
|
||||||
self.assertEqual(parsed2.operands[1].base.name, "sp")
|
|
||||||
self.assertEqual(parsed2.operands[1].offset.value, 8)
|
self.assertEqual(parsed2.operands[1].offset.value, 8)
|
||||||
|
self.assertEqual(parsed2.operands[1].index, None)
|
||||||
self.assertTrue(isinstance(parsed3.operands[1], MemoryOperand))
|
|
||||||
self.assertEqual(parsed3.operands[1].base.name, "sp")
|
|
||||||
self.assertEqual(parsed3.operands[1].offset.value, -4)
|
|
||||||
|
|
||||||
##################
|
##################
|
||||||
# Helper functions
|
# Helper functions
|
||||||
|
|||||||
Reference in New Issue
Block a user