aboutsummaryrefslogtreecommitdiff
path: root/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'riscv')
-rw-r--r--riscv/interactive.cc1
-rw-r--r--riscv/processor.cc62
-rw-r--r--riscv/processor.h145
-rw-r--r--riscv/riscv.mk.in2
-rw-r--r--riscv/v_ext_macros.h2
-rw-r--r--riscv/vector_unit.cc101
-rw-r--r--riscv/vector_unit.h135
7 files changed, 243 insertions, 205 deletions
diff --git a/riscv/interactive.cc b/riscv/interactive.cc
index 8557acc..251a1ca 100644
--- a/riscv/interactive.cc
+++ b/riscv/interactive.cc
@@ -4,6 +4,7 @@
#include "decode.h"
#include "disasm.h"
#include "mmu.h"
+#include "vector_unit.h"
#include <sys/mman.h>
#include <termios.h>
#include <map>
diff --git a/riscv/processor.cc b/riscv/processor.cc
index d161d46..0564610 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -9,6 +9,7 @@
#include "mmu.h"
#include "disasm.h"
#include "platform.h"
+#include "vector_unit.h"
#include <cinttypes>
#include <cmath>
#include <cstdlib>
@@ -511,67 +512,6 @@ void state_t::reset(processor_t* const proc, reg_t max_isa)
#endif
}
-void processor_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 processor_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();
-}
-
void processor_t::set_debug(bool value)
{
debug = value;
diff --git a/riscv/processor.h b/riscv/processor.h
index e6d8a16..a4df3b1 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -17,6 +17,7 @@
#include "isa_parser.h"
#include "triggers.h"
#include "memif.h"
+#include "vector_unit.h"
#define N_HPMCOUNTERS 29
@@ -59,68 +60,6 @@ typedef std::unordered_map<reg_t, freg_t> commit_log_reg_t;
// addr, value, size
typedef std::vector<std::tuple<reg_t, uint64_t, uint8_t>> commit_log_mem_t;
-enum VRM{
- RNU = 0,
- RNE,
- RDN,
- ROD,
- INVALID_RM
-};
-
-template<uint64_t N>
-struct type_usew_t;
-
-template<>
-struct type_usew_t<8>
-{
- using type=uint8_t;
-};
-
-template<>
-struct type_usew_t<16>
-{
- using type=uint16_t;
-};
-
-template<>
-struct type_usew_t<32>
-{
- using type=uint32_t;
-};
-
-template<>
-struct type_usew_t<64>
-{
- using type=uint64_t;
-};
-
-template<uint64_t N>
-struct type_sew_t;
-
-template<>
-struct type_sew_t<8>
-{
- using type=int8_t;
-};
-
-template<>
-struct type_sew_t<16>
-{
- using type=int16_t;
-};
-
-template<>
-struct type_sew_t<32>
-{
- using type=int32_t;
-};
-
-template<>
-struct type_sew_t<64>
-{
- using type=int64_t;
-};
-
// architectural state of a RISC-V hart
struct state_t
{
@@ -385,88 +324,6 @@ public:
reg_t lg_pmp_granularity;
reg_t pmp_tor_mask() { return -(reg_t(1) << (lg_pmp_granularity - PMP_SHIFT)); }
- class vectorUnit_t {
- public:
- processor_t* p;
- void *reg_file;
- char reg_referenced[NVPR];
- int setvl_count;
- reg_t vlmax;
- reg_t vlenb;
- csr_t_p vxsat;
- vector_csr_t_p vxrm, vstart, vl, vtype;
- reg_t vma, vta;
- reg_t vsew;
- float vflmul;
- reg_t ELEN, VLEN;
- bool vill;
- bool vstart_alu;
-
- // vector element for varies SEW
- template<class T>
- T& elt(reg_t vReg, reg_t n, bool UNUSED is_write = false) {
- 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];
- }
- public:
-
- void reset();
-
- vectorUnit_t():
- p(0),
- reg_file(0),
- reg_referenced{0},
- setvl_count(0),
- vlmax(0),
- vlenb(0),
- vxsat(0),
- vxrm(0),
- vstart(0),
- vl(0),
- vtype(0),
- vma(0),
- vta(0),
- vsew(0),
- vflmul(0),
- ELEN(0),
- VLEN(0),
- vill(false),
- vstart_alu(false) {
- }
-
- ~vectorUnit_t() {
- free(reg_file);
- reg_file = 0;
- }
-
- reg_t set_vl(int rd, int rs1, reg_t reqVL, reg_t newType);
-
- reg_t get_vlen() { return VLEN; }
- reg_t get_elen() { return ELEN; }
- reg_t get_slen() { return VLEN; }
-
- VRM get_vround_mode() {
- return (VRM)(vxrm->read());
- }
- };
-
vectorUnit_t VU;
triggers::module_t TM;
};
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index 7e38aca..1eee43a 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -42,6 +42,7 @@ riscv_hdrs = \
jtag_dtm.h \
csrs.h \
triggers.h \
+ vector_unit.h
riscv_install_hdrs = \
abstract_device.h \
@@ -94,6 +95,7 @@ riscv_srcs = \
jtag_dtm.cc \
csrs.cc \
triggers.cc \
+ vector_unit.cc \
$(riscv_gen_srcs) \
riscv_test_srcs =
diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h
index 66d8101..3fc0162 100644
--- a/riscv/v_ext_macros.h
+++ b/riscv/v_ext_macros.h
@@ -3,6 +3,8 @@
#ifndef _RISCV_V_EXT_MACROS_H
#define _RISCV_V_EXT_MACROS_H
+#include "vector_unit.h"
+
//
// vector: masking skip helper
//
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);
diff --git a/riscv/vector_unit.h b/riscv/vector_unit.h
new file mode 100644
index 0000000..b9f706c
--- /dev/null
+++ b/riscv/vector_unit.h
@@ -0,0 +1,135 @@
+// See LICENSE for license details.
+#ifndef _RISCV_VECTOR_UNIT_H
+#define _RISCV_VECTOR_UNIT_H
+
+#include "decode.h"
+#include "csrs.h"
+
+class processor_t;
+
+enum VRM{
+ RNU = 0,
+ RNE,
+ RDN,
+ ROD,
+ INVALID_RM
+};
+
+template<uint64_t N>
+struct type_usew_t;
+
+template<>
+struct type_usew_t<8>
+{
+ using type=uint8_t;
+};
+
+template<>
+struct type_usew_t<16>
+{
+ using type=uint16_t;
+};
+
+template<>
+struct type_usew_t<32>
+{
+ using type=uint32_t;
+};
+
+template<>
+struct type_usew_t<64>
+{
+ using type=uint64_t;
+};
+
+template<uint64_t N>
+struct type_sew_t;
+
+template<>
+struct type_sew_t<8>
+{
+ using type=int8_t;
+};
+
+template<>
+struct type_sew_t<16>
+{
+ using type=int16_t;
+};
+
+template<>
+struct type_sew_t<32>
+{
+ using type=int32_t;
+};
+
+template<>
+struct type_sew_t<64>
+{
+ using type=int64_t;
+};
+
+
+class vectorUnit_t
+{
+public:
+ processor_t* p;
+ void *reg_file;
+ char reg_referenced[NVPR];
+ int setvl_count;
+ reg_t vlmax;
+ reg_t vlenb;
+ csr_t_p vxsat;
+ vector_csr_t_p vxrm, vstart, vl, vtype;
+ reg_t vma, vta;
+ reg_t vsew;
+ float vflmul;
+ reg_t ELEN, VLEN;
+ bool vill;
+ bool vstart_alu;
+
+ // vector element for varies SEW
+ template<class T> T& elt(reg_t vReg, reg_t n, bool is_write = false);
+
+public:
+
+ void reset();
+
+ vectorUnit_t():
+ p(0),
+ reg_file(0),
+ reg_referenced{0},
+ setvl_count(0),
+ vlmax(0),
+ vlenb(0),
+ vxsat(0),
+ vxrm(0),
+ vstart(0),
+ vl(0),
+ vtype(0),
+ vma(0),
+ vta(0),
+ vsew(0),
+ vflmul(0),
+ ELEN(0),
+ VLEN(0),
+ vill(false),
+ vstart_alu(false) {
+ }
+
+ ~vectorUnit_t() {
+ free(reg_file);
+ reg_file = 0;
+ }
+
+ reg_t set_vl(int rd, int rs1, reg_t reqVL, reg_t newType);
+
+ reg_t get_vlen() { return VLEN; }
+ reg_t get_elen() { return ELEN; }
+ reg_t get_slen() { return VLEN; }
+
+ VRM get_vround_mode() {
+ return (VRM)(vxrm->read());
+ }
+};
+#endif