diff mbox series

[RFC,v2,54/67] Hexagon - Add Hexagon Vector eXtensions (HVX) to core definition

Message ID 1582908244-304-55-git-send-email-tsimpson@quicinc.com (mailing list archive)
State New, archived
Headers show
Series Hexagon patch series | expand

Commit Message

Taylor Simpson Feb. 28, 2020, 4:43 p.m. UTC
HVX is a set of wide vector instructions.  Machine state includes
    vector registers (VRegs)
    vector predicate registers (QRegs)
    temporary registers for packet semantics
    store buffer (masked stores and scatter/gather)

Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
---
 target/hexagon/cpu.h         | 42 +++++++++++++++++++++
 target/hexagon/insn.h        | 16 ++++++++
 target/hexagon/internal.h    |  2 +
 target/hexagon/mmvec/mmvec.h | 87 ++++++++++++++++++++++++++++++++++++++++++++
 target/hexagon/cpu.c         | 51 +++++++++++++++++++++++++-
 5 files changed, 197 insertions(+), 1 deletion(-)
 create mode 100644 target/hexagon/mmvec/mmvec.h
diff mbox series

Patch

diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h
index 6146561..6215f91 100644
--- a/target/hexagon/cpu.h
+++ b/target/hexagon/cpu.h
@@ -30,6 +30,7 @@  typedef struct CPUHexagonState CPUHexagonState;
 #include "qemu-common.h"
 #include "exec/cpu-defs.h"
 #include "hex_regs.h"
+#include "mmvec/mmvec.h"
 
 #define NUM_PREGS 4
 #ifdef CONFIG_USER_ONLY
@@ -42,6 +43,7 @@  typedef struct CPUHexagonState CPUHexagonState;
 #define STORES_MAX 2
 #define REG_WRITES_MAX 32
 #define PRED_WRITES_MAX 5                   /* 4 insns + endloop */
+#define VSTORES_MAX 2
 
 #define TYPE_HEXAGON_CPU "hexagon-cpu"
 
@@ -60,6 +62,19 @@  struct MemLog {
     uint64_t data64;
 };
 
+typedef struct {
+    target_ulong va;
+    int size;
+    mmvector_t mask;
+    mmvector_t data;
+} vstorelog_t;
+
+typedef struct {
+    unsigned char cdata[256];
+    uint32_t range;
+    uint8_t format;
+} mem_access_info_t;
+
 #define EXEC_STATUS_OK          0x0000
 #define EXEC_STATUS_STOP        0x0002
 #define EXEC_STATUS_REPLAY      0x0010
@@ -72,6 +87,9 @@  struct MemLog {
 #define CLEAR_EXCEPTION         (env->status &= (~EXEC_STATUS_EXCEPTION))
 #define SET_EXCEPTION           (env->status |= EXEC_STATUS_EXCEPTION)
 
+/* This needs to be large enough for all the reads and writes in a packet */
+#define TEMP_VECTORS_MAX        25
+
 struct CPUHexagonState {
     target_ulong gpr[TOTAL_PER_THREAD_REGS];
     target_ulong pred[NUM_PREGS];
@@ -110,6 +128,30 @@  struct CPUHexagonState {
 
     target_ulong is_gather_store_insn;
     target_ulong gather_issued;
+
+    mmvector_t VRegs[NUM_VREGS];
+    mmvector_t future_VRegs[NUM_VREGS];
+    mmvector_t tmp_VRegs[NUM_VREGS];
+
+    VRegMask VRegs_updated_tmp;
+    VRegMask VRegs_updated;
+    VRegMask VRegs_select;
+
+    mmqreg_t QRegs[NUM_QREGS];
+    mmqreg_t future_QRegs[NUM_QREGS];
+    QRegMask QRegs_updated;
+
+    vstorelog_t vstore[VSTORES_MAX];
+    uint8_t store_pending[VSTORES_MAX];
+    uint8_t vstore_pending[VSTORES_MAX];
+    uint8_t vtcm_pending;
+    vtcm_storelog_t vtcm_log;
+    mem_access_info_t mem_access[SLOTS_MAX];
+
+    int status;
+
+    mmvector_t temp_vregs[TEMP_VECTORS_MAX];
+    mmqreg_t temp_qregs[TEMP_VECTORS_MAX];
 };
 
 #define HEXAGON_CPU_CLASS(klass) \
diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h
index a80bcb9..16d298d 100644
--- a/target/hexagon/insn.h
+++ b/target/hexagon/insn.h
@@ -49,12 +49,16 @@  struct Instruction {
     size4u_t is_dcfetch:1;   /* Has an A_DCFETCH attribute */
     size4u_t is_load:1;      /* Has A_LOAD attribute */
     size4u_t is_store:1;     /* Has A_STORE attribute */
+    size4u_t is_vmem_ld:1;   /* Has an A_LOAD and an A_VMEM attribute */
+    size4u_t is_vmem_st:1;   /* Has an A_STORE and an A_VMEM attribute */
+    size4u_t is_scatgath:1;  /* Has an A_CVI_GATHER or A_CVI_SCATTER attr */
     size4u_t is_memop:1;     /* Has A_MEMOP attribute */
     size4u_t is_dealloc:1;   /* Is a dealloc return or dealloc frame */
     size4u_t is_aia:1;       /* Is a post increment */
     size4u_t is_endloop:1;   /* This is an end of loop */
     size4u_t is_2nd_jump:1;  /* This is the second jump of a dual-jump packet */
     size4u_t new_value_producer_slot:4;
+    size4u_t hvx_resource:8;
     size4s_t immed[IMMEDS_MAX];    /* immediate field */
 };
 
@@ -121,10 +125,22 @@  struct Packet {
 
     /* Misc */
     size8u_t num_rops:4;            /* Num risc ops in the packet */
+    size8u_t pkt_has_vtcm_access:1; /* Is a vmem access going to VTCM */
     size8u_t pkt_access_count:2;    /* Is a vmem access going to VTCM */
     size8u_t pkt_ldaccess_l2:2;     /* vmem ld access to l2 */
     size8u_t pkt_ldaccess_vtcm:2;   /* vmem ld access to vtcm */
 
+    /* Count the types of HVX instructions */
+    size8u_t pkt_hvx_va:4;
+    size8u_t pkt_hvx_vx:4;
+    size8u_t pkt_hvx_vp:4;
+    size8u_t pkt_hvx_vs:4;
+    size8u_t pkt_hvx_all:4;
+    size8u_t pkt_hvx_none:4;
+
+    size8u_t pkt_has_hvx:1;
+    size8u_t pkt_has_extension:1;
+
     insn_t insn[INSTRUCTIONS_MAX];
 };
 
diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h
index 092dedc..4ff7020 100644
--- a/target/hexagon/internal.h
+++ b/target/hexagon/internal.h
@@ -39,6 +39,8 @@ 
 extern int hexagon_gdb_read_register(CPUState *cpu, uint8_t *buf, int reg);
 extern int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
 
+extern void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
+extern void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
 extern void hexagon_debug(CPUHexagonState *env);
 
 #if COUNT_HEX_HELPERS
diff --git a/target/hexagon/mmvec/mmvec.h b/target/hexagon/mmvec/mmvec.h
new file mode 100644
index 0000000..145af15
--- /dev/null
+++ b/target/hexagon/mmvec/mmvec.h
@@ -0,0 +1,87 @@ 
+/*
+ *  Copyright(c) 2019-2020 Qualcomm Innovation Center, Inc. All Rights Reserved.
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef HEXAGON_MMVEC_H
+#define HEXAGON_MMVEC_H
+
+#define MAX_VEC_SIZE_LOGBYTES 7
+#define MAX_VEC_SIZE_BYTES  (1 << MAX_VEC_SIZE_LOGBYTES)
+
+#define NUM_VREGS           32
+#define NUM_QREGS           4
+
+typedef uint32_t VRegMask; /* at least NUM_VREGS bits */
+typedef uint32_t QRegMask; /* at least NUM_QREGS bits */
+
+#define VECTOR_SIZE_BYTE    (fVECSIZE())
+
+typedef union {
+    uint64_t ud[MAX_VEC_SIZE_BYTES / 8];
+    int64_t   d[MAX_VEC_SIZE_BYTES / 8];
+    uint32_t uw[MAX_VEC_SIZE_BYTES / 4];
+    int32_t   w[MAX_VEC_SIZE_BYTES / 4];
+    uint16_t uh[MAX_VEC_SIZE_BYTES / 2];
+    int16_t   h[MAX_VEC_SIZE_BYTES / 2];
+    uint8_t  ub[MAX_VEC_SIZE_BYTES / 1];
+    int8_t    b[MAX_VEC_SIZE_BYTES / 1];
+} mmvector_t;
+
+typedef union {
+    uint64_t ud[2 * MAX_VEC_SIZE_BYTES / 8];
+    int64_t   d[2 * MAX_VEC_SIZE_BYTES / 8];
+    uint32_t uw[2 * MAX_VEC_SIZE_BYTES / 4];
+    int32_t   w[2 * MAX_VEC_SIZE_BYTES / 4];
+    uint16_t uh[2 * MAX_VEC_SIZE_BYTES / 2];
+    int16_t   h[2 * MAX_VEC_SIZE_BYTES / 2];
+    uint8_t  ub[2 * MAX_VEC_SIZE_BYTES / 1];
+    int8_t    b[2 * MAX_VEC_SIZE_BYTES / 1];
+    mmvector_t v[2];
+} mmvector_pair_t;
+
+typedef union {
+    uint64_t ud[MAX_VEC_SIZE_BYTES / 8 / 8];
+    int64_t   d[MAX_VEC_SIZE_BYTES / 8 / 8];
+    uint32_t uw[MAX_VEC_SIZE_BYTES / 4 / 8];
+    int32_t   w[MAX_VEC_SIZE_BYTES / 4 / 8];
+    uint16_t uh[MAX_VEC_SIZE_BYTES / 2 / 8];
+    int16_t   h[MAX_VEC_SIZE_BYTES / 2 / 8];
+    uint8_t  ub[MAX_VEC_SIZE_BYTES / 1 / 8];
+    int8_t    b[MAX_VEC_SIZE_BYTES / 1 / 8];
+} mmqreg_t;
+
+typedef struct {
+    mmvector_t data;
+    mmvector_t mask;
+    mmvector_pair_t offsets;
+    int size;
+    target_ulong va_base;
+    target_ulong va[MAX_VEC_SIZE_BYTES];
+    int oob_access;
+    int op;
+    int op_size;
+} vtcm_storelog_t;
+
+
+/* Types of vector register assignment */
+typedef enum {
+    EXT_DFL,      /* Default */
+    EXT_NEW,      /* New - value used in the same packet */
+    EXT_TMP       /* Temp - value used but not stored to register */
+} vector_dst_type_t;
+
+#endif
+
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 576c566..ccbc113 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -122,6 +122,39 @@  static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
     fprintf(f, "  %s = 0x" TARGET_FMT_lx "\n", hexagon_regnames[regnum], value);
 }
 
+static void print_vreg(FILE *f, CPUHexagonState *env, int regnum)
+{
+    int i;
+    fprintf(f, "  v%d = (", regnum);
+    fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
+    for (i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
+        fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
+    }
+    fprintf(f, ")\n");
+}
+
+void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
+{
+    print_vreg(stdout, env, regnum);
+}
+
+static void print_qreg(FILE *f, CPUHexagonState *env, int regnum)
+{
+    int i;
+    fprintf(f, "  q%d = (", regnum);
+    fprintf(f, ", 0x%02x",
+                env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
+    for (i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
+        fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
+    }
+    fprintf(f, ")\n");
+}
+
+void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
+{
+    print_qreg(stdout, env, regnum);
+}
+
 static void hexagon_dump(CPUHexagonState *env, FILE *f)
 {
     static target_ulong last_pc;
@@ -166,6 +199,22 @@  static void hexagon_dump(CPUHexagonState *env, FILE *f)
     print_reg(f, env, HEX_REG_CS1);
 #endif
     fprintf(f, "}\n");
+
+/*
+ * The HVX register dump takes up a ton of space in the log
+ * Don't print it unless it is needed
+ */
+#define DUMP_HVX 0
+#if DUMP_HVX
+    fprintf(f, "Vector Registers = {\n");
+    for (i = 0; i < NUM_VREGS; i++) {
+        print_vreg(f, env, i);
+    }
+    for (i = 0; i < NUM_QREGS; i++) {
+        print_qreg(f, env, i);
+    }
+    fprintf(f, "}\n");
+#endif
 }
 
 static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
@@ -291,7 +340,7 @@  static void hexagon_cpu_class_init(ObjectClass *c, void *data)
     cc->gdb_core_xml_file = "hexagon-core.xml";
     cc->gdb_read_register = hexagon_gdb_read_register;
     cc->gdb_write_register = hexagon_gdb_write_register;
-    cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS;
+    cc->gdb_num_core_regs = TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREGS;
     cc->gdb_stop_before_watchpoint = true;
     cc->disas_set_info = hexagon_cpu_disas_set_info;
 #ifdef CONFIG_TCG