From nobody Sun Dec 14 06:15:38 2025 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail header.i=@quicinc.com; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=quicinc.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 1625528646529714.8527315884112; Mon, 5 Jul 2021 16:44:06 -0700 (PDT) Received: from localhost ([::1]:54256 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1m0YFx-00067S-Fd for importer@patchew.org; Mon, 05 Jul 2021 19:44:05 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:35470) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1m0Y71-0003Nk-F9 for qemu-devel@nongnu.org; Mon, 05 Jul 2021 19:34:51 -0400 Received: from alexa-out-sd-02.qualcomm.com ([199.106.114.39]:40183) by eggs.gnu.org with esmtps (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1m0Y6x-0004ez-T9 for qemu-devel@nongnu.org; Mon, 05 Jul 2021 19:34:51 -0400 Received: from unknown (HELO ironmsg-SD-alpha.qualcomm.com) ([10.53.140.30]) by alexa-out-sd-02.qualcomm.com with ESMTP; 05 Jul 2021 16:34:39 -0700 Received: from vu-tsimpson-aus.qualcomm.com (HELO vu-tsimpson1-aus.qualcomm.com) ([10.222.150.1]) by ironmsg-SD-alpha.qualcomm.com with ESMTP; 05 Jul 2021 16:34:38 -0700 Received: by vu-tsimpson1-aus.qualcomm.com (Postfix, from userid 47164) id D3B45B42; Mon, 5 Jul 2021 18:34:37 -0500 (CDT) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=quicinc.com; i=@quicinc.com; q=dns/txt; s=qcdkim; t=1625528087; x=1657064087; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=/y7FgE+4hANEVIAb3/Zu0xEpg50MnCodRitYzxWxuto=; b=Lh6NarjXLRjqB+mZZj5yb/MphF8QQ+2MTYov5Fgd7C8xdiU61MJ2ICdx L2ZGaDoykoYwSmPa6Ns9bHw5jfGGGCc5x9uvAs/g/Rhj7mCpfMC1s7CFj jF0CpcXGVTyk2NnbsiRpAwoAeQ8Bk3biZ2EDgQVmumZlYAJRBHAB5YQzu 4=; X-QCInternal: smtphost From: Taylor Simpson To: qemu-devel@nongnu.org Subject: [PATCH 02/20] Hexagon HVX (target/hexagon) add Hexagon Vector eXtensions (HVX) to core Date: Mon, 5 Jul 2021 18:34:16 -0500 Message-Id: <1625528074-19440-3-git-send-email-tsimpson@quicinc.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1625528074-19440-1-git-send-email-tsimpson@quicinc.com> References: <1625528074-19440-1-git-send-email-tsimpson@quicinc.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=199.106.114.39; envelope-from=tsimpson@qualcomm.com; helo=alexa-out-sd-02.qualcomm.com X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, HEADER_FROM_DIFFERENT_DOMAINS=0.249, RCVD_IN_DNSWL_MED=-2.3, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: ale@rev.ng, peter.maydell@linaro.org, bcain@quicinc.com, richard.henderson@linaro.org, tsimpson@quicinc.com, philmd@redhat.com Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1625528648359100001 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) Signed-off-by: Taylor Simpson --- target/hexagon/cpu.h | 35 ++++++++++++++++- target/hexagon/hex_arch_types.h | 5 +++ target/hexagon/insn.h | 3 ++ target/hexagon/internal.h | 3 ++ target/hexagon/mmvec/mmvec.h | 83 +++++++++++++++++++++++++++++++++++++= ++++ target/hexagon/cpu.c | 72 ++++++++++++++++++++++++++++++++++- 6 files changed, 198 insertions(+), 3 deletions(-) create mode 100644 target/hexagon/mmvec/mmvec.h diff --git a/target/hexagon/cpu.h b/target/hexagon/cpu.h index 2855dd3..0b377c3 100644 --- a/target/hexagon/cpu.h +++ b/target/hexagon/cpu.h @@ -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" =20 #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 =20 #define TYPE_HEXAGON_CPU "hexagon-cpu" =20 @@ -52,6 +54,13 @@ typedef struct { uint64_t data64; } MemLog; =20 +typedef struct { + target_ulong va; + int size; + MMVector mask QEMU_ALIGNED(16); + MMVector data QEMU_ALIGNED(16); +} VStoreLog; + #define EXEC_STATUS_OK 0x0000 #define EXEC_STATUS_STOP 0x0002 #define EXEC_STATUS_REPLAY 0x0010 @@ -98,7 +107,31 @@ struct CPUHexagonState { uint64_t llsc_val_i64; =20 target_ulong is_gather_store_insn; - target_ulong gather_issued; + bool gather_issued; + + MMVector VRegs[NUM_VREGS] QEMU_ALIGNED(16); + MMVector future_VRegs[NUM_VREGS] QEMU_ALIGNED(16); + MMVector tmp_VRegs[NUM_VREGS] QEMU_ALIGNED(16); + + VRegMask VRegs_updated_tmp; + VRegMask VRegs_updated; + VRegMask VRegs_select; + + MMQReg QRegs[NUM_QREGS] QEMU_ALIGNED(16); + MMQReg future_QRegs[NUM_QREGS] QEMU_ALIGNED(16); + QRegMask QRegs_updated; + + /* Temporaries used within instructions */ + MMVector zero_vector QEMU_ALIGNED(16); + MMVectorPair VddV QEMU_ALIGNED(16), + VuuV QEMU_ALIGNED(16), + VvvV QEMU_ALIGNED(16), + VxxV QEMU_ALIGNED(16); + + VStoreLog vstore[VSTORES_MAX]; + target_ulong vstore_pending[VSTORES_MAX]; + bool vtcm_pending; + VTCMStoreLog vtcm_log; }; =20 #define HEXAGON_CPU_CLASS(klass) \ diff --git a/target/hexagon/hex_arch_types.h b/target/hexagon/hex_arch_type= s.h index d721e1f..78ad607 100644 --- a/target/hexagon/hex_arch_types.h +++ b/target/hexagon/hex_arch_types.h @@ -19,6 +19,7 @@ #define HEXAGON_ARCH_TYPES_H =20 #include "qemu/osdep.h" +#include "mmvec/mmvec.h" #include "qemu/int128.h" =20 /* @@ -35,4 +36,8 @@ typedef uint64_t size8u_t; typedef int64_t size8s_t; typedef Int128 size16s_t; =20 +typedef MMVector mmvector_t; +typedef MMVectorPair mmvector_pair_t; +typedef MMQReg mmqret_t; + #endif diff --git a/target/hexagon/insn.h b/target/hexagon/insn.h index 2e34591..3872f90 100644 --- a/target/hexagon/insn.h +++ b/target/hexagon/insn.h @@ -67,6 +67,9 @@ struct Packet { bool pkt_has_store_s0; bool pkt_has_store_s1; =20 + bool pkt_has_hvx; + bool pkt_has_vhist; + Insn insn[INSTRUCTIONS_MAX]; }; =20 diff --git a/target/hexagon/internal.h b/target/hexagon/internal.h index 6b20aff..82ac304 100644 --- a/target/hexagon/internal.h +++ b/target/hexagon/internal.h @@ -31,6 +31,9 @@ =20 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); =20 extern const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS]; diff --git a/target/hexagon/mmvec/mmvec.h b/target/hexagon/mmvec/mmvec.h new file mode 100644 index 0000000..061ccce --- /dev/null +++ b/target/hexagon/mmvec/mmvec.h @@ -0,0 +1,83 @@ +/* + * Copyright(c) 2019-2021 Qualcomm Innovation Center, Inc. All Rights Res= erved. + * + * 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 . + */ + +#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; + MMVector mask; + int size; + 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 diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c index 3338365..4c7eaff 100644 --- a/target/hexagon/cpu.c +++ b/target/hexagon/cpu.c @@ -59,7 +59,7 @@ const char * const hexagon_regnames[TOTAL_PER_THREAD_REGS= ] =3D { "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31", "sa0", "lc0", "sa1", "lc1", "p3_0", "c5", "m0", "m1", "usr", "pc", "ugp", "gp", "cs0", "cs1", "c14", "c15", - "c16", "c17", "c18", "c19", "pkt_cnt", "insn_cnt", "c22", "c23", + "c16", "c17", "c18", "c19", "pkt_cnt", "insn_cnt", "hvx_cnt", "c23", "c24", "c25", "c26", "c27", "c28", "c29", "c30", "c31", }; =20 @@ -113,6 +113,57 @@ static void print_reg(FILE *f, CPUHexagonState *env, i= nt regnum) hexagon_regnames[regnum], value); } =20 +static void print_vreg(FILE *f, CPUHexagonState *env, int regnum) +{ + bool nonzero_found =3D false; + int i; + qemu_fprintf(f, " v%d =3D ( ", regnum); + qemu_fprintf(f, "0x%02x", env->VRegs[regnum].ub[MAX_VEC_SIZE_BYTES - 1= ]); + for (i =3D MAX_VEC_SIZE_BYTES - 2; i >=3D 0; i--) { + if (env->VRegs[regnum].ub[i] !=3D 0) { + nonzero_found =3D true; + break; + } + } + if (nonzero_found) { + for (i =3D MAX_VEC_SIZE_BYTES - 2; i >=3D 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); +} + +static void print_qreg(FILE *f, CPUHexagonState *env, int regnum) +{ + bool nonzero_found =3D false; + int i; + qemu_fprintf(f, " q%d =3D ( ", regnum); + qemu_fprintf(f, "0x%02x", + env->QRegs[regnum].ub[MAX_VEC_SIZE_BYTES / 8 - 1]); + for (i =3D MAX_VEC_SIZE_BYTES / 8 - 2; i >=3D 0; i--) { + if (env->QRegs[regnum].ub[i] !=3D 0) { + nonzero_found =3D true; + break; + } + } + if (nonzero_found) { + for (i =3D MAX_VEC_SIZE_BYTES / 8 - 2; i >=3D 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); +} + static void hexagon_dump(CPUHexagonState *env, FILE *f) { HexagonCPU *cpu =3D env_archcpu(env); @@ -159,6 +210,22 @@ static void hexagon_dump(CPUHexagonState *env, FILE *f) print_reg(f, env, HEX_REG_CS1); #endif qemu_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 + qemu_fprintf(f, "Vector Registers =3D {\n"); + for (int i =3D 0; i < NUM_VREGS; i++) { + print_vreg(f, env, i); + } + for (int i =3D 0; i < NUM_QREGS; i++) { + print_qreg(f, env, i); + } + qemu_fprintf(f, "}\n"); +#endif } =20 static void hexagon_dump_state(CPUState *cs, FILE *f, int flags) @@ -211,6 +278,7 @@ static void hexagon_cpu_reset(DeviceState *dev) =20 set_default_nan_mode(1, &env->fp_status); set_float_detect_tininess(float_tininess_before_rounding, &env->fp_sta= tus); + memset(&env->zero_vector, 0, sizeof(MMVector)); } =20 static void hexagon_cpu_disas_set_info(CPUState *s, disassemble_info *info) @@ -292,7 +360,7 @@ static void hexagon_cpu_class_init(ObjectClass *c, void= *data) cc->set_pc =3D hexagon_cpu_set_pc; cc->gdb_read_register =3D hexagon_gdb_read_register; cc->gdb_write_register =3D hexagon_gdb_write_register; - cc->gdb_num_core_regs =3D TOTAL_PER_THREAD_REGS; + cc->gdb_num_core_regs =3D TOTAL_PER_THREAD_REGS + NUM_VREGS + NUM_QREG= S; cc->gdb_stop_before_watchpoint =3D true; cc->disas_set_info =3D hexagon_cpu_disas_set_info; cc->tcg_ops =3D &hexagon_tcg_ops; --=20 2.7.4