Browse Source

Merge pull request #816 from scottj97/fp-csrs

Convert floating-point CSRs to csr_t
pull/822/head
Andrew Waterman 5 years ago
committed by GitHub
parent
commit
6d9fb18850
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      riscv/csrs.cc
  2. 26
      riscv/csrs.h
  3. 13
      riscv/decode.h
  4. 6
      riscv/insns/vfcvt_x_f_v.h
  5. 6
      riscv/insns/vfcvt_xu_f_v.h
  6. 2
      riscv/insns/vfmv_f_s.h
  7. 2
      riscv/insns/vfmv_s_f.h
  8. 6
      riscv/insns/vfncvt_x_f_w.h
  9. 6
      riscv/insns/vfncvt_xu_f_w.h
  10. 4
      riscv/insns/vfwcvt_x_f_v.h
  11. 4
      riscv/insns/vfwcvt_xu_f_v.h
  12. 47
      riscv/processor.cc
  13. 4
      riscv/processor.h

40
riscv/csrs.cc

@ -1116,3 +1116,43 @@ 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);
}
composite_csr_t::composite_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb):
csr_t(proc, addr),
upper_csr(upper_csr),
lower_csr(lower_csr),
upper_lsb(upper_lsb) {
}
void composite_csr_t::verify_permissions(insn_t insn, bool write) const {
// It is reasonable to assume that either underlying CSR will have
// the same permissions as this composite.
upper_csr->verify_permissions(insn, write);
}
reg_t composite_csr_t::read() const noexcept {
return (upper_csr->read() << upper_lsb) | lower_csr->read();
}
bool composite_csr_t::unlogged_write(const reg_t val) noexcept {
upper_csr->write(val >> upper_lsb);
lower_csr->write(val);
return false; // logging is done only by the underlying CSRs
}

26
riscv/csrs.h

@ -577,4 +577,30 @@ 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;
};
// For a CSR like FCSR, that is actually a view into multiple
// underlying registers.
class composite_csr_t: public csr_t {
public:
// We assume the lower_csr maps to bit 0.
composite_csr_t(processor_t* const proc, const reg_t addr, csr_t_p upper_csr, csr_t_p lower_csr, const unsigned upper_lsb);
virtual void verify_permissions(insn_t insn, bool write) const override;
virtual reg_t read() const noexcept override;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
private:
csr_t_p upper_csr;
csr_t_p lower_csr;
const unsigned upper_lsb;
};
#endif

13
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; })
@ -280,8 +280,7 @@ private:
#define require_vm do { if (insn.v_vm() == 0) require(insn.rd() != 0);} while(0);
#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 +1847,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 +2263,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();

6
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);
})

6
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);
})

2
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;

2
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;

6
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));

6
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));

4
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);
},
{
;

4
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);
},
{
;

47
riscv/processor.cc

@ -521,8 +521,10 @@ 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);
assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0
csrmap[CSR_FCSR] = std::make_shared<composite_csr_t>(proc, CSR_FFLAGS, frm, fflags, FSR_RD_SHIFT);
serialized = false;
#ifdef RISCV_ENABLE_COMMITLOG
@ -960,7 +962,7 @@ void processor_t::set_csr(int which, reg_t val)
{
#if defined(RISCV_ENABLE_COMMITLOG)
#define LOG_CSR(rd) \
STATE.log_reg_write[((which) << 4) | 4] = {get_csr(rd), 0};
STATE.log_reg_write[((rd) << 4) | 4] = {get_csr(rd), 0};
#else
#define LOG_CSR(rd)
#endif
@ -977,19 +979,6 @@ 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;
break;
case CSR_VCSR:
dirty_vs_state;
VU.vxsat = (val & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT;
@ -1012,17 +1001,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);
LOG_CSR(CSR_FCSR);
break;
case CSR_VCSR:
LOG_CSR(CSR_VXSAT);
LOG_CSR(CSR_VXRM);
@ -1072,21 +1050,6 @@ 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));
case CSR_VCSR:
require_vector_vs;
if (!extension_enabled('V'))

4
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

Loading…
Cancel
Save