From 4477cf59f7a939e91a2c216a723c9e6949785f81 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 16 Feb 2023 08:28:25 +0800 Subject: [PATCH 001/155] triggers: remove mcontrol6.timing (implement suggested trigger timings) --- riscv/triggers.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 5a2d18b20c..4957dd43f4 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -272,7 +272,6 @@ reg_t mcontrol6_t::tdata1_read(const processor_t * const proc) const noexcept { tdata1 = set_field(tdata1, CSR_MCONTROL6_VU, proc->extension_enabled('H') ? vu : 0); tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT, hit); tdata1 = set_field(tdata1, CSR_MCONTROL6_SELECT, select); - tdata1 = set_field(tdata1, CSR_MCONTROL6_TIMING, timing); tdata1 = set_field(tdata1, CSR_MCONTROL6_ACTION, action); tdata1 = set_field(tdata1, CSR_MCONTROL6_CHAIN, chain); tdata1 = set_field(tdata1, CSR_MCONTROL6_MATCH, match); @@ -293,7 +292,6 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const vu = get_field(val, CSR_MCONTROL6_VU); hit = get_field(val, CSR_MCONTROL6_HIT); select = get_field(val, CSR_MCONTROL6_SELECT); - timing = legalize_timing(val, CSR_MCONTROL6_TIMING, CSR_MCONTROL6_SELECT, CSR_MCONTROL6_EXECUTE, CSR_MCONTROL6_LOAD); action = legalize_action(val, CSR_MCONTROL6_ACTION, CSR_MCONTROL6_DMODE(xlen)); chain = allow_chain ? get_field(val, CSR_MCONTROL6_CHAIN) : 0; match = legalize_match(get_field(val, CSR_MCONTROL6_MATCH)); @@ -303,6 +301,11 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const execute = get_field(val, CSR_MCONTROL6_EXECUTE); store = get_field(val, CSR_MCONTROL6_STORE); load = get_field(val, CSR_MCONTROL6_LOAD); + + /* GDB doesn't support setting triggers in a way that combines a data load trigger + * with an address trigger to trigger on a load of a value at a given address. + * The default timing legalization on mcontrol6 assumes no such trigger setting. */ + timing = legalize_timing(val, 0, CSR_MCONTROL6_SELECT, CSR_MCONTROL6_EXECUTE, CSR_MCONTROL6_LOAD); } std::optional icount_t::detect_icount_fire(processor_t * const proc) noexcept From 983eb01557e0f447fbbcb29d088bfa682787c427 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 16 Feb 2023 08:47:21 +0800 Subject: [PATCH 002/155] triggers: refactor: update debug_defines.h Update CSR_MCONTROL6_HIT to CSR_MCONTROL6_HIT0 Include CSR_TINFO_VERSION* macros --- riscv/debug_defines.h | 2554 +++++++++++++++++++++-------------------- riscv/triggers.cc | 4 +- 2 files changed, 1340 insertions(+), 1218 deletions(-) diff --git a/riscv/debug_defines.h b/riscv/debug_defines.h index 06ba082d95..bf2dda0d96 100644 --- a/riscv/debug_defines.h +++ b/riscv/debug_defines.h @@ -1,21 +1,21 @@ -/* - * This file is auto-generated by running 'make debug_defines.h' in - * https://github.com/riscv/riscv-debug-spec/ (0e4d91e) - */ +/* SPDX-License-Identifier: BSD-2-Clause OR CC-BY-4.0 */ +/* This file was auto-generated by running 'make debug_defines' in https://github.com/riscv/riscv-debug-spec/ (bc20adc) */ +#ifndef DEBUG_DEFINES_H +#define DEBUG_DEFINES_H #define DTM_IDCODE 0x01 /* * Identifies the release version of this part. */ -#define DTM_IDCODE_VERSION_OFFSET 0x1c -#define DTM_IDCODE_VERSION_LENGTH 4 -#define DTM_IDCODE_VERSION 0xf0000000U +#define DTM_IDCODE_VERSION_OFFSET 0x1cULL +#define DTM_IDCODE_VERSION_LENGTH 4ULL +#define DTM_IDCODE_VERSION 0xf0000000ULL /* * Identifies the designer's part number of this part. */ -#define DTM_IDCODE_PARTNUMBER_OFFSET 0xc -#define DTM_IDCODE_PARTNUMBER_LENGTH 0x10 -#define DTM_IDCODE_PARTNUMBER 0xffff000 +#define DTM_IDCODE_PARTNUMBER_OFFSET 0xcULL +#define DTM_IDCODE_PARTNUMBER_LENGTH 0x10ULL +#define DTM_IDCODE_PARTNUMBER 0xffff000ULL /* * Identifies the designer/manufacturer of this part. Bits 6:0 must be * bits 6:0 of the designer/manufacturer's Identification Code as @@ -23,13 +23,46 @@ * count of the number of continuation characters (0x7f) in that same * Identification Code. */ -#define DTM_IDCODE_MANUFID_OFFSET 1 -#define DTM_IDCODE_MANUFID_LENGTH 0xb -#define DTM_IDCODE_MANUFID 0xffe -#define DTM_IDCODE_1_OFFSET 0 -#define DTM_IDCODE_1_LENGTH 1 -#define DTM_IDCODE_1 1 +#define DTM_IDCODE_MANUFID_OFFSET 1ULL +#define DTM_IDCODE_MANUFID_LENGTH 0xbULL +#define DTM_IDCODE_MANUFID 0xffeULL +#define DTM_IDCODE_1_OFFSET 0ULL +#define DTM_IDCODE_1_LENGTH 1ULL +#define DTM_IDCODE_1 1ULL #define DTM_DTMCS 0x10 +/* + * This optional field may provide additional detail about an error + * that occurred when communicating with a DM. It is updated whenever + * {dmi-op} is updated by the hardware or when 1 is written to + * {dtmcs-dmireset}. + */ +#define DTM_DTMCS_ERRINFO_OFFSET 0x12ULL +#define DTM_DTMCS_ERRINFO_LENGTH 3ULL +#define DTM_DTMCS_ERRINFO 0x1c0000ULL +/* + * not implemented: This field is not implemented. + */ +#define DTM_DTMCS_ERRINFO_NOT_IMPLEMENTED 0 +/* + * dmi error: There was an error between the DTM and DMI. + */ +#define DTM_DTMCS_ERRINFO_DMI_ERROR 1 +/* + * communication error: There was an error between the DMI and a DMI subordinate. + */ +#define DTM_DTMCS_ERRINFO_COMMUNICATION_ERROR 2 +/* + * device error: The DMI subordinate reported an error. + */ +#define DTM_DTMCS_ERRINFO_DEVICE_ERROR 3 +/* + * unknown: There is no error to report, or no further information available + * about the error. This is the reset value if the field is implemented. + */ +#define DTM_DTMCS_ERRINFO_UNKNOWN 4 +/* + * Other values are reserved for future use by this specification. + */ /* * Writing 1 to this bit does a hard reset of the DTM, * causing the DTM to forget about any outstanding DMI transactions, and @@ -39,22 +72,22 @@ * complete (e.g. a reset condition caused an inflight DMI transaction to * be cancelled). */ -#define DTM_DTMCS_DMIHARDRESET_OFFSET 0x11 -#define DTM_DTMCS_DMIHARDRESET_LENGTH 1 -#define DTM_DTMCS_DMIHARDRESET 0x20000 +#define DTM_DTMCS_DTMHARDRESET_OFFSET 0x11ULL +#define DTM_DTMCS_DTMHARDRESET_LENGTH 1ULL +#define DTM_DTMCS_DTMHARDRESET 0x20000ULL /* - * Writing 1 to this bit clears the sticky error state, but does - * not affect outstanding DMI transactions. + * Writing 1 to this bit clears the sticky error state and resets + * {dtmcs-errinfo}, but does not affect outstanding DMI transactions. */ -#define DTM_DTMCS_DMIRESET_OFFSET 0x10 -#define DTM_DTMCS_DMIRESET_LENGTH 1 -#define DTM_DTMCS_DMIRESET 0x10000 +#define DTM_DTMCS_DMIRESET_OFFSET 0x10ULL +#define DTM_DTMCS_DMIRESET_LENGTH 1ULL +#define DTM_DTMCS_DMIRESET 0x10000ULL /* * This is a hint to the debugger of the minimum number of * cycles a debugger should spend in * Run-Test/Idle after every DMI scan to avoid a `busy' - * return code (\FdtmDtmcsDmistat of 3). A debugger must still - * check \FdtmDtmcsDmistat when necessary. + * return code ({dtmcs-dmistat} of 3). A debugger must still + * check {dtmcs-dmistat} when necessary. * * 0: It is not necessary to enter Run-Test/Idle at all. * @@ -64,24 +97,24 @@ * * And so on. */ -#define DTM_DTMCS_IDLE_OFFSET 0xc -#define DTM_DTMCS_IDLE_LENGTH 3 -#define DTM_DTMCS_IDLE 0x7000 +#define DTM_DTMCS_IDLE_OFFSET 0xcULL +#define DTM_DTMCS_IDLE_LENGTH 3ULL +#define DTM_DTMCS_IDLE 0x7000ULL /* - * Read-only alias of \FdtmDmiOp. + * Read-only alias of {dmi-op}. */ -#define DTM_DTMCS_DMISTAT_OFFSET 0xa -#define DTM_DTMCS_DMISTAT_LENGTH 2 -#define DTM_DTMCS_DMISTAT 0xc00 +#define DTM_DTMCS_DMISTAT_OFFSET 0xaULL +#define DTM_DTMCS_DMISTAT_LENGTH 2ULL +#define DTM_DTMCS_DMISTAT 0xc00ULL /* - * The size of \FdmSbaddressZeroAddress in \RdtmDmi. + * The size of {sbaddress0-address} in {dtm-dmi}. */ -#define DTM_DTMCS_ABITS_OFFSET 4 -#define DTM_DTMCS_ABITS_LENGTH 6 -#define DTM_DTMCS_ABITS 0x3f0 -#define DTM_DTMCS_VERSION_OFFSET 0 -#define DTM_DTMCS_VERSION_LENGTH 4 -#define DTM_DTMCS_VERSION 0xf +#define DTM_DTMCS_ABITS_OFFSET 4ULL +#define DTM_DTMCS_ABITS_LENGTH 6ULL +#define DTM_DTMCS_ABITS 0x3f0ULL +#define DTM_DTMCS_VERSION_OFFSET 0ULL +#define DTM_DTMCS_VERSION_LENGTH 4ULL +#define DTM_DTMCS_VERSION 0xfULL /* * 0.11: Version described in spec version 0.11. */ @@ -98,48 +131,50 @@ /* * Address used for DMI access. In Update-DR this value is used * to access the DM over the DMI. + * {dmi-op} defines what this register contains after every possible + * operation. */ -#define DTM_DMI_ADDRESS_OFFSET 0x22 -#define DTM_DMI_ADDRESS_LENGTH(abits) abits -#define DTM_DMI_ADDRESS(abits) ((0x400000000ULL * (1ULL<> for priorities. */ -#define CSR_DCSR_CAUSE_OFFSET 6 -#define CSR_DCSR_CAUSE_LENGTH 3 -#define CSR_DCSR_CAUSE 0x1c0 +#define CSR_DCSR_CAUSE_OFFSET 6ULL +#define CSR_DCSR_CAUSE_LENGTH 3ULL +#define CSR_DCSR_CAUSE 0x1c0ULL /* - * ebreak: An {\tt ebreak} instruction was executed. + * ebreak: An `ebreak` instruction was executed. */ #define CSR_DCSR_CAUSE_EBREAK 1 /* @@ -336,15 +431,15 @@ */ #define CSR_DCSR_CAUSE_TRIGGER 2 /* - * haltreq: The debugger requested entry to Debug Mode using \FdmDmcontrolHaltreq. + * haltreq: The debugger requested entry to Debug Mode using {dmcontrol-haltreq}. */ #define CSR_DCSR_CAUSE_HALTREQ 3 /* - * step: The hart single stepped because \FcsrDcsrStep was set. + * step: The hart single stepped because {dcsr-step} was set. */ #define CSR_DCSR_CAUSE_STEP 4 /* - * resethaltreq: The hart halted directly out of reset due to \Fresethaltreq. It + * resethaltreq: The hart halted directly out of reset due to {resethaltreq} It * is also acceptable to report 3 when this happens. */ #define CSR_DCSR_CAUSE_RESETHALTREQ 5 @@ -354,28 +449,29 @@ */ #define CSR_DCSR_CAUSE_GROUP 6 /* - * Other values are reserved for future use. + * other: The hart halted for a reason other than the ones mentioned above. + * {dcsr-extcause} may contain a more specific reason. */ +#define CSR_DCSR_CAUSE_OTHER 7 /* * Extends the prv field with the virtualization mode the hart was operating - * in when Debug Mode was entered. The encoding is described in Table - * \ref{tab:privmode}. + * in when Debug Mode was entered. The encoding is described in <>. * A debugger can change this value to change the hart's virtualization mode * when exiting Debug Mode. * This bit is hardwired to 0 on harts that do not support virtualization mode. */ -#define CSR_DCSR_V_OFFSET 5 -#define CSR_DCSR_V_LENGTH 1 -#define CSR_DCSR_V 0x20 -#define CSR_DCSR_MPRVEN_OFFSET 4 -#define CSR_DCSR_MPRVEN_LENGTH 1 -#define CSR_DCSR_MPRVEN 0x10 +#define CSR_DCSR_V_OFFSET 5ULL +#define CSR_DCSR_V_LENGTH 1ULL +#define CSR_DCSR_V 0x20ULL +#define CSR_DCSR_MPRVEN_OFFSET 4ULL +#define CSR_DCSR_MPRVEN_LENGTH 1ULL +#define CSR_DCSR_MPRVEN 0x10ULL /* - * disabled: \FcsrMstatusMprv in \Rmstatus is ignored in Debug Mode. + * disabled: `mprv` in `mstatus` is ignored in Debug Mode. */ #define CSR_DCSR_MPRVEN_DISABLED 0 /* - * enabled: \FcsrMstatusMprv in \Rmstatus takes effect in Debug Mode. + * enabled: `mprv` in `mstatus` takes effect in Debug Mode. */ #define CSR_DCSR_MPRVEN_ENABLED 1 /* @@ -388,49 +484,54 @@ * reliable debugging may no longer be possible once this bit becomes set. * This is implementation-dependent. */ -#define CSR_DCSR_NMIP_OFFSET 3 -#define CSR_DCSR_NMIP_LENGTH 1 -#define CSR_DCSR_NMIP 8 +#define CSR_DCSR_NMIP_OFFSET 3ULL +#define CSR_DCSR_NMIP_LENGTH 1ULL +#define CSR_DCSR_NMIP 8ULL /* * When set and not in Debug Mode, the hart will only execute a single - * instruction and then enter Debug Mode. See Section~\ref{stepBit} + * instruction and then enter Debug Mode. See xref:stepbit[] * for details. * * The debugger must not change the value of this bit while the hart * is running. */ -#define CSR_DCSR_STEP_OFFSET 2 -#define CSR_DCSR_STEP_LENGTH 1 -#define CSR_DCSR_STEP 4 +#define CSR_DCSR_STEP_OFFSET 2ULL +#define CSR_DCSR_STEP_LENGTH 1ULL +#define CSR_DCSR_STEP 4ULL /* * Contains the privilege mode the hart was operating in when Debug - * Mode was entered. The encoding is described in Table - * \ref{tab:privmode}. A debugger can change this value to change + * Mode was entered. The encoding is described in <>. A debugger can change this value to change * the hart's privilege mode when exiting Debug Mode. * * Not all privilege modes are supported on all harts. If the * encoding written is not supported or the debugger is not allowed to * change to it, the hart may change to any supported privilege mode. */ -#define CSR_DCSR_PRV_OFFSET 0 -#define CSR_DCSR_PRV_LENGTH 2 -#define CSR_DCSR_PRV 3 +#define CSR_DCSR_PRV_OFFSET 0ULL +#define CSR_DCSR_PRV_LENGTH 2ULL +#define CSR_DCSR_PRV 3ULL #define CSR_DPC 0x7b1 -#define CSR_DPC_DPC_OFFSET 0 -#define CSR_DPC_DPC_LENGTH(DXLEN) DXLEN -#define CSR_DPC_DPC(DXLEN) ((1ULL< 0, otherwise it's undefined on what conditions the * trigger will match. */ #define CSR_MCONTROL_MATCH_NAPOT 1 /* * ge: Matches when any compare value is greater than (unsigned) or - * equal to \RcsrTdataTwo. + * equal to {csr-tdata2}. */ #define CSR_MCONTROL_MATCH_GE 2 /* * lt: Matches when any compare value is less than (unsigned) - * \RcsrTdataTwo. + * {csr-tdata2}. */ #define CSR_MCONTROL_MATCH_LT 3 /* - * mask low: Matches when $\frac{|XLEN|}{2}-1$:$0$ of any compare value - * equals $\frac{|XLEN|}{2}-1$:$0$ of \RcsrTdataTwo after - * $\frac{|XLEN|}{2}-1$:$0$ of the compare value is ANDed with - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of \RcsrTdataTwo. + * mask low: Matches when latexmath:[$\frac{XLEN}{2}-{1:0}] of any compare value + * equals latexmath:[$\frac{XLEN}{2}-{1:0}] of {csr-tdata2} after + * latexmath:[$\frac{XLEN}{2}-{1:0}] of the compare value is ANDed with + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of {csr-tdata2}. */ #define CSR_MCONTROL_MATCH_MASK_LOW 4 /* - * mask high: Matches when $|XLEN|-1$:$\frac{|XLEN|}{2}$ of any compare - * value equals $\frac{|XLEN|}{2}-1$:$0$ of \RcsrTdataTwo after - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of the compare value is ANDed with - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of \RcsrTdataTwo. + * mask high: Matches when `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of any compare + * value equals latexmath:[$\frac{XLEN}{2}-{1:0}] of {csr-tdata2} after + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of the compare value is ANDed with + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of {csr-tdata2}. */ #define CSR_MCONTROL_MATCH_MASK_HIGH 5 /* - * not equal: Matches when \FcsrMcontrolMatch$=0$ would not match. + * not equal: Matches when {mcontrol-match}=0 would not match. */ #define CSR_MCONTROL_MATCH_NOT_EQUAL 8 /* - * not napot: Matches when \FcsrMcontrolMatch$=1$ would not match. + * not napot: Matches when {mcontrol-match}=1 would not match. */ #define CSR_MCONTROL_MATCH_NOT_NAPOT 9 /* - * not mask low: Matches when \FcsrMcontrolMatch$=4$ would not match. + * not mask low: Matches when {mcontrol-match}=4 would not match. */ #define CSR_MCONTROL_MATCH_NOT_MASK_LOW 12 /* - * not mask high: Matches when \FcsrMcontrolMatch$=5$ would not match. + * not mask high: Matches when {mcontrol-match}=5 would not match. */ #define CSR_MCONTROL_MATCH_NOT_MASK_HIGH 13 /* * Other values are reserved for future use. * * All comparisons only look at the lower XLEN (in the current mode) - * bits of the compare values and of \RcsrTdataTwo. - * When \FcsrMcontrolSelect=1 and access size is N, this is further + * bits of the compare values and of {csr-tdata2}. + * When {mcontrol-select}=1 and access size is N, this is further * reduced, and comparisons only look at the lower N bits of the - * compare values and of \RcsrTdataTwo. + * compare values and of {csr-tdata2}. */ /* * When set, enable this trigger in M-mode. */ -#define CSR_MCONTROL_M_OFFSET 6 -#define CSR_MCONTROL_M_LENGTH 1 -#define CSR_MCONTROL_M 0x40 +#define CSR_MCONTROL_M_OFFSET 6ULL +#define CSR_MCONTROL_M_LENGTH 1ULL +#define CSR_MCONTROL_M 0x40ULL /* * When set, enable this trigger in S/HS-mode. * This bit is hard-wired to 0 if the hart does not support * S-mode. */ -#define CSR_MCONTROL_S_OFFSET 4 -#define CSR_MCONTROL_S_LENGTH 1 -#define CSR_MCONTROL_S 0x10 +#define CSR_MCONTROL_S_OFFSET 4ULL +#define CSR_MCONTROL_S_LENGTH 1ULL +#define CSR_MCONTROL_S 0x10ULL /* * When set, enable this trigger in U-mode. * This bit is hard-wired to 0 if the hart does not support * U-mode. */ -#define CSR_MCONTROL_U_OFFSET 3 -#define CSR_MCONTROL_U_LENGTH 1 -#define CSR_MCONTROL_U 8 +#define CSR_MCONTROL_U_OFFSET 3ULL +#define CSR_MCONTROL_U_LENGTH 1ULL +#define CSR_MCONTROL_U 8ULL /* * When set, the trigger fires on the virtual address or opcode of an * instruction that is executed. */ -#define CSR_MCONTROL_EXECUTE_OFFSET 2 -#define CSR_MCONTROL_EXECUTE_LENGTH 1 -#define CSR_MCONTROL_EXECUTE 4 +#define CSR_MCONTROL_EXECUTE_OFFSET 2ULL +#define CSR_MCONTROL_EXECUTE_LENGTH 1ULL +#define CSR_MCONTROL_EXECUTE 4ULL /* * When set, the trigger fires on the virtual address or data of any * store. */ -#define CSR_MCONTROL_STORE_OFFSET 1 -#define CSR_MCONTROL_STORE_LENGTH 1 -#define CSR_MCONTROL_STORE 2 +#define CSR_MCONTROL_STORE_OFFSET 1ULL +#define CSR_MCONTROL_STORE_LENGTH 1ULL +#define CSR_MCONTROL_STORE 2ULL /* * When set, the trigger fires on the virtual address or data of any * load. */ -#define CSR_MCONTROL_LOAD_OFFSET 0 -#define CSR_MCONTROL_LOAD_LENGTH 1 -#define CSR_MCONTROL_LOAD 1 +#define CSR_MCONTROL_LOAD_OFFSET 0ULL +#define CSR_MCONTROL_LOAD_LENGTH 1ULL +#define CSR_MCONTROL_LOAD 1ULL #define CSR_MCONTROL6 0x7a1 -#define CSR_MCONTROL6_TYPE_OFFSET(XLEN) (XLEN + -4) -#define CSR_MCONTROL6_TYPE_LENGTH 4 -#define CSR_MCONTROL6_TYPE(XLEN) (0xf * (1ULL<<(XLEN + -4))) -#define CSR_MCONTROL6_DMODE_OFFSET(XLEN) (XLEN + -5) -#define CSR_MCONTROL6_DMODE_LENGTH 1 -#define CSR_MCONTROL6_DMODE(XLEN) (1ULL<<(XLEN + -5)) +#define CSR_MCONTROL6_TYPE_OFFSET(XLEN) ((XLEN) + -4ULL) +#define CSR_MCONTROL6_TYPE_LENGTH 4ULL +#define CSR_MCONTROL6_TYPE(XLEN) (0xfULL * (1ULL << ((XLEN) + -4ULL))) +#define CSR_MCONTROL6_DMODE_OFFSET(XLEN) ((XLEN) + -5ULL) +#define CSR_MCONTROL6_DMODE_LENGTH 1ULL +#define CSR_MCONTROL6_DMODE(XLEN) (1ULL << ((XLEN) + -5ULL)) +/* + * If implemented, the TM updates this field every time the trigger + * fires. + */ +#define CSR_MCONTROL6_UNCERTAIN_OFFSET 0x1aULL +#define CSR_MCONTROL6_UNCERTAIN_LENGTH 1ULL +#define CSR_MCONTROL6_UNCERTAIN 0x4000000ULL +/* + * certain: The trigger that fired satisfied the configured conditions, or + * this bit is not implemented. + */ +#define CSR_MCONTROL6_UNCERTAIN_CERTAIN 0 +/* + * uncertain: The trigger that fired might not have perfectly satisfied the + * configured conditions. Due to the implementation the hardware + * cannot be certain. + */ +#define CSR_MCONTROL6_UNCERTAIN_UNCERTAIN 1 +#define CSR_MCONTROL6_HIT1_OFFSET 0x19ULL +#define CSR_MCONTROL6_HIT1_LENGTH 1ULL +#define CSR_MCONTROL6_HIT1 0x2000000ULL /* * When set, enable this trigger in VS-mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_MCONTROL6_VS_OFFSET 0x18 -#define CSR_MCONTROL6_VS_LENGTH 1 -#define CSR_MCONTROL6_VS 0x1000000 +#define CSR_MCONTROL6_VS_OFFSET 0x18ULL +#define CSR_MCONTROL6_VS_LENGTH 1ULL +#define CSR_MCONTROL6_VS 0x1000000ULL /* * When set, enable this trigger in VU-mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_MCONTROL6_VU_OFFSET 0x17 -#define CSR_MCONTROL6_VU_LENGTH 1 -#define CSR_MCONTROL6_VU 0x800000 +#define CSR_MCONTROL6_VU_OFFSET 0x17ULL +#define CSR_MCONTROL6_VU_LENGTH 1ULL +#define CSR_MCONTROL6_VU 0x800000ULL /* - * If this bit is implemented then it must become set when this - * trigger fires and may become set when this trigger matches. - * The trigger's user can set or clear it at any - * time. It is used to determine which - * trigger(s) matched. If the bit is not implemented, it is always 0 - * and writing it has no effect. + * If they are implemented, {mcontrol6-hit1} (MSB) and + * {mcontrol6-hit0} (LSB) combine into a single 2-bit field. + * The TM updates this field when the trigger fires. After the debugger + * has seen the update, it will normally write 0 to this field to so it + * can see future changes. + * + * If either of the bits is not implemented, the unimplemented bits + * will be read-only 0. + */ +#define CSR_MCONTROL6_HIT0_OFFSET 0x16ULL +#define CSR_MCONTROL6_HIT0_LENGTH 1ULL +#define CSR_MCONTROL6_HIT0 0x400000ULL +/* + * false: The trigger did not fire. + */ +#define CSR_MCONTROL6_HIT0_FALSE 0 +/* + * before: The trigger fired before the instruction that matched it was + * retired, but after all preceding instructions are retired. This + * explicitly allows for instructions to be partially executed, as + * described in xref:multistate[]. + * + * `xepc` or {csr-dpc} (depending on {mcontrol6-action}) must be set + * to the virtual address of the instruction that matched. + */ +#define CSR_MCONTROL6_HIT0_BEFORE 1 +/* + * after: The trigger fired after the instruction that triggered and at least + * one additional instruction were retired. + * `xepc` or {csr-dpc} (depending on {mcontrol6-action}) must be set + * to the virtual address of the next instruction that must be executed + * to preserve the program flow. + */ +#define CSR_MCONTROL6_HIT0_AFTER 2 +/* + * immediately after: The trigger fired just after the instruction that triggered it was + * retired, but before any subsequent instructions were executed. + * `xepc` or {csr-dpc} (depending on {mcontrol6-action}) must be set + * to the virtual address of the next instruction that must be executed + * to preserve the program flow. + * + * If the instruction performed multiple memory accesses, all of them + * have been completed. */ -#define CSR_MCONTROL6_HIT_OFFSET 0x16 -#define CSR_MCONTROL6_HIT_LENGTH 1 -#define CSR_MCONTROL6_HIT 0x400000 +#define CSR_MCONTROL6_HIT0_IMMEDIATELY_AFTER 3 /* * This bit determines the contents of the XLEN-bit compare values. */ -#define CSR_MCONTROL6_SELECT_OFFSET 0x15 -#define CSR_MCONTROL6_SELECT_LENGTH 1 -#define CSR_MCONTROL6_SELECT 0x200000 +#define CSR_MCONTROL6_SELECT_OFFSET 0x15ULL +#define CSR_MCONTROL6_SELECT_LENGTH 1ULL +#define CSR_MCONTROL6_SELECT 0x200000ULL /* * address: There is at least one compare value and it contains the lowest * virtual address of the access. @@ -1010,58 +1194,13 @@ * Any bits beyond the size of the data access will contain 0. */ #define CSR_MCONTROL6_SELECT_DATA 1 -#define CSR_MCONTROL6_TIMING_OFFSET 0x14 -#define CSR_MCONTROL6_TIMING_LENGTH 1 -#define CSR_MCONTROL6_TIMING 0x100000 -/* - * before: The action for this trigger will be taken just before the - * instruction that triggered it is committed, but after all preceding - * instructions are committed. \Rxepc or \RcsrDpc (depending - * on \FcsrMcontrolSixAction) must be set to the virtual address of the - * instruction that matched. - * - * If this is combined with \FcsrMcontrolSixLoad and - * \FcsrMcontrolSixSelect=1 then a memory access will be - * performed (including any side effects of performing such an access) even - * though the load will not update its destination register. Debuggers - * should consider this when setting such breakpoints on, for example, - * memory-mapped I/O addresses. - */ -#define CSR_MCONTROL6_TIMING_BEFORE 0 -/* - * after: The action for this trigger will be taken after the instruction - * that triggered it is committed. It should be taken before the next - * instruction is committed, but it is better to implement triggers imprecisely - * than to not implement them at all. \Rxepc or - * \RcsrDpc (depending on \FcsrMcontrolSixAction) must be set to - * the virtual address of the next instruction that must be executed to - * preserve the program flow. - */ -#define CSR_MCONTROL6_TIMING_AFTER 1 -/* - * Most hardware will only implement one timing or the other, possibly - * dependent on \FcsrMcontrolSixSelect, \FcsrMcontrolSixExecute, - * \FcsrMcontrolSixLoad, and \FcsrMcontrolSixStore. This bit - * primarily exists for the hardware to communicate to the debugger - * what will happen. Hardware may implement the bit fully writable, in - * which case the debugger has a little more control. - * - * Data load triggers with \FcsrMcontrolSixTiming of 0 will result in the same load - * happening again when the debugger lets the hart run. For data load - * triggers, debuggers must first attempt to set the breakpoint with - * \FcsrMcontrolSixTiming of 1. - * - * If a trigger with \FcsrMcontrolSixTiming of 0 matches, it is - * implementation-dependent whether that prevents a trigger with - * \FcsrMcontrolSixTiming of 1 matching as well. - */ -#define CSR_MCONTROL6_SIZE_OFFSET 0x10 -#define CSR_MCONTROL6_SIZE_LENGTH 4 -#define CSR_MCONTROL6_SIZE 0xf0000 +#define CSR_MCONTROL6_SIZE_OFFSET 0x10ULL +#define CSR_MCONTROL6_SIZE_LENGTH 3ULL +#define CSR_MCONTROL6_SIZE 0x70000ULL /* * any: The trigger will attempt to match against an access of any size. - * The behavior is only well-defined if $|select|=0$, or if the access - * size is XLEN. + * The behavior is only well-defined if {mcontrol6-select}=0, or if the + * access size is XLEN. */ #define CSR_MCONTROL6_SIZE_ANY 0 /* @@ -1087,48 +1226,36 @@ * execution of 64-bit instructions. */ #define CSR_MCONTROL6_SIZE_64BIT 5 -/* - * 80bit: The trigger will only match against execution of 80-bit instructions. - */ -#define CSR_MCONTROL6_SIZE_80BIT 6 -/* - * 96bit: The trigger will only match against execution of 96-bit instructions. - */ -#define CSR_MCONTROL6_SIZE_96BIT 7 -/* - * 112bit: The trigger will only match against execution of 112-bit instructions. - */ -#define CSR_MCONTROL6_SIZE_112BIT 8 /* * 128bit: The trigger will only match against 128-bit memory accesses or * execution of 128-bit instructions. */ -#define CSR_MCONTROL6_SIZE_128BIT 9 +#define CSR_MCONTROL6_SIZE_128BIT 6 /* * An implementation must support the value of 0, but all other values * are optional. When an implementation supports address triggers - * (\FcsrMcontrolSixSelect=0), it is recommended that those triggers + * ({mcontrol6-select}=0), it is recommended that those triggers * support every access size that the hart supports, as well as for * every instruction size that the hart supports. * * Implementations such as RV32D or RV64V are able to perform loads * and stores that are wider than XLEN. Custom extensions may also * support instructions that are wider than XLEN. Because - * \RcsrTdataTwo is of size XLEN, there is a known limitation that - * data value triggers (\FcsrMcontrolSixSelect=1) can only be supported + * {csr-tdata2} is of size XLEN, there is a known limitation that + * data value triggers ({mcontrol6-select}=1) can only be supported * for access sizes up to XLEN bits. When an implementation supports - * data value triggers (\FcsrMcontrolSixSelect=1), it is recommended + * data value triggers ({mcontrol6-select}=1), it is recommended * that those triggers support every access size up to XLEN that the * hart supports, as well as for every instruction length up to XLEN * that the hart supports. */ /* * The action to take when the trigger fires. The values are explained - * in Table~\ref{tab:action}. + * in xref:tab:action[]. */ -#define CSR_MCONTROL6_ACTION_OFFSET 0xc -#define CSR_MCONTROL6_ACTION_LENGTH 4 -#define CSR_MCONTROL6_ACTION 0xf000 +#define CSR_MCONTROL6_ACTION_OFFSET 0xcULL +#define CSR_MCONTROL6_ACTION_LENGTH 4ULL +#define CSR_MCONTROL6_ACTION 0xf000ULL /* * breakpoint: */ @@ -1157,9 +1284,9 @@ * external1: */ #define CSR_MCONTROL6_ACTION_EXTERNAL1 9 -#define CSR_MCONTROL6_CHAIN_OFFSET 0xb -#define CSR_MCONTROL6_CHAIN_LENGTH 1 -#define CSR_MCONTROL6_CHAIN 0x800 +#define CSR_MCONTROL6_CHAIN_OFFSET 0xbULL +#define CSR_MCONTROL6_CHAIN_LENGTH 1ULL +#define CSR_MCONTROL6_CHAIN 0x800ULL /* * disabled: When this trigger matches, the configured action is taken. */ @@ -1170,10 +1297,10 @@ */ #define CSR_MCONTROL6_CHAIN_ENABLED 1 /* - * A trigger chain starts on the first trigger with $|chain|=1$ after - * a trigger with $|chain|=0$, or simply on the first trigger if that - * has $|chain|=1$. It ends on the first trigger after that which has - * $|chain|=0$. This final trigger is part of the chain. The action + * A trigger chain starts on the first trigger with `chain`=1 after + * a trigger with `chain`=0, or simply on the first trigger if that + * has `chain`=1. It ends on the first trigger after that which has + * `chain`=0. This final trigger is part of the chain. The action * on all but the final trigger is ignored. The action on that final * trigger will be taken if and only if all the triggers in the chain * match at the same time. @@ -1181,152 +1308,166 @@ * Debuggers should not terminate a chain with a trigger with a * different type. It is undefined when exactly such a chain fires. * - * Because \FcsrMcontrolSixChain affects the next trigger, hardware must zero it in - * writes to \RcsrMcontrolSix that set \FcsrTdataOneDmode to 0 if the next trigger has - * \FcsrTdataOneDmode of 1. - * In addition hardware should ignore writes to \RcsrMcontrolSix that set - * \FcsrTdataOneDmode to 1 if the previous trigger has both \FcsrTdataOneDmode of 0 and - * \FcsrMcontrolSixChain of 1. Debuggers must avoid the latter case by checking - * \FcsrMcontrolSixChain on the previous trigger if they're writing \RcsrMcontrolSix. + * Because {mcontrol6-chain} affects the next trigger, hardware must zero it in + * writes to {csr-mcontrol6} that set {tdata1-dmode} to 0 if the next trigger has + * {tdata1-dmode} of 1. + * In addition hardware should ignore writes to {csr-mcontrol6} that set + * {tdata1-dmode} to 1 if the previous trigger has both {tdata1-dmode} of 0 and + * {mcontrol6-chain} of 1. Debuggers must avoid the latter case by checking + * {mcontrol6-chain} on the previous trigger if they're writing {csr-mcontrol6}. * * Implementations that wish to limit the maximum length of a trigger * chain (eg. to meet timing requirements) may do so by zeroing - * \FcsrMcontrolSixChain in writes to \RcsrMcontrolSix that would make the chain too long. + * {mcontrol6-chain} in writes to {csr-mcontrol6} that would make the chain too long. */ -#define CSR_MCONTROL6_MATCH_OFFSET 7 -#define CSR_MCONTROL6_MATCH_LENGTH 4 -#define CSR_MCONTROL6_MATCH 0x780 +#define CSR_MCONTROL6_MATCH_OFFSET 7ULL +#define CSR_MCONTROL6_MATCH_LENGTH 4ULL +#define CSR_MCONTROL6_MATCH 0x780ULL /* - * equal: Matches when any compare value equals \RcsrTdataTwo. + * equal: Matches when any compare value equals {csr-tdata2}. */ #define CSR_MCONTROL6_MATCH_EQUAL 0 /* - * napot: Matches when the top $M$ bits of any compare value match the top - * $M$ bits of \RcsrTdataTwo. - * $M$ is $|XLEN|-1$ minus the index of the least-significant bit - * containing 0 in \RcsrTdataTwo. - * \RcsrTdataTwo is WARL and if bits $|maskmax6|-1$:0 are written with all - * ones then bit $|maskmax6|-1$ will be set to 0 while the values of bits $|maskmax6|-2$:0 - * are \unspecified. - * Legal values for \RcsrTdataTwo require $M + |maskmax6| \geq |XLEN|$ and $M\gt0$. + * napot: Matches when the top `M` bits of any compare value match the top + * `M` bits of {csr-tdata2}. + * `M` is `XLEN-1` minus the index of the least-significant bit + * containing 0 in {csr-tdata2}. + * {csr-tdata2} is *WARL* and if bits `maskmax6-1:0` are written with all + * ones then bit `maskmax6-1` will be set to 0 while the values of bits `maskmax6-2:0` + * are UNSPECIFIED. + * Legal values for {csr-tdata2} require M + `maskmax6` ≥ `XLEN` and `M` > 0. * See above for how to determine maskmax6. */ #define CSR_MCONTROL6_MATCH_NAPOT 1 /* * ge: Matches when any compare value is greater than (unsigned) or - * equal to \RcsrTdataTwo. + * equal to {csr-tdata2}. */ #define CSR_MCONTROL6_MATCH_GE 2 /* * lt: Matches when any compare value is less than (unsigned) - * \RcsrTdataTwo. + * {csr-tdata2}. */ #define CSR_MCONTROL6_MATCH_LT 3 /* - * mask low: Matches when $\frac{|XLEN|}{2}-1$:$0$ of any compare value - * equals $\frac{|XLEN|}{2}-1$:$0$ of \RcsrTdataTwo after - * $\frac{|XLEN|}{2}-1$:$0$ of the compare value is ANDed with - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of \RcsrTdataTwo. + * mask low: Matches when latexmath:[$\frac{XLEN}{2}-{1:0}] of any compare value + * equals latexmath:[$\frac{XLEN}{2}-{1:0}] of {csr-tdata2} after + * latexmath:[$\frac{XLEN}{2}-{1:0}] of the compare value is ANDed with + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of {csr-tdata2}. */ #define CSR_MCONTROL6_MATCH_MASK_LOW 4 /* - * mask high: Matches when $|XLEN|-1$:$\frac{|XLEN|}{2}$ of any compare - * value equals $\frac{|XLEN|}{2}-1$:$0$ of \RcsrTdataTwo after - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of the compare value is ANDed with - * $|XLEN|-1$:$\frac{|XLEN|}{2}$ of \RcsrTdataTwo. + * mask high: Matches when `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of any compare + * value equals latexmath:[$\frac{XLEN}{2}-{1:0}] of {csr-tdata2} after + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of the compare value is ANDed with + * `XLEN-1`:latexmath:[$\frac{XLEN}{2}$] of {csr-tdata2}. */ #define CSR_MCONTROL6_MATCH_MASK_HIGH 5 /* - * not equal: Matches when \FcsrMcontrolSixMatch$=0$ would not match. + * not equal: Matches when {mcontrol6-match} `=0` would not match. */ #define CSR_MCONTROL6_MATCH_NOT_EQUAL 8 /* - * not napot: Matches when \FcsrMcontrolSixMatch$=1$ would not match. + * not napot: Matches when {mcontrol6-match} `=1` would not match. */ #define CSR_MCONTROL6_MATCH_NOT_NAPOT 9 /* - * not mask low: Matches when \FcsrMcontrolSixMatch$=4$ would not match. + * not mask low: Matches when {mcontrol6-match} `=4` would not match. */ #define CSR_MCONTROL6_MATCH_NOT_MASK_LOW 12 /* - * not mask high: Matches when \FcsrMcontrolSixMatch$=5$ would not match. + * not mask high: Matches when {mcontrol6-match} `=5` would not match. */ #define CSR_MCONTROL6_MATCH_NOT_MASK_HIGH 13 /* * Other values are reserved for future use. * * All comparisons only look at the lower XLEN (in the current mode) - * bits of the compare values and of \RcsrTdataTwo. - * When \FcsrMcontrolSelect=1 and access size is N, this is further + * bits of the compare values and of {csr-tdata2}. + * When {mcontrol-select}=1 and access size is N, this is further * reduced, and comparisons only look at the lower N bits of the - * compare values and of \RcsrTdataTwo. + * compare values and of {csr-tdata2}. */ /* * When set, enable this trigger in M-mode. */ -#define CSR_MCONTROL6_M_OFFSET 6 -#define CSR_MCONTROL6_M_LENGTH 1 -#define CSR_MCONTROL6_M 0x40 +#define CSR_MCONTROL6_M_OFFSET 6ULL +#define CSR_MCONTROL6_M_LENGTH 1ULL +#define CSR_MCONTROL6_M 0x40ULL +#define CSR_MCONTROL6_UNCERTAINEN_OFFSET 5ULL +#define CSR_MCONTROL6_UNCERTAINEN_LENGTH 1ULL +#define CSR_MCONTROL6_UNCERTAINEN 0x20ULL +/* + * disabled: This trigger will only match if the hardware can perfectly + * evaluate it. + */ +#define CSR_MCONTROL6_UNCERTAINEN_DISABLED 0 +/* + * enabled: This trigger will match if it's possible that it would match if + * the Trigger Module had perfect information about the operations + * being performed. + */ +#define CSR_MCONTROL6_UNCERTAINEN_ENABLED 1 /* * When set, enable this trigger in S/HS-mode. * This bit is hard-wired to 0 if the hart does not support * S-mode. */ -#define CSR_MCONTROL6_S_OFFSET 4 -#define CSR_MCONTROL6_S_LENGTH 1 -#define CSR_MCONTROL6_S 0x10 +#define CSR_MCONTROL6_S_OFFSET 4ULL +#define CSR_MCONTROL6_S_LENGTH 1ULL +#define CSR_MCONTROL6_S 0x10ULL /* * When set, enable this trigger in U-mode. * This bit is hard-wired to 0 if the hart does not support * U-mode. */ -#define CSR_MCONTROL6_U_OFFSET 3 -#define CSR_MCONTROL6_U_LENGTH 1 -#define CSR_MCONTROL6_U 8 +#define CSR_MCONTROL6_U_OFFSET 3ULL +#define CSR_MCONTROL6_U_LENGTH 1ULL +#define CSR_MCONTROL6_U 8ULL /* * When set, the trigger fires on the virtual address or opcode of an * instruction that is executed. */ -#define CSR_MCONTROL6_EXECUTE_OFFSET 2 -#define CSR_MCONTROL6_EXECUTE_LENGTH 1 -#define CSR_MCONTROL6_EXECUTE 4 +#define CSR_MCONTROL6_EXECUTE_OFFSET 2ULL +#define CSR_MCONTROL6_EXECUTE_LENGTH 1ULL +#define CSR_MCONTROL6_EXECUTE 4ULL /* * When set, the trigger fires on the virtual address or data of any * store. */ -#define CSR_MCONTROL6_STORE_OFFSET 1 -#define CSR_MCONTROL6_STORE_LENGTH 1 -#define CSR_MCONTROL6_STORE 2 +#define CSR_MCONTROL6_STORE_OFFSET 1ULL +#define CSR_MCONTROL6_STORE_LENGTH 1ULL +#define CSR_MCONTROL6_STORE 2ULL /* * When set, the trigger fires on the virtual address or data of any * load. */ -#define CSR_MCONTROL6_LOAD_OFFSET 0 -#define CSR_MCONTROL6_LOAD_LENGTH 1 -#define CSR_MCONTROL6_LOAD 1 +#define CSR_MCONTROL6_LOAD_OFFSET 0ULL +#define CSR_MCONTROL6_LOAD_LENGTH 1ULL +#define CSR_MCONTROL6_LOAD 1ULL #define CSR_ICOUNT 0x7a1 -#define CSR_ICOUNT_TYPE_OFFSET(XLEN) (XLEN + -4) -#define CSR_ICOUNT_TYPE_LENGTH 4 -#define CSR_ICOUNT_TYPE(XLEN) (0xf * (1ULL<<(XLEN + -4))) -#define CSR_ICOUNT_DMODE_OFFSET(XLEN) (XLEN + -5) -#define CSR_ICOUNT_DMODE_LENGTH 1 -#define CSR_ICOUNT_DMODE(XLEN) (1ULL<<(XLEN + -5)) +#define CSR_ICOUNT_TYPE_OFFSET(XLEN) ((XLEN) + -4ULL) +#define CSR_ICOUNT_TYPE_LENGTH 4ULL +#define CSR_ICOUNT_TYPE(XLEN) (0xfULL * (1ULL << ((XLEN) + -4ULL))) +#define CSR_ICOUNT_DMODE_OFFSET(XLEN) ((XLEN) + -5ULL) +#define CSR_ICOUNT_DMODE_LENGTH 1ULL +#define CSR_ICOUNT_DMODE(XLEN) (1ULL << ((XLEN) + -5ULL)) /* * When set, enable this trigger in VS-mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ICOUNT_VS_OFFSET 0x1a -#define CSR_ICOUNT_VS_LENGTH 1 -#define CSR_ICOUNT_VS 0x4000000 +#define CSR_ICOUNT_VS_OFFSET 0x1aULL +#define CSR_ICOUNT_VS_LENGTH 1ULL +#define CSR_ICOUNT_VS 0x4000000ULL /* * When set, enable this trigger in VU-mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ICOUNT_VU_OFFSET 0x19 -#define CSR_ICOUNT_VU_LENGTH 1 -#define CSR_ICOUNT_VU 0x2000000 +#define CSR_ICOUNT_VU_OFFSET 0x19ULL +#define CSR_ICOUNT_VU_LENGTH 1ULL +#define CSR_ICOUNT_VU 0x2000000ULL /* * If this bit is implemented, the hardware sets it when this * trigger fires. The trigger's user can set or clear it at any @@ -1334,53 +1475,53 @@ * trigger(s) fires. If the bit is not implemented, it is always 0 * and writing it has no effect. */ -#define CSR_ICOUNT_HIT_OFFSET 0x18 -#define CSR_ICOUNT_HIT_LENGTH 1 -#define CSR_ICOUNT_HIT 0x1000000 +#define CSR_ICOUNT_HIT_OFFSET 0x18ULL +#define CSR_ICOUNT_HIT_LENGTH 1ULL +#define CSR_ICOUNT_HIT 0x1000000ULL /* - * The trigger will generally fire after \FcsrIcountCount instructions + * The trigger will generally fire after {icount-count} instructions * in enabled modes have been executed. See above for the precise behavior. */ -#define CSR_ICOUNT_COUNT_OFFSET 0xa -#define CSR_ICOUNT_COUNT_LENGTH 0xe -#define CSR_ICOUNT_COUNT 0xfffc00 +#define CSR_ICOUNT_COUNT_OFFSET 0xaULL +#define CSR_ICOUNT_COUNT_LENGTH 0xeULL +#define CSR_ICOUNT_COUNT 0xfffc00ULL /* * When set, enable this trigger in M-mode. */ -#define CSR_ICOUNT_M_OFFSET 9 -#define CSR_ICOUNT_M_LENGTH 1 -#define CSR_ICOUNT_M 0x200 +#define CSR_ICOUNT_M_OFFSET 9ULL +#define CSR_ICOUNT_M_LENGTH 1ULL +#define CSR_ICOUNT_M 0x200ULL /* - * This bit becomes set when \FcsrIcountCount is decremented from 1 + * This bit becomes set when {icount-count} is decremented from 1 * to 0. It is cleared when the trigger fires, which will happen just * before executing the next instruction in one of the enabled modes. */ -#define CSR_ICOUNT_PENDING_OFFSET 8 -#define CSR_ICOUNT_PENDING_LENGTH 1 -#define CSR_ICOUNT_PENDING 0x100 +#define CSR_ICOUNT_PENDING_OFFSET 8ULL +#define CSR_ICOUNT_PENDING_LENGTH 1ULL +#define CSR_ICOUNT_PENDING 0x100ULL /* * When set, enable this trigger in S/HS-mode. * This bit is hard-wired to 0 if the hart does not support * S-mode. */ -#define CSR_ICOUNT_S_OFFSET 7 -#define CSR_ICOUNT_S_LENGTH 1 -#define CSR_ICOUNT_S 0x80 +#define CSR_ICOUNT_S_OFFSET 7ULL +#define CSR_ICOUNT_S_LENGTH 1ULL +#define CSR_ICOUNT_S 0x80ULL /* * When set, enable this trigger in U-mode. * This bit is hard-wired to 0 if the hart does not support * U-mode. */ -#define CSR_ICOUNT_U_OFFSET 6 -#define CSR_ICOUNT_U_LENGTH 1 -#define CSR_ICOUNT_U 0x40 +#define CSR_ICOUNT_U_OFFSET 6ULL +#define CSR_ICOUNT_U_LENGTH 1ULL +#define CSR_ICOUNT_U 0x40ULL /* * The action to take when the trigger fires. The values are explained - * in Table~\ref{tab:action}. + * in xref:tab:action[]. */ -#define CSR_ICOUNT_ACTION_OFFSET 0 -#define CSR_ICOUNT_ACTION_LENGTH 6 -#define CSR_ICOUNT_ACTION 0x3f +#define CSR_ICOUNT_ACTION_OFFSET 0ULL +#define CSR_ICOUNT_ACTION_LENGTH 6ULL +#define CSR_ICOUNT_ACTION 0x3fULL /* * breakpoint: */ @@ -1410,12 +1551,12 @@ */ #define CSR_ICOUNT_ACTION_EXTERNAL1 9 #define CSR_ITRIGGER 0x7a1 -#define CSR_ITRIGGER_TYPE_OFFSET(XLEN) (XLEN + -4) -#define CSR_ITRIGGER_TYPE_LENGTH 4 -#define CSR_ITRIGGER_TYPE(XLEN) (0xf * (1ULL<<(XLEN + -4))) -#define CSR_ITRIGGER_DMODE_OFFSET(XLEN) (XLEN + -5) -#define CSR_ITRIGGER_DMODE_LENGTH 1 -#define CSR_ITRIGGER_DMODE(XLEN) (1ULL<<(XLEN + -5)) +#define CSR_ITRIGGER_TYPE_OFFSET(XLEN) ((XLEN) + -4ULL) +#define CSR_ITRIGGER_TYPE_LENGTH 4ULL +#define CSR_ITRIGGER_TYPE(XLEN) (0xfULL * (1ULL << ((XLEN) + -4ULL))) +#define CSR_ITRIGGER_DMODE_OFFSET(XLEN) ((XLEN) + -5ULL) +#define CSR_ITRIGGER_DMODE_LENGTH 1ULL +#define CSR_ITRIGGER_DMODE(XLEN) (1ULL << ((XLEN) + -5ULL)) /* * If this bit is implemented, the hardware sets it when this * trigger matches. The trigger's user can set or clear it at any @@ -1423,66 +1564,66 @@ * trigger(s) matched. If the bit is not implemented, it is always 0 * and writing it has no effect. */ -#define CSR_ITRIGGER_HIT_OFFSET(XLEN) (XLEN + -6) -#define CSR_ITRIGGER_HIT_LENGTH 1 -#define CSR_ITRIGGER_HIT(XLEN) (1ULL<<(XLEN + -6)) +#define CSR_ITRIGGER_HIT_OFFSET(XLEN) ((XLEN) + -6ULL) +#define CSR_ITRIGGER_HIT_LENGTH 1ULL +#define CSR_ITRIGGER_HIT(XLEN) (1ULL << ((XLEN) + -6ULL)) /* * When set, enable this trigger for interrupts that are taken from VS * mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ITRIGGER_VS_OFFSET 0xc -#define CSR_ITRIGGER_VS_LENGTH 1 -#define CSR_ITRIGGER_VS 0x1000 +#define CSR_ITRIGGER_VS_OFFSET 0xcULL +#define CSR_ITRIGGER_VS_LENGTH 1ULL +#define CSR_ITRIGGER_VS 0x1000ULL /* * When set, enable this trigger for interrupts that are taken from VU * mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ITRIGGER_VU_OFFSET 0xb -#define CSR_ITRIGGER_VU_LENGTH 1 -#define CSR_ITRIGGER_VU 0x800 +#define CSR_ITRIGGER_VU_OFFSET 0xbULL +#define CSR_ITRIGGER_VU_LENGTH 1ULL +#define CSR_ITRIGGER_VU 0x800ULL /* * When set, non-maskable interrupts cause this * trigger to fire if the trigger is enabled for the current mode. */ -#define CSR_ITRIGGER_NMI_OFFSET 0xa -#define CSR_ITRIGGER_NMI_LENGTH 1 -#define CSR_ITRIGGER_NMI 0x400 +#define CSR_ITRIGGER_NMI_OFFSET 0xaULL +#define CSR_ITRIGGER_NMI_LENGTH 1ULL +#define CSR_ITRIGGER_NMI 0x400ULL /* * When set, enable this trigger for interrupts that are taken from M * mode. */ -#define CSR_ITRIGGER_M_OFFSET 9 -#define CSR_ITRIGGER_M_LENGTH 1 -#define CSR_ITRIGGER_M 0x200 +#define CSR_ITRIGGER_M_OFFSET 9ULL +#define CSR_ITRIGGER_M_LENGTH 1ULL +#define CSR_ITRIGGER_M 0x200ULL /* * When set, enable this trigger for interrupts that are taken from S/HS * mode. * This bit is hard-wired to 0 if the hart does not support * S-mode. */ -#define CSR_ITRIGGER_S_OFFSET 7 -#define CSR_ITRIGGER_S_LENGTH 1 -#define CSR_ITRIGGER_S 0x80 +#define CSR_ITRIGGER_S_OFFSET 7ULL +#define CSR_ITRIGGER_S_LENGTH 1ULL +#define CSR_ITRIGGER_S 0x80ULL /* * When set, enable this trigger for interrupts that are taken from U * mode. * This bit is hard-wired to 0 if the hart does not support * U-mode. */ -#define CSR_ITRIGGER_U_OFFSET 6 -#define CSR_ITRIGGER_U_LENGTH 1 -#define CSR_ITRIGGER_U 0x40 +#define CSR_ITRIGGER_U_OFFSET 6ULL +#define CSR_ITRIGGER_U_LENGTH 1ULL +#define CSR_ITRIGGER_U 0x40ULL /* * The action to take when the trigger fires. The values are explained - * in Table~\ref{tab:action}. + * in xref:tab:action[]. */ -#define CSR_ITRIGGER_ACTION_OFFSET 0 -#define CSR_ITRIGGER_ACTION_LENGTH 6 -#define CSR_ITRIGGER_ACTION 0x3f +#define CSR_ITRIGGER_ACTION_OFFSET 0ULL +#define CSR_ITRIGGER_ACTION_LENGTH 6ULL +#define CSR_ITRIGGER_ACTION 0x3fULL /* * breakpoint: */ @@ -1512,12 +1653,12 @@ */ #define CSR_ITRIGGER_ACTION_EXTERNAL1 9 #define CSR_ETRIGGER 0x7a1 -#define CSR_ETRIGGER_TYPE_OFFSET(XLEN) (XLEN + -4) -#define CSR_ETRIGGER_TYPE_LENGTH 4 -#define CSR_ETRIGGER_TYPE(XLEN) (0xf * (1ULL<<(XLEN + -4))) -#define CSR_ETRIGGER_DMODE_OFFSET(XLEN) (XLEN + -5) -#define CSR_ETRIGGER_DMODE_LENGTH 1 -#define CSR_ETRIGGER_DMODE(XLEN) (1ULL<<(XLEN + -5)) +#define CSR_ETRIGGER_TYPE_OFFSET(XLEN) ((XLEN) + -4ULL) +#define CSR_ETRIGGER_TYPE_LENGTH 4ULL +#define CSR_ETRIGGER_TYPE(XLEN) (0xfULL * (1ULL << ((XLEN) + -4ULL))) +#define CSR_ETRIGGER_DMODE_OFFSET(XLEN) ((XLEN) + -5ULL) +#define CSR_ETRIGGER_DMODE_LENGTH 1ULL +#define CSR_ETRIGGER_DMODE(XLEN) (1ULL << ((XLEN) + -5ULL)) /* * If this bit is implemented, the hardware sets it when this * trigger matches. The trigger's user can set or clear it at any @@ -1525,59 +1666,59 @@ * trigger(s) matched. If the bit is not implemented, it is always 0 * and writing it has no effect. */ -#define CSR_ETRIGGER_HIT_OFFSET(XLEN) (XLEN + -6) -#define CSR_ETRIGGER_HIT_LENGTH 1 -#define CSR_ETRIGGER_HIT(XLEN) (1ULL<<(XLEN + -6)) +#define CSR_ETRIGGER_HIT_OFFSET(XLEN) ((XLEN) + -6ULL) +#define CSR_ETRIGGER_HIT_LENGTH 1ULL +#define CSR_ETRIGGER_HIT(XLEN) (1ULL << ((XLEN) + -6ULL)) /* * When set, enable this trigger for exceptions that are taken from VS * mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ETRIGGER_VS_OFFSET 0xc -#define CSR_ETRIGGER_VS_LENGTH 1 -#define CSR_ETRIGGER_VS 0x1000 +#define CSR_ETRIGGER_VS_OFFSET 0xcULL +#define CSR_ETRIGGER_VS_LENGTH 1ULL +#define CSR_ETRIGGER_VS 0x1000ULL /* * When set, enable this trigger for exceptions that are taken from VU * mode. * This bit is hard-wired to 0 if the hart does not support * virtualization mode. */ -#define CSR_ETRIGGER_VU_OFFSET 0xb -#define CSR_ETRIGGER_VU_LENGTH 1 -#define CSR_ETRIGGER_VU 0x800 +#define CSR_ETRIGGER_VU_OFFSET 0xbULL +#define CSR_ETRIGGER_VU_LENGTH 1ULL +#define CSR_ETRIGGER_VU 0x800ULL /* * When set, enable this trigger for exceptions that are taken from M * mode. */ -#define CSR_ETRIGGER_M_OFFSET 9 -#define CSR_ETRIGGER_M_LENGTH 1 -#define CSR_ETRIGGER_M 0x200 +#define CSR_ETRIGGER_M_OFFSET 9ULL +#define CSR_ETRIGGER_M_LENGTH 1ULL +#define CSR_ETRIGGER_M 0x200ULL /* * When set, enable this trigger for exceptions that are taken from S/HS * mode. * This bit is hard-wired to 0 if the hart does not support * S-mode. */ -#define CSR_ETRIGGER_S_OFFSET 7 -#define CSR_ETRIGGER_S_LENGTH 1 -#define CSR_ETRIGGER_S 0x80 +#define CSR_ETRIGGER_S_OFFSET 7ULL +#define CSR_ETRIGGER_S_LENGTH 1ULL +#define CSR_ETRIGGER_S 0x80ULL /* * When set, enable this trigger for exceptions that are taken from U * mode. * This bit is hard-wired to 0 if the hart does not support * U-mode. */ -#define CSR_ETRIGGER_U_OFFSET 6 -#define CSR_ETRIGGER_U_LENGTH 1 -#define CSR_ETRIGGER_U 0x40 +#define CSR_ETRIGGER_U_OFFSET 6ULL +#define CSR_ETRIGGER_U_LENGTH 1ULL +#define CSR_ETRIGGER_U 0x40ULL /* * The action to take when the trigger fires. The values are explained - * in Table~\ref{tab:action}. + * in xref:tab:action[]. */ -#define CSR_ETRIGGER_ACTION_OFFSET 0 -#define CSR_ETRIGGER_ACTION_LENGTH 6 -#define CSR_ETRIGGER_ACTION 0x3f +#define CSR_ETRIGGER_ACTION_OFFSET 0ULL +#define CSR_ETRIGGER_ACTION_LENGTH 6ULL +#define CSR_ETRIGGER_ACTION 0x3fULL /* * breakpoint: */ @@ -1607,12 +1748,12 @@ */ #define CSR_ETRIGGER_ACTION_EXTERNAL1 9 #define CSR_TMEXTTRIGGER 0x7a1 -#define CSR_TMEXTTRIGGER_TYPE_OFFSET(XLEN) (XLEN + -4) -#define CSR_TMEXTTRIGGER_TYPE_LENGTH 4 -#define CSR_TMEXTTRIGGER_TYPE(XLEN) (0xf * (1ULL<<(XLEN + -4))) -#define CSR_TMEXTTRIGGER_DMODE_OFFSET(XLEN) (XLEN + -5) -#define CSR_TMEXTTRIGGER_DMODE_LENGTH 1 -#define CSR_TMEXTTRIGGER_DMODE(XLEN) (1ULL<<(XLEN + -5)) +#define CSR_TMEXTTRIGGER_TYPE_OFFSET(XLEN) ((XLEN) + -4ULL) +#define CSR_TMEXTTRIGGER_TYPE_LENGTH 4ULL +#define CSR_TMEXTTRIGGER_TYPE(XLEN) (0xfULL * (1ULL << ((XLEN) + -4ULL))) +#define CSR_TMEXTTRIGGER_DMODE_OFFSET(XLEN) ((XLEN) + -5ULL) +#define CSR_TMEXTTRIGGER_DMODE_LENGTH 1ULL +#define CSR_TMEXTTRIGGER_DMODE(XLEN) (1ULL << ((XLEN) + -5ULL)) /* * If this bit is implemented, the hardware sets it when this * trigger matches. The trigger's user can set or clear it at any @@ -1620,30 +1761,30 @@ * trigger(s) matched. If the bit is not implemented, it is always 0 * and writing it has no effect. */ -#define CSR_TMEXTTRIGGER_HIT_OFFSET(XLEN) (XLEN + -6) -#define CSR_TMEXTTRIGGER_HIT_LENGTH 1 -#define CSR_TMEXTTRIGGER_HIT(XLEN) (1ULL<<(XLEN + -6)) +#define CSR_TMEXTTRIGGER_HIT_OFFSET(XLEN) ((XLEN) + -6ULL) +#define CSR_TMEXTTRIGGER_HIT_LENGTH 1ULL +#define CSR_TMEXTTRIGGER_HIT(XLEN) (1ULL << ((XLEN) + -6ULL)) /* * This optional bit, when set, causes this trigger to fire whenever an attached * interrupt controller signals a trigger. */ -#define CSR_TMEXTTRIGGER_INTCTL_OFFSET 0x16 -#define CSR_TMEXTTRIGGER_INTCTL_LENGTH 1 -#define CSR_TMEXTTRIGGER_INTCTL 0x400000 +#define CSR_TMEXTTRIGGER_INTCTL_OFFSET 0x16ULL +#define CSR_TMEXTTRIGGER_INTCTL_LENGTH 1ULL +#define CSR_TMEXTTRIGGER_INTCTL 0x400000ULL /* - * Selects any combination of up to 16 external debug trigger inputs + * Selects any combination of up to 16 TM external trigger inputs * that cause this trigger to fire. */ -#define CSR_TMEXTTRIGGER_SELECT_OFFSET 6 -#define CSR_TMEXTTRIGGER_SELECT_LENGTH 0x10 -#define CSR_TMEXTTRIGGER_SELECT 0x3fffc0 +#define CSR_TMEXTTRIGGER_SELECT_OFFSET 6ULL +#define CSR_TMEXTTRIGGER_SELECT_LENGTH 0x10ULL +#define CSR_TMEXTTRIGGER_SELECT 0x3fffc0ULL /* * The action to take when the trigger fires. The values are explained - * in Table~\ref{tab:action}. + * in xref:tab:action[]. */ -#define CSR_TMEXTTRIGGER_ACTION_OFFSET 0 -#define CSR_TMEXTTRIGGER_ACTION_LENGTH 6 -#define CSR_TMEXTTRIGGER_ACTION 0x3f +#define CSR_TMEXTTRIGGER_ACTION_OFFSET 0ULL +#define CSR_TMEXTTRIGGER_ACTION_LENGTH 6ULL +#define CSR_TMEXTTRIGGER_ACTION 0x3fULL /* * breakpoint: */ @@ -1674,29 +1815,31 @@ #define CSR_TMEXTTRIGGER_ACTION_EXTERNAL1 9 #define CSR_TEXTRA32 0x7a3 /* - * Data used together with \FcsrTextraThirtytwoMhselect. + * Data used together with {textra32-mhselect}. */ -#define CSR_TEXTRA32_MHVALUE_OFFSET 0x1a -#define CSR_TEXTRA32_MHVALUE_LENGTH 6 -#define CSR_TEXTRA32_MHVALUE 0xfc000000U -#define CSR_TEXTRA32_MHSELECT_OFFSET 0x17 -#define CSR_TEXTRA32_MHSELECT_LENGTH 3 -#define CSR_TEXTRA32_MHSELECT 0x3800000 +#define CSR_TEXTRA32_MHVALUE_OFFSET 0x1aULL +#define CSR_TEXTRA32_MHVALUE_LENGTH 6ULL +#define CSR_TEXTRA32_MHVALUE 0xfc000000ULL +#define CSR_TEXTRA32_MHSELECT_OFFSET 0x17ULL +#define CSR_TEXTRA32_MHSELECT_LENGTH 3ULL +#define CSR_TEXTRA32_MHSELECT 0x3800000ULL /* - * ignore: Ignore \FcsrTextraThirtytwoMhvalue. + * ignore: Ignore {textra32-mhvalue}. */ #define CSR_TEXTRA32_MHSELECT_IGNORE 0 /* - * mcontext: This trigger will only match if the low bits of - * \RcsrMcontext/\RcsrHcontext equal \FcsrTextraThirtytwoMhvalue. + * mcontext: This trigger will only match or fire if the low bits of + * {csr-mcontext}/{csr-hcontext} equal {textra32-mhvalue}. */ #define CSR_TEXTRA32_MHSELECT_MCONTEXT 4 /* - * 1, 5 (mcontext\_select): This trigger will only match if the low bits of - * \RcsrMcontext/\RcsrHcontext equal \{\FcsrTextraThirtytwoMhvalue, mhselect[2]\}. + * 1, 5 (mcontext_select): This trigger will only match or fire if the + * low bits of + * {csr-mcontext}/{csr-hcontext} equal {{textra32-mhvalue}, mhselect[2]}. * - * 2, 6 (vmid\_select): This trigger will only match if VMID in hgatp equals the lower VMIDMAX - * (defined in the Privileged Spec) bits of \{\FcsrTextraThirtytwoMhvalue, mhselect[2]\}. + * 2, 6 (vmid_select): This trigger will only match or fire if VMID in + * hgatp equals the lower VMIDMAX + * (defined in the Privileged Spec) bits of {{textra32-mhvalue}, mhselect[2]}. * * 3, 7 (reserved): Reserved. * @@ -1704,193 +1847,192 @@ */ /* * When the least significant bit of this field is 1, it causes bits 7:0 - * in the comparison to be ignored, when \FcsrTextraThirtytwoSselect=1. + * in the comparison to be ignored, when {textra32-sselect}=1. * When the next most significant bit of this field is 1, it causes bits 15:8 - * to be ignored in the comparison, when \FcsrTextraThirtytwoSselect=1. + * to be ignored in the comparison, when {textra32-sselect}=1. */ -#define CSR_TEXTRA32_SBYTEMASK_OFFSET 0x12 -#define CSR_TEXTRA32_SBYTEMASK_LENGTH 2 -#define CSR_TEXTRA32_SBYTEMASK 0xc0000 +#define CSR_TEXTRA32_SBYTEMASK_OFFSET 0x12ULL +#define CSR_TEXTRA32_SBYTEMASK_LENGTH 2ULL +#define CSR_TEXTRA32_SBYTEMASK 0xc0000ULL /* - * Data used together with \FcsrTextraThirtytwoSselect. + * Data used together with {textra32-sselect}. * * This field should be tied to 0 when S-mode is not supported. */ -#define CSR_TEXTRA32_SVALUE_OFFSET 2 -#define CSR_TEXTRA32_SVALUE_LENGTH 0x10 -#define CSR_TEXTRA32_SVALUE 0x3fffc -#define CSR_TEXTRA32_SSELECT_OFFSET 0 -#define CSR_TEXTRA32_SSELECT_LENGTH 2 -#define CSR_TEXTRA32_SSELECT 3 +#define CSR_TEXTRA32_SVALUE_OFFSET 2ULL +#define CSR_TEXTRA32_SVALUE_LENGTH 0x10ULL +#define CSR_TEXTRA32_SVALUE 0x3fffcULL +#define CSR_TEXTRA32_SSELECT_OFFSET 0ULL +#define CSR_TEXTRA32_SSELECT_LENGTH 2ULL +#define CSR_TEXTRA32_SSELECT 3ULL /* - * ignore: Ignore \FcsrTextraThirtytwoSvalue. + * ignore: Ignore {textra32-svalue}. */ #define CSR_TEXTRA32_SSELECT_IGNORE 0 /* - * scontext: This trigger will only match if the low bits of - * \RcsrScontext equal \FcsrTextraThirtytwoSvalue. + * scontext: This trigger will only match or fire if the low bits of + * {csr-scontext} equal {textra32-svalue}. */ #define CSR_TEXTRA32_SSELECT_SCONTEXT 1 /* - * asid: This trigger will only match if: - * \begin{itemize}[noitemsep,nolistsep] - * \item the mode is VS-mode or VU-mode and ASID in \Rvsatp + * asid: This trigger will only match or fire if: + * + * * the mode is VS-mode or VU-mode and ASID in `vsatp` * equals the lower ASIDMAX (defined in the Privileged Spec) bits - * of \FcsrTextraThirtytwoSvalue. - * \item in all other modes, ASID in \Rsatp equals the lower + * of {textra32-svalue}. + * + * * in all other modes, ASID in `satp` equals the lower * ASIDMAX (defined in the Privileged Spec) bits of - * \FcsrTextraThirtytwoSvalue. - * \end{itemize} + * {textra32-svalue}. */ #define CSR_TEXTRA32_SSELECT_ASID 2 /* * This field should be tied to 0 when S-mode is not supported. */ #define CSR_TEXTRA64 0x7a3 -#define CSR_TEXTRA64_MHVALUE_OFFSET 0x33 -#define CSR_TEXTRA64_MHVALUE_LENGTH 0xd +#define CSR_TEXTRA64_MHVALUE_OFFSET 0x33ULL +#define CSR_TEXTRA64_MHVALUE_LENGTH 0xdULL #define CSR_TEXTRA64_MHVALUE 0xfff8000000000000ULL -#define CSR_TEXTRA64_MHSELECT_OFFSET 0x30 -#define CSR_TEXTRA64_MHSELECT_LENGTH 3 +#define CSR_TEXTRA64_MHSELECT_OFFSET 0x30ULL +#define CSR_TEXTRA64_MHSELECT_LENGTH 3ULL #define CSR_TEXTRA64_MHSELECT 0x7000000000000ULL /* * When the least significant bit of this field is 1, it causes bits 7:0 - * in the comparison to be ignored, when \FcsrTextraSixtyfourSselect=1. + * in the comparison to be ignored, when {textra64-sselect}=1. * Likewise, the second bit controls the comparison of bits 15:8, * third bit controls the comparison of bits 23:16, - * fourth bit controls the comparison of bits 31:24, and - * fifth bit controls the comparison of bits 33:32. - */ -#define CSR_TEXTRA64_SBYTEMASK_OFFSET 0x24 -#define CSR_TEXTRA64_SBYTEMASK_LENGTH 5 -#define CSR_TEXTRA64_SBYTEMASK 0x1f000000000ULL -#define CSR_TEXTRA64_SVALUE_OFFSET 2 -#define CSR_TEXTRA64_SVALUE_LENGTH 0x22 -#define CSR_TEXTRA64_SVALUE 0xffffffffcULL -#define CSR_TEXTRA64_SSELECT_OFFSET 0 -#define CSR_TEXTRA64_SSELECT_LENGTH 2 -#define CSR_TEXTRA64_SSELECT 3 + * and fourth bit controls the comparison of bits 31:24. + */ +#define CSR_TEXTRA64_SBYTEMASK_OFFSET 0x24ULL +#define CSR_TEXTRA64_SBYTEMASK_LENGTH 4ULL +#define CSR_TEXTRA64_SBYTEMASK 0xf000000000ULL +#define CSR_TEXTRA64_SVALUE_OFFSET 2ULL +#define CSR_TEXTRA64_SVALUE_LENGTH 0x20ULL +#define CSR_TEXTRA64_SVALUE 0x3fffffffcULL +#define CSR_TEXTRA64_SSELECT_OFFSET 0ULL +#define CSR_TEXTRA64_SSELECT_LENGTH 2ULL +#define CSR_TEXTRA64_SSELECT 3ULL #define DM_DMSTATUS 0x11 -#define DM_DMSTATUS_NDMRESETPENDING_OFFSET 0x18 -#define DM_DMSTATUS_NDMRESETPENDING_LENGTH 1 -#define DM_DMSTATUS_NDMRESETPENDING 0x1000000 +#define DM_DMSTATUS_NDMRESETPENDING_OFFSET 0x18ULL +#define DM_DMSTATUS_NDMRESETPENDING_LENGTH 1ULL +#define DM_DMSTATUS_NDMRESETPENDING 0x1000000ULL /* - * false: Unimplemented, or \FdmDmcontrolNdmreset is zero and no ndmreset is currently + * false: Unimplemented, or {dmcontrol-ndmreset} is zero and no ndmreset is currently * in progress. */ #define DM_DMSTATUS_NDMRESETPENDING_FALSE 0 /* - * true: \FdmDmcontrolNdmreset is currently nonzero, or there is an ndmreset in progress. + * true: {dmcontrol-ndmreset} is currently nonzero, or there is an ndmreset in progress. */ #define DM_DMSTATUS_NDMRESETPENDING_TRUE 1 -#define DM_DMSTATUS_STICKYUNAVAIL_OFFSET 0x17 -#define DM_DMSTATUS_STICKYUNAVAIL_LENGTH 1 -#define DM_DMSTATUS_STICKYUNAVAIL 0x800000 +#define DM_DMSTATUS_STICKYUNAVAIL_OFFSET 0x17ULL +#define DM_DMSTATUS_STICKYUNAVAIL_LENGTH 1ULL +#define DM_DMSTATUS_STICKYUNAVAIL 0x800000ULL /* - * current: The per-hart {\tt unavail} bits reflect the current state of the hart. + * current: The per-hart `unavail` bits reflect the current state of the hart. */ #define DM_DMSTATUS_STICKYUNAVAIL_CURRENT 0 /* - * sticky: The per-hart {\tt unavail} bits are sticky. Once they are set, they will - * not clear until the debugger acknowledges them using \FdmDmcontrolAckunavail. + * sticky: The per-hart `unavail` bits are sticky. Once they are set, they will + * not clear until the debugger acknowledges them using {dmcontrol-ackunavail}. */ #define DM_DMSTATUS_STICKYUNAVAIL_STICKY 1 /* - * If 1, then there is an implicit {\tt ebreak} instruction at the + * If 1, then there is an implicit `ebreak` instruction at the * non-existent word immediately after the Program Buffer. This saves - * the debugger from having to write the {\tt ebreak} itself, and + * the debugger from having to write the `ebreak` itself, and * allows the Program Buffer to be one word smaller. * - * This must be 1 when \FdmAbstractcsProgbufsize is 1. + * This must be 1 when {abstractcs-progbufsize} is 1. */ -#define DM_DMSTATUS_IMPEBREAK_OFFSET 0x16 -#define DM_DMSTATUS_IMPEBREAK_LENGTH 1 -#define DM_DMSTATUS_IMPEBREAK 0x400000 +#define DM_DMSTATUS_IMPEBREAK_OFFSET 0x16ULL +#define DM_DMSTATUS_IMPEBREAK_LENGTH 1ULL +#define DM_DMSTATUS_IMPEBREAK 0x400000ULL /* * This field is 1 when all currently selected harts have been reset * and reset has not been acknowledged for any of them. */ -#define DM_DMSTATUS_ALLHAVERESET_OFFSET 0x13 -#define DM_DMSTATUS_ALLHAVERESET_LENGTH 1 -#define DM_DMSTATUS_ALLHAVERESET 0x80000 +#define DM_DMSTATUS_ALLHAVERESET_OFFSET 0x13ULL +#define DM_DMSTATUS_ALLHAVERESET_LENGTH 1ULL +#define DM_DMSTATUS_ALLHAVERESET 0x80000ULL /* * This field is 1 when at least one currently selected hart has been * reset and reset has not been acknowledged for that hart. */ -#define DM_DMSTATUS_ANYHAVERESET_OFFSET 0x12 -#define DM_DMSTATUS_ANYHAVERESET_LENGTH 1 -#define DM_DMSTATUS_ANYHAVERESET 0x40000 +#define DM_DMSTATUS_ANYHAVERESET_OFFSET 0x12ULL +#define DM_DMSTATUS_ANYHAVERESET_LENGTH 1ULL +#define DM_DMSTATUS_ANYHAVERESET 0x40000ULL /* * This field is 1 when all currently selected harts have their - * resume ack bit\index{resume ack bit} set. + * ((resume ack bit)) set. */ -#define DM_DMSTATUS_ALLRESUMEACK_OFFSET 0x11 -#define DM_DMSTATUS_ALLRESUMEACK_LENGTH 1 -#define DM_DMSTATUS_ALLRESUMEACK 0x20000 +#define DM_DMSTATUS_ALLRESUMEACK_OFFSET 0x11ULL +#define DM_DMSTATUS_ALLRESUMEACK_LENGTH 1ULL +#define DM_DMSTATUS_ALLRESUMEACK 0x20000ULL /* * This field is 1 when any currently selected hart has its - * resume ack bit\index{resume ack bit} set. + * ((resume ack bit)) set. */ -#define DM_DMSTATUS_ANYRESUMEACK_OFFSET 0x10 -#define DM_DMSTATUS_ANYRESUMEACK_LENGTH 1 -#define DM_DMSTATUS_ANYRESUMEACK 0x10000 +#define DM_DMSTATUS_ANYRESUMEACK_OFFSET 0x10ULL +#define DM_DMSTATUS_ANYRESUMEACK_LENGTH 1ULL +#define DM_DMSTATUS_ANYRESUMEACK 0x10000ULL /* * This field is 1 when all currently selected harts do not exist in * this hardware platform. */ -#define DM_DMSTATUS_ALLNONEXISTENT_OFFSET 0xf -#define DM_DMSTATUS_ALLNONEXISTENT_LENGTH 1 -#define DM_DMSTATUS_ALLNONEXISTENT 0x8000 +#define DM_DMSTATUS_ALLNONEXISTENT_OFFSET 0xfULL +#define DM_DMSTATUS_ALLNONEXISTENT_LENGTH 1ULL +#define DM_DMSTATUS_ALLNONEXISTENT 0x8000ULL /* * This field is 1 when any currently selected hart does not exist in * this hardware platform. */ -#define DM_DMSTATUS_ANYNONEXISTENT_OFFSET 0xe -#define DM_DMSTATUS_ANYNONEXISTENT_LENGTH 1 -#define DM_DMSTATUS_ANYNONEXISTENT 0x4000 +#define DM_DMSTATUS_ANYNONEXISTENT_OFFSET 0xeULL +#define DM_DMSTATUS_ANYNONEXISTENT_LENGTH 1ULL +#define DM_DMSTATUS_ANYNONEXISTENT 0x4000ULL /* * This field is 1 when all currently selected harts are - * unavailable, or (if \FdmDmstatusStickyunavail is 1) were + * unavailable, or (if {dmstatus-stickyunavail} is 1) were * unavailable without that being acknowledged. */ -#define DM_DMSTATUS_ALLUNAVAIL_OFFSET 0xd -#define DM_DMSTATUS_ALLUNAVAIL_LENGTH 1 -#define DM_DMSTATUS_ALLUNAVAIL 0x2000 +#define DM_DMSTATUS_ALLUNAVAIL_OFFSET 0xdULL +#define DM_DMSTATUS_ALLUNAVAIL_LENGTH 1ULL +#define DM_DMSTATUS_ALLUNAVAIL 0x2000ULL /* * This field is 1 when any currently selected hart is unavailable, - * or (if \FdmDmstatusStickyunavail is 1) was unavailable without + * or (if {dmstatus-stickyunavail} is 1) was unavailable without * that being acknowledged. */ -#define DM_DMSTATUS_ANYUNAVAIL_OFFSET 0xc -#define DM_DMSTATUS_ANYUNAVAIL_LENGTH 1 -#define DM_DMSTATUS_ANYUNAVAIL 0x1000 +#define DM_DMSTATUS_ANYUNAVAIL_OFFSET 0xcULL +#define DM_DMSTATUS_ANYUNAVAIL_LENGTH 1ULL +#define DM_DMSTATUS_ANYUNAVAIL 0x1000ULL /* * This field is 1 when all currently selected harts are running. */ -#define DM_DMSTATUS_ALLRUNNING_OFFSET 0xb -#define DM_DMSTATUS_ALLRUNNING_LENGTH 1 -#define DM_DMSTATUS_ALLRUNNING 0x800 +#define DM_DMSTATUS_ALLRUNNING_OFFSET 0xbULL +#define DM_DMSTATUS_ALLRUNNING_LENGTH 1ULL +#define DM_DMSTATUS_ALLRUNNING 0x800ULL /* * This field is 1 when any currently selected hart is running. */ -#define DM_DMSTATUS_ANYRUNNING_OFFSET 0xa -#define DM_DMSTATUS_ANYRUNNING_LENGTH 1 -#define DM_DMSTATUS_ANYRUNNING 0x400 +#define DM_DMSTATUS_ANYRUNNING_OFFSET 0xaULL +#define DM_DMSTATUS_ANYRUNNING_LENGTH 1ULL +#define DM_DMSTATUS_ANYRUNNING 0x400ULL /* * This field is 1 when all currently selected harts are halted. */ -#define DM_DMSTATUS_ALLHALTED_OFFSET 9 -#define DM_DMSTATUS_ALLHALTED_LENGTH 1 -#define DM_DMSTATUS_ALLHALTED 0x200 +#define DM_DMSTATUS_ALLHALTED_OFFSET 9ULL +#define DM_DMSTATUS_ALLHALTED_LENGTH 1ULL +#define DM_DMSTATUS_ALLHALTED 0x200ULL /* * This field is 1 when any currently selected hart is halted. */ -#define DM_DMSTATUS_ANYHALTED_OFFSET 8 -#define DM_DMSTATUS_ANYHALTED_LENGTH 1 -#define DM_DMSTATUS_ANYHALTED 0x100 -#define DM_DMSTATUS_AUTHENTICATED_OFFSET 7 -#define DM_DMSTATUS_AUTHENTICATED_LENGTH 1 -#define DM_DMSTATUS_AUTHENTICATED 0x80 +#define DM_DMSTATUS_ANYHALTED_OFFSET 8ULL +#define DM_DMSTATUS_ANYHALTED_LENGTH 1ULL +#define DM_DMSTATUS_ANYHALTED 0x100ULL +#define DM_DMSTATUS_AUTHENTICATED_OFFSET 7ULL +#define DM_DMSTATUS_AUTHENTICATED_LENGTH 1ULL +#define DM_DMSTATUS_AUTHENTICATED 0x80ULL /* * false: Authentication is required before using the DM. */ @@ -1903,47 +2045,47 @@ * On components that don't implement authentication, this bit must be * preset as 1. */ -#define DM_DMSTATUS_AUTHBUSY_OFFSET 6 -#define DM_DMSTATUS_AUTHBUSY_LENGTH 1 -#define DM_DMSTATUS_AUTHBUSY 0x40 +#define DM_DMSTATUS_AUTHBUSY_OFFSET 6ULL +#define DM_DMSTATUS_AUTHBUSY_LENGTH 1ULL +#define DM_DMSTATUS_AUTHBUSY 0x40ULL /* * ready: The authentication module is ready to process the next - * read/write to \RdmAuthdata. + * read/write to {dm-authdata}. */ #define DM_DMSTATUS_AUTHBUSY_READY 0 /* - * busy: The authentication module is busy. Accessing \RdmAuthdata results + * busy: The authentication module is busy. Accessing {dm-authdata} results * in unspecified behavior. */ #define DM_DMSTATUS_AUTHBUSY_BUSY 1 /* - * \FdmDmstatusAuthbusy only becomes set in immediate response to an access to - * \RdmAuthdata. + * {dmstatus-authbusy} only becomes set in immediate response to an access to + * {dm-authdata}. */ /* * 1 if this Debug Module supports halt-on-reset functionality - * controllable by the \FdmDmcontrolSetresethaltreq and \FdmDmcontrolClrresethaltreq bits. + * controllable by the {dmcontrol-setresethaltreq} and {dmcontrol-clrresethaltreq} bits. * 0 otherwise. */ -#define DM_DMSTATUS_HASRESETHALTREQ_OFFSET 5 -#define DM_DMSTATUS_HASRESETHALTREQ_LENGTH 1 -#define DM_DMSTATUS_HASRESETHALTREQ 0x20 -#define DM_DMSTATUS_CONFSTRPTRVALID_OFFSET 4 -#define DM_DMSTATUS_CONFSTRPTRVALID_LENGTH 1 -#define DM_DMSTATUS_CONFSTRPTRVALID 0x10 +#define DM_DMSTATUS_HASRESETHALTREQ_OFFSET 5ULL +#define DM_DMSTATUS_HASRESETHALTREQ_LENGTH 1ULL +#define DM_DMSTATUS_HASRESETHALTREQ 0x20ULL +#define DM_DMSTATUS_CONFSTRPTRVALID_OFFSET 4ULL +#define DM_DMSTATUS_CONFSTRPTRVALID_LENGTH 1ULL +#define DM_DMSTATUS_CONFSTRPTRVALID 0x10ULL /* - * invalid: \RdmConfstrptrZero--\RdmConfstrptrThree hold information which + * invalid: {dm-confstrptr0}--{dm-confstrptr3} hold information which * is not relevant to the configuration structure. */ #define DM_DMSTATUS_CONFSTRPTRVALID_INVALID 0 /* - * valid: \RdmConfstrptrZero--\RdmConfstrptrThree hold the address of the + * valid: {dm-confstrptr0}--{dm-confstrptr3} hold the address of the * configuration structure. */ #define DM_DMSTATUS_CONFSTRPTRVALID_VALID 1 -#define DM_DMSTATUS_VERSION_OFFSET 0 -#define DM_DMSTATUS_VERSION_LENGTH 4 -#define DM_DMSTATUS_VERSION 0xf +#define DM_DMSTATUS_VERSION_OFFSET 0ULL +#define DM_DMSTATUS_VERSION_LENGTH 4ULL +#define DM_DMSTATUS_VERSION 0xfULL /* * none: There is no Debug Module present. */ @@ -1977,23 +2119,23 @@ * harts. Running harts will halt whenever their halt request bit is * set. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_HALTREQ_OFFSET 0x1f -#define DM_DMCONTROL_HALTREQ_LENGTH 1 -#define DM_DMCONTROL_HALTREQ 0x80000000U +#define DM_DMCONTROL_HALTREQ_OFFSET 0x1fULL +#define DM_DMCONTROL_HALTREQ_LENGTH 1ULL +#define DM_DMCONTROL_HALTREQ 0x80000000ULL /* * Writing 1 causes the currently selected harts to resume once, if * they are halted when the write occurs. It also clears the resume * ack bit for those harts. * - * \FdmDmcontrolResumereq is ignored if \FdmDmcontrolHaltreq is set. + * {dmcontrol-resumereq} is ignored if {dmcontrol-haltreq} is set. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_RESUMEREQ_OFFSET 0x1e -#define DM_DMCONTROL_RESUMEREQ_LENGTH 1 -#define DM_DMCONTROL_RESUMEREQ 0x40000000 +#define DM_DMCONTROL_RESUMEREQ_OFFSET 0x1eULL +#define DM_DMCONTROL_RESUMEREQ_LENGTH 1ULL +#define DM_DMCONTROL_RESUMEREQ 0x40000000ULL /* * This optional field writes the reset bit for all the currently * selected harts. To perform a reset the debugger writes 1, and then @@ -2006,52 +2148,52 @@ * after writing 1 the debugger can read the register back to see if * the feature is supported. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_HARTRESET_OFFSET 0x1d -#define DM_DMCONTROL_HARTRESET_LENGTH 1 -#define DM_DMCONTROL_HARTRESET 0x20000000 -#define DM_DMCONTROL_ACKHAVERESET_OFFSET 0x1c -#define DM_DMCONTROL_ACKHAVERESET_LENGTH 1 -#define DM_DMCONTROL_ACKHAVERESET 0x10000000 +#define DM_DMCONTROL_HARTRESET_OFFSET 0x1dULL +#define DM_DMCONTROL_HARTRESET_LENGTH 1ULL +#define DM_DMCONTROL_HARTRESET 0x20000000ULL +#define DM_DMCONTROL_ACKHAVERESET_OFFSET 0x1cULL +#define DM_DMCONTROL_ACKHAVERESET_LENGTH 1ULL +#define DM_DMCONTROL_ACKHAVERESET 0x10000000ULL /* * nop: No effect. */ #define DM_DMCONTROL_ACKHAVERESET_NOP 0 /* - * ack: Clears {\tt havereset} for any selected harts. + * ack: Clears `havereset` for any selected harts. */ #define DM_DMCONTROL_ACKHAVERESET_ACK 1 /* - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_ACKUNAVAIL_OFFSET 0x1b -#define DM_DMCONTROL_ACKUNAVAIL_LENGTH 1 -#define DM_DMCONTROL_ACKUNAVAIL 0x8000000 +#define DM_DMCONTROL_ACKUNAVAIL_OFFSET 0x1bULL +#define DM_DMCONTROL_ACKUNAVAIL_LENGTH 1ULL +#define DM_DMCONTROL_ACKUNAVAIL 0x8000000ULL /* * nop: No effect. */ #define DM_DMCONTROL_ACKUNAVAIL_NOP 0 /* - * ack: Clears {\tt unavail} for any selected harts that are currently available. + * ack: Clears `unavail` for any selected harts that are currently available. */ #define DM_DMCONTROL_ACKUNAVAIL_ACK 1 /* - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ /* * Selects the definition of currently selected harts. */ -#define DM_DMCONTROL_HASEL_OFFSET 0x1a -#define DM_DMCONTROL_HASEL_LENGTH 1 -#define DM_DMCONTROL_HASEL 0x4000000 +#define DM_DMCONTROL_HASEL_OFFSET 0x1aULL +#define DM_DMCONTROL_HASEL_LENGTH 1ULL +#define DM_DMCONTROL_HASEL 0x4000000ULL /* - * single: There is a single currently selected hart, that is selected by \Fhartsel. + * single: There is a single currently selected hart, that is selected by {hartsel}. */ #define DM_DMCONTROL_HASEL_SINGLE 0 /* * multiple: There may be multiple currently selected harts -- the hart - * selected by \Fhartsel, plus those selected by the hart array mask + * selected by {hartsel}, plus those selected by the hart array mask * register. */ #define DM_DMCONTROL_HASEL_MULTIPLE 1 @@ -2062,62 +2204,62 @@ * is supported. */ /* - * The low 10 bits of \Fhartsel: the DM-specific index of the hart to + * The low 10 bits of {hartsel}: the DM-specific index of the hart to * select. This hart is always part of the currently selected harts. */ -#define DM_DMCONTROL_HARTSELLO_OFFSET 0x10 -#define DM_DMCONTROL_HARTSELLO_LENGTH 0xa -#define DM_DMCONTROL_HARTSELLO 0x3ff0000 +#define DM_DMCONTROL_HARTSELLO_OFFSET 0x10ULL +#define DM_DMCONTROL_HARTSELLO_LENGTH 0xaULL +#define DM_DMCONTROL_HARTSELLO 0x3ff0000ULL /* - * The high 10 bits of \Fhartsel: the DM-specific index of the hart to + * The high 10 bits of {hartsel}: the DM-specific index of the hart to * select. This hart is always part of the currently selected harts. */ -#define DM_DMCONTROL_HARTSELHI_OFFSET 6 -#define DM_DMCONTROL_HARTSELHI_LENGTH 0xa -#define DM_DMCONTROL_HARTSELHI 0xffc0 +#define DM_DMCONTROL_HARTSELHI_OFFSET 6ULL +#define DM_DMCONTROL_HARTSELHI_LENGTH 0xaULL +#define DM_DMCONTROL_HARTSELHI 0xffc0ULL /* - * This optional field sets \Fkeepalive for all currently selected - * harts, unless \FdmDmcontrolClrkeepalive is simultaneously set to + * This optional field sets {keepalive} for all currently selected + * harts, unless {dmcontrol-clrkeepalive} is simultaneously set to * 1. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_SETKEEPALIVE_OFFSET 5 -#define DM_DMCONTROL_SETKEEPALIVE_LENGTH 1 -#define DM_DMCONTROL_SETKEEPALIVE 0x20 +#define DM_DMCONTROL_SETKEEPALIVE_OFFSET 5ULL +#define DM_DMCONTROL_SETKEEPALIVE_LENGTH 1ULL +#define DM_DMCONTROL_SETKEEPALIVE 0x20ULL /* - * This optional field clears \Fkeepalive for all currently selected + * This optional field clears {keepalive} for all currently selected * harts. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_CLRKEEPALIVE_OFFSET 4 -#define DM_DMCONTROL_CLRKEEPALIVE_LENGTH 1 -#define DM_DMCONTROL_CLRKEEPALIVE 0x10 +#define DM_DMCONTROL_CLRKEEPALIVE_OFFSET 4ULL +#define DM_DMCONTROL_CLRKEEPALIVE_LENGTH 1ULL +#define DM_DMCONTROL_CLRKEEPALIVE 0x10ULL /* * This optional field writes the halt-on-reset request bit for all - * currently selected harts, unless \FdmDmcontrolClrresethaltreq is + * currently selected harts, unless {dmcontrol-clrresethaltreq} is * simultaneously set to 1. * When set to 1, each selected hart will halt upon the next deassertion * of its reset. The halt-on-reset request bit is not automatically - * cleared. The debugger must write to \FdmDmcontrolClrresethaltreq to clear it. + * cleared. The debugger must write to {dmcontrol-clrresethaltreq} to clear it. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. * - * If \FdmDmstatusHasresethaltreq is 0, this field is not implemented. + * If {dmstatus-hasresethaltreq} is 0, this field is not implemented. */ -#define DM_DMCONTROL_SETRESETHALTREQ_OFFSET 3 -#define DM_DMCONTROL_SETRESETHALTREQ_LENGTH 1 -#define DM_DMCONTROL_SETRESETHALTREQ 8 +#define DM_DMCONTROL_SETRESETHALTREQ_OFFSET 3ULL +#define DM_DMCONTROL_SETRESETHALTREQ_LENGTH 1ULL +#define DM_DMCONTROL_SETRESETHALTREQ 8ULL /* * This optional field clears the halt-on-reset request bit for all * currently selected harts. * - * Writes apply to the new value of \Fhartsel and \FdmDmcontrolHasel. + * Writes apply to the new value of {hartsel} and {dmcontrol-hasel}. */ -#define DM_DMCONTROL_CLRRESETHALTREQ_OFFSET 2 -#define DM_DMCONTROL_CLRRESETHALTREQ_LENGTH 1 -#define DM_DMCONTROL_CLRRESETHALTREQ 4 +#define DM_DMCONTROL_CLRRESETHALTREQ_OFFSET 2ULL +#define DM_DMCONTROL_CLRRESETHALTREQ_LENGTH 1ULL +#define DM_DMCONTROL_CLRRESETHALTREQ 4ULL /* * This bit controls the reset signal from the DM to the rest of the * hardware platform. The signal should reset every part of the hardware platform, including @@ -2127,26 +2269,26 @@ * and then writes 0 * to deassert the reset. */ -#define DM_DMCONTROL_NDMRESET_OFFSET 1 -#define DM_DMCONTROL_NDMRESET_LENGTH 1 -#define DM_DMCONTROL_NDMRESET 2 +#define DM_DMCONTROL_NDMRESET_OFFSET 1ULL +#define DM_DMCONTROL_NDMRESET_LENGTH 1ULL +#define DM_DMCONTROL_NDMRESET 2ULL /* * This bit serves as a reset signal for the Debug Module itself. * After changing the value of this bit, the debugger must poll - * \RdmDmcontrol until \FdmDmcontrolDmactive has taken the requested value - * before performing any action that assumes the requested \FdmDmcontrolDmactive + * {dm-dmcontrol} until {dmcontrol-dmactive} has taken the requested value + * before performing any action that assumes the requested {dmcontrol-dmactive} * state change has completed. Hardware may * take an arbitrarily long time to complete activation or deactivation and will - * indicate completion by setting \FdmDmcontrolDmactive to the requested value. + * indicate completion by setting {dmcontrol-dmactive} to the requested value. */ -#define DM_DMCONTROL_DMACTIVE_OFFSET 0 -#define DM_DMCONTROL_DMACTIVE_LENGTH 1 -#define DM_DMCONTROL_DMACTIVE 1 +#define DM_DMCONTROL_DMACTIVE_OFFSET 0ULL +#define DM_DMCONTROL_DMACTIVE_LENGTH 1ULL +#define DM_DMCONTROL_DMACTIVE 1ULL /* * inactive: The module's state, including authentication mechanism, - * takes its reset values (the \FdmDmcontrolDmactive bit is the only bit which can + * takes its reset values (the {dmcontrol-dmactive} bit is the only bit which can * be written to something other than its reset value). Any accesses - * to the module may fail. Specifically, \FdmDmstatusVersion might not return + * to the module may fail. Specifically, {dmstatus-version} might not return * correct data. */ #define DM_DMCONTROL_DMACTIVE_INACTIVE 0 @@ -2158,9 +2300,9 @@ * No other mechanism should exist that may result in resetting the * Debug Module after power up. * - * To place the Debug Module into a known state, a debugger may write 0 to \FdmDmcontrolDmactive, - * poll until \FdmDmcontrolDmactive is observed 0, write 1 to \FdmDmcontrolDmactive, and - * poll until \FdmDmcontrolDmactive is observed 1. + * To place the Debug Module into a known state, a debugger may write 0 to {dmcontrol-dmactive}, + * poll until {dmcontrol-dmactive} is observed 0, write 1 to {dmcontrol-dmactive}, and + * poll until {dmcontrol-dmactive} is observed 1. * * Implementations may pay attention to this bit to further aid * debugging, for example by preventing the Debug Module from being @@ -2168,80 +2310,76 @@ */ #define DM_HARTINFO 0x12 /* - * Number of {\tt dscratch} registers available for the debugger - * to use during program buffer execution, starting from \RcsrDscratchZero. + * Number of `dscratch` registers available for the debugger + * to use during program buffer execution, starting from {csr-dscratch0}. * The debugger can make no assumptions about the contents of these * registers between commands. */ -#define DM_HARTINFO_NSCRATCH_OFFSET 0x14 -#define DM_HARTINFO_NSCRATCH_LENGTH 4 -#define DM_HARTINFO_NSCRATCH 0xf00000 -#define DM_HARTINFO_DATAACCESS_OFFSET 0x10 -#define DM_HARTINFO_DATAACCESS_LENGTH 1 -#define DM_HARTINFO_DATAACCESS 0x10000 +#define DM_HARTINFO_NSCRATCH_OFFSET 0x14ULL +#define DM_HARTINFO_NSCRATCH_LENGTH 4ULL +#define DM_HARTINFO_NSCRATCH 0xf00000ULL +#define DM_HARTINFO_DATAACCESS_OFFSET 0x10ULL +#define DM_HARTINFO_DATAACCESS_LENGTH 1ULL +#define DM_HARTINFO_DATAACCESS 0x10000ULL /* - * csr: The {\tt data} registers are shadowed in the hart by CSRs. + * csr: The `data` registers are shadowed in the hart by CSRs. * Each CSR is DXLEN bits in size, and corresponds - * to a single argument, per Table~\ref{tab:datareg}. + * to a single argument, per <>. */ #define DM_HARTINFO_DATAACCESS_CSR 0 /* - * memory: The {\tt data} registers are shadowed in the hart's memory map. + * memory: The `data` registers are shadowed in the hart's memory map. * Each register takes up 4 bytes in the memory map. */ #define DM_HARTINFO_DATAACCESS_MEMORY 1 /* - * If \FdmHartinfoDataaccess is 0: Number of CSRs dedicated to - * shadowing the {\tt data} registers. - * - * If \FdmHartinfoDataaccess is 1: Number of 32-bit words in the memory map - * dedicated to shadowing the {\tt data} registers. + * If {hartinfo-dataaccess} is 0: Number of CSRs dedicated to + * shadowing the `data` registers. * - * If this value is non-zero, then the {tt data} registers must go - * beyond being MRs and guarantee they each store a single value, that is - * readable/writable by either side. + * If {hartinfo-dataaccess} is 1: Number of 32-bit words in the memory map + * dedicated to shadowing the `data` registers. * - * Since there are at most 12 {\tt data} registers, the value in this + * Since there are at most 12 `data` registers, the value in this * register must be 12 or smaller. */ -#define DM_HARTINFO_DATASIZE_OFFSET 0xc -#define DM_HARTINFO_DATASIZE_LENGTH 4 -#define DM_HARTINFO_DATASIZE 0xf000 +#define DM_HARTINFO_DATASIZE_OFFSET 0xcULL +#define DM_HARTINFO_DATASIZE_LENGTH 4ULL +#define DM_HARTINFO_DATASIZE 0xf000ULL /* - * If \FdmHartinfoDataaccess is 0: The number of the first CSR dedicated to - * shadowing the {\tt data} registers. + * If {hartinfo-dataaccess} is 0: The number of the first CSR dedicated to + * shadowing the `data` registers. * - * If \FdmHartinfoDataaccess is 1: Address of RAM where the data + * If {hartinfo-dataaccess} is 1: Address of RAM where the data * registers are shadowed. This address is sign extended giving a * range of -2048 to 2047, easily addressed with a load or store using - * \Xzero as the address register. + * `x0` as the address register. */ -#define DM_HARTINFO_DATAADDR_OFFSET 0 -#define DM_HARTINFO_DATAADDR_LENGTH 0xc -#define DM_HARTINFO_DATAADDR 0xfff +#define DM_HARTINFO_DATAADDR_OFFSET 0ULL +#define DM_HARTINFO_DATAADDR_LENGTH 0xcULL +#define DM_HARTINFO_DATAADDR 0xfffULL #define DM_HAWINDOWSEL 0x14 /* * The high bits of this field may be tied to 0, depending on how large - * the array mask register is. E.g.\ on a hardware platform with 48 harts only bit 0 + * the array mask register is. E.g. on a hardware platform with 48 harts only bit 0 * of this field may actually be writable. */ -#define DM_HAWINDOWSEL_HAWINDOWSEL_OFFSET 0 -#define DM_HAWINDOWSEL_HAWINDOWSEL_LENGTH 0xf -#define DM_HAWINDOWSEL_HAWINDOWSEL 0x7fff +#define DM_HAWINDOWSEL_HAWINDOWSEL_OFFSET 0ULL +#define DM_HAWINDOWSEL_HAWINDOWSEL_LENGTH 0xfULL +#define DM_HAWINDOWSEL_HAWINDOWSEL 0x7fffULL #define DM_HAWINDOW 0x15 -#define DM_HAWINDOW_MASKDATA_OFFSET 0 -#define DM_HAWINDOW_MASKDATA_LENGTH 0x20 -#define DM_HAWINDOW_MASKDATA 0xffffffffU +#define DM_HAWINDOW_MASKDATA_OFFSET 0ULL +#define DM_HAWINDOW_MASKDATA_LENGTH 0x20ULL +#define DM_HAWINDOW_MASKDATA 0xffffffffULL #define DM_ABSTRACTCS 0x16 /* * Size of the Program Buffer, in 32-bit words. Valid sizes are 0 - 16. */ -#define DM_ABSTRACTCS_PROGBUFSIZE_OFFSET 0x18 -#define DM_ABSTRACTCS_PROGBUFSIZE_LENGTH 5 -#define DM_ABSTRACTCS_PROGBUFSIZE 0x1f000000 -#define DM_ABSTRACTCS_BUSY_OFFSET 0xc -#define DM_ABSTRACTCS_BUSY_LENGTH 1 -#define DM_ABSTRACTCS_BUSY 0x1000 +#define DM_ABSTRACTCS_PROGBUFSIZE_OFFSET 0x18ULL +#define DM_ABSTRACTCS_PROGBUFSIZE_LENGTH 5ULL +#define DM_ABSTRACTCS_PROGBUFSIZE 0x1f000000ULL +#define DM_ABSTRACTCS_BUSY_OFFSET 0xcULL +#define DM_ABSTRACTCS_BUSY_LENGTH 1ULL +#define DM_ABSTRACTCS_BUSY 0x1000ULL /* * ready: There is no abstract command currently being executed. */ @@ -2251,7 +2389,7 @@ */ #define DM_ABSTRACTCS_BUSY_BUSY 1 /* - * This bit is set as soon as \RdmCommand is written, and is + * This bit is set as soon as {dm-command} is written, and is * not cleared until that command has completed. */ /* @@ -2262,9 +2400,9 @@ * permission checks (e.g. PMP restrictions are ignored). The * details of the latter are implementation-specific. */ -#define DM_ABSTRACTCS_RELAXEDPRIV_OFFSET 0xb -#define DM_ABSTRACTCS_RELAXEDPRIV_LENGTH 1 -#define DM_ABSTRACTCS_RELAXEDPRIV 0x800 +#define DM_ABSTRACTCS_RELAXEDPRIV_OFFSET 0xbULL +#define DM_ABSTRACTCS_RELAXEDPRIV_LENGTH 1ULL +#define DM_ABSTRACTCS_RELAXEDPRIV 0x800ULL /* * full checks: Full permission checks apply. */ @@ -2278,24 +2416,24 @@ * they are cleared by writing 1 to them. No abstract command is * started until the value is reset to 0. * - * This field only contains a valid value if \FdmAbstractcsBusy is 0. + * This field only contains a valid value if {abstractcs-busy} is 0. */ -#define DM_ABSTRACTCS_CMDERR_OFFSET 8 -#define DM_ABSTRACTCS_CMDERR_LENGTH 3 -#define DM_ABSTRACTCS_CMDERR 0x700 +#define DM_ABSTRACTCS_CMDERR_OFFSET 8ULL +#define DM_ABSTRACTCS_CMDERR_LENGTH 3ULL +#define DM_ABSTRACTCS_CMDERR 0x700ULL /* * none: No error. */ #define DM_ABSTRACTCS_CMDERR_NONE 0 /* - * busy: An abstract command was executing while \RdmCommand, - * \RdmAbstractcs, or \RdmAbstractauto was written, or when one - * of the {\tt data} or {\tt progbuf} registers was read or written. - * This status is only written if \FdmAbstractcsCmderr contains 0. + * busy: An abstract command was executing while {dm-command}, + * {dm-abstractcs}, or {dm-abstractauto} was written, or when one + * of the `data` or `progbuf` registers was read or written. + * This status is only written if {abstractcs-cmderr} contains 0. */ #define DM_ABSTRACTCS_CMDERR_BUSY 1 /* - * not supported: The command in \RdmCommand is not supported. It + * not supported: The command in {dm-command} is not supported. It * may be supported with different options set, but it will not be * supported at a later time when the hart or system state are * different. @@ -2303,7 +2441,7 @@ #define DM_ABSTRACTCS_CMDERR_NOT_SUPPORTED 2 /* * exception: An exception occurred while executing the command - * (e.g.\ while executing the Program Buffer). + * (e.g. while executing the Program Buffer). */ #define DM_ABSTRACTCS_CMDERR_EXCEPTION 3 /* @@ -2312,7 +2450,7 @@ */ #define DM_ABSTRACTCS_CMDERR_HALT_RESUME 4 /* - * bus: The abstract command failed due to a bus error (e.g.\ + * bus: The abstract command failed due to a bus error (e.g. * alignment, access size, or timeout). */ #define DM_ABSTRACTCS_CMDERR_BUS 5 @@ -2325,70 +2463,70 @@ */ #define DM_ABSTRACTCS_CMDERR_OTHER 7 /* - * Number of {\tt data} registers that are implemented as part of the + * Number of `data` registers that are implemented as part of the * abstract command interface. Valid sizes are 1 -- 12. */ -#define DM_ABSTRACTCS_DATACOUNT_OFFSET 0 -#define DM_ABSTRACTCS_DATACOUNT_LENGTH 4 -#define DM_ABSTRACTCS_DATACOUNT 0xf +#define DM_ABSTRACTCS_DATACOUNT_OFFSET 0ULL +#define DM_ABSTRACTCS_DATACOUNT_LENGTH 4ULL +#define DM_ABSTRACTCS_DATACOUNT 0xfULL #define DM_COMMAND 0x17 /* * The type determines the overall functionality of this * abstract command. */ -#define DM_COMMAND_CMDTYPE_OFFSET 0x18 -#define DM_COMMAND_CMDTYPE_LENGTH 8 -#define DM_COMMAND_CMDTYPE 0xff000000U +#define DM_COMMAND_CMDTYPE_OFFSET 0x18ULL +#define DM_COMMAND_CMDTYPE_LENGTH 8ULL +#define DM_COMMAND_CMDTYPE 0xff000000ULL /* * This field is interpreted in a command-specific manner, * described for each abstract command. */ -#define DM_COMMAND_CONTROL_OFFSET 0 -#define DM_COMMAND_CONTROL_LENGTH 0x18 -#define DM_COMMAND_CONTROL 0xffffff +#define DM_COMMAND_CONTROL_OFFSET 0ULL +#define DM_COMMAND_CONTROL_LENGTH 0x18ULL +#define DM_COMMAND_CONTROL 0xffffffULL #define DM_ABSTRACTAUTO 0x18 /* * When a bit in this field is 1, read or write accesses to the - * corresponding {\tt progbuf} word cause the DM to act as if the - * current value in \RdmCommand was written there again after the - * access to {\tt progbuf} completes. + * corresponding `progbuf` word cause the DM to act as if the + * current value in {dm-command} was written there again after the + * access to `progbuf` completes. */ -#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 0x10 -#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 0x10 -#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF 0xffff0000U +#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_OFFSET 0x10ULL +#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF_LENGTH 0x10ULL +#define DM_ABSTRACTAUTO_AUTOEXECPROGBUF 0xffff0000ULL /* * When a bit in this field is 1, read or write accesses to the - * corresponding {\tt data} word cause the DM to act as if the current - * value in \RdmCommand was written there again after the - * access to {\tt data} completes. + * corresponding `data` word cause the DM to act as if the current + * value in {dm-command} was written there again after the + * access to `data` completes. */ -#define DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0 -#define DM_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 0xc -#define DM_ABSTRACTAUTO_AUTOEXECDATA 0xfff +#define DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET 0ULL +#define DM_ABSTRACTAUTO_AUTOEXECDATA_LENGTH 0xcULL +#define DM_ABSTRACTAUTO_AUTOEXECDATA 0xfffULL #define DM_CONFSTRPTR0 0x19 -#define DM_CONFSTRPTR0_ADDR_OFFSET 0 -#define DM_CONFSTRPTR0_ADDR_LENGTH 0x20 -#define DM_CONFSTRPTR0_ADDR 0xffffffffU +#define DM_CONFSTRPTR0_ADDR_OFFSET 0ULL +#define DM_CONFSTRPTR0_ADDR_LENGTH 0x20ULL +#define DM_CONFSTRPTR0_ADDR 0xffffffffULL #define DM_CONFSTRPTR1 0x1a -#define DM_CONFSTRPTR1_ADDR_OFFSET 0 -#define DM_CONFSTRPTR1_ADDR_LENGTH 0x20 -#define DM_CONFSTRPTR1_ADDR 0xffffffffU +#define DM_CONFSTRPTR1_ADDR_OFFSET 0ULL +#define DM_CONFSTRPTR1_ADDR_LENGTH 0x20ULL +#define DM_CONFSTRPTR1_ADDR 0xffffffffULL #define DM_CONFSTRPTR2 0x1b -#define DM_CONFSTRPTR2_ADDR_OFFSET 0 -#define DM_CONFSTRPTR2_ADDR_LENGTH 0x20 -#define DM_CONFSTRPTR2_ADDR 0xffffffffU +#define DM_CONFSTRPTR2_ADDR_OFFSET 0ULL +#define DM_CONFSTRPTR2_ADDR_LENGTH 0x20ULL +#define DM_CONFSTRPTR2_ADDR 0xffffffffULL #define DM_CONFSTRPTR3 0x1c -#define DM_CONFSTRPTR3_ADDR_OFFSET 0 -#define DM_CONFSTRPTR3_ADDR_LENGTH 0x20 -#define DM_CONFSTRPTR3_ADDR 0xffffffffU +#define DM_CONFSTRPTR3_ADDR_OFFSET 0ULL +#define DM_CONFSTRPTR3_ADDR_LENGTH 0x20ULL +#define DM_CONFSTRPTR3_ADDR 0xffffffffULL #define DM_NEXTDM 0x1d -#define DM_NEXTDM_ADDR_OFFSET 0 -#define DM_NEXTDM_ADDR_LENGTH 0x20 -#define DM_NEXTDM_ADDR 0xffffffffU +#define DM_NEXTDM_ADDR_OFFSET 0ULL +#define DM_NEXTDM_ADDR_LENGTH 0x20ULL +#define DM_NEXTDM_ADDR 0xffffffffULL #define DM_DATA0 0x04 -#define DM_DATA0_DATA_OFFSET 0 -#define DM_DATA0_DATA_LENGTH 0x20 -#define DM_DATA0_DATA 0xffffffffU +#define DM_DATA0_DATA_OFFSET 0ULL +#define DM_DATA0_DATA_LENGTH 0x20ULL +#define DM_DATA0_DATA 0xffffffffULL #define DM_DATA1 0x05 #define DM_DATA2 0x06 #define DM_DATA3 0x07 @@ -2401,9 +2539,9 @@ #define DM_DATA10 0x0e #define DM_DATA11 0x0f #define DM_PROGBUF0 0x20 -#define DM_PROGBUF0_DATA_OFFSET 0 -#define DM_PROGBUF0_DATA_LENGTH 0x20 -#define DM_PROGBUF0_DATA 0xffffffffU +#define DM_PROGBUF0_DATA_OFFSET 0ULL +#define DM_PROGBUF0_DATA_LENGTH 0x20ULL +#define DM_PROGBUF0_DATA 0xffffffffULL #define DM_PROGBUF1 0x21 #define DM_PROGBUF2 0x22 #define DM_PROGBUF3 0x23 @@ -2420,13 +2558,13 @@ #define DM_PROGBUF14 0x2e #define DM_PROGBUF15 0x2f #define DM_AUTHDATA 0x30 -#define DM_AUTHDATA_DATA_OFFSET 0 -#define DM_AUTHDATA_DATA_LENGTH 0x20 -#define DM_AUTHDATA_DATA 0xffffffffU +#define DM_AUTHDATA_DATA_OFFSET 0ULL +#define DM_AUTHDATA_DATA_LENGTH 0x20ULL +#define DM_AUTHDATA_DATA 0xffffffffULL #define DM_DMCS2 0x32 -#define DM_DMCS2_GROUPTYPE_OFFSET 0xb -#define DM_DMCS2_GROUPTYPE_LENGTH 1 -#define DM_DMCS2_GROUPTYPE 0x800 +#define DM_DMCS2_GROUPTYPE_OFFSET 0xbULL +#define DM_DMCS2_GROUPTYPE_LENGTH 1ULL +#define DM_DMCS2_GROUPTYPE 0x800ULL /* * halt: The remaining fields in this register configure halt groups. */ @@ -2441,17 +2579,17 @@ * If a non-existent trigger value is written here, the hardware will * change it to a valid one or 0 if no DM external triggers exist. */ -#define DM_DMCS2_DMEXTTRIGGER_OFFSET 7 -#define DM_DMCS2_DMEXTTRIGGER_LENGTH 4 -#define DM_DMCS2_DMEXTTRIGGER 0x780 +#define DM_DMCS2_DMEXTTRIGGER_OFFSET 7ULL +#define DM_DMCS2_DMEXTTRIGGER_LENGTH 4ULL +#define DM_DMCS2_DMEXTTRIGGER 0x780ULL /* - * When \FdmDmcsTwoHgselect is 0, contains the group of the hart - * specified by \Fhartsel. + * When {dmcs2-hgselect} is 0, contains the group of the hart + * specified by {hartsel}. * - * When \FdmDmcsTwoHgselect is 1, contains the group of the DM external - * trigger selected by \FdmDmcsTwoDmexttrigger. + * When {dmcs2-hgselect} is 1, contains the group of the DM external + * trigger selected by {dmcs2-dmexttrigger}. * - * The value written to this field is ignored unless \FdmDmcsTwoHgwrite + * The value written to this field is ignored unless {dmcs2-hgwrite} * is also written 1. * * Group numbers are contiguous starting at 0, with the highest number @@ -2461,30 +2599,30 @@ * * If groups aren't implemented, then this entire field is 0. */ -#define DM_DMCS2_GROUP_OFFSET 2 -#define DM_DMCS2_GROUP_LENGTH 5 -#define DM_DMCS2_GROUP 0x7c +#define DM_DMCS2_GROUP_OFFSET 2ULL +#define DM_DMCS2_GROUP_LENGTH 5ULL +#define DM_DMCS2_GROUP 0x7cULL /* - * When 1 is written and \FdmDmcsTwoHgselect is 0, for every selected - * hart the DM will change its group to the value written to \FdmDmcsTwoGroup, + * When 1 is written and {dmcs2-hgselect} is 0, for every selected + * hart the DM will change its group to the value written to {dmcs2-group}, * if the hardware supports that group for that hart. * Implementations may also change the group of a minimal set of * unselected harts in the same way, if that is necessary due to * a hardware limitation. * - * When 1 is written and \FdmDmcsTwoHgselect is 1, the DM will change - * the group of the DM external trigger selected by \FdmDmcsTwoDmexttrigger - * to the value written to \FdmDmcsTwoGroup, if the hardware supports + * When 1 is written and {dmcs2-hgselect} is 1, the DM will change + * the group of the DM external trigger selected by {dmcs2-dmexttrigger} + * to the value written to {dmcs2-group}, if the hardware supports * that group for that trigger. * * Writing 0 has no effect. */ -#define DM_DMCS2_HGWRITE_OFFSET 1 -#define DM_DMCS2_HGWRITE_LENGTH 1 -#define DM_DMCS2_HGWRITE 2 -#define DM_DMCS2_HGSELECT_OFFSET 0 -#define DM_DMCS2_HGSELECT_LENGTH 1 -#define DM_DMCS2_HGSELECT 1 +#define DM_DMCS2_HGWRITE_OFFSET 1ULL +#define DM_DMCS2_HGWRITE_LENGTH 1ULL +#define DM_DMCS2_HGWRITE 2ULL +#define DM_DMCS2_HGSELECT_OFFSET 0ULL +#define DM_DMCS2_HGSELECT_LENGTH 1ULL +#define DM_DMCS2_HGSELECT 1ULL /* * harts: Operate on harts. */ @@ -2497,25 +2635,25 @@ * If there are no DM external triggers, this field must be tied to 0. */ #define DM_HALTSUM0 0x40 -#define DM_HALTSUM0_HALTSUM0_OFFSET 0 -#define DM_HALTSUM0_HALTSUM0_LENGTH 0x20 -#define DM_HALTSUM0_HALTSUM0 0xffffffffU +#define DM_HALTSUM0_HALTSUM0_OFFSET 0ULL +#define DM_HALTSUM0_HALTSUM0_LENGTH 0x20ULL +#define DM_HALTSUM0_HALTSUM0 0xffffffffULL #define DM_HALTSUM1 0x13 -#define DM_HALTSUM1_HALTSUM1_OFFSET 0 -#define DM_HALTSUM1_HALTSUM1_LENGTH 0x20 -#define DM_HALTSUM1_HALTSUM1 0xffffffffU +#define DM_HALTSUM1_HALTSUM1_OFFSET 0ULL +#define DM_HALTSUM1_HALTSUM1_LENGTH 0x20ULL +#define DM_HALTSUM1_HALTSUM1 0xffffffffULL #define DM_HALTSUM2 0x34 -#define DM_HALTSUM2_HALTSUM2_OFFSET 0 -#define DM_HALTSUM2_HALTSUM2_LENGTH 0x20 -#define DM_HALTSUM2_HALTSUM2 0xffffffffU +#define DM_HALTSUM2_HALTSUM2_OFFSET 0ULL +#define DM_HALTSUM2_HALTSUM2_LENGTH 0x20ULL +#define DM_HALTSUM2_HALTSUM2 0xffffffffULL #define DM_HALTSUM3 0x35 -#define DM_HALTSUM3_HALTSUM3_OFFSET 0 -#define DM_HALTSUM3_HALTSUM3_LENGTH 0x20 -#define DM_HALTSUM3_HALTSUM3 0xffffffffU +#define DM_HALTSUM3_HALTSUM3_OFFSET 0ULL +#define DM_HALTSUM3_HALTSUM3_LENGTH 0x20ULL +#define DM_HALTSUM3_HALTSUM3 0xffffffffULL #define DM_SBCS 0x38 -#define DM_SBCS_SBVERSION_OFFSET 0x1d -#define DM_SBCS_SBVERSION_LENGTH 3 -#define DM_SBCS_SBVERSION 0xe0000000U +#define DM_SBCS_SBVERSION_OFFSET 0x1dULL +#define DM_SBCS_SBVERSION_LENGTH 3ULL +#define DM_SBCS_SBVERSION 0xe0000000ULL /* * legacy: The System Bus interface conforms to mainline drafts of this * spec older than 1 January, 2018. @@ -2531,41 +2669,41 @@ /* * Set when the debugger attempts to read data while a read is in * progress, or when the debugger initiates a new access while one is - * already in progress (while \FdmSbcsSbbusy is set). It remains set until + * already in progress (while {sbcs-sbbusy} is set). It remains set until * it's explicitly cleared by the debugger. * * While this field is set, no more system bus accesses can be * initiated by the Debug Module. */ -#define DM_SBCS_SBBUSYERROR_OFFSET 0x16 -#define DM_SBCS_SBBUSYERROR_LENGTH 1 -#define DM_SBCS_SBBUSYERROR 0x400000 +#define DM_SBCS_SBBUSYERROR_OFFSET 0x16ULL +#define DM_SBCS_SBBUSYERROR_LENGTH 1ULL +#define DM_SBCS_SBBUSYERROR 0x400000ULL /* - * When 1, indicates the system bus master is busy. (Whether the + * When 1, indicates the system bus manager is busy. (Whether the * system bus itself is busy is related, but not the same thing.) This * bit goes high immediately when a read or write is requested for any * reason, and does not go low until the access is fully completed. * - * Writes to \RdmSbcs while \FdmSbcsSbbusy is high result in undefined - * behavior. A debugger must not write to \RdmSbcs until it reads - * \FdmSbcsSbbusy as 0. + * Writes to {dm-sbcs} while {sbcs-sbbusy} is high result in undefined + * behavior. A debugger must not write to {dm-sbcs} until it reads + * {sbcs-sbbusy} as 0. */ -#define DM_SBCS_SBBUSY_OFFSET 0x15 -#define DM_SBCS_SBBUSY_LENGTH 1 -#define DM_SBCS_SBBUSY 0x200000 +#define DM_SBCS_SBBUSY_OFFSET 0x15ULL +#define DM_SBCS_SBBUSY_LENGTH 1ULL +#define DM_SBCS_SBBUSY 0x200000ULL /* - * When 1, every write to \RdmSbaddressZero automatically triggers a + * When 1, every write to {dm-sbaddress0} automatically triggers a * system bus read at the new address. */ -#define DM_SBCS_SBREADONADDR_OFFSET 0x14 -#define DM_SBCS_SBREADONADDR_LENGTH 1 -#define DM_SBCS_SBREADONADDR 0x100000 +#define DM_SBCS_SBREADONADDR_OFFSET 0x14ULL +#define DM_SBCS_SBREADONADDR_LENGTH 1ULL +#define DM_SBCS_SBREADONADDR 0x100000ULL /* * Select the access size to use for system bus accesses. */ -#define DM_SBCS_SBACCESS_OFFSET 0x11 -#define DM_SBCS_SBACCESS_LENGTH 3 -#define DM_SBCS_SBACCESS 0xe0000 +#define DM_SBCS_SBACCESS_OFFSET 0x11ULL +#define DM_SBCS_SBACCESS_LENGTH 3ULL +#define DM_SBCS_SBACCESS 0xe0000ULL /* * 8bit: 8-bit */ @@ -2587,35 +2725,35 @@ */ #define DM_SBCS_SBACCESS_128BIT 4 /* - * If \FdmSbcsSbaccess has an unsupported value when the DM starts a bus - * access, the access is not performed and \FdmSbcsSberror is set to 4. + * If {sbcs-sbaccess} has an unsupported value when the DM starts a bus + * access, the access is not performed and {sbcs-sberror} is set to 4. */ /* - * When 1, {\tt sbaddress} is incremented by the access size (in - * bytes) selected in \FdmSbcsSbaccess after every system bus access. + * When 1, `sbaddress` is incremented by the access size (in + * bytes) selected in {sbcs-sbaccess} after every system bus access. */ -#define DM_SBCS_SBAUTOINCREMENT_OFFSET 0x10 -#define DM_SBCS_SBAUTOINCREMENT_LENGTH 1 -#define DM_SBCS_SBAUTOINCREMENT 0x10000 +#define DM_SBCS_SBAUTOINCREMENT_OFFSET 0x10ULL +#define DM_SBCS_SBAUTOINCREMENT_LENGTH 1ULL +#define DM_SBCS_SBAUTOINCREMENT 0x10000ULL /* - * When 1, every read from \RdmSbdataZero automatically triggers a + * When 1, every read from {dm-sbdata0} automatically triggers a * system bus read at the (possibly auto-incremented) address. */ -#define DM_SBCS_SBREADONDATA_OFFSET 0xf -#define DM_SBCS_SBREADONDATA_LENGTH 1 -#define DM_SBCS_SBREADONDATA 0x8000 +#define DM_SBCS_SBREADONDATA_OFFSET 0xfULL +#define DM_SBCS_SBREADONDATA_LENGTH 1ULL +#define DM_SBCS_SBREADONDATA 0x8000ULL /* * When the Debug Module's system bus - * master encounters an error, this field gets set. The bits in this + * manager encounters an error, this field gets set. The bits in this * field remain set until they are cleared by writing 1 to them. * While this field is non-zero, no more system bus accesses can be * initiated by the Debug Module. * * An implementation may report ``Other'' (7) for any error condition. */ -#define DM_SBCS_SBERROR_OFFSET 0xc -#define DM_SBCS_SBERROR_LENGTH 3 -#define DM_SBCS_SBERROR 0x7000 +#define DM_SBCS_SBERROR_OFFSET 0xcULL +#define DM_SBCS_SBERROR_LENGTH 3ULL +#define DM_SBCS_SBERROR 0x7000ULL /* * none: There was no bus error. */ @@ -2644,101 +2782,101 @@ * Width of system bus addresses in bits. (0 indicates there is no bus * access support.) */ -#define DM_SBCS_SBASIZE_OFFSET 5 -#define DM_SBCS_SBASIZE_LENGTH 7 -#define DM_SBCS_SBASIZE 0xfe0 +#define DM_SBCS_SBASIZE_OFFSET 5ULL +#define DM_SBCS_SBASIZE_LENGTH 7ULL +#define DM_SBCS_SBASIZE 0xfe0ULL /* * 1 when 128-bit system bus accesses are supported. */ -#define DM_SBCS_SBACCESS128_OFFSET 4 -#define DM_SBCS_SBACCESS128_LENGTH 1 -#define DM_SBCS_SBACCESS128 0x10 +#define DM_SBCS_SBACCESS128_OFFSET 4ULL +#define DM_SBCS_SBACCESS128_LENGTH 1ULL +#define DM_SBCS_SBACCESS128 0x10ULL /* * 1 when 64-bit system bus accesses are supported. */ -#define DM_SBCS_SBACCESS64_OFFSET 3 -#define DM_SBCS_SBACCESS64_LENGTH 1 -#define DM_SBCS_SBACCESS64 8 +#define DM_SBCS_SBACCESS64_OFFSET 3ULL +#define DM_SBCS_SBACCESS64_LENGTH 1ULL +#define DM_SBCS_SBACCESS64 8ULL /* * 1 when 32-bit system bus accesses are supported. */ -#define DM_SBCS_SBACCESS32_OFFSET 2 -#define DM_SBCS_SBACCESS32_LENGTH 1 -#define DM_SBCS_SBACCESS32 4 +#define DM_SBCS_SBACCESS32_OFFSET 2ULL +#define DM_SBCS_SBACCESS32_LENGTH 1ULL +#define DM_SBCS_SBACCESS32 4ULL /* * 1 when 16-bit system bus accesses are supported. */ -#define DM_SBCS_SBACCESS16_OFFSET 1 -#define DM_SBCS_SBACCESS16_LENGTH 1 -#define DM_SBCS_SBACCESS16 2 +#define DM_SBCS_SBACCESS16_OFFSET 1ULL +#define DM_SBCS_SBACCESS16_LENGTH 1ULL +#define DM_SBCS_SBACCESS16 2ULL /* * 1 when 8-bit system bus accesses are supported. */ -#define DM_SBCS_SBACCESS8_OFFSET 0 -#define DM_SBCS_SBACCESS8_LENGTH 1 -#define DM_SBCS_SBACCESS8 1 +#define DM_SBCS_SBACCESS8_OFFSET 0ULL +#define DM_SBCS_SBACCESS8_LENGTH 1ULL +#define DM_SBCS_SBACCESS8 1ULL #define DM_SBADDRESS0 0x39 /* - * Accesses bits 31:0 of the physical address in {\tt sbaddress}. + * Accesses bits 31:0 of the physical address in `sbaddress`. */ -#define DM_SBADDRESS0_ADDRESS_OFFSET 0 -#define DM_SBADDRESS0_ADDRESS_LENGTH 0x20 -#define DM_SBADDRESS0_ADDRESS 0xffffffffU +#define DM_SBADDRESS0_ADDRESS_OFFSET 0ULL +#define DM_SBADDRESS0_ADDRESS_LENGTH 0x20ULL +#define DM_SBADDRESS0_ADDRESS 0xffffffffULL #define DM_SBADDRESS1 0x3a /* - * Accesses bits 63:32 of the physical address in {\tt sbaddress} (if + * Accesses bits 63:32 of the physical address in `sbaddress` (if * the system address bus is that wide). */ -#define DM_SBADDRESS1_ADDRESS_OFFSET 0 -#define DM_SBADDRESS1_ADDRESS_LENGTH 0x20 -#define DM_SBADDRESS1_ADDRESS 0xffffffffU +#define DM_SBADDRESS1_ADDRESS_OFFSET 0ULL +#define DM_SBADDRESS1_ADDRESS_LENGTH 0x20ULL +#define DM_SBADDRESS1_ADDRESS 0xffffffffULL #define DM_SBADDRESS2 0x3b /* - * Accesses bits 95:64 of the physical address in {\tt sbaddress} (if + * Accesses bits 95:64 of the physical address in `sbaddress` (if * the system address bus is that wide). */ -#define DM_SBADDRESS2_ADDRESS_OFFSET 0 -#define DM_SBADDRESS2_ADDRESS_LENGTH 0x20 -#define DM_SBADDRESS2_ADDRESS 0xffffffffU +#define DM_SBADDRESS2_ADDRESS_OFFSET 0ULL +#define DM_SBADDRESS2_ADDRESS_LENGTH 0x20ULL +#define DM_SBADDRESS2_ADDRESS 0xffffffffULL #define DM_SBADDRESS3 0x37 /* - * Accesses bits 127:96 of the physical address in {\tt sbaddress} (if + * Accesses bits 127:96 of the physical address in `sbaddress` (if * the system address bus is that wide). */ -#define DM_SBADDRESS3_ADDRESS_OFFSET 0 -#define DM_SBADDRESS3_ADDRESS_LENGTH 0x20 -#define DM_SBADDRESS3_ADDRESS 0xffffffffU +#define DM_SBADDRESS3_ADDRESS_OFFSET 0ULL +#define DM_SBADDRESS3_ADDRESS_LENGTH 0x20ULL +#define DM_SBADDRESS3_ADDRESS 0xffffffffULL #define DM_SBDATA0 0x3c /* - * Accesses bits 31:0 of {\tt sbdata}. + * Accesses bits 31:0 of `sbdata`. */ -#define DM_SBDATA0_DATA_OFFSET 0 -#define DM_SBDATA0_DATA_LENGTH 0x20 -#define DM_SBDATA0_DATA 0xffffffffU +#define DM_SBDATA0_DATA_OFFSET 0ULL +#define DM_SBDATA0_DATA_LENGTH 0x20ULL +#define DM_SBDATA0_DATA 0xffffffffULL #define DM_SBDATA1 0x3d /* - * Accesses bits 63:32 of {\tt sbdata} (if the system bus is that + * Accesses bits 63:32 of `sbdata` (if the system bus is that * wide). */ -#define DM_SBDATA1_DATA_OFFSET 0 -#define DM_SBDATA1_DATA_LENGTH 0x20 -#define DM_SBDATA1_DATA 0xffffffffU +#define DM_SBDATA1_DATA_OFFSET 0ULL +#define DM_SBDATA1_DATA_LENGTH 0x20ULL +#define DM_SBDATA1_DATA 0xffffffffULL #define DM_SBDATA2 0x3e /* - * Accesses bits 95:64 of {\tt sbdata} (if the system bus is that + * Accesses bits 95:64 of `sbdata` (if the system bus is that * wide). */ -#define DM_SBDATA2_DATA_OFFSET 0 -#define DM_SBDATA2_DATA_LENGTH 0x20 -#define DM_SBDATA2_DATA 0xffffffffU +#define DM_SBDATA2_DATA_OFFSET 0ULL +#define DM_SBDATA2_DATA_LENGTH 0x20ULL +#define DM_SBDATA2_DATA 0xffffffffULL #define DM_SBDATA3 0x3f /* - * Accesses bits 127:96 of {\tt sbdata} (if the system bus is that + * Accesses bits 127:96 of `sbdata` (if the system bus is that * wide). */ -#define DM_SBDATA3_DATA_OFFSET 0 -#define DM_SBDATA3_DATA_LENGTH 0x20 -#define DM_SBDATA3_DATA 0xffffffffU +#define DM_SBDATA3_DATA_OFFSET 0ULL +#define DM_SBDATA3_DATA_LENGTH 0x20ULL +#define DM_SBDATA3_DATA 0xffffffffULL #define DM_CUSTOM 0x1f #define DM_CUSTOM0 0x70 #define DM_CUSTOM1 0x71 @@ -2760,18 +2898,18 @@ /* * Description of what this field is used for. */ -#define SHORTNAME_FIELD_OFFSET 0 -#define SHORTNAME_FIELD_LENGTH 8 -#define SHORTNAME_FIELD 0xff +#define SHORTNAME_FIELD_OFFSET 0ULL +#define SHORTNAME_FIELD_LENGTH 8ULL +#define SHORTNAME_FIELD 0xffULL /* * This is 0 to indicate Access Register Command. */ -#define AC_ACCESS_REGISTER_CMDTYPE_OFFSET 0x18 -#define AC_ACCESS_REGISTER_CMDTYPE_LENGTH 8 -#define AC_ACCESS_REGISTER_CMDTYPE 0xff000000U -#define AC_ACCESS_REGISTER_AARSIZE_OFFSET 0x14 -#define AC_ACCESS_REGISTER_AARSIZE_LENGTH 3 -#define AC_ACCESS_REGISTER_AARSIZE 0x700000 +#define AC_ACCESS_REGISTER_CMDTYPE_OFFSET 0x18ULL +#define AC_ACCESS_REGISTER_CMDTYPE_LENGTH 8ULL +#define AC_ACCESS_REGISTER_CMDTYPE 0xff000000ULL +#define AC_ACCESS_REGISTER_AARSIZE_OFFSET 0x14ULL +#define AC_ACCESS_REGISTER_AARSIZE_LENGTH 3ULL +#define AC_ACCESS_REGISTER_AARSIZE 0x700000ULL /* * 32bit: Access the lowest 32 bits of the register. */ @@ -2785,36 +2923,36 @@ */ #define AC_ACCESS_REGISTER_AARSIZE_128BIT 4 /* - * If \FacAccessregisterAarsize specifies a size larger than the register's actual size, - * then the access must fail. If a register is accessible, then reads of \FacAccessregisterAarsize + * If {accessregister-aarsize} specifies a size larger than the register's actual size, + * then the access must fail. If a register is accessible, then reads of {accessregister-aarsize} * less than or equal to the register's actual size must be supported. * Writing less than the full register may be supported, but what - * happens to the high bits in that case is \unspecified. + * happens to the high bits in that case is UNSPECIFIED. * * This field controls the Argument Width as referenced in - * Table~\ref{tab:datareg}. + * xref:tab:datareg[]. */ -#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_OFFSET 0x13 -#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_LENGTH 1 -#define AC_ACCESS_REGISTER_AARPOSTINCREMENT 0x80000 +#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_OFFSET 0x13ULL +#define AC_ACCESS_REGISTER_AARPOSTINCREMENT_LENGTH 1ULL +#define AC_ACCESS_REGISTER_AARPOSTINCREMENT 0x80000ULL /* * disabled: No effect. This variant must be supported. */ #define AC_ACCESS_REGISTER_AARPOSTINCREMENT_DISABLED 0 /* - * enabled: After a successful register access, \FacAccessregisterRegno is + * enabled: After a successful register access, {accessregister-regno} is * incremented. Incrementing past the highest supported value - * causes \FacAccessregisterRegno to become \unspecified. Supporting + * causes {accessregister-regno} to become UNSPECIFIED. Supporting * this variant is optional. It is undefined whether the increment - * happens when \FacAccessregisterTransfer is 0. + * happens when {accessregister-transfer} is 0. */ #define AC_ACCESS_REGISTER_AARPOSTINCREMENT_ENABLED 1 -#define AC_ACCESS_REGISTER_POSTEXEC_OFFSET 0x12 -#define AC_ACCESS_REGISTER_POSTEXEC_LENGTH 1 -#define AC_ACCESS_REGISTER_POSTEXEC 0x40000 +#define AC_ACCESS_REGISTER_POSTEXEC_OFFSET 0x12ULL +#define AC_ACCESS_REGISTER_POSTEXEC_LENGTH 1ULL +#define AC_ACCESS_REGISTER_POSTEXEC 0x40000ULL /* * disabled: No effect. This variant must be supported, and is the only - * supported one if \FdmAbstractcsProgbufsize is 0. + * supported one if {abstractcs-progbufsize} is 0. */ #define AC_ACCESS_REGISTER_POSTEXEC_DISABLED 0 /* @@ -2823,83 +2961,83 @@ * optional. */ #define AC_ACCESS_REGISTER_POSTEXEC_ENABLED 1 -#define AC_ACCESS_REGISTER_TRANSFER_OFFSET 0x11 -#define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1 -#define AC_ACCESS_REGISTER_TRANSFER 0x20000 +#define AC_ACCESS_REGISTER_TRANSFER_OFFSET 0x11ULL +#define AC_ACCESS_REGISTER_TRANSFER_LENGTH 1ULL +#define AC_ACCESS_REGISTER_TRANSFER 0x20000ULL /* - * disabled: Don't do the operation specified by \FacAccessregisterWrite. + * disabled: Don't do the operation specified by {accessregister-write}. */ #define AC_ACCESS_REGISTER_TRANSFER_DISABLED 0 /* - * enabled: Do the operation specified by \FacAccessregisterWrite. + * enabled: Do the operation specified by {accessregister-write}. */ #define AC_ACCESS_REGISTER_TRANSFER_ENABLED 1 /* * This bit can be used to just execute the Program Buffer without - * having to worry about placing valid values into \FacAccessregisterAarsize or \FacAccessregisterRegno. + * having to worry about placing valid values into {accessregister-aarsize} or {accessregister-regno}. */ /* - * When \FacAccessregisterTransfer is set: + * When {accessregister-transfer} is set: */ -#define AC_ACCESS_REGISTER_WRITE_OFFSET 0x10 -#define AC_ACCESS_REGISTER_WRITE_LENGTH 1 -#define AC_ACCESS_REGISTER_WRITE 0x10000 +#define AC_ACCESS_REGISTER_WRITE_OFFSET 0x10ULL +#define AC_ACCESS_REGISTER_WRITE_LENGTH 1ULL +#define AC_ACCESS_REGISTER_WRITE 0x10000ULL /* - * arg0: Copy data from the specified register into {\tt arg0} portion - * of {\tt data}. + * arg0: Copy data from the specified register into `arg0` portion + * of `data`. */ #define AC_ACCESS_REGISTER_WRITE_ARG0 0 /* - * register: Copy data from {\tt arg0} portion of {\tt data} into the + * register: Copy data from `arg0` portion of `data` into the * specified register. */ #define AC_ACCESS_REGISTER_WRITE_REGISTER 1 /* * Number of the register to access, as described in - * Table~\ref{tab:regno}. - * \RcsrDpc may be used as an alias for PC if this command is + * xref:tab:regno[]. + * {csr-dpc} may be used as an alias for PC if this command is * supported on a non-halted hart. */ -#define AC_ACCESS_REGISTER_REGNO_OFFSET 0 -#define AC_ACCESS_REGISTER_REGNO_LENGTH 0x10 -#define AC_ACCESS_REGISTER_REGNO 0xffff +#define AC_ACCESS_REGISTER_REGNO_OFFSET 0ULL +#define AC_ACCESS_REGISTER_REGNO_LENGTH 0x10ULL +#define AC_ACCESS_REGISTER_REGNO 0xffffULL /* * This is 1 to indicate Quick Access command. */ -#define AC_QUICK_ACCESS_CMDTYPE_OFFSET 0x18 -#define AC_QUICK_ACCESS_CMDTYPE_LENGTH 8 -#define AC_QUICK_ACCESS_CMDTYPE 0xff000000U +#define AC_QUICK_ACCESS_CMDTYPE_OFFSET 0x18ULL +#define AC_QUICK_ACCESS_CMDTYPE_LENGTH 8ULL +#define AC_QUICK_ACCESS_CMDTYPE 0xff000000ULL /* * This is 2 to indicate Access Memory Command. */ -#define AC_ACCESS_MEMORY_CMDTYPE_OFFSET 0x18 -#define AC_ACCESS_MEMORY_CMDTYPE_LENGTH 8 -#define AC_ACCESS_MEMORY_CMDTYPE 0xff000000U +#define AC_ACCESS_MEMORY_CMDTYPE_OFFSET 0x18ULL +#define AC_ACCESS_MEMORY_CMDTYPE_LENGTH 8ULL +#define AC_ACCESS_MEMORY_CMDTYPE 0xff000000ULL /* * An implementation does not have to implement both virtual and * physical accesses, but it must fail accesses that it doesn't * support. */ -#define AC_ACCESS_MEMORY_AAMVIRTUAL_OFFSET 0x17 -#define AC_ACCESS_MEMORY_AAMVIRTUAL_LENGTH 1 -#define AC_ACCESS_MEMORY_AAMVIRTUAL 0x800000 +#define AC_ACCESS_MEMORY_AAMVIRTUAL_OFFSET 0x17ULL +#define AC_ACCESS_MEMORY_AAMVIRTUAL_LENGTH 1ULL +#define AC_ACCESS_MEMORY_AAMVIRTUAL 0x800000ULL /* * physical: Addresses are physical (to the hart they are performed on). */ #define AC_ACCESS_MEMORY_AAMVIRTUAL_PHYSICAL 0 /* * virtual: Addresses are virtual, and translated the way they would be from - * M-mode, with \FcsrMstatusMprv set. + * M-mode, with `MPRV` set. */ #define AC_ACCESS_MEMORY_AAMVIRTUAL_VIRTUAL 1 /* * Debug Modules on systems without address translation (i.e. virtual addresses equal physical) - * may optionally allow \FacAccessmemoryAamvirtual set to 1, which would produce the same result as - * that same abstract command with \FacAccessmemoryAamvirtual cleared. + * may optionally allow {accessmemory-aamvirtual} set to 1, which would produce the same result as + * that same abstract command with {accessmemory-aamvirtual} cleared. */ -#define AC_ACCESS_MEMORY_AAMSIZE_OFFSET 0x14 -#define AC_ACCESS_MEMORY_AAMSIZE_LENGTH 3 -#define AC_ACCESS_MEMORY_AAMSIZE 0x700000 +#define AC_ACCESS_MEMORY_AAMSIZE_OFFSET 0x14ULL +#define AC_ACCESS_MEMORY_AAMSIZE_LENGTH 3ULL +#define AC_ACCESS_MEMORY_AAMSIZE 0x700000ULL /* * 8bit: Access the lowest 8 bits of the memory location. */ @@ -2922,157 +3060,141 @@ #define AC_ACCESS_MEMORY_AAMSIZE_128BIT 4 /* * After a memory access has completed, if this bit is 1, increment - * {\tt arg1} (which contains the address used) by the number of bytes - * encoded in \FacAccessmemoryAamsize. + * `arg1` (which contains the address used) by the number of bytes + * encoded in {accessmemory-aamsize}. * * Supporting this variant is optional, but highly recommended for * performance reasons. */ -#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_OFFSET 0x13 -#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_LENGTH 1 -#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT 0x80000 -#define AC_ACCESS_MEMORY_WRITE_OFFSET 0x10 -#define AC_ACCESS_MEMORY_WRITE_LENGTH 1 -#define AC_ACCESS_MEMORY_WRITE 0x10000 +#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_OFFSET 0x13ULL +#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT_LENGTH 1ULL +#define AC_ACCESS_MEMORY_AAMPOSTINCREMENT 0x80000ULL +#define AC_ACCESS_MEMORY_WRITE_OFFSET 0x10ULL +#define AC_ACCESS_MEMORY_WRITE_LENGTH 1ULL +#define AC_ACCESS_MEMORY_WRITE 0x10000ULL /* - * arg0: Copy data from the memory location specified in {\tt arg1} into - * the low bits of {\tt arg0}. The value of the remaining bits of - * {\tt arg0} are \unspecified. + * arg0: Copy data from the memory location specified in `arg1` into + * the low bits of `arg0`. The value of the remaining bits of + * `arg0` are UNSPECIFIED. */ #define AC_ACCESS_MEMORY_WRITE_ARG0 0 /* - * memory: Copy data from the low bits of {\tt arg0} into the memory - * location specified in {\tt arg1}. + * memory: Copy data from the low bits of `arg0` into the memory + * location specified in `arg1`. */ #define AC_ACCESS_MEMORY_WRITE_MEMORY 1 /* * These bits are reserved for target-specific uses. */ -#define AC_ACCESS_MEMORY_TARGET_SPECIFIC_OFFSET 0xe -#define AC_ACCESS_MEMORY_TARGET_SPECIFIC_LENGTH 2 -#define AC_ACCESS_MEMORY_TARGET_SPECIFIC 0xc000 +#define AC_ACCESS_MEMORY_TARGET_SPECIFIC_OFFSET 0xeULL +#define AC_ACCESS_MEMORY_TARGET_SPECIFIC_LENGTH 2ULL +#define AC_ACCESS_MEMORY_TARGET_SPECIFIC 0xc000ULL #define VIRT_PRIV virtual /* * Contains the virtualization mode the hart was operating in when Debug - * Mode was entered. The encoding is described in Table \ref{tab:privmode}, + * Mode was entered. The encoding is described in <>, * and matches the virtualization mode encoding from the Privileged Spec. * A user can write this value to change the hart's virtualization mode * when exiting Debug Mode. */ -#define VIRT_PRIV_V_OFFSET 2 -#define VIRT_PRIV_V_LENGTH 1 -#define VIRT_PRIV_V 4 +#define VIRT_PRIV_V_OFFSET 2ULL +#define VIRT_PRIV_V_LENGTH 1ULL +#define VIRT_PRIV_V 4ULL /* * Contains the privilege mode the hart was operating in when Debug - * Mode was entered. The encoding is described in Table - * \ref{tab:privmode}, and matches the privilege mode encoding from + * Mode was entered. The encoding is described in <>, and matches the privilege mode encoding from * the Privileged Spec. A user can write this * value to change the hart's privilege mode when exiting Debug Mode. */ -#define VIRT_PRIV_PRV_OFFSET 0 -#define VIRT_PRIV_PRV_LENGTH 2 -#define VIRT_PRIV_PRV 3 -#define DMI_SERCS 0x34 -/* - * Number of supported serial ports. - */ -#define DMI_SERCS_SERIALCOUNT_OFFSET 0x1c -#define DMI_SERCS_SERIALCOUNT_LENGTH 4 -#define DMI_SERCS_SERIALCOUNT 0xf0000000U -/* - * Select which serial port is accessed by \RdmiSerrx and \RdmiSertx. - */ -#define DMI_SERCS_SERIAL_OFFSET 0x18 -#define DMI_SERCS_SERIAL_LENGTH 3 -#define DMI_SERCS_SERIAL 0x7000000 -#define DMI_SERCS_ERROR7_OFFSET 0x17 -#define DMI_SERCS_ERROR7_LENGTH 1 -#define DMI_SERCS_ERROR7 0x800000 -#define DMI_SERCS_VALID7_OFFSET 0x16 -#define DMI_SERCS_VALID7_LENGTH 1 -#define DMI_SERCS_VALID7 0x400000 -#define DMI_SERCS_FULL7_OFFSET 0x15 -#define DMI_SERCS_FULL7_LENGTH 1 -#define DMI_SERCS_FULL7 0x200000 -#define DMI_SERCS_ERROR6_OFFSET 0x14 -#define DMI_SERCS_ERROR6_LENGTH 1 -#define DMI_SERCS_ERROR6 0x100000 -#define DMI_SERCS_VALID6_OFFSET 0x13 -#define DMI_SERCS_VALID6_LENGTH 1 -#define DMI_SERCS_VALID6 0x80000 -#define DMI_SERCS_FULL6_OFFSET 0x12 -#define DMI_SERCS_FULL6_LENGTH 1 -#define DMI_SERCS_FULL6 0x40000 -#define DMI_SERCS_ERROR5_OFFSET 0x11 -#define DMI_SERCS_ERROR5_LENGTH 1 -#define DMI_SERCS_ERROR5 0x20000 -#define DMI_SERCS_VALID5_OFFSET 0x10 -#define DMI_SERCS_VALID5_LENGTH 1 -#define DMI_SERCS_VALID5 0x10000 -#define DMI_SERCS_FULL5_OFFSET 0xf -#define DMI_SERCS_FULL5_LENGTH 1 -#define DMI_SERCS_FULL5 0x8000 -#define DMI_SERCS_ERROR4_OFFSET 0xe -#define DMI_SERCS_ERROR4_LENGTH 1 -#define DMI_SERCS_ERROR4 0x4000 -#define DMI_SERCS_VALID4_OFFSET 0xd -#define DMI_SERCS_VALID4_LENGTH 1 -#define DMI_SERCS_VALID4 0x2000 -#define DMI_SERCS_FULL4_OFFSET 0xc -#define DMI_SERCS_FULL4_LENGTH 1 -#define DMI_SERCS_FULL4 0x1000 -#define DMI_SERCS_ERROR3_OFFSET 0xb -#define DMI_SERCS_ERROR3_LENGTH 1 -#define DMI_SERCS_ERROR3 0x800 -#define DMI_SERCS_VALID3_OFFSET 0xa -#define DMI_SERCS_VALID3_LENGTH 1 -#define DMI_SERCS_VALID3 0x400 -#define DMI_SERCS_FULL3_OFFSET 9 -#define DMI_SERCS_FULL3_LENGTH 1 -#define DMI_SERCS_FULL3 0x200 -#define DMI_SERCS_ERROR2_OFFSET 8 -#define DMI_SERCS_ERROR2_LENGTH 1 -#define DMI_SERCS_ERROR2 0x100 -#define DMI_SERCS_VALID2_OFFSET 7 -#define DMI_SERCS_VALID2_LENGTH 1 -#define DMI_SERCS_VALID2 0x80 -#define DMI_SERCS_FULL2_OFFSET 6 -#define DMI_SERCS_FULL2_LENGTH 1 -#define DMI_SERCS_FULL2 0x40 -#define DMI_SERCS_ERROR1_OFFSET 5 -#define DMI_SERCS_ERROR1_LENGTH 1 -#define DMI_SERCS_ERROR1 0x20 -#define DMI_SERCS_VALID1_OFFSET 4 -#define DMI_SERCS_VALID1_LENGTH 1 -#define DMI_SERCS_VALID1 0x10 -#define DMI_SERCS_FULL1_OFFSET 3 -#define DMI_SERCS_FULL1_LENGTH 1 -#define DMI_SERCS_FULL1 8 -/* - * 1 when the debugger-to-core queue for serial port 0 has - * over or underflowed. This bit will remain set until it is reset by - * writing 1 to this bit. - */ -#define DMI_SERCS_ERROR0_OFFSET 2 -#define DMI_SERCS_ERROR0_LENGTH 1 -#define DMI_SERCS_ERROR0 4 -/* - * 1 when the core-to-debugger queue for serial port 0 is not empty. - */ -#define DMI_SERCS_VALID0_OFFSET 1 -#define DMI_SERCS_VALID0_LENGTH 1 -#define DMI_SERCS_VALID0 2 -/* - * 1 when the debugger-to-core queue for serial port 0 is full. - */ -#define DMI_SERCS_FULL0_OFFSET 0 -#define DMI_SERCS_FULL0_LENGTH 1 -#define DMI_SERCS_FULL0 1 -#define DMI_SERTX 0x35 -#define DMI_SERTX_DATA_OFFSET 0 -#define DMI_SERTX_DATA_LENGTH 0x20 -#define DMI_SERTX_DATA 0xffffffffU -#define DMI_SERRX 0x36 -#define DMI_SERRX_DATA_OFFSET 0 -#define DMI_SERRX_DATA_LENGTH 0x20 -#define DMI_SERRX_DATA 0xffffffffU +#define VIRT_PRIV_PRV_OFFSET 0ULL +#define VIRT_PRIV_PRV_LENGTH 2ULL +#define VIRT_PRIV_PRV 3ULL +enum riscv_debug_reg_ordinal { + DTM_IDCODE_ORDINAL, + DTM_DTMCS_ORDINAL, + DTM_DMI_ORDINAL, + DTM_BYPASS_ORDINAL, + CSR_DCSR_ORDINAL, + CSR_DPC_ORDINAL, + CSR_DSCRATCH0_ORDINAL, + CSR_DSCRATCH1_ORDINAL, + CSR_TSELECT_ORDINAL, + CSR_TDATA1_ORDINAL, + CSR_TDATA2_ORDINAL, + CSR_TDATA3_ORDINAL, + CSR_TINFO_ORDINAL, + CSR_TCONTROL_ORDINAL, + CSR_SCONTEXT_ORDINAL, + CSR_MCONTEXT_ORDINAL, + CSR_MCONTROL_ORDINAL, + CSR_MCONTROL6_ORDINAL, + CSR_ICOUNT_ORDINAL, + CSR_ITRIGGER_ORDINAL, + CSR_ETRIGGER_ORDINAL, + CSR_TMEXTTRIGGER_ORDINAL, + CSR_TEXTRA32_ORDINAL, + CSR_TEXTRA64_ORDINAL, + DM_DMSTATUS_ORDINAL, + DM_DMCONTROL_ORDINAL, + DM_HARTINFO_ORDINAL, + DM_HAWINDOWSEL_ORDINAL, + DM_HAWINDOW_ORDINAL, + DM_ABSTRACTCS_ORDINAL, + DM_COMMAND_ORDINAL, + DM_ABSTRACTAUTO_ORDINAL, + DM_CONFSTRPTR0_ORDINAL, + DM_CONFSTRPTR1_ORDINAL, + DM_CONFSTRPTR2_ORDINAL, + DM_CONFSTRPTR3_ORDINAL, + DM_NEXTDM_ORDINAL, + DM_DATA0_ORDINAL, + DM_PROGBUF0_ORDINAL, + DM_AUTHDATA_ORDINAL, + DM_DMCS2_ORDINAL, + DM_HALTSUM0_ORDINAL, + DM_HALTSUM1_ORDINAL, + DM_HALTSUM2_ORDINAL, + DM_HALTSUM3_ORDINAL, + DM_SBCS_ORDINAL, + DM_SBADDRESS0_ORDINAL, + DM_SBADDRESS1_ORDINAL, + DM_SBADDRESS2_ORDINAL, + DM_SBADDRESS3_ORDINAL, + DM_SBDATA0_ORDINAL, + DM_SBDATA1_ORDINAL, + DM_SBDATA2_ORDINAL, + DM_SBDATA3_ORDINAL, + SHORTNAME_ORDINAL, + AC_ACCESS_REGISTER_ORDINAL, + AC_QUICK_ACCESS_ORDINAL, + AC_ACCESS_MEMORY_ORDINAL, + VIRT_PRIV_ORDINAL +}; +typedef struct { + struct { + unsigned int value; int is_set; + } DXLEN; + struct { + unsigned int value; int is_set; + } XLEN; + struct { + unsigned int value; int is_set; + } abits; +} riscv_debug_reg_ctx_t; + +typedef struct { + const char *name; + unsigned int lsb; // inclusive + unsigned int msb; // inclusive + const char **values; // If non-NULL, array of human-readable string for each possible value +} riscv_debug_reg_field_info_t; +typedef struct riscv_debug_reg_field_list_t { + riscv_debug_reg_field_info_t field; + struct riscv_debug_reg_field_list_t (*get_next)(riscv_debug_reg_ctx_t context); +} riscv_debug_reg_field_list_t; +typedef struct { + const char *name; + struct riscv_debug_reg_field_list_t (* const get_fields_head)(riscv_debug_reg_ctx_t context); +} riscv_debug_reg_info_t; +riscv_debug_reg_info_t get_riscv_debug_reg_info(enum riscv_debug_reg_ordinal reg_ordinal); +#endif diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 4957dd43f4..f8ceac3b24 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -270,7 +270,7 @@ reg_t mcontrol6_t::tdata1_read(const processor_t * const proc) const noexcept { tdata1 = set_field(tdata1, CSR_MCONTROL6_DMODE(xlen), dmode); tdata1 = set_field(tdata1, CSR_MCONTROL6_VS, proc->extension_enabled('H') ? vs : 0); tdata1 = set_field(tdata1, CSR_MCONTROL6_VU, proc->extension_enabled('H') ? vu : 0); - tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT, hit); + tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT0, hit); tdata1 = set_field(tdata1, CSR_MCONTROL6_SELECT, select); tdata1 = set_field(tdata1, CSR_MCONTROL6_ACTION, action); tdata1 = set_field(tdata1, CSR_MCONTROL6_CHAIN, chain); @@ -290,7 +290,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const dmode = get_field(val, CSR_MCONTROL6_DMODE(xlen)); vs = get_field(val, CSR_MCONTROL6_VS); vu = get_field(val, CSR_MCONTROL6_VU); - hit = get_field(val, CSR_MCONTROL6_HIT); + hit = get_field(val, CSR_MCONTROL6_HIT0); select = get_field(val, CSR_MCONTROL6_SELECT); action = legalize_action(val, CSR_MCONTROL6_ACTION, CSR_MCONTROL6_DMODE(xlen)); chain = allow_chain ? get_field(val, CSR_MCONTROL6_CHAIN) : 0; From 2f12bb8c58286c45b19ded54a242a03ec24131f7 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 21 Feb 2023 12:20:47 +0800 Subject: [PATCH 003/155] triggers: refactor: move mcontrol_common_t::hit to mcontrol_t::hit and mcontrol6_t::hit Add mcontrol_common_t::set_hit() --- riscv/triggers.cc | 2 +- riscv/triggers.h | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index f8ceac3b24..51a5091a4a 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -233,7 +233,7 @@ std::optional mcontrol_common_t::detect_memory_access_match(proc if (simple_match(xlen, value) && allow_action(proc->get_state())) { /* This is OK because this function is only called if the trigger was not * inhibited by the previous trigger in the chain. */ - hit = true; + set_hit(true); return match_result_t(timing_t(timing), action); } return std::nullopt; diff --git a/riscv/triggers.h b/riscv/triggers.h index 6f00122c6a..7a4a94209c 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -205,6 +205,7 @@ class mcontrol_common_t : public trigger_t { virtual bool get_store() const override { return store; } virtual bool get_load() const override { return load; } virtual action_t get_action() const override { return action; } + virtual void set_hit(bool val) = 0; virtual std::optional detect_memory_access_match(processor_t * const proc, operation_t operation, reg_t address, std::optional data) noexcept override; @@ -217,7 +218,6 @@ class mcontrol_common_t : public trigger_t { static bool legalize_timing(reg_t val, reg_t timing_mask, reg_t select_mask, reg_t execute_mask, reg_t load_mask) noexcept; bool dmode = false; action_t action = ACTION_DEBUG_EXCEPTION; - bool hit = false; bool select = false; bool timing = false; bool chain = false; @@ -231,12 +231,22 @@ class mcontrol_t : public mcontrol_common_t { public: virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; + + virtual void set_hit(bool val) override { hit = val; } + +private: + bool hit = false; }; class mcontrol6_t : public mcontrol_common_t { public: virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; + + virtual void set_hit(bool val) override { hit = val; } + +private: + bool hit = false; }; class icount_t : public trigger_t { From 2855c71b850f53d735edf00ccd3221115f597d16 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 21 Feb 2023 13:39:45 +0800 Subject: [PATCH 004/155] triggers: refactor: add typedef enum { ... } hit_t for mcontrol6 Avoid using private headers, e.g., debug_defines.h, in triggers.h --- riscv/triggers.cc | 7 ++++--- riscv/triggers.h | 15 +++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 51a5091a4a..9c81b89a36 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -233,7 +233,7 @@ std::optional mcontrol_common_t::detect_memory_access_match(proc if (simple_match(xlen, value) && allow_action(proc->get_state())) { /* This is OK because this function is only called if the trigger was not * inhibited by the previous trigger in the chain. */ - set_hit(true); + set_hit(timing ? HIT_IMMEDIATELY_AFTER : HIT_BEFORE); return match_result_t(timing_t(timing), action); } return std::nullopt; @@ -268,9 +268,10 @@ reg_t mcontrol6_t::tdata1_read(const processor_t * const proc) const noexcept { reg_t tdata1 = 0; tdata1 = set_field(tdata1, CSR_MCONTROL6_TYPE(xlen), CSR_TDATA1_TYPE_MCONTROL6); tdata1 = set_field(tdata1, CSR_MCONTROL6_DMODE(xlen), dmode); + tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT1, hit >> 1); // MSB of 2-bit field tdata1 = set_field(tdata1, CSR_MCONTROL6_VS, proc->extension_enabled('H') ? vs : 0); tdata1 = set_field(tdata1, CSR_MCONTROL6_VU, proc->extension_enabled('H') ? vu : 0); - tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT0, hit); + tdata1 = set_field(tdata1, CSR_MCONTROL6_HIT0, hit & 1); // LSB of 2-bit field tdata1 = set_field(tdata1, CSR_MCONTROL6_SELECT, select); tdata1 = set_field(tdata1, CSR_MCONTROL6_ACTION, action); tdata1 = set_field(tdata1, CSR_MCONTROL6_CHAIN, chain); @@ -290,7 +291,7 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const dmode = get_field(val, CSR_MCONTROL6_DMODE(xlen)); vs = get_field(val, CSR_MCONTROL6_VS); vu = get_field(val, CSR_MCONTROL6_VU); - hit = get_field(val, CSR_MCONTROL6_HIT0); + hit = hit_t(2 * get_field(val, CSR_MCONTROL6_HIT1) + get_field(val, CSR_MCONTROL6_HIT0)); // 2-bit field {hit1,hit0} select = get_field(val, CSR_MCONTROL6_SELECT); action = legalize_action(val, CSR_MCONTROL6_ACTION, CSR_MCONTROL6_DMODE(xlen)); chain = allow_chain ? get_field(val, CSR_MCONTROL6_CHAIN) : 0; diff --git a/riscv/triggers.h b/riscv/triggers.h index 7a4a94209c..b144ade8ed 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -51,6 +51,13 @@ struct match_result_t { action_t action; }; +typedef enum { + HIT_FALSE = 0, + HIT_BEFORE = 1, + HIT_AFTER = 2, + HIT_IMMEDIATELY_AFTER = 3 +} hit_t; + class matched_t { public: @@ -205,7 +212,7 @@ class mcontrol_common_t : public trigger_t { virtual bool get_store() const override { return store; } virtual bool get_load() const override { return load; } virtual action_t get_action() const override { return action; } - virtual void set_hit(bool val) = 0; + virtual void set_hit(hit_t val) = 0; virtual std::optional detect_memory_access_match(processor_t * const proc, operation_t operation, reg_t address, std::optional data) noexcept override; @@ -232,7 +239,7 @@ class mcontrol_t : public mcontrol_common_t { virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; - virtual void set_hit(bool val) override { hit = val; } + virtual void set_hit(hit_t val) override { hit = val != HIT_FALSE; } private: bool hit = false; @@ -243,10 +250,10 @@ class mcontrol6_t : public mcontrol_common_t { virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; - virtual void set_hit(bool val) override { hit = val; } + virtual void set_hit(hit_t UNUSED val) override { hit = HIT_BEFORE; } private: - bool hit = false; + hit_t hit = HIT_FALSE; }; class icount_t : public trigger_t { From 5e2edf84ccc02303b549bd81345b4ac56655334f Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 21 Feb 2023 13:40:59 +0800 Subject: [PATCH 005/155] triggers: implement mcontrol6.hit --- riscv/triggers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/triggers.h b/riscv/triggers.h index b144ade8ed..24f920630d 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -250,7 +250,7 @@ class mcontrol6_t : public mcontrol_common_t { virtual reg_t tdata1_read(const processor_t * const proc) const noexcept override; virtual void tdata1_write(processor_t * const proc, const reg_t val, const bool allow_chain) noexcept override; - virtual void set_hit(hit_t UNUSED val) override { hit = HIT_BEFORE; } + virtual void set_hit(hit_t val) override { hit = val; } private: hit_t hit = HIT_FALSE; From 76579667170dd50dace957d0606a320094e0a2a4 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 22 May 2024 08:48:30 +0800 Subject: [PATCH 006/155] triggers: introduce tinfo.version --- riscv/triggers.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 9c81b89a36..1d0ed8baf6 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -631,7 +631,8 @@ reg_t module_t::tinfo_read(unsigned UNUSED index) const noexcept (1 << CSR_TDATA1_TYPE_ITRIGGER) | (1 << CSR_TDATA1_TYPE_ETRIGGER) | (1 << CSR_TDATA1_TYPE_MCONTROL6) | - (1 << CSR_TDATA1_TYPE_DISABLED); + (1 << CSR_TDATA1_TYPE_DISABLED) | + (CSR_TINFO_VERSION_1 << CSR_TINFO_VERSION_OFFSET); } }; From 853105c659094122ef0769780645848646a4f463 Mon Sep 17 00:00:00 2001 From: Chih-Min Chao Date: Thu, 23 May 2024 02:24:15 -0700 Subject: [PATCH 007/155] zicflip: fix [ms]ret behavior Based on Spec chapter 3.5 "An MRET or SRET instruction is used to return from a trap in M-mode or S-mode, respectively. When executing an xRET instruction, if xPP holds the value y, then ELP is set to the value of xPELP if yLPE is 1; otherwise, it is set to NO_LP_EXPECTED; xPELP is set to NO_LP_EXPECTED." The change follow the last statement after semicolon "xPELP is set to NO_LP_EXPECTED" Signed-off-by: Chih-Min Chao --- riscv/insns/mret.h | 2 +- riscv/insns/sret.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index 1133e86b50..6d4d59fbe1 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -11,8 +11,8 @@ s = set_field(s, MSTATUS_MPP, p->extension_enabled('U') ? PRV_U : PRV_M); s = set_field(s, MSTATUS_MPV, 0); if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, MSTATUS_MPELP)); - s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED); } +s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED); STATE.mstatus->write(s); if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index aeaf087fc8..23a13b56df 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -25,7 +25,7 @@ if (!STATE.v) { } if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, SSTATUS_SPELP)); - s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED); } +s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED); STATE.sstatus->write(s); p->set_privilege(prev_prv, prev_virt); From 8ad1b68911c2b0c74bc8f00cf7f0f37bceca186e Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 24 May 2024 09:12:18 +0800 Subject: [PATCH 008/155] vector: Not logging write of reduction instructions when vl = 0 The spec says: "If vl=0, no operation is performed and the destination register is not updated." in Section 14. Vector Reduction Operations. The commit proposes setting the variable is_write to false when vl = 0, which means not logging the write. --- riscv/v_ext_macros.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h index 8f9820d913..a95af3eac0 100644 --- a/riscv/v_ext_macros.h +++ b/riscv/v_ext_macros.h @@ -608,7 +608,7 @@ static inline bool is_overlapped_widen(const int astart, int asize, reg_t rd_num = insn.rd(); \ reg_t rs1_num = insn.rs1(); \ reg_t rs2_num = insn.rs2(); \ - auto &vd_0_des = P.VU.elt::type>(rd_num, 0, true); \ + auto &vd_0_des = P.VU.elt::type>(rd_num, 0, vl > 0); \ auto vd_0_res = P.VU.elt::type>(rs1_num, 0); \ for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \ VI_LOOP_ELEMENT_SKIP(); \ @@ -639,7 +639,7 @@ static inline bool is_overlapped_widen(const int astart, int asize, reg_t rd_num = insn.rd(); \ reg_t rs1_num = insn.rs1(); \ reg_t rs2_num = insn.rs2(); \ - auto &vd_0_des = P.VU.elt::type>(rd_num, 0, true); \ + auto &vd_0_des = P.VU.elt::type>(rd_num, 0, vl > 0); \ auto vd_0_res = P.VU.elt::type>(rs1_num, 0); \ for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \ VI_LOOP_ELEMENT_SKIP(); \ @@ -1019,7 +1019,7 @@ static inline bool is_overlapped_widen(const int astart, int asize, reg_t rd_num = insn.rd(); \ reg_t rs1_num = insn.rs1(); \ reg_t rs2_num = insn.rs2(); \ - auto &vd_0_des = P.VU.elt::type>(rd_num, 0, true); \ + auto &vd_0_des = P.VU.elt::type>(rd_num, 0, vl > 0); \ auto vd_0_res = P.VU.elt::type>(rs1_num, 0); \ for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \ VI_LOOP_ELEMENT_SKIP(); \ @@ -1047,7 +1047,7 @@ static inline bool is_overlapped_widen(const int astart, int asize, reg_t rd_num = insn.rd(); \ reg_t rs1_num = insn.rs1(); \ reg_t rs2_num = insn.rs2(); \ - auto &vd_0_des = P.VU.elt::type>(rd_num, 0, true); \ + auto &vd_0_des = P.VU.elt::type>(rd_num, 0, vl > 0); \ auto vd_0_res = P.VU.elt::type>(rs1_num, 0); \ for (reg_t i = P.VU.vstart->read(); i < vl; ++i) { \ VI_LOOP_ELEMENT_SKIP(); \ From 48cf35d027051ac3c0f8d45b472bf00090f492d1 Mon Sep 17 00:00:00 2001 From: rbuchner Date: Thu, 23 May 2024 14:29:21 -0700 Subject: [PATCH 009/155] Require vector extension when attempting vxsat writes Accidentally removed in c9468f6e02. See #1660. --- riscv/csrs.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 95638d3f06..8d7737f195 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1452,6 +1452,8 @@ vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr): void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const { require_vector_vs; + if (!proc->extension_enabled('V')) + throw trap_illegal_instruction(insn.bits()); masked_csr_t::verify_permissions(insn, write); } From 6a65a806d28278ac719a192bc0b2356157d2bbe7 Mon Sep 17 00:00:00 2001 From: akifejaz Date: Mon, 27 May 2024 21:01:24 +0500 Subject: [PATCH 010/155] updated README with supported Vector Cryptography Extensions --- README.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/README.md b/README.md index ef2a1abaa1..aa9c563a83 100644 --- a/README.md +++ b/README.md @@ -51,6 +51,16 @@ Spike supports the following RISC-V ISA features: - Zfbfmin extension, v0.6 - Zvfbfmin extension, v0.6 - Zvfbfwma extension, v0.6 + - Zvbb extension, v0.9.7 + - Zvbc extension, v0.9.7 + - Zvkg extension, v0.9.7 + - Zvkned extension, v0.9.7 + - Zvknha, Zvknhb extension, v0.9.7 + - Zvksed extension, v0.9.7 + - Zvksh extension, v0.9.7 + - Zvkt extension, v0.9.7 + - Zvkn, Zvknc, Zvkng extension, v0.9.7 + - Zvks, Zvksc, Zvksg extension, v0.9.7 Versioning and APIs ------------------- From a316a37331aaaa4c8905ba37a86bde42a2c75343 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20L=C3=A9ger?= Date: Wed, 15 May 2024 17:15:40 +0200 Subject: [PATCH 011/155] add support to load ET_DYN elf MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When compiled as PIE, executable can be loaded at any memory address. Lately, OpenSBI switched to such behavior and spike was not able to load it anymore. This patch add an additional load_offset parameter for load_elf(). This load_offset value is passed as DRAM_BASE and used only for ET_DYN elfs. Signed-off-by: Clément Léger --- fesvr/elf.h | 2 ++ fesvr/elf2hex.cc | 2 +- fesvr/elfloader.cc | 19 ++++++++++++------- fesvr/elfloader.h | 3 ++- fesvr/htif.cc | 8 ++++---- fesvr/htif.h | 5 ++++- 6 files changed, 25 insertions(+), 14 deletions(-) diff --git a/fesvr/elf.h b/fesvr/elf.h index 7b38bf1165..b5a2a8d98a 100644 --- a/fesvr/elf.h +++ b/fesvr/elf.h @@ -6,6 +6,7 @@ #include #define ET_EXEC 2 +#define ET_DYN 3 #define EM_RISCV 243 #define EM_NONE 0 #define EV_CURRENT 1 @@ -21,6 +22,7 @@ #define IS_ELFLE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 1) #define IS_ELFBE(hdr) (IS_ELF(hdr) && (hdr).e_ident[5] == 2) #define IS_ELF_EXEC(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_type) == ET_EXEC) +#define IS_ELF_DYN(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_type) == ET_DYN) #define IS_ELF_RISCV(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_RISCV) #define IS_ELF_EM_NONE(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_machine) == EM_NONE) #define IS_ELF_VCURRENT(hdr) (IS_ELF(hdr) && ELF_SWAP((hdr), (hdr).e_version) == EV_CURRENT) diff --git a/fesvr/elf2hex.cc b/fesvr/elf2hex.cc index 327cf2d933..2638823b08 100644 --- a/fesvr/elf2hex.cc +++ b/fesvr/elf2hex.cc @@ -40,7 +40,7 @@ int main(int argc, char** argv) htif_hexwriter_t htif(base, width, depth); memif_t memif(&htif); reg_t entry; - load_elf(argv[3], &memif, &entry); + load_elf(argv[3], &memif, &entry, 0); std::cout << htif; return 0; diff --git a/fesvr/elfloader.cc b/fesvr/elfloader.cc index 391afa04bb..5cab0508b6 100644 --- a/fesvr/elfloader.cc +++ b/fesvr/elfloader.cc @@ -18,7 +18,8 @@ #include #include -std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0) +std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, + reg_t load_offset, unsigned required_xlen = 0) { int fd = open(fn, O_RDONLY); struct stat s; @@ -41,10 +42,14 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* throw incompat_xlen(required_xlen, xlen); } assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64)); - assert(IS_ELF_EXEC(*eh64)); + assert(IS_ELF_EXEC(*eh64) || IS_ELF_DYN(*eh64)); assert(IS_ELF_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64)); assert(IS_ELF_VCURRENT(*eh64)); + if (IS_ELF_EXEC(*eh64)) { + load_offset = 0; + } + std::vector zeros; std::map symbols; @@ -52,19 +57,19 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* do { \ ehdr_t* eh = (ehdr_t*)buf; \ phdr_t* ph = (phdr_t*)(buf + bswap(eh->e_phoff)); \ - *entry = bswap(eh->e_entry); \ + *entry = bswap(eh->e_entry) + load_offset; \ assert(size >= bswap(eh->e_phoff) + bswap(eh->e_phnum) * sizeof(*ph)); \ for (unsigned i = 0; i < bswap(eh->e_phnum); i++) { \ if (bswap(ph[i].p_type) == PT_LOAD && bswap(ph[i].p_memsz)) { \ + reg_t load_addr = bswap(ph[i].p_paddr) + load_offset; \ if (bswap(ph[i].p_filesz)) { \ assert(size >= bswap(ph[i].p_offset) + bswap(ph[i].p_filesz)); \ - memif->write(bswap(ph[i].p_paddr), bswap(ph[i].p_filesz), \ + memif->write(load_addr, bswap(ph[i].p_filesz), \ (uint8_t*)buf + bswap(ph[i].p_offset)); \ } \ if (size_t pad = bswap(ph[i].p_memsz) - bswap(ph[i].p_filesz)) { \ zeros.resize(pad); \ - memif->write(bswap(ph[i].p_paddr) + bswap(ph[i].p_filesz), pad, \ - zeros.data()); \ + memif->write(load_addr + bswap(ph[i].p_filesz), pad, zeros.data()); \ } \ } \ } \ @@ -96,7 +101,7 @@ std::map load_elf(const char* fn, memif_t* memif, reg_t* bswap(sh[strtabidx].sh_size) - bswap(sym[i].st_name); \ assert(bswap(sym[i].st_name) < bswap(sh[strtabidx].sh_size)); \ assert(strnlen(strtab + bswap(sym[i].st_name), max_len) < max_len); \ - symbols[strtab + bswap(sym[i].st_name)] = bswap(sym[i].st_value); \ + symbols[strtab + bswap(sym[i].st_name)] = bswap(sym[i].st_value) + load_offset; \ } \ } \ } while (0) diff --git a/fesvr/elfloader.h b/fesvr/elfloader.h index ae4ee78c2b..0a250cde1f 100644 --- a/fesvr/elfloader.h +++ b/fesvr/elfloader.h @@ -8,6 +8,7 @@ #include class memif_t; -std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0); +std::map load_elf(const char* fn, memif_t* memif, reg_t* entry, + reg_t load_offset, unsigned required_xlen = 0); #endif diff --git a/fesvr/htif.cc b/fesvr/htif.cc index 8b5eb8dc84..46f15d3169 100644 --- a/fesvr/htif.cc +++ b/fesvr/htif.cc @@ -103,7 +103,7 @@ static void bad_address(const std::string& situation, reg_t addr) exit(-1); } -std::map htif_t::load_payload(const std::string& payload, reg_t* entry) +std::map htif_t::load_payload(const std::string& payload, reg_t* entry, reg_t load_offset) { std::string path; if (access(payload.c_str(), F_OK) == 0) @@ -143,7 +143,7 @@ std::map htif_t::load_payload(const std::string& payload, } preload_aware_memif(this); try { - return load_elf(path.c_str(), &preload_aware_memif, entry, expected_xlen); + return load_elf(path.c_str(), &preload_aware_memif, entry, load_offset, expected_xlen); } catch (mem_trap_t& t) { bad_address("loading payload " + payload, t.get_tval()); abort(); @@ -152,7 +152,7 @@ std::map htif_t::load_payload(const std::string& payload, void htif_t::load_program() { - std::map symbols = load_payload(targs[0], &entry); + std::map symbols = load_payload(targs[0], &entry, load_offset); if (symbols.count("tohost") && symbols.count("fromhost")) { tohost_addr = symbols["tohost"]; @@ -169,7 +169,7 @@ void htif_t::load_program() for (auto payload : payloads) { reg_t dummy_entry; - load_payload(payload, &dummy_entry); + load_payload(payload, &dummy_entry, 0); } class nop_memif_t : public memif_t { diff --git a/fesvr/htif.h b/fesvr/htif.h index dd7c060e41..74511f58a5 100644 --- a/fesvr/htif.h +++ b/fesvr/htif.h @@ -7,6 +7,7 @@ #include "syscall.h" #include "device.h" #include "byteorder.h" +#include "../riscv/platform.h" #include #include #include @@ -58,7 +59,8 @@ class htif_t : public chunked_memif_t virtual size_t chunk_align() = 0; virtual size_t chunk_max_size() = 0; - virtual std::map load_payload(const std::string& payload, reg_t* entry); + virtual std::map load_payload(const std::string& payload, reg_t* entry, + reg_t load_addr); virtual void load_program(); virtual void idle() {} @@ -79,6 +81,7 @@ class htif_t : public chunked_memif_t void register_devices(); void usage(const char * program_name); unsigned int expected_xlen = 0; + const reg_t load_offset = DRAM_BASE; memif_t mem; reg_t entry; bool writezeros; From e7d46b854397d453fcbe7ccfcea6c9970f315a59 Mon Sep 17 00:00:00 2001 From: akifejaz Date: Wed, 29 May 2024 22:52:13 +0500 Subject: [PATCH 012/155] corrected the crypto extension version --- README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index aa9c563a83..c6f84842f7 100644 --- a/README.md +++ b/README.md @@ -51,16 +51,16 @@ Spike supports the following RISC-V ISA features: - Zfbfmin extension, v0.6 - Zvfbfmin extension, v0.6 - Zvfbfwma extension, v0.6 - - Zvbb extension, v0.9.7 - - Zvbc extension, v0.9.7 - - Zvkg extension, v0.9.7 - - Zvkned extension, v0.9.7 - - Zvknha, Zvknhb extension, v0.9.7 - - Zvksed extension, v0.9.7 - - Zvksh extension, v0.9.7 - - Zvkt extension, v0.9.7 - - Zvkn, Zvknc, Zvkng extension, v0.9.7 - - Zvks, Zvksc, Zvksg extension, v0.9.7 + - Zvbb extension, v1.0 + - Zvbc extension, v1.0 + - Zvkg extension, v1.0 + - Zvkned extension, v1.0 + - Zvknha, Zvknhb extension, v1.0 + - Zvksed extension, v1.0 + - Zvksh extension, v1.0 + - Zvkt extension, v1.0 + - Zvkn, Zvknc, Zvkng extension, v1.0 + - Zvks, Zvksc, Zvksg extension, v1.0 Versioning and APIs ------------------- From 148e6d63e036a611537f7afbee771d9b83d348fb Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 31 May 2024 01:22:34 -0700 Subject: [PATCH 013/155] No need to check if Zicfilp is enabled before checking ELP ELP will be zero if Zicfilp is not enabled. --- riscv/processor.cc | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 7a63f3c125..05647311f1 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -993,9 +993,7 @@ const char* processor_t::get_symbol(uint64_t addr) void processor_t::execute_insn_prehook(insn_t insn) { - if (extension_enabled(EXT_ZICFILP)) { - zicfilp_check_if_lpad_required(state.elp, insn); - } + zicfilp_check_if_lpad_required(state.elp, insn); } void processor_t::disasm(insn_t insn) From 759599553bab6c95399253ba366a0f5b1b3dd48f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 31 May 2024 01:24:02 -0700 Subject: [PATCH 014/155] Avoid checking ELP before every instruction fetch Serialize after setting ELP. That way, we can hoist the check outside of the main simulation loop. --- riscv/execute.cc | 4 ++-- riscv/insns/c_jalr.h | 1 + riscv/insns/c_jr.h | 1 + riscv/insns/jalr.h | 1 + riscv/processor.cc | 16 ++++++---------- riscv/processor.h | 2 +- 6 files changed, 12 insertions(+), 13 deletions(-) diff --git a/riscv/execute.cc b/riscv/execute.cc index b2532c960a..f263dce995 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -247,6 +247,8 @@ void processor_t::step(size_t n) { take_pending_interrupt(); + check_if_lpad_required(); + if (unlikely(slow_path())) { // Main simulation loop, slow path. @@ -280,7 +282,6 @@ void processor_t::step(size_t n) in_wfi = false; insn_fetch_t fetch = mmu->load_insn(pc); - execute_insn_prehook(fetch.insn); if (debug && !state.serialized) disasm(fetch.insn); pc = execute_insn_logged(this, pc, fetch); @@ -292,7 +293,6 @@ void processor_t::step(size_t n) // Main simulation loop, fast path. for (auto ic_entry = _mmu->access_icache(pc); ; ) { auto fetch = ic_entry->data; - execute_insn_prehook(fetch.insn); pc = execute_insn_fast(this, pc, fetch); ic_entry = ic_entry->next; if (unlikely(ic_entry->tag != pc)) diff --git a/riscv/insns/c_jalr.h b/riscv/insns/c_jalr.h index 12bc7f9ed6..694f183b9a 100644 --- a/riscv/insns/c_jalr.h +++ b/riscv/insns/c_jalr.h @@ -6,4 +6,5 @@ WRITE_REG(X_RA, tmp); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rvc_rs1()); + serialize(); } diff --git a/riscv/insns/c_jr.h b/riscv/insns/c_jr.h index c5162e93fe..af43dd34ee 100644 --- a/riscv/insns/c_jr.h +++ b/riscv/insns/c_jr.h @@ -4,4 +4,5 @@ set_pc(RVC_RS1 & ~reg_t(1)); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rvc_rs1()); + serialize(); } diff --git a/riscv/insns/jalr.h b/riscv/insns/jalr.h index 0622a2290d..0606f67283 100644 --- a/riscv/insns/jalr.h +++ b/riscv/insns/jalr.h @@ -4,4 +4,5 @@ WRITE_RD(tmp); if (ZICFILP_xLPE(STATE.v, STATE.prv)) { STATE.elp = ZICFILP_IS_LP_EXPECTED(insn.rs1()); + serialize(); } diff --git a/riscv/processor.cc b/riscv/processor.cc index 05647311f1..da49a37e95 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -94,14 +94,6 @@ processor_t::~processor_t() delete disassembler; } -static void zicfilp_check_if_lpad_required(const elp_t elp, insn_t insn) -{ - if (unlikely(elp == elp_t::LP_EXPECTED)) { - // also see riscv/lpad.h for more checks performed - software_check((insn.bits() & MASK_LPAD) == MATCH_LPAD, LANDING_PAD_FAULT); - } -} - static void bad_option_string(const char *option, const char *value, const char *msg) { @@ -991,9 +983,13 @@ const char* processor_t::get_symbol(uint64_t addr) return sim->get_symbol(addr); } -void processor_t::execute_insn_prehook(insn_t insn) +void processor_t::check_if_lpad_required() { - zicfilp_check_if_lpad_required(state.elp, insn); + if (unlikely(state.elp == elp_t::LP_EXPECTED)) { + // also see insns/lpad.h for more checks performed + insn_fetch_t fetch = mmu->load_insn(state.pc); + software_check((fetch.insn.bits() & MASK_LPAD) == MATCH_LPAD, LANDING_PAD_FAULT); + } } void processor_t::disasm(insn_t insn) diff --git a/riscv/processor.h b/riscv/processor.h index f3e5294e68..3e37b43863 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -319,7 +319,7 @@ class processor_t : public abstract_device_t void clear_waiting_for_interrupt() { in_wfi = false; }; bool is_waiting_for_interrupt() { return in_wfi; }; - void execute_insn_prehook(insn_t insn); + void check_if_lpad_required(); private: const isa_parser_t * const isa; From db762327efe1c754081f7cbfa1f1cae168fedf17 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 11 Jun 2024 09:27:33 +0800 Subject: [PATCH 015/155] triggers: implement tcontrol Implement Debug spec Section 5.7.6. Trigger Control (tcontrol). This commit lets tcontrol be read-only 0 if number of triggers is 0. --- riscv/insn_template.h | 1 + riscv/insns/mret.h | 1 + riscv/processor.cc | 4 ++++ riscv/processor.h | 1 + riscv/triggers.cc | 3 ++- 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/riscv/insn_template.h b/riscv/insn_template.h index 88a41c2a75..bf9d9d74ed 100644 --- a/riscv/insn_template.h +++ b/riscv/insn_template.h @@ -8,4 +8,5 @@ #include "specialize.h" #include "tracer.h" #include "v_ext_macros.h" +#include "debug_defines.h" #include diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index 6d4d59fbe1..3fe920cb10 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -15,4 +15,5 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) { s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED); STATE.mstatus->write(s); if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change +STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0); p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/processor.cc b/riscv/processor.cc index da49a37e95..a1cec6c23d 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -11,6 +11,7 @@ #include "disasm.h" #include "platform.h" #include "vector_unit.h" +#include "debug_defines.h" #include #include #include @@ -403,11 +404,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2); csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3); csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO); + csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0); } else { csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1, 0); csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2, 0); csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3, 0); csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO, 0); + csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, 0); } unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); @@ -951,6 +954,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) state.elp = elp_t::NO_LP_EXPECTED; state.mstatus->write(s); if (state.mstatush) state.mstatush->write(s >> 32); // log mstatush change + state.tcontrol->write((state.tcontrol->read() & CSR_TCONTROL_MTE) ? CSR_TCONTROL_MPTE : 0); set_privilege(PRV_M, false); } } diff --git a/riscv/processor.h b/riscv/processor.h index 3e37b43863..c03c3ef672 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -141,6 +141,7 @@ struct state_t dcsr_csr_t_p dcsr; csr_t_p tselect; csr_t_p tdata2; + csr_t_p tcontrol; csr_t_p scontext; csr_t_p mcontext; diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 1d0ed8baf6..aa258bd202 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -59,7 +59,8 @@ bool trigger_t::common_match(processor_t * const proc, bool use_prev_prv) const auto state = proc->get_state(); auto prv = use_prev_prv ? state->prev_prv : state->prv; auto v = use_prev_prv ? state->prev_v : state->v; - return mode_match(prv, v) && textra_match(proc); + auto m_enabled = get_action() != 0 || (state->tcontrol->read() & CSR_TCONTROL_MTE); + return (prv < PRV_M || m_enabled) && mode_match(prv, v) && textra_match(proc); } bool trigger_t::mode_match(reg_t prv, bool v) const noexcept From 025a50d51af24e8ee94d200ac09041779fe40acf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:25:47 -0700 Subject: [PATCH 016/155] Add missing instructions to Makefile --- riscv/riscv.mk.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 469c48dcfe..aef59399bd 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1061,6 +1061,9 @@ riscv_insn_ext_zimop = \ mop_r_N \ mop_rr_N \ +riscv_insn_ext_zcmop = \ + c_mop_N \ + riscv_insn_ext_zicfilp = \ lpad @@ -1114,6 +1117,7 @@ riscv_insn_list = \ $(riscv_insn_smrnmi) \ $(riscv_insn_svinval) \ $(riscv_insn_ext_zimop) \ + $(riscv_insn_ext_zcmop) \ $(riscv_insn_ext_zicfilp) \ $(riscv_insn_ext_zicfiss) \ From 5defb11363cb01c08a3aca038cf84ddb4afe7719 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 30 May 2024 21:33:11 -0700 Subject: [PATCH 017/155] Remove unnecessary instructions from overlap list - c.fsdsp need not be listed since cm.push etc. are listed - mop.r.28/mop.rr.7 don't have corresponding files in riscv/insns/ - the rest are just erroneous --- riscv/overlap_list.h | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index 04ae44364a..f464835a56 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -1,6 +1,3 @@ -DECLARE_OVERLAP_INSN(c_fsdsp, EXT_ZCD) -DECLARE_OVERLAP_INSN(c_fld, EXT_ZCD) -DECLARE_OVERLAP_INSN(c_fldsp, EXT_ZCD) DECLARE_OVERLAP_INSN(cm_push, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_pop, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_popret, EXT_ZCMP) @@ -8,19 +5,11 @@ DECLARE_OVERLAP_INSN(cm_popretz, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mva01s, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mvsa01, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_jalt, EXT_ZCMT) -DECLARE_OVERLAP_INSN(c_fsd, EXT_ZCD) DECLARE_OVERLAP_INSN(c_ebreak, EXT_ZCA) DECLARE_OVERLAP_INSN(c_jalr, EXT_ZCA) DECLARE_OVERLAP_INSN(c_jr, EXT_ZCA) -DECLARE_OVERLAP_INSN(vaesdf_vv, EXT_ZVKNED) -DECLARE_OVERLAP_INSN(vghsh_vv, EXT_ZVKG) -DECLARE_OVERLAP_INSN(vsha2ms_vv, EXT_ZVKNHA) -DECLARE_OVERLAP_INSN(vsha2ms_vv, EXT_ZVKNHB) -DECLARE_OVERLAP_INSN(vsm3me_vv, EXT_ZVKSH) DECLARE_OVERLAP_INSN(lpad, EXT_ZICFILP) -DECLARE_OVERLAP_INSN(mop_r_28, EXT_ZIMOP) DECLARE_OVERLAP_INSN(mop_r_N, EXT_ZIMOP) -DECLARE_OVERLAP_INSN(mop_rr_7, EXT_ZIMOP) DECLARE_OVERLAP_INSN(mop_rr_N, EXT_ZIMOP) DECLARE_OVERLAP_INSN(c_sspush_x1, EXT_ZICFISS) DECLARE_OVERLAP_INSN(c_sspopchk_x5, EXT_ZICFISS) From 74ee3b76169f98f4bf735b539c472d691c1588cf Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 30 May 2024 21:46:05 -0700 Subject: [PATCH 018/155] Refine Zicfiss overlap list We get better error checking if we list only the more specific instructions and omit the more general ones (mop.r.N/mop.rr.N). --- riscv/overlap_list.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index f464835a56..85584265f7 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -9,8 +9,11 @@ DECLARE_OVERLAP_INSN(c_ebreak, EXT_ZCA) DECLARE_OVERLAP_INSN(c_jalr, EXT_ZCA) DECLARE_OVERLAP_INSN(c_jr, EXT_ZCA) DECLARE_OVERLAP_INSN(lpad, EXT_ZICFILP) -DECLARE_OVERLAP_INSN(mop_r_N, EXT_ZIMOP) -DECLARE_OVERLAP_INSN(mop_rr_N, EXT_ZIMOP) +DECLARE_OVERLAP_INSN(ssrdp, EXT_ZICFISS) +DECLARE_OVERLAP_INSN(sspush_x1, EXT_ZICFISS) +DECLARE_OVERLAP_INSN(sspush_x5, EXT_ZICFISS) +DECLARE_OVERLAP_INSN(sspopchk_x1, EXT_ZICFISS) +DECLARE_OVERLAP_INSN(sspopchk_x5, EXT_ZICFISS) DECLARE_OVERLAP_INSN(c_sspush_x1, EXT_ZICFISS) DECLARE_OVERLAP_INSN(c_sspopchk_x5, EXT_ZICFISS) DECLARE_OVERLAP_INSN(c_mop_N, EXT_ZCMOP) From ca38d97e7b0ab0b482e50e1381dfb28eab48aefa Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 30 May 2024 21:46:56 -0700 Subject: [PATCH 019/155] Add comments to overlap list --- riscv/overlap_list.h | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index 85584265f7..7468e87a41 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -1,3 +1,4 @@ +// these overlap c.fsdsp DECLARE_OVERLAP_INSN(cm_push, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_pop, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_popret, EXT_ZCMP) @@ -5,10 +6,18 @@ DECLARE_OVERLAP_INSN(cm_popretz, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mva01s, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_mvsa01, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_jalt, EXT_ZCMT) + +// c.ebreak and c.jalr overlap c.add DECLARE_OVERLAP_INSN(c_ebreak, EXT_ZCA) DECLARE_OVERLAP_INSN(c_jalr, EXT_ZCA) + +// c.jr overlaps c.mv DECLARE_OVERLAP_INSN(c_jr, EXT_ZCA) + +// lpad overlaps auipc DECLARE_OVERLAP_INSN(lpad, EXT_ZICFILP) + +// these overlap Zimop/Zcmop DECLARE_OVERLAP_INSN(ssrdp, EXT_ZICFISS) DECLARE_OVERLAP_INSN(sspush_x1, EXT_ZICFISS) DECLARE_OVERLAP_INSN(sspush_x5, EXT_ZICFISS) From acd43e0191ae9afa8099a00bb9162b134233b01f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:22:05 -0700 Subject: [PATCH 020/155] Preserve the ordering of the instruction list --- riscv/processor.cc | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index a1cec6c23d..3a9c0d94ca 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -1072,24 +1072,6 @@ reg_t illegal_instruction(processor_t UNUSED *p, insn_t insn, reg_t UNUSED pc) throw trap_illegal_instruction(insn.bits() & 0xffffffffULL); } -static insn_desc_t -propagate_instruction_in_vector(std::vector &instructions, - std::vector::iterator it) { - assert(it != instructions.end()); - insn_desc_t desc = *it; - if (it->mask != 0 && it != instructions.begin() && - std::next(it) != instructions.end()) { - if (it->match != std::prev(it)->match && - it->match != std::next(it)->match) { - // move to front of opcode list to reduce miss penalty - while (--it >= instructions.begin()) - *std::next(it) = *it; - instructions[0] = desc; - } - } - return desc; -} - insn_func_t processor_t::decode_insn(insn_t insn) { // look up opcode in hash table @@ -1105,13 +1087,11 @@ insn_func_t processor_t::decode_insn(insn_t insn) }; auto p = std::find_if(custom_instructions.begin(), custom_instructions.end(), matching); - if (p != custom_instructions.end()) { - desc = propagate_instruction_in_vector(custom_instructions, p); - } else { + if (p == custom_instructions.end()) { p = std::find_if(instructions.begin(), instructions.end(), matching); assert(p != instructions.end()); - desc = propagate_instruction_in_vector(instructions, p); } + desc = *p; opcode_cache[idx] = desc; opcode_cache[idx].match = insn.bits(); } From 625e9451a75b3094597a1b1647cb71fa65bd8b98 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:30:34 -0700 Subject: [PATCH 021/155] Keep potentially overlapping instructions in order at head of list --- riscv/processor.cc | 52 ++++++++++++++++++++++++++++------------------ 1 file changed, 32 insertions(+), 20 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 3a9c0d94ca..c8cb5bec87 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -1111,17 +1111,6 @@ void processor_t::register_insn(insn_desc_t desc, bool is_custom) { void processor_t::build_opcode_map() { - struct cmp { - bool operator()(const insn_desc_t& lhs, const insn_desc_t& rhs) { - if (lhs.match == rhs.match) - return lhs.mask > rhs.mask; - return lhs.match > rhs.match; - } - }; - - std::sort(instructions.begin(), instructions.end(), cmp()); - std::sort(custom_instructions.begin(), custom_instructions.end(), cmp()); - for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++) opcode_cache[i] = insn_desc_t::illegal(); } @@ -1145,15 +1134,12 @@ void processor_t::register_base_instructions() { #define DECLARE_INSN(name, match, mask) \ insn_bits_t name##_match = (match), name##_mask = (mask); \ - bool name##_supported = true; + isa_extension_t name##_ext = NUM_ISA_EXTENSIONS; \ + bool name##_overlapping = false; #include "encoding.h" #undef DECLARE_INSN - #define DECLARE_OVERLAP_INSN(name, ext) { name##_supported = isa->extension_enabled(ext); } - #include "overlap_list.h" - #undef DECLARE_OVERLAP_INSN - #define DEFINE_INSN(name) \ extern reg_t fast_rv32i_##name(processor_t*, insn_t, reg_t); \ extern reg_t fast_rv64i_##name(processor_t*, insn_t, reg_t); \ @@ -1162,8 +1148,14 @@ void processor_t::register_base_instructions() extern reg_t logged_rv32i_##name(processor_t*, insn_t, reg_t); \ extern reg_t logged_rv64i_##name(processor_t*, insn_t, reg_t); \ extern reg_t logged_rv32e_##name(processor_t*, insn_t, reg_t); \ - extern reg_t logged_rv64e_##name(processor_t*, insn_t, reg_t); \ - if (name##_supported) { \ + extern reg_t logged_rv64e_##name(processor_t*, insn_t, reg_t); + #include "insn_list.h" + #undef DEFINE_INSN + + // add overlapping instructions first, in order + #define DECLARE_OVERLAP_INSN(name, ext) \ + name##_overlapping = true; \ + if (isa->extension_enabled(ext)) \ register_base_insn((insn_desc_t) { \ name##_match, \ name##_mask, \ @@ -1174,9 +1166,29 @@ void processor_t::register_base_instructions() logged_rv32i_##name, \ logged_rv64i_##name, \ logged_rv32e_##name, \ - logged_rv64e_##name}); \ - } + logged_rv64e_##name}); + #include "overlap_list.h" + #undef DECLARE_OVERLAP_INSN + + // add all other instructions. since they are non-overlapping, the order + // does not affect correctness, but more frequent instructions should + // appear earlier to improve search time on opcode_cache misses. + #define DEFINE_INSN(name) \ + if (!name##_overlapping) \ + register_base_insn((insn_desc_t) { \ + name##_match, \ + name##_mask, \ + fast_rv32i_##name, \ + fast_rv64i_##name, \ + fast_rv32e_##name, \ + fast_rv64e_##name, \ + logged_rv32i_##name, \ + logged_rv64i_##name, \ + logged_rv32e_##name, \ + logged_rv64e_##name}); #include "insn_list.h" + #undef DEFINE_INSN + // terminate instruction list with a catch-all register_base_insn(insn_desc_t::illegal()); From 4d2347868416442347a0c4a95152ebc106f10312 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:24:44 -0700 Subject: [PATCH 022/155] Compensate for perf loss of not mutating insn list by presorting it --- riscv/riscv.mk.in | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index aef59399bd..689a198bcd 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -1088,20 +1088,20 @@ riscv_insn_ext_zvk = \ $(riscv_insn_ext_zvksh) \ riscv_insn_list = \ - $(if $(HAVE_INT128),$(riscv_insn_ext_v),) \ - $(riscv_insn_ext_a) \ + $(riscv_insn_ext_i) \ + $(riscv_insn_ext_c) \ + $(riscv_insn_ext_f) \ + $(riscv_insn_ext_d) \ + $(riscv_insn_ext_m) \ $(riscv_insn_ext_b) \ + $(riscv_insn_ext_a) \ + $(if $(HAVE_INT128),$(riscv_insn_ext_v),) \ $(riscv_insn_ext_bf16) \ - $(riscv_insn_ext_c) \ $(riscv_insn_ext_cmo) \ - $(riscv_insn_ext_d) \ $(riscv_insn_ext_d_zfa) \ - $(riscv_insn_ext_f) \ $(riscv_insn_ext_f_zfa) \ $(riscv_insn_ext_h) \ - $(riscv_insn_ext_i) \ $(riscv_insn_ext_k) \ - $(riscv_insn_ext_m) \ $(riscv_insn_ext_q) \ $(riscv_insn_ext_q_zfa) \ $(riscv_insn_ext_zacas) \ From 48f815488e810b37bbeb1b0826f8154f4c50145f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:32:27 -0700 Subject: [PATCH 023/155] Improve hit rate of opcode cache to compensate for not mutating insn list --- riscv/processor.cc | 21 +++++++++++------- riscv/processor.h | 54 ++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 58 insertions(+), 17 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index c8cb5bec87..a81306801c 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -1064,6 +1064,12 @@ reg_t processor_t::get_csr(int which, insn_t insn, bool write, bool peek) throw trap_illegal_instruction(insn.bits()); } +const insn_desc_t insn_desc_t::illegal_instruction = { + 0, 0, + &::illegal_instruction, &::illegal_instruction, &::illegal_instruction, &::illegal_instruction, + &::illegal_instruction, &::illegal_instruction, &::illegal_instruction, &::illegal_instruction +}; + reg_t illegal_instruction(processor_t UNUSED *p, insn_t insn, reg_t UNUSED pc) { // The illegal instruction can be longer than ILEN bits, where the tval will @@ -1076,11 +1082,11 @@ insn_func_t processor_t::decode_insn(insn_t insn) { // look up opcode in hash table size_t idx = insn.bits() % OPCODE_CACHE_SIZE; - insn_desc_t desc = opcode_cache[idx]; + auto [hit, desc] = opcode_cache[idx].lookup(insn.bits()); bool rve = extension_enabled('E'); - if (unlikely(insn.bits() != desc.match)) { + if (unlikely(!hit)) { // fall back to linear search auto matching = [insn_bits = insn.bits()](const insn_desc_t &d) { return (insn_bits & d.mask) == d.match; @@ -1091,12 +1097,11 @@ insn_func_t processor_t::decode_insn(insn_t insn) p = std::find_if(instructions.begin(), instructions.end(), matching); assert(p != instructions.end()); } - desc = *p; - opcode_cache[idx] = desc; - opcode_cache[idx].match = insn.bits(); + desc = &*p; + opcode_cache[idx].replace(insn.bits(), desc); } - return desc.func(xlen, rve, log_commits_enabled); + return desc->func(xlen, rve, log_commits_enabled); } void processor_t::register_insn(insn_desc_t desc, bool is_custom) { @@ -1112,7 +1117,7 @@ void processor_t::register_insn(insn_desc_t desc, bool is_custom) { void processor_t::build_opcode_map() { for (size_t i = 0; i < OPCODE_CACHE_SIZE; i++) - opcode_cache[i] = insn_desc_t::illegal(); + opcode_cache[i].reset(); } void processor_t::register_extension(extension_t *x) { @@ -1190,7 +1195,7 @@ void processor_t::register_base_instructions() #undef DEFINE_INSN // terminate instruction list with a catch-all - register_base_insn(insn_desc_t::illegal()); + register_base_insn(insn_desc_t::illegal_instruction); build_opcode_map(); } diff --git a/riscv/processor.h b/riscv/processor.h index c03c3ef672..9b776e292c 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -43,7 +43,7 @@ struct insn_desc_t insn_func_t logged_rv32e; insn_func_t logged_rv64e; - insn_func_t func(int xlen, bool rve, bool logged) + insn_func_t func(int xlen, bool rve, bool logged) const { if (logged) if (rve) @@ -57,12 +57,7 @@ struct insn_desc_t return xlen == 64 ? fast_rv64i : fast_rv32i; } - static insn_desc_t illegal() - { - return {0, 0, - &illegal_instruction, &illegal_instruction, &illegal_instruction, &illegal_instruction, - &illegal_instruction, &illegal_instruction, &illegal_instruction, &illegal_instruction}; - } + static const insn_desc_t illegal_instruction; }; // regnum, data @@ -196,6 +191,47 @@ struct state_t elp_t elp; }; +class opcode_cache_entry_t { + public: + opcode_cache_entry_t() + { + reset(); + } + + void reset() + { + for (size_t i = 0; i < associativity; i++) { + tag[i] = 0; + contents[i] = &insn_desc_t::illegal_instruction; + } + } + + void replace(insn_bits_t opcode, const insn_desc_t* desc) + { + for (size_t i = associativity - 1; i > 0; i--) { + tag[i] = tag[i-1]; + contents[i] = contents[i-1]; + } + + tag[0] = opcode; + contents[0] = desc; + } + + std::tuple lookup(insn_bits_t opcode) + { + for (size_t i = 0; i < associativity; i++) + if (tag[i] == opcode) + return std::tuple(true, contents[i]); + + return std::tuple(false, nullptr); + } + + private: + static const size_t associativity = 4; + insn_bits_t tag[associativity]; + const insn_desc_t* contents[associativity]; +}; + // this class represents one processor in a RISC-V machine. class processor_t : public abstract_device_t { @@ -351,8 +387,8 @@ class processor_t : public abstract_device_t std::vector custom_instructions; std::unordered_map pc_histogram; - static const size_t OPCODE_CACHE_SIZE = 8191; - insn_desc_t opcode_cache[OPCODE_CACHE_SIZE]; + static const size_t OPCODE_CACHE_SIZE = 4095; + opcode_cache_entry_t opcode_cache[OPCODE_CACHE_SIZE]; void take_pending_interrupt() { take_interrupt(state.mip->read() & state.mie->read()); } void take_interrupt(reg_t mask); // take first enabled interrupt in mask From 0325be55596b0e7386a792580d8fca2e9bb74c35 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:34:08 -0700 Subject: [PATCH 024/155] Separate RV32 and RV64 C instructions into separate files --- riscv/insns/c_flw.h | 11 +++-------- riscv/insns/c_flwsp.h | 12 +++--------- riscv/insns/c_fsw.h | 11 +++-------- riscv/insns/c_fswsp.h | 11 +++-------- riscv/insns/c_ld.h | 2 ++ riscv/insns/c_ldsp.h | 3 +++ riscv/insns/c_sd.h | 2 ++ riscv/insns/c_sdsp.h | 2 ++ riscv/overlap_list.h | 6 ++++++ riscv/riscv.mk.in | 4 ++++ 10 files changed, 31 insertions(+), 33 deletions(-) create mode 100644 riscv/insns/c_ld.h create mode 100644 riscv/insns/c_ldsp.h create mode 100644 riscv/insns/c_sd.h create mode 100644 riscv/insns/c_sdsp.h diff --git a/riscv/insns/c_flw.h b/riscv/insns/c_flw.h index 95ae260282..aa64bf14ab 100644 --- a/riscv/insns/c_flw.h +++ b/riscv/insns/c_flw.h @@ -1,8 +1,3 @@ -if (xlen == 32) { - require_extension(EXT_ZCF); - require_fp; - WRITE_RVC_FRS2S(f32(MMU.load(RVC_RS1S + insn.rvc_lw_imm()))); -} else { // c.ld - require_extension(EXT_ZCA); - WRITE_RVC_RS2S(MMU.load(RVC_RS1S + insn.rvc_ld_imm())); -} +require_extension(EXT_ZCF); +require_fp; +WRITE_RVC_FRS2S(f32(MMU.load(RVC_RS1S + insn.rvc_lw_imm()))); diff --git a/riscv/insns/c_flwsp.h b/riscv/insns/c_flwsp.h index eea0ec53ca..caea77c949 100644 --- a/riscv/insns/c_flwsp.h +++ b/riscv/insns/c_flwsp.h @@ -1,9 +1,3 @@ -if (xlen == 32) { - require_extension(EXT_ZCF); - require_fp; - WRITE_FRD(f32(MMU.load(RVC_SP + insn.rvc_lwsp_imm()))); -} else { // c.ldsp - require_extension(EXT_ZCA); - require(insn.rvc_rd() != 0); - WRITE_RD(MMU.load(RVC_SP + insn.rvc_ldsp_imm())); -} +require_extension(EXT_ZCF); +require_fp; +WRITE_FRD(f32(MMU.load(RVC_SP + insn.rvc_lwsp_imm()))); diff --git a/riscv/insns/c_fsw.h b/riscv/insns/c_fsw.h index d7d6fed365..dda411ad71 100644 --- a/riscv/insns/c_fsw.h +++ b/riscv/insns/c_fsw.h @@ -1,8 +1,3 @@ -if (xlen == 32) { - require_extension(EXT_ZCF); - require_fp; - MMU.store(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]); -} else { // c.sd - require_extension(EXT_ZCA); - MMU.store(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); -} +require_extension(EXT_ZCF); +require_fp; +MMU.store(RVC_RS1S + insn.rvc_lw_imm(), RVC_FRS2S.v[0]); diff --git a/riscv/insns/c_fswsp.h b/riscv/insns/c_fswsp.h index 5952251074..6ea5c05831 100644 --- a/riscv/insns/c_fswsp.h +++ b/riscv/insns/c_fswsp.h @@ -1,8 +1,3 @@ -if (xlen == 32) { - require_extension(EXT_ZCF); - require_fp; - MMU.store(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]); -} else { // c.sdsp - require_extension(EXT_ZCA); - MMU.store(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); -} +require_extension(EXT_ZCF); +require_fp; +MMU.store(RVC_SP + insn.rvc_swsp_imm(), RVC_FRS2.v[0]); diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h new file mode 100644 index 0000000000..988ea98e76 --- /dev/null +++ b/riscv/insns/c_ld.h @@ -0,0 +1,2 @@ +require_extension(EXT_ZCA); +WRITE_RVC_RS2S(MMU.load(RVC_RS1S + insn.rvc_ld_imm())); diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h new file mode 100644 index 0000000000..f1960406b4 --- /dev/null +++ b/riscv/insns/c_ldsp.h @@ -0,0 +1,3 @@ +require_extension(EXT_ZCA); +require(insn.rvc_rd() != 0); +WRITE_RD(MMU.load(RVC_SP + insn.rvc_ldsp_imm())); diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h new file mode 100644 index 0000000000..ff8f77d4eb --- /dev/null +++ b/riscv/insns/c_sd.h @@ -0,0 +1,2 @@ +require_extension(EXT_ZCA); +MMU.store(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h new file mode 100644 index 0000000000..f7b8a28cc8 --- /dev/null +++ b/riscv/insns/c_sdsp.h @@ -0,0 +1,2 @@ +require_extension(EXT_ZCA); +MMU.store(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); diff --git a/riscv/overlap_list.h b/riscv/overlap_list.h index 7468e87a41..253be457cc 100644 --- a/riscv/overlap_list.h +++ b/riscv/overlap_list.h @@ -1,3 +1,9 @@ +// these overlap c.ld[sp]/c.sd[sp] +DECLARE_OVERLAP_INSN(c_flw, EXT_ZCF) +DECLARE_OVERLAP_INSN(c_flwsp, EXT_ZCF) +DECLARE_OVERLAP_INSN(c_fsw, EXT_ZCF) +DECLARE_OVERLAP_INSN(c_fswsp, EXT_ZCF) + // these overlap c.fsdsp DECLARE_OVERLAP_INSN(cm_push, EXT_ZCMP) DECLARE_OVERLAP_INSN(cm_pop, EXT_ZCMP) diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 689a198bcd..60723b58e6 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -182,6 +182,8 @@ riscv_insn_ext_c = \ c_jr \ c_li \ c_lui \ + c_ld \ + c_ldsp \ c_lw \ c_lwsp \ c_mv \ @@ -191,6 +193,8 @@ riscv_insn_ext_c = \ c_srli \ c_sub \ c_subw \ + c_sd \ + c_sdsp \ c_sw \ c_swsp \ c_xor \ From 40b660af4d32454e6625cba0147f90a402a1a72c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 10 Jun 2024 18:35:01 -0700 Subject: [PATCH 025/155] Validate contents of overlap list in CI --- riscv/check-opcode-overlap.t.cc | 45 +++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 13 deletions(-) diff --git a/riscv/check-opcode-overlap.t.cc b/riscv/check-opcode-overlap.t.cc index 2922001278..e1a3b06723 100644 --- a/riscv/check-opcode-overlap.t.cc +++ b/riscv/check-opcode-overlap.t.cc @@ -1,6 +1,6 @@ #include "decode.h" #include "common.h" -#include +#include #include #include #include @@ -11,13 +11,9 @@ struct opcode { std::string name; }; -static void check_overlap(const opcode& a, const opcode& b) +static bool overlaps(const opcode& a, const opcode& b) { - if ((a.match & b.mask) == b.match) { - fprintf(stderr, "Instruction %s (%" PRIx64 ") overlaps instruction %s (%" PRIx64 ", mask %" PRIx64 ")\n", - a.name.c_str(), a.match, b.name.c_str(), b.match, b.mask); - exit(-1); - } + return (a.mask & b.mask & (a.match ^ b.match)) == 0; } int main() @@ -34,24 +30,47 @@ int main() #undef DEFINE_INSN }; - std::unordered_set overlap_list; + std::unordered_map overlap_list; #define DECLARE_OVERLAP_INSN(name, ext) \ - overlap_list.insert(std::string(#name)); + overlap_list[std::string(#name)] = false; #include "overlap_list.h" #undef DECLARE_OVERLAP_INSN std::vector list; - for (size_t i = 0; i < sizeof(static_list) / sizeof(static_list[0]); i++) { + for (size_t i = 0; i < std::size(static_list); i++) { if (!overlap_list.count(static_list[i].name)) list.push_back(&static_list[i]); } + bool ok = true; + for (size_t i = 1; i < list.size(); i++) { for (size_t j = 0; j < i; j++) { - check_overlap(*list[i], *list[j]); - check_overlap(*list[j], *list[i]); + if (overlaps(*list[i], *list[j])) { + fprintf(stderr, "Instruction %s (%" PRIx64 ") overlaps instruction %s (%" PRIx64 ", mask %" PRIx64 ")\n", + list[i]->name.c_str(), list[i]->match, list[j]->name.c_str(), list[j]->match, list[j]->mask); + ok = false; + } + } + } + + // make sure nothing in the overlap list is unused + for (size_t i = 1; i < std::size(static_list); i++) { + for (size_t j = 0; j < i; j++) { + if (overlaps(static_list[i], static_list[j])) { + overlap_list[static_list[i].name] = true; + overlap_list[static_list[j].name] = true; + } + } + } + + for (auto const& [name, used] : overlap_list) { + if (!used) { + fprintf(stderr, "Instruction %s overlaps nothing, so overlap list entry has no effect\n", + name.c_str()); + ok = false; } } - return 0; + return ok ? 0 : -1; } From 055624200a34bcc8d4c7acde040466f7d2001637 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 12 Jun 2024 18:39:59 -0700 Subject: [PATCH 026/155] Fix a few compile warnings --- riscv/debug_module.h | 32 ++++++++++++++++---------------- riscv/triggers.cc | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/riscv/debug_module.h b/riscv/debug_module.h index bca29b27a8..377148910d 100644 --- a/riscv/debug_module.h +++ b/riscv/debug_module.h @@ -11,7 +11,7 @@ class simif_t; class bus_t; class processor_t; -typedef struct { +struct debug_module_config_t { // Size of program_buffer in 32-bit words, as exposed to the rest of the // world. unsigned progbufsize = 2; @@ -23,9 +23,9 @@ typedef struct { bool support_abstract_fpr_access = true; bool support_haltgroups = true; bool support_impebreak = true; -} debug_module_config_t; +}; -typedef struct { +struct dmcontrol_t { bool haltreq; bool resumereq; bool hasel; @@ -33,9 +33,9 @@ typedef struct { bool hartreset; bool dmactive; bool ndmreset; -} dmcontrol_t; +}; -typedef struct { +struct dmstatus_t { bool impebreak; bool allhavereset; bool anyhavereset; @@ -53,30 +53,30 @@ typedef struct { bool authbusy; bool cfgstrvalid; unsigned version; -} dmstatus_t; +}; -typedef enum cmderr { +enum cmderr_t { CMDERR_NONE = 0, CMDERR_BUSY = 1, CMDERR_NOTSUP = 2, CMDERR_EXCEPTION = 3, CMDERR_HALTRESUME = 4, CMDERR_OTHER = 7 -} cmderr_t; +}; -typedef struct { +struct abstractcs_t { bool busy; unsigned datacount; unsigned progbufsize; cmderr_t cmderr; -} abstractcs_t; +}; -typedef struct { +struct abstractauto_t { unsigned autoexecprogbuf; unsigned autoexecdata; -} abstractauto_t; +}; -typedef struct { +struct sbcs_t { unsigned version; bool readonaddr; unsigned sbaccess; @@ -90,14 +90,14 @@ typedef struct { bool access16; bool access8; bool sbbusyerror; -} sbcs_t; +}; -typedef struct { +struct hart_debug_state_t { bool halted; bool resumeack; bool havereset; uint8_t haltgroup; -} hart_debug_state_t; +}; class debug_module_t : public abstract_device_t { diff --git a/riscv/triggers.cc b/riscv/triggers.cc index aa258bd202..de3da403dd 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -83,7 +83,7 @@ bool trigger_t::textra_match(processor_t * const proc) const noexcept if (sselect == SSELECT_SCONTEXT) { reg_t mask = (reg_t(1) << ((xlen == 32) ? CSR_TEXTRA32_SVALUE_LENGTH : CSR_TEXTRA64_SVALUE_LENGTH)) - 1; assert(CSR_TEXTRA32_SBYTEMASK_LENGTH < CSR_TEXTRA64_SBYTEMASK_LENGTH); - for (int i = 0; i < CSR_TEXTRA64_SBYTEMASK_LENGTH; i++) + for (unsigned i = 0; i < CSR_TEXTRA64_SBYTEMASK_LENGTH; i++) if (sbytemask & (1 << i)) mask &= ~(reg_t(0xff) << (i * 8)); if ((state->scontext->read() & mask) != (svalue & mask)) From 70d26d64e6ba2da329357a88dc313277fff6c22c Mon Sep 17 00:00:00 2001 From: Christian Herber Date: Mon, 10 Jun 2024 16:48:27 +0200 Subject: [PATCH 027/155] Adding Zilsd and Zcmlsd extensions (Load/store pair for RV32) --- README.md | 2 ++ disasm/disasm.cc | 5 ++++- disasm/isa_parser.cc | 14 ++++++++++++++ riscv/decode_macros.h | 26 ++++++++++++++++++-------- riscv/insns/c_ld.h | 8 +++++++- riscv/insns/c_ldsp.h | 8 +++++++- riscv/insns/c_sd.h | 8 +++++++- riscv/insns/c_sdsp.h | 8 +++++++- riscv/insns/ld.h | 10 ++++++++-- riscv/insns/sd.h | 9 +++++++-- riscv/isa_parser.h | 2 ++ 11 files changed, 83 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index c6f84842f7..51af8bc3c9 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,8 @@ Spike supports the following RISC-V ISA features: - Zvkt extension, v1.0 - Zvkn, Zvknc, Zvkng extension, v1.0 - Zvks, Zvksc, Zvksg extension, v1.0 + - Zilsd extension, v0.9.0 + - Zcmlsd extension, v0.9.0 Versioning and APIs ------------------- diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 7c07ec35c9..5c0e9e0326 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -1391,11 +1391,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) if (isa->get_max_xlen() == 32) { DISASM_INSN("c.jal", c_jal, 0, {&rvc_jump_target}); } else { + DISASM_INSN("c.addiw", c_addiw, 0, {&xrd, &rvc_imm}); + } + + if (isa->get_max_xlen() == 64 || isa->extension_enabled(EXT_ZCMLSD)) { DISASM_INSN("c.ld", c_ld, 0, {&rvc_rs2s, &rvc_ld_address}); DISASM_INSN("c.ldsp", c_ldsp, 0, {&xrd, &rvc_ldsp_address}); DISASM_INSN("c.sd", c_sd, 0, {&rvc_rs2s, &rvc_ld_address}); DISASM_INSN("c.sdsp", c_sdsp, 0, {&rvc_rs2, &rvc_sdsp_address}); - DISASM_INSN("c.addiw", c_addiw, 0, {&xrd, &rvc_imm}); } } diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index ee57a511da..7d3d002718 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -239,6 +239,12 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZICOND] = true; } else if (ext_str == "zihpm") { extension_table[EXT_ZIHPM] = true; + } else if (ext_str == "zilsd") { + if (max_xlen != 32) + bad_isa_string(str, "'Zilsd' requires RV32"); + extension_table[EXT_ZILSD] = true; + } else if (ext_str == "zcmlsd") { + extension_table[EXT_ZCMLSD] = true; } else if (ext_str == "zvbb") { extension_table[EXT_ZVBB] = true; } else if (ext_str == "zvbc") { @@ -324,6 +330,14 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); } + if (extension_table[EXT_ZCMLSD] && extension_table[EXT_ZCF]) { + bad_isa_string(str, "'Zcmlsd' extension conflicts with 'Zcf' extensions"); + } + + if (extension_table[EXT_ZCMLSD] && (!extension_table[EXT_ZCA] || !extension_table[EXT_ZILSD])) { + bad_isa_string(str, "'Zcmlsd' extension requires 'Zca' and 'Zilsd' extensions"); + } + if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) { bad_isa_string(str, "'Zfbfmin' extension requires 'F' extension"); } diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index bd871fa767..7365a866ae 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -42,6 +42,15 @@ }) #define WRITE_VSTATUS STATE.log_reg_write[3] = {0, 0}; +/* the value parameter needs to be evaluated before writing to the registers */ +#define WRITE_REG_PAIR(reg, value) \ + if (reg != 0) { \ + require((reg) % 2 == 0); \ + uint64_t val = (value); \ + WRITE_REG(reg, sext32(val)); \ + WRITE_REG((reg) + 1, (sreg_t(val)) >> 32); \ + } + // RVC macros #define WRITE_RVC_RS1S(value) WRITE_REG(insn.rvc_rs1s(), value) #define WRITE_RVC_RS2S(value) WRITE_REG(insn.rvc_rs2s(), value) @@ -69,13 +78,15 @@ #define RS1_PAIR READ_REG_PAIR(insn.rs1()) #define RS2_PAIR READ_REG_PAIR(insn.rs2()) #define RD_PAIR READ_REG_PAIR(insn.rd()) +#define WRITE_RD_PAIR(value) WRITE_REG_PAIR(insn.rd(), value) -#define WRITE_RD_PAIR(value) \ - if (insn.rd() != 0) { \ - require(insn.rd() % 2 == 0); \ - WRITE_REG(insn.rd(), sext32(value)); \ - WRITE_REG(insn.rd() + 1, (sreg_t(value)) >> 32); \ - } +// Zilsd macros +#define WRITE_RD_D(value) (xlen == 32 ? WRITE_RD_PAIR(value) : WRITE_RD(value)) + +// Zcmlsd macros +#define WRITE_RVC_RS2S_PAIR(value) WRITE_REG_PAIR(insn.rvc_rs2s(), value) +#define RVC_RS2S_PAIR READ_REG_PAIR(insn.rvc_rs2s()) +#define RVC_RS2_PAIR READ_REG_PAIR(insn.rvc_rs2()) // FPU macros #define READ_ZDINX_REG(reg) (xlen == 32 ? f64(READ_REG_PAIR(reg)) : f64(STATE.XPR[reg] & (uint64_t)-1)) @@ -122,8 +133,7 @@ do { \ do { \ if (p->extension_enabled(EXT_ZFINX)) { \ if (xlen == 32) { \ - uint64_t val = (value).v; \ - WRITE_RD_PAIR(val); \ + WRITE_RD_PAIR((value).v); \ } else { \ WRITE_REG(insn.rd(), (value).v); \ } \ diff --git a/riscv/insns/c_ld.h b/riscv/insns/c_ld.h index 988ea98e76..18e0d5ef50 100644 --- a/riscv/insns/c_ld.h +++ b/riscv/insns/c_ld.h @@ -1,2 +1,8 @@ require_extension(EXT_ZCA); -WRITE_RVC_RS2S(MMU.load(RVC_RS1S + insn.rvc_ld_imm())); +require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD)); + +if (xlen == 32) { + WRITE_RVC_RS2S_PAIR(MMU.load(RVC_RS1S + insn.rvc_ld_imm())); +} else { + WRITE_RVC_RS2S(MMU.load(RVC_RS1S + insn.rvc_ld_imm())); +} diff --git a/riscv/insns/c_ldsp.h b/riscv/insns/c_ldsp.h index f1960406b4..d8c8ec8ea2 100644 --- a/riscv/insns/c_ldsp.h +++ b/riscv/insns/c_ldsp.h @@ -1,3 +1,9 @@ require_extension(EXT_ZCA); +require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD)); require(insn.rvc_rd() != 0); -WRITE_RD(MMU.load(RVC_SP + insn.rvc_ldsp_imm())); + +if (xlen == 32) { + WRITE_RD_PAIR(MMU.load(RVC_SP + insn.rvc_ldsp_imm())); +} else { + WRITE_RD(MMU.load(RVC_SP + insn.rvc_ldsp_imm())); +} diff --git a/riscv/insns/c_sd.h b/riscv/insns/c_sd.h index ff8f77d4eb..dba9b0756c 100644 --- a/riscv/insns/c_sd.h +++ b/riscv/insns/c_sd.h @@ -1,2 +1,8 @@ require_extension(EXT_ZCA); -MMU.store(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); +require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD)); + +if (xlen == 32) { + MMU.store(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S_PAIR); +} else { + MMU.store(RVC_RS1S + insn.rvc_ld_imm(), RVC_RS2S); +} diff --git a/riscv/insns/c_sdsp.h b/riscv/insns/c_sdsp.h index f7b8a28cc8..e95aefaa0e 100644 --- a/riscv/insns/c_sdsp.h +++ b/riscv/insns/c_sdsp.h @@ -1,2 +1,8 @@ require_extension(EXT_ZCA); -MMU.store(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); +require((xlen == 64) || p->extension_enabled(EXT_ZCMLSD)); + +if (xlen == 32) { + MMU.store(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2_PAIR); +} else { + MMU.store(RVC_SP + insn.rvc_sdsp_imm(), RVC_RS2); +} diff --git a/riscv/insns/ld.h b/riscv/insns/ld.h index 3dea301e2a..cb0399b722 100644 --- a/riscv/insns/ld.h +++ b/riscv/insns/ld.h @@ -1,2 +1,8 @@ -require_rv64; -WRITE_RD(MMU.load(RS1 + insn.i_imm())); +require((xlen == 64) || p->extension_enabled(EXT_ZILSD)); + +if (xlen == 32) { + WRITE_RD_PAIR(MMU.load(RS1 + insn.i_imm())); +} else { + WRITE_RD(MMU.load(RS1 + insn.i_imm())); +} + diff --git a/riscv/insns/sd.h b/riscv/insns/sd.h index 5c9dd4e1b9..c80f1376ab 100644 --- a/riscv/insns/sd.h +++ b/riscv/insns/sd.h @@ -1,2 +1,7 @@ -require_rv64; -MMU.store(RS1 + insn.s_imm(), RS2); +require((xlen == 64) || p->extension_enabled(EXT_ZILSD)); + +if (xlen == 32) { + MMU.store(RS1 + insn.s_imm(), RS2_PAIR); +} else { + MMU.store(RS1 + insn.s_imm(), RS2); +} diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 65c34fd830..ae9ed946ee 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -23,6 +23,7 @@ typedef enum { EXT_ZCB, EXT_ZCD, EXT_ZCF, + EXT_ZCMLSD, EXT_ZCMP, EXT_ZCMT, EXT_ZKND, @@ -53,6 +54,7 @@ typedef enum { EXT_ZICNTR, EXT_ZICOND, EXT_ZIHPM, + EXT_ZILSD, EXT_ZVBB, EXT_ZVBC, EXT_ZVFBFMIN, From 6c008e990c999dca2f1fff06c5bc96e455f63acd Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 12 Jun 2024 18:06:35 -0700 Subject: [PATCH 028/155] Make softfloat's rounding mode thread-local This has no effect on Spike itself, but it might matter for anyone who's using Spike as a library in a multithreaded program. --- softfloat/softfloat.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index eb78d74de7..72daccb129 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -50,8 +50,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "softfloat_types.h" -#ifndef THREAD_LOCAL -#define THREAD_LOCAL +#if __has_include() +# include +# define THREAD_LOCAL thread_local +#else +# define THREAD_LOCAL _Thread_local #endif #ifdef __cplusplus From 4a884e684cd925d484bdb357942594a9442f32a0 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 14 Jun 2024 18:25:47 -0700 Subject: [PATCH 029/155] Consistently order BF16 routines in Makefile and softfloat.h --- softfloat/softfloat.h | 8 ++++++-- softfloat/softfloat.mk.in | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index 72daccb129..ce6c38ab66 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -157,7 +157,6 @@ uint_fast64_t f16_to_ui64_r_minMag( float16_t, bool ); int_fast32_t f16_to_i32_r_minMag( float16_t, bool ); int_fast64_t f16_to_i64_r_minMag( float16_t, bool ); float32_t f16_to_f32( float16_t ); -float32_t bf16_to_f32( bfloat16_t ); float64_t f16_to_f64( float16_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t f16_to_extF80( float16_t ); @@ -186,6 +185,11 @@ uint_fast16_t f16_classify( float16_t ); float16_t f16_rsqrte7( float16_t ); float16_t f16_recip7( float16_t ); +/*---------------------------------------------------------------------------- +| BFloat16 operations. +*----------------------------------------------------------------------------*/ +float32_t bf16_to_f32( bfloat16_t ); + /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. *----------------------------------------------------------------------------*/ @@ -199,8 +203,8 @@ uint_fast32_t f32_to_ui32_r_minMag( float32_t, bool ); uint_fast64_t f32_to_ui64_r_minMag( float32_t, bool ); int_fast32_t f32_to_i32_r_minMag( float32_t, bool ); int_fast64_t f32_to_i64_r_minMag( float32_t, bool ); -float16_t f32_to_f16( float32_t ); bfloat16_t f32_to_bf16( float32_t ); +float16_t f32_to_f16( float32_t ); float64_t f32_to_f64( float32_t ); #ifdef SOFTFLOAT_FAST_INT64 extFloat80_t f32_to_extF80( float32_t ); diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 9c780ac751..1e8611a356 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -1,6 +1,7 @@ softfloat_subproject_deps = softfloat_c_srcs = \ + bf16_to_f32.c \ f128_add.c \ f128_classify.c \ f128_div.c \ @@ -45,7 +46,6 @@ softfloat_c_srcs = \ f16_sqrt.c \ f16_sub.c \ f16_to_f128.c \ - bf16_to_f32.c \ f16_to_f32.c \ f16_to_f64.c \ f16_to_i8.c \ @@ -76,8 +76,8 @@ softfloat_c_srcs = \ f32_roundToInt.c \ f32_sqrt.c \ f32_sub.c \ - f32_to_f128.c \ f32_to_bf16.c \ + f32_to_f128.c \ f32_to_f16.c \ f32_to_f64.c \ f32_to_i16.c \ From 59b6458a66dba0c592595f2c06204f4e0f369188 Mon Sep 17 00:00:00 2001 From: Chao Du <124672769+Du-Chao@users.noreply.github.com> Date: Tue, 18 Jun 2024 10:43:03 +0800 Subject: [PATCH 030/155] Add a prerequisite for building Otherwise, configure will fail with 'Could not find a version of the Boost::Asio library!' --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 51af8bc3c9..63f29eb8e1 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Build Steps We assume that the RISCV environment variable is set to the RISC-V tools install path. - $ apt-get install device-tree-compiler libboost-regex-dev + $ apt-get install device-tree-compiler libboost-regex-dev libboost-system-dev $ mkdir build $ cd build $ ../configure --prefix=$RISCV From fe47d091e1bd833ec0e1250df1414ace63c19cac Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 18 Jun 2024 17:24:24 -0700 Subject: [PATCH 031/155] Add several BF16 ops to SoftFloat --- softfloat/bf16_add.c | 50 +++++++++++++++++++++++++++++ softfloat/bf16_div.c | 50 +++++++++++++++++++++++++++++ softfloat/bf16_mul.c | 50 +++++++++++++++++++++++++++++ softfloat/bf16_mulAdd.c | 67 +++++++++++++++++++++++++++++++++++++++ softfloat/bf16_sqrt.c | 49 ++++++++++++++++++++++++++++ softfloat/bf16_sub.c | 50 +++++++++++++++++++++++++++++ softfloat/bf16_to_f64.c | 49 ++++++++++++++++++++++++++++ softfloat/f64_to_bf16.c | 54 +++++++++++++++++++++++++++++++ softfloat/softfloat.h | 8 +++++ softfloat/softfloat.mk.in | 8 +++++ 10 files changed, 435 insertions(+) create mode 100644 softfloat/bf16_add.c create mode 100644 softfloat/bf16_div.c create mode 100644 softfloat/bf16_mul.c create mode 100644 softfloat/bf16_mulAdd.c create mode 100644 softfloat/bf16_sqrt.c create mode 100644 softfloat/bf16_sub.c create mode 100644 softfloat/bf16_to_f64.c create mode 100644 softfloat/f64_to_bf16.c diff --git a/softfloat/bf16_add.c b/softfloat/bf16_add.c new file mode 100644 index 0000000000..9314fa8141 --- /dev/null +++ b/softfloat/bf16_add.c @@ -0,0 +1,50 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_add( bfloat16_t a, bfloat16_t b ) +{ + float32_t f32A = { (uint_fast32_t)a.v << 16 }; + float32_t f32B = { (uint_fast32_t)b.v << 16 }; + + return f32_to_bf16 ( f32_add ( f32A, f32B ) ); +} + diff --git a/softfloat/bf16_div.c b/softfloat/bf16_div.c new file mode 100644 index 0000000000..93501b00a8 --- /dev/null +++ b/softfloat/bf16_div.c @@ -0,0 +1,50 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_div( bfloat16_t a, bfloat16_t b ) +{ + float32_t f32A = { (uint_fast32_t)a.v << 16 }; + float32_t f32B = { (uint_fast32_t)b.v << 16 }; + + return f32_to_bf16 ( f32_div ( f32A, f32B ) ); +} + diff --git a/softfloat/bf16_mul.c b/softfloat/bf16_mul.c new file mode 100644 index 0000000000..57030448fa --- /dev/null +++ b/softfloat/bf16_mul.c @@ -0,0 +1,50 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_mul( bfloat16_t a, bfloat16_t b ) +{ + float32_t f32A = { (uint_fast32_t)a.v << 16 }; + float32_t f32B = { (uint_fast32_t)b.v << 16 }; + + return f32_to_bf16 ( f32_mul ( f32A, f32B ) ); +} + diff --git a/softfloat/bf16_mulAdd.c b/softfloat/bf16_mulAdd.c new file mode 100644 index 0000000000..5e67396793 --- /dev/null +++ b/softfloat/bf16_mulAdd.c @@ -0,0 +1,67 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014 The Regents of the University of California. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_mulAdd( bfloat16_t a, bfloat16_t b, bfloat16_t c ) +{ + uint_fast8_t roundingMode = softfloat_roundingMode; + + float64_t f64A = bf16_to_f64( a ); + float64_t f64B = bf16_to_f64( b ); + float64_t f64C = bf16_to_f64( c ); + + float64_t prod = f64_mul( f64A, f64B ); + + softfloat_roundingMode = softfloat_round_odd; + + float64_t sum = f64_add( prod, f64C ); + + softfloat_roundingMode = roundingMode; + + /* When rounding down, return -0 instead of +0 when product's sign + * differs from C's sign. */ + if ( softfloat_roundingMode == softfloat_round_min + && sum.v == 0 + && ( ( prod.v ^ f64C.v ) & 0x8000000000000000U ) != 0 ) + return (bfloat16_t) { 0x8000 }; + + return f64_to_bf16( sum ); +} + diff --git a/softfloat/bf16_sqrt.c b/softfloat/bf16_sqrt.c new file mode 100644 index 0000000000..9d4f2ebe79 --- /dev/null +++ b/softfloat/bf16_sqrt.c @@ -0,0 +1,49 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_sqrt( bfloat16_t a ) +{ + float32_t f32A = { (uint_fast32_t)a.v << 16 }; + + return f32_to_bf16 ( f32_sqrt ( f32A ) ); +} + diff --git a/softfloat/bf16_sub.c b/softfloat/bf16_sub.c new file mode 100644 index 0000000000..762d854a8e --- /dev/null +++ b/softfloat/bf16_sub.c @@ -0,0 +1,50 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "softfloat.h" + +bfloat16_t bf16_sub( bfloat16_t a, bfloat16_t b ) +{ + float32_t f32A = { (uint_fast32_t)a.v << 16 }; + float32_t f32B = { (uint_fast32_t)b.v << 16 }; + + return f32_to_bf16 ( f32_sub ( f32A, f32B ) ); +} + diff --git a/softfloat/bf16_to_f64.c b/softfloat/bf16_to_f64.c new file mode 100644 index 0000000000..9b46781c85 --- /dev/null +++ b/softfloat/bf16_to_f64.c @@ -0,0 +1,49 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015, 2016, 2017 The Regents of the +University of California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +float64_t bf16_to_f64( bfloat16_t a ) +{ + float32_t f32A = (float32_t) { (uint_fast32_t)a.v << 16 }; + + return f32_to_f64( f32A ); +} diff --git a/softfloat/f64_to_bf16.c b/softfloat/f64_to_bf16.c new file mode 100644 index 0000000000..a3209795d2 --- /dev/null +++ b/softfloat/f64_to_bf16.c @@ -0,0 +1,54 @@ + +/*============================================================================ + +This C source file is part of the SoftFloat IEEE Floating-Point Arithmetic +Package, Release 3d, by John R. Hauser. + +Copyright 2011, 2012, 2013, 2014, 2015 The Regents of the University of +California. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, + this list of conditions, and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions, and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the University nor the names of its contributors may + be used to endorse or promote products derived from this software without + specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS "AS IS", AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ARE +DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=============================================================================*/ + +#include +#include +#include "platform.h" +#include "internals.h" +#include "specialize.h" +#include "softfloat.h" + +bfloat16_t f64_to_bf16( float64_t a ) +{ + uint_fast8_t roundingMode = softfloat_roundingMode; + softfloat_roundingMode = softfloat_round_odd; + + float32_t f32A = f64_to_f32( a ); + + softfloat_roundingMode = roundingMode; + + return f32_to_bf16( f32A ); +} diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index ce6c38ab66..09d723577a 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -189,6 +189,13 @@ float16_t f16_recip7( float16_t ); | BFloat16 operations. *----------------------------------------------------------------------------*/ float32_t bf16_to_f32( bfloat16_t ); +float64_t bf16_to_f64( bfloat16_t ); +bfloat16_t bf16_add( bfloat16_t, bfloat16_t ); +bfloat16_t bf16_sub( bfloat16_t, bfloat16_t ); +bfloat16_t bf16_mul( bfloat16_t, bfloat16_t ); +bfloat16_t bf16_mulAdd( bfloat16_t, bfloat16_t, bfloat16_t ); +bfloat16_t bf16_div( bfloat16_t, bfloat16_t ); +bfloat16_t bf16_sqrt( bfloat16_t ); /*---------------------------------------------------------------------------- | 32-bit (single-precision) floating-point operations. @@ -244,6 +251,7 @@ uint_fast32_t f64_to_ui32_r_minMag( float64_t, bool ); uint_fast64_t f64_to_ui64_r_minMag( float64_t, bool ); int_fast32_t f64_to_i32_r_minMag( float64_t, bool ); int_fast64_t f64_to_i64_r_minMag( float64_t, bool ); +bfloat16_t f64_to_bf16( float64_t ); float16_t f64_to_f16( float64_t ); float32_t f64_to_f32( float64_t ); #ifdef SOFTFLOAT_FAST_INT64 diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 1e8611a356..626b611695 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -1,7 +1,14 @@ softfloat_subproject_deps = softfloat_c_srcs = \ + bf16_add.c \ + bf16_div.c \ + bf16_mul.c \ + bf16_mulAdd.c \ + bf16_sqrt.c \ + bf16_sub.c \ bf16_to_f32.c \ + bf16_to_f64.c \ f128_add.c \ f128_classify.c \ f128_div.c \ @@ -106,6 +113,7 @@ softfloat_c_srcs = \ f64_roundToInt.c \ f64_sqrt.c \ f64_sub.c \ + f64_to_bf16.c \ f64_to_f128.c \ f64_to_f16.c \ f64_to_f32.c \ From c6cb05ceb7951d48cc4a94b7b5b25bff82581d56 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 20 Jun 2024 16:40:33 -0700 Subject: [PATCH 032/155] In isa_parser, move extensionology code before error-checking code Resolves #1696 --- disasm/isa_parser.cc | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 7d3d002718..7c607d77a9 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -330,26 +330,6 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) bad_isa_string(str, ("can't parse: " + std::string(p)).c_str()); } - if (extension_table[EXT_ZCMLSD] && extension_table[EXT_ZCF]) { - bad_isa_string(str, "'Zcmlsd' extension conflicts with 'Zcf' extensions"); - } - - if (extension_table[EXT_ZCMLSD] && (!extension_table[EXT_ZCA] || !extension_table[EXT_ZILSD])) { - bad_isa_string(str, "'Zcmlsd' extension requires 'Zca' and 'Zilsd' extensions"); - } - - if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) { - bad_isa_string(str, "'Zfbfmin' extension requires 'F' extension"); - } - - if ((extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZVFBFWMA]) && !extension_table['V']) { - bad_isa_string(str, "'Zvfbfmin/Zvfbfwma' extension requires 'V' extension"); - } - - if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZFHMIN]) { - extension_table[EXT_INTERNAL_ZFH_MOVE] = true; - } - if (extension_table['A']) { extension_table[EXT_ZAAMO] = true; extension_table[EXT_ZALRSC] = true; @@ -373,6 +353,26 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZCD] = true; } + if (extension_table[EXT_ZCMLSD] && extension_table[EXT_ZCF]) { + bad_isa_string(str, "'Zcmlsd' extension conflicts with 'Zcf' extensions"); + } + + if (extension_table[EXT_ZCMLSD] && (!extension_table[EXT_ZCA] || !extension_table[EXT_ZILSD])) { + bad_isa_string(str, "'Zcmlsd' extension requires 'Zca' and 'Zilsd' extensions"); + } + + if (extension_table[EXT_ZFBFMIN] && !extension_table['F']) { + bad_isa_string(str, "'Zfbfmin' extension requires 'F' extension"); + } + + if ((extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZVFBFWMA]) && !extension_table['V']) { + bad_isa_string(str, "'Zvfbfmin/Zvfbfwma' extension requires 'V' extension"); + } + + if (extension_table[EXT_ZFBFMIN] || extension_table[EXT_ZVFBFMIN] || extension_table[EXT_ZFHMIN]) { + extension_table[EXT_INTERNAL_ZFH_MOVE] = true; + } + if (extension_table[EXT_ZFINX] && extension_table['F']) { bad_isa_string(str, ("Zfinx/Zdinx/Zhinx{min} extensions conflict with 'F/D/Q/Zfh{min}' extensions")); } From 0408e797b139dbc1aaa52cb33dea047ad8d230ad Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:15:12 -0700 Subject: [PATCH 033/155] Add isa_parser parsing for zvl/zve --- disasm/isa_parser.cc | 37 ++++++++++++++++++++++++++++++++++++- riscv/isa_parser.h | 4 ++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 7c607d77a9..f1ba9f3914 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -38,6 +38,11 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) else bad_isa_string(str, "ISA strings must begin with RV32 or RV64"); + vlen = 0; + elen = 0; + zvf = false; + zvd = false; + switch (isa_string[4]) { case 'g': // G = IMAFD_Zicsr_Zifencei, but Spike includes the latter two @@ -70,7 +75,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) } switch (*p) { - case 'v': // even rv32iv implies double float + case 'v': vlen = 128; elen = 64; zvf = true; zvd = true; + // even rv32iv implies double float case 'q': extension_table['D'] = true; // Fall through case 'd': extension_table['F'] = true; @@ -314,6 +320,35 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZICFILP] = true; } else if (ext_str == "zicfiss") { extension_table[EXT_ZICFISS] = true; + } else if (ext_str.substr(0, 3) == "zvl") { + reg_t new_vlen; + try { + new_vlen = std::stol(ext_str.substr(3, ext_str.size() - 4)); + } catch (std::logic_error& e) { + new_vlen = 0; + } + if ((new_vlen & (new_vlen - 1)) != 0 || new_vlen < 32) + bad_isa_string(str, ("Invalid Zvl string: " + ext_str).c_str()); + vlen = std::max(vlen, new_vlen); + } else if (ext_str.substr(0, 3) == "zve") { + reg_t new_elen; + try { + new_elen = std::stol(ext_str.substr(3, ext_str.size() - 4)); + } catch (std::logic_error& e) { + new_elen = 0; + } + if (ext_str.substr(5) == "d") { + zvd |= true; zvf |= true; + } else if (ext_str.substr(5) == "f") { + zvf |= true; + } else if (ext_str.substr(5) == "x") { + /* do nothing */ + } else { + new_elen = 0; + } + if (new_elen != 32 && new_elen != 64) + bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str()); + elen = std::max(elen, new_elen); } else if (ext_str[0] == 'x') { extension_table['X'] = true; if (ext_str.size() == 1) { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index ae9ed946ee..8aee29363c 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -116,6 +116,10 @@ class isa_parser_t { protected: unsigned max_xlen; reg_t max_isa; + reg_t vlen; + reg_t elen; + bool zvf; + bool zvd; std::bitset extension_table; std::string isa_string; std::set extensions; From ede537120b87ebb7ab174a34a79f0287bb50adab Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:15:48 -0700 Subject: [PATCH 034/155] Add Zvl/Zve validation to isa_parser --- disasm/isa_parser.cc | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index f1ba9f3914..c35e449d69 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -459,6 +459,27 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) "extensions are incompatible with WORDS_BIGENDIAN setups."); } #endif + + if ((vlen != 0) ^ (elen != 0)) { + bad_isa_string(str, "Invalid Zvl/Zve configuration"); + } + + if (extension_table[EXT_ZVFHMIN] && (vlen == 0 || elen == 0 || !zvf)) { + bad_isa_string(str, "'Zvfhmin' extension requires Zve32f"); + } + + if (extension_table[EXT_ZVFH] && (vlen == 0 || elen == 0 || !zvf || !extension_table[EXT_ZVFHMIN])) { + bad_isa_string(str, "'Zvfh' extension requires Zve32f and 'Zvfhmin'"); + } + + if (zvd && !extension_table['D'] && elen < 64) { + bad_isa_string(str, "'ZveXXd' extension requires D"); + } + + if (zvf && !extension_table['F']) { + bad_isa_string(str, "'ZveXXf' extension requires F"); + } + std::string lowercase = strtolower(priv); bool user = false, supervisor = false; From a3a626b924ded1a0535334a65464f5ee3580d0a2 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:16:48 -0700 Subject: [PATCH 035/155] Add accessors to isa_parser's VLEN/ELEN --- riscv/isa_parser.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 8aee29363c..82c469a264 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -102,12 +102,15 @@ class isa_parser_t { unsigned get_max_xlen() const { return max_xlen; } reg_t get_max_isa() const { return max_isa; } std::string get_isa_string() const { return isa_string; } + reg_t get_vlen() const { return vlen; } + reg_t get_elen() const { return elen; } bool extension_enabled(unsigned char ext) const { return extension_enabled(isa_extension_t(ext)); } bool extension_enabled(isa_extension_t ext) const { return extension_table[ext]; } + bool has_any_vector() const { return vlen > 0; } std::bitset get_extension_table() const { return extension_table; } From 24d5693930b1e5657971941a64cb3bd9165e76d4 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:18:46 -0700 Subject: [PATCH 036/155] Relax has_fs dependency on misa.v isa_parser should already require any Zvef or Zved extensions imply F/D --- riscv/csrs.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 8d7737f195..ad5ae08802 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -411,8 +411,7 @@ base_status_csr_t::base_status_csr_t(processor_t* const proc, const reg_t addr): reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { // If a configuration has FS bits, they will always be accessible no // matter the state of misa. - const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F') - || proc->extension_enabled('V')) && !proc->extension_enabled(EXT_ZFINX); + const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F')) && !proc->extension_enabled(EXT_ZFINX); const bool has_vs = proc->extension_enabled('V'); return 0 | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0) From 9925435513d001027dc6fea1584fefd5b9bfb249 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:20:46 -0700 Subject: [PATCH 037/155] Allow disassembly from implementations that are not full V --- disasm/disasm.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 5c0e9e0326..343fff7201 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -1455,7 +1455,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_INSN("cm.jalt", cm_jalt, 0, {&rvcm_jt_index}); } - if (isa->extension_enabled('V')) { + if (isa->has_any_vector()) { DISASM_INSN("vsetivli", vsetivli, 0, {&xrd, &zimm5, &v_vtype}); DISASM_INSN("vsetvli", vsetvli, 0, {&xrd, &xrs1, &v_vtype}); DEFINE_RTYPE(vsetvl); From 457ea8c0cdf5fd4a3bd04e0b9ea6d3b863d56841 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:21:30 -0700 Subject: [PATCH 038/155] Relax zvfh/zvfhmin dependency on V, they only actually depend on Zve --- disasm/isa_parser.cc | 3 --- 1 file changed, 3 deletions(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index c35e449d69..a22e8d62f6 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -101,9 +101,6 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) if (ext_str == "zfh") extension_table[EXT_ZFH] = true; } else if (ext_str == "zvfh" || ext_str == "zvfhmin") { - if (!extension_table['V']) - bad_isa_string(str, ("'" + ext_str + "' extension requires 'V'").c_str()); - extension_table[EXT_ZVFHMIN] = true; if (ext_str == "zvfh") { From a484f6efc5f50836bb8d846180dfbb9786d09ae2 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:22:10 -0700 Subject: [PATCH 039/155] Relax vector_csr dependency on 'V' --- riscv/csrs.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index ad5ae08802..e985db3065 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1428,8 +1428,6 @@ vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_ void vector_csr_t::verify_permissions(insn_t insn, bool write) const { require_vector_vs; - if (!proc->extension_enabled('V')) - throw trap_illegal_instruction(insn.bits()); basic_csr_t::verify_permissions(insn, write); } @@ -1451,8 +1449,6 @@ vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr): void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const { require_vector_vs; - if (!proc->extension_enabled('V')) - throw trap_illegal_instruction(insn.bits()); masked_csr_t::verify_permissions(insn, write); } From 08d5119d3b58463c9951e625663369742808de9c Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:23:01 -0700 Subject: [PATCH 040/155] Relax mstatus.vs dependency on full V --- riscv/csrs.cc | 3 ++- riscv/processor.h | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index e985db3065..02a2c4fec6 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -412,7 +412,8 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { // If a configuration has FS bits, they will always be accessible no // matter the state of misa. const bool has_fs = (proc->extension_enabled('S') || proc->extension_enabled('F')) && !proc->extension_enabled(EXT_ZFINX); - const bool has_vs = proc->extension_enabled('V'); + // Implementations w/o V may still have mstatus.vs, + const bool has_vs = proc->any_vector_extensions(); return 0 | (proc->extension_enabled('S') ? (SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_SPP) : 0) | (has_page ? (SSTATUS_SUM | SSTATUS_MXR) : 0) diff --git a/riscv/processor.h b/riscv/processor.h index 9b776e292c..1f11393833 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -273,6 +273,9 @@ class processor_t : public abstract_device_t bool any_custom_extensions() const { return !custom_extensions.empty(); } + bool any_vector_extensions() const { + return VU.VLEN > 0; + } bool extension_enabled(unsigned char ext) const { return extension_enabled(isa_extension_t(ext)); } From 9ee100f580178c315c2d48cd712feda47a755248 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:23:59 -0700 Subject: [PATCH 041/155] Relax require_vector check for misa.V --- riscv/decode_macros.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 7365a866ae..675634a65e 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -171,7 +171,6 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_vector(alu) \ do { \ require_vector_vs; \ - require_extension('V'); \ require(!P.VU.vill); \ if (alu && !P.VU.vstart_alu) \ require(P.VU.vstart->read() == 0); \ @@ -181,7 +180,6 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_vector_novtype(is_log) \ do { \ require_vector_vs; \ - require_extension('V'); \ if (is_log) \ WRITE_VSTATUS; \ dirty_vs_state; \ From 9f5df7f4dbef18c8c22d5e9a8bfca48fc50cfdc6 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:24:51 -0700 Subject: [PATCH 042/155] Disallow any vector, not just V, when no __int128 type is present --- riscv/processor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index a81306801c..43f5627572 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -44,7 +44,7 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, TM.proc = this; #ifndef HAVE_INT128 - if (isa->extension_enabled('V')) { + if (isa->has_any_vector()) { fprintf(stderr, "V extension is not supported on platforms without __int128 type\n"); abort(); } From 0f4642ee44ba026bed7bc6f8b0d738de8cc9d948 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:25:15 -0700 Subject: [PATCH 043/155] Switch to Zvl/Zve parsing from isa_parser, instead of varch --- riscv/processor.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 43f5627572..516618d412 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -55,7 +55,10 @@ processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, } #endif - parse_varch_string(cfg->varch); + VU.VLEN = isa->get_vlen(); + VU.ELEN = isa->get_elen(); + VU.vlenb = isa->get_vlen() / 8; + VU.vstart_alu = 0; register_base_instructions(); mmu = new mmu_t(sim, cfg->endianness, this); From 3b6a8fa06ec04bee5634a52b01a4df0d5a91f826 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:30:19 -0700 Subject: [PATCH 044/155] Remove all --varch parsing --- .github/workflows/debug-smoke.yml | 2 +- config.h.in | 3 -- configure | 17 --------- riscv/cfg.cc | 1 - riscv/cfg.h | 1 - riscv/processor.cc | 61 ------------------------------- riscv/processor.h | 1 - riscv/riscv.ac | 6 --- spike_main/spike.cc | 2 - 9 files changed, 1 insertion(+), 93 deletions(-) diff --git a/.github/workflows/debug-smoke.yml b/.github/workflows/debug-smoke.yml index 090e4d97c4..6ecc5fba09 100644 --- a/.github/workflows/debug-smoke.yml +++ b/.github/workflows/debug-smoke.yml @@ -47,7 +47,7 @@ jobs: run: | git clone --recurse-submodules https://github.com/riscv-software-src/riscv-tests.git cd riscv-tests - git checkout bd0a19c136927eaa3b7296a591a896c141affb6b + git checkout 00ab5f0dd4cf56b5a0551bc5adedf60c765d0c66 - name: Run Tests run: | diff --git a/config.h.in b/config.h.in index 95514fddbc..aef35963c8 100644 --- a/config.h.in +++ b/config.h.in @@ -12,9 +12,6 @@ /* Default value for --priv switch */ #undef DEFAULT_PRIV -/* Default value for --varch switch */ -#undef DEFAULT_VARCH - /* Define if subproject MCPPBS_SPROJ_NORM is enabled */ #undef DISASM_ENABLED diff --git a/configure b/configure index 8095688d7b..4ad998a654 100755 --- a/configure +++ b/configure @@ -739,7 +739,6 @@ with_boost_asio with_boost_regex with_isa with_priv -with_varch with_target enable_dual_endian ' @@ -1407,8 +1406,6 @@ Optional Packages: --with-isa=RV64IMAFDC_zicntr_zihpm Sets the default RISC-V ISA --with-priv=MSU Sets the default RISC-V privilege modes supported - --with-varch=vlen:128,elen:64 - Sets the default vector config --with-target=riscv64-unknown-elf Sets the default target config @@ -6593,20 +6590,6 @@ fi -# Check whether --with-varch was given. -if test ${with_varch+y} -then : - withval=$with_varch; -printf "%s\n" "#define DEFAULT_VARCH \"$withval\"" >>confdefs.h - -else $as_nop - -printf "%s\n" "#define DEFAULT_VARCH \"vlen:128,elen:64\"" >>confdefs.h - -fi - - - # Check whether --with-target was given. if test ${with_target+y} then : diff --git a/riscv/cfg.cc b/riscv/cfg.cc index d105eb5e0d..67dfdb4c5d 100644 --- a/riscv/cfg.cc +++ b/riscv/cfg.cc @@ -35,7 +35,6 @@ cfg_t::cfg_t() bootargs = nullptr; isa = DEFAULT_ISA; priv = DEFAULT_PRIV; - varch = DEFAULT_VARCH; misaligned = false; endianness = endianness_little; pmpregions = 16; diff --git a/riscv/cfg.h b/riscv/cfg.h index 63465e644a..c972f031d2 100644 --- a/riscv/cfg.h +++ b/riscv/cfg.h @@ -67,7 +67,6 @@ class cfg_t const char * bootargs; const char * isa; const char * priv; - const char * varch; bool misaligned; endianness_t endianness; reg_t pmpregions; diff --git a/riscv/processor.cc b/riscv/processor.cc index 516618d412..9498b8fe77 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -105,11 +105,6 @@ static void bad_option_string(const char *option, const char *value, abort(); } -static void bad_varch_string(const char* varch, const char *msg) -{ - bad_option_string("--varch", varch, msg); -} - static std::string get_string_token(std::string str, const char delimiter, size_t& pos) { size_t _pos = pos; @@ -117,17 +112,6 @@ static std::string get_string_token(std::string str, const char delimiter, size_ return str.substr(_pos, pos - _pos); } -static int get_int_token(std::string str, const char delimiter, size_t& pos) -{ - size_t _pos = pos; - while (pos < str.length() && str[pos] != delimiter) { - if (!isdigit(str[pos])) - bad_varch_string(str.c_str(), "Unsupported value"); // An integer is expected - ++pos; - } - return (pos == _pos) ? 0 : stoi(str.substr(_pos, pos - _pos)); -} - static bool check_pow2(int val) { return ((val & (val - 1))) == 0; @@ -141,51 +125,6 @@ static std::string strtolower(const char* str) return res; } -void processor_t::parse_varch_string(const char* s) -{ - std::string str = strtolower(s); - size_t pos = 0; - size_t len = str.length(); - int vlen = 0; - int elen = 0; - int vstart_alu = 0; - - while (pos < len) { - std::string attr = get_string_token(str, ':', pos); - - ++pos; - - if (attr == "vlen") - vlen = get_int_token(str, ',', pos); - else if (attr == "elen") - elen = get_int_token(str, ',', pos); - else if (attr == "vstartalu") - vstart_alu = get_int_token(str, ',', pos); - else - bad_varch_string(s, "Unsupported token"); - - ++pos; - } - - // The integer should be the power of 2 - if (!check_pow2(vlen) || !check_pow2(elen)) { - bad_varch_string(s, "The integer value should be the power of 2"); - } - - /* Vector spec requirements. */ - if (vlen < elen) - bad_varch_string(s, "vlen must be >= elen"); - - /* spike requirements. */ - if (vlen > 4096) - bad_varch_string(s, "vlen must be <= 4096"); - - VU.VLEN = vlen; - VU.ELEN = elen; - VU.vlenb = vlen / 8; - VU.vstart_alu = vstart_alu; -} - static int xlen_to_uxl(int xlen) { if (xlen == 32) diff --git a/riscv/processor.h b/riscv/processor.h index 1f11393833..14b828cfef 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -410,7 +410,6 @@ class processor_t : public abstract_device_t friend class plic_t; friend class extension_t; - void parse_varch_string(const char*); void parse_priv_string(const char*); void build_opcode_map(); void register_base_instructions(); diff --git a/riscv/riscv.ac b/riscv/riscv.ac index 5785f27914..378fd10f9c 100644 --- a/riscv/riscv.ac +++ b/riscv/riscv.ac @@ -20,12 +20,6 @@ AC_ARG_WITH(priv, AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "$withval", [Default value for --priv switch]), AC_DEFINE_UNQUOTED([DEFAULT_PRIV], "MSU", [Default value for --priv switch])) -AC_ARG_WITH(varch, - [AS_HELP_STRING([--with-varch=vlen:128,elen:64], - [Sets the default vector config])], - AC_DEFINE_UNQUOTED([DEFAULT_VARCH], "$withval", [Default value for --varch switch]), - AC_DEFINE([DEFAULT_VARCH], ["vlen:128,elen:64"], [Default value for --varch switch])) - AC_ARG_WITH(target, [AS_HELP_STRING([--with-target=riscv64-unknown-elf], [Sets the default target config])], diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 6596bc1a58..1a298f2d5c 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -45,7 +45,6 @@ static void help(int exit_code = 1) fprintf(stderr, " --pmpregions= Number of PMP regions [default 16]\n"); fprintf(stderr, " --pmpgranularity= PMP Granularity in bytes [default 4]\n"); fprintf(stderr, " --priv= RISC-V privilege modes supported [default %s]\n", DEFAULT_PRIV); - fprintf(stderr, " --varch= RISC-V Vector uArch string [default %s]\n", DEFAULT_VARCH); fprintf(stderr, " --pc=
Override ELF entry point\n"); fprintf(stderr, " --hartids= Explicitly specify hartids, default is 0,1,...\n"); fprintf(stderr, " --ic=:: Instantiate a cache model with S sets,\n"); @@ -404,7 +403,6 @@ int main(int argc, char** argv) parser.option(0, "pmpregions", 1, [&](const char* s){cfg.pmpregions = atoul_safe(s);}); parser.option(0, "pmpgranularity", 1, [&](const char* s){cfg.pmpgranularity = atoul_safe(s);}); parser.option(0, "priv", 1, [&](const char* s){cfg.priv = s;}); - parser.option(0, "varch", 1, [&](const char* s){cfg.varch = s;}); parser.option(0, "device", 1, device_parser); parser.option(0, "extension", 1, [&](const char* s){extensions.push_back(find_extension(s));}); parser.option(0, "dump-dts", 0, [&](const char UNUSED *s){dump_dts = true;}); From 67e205c289becb42b4e8495b46385688c1c167f7 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:30:33 -0700 Subject: [PATCH 045/155] Restrict spike to vlen <= 4096 --- disasm/isa_parser.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index a22e8d62f6..cba5516c67 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -457,6 +457,10 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) } #endif + if (vlen > 4096) { + bad_isa_string(str, "Spike does not currently support VLEN > 4096b"); + } + if ((vlen != 0) ^ (elen != 0)) { bad_isa_string(str, "Invalid Zvl/Zve configuration"); } From c790f73ae94d358e9493187fdbcc9053ed7af7d8 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 20 Jun 2024 14:53:33 -0700 Subject: [PATCH 046/155] Vector-fp instructions depend on zve, not F/D --- riscv/isa_parser.h | 2 ++ riscv/v_ext_macros.h | 20 ++++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 82c469a264..afb49f2959 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -104,6 +104,8 @@ class isa_parser_t { std::string get_isa_string() const { return isa_string; } reg_t get_vlen() const { return vlen; } reg_t get_elen() const { return elen; } + bool get_zvf() const { return zvf; } + bool get_zvd() const { return zvd; } bool extension_enabled(unsigned char ext) const { return extension_enabled(isa_extension_t(ext)); } diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h index a95af3eac0..3e8a653863 100644 --- a/riscv/v_ext_macros.h +++ b/riscv/v_ext_macros.h @@ -1449,8 +1449,8 @@ reg_t index[P.VU.vlmax]; \ #define VI_VFP_COMMON \ require_fp; \ require((P.VU.vsew == e16 && p->extension_enabled(EXT_ZVFH)) || \ - (P.VU.vsew == e32 && p->extension_enabled('F')) || \ - (P.VU.vsew == e64 && p->extension_enabled('D'))); \ + (P.VU.vsew == e32 && p->get_isa().get_zvf()) || \ + (P.VU.vsew == e64 && p->get_isa().get_zvd())); \ require_vector(true); \ require(STATE.frm->read() < 0x5); \ reg_t UNUSED vl = P.VU.vl->read(); \ @@ -1662,8 +1662,8 @@ reg_t index[P.VU.vlmax]; \ #define VI_VFP_VV_LOOP_WIDE_REDUCTION(BODY16, BODY32) \ VI_CHECK_REDUCTION(true) \ VI_VFP_COMMON \ - require((P.VU.vsew == e16 && p->extension_enabled('F')) || \ - (P.VU.vsew == e32 && p->extension_enabled('D'))); \ + require((P.VU.vsew == e16 && p->get_isa().get_zvf()) || \ + (P.VU.vsew == e32 && p->get_isa().get_zvd())); \ bool is_active = false; \ switch (P.VU.vsew) { \ case e16: { \ @@ -1948,17 +1948,17 @@ reg_t index[P.VU.vlmax]; \ switch (P.VU.vsew) { \ case e16: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(16, 16, sign), \ - { p->extension_enabled(EXT_ZVFH); }, \ + { require(p->extension_enabled(EXT_ZVFH)); }, \ BODY16); } \ break; \ case e32: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(32, 32, sign), \ - { p->extension_enabled('F'); }, \ + { require(p->get_isa().get_zvf()); }, \ BODY32); } \ break; \ case e64: \ { VI_VFP_CVT_LOOP(CVT_INT_TO_FP_PARAMS(64, 64, sign), \ - { p->extension_enabled('D'); }, \ + { require(p->get_isa().get_zvd()); }, \ BODY64); } \ break; \ default: \ @@ -1972,17 +1972,17 @@ reg_t index[P.VU.vlmax]; \ switch (P.VU.vsew) { \ case e16: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(16, 16, sign), \ - { p->extension_enabled(EXT_ZVFH); }, \ + { require(p->extension_enabled(EXT_ZVFH)); }, \ BODY16); } \ break; \ case e32: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(32, 32, sign), \ - { p->extension_enabled('F'); }, \ + { require(p->get_isa().get_zvf()); }, \ BODY32); } \ break; \ case e64: \ { VI_VFP_CVT_LOOP(CVT_FP_TO_INT_PARAMS(64, 64, sign), \ - { p->extension_enabled('D'); }, \ + { require(p->get_isa().get_zvd()); }, \ BODY64); } \ break; \ default: \ From 29da1405c43ff6f2b6c4f7f8ea41ec59810a4e55 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 21 Jun 2024 16:34:25 -0700 Subject: [PATCH 047/155] Fix C/C++ thread-local linkage differently Just admit Mac OS is broken, so explicitly special-case it. See #1689 and #1703 --- softfloat/softfloat.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/softfloat/softfloat.h b/softfloat/softfloat.h index 72daccb129..8f533c86d8 100644 --- a/softfloat/softfloat.h +++ b/softfloat/softfloat.h @@ -50,8 +50,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include "softfloat_types.h" -#if __has_include() -# include +#if defined(__cplusplus) && !defined(__APPLE__) # define THREAD_LOCAL thread_local #else # define THREAD_LOCAL _Thread_local From ef7416ce1d3e4511fe7fd6f4568edbbee25a0830 Mon Sep 17 00:00:00 2001 From: Rafael Sene Date: Sat, 22 Jun 2024 11:26:41 -0300 Subject: [PATCH 048/155] Fix: Add missing header for std::logic_error - Included in isa_parser.cc to resolve compilation error due to missing type 'std::logic_error'. Signed-off-by: Rafael Sene --- disasm/isa_parser.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index cba5516c67..e37b72f3ad 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -1,4 +1,5 @@ #include "isa_parser.h" +#include static std::string strtolower(const char* str) { From 7f93baf4636fd6c80910970fdf4f8632465c1ace Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Wed, 26 Jun 2024 16:30:07 -0700 Subject: [PATCH 049/155] Fix riscv-tests commit for CI * https://github.com/riscv-software-src/riscv-tests/pull/567 was merged by squash accidentally, so the reference commit was lost --- .github/workflows/debug-smoke.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/debug-smoke.yml b/.github/workflows/debug-smoke.yml index 6ecc5fba09..7d6cc0036a 100644 --- a/.github/workflows/debug-smoke.yml +++ b/.github/workflows/debug-smoke.yml @@ -47,7 +47,7 @@ jobs: run: | git clone --recurse-submodules https://github.com/riscv-software-src/riscv-tests.git cd riscv-tests - git checkout 00ab5f0dd4cf56b5a0551bc5adedf60c765d0c66 + git checkout e06a435c1e545def71e833031356372f0828f165 - name: Run Tests run: | From 389851ce15f35b71b6f73b818ff046cf248f692e Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Jun 2024 18:10:13 -0700 Subject: [PATCH 050/155] Add disassembly for Zfa extension --- disasm/disasm.cc | 103 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 343fff7201..7deb932a59 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -193,6 +193,47 @@ struct : public arg_t { } } v_zimm6; +struct : public arg_t { + std::string to_string(insn_t insn) const { + static const char* table[32] = { + "-1.0", + "min", + "1.52587890625e-05", + "3.0517578125e-05", + "0.00390625", + "0.0078125", + "0.0625", + "0.125", + "0.25", + "0.3125", + "0.375", + "0.4375", + "0.5", + "0.625", + "0.75", + "0.875", + "1.0", + "1.25", + "1.5", + "1.75", + "2.0", + "2.5", + "3.0", + "4.0", + "8.0", + "16.0", + "128.0", + "256.0", + "32768.0", + "65536.0", + "inf", + "nan" + }; + + return table[insn.rs1()]; + } +} fli_imm; + struct : public arg_t { std::string to_string(insn_t insn) const { int32_t target = insn.sb_imm(); @@ -644,11 +685,21 @@ static void NOINLINE add_xftype_insn(disassembler_t* d, const char* name, uint32 d->add_insn(new disasm_insn_t(name, match, mask, {&frd, &xrs1})); } +static void NOINLINE add_xf2type_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) +{ + d->add_insn(new disasm_insn_t(name, match, mask, {&frd, &xrs1, &xrs2})); +} + static void NOINLINE add_fx2type_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) { d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &frs1, &frs2})); } +static void NOINLINE add_flitype_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) +{ + d->add_insn(new disasm_insn_t(name, match, mask, {&xrd, &fli_imm})); +} + static void NOINLINE add_sfence_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) { d->add_insn(new disasm_insn_t(name, match, mask, {&xrs1, &xrs2})); @@ -794,7 +845,9 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) #define DEFINE_FR3TYPE(code) add_fr3type_insn(this, #code, match_##code, mask_##code); #define DEFINE_FXTYPE(code) add_fxtype_insn(this, #code, match_##code, mask_##code); #define DEFINE_FX2TYPE(code) add_fx2type_insn(this, #code, match_##code, mask_##code); + #define DEFINE_FLITYPE(code) add_flitype_insn(this, #code, match_##code, mask_##code); #define DEFINE_XFTYPE(code) add_xftype_insn(this, #code, match_##code, mask_##code); + #define DEFINE_XF2TYPE(code) add_xf2type_insn(this, #code, match_##code, mask_##code); #define DEFINE_SFENCE_TYPE(code) add_sfence_insn(this, #code, match_##code, mask_##code); add_insn(new disasm_insn_t("unimp", match_csrrw|(CSR_CYCLE<<20), 0xffffffff, {})); @@ -1179,6 +1232,56 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DEFINE_FX2TYPE(fle_d); } + if (isa->extension_enabled(EXT_ZFA)) { + DEFINE_FLITYPE(fli_s); + DEFINE_FRTYPE(fminm_s); + DEFINE_FRTYPE(fmaxm_s); + DEFINE_FR1TYPE(fround_s); + DEFINE_FR1TYPE(froundnx_s); + DEFINE_FX2TYPE(fleq_s); + DEFINE_FX2TYPE(fltq_s); + + if (isa->extension_enabled(EXT_ZFH) || isa->extension_enabled(EXT_ZVFH)) { + DEFINE_FLITYPE(fli_h); + DEFINE_FRTYPE(fminm_h); + DEFINE_FRTYPE(fmaxm_h); + DEFINE_FR1TYPE(fround_h); + DEFINE_FR1TYPE(froundnx_h); + DEFINE_FX2TYPE(fleq_h); + DEFINE_FX2TYPE(fltq_h); + } + + if (isa->extension_enabled('D')) { + DEFINE_FLITYPE(fli_d); + DEFINE_FRTYPE(fminm_d); + DEFINE_FRTYPE(fmaxm_d); + DEFINE_FR1TYPE(fround_d); + DEFINE_FR1TYPE(froundnx_d); + DEFINE_FX2TYPE(fleq_d); + DEFINE_FX2TYPE(fltq_d); + + if (isa->get_max_xlen() == 32) { + DEFINE_XF2TYPE(fmvp_d_x); + DEFINE_FXTYPE(fmvh_x_d); + } + } + + if (isa->extension_enabled('Q')) { + DEFINE_FLITYPE(fli_q); + DEFINE_FRTYPE(fminm_q); + DEFINE_FRTYPE(fmaxm_q); + DEFINE_FR1TYPE(fround_q); + DEFINE_FR1TYPE(froundnx_q); + DEFINE_FX2TYPE(fleq_q); + DEFINE_FX2TYPE(fltq_q); + + if (isa->get_max_xlen() == 64) { + DEFINE_XF2TYPE(fmvp_q_x); + DEFINE_FXTYPE(fmvh_x_q); + } + } + } + if (isa->extension_enabled(EXT_ZDINX)) { DEFINE_RTYPE(fadd_d); DEFINE_RTYPE(fsub_d); From 6854a911fd4c23650a65acbf5314e2cd3e1637b9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 26 Jun 2024 18:10:27 -0700 Subject: [PATCH 051/155] Expand default disassembly ISA --- disasm/disasm.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 7deb932a59..c3ba62a690 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -2249,7 +2249,8 @@ disassembler_t::disassembler_t(const isa_parser_t *isa) // next-highest priority: other instructions in same base ISA std::string fallback_isa_string = std::string("rv") + std::to_string(isa->get_max_xlen()) + - "gqcvh_zfh_zba_zbb_zbc_zbs_zcb_zicbom_zicboz_zicond_zkn_zkr_zks_svinval_zcmop_zimop"; + "gqcvh_zfh_zfa_zba_zbb_zbc_zbs_zcb_zicbom_zicboz_zicond_zk_zks_svinval_" + "zcmop_zimop_zawrs_zicfiss_zicfilp_zvknc_zvkg_zvfbfmin_zvfbfwma_zfbfmin"; isa_parser_t fallback_isa(fallback_isa_string.c_str(), DEFAULT_PRIV); add_instructions(&fallback_isa); From e72fcaa6748337905811632a36fbc67d8d3979e2 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 26 Jun 2024 15:48:05 -0700 Subject: [PATCH 052/155] Add insn cmds to interactive debug mode --- riscv/interactive.cc | 74 ++++++++++++++++++++++++++++++++------------ riscv/sim.h | 2 ++ 2 files changed, 57 insertions(+), 19 deletions(-) diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 71e26e6221..3f7651312d 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -277,6 +277,7 @@ void sim_t::interactive() funcs["fregs"] = &sim_t::interactive_fregs; funcs["fregd"] = &sim_t::interactive_fregd; funcs["pc"] = &sim_t::interactive_pc; + funcs["insn"] = &sim_t::interactive_insn; funcs["priv"] = &sim_t::interactive_priv; funcs["mem"] = &sim_t::interactive_mem; funcs["str"] = &sim_t::interactive_str; @@ -367,6 +368,7 @@ void sim_t::interactive_help(const std::string& cmd, const std::vector # Display double precision in \n" "vreg [reg] # Display vector [reg] (all if omitted) in \n" "pc # Show current PC in \n" + "insn # Show current instruction corresponding to PC in \n" "priv # Show current privilege level in \n" "mem [core] # Show contents of virtual memory in [core] (physical memory if omitted)\n" "str [core] # Show NUL-terminated C string at virtual address in [core] (physical address if omitted)\n" @@ -377,6 +379,8 @@ void sim_t::interactive_help(const std::string& cmd, const std::vector # Run noisy and stop when in hits \n" "until pc # Stop when PC in hits \n" "untiln pc # Run noisy and stop when PC in hits \n" + "until insn # Stop when instruction corresponding to PC in hits \n" + "untiln insn # Run noisy and stop when instruction corresponding to PC in hits \n" "until mem [core] # Stop when virtual memory in [core] (physical address if omitted) becomes \n" "untiln mem [core] # Run noisy and stop when virtual memory in [core] (physical address if omitted) becomes \n" "while reg # Run while in is \n" @@ -448,6 +452,54 @@ void sim_t::interactive_pc(const std::string& cmd, const std::vectorload(addr); + break; + case 4: + val = mmu->load(addr); + break; + case 2: + case 6: + val = mmu->load(addr); + break; + default: + val = mmu->load(addr); + break; + } + return val; +} + +reg_t sim_t::get_insn(const std::vector& args) +{ + if (args.size() != 1) + throw trap_interactive(); + + processor_t *p = get_core(args[0]); + reg_t addr = p->get_state()->pc; + mmu_t* mmu = p->get_mmu(); + return load(mmu, addr); +} + +void sim_t::interactive_insn(const std::string& cmd, const std::vector& args) +{ + if (args.size() != 1) + throw trap_interactive(); + + processor_t *p = get_core(args[0]); + int max_xlen = p->get_isa().get_max_xlen(); + + insn_t insn(get_insn(args)); + + std::ostream out(sout_.rdbuf()); + out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) + << zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl; +} + void sim_t::interactive_priv(const std::string& cmd, const std::vector& args) { if (args.size() != 1) @@ -647,27 +699,11 @@ reg_t sim_t::get_mem(const std::vector& args) addr_str = args[1]; } - reg_t addr = strtol(addr_str.c_str(),NULL,16), val; + reg_t addr = strtol(addr_str.c_str(),NULL,16); if (addr == LONG_MAX) addr = strtoul(addr_str.c_str(),NULL,16); - switch (addr % 8) - { - case 0: - val = mmu->load(addr); - break; - case 4: - val = mmu->load(addr); - break; - case 2: - case 6: - val = mmu->load(addr); - break; - default: - val = mmu->load(addr); - break; - } - return val; + return load(mmu, addr); } void sim_t::interactive_mem(const std::string& cmd, const std::vector& args) @@ -743,6 +779,7 @@ void sim_t::interactive_until(const std::string& cmd, const std::vectorget_mtimecmp(p->get_id()) << std::endl; } - diff --git a/riscv/sim.h b/riscv/sim.h index 726de7d794..540d80d857 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -123,6 +123,7 @@ class sim_t : public htif_t, public simif_t void interactive_fregs(const std::string& cmd, const std::vector& args); void interactive_fregd(const std::string& cmd, const std::vector& args); void interactive_pc(const std::string& cmd, const std::vector& args); + void interactive_insn(const std::string& cmd, const std::vector& args); void interactive_priv(const std::string& cmd, const std::vector& args); void interactive_mem(const std::string& cmd, const std::vector& args); void interactive_str(const std::string& cmd, const std::vector& args); @@ -136,6 +137,7 @@ class sim_t : public htif_t, public simif_t freg_t get_freg(const std::vector& args, int size); reg_t get_mem(const std::vector& args); reg_t get_pc(const std::vector& args); + reg_t get_insn(const std::vector& args); friend class processor_t; friend class mmu_t; From abb2d55541d38a78773e185c760a911e58997e41 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 28 Jun 2024 00:13:51 -0700 Subject: [PATCH 053/155] Fix insn interactive command (catch/print trap, use proper access func) --- riscv/interactive.cc | 59 ++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 3f7651312d..0adc4da7f6 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -452,37 +452,16 @@ void sim_t::interactive_pc(const std::string& cmd, const std::vectorload(addr); - break; - case 4: - val = mmu->load(addr); - break; - case 2: - case 6: - val = mmu->load(addr); - break; - default: - val = mmu->load(addr); - break; - } - return val; -} - reg_t sim_t::get_insn(const std::vector& args) { if (args.size() != 1) throw trap_interactive(); processor_t *p = get_core(args[0]); - reg_t addr = p->get_state()->pc; + reg_t pc = p->get_state()->pc; mmu_t* mmu = p->get_mmu(); - return load(mmu, addr); + icache_entry_t* ic_entry = mmu->access_icache(pc); + return ic_entry->data.insn.bits(); } void sim_t::interactive_insn(const std::string& cmd, const std::vector& args) @@ -493,11 +472,16 @@ void sim_t::interactive_insn(const std::string& cmd, const std::vectorget_isa().get_max_xlen(); - insn_t insn(get_insn(args)); - std::ostream out(sout_.rdbuf()); - out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) - << zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl; + try + { + insn_t insn(get_insn(args)); + out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) + << zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl; + } + catch (trap_t& t) { + out << "Unable to obtain insn due to " << t.name() << std::endl; + } } void sim_t::interactive_priv(const std::string& cmd, const std::vector& args) @@ -703,7 +687,24 @@ reg_t sim_t::get_mem(const std::vector& args) if (addr == LONG_MAX) addr = strtoul(addr_str.c_str(),NULL,16); - return load(mmu, addr); + reg_t val; + switch (addr % 8) + { + case 0: + val = mmu->load(addr); + break; + case 4: + val = mmu->load(addr); + break; + case 2: + case 6: + val = mmu->load(addr); + break; + default: + val = mmu->load(addr); + break; + } + return val; } void sim_t::interactive_mem(const std::string& cmd, const std::vector& args) From 3947fa0e1cd4f244ee191c67790e033d9b3e7fa3 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Fri, 28 Jun 2024 10:17:45 -0700 Subject: [PATCH 054/155] Don't print vregs if no V exts --- riscv/interactive.cc | 63 ++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 3f7651312d..b0855faa55 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -580,39 +580,44 @@ void sim_t::interactive_vreg(const std::string& cmd, const std::vectorVU.get_vlen()) >> 3; - const int elen = (int)(p->VU.get_elen()) >> 3; - const int num_elem = vlen/elen; - - std::ostream out(sout_.rdbuf()); - out << std::dec << "VLEN=" << (vlen << 3) << " bits; ELEN=" << (elen << 3) << " bits" << std::endl; - - for (int r = rstart; r < rend; ++r) { - out << std::setfill (' ') << std::left << std::setw(4) << vr_name[r] << std::right << ": "; - for (int e = num_elem-1; e >= 0; --e) { - uint64_t val; - switch (elen) { - case 8: - val = p->VU.elt(r, e); - out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(16) << val << " "; - break; - case 4: - val = p->VU.elt(r, e); - out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (uint32_t)val << " "; - break; - case 2: - val = p->VU.elt(r, e); - out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (uint16_t)val << " "; - break; - case 1: - val = p->VU.elt(r, e); - out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (int)(uint8_t)val << " "; - break; + if (p->any_vector_extensions()) { + const int vlen = (int)(p->VU.get_vlen()) >> 3; + const int elen = (int)(p->VU.get_elen()) >> 3; + const int num_elem = vlen/elen; + + out << std::dec << "VLEN=" << (vlen << 3) << " bits; ELEN=" << (elen << 3) << " bits" << std::endl; + + for (int r = rstart; r < rend; ++r) { + out << std::setfill (' ') << std::left << std::setw(4) << vr_name[r] << std::right << ": "; + for (int e = num_elem-1; e >= 0; --e) { + uint64_t val; + switch (elen) { + case 8: + val = p->VU.elt(r, e); + out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(16) << val << " "; + break; + case 4: + val = p->VU.elt(r, e); + out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (uint32_t)val << " "; + break; + case 2: + val = p->VU.elt(r, e); + out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (uint16_t)val << " "; + break; + case 1: + val = p->VU.elt(r, e); + out << std::dec << "[" << e << "]: 0x" << std::hex << std::setfill ('0') << std::setw(8) << (int)(uint8_t)val << " "; + break; + } } + out << std::endl; } - out << std::endl; + } else { + out << "Processor selected does not support any vector extensions" << std::endl; } } From ec292be4fdac9685c9d6f2f209b73743c2e573f7 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Jul 2024 10:12:52 +0800 Subject: [PATCH 055/155] Update encoding.h for pointer masking Rename DCSR_STOPCYCLE to DCSR_STOPCOUNT Rename DCSR_HALT to DCSR_NMIP --- riscv/csrs.cc | 4 +- riscv/encoding.h | 265 ++++++++++++++++++++--------------------------- 2 files changed, 114 insertions(+), 155 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 02a2c4fec6..e99ae84d64 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1312,7 +1312,7 @@ reg_t dcsr_csr_t::read() const noexcept { result = set_field(result, DCSR_EBREAKU, ebreaku); result = set_field(result, CSR_DCSR_EBREAKVS, ebreakvs); result = set_field(result, CSR_DCSR_EBREAKVU, ebreakvu); - result = set_field(result, DCSR_STOPCYCLE, 0); + result = set_field(result, DCSR_STOPCOUNT, 0); result = set_field(result, DCSR_STOPTIME, 0); result = set_field(result, DCSR_CAUSE, cause); result = set_field(result, DCSR_STEP, step); @@ -1331,7 +1331,7 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept { ebreaku = proc->extension_enabled('U') ? get_field(val, DCSR_EBREAKU) : false; ebreakvs = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVS) : false; ebreakvu = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVU) : false; - halt = get_field(val, DCSR_HALT); + halt = get_field(val, DCSR_NMIP); v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false; pelp = proc->extension_enabled(EXT_ZICFILP) ? static_cast(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED; diff --git a/riscv/encoding.h b/riscv/encoding.h index 4b2e0b6516..d5fb1de591 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -4,7 +4,7 @@ /* * This file is auto-generated by running 'make' in - * https://github.com/riscv/riscv-opcodes (7bed351) + * https://github.com/riscv/riscv-opcodes (c55d30f) */ #ifndef RISCV_CSR_ENCODING_H @@ -30,6 +30,7 @@ #define MSTATUS_TW 0x00200000 #define MSTATUS_TSR 0x00400000 #define MSTATUS_SPELP 0x00800000 +#define MSTATUS_SDT 0x01000000 #define MSTATUS32_SD 0x80000000 #define MSTATUS_UXL 0x0000000300000000 #define MSTATUS_SXL 0x0000000C00000000 @@ -38,12 +39,14 @@ #define MSTATUS_GVA 0x0000004000000000 #define MSTATUS_MPV 0x0000008000000000 #define MSTATUS_MPELP 0x0000020000000000 +#define MSTATUS_MDT 0x0000040000000000 #define MSTATUS64_SD 0x8000000000000000 #define MSTATUSH_SBE 0x00000010 #define MSTATUSH_MBE 0x00000020 #define MSTATUSH_GVA 0x00000040 #define MSTATUSH_MPV 0x00000080 +#define MSTATUSH_MDT 0x00000400 #define SSTATUS_UIE 0x00000001 #define SSTATUS_SIE 0x00000002 @@ -57,6 +60,7 @@ #define SSTATUS_SUM 0x00040000 #define SSTATUS_MXR 0x00080000 #define SSTATUS_SPELP 0x00800000 +#define SSTATUS_SDT 0x01000000 #define SSTATUS32_SD 0x80000000 #define SSTATUS_UXL 0x0000000300000000 #define SSTATUS64_SD 0x8000000000000000 @@ -71,6 +75,7 @@ #define HSTATUS_SPV 0x00000080 #define HSTATUS_GVA 0x00000040 #define HSTATUS_VSBE 0x00000020 +#define HSTATUS_HUPMM 0x0003000000000000 #define USTATUS_UIE 0x00000001 #define USTATUS_UPIE 0x00000010 @@ -79,19 +84,22 @@ #define MNSTATUS_MNPP 0x00001800 #define MNSTATUS_MNPV 0x00000080 -#define DCSR_XDEBUGVER (3U<<30) -#define DCSR_NDRESET (1<<29) -#define DCSR_FULLRESET (1<<28) +#define DCSR_XDEBUGVER (15U<<28) +#define DCSR_EXTCAUSE (7<<24) +#define DCSR_CETRIG (1<<19) #define DCSR_PELP (1<<18) +#define DCSR_EBREAKVS (1<<17) +#define DCSR_EBREAKVU (1<<16) #define DCSR_EBREAKM (1<<15) -#define DCSR_EBREAKH (1<<14) #define DCSR_EBREAKS (1<<13) #define DCSR_EBREAKU (1<<12) -#define DCSR_STOPCYCLE (1<<10) +#define DCSR_STEPIE (1<<11) +#define DCSR_STOPCOUNT (1<<10) #define DCSR_STOPTIME (1<<9) #define DCSR_CAUSE (7<<6) -#define DCSR_DEBUGINT (1<<5) -#define DCSR_HALT (1<<3) +#define DCSR_V (1<<5) +#define DCSR_MPRVEN (1<<4) +#define DCSR_NMIP (1<<3) #define DCSR_STEP (1<<2) #define DCSR_PRV (3<<0) @@ -168,10 +176,13 @@ #define MENVCFG_CBIE 0x00000030 #define MENVCFG_CBCFE 0x00000040 #define MENVCFG_CBZE 0x00000080 +#define MENVCFG_PMM 0x0000000300000000 +#define MENVCFG_DTE 0x0800000000000000 #define MENVCFG_ADUE 0x2000000000000000 #define MENVCFG_PBMTE 0x4000000000000000 #define MENVCFG_STCE 0x8000000000000000 +#define MENVCFGH_DTE 0x08000000 #define MENVCFGH_ADUE 0x20000000 #define MENVCFGH_PBMTE 0x40000000 #define MENVCFGH_STCE 0x80000000 @@ -179,6 +190,7 @@ #define MSTATEEN0_CS 0x00000001 #define MSTATEEN0_FCSR 0x00000002 #define MSTATEEN0_JVT 0x00000004 +#define MSTATEEN0_CTR 0x0040000000000000 #define MSTATEEN0_PRIV114 0x0080000000000000 #define MSTATEEN0_HCONTEXT 0x0200000000000000 #define MSTATEEN0_AIA 0x0800000000000000 @@ -186,6 +198,7 @@ #define MSTATEEN0_HENVCFG 0x4000000000000000 #define MSTATEEN_HSTATEEN 0x8000000000000000 +#define MSTATEEN0H_CTR 0x00400000 #define MSTATEEN0H_PRIV114 0x00800000 #define MSTATEEN0H_HCONTEXT 0x02000000 #define MSTATEEN0H_AIA 0x08000000 @@ -213,10 +226,13 @@ #define HENVCFG_CBIE 0x00000030 #define HENVCFG_CBCFE 0x00000040 #define HENVCFG_CBZE 0x00000080 +#define HENVCFG_PMM 0x0000000300000000 +#define HENVCFG_DTE 0x0800000000000000 #define HENVCFG_ADUE 0x2000000000000000 #define HENVCFG_PBMTE 0x4000000000000000 #define HENVCFG_STCE 0x8000000000000000 +#define HENVCFGH_DTE 0x08000000 #define HENVCFGH_ADUE 0x20000000 #define HENVCFGH_PBMTE 0x40000000 #define HENVCFGH_STCE 0x80000000 @@ -236,12 +252,14 @@ #define HSTATEEN0_CS 0x00000001 #define HSTATEEN0_FCSR 0x00000002 #define HSTATEEN0_JVT 0x00000004 +#define HSTATEEN0_CTR 0x0040000000000000 #define HSTATEEN0_SCONTEXT 0x0200000000000000 #define HSTATEEN0_AIA 0x0800000000000000 #define HSTATEEN0_CSRIND 0x1000000000000000 #define HSTATEEN0_SENVCFG 0x4000000000000000 #define HSTATEEN_SSTATEEN 0x8000000000000000 +#define HSTATEEN0H_CTR 0x00400000 #define HSTATEEN0H_SCONTEXT 0x02000000 #define HSTATEEN0H_AIA 0x08000000 #define HSTATEEN0H_CSRIND 0x10000000 @@ -254,6 +272,7 @@ #define SENVCFG_CBIE 0x00000030 #define SENVCFG_CBCFE 0x00000040 #define SENVCFG_CBZE 0x00000080 +#define SENVCFG_PMM 0x0000000300000000 #define SSTATEEN0_CS 0x00000001 #define SSTATEEN0_FCSR 0x00000002 @@ -265,6 +284,7 @@ #define MSECCFG_USEED 0x00000100 #define MSECCFG_SSEED 0x00000200 #define MSECCFG_MLPE 0x00000400 +#define MSECCFG_PMM 0x0000000300000000 /* jvt fields */ #define JVT_MODE 0x3F @@ -324,6 +344,73 @@ #define PMP_NA4 0x10 #define PMP_NAPOT 0x18 +#define MCTRCTL_U 0x0000000000000001 +#define MCTRCTL_S 0x0000000000000002 +#define MCTRCTL_M 0x0000000000000004 +#define MCTRCTL_RASEMU 0x0000000000000080 +#define MCTRCTL_STE 0x0000000000000100 +#define MCTRCTL_MTE 0x0000000000000200 +#define MCTRCTL_BPFRZ 0x0000000000000800 +#define MCTRCTL_LCOFIFRZ 0x0000000000001000 +#define MCTRCTL_EXCINH 0x0000000200000000 +#define MCTRCTL_INTRINH 0x0000000400000000 +#define MCTRCTL_TRETINH 0x0000000800000000 +#define MCTRCTL_NTBREN 0x0000001000000000 +#define MCTRCTL_TKBRINH 0x0000002000000000 +#define MCTRCTL_INDCALLINH 0x0000010000000000 +#define MCTRCTL_DIRCALLINH 0x0000020000000000 +#define MCTRCTL_INDJMPINH 0x0000040000000000 +#define MCTRCTL_DIRJMPINH 0x0000080000000000 +#define MCTRCTL_CORSWAPINH 0x0000100000000000 +#define MCTRCTL_RETINH 0x0000200000000000 +#define MCTRCTL_INDLJMPINH 0x0000400000000000 +#define MCTRCTL_DIRLJMPINH 0x0000800000000000 + +#define SCTRCTL_U 0x0000000000000001 +#define SCTRCTL_S 0x0000000000000002 +#define SCTRCTL_RASEMU 0x0000000000000080 +#define SCTRCTL_STE 0x0000000000000100 +#define SCTRCTL_BPFRZ 0x0000000000000800 +#define SCTRCTL_LCOFIFRZ 0x0000000000001000 +#define SCTRCTL_EXCINH 0x0000000200000000 +#define SCTRCTL_INTRINH 0x0000000400000000 +#define SCTRCTL_TRETINH 0x0000000800000000 +#define SCTRCTL_NTBREN 0x0000001000000000 +#define SCTRCTL_TKBRINH 0x0000002000000000 +#define SCTRCTL_INDCALLINH 0x0000010000000000 +#define SCTRCTL_DIRCALLINH 0x0000020000000000 +#define SCTRCTL_INDJMPINH 0x0000040000000000 +#define SCTRCTL_DIRJMPINH 0x0000080000000000 +#define SCTRCTL_CORSWAPINH 0x0000100000000000 +#define SCTRCTL_RETINH 0x0000200000000000 +#define SCTRCTL_INDLJMPINH 0x0000400000000000 +#define SCTRCTL_DIRLJMPINH 0x0000800000000000 + +#define VSCTRCTL_U 0x0000000000000001 +#define VSCTRCTL_S 0x0000000000000002 +#define VSCTRCTL_RASEMU 0x0000000000000080 +#define VSCTRCTL_STE 0x0000000000000100 +#define VSCTRCTL_BPFRZ 0x0000000000000800 +#define VSCTRCTL_LCOFIFRZ 0x0000000000001000 +#define VSCTRCTL_EXCINH 0x0000000200000000 +#define VSCTRCTL_INTRINH 0x0000000400000000 +#define VSCTRCTL_TRETINH 0x0000000800000000 +#define VSCTRCTL_NTBREN 0x0000001000000000 +#define VSCTRCTL_TKBRINH 0x0000002000000000 +#define VSCTRCTL_INDCALLINH 0x0000010000000000 +#define VSCTRCTL_DIRCALLINH 0x0000020000000000 +#define VSCTRCTL_INDJMPINH 0x0000040000000000 +#define VSCTRCTL_DIRJMPINH 0x0000080000000000 +#define VSCTRCTL_CORSWAPINH 0x0000100000000000 +#define VSCTRCTL_RETINH 0x0000200000000000 +#define VSCTRCTL_INDLJMPINH 0x0000400000000000 +#define VSCTRCTL_DIRLJMPINH 0x0000800000000000 + +#define SCTRDEPTH_DEPTH 0x00000007 + +#define SCTRSTATUS_WRPTR 0x000000FF +#define SCTRSTATUS_FROZEN 0x80000000 + #define IRQ_U_SOFT 0 #define IRQ_S_SOFT 1 #define IRQ_VS_SOFT 2 @@ -425,8 +512,6 @@ #define RISCV_ENCODING_H #define MATCH_ADD 0x33 #define MASK_ADD 0xfe00707f -#define MATCH_ADD64 0xc0001077 -#define MASK_ADD64 0xfe00707f #define MATCH_ADD_UW 0x800003b #define MASK_ADD_UW 0xfe00707f #define MATCH_ADDI 0x13 @@ -1151,14 +1236,6 @@ #define MASK_JAL 0x7f #define MATCH_JALR 0x67 #define MASK_JALR 0x707f -#define MATCH_KADD64 0x90001077 -#define MASK_KADD64 0xfe00707f -#define MATCH_KMAR64 0x94001077 -#define MASK_KMAR64 0xfe00707f -#define MATCH_KMSR64 0x96001077 -#define MASK_KMSR64 0xfe00707f -#define MATCH_KSUB64 0x92001077 -#define MASK_KSUB64 0xfe00707f #define MATCH_LB 0x3 #define MASK_LB 0x707f #define MATCH_LB_AQ 0x3400002f @@ -1293,10 +1370,6 @@ #define MASK_MULHSU 0xfe00707f #define MATCH_MULHU 0x2003033 #define MASK_MULHU 0xfe00707f -#define MATCH_MULR64 0xf0001077 -#define MASK_MULR64 0xfe00707f -#define MATCH_MULSR64 0xe0001077 -#define MASK_MULSR64 0xfe00707f #define MATCH_MULW 0x200003b #define MASK_MULW 0xfe00707f #define MATCH_OR 0x6033 @@ -1319,8 +1392,6 @@ #define MASK_PREFETCH_R 0x1f07fff #define MATCH_PREFETCH_W 0x306013 #define MASK_PREFETCH_W 0x1f07fff -#define MATCH_RADD64 0x80001077 -#define MASK_RADD64 0xfe00707f #define MATCH_REM 0x2006033 #define MASK_REM 0xfe00707f #define MATCH_REMU 0x2007033 @@ -1341,8 +1412,6 @@ #define MASK_RORIW 0xfe00707f #define MATCH_RORW 0x6000503b #define MASK_RORW 0xfe00707f -#define MATCH_RSUB64 0x82001077 -#define MASK_RSUB64 0xfe00707f #define MATCH_SB 0x23 #define MASK_SB 0x707f #define MATCH_SB_RL 0x3a00002f @@ -1351,6 +1420,8 @@ #define MASK_SC_D 0xf800707f #define MATCH_SC_W 0x1800202f #define MASK_SC_W 0xf800707f +#define MATCH_SCTRCLR 0x10400073 +#define MASK_SCTRCLR 0xffffffff #define MATCH_SD 0x3023 #define MASK_SD 0x707f #define MATCH_SD_RL 0x3a00302f @@ -1425,14 +1496,6 @@ #define MASK_SLLIW 0xfe00707f #define MATCH_SLLW 0x103b #define MASK_SLLW 0xfe00707f -#define MATCH_SLO 0x20001033 -#define MASK_SLO 0xfe00707f -#define MATCH_SLOI 0x20001013 -#define MASK_SLOI 0xfc00707f -#define MATCH_SLOIW 0x2000101b -#define MASK_SLOIW 0xfe00707f -#define MATCH_SLOW 0x2000103b -#define MASK_SLOW 0xfe00707f #define MATCH_SLT 0x2033 #define MASK_SLT 0xfe00707f #define MATCH_SLTI 0x2013 @@ -1449,40 +1512,6 @@ #define MASK_SM4ED 0x3e00707f #define MATCH_SM4KS 0x34000033 #define MASK_SM4KS 0x3e00707f -#define MATCH_SMAL 0x5e001077 -#define MASK_SMAL 0xfe00707f -#define MATCH_SMALBB 0x88001077 -#define MASK_SMALBB 0xfe00707f -#define MATCH_SMALBT 0x98001077 -#define MASK_SMALBT 0xfe00707f -#define MATCH_SMALDA 0x8c001077 -#define MASK_SMALDA 0xfe00707f -#define MATCH_SMALDRS 0x9a001077 -#define MASK_SMALDRS 0xfe00707f -#define MATCH_SMALDS 0x8a001077 -#define MASK_SMALDS 0xfe00707f -#define MATCH_SMALTT 0xa8001077 -#define MASK_SMALTT 0xfe00707f -#define MATCH_SMALXDA 0x9c001077 -#define MASK_SMALXDA 0xfe00707f -#define MATCH_SMALXDS 0xaa001077 -#define MASK_SMALXDS 0xfe00707f -#define MATCH_SMAR64 0x84001077 -#define MASK_SMAR64 0xfe00707f -#define MATCH_SMSLDA 0xac001077 -#define MASK_SMSLDA 0xfe00707f -#define MATCH_SMSLXDA 0xbc001077 -#define MASK_SMSLXDA 0xfe00707f -#define MATCH_SMSR64 0x86001077 -#define MASK_SMSR64 0xfe00707f -#define MATCH_SMUL16 0xa0000077 -#define MASK_SMUL16 0xfe00707f -#define MATCH_SMUL8 0xa8000077 -#define MASK_SMUL8 0xfe00707f -#define MATCH_SMULX16 0xa2000077 -#define MASK_SMULX16 0xfe00707f -#define MATCH_SMULX8 0xaa000077 -#define MASK_SMULX8 0xfe00707f #define MATCH_SRA 0x40005033 #define MASK_SRA 0xfe00707f #define MATCH_SRAI 0x40005013 @@ -1505,14 +1534,6 @@ #define MASK_SRLIW 0xfe00707f #define MATCH_SRLW 0x503b #define MASK_SRLW 0xfe00707f -#define MATCH_SRO 0x20005033 -#define MASK_SRO 0xfe00707f -#define MATCH_SROI 0x20005013 -#define MASK_SROI 0xfc00707f -#define MATCH_SROIW 0x2000501b -#define MASK_SROIW 0xfe00707f -#define MATCH_SROW 0x2000503b -#define MASK_SROW 0xfe00707f #define MATCH_SSAMOSWAP_D 0x4800302f #define MASK_SSAMOSWAP_D 0xf800707f #define MATCH_SSAMOSWAP_W 0x4800202f @@ -1529,40 +1550,14 @@ #define MASK_SSRDP 0xfffff07f #define MATCH_SUB 0x40000033 #define MASK_SUB 0xfe00707f -#define MATCH_SUB64 0xc2001077 -#define MASK_SUB64 0xfe00707f #define MATCH_SUBW 0x4000003b #define MASK_SUBW 0xfe00707f #define MATCH_SW 0x2023 #define MASK_SW 0x707f #define MATCH_SW_RL 0x3a00202f #define MASK_SW_RL 0xfa007fff -#define MATCH_UKADD64 0xb0001077 -#define MASK_UKADD64 0xfe00707f -#define MATCH_UKMAR64 0xb4001077 -#define MASK_UKMAR64 0xfe00707f -#define MATCH_UKMSR64 0xb6001077 -#define MASK_UKMSR64 0xfe00707f -#define MATCH_UKSUB64 0xb2001077 -#define MASK_UKSUB64 0xfe00707f -#define MATCH_UMAR64 0xa4001077 -#define MASK_UMAR64 0xfe00707f -#define MATCH_UMSR64 0xa6001077 -#define MASK_UMSR64 0xfe00707f -#define MATCH_UMUL16 0xb0000077 -#define MASK_UMUL16 0xfe00707f -#define MATCH_UMUL8 0xb8000077 -#define MASK_UMUL8 0xfe00707f -#define MATCH_UMULX16 0xb2000077 -#define MASK_UMULX16 0xfe00707f -#define MATCH_UMULX8 0xba000077 -#define MASK_UMULX8 0xfe00707f #define MATCH_UNSHFLI 0x8005013 #define MASK_UNSHFLI 0xfe00707f -#define MATCH_URADD64 0xa0001077 -#define MASK_URADD64 0xfe00707f -#define MATCH_URSUB64 0xa2001077 -#define MASK_URSUB64 0xfe00707f #define MATCH_VAADD_VV 0x24002057 #define MASK_VAADD_VV 0xfc00707f #define MATCH_VAADD_VX 0x24006057 @@ -2487,6 +2482,8 @@ #define CSR_STVAL 0x143 #define CSR_SIP 0x144 #define CSR_STIMECMP 0x14d +#define CSR_SCTRCTL 0x14e +#define CSR_SCTRSTATUS 0x14f #define CSR_SISELECT 0x150 #define CSR_SIREG 0x151 #define CSR_SIREG2 0x152 @@ -2495,6 +2492,7 @@ #define CSR_SIREG5 0x156 #define CSR_SIREG6 0x157 #define CSR_STOPEI 0x15c +#define CSR_SCTRDEPTH 0x15f #define CSR_SATP 0x180 #define CSR_SRMCFG 0x181 #define CSR_SCONTEXT 0x5a8 @@ -2507,6 +2505,7 @@ #define CSR_VSTVAL 0x243 #define CSR_VSIP 0x244 #define CSR_VSTIMECMP 0x24d +#define CSR_VSCTRCTL 0x24e #define CSR_VSISELECT 0x250 #define CSR_VSIREG 0x251 #define CSR_VSIREG2 0x252 @@ -2579,6 +2578,7 @@ #define CSR_MIP 0x344 #define CSR_MTINST 0x34a #define CSR_MTVAL2 0x34b +#define CSR_MCTRCTL 0x34e #define CSR_MISELECT 0x350 #define CSR_MIREG 0x351 #define CSR_MIREG2 0x352 @@ -3007,7 +3007,6 @@ #endif #ifdef DECLARE_INSN DECLARE_INSN(add, MATCH_ADD, MASK_ADD) -DECLARE_INSN(add64, MATCH_ADD64, MASK_ADD64) DECLARE_INSN(add_uw, MATCH_ADD_UW, MASK_ADD_UW) DECLARE_INSN(addi, MATCH_ADDI, MASK_ADDI) DECLARE_INSN(addiw, MATCH_ADDIW, MASK_ADDIW) @@ -3370,10 +3369,6 @@ DECLARE_INSN(hsv_h, MATCH_HSV_H, MASK_HSV_H) DECLARE_INSN(hsv_w, MATCH_HSV_W, MASK_HSV_W) DECLARE_INSN(jal, MATCH_JAL, MASK_JAL) DECLARE_INSN(jalr, MATCH_JALR, MASK_JALR) -DECLARE_INSN(kadd64, MATCH_KADD64, MASK_KADD64) -DECLARE_INSN(kmar64, MATCH_KMAR64, MASK_KMAR64) -DECLARE_INSN(kmsr64, MATCH_KMSR64, MASK_KMSR64) -DECLARE_INSN(ksub64, MATCH_KSUB64, MASK_KSUB64) DECLARE_INSN(lb, MATCH_LB, MASK_LB) DECLARE_INSN(lb_aq, MATCH_LB_AQ, MASK_LB_AQ) DECLARE_INSN(lbu, MATCH_LBU, MASK_LBU) @@ -3441,8 +3436,6 @@ DECLARE_INSN(mul, MATCH_MUL, MASK_MUL) DECLARE_INSN(mulh, MATCH_MULH, MASK_MULH) DECLARE_INSN(mulhsu, MATCH_MULHSU, MASK_MULHSU) DECLARE_INSN(mulhu, MATCH_MULHU, MASK_MULHU) -DECLARE_INSN(mulr64, MATCH_MULR64, MASK_MULR64) -DECLARE_INSN(mulsr64, MATCH_MULSR64, MASK_MULSR64) DECLARE_INSN(mulw, MATCH_MULW, MASK_MULW) DECLARE_INSN(or, MATCH_OR, MASK_OR) DECLARE_INSN(ori, MATCH_ORI, MASK_ORI) @@ -3454,7 +3447,6 @@ DECLARE_INSN(pause, MATCH_PAUSE, MASK_PAUSE) DECLARE_INSN(prefetch_i, MATCH_PREFETCH_I, MASK_PREFETCH_I) DECLARE_INSN(prefetch_r, MATCH_PREFETCH_R, MASK_PREFETCH_R) DECLARE_INSN(prefetch_w, MATCH_PREFETCH_W, MASK_PREFETCH_W) -DECLARE_INSN(radd64, MATCH_RADD64, MASK_RADD64) DECLARE_INSN(rem, MATCH_REM, MASK_REM) DECLARE_INSN(remu, MATCH_REMU, MASK_REMU) DECLARE_INSN(remuw, MATCH_REMUW, MASK_REMUW) @@ -3465,11 +3457,11 @@ DECLARE_INSN(ror, MATCH_ROR, MASK_ROR) DECLARE_INSN(rori, MATCH_RORI, MASK_RORI) DECLARE_INSN(roriw, MATCH_RORIW, MASK_RORIW) DECLARE_INSN(rorw, MATCH_RORW, MASK_RORW) -DECLARE_INSN(rsub64, MATCH_RSUB64, MASK_RSUB64) DECLARE_INSN(sb, MATCH_SB, MASK_SB) DECLARE_INSN(sb_rl, MATCH_SB_RL, MASK_SB_RL) DECLARE_INSN(sc_d, MATCH_SC_D, MASK_SC_D) DECLARE_INSN(sc_w, MATCH_SC_W, MASK_SC_W) +DECLARE_INSN(sctrclr, MATCH_SCTRCLR, MASK_SCTRCLR) DECLARE_INSN(sd, MATCH_SD, MASK_SD) DECLARE_INSN(sd_rl, MATCH_SD_RL, MASK_SD_RL) DECLARE_INSN(sext_b, MATCH_SEXT_B, MASK_SEXT_B) @@ -3507,10 +3499,6 @@ DECLARE_INSN(slli_rv32, MATCH_SLLI_RV32, MASK_SLLI_RV32) DECLARE_INSN(slli_uw, MATCH_SLLI_UW, MASK_SLLI_UW) DECLARE_INSN(slliw, MATCH_SLLIW, MASK_SLLIW) DECLARE_INSN(sllw, MATCH_SLLW, MASK_SLLW) -DECLARE_INSN(slo, MATCH_SLO, MASK_SLO) -DECLARE_INSN(sloi, MATCH_SLOI, MASK_SLOI) -DECLARE_INSN(sloiw, MATCH_SLOIW, MASK_SLOIW) -DECLARE_INSN(slow, MATCH_SLOW, MASK_SLOW) DECLARE_INSN(slt, MATCH_SLT, MASK_SLT) DECLARE_INSN(slti, MATCH_SLTI, MASK_SLTI) DECLARE_INSN(sltiu, MATCH_SLTIU, MASK_SLTIU) @@ -3519,23 +3507,6 @@ DECLARE_INSN(sm3p0, MATCH_SM3P0, MASK_SM3P0) DECLARE_INSN(sm3p1, MATCH_SM3P1, MASK_SM3P1) DECLARE_INSN(sm4ed, MATCH_SM4ED, MASK_SM4ED) DECLARE_INSN(sm4ks, MATCH_SM4KS, MASK_SM4KS) -DECLARE_INSN(smal, MATCH_SMAL, MASK_SMAL) -DECLARE_INSN(smalbb, MATCH_SMALBB, MASK_SMALBB) -DECLARE_INSN(smalbt, MATCH_SMALBT, MASK_SMALBT) -DECLARE_INSN(smalda, MATCH_SMALDA, MASK_SMALDA) -DECLARE_INSN(smaldrs, MATCH_SMALDRS, MASK_SMALDRS) -DECLARE_INSN(smalds, MATCH_SMALDS, MASK_SMALDS) -DECLARE_INSN(smaltt, MATCH_SMALTT, MASK_SMALTT) -DECLARE_INSN(smalxda, MATCH_SMALXDA, MASK_SMALXDA) -DECLARE_INSN(smalxds, MATCH_SMALXDS, MASK_SMALXDS) -DECLARE_INSN(smar64, MATCH_SMAR64, MASK_SMAR64) -DECLARE_INSN(smslda, MATCH_SMSLDA, MASK_SMSLDA) -DECLARE_INSN(smslxda, MATCH_SMSLXDA, MASK_SMSLXDA) -DECLARE_INSN(smsr64, MATCH_SMSR64, MASK_SMSR64) -DECLARE_INSN(smul16, MATCH_SMUL16, MASK_SMUL16) -DECLARE_INSN(smul8, MATCH_SMUL8, MASK_SMUL8) -DECLARE_INSN(smulx16, MATCH_SMULX16, MASK_SMULX16) -DECLARE_INSN(smulx8, MATCH_SMULX8, MASK_SMULX8) DECLARE_INSN(sra, MATCH_SRA, MASK_SRA) DECLARE_INSN(srai, MATCH_SRAI, MASK_SRAI) DECLARE_INSN(srai_rv32, MATCH_SRAI_RV32, MASK_SRAI_RV32) @@ -3547,10 +3518,6 @@ DECLARE_INSN(srli, MATCH_SRLI, MASK_SRLI) DECLARE_INSN(srli_rv32, MATCH_SRLI_RV32, MASK_SRLI_RV32) DECLARE_INSN(srliw, MATCH_SRLIW, MASK_SRLIW) DECLARE_INSN(srlw, MATCH_SRLW, MASK_SRLW) -DECLARE_INSN(sro, MATCH_SRO, MASK_SRO) -DECLARE_INSN(sroi, MATCH_SROI, MASK_SROI) -DECLARE_INSN(sroiw, MATCH_SROIW, MASK_SROIW) -DECLARE_INSN(srow, MATCH_SROW, MASK_SROW) DECLARE_INSN(ssamoswap_d, MATCH_SSAMOSWAP_D, MASK_SSAMOSWAP_D) DECLARE_INSN(ssamoswap_w, MATCH_SSAMOSWAP_W, MASK_SSAMOSWAP_W) DECLARE_INSN(sspopchk_x1, MATCH_SSPOPCHK_X1, MASK_SSPOPCHK_X1) @@ -3559,23 +3526,10 @@ DECLARE_INSN(sspush_x1, MATCH_SSPUSH_X1, MASK_SSPUSH_X1) DECLARE_INSN(sspush_x5, MATCH_SSPUSH_X5, MASK_SSPUSH_X5) DECLARE_INSN(ssrdp, MATCH_SSRDP, MASK_SSRDP) DECLARE_INSN(sub, MATCH_SUB, MASK_SUB) -DECLARE_INSN(sub64, MATCH_SUB64, MASK_SUB64) DECLARE_INSN(subw, MATCH_SUBW, MASK_SUBW) DECLARE_INSN(sw, MATCH_SW, MASK_SW) DECLARE_INSN(sw_rl, MATCH_SW_RL, MASK_SW_RL) -DECLARE_INSN(ukadd64, MATCH_UKADD64, MASK_UKADD64) -DECLARE_INSN(ukmar64, MATCH_UKMAR64, MASK_UKMAR64) -DECLARE_INSN(ukmsr64, MATCH_UKMSR64, MASK_UKMSR64) -DECLARE_INSN(uksub64, MATCH_UKSUB64, MASK_UKSUB64) -DECLARE_INSN(umar64, MATCH_UMAR64, MASK_UMAR64) -DECLARE_INSN(umsr64, MATCH_UMSR64, MASK_UMSR64) -DECLARE_INSN(umul16, MATCH_UMUL16, MASK_UMUL16) -DECLARE_INSN(umul8, MATCH_UMUL8, MASK_UMUL8) -DECLARE_INSN(umulx16, MATCH_UMULX16, MASK_UMULX16) -DECLARE_INSN(umulx8, MATCH_UMULX8, MASK_UMULX8) DECLARE_INSN(unshfli, MATCH_UNSHFLI, MASK_UNSHFLI) -DECLARE_INSN(uradd64, MATCH_URADD64, MASK_URADD64) -DECLARE_INSN(ursub64, MATCH_URSUB64, MASK_URSUB64) DECLARE_INSN(vaadd_vv, MATCH_VAADD_VV, MASK_VAADD_VV) DECLARE_INSN(vaadd_vx, MATCH_VAADD_VX, MASK_VAADD_VX) DECLARE_INSN(vaaddu_vv, MATCH_VAADDU_VV, MASK_VAADDU_VV) @@ -4071,6 +4025,8 @@ DECLARE_CSR(scause, CSR_SCAUSE) DECLARE_CSR(stval, CSR_STVAL) DECLARE_CSR(sip, CSR_SIP) DECLARE_CSR(stimecmp, CSR_STIMECMP) +DECLARE_CSR(sctrctl, CSR_SCTRCTL) +DECLARE_CSR(sctrstatus, CSR_SCTRSTATUS) DECLARE_CSR(siselect, CSR_SISELECT) DECLARE_CSR(sireg, CSR_SIREG) DECLARE_CSR(sireg2, CSR_SIREG2) @@ -4079,6 +4035,7 @@ DECLARE_CSR(sireg4, CSR_SIREG4) DECLARE_CSR(sireg5, CSR_SIREG5) DECLARE_CSR(sireg6, CSR_SIREG6) DECLARE_CSR(stopei, CSR_STOPEI) +DECLARE_CSR(sctrdepth, CSR_SCTRDEPTH) DECLARE_CSR(satp, CSR_SATP) DECLARE_CSR(srmcfg, CSR_SRMCFG) DECLARE_CSR(scontext, CSR_SCONTEXT) @@ -4091,6 +4048,7 @@ DECLARE_CSR(vscause, CSR_VSCAUSE) DECLARE_CSR(vstval, CSR_VSTVAL) DECLARE_CSR(vsip, CSR_VSIP) DECLARE_CSR(vstimecmp, CSR_VSTIMECMP) +DECLARE_CSR(vsctrctl, CSR_VSCTRCTL) DECLARE_CSR(vsiselect, CSR_VSISELECT) DECLARE_CSR(vsireg, CSR_VSIREG) DECLARE_CSR(vsireg2, CSR_VSIREG2) @@ -4163,6 +4121,7 @@ DECLARE_CSR(mtval, CSR_MTVAL) DECLARE_CSR(mip, CSR_MIP) DECLARE_CSR(mtinst, CSR_MTINST) DECLARE_CSR(mtval2, CSR_MTVAL2) +DECLARE_CSR(mctrctl, CSR_MCTRCTL) DECLARE_CSR(miselect, CSR_MISELECT) DECLARE_CSR(mireg, CSR_MIREG) DECLARE_CSR(mireg2, CSR_MIREG2) @@ -4469,10 +4428,10 @@ DECLARE_CAUSE("misaligned load", CAUSE_MISALIGNED_LOAD) DECLARE_CAUSE("load access", CAUSE_LOAD_ACCESS) DECLARE_CAUSE("misaligned store", CAUSE_MISALIGNED_STORE) DECLARE_CAUSE("store access", CAUSE_STORE_ACCESS) -DECLARE_CAUSE("user_ecall", CAUSE_USER_ECALL) -DECLARE_CAUSE("supervisor_ecall", CAUSE_SUPERVISOR_ECALL) -DECLARE_CAUSE("virtual_supervisor_ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL) -DECLARE_CAUSE("machine_ecall", CAUSE_MACHINE_ECALL) +DECLARE_CAUSE("user ecall", CAUSE_USER_ECALL) +DECLARE_CAUSE("supervisor ecall", CAUSE_SUPERVISOR_ECALL) +DECLARE_CAUSE("virtual supervisor ecall", CAUSE_VIRTUAL_SUPERVISOR_ECALL) +DECLARE_CAUSE("machine ecall", CAUSE_MACHINE_ECALL) DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) From 952b98fd8b0f915e8a5eb6f0df8dcc3fdfd56c8c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 1 Jul 2024 21:04:05 -0700 Subject: [PATCH 056/155] Loads to shadow-stack pages are allowed --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index d10e23aeb2..8acbc2bf2c 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -557,7 +557,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) // shadow stack access cause store access fault if xwr!=010 and xwr!=001 throw trap_store_access_fault(virt, addr, 0, 0); } else if (type == FETCH || hlvx ? !(pte & PTE_X) : - type == LOAD ? !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : + type == LOAD ? !(pte & PTE_R) && !(sse && (pte & PTE_W)) && !(mxr && (pte & PTE_X)) : !(pte & PTE_W)) { break; } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { From 436b684ff5f4ddeb0caeca65e5347836dcd7d05e Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:41:05 +0800 Subject: [PATCH 057/155] pointer masking: Support _smmpm to --isa --- disasm/isa_parser.cc | 2 ++ riscv/isa_parser.h | 1 + 2 files changed, 3 insertions(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 140bc871ca..2b36af46f6 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -318,6 +318,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZICFILP] = true; } else if (ext_str == "zicfiss") { extension_table[EXT_ZICFISS] = true; + } else if (ext_str == "smmpm") { + extension_table[EXT_SMMPM] = true; } else if (ext_str.substr(0, 3) == "zvl") { reg_t new_vlen; try { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 783af80c6d..891413f699 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -82,6 +82,7 @@ typedef enum { EXT_ZICFILP, EXT_ZICFISS, EXT_SSDBLTRP, + EXT_SMMPM, NUM_ISA_EXTENSIONS } isa_extension_t; From 58defa070e9974aa71e4b2dfd9a17e6a0d0b99b4 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:41:18 +0800 Subject: [PATCH 058/155] pointer masking: Let mseccfg.PMM be WARL if with Smmpm --- riscv/csrs.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index a3f088cc1a..e076bb521f 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -286,6 +286,7 @@ mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr): void mseccfg_csr_t::verify_permissions(insn_t insn, bool write) const { basic_csr_t::verify_permissions(insn, write); if (!proc->extension_enabled(EXT_SMEPMP) && + !proc->extension_enabled(EXT_SMMPM) && !proc->extension_enabled(EXT_ZICFILP) && !proc->extension_enabled(EXT_ZKR)) throw trap_illegal_instruction(insn.bits()); @@ -342,6 +343,12 @@ bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept { new_val |= (val & MSECCFG_MLPE); } + if (proc->extension_enabled(EXT_SMMPM)) { + const reg_t pmm_reserved = 1; // Reserved value of mseccfg.PMM + reg_t pmm = get_field(val, MSECCFG_PMM); + new_val = set_field(new_val, MSECCFG_PMM, pmm != pmm_reserved ? pmm : 0); + } + return basic_csr_t::unlogged_write(new_val); } From c70e0c2a1909dbd8aca91d93115149e4fbd547a1 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Jul 2024 09:30:53 +0800 Subject: [PATCH 059/155] refactor: Implement sext(x, pos) macro --- riscv/decode_macros.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 675634a65e..7fdec4e400 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -218,8 +218,9 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define sext32(x) ((sreg_t)(int32_t)(x)) #define zext32(x) ((reg_t)(uint32_t)(x)) -#define sext_xlen(x) (((sreg_t)(x) << (64 - xlen)) >> (64 - xlen)) +#define sext(x, pos) (((sreg_t)(x) << (64 - (pos))) >> (64 - (pos))) #define zext(x, pos) (((reg_t)(x) << (64 - (pos))) >> (64 - (pos))) +#define sext_xlen(x) sext(x, xlen) #define zext_xlen(x) zext(x, xlen) #define set_pc(x) \ From dfdd13f529c02d4d41a38b98e1e741c1e2bce638 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 14:38:10 +0800 Subject: [PATCH 060/155] refactor: Move implementation of generate_access_info() to riscv/mmu.cc --- riscv/mmu.cc | 19 +++++++++++++++++++ riscv/mmu.h | 19 +------------------ 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 37bdb9031c..3635c7713b 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -607,3 +607,22 @@ void mmu_t::register_memtracer(memtracer_t* t) flush_tlb(); tracer.hook(t); } + +mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) { + if (!proc) + return {addr, 0, false, {}, type}; + bool virt = proc->state.v; + reg_t mode = proc->state.prv; + if (type != FETCH) { + if (in_mprv()) { + mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP); + if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M) + virt = true; + } + if (xlate_flags.forced_virt) { + virt = true; + mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); + } + } + return {addr, mode, virt, xlate_flags, type}; +} diff --git a/riscv/mmu.h b/riscv/mmu.h index 3e4ae9a74b..983d802169 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -71,24 +71,7 @@ class mmu_t std::map alloc_cache; std::vector> addr_tbl; - mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) { - if (!proc) - return {addr, 0, false, {}, type}; - bool virt = proc->state.v; - reg_t mode = proc->state.prv; - if (type != FETCH) { - if (in_mprv()) { - mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP); - if (get_field(proc->state.mstatus->read(), MSTATUS_MPV) && mode != PRV_M) - virt = true; - } - if (xlate_flags.forced_virt) { - virt = true; - mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); - } - } - return {addr, mode, virt, xlate_flags, type}; - } + mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags); public: mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc); From a15cf880e7956663de4b273c84dbee2f80097e09 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 14:48:26 +0800 Subject: [PATCH 061/155] pointer masking: Let load take into account pointer masking --- riscv/mmu.cc | 24 ++++++++++++++++++++++-- riscv/mmu.h | 15 ++++++++++----- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 3635c7713b..fe0929bc5d 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -5,6 +5,7 @@ #include "arith.h" #include "simif.h" #include "processor.h" +#include "decode_macros.h" mmu_t::mmu_t(simif_t* sim, endianness_t endianness, processor_t* proc) : sim(sim), proc(proc), @@ -608,9 +609,24 @@ void mmu_t::register_memtracer(memtracer_t* t) tracer.hook(t); } +reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv) const { + if (!proc || proc->get_xlen() != 64) + return 0; + + reg_t pmm = 0; + if (effective_priv == PRV_M) + pmm = get_field(proc->state.mseccfg->read(), MSECCFG_PMM); + + switch (pmm) { + case 2: return 7; + case 3: return 16; + } + return 0; +} + mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags) { if (!proc) - return {addr, 0, false, {}, type}; + return {addr, addr, 0, false, {}, type}; bool virt = proc->state.v; reg_t mode = proc->state.prv; if (type != FETCH) { @@ -624,5 +640,9 @@ mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlat mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); } } - return {addr, mode, virt, xlate_flags, type}; + reg_t pmlen = get_pmlen(virt, mode); + reg_t satp = proc->state.satp->readvirt(virt); + bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF; + reg_t transformed_addr = is_physical_addr ? zext(addr, 64 - pmlen) : sext(addr, 64 - pmlen); + return {addr, transformed_addr, mode, virt, xlate_flags, type}; } diff --git a/riscv/mmu.h b/riscv/mmu.h index 983d802169..5cf321efd6 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -51,13 +51,14 @@ struct xlate_flags_t { struct mem_access_info_t { const reg_t vaddr; + const reg_t transformed_vaddr; const reg_t effective_priv; const bool effective_virt; const xlate_flags_t flags; const access_type type; mem_access_info_t split_misaligned_access(reg_t offset) const { - return {vaddr + offset, effective_priv, effective_virt, flags, type}; + return {vaddr + offset, transformed_vaddr + offset, effective_priv, effective_virt, flags, type}; } }; @@ -71,6 +72,7 @@ class mmu_t std::map alloc_cache; std::vector> addr_tbl; + reg_t get_pmlen(bool effective_virt, reg_t effective_priv) const; mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags); public: @@ -79,15 +81,18 @@ class mmu_t template T ALWAYS_INLINE load(reg_t addr, xlate_flags_t xlate_flags = {}) { + auto access_info = generate_access_info(addr, LOAD, xlate_flags); + reg_t transformed_addr = access_info.transformed_vaddr; + target_endian res; - reg_t vpn = addr >> PGSHIFT; - bool aligned = (addr & (sizeof(T) - 1)) == 0; + reg_t vpn = transformed_addr >> PGSHIFT; + bool aligned = (transformed_addr & (sizeof(T) - 1)) == 0; bool tlb_hit = tlb_load_tag[vpn % TLB_ENTRIES] == vpn; if (likely(!xlate_flags.is_special_access() && aligned && tlb_hit)) { - res = *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr); + res = *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr); } else { - load_slow_path(addr, sizeof(T), (uint8_t*)&res, xlate_flags); + load_slow_path(transformed_addr, sizeof(T), (uint8_t*)&res, xlate_flags); } if (unlikely(proc && proc->get_log_commits_enabled())) From 37d06eb8ba7d15c853112f7aa2d4dc69992f1508 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 15 Jul 2024 15:54:13 +0800 Subject: [PATCH 062/155] pointer masking: performance: Move pointer masking out of load fast path --- riscv/mmu.cc | 28 +++++++++++++++------------- riscv/mmu.h | 11 ++++------- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index fe0929bc5d..11f58325ca 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -55,7 +55,7 @@ void throw_access_exception(bool virt, reg_t addr, access_type type) reg_t mmu_t::translate(mem_access_info_t access_info, reg_t len) { - reg_t addr = access_info.vaddr; + reg_t addr = access_info.transformed_vaddr; access_type type = access_info.type; if (!proc) return addr; @@ -193,9 +193,10 @@ void mmu_t::check_triggers(triggers::operation_t operation, reg_t address, bool void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info) { reg_t addr = access_info.vaddr; - reg_t vpn = addr >> PGSHIFT; + reg_t transformed_addr = access_info.transformed_vaddr; + reg_t vpn = transformed_addr >> PGSHIFT; if (!access_info.flags.is_special_access() && vpn == (tlb_load_tag[vpn % TLB_ENTRIES] & ~TLB_CHECK_TRIGGERS)) { - auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + addr; + auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr; memcpy(bytes, host_addr, len); return; } @@ -203,7 +204,7 @@ void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_ reg_t paddr = translate(access_info, len); if (access_info.flags.lr && !sim->reservable(paddr)) { - throw trap_load_access_fault(access_info.effective_virt, addr, 0, 0); + throw trap_load_access_fault(access_info.effective_virt, transformed_addr, 0, 0); } if (auto host_addr = sim->addr_to_mem(paddr)) { @@ -214,7 +215,7 @@ void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_ refill_tlb(addr, paddr, host_addr, LOAD); } else if (!mmio_load(paddr, len, bytes)) { - throw trap_load_access_fault(access_info.effective_virt, addr, 0, 0); + throw trap_load_access_fault(access_info.effective_virt, transformed_addr, 0, 0); } if (access_info.flags.lr) { @@ -225,30 +226,31 @@ void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_ void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags) { auto access_info = generate_access_info(addr, LOAD, xlate_flags); - check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt); + reg_t transformed_addr = access_info.transformed_vaddr; + check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt); - if ((addr & (len - 1)) == 0) { + if ((transformed_addr & (len - 1)) == 0) { load_slow_path_intrapage(len, bytes, access_info); } else { bool gva = access_info.effective_virt; if (!is_misaligned_enabled()) - throw trap_load_address_misaligned(gva, addr, 0, 0); + throw trap_load_address_misaligned(gva, transformed_addr, 0, 0); if (access_info.flags.lr) - throw trap_load_access_fault(gva, addr, 0, 0); + throw trap_load_access_fault(gva, transformed_addr, 0, 0); - reg_t len_page0 = std::min(len, PGSIZE - addr % PGSIZE); + reg_t len_page0 = std::min(len, PGSIZE - transformed_addr % PGSIZE); load_slow_path_intrapage(len_page0, bytes, access_info); if (len_page0 != len) load_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0)); } while (len > sizeof(reg_t)) { - check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes)); + check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), bytes)); len -= sizeof(reg_t); bytes += sizeof(reg_t); } - check_triggers(triggers::OPERATION_LOAD, addr, access_info.effective_virt, reg_from_bytes(len, bytes)); + check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt, reg_from_bytes(len, bytes)); } void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store) @@ -485,7 +487,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty reg_t mmu_t::walk(mem_access_info_t access_info) { access_type type = access_info.type; - reg_t addr = access_info.vaddr; + reg_t addr = access_info.transformed_vaddr; bool virt = access_info.effective_virt; bool hlvx = access_info.flags.hlvx; reg_t mode = access_info.effective_priv; diff --git a/riscv/mmu.h b/riscv/mmu.h index 5cf321efd6..5d5f4ed616 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -81,18 +81,15 @@ class mmu_t template T ALWAYS_INLINE load(reg_t addr, xlate_flags_t xlate_flags = {}) { - auto access_info = generate_access_info(addr, LOAD, xlate_flags); - reg_t transformed_addr = access_info.transformed_vaddr; - target_endian res; - reg_t vpn = transformed_addr >> PGSHIFT; - bool aligned = (transformed_addr & (sizeof(T) - 1)) == 0; + reg_t vpn = addr >> PGSHIFT; + bool aligned = (addr & (sizeof(T) - 1)) == 0; bool tlb_hit = tlb_load_tag[vpn % TLB_ENTRIES] == vpn; if (likely(!xlate_flags.is_special_access() && aligned && tlb_hit)) { - res = *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr); + res = *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr); } else { - load_slow_path(transformed_addr, sizeof(T), (uint8_t*)&res, xlate_flags); + load_slow_path(addr, sizeof(T), (uint8_t*)&res, xlate_flags); } if (unlikely(proc && proc->get_log_commits_enabled())) From f47782cf9e8aaa956e880d86776416a23ce60c83 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 14:04:12 +0800 Subject: [PATCH 063/155] refactor: Rename parameter addr to original_addr in load_slow_path() --- riscv/mmu.cc | 4 ++-- riscv/mmu.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 11f58325ca..2e7741f947 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -223,9 +223,9 @@ void mmu_t::load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_ } } -void mmu_t::load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags) +void mmu_t::load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags) { - auto access_info = generate_access_info(addr, LOAD, xlate_flags); + auto access_info = generate_access_info(original_addr, LOAD, xlate_flags); reg_t transformed_addr = access_info.transformed_vaddr; check_triggers(triggers::OPERATION_LOAD, transformed_addr, access_info.effective_virt); diff --git a/riscv/mmu.h b/riscv/mmu.h index 5d5f4ed616..3d3b79b953 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -401,7 +401,7 @@ class mmu_t // handle uncommon cases: TLB misses, page faults, MMIO tlb_entry_t fetch_slow_path(reg_t addr); - void load_slow_path(reg_t addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags); + void load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags); void load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info); void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool require_alignment); void store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store); From 9be6070c566d60b931efd2627f77b4e2d667028b Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 15 Jul 2024 16:19:12 +0800 Subject: [PATCH 064/155] pointer masking: Let store take into account pointer masking --- riscv/mmu.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index 3d3b79b953..a0d2ef94cb 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -123,15 +123,18 @@ class mmu_t template void ALWAYS_INLINE store(reg_t addr, T val, xlate_flags_t xlate_flags = {}) { - reg_t vpn = addr >> PGSHIFT; - bool aligned = (addr & (sizeof(T) - 1)) == 0; + auto access_info = generate_access_info(addr, STORE, xlate_flags); + reg_t transformed_addr = access_info.transformed_vaddr; + + reg_t vpn = transformed_addr >> PGSHIFT; + bool aligned = (transformed_addr & (sizeof(T) - 1)) == 0; bool tlb_hit = tlb_store_tag[vpn % TLB_ENTRIES] == vpn; if (!xlate_flags.is_special_access() && likely(aligned && tlb_hit)) { - *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); + *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr) = to_target(val); } else { target_endian target_val = to_target(val); - store_slow_path(addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false); + store_slow_path(transformed_addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false); } if (unlikely(proc && proc->get_log_commits_enabled())) From 68df89718f69eeb1da18851bed91f8c58e689f40 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 15 Jul 2024 16:11:05 +0800 Subject: [PATCH 065/155] pointer masking: performance: Move pointer masking out of store fast path --- riscv/mmu.cc | 20 +++++++++++--------- riscv/mmu.h | 11 ++++------- 2 files changed, 15 insertions(+), 16 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 2e7741f947..1daf60c0c8 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -256,10 +256,11 @@ void mmu_t::load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store) { reg_t addr = access_info.vaddr; - reg_t vpn = addr >> PGSHIFT; + reg_t transformed_addr = access_info.transformed_vaddr; + reg_t vpn = transformed_addr >> PGSHIFT; if (!access_info.flags.is_special_access() && vpn == (tlb_store_tag[vpn % TLB_ENTRIES] & ~TLB_CHECK_TRIGGERS)) { if (actually_store) { - auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + addr; + auto host_addr = tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr; memcpy(host_addr, bytes, len); } return; @@ -275,7 +276,7 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces else if (!access_info.flags.is_special_access()) refill_tlb(addr, paddr, host_addr, STORE); } else if (!mmio_store(paddr, len, bytes)) { - throw trap_store_access_fault(access_info.effective_virt, addr, 0, 0); + throw trap_store_access_fault(access_info.effective_virt, transformed_addr, 0, 0); } } } @@ -283,26 +284,27 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment) { auto access_info = generate_access_info(addr, STORE, xlate_flags); + reg_t transformed_addr = access_info.transformed_vaddr; if (actually_store) { reg_t trig_len = len; const uint8_t* trig_bytes = bytes; while (trig_len > sizeof(reg_t)) { - check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes)); + check_triggers(triggers::OPERATION_STORE, transformed_addr, access_info.effective_virt, reg_from_bytes(sizeof(reg_t), trig_bytes)); trig_len -= sizeof(reg_t); trig_bytes += sizeof(reg_t); } - check_triggers(triggers::OPERATION_STORE, addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes)); + check_triggers(triggers::OPERATION_STORE, transformed_addr, access_info.effective_virt, reg_from_bytes(trig_len, trig_bytes)); } - if (addr & (len - 1)) { + if (transformed_addr & (len - 1)) { bool gva = access_info.effective_virt; if (!is_misaligned_enabled()) - throw trap_store_address_misaligned(gva, addr, 0, 0); + throw trap_store_address_misaligned(gva, transformed_addr, 0, 0); if (require_alignment) - throw trap_store_access_fault(gva, addr, 0, 0); + throw trap_store_access_fault(gva, transformed_addr, 0, 0); - reg_t len_page0 = std::min(len, PGSIZE - addr % PGSIZE); + reg_t len_page0 = std::min(len, PGSIZE - transformed_addr % PGSIZE); store_slow_path_intrapage(len_page0, bytes, access_info, actually_store); if (len_page0 != len) store_slow_path_intrapage(len - len_page0, bytes + len_page0, access_info.split_misaligned_access(len_page0), actually_store); diff --git a/riscv/mmu.h b/riscv/mmu.h index a0d2ef94cb..3d3b79b953 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -123,18 +123,15 @@ class mmu_t template void ALWAYS_INLINE store(reg_t addr, T val, xlate_flags_t xlate_flags = {}) { - auto access_info = generate_access_info(addr, STORE, xlate_flags); - reg_t transformed_addr = access_info.transformed_vaddr; - - reg_t vpn = transformed_addr >> PGSHIFT; - bool aligned = (transformed_addr & (sizeof(T) - 1)) == 0; + reg_t vpn = addr >> PGSHIFT; + bool aligned = (addr & (sizeof(T) - 1)) == 0; bool tlb_hit = tlb_store_tag[vpn % TLB_ENTRIES] == vpn; if (!xlate_flags.is_special_access() && likely(aligned && tlb_hit)) { - *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + transformed_addr) = to_target(val); + *(target_endian*)(tlb_data[vpn % TLB_ENTRIES].host_offset + addr) = to_target(val); } else { target_endian target_val = to_target(val); - store_slow_path(transformed_addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false); + store_slow_path(addr, sizeof(T), (const uint8_t*)&target_val, xlate_flags, true, false); } if (unlikely(proc && proc->get_log_commits_enabled())) From 5beff7ad1902fce13b63dfd1f1ad958536f76121 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 14:05:29 +0800 Subject: [PATCH 066/155] refactor: Rename parameter addr to original_addr in store_slow_path() --- riscv/mmu.cc | 4 ++-- riscv/mmu.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 1daf60c0c8..9fa327cb2c 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -281,9 +281,9 @@ void mmu_t::store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_acces } } -void mmu_t::store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment) +void mmu_t::store_slow_path(reg_t original_addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool UNUSED require_alignment) { - auto access_info = generate_access_info(addr, STORE, xlate_flags); + auto access_info = generate_access_info(original_addr, STORE, xlate_flags); reg_t transformed_addr = access_info.transformed_vaddr; if (actually_store) { reg_t trig_len = len; diff --git a/riscv/mmu.h b/riscv/mmu.h index 3d3b79b953..0e56f04472 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -403,7 +403,7 @@ class mmu_t tlb_entry_t fetch_slow_path(reg_t addr); void load_slow_path(reg_t original_addr, reg_t len, uint8_t* bytes, xlate_flags_t xlate_flags); void load_slow_path_intrapage(reg_t len, uint8_t* bytes, mem_access_info_t access_info); - void store_slow_path(reg_t addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool require_alignment); + void store_slow_path(reg_t original_addr, reg_t len, const uint8_t* bytes, xlate_flags_t xlate_flags, bool actually_store, bool require_alignment); void store_slow_path_intrapage(reg_t len, const uint8_t* bytes, mem_access_info_t access_info, bool actually_store); bool mmio_fetch(reg_t paddr, size_t len, uint8_t* bytes); bool mmio_load(reg_t paddr, size_t len, uint8_t* bytes); From 42776e6170bdca0ac6dfe8a66b200325a0e918f5 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Jul 2024 13:22:58 +0800 Subject: [PATCH 067/155] pointer masking: Let cache-block zero instruction (cbo.zero) take into account pointer masking --- riscv/mmu.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index 0e56f04472..370783f37e 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -221,9 +221,12 @@ class mmu_t } void cbo_zero(reg_t addr) { - auto base = addr & ~(blocksz - 1); + auto access_info = generate_access_info(addr, STORE, {}); + reg_t transformed_addr = access_info.transformed_vaddr; + + auto base = transformed_addr & ~(blocksz - 1); for (size_t offset = 0; offset < blocksz; offset += 1) { - check_triggers(triggers::OPERATION_STORE, base + offset, false, addr, std::nullopt); + check_triggers(triggers::OPERATION_STORE, base + offset, false, transformed_addr, std::nullopt); store(base + offset, 0); } } From 91173cbbc797e0d5bbc4b70655d313b0ad6effef Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 15 Jul 2024 16:27:57 +0800 Subject: [PATCH 068/155] pointer masking: Let cache-block management instructions take into account pointer masking --- riscv/mmu.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index 370783f37e..ec184ed5e3 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -232,16 +232,19 @@ class mmu_t } void clean_inval(reg_t addr, bool clean, bool inval) { - auto base = addr & ~(blocksz - 1); + auto access_info = generate_access_info(addr, LOAD, {}); + reg_t transformed_addr = access_info.transformed_vaddr; + + auto base = transformed_addr & ~(blocksz - 1); for (size_t offset = 0; offset < blocksz; offset += 1) - check_triggers(triggers::OPERATION_STORE, base + offset, false, addr, std::nullopt); + check_triggers(triggers::OPERATION_STORE, base + offset, false, transformed_addr, std::nullopt); convert_load_traps_to_store_traps({ - const reg_t paddr = translate(generate_access_info(addr, LOAD, {}), 1); + const reg_t paddr = translate(generate_access_info(transformed_addr, LOAD, {}), 1); if (sim->reservable(paddr)) { if (tracer.interested_in_range(paddr, paddr + PGSIZE, LOAD)) tracer.clean_invalidate(paddr, blocksz, clean, inval); } else { - throw trap_store_access_fault((proc) ? proc->state.v : false, addr, 0, 0); + throw trap_store_access_fault((proc) ? proc->state.v : false, transformed_addr, 0, 0); } }) } From a8cc689675fbe7dedc121b4bdeedba3c8ed1a620 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 15:18:28 +0800 Subject: [PATCH 069/155] refactor: Add const qualifier to mmu_t::in_mprv() --- riscv/mmu.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index ec184ed5e3..813e52f1ad 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -481,7 +481,7 @@ class mmu_t return (uint16_t*)(translate_insn_addr(addr).host_offset + addr); } - inline bool in_mprv() + inline bool in_mprv() const { return proc != nullptr && !(proc->state.mnstatus && !get_field(proc->state.mnstatus->read(), MNSTATUS_NMIE)) From fb761259b3250f141d199c6f1ed3d3ead65f8037 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 15:22:08 +0800 Subject: [PATCH 070/155] pointer masking: Let pointer masking not apply when both MPRV and MXR are set --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 9fa327cb2c..536c95ac94 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -614,7 +614,7 @@ void mmu_t::register_memtracer(memtracer_t* t) } reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv) const { - if (!proc || proc->get_xlen() != 64) + if (!proc || proc->get_xlen() != 64 || (in_mprv() && (proc->state.sstatus->read() & MSTATUS_MXR))) return 0; reg_t pmm = 0; From 8b5cb0fff2b8d12c4acc13ccced05b9800cb7a25 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 18 Jul 2024 15:13:12 +0800 Subject: [PATCH 071/155] pointer masking: Let HLVX.* instructions not subject to pointer masking --- riscv/mmu.cc | 6 +++--- riscv/mmu.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 536c95ac94..11794a4a99 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -613,8 +613,8 @@ void mmu_t::register_memtracer(memtracer_t* t) tracer.hook(t); } -reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv) const { - if (!proc || proc->get_xlen() != 64 || (in_mprv() && (proc->state.sstatus->read() & MSTATUS_MXR))) +reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const { + if (!proc || proc->get_xlen() != 64 || (in_mprv() && (proc->state.sstatus->read() & MSTATUS_MXR)) || flags.hlvx) return 0; reg_t pmm = 0; @@ -644,7 +644,7 @@ mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlat mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); } } - reg_t pmlen = get_pmlen(virt, mode); + reg_t pmlen = get_pmlen(virt, mode, xlate_flags); reg_t satp = proc->state.satp->readvirt(virt); bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF; reg_t transformed_addr = is_physical_addr ? zext(addr, 64 - pmlen) : sext(addr, 64 - pmlen); diff --git a/riscv/mmu.h b/riscv/mmu.h index 813e52f1ad..0aa1f96704 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -72,7 +72,7 @@ class mmu_t std::map alloc_cache; std::vector> addr_tbl; - reg_t get_pmlen(bool effective_virt, reg_t effective_priv) const; + reg_t get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const; mem_access_info_t generate_access_info(reg_t addr, access_type type, xlate_flags_t xlate_flags); public: From eea20ae6a2c949079fbb5a8fa547a0f5a609cfc6 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:34:44 +0800 Subject: [PATCH 072/155] pointer masking: Support _smnpm to --isa --- disasm/isa_parser.cc | 2 ++ riscv/isa_parser.h | 1 + 2 files changed, 3 insertions(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 2b36af46f6..2c52347e2b 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -320,6 +320,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_ZICFISS] = true; } else if (ext_str == "smmpm") { extension_table[EXT_SMMPM] = true; + } else if (ext_str == "smnpm") { + extension_table[EXT_SMNPM] = true; } else if (ext_str.substr(0, 3) == "zvl") { reg_t new_vlen; try { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 891413f699..e9458ed6fd 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -83,6 +83,7 @@ typedef enum { EXT_ZICFISS, EXT_SSDBLTRP, EXT_SMMPM, + EXT_SMNPM, NUM_ISA_EXTENSIONS } isa_extension_t; From 6cc342bcfae27b398300acdaba2d27ee3ebeb2b1 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:35:01 +0800 Subject: [PATCH 073/155] pointer masking: Let menvcfg.PMM be WARL if with Smnpm --- riscv/csrs.cc | 7 ++++++- riscv/processor.cc | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index e076bb521f..7996082fab 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -975,7 +975,12 @@ envcfg_csr_t::envcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_ bool envcfg_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t cbie_reserved = 2; // Reserved value of xenvcfg.CBIE - const reg_t adjusted_val = get_field(val, MENVCFG_CBIE) != cbie_reserved ? val : set_field(val, MENVCFG_CBIE, 0); + reg_t adjusted_val = get_field(val, MENVCFG_CBIE) != cbie_reserved ? val : set_field(val, MENVCFG_CBIE, 0); + + const reg_t pmm_reserved = 1; // Reserved value of xseccfg.PMM + const reg_t pmm = get_field(adjusted_val, MENVCFG_PMM); + adjusted_val = set_field(adjusted_val, MENVCFG_PMM, pmm != pmm_reserved ? pmm : 0); + return masked_csr_t::unlogged_write(adjusted_val); } diff --git a/riscv/processor.cc b/riscv/processor.cc index 7299548a00..2c3a5ee939 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -388,6 +388,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled_const('U')) { const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | From 370f741a97a496f368ad461614a4a4bae90dd103 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:36:20 +0800 Subject: [PATCH 074/155] pointer masking: Support _ssnpm to --isa --- disasm/isa_parser.cc | 2 ++ riscv/isa_parser.h | 1 + 2 files changed, 3 insertions(+) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 2c52347e2b..79203dfbe2 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -322,6 +322,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) extension_table[EXT_SMMPM] = true; } else if (ext_str == "smnpm") { extension_table[EXT_SMNPM] = true; + } else if (ext_str == "ssnpm") { + extension_table[EXT_SSNPM] = true; } else if (ext_str.substr(0, 3) == "zvl") { reg_t new_vlen; try { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index e9458ed6fd..45f637c640 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -84,6 +84,7 @@ typedef enum { EXT_SSDBLTRP, EXT_SMMPM, EXT_SMNPM, + EXT_SSNPM, NUM_ISA_EXTENSIONS } isa_extension_t; From faeef6ee149023087798413c90a0eb5930523e9b Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:37:38 +0800 Subject: [PATCH 075/155] pointer masking: Let [sh]envcfg.PMM be WARL if with Ssnpm --- riscv/processor.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/riscv/processor.cc b/riscv/processor.cc index 2c3a5ee939..a3b55b468e 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -405,11 +405,13 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) } const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); csrmap[CSR_SENVCFG] = senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | From f710dc706bbea2f7a9f6812822ed84a4888d1940 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:24:28 +0800 Subject: [PATCH 076/155] pointer masking: Implement Smnpm (Flush TLB on changing *envcfg.PMM) --- riscv/csrs.cc | 3 +++ riscv/mmu.cc | 2 ++ 2 files changed, 5 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 7996082fab..058e73c108 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -981,6 +981,9 @@ bool envcfg_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t pmm = get_field(adjusted_val, MENVCFG_PMM); adjusted_val = set_field(adjusted_val, MENVCFG_PMM, pmm != pmm_reserved ? pmm : 0); + if (get_field(adjusted_val, MENVCFG_PMM) != get_field(read(), MENVCFG_PMM)) + proc->get_mmu()->flush_tlb(); + return masked_csr_t::unlogged_write(adjusted_val); } diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 11794a4a99..e550a29b37 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -620,6 +620,8 @@ reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t reg_t pmm = 0; if (effective_priv == PRV_M) pmm = get_field(proc->state.mseccfg->read(), MSECCFG_PMM); + else if (!effective_virt && (effective_priv == PRV_S || (!proc->extension_enabled('S') && effective_priv == PRV_U))) + pmm = get_field(proc->state.menvcfg->read(), MENVCFG_PMM); switch (pmm) { case 2: return 7; From c268fb2564348d59eaf3800f537035bd16cba401 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 5 Jul 2024 16:30:29 +0800 Subject: [PATCH 077/155] pointer masking: Implement [sh]envcfg.PMM --- riscv/mmu.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index e550a29b37..0b0be170f6 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -622,6 +622,10 @@ reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t pmm = get_field(proc->state.mseccfg->read(), MSECCFG_PMM); else if (!effective_virt && (effective_priv == PRV_S || (!proc->extension_enabled('S') && effective_priv == PRV_U))) pmm = get_field(proc->state.menvcfg->read(), MENVCFG_PMM); + else if (effective_virt && effective_priv == PRV_S) + pmm = get_field(proc->state.henvcfg->read(), HENVCFG_PMM); + else if (effective_priv == PRV_U) + pmm = get_field(proc->state.senvcfg->read(), SENVCFG_PMM); switch (pmm) { case 2: return 7; From 69f0c46fe3472eb4b155fd86ad6802f4ac5820b4 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Jul 2024 14:23:55 +0800 Subject: [PATCH 078/155] refactor: Add specialized hstatus_csr_t --- riscv/csrs.cc | 13 +++++++++++++ riscv/csrs.h | 7 +++++++ riscv/processor.cc | 6 +----- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 058e73c108..4ab1331a0d 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1851,3 +1851,16 @@ void mtval2_csr_t::verify_permissions(insn_t insn, bool write) const { if (!proc->extension_enabled('H') && !proc->extension_enabled(EXT_SSDBLTRP)) throw trap_illegal_instruction(insn.bits()); } + +hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr): + basic_csr_t(proc, addr, set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen()))) { +} + +bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept { + const reg_t mask = HSTATUS_VTSR | HSTATUS_VTW + | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0) + | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; + + const reg_t new_hstatus = (read() & ~mask) | (val & mask); + return basic_csr_t::unlogged_write(new_hstatus); +} diff --git a/riscv/csrs.h b/riscv/csrs.h index dc89963c4a..db61fba980 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -891,4 +891,11 @@ class mtval2_csr_t: public hypervisor_csr_t { mtval2_csr_t(processor_t* const proc, const reg_t addr); virtual void verify_permissions(insn_t insn, bool write) const override; }; + +class hstatus_csr_t final: public basic_csr_t { + public: + hstatus_csr_t(processor_t* const proc, const reg_t addr); + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; +}; #endif diff --git a/riscv/processor.cc b/riscv/processor.cc index a3b55b468e..418599b073 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -297,11 +297,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_SCAUSE] = scause = std::make_shared(proc, nonvirtual_scause, vscause); csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); csrmap[CSR_MTINST] = mtinst = std::make_shared(proc, CSR_MTINST); - const reg_t hstatus_init = set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen())); - const reg_t hstatus_mask = HSTATUS_VTSR | HSTATUS_VTW - | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0) - | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; - csrmap[CSR_HSTATUS] = hstatus = std::make_shared(proc, CSR_HSTATUS, hstatus_mask, hstatus_init); + csrmap[CSR_HSTATUS] = hstatus = std::make_shared(proc, CSR_HSTATUS); csrmap[CSR_HGEIE] = std::make_shared(proc, CSR_HGEIE, 0); csrmap[CSR_HGEIP] = std::make_shared(proc, CSR_HGEIP, 0); csrmap[CSR_HIDELEG] = hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg); From 7f8c6638868d316096e63a3aea8e3277c615971b Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 2 Jul 2024 14:34:35 +0800 Subject: [PATCH 079/155] pointer masking: Implement hstatus.HUPMM (Flush TLB on changing hstatus.HUPMM) --- riscv/csrs.cc | 9 ++++++++- riscv/mmu.cc | 4 ++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 4ab1331a0d..a74cf15125 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1859,8 +1859,15 @@ hstatus_csr_t::hstatus_csr_t(processor_t* const proc, const reg_t addr): bool hstatus_csr_t::unlogged_write(const reg_t val) noexcept { const reg_t mask = HSTATUS_VTSR | HSTATUS_VTW | (proc->supports_impl(IMPL_MMU) ? HSTATUS_VTVM : 0) + | (proc->extension_enabled(EXT_SSNPM) ? HSTATUS_HUPMM : 0) | HSTATUS_HU | HSTATUS_SPVP | HSTATUS_SPV | HSTATUS_GVA; - const reg_t new_hstatus = (read() & ~mask) | (val & mask); + const reg_t pmm_reserved = 1; // Reserved value of mseccfg.PMM + reg_t pmm = get_field(val, HSTATUS_HUPMM); + const reg_t adjusted_val = set_field(val, HSTATUS_HUPMM, pmm != pmm_reserved ? pmm : 0); + + const reg_t new_hstatus = (read() & ~mask) | (adjusted_val & mask); + if (get_field(new_hstatus, HSTATUS_HUPMM) != get_field(read(), HSTATUS_HUPMM)) + proc->get_mmu()->flush_tlb(); return basic_csr_t::unlogged_write(new_hstatus); } diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 0b0be170f6..94997a23e9 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -624,8 +624,12 @@ reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t pmm = get_field(proc->state.menvcfg->read(), MENVCFG_PMM); else if (effective_virt && effective_priv == PRV_S) pmm = get_field(proc->state.henvcfg->read(), HENVCFG_PMM); + else if (proc->state.prv == PRV_U && flags.forced_virt) + pmm = get_field(proc->state.hstatus->read(), HSTATUS_HUPMM); else if (effective_priv == PRV_U) pmm = get_field(proc->state.senvcfg->read(), SENVCFG_PMM); + else + assert(false); switch (pmm) { case 2: return 7; From eccb557d613075335879289aae8c97fe3a782b30 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 17 Jul 2024 08:43:10 +0800 Subject: [PATCH 080/155] Fix require_vector_vs checking by reverting https://github.com/riscv-software-src/riscv-isa-sim/commit/66c4853bdc5b22bf4c4b364218c713e3f1e487f3 The require_vector_vs, i.e., sstatus_csr_t::enabled(SSTATUS_VS), was expected to provide has_any_vector() check [1]. Unfortunately, a previous commit [2] made the sstatus_csr_t::enabled(SSTATUS_VS) true without any vector extension. The previous commit [2] was for P-extension, which has been removed from Spike [3]. This commit reverts the commit [2] and corrects require_vector_vs [1]. [1] https://github.com/riscv-software-src/riscv-isa-sim/pull/1701/commits/a484f6efc5f50836bb8d846180dfbb9786d09ae2 [2] https://github.com/riscv-software-src/riscv-isa-sim/commit/66c4853bdc5b22bf4c4b364218c713e3f1e487f3 [3] https://github.com/riscv-software-src/riscv-isa-sim/pull/1660 --- riscv/csrs.cc | 5 ----- 1 file changed, 5 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..9fcc135305 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -642,11 +642,6 @@ bool sstatus_csr_t::enabled(const reg_t which) { if (!state->v || (virt_sstatus->read() & which) != 0) return true; } - - // If the field doesn't exist, it is always enabled. See #823. - if (!orig_sstatus->field_exists(which)) - return true; - return false; } From cefa747e9a241e1fe7a7dcd32108d3a889cbed6f Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 19 Jul 2024 08:25:18 +0800 Subject: [PATCH 081/155] Check if any vector extensions for vector CSRs --- riscv/csrs.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 9fcc135305..e73a904985 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1446,7 +1446,7 @@ vector_csr_t::vector_csr_t(processor_t* const proc, const reg_t addr, const reg_ } void vector_csr_t::verify_permissions(insn_t insn, bool write) const { - require_vector_vs; + require(proc->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS)); basic_csr_t::verify_permissions(insn, write); } @@ -1467,7 +1467,7 @@ vxsat_csr_t::vxsat_csr_t(processor_t* const proc, const reg_t addr): } void vxsat_csr_t::verify_permissions(insn_t insn, bool write) const { - require_vector_vs; + require(proc->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS)); masked_csr_t::verify_permissions(insn, write); } From 67933ec0c397124aa27f558c973673a5d74a39e5 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 19 Jul 2024 08:27:51 +0800 Subject: [PATCH 082/155] Check any_vector_extensions() in require_vector_vs --- riscv/decode_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 675634a65e..338d443c09 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -167,7 +167,7 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) #define require_fs require(STATE.sstatus->enabled(SSTATUS_FS)) #define require_fp STATE.fflags->verify_permissions(insn, false) #define require_accelerator require(STATE.sstatus->enabled(SSTATUS_XS)) -#define require_vector_vs require(STATE.sstatus->enabled(SSTATUS_VS)) +#define require_vector_vs require(p->any_vector_extensions() && STATE.sstatus->enabled(SSTATUS_VS)) #define require_vector(alu) \ do { \ require_vector_vs; \ From af90d427af03fe11ba84d962fb539e8d33976d69 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 19 Jul 2024 09:44:03 +0800 Subject: [PATCH 083/155] vector: check extension existence before reading vl --- riscv/v_ext_macros.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h index 3e8a653863..efec7a2c1b 100644 --- a/riscv/v_ext_macros.h +++ b/riscv/v_ext_macros.h @@ -1202,10 +1202,10 @@ reg_t index[P.VU.vlmax]; \ #define VI_LD(stride, offset, elt_width, is_mask_ldst) \ const reg_t nf = insn.v_nf() + 1; \ + VI_CHECK_LOAD(elt_width, is_mask_ldst); \ const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \ const reg_t baseAddr = RS1; \ const reg_t vd = insn.rd(); \ - VI_CHECK_LOAD(elt_width, is_mask_ldst); \ for (reg_t i = 0; i < vl; ++i) { \ VI_ELEMENT_SKIP; \ VI_STRIP(i); \ @@ -1220,12 +1220,12 @@ reg_t index[P.VU.vlmax]; \ #define VI_LD_INDEX(elt_width, is_seg) \ const reg_t nf = insn.v_nf() + 1; \ + VI_CHECK_LD_INDEX(elt_width); \ const reg_t vl = P.VU.vl->read(); \ const reg_t baseAddr = RS1; \ const reg_t vd = insn.rd(); \ if (!is_seg) \ require(nf == 1); \ - VI_CHECK_LD_INDEX(elt_width); \ VI_DUPLICATE_VREG(insn.rs2(), elt_width); \ for (reg_t i = 0; i < vl; ++i) { \ VI_ELEMENT_SKIP; \ @@ -1256,10 +1256,10 @@ reg_t index[P.VU.vlmax]; \ #define VI_ST(stride, offset, elt_width, is_mask_ldst) \ const reg_t nf = insn.v_nf() + 1; \ + VI_CHECK_STORE(elt_width, is_mask_ldst); \ const reg_t vl = is_mask_ldst ? ((P.VU.vl->read() + 7) / 8) : P.VU.vl->read(); \ const reg_t baseAddr = RS1; \ const reg_t vs3 = insn.rd(); \ - VI_CHECK_STORE(elt_width, is_mask_ldst); \ for (reg_t i = 0; i < vl; ++i) { \ VI_STRIP(i) \ VI_ELEMENT_SKIP; \ @@ -1274,12 +1274,12 @@ reg_t index[P.VU.vlmax]; \ #define VI_ST_INDEX(elt_width, is_seg) \ const reg_t nf = insn.v_nf() + 1; \ + VI_CHECK_ST_INDEX(elt_width); \ const reg_t vl = P.VU.vl->read(); \ const reg_t baseAddr = RS1; \ const reg_t vs3 = insn.rd(); \ if (!is_seg) \ require(nf == 1); \ - VI_CHECK_ST_INDEX(elt_width); \ VI_DUPLICATE_VREG(insn.rs2(), elt_width); \ for (reg_t i = 0; i < vl; ++i) { \ VI_STRIP(i) \ @@ -1310,10 +1310,10 @@ reg_t index[P.VU.vlmax]; \ #define VI_LDST_FF(elt_width) \ const reg_t nf = insn.v_nf() + 1; \ + VI_CHECK_LOAD(elt_width, false); \ const reg_t vl = p->VU.vl->read(); \ const reg_t baseAddr = RS1; \ const reg_t rd_num = insn.rd(); \ - VI_CHECK_LOAD(elt_width, false); \ bool early_stop = false; \ for (reg_t i = p->VU.vstart->read(); i < vl; ++i) { \ VI_STRIP(i); \ From 707b1f24841fbe80453f5978ac298df14c54546d Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 19 Jul 2024 09:46:43 +0800 Subject: [PATCH 084/155] Instantiate vector CSRs only if any_vector_extensions() --- riscv/processor.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 7a6989ea67..80c2746217 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -577,7 +577,8 @@ void processor_t::reset() state.reset(this, isa->get_max_isa()); state.dcsr->halt = halt_on_reset; halt_on_reset = false; - VU.reset(); + if (any_vector_extensions()) + VU.reset(); in_wfi = false; if (n_pmp > 0) { From 0797c21001791ce31ffc871c8f3ab6964d901a30 Mon Sep 17 00:00:00 2001 From: Ved Shanbhogue Date: Thu, 20 Jun 2024 09:08:32 -0500 Subject: [PATCH 085/155] Add Ssdbltrp --- disasm/isa_parser.cc | 2 ++ riscv/csrs.cc | 41 +++++++++++++++++++++++++++++++++++++---- riscv/csrs.h | 20 +++++++++++++------- riscv/encoding.h | 2 ++ riscv/insns/dret.h | 6 ++++++ riscv/insns/mret.h | 4 ++++ riscv/insns/sret.h | 7 +++++++ riscv/isa_parser.h | 1 + riscv/processor.cc | 25 ++++++++++++++++++++----- riscv/trap.h | 1 + 10 files changed, 93 insertions(+), 16 deletions(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index e37b72f3ad..140bc871ca 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -347,6 +347,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) if (new_elen != 32 && new_elen != 64) bad_isa_string(str, ("Invalid Zve string: " + ext_str).c_str()); elen = std::max(elen, new_elen); + } else if (ext_str == "ssdbltrp") { + extension_table[EXT_SSDBLTRP] = true; } else if (ext_str[0] == 'x') { extension_table['X'] = true; if (ext_str.size() == 1) { diff --git a/riscv/csrs.cc b/riscv/csrs.cc index e99ae84d64..01720eb948 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -421,6 +421,7 @@ reg_t base_status_csr_t::compute_sstatus_write_mask() const noexcept { | (proc->any_custom_extensions() ? SSTATUS_XS : 0) | (has_vs ? SSTATUS_VS : 0) | (proc->extension_enabled(EXT_ZICFILP) ? SSTATUS_SPELP : 0) + | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0) ; } @@ -464,12 +465,23 @@ vsstatus_csr_t::vsstatus_csr_t(processor_t* const proc, const reg_t addr): } bool vsstatus_csr_t::unlogged_write(const reg_t val) noexcept { - const reg_t newval = (this->val & ~sstatus_write_mask) | (val & sstatus_write_mask); + const reg_t hDTE = (state->henvcfg->read() & HENVCFG_DTE); + const reg_t adj_write_mask = sstatus_write_mask & ~(hDTE ? 0 : SSTATUS_SDT); + reg_t newval = (this->val & ~adj_write_mask) | (val & adj_write_mask); + + newval = (newval & SSTATUS_SDT) ? (newval & ~SSTATUS_SIE) : newval; + if (state->v) maybe_flush_tlb(newval); this->val = adjust_sd(newval); return true; } +reg_t vsstatus_csr_t::read() const noexcept { + const reg_t hDTE = state->henvcfg->read() & HENVCFG_DTE; + const reg_t adj_read_mask = sstatus_read_mask & ~(hDTE ? 0 : SSTATUS_SDT); + return this->val & adj_read_mask; +} + // implement class sstatus_proxy_csr_t sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus): base_status_csr_t(proc, addr), @@ -477,16 +489,26 @@ sstatus_proxy_csr_t::sstatus_proxy_csr_t(processor_t* const proc, const reg_t ad } bool sstatus_proxy_csr_t::unlogged_write(const reg_t val) noexcept { - const reg_t new_mstatus = (mstatus->read() & ~sstatus_write_mask) | (val & sstatus_write_mask); + const reg_t mDTE = (state->menvcfg->read() & MENVCFG_DTE); + const reg_t adj_write_mask = sstatus_write_mask & ~(mDTE ? 0 : SSTATUS_SDT); + reg_t new_mstatus = (mstatus->read() & ~adj_write_mask) | (val & adj_write_mask); + + new_mstatus = (new_mstatus & SSTATUS_SDT) ? (new_mstatus & ~SSTATUS_SIE) : new_mstatus; // On RV32 this will only log the low 32 bits, so make sure we're // not modifying anything in the upper 32 bits. - assert((sstatus_write_mask & 0xffffffffU) == sstatus_write_mask); + assert((adj_write_mask & 0xffffffffU) == adj_write_mask); mstatus->write(new_mstatus); return false; // avoid double logging: already logged by mstatus->write() } +reg_t sstatus_proxy_csr_t::read() const noexcept { + const reg_t mDTE = state->menvcfg->read() & MENVCFG_DTE; + const reg_t adj_read_mask = sstatus_read_mask & ~(mDTE ? 0 : SSTATUS_SDT); + return mstatus->read() & adj_read_mask; +} + // implement class mstatus_csr_t mstatus_csr_t::mstatus_csr_t(processor_t* const proc, const reg_t addr): base_status_csr_t(proc, addr), @@ -506,6 +528,7 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { | (has_gva ? MSTATUS_GVA : 0) | (has_mpv ? MSTATUS_MPV : 0) | (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0) + | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0) ; const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP)); @@ -1548,7 +1571,7 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { } bool henvcfg_csr_t::unlogged_write(const reg_t val) noexcept { - const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE); + const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE); return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask)); } @@ -1765,3 +1788,13 @@ void ssp_csr_t::verify_permissions(insn_t insn, bool write) const { DECLARE_XENVCFG_VARS(SSE); require_envcfg(SSE); } + +mtval2_csr_t::mtval2_csr_t(processor_t* const proc, const reg_t addr): + hypervisor_csr_t(proc, addr) { +} + +void mtval2_csr_t::verify_permissions(insn_t insn, bool write) const { + basic_csr_t::verify_permissions(insn, write); + if (!proc->extension_enabled('H') && !proc->extension_enabled(EXT_SSDBLTRP)) + throw trap_illegal_instruction(insn.bits()); +} diff --git a/riscv/csrs.h b/riscv/csrs.h index 658ffdb7b7..ad165b6b90 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -234,13 +234,12 @@ typedef std::shared_ptr base_status_csr_t_p; // For vsstatus, which is its own separate architectural register // (unlike sstatus) +// vstatus.sdt is read_only 0 when henvcfg.dte = 0 class vsstatus_csr_t final: public base_status_csr_t { public: vsstatus_csr_t(processor_t* const proc, const reg_t addr); - reg_t read() const noexcept override { - return val; - } + virtual reg_t read() const noexcept override; protected: virtual bool unlogged_write(const reg_t val) noexcept override; @@ -300,13 +299,12 @@ class rv32_high_csr_t: public csr_t { csr_t_p orig; }; +// sstatus.sdt is read_only 0 when menvcfg.dte = 0 class sstatus_proxy_csr_t final: public base_status_csr_t { public: sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus); - reg_t read() const noexcept override { - return mstatus->read() & sstatus_read_mask; - } + virtual reg_t read() const noexcept override; protected: virtual bool unlogged_write(const reg_t val) noexcept override; @@ -480,12 +478,13 @@ class envcfg_csr_t: public masked_csr_t { // henvcfg.pbmte is read_only 0 when menvcfg.pbmte = 0 // henvcfg.stce is read_only 0 when menvcfg.stce = 0 // henvcfg.hade is read_only 0 when menvcfg.hade = 0 +// henvcfg.dte is read_only 0 when menvcfg.dte = 0 class henvcfg_csr_t final: public envcfg_csr_t { public: henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg); reg_t read() const noexcept override { - return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE)) & masked_csr_t::read(); + return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE)) & masked_csr_t::read(); } virtual void verify_permissions(insn_t insn, bool write) const override; @@ -880,4 +879,11 @@ class ssp_csr_t final : public masked_csr_t { ssp_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init); virtual void verify_permissions(insn_t insn, bool write) const override; }; + +// mtval2 CSR provided by H extension - but required if Ssdbltrp is implemented +class mtval2_csr_t: public hypervisor_csr_t { + public: + mtval2_csr_t(processor_t* const proc, const reg_t addr); + virtual void verify_permissions(insn_t insn, bool write) const override; +}; #endif diff --git a/riscv/encoding.h b/riscv/encoding.h index d5fb1de591..675b4f6438 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -2891,6 +2891,7 @@ #define CAUSE_FETCH_PAGE_FAULT 0xc #define CAUSE_LOAD_PAGE_FAULT 0xd #define CAUSE_STORE_PAGE_FAULT 0xf +#define CAUSE_DOUBLE_TRAP 0x10 #define CAUSE_SOFTWARE_CHECK_FAULT 0x12 #define CAUSE_HARDWARE_ERROR_FAULT 0x13 #define CAUSE_FETCH_GUEST_PAGE_FAULT 0x14 @@ -4435,6 +4436,7 @@ DECLARE_CAUSE("machine ecall", CAUSE_MACHINE_ECALL) DECLARE_CAUSE("fetch page fault", CAUSE_FETCH_PAGE_FAULT) DECLARE_CAUSE("load page fault", CAUSE_LOAD_PAGE_FAULT) DECLARE_CAUSE("store page fault", CAUSE_STORE_PAGE_FAULT) +DECLARE_CAUSE("double trap", CAUSE_DOUBLE_TRAP) DECLARE_CAUSE("software check fault", CAUSE_SOFTWARE_CHECK_FAULT) DECLARE_CAUSE("hardware error fault", CAUSE_HARDWARE_ERROR_FAULT) DECLARE_CAUSE("fetch guest page fault", CAUSE_FETCH_GUEST_PAGE_FAULT) diff --git a/riscv/insns/dret.h b/riscv/insns/dret.h index bdcf3dbb60..60aaf217b6 100644 --- a/riscv/insns/dret.h +++ b/riscv/insns/dret.h @@ -7,6 +7,12 @@ p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v); if (STATE.prv < PRV_M) STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV); +if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v) + STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT); + +if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U) + STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT); + /* We're not in Debug Mode anymore. */ STATE.debug_mode = false; diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index 3fe920cb10..140ebde778 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -13,6 +13,10 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, MSTATUS_MPELP)); } s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED); +if (prev_prv == PRV_U || prev_virt) + s = set_field(s, MSTATUS_SDT, 0); +if (prev_virt && prev_prv == PRV_U) + STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT); STATE.mstatus->write(s); if (STATE.mstatush) STATE.mstatush->write(s >> 32); // log mstatush change STATE.tcontrol->write((STATE.tcontrol->read() & CSR_TCONTROL_MPTE) ? (CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE) : 0); diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index 23a13b56df..fe007d328b 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -27,5 +27,12 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, SSTATUS_SPELP)); } s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED); + +if (STATE.prv == PRV_S) { + s = set_field(s, SSTATUS_SDT, 0); + if (!STATE.v && prev_virt && prev_prv == PRV_U) + STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT); +} + STATE.sstatus->write(s); p->set_privilege(prev_prv, prev_virt); diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index afb49f2959..783af80c6d 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -81,6 +81,7 @@ typedef enum { EXT_SSQOSID, EXT_ZICFILP, EXT_ZICFISS, + EXT_SSDBLTRP, NUM_ISA_EXTENSIONS } isa_extension_t; diff --git a/riscv/processor.cc b/riscv/processor.cc index 9498b8fe77..7a6989ea67 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -295,7 +295,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) nonvirtual_scause = std::make_shared(proc, CSR_SCAUSE); csrmap[CSR_VSCAUSE] = vscause = std::make_shared(proc, CSR_VSCAUSE); csrmap[CSR_SCAUSE] = scause = std::make_shared(proc, nonvirtual_scause, vscause); - csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); + csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); csrmap[CSR_MTINST] = mtinst = std::make_shared(proc, CSR_MTINST); const reg_t hstatus_init = set_field((reg_t)0, HSTATUS_VSXL, xlen_to_uxl(proc->get_const_xlen())); const reg_t hstatus_mask = HSTATUS_VTSR | HSTATUS_VTW @@ -391,7 +391,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0); + (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0); menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init); if (xlen == 32) { @@ -411,7 +412,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0); + (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0); henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg); if (xlen == 32) { @@ -820,6 +822,7 @@ void processor_t::take_trap(trap_t& t, reg_t epc) bool curr_virt = state.v; const reg_t interrupt_bit = (reg_t)1 << (max_xlen - 1); bool interrupt = (bit & interrupt_bit) != 0; + bool supv_double_trap = false; if (interrupt) { vsdeleg = (curr_virt && state.prv <= PRV_S) ? state.hideleg->read() : 0; hsdeleg = (state.prv <= PRV_S) ? state.mideleg->read() : 0; @@ -828,6 +831,14 @@ void processor_t::take_trap(trap_t& t, reg_t epc) vsdeleg = (curr_virt && state.prv <= PRV_S) ? (state.medeleg->read() & state.hedeleg->read()) : 0; hsdeleg = (state.prv <= PRV_S) ? state.medeleg->read() : 0; } + // An unexpected trap - a trap when SDT is 1 - traps to M-mode + if ((state.prv <= PRV_S && bit < max_xlen) && + (((vsdeleg >> bit) & 1) || ((hsdeleg >> bit) & 1))) { + reg_t s = curr_virt ? state.nonvirtual_sstatus->read() : state.sstatus->read(); + supv_double_trap = get_field(s, MSTATUS_SDT); + if (supv_double_trap) + vsdeleg = hsdeleg = 0; + } if (state.prv <= PRV_S && bit < max_xlen && ((vsdeleg >> bit) & 1)) { // Handle the trap in VS-mode const reg_t adjusted_cause = interrupt ? bit - 1 : bit; // VSSIP -> SSIP, etc @@ -842,6 +853,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); s = set_field(s, MSTATUS_SPELP, state.elp); + if ((state.menvcfg->read() & MENVCFG_DTE) && (state.henvcfg->read() & HENVCFG_DTE)) + s = set_field(s, MSTATUS_SDT, 1); state.elp = elp_t::NO_LP_EXPECTED; state.sstatus->write(s); set_privilege(PRV_S, true); @@ -860,6 +873,8 @@ void processor_t::take_trap(trap_t& t, reg_t epc) s = set_field(s, MSTATUS_SPP, state.prv); s = set_field(s, MSTATUS_SIE, 0); s = set_field(s, MSTATUS_SPELP, state.elp); + if (state.menvcfg->read() & MENVCFG_DTE) + s = set_field(s, MSTATUS_SDT, 1); state.elp = elp_t::NO_LP_EXPECTED; state.nonvirtual_sstatus->write(s); if (extension_enabled('H')) { @@ -881,9 +896,9 @@ void processor_t::take_trap(trap_t& t, reg_t epc) const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE)); state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address; state.mepc->write(epc); - state.mcause->write(t.cause()); + state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause()); state.mtval->write(t.get_tval()); - state.mtval2->write(t.get_tval2()); + state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2()); state.mtinst->write(t.get_tinst()); reg_t s = state.mstatus->read(); diff --git a/riscv/trap.h b/riscv/trap.h index 5eb62cfd01..5ea56e2426 100644 --- a/riscv/trap.h +++ b/riscv/trap.h @@ -115,6 +115,7 @@ DECLARE_TRAP(CAUSE_MACHINE_ECALL, machine_ecall) DECLARE_MEM_TRAP(CAUSE_FETCH_PAGE_FAULT, instruction_page_fault) DECLARE_MEM_TRAP(CAUSE_LOAD_PAGE_FAULT, load_page_fault) DECLARE_MEM_TRAP(CAUSE_STORE_PAGE_FAULT, store_page_fault) +DECLARE_TRAP(CAUSE_DOUBLE_TRAP, double_trap) DECLARE_MEM_GVA_TRAP(CAUSE_FETCH_GUEST_PAGE_FAULT, instruction_guest_page_fault) DECLARE_MEM_GVA_TRAP(CAUSE_LOAD_GUEST_PAGE_FAULT, load_guest_page_fault) DECLARE_INST_TRAP(CAUSE_VIRTUAL_INSTRUCTION, virtual_instruction) From ad86a5fc5c9e780b0c0ace75567d76f4fc53130a Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 15 Jul 2024 10:01:31 +0800 Subject: [PATCH 086/155] Deprecate dcsr.halt The debug spec 1.0.0-rc3 deprecates the dcsr.halt and lets the bit become dcsr.nmip. This commit separates the halt variable from the dcsr.nmip and designates it as an internal variable for halt_on_reset (-H). Additionally, this commit removes the notifying comment about the deprecated dcsr.halt in the main loop. --- riscv/csrs.cc | 1 - riscv/execute.cc | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..b6ec20b970 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1354,7 +1354,6 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept { ebreaku = proc->extension_enabled('U') ? get_field(val, DCSR_EBREAKU) : false; ebreakvs = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVS) : false; ebreakvu = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_EBREAKVU) : false; - halt = get_field(val, DCSR_NMIP); v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false; pelp = proc->extension_enabled(EXT_ZICFILP) ? static_cast(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED; diff --git a/riscv/execute.cc b/riscv/execute.cc index f263dce995..cc77d88eec 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -216,7 +216,7 @@ void processor_t::step(size_t n) enter_debug_mode(DCSR_CAUSE_DEBUGINT); } else if (halt_request == HR_GROUP) { enter_debug_mode(DCSR_CAUSE_GROUP); - } // !!!The halt bit in DCSR is deprecated. + } else if (state.dcsr->halt) { enter_debug_mode(DCSR_CAUSE_HALT); } From 50c89eaba38c698911add01cda502127f02ce9a7 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 20:20:53 -0700 Subject: [PATCH 087/155] zkr: check extension availability in csr_mseccef permssion check --- riscv/csrs.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..a45770dd22 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -286,7 +286,8 @@ mseccfg_csr_t::mseccfg_csr_t(processor_t* const proc, const reg_t addr): void mseccfg_csr_t::verify_permissions(insn_t insn, bool write) const { basic_csr_t::verify_permissions(insn, write); if (!proc->extension_enabled(EXT_SMEPMP) && - !proc->extension_enabled(EXT_ZICFILP)) + !proc->extension_enabled(EXT_ZICFILP) && + !proc->extension_enabled(EXT_ZKR)) throw trap_illegal_instruction(insn.bits()); } From 4fe12b25db1b2f71d4cebd2c178308d90d92eec4 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 21:05:34 -0700 Subject: [PATCH 088/155] ssqosid: modify permission check condition for srmcfg The srmcfg csr number is 0x181 which is a S-mode csr The patche uses independant permission check to make the csr available even there is no S-mode --- riscv/csrs.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..fdf7b18f41 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1752,8 +1752,6 @@ srmcfg_csr_t::srmcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_ } void srmcfg_csr_t::verify_permissions(insn_t insn, bool write) const { - csr_t::verify_permissions(insn, write); - if (!proc->extension_enabled(EXT_SSQOSID)) throw trap_illegal_instruction(insn.bits()); @@ -1764,6 +1762,10 @@ void srmcfg_csr_t::verify_permissions(insn_t insn, bool write) const { if (state->v) throw trap_virtual_instruction(insn.bits()); + + if (state->prv < PRV_S) { + throw trap_illegal_instruction(insn.bits()); + } } hvip_csr_t::hvip_csr_t(processor_t* const proc, const reg_t addr, const reg_t init): From f205bc4c297bb75079eeed84d28f51db0b41c81f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:50:41 -0700 Subject: [PATCH 089/155] Add missing include --- riscv/cfg.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/riscv/cfg.cc b/riscv/cfg.cc index 67dfdb4c5d..8763240b91 100644 --- a/riscv/cfg.cc +++ b/riscv/cfg.cc @@ -1,5 +1,6 @@ // See LICENSE for license details. +#include "config.h" #include "cfg.h" #include "mmu.h" #include "decode.h" From c96f57e0bb17e805403d6e0f6bd7f8618c24cfee Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:10:58 -0700 Subject: [PATCH 090/155] Fix warning by renaming C++ source to .cc --- ci-tests/test-spike | 2 +- ci-tests/{testlib.c => testlib.cc} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename ci-tests/{testlib.c => testlib.cc} (100%) diff --git a/ci-tests/test-spike b/ci-tests/test-spike index 0540739dda..e0b9fe0063 100755 --- a/ci-tests/test-spike +++ b/ci-tests/test-spike @@ -13,7 +13,7 @@ tar xf spike-ci.tar time ../install/bin/spike --isa=rv64gc pk hello | grep "Hello, world! Pi is approximately 3.141588." # check that including sim.h in an external project works -g++ -std=c++17 -I../install/include -L../install/lib $DIR/testlib.c -lriscv -o test-libriscv +g++ -std=c++17 -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv g++ -std=c++17 -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext LD_LIBRARY_PATH=../install/lib ./test-libriscv pk hello| grep "Hello, world! Pi is approximately 3.141588." diff --git a/ci-tests/testlib.c b/ci-tests/testlib.cc similarity index 100% rename from ci-tests/testlib.c rename to ci-tests/testlib.cc From fb2adef30e75438926a74bc268aba1f355a45996 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:41:38 -0700 Subject: [PATCH 091/155] update c++ version to c++2a for CI tests --- ci-tests/test-spike | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci-tests/test-spike b/ci-tests/test-spike index e0b9fe0063..8202bcdafa 100755 --- a/ci-tests/test-spike +++ b/ci-tests/test-spike @@ -13,8 +13,8 @@ tar xf spike-ci.tar time ../install/bin/spike --isa=rv64gc pk hello | grep "Hello, world! Pi is approximately 3.141588." # check that including sim.h in an external project works -g++ -std=c++17 -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv -g++ -std=c++17 -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext +g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv +g++ -std=c++2a -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext LD_LIBRARY_PATH=../install/lib ./test-libriscv pk hello| grep "Hello, world! Pi is approximately 3.141588." LD_LIBRARY_PATH=../install/lib ./test-customext pk dummy-slliuw | grep "Executed successfully" From 238e0ac8599c3ad6a7cec8a9ede9b26a1d87688d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:42:59 -0700 Subject: [PATCH 092/155] Use "" rather than <> includes in libfdt.h --- fdt/libfdt.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fdt/libfdt.h b/fdt/libfdt.h index d2356cce43..8fb42fb684 100644 --- a/fdt/libfdt.h +++ b/fdt/libfdt.h @@ -6,8 +6,8 @@ * Copyright (C) 2006 David Gibson, IBM Corporation. */ -#include -#include +#include "libfdt_env.h" +#include "fdt.h" #define FDT_FIRST_SUPPORTED_VERSION 0x02 #define FDT_LAST_SUPPORTED_VERSION 0x11 From 8feeaf32024dd8b9f1c86879aa8c87d9b81228e9 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:43:21 -0700 Subject: [PATCH 093/155] Add include guards to entropy_source.h --- riscv/entropy_source.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/riscv/entropy_source.h b/riscv/entropy_source.h index 148e6b0529..64e12a1db0 100644 --- a/riscv/entropy_source.h +++ b/riscv/entropy_source.h @@ -1,3 +1,7 @@ +// See LICENSE for license details. + +#ifndef _RISCV_ENTROPY_SOURCE_H +#define _RISCV_ENTROPY_SOURCE_H #include #include @@ -116,3 +120,4 @@ class entropy_source { }; +#endif From 3e44fee39841e2cad52f007a7c4bd7d9ac0f812b Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:43:35 -0700 Subject: [PATCH 094/155] Don't install private softfloat headers --- softfloat/softfloat.mk.in | 5 ----- 1 file changed, 5 deletions(-) diff --git a/softfloat/softfloat.mk.in b/softfloat/softfloat.mk.in index 626b611695..e6e3998e2b 100644 --- a/softfloat/softfloat.mk.in +++ b/softfloat/softfloat.mk.in @@ -243,8 +243,3 @@ softfloat_test_srcs = softfloat_install_hdrs = \ softfloat.h \ softfloat_types.h \ - primitives.h \ - internals.h \ - platform.h \ - primitiveTypes.h \ - specialize.h \ From 97a7244371627f37f8086259002e4ed2894f5d0e Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:43:59 -0700 Subject: [PATCH 095/155] Avoid dependence on config.h in byteorder.h The runtime check will compile out. --- fesvr/byteorder.h | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/fesvr/byteorder.h b/fesvr/byteorder.h index d9e503a271..71ce515538 100644 --- a/fesvr/byteorder.h +++ b/fesvr/byteorder.h @@ -3,8 +3,8 @@ #ifndef _RISCV_BYTEORDER_H #define _RISCV_BYTEORDER_H -#include "config.h" #include +#include static inline uint8_t swap(uint8_t n) { return n; } static inline uint16_t swap(uint16_t n) { return (n >> 8) | (n << 8); } @@ -22,17 +22,11 @@ static inline uint128_t swap(uint128_t n) { return (uint128_t(swap(uint64_t(n))) static inline int128_t swap(int128_t n) { return int128_t(swap(uint128_t(n))); } #endif -#ifdef WORDS_BIGENDIAN -template static inline T from_be(T n) { return n; } -template static inline T to_be(T n) { return n; } -template static inline T from_le(T n) { return swap(n); } -template static inline T to_le(T n) { return swap(n); } -#else -template static inline T from_le(T n) { return n; } -template static inline T to_le(T n) { return n; } -template static inline T from_be(T n) { return swap(n); } -template static inline T to_be(T n) { return swap(n); } -#endif +static inline bool is_be() { return htonl(1) == 1; } +template static inline T from_be(T n) { return is_be() ? n : swap(n); } +template static inline T to_be(T n) { return from_be(n); } +template static inline T from_le(T n) { return is_be() ? swap(n) : n; } +template static inline T to_le(T n) { return from_le(n); } // Wrapper to mark a value as target endian, to guide conversion code From 77654f6011d215c930a428fbed9fd002db0df1bc Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:44:38 -0700 Subject: [PATCH 096/155] Obtain definition of reg_t in elfloader.h --- fesvr/elfloader.h | 1 + 1 file changed, 1 insertion(+) diff --git a/fesvr/elfloader.h b/fesvr/elfloader.h index 0a250cde1f..6cbdda3b39 100644 --- a/fesvr/elfloader.h +++ b/fesvr/elfloader.h @@ -4,6 +4,7 @@ #define _ELFLOADER_H #include "elf.h" +#include "memif.h" #include #include From a4924928a74eaa735cd0c0f94c7f74b7a1408d2c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:45:40 -0700 Subject: [PATCH 097/155] Add install-hdrs-list.h target Only used by CI tests. --- Makefile.in | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile.in b/Makefile.in index f90159e924..d2d40e1d58 100644 --- a/Makefile.in +++ b/Makefile.in @@ -385,6 +385,15 @@ install-hdrs : $(install_hdrs) $(INSTALL_HDR) $(src_dir)/$$file $(install_hdrs_dir)/`dirname $$file`; \ done +install-hdrs-list.h: $(install_hdrs) + rm -f $@.tmp + for file in $(subst $(src_dir)/,,$^); \ + do \ + $(MKINSTALLDIRS) $(install_hdrs_dir)/`dirname $$file`; \ + echo "#include <$(src_dir)/$$file>" >> $@.tmp; \ + done + mv $@.tmp $@ + install-libs : $(install_libs) $(MKINSTALLDIRS) $(install_libs_dir) for file in $^; \ From aa73432e581b978505f098f468c4868b68198308 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 16 Jul 2024 19:45:54 -0700 Subject: [PATCH 098/155] Check in CI that all installed headers are usable --- ci-tests/build-spike | 2 +- ci-tests/test-spike | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/ci-tests/build-spike b/ci-tests/build-spike index 058defdfc6..8774b5e131 100755 --- a/ci-tests/build-spike +++ b/ci-tests/build-spike @@ -11,7 +11,7 @@ mkdir install CXXFLAGS="-Wnon-virtual-dtor" CFLAGS="-Werror -Wignored-qualifiers -Wunused-function -Wunused-parameter -Wunused-variable" $DIR/../configure --prefix=`pwd`/install make -j"$(nproc 2> /dev/null || sysctl -n hw.ncpu)" make check -make install +make install install-hdrs-list.h # check that help message prints without error install/bin/spike -h diff --git a/ci-tests/test-spike b/ci-tests/test-spike index 8202bcdafa..9826232973 100755 --- a/ci-tests/test-spike +++ b/ci-tests/test-spike @@ -16,5 +16,8 @@ time ../install/bin/spike --isa=rv64gc pk hello | grep "Hello, world! Pi is app g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o test-libriscv g++ -std=c++2a -I../install/include -L../install/lib $DIR/test-customext.cc -lriscv -o test-customext +# check that all installed headers are functional +g++ -std=c++2a -I../install/include -L../install/lib $DIR/testlib.cc -lriscv -o /dev/null -include ../install-hdrs-list.h + LD_LIBRARY_PATH=../install/lib ./test-libriscv pk hello| grep "Hello, world! Pi is approximately 3.141588." LD_LIBRARY_PATH=../install/lib ./test-customext pk dummy-slliuw | grep "Executed successfully" From 08463028d68fe75d1bc59c9f20b9c86f8bd9f460 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 20:14:12 -0700 Subject: [PATCH 099/155] excp: support hardware_error_exception delegation enable M -> S and HS -> VU/VS delegation --- riscv/csrs.cc | 1 + riscv/processor.cc | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..dcd256296c 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -930,6 +930,7 @@ bool medeleg_csr_t::unlogged_write(const reg_t val) noexcept { | (1 << CAUSE_STORE_PAGE_FAULT) | (proc->extension_enabled('H') ? hypervisor_exceptions : 0) | (1 << CAUSE_SOFTWARE_CHECK_FAULT) + | (1 << CAUSE_HARDWARE_ERROR_FAULT) ; return basic_csr_t::unlogged_write((read() & ~mask) | (val & mask)); } diff --git a/riscv/processor.cc b/riscv/processor.cc index 7a6989ea67..7299548a00 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -318,7 +318,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (1 << CAUSE_FETCH_PAGE_FAULT) | (1 << CAUSE_LOAD_PAGE_FAULT) | (1 << CAUSE_STORE_PAGE_FAULT) | - (1 << CAUSE_SOFTWARE_CHECK_FAULT); + (1 << CAUSE_SOFTWARE_CHECK_FAULT) | + (1 << CAUSE_HARDWARE_ERROR_FAULT); csrmap[CSR_HEDELEG] = hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0); csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0); htimedelta = std::make_shared(proc, CSR_HTIMEDELTA, 0); From 0f0c1c1c2a43df20c7153f75f296e4363fbc6105 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 19:43:27 -0700 Subject: [PATCH 100/155] zicfiss: fix missed throw to store access fault of shadow stack page --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 8acbc2bf2c..6af88e72a0 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -496,7 +496,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) if (ss_access) { if (vm.levels == 0) - trap_store_access_fault(virt, addr, 0, 0); + throw trap_store_access_fault(virt, addr, 0, 0); type = STORE; } From e9af319bc0d0f0a08345718e398678577f88b426 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 19:54:14 -0700 Subject: [PATCH 101/155] zicfiss: modify check condicton to loads to shadow-stack pages --- riscv/mmu.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 6af88e72a0..37bdb9031c 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -526,6 +526,7 @@ reg_t mmu_t::walk(mem_access_info_t access_info) bool pbmte = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_PBMTE) : (proc->get_state()->menvcfg->read() & MENVCFG_PBMTE); bool hade = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_ADUE) : (proc->get_state()->menvcfg->read() & MENVCFG_ADUE); bool sse = virt ? (proc->get_state()->henvcfg->read() & HENVCFG_SSE) : (proc->get_state()->menvcfg->read() & MENVCFG_SSE); + bool ss_page = !(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X); if (pte & PTE_RSVD) { break; @@ -547,17 +548,17 @@ reg_t mmu_t::walk(mem_access_info_t access_info) // not shadow stack access xwr=110 or xwr=010 page cause page fault // shadow stack access with PTE_X moved to following check break; - } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && (type == STORE && !ss_access)) { + } else if (ss_page && (type == STORE && !ss_access)) { // not shadow stack store and xwr = 010 cause access-fault throw trap_store_access_fault(virt, addr, 0, 0); - } else if ((!(pte & PTE_R) && (pte & PTE_W) && !(pte & PTE_X)) && type == FETCH) { + } else if (ss_page && type == FETCH) { // fetch from shadow stack pages cause instruction access-fault throw trap_instruction_access_fault(virt, addr, 0, 0); } else if ((((pte & PTE_R) && (pte & PTE_W)) || (pte & PTE_X)) && ss_access) { // shadow stack access cause store access fault if xwr!=010 and xwr!=001 throw trap_store_access_fault(virt, addr, 0, 0); } else if (type == FETCH || hlvx ? !(pte & PTE_X) : - type == LOAD ? !(pte & PTE_R) && !(sse && (pte & PTE_W)) && !(mxr && (pte & PTE_X)) : + type == LOAD ? !(sse && ss_page) && !(pte & PTE_R) && !(mxr && (pte & PTE_X)) : !(pte & PTE_W)) { break; } else if ((ppn & ((reg_t(1) << ptshift) - 1)) != 0) { From 0a4f0b3da67f4ac47d260a38bb956686d035b3d9 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 20:57:04 -0700 Subject: [PATCH 102/155] zkr: enable write for useed/sseed fileds of mseccfg csr --- riscv/csrs.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index a45770dd22..635faae784 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -322,6 +322,11 @@ bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept { new_val |= (val & MSECCFG_MMWP); //MMWP is sticky new_val |= (val & MSECCFG_MML); //MML is sticky + if (proc->extension_enabled(EXT_ZKR)) { + uint64_t mask = MSECCFG_USEED | MSECCFG_SSEED; + new_val = (new_val & ~mask) | (val & mask); + } + proc->get_mmu()->flush_tlb(); if (proc->extension_enabled(EXT_ZICFILP)) { From 229b159465bf23b20cc29879d0c68acc8fc792f6 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 17 Jul 2024 15:22:41 +0800 Subject: [PATCH 103/155] Fix ePMP checking on hlvx instructions The hlvx instruction must grant PMP permissions of both execution and reading. Thus, with ePMP (mseccfg.MML==1), the hlvx instructions are only permitted with pmpcfg.RWXL=0111 from M-mode. --- riscv/csrs.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index b6ec20b970..56d6193626 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -197,13 +197,13 @@ bool pmpaddr_csr_t::access_ok(access_type type, reg_t mode, bool hlvx) const noe if (mseccfg_mml) { if (cfgx && cfgw && cfgr && cfgl) { // Locked Shared data region: Read only on both M and S/U mode. - return typer; + return typer && !hlvx; } else { const bool mml_shared_region = !cfgr && cfgw; const bool mml_chk_normal = (prvm == cfgl) && normal_rwx; const bool mml_chk_shared = - (!cfgl && cfgx && (typer || typew)) || - (!cfgl && !cfgx && (typer || (typew && prvm))) || + (!cfgl && cfgx && ((typer && !hlvx) || typew)) || + (!cfgl && !cfgx && ((typer && !hlvx) || (typew && prvm))) || (cfgl && typex) || (cfgl && typer && cfgx && prvm); return mml_shared_region ? mml_chk_shared : mml_chk_normal; From 6dbc8cad8affd04504688c333391be11aff7a7f4 Mon Sep 17 00:00:00 2001 From: Binno Date: Thu, 11 Jul 2024 20:47:53 -0700 Subject: [PATCH 104/155] zkr: entropy source access control for seed csr --- riscv/csrs.cc | 18 ++++++++++++++++++ riscv/csrs.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 635faae784..65d16897d6 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -303,6 +303,14 @@ bool mseccfg_csr_t::get_rlb() const noexcept { return (read() & MSECCFG_RLB); } +bool mseccfg_csr_t::get_useed() const noexcept { + return (read() & MSECCFG_USEED); +} + +bool mseccfg_csr_t::get_sseed() const noexcept { + return (read() & MSECCFG_SSEED); +} + bool mseccfg_csr_t::unlogged_write(const reg_t val) noexcept { if (proc->n_pmp == 0) return false; @@ -1440,6 +1448,16 @@ void seed_csr_t::verify_permissions(insn_t insn, bool write) const { if (!proc->extension_enabled(EXT_ZKR) || !write) throw trap_illegal_instruction(insn.bits()); csr_t::verify_permissions(insn, write); + + if (state->v) { + if (state->mseccfg->get_sseed() && write) + throw trap_virtual_instruction(insn.bits()); + else + throw trap_illegal_instruction(insn.bits()); + } else if ((state->prv == PRV_U && !state->mseccfg->get_useed()) || + (state->prv == PRV_S && !state->mseccfg->get_sseed())) { + throw trap_illegal_instruction(insn.bits()); + } } reg_t seed_csr_t::read() const noexcept { diff --git a/riscv/csrs.h b/riscv/csrs.h index ad165b6b90..fd369924a8 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -150,6 +150,8 @@ class mseccfg_csr_t: public basic_csr_t { bool get_mml() const noexcept; bool get_mmwp() const noexcept; bool get_rlb() const noexcept; + bool get_useed() const noexcept; + bool get_sseed() const noexcept; protected: virtual bool unlogged_write(const reg_t val) noexcept override; }; From ea5138d24deacf5d98acb79643a687224b3d4404 Mon Sep 17 00:00:00 2001 From: Binno Date: Wed, 10 Jul 2024 22:40:18 -0700 Subject: [PATCH 105/155] The senvcfg.SSE will read (only) as zero when menvcfg.SSE is 0 --- riscv/csrs.cc | 14 +++++++++++++- riscv/csrs.h | 9 ++++++--- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 01720eb948..149b687d88 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -1561,6 +1561,18 @@ void senvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { masked_csr_t::verify_permissions(insn, write); } +// senvcfg.sse is read_only 0 when menvcfg.sse = 0 +reg_t senvcfg_csr_t::read() const noexcept { + reg_t envcfg = state->v ? state->henvcfg->read() : state->menvcfg->read(); + return masked_csr_t::read() & ~(envcfg & MENVCFG_SSE ? 0 : MENVCFG_SSE); +} + +bool senvcfg_csr_t::unlogged_write(const reg_t val) noexcept { + reg_t envcfg = state->v ? state->henvcfg->read() : state->menvcfg->read(); + const reg_t mask = envcfg | ~MENVCFG_SSE; + return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask)); +} + void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { if (proc->extension_enabled(EXT_SMSTATEEN)) { if ((state->prv < PRV_M) && !(state->mstateen[0]->read() & MSTATEEN0_HENVCFG)) @@ -1571,7 +1583,7 @@ void henvcfg_csr_t::verify_permissions(insn_t insn, bool write) const { } bool henvcfg_csr_t::unlogged_write(const reg_t val) noexcept { - const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE); + const reg_t mask = menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE | MENVCFG_SSE); return envcfg_csr_t::unlogged_write((masked_csr_t::read() & ~mask) | (val & mask)); } diff --git a/riscv/csrs.h b/riscv/csrs.h index ad165b6b90..609af070c3 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -479,14 +479,13 @@ class envcfg_csr_t: public masked_csr_t { // henvcfg.stce is read_only 0 when menvcfg.stce = 0 // henvcfg.hade is read_only 0 when menvcfg.hade = 0 // henvcfg.dte is read_only 0 when menvcfg.dte = 0 +// henvcfg.sse is read_only 0 when menvcfg.sse = 0 class henvcfg_csr_t final: public envcfg_csr_t { public: henvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, csr_t_p menvcfg); - reg_t read() const noexcept override { - return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE)) & masked_csr_t::read(); + return (menvcfg->read() | ~(MENVCFG_PBMTE | MENVCFG_STCE | MENVCFG_ADUE | MENVCFG_DTE | MENVCFG_SSE)) & masked_csr_t::read(); } - virtual void verify_permissions(insn_t insn, bool write) const override; protected: @@ -786,7 +785,11 @@ class sstateen_csr_t: public hstateen_csr_t { class senvcfg_csr_t final: public envcfg_csr_t { public: senvcfg_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init); + reg_t read() const noexcept override; virtual void verify_permissions(insn_t insn, bool write) const override; + + protected: + virtual bool unlogged_write(const reg_t val) noexcept override; }; class stimecmp_csr_t: public basic_csr_t { From 1342c687f2b0429b3b185c9f11080300ca14529e Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 23 Jul 2024 08:42:05 +0800 Subject: [PATCH 106/155] refactor: set_fp_exceptions: Use a new macro raise_fp_exceptions(flags) and refine coding style for clearity --- riscv/decode_macros.h | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 675634a65e..8574f0d2ce 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -211,10 +211,12 @@ static inline bool is_aligned(const unsigned val, const unsigned pos) } \ } while (0); -#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \ - STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \ - } \ - softfloat_exceptionFlags = 0; }) +#define raise_fp_exceptions(flags) do { if (flags) STATE.fflags->write(STATE.fflags->read() | (flags)); } while (0); +#define set_fp_exceptions \ + do { \ + raise_fp_exceptions(softfloat_exceptionFlags); \ + softfloat_exceptionFlags = 0; \ + } while (0); #define sext32(x) ((sreg_t)(int32_t)(x)) #define zext32(x) ((reg_t)(uint32_t)(x)) From e86e653ef35fcd6de8bb2ebe701dccdb9f30a6c7 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 22 Jul 2024 17:50:54 +0800 Subject: [PATCH 107/155] fcvtmod.w.h: Not update fflags if no exception flag, e.g., exp == frac == 0 --- riscv/insns/fcvtmod_w_d.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/riscv/insns/fcvtmod_w_d.h b/riscv/insns/fcvtmod_w_d.h index e39400d27e..231f605c5a 100644 --- a/riscv/insns/fcvtmod_w_d.h +++ b/riscv/insns/fcvtmod_w_d.h @@ -55,6 +55,5 @@ if (exp == 0) { } WRITE_RD(sext32(frac)); -STATE.fflags->write(STATE.fflags->read() | - (inexact ? softfloat_flag_inexact : 0) | +raise_fp_exceptions((inexact ? softfloat_flag_inexact : 0) | (invalid ? softfloat_flag_invalid : 0)); From 94d21c99f81d28b3b28594a390c8370d4d52d583 Mon Sep 17 00:00:00 2001 From: Chih-Min Chao Date: Wed, 24 Jul 2024 18:45:26 -0700 Subject: [PATCH 108/155] svpbmt: don't reset [mh]envcfg.pbmt to 1 The part is introducd by ea70a93 to keep backward compatiable but the behavior is not mentioned and defined in spec. The patch remove this initialization part of pbmt in [mh]envcfg Signed-off-by: Chih-Min Chao --- riscv/processor.cc | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 4471fb8814..75eae5f016 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -391,8 +391,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); - const reg_t menvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0); - menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, menvcfg_init); + menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); if (xlen == 32) { csrmap[CSR_MENVCFG] = std::make_shared(proc, CSR_MENVCFG, menvcfg); csrmap[CSR_MENVCFGH] = std::make_shared(proc, CSR_MENVCFGH, menvcfg); @@ -414,8 +413,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); - const reg_t henvcfg_init = (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0); - henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, henvcfg_init, menvcfg); + henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); if (xlen == 32) { csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); From 54a5e38484a1721153404d25f7f3a92c834149a5 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 31 Jul 2024 08:15:33 +0800 Subject: [PATCH 109/155] vnclip.wx: Check if there is any vector extension before using vector CSRs --- riscv/insns/vnclip_wx.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/insns/vnclip_wx.h b/riscv/insns/vnclip_wx.h index 482eace493..fffebafcb1 100644 --- a/riscv/insns/vnclip_wx.h +++ b/riscv/insns/vnclip_wx.h @@ -1,9 +1,9 @@ // vnclip: vd[i] = clip(round(vs2[i] + rnd) >> rs1[i]) -VRM xrm = P.VU.get_vround_mode(); -int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); -int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); VI_VX_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); + int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); int128_t result = vs2; unsigned shift = rs1 & ((sew * 2) - 1); From e9f620ffb53889be2de8997f2f48053160e3b5b6 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 31 Jul 2024 13:36:22 +0800 Subject: [PATCH 110/155] vector: Check if there is any vector extension before using vector CSRs --- riscv/insns/vnclip_wi.h | 6 +++--- riscv/insns/vnclip_wv.h | 6 +++--- riscv/insns/vnclipu_wi.h | 6 +++--- riscv/insns/vnclipu_wv.h | 6 +++--- riscv/insns/vnclipu_wx.h | 6 +++--- riscv/insns/vsmul_vv.h | 8 ++++---- riscv/insns/vsmul_vx.h | 8 ++++---- riscv/insns/vssra_vi.h | 2 +- riscv/insns/vssra_vv.h | 2 +- riscv/insns/vssra_vx.h | 2 +- riscv/insns/vssrl_vi.h | 2 +- riscv/insns/vssrl_vv.h | 2 +- riscv/insns/vssrl_vx.h | 2 +- riscv/v_ext_macros.h | 8 ++++---- 14 files changed, 33 insertions(+), 33 deletions(-) diff --git a/riscv/insns/vnclip_wi.h b/riscv/insns/vnclip_wi.h index ea6898cf50..4805173c92 100644 --- a/riscv/insns/vnclip_wi.h +++ b/riscv/insns/vnclip_wi.h @@ -1,9 +1,9 @@ // vnclip: vd[i] = clip(round(vs2[i] + rnd) >> simm) -VRM xrm = P.VU.get_vround_mode(); -int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); -int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); VI_VI_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); + int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); int128_t result = vs2; unsigned shift = zimm5 & ((sew * 2) - 1); diff --git a/riscv/insns/vnclip_wv.h b/riscv/insns/vnclip_wv.h index 63b84c6582..1f7558a6d3 100644 --- a/riscv/insns/vnclip_wv.h +++ b/riscv/insns/vnclip_wv.h @@ -1,9 +1,9 @@ // vnclip: vd[i] = clip(round(vs2[i] + rnd) >> vs1[i]) -VRM xrm = P.VU.get_vround_mode(); -int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); -int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); VI_VV_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); + int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); int128_t result = vs2; unsigned shift = vs1 & ((sew * 2) - 1); diff --git a/riscv/insns/vnclipu_wi.h b/riscv/insns/vnclipu_wi.h index 441a3a7d61..10735bacac 100644 --- a/riscv/insns/vnclipu_wi.h +++ b/riscv/insns/vnclipu_wi.h @@ -1,9 +1,9 @@ // vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> simm) -VRM xrm = P.VU.get_vround_mode(); -uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); -uint64_t sign_mask = UINT64_MAX << P.VU.vsew; VI_VI_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); + uint64_t sign_mask = UINT64_MAX << P.VU.vsew; uint128_t result = vs2_u; unsigned shift = zimm5 & ((sew * 2) - 1); diff --git a/riscv/insns/vnclipu_wv.h b/riscv/insns/vnclipu_wv.h index 8072489904..0e3e8b09d5 100644 --- a/riscv/insns/vnclipu_wv.h +++ b/riscv/insns/vnclipu_wv.h @@ -1,9 +1,9 @@ // vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> vs1[i]) -VRM xrm = P.VU.get_vround_mode(); -uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); -uint64_t sign_mask = UINT64_MAX << P.VU.vsew; VI_VV_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); + uint64_t sign_mask = UINT64_MAX << P.VU.vsew; uint128_t result = vs2_u; unsigned shift = vs1 & ((sew * 2) - 1); diff --git a/riscv/insns/vnclipu_wx.h b/riscv/insns/vnclipu_wx.h index b2d91c3339..d7c6bea5e1 100644 --- a/riscv/insns/vnclipu_wx.h +++ b/riscv/insns/vnclipu_wx.h @@ -1,9 +1,9 @@ // vnclipu: vd[i] = clip(round(vs2[i] + rnd) >> rs1[i]) -VRM xrm = P.VU.get_vround_mode(); -uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); -uint64_t sign_mask = UINT64_MAX << P.VU.vsew; VI_VX_LOOP_NARROW ({ + VRM xrm = P.VU.get_vround_mode(); + uint64_t uint_max = UINT64_MAX >> (64 - P.VU.vsew); + uint64_t sign_mask = UINT64_MAX << P.VU.vsew; uint128_t result = vs2_u; unsigned shift = rs1 & ((sew * 2) - 1); diff --git a/riscv/insns/vsmul_vv.h b/riscv/insns/vsmul_vv.h index 49e42c1fa6..c1d0a57097 100644 --- a/riscv/insns/vsmul_vv.h +++ b/riscv/insns/vsmul_vv.h @@ -1,10 +1,10 @@ // vsmul.vv vd, vs2, vs1 -VRM xrm = P.VU.get_vround_mode(); -int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); -int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); - VI_VV_LOOP ({ + VRM xrm = P.VU.get_vround_mode(); + int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); + int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); + bool overflow = vs1 == vs2 && vs1 == int_min; int128_t result = (int128_t)vs1 * (int128_t)vs2; diff --git a/riscv/insns/vsmul_vx.h b/riscv/insns/vsmul_vx.h index d2724eee4e..c2e531cbc1 100644 --- a/riscv/insns/vsmul_vx.h +++ b/riscv/insns/vsmul_vx.h @@ -1,10 +1,10 @@ // vsmul.vx vd, vs2, rs1 -VRM xrm = P.VU.get_vround_mode(); -int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); -int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); - VI_VX_LOOP ({ + VRM xrm = P.VU.get_vround_mode(); + int64_t int_max = INT64_MAX >> (64 - P.VU.vsew); + int64_t int_min = INT64_MIN >> (64 - P.VU.vsew); + bool overflow = rs1 == vs2 && rs1 == int_min; int128_t result = (int128_t)rs1 * (int128_t)vs2; diff --git a/riscv/insns/vssra_vi.h b/riscv/insns/vssra_vi.h index ff2e1c585c..64a41a7c0a 100644 --- a/riscv/insns/vssra_vi.h +++ b/riscv/insns/vssra_vi.h @@ -1,7 +1,7 @@ // vssra.vi vd, vs2, simm5 -VRM xrm = P.VU.get_vround_mode(); VI_VI_LOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = simm5 & (sew - 1) & 0x1f; int128_t val = vs2; diff --git a/riscv/insns/vssra_vv.h b/riscv/insns/vssra_vv.h index 7bbc766ff1..babca47701 100644 --- a/riscv/insns/vssra_vv.h +++ b/riscv/insns/vssra_vv.h @@ -1,7 +1,7 @@ // vssra.vv vd, vs2, vs1 -VRM xrm = P.VU.get_vround_mode(); VI_VV_LOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = vs1 & (sew - 1); int128_t val = vs2; diff --git a/riscv/insns/vssra_vx.h b/riscv/insns/vssra_vx.h index 068a22b692..3d70726847 100644 --- a/riscv/insns/vssra_vx.h +++ b/riscv/insns/vssra_vx.h @@ -1,7 +1,7 @@ // vssra.vx vd, vs2, rs1 -VRM xrm = P.VU.get_vround_mode(); VI_VX_LOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = rs1 & (sew - 1); int128_t val = vs2; diff --git a/riscv/insns/vssrl_vi.h b/riscv/insns/vssrl_vi.h index d125164d6a..99902353c4 100644 --- a/riscv/insns/vssrl_vi.h +++ b/riscv/insns/vssrl_vi.h @@ -1,7 +1,7 @@ // vssra.vi vd, vs2, simm5 -VRM xrm = P.VU.get_vround_mode(); VI_VI_ULOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = zimm5 & (sew - 1) & 0x1f; uint128_t val = vs2; diff --git a/riscv/insns/vssrl_vv.h b/riscv/insns/vssrl_vv.h index a8e5d16423..f8924baf6a 100644 --- a/riscv/insns/vssrl_vv.h +++ b/riscv/insns/vssrl_vv.h @@ -1,7 +1,7 @@ // vssrl.vv vd, vs2, vs1 -VRM xrm = P.VU.get_vround_mode(); VI_VV_ULOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = vs1 & (sew - 1); uint128_t val = vs2; diff --git a/riscv/insns/vssrl_vx.h b/riscv/insns/vssrl_vx.h index ee3cb3462f..04468d57e7 100644 --- a/riscv/insns/vssrl_vx.h +++ b/riscv/insns/vssrl_vx.h @@ -1,7 +1,7 @@ // vssrl.vx vd, vs2, rs1 -VRM xrm = P.VU.get_vround_mode(); VI_VX_ULOOP ({ + VRM xrm = P.VU.get_vround_mode(); int sh = rs1 & (sew - 1); uint128_t val = vs2; diff --git a/riscv/v_ext_macros.h b/riscv/v_ext_macros.h index efec7a2c1b..b6365aa561 100644 --- a/riscv/v_ext_macros.h +++ b/riscv/v_ext_macros.h @@ -1144,32 +1144,32 @@ static inline bool is_overlapped_widen(const int astart, int asize, // average loop #define VI_VV_LOOP_AVG(op) \ -VRM xrm = p->VU.get_vround_mode(); \ VI_VV_LOOP({ \ + VRM xrm = p->VU.get_vround_mode(); \ uint128_t res = ((uint128_t)vs2) op vs1; \ INT_ROUNDING(res, xrm, 1); \ vd = res >> 1; \ }) #define VI_VX_LOOP_AVG(op) \ -VRM xrm = p->VU.get_vround_mode(); \ VI_VX_LOOP({ \ + VRM xrm = p->VU.get_vround_mode(); \ uint128_t res = ((uint128_t)vs2) op rs1; \ INT_ROUNDING(res, xrm, 1); \ vd = res >> 1; \ }) #define VI_VV_ULOOP_AVG(op) \ -VRM xrm = p->VU.get_vround_mode(); \ VI_VV_ULOOP({ \ + VRM xrm = p->VU.get_vround_mode(); \ uint128_t res = ((uint128_t)vs2) op vs1; \ INT_ROUNDING(res, xrm, 1); \ vd = res >> 1; \ }) #define VI_VX_ULOOP_AVG(op) \ -VRM xrm = p->VU.get_vround_mode(); \ VI_VX_ULOOP({ \ + VRM xrm = p->VU.get_vround_mode(); \ uint128_t res = ((uint128_t)vs2) op rs1; \ INT_ROUNDING(res, xrm, 1); \ vd = res >> 1; \ From 584f8551e6c4640c173d72908c89783591e16a2a Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Wed, 31 Jul 2024 16:42:37 -0700 Subject: [PATCH 111/155] Fix segfault accessing menvcfg when U-mode doesn't exist The simplest fix is to create the CSRs even if they don't need to exist, and just skip adding them to the CSR map to prevent the target machine from being able to access them. It looks like there are other place we should be following this pattern: e.g. why does sstatus exist if S-mode does not exist? But that's a matter for another day. Resolves #1752 --- riscv/processor.cc | 56 +++++++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 75eae5f016..33f1dd4ddd 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -381,39 +381,43 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MVENDORID] = std::make_shared(proc, CSR_MVENDORID, 0); csrmap[CSR_MHARTID] = std::make_shared(proc, CSR_MHARTID, proc->get_id()); csrmap[CSR_MCONFIGPTR] = std::make_shared(proc, CSR_MCONFIGPTR, 0); + const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | + (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | + (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); + menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); if (proc->extension_enabled_const('U')) { - const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); - menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); if (xlen == 32) { csrmap[CSR_MENVCFG] = std::make_shared(proc, CSR_MENVCFG, menvcfg); csrmap[CSR_MENVCFGH] = std::make_shared(proc, CSR_MENVCFGH, menvcfg); } else { csrmap[CSR_MENVCFG] = menvcfg; } - const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); - csrmap[CSR_SENVCFG] = senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); - const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); - henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); + } + const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); + senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); + if (proc->extension_enabled_const('S')) + csrmap[CSR_SENVCFG] = senvcfg; + const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | + (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | + (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); + henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); + if (proc->extension_enabled_const('H')) { if (xlen == 32) { csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); From a17842c0c59003aed866009c325f43c44bcce815 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 1 Aug 2024 16:48:26 +0800 Subject: [PATCH 112/155] vcompress.vm: Check if there is any vector extension before using vector CSRs --- riscv/insns/vcompress_vm.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/riscv/insns/vcompress_vm.h b/riscv/insns/vcompress_vm.h index d35b8baa12..45d2178ae2 100644 --- a/riscv/insns/vcompress_vm.h +++ b/riscv/insns/vcompress_vm.h @@ -1,13 +1,14 @@ // vcompress vd, vs2, vs1 -require(P.VU.vstart->read() == 0); -require_align(insn.rd(), P.VU.vflmul); -require_align(insn.rs2(), P.VU.vflmul); require(insn.rd() != insn.rs2()); -require_noover(insn.rd(), P.VU.vflmul, insn.rs1(), 1); reg_t pos = 0; VI_GENERAL_LOOP_BASE + require(P.VU.vstart->read() == 0); + require_align(insn.rd(), P.VU.vflmul); + require_align(insn.rs2(), P.VU.vflmul); + require_noover(insn.rd(), P.VU.vflmul, insn.rs1(), 1); + const int midx = i / 64; const int mpos = i % 64; From c536affe53f28aaf931b547a5f1b028d4b28f4f0 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 30 Jun 2024 00:08:54 -0700 Subject: [PATCH 113/155] Pass cfg into make_dts --- riscv/dts.cc | 21 ++++++++++++--------- riscv/dts.h | 7 ++----- riscv/sim.cc | 5 +---- 3 files changed, 15 insertions(+), 18 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index 8304171b56..4f62cdf446 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -13,14 +13,17 @@ #include std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, - reg_t initrd_start, reg_t initrd_end, - const char* bootargs, - size_t pmpregions, - size_t pmpgranularity, - std::vector procs, + const cfg_t* cfg, + const isa_parser_t* isa, std::vector> mems, std::string device_nodes) { + reg_t initrd_start = cfg->initrd_bounds.first; + reg_t initrd_end = cfg->initrd_bounds.second; + const char* bootargs = cfg->bootargs; + reg_t pmpregions = cfg->pmpregions; + reg_t pmpgranularity = cfg->pmpgranularity; + std::stringstream s; s << std::dec << "/dts-v1/;\n" @@ -54,14 +57,14 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, " #address-cells = <1>;\n" " #size-cells = <0>;\n" " timebase-frequency = <" << (cpu_hz/insns_per_rtc_tick) << ">;\n"; - for (size_t i = 0; i < procs.size(); i++) { + for (size_t i = 0; i < cfg->nprocs(); i++) { s << " CPU" << i << ": cpu@" << i << " {\n" " device_type = \"cpu\";\n" - " reg = <" << i << ">;\n" + " reg = <" << cfg->hartids[i] << ">;\n" " status = \"okay\";\n" " compatible = \"riscv\";\n" - " riscv,isa = \"" << procs[i]->get_isa().get_isa_string() << "\";\n" - " mmu-type = \"riscv," << (procs[i]->get_isa().get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" + " riscv,isa = \"" << isa->get_isa_string() << "\";\n" + " mmu-type = \"riscv," << (isa->get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" " riscv,pmpregions = <" << pmpregions << ">;\n" " riscv,pmpgranularity = <" << pmpgranularity << ">;\n" " clock-frequency = <" << cpu_hz << ">;\n" diff --git a/riscv/dts.h b/riscv/dts.h index 7afe376cbc..73c0a0234b 100644 --- a/riscv/dts.h +++ b/riscv/dts.h @@ -7,11 +7,8 @@ #include std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, - reg_t initrd_start, reg_t initrd_end, - const char* bootargs, - size_t pmpregions, - size_t pmpgranularity, - std::vector procs, + const cfg_t* cfg, + const isa_parser_t* isa, std::vector> mems, std::string device_nodes); diff --git a/riscv/sim.cc b/riscv/sim.cc index d08e274d9d..3b46338319 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -141,10 +141,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, const std::vector& sargs = factory_sargs.second; device_nodes.append(factory->generate_dts(this, sargs)); } - dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, - initrd_bounds.first, initrd_bounds.second, - cfg->bootargs, cfg->pmpregions, cfg->pmpgranularity, - procs, mems, device_nodes); + dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, &isa, mems, device_nodes); dtb = dts_compile(dts); } From 6f4116d340b578e5d18a583c313008b7b17bd6da Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 30 Jun 2024 14:27:57 -0700 Subject: [PATCH 114/155] Move isa property to a field of processor_t, not sim_t This incidentally makes it easier to support heterogeneous-hart configs in the future --- riscv/dts.cc | 6 +++--- riscv/dts.h | 1 - riscv/processor.cc | 39 +++++++++++++++++----------------- riscv/processor.h | 9 ++++---- riscv/sim.cc | 8 +++---- riscv/sim.h | 1 - spike_main/spike-log-parser.cc | 2 +- 7 files changed, 33 insertions(+), 33 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index 4f62cdf446..a195257dca 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -14,7 +14,6 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, const cfg_t* cfg, - const isa_parser_t* isa, std::vector> mems, std::string device_nodes) { @@ -23,6 +22,7 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, const char* bootargs = cfg->bootargs; reg_t pmpregions = cfg->pmpregions; reg_t pmpgranularity = cfg->pmpgranularity; + isa_parser_t isa(cfg->isa, cfg->priv); std::stringstream s; s << std::dec << @@ -63,8 +63,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, " reg = <" << cfg->hartids[i] << ">;\n" " status = \"okay\";\n" " compatible = \"riscv\";\n" - " riscv,isa = \"" << isa->get_isa_string() << "\";\n" - " mmu-type = \"riscv," << (isa->get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" + " riscv,isa = \"" << isa.get_isa_string() << "\";\n" + " mmu-type = \"riscv," << (isa.get_max_xlen() <= 32 ? "sv32" : "sv57") << "\";\n" " riscv,pmpregions = <" << pmpregions << ">;\n" " riscv,pmpgranularity = <" << pmpgranularity << ">;\n" " clock-frequency = <" << cpu_hz << ">;\n" diff --git a/riscv/dts.h b/riscv/dts.h index 73c0a0234b..93a0b15c69 100644 --- a/riscv/dts.h +++ b/riscv/dts.h @@ -8,7 +8,6 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, const cfg_t* cfg, - const isa_parser_t* isa, std::vector> mems, std::string device_nodes); diff --git a/riscv/processor.cc b/riscv/processor.cc index 33f1dd4ddd..991cd736c9 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -30,49 +30,50 @@ #undef STATE #define STATE state -processor_t::processor_t(const isa_parser_t *isa, const cfg_t *cfg, +processor_t::processor_t(const char* isa_str, const char* priv_str, + const cfg_t *cfg, simif_t* sim, uint32_t id, bool halt_on_reset, FILE* log_file, std::ostream& sout_) - : debug(false), halt_request(HR_NONE), isa(isa), cfg(cfg), sim(sim), id(id), xlen(0), +: debug(false), halt_request(HR_NONE), isa(isa_str, priv_str), cfg(cfg), sim(sim), id(id), xlen(0), histogram_enabled(false), log_commits_enabled(false), log_file(log_file), sout_(sout_.rdbuf()), halt_on_reset(halt_on_reset), in_wfi(false), check_triggers_icount(false), - impl_table(256, false), extension_enable_table(isa->get_extension_table()), + impl_table(256, false), extension_enable_table(isa.get_extension_table()), last_pc(1), executions(1), TM(cfg->trigger_count) { VU.p = this; TM.proc = this; #ifndef HAVE_INT128 - if (isa->has_any_vector()) { + if (isa.has_any_vector()) { fprintf(stderr, "V extension is not supported on platforms without __int128 type\n"); abort(); } - if (isa->extension_enabled(EXT_ZACAS) && isa->get_max_xlen() == 64) { + if (isa.extension_enabled(EXT_ZACAS) && isa.get_max_xlen() == 64) { fprintf(stderr, "Zacas extension is not supported on 64-bit platforms without __int128 type\n"); abort(); } #endif - VU.VLEN = isa->get_vlen(); - VU.ELEN = isa->get_elen(); - VU.vlenb = isa->get_vlen() / 8; + VU.VLEN = isa.get_vlen(); + VU.ELEN = isa.get_elen(); + VU.vlenb = isa.get_vlen() / 8; VU.vstart_alu = 0; register_base_instructions(); mmu = new mmu_t(sim, cfg->endianness, this); - disassembler = new disassembler_t(isa); - for (auto e : isa->get_extensions()) + disassembler = new disassembler_t(&isa); + for (auto e : isa.get_extensions()) register_extension(find_extension(e.c_str())()); set_pmp_granularity(cfg->pmpgranularity); set_pmp_num(cfg->pmpregions); - if (isa->get_max_xlen() == 32) + if (isa.get_max_xlen() == 32) set_mmu_capability(IMPL_MMU_SV32); - else if (isa->get_max_xlen() == 64) + else if (isa.get_max_xlen() == 64) set_mmu_capability(IMPL_MMU_SV57); set_impl(IMPL_MMU_ASID, true); @@ -575,8 +576,8 @@ void processor_t::enable_log_commits() void processor_t::reset() { - xlen = isa->get_max_xlen(); - state.reset(this, isa->get_max_isa()); + xlen = isa.get_max_xlen(); + state.reset(this, isa.get_max_isa()); state.dcsr->halt = halt_on_reset; halt_on_reset = false; if (any_vector_extensions()) @@ -724,7 +725,7 @@ void processor_t::take_interrupt(reg_t pending_interrupts) abort(); if (check_triggers_icount) TM.detect_icount_match(); - throw trap_t(((reg_t)1 << (isa->get_max_xlen() - 1)) | ctz(enabled_interrupts)); + throw trap_t(((reg_t)1 << (isa.get_max_xlen() - 1)) | ctz(enabled_interrupts)); } } @@ -796,7 +797,7 @@ void processor_t::debug_output_log(std::stringstream *s) void processor_t::take_trap(trap_t& t, reg_t epc) { - unsigned max_xlen = isa->get_max_xlen(); + unsigned max_xlen = isa.get_max_xlen(); if (debug) { std::stringstream s; // first put everything in a string, later send it to output @@ -974,7 +975,7 @@ void processor_t::disasm(insn_t insn) << ": Executed " << executions << " times" << std::endl; } - unsigned max_xlen = isa->get_max_xlen(); + unsigned max_xlen = isa.get_max_xlen(); s << "core " << std::dec << std::setfill(' ') << std::setw(3) << id << std::hex << ": 0x" << std::setfill('0') << std::setw(max_xlen / 4) @@ -993,7 +994,7 @@ void processor_t::disasm(insn_t insn) int processor_t::paddr_bits() { - unsigned max_xlen = isa->get_max_xlen(); + unsigned max_xlen = isa.get_max_xlen(); assert(xlen == max_xlen); return max_xlen == 64 ? 50 : 34; } @@ -1120,7 +1121,7 @@ void processor_t::register_base_instructions() // add overlapping instructions first, in order #define DECLARE_OVERLAP_INSN(name, ext) \ name##_overlapping = true; \ - if (isa->extension_enabled(ext)) \ + if (isa.extension_enabled(ext)) \ register_base_insn((insn_desc_t) { \ name##_match, \ name##_mask, \ diff --git a/riscv/processor.h b/riscv/processor.h index 14b828cfef..352af537b3 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -236,12 +236,13 @@ class opcode_cache_entry_t { class processor_t : public abstract_device_t { public: - processor_t(const isa_parser_t *isa, const cfg_t* cfg, + processor_t(const char* isa_str, const char* priv_str, + const cfg_t* cfg, simif_t* sim, uint32_t id, bool halt_on_reset, FILE *log_file, std::ostream& sout_); // because of command line option --log and -s we need both ~processor_t(); - const isa_parser_t &get_isa() { return *isa; } + const isa_parser_t &get_isa() { return isa; } const cfg_t &get_cfg() { return *cfg; } void set_debug(bool value); @@ -303,7 +304,7 @@ class processor_t : public abstract_device_t void set_extension_enable(unsigned char ext, bool enable) { assert(!extension_assumed_const[ext]); extension_dynamic[ext] = true; - extension_enable_table[ext] = enable && isa->extension_enabled(ext); + extension_enable_table[ext] = enable && isa.extension_enabled(ext); } void set_impl(uint8_t impl, bool val) { impl_table[impl] = val; } bool supports_impl(uint8_t impl) const { @@ -362,7 +363,7 @@ class processor_t : public abstract_device_t void check_if_lpad_required(); private: - const isa_parser_t * const isa; + const isa_parser_t isa; const cfg_t * const cfg; simif_t* sim; diff --git a/riscv/sim.cc b/riscv/sim.cc index 3b46338319..1c1f65ad7b 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -46,7 +46,6 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, bool socket_enabled, FILE *cmd_file) // needed for command line option --cmd : htif_t(args), - isa(cfg->isa, cfg->priv), cfg(cfg), mems(mems), procs(std::max(cfg->nprocs(), size_t(1))), @@ -99,7 +98,8 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, debug_mmu = new mmu_t(this, cfg->endianness, NULL); for (size_t i = 0; i < cfg->nprocs(); i++) { - procs[i] = new processor_t(&isa, cfg, this, cfg->hartids[i], halted, + procs[i] = new processor_t(cfg->isa, cfg->priv, + cfg, this, cfg->hartids[i], halted, log_file.get(), sout_); harts[cfg->hartids[i]] = procs[i]; } @@ -141,7 +141,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, const std::vector& sargs = factory_sargs.second; device_nodes.append(factory->generate_dts(this, sargs)); } - dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, &isa, mems, device_nodes); + dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes); dtb = dts_compile(dts); } @@ -253,7 +253,7 @@ int sim_t::run() if (!debug && log) set_procs_debug(true); - htif_t::set_expected_xlen(isa.get_max_xlen()); + htif_t::set_expected_xlen(harts[0]->get_isa().get_max_xlen()); // htif_t::run() will repeatedly call back into sim_t::idle(), each // invocation of which will advance target time diff --git a/riscv/sim.h b/riscv/sim.h index 540d80d857..93a2c21dde 100644 --- a/riscv/sim.h +++ b/riscv/sim.h @@ -69,7 +69,6 @@ class sim_t : public htif_t, public simif_t static const size_t CPU_HZ = 1000000000; // 1GHz CPU private: - isa_parser_t isa; const cfg_t * const cfg; std::vector> mems; std::vector procs; diff --git a/spike_main/spike-log-parser.cc b/spike_main/spike-log-parser.cc index a054e95a69..55ff9998b3 100644 --- a/spike_main/spike-log-parser.cc +++ b/spike_main/spike-log-parser.cc @@ -31,7 +31,7 @@ int main(int UNUSED argc, char** argv) cfg_t cfg; isa_parser_t isa(isa_string, DEFAULT_PRIV); - processor_t p(&isa, &cfg, 0, 0, false, nullptr, cerr); + processor_t p(isa_string, DEFAULT_PRIV, &cfg, 0, 0, false, nullptr, cerr); if (extension) { p.register_extension(extension()); } From f11bd7b511d7909f0291589e3aaab720ededdc8a Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 30 Jun 2024 14:55:46 -0700 Subject: [PATCH 115/155] Support parsing procs fully from DTS --- riscv/dts.cc | 41 +++++++++++++++++++++++ riscv/dts.h | 2 ++ riscv/sim.cc | 92 ++++++++++++++++++++++++++++++---------------------- 3 files changed, 97 insertions(+), 38 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index a195257dca..7f50dd822e 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -389,3 +389,44 @@ int fdt_parse_mmu_type(const void *fdt, int cpu_offset, const char **mmu_type) return 0; } + +int fdt_parse_isa(const void *fdt, int cpu_offset, const char **isa) +{ + assert(isa); + + int len, rc; + const void *prop; + + if ((rc = check_cpu_node(fdt, cpu_offset)) < 0) + return rc; + + prop = fdt_getprop(fdt, cpu_offset, "riscv,isa", &len); + if (!prop || !len) + return -EINVAL; + + *isa = (const char *)prop; + + return 0; +} + +int fdt_parse_hartid(const void *fdt, int cpu_offset, uint32_t *hartid) +{ + int len, rc; + const void *prop; + const fdt32_t *val; + + if ((rc = check_cpu_node(fdt, cpu_offset)) < 0) + return rc; + + val = (fdt32_t*) fdt_getprop(fdt, cpu_offset, "reg", &len); + if (!val || len < (int) sizeof(fdt32_t)) + return -EINVAL; + + if (len > (int) sizeof(fdt32_t)) + val++; + + if (hartid) + *hartid = fdt32_to_cpu(*val); + + return 0; +} diff --git a/riscv/dts.h b/riscv/dts.h index 93a0b15c69..d58093bee7 100644 --- a/riscv/dts.h +++ b/riscv/dts.h @@ -29,4 +29,6 @@ int fdt_parse_ns16550(const void *fdt, reg_t *ns16550_addr, int fdt_parse_pmp_num(const void *fdt, int cpu_offset, reg_t *pmp_num); int fdt_parse_pmp_alignment(const void *fdt, int cpu_offset, reg_t *pmp_align); int fdt_parse_mmu_type(const void *fdt, int cpu_offset, const char **mmu_type); +int fdt_parse_isa(const void *fdt, int cpu_offset, const char **isa_str); +int fdt_parse_hartid(const void *fdt, int cpu_offset, uint32_t *hartid); #endif diff --git a/riscv/sim.cc b/riscv/sim.cc index 1c1f65ad7b..b0355ae45a 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -48,7 +48,6 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, : htif_t(args), cfg(cfg), mems(mems), - procs(std::max(cfg->nprocs(), size_t(1))), dtb_enabled(dtb_enabled), log_file(log_path), cmd_file(cmd_file), @@ -97,15 +96,16 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, debug_mmu = new mmu_t(this, cfg->endianness, NULL); - for (size_t i = 0; i < cfg->nprocs(); i++) { - procs[i] = new processor_t(cfg->isa, cfg->priv, - cfg, this, cfg->hartids[i], halted, - log_file.get(), sout_); - harts[cfg->hartids[i]] = procs[i]; - } - // When running without using a dtb, skip the fdt-based configuration steps - if (!dtb_enabled) return; + if (!dtb_enabled) { + for (size_t i = 0; i < cfg->nprocs(); i++) { + procs.push_back(new processor_t(cfg->isa, cfg->priv, + cfg, this, cfg->hartids[i], halted, + log_file.get(), sout_)); + harts[cfg->hartids[i]] = procs[i]; + return; + } + } // otherwise, generate the procs by parsing the DTS // Only make a CLINT (Core-Local INTerrupt controller) and PLIC (Platform- // Level-Interrupt-Controller) if they are specified in the device tree @@ -159,24 +159,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, void *fdt = (void *)dtb.c_str(); - for (size_t i = 0; i < device_factories.size(); i++) { - const device_factory_t* factory = device_factories[i].first; - const std::vector& sargs = device_factories[i].second; - reg_t device_base = 0; - abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs); - if (device) { - assert(device_base); - std::shared_ptr dev_ptr(device); - add_device(device_base, dev_ptr); - - if (i == 0) // clint_factory - clint = std::static_pointer_cast(dev_ptr); - else if (i == 1) // plic_factory - plic = std::static_pointer_cast(dev_ptr); - } - } - - //per core attribute + // per core attribute int cpu_offset = 0, cpu_map_offset, rc; size_t cpu_idx = 0; cpu_offset = fdt_get_offset(fdt, "/cpus"); @@ -190,10 +173,33 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, if (!(cpu_map_offset < 0) && cpu_offset == cpu_map_offset) continue; - if (cpu_idx >= nprocs()) - break; + if (cpu_idx != procs.size()) { + std::cerr << "Spike only supports contiguous CPU IDs in the DTS" << std::endl; + exit(1); + } - //handle pmp + // handle isa string + const char* isa_str; + rc = fdt_parse_isa(fdt, cpu_offset, &isa_str); + if (rc != 0) { + std::cerr << "core (" << cpu_idx << ") has an invalid or missing 'riscv,isa'\n"; + exit(1); + } + + // handle hartid + uint32_t hartid; + rc = fdt_parse_hartid(fdt, cpu_offset, &hartid); + if (rc != 0) { + std::cerr << "core (" << cpu_idx << ") has an invalid or missing `reg` (hartid)\n"; + exit(1); + } + + procs.push_back(new processor_t(isa_str, DEFAULT_PRIV, + cfg, this, hartid, halted, + log_file.get(), sout_)); + harts[hartid] = procs[cpu_idx]; + + // handle pmp reg_t pmp_num, pmp_granularity; if (fdt_parse_pmp_num(fdt, cpu_offset, &pmp_num) != 0) pmp_num = 0; @@ -203,7 +209,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, procs[cpu_idx]->set_pmp_granularity(pmp_granularity); } - //handle mmu-type + // handle mmu-type const char *mmu_type; rc = fdt_parse_mmu_type(fdt, cpu_offset, &mmu_type); if (rc == 0) { @@ -217,7 +223,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, } else if (strncmp(mmu_type, "riscv,sv57", strlen("riscv,sv57")) == 0) { procs[cpu_idx]->set_mmu_capability(IMPL_MMU_SV57); } else if (strncmp(mmu_type, "riscv,sbare", strlen("riscv,sbare")) == 0) { - //has been set in the beginning + // has been set in the beginning } else { std::cerr << "core (" << cpu_idx @@ -232,12 +238,22 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, cpu_idx++; } - if (cpu_idx != nprocs()) { - std::cerr << "core number in dts (" - << cpu_idx - << ") doesn't match it in command line (" - << nprocs() << ").\n"; - exit(1); + // must be located after procs/harts are set (devices might use sim_t get_* member functions) + for (size_t i = 0; i < device_factories.size(); i++) { + const device_factory_t* factory = device_factories[i].first; + const std::vector& sargs = device_factories[i].second; + reg_t device_base = 0; + abstract_device_t* device = factory->parse_from_fdt(fdt, this, &device_base, sargs); + if (device) { + assert(device_base); + std::shared_ptr dev_ptr(device); + add_device(device_base, dev_ptr); + + if (i == 0) // clint_factory + clint = std::static_pointer_cast(dev_ptr); + else if (i == 1) // plic_factory + plic = std::static_pointer_cast(dev_ptr); + } } } From 398101b53f46c0dfdfa3c4540a8a8492aad725c0 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 3 Jul 2024 11:59:23 -0700 Subject: [PATCH 116/155] Generalize DTC compilation to support both DTS/B --- riscv/dts.cc | 87 +++++++++++++++++++++++++++------------------------- riscv/dts.h | 2 +- riscv/sim.cc | 3 +- 3 files changed, 49 insertions(+), 43 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index 7f50dd822e..7ca7c4e3fc 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -99,86 +99,91 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, return s.str(); } -std::string dts_compile(const std::string& dts) +std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type) { - // Convert the DTS to DTB - int dts_pipe[2]; - pid_t dts_pid; + if (input_type == output_type) + std::cerr << "Must have differing {in,out}put types for running " DTC << std::endl; + + if (!((input_type == "dts" && output_type == "dtb") || (input_type == "dtb" && output_type == "dts"))) + std::cerr << "Invalid {in,out}put types for running " DTC ": Must convert from 'dts' to 'dtb' (or vice versa)" << std::endl; + + int dtc_input_pipe[2]; + pid_t dtc_input_pid; fflush(NULL); // flush stdout/stderr before forking - if (pipe(dts_pipe) != 0 || (dts_pid = fork()) < 0) { - std::cerr << "Failed to fork dts child: " << strerror(errno) << std::endl; + if (pipe(dtc_input_pipe) != 0 || (dtc_input_pid = fork()) < 0) { + std::cerr << "Failed to fork dtc_input child: " << strerror(errno) << std::endl; exit(1); } - // Child process to output dts - if (dts_pid == 0) { - close(dts_pipe[0]); - int step, len = dts.length(); - const char *buf = dts.c_str(); + // Child process to output dtc_input + if (dtc_input_pid == 0) { + close(dtc_input_pipe[0]); + int step, len = dtc_input.length(); + const char *buf = dtc_input.c_str(); for (int done = 0; done < len; done += step) { - step = write(dts_pipe[1], buf+done, len-done); + step = write(dtc_input_pipe[1], buf+done, len-done); if (step == -1) { - std::cerr << "Failed to write dts: " << strerror(errno) << std::endl; + std::cerr << "Failed to write dtc_input: " << strerror(errno) << std::endl; exit(1); } } - close(dts_pipe[1]); + close(dtc_input_pipe[1]); exit(0); } - pid_t dtb_pid; - int dtb_pipe[2]; - if (pipe(dtb_pipe) != 0 || (dtb_pid = fork()) < 0) { - std::cerr << "Failed to fork dtb child: " << strerror(errno) << std::endl; + pid_t dtc_output_pid; + int dtc_output_pipe[2]; + if (pipe(dtc_output_pipe) != 0 || (dtc_output_pid = fork()) < 0) { + std::cerr << "Failed to fork dtc_output child: " << strerror(errno) << std::endl; exit(1); } - // Child process to output dtb - if (dtb_pid == 0) { - dup2(dts_pipe[0], 0); - dup2(dtb_pipe[1], 1); - close(dts_pipe[0]); - close(dts_pipe[1]); - close(dtb_pipe[0]); - close(dtb_pipe[1]); - execlp(DTC, DTC, "-O", "dtb", (char *)0); + // Child process to output dtc_output + if (dtc_output_pid == 0) { + dup2(dtc_input_pipe[0], 0); + dup2(dtc_output_pipe[1], 1); + close(dtc_input_pipe[0]); + close(dtc_input_pipe[1]); + close(dtc_output_pipe[0]); + close(dtc_output_pipe[1]); + execlp(DTC, DTC, "-O", output_type.c_str(), "-I", input_type.c_str(), (char *)0); std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl; exit(1); } - close(dts_pipe[1]); - close(dts_pipe[0]); - close(dtb_pipe[1]); + close(dtc_input_pipe[1]); + close(dtc_input_pipe[0]); + close(dtc_output_pipe[1]); - // Read-out dtb - std::stringstream dtb; + // Read-out dtc_output + std::stringstream dtc_output; int got; char buf[4096]; - while ((got = read(dtb_pipe[0], buf, sizeof(buf))) > 0) { - dtb.write(buf, got); + while ((got = read(dtc_output_pipe[0], buf, sizeof(buf))) > 0) { + dtc_output.write(buf, got); } if (got == -1) { - std::cerr << "Failed to read dtb: " << strerror(errno) << std::endl; + std::cerr << "Failed to read dtc_output: " << strerror(errno) << std::endl; exit(1); } - close(dtb_pipe[0]); + close(dtc_output_pipe[0]); // Reap children int status; - waitpid(dts_pid, &status, 0); + waitpid(dtc_input_pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - std::cerr << "Child dts process failed" << std::endl; + std::cerr << "Child dtc_input process failed" << std::endl; exit(1); } - waitpid(dtb_pid, &status, 0); + waitpid(dtc_output_pid, &status, 0); if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - std::cerr << "Child dtb process failed" << std::endl; + std::cerr << "Child dtc_output process failed" << std::endl; exit(1); } - return dtb.str(); + return dtc_output.str(); } int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr, diff --git a/riscv/dts.h b/riscv/dts.h index d58093bee7..987f2698af 100644 --- a/riscv/dts.h +++ b/riscv/dts.h @@ -11,7 +11,7 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, std::vector> mems, std::string device_nodes); -std::string dts_compile(const std::string& dts); +std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type); int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr, unsigned long *size, const char *field); diff --git a/riscv/sim.cc b/riscv/sim.cc index b0355ae45a..e9928f5c2a 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -133,6 +133,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, std::stringstream strstream; strstream << fin.rdbuf(); dtb = strstream.str(); + dts = dtc_compile(dtb, "dtb", "dts"); } else { std::pair initrd_bounds = cfg->initrd_bounds; std::string device_nodes; @@ -142,7 +143,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, device_nodes.append(factory->generate_dts(this, sargs)); } dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes); - dtb = dts_compile(dts); + dtb = dtc_compile(dts, "dts", "dtb"); } int fdt_code = fdt_check_header(dtb.c_str()); From deeda9aa9078d8cd3160b7b83453abe074c704e8 Mon Sep 17 00:00:00 2001 From: abejgonzalez Date: Wed, 3 Jul 2024 14:03:52 -0700 Subject: [PATCH 117/155] Fix trap interactive output --- riscv/interactive.cc | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/riscv/interactive.cc b/riscv/interactive.cc index 9a4b697857..2701f49308 100644 --- a/riscv/interactive.cc +++ b/riscv/interactive.cc @@ -342,8 +342,10 @@ void sim_t::interactive() (this->*funcs[cmd])(cmd, args); else out << "Unknown command " << cmd << std::endl; - } catch(trap_t& t) { + } catch(trap_interactive& t) { out << "Bad or missing arguments for command " << cmd << std::endl; + } catch(trap_t& t){ + out << "Received trap: " << t.name() << std::endl; } #ifdef HAVE_BOOST_ASIO if (socketif) @@ -473,15 +475,9 @@ void sim_t::interactive_insn(const std::string& cmd, const std::vectorget_isa().get_max_xlen(); std::ostream out(sout_.rdbuf()); - try - { - insn_t insn(get_insn(args)); - out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) - << zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl; - } - catch (trap_t& t) { - out << "Unable to obtain insn due to " << t.name() << std::endl; - } + insn_t insn(get_insn(args)); // ensure this is outside of ostream to not pollute output on non-interactive trap + out << std::hex << std::setfill('0') << "0x" << std::setw(max_xlen/4) + << zext(insn.bits(), max_xlen) << " " << p->get_disassembler()->disassemble(insn) << std::endl; } void sim_t::interactive_priv(const std::string& cmd, const std::vector& args) @@ -717,8 +713,9 @@ void sim_t::interactive_mem(const std::string& cmd, const std::vectorget_isa().get_max_xlen(); std::ostream out(sout_.rdbuf()); + reg_t mem_val = get_mem(args); // ensure this is outside of ostream to not pollute output on non-interactive trap out << std::hex << "0x" << std::setfill('0') << std::setw(max_xlen/4) - << zext(get_mem(args), max_xlen) << std::endl; + << zext(mem_val, max_xlen) << std::endl; } void sim_t::interactive_str(const std::string& cmd, const std::vector& args) From eb3ccab33e9b79e4eb502abfd5b5fbb89619dd3c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 13:24:09 -0700 Subject: [PATCH 118/155] Avoid magic constants in hpmcounter implementation --- riscv/csrs.cc | 12 ++++++------ riscv/processor.cc | 22 +++++++++++----------- riscv/processor.h | 1 + 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 3fc44e01b1..6fdd6a38c2 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -738,9 +738,9 @@ bool misa_csr_t::unlogged_write(const reg_t val) noexcept { state->mie->write_with_mask(MIP_HS_MASK, 0); // also takes care of hie, sie state->mip->write_with_mask(MIP_HS_MASK, 0); // also takes care of hip, sip, hvip state->hstatus->write(0); - for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) { - const reg_t new_mevent = state->mevent[i - 3]->read() & ~(MHPMEVENT_VUINH | MHPMEVENT_VSINH); - state->mevent[i - 3]->write(new_mevent); + for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { + const reg_t new_mevent = state->mevent[i]->read() & ~(MHPMEVENT_VUINH | MHPMEVENT_VSINH); + state->mevent[i]->write(new_mevent); } } @@ -1668,9 +1668,9 @@ void scountovf_csr_t::verify_permissions(insn_t insn, bool write) const { reg_t scountovf_csr_t::read() const noexcept { reg_t val = 0; - for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) { - bool of = state->mevent[i - 3]->read() & MHPMEVENT_OF; - val |= of << i; + for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { + bool of = state->mevent[i]->read() & MHPMEVENT_OF; + val |= of << (i + FIRST_HPMCOUNTER); } /* In M and S modes, scountovf bit X is readable when mcounteren bit X is set, */ diff --git a/riscv/processor.cc b/riscv/processor.cc index 33f1dd4ddd..e7ed2b0722 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -193,14 +193,14 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[CSR_MINSTRET] = minstret; csrmap[CSR_MCYCLE] = mcycle; } - for (reg_t i = 3; i < N_HPMCOUNTERS + 3; ++i) { - const reg_t which_mevent = CSR_MHPMEVENT3 + i - 3; - const reg_t which_meventh = CSR_MHPMEVENT3H + i - 3; - const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i - 3; - const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i - 3; - const reg_t which_counter = CSR_HPMCOUNTER3 + i - 3; - const reg_t which_counterh = CSR_HPMCOUNTER3H + i - 3; - mevent[i - 3] = std::make_shared(proc, which_mevent); + for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { + const reg_t which_mevent = CSR_MHPMEVENT3 + i; + const reg_t which_meventh = CSR_MHPMEVENT3H + i; + const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i; + const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i; + const reg_t which_counter = CSR_HPMCOUNTER3 + i; + const reg_t which_counterh = CSR_HPMCOUNTER3H + i; + mevent[i] = std::make_shared(proc, which_mevent); auto mcounter = std::make_shared(proc, which_mcounter, 0); csrmap[which_mcounter] = mcounter; @@ -209,7 +209,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[which_counter] = counter; } if (xlen == 32) { - csrmap[which_mevent] = std::make_shared(proc, which_mevent, mevent[i - 3]);; + csrmap[which_mevent] = std::make_shared(proc, which_mevent, mevent[i]);; auto mcounterh = std::make_shared(proc, which_mcounterh, 0); csrmap[which_mcounterh] = mcounterh; if (proc->extension_enabled_const(EXT_ZIHPM)) { @@ -217,11 +217,11 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) csrmap[which_counterh] = counterh; } if (proc->extension_enabled_const(EXT_SSCOFPMF)) { - auto meventh = std::make_shared(proc, which_meventh, mevent[i - 3]); + auto meventh = std::make_shared(proc, which_meventh, mevent[i]); csrmap[which_meventh] = meventh; } } else { - csrmap[which_mevent] = mevent[i - 3]; + csrmap[which_mevent] = mevent[i]; } } csrmap[CSR_MCOUNTINHIBIT] = std::make_shared(proc, CSR_MCOUNTINHIBIT, 0); diff --git a/riscv/processor.h b/riscv/processor.h index 14b828cfef..dface577a6 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -18,6 +18,7 @@ #include "../fesvr/memif.h" #include "vector_unit.h" +#define FIRST_HPMCOUNTER 3 #define N_HPMCOUNTERS 29 class processor_t; From 39ba3fe46de71ba57225dd008579ade91509efea Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 13:41:36 -0700 Subject: [PATCH 119/155] Fix enabling hypervisor extension I introduced a regression in #1753. Resolves #1755 --- riscv/processor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/processor.cc b/riscv/processor.cc index 33f1dd4ddd..4ac222210f 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -417,7 +417,7 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); - if (proc->extension_enabled_const('H')) { + if (proc->extension_enabled('H')) { if (xlen == 32) { csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); From d9f21fc2db310716df08c628c7e037d575836315 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 17:04:20 -0700 Subject: [PATCH 120/155] Improve dts <-> dtb API Avoid exposing the string args to the API. --- riscv/dts.cc | 19 +++++++++++++------ riscv/dts.h | 3 ++- riscv/sim.cc | 4 ++-- 3 files changed, 17 insertions(+), 9 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index 7ca7c4e3fc..48e538247c 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -99,13 +99,10 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, return s.str(); } -std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type) +static std::string dtc_compile(const std::string& dtc_input, bool compile) { - if (input_type == output_type) - std::cerr << "Must have differing {in,out}put types for running " DTC << std::endl; - - if (!((input_type == "dts" && output_type == "dtb") || (input_type == "dtb" && output_type == "dts"))) - std::cerr << "Invalid {in,out}put types for running " DTC ": Must convert from 'dts' to 'dtb' (or vice versa)" << std::endl; + const std::string input_type = compile ? "dts" : "dtb"; + const std::string output_type = compile ? "dtb" : "dts"; int dtc_input_pipe[2]; pid_t dtc_input_pid; @@ -186,6 +183,16 @@ std::string dtc_compile(const std::string& dtc_input, const std::string& input_t return dtc_output.str(); } +std::string dtb_to_dts(const std::string& dtc_input) +{ + return dtc_compile(dtc_input, false); +} + +std::string dts_to_dtb(const std::string& dtc_input) +{ + return dtc_compile(dtc_input, true); +} + int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr, unsigned long *size, const char *field) { diff --git a/riscv/dts.h b/riscv/dts.h index 987f2698af..730dea7765 100644 --- a/riscv/dts.h +++ b/riscv/dts.h @@ -11,7 +11,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, std::vector> mems, std::string device_nodes); -std::string dtc_compile(const std::string& dtc_input, const std::string& input_type, const std::string& output_type); +std::string dts_to_dtb(const std::string& dtc_input); +std::string dtb_to_dts(const std::string& dtc_input); int fdt_get_node_addr_size(const void *fdt, int node, reg_t *addr, unsigned long *size, const char *field); diff --git a/riscv/sim.cc b/riscv/sim.cc index e9928f5c2a..0e2717110b 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -133,7 +133,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, std::stringstream strstream; strstream << fin.rdbuf(); dtb = strstream.str(); - dts = dtc_compile(dtb, "dtb", "dts"); + dts = dtb_to_dts(dtb); } else { std::pair initrd_bounds = cfg->initrd_bounds; std::string device_nodes; @@ -143,7 +143,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, device_nodes.append(factory->generate_dts(this, sargs)); } dts = make_dts(INSNS_PER_RTC_TICK, CPU_HZ, cfg, mems, device_nodes); - dtb = dtc_compile(dts, "dts", "dtb"); + dtb = dts_to_dtb(dts); } int fdt_code = fdt_check_header(dtb.c_str()); From b9ecc1d4e5b9cc4e4c3e6793516e1809aec76762 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 17:06:49 -0700 Subject: [PATCH 121/155] In dtc_compile, use c string instead of stl string --- riscv/dts.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/riscv/dts.cc b/riscv/dts.cc index 48e538247c..9751ffeee1 100644 --- a/riscv/dts.cc +++ b/riscv/dts.cc @@ -101,8 +101,8 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz, static std::string dtc_compile(const std::string& dtc_input, bool compile) { - const std::string input_type = compile ? "dts" : "dtb"; - const std::string output_type = compile ? "dtb" : "dts"; + const char* input_type = compile ? "dts" : "dtb"; + const char* output_type = compile ? "dtb" : "dts"; int dtc_input_pipe[2]; pid_t dtc_input_pid; @@ -144,7 +144,7 @@ static std::string dtc_compile(const std::string& dtc_input, bool compile) close(dtc_input_pipe[1]); close(dtc_output_pipe[0]); close(dtc_output_pipe[1]); - execlp(DTC, DTC, "-O", output_type.c_str(), "-I", input_type.c_str(), (char *)0); + execlp(DTC, DTC, "-O", output_type, "-I", input_type, nullptr); std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl; exit(1); } From e98294c3c2ef464e233814f1cc9ce59550dba41f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 14:49:53 -0700 Subject: [PATCH 122/155] Move CSR initialization to its own file --- riscv/csr_init.cc | 401 +++++++++++++++++++++++++++++++++++++++++++++ riscv/processor.cc | 400 +------------------------------------------- riscv/processor.h | 3 + riscv/riscv.mk.in | 1 + 4 files changed, 408 insertions(+), 397 deletions(-) create mode 100644 riscv/csr_init.cc diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc new file mode 100644 index 0000000000..8cbebb9a6e --- /dev/null +++ b/riscv/csr_init.cc @@ -0,0 +1,401 @@ +#include "processor.h" +#include "debug_defines.h" + +void state_t::csr_init(processor_t* const proc, reg_t max_isa) +{ + // This assumes xlen is always max_xlen, which is true today (see + // mstatus_csr_t::unlogged_write()): + auto xlen = proc->get_isa().get_max_xlen(); + + csrmap[CSR_MISA] = misa = std::make_shared(proc, CSR_MISA, max_isa); + mstatus = std::make_shared(proc, CSR_MSTATUS); + + if (xlen == 32) { + csrmap[CSR_MSTATUS] = std::make_shared(proc, CSR_MSTATUS, mstatus); + csrmap[CSR_MSTATUSH] = mstatush = std::make_shared(proc, CSR_MSTATUSH, mstatus); + } else { + csrmap[CSR_MSTATUS] = mstatus; + } + csrmap[CSR_MEPC] = mepc = std::make_shared(proc, CSR_MEPC); + csrmap[CSR_MTVAL] = mtval = std::make_shared(proc, CSR_MTVAL, 0); + csrmap[CSR_MSCRATCH] = std::make_shared(proc, CSR_MSCRATCH, 0); + csrmap[CSR_MTVEC] = mtvec = std::make_shared(proc, CSR_MTVEC); + csrmap[CSR_MCAUSE] = mcause = std::make_shared(proc, CSR_MCAUSE); + + auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF); + const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH | + MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0; + auto minstretcfg = std::make_shared(proc, CSR_MINSTRETCFG, mask, 0); + auto mcyclecfg = std::make_shared(proc, CSR_MCYCLECFG, mask, 0); + + minstret = std::make_shared(proc, CSR_MINSTRET, minstretcfg); + mcycle = std::make_shared(proc, CSR_MCYCLE, mcyclecfg); + time = std::make_shared(proc, CSR_TIME); + if (proc->extension_enabled_const(EXT_ZICNTR)) { + csrmap[CSR_INSTRET] = std::make_shared(proc, CSR_INSTRET, minstret); + csrmap[CSR_CYCLE] = std::make_shared(proc, CSR_CYCLE, mcycle); + csrmap[CSR_TIME] = time_proxy = std::make_shared(proc, CSR_TIME, time); + } + if (xlen == 32) { + csr_t_p minstreth, mcycleh; + csrmap[CSR_MINSTRET] = std::make_shared(proc, CSR_MINSTRET, minstret); + csrmap[CSR_MINSTRETH] = minstreth = std::make_shared(proc, CSR_MINSTRETH, minstret); + csrmap[CSR_MCYCLE] = std::make_shared(proc, CSR_MCYCLE, mcycle); + csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared(proc, CSR_MCYCLEH, mcycle); + if (proc->extension_enabled_const(EXT_ZICNTR)) { + auto timeh = std::make_shared(proc, CSR_TIMEH, time); + csrmap[CSR_INSTRETH] = std::make_shared(proc, CSR_INSTRETH, minstreth); + csrmap[CSR_CYCLEH] = std::make_shared(proc, CSR_CYCLEH, mcycleh); + csrmap[CSR_TIMEH] = std::make_shared(proc, CSR_TIMEH, timeh); + } + } else { + csrmap[CSR_MINSTRET] = minstret; + csrmap[CSR_MCYCLE] = mcycle; + } + for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { + const reg_t which_mevent = CSR_MHPMEVENT3 + i; + const reg_t which_meventh = CSR_MHPMEVENT3H + i; + const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i; + const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i; + const reg_t which_counter = CSR_HPMCOUNTER3 + i; + const reg_t which_counterh = CSR_HPMCOUNTER3H + i; + mevent[i] = std::make_shared(proc, which_mevent); + auto mcounter = std::make_shared(proc, which_mcounter, 0); + csrmap[which_mcounter] = mcounter; + + if (proc->extension_enabled_const(EXT_ZIHPM)) { + auto counter = std::make_shared(proc, which_counter, mcounter); + csrmap[which_counter] = counter; + } + if (xlen == 32) { + csrmap[which_mevent] = std::make_shared(proc, which_mevent, mevent[i]);; + auto mcounterh = std::make_shared(proc, which_mcounterh, 0); + csrmap[which_mcounterh] = mcounterh; + if (proc->extension_enabled_const(EXT_ZIHPM)) { + auto counterh = std::make_shared(proc, which_counterh, mcounterh); + csrmap[which_counterh] = counterh; + } + if (proc->extension_enabled_const(EXT_SSCOFPMF)) { + auto meventh = std::make_shared(proc, which_meventh, mevent[i]); + csrmap[which_meventh] = meventh; + } + } else { + csrmap[which_mevent] = mevent[i]; + } + } + csrmap[CSR_MCOUNTINHIBIT] = std::make_shared(proc, CSR_MCOUNTINHIBIT, 0); + if (proc->extension_enabled_const(EXT_SSCOFPMF)) + csrmap[CSR_SCOUNTOVF] = std::make_shared(proc, CSR_SCOUNTOVF); + csrmap[CSR_MIE] = mie = std::make_shared(proc, CSR_MIE); + csrmap[CSR_MIP] = mip = std::make_shared(proc, CSR_MIP); + auto sip_sie_accr = std::make_shared( + this, + ~MIP_HS_MASK, // read_mask + MIP_SSIP | MIP_LCOFIP, // ip_write_mask + ~MIP_HS_MASK, // ie_write_mask + generic_int_accessor_t::mask_mode_t::MIDELEG, + 0 // shiftamt + ); + + auto hip_hie_accr = std::make_shared( + this, + MIP_HS_MASK, // read_mask + MIP_VSSIP, // ip_write_mask + MIP_HS_MASK, // ie_write_mask + generic_int_accessor_t::mask_mode_t::MIDELEG, + 0 // shiftamt + ); + + auto vsip_vsie_accr = std::make_shared( + this, + MIP_VS_MASK, // read_mask + MIP_VSSIP, // ip_write_mask + MIP_VS_MASK, // ie_write_mask + generic_int_accessor_t::mask_mode_t::HIDELEG, + 1 // shiftamt + ); + + auto nonvirtual_sip = std::make_shared(proc, CSR_SIP, sip_sie_accr); + auto vsip = std::make_shared(proc, CSR_VSIP, vsip_vsie_accr); + csrmap[CSR_VSIP] = vsip; + csrmap[CSR_SIP] = std::make_shared(proc, nonvirtual_sip, vsip); + csrmap[CSR_HIP] = std::make_shared(proc, CSR_HIP, hip_hie_accr); + csrmap[CSR_HVIP] = hvip = std::make_shared(proc, CSR_HVIP, 0); + + auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); + auto vsie = std::make_shared(proc, CSR_VSIE, vsip_vsie_accr); + csrmap[CSR_VSIE] = vsie; + csrmap[CSR_SIE] = std::make_shared(proc, nonvirtual_sie, vsie); + csrmap[CSR_HIE] = std::make_shared(proc, CSR_HIE, hip_hie_accr); + + csrmap[CSR_MEDELEG] = medeleg = std::make_shared(proc, CSR_MEDELEG); + csrmap[CSR_MIDELEG] = mideleg = std::make_shared(proc, CSR_MIDELEG); + const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); + mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0); + if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren; + csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0); + nonvirtual_sepc = std::make_shared(proc, CSR_SEPC); + csrmap[CSR_VSEPC] = vsepc = std::make_shared(proc, CSR_VSEPC); + csrmap[CSR_SEPC] = sepc = std::make_shared(proc, nonvirtual_sepc, vsepc); + nonvirtual_stval = std::make_shared(proc, CSR_STVAL, 0); + csrmap[CSR_VSTVAL] = vstval = std::make_shared(proc, CSR_VSTVAL, 0); + csrmap[CSR_STVAL] = stval = std::make_shared(proc, nonvirtual_stval, vstval); + auto sscratch = std::make_shared(proc, CSR_SSCRATCH, 0); + auto vsscratch = std::make_shared(proc, CSR_VSSCRATCH, 0); + // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt): + csrmap[CSR_SSCRATCH] = std::make_shared(proc, sscratch, vsscratch); + csrmap[CSR_VSSCRATCH] = vsscratch; + nonvirtual_stvec = std::make_shared(proc, CSR_STVEC); + csrmap[CSR_VSTVEC] = vstvec = std::make_shared(proc, CSR_VSTVEC); + csrmap[CSR_STVEC] = stvec = std::make_shared(proc, nonvirtual_stvec, vstvec); + auto nonvirtual_satp = std::make_shared(proc, CSR_SATP); + csrmap[CSR_VSATP] = vsatp = std::make_shared(proc, CSR_VSATP); + csrmap[CSR_SATP] = satp = std::make_shared(proc, nonvirtual_satp, vsatp); + nonvirtual_scause = std::make_shared(proc, CSR_SCAUSE); + csrmap[CSR_VSCAUSE] = vscause = std::make_shared(proc, CSR_VSCAUSE); + csrmap[CSR_SCAUSE] = scause = std::make_shared(proc, nonvirtual_scause, vscause); + csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); + csrmap[CSR_MTINST] = mtinst = std::make_shared(proc, CSR_MTINST); + csrmap[CSR_HSTATUS] = hstatus = std::make_shared(proc, CSR_HSTATUS); + csrmap[CSR_HGEIE] = std::make_shared(proc, CSR_HGEIE, 0); + csrmap[CSR_HGEIP] = std::make_shared(proc, CSR_HGEIP, 0); + csrmap[CSR_HIDELEG] = hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg); + const reg_t hedeleg_mask = + (1 << CAUSE_MISALIGNED_FETCH) | + (1 << CAUSE_FETCH_ACCESS) | + (1 << CAUSE_ILLEGAL_INSTRUCTION) | + (1 << CAUSE_BREAKPOINT) | + (1 << CAUSE_MISALIGNED_LOAD) | + (1 << CAUSE_LOAD_ACCESS) | + (1 << CAUSE_MISALIGNED_STORE) | + (1 << CAUSE_STORE_ACCESS) | + (1 << CAUSE_USER_ECALL) | + (1 << CAUSE_FETCH_PAGE_FAULT) | + (1 << CAUSE_LOAD_PAGE_FAULT) | + (1 << CAUSE_STORE_PAGE_FAULT) | + (1 << CAUSE_SOFTWARE_CHECK_FAULT) | + (1 << CAUSE_HARDWARE_ERROR_FAULT); + csrmap[CSR_HEDELEG] = hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0); + csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0); + htimedelta = std::make_shared(proc, CSR_HTIMEDELTA, 0); + if (xlen == 32) { + csrmap[CSR_HTIMEDELTA] = std::make_shared(proc, CSR_HTIMEDELTA, htimedelta); + csrmap[CSR_HTIMEDELTAH] = std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta); + } else { + csrmap[CSR_HTIMEDELTA] = htimedelta; + } + csrmap[CSR_HTVAL] = htval = std::make_shared(proc, CSR_HTVAL, 0); + csrmap[CSR_HTINST] = htinst = std::make_shared(proc, CSR_HTINST, 0); + csrmap[CSR_HGATP] = hgatp = std::make_shared(proc, CSR_HGATP); + nonvirtual_sstatus = std::make_shared(proc, CSR_SSTATUS, mstatus); + csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared(proc, CSR_VSSTATUS); + csrmap[CSR_SSTATUS] = sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus); + + csrmap[CSR_DPC] = dpc = std::make_shared(proc, CSR_DPC); + csrmap[CSR_DSCRATCH0] = std::make_shared(proc, CSR_DSCRATCH0); + csrmap[CSR_DSCRATCH1] = std::make_shared(proc, CSR_DSCRATCH1); + csrmap[CSR_DCSR] = dcsr = std::make_shared(proc, CSR_DCSR); + + csrmap[CSR_TSELECT] = tselect = std::make_shared(proc, CSR_TSELECT); + if (proc->get_cfg().trigger_count > 0) { + csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1); + csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2); + csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3); + csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO); + csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0); + } else { + csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1, 0); + csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2, 0); + csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3, 0); + csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO, 0); + csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, 0); + } + unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 + csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); + unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension + csrmap[CSR_HCONTEXT] = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); + csrmap[CSR_MCONTEXT] = mcontext = std::make_shared(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); + csrmap[CSR_MSECCFG] = mseccfg = std::make_shared(proc, CSR_MSECCFG); + + for (int i = 0; i < max_pmp; ++i) { + csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared(proc, CSR_PMPADDR0 + i); + } + for (int i = 0; i < max_pmp; i += xlen / 8) { + reg_t addr = CSR_PMPCFG0 + i / 4; + csrmap[addr] = std::make_shared(proc, addr); + } + + csrmap[CSR_FFLAGS] = fflags = std::make_shared(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0); + csrmap[CSR_FRM] = frm = std::make_shared(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0); + assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0 + csrmap[CSR_FCSR] = std::make_shared(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT); + + csrmap[CSR_SEED] = std::make_shared(proc, CSR_SEED); + + csrmap[CSR_MARCHID] = std::make_shared(proc, CSR_MARCHID, 5); + csrmap[CSR_MIMPID] = std::make_shared(proc, CSR_MIMPID, 0); + csrmap[CSR_MVENDORID] = std::make_shared(proc, CSR_MVENDORID, 0); + csrmap[CSR_MHARTID] = std::make_shared(proc, CSR_MHARTID, proc->get_id()); + csrmap[CSR_MCONFIGPTR] = std::make_shared(proc, CSR_MCONFIGPTR, 0); + const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | + (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | + (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); + menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); + if (proc->extension_enabled_const('U')) { + if (xlen == 32) { + csrmap[CSR_MENVCFG] = std::make_shared(proc, CSR_MENVCFG, menvcfg); + csrmap[CSR_MENVCFGH] = std::make_shared(proc, CSR_MENVCFGH, menvcfg); + } else { + csrmap[CSR_MENVCFG] = menvcfg; + } + } + const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); + senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); + if (proc->extension_enabled_const('S')) + csrmap[CSR_SENVCFG] = senvcfg; + const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | + (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | + (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | + (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | + (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | + (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | + (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | + (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | + (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); + henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); + if (proc->extension_enabled('H')) { + if (xlen == 32) { + csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); + csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); + } else { + csrmap[CSR_HENVCFG] = henvcfg; + } + } + if (proc->extension_enabled_const(EXT_SMSTATEEN)) { + const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | + (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) | + SSTATEEN0_CS; + const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; + const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0); + for (int i = 0; i < 4; i++) { + const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN; + mstateen[i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0); + if (xlen == 32) { + csrmap[CSR_MSTATEEN0 + i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen[i]); + csrmap[CSR_MSTATEEN0H + i] = std::make_shared(proc, CSR_MSTATEEN0H + i, mstateen[i]); + } else { + csrmap[CSR_MSTATEEN0 + i] = mstateen[i]; + } + + const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN; + hstateen[i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i); + if (xlen == 32) { + csrmap[CSR_HSTATEEN0 + i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i]); + csrmap[CSR_HSTATEEN0H + i] = std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i]); + } else { + csrmap[CSR_HSTATEEN0 + i] = hstateen[i]; + } + + const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0; + csrmap[CSR_SSTATEEN0 + i] = sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i); + } + } + + if (proc->extension_enabled_const(EXT_SMRNMI)) { + csrmap[CSR_MNSCRATCH] = std::make_shared(proc, CSR_MNSCRATCH, 0); + csrmap[CSR_MNEPC] = mnepc = std::make_shared(proc, CSR_MNEPC); + csrmap[CSR_MNCAUSE] = std::make_shared(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)); + csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared(proc, CSR_MNSTATUS); + } + + if (proc->extension_enabled_const(EXT_SSTC)) { + stimecmp = std::make_shared(proc, CSR_STIMECMP, MIP_STIP); + vstimecmp = std::make_shared(proc, CSR_VSTIMECMP, MIP_VSTIP); + auto virtualized_stimecmp = std::make_shared(proc, stimecmp, vstimecmp); + if (xlen == 32) { + csrmap[CSR_STIMECMP] = std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp); + csrmap[CSR_STIMECMPH] = std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp); + csrmap[CSR_VSTIMECMP] = std::make_shared(proc, CSR_VSTIMECMP, vstimecmp); + csrmap[CSR_VSTIMECMPH] = std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp); + } else { + csrmap[CSR_STIMECMP] = virtualized_stimecmp; + csrmap[CSR_VSTIMECMP] = vstimecmp; + } + } + + if (proc->extension_enabled(EXT_ZCMT)) + csrmap[CSR_JVT] = jvt = std::make_shared(proc, CSR_JVT, 0); + + if (proc->extension_enabled(EXT_ZICFISS)) { + reg_t ssp_mask = -reg_t(xlen / 8); + csrmap[CSR_SSP] = ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0); + } + + + // Smcsrind / Sscsrind + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; + sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; + + if (proc->extension_enabled_const(EXT_SMCSRIND)) { + csr_t_p miselect = std::make_shared(proc, CSR_MISELECT, 0); + csrmap[CSR_MISELECT] = miselect; + + const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; + auto i = 0; + for (auto csr : mireg_csrs) { + csrmap[csr] = mireg[i] = std::make_shared(proc, csr, miselect); + i++; + } + } + + if (proc->extension_enabled_const(EXT_SSCSRIND)) { + csr_t_p vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); + csrmap[CSR_VSISELECT] = vsiselect; + csr_t_p siselect = std::make_shared(proc, CSR_SISELECT, 0); + csrmap[CSR_SISELECT] = std::make_shared(proc, siselect, vsiselect); + + const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; + auto i = 0; + for (auto csr : vsireg_csrs) { + csrmap[csr] = vsireg[i] = std::make_shared(proc, csr, vsiselect); + i++; + } + + const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; + i = 0; + for (auto csr : sireg_csrs) { + sireg[i] = std::make_shared(proc, csr, siselect); + csrmap[csr] = std::make_shared(proc, sireg[i], vsireg[i]); + i++; + } + } + + if (smcntrpmf_enabled) { + if (xlen == 32) { + csrmap[CSR_MCYCLECFG] = std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg); + csrmap[CSR_MCYCLECFGH] = std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg); + csrmap[CSR_MINSTRETCFG] = std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg); + csrmap[CSR_MINSTRETCFGH] = std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg); + } else { + csrmap[CSR_MCYCLECFG] = mcyclecfg; + csrmap[CSR_MINSTRETCFG] = minstretcfg; + } + } + + if (proc->extension_enabled_const(EXT_SSQOSID)) { + const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; + srmcfg = std::make_shared(proc, CSR_SRMCFG, srmcfg_mask, 0); + csrmap[CSR_SRMCFG] = srmcfg; + } +} diff --git a/riscv/processor.cc b/riscv/processor.cc index f6d68b1d62..d480f8f33d 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -141,411 +141,15 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) XPR.reset(); FPR.reset(); - // This assumes xlen is always max_xlen, which is true today (see - // mstatus_csr_t::unlogged_write()): - auto xlen = proc->get_isa().get_max_xlen(); - prv = prev_prv = PRV_M; v = prev_v = false; prv_changed = false; v_changed = false; - csrmap[CSR_MISA] = misa = std::make_shared(proc, CSR_MISA, max_isa); - mstatus = std::make_shared(proc, CSR_MSTATUS); - if (xlen == 32) { - csrmap[CSR_MSTATUS] = std::make_shared(proc, CSR_MSTATUS, mstatus); - csrmap[CSR_MSTATUSH] = mstatush = std::make_shared(proc, CSR_MSTATUSH, mstatus); - } else { - csrmap[CSR_MSTATUS] = mstatus; - } - csrmap[CSR_MEPC] = mepc = std::make_shared(proc, CSR_MEPC); - csrmap[CSR_MTVAL] = mtval = std::make_shared(proc, CSR_MTVAL, 0); - csrmap[CSR_MSCRATCH] = std::make_shared(proc, CSR_MSCRATCH, 0); - csrmap[CSR_MTVEC] = mtvec = std::make_shared(proc, CSR_MTVEC); - csrmap[CSR_MCAUSE] = mcause = std::make_shared(proc, CSR_MCAUSE); - - auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF); - const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH | - MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0; - auto minstretcfg = std::make_shared(proc, CSR_MINSTRETCFG, mask, 0); - auto mcyclecfg = std::make_shared(proc, CSR_MCYCLECFG, mask, 0); - - minstret = std::make_shared(proc, CSR_MINSTRET, minstretcfg); - mcycle = std::make_shared(proc, CSR_MCYCLE, mcyclecfg); - time = std::make_shared(proc, CSR_TIME); - if (proc->extension_enabled_const(EXT_ZICNTR)) { - csrmap[CSR_INSTRET] = std::make_shared(proc, CSR_INSTRET, minstret); - csrmap[CSR_CYCLE] = std::make_shared(proc, CSR_CYCLE, mcycle); - csrmap[CSR_TIME] = time_proxy = std::make_shared(proc, CSR_TIME, time); - } - if (xlen == 32) { - csr_t_p minstreth, mcycleh; - csrmap[CSR_MINSTRET] = std::make_shared(proc, CSR_MINSTRET, minstret); - csrmap[CSR_MINSTRETH] = minstreth = std::make_shared(proc, CSR_MINSTRETH, minstret); - csrmap[CSR_MCYCLE] = std::make_shared(proc, CSR_MCYCLE, mcycle); - csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared(proc, CSR_MCYCLEH, mcycle); - if (proc->extension_enabled_const(EXT_ZICNTR)) { - auto timeh = std::make_shared(proc, CSR_TIMEH, time); - csrmap[CSR_INSTRETH] = std::make_shared(proc, CSR_INSTRETH, minstreth); - csrmap[CSR_CYCLEH] = std::make_shared(proc, CSR_CYCLEH, mcycleh); - csrmap[CSR_TIMEH] = std::make_shared(proc, CSR_TIMEH, timeh); - } - } else { - csrmap[CSR_MINSTRET] = minstret; - csrmap[CSR_MCYCLE] = mcycle; - } - for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { - const reg_t which_mevent = CSR_MHPMEVENT3 + i; - const reg_t which_meventh = CSR_MHPMEVENT3H + i; - const reg_t which_mcounter = CSR_MHPMCOUNTER3 + i; - const reg_t which_mcounterh = CSR_MHPMCOUNTER3H + i; - const reg_t which_counter = CSR_HPMCOUNTER3 + i; - const reg_t which_counterh = CSR_HPMCOUNTER3H + i; - mevent[i] = std::make_shared(proc, which_mevent); - auto mcounter = std::make_shared(proc, which_mcounter, 0); - csrmap[which_mcounter] = mcounter; - - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counter = std::make_shared(proc, which_counter, mcounter); - csrmap[which_counter] = counter; - } - if (xlen == 32) { - csrmap[which_mevent] = std::make_shared(proc, which_mevent, mevent[i]);; - auto mcounterh = std::make_shared(proc, which_mcounterh, 0); - csrmap[which_mcounterh] = mcounterh; - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counterh = std::make_shared(proc, which_counterh, mcounterh); - csrmap[which_counterh] = counterh; - } - if (proc->extension_enabled_const(EXT_SSCOFPMF)) { - auto meventh = std::make_shared(proc, which_meventh, mevent[i]); - csrmap[which_meventh] = meventh; - } - } else { - csrmap[which_mevent] = mevent[i]; - } - } - csrmap[CSR_MCOUNTINHIBIT] = std::make_shared(proc, CSR_MCOUNTINHIBIT, 0); - if (proc->extension_enabled_const(EXT_SSCOFPMF)) - csrmap[CSR_SCOUNTOVF] = std::make_shared(proc, CSR_SCOUNTOVF); - csrmap[CSR_MIE] = mie = std::make_shared(proc, CSR_MIE); - csrmap[CSR_MIP] = mip = std::make_shared(proc, CSR_MIP); - auto sip_sie_accr = std::make_shared( - this, - ~MIP_HS_MASK, // read_mask - MIP_SSIP | MIP_LCOFIP, // ip_write_mask - ~MIP_HS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::MIDELEG, - 0 // shiftamt - ); - - auto hip_hie_accr = std::make_shared( - this, - MIP_HS_MASK, // read_mask - MIP_VSSIP, // ip_write_mask - MIP_HS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::MIDELEG, - 0 // shiftamt - ); - - auto vsip_vsie_accr = std::make_shared( - this, - MIP_VS_MASK, // read_mask - MIP_VSSIP, // ip_write_mask - MIP_VS_MASK, // ie_write_mask - generic_int_accessor_t::mask_mode_t::HIDELEG, - 1 // shiftamt - ); - - auto nonvirtual_sip = std::make_shared(proc, CSR_SIP, sip_sie_accr); - auto vsip = std::make_shared(proc, CSR_VSIP, vsip_vsie_accr); - csrmap[CSR_VSIP] = vsip; - csrmap[CSR_SIP] = std::make_shared(proc, nonvirtual_sip, vsip); - csrmap[CSR_HIP] = std::make_shared(proc, CSR_HIP, hip_hie_accr); - csrmap[CSR_HVIP] = hvip = std::make_shared(proc, CSR_HVIP, 0); - - auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); - auto vsie = std::make_shared(proc, CSR_VSIE, vsip_vsie_accr); - csrmap[CSR_VSIE] = vsie; - csrmap[CSR_SIE] = std::make_shared(proc, nonvirtual_sie, vsie); - csrmap[CSR_HIE] = std::make_shared(proc, CSR_HIE, hip_hie_accr); - - csrmap[CSR_MEDELEG] = medeleg = std::make_shared(proc, CSR_MEDELEG); - csrmap[CSR_MIDELEG] = mideleg = std::make_shared(proc, CSR_MIDELEG); - const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); - mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0); - if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren; - csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0); - nonvirtual_sepc = std::make_shared(proc, CSR_SEPC); - csrmap[CSR_VSEPC] = vsepc = std::make_shared(proc, CSR_VSEPC); - csrmap[CSR_SEPC] = sepc = std::make_shared(proc, nonvirtual_sepc, vsepc); - nonvirtual_stval = std::make_shared(proc, CSR_STVAL, 0); - csrmap[CSR_VSTVAL] = vstval = std::make_shared(proc, CSR_VSTVAL, 0); - csrmap[CSR_STVAL] = stval = std::make_shared(proc, nonvirtual_stval, vstval); - auto sscratch = std::make_shared(proc, CSR_SSCRATCH, 0); - auto vsscratch = std::make_shared(proc, CSR_VSSCRATCH, 0); - // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt): - csrmap[CSR_SSCRATCH] = std::make_shared(proc, sscratch, vsscratch); - csrmap[CSR_VSSCRATCH] = vsscratch; - nonvirtual_stvec = std::make_shared(proc, CSR_STVEC); - csrmap[CSR_VSTVEC] = vstvec = std::make_shared(proc, CSR_VSTVEC); - csrmap[CSR_STVEC] = stvec = std::make_shared(proc, nonvirtual_stvec, vstvec); - auto nonvirtual_satp = std::make_shared(proc, CSR_SATP); - csrmap[CSR_VSATP] = vsatp = std::make_shared(proc, CSR_VSATP); - csrmap[CSR_SATP] = satp = std::make_shared(proc, nonvirtual_satp, vsatp); - nonvirtual_scause = std::make_shared(proc, CSR_SCAUSE); - csrmap[CSR_VSCAUSE] = vscause = std::make_shared(proc, CSR_VSCAUSE); - csrmap[CSR_SCAUSE] = scause = std::make_shared(proc, nonvirtual_scause, vscause); - csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); - csrmap[CSR_MTINST] = mtinst = std::make_shared(proc, CSR_MTINST); - csrmap[CSR_HSTATUS] = hstatus = std::make_shared(proc, CSR_HSTATUS); - csrmap[CSR_HGEIE] = std::make_shared(proc, CSR_HGEIE, 0); - csrmap[CSR_HGEIP] = std::make_shared(proc, CSR_HGEIP, 0); - csrmap[CSR_HIDELEG] = hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg); - const reg_t hedeleg_mask = - (1 << CAUSE_MISALIGNED_FETCH) | - (1 << CAUSE_FETCH_ACCESS) | - (1 << CAUSE_ILLEGAL_INSTRUCTION) | - (1 << CAUSE_BREAKPOINT) | - (1 << CAUSE_MISALIGNED_LOAD) | - (1 << CAUSE_LOAD_ACCESS) | - (1 << CAUSE_MISALIGNED_STORE) | - (1 << CAUSE_STORE_ACCESS) | - (1 << CAUSE_USER_ECALL) | - (1 << CAUSE_FETCH_PAGE_FAULT) | - (1 << CAUSE_LOAD_PAGE_FAULT) | - (1 << CAUSE_STORE_PAGE_FAULT) | - (1 << CAUSE_SOFTWARE_CHECK_FAULT) | - (1 << CAUSE_HARDWARE_ERROR_FAULT); - csrmap[CSR_HEDELEG] = hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0); - csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0); - htimedelta = std::make_shared(proc, CSR_HTIMEDELTA, 0); - if (xlen == 32) { - csrmap[CSR_HTIMEDELTA] = std::make_shared(proc, CSR_HTIMEDELTA, htimedelta); - csrmap[CSR_HTIMEDELTAH] = std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta); - } else { - csrmap[CSR_HTIMEDELTA] = htimedelta; - } - csrmap[CSR_HTVAL] = htval = std::make_shared(proc, CSR_HTVAL, 0); - csrmap[CSR_HTINST] = htinst = std::make_shared(proc, CSR_HTINST, 0); - csrmap[CSR_HGATP] = hgatp = std::make_shared(proc, CSR_HGATP); - nonvirtual_sstatus = std::make_shared(proc, CSR_SSTATUS, mstatus); - csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared(proc, CSR_VSSTATUS); - csrmap[CSR_SSTATUS] = sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus); - - csrmap[CSR_DPC] = dpc = std::make_shared(proc, CSR_DPC); - csrmap[CSR_DSCRATCH0] = std::make_shared(proc, CSR_DSCRATCH0); - csrmap[CSR_DSCRATCH1] = std::make_shared(proc, CSR_DSCRATCH1); - csrmap[CSR_DCSR] = dcsr = std::make_shared(proc, CSR_DCSR); - - csrmap[CSR_TSELECT] = tselect = std::make_shared(proc, CSR_TSELECT); - if (proc->get_cfg().trigger_count > 0) { - csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2); - csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3); - csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0); - } else { - csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1, 0); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2, 0); - csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3, 0); - csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO, 0); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, 0); - } - unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 - csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); - unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension - csrmap[CSR_HCONTEXT] = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); - csrmap[CSR_MCONTEXT] = mcontext = std::make_shared(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); + serialized = false; debug_mode = false; single_step = STEP_NONE; - csrmap[CSR_MSECCFG] = mseccfg = std::make_shared(proc, CSR_MSECCFG); - - for (int i = 0; i < max_pmp; ++i) { - csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared(proc, CSR_PMPADDR0 + i); - } - for (int i = 0; i < max_pmp; i += xlen / 8) { - reg_t addr = CSR_PMPCFG0 + i / 4; - csrmap[addr] = std::make_shared(proc, addr); - } - - csrmap[CSR_FFLAGS] = fflags = std::make_shared(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0); - csrmap[CSR_FRM] = frm = std::make_shared(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0); - assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0 - csrmap[CSR_FCSR] = std::make_shared(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT); - - csrmap[CSR_SEED] = std::make_shared(proc, CSR_SEED); - - csrmap[CSR_MARCHID] = std::make_shared(proc, CSR_MARCHID, 5); - csrmap[CSR_MIMPID] = std::make_shared(proc, CSR_MIMPID, 0); - csrmap[CSR_MVENDORID] = std::make_shared(proc, CSR_MVENDORID, 0); - csrmap[CSR_MHARTID] = std::make_shared(proc, CSR_MHARTID, proc->get_id()); - csrmap[CSR_MCONFIGPTR] = std::make_shared(proc, CSR_MCONFIGPTR, 0); - const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? MENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? MENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? MENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? MENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); - menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); - if (proc->extension_enabled_const('U')) { - if (xlen == 32) { - csrmap[CSR_MENVCFG] = std::make_shared(proc, CSR_MENVCFG, menvcfg); - csrmap[CSR_MENVCFGH] = std::make_shared(proc, CSR_MENVCFGH, menvcfg); - } else { - csrmap[CSR_MENVCFG] = menvcfg; - } - } - const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); - senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); - if (proc->extension_enabled_const('S')) - csrmap[CSR_SENVCFG] = senvcfg; - const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | - (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | - (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | - (proc->extension_enabled(EXT_SVADU) ? HENVCFG_ADUE: 0) | - (proc->extension_enabled(EXT_SVPBMT) ? HENVCFG_PBMTE : 0) | - (proc->extension_enabled(EXT_SSTC) ? HENVCFG_STCE : 0) | - (proc->extension_enabled(EXT_ZICFILP) ? HENVCFG_LPE : 0) | - (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | - (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); - henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); - if (proc->extension_enabled('H')) { - if (xlen == 32) { - csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); - csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); - } else { - csrmap[CSR_HENVCFG] = henvcfg; - } - } - if (proc->extension_enabled_const(EXT_SMSTATEEN)) { - const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | - (proc->extension_enabled(EXT_ZCMT) ? SSTATEEN0_JVT : 0) | - SSTATEEN0_CS; - const reg_t hstateen0_mask = sstateen0_mask | HSTATEEN0_SENVCFG | HSTATEEN_SSTATEEN; - const reg_t mstateen0_mask = hstateen0_mask | (proc->extension_enabled(EXT_SSQOSID) ? MSTATEEN0_PRIV114 : 0); - for (int i = 0; i < 4; i++) { - const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN; - mstateen[i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0); - if (xlen == 32) { - csrmap[CSR_MSTATEEN0 + i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen[i]); - csrmap[CSR_MSTATEEN0H + i] = std::make_shared(proc, CSR_MSTATEEN0H + i, mstateen[i]); - } else { - csrmap[CSR_MSTATEEN0 + i] = mstateen[i]; - } - - const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN; - hstateen[i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i); - if (xlen == 32) { - csrmap[CSR_HSTATEEN0 + i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i]); - csrmap[CSR_HSTATEEN0H + i] = std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i]); - } else { - csrmap[CSR_HSTATEEN0 + i] = hstateen[i]; - } - - const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0; - csrmap[CSR_SSTATEEN0 + i] = sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i); - } - } - - if (proc->extension_enabled_const(EXT_SMRNMI)) { - csrmap[CSR_MNSCRATCH] = std::make_shared(proc, CSR_MNSCRATCH, 0); - csrmap[CSR_MNEPC] = mnepc = std::make_shared(proc, CSR_MNEPC); - csrmap[CSR_MNCAUSE] = std::make_shared(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)); - csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared(proc, CSR_MNSTATUS); - } - - if (proc->extension_enabled_const(EXT_SSTC)) { - stimecmp = std::make_shared(proc, CSR_STIMECMP, MIP_STIP); - vstimecmp = std::make_shared(proc, CSR_VSTIMECMP, MIP_VSTIP); - auto virtualized_stimecmp = std::make_shared(proc, stimecmp, vstimecmp); - if (xlen == 32) { - csrmap[CSR_STIMECMP] = std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp); - csrmap[CSR_STIMECMPH] = std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp); - csrmap[CSR_VSTIMECMP] = std::make_shared(proc, CSR_VSTIMECMP, vstimecmp); - csrmap[CSR_VSTIMECMPH] = std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp); - } else { - csrmap[CSR_STIMECMP] = virtualized_stimecmp; - csrmap[CSR_VSTIMECMP] = vstimecmp; - } - } - - if (proc->extension_enabled(EXT_ZCMT)) - csrmap[CSR_JVT] = jvt = std::make_shared(proc, CSR_JVT, 0); - - if (proc->extension_enabled(EXT_ZICFISS)) { - reg_t ssp_mask = -reg_t(xlen / 8); - csrmap[CSR_SSP] = ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0); - } - - - // Smcsrind / Sscsrind - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; - - if (proc->extension_enabled_const(EXT_SMCSRIND)) { - csr_t_p miselect = std::make_shared(proc, CSR_MISELECT, 0); - csrmap[CSR_MISELECT] = miselect; - - const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; - auto i = 0; - for (auto csr : mireg_csrs) { - csrmap[csr] = mireg[i] = std::make_shared(proc, csr, miselect); - i++; - } - } - - if (proc->extension_enabled_const(EXT_SSCSRIND)) { - csr_t_p vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); - csrmap[CSR_VSISELECT] = vsiselect; - csr_t_p siselect = std::make_shared(proc, CSR_SISELECT, 0); - csrmap[CSR_SISELECT] = std::make_shared(proc, siselect, vsiselect); - - const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; - auto i = 0; - for (auto csr : vsireg_csrs) { - csrmap[csr] = vsireg[i] = std::make_shared(proc, csr, vsiselect); - i++; - } - - const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; - i = 0; - for (auto csr : sireg_csrs) { - sireg[i] = std::make_shared(proc, csr, siselect); - csrmap[csr] = std::make_shared(proc, sireg[i], vsireg[i]); - i++; - } - } - - if (smcntrpmf_enabled) { - if (xlen == 32) { - csrmap[CSR_MCYCLECFG] = std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg); - csrmap[CSR_MCYCLECFGH] = std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg); - csrmap[CSR_MINSTRETCFG] = std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg); - csrmap[CSR_MINSTRETCFGH] = std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg); - } else { - csrmap[CSR_MCYCLECFG] = mcyclecfg; - csrmap[CSR_MINSTRETCFG] = minstretcfg; - } - } - - if (proc->extension_enabled_const(EXT_SSQOSID)) { - const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; - srmcfg = std::make_shared(proc, CSR_SRMCFG, srmcfg_mask, 0); - csrmap[CSR_SRMCFG] = srmcfg; - } - - serialized = false; - log_reg_write.clear(); log_mem_read.clear(); log_mem_write.clear(); @@ -554,6 +158,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) last_inst_flen = 0; elp = elp_t::NO_LP_EXPECTED; + + csr_init(proc, max_isa); } void processor_t::set_debug(bool value) diff --git a/riscv/processor.h b/riscv/processor.h index 1e7a7421fd..cdd32d5539 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -190,6 +190,9 @@ struct state_t int last_inst_flen; elp_t elp; + + private: + void csr_init(processor_t* const proc, reg_t max_isa); }; class opcode_cache_entry_t { diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in index 60723b58e6..bc512bfa41 100644 --- a/riscv/riscv.mk.in +++ b/riscv/riscv.mk.in @@ -68,6 +68,7 @@ riscv_srcs = \ remote_bitbang.cc \ jtag_dtm.cc \ csrs.cc \ + csr_init.cc \ triggers.cc \ vector_unit.cc \ socketif.cc \ From 2597b4b4ebdcde9dc89c09937d46bf61d2039c29 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 15:07:59 -0700 Subject: [PATCH 123/155] Add CSRs through an interface, rather than mutating csrmap --- riscv/csr_init.cc | 287 ++++++++++++++++++++++--------------------- riscv/processor.h | 1 + riscv/vector_unit.cc | 16 +-- 3 files changed, 156 insertions(+), 148 deletions(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 8cbebb9a6e..80d640b72f 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -1,26 +1,31 @@ #include "processor.h" #include "debug_defines.h" +void state_t::add_csr(reg_t addr, const csr_t_p& csr) +{ + csrmap[addr] = csr; +} + void state_t::csr_init(processor_t* const proc, reg_t max_isa) { // This assumes xlen is always max_xlen, which is true today (see // mstatus_csr_t::unlogged_write()): auto xlen = proc->get_isa().get_max_xlen(); - csrmap[CSR_MISA] = misa = std::make_shared(proc, CSR_MISA, max_isa); + add_csr(CSR_MISA, misa = std::make_shared(proc, CSR_MISA, max_isa)); mstatus = std::make_shared(proc, CSR_MSTATUS); if (xlen == 32) { - csrmap[CSR_MSTATUS] = std::make_shared(proc, CSR_MSTATUS, mstatus); - csrmap[CSR_MSTATUSH] = mstatush = std::make_shared(proc, CSR_MSTATUSH, mstatus); + add_csr(CSR_MSTATUS, std::make_shared(proc, CSR_MSTATUS, mstatus)); + add_csr(CSR_MSTATUSH, mstatush = std::make_shared(proc, CSR_MSTATUSH, mstatus)); } else { - csrmap[CSR_MSTATUS] = mstatus; + add_csr(CSR_MSTATUS, mstatus); } - csrmap[CSR_MEPC] = mepc = std::make_shared(proc, CSR_MEPC); - csrmap[CSR_MTVAL] = mtval = std::make_shared(proc, CSR_MTVAL, 0); - csrmap[CSR_MSCRATCH] = std::make_shared(proc, CSR_MSCRATCH, 0); - csrmap[CSR_MTVEC] = mtvec = std::make_shared(proc, CSR_MTVEC); - csrmap[CSR_MCAUSE] = mcause = std::make_shared(proc, CSR_MCAUSE); + add_csr(CSR_MEPC, mepc = std::make_shared(proc, CSR_MEPC)); + add_csr(CSR_MTVAL, mtval = std::make_shared(proc, CSR_MTVAL, 0)); + add_csr(CSR_MSCRATCH, std::make_shared(proc, CSR_MSCRATCH, 0)); + add_csr(CSR_MTVEC, mtvec = std::make_shared(proc, CSR_MTVEC)); + add_csr(CSR_MCAUSE, mcause = std::make_shared(proc, CSR_MCAUSE)); auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF); const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH | @@ -32,25 +37,25 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) mcycle = std::make_shared(proc, CSR_MCYCLE, mcyclecfg); time = std::make_shared(proc, CSR_TIME); if (proc->extension_enabled_const(EXT_ZICNTR)) { - csrmap[CSR_INSTRET] = std::make_shared(proc, CSR_INSTRET, minstret); - csrmap[CSR_CYCLE] = std::make_shared(proc, CSR_CYCLE, mcycle); - csrmap[CSR_TIME] = time_proxy = std::make_shared(proc, CSR_TIME, time); + add_csr(CSR_INSTRET, std::make_shared(proc, CSR_INSTRET, minstret)); + add_csr(CSR_CYCLE, std::make_shared(proc, CSR_CYCLE, mcycle)); + add_csr(CSR_TIME, time_proxy = std::make_shared(proc, CSR_TIME, time)); } if (xlen == 32) { csr_t_p minstreth, mcycleh; - csrmap[CSR_MINSTRET] = std::make_shared(proc, CSR_MINSTRET, minstret); - csrmap[CSR_MINSTRETH] = minstreth = std::make_shared(proc, CSR_MINSTRETH, minstret); - csrmap[CSR_MCYCLE] = std::make_shared(proc, CSR_MCYCLE, mcycle); - csrmap[CSR_MCYCLEH] = mcycleh = std::make_shared(proc, CSR_MCYCLEH, mcycle); + add_csr(CSR_MINSTRET, std::make_shared(proc, CSR_MINSTRET, minstret)); + add_csr(CSR_MINSTRETH, minstreth = std::make_shared(proc, CSR_MINSTRETH, minstret)); + add_csr(CSR_MCYCLE, std::make_shared(proc, CSR_MCYCLE, mcycle)); + add_csr(CSR_MCYCLEH, mcycleh = std::make_shared(proc, CSR_MCYCLEH, mcycle)); if (proc->extension_enabled_const(EXT_ZICNTR)) { auto timeh = std::make_shared(proc, CSR_TIMEH, time); - csrmap[CSR_INSTRETH] = std::make_shared(proc, CSR_INSTRETH, minstreth); - csrmap[CSR_CYCLEH] = std::make_shared(proc, CSR_CYCLEH, mcycleh); - csrmap[CSR_TIMEH] = std::make_shared(proc, CSR_TIMEH, timeh); + add_csr(CSR_INSTRETH, std::make_shared(proc, CSR_INSTRETH, minstreth)); + add_csr(CSR_CYCLEH, std::make_shared(proc, CSR_CYCLEH, mcycleh)); + add_csr(CSR_TIMEH, std::make_shared(proc, CSR_TIMEH, timeh)); } } else { - csrmap[CSR_MINSTRET] = minstret; - csrmap[CSR_MCYCLE] = mcycle; + add_csr(CSR_MINSTRET, minstret); + add_csr(CSR_MCYCLE, mcycle); } for (reg_t i = 0; i < N_HPMCOUNTERS; ++i) { const reg_t which_mevent = CSR_MHPMEVENT3 + i; @@ -61,33 +66,33 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) const reg_t which_counterh = CSR_HPMCOUNTER3H + i; mevent[i] = std::make_shared(proc, which_mevent); auto mcounter = std::make_shared(proc, which_mcounter, 0); - csrmap[which_mcounter] = mcounter; + add_csr(which_mcounter, mcounter); if (proc->extension_enabled_const(EXT_ZIHPM)) { auto counter = std::make_shared(proc, which_counter, mcounter); - csrmap[which_counter] = counter; + add_csr(which_counter, counter); } if (xlen == 32) { - csrmap[which_mevent] = std::make_shared(proc, which_mevent, mevent[i]);; + add_csr(which_mevent, std::make_shared(proc, which_mevent, mevent[i])); auto mcounterh = std::make_shared(proc, which_mcounterh, 0); - csrmap[which_mcounterh] = mcounterh; + add_csr(which_mcounterh, mcounterh); if (proc->extension_enabled_const(EXT_ZIHPM)) { auto counterh = std::make_shared(proc, which_counterh, mcounterh); - csrmap[which_counterh] = counterh; + add_csr(which_counterh, counterh); } if (proc->extension_enabled_const(EXT_SSCOFPMF)) { auto meventh = std::make_shared(proc, which_meventh, mevent[i]); - csrmap[which_meventh] = meventh; + add_csr(which_meventh, meventh); } } else { - csrmap[which_mevent] = mevent[i]; + add_csr(which_mevent, mevent[i]); } } - csrmap[CSR_MCOUNTINHIBIT] = std::make_shared(proc, CSR_MCOUNTINHIBIT, 0); + add_csr(CSR_MCOUNTINHIBIT, std::make_shared(proc, CSR_MCOUNTINHIBIT, 0)); if (proc->extension_enabled_const(EXT_SSCOFPMF)) - csrmap[CSR_SCOUNTOVF] = std::make_shared(proc, CSR_SCOUNTOVF); - csrmap[CSR_MIE] = mie = std::make_shared(proc, CSR_MIE); - csrmap[CSR_MIP] = mip = std::make_shared(proc, CSR_MIP); + add_csr(CSR_SCOUNTOVF, std::make_shared(proc, CSR_SCOUNTOVF)); + add_csr(CSR_MIE, mie = std::make_shared(proc, CSR_MIE)); + add_csr(CSR_MIP, mip = std::make_shared(proc, CSR_MIP)); auto sip_sie_accr = std::make_shared( this, ~MIP_HS_MASK, // read_mask @@ -117,49 +122,50 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) auto nonvirtual_sip = std::make_shared(proc, CSR_SIP, sip_sie_accr); auto vsip = std::make_shared(proc, CSR_VSIP, vsip_vsie_accr); - csrmap[CSR_VSIP] = vsip; - csrmap[CSR_SIP] = std::make_shared(proc, nonvirtual_sip, vsip); - csrmap[CSR_HIP] = std::make_shared(proc, CSR_HIP, hip_hie_accr); - csrmap[CSR_HVIP] = hvip = std::make_shared(proc, CSR_HVIP, 0); + add_csr(CSR_VSIP, vsip); + add_csr(CSR_SIP, std::make_shared(proc, nonvirtual_sip, vsip)); + add_csr(CSR_HIP, std::make_shared(proc, CSR_HIP, hip_hie_accr)); + add_csr(CSR_HVIP, hvip = std::make_shared(proc, CSR_HVIP, 0)); auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); auto vsie = std::make_shared(proc, CSR_VSIE, vsip_vsie_accr); - csrmap[CSR_VSIE] = vsie; - csrmap[CSR_SIE] = std::make_shared(proc, nonvirtual_sie, vsie); - csrmap[CSR_HIE] = std::make_shared(proc, CSR_HIE, hip_hie_accr); + add_csr(CSR_VSIE, vsie); + add_csr(CSR_SIE, std::make_shared(proc, nonvirtual_sie, vsie)); + add_csr(CSR_HIE, std::make_shared(proc, CSR_HIE, hip_hie_accr)); - csrmap[CSR_MEDELEG] = medeleg = std::make_shared(proc, CSR_MEDELEG); - csrmap[CSR_MIDELEG] = mideleg = std::make_shared(proc, CSR_MIDELEG); + add_csr(CSR_MEDELEG, medeleg = std::make_shared(proc, CSR_MEDELEG)); + add_csr(CSR_MIDELEG, mideleg = std::make_shared(proc, CSR_MIDELEG)); const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0); - if (proc->extension_enabled_const('U')) csrmap[CSR_MCOUNTEREN] = mcounteren; - csrmap[CSR_SCOUNTEREN] = scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0); + if (proc->extension_enabled_const('U')) + add_csr(CSR_MCOUNTEREN, mcounteren); + add_csr(CSR_SCOUNTEREN, scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0)); nonvirtual_sepc = std::make_shared(proc, CSR_SEPC); - csrmap[CSR_VSEPC] = vsepc = std::make_shared(proc, CSR_VSEPC); - csrmap[CSR_SEPC] = sepc = std::make_shared(proc, nonvirtual_sepc, vsepc); + add_csr(CSR_VSEPC, vsepc = std::make_shared(proc, CSR_VSEPC)); + add_csr(CSR_SEPC, sepc = std::make_shared(proc, nonvirtual_sepc, vsepc)); nonvirtual_stval = std::make_shared(proc, CSR_STVAL, 0); - csrmap[CSR_VSTVAL] = vstval = std::make_shared(proc, CSR_VSTVAL, 0); - csrmap[CSR_STVAL] = stval = std::make_shared(proc, nonvirtual_stval, vstval); + add_csr(CSR_VSTVAL, vstval = std::make_shared(proc, CSR_VSTVAL, 0)); + add_csr(CSR_STVAL, stval = std::make_shared(proc, nonvirtual_stval, vstval)); auto sscratch = std::make_shared(proc, CSR_SSCRATCH, 0); auto vsscratch = std::make_shared(proc, CSR_VSSCRATCH, 0); // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt): - csrmap[CSR_SSCRATCH] = std::make_shared(proc, sscratch, vsscratch); - csrmap[CSR_VSSCRATCH] = vsscratch; + add_csr(CSR_SSCRATCH, std::make_shared(proc, sscratch, vsscratch)); + add_csr(CSR_VSSCRATCH, vsscratch); nonvirtual_stvec = std::make_shared(proc, CSR_STVEC); - csrmap[CSR_VSTVEC] = vstvec = std::make_shared(proc, CSR_VSTVEC); - csrmap[CSR_STVEC] = stvec = std::make_shared(proc, nonvirtual_stvec, vstvec); + add_csr(CSR_VSTVEC, vstvec = std::make_shared(proc, CSR_VSTVEC)); + add_csr(CSR_STVEC, stvec = std::make_shared(proc, nonvirtual_stvec, vstvec)); auto nonvirtual_satp = std::make_shared(proc, CSR_SATP); - csrmap[CSR_VSATP] = vsatp = std::make_shared(proc, CSR_VSATP); - csrmap[CSR_SATP] = satp = std::make_shared(proc, nonvirtual_satp, vsatp); + add_csr(CSR_VSATP, vsatp = std::make_shared(proc, CSR_VSATP)); + add_csr(CSR_SATP, satp = std::make_shared(proc, nonvirtual_satp, vsatp)); nonvirtual_scause = std::make_shared(proc, CSR_SCAUSE); - csrmap[CSR_VSCAUSE] = vscause = std::make_shared(proc, CSR_VSCAUSE); - csrmap[CSR_SCAUSE] = scause = std::make_shared(proc, nonvirtual_scause, vscause); - csrmap[CSR_MTVAL2] = mtval2 = std::make_shared(proc, CSR_MTVAL2); - csrmap[CSR_MTINST] = mtinst = std::make_shared(proc, CSR_MTINST); - csrmap[CSR_HSTATUS] = hstatus = std::make_shared(proc, CSR_HSTATUS); - csrmap[CSR_HGEIE] = std::make_shared(proc, CSR_HGEIE, 0); - csrmap[CSR_HGEIP] = std::make_shared(proc, CSR_HGEIP, 0); - csrmap[CSR_HIDELEG] = hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg); + add_csr(CSR_VSCAUSE, vscause = std::make_shared(proc, CSR_VSCAUSE)); + add_csr(CSR_SCAUSE, scause = std::make_shared(proc, nonvirtual_scause, vscause)); + add_csr(CSR_MTVAL2, mtval2 = std::make_shared(proc, CSR_MTVAL2)); + add_csr(CSR_MTINST, mtinst = std::make_shared(proc, CSR_MTINST)); + add_csr(CSR_HSTATUS, hstatus = std::make_shared(proc, CSR_HSTATUS)); + add_csr(CSR_HGEIE, std::make_shared(proc, CSR_HGEIE, 0)); + add_csr(CSR_HGEIP, std::make_shared(proc, CSR_HGEIP, 0)); + add_csr(CSR_HIDELEG, hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg)); const reg_t hedeleg_mask = (1 << CAUSE_MISALIGNED_FETCH) | (1 << CAUSE_FETCH_ACCESS) | @@ -175,68 +181,69 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) (1 << CAUSE_STORE_PAGE_FAULT) | (1 << CAUSE_SOFTWARE_CHECK_FAULT) | (1 << CAUSE_HARDWARE_ERROR_FAULT); - csrmap[CSR_HEDELEG] = hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0); - csrmap[CSR_HCOUNTEREN] = hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0); + add_csr(CSR_HEDELEG, hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0)); + add_csr(CSR_HCOUNTEREN, hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0)); htimedelta = std::make_shared(proc, CSR_HTIMEDELTA, 0); if (xlen == 32) { - csrmap[CSR_HTIMEDELTA] = std::make_shared(proc, CSR_HTIMEDELTA, htimedelta); - csrmap[CSR_HTIMEDELTAH] = std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta); + add_csr(CSR_HTIMEDELTA, std::make_shared(proc, CSR_HTIMEDELTA, htimedelta)); + add_csr(CSR_HTIMEDELTAH, std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta)); } else { - csrmap[CSR_HTIMEDELTA] = htimedelta; + add_csr(CSR_HTIMEDELTA, htimedelta); } - csrmap[CSR_HTVAL] = htval = std::make_shared(proc, CSR_HTVAL, 0); - csrmap[CSR_HTINST] = htinst = std::make_shared(proc, CSR_HTINST, 0); - csrmap[CSR_HGATP] = hgatp = std::make_shared(proc, CSR_HGATP); + add_csr(CSR_HTVAL, htval = std::make_shared(proc, CSR_HTVAL, 0)); + add_csr(CSR_HTINST, htinst = std::make_shared(proc, CSR_HTINST, 0)); + add_csr(CSR_HGATP, hgatp = std::make_shared(proc, CSR_HGATP)); nonvirtual_sstatus = std::make_shared(proc, CSR_SSTATUS, mstatus); - csrmap[CSR_VSSTATUS] = vsstatus = std::make_shared(proc, CSR_VSSTATUS); - csrmap[CSR_SSTATUS] = sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus); + add_csr(CSR_VSSTATUS, vsstatus = std::make_shared(proc, CSR_VSSTATUS)); + add_csr(CSR_SSTATUS, sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus)); - csrmap[CSR_DPC] = dpc = std::make_shared(proc, CSR_DPC); - csrmap[CSR_DSCRATCH0] = std::make_shared(proc, CSR_DSCRATCH0); - csrmap[CSR_DSCRATCH1] = std::make_shared(proc, CSR_DSCRATCH1); - csrmap[CSR_DCSR] = dcsr = std::make_shared(proc, CSR_DCSR); + add_csr(CSR_DPC, dpc = std::make_shared(proc, CSR_DPC)); + add_csr(CSR_DSCRATCH0, std::make_shared(proc, CSR_DSCRATCH0)); + add_csr(CSR_DSCRATCH1, std::make_shared(proc, CSR_DSCRATCH1)); + add_csr(CSR_DCSR, dcsr = std::make_shared(proc, CSR_DCSR)); - csrmap[CSR_TSELECT] = tselect = std::make_shared(proc, CSR_TSELECT); + add_csr(CSR_TSELECT, tselect = std::make_shared(proc, CSR_TSELECT)); if (proc->get_cfg().trigger_count > 0) { - csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2); - csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3); - csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0); + add_csr(CSR_TDATA1, std::make_shared(proc, CSR_TDATA1)); + add_csr(CSR_TDATA2, tdata2 = std::make_shared(proc, CSR_TDATA2)); + add_csr(CSR_TDATA3, std::make_shared(proc, CSR_TDATA3)); + add_csr(CSR_TINFO, std::make_shared(proc, CSR_TINFO)); + add_csr(CSR_TCONTROL, tcontrol = std::make_shared(proc, CSR_TCONTROL, CSR_TCONTROL_MPTE | CSR_TCONTROL_MTE, 0)); } else { - csrmap[CSR_TDATA1] = std::make_shared(proc, CSR_TDATA1, 0); - csrmap[CSR_TDATA2] = tdata2 = std::make_shared(proc, CSR_TDATA2, 0); - csrmap[CSR_TDATA3] = std::make_shared(proc, CSR_TDATA3, 0); - csrmap[CSR_TINFO] = std::make_shared(proc, CSR_TINFO, 0); - csrmap[CSR_TCONTROL] = tcontrol = std::make_shared(proc, CSR_TCONTROL, 0); + add_csr(CSR_TDATA1, std::make_shared(proc, CSR_TDATA1, 0)); + add_csr(CSR_TDATA2, tdata2 = std::make_shared(proc, CSR_TDATA2, 0)); + add_csr(CSR_TDATA3, std::make_shared(proc, CSR_TDATA3, 0)); + add_csr(CSR_TINFO, std::make_shared(proc, CSR_TINFO, 0)); + add_csr(CSR_TCONTROL, tcontrol = std::make_shared(proc, CSR_TCONTROL, 0)); } unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 - csrmap[CSR_SCONTEXT] = scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0); + add_csr(CSR_SCONTEXT, scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0)); unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension - csrmap[CSR_HCONTEXT] = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); - csrmap[CSR_MCONTEXT] = mcontext = std::make_shared(proc, CSR_MCONTEXT, csrmap[CSR_HCONTEXT]); - csrmap[CSR_MSECCFG] = mseccfg = std::make_shared(proc, CSR_MSECCFG); + auto hcontext = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); + add_csr(CSR_HCONTEXT, hcontext); + add_csr(CSR_MCONTEXT, mcontext = std::make_shared(proc, CSR_MCONTEXT, hcontext)); + add_csr(CSR_MSECCFG, mseccfg = std::make_shared(proc, CSR_MSECCFG)); for (int i = 0; i < max_pmp; ++i) { - csrmap[CSR_PMPADDR0 + i] = pmpaddr[i] = std::make_shared(proc, CSR_PMPADDR0 + i); + add_csr(CSR_PMPADDR0 + i, pmpaddr[i] = std::make_shared(proc, CSR_PMPADDR0 + i)); } for (int i = 0; i < max_pmp; i += xlen / 8) { reg_t addr = CSR_PMPCFG0 + i / 4; - csrmap[addr] = std::make_shared(proc, addr); + add_csr(addr, std::make_shared(proc, addr)); } - csrmap[CSR_FFLAGS] = fflags = std::make_shared(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0); - csrmap[CSR_FRM] = frm = std::make_shared(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0); + add_csr(CSR_FFLAGS, fflags = std::make_shared(proc, CSR_FFLAGS, FSR_AEXC >> FSR_AEXC_SHIFT, 0)); + add_csr(CSR_FRM, frm = std::make_shared(proc, CSR_FRM, FSR_RD >> FSR_RD_SHIFT, 0)); assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0 - csrmap[CSR_FCSR] = std::make_shared(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT); + add_csr(CSR_FCSR, std::make_shared(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT)); - csrmap[CSR_SEED] = std::make_shared(proc, CSR_SEED); + add_csr(CSR_SEED, std::make_shared(proc, CSR_SEED)); - csrmap[CSR_MARCHID] = std::make_shared(proc, CSR_MARCHID, 5); - csrmap[CSR_MIMPID] = std::make_shared(proc, CSR_MIMPID, 0); - csrmap[CSR_MVENDORID] = std::make_shared(proc, CSR_MVENDORID, 0); - csrmap[CSR_MHARTID] = std::make_shared(proc, CSR_MHARTID, proc->get_id()); - csrmap[CSR_MCONFIGPTR] = std::make_shared(proc, CSR_MCONFIGPTR, 0); + add_csr(CSR_MARCHID, std::make_shared(proc, CSR_MARCHID, 5)); + add_csr(CSR_MIMPID, std::make_shared(proc, CSR_MIMPID, 0)); + add_csr(CSR_MVENDORID, std::make_shared(proc, CSR_MVENDORID, 0)); + add_csr(CSR_MHARTID, std::make_shared(proc, CSR_MHARTID, proc->get_id())); + add_csr(CSR_MCONFIGPTR, std::make_shared(proc, CSR_MCONFIGPTR, 0)); const reg_t menvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? MENVCFG_CBCFE | MENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? MENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SMNPM) ? MENVCFG_PMM : 0) | @@ -249,10 +256,10 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); if (proc->extension_enabled_const('U')) { if (xlen == 32) { - csrmap[CSR_MENVCFG] = std::make_shared(proc, CSR_MENVCFG, menvcfg); - csrmap[CSR_MENVCFGH] = std::make_shared(proc, CSR_MENVCFGH, menvcfg); + add_csr(CSR_MENVCFG, std::make_shared(proc, CSR_MENVCFG, menvcfg)); + add_csr(CSR_MENVCFGH, std::make_shared(proc, CSR_MENVCFGH, menvcfg)); } else { - csrmap[CSR_MENVCFG] = menvcfg; + add_csr(CSR_MENVCFG, menvcfg); } } const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | @@ -262,7 +269,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); if (proc->extension_enabled_const('S')) - csrmap[CSR_SENVCFG] = senvcfg; + add_csr(CSR_SENVCFG, senvcfg); const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | @@ -275,10 +282,10 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); if (proc->extension_enabled('H')) { if (xlen == 32) { - csrmap[CSR_HENVCFG] = std::make_shared(proc, CSR_HENVCFG, henvcfg); - csrmap[CSR_HENVCFGH] = std::make_shared(proc, CSR_HENVCFGH, henvcfg); + add_csr(CSR_HENVCFG, std::make_shared(proc, CSR_HENVCFG, henvcfg)); + add_csr(CSR_HENVCFGH, std::make_shared(proc, CSR_HENVCFGH, henvcfg)); } else { - csrmap[CSR_HENVCFG] = henvcfg; + add_csr(CSR_HENVCFG, henvcfg); } } if (proc->extension_enabled_const(EXT_SMSTATEEN)) { @@ -291,31 +298,31 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) const reg_t mstateen_mask = i == 0 ? mstateen0_mask : MSTATEEN_HSTATEEN; mstateen[i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen_mask, 0); if (xlen == 32) { - csrmap[CSR_MSTATEEN0 + i] = std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen[i]); - csrmap[CSR_MSTATEEN0H + i] = std::make_shared(proc, CSR_MSTATEEN0H + i, mstateen[i]); + add_csr(CSR_MSTATEEN0 + i, std::make_shared(proc, CSR_MSTATEEN0 + i, mstateen[i])); + add_csr(CSR_MSTATEEN0H + i, std::make_shared(proc, CSR_MSTATEEN0H + i, mstateen[i])); } else { - csrmap[CSR_MSTATEEN0 + i] = mstateen[i]; + add_csr(CSR_MSTATEEN0 + i, mstateen[i]); } const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN; hstateen[i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i); if (xlen == 32) { - csrmap[CSR_HSTATEEN0 + i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i]); - csrmap[CSR_HSTATEEN0H + i] = std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i]); + add_csr(CSR_HSTATEEN0 + i, std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i])); + add_csr(CSR_HSTATEEN0H + i, std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i])); } else { - csrmap[CSR_HSTATEEN0 + i] = hstateen[i]; + add_csr(CSR_HSTATEEN0 + i, hstateen[i]); } const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0; - csrmap[CSR_SSTATEEN0 + i] = sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i); + add_csr(CSR_SSTATEEN0 + i, sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i)); } } if (proc->extension_enabled_const(EXT_SMRNMI)) { - csrmap[CSR_MNSCRATCH] = std::make_shared(proc, CSR_MNSCRATCH, 0); - csrmap[CSR_MNEPC] = mnepc = std::make_shared(proc, CSR_MNEPC); - csrmap[CSR_MNCAUSE] = std::make_shared(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1)); - csrmap[CSR_MNSTATUS] = mnstatus = std::make_shared(proc, CSR_MNSTATUS); + add_csr(CSR_MNSCRATCH, std::make_shared(proc, CSR_MNSCRATCH, 0)); + add_csr(CSR_MNEPC, mnepc = std::make_shared(proc, CSR_MNEPC)); + add_csr(CSR_MNCAUSE, std::make_shared(proc, CSR_MNCAUSE, (reg_t)1 << (xlen - 1))); + add_csr(CSR_MNSTATUS, mnstatus = std::make_shared(proc, CSR_MNSTATUS)); } if (proc->extension_enabled_const(EXT_SSTC)) { @@ -323,22 +330,22 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) vstimecmp = std::make_shared(proc, CSR_VSTIMECMP, MIP_VSTIP); auto virtualized_stimecmp = std::make_shared(proc, stimecmp, vstimecmp); if (xlen == 32) { - csrmap[CSR_STIMECMP] = std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp); - csrmap[CSR_STIMECMPH] = std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp); - csrmap[CSR_VSTIMECMP] = std::make_shared(proc, CSR_VSTIMECMP, vstimecmp); - csrmap[CSR_VSTIMECMPH] = std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp); + add_csr(CSR_STIMECMP, std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp)); + add_csr(CSR_STIMECMPH, std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp)); + add_csr(CSR_VSTIMECMP, std::make_shared(proc, CSR_VSTIMECMP, vstimecmp)); + add_csr(CSR_VSTIMECMPH, std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp)); } else { - csrmap[CSR_STIMECMP] = virtualized_stimecmp; - csrmap[CSR_VSTIMECMP] = vstimecmp; + add_csr(CSR_STIMECMP, virtualized_stimecmp); + add_csr(CSR_VSTIMECMP, vstimecmp); } } if (proc->extension_enabled(EXT_ZCMT)) - csrmap[CSR_JVT] = jvt = std::make_shared(proc, CSR_JVT, 0); + add_csr(CSR_JVT, jvt = std::make_shared(proc, CSR_JVT, 0)); if (proc->extension_enabled(EXT_ZICFISS)) { reg_t ssp_mask = -reg_t(xlen / 8); - csrmap[CSR_SSP] = ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0); + add_csr(CSR_SSP, ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0)); } @@ -349,26 +356,26 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled_const(EXT_SMCSRIND)) { csr_t_p miselect = std::make_shared(proc, CSR_MISELECT, 0); - csrmap[CSR_MISELECT] = miselect; + add_csr(CSR_MISELECT, miselect); const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; auto i = 0; for (auto csr : mireg_csrs) { - csrmap[csr] = mireg[i] = std::make_shared(proc, csr, miselect); + add_csr(csr, mireg[i] = std::make_shared(proc, csr, miselect)); i++; } } if (proc->extension_enabled_const(EXT_SSCSRIND)) { csr_t_p vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); - csrmap[CSR_VSISELECT] = vsiselect; + add_csr(CSR_VSISELECT, vsiselect); csr_t_p siselect = std::make_shared(proc, CSR_SISELECT, 0); - csrmap[CSR_SISELECT] = std::make_shared(proc, siselect, vsiselect); + add_csr(CSR_SISELECT, std::make_shared(proc, siselect, vsiselect)); const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; auto i = 0; for (auto csr : vsireg_csrs) { - csrmap[csr] = vsireg[i] = std::make_shared(proc, csr, vsiselect); + add_csr(csr, vsireg[i] = std::make_shared(proc, csr, vsiselect)); i++; } @@ -376,26 +383,26 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) i = 0; for (auto csr : sireg_csrs) { sireg[i] = std::make_shared(proc, csr, siselect); - csrmap[csr] = std::make_shared(proc, sireg[i], vsireg[i]); + add_csr(csr, std::make_shared(proc, sireg[i], vsireg[i])); i++; } } if (smcntrpmf_enabled) { if (xlen == 32) { - csrmap[CSR_MCYCLECFG] = std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg); - csrmap[CSR_MCYCLECFGH] = std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg); - csrmap[CSR_MINSTRETCFG] = std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg); - csrmap[CSR_MINSTRETCFGH] = std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg); + add_csr(CSR_MCYCLECFG, std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg)); + add_csr(CSR_MCYCLECFGH, std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg)); + add_csr(CSR_MINSTRETCFG, std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg)); + add_csr(CSR_MINSTRETCFGH, std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg)); } else { - csrmap[CSR_MCYCLECFG] = mcyclecfg; - csrmap[CSR_MINSTRETCFG] = minstretcfg; + add_csr(CSR_MCYCLECFG, mcyclecfg); + add_csr(CSR_MINSTRETCFG, minstretcfg); } } if (proc->extension_enabled_const(EXT_SSQOSID)) { const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; srmcfg = std::make_shared(proc, CSR_SRMCFG, srmcfg_mask, 0); - csrmap[CSR_SRMCFG] = srmcfg; + add_csr(CSR_SRMCFG, srmcfg); } } diff --git a/riscv/processor.h b/riscv/processor.h index cdd32d5539..263b769afc 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -71,6 +71,7 @@ typedef std::vector> commit_log_mem_t; struct state_t { void reset(processor_t* const proc, reg_t max_isa); + void add_csr(reg_t addr, const csr_t_p& csr); reg_t pc; regfile_t XPR; diff --git a/riscv/vector_unit.cc b/riscv/vector_unit.cc index 08adc6166d..a5c35f8f01 100644 --- a/riscv/vector_unit.cc +++ b/riscv/vector_unit.cc @@ -13,15 +13,15 @@ void vectorUnit_t::vectorUnit_t::reset() reg_file = malloc(NVPR * vlenb); memset(reg_file, 0, NVPR * vlenb); - auto& csrmap = p->get_state()->csrmap; - csrmap[CSR_VXSAT] = vxsat = std::make_shared(p, CSR_VXSAT); - csrmap[CSR_VSTART] = vstart = std::make_shared(p, CSR_VSTART, /*mask*/ VLEN - 1); - csrmap[CSR_VXRM] = vxrm = std::make_shared(p, CSR_VXRM, /*mask*/ 0x3ul); - csrmap[CSR_VL] = vl = std::make_shared(p, CSR_VL, /*mask*/ 0); - csrmap[CSR_VTYPE] = vtype = std::make_shared(p, CSR_VTYPE, /*mask*/ 0); - csrmap[CSR_VLENB] = std::make_shared(p, CSR_VLENB, /*mask*/ 0, /*init*/ vlenb); + auto state = p->get_state(); + state->add_csr(CSR_VXSAT, vxsat = std::make_shared(p, CSR_VXSAT)); + state->add_csr(CSR_VSTART, vstart = std::make_shared(p, CSR_VSTART, /*mask*/ VLEN - 1)); + state->add_csr(CSR_VXRM, vxrm = std::make_shared(p, CSR_VXRM, /*mask*/ 0x3ul)); + state->add_csr(CSR_VL, vl = std::make_shared(p, CSR_VL, /*mask*/ 0)); + state->add_csr(CSR_VTYPE, vtype = std::make_shared(p, CSR_VTYPE, /*mask*/ 0)); + state->add_csr(CSR_VLENB, std::make_shared(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(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT); + state->add_csr(CSR_VCSR, std::make_shared(p, CSR_VCSR, vxrm, vxsat, VCSR_VXRM_SHIFT)); vtype->write_raw(0); set_vl(0, 0, 0, -1); // default to illegal configuration From 3c0e6bfa69b43b77f15de6e0598452637283896e Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 15:24:09 -0700 Subject: [PATCH 124/155] Refactor initialization of mode-specific CSRs The if-statements are boilerplate. --- riscv/csr_init.cc | 38 ++++++++++++++++++-------------------- 1 file changed, 18 insertions(+), 20 deletions(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 80d640b72f..7d96242c02 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -6,6 +6,12 @@ void state_t::add_csr(reg_t addr, const csr_t_p& csr) csrmap[addr] = csr; } +#define add_const_ext_csr(ext, addr, csr) do { auto csr__ = (csr); if (proc->extension_enabled_const(ext)) { add_csr(addr, csr__); } } while (0) +#define add_ext_csr(ext, addr, csr) do { auto csr__ = (csr); if (proc->extension_enabled(ext)) { add_csr(addr, csr__); } } while (0) +#define add_user_csr(addr, csr) add_const_ext_csr('U', addr, csr) +#define add_supervisor_csr(addr, csr) add_const_ext_csr('S', addr, csr) +#define add_hypervisor_csr(addr, csr) add_ext_csr('H', addr, csr) + void state_t::csr_init(processor_t* const proc, reg_t max_isa) { // This assumes xlen is always max_xlen, which is true today (see @@ -136,9 +142,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) add_csr(CSR_MEDELEG, medeleg = std::make_shared(proc, CSR_MEDELEG)); add_csr(CSR_MIDELEG, mideleg = std::make_shared(proc, CSR_MIDELEG)); const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); - mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0); - if (proc->extension_enabled_const('U')) - add_csr(CSR_MCOUNTEREN, mcounteren); + add_user_csr(CSR_MCOUNTEREN, mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0)); add_csr(CSR_SCOUNTEREN, scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0)); nonvirtual_sepc = std::make_shared(proc, CSR_SEPC); add_csr(CSR_VSEPC, vsepc = std::make_shared(proc, CSR_VSEPC)); @@ -254,22 +258,18 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFISS) ? MENVCFG_SSE : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? MENVCFG_DTE : 0); menvcfg = std::make_shared(proc, CSR_MENVCFG, menvcfg_mask, 0); - if (proc->extension_enabled_const('U')) { - if (xlen == 32) { - add_csr(CSR_MENVCFG, std::make_shared(proc, CSR_MENVCFG, menvcfg)); - add_csr(CSR_MENVCFGH, std::make_shared(proc, CSR_MENVCFGH, menvcfg)); - } else { - add_csr(CSR_MENVCFG, menvcfg); - } + if (xlen == 32) { + add_user_csr(CSR_MENVCFG, std::make_shared(proc, CSR_MENVCFG, menvcfg)); + add_user_csr(CSR_MENVCFGH, std::make_shared(proc, CSR_MENVCFGH, menvcfg)); + } else { + add_user_csr(CSR_MENVCFG, menvcfg); } const reg_t senvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? SENVCFG_CBCFE | SENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? SENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SSNPM) ? SENVCFG_PMM : 0) | (proc->extension_enabled(EXT_ZICFILP) ? SENVCFG_LPE : 0) | (proc->extension_enabled(EXT_ZICFISS) ? SENVCFG_SSE : 0); - senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0); - if (proc->extension_enabled_const('S')) - add_csr(CSR_SENVCFG, senvcfg); + add_supervisor_csr(CSR_SENVCFG, senvcfg = std::make_shared(proc, CSR_SENVCFG, senvcfg_mask, 0)); const reg_t henvcfg_mask = (proc->extension_enabled(EXT_ZICBOM) ? HENVCFG_CBCFE | HENVCFG_CBIE : 0) | (proc->extension_enabled(EXT_ZICBOZ) ? HENVCFG_CBZE : 0) | (proc->extension_enabled(EXT_SSNPM) ? HENVCFG_PMM : 0) | @@ -280,13 +280,11 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) (proc->extension_enabled(EXT_ZICFISS) ? HENVCFG_SSE : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? HENVCFG_DTE : 0); henvcfg = std::make_shared(proc, CSR_HENVCFG, henvcfg_mask, 0, menvcfg); - if (proc->extension_enabled('H')) { - if (xlen == 32) { - add_csr(CSR_HENVCFG, std::make_shared(proc, CSR_HENVCFG, henvcfg)); - add_csr(CSR_HENVCFGH, std::make_shared(proc, CSR_HENVCFGH, henvcfg)); - } else { - add_csr(CSR_HENVCFG, henvcfg); - } + if (xlen == 32) { + add_hypervisor_csr(CSR_HENVCFG, std::make_shared(proc, CSR_HENVCFG, henvcfg)); + add_hypervisor_csr(CSR_HENVCFGH, std::make_shared(proc, CSR_HENVCFGH, henvcfg)); + } else { + add_hypervisor_csr(CSR_HENVCFG, henvcfg); } if (proc->extension_enabled_const(EXT_SMSTATEEN)) { const reg_t sstateen0_mask = (proc->extension_enabled(EXT_ZFINX) ? SSTATEEN0_FCSR : 0) | From a81d59754f66101af2c05b37ac7e94ecf889edc3 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 16:06:26 -0700 Subject: [PATCH 125/155] Remove boilerplate from most CSR instantiations --- riscv/csr_init.cc | 94 +++++++++++++++++------------------------------ riscv/processor.h | 2 - 2 files changed, 34 insertions(+), 62 deletions(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 7d96242c02..961a4b475a 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -33,11 +33,10 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) add_csr(CSR_MTVEC, mtvec = std::make_shared(proc, CSR_MTVEC)); add_csr(CSR_MCAUSE, mcause = std::make_shared(proc, CSR_MCAUSE)); - auto smcntrpmf_enabled = proc->extension_enabled_const(EXT_SMCNTRPMF); - const reg_t mask = smcntrpmf_enabled ? MHPMEVENT_MINH | MHPMEVENT_SINH | - MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH : 0; - auto minstretcfg = std::make_shared(proc, CSR_MINSTRETCFG, mask, 0); - auto mcyclecfg = std::make_shared(proc, CSR_MCYCLECFG, mask, 0); + const reg_t minstretcfg_mask = !proc->extension_enabled_const(EXT_SMCNTRPMF) ? 0 : + MHPMEVENT_MINH | MHPMEVENT_SINH | MHPMEVENT_UINH | MHPMEVENT_VSINH | MHPMEVENT_VUINH; + auto minstretcfg = std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg_mask, 0); + auto mcyclecfg = std::make_shared(proc, CSR_MCYCLECFG, minstretcfg_mask, 0); minstret = std::make_shared(proc, CSR_MINSTRET, minstretcfg); mcycle = std::make_shared(proc, CSR_MCYCLE, mcyclecfg); @@ -74,29 +73,21 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) auto mcounter = std::make_shared(proc, which_mcounter, 0); add_csr(which_mcounter, mcounter); - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counter = std::make_shared(proc, which_counter, mcounter); - add_csr(which_counter, counter); - } + auto counter = std::make_shared(proc, which_counter, mcounter); + add_const_ext_csr(EXT_ZIHPM, which_counter, counter); + if (xlen == 32) { add_csr(which_mevent, std::make_shared(proc, which_mevent, mevent[i])); auto mcounterh = std::make_shared(proc, which_mcounterh, 0); add_csr(which_mcounterh, mcounterh); - if (proc->extension_enabled_const(EXT_ZIHPM)) { - auto counterh = std::make_shared(proc, which_counterh, mcounterh); - add_csr(which_counterh, counterh); - } - if (proc->extension_enabled_const(EXT_SSCOFPMF)) { - auto meventh = std::make_shared(proc, which_meventh, mevent[i]); - add_csr(which_meventh, meventh); - } + add_const_ext_csr(EXT_ZIHPM, which_counterh, std::make_shared(proc, which_counterh, mcounterh)); + add_const_ext_csr(EXT_SSCOFPMF, which_meventh, std::make_shared(proc, which_meventh, mevent[i])); } else { add_csr(which_mevent, mevent[i]); } } add_csr(CSR_MCOUNTINHIBIT, std::make_shared(proc, CSR_MCOUNTINHIBIT, 0)); - if (proc->extension_enabled_const(EXT_SSCOFPMF)) - add_csr(CSR_SCOUNTOVF, std::make_shared(proc, CSR_SCOUNTOVF)); + add_const_ext_csr(EXT_SSCOFPMF, CSR_SCOUNTOVF, std::make_shared(proc, CSR_SCOUNTOVF)); add_csr(CSR_MIE, mie = std::make_shared(proc, CSR_MIE)); add_csr(CSR_MIP, mip = std::make_shared(proc, CSR_MIP)); auto sip_sie_accr = std::make_shared( @@ -338,69 +329,52 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) } } - if (proc->extension_enabled(EXT_ZCMT)) - add_csr(CSR_JVT, jvt = std::make_shared(proc, CSR_JVT, 0)); + add_ext_csr(EXT_ZCMT, CSR_JVT, jvt = std::make_shared(proc, CSR_JVT, 0)); - if (proc->extension_enabled(EXT_ZICFISS)) { - reg_t ssp_mask = -reg_t(xlen / 8); - add_csr(CSR_SSP, ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0)); - } + const reg_t ssp_mask = -reg_t(xlen / 8); + add_ext_csr(EXT_ZICFISS, CSR_SSP, ssp = std::make_shared(proc, CSR_SSP, ssp_mask, 0)); // Smcsrind / Sscsrind - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p mireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p sireg[6]; - sscsrind_reg_csr_t::sscsrind_reg_csr_t_p vsireg[6]; - if (proc->extension_enabled_const(EXT_SMCSRIND)) { csr_t_p miselect = std::make_shared(proc, CSR_MISELECT, 0); add_csr(CSR_MISELECT, miselect); const reg_t mireg_csrs[] = { CSR_MIREG, CSR_MIREG2, CSR_MIREG3, CSR_MIREG4, CSR_MIREG5, CSR_MIREG6 }; - auto i = 0; - for (auto csr : mireg_csrs) { - add_csr(csr, mireg[i] = std::make_shared(proc, csr, miselect)); - i++; - } + for (auto csr : mireg_csrs) + add_csr(csr, std::make_shared(proc, csr, miselect)); } if (proc->extension_enabled_const(EXT_SSCSRIND)) { csr_t_p vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); add_csr(CSR_VSISELECT, vsiselect); + csr_t_p siselect = std::make_shared(proc, CSR_SISELECT, 0); add_csr(CSR_SISELECT, std::make_shared(proc, siselect, vsiselect)); const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; - auto i = 0; - for (auto csr : vsireg_csrs) { - add_csr(csr, vsireg[i] = std::make_shared(proc, csr, vsiselect)); - i++; - } - const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; - i = 0; - for (auto csr : sireg_csrs) { - sireg[i] = std::make_shared(proc, csr, siselect); - add_csr(csr, std::make_shared(proc, sireg[i], vsireg[i])); - i++; + for (size_t i = 0; i < std::size(vsireg_csrs); i++) { + auto vsireg = std::make_shared(proc, vsireg_csrs[i], vsiselect); + add_csr(vsireg_csrs[i], vsireg); + + auto sireg = std::make_shared(proc, sireg_csrs[i], siselect); + add_csr(sireg_csrs[i], std::make_shared(proc, sireg, vsireg)); } } - if (smcntrpmf_enabled) { - if (xlen == 32) { - add_csr(CSR_MCYCLECFG, std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg)); - add_csr(CSR_MCYCLECFGH, std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg)); - add_csr(CSR_MINSTRETCFG, std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg)); - add_csr(CSR_MINSTRETCFGH, std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg)); - } else { - add_csr(CSR_MCYCLECFG, mcyclecfg); - add_csr(CSR_MINSTRETCFG, minstretcfg); - } + if (proc->extension_enabled_const(EXT_SMCNTRPMF)) { + if (xlen == 32) { + add_csr(CSR_MCYCLECFG, std::make_shared(proc, CSR_MCYCLECFG, mcyclecfg)); + add_csr(CSR_MCYCLECFGH, std::make_shared(proc, CSR_MCYCLECFGH, mcyclecfg)); + add_csr(CSR_MINSTRETCFG, std::make_shared(proc, CSR_MINSTRETCFG, minstretcfg)); + add_csr(CSR_MINSTRETCFGH, std::make_shared(proc, CSR_MINSTRETCFGH, minstretcfg)); + } else { + add_csr(CSR_MCYCLECFG, mcyclecfg); + add_csr(CSR_MINSTRETCFG, minstretcfg); + } } - if (proc->extension_enabled_const(EXT_SSQOSID)) { - const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; - srmcfg = std::make_shared(proc, CSR_SRMCFG, srmcfg_mask, 0); - add_csr(CSR_SRMCFG, srmcfg); - } + const reg_t srmcfg_mask = SRMCFG_MCID | SRMCFG_RCID; + add_const_ext_csr(EXT_SSQOSID, CSR_SRMCFG, std::make_shared(proc, CSR_SRMCFG, srmcfg_mask, 0)); } diff --git a/riscv/processor.h b/riscv/processor.h index 263b769afc..26d0878208 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -169,8 +169,6 @@ struct state_t csr_t_p stimecmp; csr_t_p vstimecmp; - csr_t_p srmcfg; - csr_t_p ssp; bool serialized; // whether timer CSRs are in a well-defined state From 1ecad57eae3f9dac5aabc0d307817df31d28bb2d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Thu, 1 Aug 2024 16:48:47 -0700 Subject: [PATCH 126/155] Only add CSRs if corresponding extensions are enabled --- riscv/csr_init.cc | 112 +++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 55 deletions(-) diff --git a/riscv/csr_init.cc b/riscv/csr_init.cc index 961a4b475a..d72c925041 100644 --- a/riscv/csr_init.cc +++ b/riscv/csr_init.cc @@ -119,48 +119,50 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) auto nonvirtual_sip = std::make_shared(proc, CSR_SIP, sip_sie_accr); auto vsip = std::make_shared(proc, CSR_VSIP, vsip_vsie_accr); - add_csr(CSR_VSIP, vsip); - add_csr(CSR_SIP, std::make_shared(proc, nonvirtual_sip, vsip)); - add_csr(CSR_HIP, std::make_shared(proc, CSR_HIP, hip_hie_accr)); - add_csr(CSR_HVIP, hvip = std::make_shared(proc, CSR_HVIP, 0)); + add_hypervisor_csr(CSR_VSIP, vsip); + add_supervisor_csr(CSR_SIP, std::make_shared(proc, nonvirtual_sip, vsip)); + add_hypervisor_csr(CSR_HIP, std::make_shared(proc, CSR_HIP, hip_hie_accr)); + add_hypervisor_csr(CSR_HVIP, hvip = std::make_shared(proc, CSR_HVIP, 0)); auto nonvirtual_sie = std::make_shared(proc, CSR_SIE, sip_sie_accr); auto vsie = std::make_shared(proc, CSR_VSIE, vsip_vsie_accr); - add_csr(CSR_VSIE, vsie); - add_csr(CSR_SIE, std::make_shared(proc, nonvirtual_sie, vsie)); - add_csr(CSR_HIE, std::make_shared(proc, CSR_HIE, hip_hie_accr)); + add_hypervisor_csr(CSR_VSIE, vsie); + add_supervisor_csr(CSR_SIE, std::make_shared(proc, nonvirtual_sie, vsie)); + add_hypervisor_csr(CSR_HIE, std::make_shared(proc, CSR_HIE, hip_hie_accr)); - add_csr(CSR_MEDELEG, medeleg = std::make_shared(proc, CSR_MEDELEG)); - add_csr(CSR_MIDELEG, mideleg = std::make_shared(proc, CSR_MIDELEG)); + add_supervisor_csr(CSR_MEDELEG, medeleg = std::make_shared(proc, CSR_MEDELEG)); + add_supervisor_csr(CSR_MIDELEG, mideleg = std::make_shared(proc, CSR_MIDELEG)); const reg_t counteren_mask = (proc->extension_enabled_const(EXT_ZICNTR) ? 0x7UL : 0x0) | (proc->extension_enabled_const(EXT_ZIHPM) ? 0xfffffff8ULL : 0x0); add_user_csr(CSR_MCOUNTEREN, mcounteren = std::make_shared(proc, CSR_MCOUNTEREN, counteren_mask, 0)); - add_csr(CSR_SCOUNTEREN, scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0)); + add_supervisor_csr(CSR_SCOUNTEREN, scounteren = std::make_shared(proc, CSR_SCOUNTEREN, counteren_mask, 0)); nonvirtual_sepc = std::make_shared(proc, CSR_SEPC); - add_csr(CSR_VSEPC, vsepc = std::make_shared(proc, CSR_VSEPC)); - add_csr(CSR_SEPC, sepc = std::make_shared(proc, nonvirtual_sepc, vsepc)); + add_hypervisor_csr(CSR_VSEPC, vsepc = std::make_shared(proc, CSR_VSEPC)); + add_supervisor_csr(CSR_SEPC, sepc = std::make_shared(proc, nonvirtual_sepc, vsepc)); nonvirtual_stval = std::make_shared(proc, CSR_STVAL, 0); - add_csr(CSR_VSTVAL, vstval = std::make_shared(proc, CSR_VSTVAL, 0)); - add_csr(CSR_STVAL, stval = std::make_shared(proc, nonvirtual_stval, vstval)); + add_hypervisor_csr(CSR_VSTVAL, vstval = std::make_shared(proc, CSR_VSTVAL, 0)); + add_supervisor_csr(CSR_STVAL, stval = std::make_shared(proc, nonvirtual_stval, vstval)); auto sscratch = std::make_shared(proc, CSR_SSCRATCH, 0); auto vsscratch = std::make_shared(proc, CSR_VSSCRATCH, 0); // Note: if max_isa does not include H, we don't really need this virtualized_csr_t at all (though it doesn't hurt): - add_csr(CSR_SSCRATCH, std::make_shared(proc, sscratch, vsscratch)); - add_csr(CSR_VSSCRATCH, vsscratch); + add_supervisor_csr(CSR_SSCRATCH, std::make_shared(proc, sscratch, vsscratch)); + add_hypervisor_csr(CSR_VSSCRATCH, vsscratch); nonvirtual_stvec = std::make_shared(proc, CSR_STVEC); - add_csr(CSR_VSTVEC, vstvec = std::make_shared(proc, CSR_VSTVEC)); - add_csr(CSR_STVEC, stvec = std::make_shared(proc, nonvirtual_stvec, vstvec)); + add_hypervisor_csr(CSR_VSTVEC, vstvec = std::make_shared(proc, CSR_VSTVEC)); + add_supervisor_csr(CSR_STVEC, stvec = std::make_shared(proc, nonvirtual_stvec, vstvec)); auto nonvirtual_satp = std::make_shared(proc, CSR_SATP); - add_csr(CSR_VSATP, vsatp = std::make_shared(proc, CSR_VSATP)); - add_csr(CSR_SATP, satp = std::make_shared(proc, nonvirtual_satp, vsatp)); + add_hypervisor_csr(CSR_VSATP, vsatp = std::make_shared(proc, CSR_VSATP)); + add_supervisor_csr(CSR_SATP, satp = std::make_shared(proc, nonvirtual_satp, vsatp)); nonvirtual_scause = std::make_shared(proc, CSR_SCAUSE); - add_csr(CSR_VSCAUSE, vscause = std::make_shared(proc, CSR_VSCAUSE)); - add_csr(CSR_SCAUSE, scause = std::make_shared(proc, nonvirtual_scause, vscause)); - add_csr(CSR_MTVAL2, mtval2 = std::make_shared(proc, CSR_MTVAL2)); - add_csr(CSR_MTINST, mtinst = std::make_shared(proc, CSR_MTINST)); - add_csr(CSR_HSTATUS, hstatus = std::make_shared(proc, CSR_HSTATUS)); - add_csr(CSR_HGEIE, std::make_shared(proc, CSR_HGEIE, 0)); - add_csr(CSR_HGEIP, std::make_shared(proc, CSR_HGEIP, 0)); - add_csr(CSR_HIDELEG, hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg)); + add_hypervisor_csr(CSR_VSCAUSE, vscause = std::make_shared(proc, CSR_VSCAUSE)); + add_supervisor_csr(CSR_SCAUSE, scause = std::make_shared(proc, nonvirtual_scause, vscause)); + mtval2 = std::make_shared(proc, CSR_MTVAL2); + if (proc->extension_enabled('H') || proc->extension_enabled(EXT_SSDBLTRP)) + add_csr(CSR_MTVAL2, mtval2); + add_hypervisor_csr(CSR_MTINST, mtinst = std::make_shared(proc, CSR_MTINST)); + add_hypervisor_csr(CSR_HSTATUS, hstatus = std::make_shared(proc, CSR_HSTATUS)); + add_hypervisor_csr(CSR_HGEIE, std::make_shared(proc, CSR_HGEIE, 0)); + add_hypervisor_csr(CSR_HGEIP, std::make_shared(proc, CSR_HGEIP, 0)); + add_hypervisor_csr(CSR_HIDELEG, hideleg = std::make_shared(proc, CSR_HIDELEG, mideleg)); const reg_t hedeleg_mask = (1 << CAUSE_MISALIGNED_FETCH) | (1 << CAUSE_FETCH_ACCESS) | @@ -176,21 +178,21 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) (1 << CAUSE_STORE_PAGE_FAULT) | (1 << CAUSE_SOFTWARE_CHECK_FAULT) | (1 << CAUSE_HARDWARE_ERROR_FAULT); - add_csr(CSR_HEDELEG, hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0)); - add_csr(CSR_HCOUNTEREN, hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0)); + add_hypervisor_csr(CSR_HEDELEG, hedeleg = std::make_shared(proc, CSR_HEDELEG, hedeleg_mask, 0)); + add_hypervisor_csr(CSR_HCOUNTEREN, hcounteren = std::make_shared(proc, CSR_HCOUNTEREN, counteren_mask, 0)); htimedelta = std::make_shared(proc, CSR_HTIMEDELTA, 0); if (xlen == 32) { - add_csr(CSR_HTIMEDELTA, std::make_shared(proc, CSR_HTIMEDELTA, htimedelta)); - add_csr(CSR_HTIMEDELTAH, std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta)); + add_hypervisor_csr(CSR_HTIMEDELTA, std::make_shared(proc, CSR_HTIMEDELTA, htimedelta)); + add_hypervisor_csr(CSR_HTIMEDELTAH, std::make_shared(proc, CSR_HTIMEDELTAH, htimedelta)); } else { - add_csr(CSR_HTIMEDELTA, htimedelta); + add_hypervisor_csr(CSR_HTIMEDELTA, htimedelta); } - add_csr(CSR_HTVAL, htval = std::make_shared(proc, CSR_HTVAL, 0)); - add_csr(CSR_HTINST, htinst = std::make_shared(proc, CSR_HTINST, 0)); - add_csr(CSR_HGATP, hgatp = std::make_shared(proc, CSR_HGATP)); + add_hypervisor_csr(CSR_HTVAL, htval = std::make_shared(proc, CSR_HTVAL, 0)); + add_hypervisor_csr(CSR_HTINST, htinst = std::make_shared(proc, CSR_HTINST, 0)); + add_hypervisor_csr(CSR_HGATP, hgatp = std::make_shared(proc, CSR_HGATP)); nonvirtual_sstatus = std::make_shared(proc, CSR_SSTATUS, mstatus); - add_csr(CSR_VSSTATUS, vsstatus = std::make_shared(proc, CSR_VSSTATUS)); - add_csr(CSR_SSTATUS, sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus)); + add_hypervisor_csr(CSR_VSSTATUS, vsstatus = std::make_shared(proc, CSR_VSSTATUS)); + add_supervisor_csr(CSR_SSTATUS, sstatus = std::make_shared(proc, nonvirtual_sstatus, vsstatus)); add_csr(CSR_DPC, dpc = std::make_shared(proc, CSR_DPC)); add_csr(CSR_DSCRATCH0, std::make_shared(proc, CSR_DSCRATCH0)); @@ -212,10 +214,10 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) add_csr(CSR_TCONTROL, tcontrol = std::make_shared(proc, CSR_TCONTROL, 0)); } unsigned scontext_length = (xlen == 32 ? 16 : 32); // debug spec suggests 16-bit for RV32 and 32-bit for RV64 - add_csr(CSR_SCONTEXT, scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0)); + add_supervisor_csr(CSR_SCONTEXT, scontext = std::make_shared(proc, CSR_SCONTEXT, (reg_t(1) << scontext_length) - 1, 0)); unsigned hcontext_length = (xlen == 32 ? 6 : 13) + (proc->extension_enabled('H') ? 1 : 0); // debug spec suggest 7-bit (6-bit) for RV32 and 14-bit (13-bit) for RV64 with (without) H extension auto hcontext = std::make_shared(proc, CSR_HCONTEXT, (reg_t(1) << hcontext_length) - 1, 0); - add_csr(CSR_HCONTEXT, hcontext); + add_hypervisor_csr(CSR_HCONTEXT, hcontext); add_csr(CSR_MCONTEXT, mcontext = std::make_shared(proc, CSR_MCONTEXT, hcontext)); add_csr(CSR_MSECCFG, mseccfg = std::make_shared(proc, CSR_MSECCFG)); @@ -232,7 +234,7 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) assert(FSR_AEXC_SHIFT == 0); // composite_csr_t assumes fflags begins at bit 0 add_csr(CSR_FCSR, std::make_shared(proc, CSR_FCSR, frm, fflags, FSR_RD_SHIFT)); - add_csr(CSR_SEED, std::make_shared(proc, CSR_SEED)); + add_ext_csr(EXT_ZKR, CSR_SEED, std::make_shared(proc, CSR_SEED)); add_csr(CSR_MARCHID, std::make_shared(proc, CSR_MARCHID, 5)); add_csr(CSR_MIMPID, std::make_shared(proc, CSR_MIMPID, 0)); @@ -296,14 +298,14 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) const reg_t hstateen_mask = i == 0 ? hstateen0_mask : HSTATEEN_SSTATEEN; hstateen[i] = std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen_mask, 0, i); if (xlen == 32) { - add_csr(CSR_HSTATEEN0 + i, std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i])); - add_csr(CSR_HSTATEEN0H + i, std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i])); + add_hypervisor_csr(CSR_HSTATEEN0 + i, std::make_shared(proc, CSR_HSTATEEN0 + i, hstateen[i])); + add_hypervisor_csr(CSR_HSTATEEN0H + i, std::make_shared(proc, CSR_HSTATEEN0H + i, hstateen[i])); } else { - add_csr(CSR_HSTATEEN0 + i, hstateen[i]); + add_hypervisor_csr(CSR_HSTATEEN0 + i, hstateen[i]); } const reg_t sstateen_mask = i == 0 ? sstateen0_mask : 0; - add_csr(CSR_SSTATEEN0 + i, sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i)); + add_supervisor_csr(CSR_SSTATEEN0 + i, sstateen[i] = std::make_shared(proc, CSR_SSTATEEN0 + i, sstateen_mask, 0, i)); } } @@ -319,13 +321,13 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) vstimecmp = std::make_shared(proc, CSR_VSTIMECMP, MIP_VSTIP); auto virtualized_stimecmp = std::make_shared(proc, stimecmp, vstimecmp); if (xlen == 32) { - add_csr(CSR_STIMECMP, std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp)); - add_csr(CSR_STIMECMPH, std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp)); - add_csr(CSR_VSTIMECMP, std::make_shared(proc, CSR_VSTIMECMP, vstimecmp)); - add_csr(CSR_VSTIMECMPH, std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp)); + add_supervisor_csr(CSR_STIMECMP, std::make_shared(proc, CSR_STIMECMP, virtualized_stimecmp)); + add_supervisor_csr(CSR_STIMECMPH, std::make_shared(proc, CSR_STIMECMPH, virtualized_stimecmp)); + add_hypervisor_csr(CSR_VSTIMECMP, std::make_shared(proc, CSR_VSTIMECMP, vstimecmp)); + add_hypervisor_csr(CSR_VSTIMECMPH, std::make_shared(proc, CSR_VSTIMECMPH, vstimecmp)); } else { - add_csr(CSR_STIMECMP, virtualized_stimecmp); - add_csr(CSR_VSTIMECMP, vstimecmp); + add_supervisor_csr(CSR_STIMECMP, virtualized_stimecmp); + add_hypervisor_csr(CSR_VSTIMECMP, vstimecmp); } } @@ -347,19 +349,19 @@ void state_t::csr_init(processor_t* const proc, reg_t max_isa) if (proc->extension_enabled_const(EXT_SSCSRIND)) { csr_t_p vsiselect = std::make_shared(proc, CSR_VSISELECT, 0); - add_csr(CSR_VSISELECT, vsiselect); + add_hypervisor_csr(CSR_VSISELECT, vsiselect); csr_t_p siselect = std::make_shared(proc, CSR_SISELECT, 0); - add_csr(CSR_SISELECT, std::make_shared(proc, siselect, vsiselect)); + add_supervisor_csr(CSR_SISELECT, std::make_shared(proc, siselect, vsiselect)); const reg_t vsireg_csrs[] = { CSR_VSIREG, CSR_VSIREG2, CSR_VSIREG3, CSR_VSIREG4, CSR_VSIREG5, CSR_VSIREG6 }; const reg_t sireg_csrs[] = { CSR_SIREG, CSR_SIREG2, CSR_SIREG3, CSR_SIREG4, CSR_SIREG5, CSR_SIREG6 }; for (size_t i = 0; i < std::size(vsireg_csrs); i++) { auto vsireg = std::make_shared(proc, vsireg_csrs[i], vsiselect); - add_csr(vsireg_csrs[i], vsireg); + add_hypervisor_csr(vsireg_csrs[i], vsireg); auto sireg = std::make_shared(proc, sireg_csrs[i], siselect); - add_csr(sireg_csrs[i], std::make_shared(proc, sireg, vsireg)); + add_supervisor_csr(sireg_csrs[i], std::make_shared(proc, sireg, vsireg)); } } From e749bb0923f0571ee897fe1f75808de7b0d1753d Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 2 Aug 2024 13:16:06 +0800 Subject: [PATCH 127/155] Let MXR not affect implicit memory access for VS-stage address translation The behavior of MXR is clarified in https://github.com/riscv/riscv-isa-manual/pull/1543. --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 94997a23e9..ffbe66dce1 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -404,7 +404,7 @@ reg_t mmu_t::s2xlate(reg_t gva, reg_t gpa, access_type type, access_type trap_ty int maxgpabits = vm.levels * vm.idxbits + vm.widenbits + PGSHIFT; reg_t maxgpa = (1ULL << maxgpabits) - 1; - bool mxr = proc->state.sstatus->readvirt(false) & MSTATUS_MXR; + bool mxr = !is_for_vs_pt_addr && (proc->state.sstatus->readvirt(false) & MSTATUS_MXR); // tinst is set to 0x3000/0x3020 - for RV64 read/write respectively for // VS-stage address translation (for spike HSXLEN == VSXLEN always) else // tinst is set to 0x2000/0x2020 - for RV32 read/write respectively for From 92833d12701bd9072a7431f5ef350cf8634913cb Mon Sep 17 00:00:00 2001 From: Christian Herber Date: Wed, 7 Aug 2024 15:46:11 +0200 Subject: [PATCH 128/155] Add implemented extensions to readme - Fixes #1761 --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 63f29eb8e1..ed03cf2e55 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,7 @@ Spike supports the following RISC-V ISA features: - RV32E and RV64E base ISAs, v1.9 - Zifencei extension, v2.0 - Zicsr extension, v2.0 + - Zicntr extension, v2.0 - M extension, v2.0 - A extension, v2.1 - F extension, v2.2 @@ -61,6 +62,7 @@ Spike supports the following RISC-V ISA features: - Zvkt extension, v1.0 - Zvkn, Zvknc, Zvkng extension, v1.0 - Zvks, Zvksc, Zvksg extension, v1.0 + - Zicond extension, v1.0 - Zilsd extension, v0.9.0 - Zcmlsd extension, v0.9.0 From ddba69c98017a8a89a4dd255bf3e957c8c873890 Mon Sep 17 00:00:00 2001 From: Ved Shanbhogue Date: Wed, 7 Aug 2024 09:16:54 -0500 Subject: [PATCH 129/155] update readme with extensions --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index ed03cf2e55..bdb81bb449 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,7 @@ Spike supports the following RISC-V ISA features: - Zicntr extension, v2.0 - M extension, v2.0 - A extension, v2.1 + - B extension, v1.0 - F extension, v2.2 - D extension, v2.2 - Q extension, v2.2 @@ -38,11 +39,21 @@ Spike supports the following RISC-V ISA features: - Svnapot extension, v1.0 - Svpbmt extension, v1.0 - Svinval extension, v1.0 + - Svadu extension, v1.0 - Sdext extension, v1.0-STABLE - Sdtrig extension, v1.0-STABLE - Smepmp extension v1.0 - Smstateen extension, v1.0 - Sscofpmf v0.5.2 + - Ssdbltrp extension, v1.0 + - Ssqosid extension, v1.0 + - Zaamo extension, v1.0 + - Zalrsc extension, v1.0 + - Zabha extension, v1.0 + - Zacas extension, v1.0 + - Zawrs extension, v1.0 + - Zicfiss extension, v1.0 + - Zicfilp extension, v1.0 - Zca extension, v1.0 - Zcb extension, v1.0 - Zcf extension, v1.0 From c302e8bd16f5c05faff4e2ecfdeebcb502a55578 Mon Sep 17 00:00:00 2001 From: Ved Shanbhogue Date: Thu, 4 Jul 2024 14:47:27 -0500 Subject: [PATCH 130/155] Add Smdbltrp --- README.md | 1 + disasm/isa_parser.cc | 2 ++ riscv/csrs.cc | 16 ++++++++++++++-- riscv/csrs.h | 4 +++- riscv/encoding.h | 7 +++++-- riscv/execute.cc | 36 ++++++++++++++++++++++++++++-------- riscv/insns/dret.h | 10 +++++++++- riscv/insns/mret.h | 1 + riscv/insns/sret.h | 9 +++++++++ riscv/isa_parser.h | 1 + riscv/processor.cc | 24 +++++++++++++++++++----- riscv/processor.h | 4 +++- 12 files changed, 95 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 63f29eb8e1..4b36bf5605 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,7 @@ Spike supports the following RISC-V ISA features: - Sdtrig extension, v1.0-STABLE - Smepmp extension v1.0 - Smstateen extension, v1.0 + - Smdbltrp extension, v1.0 - Sscofpmf v0.5.2 - Zca extension, v1.0 - Zcb extension, v1.0 diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 79203dfbe2..72554a83b2 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -355,6 +355,8 @@ isa_parser_t::isa_parser_t(const char* str, const char *priv) elen = std::max(elen, new_elen); } else if (ext_str == "ssdbltrp") { extension_table[EXT_SSDBLTRP] = true; + } else if (ext_str == "smdbltrp") { + extension_table[EXT_SMDBLTRP] = true; } else if (ext_str[0] == 'x') { extension_table['X'] = true; if (ext_str.size() == 1) { diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 6fdd6a38c2..7ea1e4fa11 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -548,13 +548,17 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { | (has_page ? MSTATUS_TVM : 0) | (has_gva ? MSTATUS_GVA : 0) | (has_mpv ? MSTATUS_MPV : 0) + | (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0) | (proc->extension_enabled(EXT_ZICFILP) ? (MSTATUS_SPELP | MSTATUS_MPELP) : 0) | (proc->extension_enabled(EXT_SSDBLTRP) ? SSTATUS_SDT : 0) ; const reg_t requested_mpp = proc->legalize_privilege(get_field(val, MSTATUS_MPP)); const reg_t adjusted_val = set_field(val, MSTATUS_MPP, requested_mpp); - const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); + reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); + if (new_mstatus & MSTATUS_MDT) { + new_mstatus = new_mstatus & ~MSTATUS_MIE; + } maybe_flush_tlb(new_mstatus); this->val = adjust_sd(new_mstatus); return true; @@ -569,6 +573,7 @@ reg_t mstatus_csr_t::compute_mstatus_initial_value() const noexcept { | (proc->extension_enabled_const('U') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_UXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->extension_enabled_const('S') && (proc->get_const_xlen() != 32) ? set_field((reg_t)0, MSTATUS_SXL, xlen_to_uxl(proc->get_const_xlen())) : 0) | (proc->get_mmu()->is_target_big_endian() ? big_endian_bits : 0) + | (proc->extension_enabled(EXT_SMDBLTRP) ? MSTATUS_MDT : 0) | 0; // initial value for mstatus } @@ -1343,6 +1348,8 @@ dcsr_csr_t::dcsr_csr_t(processor_t* const proc, const reg_t addr): halt(false), v(false), cause(0), + ext_cause(0), + cetrig(0), pelp(elp_t::NO_LP_EXPECTED) { } @@ -1363,6 +1370,9 @@ reg_t dcsr_csr_t::read() const noexcept { result = set_field(result, DCSR_STOPCOUNT, 0); result = set_field(result, DCSR_STOPTIME, 0); result = set_field(result, DCSR_CAUSE, cause); + result = set_field(result, DCSR_EXTCAUSE, ext_cause); + if (proc->extension_enabled(EXT_SMDBLTRP)) + result = set_field(result, DCSR_CETRIG, cetrig); result = set_field(result, DCSR_STEP, step); result = set_field(result, DCSR_PRV, prv); result = set_field(result, CSR_DCSR_V, v); @@ -1382,12 +1392,14 @@ bool dcsr_csr_t::unlogged_write(const reg_t val) noexcept { v = proc->extension_enabled('H') ? get_field(val, CSR_DCSR_V) : false; pelp = proc->extension_enabled(EXT_ZICFILP) ? static_cast(get_field(val, DCSR_PELP)) : elp_t::NO_LP_EXPECTED; + cetrig = proc->extension_enabled(EXT_SMDBLTRP) ? get_field(val, DCSR_CETRIG) : false; return true; } -void dcsr_csr_t::update_fields(const uint8_t cause, const reg_t prv, +void dcsr_csr_t::update_fields(const uint8_t cause, uint8_t ext_cause, const reg_t prv, const bool v, const elp_t pelp) noexcept { this->cause = cause; + this->ext_cause = ext_cause; this->prv = prv; this->v = v; this->pelp = pelp; diff --git a/riscv/csrs.h b/riscv/csrs.h index db61fba980..4055d86272 100644 --- a/riscv/csrs.h +++ b/riscv/csrs.h @@ -684,7 +684,7 @@ class dcsr_csr_t: public csr_t { dcsr_csr_t(processor_t* const proc, const reg_t addr); virtual void verify_permissions(insn_t insn, bool write) const override; virtual reg_t read() const noexcept override; - void update_fields(const uint8_t cause, const reg_t prv, + void update_fields(const uint8_t cause, const uint8_t ext_cause, const reg_t prv, const bool v, const elp_t pelp) noexcept; protected: virtual bool unlogged_write(const reg_t val) noexcept override; @@ -699,6 +699,8 @@ class dcsr_csr_t: public csr_t { bool halt; bool v; uint8_t cause; + uint8_t ext_cause; + bool cetrig; elp_t pelp; }; diff --git a/riscv/encoding.h b/riscv/encoding.h index 675b4f6438..5f8eb7a694 100644 --- a/riscv/encoding.h +++ b/riscv/encoding.h @@ -4,7 +4,7 @@ /* * This file is auto-generated by running 'make' in - * https://github.com/riscv/riscv-opcodes (c55d30f) + * https://github.com/riscv/riscv-opcodes (048218e) */ #ifndef RISCV_CSR_ENCODING_H @@ -110,6 +110,9 @@ #define DCSR_CAUSE_STEP 4 #define DCSR_CAUSE_HALT 5 #define DCSR_CAUSE_GROUP 6 +#define DCSR_CAUSE_EXTCAUSE 7 + +#define DCSR_EXTCAUSE_CRITERR 0 #define MCONTROL_TYPE(xlen) (0xfULL<<((xlen)-4)) #define MCONTROL_DMODE(xlen) (1ULL<<((xlen)-5)) @@ -117,7 +120,7 @@ #define MCONTROL_SELECT (1<<19) #define MCONTROL_TIMING (1<<18) -#define MCONTROL_ACTION (0x3f<<12) +#define MCONTROL_ACTION (0xf<<12) #define MCONTROL_CHAIN (1<<11) #define MCONTROL_MATCH (0xf<<7) #define MCONTROL_M (1<<6) diff --git a/riscv/execute.cc b/riscv/execute.cc index cc77d88eec..f4c88cafa9 100644 --- a/riscv/execute.cc +++ b/riscv/execute.cc @@ -213,12 +213,11 @@ void processor_t::step(size_t n) { if (!state.debug_mode) { if (halt_request == HR_REGULAR) { - enter_debug_mode(DCSR_CAUSE_DEBUGINT); + enter_debug_mode(DCSR_CAUSE_DEBUGINT, 0); } else if (halt_request == HR_GROUP) { - enter_debug_mode(DCSR_CAUSE_GROUP); - } - else if (state.dcsr->halt) { - enter_debug_mode(DCSR_CAUSE_HALT); + enter_debug_mode(DCSR_CAUSE_GROUP, 0); + } else if (state.dcsr->halt) { + enter_debug_mode(DCSR_CAUSE_HALT, 0); } } @@ -257,7 +256,7 @@ void processor_t::step(size_t n) if (unlikely(!state.serialized && state.single_step == state.STEP_STEPPED)) { state.single_step = state.STEP_NONE; if (!state.debug_mode) { - enter_debug_mode(DCSR_CAUSE_STEP); + enter_debug_mode(DCSR_CAUSE_STEP, 0); // enter_debug_mode changed state.pc, so we can't just continue. break; } @@ -286,6 +285,17 @@ void processor_t::step(size_t n) disasm(fetch.insn); pc = execute_insn_logged(this, pc, fetch); advance_pc(); + + // Resume from debug mode in critical error + if (state.critical_error && !state.debug_mode) { + if (state.dcsr->read() & DCSR_CETRIG) { + enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR); + } else { + // Handling of critical error is implementation defined + // For now just enter debug mode + enter_debug_mode(DCSR_CAUSE_HALT, 0); + } + } } } else while (instret < n) @@ -311,13 +321,23 @@ void processor_t::step(size_t n) take_trap(t, pc); n = instret; + // If critical error then enter debug mode critical error trigger enabled + if (state.critical_error) { + if (state.dcsr->read() & DCSR_CETRIG) { + enter_debug_mode(DCSR_CAUSE_EXTCAUSE, DCSR_EXTCAUSE_CRITERR); + } else { + // Handling of critical error is implementation defined + // For now just enter debug mode + enter_debug_mode(DCSR_CAUSE_HALT, 0); + } + } // Trigger action takes priority over single step auto match = TM.detect_trap_match(t); if (match.has_value()) take_trigger_action(match->action, 0, state.pc, 0); else if (unlikely(state.single_step == state.STEP_STEPPED)) { state.single_step = state.STEP_NONE; - enter_debug_mode(DCSR_CAUSE_STEP); + enter_debug_mode(DCSR_CAUSE_STEP, 0); } } catch (triggers::matched_t& t) @@ -330,7 +350,7 @@ void processor_t::step(size_t n) } catch(trap_debug_mode&) { - enter_debug_mode(DCSR_CAUSE_SWBP); + enter_debug_mode(DCSR_CAUSE_SWBP, 0); } catch (wait_for_interrupt_t &t) { diff --git a/riscv/insns/dret.h b/riscv/insns/dret.h index 60aaf217b6..0f94f882af 100644 --- a/riscv/insns/dret.h +++ b/riscv/insns/dret.h @@ -4,8 +4,16 @@ if (ZICFILP_xLPE(STATE.dcsr->v, STATE.dcsr->prv)) { STATE.elp = STATE.dcsr->pelp; } p->set_privilege(STATE.dcsr->prv, STATE.dcsr->v); -if (STATE.prv < PRV_M) +if (STATE.prv < PRV_M) { STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MPRV); + STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT); +} + +if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v) + STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT); + +if (STATE.dcsr->v && STATE.dcsr->prv == PRV_U) + STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT); if (STATE.dcsr->prv == PRV_U || STATE.dcsr->v) STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT); diff --git a/riscv/insns/mret.h b/riscv/insns/mret.h index 140ebde778..4172b75fbb 100644 --- a/riscv/insns/mret.h +++ b/riscv/insns/mret.h @@ -13,6 +13,7 @@ if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, MSTATUS_MPELP)); } s = set_field(s, MSTATUS_MPELP, elp_t::NO_LP_EXPECTED); +s = set_field(s, MSTATUS_MDT, 0); if (prev_prv == PRV_U || prev_virt) s = set_field(s, MSTATUS_SDT, 0); if (prev_virt && prev_prv == PRV_U) diff --git a/riscv/insns/sret.h b/riscv/insns/sret.h index fe007d328b..efb4fa6d72 100644 --- a/riscv/insns/sret.h +++ b/riscv/insns/sret.h @@ -26,6 +26,15 @@ if (!STATE.v) { if (ZICFILP_xLPE(prev_virt, prev_prv)) { STATE.elp = static_cast(get_field(s, SSTATUS_SPELP)); } + +if (STATE.prv == PRV_M) { + STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_MDT); + if (prev_prv == PRV_U || prev_virt) + STATE.mstatus->write(STATE.mstatus->read() & ~MSTATUS_SDT); + if (prev_virt && prev_prv == PRV_U) + STATE.vsstatus->write(STATE.vsstatus->read() & ~SSTATUS_SDT); +} + s = set_field(s, SSTATUS_SPELP, elp_t::NO_LP_EXPECTED); if (STATE.prv == PRV_S) { diff --git a/riscv/isa_parser.h b/riscv/isa_parser.h index 45f637c640..12cc52ec14 100644 --- a/riscv/isa_parser.h +++ b/riscv/isa_parser.h @@ -82,6 +82,7 @@ typedef enum { EXT_ZICFILP, EXT_ZICFISS, EXT_SSDBLTRP, + EXT_SMDBLTRP, EXT_SMMPM, EXT_SMNPM, EXT_SSNPM, diff --git a/riscv/processor.cc b/riscv/processor.cc index d480f8f33d..0b318f5e12 100644 --- a/riscv/processor.cc +++ b/riscv/processor.cc @@ -159,6 +159,8 @@ void state_t::reset(processor_t* const proc, reg_t max_isa) elp = elp_t::NO_LP_EXPECTED; + critical_error = false; + csr_init(proc, max_isa); } @@ -379,11 +381,11 @@ const char* processor_t::get_privilege_string() abort(); } -void processor_t::enter_debug_mode(uint8_t cause) +void processor_t::enter_debug_mode(uint8_t cause, uint8_t extcause) { const bool has_zicfilp = extension_enabled(EXT_ZICFILP); state.debug_mode = true; - state.dcsr->update_fields(cause, state.prv, state.v, state.elp); + state.dcsr->update_fields(cause, extcause, state.prv, state.v, state.elp); state.elp = elp_t::NO_LP_EXPECTED; set_privilege(PRV_M, false); state.dpc->write(state.pc); @@ -500,10 +502,23 @@ void processor_t::take_trap(trap_t& t, reg_t epc) // Handle the trap in M-mode const reg_t vector = (state.mtvec->read() & 1) && interrupt ? 4 * bit : 0; const reg_t trap_handler_address = (state.mtvec->read() & ~(reg_t)1) + vector; - // RNMI exception vector is implementation-defined. Since we don't model // RNMI sources, the feature isn't very useful, so pick an invalid address. + // RNMI exception vector is implementation-defined. Since we don't model const reg_t rnmi_trap_handler_address = 0; const bool nmie = !(state.mnstatus && !get_field(state.mnstatus->read(), MNSTATUS_NMIE)); + + reg_t s = state.mstatus->read(); + if ( extension_enabled(EXT_SMDBLTRP)) { + if (get_field(s, MSTATUS_MDT) || !nmie) { + // Critical error - Double trap in M-mode or trap when nmie is 0 + // RNMI is not modeled else double trap in M-mode would trap to + // RNMI handler instead of leading to a critical error + state.critical_error = 1; + return; + } + s = set_field(s, MSTATUS_MDT, 1); + } + state.pc = !nmie ? rnmi_trap_handler_address : trap_handler_address; state.mepc->write(epc); state.mcause->write(supv_double_trap ? CAUSE_DOUBLE_TRAP : t.cause()); @@ -511,7 +526,6 @@ void processor_t::take_trap(trap_t& t, reg_t epc) state.mtval2->write(supv_double_trap ? t.cause() : t.get_tval2()); state.mtinst->write(t.get_tinst()); - reg_t s = state.mstatus->read(); s = set_field(s, MSTATUS_MPIE, get_field(s, MSTATUS_MIE)); s = set_field(s, MSTATUS_MPP, state.prv); s = set_field(s, MSTATUS_MIE, 0); @@ -537,7 +551,7 @@ void processor_t::take_trigger_action(triggers::action_t action, reg_t breakpoin switch (action) { case triggers::ACTION_DEBUG_MODE: - enter_debug_mode(DCSR_CAUSE_HWBP); + enter_debug_mode(DCSR_CAUSE_HWBP, 0); break; case triggers::ACTION_DEBUG_EXCEPTION: { trap_breakpoint trap(virt, breakpoint_tval); diff --git a/riscv/processor.h b/riscv/processor.h index 26d0878208..167cd88c0b 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -190,6 +190,8 @@ struct state_t elp_t elp; + bool critical_error; + private: void csr_init(processor_t* const proc, reg_t max_isa); }; @@ -405,7 +407,7 @@ class processor_t : public abstract_device_t void register_insn(insn_desc_t, bool); int paddr_bits(); - void enter_debug_mode(uint8_t cause); + void enter_debug_mode(uint8_t cause, uint8_t ext_cause); void debug_output_log(std::stringstream *s); // either output to interactive user or write to log file From 8b05d84ee90cc3d816030109e7a79986de1e252c Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 9 Aug 2024 09:47:04 -0700 Subject: [PATCH 131/155] Use ordered map for commit log In general, unordered maps should not be used for iteration, only for lookups. In this case, using an ordered map guarantees that the order in which writes are logged is consistent for a given instruction. Resolves #1499 --- riscv/processor.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/processor.h b/riscv/processor.h index 26d0878208..df77fc6ac2 100644 --- a/riscv/processor.h +++ b/riscv/processor.h @@ -62,7 +62,7 @@ struct insn_desc_t }; // regnum, data -typedef std::unordered_map commit_log_reg_t; +typedef std::map commit_log_reg_t; // addr, value, size typedef std::vector> commit_log_mem_t; From 9031c7b6515afaf5d8d2ece3176888deb94930e9 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Sun, 11 Aug 2024 16:42:36 -0700 Subject: [PATCH 132/155] Fix ordering of B single-letter extension The canonical order is IMAFDQLCBKJTPVH Signed-off-by: Jerry Zhao --- disasm/isa_parser.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/disasm/isa_parser.cc b/disasm/isa_parser.cc index 79203dfbe2..54dbf65a58 100644 --- a/disasm/isa_parser.cc +++ b/disasm/isa_parser.cc @@ -30,7 +30,7 @@ static void bad_priv_string(const char* priv) isa_parser_t::isa_parser_t(const char* str, const char *priv) { isa_string = strtolower(str); - const char* all_subsets = "mafdqcpvhb"; + const char* all_subsets = "mafdqcbpvh"; if (isa_string.compare(0, 4, "rv32") == 0) max_xlen = 32; From 20a508244aa8017d9a36a8e6b3257a6ffc22042c Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 12 Aug 2024 15:20:22 +0800 Subject: [PATCH 133/155] Fix a typo in https://github.com/riscv-software-src/riscv-isa-sim/pull/1721/commits/f11bd7b511d7909f0291589e3aaab720ededdc8a --- riscv/sim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/sim.cc b/riscv/sim.cc index 0e2717110b..a44aea9413 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -103,8 +103,8 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, cfg, this, cfg->hartids[i], halted, log_file.get(), sout_)); harts[cfg->hartids[i]] = procs[i]; - return; } + return; } // otherwise, generate the procs by parsing the DTS // Only make a CLINT (Core-Local INTerrupt controller) and PLIC (Platform- From 38330930daa2d5887d8f163661a18bf6e5378be8 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Fri, 16 Aug 2024 15:04:42 +0800 Subject: [PATCH 134/155] pointer masking: Fix: Let transformed_addr of fetching be unchanged The transformation does not apply to implicit accesses such as instruction fetches. --- riscv/mmu.cc | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index ffbe66dce1..62e8402d33 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -643,6 +643,7 @@ mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlat return {addr, addr, 0, false, {}, type}; bool virt = proc->state.v; reg_t mode = proc->state.prv; + reg_t transformed_addr = addr; if (type != FETCH) { if (in_mprv()) { mode = get_field(proc->state.mstatus->read(), MSTATUS_MPP); @@ -653,10 +654,10 @@ mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlat virt = true; mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); } + reg_t pmlen = get_pmlen(virt, mode, xlate_flags); + reg_t satp = proc->state.satp->readvirt(virt); + bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF; + transformed_addr = is_physical_addr ? zext(addr, 64 - pmlen) : sext(addr, 64 - pmlen); } - reg_t pmlen = get_pmlen(virt, mode, xlate_flags); - reg_t satp = proc->state.satp->readvirt(virt); - bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF; - reg_t transformed_addr = is_physical_addr ? zext(addr, 64 - pmlen) : sext(addr, 64 - pmlen); return {addr, transformed_addr, mode, virt, xlate_flags, type}; } From 0648ab40fc0742a8dbdbfbf82d71bbe0a3385317 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Sun, 18 Aug 2024 10:07:45 +0800 Subject: [PATCH 135/155] pointer masking: refactor: Use xlen to avoid sketchy, hardcoded number 64 --- riscv/mmu.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 62e8402d33..5d3454163f 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -654,10 +654,11 @@ mem_access_info_t mmu_t::generate_access_info(reg_t addr, access_type type, xlat virt = true; mode = get_field(proc->state.hstatus->read(), HSTATUS_SPVP); } + auto xlen = proc->get_const_xlen(); reg_t pmlen = get_pmlen(virt, mode, xlate_flags); reg_t satp = proc->state.satp->readvirt(virt); bool is_physical_addr = mode == PRV_M || get_field(satp, SATP64_MODE) == SATP_MODE_OFF; - transformed_addr = is_physical_addr ? zext(addr, 64 - pmlen) : sext(addr, 64 - pmlen); + transformed_addr = is_physical_addr ? zext(addr, xlen - pmlen) : sext(addr, xlen - pmlen); } return {addr, transformed_addr, mode, virt, xlate_flags, type}; } From 1a15805b946c2110cda279a4b7d84a382d0065b9 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Mon, 12 Aug 2024 09:13:38 -0700 Subject: [PATCH 136/155] Fix mcontrol6 mask low/high operations. I doubt this code was ever tested, and this change isn't tested either, because OpenOCD doesn't use this trigger type. This problem was reported in https://github.com/riscv/riscv-debug-spec/issues/1057 --- riscv/triggers.cc | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index de3da403dd..9eac9684e1 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -195,13 +195,17 @@ bool mcontrol_common_t::simple_match(unsigned xlen, reg_t value) const { return value < tdata2; case MATCH_MASK_LOW: { - reg_t mask = tdata2 >> (xlen/2); - return (value & mask) == (tdata2 & mask); + reg_t tdata2_high = tdata2 >> (xlen/2); + reg_t tdata2_low = tdata2 & ((reg_t(1) << (xlen/2)) - 1); + reg_t value_low = value & ((reg_t(1) << (xlen/2)) - 1); + return (value_low & tdata2_high) == tdata2_low; } case MATCH_MASK_HIGH: { - reg_t mask = tdata2 >> (xlen/2); - return ((value >> (xlen/2)) & mask) == (tdata2 & mask); + reg_t tdata2_high = tdata2 >> (xlen/2); + reg_t tdata2_low = tdata2 & ((reg_t(1) << (xlen/2)) - 1); + reg_t value_high = value >> (xlen/2); + return (value_high & tdata2_high) == tdata2_low; } } assert(0); From a1506ec006bad9c727652a5f7fbfe91c52572565 Mon Sep 17 00:00:00 2001 From: Tim Newsome Date: Tue, 20 Aug 2024 09:11:27 -0700 Subject: [PATCH 137/155] For mcontrol6, default to BEFORE timing. The existing implementation would end up using AFTER even for instruction execute and data store triggers, which is not desirable. --- riscv/triggers.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 9eac9684e1..5f3ffee38d 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -265,7 +265,14 @@ bool mcontrol_common_t::legalize_timing(reg_t val, reg_t timing_mask, reg_t sele return TIMING_AFTER; if (get_field(val, execute_mask)) return TIMING_BEFORE; - return get_field(val, timing_mask); + if (timing_mask) { + // Use the requested timing. + return get_field(val, timing_mask); + } else { + // For mcontrol6 you can't request a timing. Default to before since that's + // most useful to the user. + return TIMING_BEFORE; + } } reg_t mcontrol6_t::tdata1_read(const processor_t * const proc) const noexcept { From c72eca86877e43b7595a46219f7eb136154ce912 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 23 Aug 2024 14:48:21 -0700 Subject: [PATCH 138/155] Refactor insn_template to be more DRY --- riscv/insn_template.cc | 47 +++++++++++++++++++++--------------------- 1 file changed, 23 insertions(+), 24 deletions(-) diff --git a/riscv/insn_template.cc b/riscv/insn_template.cc index 9194d19f46..168e2dc836 100644 --- a/riscv/insn_template.cc +++ b/riscv/insn_template.cc @@ -5,24 +5,29 @@ #define DECODE_MACRO_USAGE_LOGGED 0 +#define PROLOGUE \ + reg_t npc = sext_xlen(pc + insn_length(OPCODE)) + +#define EPILOGUE \ + trace_opcode(p, OPCODE, insn); \ + return npc + reg_t fast_rv32i_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 32 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } reg_t fast_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 64 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } #undef DECODE_MACRO_USAGE_LOGGED @@ -31,21 +36,19 @@ reg_t fast_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc) reg_t logged_rv32i_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 32 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } reg_t logged_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 64 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } #undef CHECK_REG @@ -57,21 +60,19 @@ reg_t logged_rv64i_NAME(processor_t* p, insn_t insn, reg_t pc) reg_t fast_rv32e_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 32 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } reg_t fast_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 64 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } #undef DECODE_MACRO_USAGE_LOGGED @@ -80,19 +81,17 @@ reg_t fast_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc) reg_t logged_rv32e_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 32 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } reg_t logged_rv64e_NAME(processor_t* p, insn_t insn, reg_t pc) { #define xlen 64 - reg_t npc = sext_xlen(pc + insn_length(OPCODE)); + PROLOGUE; #include "insns/NAME.h" - trace_opcode(p, OPCODE, insn); + EPILOGUE; #undef xlen - return npc; } From 5efbfcbfa4611eb530c0854b4165613b73582f2d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 23 Aug 2024 14:59:09 -0700 Subject: [PATCH 139/155] Fix exception priority for RV32E loads and AMOs --- riscv/decode_macros.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index 0f32a3a106..e247487cc6 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -30,9 +30,9 @@ * 4 : csr */ #define WRITE_REG(reg, value) ({ \ + CHECK_REG(reg); \ reg_t wdata = (value); /* value may have side effects */ \ if (DECODE_MACRO_USAGE_LOGGED) STATE.log_reg_write[(reg) << 4] = {wdata, 0}; \ - CHECK_REG(reg); \ STATE.XPR.write(reg, wdata); \ }) #define WRITE_FREG(reg, value) ({ \ From 73bc67839acf9577b075b8d314f6514dcab2afd2 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Fri, 23 Aug 2024 14:59:34 -0700 Subject: [PATCH 140/155] Fix exception priority for RV32E JAL/JALR --- riscv/decode_macros.h | 1 + riscv/insns/jal.h | 1 + riscv/insns/jalr.h | 1 + 3 files changed, 3 insertions(+) diff --git a/riscv/decode_macros.h b/riscv/decode_macros.h index e247487cc6..1aa74fb86c 100644 --- a/riscv/decode_macros.h +++ b/riscv/decode_macros.h @@ -22,6 +22,7 @@ #define RS2 READ_REG(insn.rs2()) #define RS3 READ_REG(insn.rs3()) #define WRITE_RD(value) WRITE_REG(insn.rd(), value) +#define CHECK_RD() CHECK_REG(insn.rd()) /* 0 : int * 1 : floating diff --git a/riscv/insns/jal.h b/riscv/insns/jal.h index cd599641e2..e7a75c78ea 100644 --- a/riscv/insns/jal.h +++ b/riscv/insns/jal.h @@ -1,3 +1,4 @@ +CHECK_RD(); reg_t tmp = npc; set_pc(JUMP_TARGET); WRITE_RD(tmp); diff --git a/riscv/insns/jalr.h b/riscv/insns/jalr.h index 0606f67283..de84e891cd 100644 --- a/riscv/insns/jalr.h +++ b/riscv/insns/jalr.h @@ -1,3 +1,4 @@ +CHECK_RD(); reg_t tmp = npc; set_pc((RS1 + insn.i_imm()) & ~reg_t(1)); WRITE_RD(tmp); From 71bdc3bbd13a635637d730b2152aff912a929074 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Mon, 26 Aug 2024 14:18:51 +0800 Subject: [PATCH 141/155] pointer masking: Pointer masking does not apply when MXR=1 regardless of MPRV in v1.0.0-rc2 Reference: https://github.com/riscv/riscv-j-extension/issues/70 --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index 5d3454163f..e827f4ad3d 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -614,7 +614,7 @@ void mmu_t::register_memtracer(memtracer_t* t) } reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const { - if (!proc || proc->get_xlen() != 64 || (in_mprv() && (proc->state.sstatus->read() & MSTATUS_MXR)) || flags.hlvx) + if (!proc || proc->get_xlen() != 64 || (proc->state.sstatus->read() & MSTATUS_MXR) || flags.hlvx) return 0; reg_t pmm = 0; From d13dc0b3e30ceaa92b0b125bdb2747bcdd020819 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 27 Aug 2024 09:10:21 +0800 Subject: [PATCH 142/155] triggers: mcontrol: refactor: Add mcontrol_t::maskmax --- riscv/triggers.cc | 2 +- riscv/triggers.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 9eac9684e1..59cad80d6a 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -146,7 +146,7 @@ reg_t mcontrol_t::tdata1_read(const processor_t * const proc) const noexcept { auto xlen = proc->get_xlen(); v = set_field(v, MCONTROL_TYPE(xlen), CSR_TDATA1_TYPE_MCONTROL); v = set_field(v, CSR_MCONTROL_DMODE(xlen), dmode); - v = set_field(v, MCONTROL_MASKMAX(xlen), 0); + v = set_field(v, MCONTROL_MASKMAX(xlen), maskmax); v = set_field(v, CSR_MCONTROL_HIT, hit); v = set_field(v, MCONTROL_SELECT, select); v = set_field(v, MCONTROL_TIMING, timing); diff --git a/riscv/triggers.h b/riscv/triggers.h index 24f920630d..0ff86f00f3 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -243,6 +243,7 @@ class mcontrol_t : public mcontrol_common_t { private: bool hit = false; + const reg_t maskmax = 0; }; class mcontrol6_t : public mcontrol_common_t { From 1510a6e461719798d3702c3e786123a96444da03 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 27 Aug 2024 09:20:56 +0800 Subject: [PATCH 143/155] triggers: Let mcontrol.match be default (0/equal) if maskmax is 0 --- riscv/triggers.cc | 9 +++++---- riscv/triggers.h | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/riscv/triggers.cc b/riscv/triggers.cc index 59cad80d6a..5e877d1732 100644 --- a/riscv/triggers.cc +++ b/riscv/triggers.cc @@ -171,7 +171,7 @@ void mcontrol_t::tdata1_write(processor_t * const proc, const reg_t val, const b timing = legalize_timing(val, MCONTROL_TIMING, MCONTROL_SELECT, MCONTROL_EXECUTE, MCONTROL_LOAD); action = legalize_action(val, MCONTROL_ACTION, CSR_MCONTROL_DMODE(xlen)); chain = allow_chain ? get_field(val, MCONTROL_CHAIN) : 0; - match = legalize_match(get_field(val, MCONTROL_MATCH)); + match = legalize_match(get_field(val, MCONTROL_MATCH), maskmax); m = get_field(val, MCONTROL_M); s = proc->extension_enabled_const('S') ? get_field(val, CSR_MCONTROL_S) : 0; u = proc->extension_enabled_const('U') ? get_field(val, CSR_MCONTROL_U) : 0; @@ -244,11 +244,11 @@ std::optional mcontrol_common_t::detect_memory_access_match(proc return std::nullopt; } -mcontrol_common_t::match_t mcontrol_common_t::legalize_match(reg_t val) noexcept +mcontrol_common_t::match_t mcontrol_common_t::legalize_match(reg_t val, reg_t maskmax) noexcept { switch (val) { + case MATCH_NAPOT: if (maskmax == 0) return MATCH_EQUAL; case MATCH_EQUAL: - case MATCH_NAPOT: case MATCH_GE: case MATCH_LT: case MATCH_MASK_LOW: @@ -294,13 +294,14 @@ void mcontrol6_t::tdata1_write(processor_t * const proc, const reg_t val, const auto xlen = proc->get_const_xlen(); assert(get_field(val, CSR_MCONTROL6_TYPE(xlen)) == CSR_TDATA1_TYPE_MCONTROL6); dmode = get_field(val, CSR_MCONTROL6_DMODE(xlen)); + const reg_t maskmax6 = xlen - 1; vs = get_field(val, CSR_MCONTROL6_VS); vu = get_field(val, CSR_MCONTROL6_VU); hit = hit_t(2 * get_field(val, CSR_MCONTROL6_HIT1) + get_field(val, CSR_MCONTROL6_HIT0)); // 2-bit field {hit1,hit0} select = get_field(val, CSR_MCONTROL6_SELECT); action = legalize_action(val, CSR_MCONTROL6_ACTION, CSR_MCONTROL6_DMODE(xlen)); chain = allow_chain ? get_field(val, CSR_MCONTROL6_CHAIN) : 0; - match = legalize_match(get_field(val, CSR_MCONTROL6_MATCH)); + match = legalize_match(get_field(val, CSR_MCONTROL6_MATCH), maskmax6); m = get_field(val, CSR_MCONTROL6_M); s = proc->extension_enabled_const('S') ? get_field(val, CSR_MCONTROL6_S) : 0; u = proc->extension_enabled_const('U') ? get_field(val, CSR_MCONTROL6_U) : 0; diff --git a/riscv/triggers.h b/riscv/triggers.h index 0ff86f00f3..d88678defa 100644 --- a/riscv/triggers.h +++ b/riscv/triggers.h @@ -221,7 +221,7 @@ class mcontrol_common_t : public trigger_t { bool simple_match(unsigned xlen, reg_t value) const; protected: - static match_t legalize_match(reg_t val) noexcept; + static match_t legalize_match(reg_t val, reg_t maskmax) noexcept; static bool legalize_timing(reg_t val, reg_t timing_mask, reg_t select_mask, reg_t execute_mask, reg_t load_mask) noexcept; bool dmode = false; action_t action = ACTION_DEBUG_EXCEPTION; From eb07f100a37c12d2c0eb5501394c6c09342985c8 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Tue, 27 Aug 2024 13:57:03 -0700 Subject: [PATCH 144/155] Use cmdline --priv flag when parsing proc configurations from DTB --- riscv/sim.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/sim.cc b/riscv/sim.cc index a44aea9413..115fc0c4c9 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -195,7 +195,7 @@ sim_t::sim_t(const cfg_t *cfg, bool halted, exit(1); } - procs.push_back(new processor_t(isa_str, DEFAULT_PRIV, + procs.push_back(new processor_t(isa_str, cfg->priv, cfg, this, hartid, halted, log_file.get(), sout_)); harts[hartid] = procs[cpu_idx]; From 1b33b5426ba878555fbe87a26865fc42d26488ce Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 27 Aug 2024 16:54:46 -0700 Subject: [PATCH 145/155] Factor out create_mem_region from parse_mem_layout --- spike_main/spike.cc | 77 ++++++++++++++++++++++++--------------------- 1 file changed, 41 insertions(+), 36 deletions(-) diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 1a298f2d5c..14b02e7e8b 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -191,6 +191,46 @@ merge_overlapping_memory_regions(std::vector mems) return merged_mem; } +static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long size) +{ + // page-align base and size + auto base0 = base, size0 = size; + size += base0 % PGSIZE; + base -= base0 % PGSIZE; + if (size % PGSIZE != 0) + size += PGSIZE - size % PGSIZE; + + if (size != size0) { + fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n" + "to the %ld KiB page size: [0x%llX, 0x%llX]\n", + base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1); + } + + if (!mem_cfg_t::check_if_supported(base, size)) { + fprintf(stderr, "Unsupported memory region " + "{base = 0x%llX, size = 0x%llX} specified\n", + base, size); + exit(EXIT_FAILURE); + } + + const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull; + assert(max_allowed_pa <= std::numeric_limits::max()); + mem_cfg_t mem_region(base, size); + if (mem_region.get_inclusive_end() > max_allowed_pa) { + int bits_required = 64 - clz(mem_region.get_inclusive_end()); + fprintf(stderr, "Unsupported memory region " + "{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified," + " which requires %d bits of physical address\n" + " The largest accessible physical address " + "is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n", + mem_region.get_base(), mem_region.get_size(), bits_required, + max_allowed_pa, MAX_PADDR_BITS); + exit(EXIT_FAILURE); + } + + return mem_region; +} + static std::vector parse_mem_layout(const char* arg) { std::vector res; @@ -213,42 +253,7 @@ static std::vector parse_mem_layout(const char* arg) help(); auto size = strtoull(p + 1, &p, 0); - // page-align base and size - auto base0 = base, size0 = size; - size += base0 % PGSIZE; - base -= base0 % PGSIZE; - if (size % PGSIZE != 0) - size += PGSIZE - size % PGSIZE; - - if (size != size0) { - fprintf(stderr, "Warning: the memory at [0x%llX, 0x%llX] has been realigned\n" - "to the %ld KiB page size: [0x%llX, 0x%llX]\n", - base0, base0 + size0 - 1, long(PGSIZE / 1024), base, base + size - 1); - } - - if (!mem_cfg_t::check_if_supported(base, size)) { - fprintf(stderr, "Unsupported memory region " - "{base = 0x%llX, size = 0x%llX} specified\n", - base, size); - exit(EXIT_FAILURE); - } - - const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull; - assert(max_allowed_pa <= std::numeric_limits::max()); - mem_cfg_t mem_region(base, size); - if (mem_region.get_inclusive_end() > max_allowed_pa) { - int bits_required = 64 - clz(mem_region.get_inclusive_end()); - fprintf(stderr, "Unsupported memory region " - "{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified," - " which requires %d bits of physical address\n" - " The largest accessible physical address " - "is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n", - mem_region.get_base(), mem_region.get_size(), bits_required, - max_allowed_pa, MAX_PADDR_BITS); - exit(EXIT_FAILURE); - } - - res.push_back(mem_region); + res.push_back(create_mem_region(base, size)); if (!*p) break; From eb85c33899ea06a7011d857375282926243442dd Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 27 Aug 2024 16:55:16 -0700 Subject: [PATCH 146/155] Check size_t bounds overflow in create_mem_region --- riscv/cfg.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/riscv/cfg.cc b/riscv/cfg.cc index 8763240b91..2f9a229b0b 100644 --- a/riscv/cfg.cc +++ b/riscv/cfg.cc @@ -18,13 +18,15 @@ bool mem_cfg_t::check_if_supported(reg_t base, reg_t size) // the regions in the first place, but we have them here to make sure that // we can't end up describing memory regions that don't make sense. They // ask that the page size is a multiple of the minimum page size, that the - // page is aligned to the minimum page size, that the page is non-empty and - // that the top address is still representable in a reg_t. + // page is aligned to the minimum page size, that the page is non-empty, + // that the size doesn't overflow size_t, and that the top address is still + // representable in a reg_t. // // Note: (base + size == 0) part of the assertion is to handle cases like // { base = 0xffff_ffff_ffff_f000, size: 0x1000 } return (size % PGSIZE == 0) && (base % PGSIZE == 0) && + (size_t(size) == size) && (size > 0) && ((base + size > base) || (base + size == 0)); } From 16870946ed32d79b1eb4597d9266194b3b543c3f Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 27 Aug 2024 16:55:43 -0700 Subject: [PATCH 147/155] Use create_mem_region for legacy -m argument --- spike_main/spike.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 14b02e7e8b..4c09ac38b8 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -240,9 +240,9 @@ static std::vector parse_mem_layout(const char* arg) auto mb = strtoull(arg, &p, 0); if (*p == 0) { reg_t size = reg_t(mb) << 20; - if (size != (size_t)size) - throw std::runtime_error("Size would overflow size_t"); - res.push_back(mem_cfg_t(reg_t(DRAM_BASE), size)); + if ((size >> 20) != mb) + throw std::runtime_error("Memory size too large"); + res.push_back(create_mem_region(DRAM_BASE, size)); return res; } From 52f045d9ba21fe0552c1475e4171fddc3c13c5e3 Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Tue, 27 Aug 2024 18:08:50 -0700 Subject: [PATCH 148/155] Lift restriction on physical-address size It remains true that PTEs can only represent addresses >= 2^56, but there's no need to impose that constraint on untranslated accesses. --- riscv/mmu.h | 2 +- riscv/sim.cc | 3 ++- spike_main/spike.cc | 17 +---------------- 3 files changed, 4 insertions(+), 18 deletions(-) diff --git a/riscv/mmu.h b/riscv/mmu.h index 0aa1f96704..1047a71261 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -19,7 +19,7 @@ #define PGSHIFT 12 const reg_t PGSIZE = 1 << PGSHIFT; const reg_t PGMASK = ~(PGSIZE-1); -#define MAX_PADDR_BITS 56 // imposed by Sv39 / Sv48 +#define MAX_PADDR_BITS 64 struct insn_fetch_t { diff --git a/riscv/sim.cc b/riscv/sim.cc index d08e274d9d..8ab74b182b 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -322,7 +322,8 @@ void sim_t::set_procs_debug(bool value) static bool paddr_ok(reg_t addr) { - return (addr >> MAX_PADDR_BITS) == 0; + static_assert(MAX_PADDR_BITS == 8 * sizeof(addr)); + return true; } bool sim_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes) diff --git a/spike_main/spike.cc b/spike_main/spike.cc index 4c09ac38b8..d656d64e4f 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -213,22 +213,7 @@ static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long s exit(EXIT_FAILURE); } - const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull; - assert(max_allowed_pa <= std::numeric_limits::max()); - mem_cfg_t mem_region(base, size); - if (mem_region.get_inclusive_end() > max_allowed_pa) { - int bits_required = 64 - clz(mem_region.get_inclusive_end()); - fprintf(stderr, "Unsupported memory region " - "{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified," - " which requires %d bits of physical address\n" - " The largest accessible physical address " - "is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n", - mem_region.get_base(), mem_region.get_size(), bits_required, - max_allowed_pa, MAX_PADDR_BITS); - exit(EXIT_FAILURE); - } - - return mem_region; + return mem_cfg_t(base, size); } static std::vector parse_mem_layout(const char* arg) From 61d277c49c7843476abe671f05aa78f08e6278b2 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Wed, 28 Aug 2024 11:34:57 +0800 Subject: [PATCH 149/155] pointer masking: Consider effective v bit instead of current v bit A previous commit removes the effectiveness of MPRV to MXR. (https://github.com/riscv-software-src/riscv-isa-sim/pull/1784) However, the removal implies the MPRV affects point masking individually, and the MXR should consider the effective v bit. --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index e827f4ad3d..ea86900da3 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -614,7 +614,7 @@ void mmu_t::register_memtracer(memtracer_t* t) } reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const { - if (!proc || proc->get_xlen() != 64 || (proc->state.sstatus->read() & MSTATUS_MXR) || flags.hlvx) + if (!proc || proc->get_xlen() != 64 || (proc->state.sstatus->readvirt(effective_virt) & MSTATUS_MXR) || flags.hlvx) return 0; reg_t pmm = 0; From 84a212e93bac83db1537c7ff14985c3c414f7f31 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Thu, 29 Aug 2024 16:05:42 +0800 Subject: [PATCH 150/155] pointer masking: Always apply sstatus.MXR regardless of effective V ISA spec says "Setting MXR at HS-level overrides both VS-stage and G-stage execute-only permissions." --- riscv/mmu.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/riscv/mmu.cc b/riscv/mmu.cc index ea86900da3..38ecb65144 100644 --- a/riscv/mmu.cc +++ b/riscv/mmu.cc @@ -614,7 +614,7 @@ void mmu_t::register_memtracer(memtracer_t* t) } reg_t mmu_t::get_pmlen(bool effective_virt, reg_t effective_priv, xlate_flags_t flags) const { - if (!proc || proc->get_xlen() != 64 || (proc->state.sstatus->readvirt(effective_virt) & MSTATUS_MXR) || flags.hlvx) + if (!proc || proc->get_xlen() != 64 || ((proc->state.sstatus->readvirt(false) | proc->state.sstatus->readvirt(effective_virt)) & MSTATUS_MXR) || flags.hlvx) return 0; reg_t pmm = 0; From ff6210921127925582802bf7e7ad6952c0e0758f Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 3 Sep 2024 08:54:06 +0800 Subject: [PATCH 151/155] vector: disassemble: Let operand ordering be vd, [vr]s1, vs2 to vector single-width integer multiply-add instructions --- disasm/disasm.cc | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index c3ba62a690..b5e842872f 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -735,11 +735,21 @@ static void NOINLINE add_vector_vv_insn(disassembler_t* d, const char* name, uin d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &vs1, opt, &vm})); } +static void NOINLINE add_vector_multiplyadd_vv_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) +{ + d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs1, &vs2, opt, &vm})); +} + static void NOINLINE add_vector_vx_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) { d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &xrs1, opt, &vm})); } +static void NOINLINE add_vector_multiplyadd_vx_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) +{ + d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &xrs1, &vs2, opt, &vm})); +} + static void NOINLINE add_vector_vf_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) { d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &frs1, opt, &vm})); @@ -1642,7 +1652,9 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) #define DEFINE_VECTOR_V(code) add_vector_v_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VV(code) add_vector_vv_insn(this, #code, match_##code, mask_##code) + #define DEFINE_VECTOR_MULTIPLYADD_VV(code) add_vector_multiplyadd_vv_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VX(code) add_vector_vx_insn(this, #code, match_##code, mask_##code) + #define DEFINE_VECTOR_MULTIPLYADD_VX(code) add_vector_multiplyadd_vx_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VF(code) add_vector_vf_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VI(code) add_vector_vi_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VIU(code) add_vector_viu_insn(this, #code, match_##code, mask_##code) @@ -1659,6 +1671,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DEFINE_VECTOR_VV(name##_vv); \ DEFINE_VECTOR_VX(name##_vx) + #define DISASM_OPIV_MULTIPLYADD_VX__INSN(name, sign) \ + DEFINE_VECTOR_MULTIPLYADD_VV(name##_vv); \ + DEFINE_VECTOR_MULTIPLYADD_VX(name##_vx) + #define DISASM_OPIV__XI_INSN(name, sign) \ DEFINE_VECTOR_VX(name##_vx); \ if (sign) \ @@ -1821,10 +1837,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_OPIV_VX__INSN(vmul, 1); DISASM_OPIV_VX__INSN(vmulhsu, 0); DISASM_OPIV_VX__INSN(vmulh, 1); - DISASM_OPIV_VX__INSN(vmadd, 1); - DISASM_OPIV_VX__INSN(vnmsub, 1); - DISASM_OPIV_VX__INSN(vmacc, 1); - DISASM_OPIV_VX__INSN(vnmsac, 1); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vmadd, 1); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vnmsub, 1); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vmacc, 1); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vnmsac, 1); //0b11_0000 DISASM_OPIV_VX__INSN(vwaddu, 0); From 7f38a503d032adafc10b3e9eea006d65e464e991 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 3 Sep 2024 08:56:02 +0800 Subject: [PATCH 152/155] vector: disassemble: Let operand ordering be vd, [vr]s1, vs2 to vector widening integer multiply-add instructions --- disasm/disasm.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index b5e842872f..1741969599 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -1694,6 +1694,8 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) #define DISASM_OPIV__X__INSN(name, sign) DEFINE_VECTOR_VX(name##_vx) + #define DISASM_OPIV_MULTIPLYADD__X__INSN(name, sign) DEFINE_VECTOR_MULTIPLYADD_VX(name##_vx) + #define DEFINE_VECTOR_VVM(name) \ add_vector_vvm_insn(this, #name, match_##name, mask_##name | mask_vm) @@ -1854,10 +1856,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_OPIV_VX__INSN(vwmulu, 0); DISASM_OPIV_VX__INSN(vwmulsu, 0); DISASM_OPIV_VX__INSN(vwmul, 1); - DISASM_OPIV_VX__INSN(vwmaccu, 0); - DISASM_OPIV_VX__INSN(vwmacc, 1); - DISASM_OPIV__X__INSN(vwmaccus, 1); - DISASM_OPIV_VX__INSN(vwmaccsu, 0); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmaccu, 0); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmacc, 1); + DISASM_OPIV_MULTIPLYADD__X__INSN(vwmaccus, 1); + DISASM_OPIV_MULTIPLYADD_VX__INSN(vwmaccsu, 0); #undef DISASM_OPIV_VXI_INSN #undef DISASM_OPIV_VX__INSN From b47d0baab34a03268f936c1c9400d61c46d54d67 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 3 Sep 2024 08:49:06 +0800 Subject: [PATCH 153/155] vector: disassemble: Let operand ordering be vd, [vf]s1, vs2 to vector single-width floating-point fused multiply-add instructions --- disasm/disasm.cc | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index 1741969599..bad2ec43c0 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -755,6 +755,11 @@ static void NOINLINE add_vector_vf_insn(disassembler_t* d, const char* name, uin d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &frs1, opt, &vm})); } +static void NOINLINE add_vector_multiplyadd_vf_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) +{ + d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &frs1, &vs2, opt, &vm})); +} + static void NOINLINE add_vector_vi_insn(disassembler_t* d, const char* name, uint32_t match, uint32_t mask) { d->add_insn(new disasm_insn_t(name, match, mask, {&vd, &vs2, &v_simm5, opt, &vm})); @@ -1656,6 +1661,7 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) #define DEFINE_VECTOR_VX(code) add_vector_vx_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_MULTIPLYADD_VX(code) add_vector_multiplyadd_vx_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VF(code) add_vector_vf_insn(this, #code, match_##code, mask_##code) + #define DEFINE_VECTOR_MULTIPLYADD_VF(code) add_vector_multiplyadd_vf_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VI(code) add_vector_vi_insn(this, #code, match_##code, mask_##code) #define DEFINE_VECTOR_VIU(code) add_vector_viu_insn(this, #code, match_##code, mask_##code) @@ -1876,6 +1882,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DEFINE_VECTOR_VV(name##_vv); \ DEFINE_VECTOR_VF(name##_vf) + #define DISASM_OPIV_MULTIPLYADD_VF_INSN(name) \ + DEFINE_VECTOR_MULTIPLYADD_VV(name##_vv); \ + DEFINE_VECTOR_MULTIPLYADD_VF(name##_vf) + #define DISASM_OPIV_WF_INSN(name) \ DEFINE_VECTOR_VV(name##_wv); \ DEFINE_VECTOR_VF(name##_wf) @@ -1943,14 +1953,14 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_OPIV_VF_INSN(vfmul); DISASM_OPIV__F_INSN(vfrsub); - DISASM_OPIV_VF_INSN(vfmadd); - DISASM_OPIV_VF_INSN(vfnmadd); - DISASM_OPIV_VF_INSN(vfmsub); - DISASM_OPIV_VF_INSN(vfnmsub); - DISASM_OPIV_VF_INSN(vfmacc); - DISASM_OPIV_VF_INSN(vfnmacc); - DISASM_OPIV_VF_INSN(vfmsac); - DISASM_OPIV_VF_INSN(vfnmsac); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmadd); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmadd); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmsub); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmsub); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmacc); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmacc); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfmsac); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfnmsac); //0b11_0000 DISASM_OPIV_VF_INSN(vfwadd); From 6a1a5db16b60abaecd235f78f5d70716bf47c9a9 Mon Sep 17 00:00:00 2001 From: YenHaoChen Date: Tue, 3 Sep 2024 08:49:53 +0800 Subject: [PATCH 154/155] vector: disassemble: Let operand ordering be vd, [vf]s1, vs2 to vector widening floating-point fused multiply-add instructions --- disasm/disasm.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/disasm/disasm.cc b/disasm/disasm.cc index bad2ec43c0..f1967d0a27 100644 --- a/disasm/disasm.cc +++ b/disasm/disasm.cc @@ -1970,10 +1970,10 @@ void disassembler_t::add_instructions(const isa_parser_t* isa) DISASM_OPIV_WF_INSN(vfwadd); DISASM_OPIV_WF_INSN(vfwsub); DISASM_OPIV_VF_INSN(vfwmul); - DISASM_OPIV_VF_INSN(vfwmacc); - DISASM_OPIV_VF_INSN(vfwnmacc); - DISASM_OPIV_VF_INSN(vfwmsac); - DISASM_OPIV_VF_INSN(vfwnmsac); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwmacc); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwnmacc); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwmsac); + DISASM_OPIV_MULTIPLYADD_VF_INSN(vfwnmsac); #undef DISASM_OPIV_VF_INSN #undef DISASM_OPIV__F_INSN From 04a17bd198953da8cfe6154c60592d30cb62f529 Mon Sep 17 00:00:00 2001 From: lewislzh Date: Thu, 5 Sep 2024 17:03:28 +0800 Subject: [PATCH 155/155] fix : compile error of merge * Revert "Lift restriction on physical-address size" This reverts commit 52f045d9ba21fe0552c1475e4171fddc3c13c5e3. * fix some merge compile errors --- difftest/difftest.cc | 1 - riscv/csrs.cc | 2 +- riscv/mmu.h | 2 +- riscv/sim.cc | 3 +-- spike_main/spike.cc | 17 ++++++++++++++++- 5 files changed, 19 insertions(+), 6 deletions(-) diff --git a/difftest/difftest.cc b/difftest/difftest.cc index e43dfe9334..0d6b9ec138 100644 --- a/difftest/difftest.cc +++ b/difftest/difftest.cc @@ -447,7 +447,6 @@ const cfg_t *DifftestRef::create_cfg() { cfg->bootargs = nullptr; cfg->isa = CONFIG_DIFF_ISA_STRING; cfg->priv = DEFAULT_PRIV; - cfg->varch = DEFAULT_VARCH; cfg->misaligned = false; // const endianness_t default_endianness, cfg->endianness = endianness_little; diff --git a/riscv/csrs.cc b/riscv/csrs.cc index 265f47d006..bafc6a7345 100644 --- a/riscv/csrs.cc +++ b/riscv/csrs.cc @@ -579,7 +579,7 @@ bool mstatus_csr_t::unlogged_write(const reg_t val) noexcept { reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); new_mstatus ^= new_mstatus & (0x3 << 13); // FS is always zero #else - const reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); + reg_t new_mstatus = (read() & ~mask) | (adjusted_val & mask); if (new_mstatus & MSTATUS_MDT) { new_mstatus = new_mstatus & ~MSTATUS_MIE; } diff --git a/riscv/mmu.h b/riscv/mmu.h index 5cd4b3128e..0e6ab89363 100644 --- a/riscv/mmu.h +++ b/riscv/mmu.h @@ -22,7 +22,7 @@ const reg_t PGMASK = ~(PGSIZE-1); #ifdef CONFIG_MAX_PADDR_BITS #define MAX_PADDR_BITS CONFIG_MAX_PADDR_BITS #else -#define MAX_PADDR_BITS 64 +#define MAX_PADDR_BITS 56 // imposed by Sv39 / Sv48 #endif struct insn_fetch_t diff --git a/riscv/sim.cc b/riscv/sim.cc index 2164da803a..a42e746238 100644 --- a/riscv/sim.cc +++ b/riscv/sim.cc @@ -340,8 +340,7 @@ void sim_t::set_procs_debug(bool value) static bool paddr_ok(reg_t addr) { - static_assert(MAX_PADDR_BITS == 8 * sizeof(addr)); - return true; + return (addr >> MAX_PADDR_BITS) == 0; } bool sim_t::mmio_load(reg_t paddr, size_t len, uint8_t* bytes) diff --git a/spike_main/spike.cc b/spike_main/spike.cc index d656d64e4f..4c09ac38b8 100644 --- a/spike_main/spike.cc +++ b/spike_main/spike.cc @@ -213,7 +213,22 @@ static mem_cfg_t create_mem_region(unsigned long long base, unsigned long long s exit(EXIT_FAILURE); } - return mem_cfg_t(base, size); + const unsigned long long max_allowed_pa = (1ull << MAX_PADDR_BITS) - 1ull; + assert(max_allowed_pa <= std::numeric_limits::max()); + mem_cfg_t mem_region(base, size); + if (mem_region.get_inclusive_end() > max_allowed_pa) { + int bits_required = 64 - clz(mem_region.get_inclusive_end()); + fprintf(stderr, "Unsupported memory region " + "{base = 0x%" PRIX64 ", size = 0x%" PRIX64 "} specified," + " which requires %d bits of physical address\n" + " The largest accessible physical address " + "is 0x%llX (defined by MAX_PADDR_BITS constant, which is %d)\n", + mem_region.get_base(), mem_region.get_size(), bits_required, + max_allowed_pa, MAX_PADDR_BITS); + exit(EXIT_FAILURE); + } + + return mem_region; } static std::vector parse_mem_layout(const char* arg)