diff mbox series

[04/65] target/riscv: Override some csr ops for XTheadVector

Message ID 20240412073735.76413-5-eric.huang@linux.alibaba.com
State New
Headers show
Series target/riscv: Support XTheadVector extension | expand

Commit Message

Huang Tao April 12, 2024, 7:36 a.m. UTC
Some CSR operations have different behavior when XTheadVector is enabled.
In this patch, we override the RISC-V standard implementation of these
CSRs with a vendor implementation. Additionally, we attempt to use the
decorator pattern to explicitly list the different behaviors between
xtheadvector and the RISC-V standard.

Signed-off-by: Huang Tao <eric.huang@linux.alibaba.com>
---
 target/riscv/cpu.h      |  36 +++++++++
 target/riscv/cpu_bits.h |  18 +++++
 target/riscv/csr.c      |  42 +++++-----
 target/riscv/th_csr.c   | 169 +++++++++++++++++++++++++++++++++++++++-
 4 files changed, 243 insertions(+), 22 deletions(-)
diff mbox series

Patch

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 8d0b500758..6558e652df 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -813,6 +813,42 @@  void riscv_add_satp_mode_properties(Object *obj);
 bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu);
 
 /* CSR function table */
+RISCVException fs(CPURISCVState *env, int csrno);
+RISCVException vs(CPURISCVState *env, int csrno);
+RISCVException any(CPURISCVState *env, int csrno);
+RISCVException smode(CPURISCVState *env, int csrno);
+RISCVException read_fcsr(CPURISCVState *env, int csrno,
+                         target_ulong *val);
+RISCVException write_fcsr(CPURISCVState *env, int csrno,
+                          target_ulong val);
+RISCVException read_vtype(CPURISCVState *env, int csrno,
+                          target_ulong *val);
+RISCVException read_vl(CPURISCVState *env, int csrno,
+                       target_ulong *val);
+RISCVException read_vlenb(CPURISCVState *env, int csrno,
+                          target_ulong *val);
+RISCVException read_vxrm(CPURISCVState *env, int csrno,
+                         target_ulong *val);
+RISCVException write_vxrm(CPURISCVState *env, int csrno,
+                          target_ulong val);
+RISCVException read_vxsat(CPURISCVState *env, int csrno,
+                          target_ulong *val);
+RISCVException write_vxsat(CPURISCVState *env, int csrno,
+                           target_ulong val);
+RISCVException read_vstart(CPURISCVState *env, int csrno,
+                           target_ulong *val);
+RISCVException write_vstart(CPURISCVState *env, int csrno,
+                            target_ulong val);
+RISCVException read_mstatus(CPURISCVState *env, int csrno,
+                            target_ulong *val);
+RISCVException write_mstatus(CPURISCVState *env, int csrno,
+                             target_ulong val);
+RISCVException write_sstatus(CPURISCVState *env, int csrno,
+                             target_ulong val);
+RISCVException read_sstatus(CPURISCVState *env, int csrno,
+                            target_ulong *val);
+RISCVException read_vcsr(CPURISCVState *env, int csrno, target_ulong *val);
+RISCVException write_vcsr(CPURISCVState *env, int csrno, target_ulong val);
 extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE];
 
 extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[];
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index fc2068ee4d..5a5e0ed444 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -904,4 +904,22 @@  typedef enum RISCVException {
 #define MCONTEXT64                         0x0000000000001FFFULL
 #define MCONTEXT32_HCONTEXT                0x0000007F
 #define MCONTEXT64_HCONTEXT                0x0000000000003FFFULL
+
+/* Xuantie custom CSRs */
+#define TH_MSTATUS_VS     0x01800000
+
+#define TH_FSR_VXRM_SHIFT      9
+#define TH_FSR_VXRM            (0x3 << TH_FSR_VXRM_SHIFT)
+
+#define TH_FSR_VXSAT_SHIFT     8
+#define TH_FSR_VXSAT           (0x1 << TH_FSR_VXSAT_SHIFT)
+
+#define TH_VTYPE_LMUL_SHIFT    0
+#define TH_VTYPE_LMUL          (0x3 << TH_VTYPE_LMUL_SHIFT)
+
+#define TH_VTYPE_SEW_SHIFT     2
+#define TH_VTYPE_SEW           (0x7 << TH_VTYPE_SEW_SHIFT)
+
+#define TH_VTYPE_CLEAR_SHIFT   5
+#define TH_VTYPE_CLEAR         (0x7 << TH_VTYPE_CLEAR_SHIFT)
 #endif
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 726096444f..797929d5b9 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -76,7 +76,7 @@  RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit)
 }
 #endif
 
-static RISCVException fs(CPURISCVState *env, int csrno)
+RISCVException fs(CPURISCVState *env, int csrno)
 {
 #if !defined(CONFIG_USER_ONLY)
     if (!env->debugger && !riscv_cpu_fp_enabled(env) &&
@@ -91,7 +91,7 @@  static RISCVException fs(CPURISCVState *env, int csrno)
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException vs(CPURISCVState *env, int csrno)
+RISCVException vs(CPURISCVState *env, int csrno)
 {
     if (riscv_cpu_cfg(env)->ext_zve32f) {
 #if !defined(CONFIG_USER_ONLY)
@@ -227,7 +227,7 @@  static RISCVException sscofpmf(CPURISCVState *env, int csrno)
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException any(CPURISCVState *env, int csrno)
+RISCVException any(CPURISCVState *env, int csrno)
 {
     return RISCV_EXCP_NONE;
 }
@@ -260,7 +260,7 @@  static RISCVException aia_any32(CPURISCVState *env, int csrno)
     return any32(env, csrno);
 }
 
-static RISCVException smode(CPURISCVState *env, int csrno)
+RISCVException smode(CPURISCVState *env, int csrno)
 {
     if (riscv_has_ext(env, RVS)) {
         return RISCV_EXCP_NONE;
@@ -635,7 +635,7 @@  static RISCVException write_frm(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_fcsr(CPURISCVState *env, int csrno,
+RISCVException read_fcsr(CPURISCVState *env, int csrno,
                                 target_ulong *val)
 {
     *val = (riscv_cpu_get_fflags(env) << FSR_AEXC_SHIFT)
@@ -643,7 +643,7 @@  static RISCVException read_fcsr(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_fcsr(CPURISCVState *env, int csrno,
+RISCVException write_fcsr(CPURISCVState *env, int csrno,
                                  target_ulong val)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -656,7 +656,7 @@  static RISCVException write_fcsr(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vtype(CPURISCVState *env, int csrno,
+RISCVException read_vtype(CPURISCVState *env, int csrno,
                                  target_ulong *val)
 {
     uint64_t vill;
@@ -674,28 +674,28 @@  static RISCVException read_vtype(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vl(CPURISCVState *env, int csrno,
+RISCVException read_vl(CPURISCVState *env, int csrno,
                               target_ulong *val)
 {
     *val = env->vl;
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vlenb(CPURISCVState *env, int csrno,
+RISCVException read_vlenb(CPURISCVState *env, int csrno,
                                  target_ulong *val)
 {
     *val = riscv_cpu_cfg(env)->vlenb;
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vxrm(CPURISCVState *env, int csrno,
+RISCVException read_vxrm(CPURISCVState *env, int csrno,
                                 target_ulong *val)
 {
     *val = env->vxrm;
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_vxrm(CPURISCVState *env, int csrno,
+RISCVException write_vxrm(CPURISCVState *env, int csrno,
                                  target_ulong val)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -705,14 +705,14 @@  static RISCVException write_vxrm(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vxsat(CPURISCVState *env, int csrno,
+RISCVException read_vxsat(CPURISCVState *env, int csrno,
                                  target_ulong *val)
 {
     *val = env->vxsat;
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_vxsat(CPURISCVState *env, int csrno,
+RISCVException write_vxsat(CPURISCVState *env, int csrno,
                                   target_ulong val)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -722,14 +722,14 @@  static RISCVException write_vxsat(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vstart(CPURISCVState *env, int csrno,
+RISCVException read_vstart(CPURISCVState *env, int csrno,
                                   target_ulong *val)
 {
     *val = env->vstart;
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_vstart(CPURISCVState *env, int csrno,
+RISCVException write_vstart(CPURISCVState *env, int csrno,
                                    target_ulong val)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -743,14 +743,14 @@  static RISCVException write_vstart(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_vcsr(CPURISCVState *env, int csrno,
+RISCVException read_vcsr(CPURISCVState *env, int csrno,
                                 target_ulong *val)
 {
     *val = (env->vxrm << VCSR_VXRM_SHIFT) | (env->vxsat << VCSR_VXSAT_SHIFT);
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_vcsr(CPURISCVState *env, int csrno,
+RISCVException write_vcsr(CPURISCVState *env, int csrno,
                                  target_ulong val)
 {
 #if !defined(CONFIG_USER_ONLY)
@@ -1286,7 +1286,7 @@  static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
     return status;
 }
 
-static RISCVException read_mstatus(CPURISCVState *env, int csrno,
+RISCVException read_mstatus(CPURISCVState *env, int csrno,
                                    target_ulong *val)
 {
     *val = add_status_sd(riscv_cpu_mxl(env), env->mstatus);
@@ -1351,7 +1351,7 @@  static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
     return val;
 }
 
-static RISCVException write_mstatus(CPURISCVState *env, int csrno,
+RISCVException write_mstatus(CPURISCVState *env, int csrno,
                                     target_ulong val)
 {
     uint64_t mstatus = env->mstatus;
@@ -2639,7 +2639,7 @@  static RISCVException read_sstatus_i128(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_sstatus(CPURISCVState *env, int csrno,
+RISCVException read_sstatus(CPURISCVState *env, int csrno,
                                    target_ulong *val)
 {
     target_ulong mask = (sstatus_v1_10_mask);
@@ -2651,7 +2651,7 @@  static RISCVException read_sstatus(CPURISCVState *env, int csrno,
     return RISCV_EXCP_NONE;
 }
 
-static RISCVException write_sstatus(CPURISCVState *env, int csrno,
+RISCVException write_sstatus(CPURISCVState *env, int csrno,
                                     target_ulong val)
 {
     target_ulong mask = (sstatus_v1_10_mask);
diff --git a/target/riscv/th_csr.c b/target/riscv/th_csr.c
index dc087b1ffa..4fc488fc10 100644
--- a/target/riscv/th_csr.c
+++ b/target/riscv/th_csr.c
@@ -41,7 +41,124 @@  static int test_thead_mvendorid(RISCVCPU *cpu)
     return 0;
 }
 
+/*
+ * In XTheadVector, vcsr is inaccessible
+ * and we just check ext_xtheadvector instead of ext_zve32f
+ */
+static RISCVException th_vs(CPURISCVState *env, int csrno)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    if (cpu->cfg.ext_xtheadvector) {
+        if (csrno == CSR_VCSR) {
+            return RISCV_EXCP_ILLEGAL_INST;
+        }
+        return RISCV_EXCP_NONE;
+    }
+    return vs(env, csrno);
+}
+
+static RISCVException
+th_read_fcsr(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    RISCVException ret = read_fcsr(env, csrno, val);
+    if (cpu->cfg.ext_xtheadvector) {
+        *val = set_field(*val, TH_FSR_VXRM,  env->vxrm);
+        *val = set_field(*val, TH_FSR_VXSAT,  env->vxsat);
+    }
+    return ret;
+}
+
+static RISCVException
+th_write_fcsr(CPURISCVState *env, int csrno, target_ulong val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    if (cpu->cfg.ext_xtheadvector) {
+        env->vxrm = get_field(val, TH_FSR_VXRM);
+        env->vxsat = get_field(val, TH_FSR_VXSAT);
+    }
+    return write_fcsr(env, csrno, val);
+}
+
+/*
+ * We use the RVV1.0 format for env->vtype
+ * When reading vtype, we need to change the format.
+ * In RVV1.0:
+ *   vtype[7] -> vma
+ *   vtype[6] -> vta
+ *   vtype[5:3] -> vsew
+ *   vtype[2:0] -> vlmul
+ * In XTheadVector:
+ *   vtype[6:5] -> vediv
+ *   vtype[4:2] -> vsew
+ *   vtype[1:0] -> vlmul
+ * Although vlmul size is different between RVV1.0 and XTheadVector,
+ * the lower 2 bits have the same meaning.
+ * vma, vta and vediv are useless in XTheadVector, So we need to clear
+ * vtype[7:5] for XTheadVector
+ */
+static RISCVException
+th_read_vtype(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    RISCVException ret = read_vtype(env, csrno, val);
+    if (cpu->cfg.ext_xtheadvector) {
+        *val = set_field(*val, TH_VTYPE_LMUL,
+                          FIELD_EX64(*val, VTYPE, VLMUL));
+        *val = set_field(*val, TH_VTYPE_SEW,
+                          FIELD_EX64(*val, VTYPE, VSEW));
+        *val = set_field(*val, TH_VTYPE_CLEAR, 0);
+    }
+    return ret;
+}
+
 #if !defined(CONFIG_USER_ONLY)
+static RISCVException
+th_read_mstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    RISCVException ret = read_mstatus(env, csrno, val);
+    if (cpu->cfg.ext_xtheadvector) {
+        *val = set_field(*val, TH_MSTATUS_VS,
+                         get_field(*val, MSTATUS_VS));
+    }
+    return ret;
+}
+
+static RISCVException
+th_write_mstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    if (cpu->cfg.ext_xtheadvector) {
+        val = set_field(val, MSTATUS_VS,
+                        get_field(val, TH_MSTATUS_VS));
+    }
+    return write_mstatus(env, csrno, val);
+}
+
+static RISCVException
+th_read_sstatus(CPURISCVState *env, int csrno, target_ulong *val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    RISCVException ret = read_sstatus(env, csrno, val);
+    if (cpu->cfg.ext_xtheadvector) {
+        *val = set_field(*val, TH_MSTATUS_VS,
+                        get_field(*val, MSTATUS_VS));
+    }
+    return ret;
+}
+
+static RISCVException
+th_write_sstatus(CPURISCVState *env, int csrno, target_ulong val)
+{
+    RISCVCPU *cpu = env_archcpu(env);
+    if (cpu->cfg.ext_xtheadvector) {
+        val = set_field(val, MSTATUS_VS,
+                        get_field(val, TH_MSTATUS_VS));
+    }
+    return write_sstatus(env, csrno, val);
+}
+
 static RISCVException s_mode_csr(CPURISCVState *env, int csrno)
 {
     if (env->debugger)
@@ -63,13 +180,63 @@  static RISCVException read_th_sxstatus(CPURISCVState *env, int csrno,
 #endif
 
 static riscv_csr th_csr_list[] = {
+    {
+        .csrno = CSR_FCSR,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "fcsr", fs, th_read_fcsr, th_write_fcsr }
+    },
+    {
+        .csrno = CSR_VSTART,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vstart", th_vs, read_vstart, write_vstart }
+    },
+    {
+        .csrno = CSR_VXSAT,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vxsat", th_vs, read_vxsat, write_vxsat }
+    },
+    {
+        .csrno = CSR_VXRM,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vxrm", th_vs, read_vxrm, write_vxrm }
+    },
+    {
+        .csrno = CSR_VCSR,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vcsr", th_vs, read_vcsr, write_vcsr }
+    },
+    {
+        .csrno = CSR_VL,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vl", th_vs, read_vl}
+    },
+    {
+        .csrno = CSR_VTYPE,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vtype", th_vs, th_read_vtype}
+    },
+    {
+        .csrno = CSR_VLENB,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "vlenb", th_vs, read_vlenb}
+    },
 #if !defined(CONFIG_USER_ONLY)
+    {
+        .csrno = CSR_MSTATUS,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "mstatus", any, th_read_mstatus, th_write_mstatus}
+    },
+    {
+        .csrno = CSR_SSTATUS,
+        .insertion_test = test_thead_mvendorid,
+        .csr_ops = { "sstatus", smode, th_read_sstatus, th_write_sstatus}
+    },
     {
         .csrno = CSR_TH_SXSTATUS,
         .insertion_test = test_thead_mvendorid,
         .csr_ops = { "th.sxstatus", s_mode_csr, read_th_sxstatus }
     },
-#endif
+#endif /* !CONFIG_USER_ONLY */
 };
 
 void th_register_custom_csrs(RISCVCPU *cpu)