Browse Source

Merge pull request #821 from scottj97/vector-csrs

Convert vector CSRs to csr_t -- completes refactoring of CSRs
pull/822/head
Andrew Waterman 5 years ago
committed by GitHub
parent
commit
583bd1e8b7
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 40
      riscv/csrs.cc
  2. 16
      riscv/csrs.h
  3. 148
      riscv/decode.h
  4. 2
      riscv/execute.cc
  5. 2
      riscv/insns/vcompress_vm.h
  6. 8
      riscv/insns/vcpop_m.h
  7. 8
      riscv/insns/vfirst_m.h
  8. 8
      riscv/insns/vfmerge_vfm.h
  9. 2
      riscv/insns/vfmv_f_s.h
  10. 6
      riscv/insns/vfmv_s_f.h
  11. 8
      riscv/insns/vfmv_v_f.h
  12. 6
      riscv/insns/vid_v.h
  13. 4
      riscv/insns/viota_m.h
  14. 6
      riscv/insns/vmsbf_m.h
  15. 6
      riscv/insns/vmsif_m.h
  16. 6
      riscv/insns/vmsof_m.h
  17. 6
      riscv/insns/vmv_s_x.h
  18. 2
      riscv/insns/vmv_x_s.h
  19. 8
      riscv/insns/vmvnfr_v.h
  20. 4
      riscv/insns/vnclip_wi.h
  21. 4
      riscv/insns/vnclip_wv.h
  22. 4
      riscv/insns/vnclip_wx.h
  23. 2
      riscv/insns/vnclipu_wi.h
  24. 2
      riscv/insns/vnclipu_wv.h
  25. 2
      riscv/insns/vnclipu_wx.h
  26. 2
      riscv/insns/vrgather_vi.h
  27. 2
      riscv/insns/vsadd_vi.h
  28. 3
      riscv/insns/vsadd_vv.h
  29. 2
      riscv/insns/vsadd_vx.h
  30. 2
      riscv/insns/vsaddu_vi.h
  31. 2
      riscv/insns/vsaddu_vv.h
  32. 2
      riscv/insns/vsaddu_vx.h
  33. 2
      riscv/insns/vslideup_vi.h
  34. 2
      riscv/insns/vslideup_vx.h
  35. 2
      riscv/insns/vsmul_vv.h
  36. 2
      riscv/insns/vsmul_vx.h
  37. 2
      riscv/insns/vssub_vv.h
  38. 2
      riscv/insns/vssub_vx.h
  39. 2
      riscv/insns/vssubu_vv.h
  40. 2
      riscv/insns/vssubu_vx.h
  41. 155
      riscv/processor.cc
  42. 27
      riscv/processor.h

40
riscv/csrs.cc

@ -33,7 +33,9 @@ void csr_t::verify_permissions(insn_t insn, bool write) const {
(csr_priv == PRV_HS && !proc->extension_enabled('H')))
throw trap_illegal_instruction(insn.bits());
if ((write && csr_read_only) || priv < csr_priv) {
if (write && csr_read_only)
throw trap_illegal_instruction(insn.bits());
if (priv < csr_priv) {
if (state->v && csr_priv <= PRV_HS)
throw trap_virtual_instruction(insn.bits());
throw trap_illegal_instruction(insn.bits());
@ -1075,7 +1077,15 @@ void dpc_csr_t::verify_permissions(insn_t insn, bool write) const {
dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr):
csr_t(proc, addr) {
csr_t(proc, addr),
prv(0),
step(false),
ebreakm(false),
ebreakh(false),
ebreaks(false),
ebreaku(false),
halt(false),
cause(0) {
}
void dcsr_csr_t::verify_permissions(insn_t insn, bool write) const {
@ -1177,3 +1187,29 @@ bool sentropy_csr_t::unlogged_write(const reg_t val) noexcept {
proc->es.set_sentropy(val);
return true;
}
vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init):
basic_csr_t(proc, addr, init),
mask(mask) {
}
void vector_csr_t::verify_permissions(insn_t insn, bool write) const {
require_vector_vs;
if (!proc->extension_enabled('V'))
throw trap_illegal_instruction(insn.bits());
basic_csr_t::verify_permissions(insn, write);
}
void vector_csr_t::write_raw(const reg_t val) noexcept {
const bool success = basic_csr_t::unlogged_write(val);
if (success)
log_write();
}
bool vector_csr_t::unlogged_write(const reg_t val) noexcept {
if (mask == 0) return false;
dirty_vs_state;
return basic_csr_t::unlogged_write(val & mask);
}

16
riscv/csrs.h

@ -614,4 +614,20 @@ class sentropy_csr_t: public csr_t {
};
class vector_csr_t: public basic_csr_t {
public:
vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init=0);
virtual void verify_permissions(insn_t insn, bool write) const override;
// Write without regard to mask, and without touching mstatus.VS
void write_raw(const reg_t val) noexcept;
protected:
virtual bool unlogged_write(const reg_t val) noexcept override;
private:
reg_t mask;
};
typedef std::shared_ptr<vector_csr_t> vector_csr_t_p;
#endif

148
riscv/decode.h

@ -258,7 +258,7 @@ private:
require_extension('V'); \
require(!P.VU.vill); \
if (alu && !P.VU.vstart_alu) \
require(P.VU.vstart == 0); \
require(P.VU.vstart->read() == 0); \
WRITE_VSTATUS; \
dirty_vs_state; \
} while (0);
@ -267,7 +267,7 @@ private:
require_vector_vs; \
require_extension('V'); \
if (alu && !P.VU.vstart_alu) \
require(P.VU.vstart == 0); \
require(P.VU.vstart->read() == 0); \
if (is_log) \
WRITE_VSTATUS; \
dirty_vs_state; \
@ -368,11 +368,7 @@ inline freg_t f128_negate(freg_t a)
#define validate_csr(which, write) ({ \
if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \
STATE.serialized = false; \
/* disallow writes to read-only CSRs */ \
unsigned csr_read_only = get_field((which), 0xC00) == 3; \
if ((write) && csr_read_only) \
throw trap_illegal_instruction(insn.bits()); \
/* other permissions checks occur in get_csr */ \
/* permissions check occurs in get_csr */ \
(which); })
/* For debug only. This will fail if the native machine's float types are not IEEE */
@ -431,7 +427,7 @@ inline long double to_f(float128_t f){long double r; memcpy(&r, &f, sizeof(r));
#define VI_ELEMENT_SKIP(inx) \
if (inx >= vl) { \
continue; \
} else if (inx < P.VU.vstart) { \
} else if (inx < P.VU.vstart->read()) { \
continue; \
} else { \
VI_LOOP_ELEMENT_SKIP(); \
@ -598,7 +594,7 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
require(P.VU.vsew * 2 <= P.VU.ELEN); \
} \
require_align(insn.rs2(), P.VU.vflmul); \
require(P.VU.vstart == 0); \
require(P.VU.vstart->read() == 0); \
#define VI_CHECK_SLIDE(is_over) \
require_align(insn.rs2(), P.VU.vflmul); \
@ -614,12 +610,12 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
#define VI_GENERAL_LOOP_BASE \
require(P.VU.vsew >= e8 && P.VU.vsew <= e64); \
require_vector(true);\
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t sew = P.VU.vsew; \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
for (reg_t i=P.VU.vstart; i<vl; ++i){
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){
#define VI_LOOP_BASE \
VI_GENERAL_LOOP_BASE \
@ -627,24 +623,24 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
#define VI_LOOP_END \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LOOP_REDUCTION_END(x) \
} \
if (vl > 0) { \
vd_0_des = vd_0_res; \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LOOP_CMP_BASE \
require(P.VU.vsew >= e8 && P.VU.vsew <= e64); \
require_vector(true);\
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t sew = P.VU.vsew; \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP(); \
uint64_t mmask = UINT64_C(1) << mpos; \
uint64_t &vdi = P.VU.elt<uint64_t>(insn.rd(), midx, true); \
@ -653,13 +649,13 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
#define VI_LOOP_CMP_END \
vdi = (vdi & ~mmask) | (((res) << mpos) & mmask); \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LOOP_MASK(op) \
require(P.VU.vsew <= e64); \
require_vector(true);\
reg_t vl = P.VU.vl; \
for (reg_t i = P.VU.vstart; i < vl; ++i) { \
reg_t vl = P.VU.vl->read(); \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
int midx = i / 64; \
int mpos = i % 64; \
uint64_t mmask = UINT64_C(1) << mpos; \
@ -668,7 +664,7 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
uint64_t &res = P.VU.elt<uint64_t>(insn.rd(), midx, true); \
res = (res & ~mmask) | ((op) & (1ULL << mpos)); \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LOOP_NSHIFT_BASE \
VI_GENERAL_LOOP_BASE; \
@ -949,13 +945,13 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
// reduction loop - signed
#define VI_LOOP_REDUCTION_BASE(x) \
require(x >= e8 && x <= e64); \
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
auto &vd_0_des = P.VU.elt<type_sew_t<x>::type>(rd_num, 0, true); \
auto vd_0_res = P.VU.elt<type_sew_t<x>::type>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP(); \
auto vs2 = P.VU.elt<type_sew_t<x>::type>(rs2_num, i); \
@ -980,13 +976,13 @@ static inline bool is_aligned(const unsigned val, const unsigned pos)
// reduction loop - unsgied
#define VI_ULOOP_REDUCTION_BASE(x) \
require(x >= e8 && x <= e64); \
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
auto &vd_0_des = P.VU.elt<type_usew_t<x>::type>(rd_num, 0, true); \
auto vd_0_res = P.VU.elt<type_usew_t<x>::type>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP(); \
auto vs2 = P.VU.elt<type_usew_t<x>::type>(rs2_num, i);
@ -1299,13 +1295,13 @@ VI_LOOP_END
// wide reduction loop - signed
#define VI_LOOP_WIDE_REDUCTION_BASE(sew1, sew2) \
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
auto &vd_0_des = P.VU.elt<type_sew_t<sew2>::type>(rd_num, 0, true); \
auto vd_0_res = P.VU.elt<type_sew_t<sew2>::type>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP(); \
auto vs2 = P.VU.elt<type_sew_t<sew1>::type>(rs2_num, i);
@ -1327,13 +1323,13 @@ VI_LOOP_END
// wide reduction loop - unsigned
#define VI_ULOOP_WIDE_REDUCTION_BASE(sew1, sew2) \
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
auto &vd_0_des = P.VU.elt<type_usew_t<sew2>::type>(rd_num, 0, true); \
auto vd_0_res = P.VU.elt<type_usew_t<sew2>::type>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i) { \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
auto vs2 = P.VU.elt<type_usew_t<sew1>::type>(rs2_num, i);
@ -1521,7 +1517,7 @@ VI_LOOP_END
#define VI_DUPLICATE_VREG(reg_num, idx_sew) \
reg_t index[P.VU.vlmax]; \
for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl->read() != 0; ++i) { \
switch(idx_sew) { \
case e8: \
index[i] = P.VU.elt<uint8_t>(reg_num, i); \
@ -1540,25 +1536,25 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
#define VI_LD(stride, offset, elt_width, is_mask_ldst) \
const reg_t nf = insn.v_nf() + 1; \
const reg_t vl = is_mask_ldst ? ((P.VU.vl + 7) / 8) : P.VU.vl; \
const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vd = insn.rd(); \
VI_CHECK_LOAD(elt_width, is_mask_ldst); \
for (reg_t i = 0; i < vl; ++i) { \
VI_ELEMENT_SKIP(i); \
VI_STRIP(i); \
P.VU.vstart = i; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
elt_width##_t val = MMU.load_##elt_width( \
baseAddr + (stride) + (offset) * sizeof(elt_width##_t)); \
P.VU.elt<elt_width##_t>(vd + fn * emul, vreg_inx, true) = val; \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LD_INDEX(elt_width, is_seg) \
const reg_t nf = insn.v_nf() + 1; \
const reg_t vl = P.VU.vl; \
const reg_t vl = P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vd = insn.rd(); \
if (!is_seg) \
@ -1568,7 +1564,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
for (reg_t i = 0; i < vl; ++i) { \
VI_ELEMENT_SKIP(i); \
VI_STRIP(i); \
P.VU.vstart = i; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
switch(P.VU.vsew){ \
case e8: \
@ -1590,29 +1586,29 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
} \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_ST(stride, offset, elt_width, is_mask_ldst) \
const reg_t nf = insn.v_nf() + 1; \
const reg_t vl = is_mask_ldst ? ((P.VU.vl + 7) / 8) : P.VU.vl; \
const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vs3 = insn.rd(); \
VI_CHECK_STORE(elt_width, is_mask_ldst); \
for (reg_t i = 0; i < vl; ++i) { \
VI_STRIP(i) \
VI_ELEMENT_SKIP(i); \
P.VU.vstart = i; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
elt_width##_t val = P.VU.elt<elt_width##_t>(vs3 + fn * emul, vreg_inx); \
MMU.store_##elt_width( \
baseAddr + (stride) + (offset) * sizeof(elt_width##_t), val); \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_ST_INDEX(elt_width, is_seg) \
const reg_t nf = insn.v_nf() + 1; \
const reg_t vl = P.VU.vl; \
const reg_t vl = P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vs3 = insn.rd(); \
if (!is_seg) \
@ -1622,7 +1618,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
for (reg_t i = 0; i < vl; ++i) { \
VI_STRIP(i) \
VI_ELEMENT_SKIP(i); \
P.VU.vstart = i; \
P.VU.vstart->write(i); \
for (reg_t fn = 0; fn < nf; ++fn) { \
switch (P.VU.vsew) { \
case e8: \
@ -1644,17 +1640,17 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
} \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_LDST_FF(elt_width) \
const reg_t nf = insn.v_nf() + 1; \
const reg_t sew = p->VU.vsew; \
const reg_t vl = p->VU.vl; \
const reg_t vl = p->VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t rd_num = insn.rd(); \
VI_CHECK_LOAD(elt_width, false); \
bool early_stop = false; \
for (reg_t i = p->VU.vstart; i < vl; ++i) { \
for (reg_t i = p->VU.vstart->read(); i < vl; ++i) { \
VI_STRIP(i); \
VI_ELEMENT_SKIP(i); \
\
@ -1668,7 +1664,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
throw; /* Only take exception on zeroth element */ \
/* Reduce VL if an exception occurs on a later element */ \
early_stop = true; \
P.VU.vl = i; \
P.VU.vl->write_raw(i); \
break; \
} \
p->VU.elt<elt_width##_t>(rd_num + fn * emul, vreg_inx, true) = val; \
@ -1678,7 +1674,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
break; \
} \
} \
p->VU.vstart = 0;
p->VU.vstart->write(0);
#define VI_LD_WHOLE(elt_width) \
require_vector_novtype(true, false); \
@ -1688,24 +1684,24 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
require_align(vd, len); \
const reg_t elt_per_reg = P.VU.vlenb / sizeof(elt_width ## _t); \
const reg_t size = len * elt_per_reg; \
if (P.VU.vstart < size) { \
reg_t i = P.VU.vstart / elt_per_reg; \
reg_t off = P.VU.vstart % elt_per_reg; \
if (P.VU.vstart->read() < size) { \
reg_t i = P.VU.vstart->read() / elt_per_reg; \
reg_t off = P.VU.vstart->read() % elt_per_reg; \
if (off) { \
for (reg_t pos = off; pos < elt_per_reg; ++pos) { \
auto val = MMU.load_## elt_width(baseAddr + \
P.VU.vstart * sizeof(elt_width ## _t)); \
P.VU.vstart->read() * sizeof(elt_width ## _t)); \
P.VU.elt<elt_width ## _t>(vd + i, pos, true) = val; \
P.VU.vstart++; \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
++i; \
} \
for (; i < len; ++i) { \
for (reg_t pos = 0; pos < elt_per_reg; ++pos) { \
auto val = MMU.load_## elt_width(baseAddr + \
P.VU.vstart * sizeof(elt_width ## _t)); \
P.VU.vstart->read() * sizeof(elt_width ## _t)); \
P.VU.elt<elt_width ## _t>(vd + i, pos, true) = val; \
P.VU.vstart++; \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
} \
} \
@ -1719,26 +1715,26 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
require_align(vs3, len); \
const reg_t size = len * P.VU.vlenb; \
\
if (P.VU.vstart < size) { \
reg_t i = P.VU.vstart / P.VU.vlenb; \
reg_t off = P.VU.vstart % P.VU.vlenb; \
if (P.VU.vstart->read() < size) { \
reg_t i = P.VU.vstart->read() / P.VU.vlenb; \
reg_t off = P.VU.vstart->read() % P.VU.vlenb; \
if (off) { \
for (reg_t pos = off; pos < P.VU.vlenb; ++pos) { \
auto val = P.VU.elt<uint8_t>(vs3 + i, pos); \
MMU.store_uint8(baseAddr + P.VU.vstart, val); \
P.VU.vstart++; \
MMU.store_uint8(baseAddr + P.VU.vstart->read(), val); \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
i++; \
} \
for (; i < len; ++i) { \
for (reg_t pos = 0; pos < P.VU.vlenb; ++pos) { \
auto val = P.VU.elt<uint8_t>(vs3 + i, pos); \
MMU.store_uint8(baseAddr + P.VU.vstart, val); \
P.VU.vstart++; \
MMU.store_uint8(baseAddr + P.VU.vstart->read(), val); \
P.VU.vstart->write(P.VU.vstart->read() + 1); \
} \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
//
// vector: amo
@ -1765,13 +1761,13 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
} \
} \
VI_DUPLICATE_VREG(insn.rs2(), idx_type); \
const reg_t vl = P.VU.vl; \
const reg_t vl = P.VU.vl->read(); \
const reg_t baseAddr = RS1; \
const reg_t vd = insn.rd(); \
for (reg_t i = P.VU.vstart; i < vl; ++i) { \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
VI_ELEMENT_SKIP(i); \
VI_STRIP(i); \
P.VU.vstart = i; \
P.VU.vstart->write(i); \
switch (P.VU.vsew) { \
case e32: {\
auto vs3 = P.VU.elt< type ## 32_t>(vd, vreg_inx); \
@ -1792,7 +1788,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
break; \
} \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
// vector: sign/unsiged extension
#define VI_VV_EXT(div, type) \
@ -1848,7 +1844,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
(P.VU.vsew == e64 && p->extension_enabled('D'))); \
require_vector(true);\
require(STATE.frm->read() < 0x5);\
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
@ -1856,12 +1852,12 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
#define VI_VFP_LOOP_BASE \
VI_VFP_COMMON \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP();
#define VI_VFP_LOOP_CMP_BASE \
VI_VFP_COMMON \
for (reg_t i = P.VU.vstart; i < vl; ++i) { \
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
uint64_t mmask = UINT64_C(1) << mpos; \
uint64_t &vdi = P.VU.elt<uint64_t>(rd_num, midx, true); \
@ -1872,7 +1868,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
float##width##_t vs1_0 = P.VU.elt<float##width##_t>(rs1_num, 0); \
vd_0 = vs1_0; \
bool is_active = false; \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP(); \
float##width##_t vs2 = P.VU.elt<float##width##_t>(rs2_num, i); \
is_active = true; \
@ -1880,16 +1876,16 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
#define VI_VFP_LOOP_WIDE_REDUCTION_BASE \
VI_VFP_COMMON \
float64_t vd_0 = f64(P.VU.elt<float64_t>(rs1_num, 0).v); \
for (reg_t i=P.VU.vstart; i<vl; ++i) { \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) { \
VI_LOOP_ELEMENT_SKIP();
#define VI_VFP_LOOP_END \
} \
P.VU.vstart = 0; \
P.VU.vstart->write(0); \
#define VI_VFP_LOOP_REDUCTION_END(x) \
} \
P.VU.vstart = 0; \
P.VU.vstart->write(0); \
if (vl > 0) { \
if (is_propagate && !is_active) { \
switch (x) { \
@ -1951,7 +1947,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
break; \
}; \
} \
P.VU.vstart = 0;
P.VU.vstart->write(0);
#define VI_VFP_VV_LOOP(BODY16, BODY32, BODY64) \
VI_CHECK_SSS(true); \
@ -2056,7 +2052,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
switch(P.VU.vsew) { \
case e16: {\
float32_t vd_0 = P.VU.elt<float32_t>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i) { \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
is_active = true; \
float32_t vs2 = f16_to_f32(P.VU.elt<float16_t>(rs2_num, i)); \
@ -2067,7 +2063,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
}\
case e32: {\
float64_t vd_0 = P.VU.elt<float64_t>(rs1_num, 0); \
for (reg_t i=P.VU.vstart; i<vl; ++i) { \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) { \
VI_LOOP_ELEMENT_SKIP(); \
is_active = true; \
float64_t vs2 = f32_to_f64(P.VU.elt<float32_t>(rs2_num, i)); \
@ -2264,12 +2260,12 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
(P.VU.vsew == e16 && p->extension_enabled('F')) || \
(P.VU.vsew == e32 && p->extension_enabled('D'))); \
require(STATE.frm->read() < 0x5);\
reg_t vl = P.VU.vl; \
reg_t vl = P.VU.vl->read(); \
reg_t rd_num = insn.rd(); \
reg_t rs1_num = insn.rs1(); \
reg_t rs2_num = insn.rs2(); \
softfloat_roundingMode = STATE.frm->read(); \
for (reg_t i=P.VU.vstart; i<vl; ++i){ \
for (reg_t i=P.VU.vstart->read(); i<vl; ++i){ \
VI_LOOP_ELEMENT_SKIP();
#define VI_VFP_CVT_SCALE(BODY8, BODY16, BODY32, \
@ -2347,7 +2343,7 @@ for (reg_t i = 0; i < P.VU.vlmax && P.VU.vl != 0; ++i) { \
}
#define P_SET_OV(ov) \
P.VU.vxsat |= ov;
P.VU.vxsat->write(P.VU.vxsat->read() | ov);
#define P_SAT(R, BIT) \
if (R > INT##BIT##_MAX) { \

2
riscv/execute.cc

@ -125,7 +125,7 @@ static void commit_log_print_insn(processor_t *p, reg_t pc, insn_t insn)
p->VU.vsew,
p->VU.vflmul < 1 ? "mf" : "m",
p->VU.vflmul < 1 ? (reg_t)(1 / p->VU.vflmul) : (reg_t)p->VU.vflmul,
p->VU.vl);
p->VU.vl->read());
show_vec = true;
}

2
riscv/insns/vcompress_vm.h

@ -1,5 +1,5 @@
// vcompress vd, vs2, vs1
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
require_align(insn.rd(), P.VU.vflmul);
require_align(insn.rs2(), P.VU.vflmul);
require(insn.rd() != insn.rs2());

8
riscv/insns/vcpop_m.h

@ -1,13 +1,13 @@
// vmpopc rd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t sew = P.VU.vsew;
reg_t rd_num = insn.rd();
reg_t rs2_num = insn.rs2();
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
reg_t popcount = 0;
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
const int midx = i / 32;
const int mpos = i % 32;
@ -19,5 +19,5 @@ for (reg_t i=P.VU.vstart; i<vl; ++i) {
popcount += (vs2_lsb && do_mask);
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);
WRITE_RD(popcount);

8
riscv/insns/vfirst_m.h

@ -1,13 +1,13 @@
// vmfirst rd, vs2
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t sew = P.VU.vsew;
reg_t rd_num = insn.rd();
reg_t rs2_num = insn.rs2();
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
reg_t pos = -1;
for (reg_t i=P.VU.vstart; i < vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i < vl; ++i) {
VI_LOOP_ELEMENT_SKIP()
bool vs2_lsb = ((P.VU.elt<uint64_t>(rs2_num, midx ) >> mpos) & 0x1) == 1;
@ -16,5 +16,5 @@ for (reg_t i=P.VU.vstart; i < vl; ++i) {
break;
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);
WRITE_RD(pos);

8
riscv/insns/vfmerge_vfm.h

@ -4,7 +4,7 @@ VI_VFP_COMMON;
switch(P.VU.vsew) {
case e16:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float16_t>(rd_num, i, true);
auto rs1 = f16(READ_FREG(rs1_num));
auto vs2 = P.VU.elt<float16_t>(rs2_num, i);
@ -17,7 +17,7 @@ switch(P.VU.vsew) {
}
break;
case e32:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float32_t>(rd_num, i, true);
auto rs1 = f32(READ_FREG(rs1_num));
auto vs2 = P.VU.elt<float32_t>(rs2_num, i);
@ -30,7 +30,7 @@ switch(P.VU.vsew) {
}
break;
case e64:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float64_t>(rd_num, i, true);
auto rs1 = f64(READ_FREG(rs1_num));
auto vs2 = P.VU.elt<float64_t>(rs2_num, i);
@ -47,4 +47,4 @@ switch(P.VU.vsew) {
break;
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

2
riscv/insns/vfmv_f_s.h

@ -35,4 +35,4 @@ if (FLEN == 64) {
WRITE_FRD(f32(vs2_0));
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

6
riscv/insns/vfmv_s_f.h

@ -6,9 +6,9 @@ require((P.VU.vsew == e16 && p->extension_enabled(EXT_ZFH)) ||
(P.VU.vsew == e64 && p->extension_enabled('D')));
require(STATE.frm->read() < 0x5);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
if (vl > 0 && P.VU.vstart < vl) {
if (vl > 0 && P.VU.vstart->read() < vl) {
reg_t rd_num = insn.rd();
switch(P.VU.vsew) {
@ -26,4 +26,4 @@ if (vl > 0 && P.VU.vstart < vl) {
break;
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

8
riscv/insns/vfmv_v_f.h

@ -3,7 +3,7 @@ require_align(insn.rd(), P.VU.vflmul);
VI_VFP_COMMON
switch(P.VU.vsew) {
case e16:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float16_t>(rd_num, i, true);
auto rs1 = f16(READ_FREG(rs1_num));
@ -11,7 +11,7 @@ switch(P.VU.vsew) {
}
break;
case e32:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float32_t>(rd_num, i, true);
auto rs1 = f32(READ_FREG(rs1_num));
@ -19,7 +19,7 @@ switch(P.VU.vsew) {
}
break;
case e64:
for (reg_t i=P.VU.vstart; i<vl; ++i) {
for (reg_t i=P.VU.vstart->read(); i<vl; ++i) {
auto &vd = P.VU.elt<float64_t>(rd_num, i, true);
auto rs1 = f64(READ_FREG(rs1_num));
@ -28,4 +28,4 @@ switch(P.VU.vsew) {
break;
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

6
riscv/insns/vid_v.h

@ -1,7 +1,7 @@
// vmpopc rd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t sew = P.VU.vsew;
reg_t rd_num = insn.rd();
reg_t rs1_num = insn.rs1();
@ -9,7 +9,7 @@ reg_t rs2_num = insn.rs2();
require_align(rd_num, P.VU.vflmul);
require_vm;
for (reg_t i = P.VU.vstart ; i < P.VU.vl; ++i) {
for (reg_t i = P.VU.vstart->read() ; i < P.VU.vl->read(); ++i) {
VI_LOOP_ELEMENT_SKIP();
switch (sew) {
@ -28,4 +28,4 @@ for (reg_t i = P.VU.vstart ; i < P.VU.vl; ++i) {
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

4
riscv/insns/viota_m.h

@ -1,12 +1,12 @@
// vmpopc rd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t sew = P.VU.vsew;
reg_t rd_num = insn.rd();
reg_t rs1_num = insn.rs1();
reg_t rs2_num = insn.rs2();
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
require_vm;
require_align(rd_num, P.VU.vflmul);
require_noover(rd_num, P.VU.vflmul, rs2_num, 1);

6
riscv/insns/vmsbf_m.h

@ -1,16 +1,16 @@
// vmsbf.m vd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
require_vm;
require(insn.rd() != insn.rs2());
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t rd_num = insn.rd();
reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart; i < vl; ++i) {
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
const int midx = i / 64;
const int mpos = i % 64;
const uint64_t mmask = UINT64_C(1) << mpos; \

6
riscv/insns/vmsif_m.h

@ -1,16 +1,16 @@
// vmsif.m rd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
require_vm;
require(insn.rd() != insn.rs2());
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t rd_num = insn.rd();
reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart ; i < vl; ++i) {
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
const int midx = i / 64;
const int mpos = i % 64;
const uint64_t mmask = UINT64_C(1) << mpos; \

6
riscv/insns/vmsof_m.h

@ -1,16 +1,16 @@
// vmsof.m rd, vs2, vm
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
require_vector(true);
require(P.VU.vstart == 0);
require(P.VU.vstart->read() == 0);
require_vm;
require(insn.rd() != insn.rs2());
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
reg_t rd_num = insn.rd();
reg_t rs2_num = insn.rs2();
bool has_one = false;
for (reg_t i = P.VU.vstart ; i < vl; ++i) {
for (reg_t i = P.VU.vstart->read() ; i < vl; ++i) {
const int midx = i / 64;
const int mpos = i % 64;
const uint64_t mmask = UINT64_C(1) << mpos; \

6
riscv/insns/vmv_s_x.h

@ -2,9 +2,9 @@
require_vector(true);
require(insn.v_vm() == 1);
require(P.VU.vsew >= e8 && P.VU.vsew <= e64);
reg_t vl = P.VU.vl;
reg_t vl = P.VU.vl->read();
if (vl > 0 && P.VU.vstart < vl) {
if (vl > 0 && P.VU.vstart->read() < vl) {
reg_t rd_num = insn.rd();
reg_t sew = P.VU.vsew;
@ -26,4 +26,4 @@ if (vl > 0 && P.VU.vstart < vl) {
vl = 0;
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

2
riscv/insns/vmv_x_s.h

@ -28,4 +28,4 @@ if (!(rs1 >= 0 && rs1 < (P.VU.get_vlen() / sew))) {
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

8
riscv/insns/vmvnfr_v.h

@ -9,9 +9,9 @@ require_align(vs2, len);
const reg_t size = len * P.VU.vlenb;
//register needs one-by-one copy to keep commitlog correct
if (vd != vs2 && P.VU.vstart < size) {
reg_t i = P.VU.vstart / P.VU.vlenb;
reg_t off = P.VU.vstart % P.VU.vlenb;
if (vd != vs2 && P.VU.vstart->read() < size) {
reg_t i = P.VU.vstart->read() / P.VU.vlenb;
reg_t off = P.VU.vstart->read() % P.VU.vlenb;
if (off) {
memcpy(&P.VU.elt<uint8_t>(vd + i, off, true),
&P.VU.elt<uint8_t>(vs2 + i, off), P.VU.vlenb - off);
@ -24,4 +24,4 @@ if (vd != vs2 && P.VU.vstart < size) {
}
}
P.VU.vstart = 0;
P.VU.vstart->write(0);

4
riscv/insns/vnclip_wi.h

@ -15,10 +15,10 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result < int_min) {
result = int_min;
P.VU.vxsat = 1;
P_SET_OV(1);
} else if (result > int_max) {
result = int_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

4
riscv/insns/vnclip_wv.h

@ -15,10 +15,10 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result < int_min) {
result = int_min;
P.VU.vxsat = 1;
P_SET_OV(1);
} else if (result > int_max) {
result = int_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

4
riscv/insns/vnclip_wx.h

@ -15,10 +15,10 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result < int_min) {
result = int_min;
P.VU.vxsat = 1;
P_SET_OV(1);
} else if (result > int_max) {
result = int_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vnclipu_wi.h

@ -16,7 +16,7 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result & sign_mask) {
result = uint_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vnclipu_wv.h

@ -15,7 +15,7 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result & sign_mask) {
result = uint_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vnclipu_wx.h

@ -15,7 +15,7 @@ VI_VVXI_LOOP_NARROW
// saturation
if (result & sign_mask) {
result = uint_max;
P.VU.vxsat = 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vrgather_vi.h

@ -8,7 +8,7 @@ reg_t zimm5 = insn.v_zimm5();
VI_LOOP_BASE
for (reg_t i = P.VU.vstart; i < vl; ++i) {
for (reg_t i = P.VU.vstart->read(); i < vl; ++i) {
VI_LOOP_ELEMENT_SKIP();
switch (sew) {

2
riscv/insns/vsadd_vi.h

@ -24,5 +24,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

3
riscv/insns/vsadd_vv.h

@ -24,6 +24,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

2
riscv/insns/vsadd_vx.h

@ -24,5 +24,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

2
riscv/insns/vsaddu_vi.h

@ -7,5 +7,5 @@ VI_VI_ULOOP
sat = vd < vs2;
vd |= -(vd < vs2);
P.VU.vxsat |= sat;
P_SET_OV(sat);
})

2
riscv/insns/vsaddu_vv.h

@ -7,5 +7,5 @@ VI_VV_ULOOP
sat = vd < vs2;
vd |= -(vd < vs2);
P.VU.vxsat |= sat;
P_SET_OV(sat);
})

2
riscv/insns/vsaddu_vx.h

@ -7,6 +7,6 @@ VI_VX_ULOOP
sat = vd < vs2;
vd |= -(vd < vs2);
P.VU.vxsat |= sat;
P_SET_OV(sat);
})

2
riscv/insns/vslideup_vi.h

@ -3,7 +3,7 @@ VI_CHECK_SLIDE(true);
const reg_t offset = insn.v_zimm5();
VI_LOOP_BASE
if (P.VU.vstart < offset && i < offset)
if (P.VU.vstart->read() < offset && i < offset)
continue;
switch (sew) {

2
riscv/insns/vslideup_vx.h

@ -3,7 +3,7 @@ VI_CHECK_SLIDE(true);
const reg_t offset = RS1;
VI_LOOP_BASE
if (P.VU.vstart < offset && i < offset)
if (P.VU.vstart->read() < offset && i < offset)
continue;
switch (sew) {

2
riscv/insns/vsmul_vv.h

@ -25,7 +25,7 @@ VI_VV_LOOP
// saturation
if (overflow) {
result = int_max;
P.VU.vxsat |= 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vsmul_vx.h

@ -26,7 +26,7 @@ VI_VX_LOOP
// max saturation
if (overflow) {
result = int_max;
P.VU.vxsat |= 1;
P_SET_OV(1);
}
vd = result;

2
riscv/insns/vssub_vv.h

@ -25,5 +25,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

2
riscv/insns/vssub_vx.h

@ -25,5 +25,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

2
riscv/insns/vssubu_vv.h

@ -25,6 +25,6 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

2
riscv/insns/vssubu_vx.h

@ -25,5 +25,5 @@ default: {
break;
}
}
P.VU.vxsat |= sat;
P_SET_OV(sat);
VI_LOOP_END

155
riscv/processor.cc

@ -524,7 +524,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
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);
csrmap[CSR_FCSR] = std::make_shared<composite_csr_t>(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT);
csrmap[CSR_SENTROPY] = std::make_shared<sentropy_csr_t>(proc, CSR_SENTROPY);
@ -552,14 +552,24 @@ void processor_t::vectorUnit_t::reset(){
reg_file = malloc(NVPR * vlenb);
memset(reg_file, 0, NVPR * vlenb);
vtype = 0;
auto& csrmap = p->get_state()->csrmap;
csrmap[CSR_VXSAT] = vxsat = std::make_shared<vector_csr_t>(p, CSR_VXSAT, /*mask*/ 0x1ul);
csrmap[CSR_VSTART] = vstart = std::make_shared<vector_csr_t>(p, CSR_VSTART, /*mask*/ VLEN - 1);
csrmap[CSR_VXRM] = vxrm = std::make_shared<vector_csr_t>(p, CSR_VXRM, /*mask*/ 0x3ul);
csrmap[CSR_VL] = vl = std::make_shared<vector_csr_t>(p, CSR_VL, /*mask*/ 0);
csrmap[CSR_VTYPE] = vtype = std::make_shared<vector_csr_t>(p, CSR_VTYPE, /*mask*/ 0);
csrmap[CSR_VLENB] = std::make_shared<vector_csr_t>(p, CSR_VLENB, /*mask*/ 0, /*init*/ vlenb);
assert(VCSR_VXSAT_SHIFT == 0); // composite_csr_t assumes vxsat begins at bit 0
csrmap[CSR_VCSR] = std::make_shared<composite_csr_t>(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT);
vtype->write_raw(0);
set_vl(0, 0, 0, -1); // default to illegal configuration
}
reg_t processor_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t newType){
int new_vlmul = 0;
if (vtype != newType){
vtype = newType;
if (vtype->read() != newType){
vtype->write_raw(newType);
vsew = 1 << (extract64(newType, 3, 3) + 3);
new_vlmul = int8_t(extract64(newType, 0, 3) << 5) >> 5;
vflmul = new_vlmul >= 0 ? 1 << new_vlmul : 1.0 / (1 << -new_vlmul);
@ -573,24 +583,24 @@ reg_t processor_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t newT
if (vill) {
vlmax = 0;
vtype = UINT64_MAX << (p->get_xlen() - 1);
vtype->write_raw(UINT64_MAX << (p->get_xlen() - 1));
}
}
// set vl
if (vlmax == 0) {
vl = 0;
vl->write_raw(0);
} else if (rd == 0 && rs1 == 0) {
vl = vl > vlmax ? vlmax : vl;
vl->write_raw(vl->read() > vlmax ? vlmax : vl->read());
} else if (rd != 0 && rs1 == 0) {
vl = vlmax;
vl->write_raw(vlmax);
} else if (rs1 != 0) {
vl = reqVL > vlmax ? vlmax : reqVL;
vl->write_raw(reqVL > vlmax ? vlmax : reqVL);
}
vstart = 0;
vstart->write_raw(0);
setvl_count++;
return vl;
return vl->read();
}
void processor_t::set_debug(bool value)
@ -968,60 +978,12 @@ int processor_t::paddr_bits()
void processor_t::set_csr(int which, reg_t val)
{
#if defined(RISCV_ENABLE_COMMITLOG)
#define LOG_CSR(rd) \
STATE.log_reg_write[((rd) << 4) | 4] = {get_csr(rd), 0};
#else
#define LOG_CSR(rd)
#endif
val = zext_xlen(val);
auto search = state.csrmap.find(which);
if (search != state.csrmap.end()) {
search->second->write(val);
return;
}
switch (which)
{
case CSR_VCSR:
dirty_vs_state;
VU.vxsat = (val & VCSR_VXSAT) >> VCSR_VXSAT_SHIFT;
VU.vxrm = (val & VCSR_VXRM) >> VCSR_VXRM_SHIFT;
break;
case CSR_VSTART:
dirty_vs_state;
VU.vstart = val & (VU.get_vlen() - 1);
break;
case CSR_VXSAT:
dirty_vs_state;
VU.vxsat = val & 0x1ul;
break;
case CSR_VXRM:
dirty_vs_state;
VU.vxrm = val & 0x3ul;
break;
}
#if defined(RISCV_ENABLE_COMMITLOG)
switch (which)
{
case CSR_VCSR:
LOG_CSR(CSR_VXSAT);
LOG_CSR(CSR_VXRM);
break;
case CSR_VSTART:
LOG_CSR(CSR_VSTART);
break;
case CSR_VXSAT:
LOG_CSR(CSR_VXSAT);
break;
case CSR_VXRM:
LOG_CSR(CSR_VXRM);
break;
}
#endif
}
// Note that get_csr is sometimes called when read side-effects should not
@ -1029,90 +991,15 @@ void processor_t::set_csr(int which, reg_t val)
// side effects on reads.
reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek)
{
reg_t res = 0;
#define ret(n) do { \
res = (n); \
goto out; \
} while (false)
auto search = state.csrmap.find(which);
if (search != state.csrmap.end()) {
if (!peek)
search->second->verify_permissions(insn, write);
return search->second->read();
}
switch (which)
{
case CSR_VCSR:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret((VU.vxsat << VCSR_VXSAT_SHIFT) | (VU.vxrm << VCSR_VXRM_SHIFT));
case CSR_VSTART:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vstart);
case CSR_VXSAT:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vxsat);
case CSR_VXRM:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vxrm);
case CSR_VL:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vl);
case CSR_VTYPE:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vtype);
case CSR_VLENB:
require_vector_vs;
if (!extension_enabled('V'))
break;
ret(VU.vlenb);
}
#undef ret
// If we get here, the CSR doesn't exist. Unimplemented CSRs always throw
// illegal-instruction exceptions, not virtual-instruction exceptions.
throw_illegal:
throw trap_illegal_instruction(insn.bits());
throw_virtual:
throw trap_virtual_instruction(insn.bits());
out:
// Check permissions. Raise virtual-instruction exception if V=1,
// privileges are insufficient, and the CSR belongs to supervisor or
// hypervisor. Raise illegal-instruction exception otherwise.
if (peek)
return res;
unsigned csr_priv = get_field(which, 0x300);
unsigned priv = state.prv == PRV_S && !state.v ? PRV_HS : state.prv;
if ((csr_priv == PRV_S && !extension_enabled('S')) ||
(csr_priv == PRV_HS && !extension_enabled('H')))
goto throw_illegal;
if (priv < csr_priv) {
if (state.v && csr_priv <= PRV_HS)
goto throw_virtual;
goto throw_illegal;
}
return res;
}
reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc)

27
riscv/processor.h

@ -511,7 +511,8 @@ public:
char reg_referenced[NVPR];
int setvl_count;
reg_t vlmax;
reg_t vstart, vxrm, vxsat, vl, vtype, vlenb;
reg_t vlenb;
vector_csr_t_p vxrm, vstart, vxsat, vl, vtype;
reg_t vma, vta;
reg_t vsew;
float vflmul;
@ -546,8 +547,26 @@ public:
void reset();
vectorUnit_t(){
reg_file = 0;
vectorUnit_t():
p(0),
reg_file(0),
reg_referenced{0},
setvl_count(0),
vlmax(0),
vlenb(0),
vxrm(0),
vstart(0),
vxsat(0),
vl(0),
vtype(0),
vma(0),
vta(0),
vsew(0),
vflmul(0),
ELEN(0),
VLEN(0),
vill(false),
vstart_alu(false) {
}
~vectorUnit_t(){
@ -562,7 +581,7 @@ public:
reg_t get_slen() { return VLEN; }
VRM get_vround_mode() {
return (VRM)vxrm;
return (VRM)(vxrm->read());
}
};

Loading…
Cancel
Save