Hexagon HVX (target/hexagon) add Hexagon Vector eXtensions (HVX) to core

HVX is a set of wide vector instructions.  Machine state includes
    vector registers (VRegs)
    vector predicate registers (QRegs)
    temporary registers for intermediate values
    store buffer (masked stores and scatter/gather)

Acked-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Taylor Simpson <tsimpson@quicinc.com>
This commit is contained in:
Taylor Simpson 2021-03-17 11:48:57 -05:00
parent 375bcf389f
commit a1559537d1
6 changed files with 200 additions and 6 deletions

View File

@ -113,7 +113,66 @@ static void print_reg(FILE *f, CPUHexagonState *env, int regnum)
hexagon_regnames[regnum], value);
}
static void hexagon_dump(CPUHexagonState *env, FILE *f)
static void print_vreg(FILE *f, CPUHexagonState *env, int regnum,
bool skip_if_zero)
{
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES; i++) {
if (env->VRegs[regnum].ub[i] != 0) {
nonzero_found = true;
break;
}
}
if (!nonzero_found) {
return;
}
}
qemu_fprintf(f, " v%d = ( ", regnum);
qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1]);
for (int i = MAX_VEC_SIZE_BYTES - 2; i >= 0; i--) {
qemu_fprintf(f, ", 0x%02x", env->VRegs[regnum].ub[i]);
}
qemu_fprintf(f, " )\n");
}
void hexagon_debug_vreg(CPUHexagonState *env, int regnum)
{
print_vreg(stdout, env, regnum, false);
}
static void print_qreg(FILE *f, CPUHexagonState *env, int regnum,
bool skip_if_zero)
{
if (skip_if_zero) {
bool nonzero_found = false;
for (int i = 0; i < MAX_VEC_SIZE_BYTES / 8; i++) {
if (env->QRegs[regnum].ub[i] != 0) {
nonzero_found = true;
break;
}
}
if (!nonzero_found) {
return;
}
}
qemu_fprintf(f, " q%d = ( ", regnum);
qemu_fprintf(f, "0x%02x",
env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]);
for (int i = MAX_VEC_SIZE_BYTES / 8 - 2; i >= 0; i--) {
qemu_fprintf(f, ", 0x%02x", env->QRegs[regnum].ub[i]);
}
qemu_fprintf(f, " )\n");
}
void hexagon_debug_qreg(CPUHexagonState *env, int regnum)
{
print_qreg(stdout, env, regnum, false);
}
static void hexagon_dump(CPUHexagonState *env, FILE *f, int flags)
{
HexagonCPU *cpu = env_archcpu(env);
@ -159,6 +218,17 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f)
print_reg(f, env, HEX_REG_CS1);
#endif
qemu_fprintf(f, "}\n");
if (flags & CPU_DUMP_FPU) {
qemu_fprintf(f, "Vector Registers = {\n");
for (int i = 0; i < NUM_VREGS; i++) {
print_vreg(f, env, i, true);
}
for (int i = 0; i < NUM_QREGS; i++) {
print_qreg(f, env, i, true);
}
qemu_fprintf(f, "}\n");
}
}
static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
@ -166,12 +236,12 @@ static void hexagon_dump_state(CPUState *cs, FILE *f, int flags)
HexagonCPU *cpu = HEXAGON_CPU(cs);
CPUHexagonState *env = &cpu->env;
hexagon_dump(env, f);
hexagon_dump(env, f, flags);
}
void hexagon_debug(CPUHexagonState *env)
{
hexagon_dump(env, stdout);
hexagon_dump(env, stdout, CPU_DUMP_FPU);
}
static void hexagon_cpu_set_pc(CPUState *cs, vaddr value)
@ -292,7 +362,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void *data)
cc->set_pc = hexagon_cpu_set_pc;
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;
cc->tcg_ops = &hexagon_tcg_ops;

View File

@ -26,6 +26,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
#define TOTAL_PER_THREAD_REGS 64
@ -34,6 +35,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"
@ -52,6 +54,13 @@ typedef struct {
uint64_t data64;
} MemLog;
typedef struct {
target_ulong va;
int size;
DECLARE_BITMAP(mask, MAX_VEC_SIZE_BYTES) QEMU_ALIGNED(16);
MMVector data QEMU_ALIGNED(16);
} VStoreLog;
#define EXEC_STATUS_OK 0x0000
#define EXEC_STATUS_STOP 0x0002
#define EXEC_STATUS_REPLAY 0x0010
@ -64,6 +73,9 @@ typedef struct {
#define CLEAR_EXCEPTION (env->status &= (~EXEC_STATUS_EXCEPTION))
#define SET_EXCEPTION (env->status |= EXEC_STATUS_EXCEPTION)
/* Maximum number of vector temps in a packet */
#define VECTOR_TEMPS_MAX 4
struct CPUHexagonState {
target_ulong gpr[TOTAL_PER_THREAD_REGS];
target_ulong pred[NUM_PREGS];
@ -97,8 +109,27 @@ struct CPUHexagonState {
target_ulong llsc_val;
uint64_t llsc_val_i64;
target_ulong is_gather_store_insn;
target_ulong gather_issued;
MMVector VRegs[NUM_VREGS] QEMU_ALIGNED(16);
MMVector future_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
MMVector tmp_VRegs[VECTOR_TEMPS_MAX] QEMU_ALIGNED(16);
VRegMask VRegs_updated;
MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16);
MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16);
QRegMask QRegs_updated;
/* Temporaries used within instructions */
MMVectorPair VuuV QEMU_ALIGNED(16);
MMVectorPair VvvV QEMU_ALIGNED(16);
MMVectorPair VxxV QEMU_ALIGNED(16);
MMVector vtmp QEMU_ALIGNED(16);
MMQReg qtmp QEMU_ALIGNED(16);
VStoreLog vstore[VSTORES_MAX];
target_ulong vstore_pending[VSTORES_MAX];
bool vtcm_pending;
VTCMStoreLog vtcm_log;
};
#define HEXAGON_CPU_CLASS(klass) \

View File

@ -19,6 +19,7 @@
#define HEXAGON_ARCH_TYPES_H
#include "qemu/osdep.h"
#include "mmvec/mmvec.h"
#include "qemu/int128.h"
/*
@ -35,4 +36,8 @@ typedef uint64_t size8u_t;
typedef int64_t size8s_t;
typedef Int128 size16s_t;
typedef MMVector mmvector_t;
typedef MMVectorPair mmvector_pair_t;
typedef MMQReg mmqret_t;
#endif

View File

@ -67,6 +67,9 @@ struct Packet {
bool pkt_has_store_s0;
bool pkt_has_store_s1;
bool pkt_has_hvx;
Insn *vhist_insn;
Insn insn[INSTRUCTIONS_MAX];
};

View File

@ -31,6 +31,9 @@
int hexagon_gdb_read_register(CPUState *cpu, GByteArray *buf, int reg);
int hexagon_gdb_write_register(CPUState *cpu, uint8_t *buf, int reg);
void hexagon_debug_vreg(CPUHexagonState *env, int regnum);
void hexagon_debug_qreg(CPUHexagonState *env, int regnum);
void hexagon_debug(CPUHexagonState *env);
extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS];

View File

@ -0,0 +1,82 @@
/*
* Copyright(c) 2019-2021 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;
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 v[2];
} MMVectorPair;
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;
typedef struct {
MMVector data;
DECLARE_BITMAP(mask, MAX_VEC_SIZE_BYTES);
target_ulong va[MAX_VEC_SIZE_BYTES];
bool op;
int op_size;
} VTCMStoreLog;
/* 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 */
} VRegWriteType;
#endif