aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
authorScott Johnson <scott.johnson@arilinc.com>2021-09-24 22:02:14 -0700
committerScott Johnson <scott.johnson@arilinc.com>2021-09-27 18:00:28 -0700
commit2b26a3cdf1cf391893a0a1a31815ac59d96ff05c (patch)
tree72bb3f45134ad2dce2c3135e9fa731fcdac6e8d7 /riscv
parentede97384f6f760a1a2c8b15f329e3e7c574a0301 (diff)
downloadspike-2b26a3cdf1cf391893a0a1a31815ac59d96ff05c.zip
spike-2b26a3cdf1cf391893a0a1a31815ac59d96ff05c.tar.gz
spike-2b26a3cdf1cf391893a0a1a31815ac59d96ff05c.tar.bz2
Convert frm & fflags to csr_t
Adds proper logging of fflags on FP arithmetic ops.
Diffstat (limited to 'riscv')
-rw-r--r--riscv/csrs.cc16
-rw-r--r--riscv/csrs.h9
-rw-r--r--riscv/decode.h12
-rw-r--r--riscv/insns/vfcvt_x_f_v.h6
-rw-r--r--riscv/insns/vfcvt_xu_f_v.h6
-rw-r--r--riscv/insns/vfmv_f_s.h2
-rw-r--r--riscv/insns/vfmv_s_f.h2
-rw-r--r--riscv/insns/vfncvt_x_f_w.h6
-rw-r--r--riscv/insns/vfncvt_xu_f_w.h6
-rw-r--r--riscv/insns/vfwcvt_x_f_v.h4
-rw-r--r--riscv/insns/vfwcvt_xu_f_v.h4
-rw-r--r--riscv/processor.cc38
-rw-r--r--riscv/processor.h4
13 files changed, 56 insertions, 59 deletions
diff --git a/riscv/csrs.cc b/riscv/csrs.cc
index 5060f48..461d4d1 100644
--- a/riscv/csrs.cc
+++ b/riscv/csrs.cc
@@ -1116,3 +1116,19 @@ void dcsr_csr_t::write_cause_and_prv(uint8_t cause, reg_t prv) noexcept {
this->prv = prv;
log_write();
}
+
+
+float_csr_t::float_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
+ masked_csr_t(proc, addr, mask, init) {
+}
+
+void float_csr_t::verify_permissions(insn_t insn, bool write) const {
+ require_fp;
+ if (!proc->extension_enabled('F'))
+ throw trap_illegal_instruction(insn.bits());
+}
+
+bool float_csr_t::unlogged_write(const reg_t val) noexcept {
+ dirty_fp_state;
+ return masked_csr_t::unlogged_write(val);
+}
diff --git a/riscv/csrs.h b/riscv/csrs.h
index fd20782..cf726a2 100644
--- a/riscv/csrs.h
+++ b/riscv/csrs.h
@@ -577,4 +577,13 @@ class dcsr_csr_t: public csr_t {
typedef std::shared_ptr<dcsr_csr_t> dcsr_csr_t_p;
+
+class float_csr_t: public masked_csr_t {
+ public:
+ float_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init);
+ virtual void verify_permissions(insn_t insn, bool write) const override;
+ protected:
+ virtual bool unlogged_write(const reg_t val) noexcept override;
+};
+
#endif
diff --git a/riscv/decode.h b/riscv/decode.h
index a54f1f0..2429ae7 100644
--- a/riscv/decode.h
+++ b/riscv/decode.h
@@ -234,7 +234,7 @@ private:
#define BRANCH_TARGET (pc + insn.sb_imm())
#define JUMP_TARGET (pc + insn.uj_imm())
#define RM ({ int rm = insn.rm(); \
- if(rm == 7) rm = STATE.frm; \
+ if(rm == 7) rm = STATE.frm->read(); \
if(rm > 4) throw trap_illegal_instruction(insn.bits()); \
rm; })
@@ -281,7 +281,7 @@ private:
#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
dirty_fp_state; \
- STATE.fflags |= softfloat_exceptionFlags; \
+ STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \
} \
softfloat_exceptionFlags = 0; })
@@ -1848,12 +1848,12 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
(P.VU.vsew == e32 && p->extension_enabled('F')) || \
(P.VU.vsew == e64 && p->extension_enabled('D'))); \
require_vector(true);\
- require(STATE.frm < 0x5);\
+ require(STATE.frm->read() < 0x5);\
reg_t vl = P.VU.vl; \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
- softfloat_roundingMode = STATE.frm;
+ softfloat_roundingMode = STATE.frm->read();
#define VI_VFP_LOOP_BASE \
VI_VFP_COMMON \
@@ -2264,12 +2264,12 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
require((P.VU.vsew == e8 && p->extension_enabled(EXT_ZFH)) || \
(P.VU.vsew == e16 && p->extension_enabled('F')) || \
(P.VU.vsew == e32 && p->extension_enabled('D'))); \
- require(STATE.frm < 0x5);\
+ require(STATE.frm->read() < 0x5);\
reg_t vl = P.VU.vl; \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
- softfloat_roundingMode = STATE.frm; \
+ softfloat_roundingMode = STATE.frm->read(); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP();
diff --git a/riscv/insns/vfcvt_x_f_v.h b/riscv/insns/vfcvt_x_f_v.h
index 01e5ca1..7e507a3 100644
--- a/riscv/insns/vfcvt_x_f_v.h
+++ b/riscv/insns/vfcvt_x_f_v.h
@@ -1,11 +1,11 @@
// vfcvt.x.f.v vd, vd2, vm
VI_VFP_VF_LOOP
({
- P.VU.elt<int16_t>(rd_num, i) = f16_to_i16(vs2, STATE.frm, true);
+ P.VU.elt<int16_t>(rd_num, i) = f16_to_i16(vs2, STATE.frm->read(), true);
},
{
- P.VU.elt<int32_t>(rd_num, i) = f32_to_i32(vs2, STATE.frm, true);
+ P.VU.elt<int32_t>(rd_num, i) = f32_to_i32(vs2, STATE.frm->read(), true);
},
{
- P.VU.elt<int64_t>(rd_num, i) = f64_to_i64(vs2, STATE.frm, true);
+ P.VU.elt<int64_t>(rd_num, i) = f64_to_i64(vs2, STATE.frm->read(), true);
})
diff --git a/riscv/insns/vfcvt_xu_f_v.h b/riscv/insns/vfcvt_xu_f_v.h
index 725cbda..51c00ca 100644
--- a/riscv/insns/vfcvt_xu_f_v.h
+++ b/riscv/insns/vfcvt_xu_f_v.h
@@ -1,11 +1,11 @@
// vfcvt.xu.f.v vd, vd2, vm
VI_VFP_VV_LOOP
({
- P.VU.elt<uint16_t>(rd_num, i) = f16_to_ui16(vs2, STATE.frm, true);
+ P.VU.elt<uint16_t>(rd_num, i) = f16_to_ui16(vs2, STATE.frm->read(), true);
},
{
- P.VU.elt<uint32_t>(rd_num, i) = f32_to_ui32(vs2, STATE.frm, true);
+ P.VU.elt<uint32_t>(rd_num, i) = f32_to_ui32(vs2, STATE.frm->read(), true);
},
{
- P.VU.elt<uint64_t>(rd_num, i) = f64_to_ui64(vs2, STATE.frm, true);
+ P.VU.elt<uint64_t>(rd_num, i) = f64_to_ui64(vs2, STATE.frm->read(), true);
})
diff --git a/riscv/insns/vfmv_f_s.h b/riscv/insns/vfmv_f_s.h
index 3309e47..06d93b2 100644
--- a/riscv/insns/vfmv_f_s.h
+++ b/riscv/insns/vfmv_f_s.h
@@ -4,7 +4,7 @@ require_fp;
require((P.VU.vsew == e16 && p->extension_enabled(EXT_ZFH)) ||
(P.VU.vsew == e32 && p->extension_enabled('F')) ||
(P.VU.vsew == e64 && p->extension_enabled('D')));
-require(STATE.frm < 0x5);
+require(STATE.frm->read() < 0x5);
reg_t rs2_num = insn.rs2();
uint64_t vs2_0 = 0;
diff --git a/riscv/insns/vfmv_s_f.h b/riscv/insns/vfmv_s_f.h
index d12fd91..4e7f82e 100644
--- a/riscv/insns/vfmv_s_f.h
+++ b/riscv/insns/vfmv_s_f.h
@@ -4,7 +4,7 @@ require_fp;
require((P.VU.vsew == e16 && p->extension_enabled(EXT_ZFH)) ||
(P.VU.vsew == e32 && p->extension_enabled('F')) ||
(P.VU.vsew == e64 && p->extension_enabled('D')));
-require(STATE.frm < 0x5);
+require(STATE.frm->read() < 0x5);
reg_t vl = P.VU.vl;
diff --git a/riscv/insns/vfncvt_x_f_w.h b/riscv/insns/vfncvt_x_f_w.h
index a342e3f..a8a6dfb 100644
--- a/riscv/insns/vfncvt_x_f_w.h
+++ b/riscv/insns/vfncvt_x_f_w.h
@@ -2,15 +2,15 @@
VI_VFP_CVT_SCALE
({
auto vs2 = P.VU.elt<float16_t>(rs2_num, i);
- P.VU.elt<int8_t>(rd_num, i, true) = f16_to_i8(vs2, STATE.frm, true);
+ P.VU.elt<int8_t>(rd_num, i, true) = f16_to_i8(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float32_t>(rs2_num, i);
- P.VU.elt<int16_t>(rd_num, i, true) = f32_to_i16(vs2, STATE.frm, true);
+ P.VU.elt<int16_t>(rd_num, i, true) = f32_to_i16(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float64_t>(rs2_num, i);
- P.VU.elt<int32_t>(rd_num, i, true) = f64_to_i32(vs2, STATE.frm, true);
+ P.VU.elt<int32_t>(rd_num, i, true) = f64_to_i32(vs2, STATE.frm->read(), true);
},
{
require(p->extension_enabled(EXT_ZFH));
diff --git a/riscv/insns/vfncvt_xu_f_w.h b/riscv/insns/vfncvt_xu_f_w.h
index 6fda694..bff733e 100644
--- a/riscv/insns/vfncvt_xu_f_w.h
+++ b/riscv/insns/vfncvt_xu_f_w.h
@@ -2,15 +2,15 @@
VI_VFP_CVT_SCALE
({
auto vs2 = P.VU.elt<float16_t>(rs2_num, i);
- P.VU.elt<uint8_t>(rd_num, i, true) = f16_to_ui8(vs2, STATE.frm, true);
+ P.VU.elt<uint8_t>(rd_num, i, true) = f16_to_ui8(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float32_t>(rs2_num, i);
- P.VU.elt<uint16_t>(rd_num, i, true) = f32_to_ui16(vs2, STATE.frm, true);
+ P.VU.elt<uint16_t>(rd_num, i, true) = f32_to_ui16(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float64_t>(rs2_num, i);
- P.VU.elt<uint32_t>(rd_num, i, true) = f64_to_ui32(vs2, STATE.frm, true);
+ P.VU.elt<uint32_t>(rd_num, i, true) = f64_to_ui32(vs2, STATE.frm->read(), true);
},
{
require(p->extension_enabled(EXT_ZFH));
diff --git a/riscv/insns/vfwcvt_x_f_v.h b/riscv/insns/vfwcvt_x_f_v.h
index 60ebbca..5e0c064 100644
--- a/riscv/insns/vfwcvt_x_f_v.h
+++ b/riscv/insns/vfwcvt_x_f_v.h
@@ -5,11 +5,11 @@ VI_VFP_CVT_SCALE
},
{
auto vs2 = P.VU.elt<float16_t>(rs2_num, i);
- P.VU.elt<int32_t>(rd_num, i, true) = f16_to_i32(vs2, STATE.frm, true);
+ P.VU.elt<int32_t>(rd_num, i, true) = f16_to_i32(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float32_t>(rs2_num, i);
- P.VU.elt<int64_t>(rd_num, i, true) = f32_to_i64(vs2, STATE.frm, true);
+ P.VU.elt<int64_t>(rd_num, i, true) = f32_to_i64(vs2, STATE.frm->read(), true);
},
{
;
diff --git a/riscv/insns/vfwcvt_xu_f_v.h b/riscv/insns/vfwcvt_xu_f_v.h
index a6a0591..f3243c8 100644
--- a/riscv/insns/vfwcvt_xu_f_v.h
+++ b/riscv/insns/vfwcvt_xu_f_v.h
@@ -5,11 +5,11 @@ VI_VFP_CVT_SCALE
},
{
auto vs2 = P.VU.elt<float16_t>(rs2_num, i);
- P.VU.elt<uint32_t>(rd_num, i, true) = f16_to_ui32(vs2, STATE.frm, true);
+ P.VU.elt<uint32_t>(rd_num, i, true) = f16_to_ui32(vs2, STATE.frm->read(), true);
},
{
auto vs2 = P.VU.elt<float32_t>(rs2_num, i);
- P.VU.elt<uint64_t>(rd_num, i, true) = f32_to_ui64(vs2, STATE.frm, true);
+ P.VU.elt<uint64_t>(rd_num, i, true) = f32_to_ui64(vs2, STATE.frm->read(), true);
},
{
;
diff --git a/riscv/processor.cc b/riscv/processor.cc
index b87d276..4727d0c 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -521,8 +521,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
csrmap[addr] = std::make_shared<pmpcfg_csr_t>(proc, addr);
}
- fflags = 0;
- frm = 0;
+ csrmap[CSR_FFLAGS] = fflags = std::make_shared<float_csr_t>(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0);
+ csrmap[CSR_FRM] = frm = std::make_shared<float_csr_t>(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0);
serialized = false;
#ifdef RISCV_ENABLE_COMMITLOG
@@ -977,18 +977,10 @@ void processor_t::set_csr(int which, reg_t val)
case CSR_SENTROPY:
es.set_sentropy(val);
break;
- case CSR_FFLAGS:
- dirty_fp_state;
- state.fflags = val & (FSR_AEXC >> FSR_AEXC_SHIFT);
- break;
- case CSR_FRM:
- dirty_fp_state;
- state.frm = val & (FSR_RD >> FSR_RD_SHIFT);
- break;
case CSR_FCSR:
dirty_fp_state;
- state.fflags = (val & FSR_AEXC) >> FSR_AEXC_SHIFT;
- state.frm = (val & FSR_RD) >> FSR_RD_SHIFT;
+ state.fflags->write((val & FSR_AEXC) >> FSR_AEXC_SHIFT);
+ state.frm->write((val & FSR_RD) >> FSR_RD_SHIFT);
break;
case CSR_VCSR:
dirty_vs_state;
@@ -1012,16 +1004,6 @@ void processor_t::set_csr(int which, reg_t val)
#if defined(RISCV_ENABLE_COMMITLOG)
switch (which)
{
- case CSR_FFLAGS:
- LOG_CSR(CSR_FFLAGS);
- break;
- case CSR_FRM:
- LOG_CSR(CSR_FRM);
- break;
- case CSR_FCSR:
- LOG_CSR(CSR_FFLAGS);
- LOG_CSR(CSR_FRM);
- break;
case CSR_VCSR:
LOG_CSR(CSR_VXSAT);
LOG_CSR(CSR_VXRM);
@@ -1071,21 +1053,11 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
if (!write)
break;
ret(es.get_sentropy());
- case CSR_FFLAGS:
- require_fp;
- if (!extension_enabled('F'))
- break;
- ret(state.fflags);
- case CSR_FRM:
- require_fp;
- if (!extension_enabled('F'))
- break;
- ret(state.frm);
case CSR_FCSR:
require_fp;
if (!extension_enabled('F'))
break;
- ret((state.fflags << FSR_AEXC_SHIFT) | (state.frm << FSR_RD_SHIFT));
+ ret((state.fflags->read() << FSR_AEXC_SHIFT) | (state.frm->read() << FSR_RD_SHIFT));
case CSR_VCSR:
require_vector_vs;
if (!extension_enabled('V'))
diff --git a/riscv/processor.h b/riscv/processor.h
index a9b75fd..fd16812 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -199,8 +199,8 @@ struct state_t
static const int max_pmp = 16;
pmpaddr_csr_t_p pmpaddr[max_pmp];
- uint32_t fflags;
- uint32_t frm;
+ csr_t_p fflags;
+ csr_t_p frm;
bool serialized; // whether timer CSRs are in a well-defined state
// When true, execute a single instruction and then enter debug mode. This