Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions ci-tests/spike-ld.ld
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ENTRY (_entry)

SECTIONS {
. = 0x80000000;
.text : { *(.text) }
.data : { *(.data) }
}

39 changes: 39 additions & 0 deletions ci-tests/test-spike
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ riscv64-linux-gnu-gcc -static -O2 -o hello $CI/hello.c
riscv64-linux-gnu-gcc -static -O2 -o dummy-slliuw $CI/dummy-slliuw.c
riscv64-linux-gnu-gcc -static -O2 -o customcsr $CI/customcsr.c
riscv64-linux-gnu-gcc -static -O2 -o atomics $CI/atomics.c
riscv64-linux-gnu-gcc -static -nostdlib -o test-spiketama1s-ext -O0 -march=rv64gcv -mabi=lp64d -T $CI/spike-ld.ld $CI/test-spiketama1s-ext.S

# run snippy-based tests
wget https://github.com/syntacore/snippy/releases/download/snippy-2.1/snippy-x86_64-linux.tar.xz
Expand All @@ -46,6 +47,44 @@ g++ -std=c++2a -I$INSTALL/include -L$INSTALL/lib $CI/testlib.cc -lriscv -o /dev/
# run tests
time $INSTALL/bin/spike --isa=rv64gc $BUILD/pk/pk hello | grep "Hello, world! Pi is approximately 3.141588."
$INSTALL/bin/spike --log-commits --isa=rv64gc $BUILD/pk/pk atomics 2> /dev/null | grep "First atomic counter is 1000, second is 100"
$INSTALL/bin/spike -l --log-commits --isa=rv64gcv_xspiketama_xspikema1s_xspiketa1s test-spiketama1s-ext &> spike-all-fill1s.log
grep "v2 0x00000000ffffffffffffffff00000002" spike-all-fill1s.log
grep "v3 0xffffffff000000000000000000000003" spike-all-fill1s.log
grep "v4 0xffffffffffffffff0000000000000000" spike-all-fill1s.log
grep "v5 0x0000000000000000ffffffffffffffff" spike-all-fill1s.log
grep "v6 0x00000000000000000000000000000000" spike-all-fill1s.log
grep "v8 0x00000000000000000000000000000000" spike-all-fill1s.log
grep "v9 0x00000000000000000000000000000000" spike-all-fill1s.log
grep "v10 0xffffffffffffffff0000000000000000" spike-all-fill1s.log
grep "v11 0xffffffffffffffffffffffffffffffff" spike-all-fill1s.log
$INSTALL/bin/spike -l --log-commits --isa=rv64gcv_xspiketama_xspikema1s test-spiketama1s-ext &> spike-mask-fill1s.log
grep "v2 0x00000000ffffffffffffffff00000002" spike-mask-fill1s.log
grep "v3 0x00000000000000000000000000000003" spike-mask-fill1s.log
grep "v4 0xffffffffffffffff0000000000000000" spike-mask-fill1s.log
grep "v5 0x0000000000000000ffffffffffffffff" spike-mask-fill1s.log
grep "v6 0x00000000000000000000000000000000" spike-mask-fill1s.log
grep "v8 0x00000000000000000000000000000000" spike-mask-fill1s.log
grep "v9 0x00000000000000000000000000000000" spike-mask-fill1s.log
grep "v10 0x00000000000000000000000000000000" spike-mask-fill1s.log
$INSTALL/bin/spike -l --log-commits --isa=rv64gcv_xspiketama_xspiketa1s test-spiketama1s-ext &> spike-tail-fill1s.log
grep "v2 0x00000000000000000000000000000002" spike-tail-fill1s.log
grep "v3 0xffffffff000000000000000000000003" spike-tail-fill1s.log
grep "v4 0x00000000000000000000000000000000" spike-tail-fill1s.log
grep "v5 0x00000000000000000000000000000000" spike-tail-fill1s.log
grep "v6 0x00000000000000000000000000000000" spike-tail-fill1s.log
grep "v8 0x00000000000000000000000000000000" spike-tail-fill1s.log
grep "v9 0x00000000000000000000000000000000" spike-tail-fill1s.log
grep "v10 0xffffffffffffffff0000000000000000" spike-tail-fill1s.log
grep "v11 0xffffffffffffffffffffffffffffffff" spike-tail-fill1s.log
$INSTALL/bin/spike -l --log-commits --isa=rv64gcv test-spiketama1s-ext &> spike-undisturbed.log
grep "v2 0x00000000000000000000000000000002" spike-undisturbed.log
grep "v3 0x00000000000000000000000000000003" spike-undisturbed.log
grep "v4 0x00000000000000000000000000000000" spike-undisturbed.log
grep "v5 0x00000000000000000000000000000000" spike-undisturbed.log
grep "v6 0x00000000000000000000000000000000" spike-undisturbed.log
grep "v8 0x00000000000000000000000000000000" spike-undisturbed.log
grep "v9 0x00000000000000000000000000000000" spike-undisturbed.log
grep "v10 0x00000000000000000000000000000000" spike-undisturbed.log
LD_LIBRARY_PATH=$INSTALL/lib ./test-libriscv $BUILD/pk/pk hello | grep "Hello, world! Pi is approximately 3.141588."
LD_LIBRARY_PATH=$INSTALL/lib ./test-customext $BUILD/pk/pk dummy-slliuw | grep "Executed successfully"
LD_LIBRARY_PATH=$INSTALL/lib ./test-custom-csr $BUILD/pk/pk customcsr | grep "Executed successfully"
85 changes: 85 additions & 0 deletions ci-tests/test-spiketama1s-ext.S
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
.option norvc

.global _entry
.global fromhost
.global tohost

.text
_entry:
la t0, exception_handler
csrw mtvec, t0
csrr t1, mstatus
// Setting bit number 9 (mstatus.VS)
li t2, 1
slli t2, t2, 9
or t1, t1, t2
// Setting bit number 13 (mstatus.FS)
li t3, 1
slli t3, t3, 13
or t1, t1, t3
csrw mstatus, t1

//----------------------------MASK AGNOSTIC TEST-------------------------------
// Tail undisturbed, mask agnostic with VL = 3
vsetivli a0, 3, e32, m1, tu, ma
vmclr.m v0
// Mask v0 - 0b...001
vadd.vi v0, v0, 1
// Fourth element should be zero because of tu
// If mask fill 1s extension (xspikema1s) enable:
// Second and third elements should be 0xffffffff because of 001 mask
// v2 0x00000000ffffffffffffffff00000002
// If mask fill 1s extension (xspikema1s) disable:
// Second and third elements should be zero because of 001 mask
// v2 0x00000000000000000000000000000002
vadd.vv v2, v0, v0, v0.t

//----------------------------TAIL AGNOSTIC TEST-------------------------------
vsetivli a0, 3, e32, m1, ta, mu
// Second and third elements should be zero because of 001 mask with mu
// If tail fill 1s extension (xspiketa1s) enable:
// Fourth element should be 0xffffffff because of ta
// v3 0xffffffff000000000000000000000003
// If tail fill 1s extension (xspiketa1s) disable:
// Fourth element should be zero because of ta
// v3 0x00000000000000000000000000000003
vadd.vv v3, v2, v0, v0.t

//---------------------------MASK AGNOSTIC M4 TEST-----------------------------
vsetivli a0, 5, e64, m4, tu, ma
vmclr.m v0
// Mask v0 - 0b...11001
vadd.vi v0, v0, -7
vadd.vv v4, v4, v4, v0.t

//---------------------------TAIL AGNOSTIC M4 TEST-----------------------------
vsetivli a0, 5, e64, m4, ta, mu
// Mask v0 - 0b...11001
vadd.vv v8, v8, v8, v0.t

//---------------------------------END TESTING---------------------------------
la t0, exit
jalr t0

exception_handler:
csrr x10, mcause
// In case of breakpoint (Interrupt = 0, Exception code = 3) we finalize.
// Otherwise it's not the expected behavior and we go into an infinite loop.
li x11, 3
beq x10, x11, exit
j infinite_loop

exit:
li ra, 1
la sp, tohost
sd ra, 0(sp)

infinite_loop:
j infinite_loop

.balign 64
tohost:
.8byte 0x0
.balign 64
fromhost:
.8byte 0x0
14 changes: 14 additions & 0 deletions customext/agnostic.mk
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
customext_srcs += \
spikema1s.cc \
spiketa1s.cc \
spiketama.cc \
$(agnostic_rvv_gen_srcs) \

agnostic_riscv_insn_ext_v = \
vadd_vv \

agnostic_rvv_gen_srcs = $(addsuffix _agnostic.cc,$(agnostic_riscv_insn_ext_v))

$(agnostic_rvv_gen_srcs): %_agnostic.cc: $(src_dir)/riscv/insns/%.h $(src_dir)/customext/spiketama_insns.cc
sed 's/NAME/$(subst _agnostic.cc,,$@)/' $(src_dir)/customext/spiketama_insns.cc > $@

49 changes: 49 additions & 0 deletions customext/agnostic_macros.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#ifndef _RISCV_AGNOSTIC_MACROS_H
#define _RISCV_AGNOSTIC_MACROS_H

#include "decode_macros.h"
#include "insn_macros.h"

#define AGNOSTIC_RVV_PARAMS \
reg_t UNUSED vl = P.VU.vl->read(); \
reg_t UNUSED vstart = P.VU.vstart->read(); \
reg_t UNUSED sew = P.VU.vsew; \
reg_t rd_num_start = insn.rd(); \
reg_t rd_num = rd_num_start;

#define AGNOSTIC_VD_PARAM(x) \
type_sew_t<x>::type &vd = P.VU.elt<type_sew_t<x>::type>(rd_num, i, true); \
type_usew_t<x>::type all_ones = -1;

#define AGNOSTIC_SEW_SWITCH(BODY) \
do { \
if (sew == e8) { \
AGNOSTIC_VD_PARAM(e8); \
BODY; \
} else if (sew == e16) { \
AGNOSTIC_VD_PARAM(e16); \
BODY; \
} else if (sew == e32) { \
AGNOSTIC_VD_PARAM(e32); \
BODY; \
} else if (sew == e64) { \
AGNOSTIC_VD_PARAM(e64); \
BODY; \
} \
} while (0)

#define AGNOSTIC_LOOP_TAIL(BODY, TAIL_FROM, TAIL_TO) \
do { \
AGNOSTIC_RVV_PARAMS; \
for (reg_t i = (TAIL_FROM); i < (TAIL_TO); ++i) { \
AGNOSTIC_SEW_SWITCH(BODY); \
} \
} while (0)

#define AGNOSTIC_LOOP_BODY(BODY) AGNOSTIC_LOOP_TAIL(BODY, vstart, vl)

inline bool is_vadd_vv(insn_t insn) {
return (insn.bits() & MASK_VADD_VV) == MATCH_VADD_VV;
}

#endif
2 changes: 2 additions & 0 deletions customext/customext.mk.in
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ customext_srcs = \
cflush.cc \

customext_install_shared_lib = yes

include $(src_dir)/customext/agnostic.mk
51 changes: 51 additions & 0 deletions customext/spikema1s.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#include "agnostic_macros.h"
#include "extension.h"
#include "processor.h"

extern std::vector<insn_func_t> agnostic_postprocesses;

static reg_t mask_agnostic_fill1s(processor_t *p, insn_t insn, reg_t pc) {
// TODO: So far, only instruction vadd.vv is supported.
if (!is_vadd_vv(insn))
return pc;
// When vm==1 then instruction unmasked, therefore, the agnostic policy does
// not apply to any elements.
if (insn.v_vm())
return pc;
// When vma==0 then undisturbed policy is in effect.
if (p->VU.vma == 0)
return pc;

AGNOSTIC_LOOP_BODY({ // mask agnostic - fill 1s
if (!p->VU.mask_elt(0, i))
vd = all_ones;
});
return pc;
}

struct mask_agnostic_fill1s_t : public extension_t {
const char *name() const override { return "spikema1s"; }

mask_agnostic_fill1s_t() {}

std::vector<insn_desc_t> get_instructions(const processor_t &) override {
return {};
}

std::vector<disasm_insn_t *> get_disasms(const processor_t *) override {
return {};
}

void reset(processor_t &) override {
auto &insn_postprocesses = agnostic_postprocesses;
auto mask_func = std::find(insn_postprocesses.begin(),
insn_postprocesses.end(), &mask_agnostic_fill1s);
if (mask_func == insn_postprocesses.end())
insn_postprocesses.push_back(&mask_agnostic_fill1s);
}
};

REGISTER_EXTENSION(spikema1s, []() {
static mask_agnostic_fill1s_t ext;
return &ext;
})
60 changes: 60 additions & 0 deletions customext/spiketa1s.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "agnostic_macros.h"
#include "extension.h"
#include "processor.h"

extern std::vector<insn_func_t> agnostic_postprocesses;

static reg_t tail_agnostic_fill1s(processor_t *p, insn_t insn, reg_t pc) {
// TODO: So far, only instruction vadd.vv is supported.
if (!is_vadd_vv(insn))
return pc;
// When vta==0 then undisturbed policy is in effect.
if (p->VU.vta == 0)
return pc;
reg_t vl = p->VU.vl->read();
// rvv-spec-1.0: When vstart ≥ vl, there are no body elements, and no
// elements are updated in any destination vector register group, including
// that no tail elements are updated with agnostic values. As a consequence,
// when vl=0, no elements, including agnostic elements, are updated in the
// destination vector register group regardless of vstart.
// FIXME: Vstart is used here, which was reset to 0 as a result of executing
// this instruction, we need to get the old value of Vstart here.
if (p->VU.vstart->read() >= vl || vl == 0)
return pc;

reg_t tail_from = vl;
reg_t vl_one_reg = p->VU.VLEN / p->VU.vsew;
reg_t tail_to = std::max(p->VU.vlmax, vl_one_reg);

AGNOSTIC_LOOP_TAIL(
// tail agnostic - fill 1s
{ vd = all_ones; }, tail_from, tail_to);
return pc;
}

struct tail_agnostic_fill1s_t : public extension_t {
const char *name() const override { return "spiketa1s"; }

tail_agnostic_fill1s_t() {}

std::vector<insn_desc_t> get_instructions(const processor_t &) override {
return {};
}

std::vector<disasm_insn_t *> get_disasms(const processor_t *) override {
return {};
}

void reset(processor_t &) override {
auto &insn_postprocesses = agnostic_postprocesses;
auto tail_func = std::find(insn_postprocesses.begin(),
insn_postprocesses.end(), &tail_agnostic_fill1s);
if (tail_func == insn_postprocesses.end())
insn_postprocesses.push_back(&tail_agnostic_fill1s);
}
};

REGISTER_EXTENSION(spiketa1s, []() {
static tail_agnostic_fill1s_t ext;
return &ext;
})
62 changes: 62 additions & 0 deletions customext/spiketama.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
#include "extension.h"
#include "processor.h"

#include <algorithm>

std::vector<insn_func_t> agnostic_postprocesses;

struct agnostic_t : public extension_t {
const char *name() const override { return "spiketama"; }

agnostic_t() {}

std::vector<insn_desc_t> get_instructions(const processor_t &) override {
std::vector<insn_desc_t> agnostic_insn_list;

#define AGNOSTIC_DECLARE_INSN(name, match, mask) \
insn_bits_t name##_match = (match), name##_mask = (mask);

#include "spiketama_insns.h"
#undef AGNOSTIC_DECLARE_INSN

#define AGNOSTIC_DECLARE_INSN(name, match, mask) \
extern reg_t agnostic_fast_rv32i_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_fast_rv64i_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_fast_rv32e_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_fast_rv64e_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_logged_rv32i_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_logged_rv64i_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_logged_rv32e_##name(processor_t *, insn_t, reg_t); \
extern reg_t agnostic_logged_rv64e_##name(processor_t *, insn_t, reg_t);
#include "spiketama_insns.h"
#undef AGNOSTIC_DECLARE_INSN

#define AGNOSTIC_DECLARE_INSN(name, match, mask) \
{ \
insn_desc_t insn = {name##_match, \
name##_mask, \
agnostic_fast_rv32i_##name, \
agnostic_fast_rv64i_##name, \
agnostic_fast_rv32e_##name, \
agnostic_fast_rv64e_##name, \
agnostic_logged_rv32i_##name, \
agnostic_logged_rv64i_##name, \
agnostic_logged_rv32e_##name, \
agnostic_logged_rv64e_##name}; \
agnostic_insn_list.push_back(insn); \
}
#include "spiketama_insns.h"
#undef AGNOSTIC_DECLARE_INSN

return agnostic_insn_list;
}

std::vector<disasm_insn_t *> get_disasms(const processor_t *) override {
return {};
}
};

REGISTER_EXTENSION(spiketama, []() {
static agnostic_t ext;
return &ext;
})
Loading