aboutsummaryrefslogtreecommitdiff
path: root/riscv/vector_unit.cc
diff options
context:
space:
mode:
Diffstat (limited to 'riscv/vector_unit.cc')
-rw-r--r--riscv/vector_unit.cc101
1 files changed, 101 insertions, 0 deletions
diff --git a/riscv/vector_unit.cc b/riscv/vector_unit.cc
new file mode 100644
index 0000000..17c63a9
--- /dev/null
+++ b/riscv/vector_unit.cc
@@ -0,0 +1,101 @@
+// See LICENSE for license details
+
+#include "config.h"
+#include "vector_unit.h"
+#include "processor.h"
+#include "arith.h"
+
+void vectorUnit_t::vectorUnit_t::reset()
+{
+ free(reg_file);
+ VLEN = get_vlen();
+ ELEN = get_elen();
+ reg_file = malloc(NVPR * vlenb);
+ memset(reg_file, 0, NVPR * vlenb);
+
+ auto& csrmap = p->get_state()->csrmap;
+ csrmap[CSR_VXSAT] = vxsat = std::make_shared<vxsat_csr_t>(p, CSR_VXSAT);
+ 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 vectorUnit_t::vectorUnit_t::set_vl(int rd, int rs1, reg_t reqVL, reg_t newType)
+{
+ int new_vlmul = 0;
+ if (vtype->read() != 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);
+ vlmax = (VLEN/vsew) * vflmul;
+ vta = extract64(newType, 6, 1);
+ vma = extract64(newType, 7, 1);
+
+ vill = !(vflmul >= 0.125 && vflmul <= 8)
+ || vsew > std::min(vflmul, 1.0f) * ELEN
+ || (newType >> 8) != 0;
+
+ if (vill) {
+ vlmax = 0;
+ vtype->write_raw(UINT64_MAX << (p->get_xlen() - 1));
+ } else {
+ vtype->write_raw(newType);
+ }
+ }
+
+ // set vl
+ if (vlmax == 0) {
+ vl->write_raw(0);
+ } else if (rd == 0 && rs1 == 0) {
+ vl->write_raw(vl->read() > vlmax ? vlmax : vl->read());
+ } else if (rd != 0 && rs1 == 0) {
+ vl->write_raw(vlmax);
+ } else if (rs1 != 0) {
+ vl->write_raw(reqVL > vlmax ? vlmax : reqVL);
+ }
+
+ vstart->write_raw(0);
+ setvl_count++;
+ return vl->read();
+}
+
+template<class T> T& vectorUnit_t::elt(reg_t vReg, reg_t n, bool UNUSED is_write) {
+ assert(vsew != 0);
+ assert((VLEN >> 3)/sizeof(T) > 0);
+ reg_t elts_per_reg = (VLEN >> 3) / (sizeof(T));
+ vReg += n / elts_per_reg;
+ n = n % elts_per_reg;
+#ifdef WORDS_BIGENDIAN
+ // "V" spec 0.7.1 requires lower indices to map to lower significant
+ // bits when changing SEW, thus we need to index from the end on BE.
+ n ^= elts_per_reg - 1;
+#endif
+ reg_referenced[vReg] = 1;
+
+#ifdef RISCV_ENABLE_COMMITLOG
+ if (is_write)
+ p->get_state()->log_reg_write[((vReg) << 4) | 2] = {0, 0};
+#endif
+
+ T *regStart = (T*)((char*)reg_file + vReg * (VLEN >> 3));
+ return regStart[n];
+}
+
+template signed char& vectorUnit_t::elt<signed char>(reg_t, reg_t, bool);
+template short& vectorUnit_t::elt<short>(reg_t, reg_t, bool);
+template int& vectorUnit_t::elt<int>(reg_t, reg_t, bool);
+template long& vectorUnit_t::elt<long>(reg_t, reg_t, bool);
+template uint8_t& vectorUnit_t::elt<uint8_t>(reg_t, reg_t, bool);
+template uint16_t& vectorUnit_t::elt<uint16_t>(reg_t, reg_t, bool);
+template uint32_t& vectorUnit_t::elt<uint32_t>(reg_t, reg_t, bool);
+template uint64_t& vectorUnit_t::elt<uint64_t>(reg_t, reg_t, bool);
+template float16_t& vectorUnit_t::elt<float16_t>(reg_t, reg_t, bool);
+template float32_t& vectorUnit_t::elt<float32_t>(reg_t, reg_t, bool);
+template float64_t& vectorUnit_t::elt<float64_t>(reg_t, reg_t, bool);