mirror of
https://github.com/openhwgroup/cva6.git
synced 2025-04-22 13:17:41 -04:00
Merge pull request #1937 from zchamski/pr/spike-update-vendorized-tree
Update vendorized Spike tree and Spike-related components.
This commit is contained in:
commit
e3ec071f66
512 changed files with 19151 additions and 13856 deletions
|
@ -152,8 +152,8 @@ pub_build_tools:
|
|||
# If initially set to "__local__", SPIKE_INSTALL_DIR will be resolved
|
||||
# to an absolute path by the installation script.
|
||||
- source cva6/regress/install-spike.sh
|
||||
# Strip locally built binaries and customext library to reduce artifact size.
|
||||
- '[ -f $(pwd)/tools/spike/bin/spike ] && strip $(pwd)/tools/spike/bin/spike* $(pwd)/tools/spike/lib/libcustomext.so'
|
||||
# Strip locally built binaries and libraries to reduce artifact size.
|
||||
- '[ -f $(pwd)/tools/spike/bin/spike ] && strip $(pwd)/tools/spike/bin/spike* $(pwd)/tools/spike/lib/lib*.*'
|
||||
artifacts:
|
||||
paths:
|
||||
- tools/spike/
|
||||
|
|
|
@ -196,7 +196,7 @@ endif
|
|||
dpi-library = $(VCS_WORK_DIR)/work-dpi
|
||||
dpi_build:
|
||||
mkdir -p $(dpi-library)
|
||||
g++ -shared -fPIC -std=c++0x -Bsymbolic -std=c++11 -I../corev_apu/tb/dpi -O3 -I$(SPIKE_ROOT)/include \
|
||||
g++ -shared -fPIC -std=c++17 -Bsymbolic -I../corev_apu/tb/dpi -O3 -I$(SPIKE_ROOT)/include \
|
||||
-I$(VCS_HOME)/include -I$(RISCV)/include -c $(CVA6_REPO_DIR)/corev_apu/tb/dpi/elfloader.cc \
|
||||
-o $(dpi-library)/elfloader.o
|
||||
g++ -shared -m64 -o $(dpi-library)/ariane_dpi.so $(dpi-library)/elfloader.o -L$(RISCV)/lib -Wl,-rpath,$(RISCV)/lib
|
||||
|
|
12
vendor/patches/riscv/riscv-isa-sim/0001-generate-shared-fesvr-lib.patch
vendored
Normal file
12
vendor/patches/riscv/riscv-isa-sim/0001-generate-shared-fesvr-lib.patch
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
diff --git a/fesvr/fesvr.mk.in b/fesvr/fesvr.mk.in
|
||||
index 695de5278..43aed6786 100644
|
||||
--- a/fesvr/fesvr.mk.in
|
||||
+++ b/fesvr/fesvr.mk.in
|
||||
@@ -20,6 +20,7 @@ fesvr_install_hdrs = $(fesvr_hdrs)
|
||||
fesvr_install_config_hdr = yes
|
||||
|
||||
fesvr_install_lib = yes
|
||||
+fesvr_install_shared_lib = yes
|
||||
|
||||
fesvr_srcs = \
|
||||
elfloader.cc \
|
15
vendor/patches/riscv/riscv-isa-sim/0002-improve-extension-loading-diagnostics.patch
vendored
Normal file
15
vendor/patches/riscv/riscv-isa-sim/0002-improve-extension-loading-diagnostics.patch
vendored
Normal file
|
@ -0,0 +1,15 @@
|
|||
diff --git a/riscv/extensions.cc b/riscv/extensions.cc
|
||||
index 347dc5e91..b488aad15 100644
|
||||
--- a/riscv/extensions.cc
|
||||
+++ b/riscv/extensions.cc
|
||||
@@ -27,8 +27,8 @@ std::function<extension_t*()> find_extension(const char* name)
|
||||
if (!dlh) {
|
||||
dlh = dlopen(libdefault.c_str(), RTLD_LAZY);
|
||||
if (!dlh) {
|
||||
- fprintf(stderr, "couldn't find shared library either '%s' or '%s')\n",
|
||||
- libname.c_str(), libdefault.c_str());
|
||||
+ fprintf(stderr, "couldn't load shared library (either '%s' or '%s'), reason: %s\n",
|
||||
+ libname.c_str(), libdefault.c_str(), dlerror());
|
||||
exit(-1);
|
||||
}
|
||||
|
533
vendor/patches/riscv/riscv-isa-sim/0003-add-cvxif-extension.patch
vendored
Normal file
533
vendor/patches/riscv/riscv-isa-sim/0003-add-cvxif-extension.patch
vendored
Normal file
|
@ -0,0 +1,533 @@
|
|||
diff --git a/customext/customext.mk.in b/customext/customext.mk.in
|
||||
index a14e771c2..888634b46 100644
|
||||
--- a/customext/customext.mk.in
|
||||
+++ b/customext/customext.mk.in
|
||||
@@ -7,5 +7,6 @@ customext_subproject_deps = \
|
||||
customext_srcs = \
|
||||
dummy_rocc.cc \
|
||||
cflush.cc \
|
||||
+ cvxif.cc \
|
||||
|
||||
customext_install_shared_lib = yes
|
||||
diff --git a/customext/cvxif.cc b/customext/cvxif.cc
|
||||
new file mode 100644
|
||||
index 000000000..dd1a7329a
|
||||
--- /dev/null
|
||||
+++ b/customext/cvxif.cc
|
||||
@@ -0,0 +1,226 @@
|
||||
+// Copyright (C) 2022 Thales DIS Design Services SAS
|
||||
+//
|
||||
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0.
|
||||
+//
|
||||
+// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
+
|
||||
+#include "cvxif.h"
|
||||
+#include "mmu.h"
|
||||
+#include <cstring>
|
||||
+
|
||||
+// Define custom insns templates.
|
||||
+// The insn-level wrapper is 'c##n' (default implementation,
|
||||
+// writeback disabled), the default implementation
|
||||
+// is 'custom##n': illegal instruction, return 0.
|
||||
+// The writeback controller 'cvxif_extn_t::do_writeback_p'
|
||||
+// is in charge of determining if writeback is required or not.
|
||||
+// Expected instruction encoding is 4 bytes.
|
||||
+#define customX(n) \
|
||||
+static reg_t c##n(processor_t* p, insn_t insn, reg_t pc) \
|
||||
+ { \
|
||||
+ cvxif_t* cvxif = static_cast<cvxif_t*>(p->get_extension()); \
|
||||
+ cvxif_insn_t custom_insn; \
|
||||
+ custom_insn.i = insn; \
|
||||
+ reg_t xd = cvxif->default_custom##n(custom_insn); \
|
||||
+ if (cvxif->do_writeback_p(custom_insn)) \
|
||||
+ WRITE_RD(xd); \
|
||||
+ return pc+4; \
|
||||
+ } \
|
||||
+ \
|
||||
+ reg_t default_custom##n(cvxif_insn_t insn) \
|
||||
+ { \
|
||||
+ return custom##n(insn); \
|
||||
+ }
|
||||
+
|
||||
+// This class instantiates the CV-X-IF interface.
|
||||
+class cvxif_t : public cvxif_extn_t
|
||||
+{
|
||||
+ public:
|
||||
+ const char* name() { return "cvxif_spike"; }
|
||||
+
|
||||
+ bool do_writeback_p(cvxif_insn_t copro_insn)
|
||||
+ {
|
||||
+ // INSN_R personality serves to simplify access to standard encoding fields.
|
||||
+ cvxif_r_insn_t insn_r = copro_insn.r_type;
|
||||
+
|
||||
+ if (insn_r.opcode != MATCH_CUSTOM3)
|
||||
+ return false;
|
||||
+ else switch (insn_r.funct3)
|
||||
+ {
|
||||
+ case 0b000:
|
||||
+ // CUSTOM_NOP and CUSTOM_EXC have rd == x0.
|
||||
+ // Return TRUE if destination is NOT x0.
|
||||
+ return (insn_r.rd != 0x0);
|
||||
+
|
||||
+ case 0b010:
|
||||
+ // Return false for CUS_SD.
|
||||
+ return false;
|
||||
+
|
||||
+ default:
|
||||
+ // All other cases: writeback is assumed REQUIRED.
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Custom0 instructions: default behaviour.
|
||||
+ reg_t custom0(cvxif_insn_t incoming_insn)
|
||||
+ {
|
||||
+ illegal_instruction();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // Custom1 instructions: default behaviour.
|
||||
+ reg_t custom1(cvxif_insn_t incoming_insn)
|
||||
+ {
|
||||
+ illegal_instruction();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // Custom2 instructions: default behaviour.
|
||||
+ reg_t custom2(cvxif_insn_t incoming_insn)
|
||||
+ {
|
||||
+ illegal_instruction();
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ // Custom3 instructions: provide an explicit implementation of decode+exec.
|
||||
+ reg_t custom3(cvxif_insn_t incoming_insn)
|
||||
+ {
|
||||
+ // Assume R-type insn: it shares opcode and funct3 fields with other CVXIF insn formats.
|
||||
+ cvxif_r_insn_t r_insn = incoming_insn.r_type;
|
||||
+ // INSN_T simplifies access to register values.
|
||||
+ insn_t insn = incoming_insn.i;
|
||||
+
|
||||
+ switch (r_insn.funct3)
|
||||
+ {
|
||||
+ case 0:
|
||||
+
|
||||
+ // funct7[1:0] == 0b01: three-input RV add.
|
||||
+ // If rd is x0: illegal instruction.
|
||||
+ if ((r_insn.funct7 & 0x3) == 0b01)
|
||||
+ {
|
||||
+ if (insn.rd() == 0x0)
|
||||
+ illegal_instruction();
|
||||
+
|
||||
+ // Destination is not x0: R4-type insn performing a 3-operand RV add
|
||||
+ return (reg_t) ((reg_t) RS1 + (reg_t) RS2 + (reg_t) RS3);
|
||||
+ }
|
||||
+
|
||||
+ // Non-memory operations (including NOP and EXC)
|
||||
+ switch (r_insn.funct7 & 0b1111001)
|
||||
+ {
|
||||
+ case 0:
|
||||
+ {
|
||||
+ // Single-cycle RV addition with privilege: all non-privilege bits are zero.
|
||||
+ // funct7[2:1] == 0x0 (PRV_U): CUS_ADD (single-cycle RV ADD, any mode)
|
||||
+ // funct7[2:1] == 0x1 (PRV_S): CUS_S_ADD (single-cycle S-/M-mode RV ADD)
|
||||
+ // funct7[2:1] == 0x2 (PRV_HS): ILLEGAL
|
||||
+ // funct7[2:1] == 0x3 (PRV_M): CUS_M_ADD (single-cycle M-mode RV ADD)
|
||||
+ reg_t required_priv = (r_insn.funct7 & 0x6) >> 1;
|
||||
+ if (required_priv != PRV_HS && (p->get_state()->prv & required_priv) == required_priv)
|
||||
+ return (reg_t) ((reg_t) RS1 + (reg_t) RS2);
|
||||
+ else
|
||||
+ illegal_instruction();
|
||||
+ }
|
||||
+
|
||||
+ case 0x8:
|
||||
+ // Multi-cycle RV add.
|
||||
+ // TODO FIXME: Represent delay.
|
||||
+ return (reg_t) ((reg_t) RS1 + (reg_t) RS2);
|
||||
+
|
||||
+ case 0x40:
|
||||
+ // Exception. MCAUSE[4:0] encoded in RS1, MCAUSE[5] assumed to be 0.
|
||||
+ if (insn.rd() == 0x0 && insn.rs2() == 0x0)
|
||||
+ {
|
||||
+ // Raise an exception only if registers rd and rs2 are both x0 (no 'bit 5' extension yet).
|
||||
+ raise_exception(insn, insn.rs1());
|
||||
+ // Writeback will be disabled by 'do_writeback_p'.
|
||||
+ return (reg_t) -1;
|
||||
+ }
|
||||
+ else
|
||||
+ // Illegal instruction.
|
||||
+ illegal_instruction();
|
||||
+
|
||||
+ default:
|
||||
+ illegal_instruction();
|
||||
+ }
|
||||
+
|
||||
+ case 1:
|
||||
+ // Perform RV load. If runtime XLEN is not 64, assume 32.
|
||||
+ if (p->get_xlen() == 64)
|
||||
+ return MMU.load_int64(RS1 + insn.i_imm());
|
||||
+ else
|
||||
+ return MMU.load_int32(RS1 + insn.i_imm());
|
||||
+
|
||||
+ case 2:
|
||||
+ // Perform RV store. If runtime XLEN is not 64, assume 32.
|
||||
+ if (p->get_xlen() == 64)
|
||||
+ MMU.store_uint64(RS1 + insn.s_imm(), RS2);
|
||||
+ else
|
||||
+ MMU.store_uint32(RS1 + insn.s_imm(), RS2);
|
||||
+
|
||||
+ // Writeback will be disabled by 'do_writeback_p'.
|
||||
+ break;
|
||||
+
|
||||
+ default:
|
||||
+ illegal_instruction();
|
||||
+ }
|
||||
+
|
||||
+ // FORNOW: Return 0xf......f to simplify debugging.
|
||||
+ return (reg_t) -1;
|
||||
+ }
|
||||
+
|
||||
+ cvxif_t()
|
||||
+ {
|
||||
+ }
|
||||
+
|
||||
+ void raise_exception(insn_t insn, reg_t exc_index)
|
||||
+ {
|
||||
+ switch (exc_index) {
|
||||
+ case CAUSE_MISALIGNED_LOAD:
|
||||
+ // Use 0x1 as perfectly unaligned address;-)
|
||||
+ throw trap_load_address_misaligned((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ case CAUSE_LOAD_ACCESS:
|
||||
+ // Use 0x1 as invalid address.
|
||||
+ throw trap_load_access_fault((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ case CAUSE_MISALIGNED_STORE:
|
||||
+ // Use 0x1 as perfectly unaligned address;-)
|
||||
+ throw trap_store_address_misaligned((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ case CAUSE_STORE_ACCESS:
|
||||
+ // Use 0x1 as invalid address.
|
||||
+ throw trap_store_access_fault((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ case CAUSE_LOAD_PAGE_FAULT:
|
||||
+ // Use 0x1 as always-faulting address.
|
||||
+ throw trap_load_page_fault((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ case CAUSE_STORE_PAGE_FAULT:
|
||||
+ // Use 0x1 as always-faulting address.
|
||||
+ throw trap_store_page_fault((p ? p->get_state()->v : false), 1, 0, 0);
|
||||
+ default:
|
||||
+ illegal_instruction();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Define templates of new instructions.
|
||||
+ customX(0)
|
||||
+ customX(1)
|
||||
+ customX(2)
|
||||
+ customX(3)
|
||||
+
|
||||
+ // Set instruction handlers for customN opcode patterns.
|
||||
+ // NOTE: This method may need revisiting if multiple custom extensions are to be loaded
|
||||
+ // simultaneously in the future.
|
||||
+ std::vector<insn_desc_t> get_instructions()
|
||||
+ {
|
||||
+ std::vector<insn_desc_t> insns;
|
||||
+ insns.push_back((insn_desc_t){0x0b, 0x7f, &::illegal_instruction, c0});
|
||||
+ insns.push_back((insn_desc_t){0x2b, 0x7f, &::illegal_instruction, c1});
|
||||
+ insns.push_back((insn_desc_t){0x5b, 0x7f, &::illegal_instruction, c2});
|
||||
+ insns.push_back((insn_desc_t){0x7b, 0x7f, &c3, c3});
|
||||
+ return insns;
|
||||
+ }
|
||||
+
|
||||
+private:
|
||||
+ // State variables go here.
|
||||
+};
|
||||
+
|
||||
+REGISTER_EXTENSION(cvxif, []() { return new cvxif_t; })
|
||||
diff --git a/customext/cvxif_test.c b/customext/cvxif_test.c
|
||||
new file mode 100644
|
||||
index 000000000..d39ca2229
|
||||
--- /dev/null
|
||||
+++ b/customext/cvxif_test.c
|
||||
@@ -0,0 +1,111 @@
|
||||
+// Copyright (C) 2022 Thales DIS Design Services SAS
|
||||
+//
|
||||
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0.
|
||||
+//
|
||||
+// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
+//
|
||||
+// The following is a RISC-V program to test the functionality of the
|
||||
+// basic CVXIF accelerator interface on the Core-V side.
|
||||
+// Compile using "riscv-none-elf-gcc -O2 cvxif_test.elf cvxif_test.c"
|
||||
+// with -march=/-mabi= settings appropriate for your project.
|
||||
+// Run using "spike -l --extension=cvxif cvxif_test.elf", adding
|
||||
+// an --isa= setting appropriate for your project.
|
||||
+//
|
||||
+// Upon simulating the compiled program, the trace should contain five
|
||||
+// instances of custom3 instructions (the third one being decoded as
|
||||
+// 'unknown').
|
||||
+// The last occurrence of 'custom3' instruction in the trace, encoded as
|
||||
+// 0x8002007b, should be immediately followed by exception
|
||||
+// 'trap_load_address_misaligned' with a tval equal to 0x1 and the
|
||||
+// execution should terminate correctly with exit code 0.
|
||||
+//
|
||||
+// In 64-bit mode, the trace of the last occurrence of custom3
|
||||
+// instruction should be equivalent to
|
||||
+//
|
||||
+// core 0: 0x0000000080002686 (0x8002007b) custom3 (args unknown)
|
||||
+// core 0: exception trap_load_address_misaligned, epc 0x0000000080002686
|
||||
+// core 0: tval 0x0000000000000001
|
||||
+//
|
||||
+// The corresponding trace in 32-bit mode should be equivalent to
|
||||
+//
|
||||
+// core 0: 0x8000205a (0x8002007b) custom3 (args unknown)
|
||||
+// core 0: exception trap_load_address_misaligned, epc 0x8000205a
|
||||
+// core 0: tval 0x00000001
|
||||
+
|
||||
+#include <assert.h>
|
||||
+#include <stdio.h>
|
||||
+#include <stdint.h>
|
||||
+#include <stdlib.h>
|
||||
+
|
||||
+// Values of MCAUSE corresponding to exceptions coming from the coprocessor I/F
|
||||
+#define CAUSE_MISALIGNED_LOAD 0x4
|
||||
+#define CAUSE_LOAD_ACCESS 0x5
|
||||
+#define CAUSE_MISALIGNED_STORE 0x6
|
||||
+#define CAUSE_STORE_ACCESS 0x7
|
||||
+#define CAUSE_LOAD_PAGE_FAULT 0xd
|
||||
+#define CAUSE_STORE_PAGE_FAULT 0xf
|
||||
+#define CAUSE_COPROCESSOR_EXCEPTION 0x20
|
||||
+
|
||||
+// Value of TVAL to pass around.
|
||||
+#define COPRO_TVAL_TEST 0x1a
|
||||
+
|
||||
+// Macro to read a CSR (from spike's "encoding.h")
|
||||
+#define read_csr(reg) ({ unsigned long __tmp; \
|
||||
+ asm volatile ("csrr %0, " #reg : "=r"(__tmp)); \
|
||||
+ __tmp; })
|
||||
+
|
||||
+int main() {
|
||||
+ // "unsigned long int" is always XLEN bits wide.
|
||||
+ unsigned long int x = 123, y = 456, z = 0, t = 0;
|
||||
+ static unsigned long int amem = 111, bmem = 0;
|
||||
+ unsigned long a;
|
||||
+
|
||||
+ // Add x + y into z. Funct7 == 0, funct3 == 0x0.
|
||||
+ asm volatile (".insn r CUSTOM_3, 0, 0, %0, %1, %2" : "=r"(z) : "r"(x), "r"(y));
|
||||
+ if (z != 123 + 456)
|
||||
+ {
|
||||
+ // printf("FAILURE!!!\n");
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ // Add three operands in a single R4-type add.
|
||||
+ // Leverage current values of x, y and z (z == x + y).
|
||||
+ asm volatile (".insn r CUSTOM_3, 0, 0x1, %0, %1, %2, %3" : "=r"(t) : "r"(x), "r"(y), "r"(z));
|
||||
+ if (t != x + y + z)
|
||||
+ {
|
||||
+ // printf("FAILURE");
|
||||
+ return 2;
|
||||
+ }
|
||||
+ // Load 'a' from 'amem'. CUSTOM_LD: opcode == CUSTOM_3, insn_type == I, funct3 == 0x1.
|
||||
+ asm volatile (".insn i CUSTOM_3, 0x1, %0, %1" : "=r"(a) : "m"(amem), "I"(0));
|
||||
+ if (a != 111)
|
||||
+ {
|
||||
+ // printf("FAILURE!!!\n");
|
||||
+ return 3;
|
||||
+ }
|
||||
+
|
||||
+ // Store 'a' in 'bmem'. CUSTOM_SD: opcode == CUSTOM_3, insn_type == S, funct3 == 0x2.
|
||||
+ asm volatile (".insn s CUSTOM_3, 0x2, %0, %1" : : "r"(a), "m"(bmem));
|
||||
+ if (bmem != 111)
|
||||
+ {
|
||||
+ // printf("FAILURE!!!\n");
|
||||
+ return 4;
|
||||
+ }
|
||||
+
|
||||
+ // Generate a misaligned load exception (mcause == 0x4).
|
||||
+ asm volatile (".insn r CUSTOM_3, 0x0, 0x40, x0, x4, x0" : : );
|
||||
+
|
||||
+ // If we get here, then the exception test failed ==> exit with general failure code.
|
||||
+ exit(1337);
|
||||
+}
|
||||
+
|
||||
+// Override default trap handler.
|
||||
+uintptr_t handle_trap(uintptr_t cause, uintptr_t epc, uintptr_t regs[32])
|
||||
+{
|
||||
+ if (cause == CAUSE_MISALIGNED_LOAD)
|
||||
+ // Successfully terminate.
|
||||
+ exit(0);
|
||||
+ else
|
||||
+ // Fail with explicit retcode.
|
||||
+ exit(5);
|
||||
+}
|
||||
diff --git a/riscv/cvxif.h b/riscv/cvxif.h
|
||||
new file mode 100644
|
||||
index 000000000..e3a6fba1d
|
||||
--- /dev/null
|
||||
+++ b/riscv/cvxif.h
|
||||
@@ -0,0 +1,77 @@
|
||||
+// Copyright (C) 2022 Thales DIS Design Services SAS
|
||||
+//
|
||||
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0.
|
||||
+//
|
||||
+// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
+
|
||||
+#ifndef _RISCV_CVXIF_H
|
||||
+#define _RISCV_CVXIF_H
|
||||
+
|
||||
+#include "extension.h"
|
||||
+
|
||||
+// R-type instruction format
|
||||
+struct cvxif_r_insn_t
|
||||
+{
|
||||
+ unsigned opcode : 7;
|
||||
+ unsigned rd : 5;
|
||||
+ unsigned funct3 : 3;
|
||||
+ unsigned rs1 : 5;
|
||||
+ unsigned rs2 : 5;
|
||||
+ unsigned funct7 : 7;
|
||||
+};
|
||||
+
|
||||
+// R4-type instruction format
|
||||
+struct cvxif_r4_insn_t
|
||||
+{
|
||||
+ unsigned opcode : 7;
|
||||
+ unsigned rd : 5;
|
||||
+ unsigned funct3 : 3;
|
||||
+ unsigned rs1 : 5;
|
||||
+ unsigned rs2 : 5;
|
||||
+ unsigned funct2 : 2;
|
||||
+ unsigned rs3 : 5;
|
||||
+};
|
||||
+
|
||||
+// I-type instruction format
|
||||
+struct cvxif_i_insn_t
|
||||
+{
|
||||
+ unsigned opcode : 7;
|
||||
+ unsigned rd : 5;
|
||||
+ unsigned funct3 : 3;
|
||||
+ unsigned rs1 : 5;
|
||||
+ unsigned imm : 12;
|
||||
+};
|
||||
+
|
||||
+// S-type instruction format
|
||||
+struct cvxif_s_insn_t
|
||||
+{
|
||||
+ unsigned opcode : 7;
|
||||
+ unsigned imm_low : 5;
|
||||
+ unsigned funct3 : 3;
|
||||
+ unsigned rs1 : 5;
|
||||
+ unsigned rs2 : 5;
|
||||
+ unsigned imm_high : 7;
|
||||
+};
|
||||
+
|
||||
+union cvxif_insn_t
|
||||
+{
|
||||
+ cvxif_r_insn_t r_type;
|
||||
+ cvxif_r4_insn_t r4_type;
|
||||
+ cvxif_i_insn_t i_type;
|
||||
+ cvxif_s_insn_t s_type;
|
||||
+ insn_t i;
|
||||
+};
|
||||
+
|
||||
+class cvxif_extn_t : public extension_t
|
||||
+{
|
||||
+ public:
|
||||
+ virtual bool do_writeback_p(cvxif_insn_t insn);
|
||||
+ virtual reg_t custom0(cvxif_insn_t insn);
|
||||
+ virtual reg_t custom1(cvxif_insn_t insn);
|
||||
+ virtual reg_t custom2(cvxif_insn_t insn);
|
||||
+ virtual reg_t custom3(cvxif_insn_t insn);
|
||||
+ std::vector<insn_desc_t> get_instructions();
|
||||
+ std::vector<disasm_insn_t*> get_disasms();
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
diff --git a/riscv/cvxif_base.cc b/riscv/cvxif_base.cc
|
||||
new file mode 100644
|
||||
index 000000000..5097344c5
|
||||
--- /dev/null
|
||||
+++ b/riscv/cvxif_base.cc
|
||||
@@ -0,0 +1,64 @@
|
||||
+// Copyright (C) 2022 Thales DIS Design Services SAS
|
||||
+//
|
||||
+// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0.
|
||||
+//
|
||||
+// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
+
|
||||
+#include "cvxif.h"
|
||||
+#include "trap.h"
|
||||
+#include <cstdlib>
|
||||
+
|
||||
+// Virtual base class of CVXIF.
|
||||
+
|
||||
+// Return true if writeback is required.
|
||||
+// Be on the safe side, disable writeback.
|
||||
+bool cvxif_extn_t::do_writeback_p(cvxif_insn_t insn)
|
||||
+{
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+// Define custom insns templates.
|
||||
+// The insn-level wrapper is 'c##n' (default implementation,
|
||||
+// writeback disabled), the default implementation
|
||||
+// is 'custom##n': illegal instruction, return 0.
|
||||
+// The writeback controller 'cvxif_extn_t::do_writeback_p'
|
||||
+// is in charge of determining if writeback is required or not.
|
||||
+// Expected instruction encoding is 4 bytes.
|
||||
+#define customX(n) \
|
||||
+static reg_t c##n(processor_t* p, insn_t insn, reg_t pc) \
|
||||
+ { \
|
||||
+ cvxif_extn_t* cvxif = static_cast<cvxif_extn_t*>(p->get_extension()); \
|
||||
+ cvxif_insn_t custom_insn; \
|
||||
+ custom_insn.i = insn; \
|
||||
+ reg_t xd = cvxif->custom##n(custom_insn); \
|
||||
+ if (cvxif->do_writeback_p(custom_insn)) \
|
||||
+ WRITE_RD(xd); \
|
||||
+ return pc+4; \
|
||||
+ } \
|
||||
+ \
|
||||
+ reg_t cvxif_extn_t::custom##n(cvxif_insn_t insn) \
|
||||
+ { \
|
||||
+ illegal_instruction(); \
|
||||
+ return -1; \
|
||||
+ }
|
||||
+
|
||||
+customX(0)
|
||||
+customX(1)
|
||||
+customX(2)
|
||||
+customX(3)
|
||||
+
|
||||
+std::vector<insn_desc_t> cvxif_extn_t::get_instructions()
|
||||
+{
|
||||
+ std::vector<insn_desc_t> insns;
|
||||
+ insns.push_back((insn_desc_t){0x0b, 0x7f, &::illegal_instruction, c0});
|
||||
+ insns.push_back((insn_desc_t){0x2b, 0x7f, &::illegal_instruction, c1});
|
||||
+ insns.push_back((insn_desc_t){0x5b, 0x7f, &::illegal_instruction, c2});
|
||||
+ insns.push_back((insn_desc_t){0x7b, 0x7f, &::illegal_instruction, c3});
|
||||
+ return insns;
|
||||
+}
|
||||
+
|
||||
+std::vector<disasm_insn_t*> cvxif_extn_t::get_disasms()
|
||||
+{
|
||||
+ std::vector<disasm_insn_t*> insns;
|
||||
+ return insns;
|
||||
+}
|
||||
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
|
||||
index 56014662c..3da5f6d8b 100644
|
||||
--- a/riscv/riscv.mk.in
|
||||
+++ b/riscv/riscv.mk.in
|
||||
@@ -26,6 +26,7 @@ riscv_hdrs = \
|
||||
cfg.h \
|
||||
common.h \
|
||||
csrs.h \
|
||||
+ cvxif.h \
|
||||
debug_defines.h \
|
||||
debug_module.h \
|
||||
debug_rom_defines.h \
|
||||
@@ -58,6 +59,7 @@
|
||||
extension.cc \
|
||||
extensions.cc \
|
||||
rocc.cc \
|
||||
+ cvxif_base.cc \
|
||||
devices.cc \
|
||||
rom.cc \
|
||||
clint.cc \
|
2
vendor/riscv/riscv-isa-sim/.gitignore
vendored
2
vendor/riscv/riscv-isa-sim/.gitignore
vendored
|
@ -5,3 +5,5 @@ autom4te.cache/
|
|||
*.o
|
||||
*.d
|
||||
.gdb_history
|
||||
.#*
|
||||
*~
|
||||
|
|
13
vendor/riscv/riscv-isa-sim/Makefile.in
vendored
13
vendor/riscv/riscv-isa-sim/Makefile.in
vendored
|
@ -94,11 +94,11 @@ VPATH := $(addprefix $(src_dir)/, $(sprojs_enabled))
|
|||
# highest.
|
||||
|
||||
default-CFLAGS := -DPREFIX=\"$(prefix)\" -Wall -Wno-unused -Wno-nonportable-include-path -g -O2 -fPIC
|
||||
default-CXXFLAGS := $(default-CFLAGS) -std=c++11
|
||||
default-CXXFLAGS := $(default-CFLAGS) -std=c++17
|
||||
|
||||
mcppbs-CPPFLAGS := @CPPFLAGS@
|
||||
mcppbs-CFLAGS := $(default-CFLAGS) @CFLAGS@
|
||||
mcppbs-CXXFLAGS := $(default-CXXFLAGS) @CXXFLAGS@
|
||||
mcppbs-CXXFLAGS := $(mcppbs-CFLAGS) $(default-CXXFLAGS) @CXXFLAGS@
|
||||
|
||||
CC := @CC@
|
||||
CXX := @CXX@
|
||||
|
@ -219,7 +219,7 @@ $(2)_deps := $$(patsubst %.o, %.d, $$($(2)_objs))
|
|||
$(2)_deps += $$(patsubst %.o, %.d, $$($(2)_c_objs))
|
||||
$(2)_deps += $$(patsubst %.h, %.h.d, $$($(2)_precompiled_hdrs))
|
||||
$$($(2)_pch) : %.h.gch : %.h
|
||||
$(COMPILE) -x c++-header $$< -o $$@
|
||||
$(COMPILE) -x c++-header $$< -c -o $$@
|
||||
$$($(2)_objs) : %.o : %.cc $$($(2)_gen_hdrs) $$($(2)_pch)
|
||||
$(COMPILE) $(if $(HAVE_CLANG_PCH), $$(if $$($(2)_pch), -include-pch $$($(2)_pch))) $$($(2)_CFLAGS) -c $$<
|
||||
$$($(2)_c_objs) : %.o : %.c $$($(2)_gen_hdrs)
|
||||
|
@ -241,7 +241,8 @@ $(2)_lib_libnames := $$(patsubst %, lib%.a, $$($(2)_lib_libs))
|
|||
$(2)_lib_libarg := $$(patsubst %, -l%, $$($(2)_lib_libs))
|
||||
$(2)_lib_libnames_shared := $$(if $$($(2)_install_shared_lib),lib$(1).so,)
|
||||
|
||||
lib$(1).a : $$($(2)_objs) $$($(2)_c_objs) $$($(2)_lib_libnames)
|
||||
lib$(1).a : $$($(2)_objs) $$($(2)_c_objs)
|
||||
rm -f $$@
|
||||
$(AR) rcs $$@ $$^
|
||||
lib$(1).so : $$($(2)_objs) $$($(2)_c_objs) $$($(2)_lib_libnames_shared) $$($(2)_lib_libnames)
|
||||
$(LINK) -shared -o $$@ $(if $(filter Darwin,$(shell uname -s)),-install_name $(install_libs_dir)/$$@) $$^ $$($(2)_lib_libnames) $(LIBS)
|
||||
|
@ -326,10 +327,6 @@ clean-$(1) :
|
|||
|
||||
# Update running variables
|
||||
|
||||
libs += lib$(1).a
|
||||
objs += $$($(2)_objs)
|
||||
srcs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_srcs))
|
||||
hdrs += $$(addprefix $(src_dir)/$(1)/, $$($(2)_hdrs)) $$($(2)_gen_hdrs)
|
||||
junk += $$($(2)_junk)
|
||||
deps += $$($(2)_deps)
|
||||
|
||||
|
|
39
vendor/riscv/riscv-isa-sim/README.md
vendored
39
vendor/riscv/riscv-isa-sim/README.md
vendored
|
@ -27,13 +27,28 @@ Spike supports the following RISC-V ISA features:
|
|||
- Zbb extension, v1.0
|
||||
- Zbc extension, v1.0
|
||||
- Zbs extension, v1.0
|
||||
- Zfh and Zfhmin half-precision floating-point extensions, v1.0
|
||||
- Zfinx extension, v1.0
|
||||
- Zmmul integer multiplication extension, v1.0
|
||||
- Zicbom, Zicbop, Zicboz cache-block maintenance extensions, v1.0
|
||||
- Conformance to both RVWMO and RVTSO (Spike is sequentially consistent)
|
||||
- Machine, Supervisor, and User modes, v1.11
|
||||
- Hypervisor extension, v1.0
|
||||
- Svnapot extension, v1.0
|
||||
- Svpbmt extension, v1.0
|
||||
- Svinval extension, v1.0
|
||||
- Debug v0.14
|
||||
- Sdext extension, v1.0-STABLE
|
||||
- Sdtrig extension, v1.0-STABLE
|
||||
- 4 triggers support type={2, 3, 4, 5, 6, 15} (mcontrol, icount, itrigger, etrigger, mcontrol6, disabled)
|
||||
- Smepmp extension v1.0
|
||||
- Smstateen extension, v1.0
|
||||
- Sscofpmf v0.5.2
|
||||
- Zca extension, v1.0
|
||||
- Zcb extension, v1.0
|
||||
- Zcf extension, v1.0
|
||||
- Zcd extension, v1.0
|
||||
- Zcmp extension, v1.0
|
||||
- Zcmt extension, v1.0
|
||||
|
||||
As a Spike extension, the remainder of the proposed
|
||||
[Bit-Manipulation Extensions](https://github.com/riscv/riscv-bitmanip)
|
||||
|
@ -41,6 +56,14 @@ is provided under the Spike-custom extension name _Xbitmanip_.
|
|||
These instructions (and, of course, the extension name) are not RISC-V
|
||||
standards.
|
||||
|
||||
These proposed bit-manipulation extensions can be split into further
|
||||
groups: Zbp, Zbs, Zbe, Zbf, Zbc, Zbm, Zbr, Zbt. Note that Zbc is
|
||||
ratified, but the original proposal contained some extra instructions
|
||||
(64-bit carryless multiplies) which are captured here.
|
||||
|
||||
To enable these extensions individually, use the Spike-custom
|
||||
extension names _XZbp_, _XZbs_, _XZbc_, and so on.
|
||||
|
||||
Versioning and APIs
|
||||
-------------------
|
||||
|
||||
|
@ -211,7 +234,7 @@ OUTPUT_ARCH( "riscv" )
|
|||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x10010000;
|
||||
. = 0x10110000;
|
||||
.text : { *(.text) }
|
||||
.data : { *(.data) }
|
||||
}
|
||||
|
@ -221,19 +244,19 @@ $ riscv64-unknown-elf-gcc -g -Og -T spike.lds -nostartfiles -o rot13-64 rot13-64
|
|||
|
||||
To debug this program, first run spike telling it to listen for OpenOCD:
|
||||
```
|
||||
$ spike --rbb-port=9824 -m0x10000000:0x20000 rot13-64
|
||||
$ spike --rbb-port=9824 -m0x10100000:0x20000 rot13-64
|
||||
Listening for remote bitbang connection on port 9824.
|
||||
```
|
||||
|
||||
In a separate shell run OpenOCD with the appropriate configuration file:
|
||||
```
|
||||
$ cat spike.cfg
|
||||
interface remote_bitbang
|
||||
remote_bitbang_host localhost
|
||||
remote_bitbang_port 9824
|
||||
adapter driver remote_bitbang
|
||||
remote_bitbang host localhost
|
||||
remote_bitbang port 9824
|
||||
|
||||
set _CHIPNAME riscv
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x10e31913
|
||||
jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0xdeadbeef
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME riscv -chain-position $_TARGETNAME
|
||||
|
@ -277,7 +300,7 @@ $2 = 0
|
|||
(gdb) print text
|
||||
$3 = "Vafgehpgvba frgf jnag gb or serr!"
|
||||
(gdb) b done
|
||||
Breakpoint 1 at 0x10010064: file rot13.c, line 22.
|
||||
Breakpoint 1 at 0x10110064: file rot13.c, line 22.
|
||||
(gdb) c
|
||||
Continuing.
|
||||
Disabling abstract command writes to CSRs.
|
||||
|
|
34
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/Makefile_common.inc
vendored
Normal file
34
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/Makefile_common.inc
vendored
Normal file
|
@ -0,0 +1,34 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv$(XLEN)-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/C/Makefile.include
vendored
Normal file
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/C/Makefile.include
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32ec \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
||||
RUN_TARGET=\
|
||||
$(RUN_CMD)
|
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/E/Makefile.include
vendored
Normal file
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/E/Makefile.include
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32e \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
||||
RUN_TARGET=\
|
||||
$(RUN_CMD)
|
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/M/Makefile.include
vendored
Normal file
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32e_unratified/M/Makefile.include
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32em \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
||||
RUN_TARGET=\
|
||||
$(RUN_CMD)
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32ic \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32i_m/F/Makefile.include
vendored
Normal file
7
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv32i_m/F/Makefile.include
vendored
Normal file
|
@ -0,0 +1,7 @@
|
|||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32if \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
||||
RUN_TARGET=\
|
||||
$(RUN_CMD)
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32i \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32im \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32i \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv32-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv32ic \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64ic \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
8
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv64i_m/D/Makefile.include
vendored
Normal file
8
vendor/riscv/riscv-isa-sim/arch_test_target/spike/device/rv64i_m/D/Makefile.include
vendored
Normal file
|
@ -0,0 +1,8 @@
|
|||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64ifd \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
||||
RUN_TARGET=\
|
||||
$(RUN_CMD)
|
||||
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64i \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64im \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,38 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64i \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -1,37 +1,4 @@
|
|||
TARGET_SIM ?= spike
|
||||
TARGET_FLAGS ?= $(RISCV_TARGET_FLAGS)
|
||||
ifeq ($(shell command -v $(TARGET_SIM) 2> /dev/null),)
|
||||
$(error Target simulator executable '$(TARGET_SIM)` not found)
|
||||
endif
|
||||
|
||||
RISCV_PREFIX ?= riscv64-unknown-elf-
|
||||
RISCV_GCC ?= $(RISCV_PREFIX)gcc
|
||||
RISCV_OBJDUMP ?= $(RISCV_PREFIX)objdump
|
||||
RISCV_GCC_OPTS ?= -g -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles $(RVTEST_DEFINES)
|
||||
|
||||
COMPILE_CMD = $$(RISCV_GCC) $(1) $$(RISCV_GCC_OPTS) \
|
||||
-I$(ROOTDIR)/riscv-test-suite/env/ \
|
||||
-I$(TARGETDIR)/$(RISCV_TARGET)/ \
|
||||
-T$(TARGETDIR)/$(RISCV_TARGET)/link.ld \
|
||||
$$(<) -o $$@
|
||||
OBJ_CMD = $$(RISCV_OBJDUMP) $$@ -D > $$@.objdump; \
|
||||
$$(RISCV_OBJDUMP) $$@ --source > $$@.debug
|
||||
|
||||
|
||||
COMPILE_TARGET=\
|
||||
$(COMPILE_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m$$(RISCV_GCC) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ; \
|
||||
$(OBJ_CMD); \
|
||||
if [ $$$$? -ne 0 ] ; \
|
||||
then \
|
||||
echo "\e[31m $$(RISCV_OBJDUMP) failed for target $$(@) \e[39m" ; \
|
||||
exit 1 ; \
|
||||
fi ;
|
||||
|
||||
include $(TARGETDIR)/spike/device/Makefile_common.inc
|
||||
RUN_CMD = $(TARGET_SIM) $(TARGET_FLAGS) --isa=rv64ic \
|
||||
+signature=$(*).signature.output +signature-granularity=4\
|
||||
$<
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
addi x1, x1, 4; \
|
||||
li x1, 1; \
|
||||
write_tohost: \
|
||||
sw x1, tohost, t5; \
|
||||
sw x1, tohost, t1; \
|
||||
self_loop: j self_loop;
|
||||
|
||||
#define RVMODEL_BOOT
|
||||
|
|
17
vendor/riscv/riscv-isa-sim/config.h.in
vendored
17
vendor/riscv/riscv-isa-sim/config.h.in
vendored
|
@ -33,6 +33,9 @@
|
|||
/* define if the Boost::ASIO library is available */
|
||||
#undef HAVE_BOOST_ASIO
|
||||
|
||||
/* define if the Boost::Regex library is available */
|
||||
#undef HAVE_BOOST_REGEX
|
||||
|
||||
/* Dynamic library loading is supported */
|
||||
#undef HAVE_DLOPEN
|
||||
|
||||
|
@ -99,21 +102,9 @@
|
|||
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
|
||||
#undef RISCV_ENABLED
|
||||
|
||||
/* Enable commit log generation */
|
||||
#undef RISCV_ENABLE_COMMITLOG
|
||||
|
||||
/* Enable hardware management of PTE accessed and dirty bits */
|
||||
#undef RISCV_ENABLE_DIRTY
|
||||
|
||||
/* Enable support for running target in either endianness */
|
||||
#undef RISCV_ENABLE_DUAL_ENDIAN
|
||||
|
||||
/* Enable PC histogram generation */
|
||||
#undef RISCV_ENABLE_HISTOGRAM
|
||||
|
||||
/* Enable hardware support for misaligned loads and stores */
|
||||
#undef RISCV_ENABLE_MISALIGNED
|
||||
|
||||
/* Define if subproject MCPPBS_SPROJ_NORM is enabled */
|
||||
#undef SOFTFLOAT_ENABLED
|
||||
|
||||
|
@ -126,7 +117,7 @@
|
|||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Default value for --with-target switch */
|
||||
/* Default value for --target switch */
|
||||
#undef TARGET_ARCH
|
||||
|
||||
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
|
||||
|
|
67
vendor/riscv/riscv-isa-sim/configure
vendored
67
vendor/riscv/riscv-isa-sim/configure
vendored
|
@ -715,10 +715,6 @@ with_isa
|
|||
with_priv
|
||||
with_varch
|
||||
with_target
|
||||
enable_commitlog
|
||||
enable_histogram
|
||||
enable_dirty
|
||||
enable_misaligned
|
||||
enable_dual_endian
|
||||
'
|
||||
ac_precious_vars='build_alias
|
||||
|
@ -1362,12 +1358,6 @@ Optional Features:
|
|||
--enable-stow Enable stow-based install
|
||||
--enable-optional-subprojects
|
||||
Enable all optional subprojects
|
||||
--enable-commitlog Enable commit log generation
|
||||
--enable-histogram Enable PC histogram generation
|
||||
--enable-dirty Enable hardware management of PTE accessed and dirty
|
||||
bits
|
||||
--enable-misaligned Enable hardware support for misaligned loads and
|
||||
stores
|
||||
--enable-dual-endian Enable support for running target in either
|
||||
endianness
|
||||
|
||||
|
@ -1391,7 +1381,8 @@ Optional Packages:
|
|||
use the Regex library from boost - it is possible to
|
||||
specify a certain library for the linker e.g.
|
||||
--with-boost-regex=boost_regex-gcc-mt-d-1_33_1
|
||||
--with-isa=RV64IMAFDC Sets the default RISC-V ISA
|
||||
--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
|
||||
|
@ -5886,7 +5877,7 @@ _ACEOF
|
|||
else
|
||||
|
||||
cat >>confdefs.h <<_ACEOF
|
||||
#define DEFAULT_ISA "RV64IMAFDC"
|
||||
#define DEFAULT_ISA "RV64IMAFDC_zicntr_zihpm"
|
||||
_ACEOF
|
||||
|
||||
fi
|
||||
|
@ -6054,58 +6045,6 @@ else
|
|||
fi
|
||||
|
||||
|
||||
# Check whether --enable-commitlog was given.
|
||||
if test "${enable_commitlog+set}" = set; then :
|
||||
enableval=$enable_commitlog;
|
||||
fi
|
||||
|
||||
if test "x$enable_commitlog" = "xyes"; then :
|
||||
|
||||
|
||||
$as_echo "#define RISCV_ENABLE_COMMITLOG /**/" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-histogram was given.
|
||||
if test "${enable_histogram+set}" = set; then :
|
||||
enableval=$enable_histogram;
|
||||
fi
|
||||
|
||||
if test "x$enable_histogram" = "xyes"; then :
|
||||
|
||||
|
||||
$as_echo "#define RISCV_ENABLE_HISTOGRAM /**/" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-dirty was given.
|
||||
if test "${enable_dirty+set}" = set; then :
|
||||
enableval=$enable_dirty;
|
||||
fi
|
||||
|
||||
if test "x$enable_dirty" = "xyes"; then :
|
||||
|
||||
|
||||
$as_echo "#define RISCV_ENABLE_DIRTY /**/" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-misaligned was given.
|
||||
if test "${enable_misaligned+set}" = set; then :
|
||||
enableval=$enable_misaligned;
|
||||
fi
|
||||
|
||||
if test "x$enable_misaligned" = "xyes"; then :
|
||||
|
||||
|
||||
$as_echo "#define RISCV_ENABLE_MISALIGNED /**/" >>confdefs.h
|
||||
|
||||
|
||||
fi
|
||||
|
||||
# Check whether --enable-dual-endian was given.
|
||||
if test "${enable_dual_endian+set}" = set; then :
|
||||
enableval=$enable_dual_endian;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include "insn_macros.h"
|
||||
#include "extension.h"
|
||||
#include "decode_macros.h"
|
||||
#include <cstring>
|
||||
|
||||
struct : public arg_t {
|
||||
|
@ -24,9 +25,9 @@ class cflush_t : public extension_t
|
|||
|
||||
std::vector<insn_desc_t> get_instructions() {
|
||||
std::vector<insn_desc_t> insns;
|
||||
insns.push_back((insn_desc_t){0xFC000073, 0xFFF07FFF, custom_cflush, custom_cflush});
|
||||
insns.push_back((insn_desc_t){0xFC200073, 0xFFF07FFF, custom_cflush, custom_cflush});
|
||||
insns.push_back((insn_desc_t){0xFC100073, 0xFFF07FFF, custom_cflush, custom_cflush});
|
||||
insns.push_back((insn_desc_t){0xFC000073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
|
||||
insns.push_back((insn_desc_t){0xFC200073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
|
||||
insns.push_back((insn_desc_t){0xFC100073, 0xFFF07FFF, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush, custom_cflush});
|
||||
return insns;
|
||||
}
|
||||
|
||||
|
|
12
vendor/riscv/riscv-isa-sim/customext/cvxif.cc
vendored
12
vendor/riscv/riscv-isa-sim/customext/cvxif.cc
vendored
|
@ -4,6 +4,8 @@
|
|||
//
|
||||
// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
|
||||
#define DECODE_MACRO_USAGE_LOGGED 1
|
||||
#include "decode_macros.h"
|
||||
#include "cvxif.h"
|
||||
#include "mmu.h"
|
||||
#include <cstring>
|
||||
|
@ -43,7 +45,7 @@ class cvxif_t : public cvxif_extn_t
|
|||
// INSN_R personality serves to simplify access to standard encoding fields.
|
||||
cvxif_r_insn_t insn_r = copro_insn.r_type;
|
||||
|
||||
if (insn_r.opcode != MATCH_CUSTOM3)
|
||||
if (insn_r.opcode != 0x7b /* MATCH_CUSTOM3 */)
|
||||
return false;
|
||||
else switch (insn_r.funct3)
|
||||
{
|
||||
|
@ -148,16 +150,16 @@ class cvxif_t : public cvxif_extn_t
|
|||
case 1:
|
||||
// Perform RV load. If runtime XLEN is not 64, assume 32.
|
||||
if (p->get_xlen() == 64)
|
||||
return MMU.load_int64(RS1 + insn.i_imm());
|
||||
return MMU.load<int64_t>(RS1 + insn.i_imm());
|
||||
else
|
||||
return MMU.load_int32(RS1 + insn.i_imm());
|
||||
return MMU.load<int32_t>(RS1 + insn.i_imm());
|
||||
|
||||
case 2:
|
||||
// Perform RV store. If runtime XLEN is not 64, assume 32.
|
||||
if (p->get_xlen() == 64)
|
||||
MMU.store_uint64(RS1 + insn.s_imm(), RS2);
|
||||
MMU.store<uint64_t>(RS1 + insn.s_imm(), RS2);
|
||||
else
|
||||
MMU.store_uint32(RS1 + insn.s_imm(), RS2);
|
||||
MMU.store<uint32_t>(RS1 + insn.s_imm(), RS2);
|
||||
|
||||
// Writeback will be disabled by 'do_writeback_p'.
|
||||
break;
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
// core 0: tval 0x0000000000000001
|
||||
//
|
||||
// The corresponding trace in 32-bit mode should be equivalent to
|
||||
//
|
||||
//
|
||||
// core 0: 0x8000205a (0x8002007b) custom3 (args unknown)
|
||||
// core 0: exception trap_load_address_misaligned, epc 0x8000205a
|
||||
// core 0: tval 0x00000001
|
||||
|
|
|
@ -7,7 +7,7 @@ class dummy_rocc_t : public rocc_t
|
|||
public:
|
||||
const char* name() { return "dummy_rocc"; }
|
||||
|
||||
reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t xs2)
|
||||
reg_t custom0(rocc_insn_t insn, reg_t xs1, reg_t UNUSED xs2)
|
||||
{
|
||||
reg_t prev_acc = acc[insn.rs2];
|
||||
|
||||
|
@ -22,7 +22,7 @@ class dummy_rocc_t : public rocc_t
|
|||
case 1: // xd <- acc (the only real work is the return statement below)
|
||||
break;
|
||||
case 2: // acc[rs2] <- Mem[xs1]
|
||||
acc[insn.rs2] = p->get_mmu()->load_uint64(xs1);
|
||||
acc[insn.rs2] = p->get_mmu()->load<uint64_t>(xs1);
|
||||
break;
|
||||
case 3: // acc[rs2] <- accX + xs1
|
||||
acc[insn.rs2] += xs1;
|
||||
|
|
|
@ -18,7 +18,7 @@ all: $(patsubst %,%.h,$(ELFS))
|
|||
$(OBJCOPY) -O binary --only-section .text $^ $@
|
||||
|
||||
debug_rom: $(DEPS)
|
||||
$(COMPILE) -o $@ $^
|
||||
$(COMPILE) -o $@ $<
|
||||
|
||||
clean:
|
||||
rm -f $(ELFS) debug_rom*.raw debug_rom.h
|
||||
|
|
|
@ -23,7 +23,7 @@ _entry:
|
|||
// This fence is required because the execution may have written something
|
||||
// into the Abstract Data or Program Buffer registers.
|
||||
fence
|
||||
csrw CSR_DSCRATCH, s0 // Save s0 to allow signaling MHARTID
|
||||
csrw CSR_DSCRATCH0, s0 // Save s0 to allow signaling MHARTID
|
||||
|
||||
// We continue to let the hart know that we are halted in order that
|
||||
// a DM which was reset is still made aware that a hart is halted.
|
||||
|
@ -46,14 +46,14 @@ _exception:
|
|||
// Restore S0, which we always save to dscratch.
|
||||
// We need this in case the user tried an abstract write to a
|
||||
// non-existent CSR.
|
||||
csrr s0, CSR_DSCRATCH
|
||||
csrr s0, CSR_DSCRATCH0
|
||||
sw zero, DEBUG_ROM_EXCEPTION(zero) // Let debug module know you got an exception.
|
||||
ebreak
|
||||
|
||||
going:
|
||||
csrr s0, CSR_MHARTID
|
||||
sw s0, DEBUG_ROM_GOING(zero) // When debug module sees this write, the GO flag is reset.
|
||||
csrr s0, CSR_DSCRATCH // Restore s0 here
|
||||
csrr s0, CSR_DSCRATCH0 // Restore s0 here
|
||||
fence
|
||||
fence.i
|
||||
jalr zero, zero, %lo(whereto) // Debug module will put different instructions and data in the RAM,
|
||||
|
@ -63,7 +63,7 @@ going:
|
|||
_resume:
|
||||
csrr s0, CSR_MHARTID
|
||||
sw s0, DEBUG_ROM_RESUMING(zero) // When Debug Module sees this write, the RESUME flag is reset.
|
||||
csrr s0, CSR_DSCRATCH // Restore s0
|
||||
csrr s0, CSR_DSCRATCH0 // Restore s0
|
||||
dret
|
||||
|
||||
// END OF ACTUAL "ROM" CONTENTS. BELOW IS JUST FOR LINKER SCRIPT.
|
||||
|
|
2355
vendor/riscv/riscv-isa-sim/disasm/disasm.cc
vendored
2355
vendor/riscv/riscv-isa-sim/disasm/disasm.cc
vendored
File diff suppressed because it is too large
Load diff
5
vendor/riscv/riscv-isa-sim/fdt/fdt.mk.in
vendored
5
vendor/riscv/riscv-isa-sim/fdt/fdt.mk.in
vendored
|
@ -1,10 +1,5 @@
|
|||
fdt_subproject_deps = \
|
||||
|
||||
fdt_hdrs = \
|
||||
fdt.h \
|
||||
libfdt.h \
|
||||
libfdt_env.h \
|
||||
|
||||
fdt_c_srcs = \
|
||||
fdt.c \
|
||||
fdt_ro.c \
|
||||
|
|
2
vendor/riscv/riscv-isa-sim/fesvr/context.cc
vendored
2
vendor/riscv/riscv-isa-sim/fesvr/context.cc
vendored
|
@ -49,7 +49,7 @@ void context_t::init(void (*f)(void*), void* a)
|
|||
#ifdef USE_UCONTEXT
|
||||
getcontext(context.get());
|
||||
context->uc_link = creator->context.get();
|
||||
context->uc_stack.ss_size = 64*1024;
|
||||
context->uc_stack.ss_size = 1024 * 1024;
|
||||
context->uc_stack.ss_sp = new void*[context->uc_stack.ss_size/sizeof(void*)];
|
||||
#ifndef GLIBC_64BIT_PTR_BUG
|
||||
makecontext(context.get(), (void(*)(void))&context_t::wrapper, 1, this);
|
||||
|
|
1418
vendor/riscv/riscv-isa-sim/fesvr/debug_defines.h
vendored
1418
vendor/riscv/riscv-isa-sim/fesvr/debug_defines.h
vendored
File diff suppressed because it is too large
Load diff
3
vendor/riscv/riscv-isa-sim/fesvr/device.cc
vendored
3
vendor/riscv/riscv-isa-sim/fesvr/device.cc
vendored
|
@ -33,7 +33,7 @@ void device_t::handle_command(command_t cmd)
|
|||
command_handlers[cmd.cmd()](cmd);
|
||||
}
|
||||
|
||||
void device_t::handle_null_command(command_t cmd)
|
||||
void device_t::handle_null_command(command_t)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,6 @@ void device_t::handle_identify(command_t cmd)
|
|||
{
|
||||
size_t what = cmd.payload() % command_t::MAX_COMMANDS;
|
||||
uint64_t addr = cmd.payload() / command_t::MAX_COMMANDS;
|
||||
assert(addr % IDENTITY_SIZE == 0);
|
||||
|
||||
char id[IDENTITY_SIZE] = {0};
|
||||
if (what == command_t::MAX_COMMANDS-1)
|
||||
|
|
1
vendor/riscv/riscv-isa-sim/fesvr/device.h
vendored
1
vendor/riscv/riscv-isa-sim/fesvr/device.h
vendored
|
@ -6,6 +6,7 @@
|
|||
#include <cstring>
|
||||
#include <string>
|
||||
#include <functional>
|
||||
#include <cstdint>
|
||||
|
||||
class memif_t;
|
||||
|
||||
|
|
124
vendor/riscv/riscv-isa-sim/fesvr/dtm.cc
vendored
124
vendor/riscv/riscv-isa-sim/fesvr/dtm.cc
vendored
|
@ -1,6 +1,5 @@
|
|||
#include "dtm.h"
|
||||
#include "debug_defines.h"
|
||||
#include "encoding.h"
|
||||
#include "riscv/debug_defines.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
@ -38,16 +37,13 @@
|
|||
#define S1 9
|
||||
|
||||
#define AC_AR_REGNO(x) ((0x1000 | x) << AC_ACCESS_REGISTER_REGNO_OFFSET)
|
||||
#define AC_AR_SIZE(x) (((x == 128)? 4 : (x == 64 ? 3 : 2)) << AC_ACCESS_REGISTER_SIZE_OFFSET)
|
||||
#define AC_AR_SIZE(x) (((x == 128)? 4 : (x == 64 ? 3 : 2)) << AC_ACCESS_REGISTER_AARSIZE_OFFSET)
|
||||
|
||||
#define WRITE 1
|
||||
#define SET 2
|
||||
#define CLEAR 3
|
||||
#define CSRRx(type, dst, csr, src) (0x73 | ((type) << 12) | ((dst) << 7) | ((src) << 15) | (uint32_t)((csr) << 20))
|
||||
|
||||
#define get_field(reg, mask) (((reg) & (mask)) / ((mask) & ~((mask) << 1)))
|
||||
#define set_field(reg, mask, val) (((reg) & ~(mask)) | (((val) * ((mask) & ~((mask) << 1))) & (mask)))
|
||||
|
||||
#define RUN_AC_OR_DIE(a, b, c, d, e) { \
|
||||
uint32_t cmderr = run_abstract_command(a, b, c, d, e); \
|
||||
if (cmderr) { \
|
||||
|
@ -79,22 +75,22 @@ void dtm_t::nop()
|
|||
}
|
||||
|
||||
void dtm_t::select_hart(int hartsel) {
|
||||
int dmcontrol = read(DMI_DMCONTROL);
|
||||
write (DMI_DMCONTROL, set_field(dmcontrol, DMI_DMCONTROL_HARTSEL, hartsel));
|
||||
int dmcontrol = read(DM_DMCONTROL);
|
||||
write (DM_DMCONTROL, set_field(dmcontrol, DM_DMCONTROL_HASEL, hartsel));
|
||||
current_hart = hartsel;
|
||||
}
|
||||
|
||||
int dtm_t::enumerate_harts() {
|
||||
int max_hart = (1 << DMI_DMCONTROL_HARTSEL_LENGTH) - 1;
|
||||
write(DMI_DMCONTROL, set_field(read(DMI_DMCONTROL), DMI_DMCONTROL_HARTSEL, max_hart));
|
||||
read(DMI_DMSTATUS);
|
||||
max_hart = get_field(read(DMI_DMCONTROL), DMI_DMCONTROL_HARTSEL);
|
||||
int max_hart = (1 << DM_DMCONTROL_HASEL_LENGTH) - 1;
|
||||
write(DM_DMCONTROL, set_field(read(DM_DMCONTROL), DM_DMCONTROL_HASEL, max_hart));
|
||||
read(DM_DMSTATUS);
|
||||
max_hart = get_field(read(DM_DMCONTROL), DM_DMCONTROL_HASEL);
|
||||
|
||||
int hartsel;
|
||||
for (hartsel = 0; hartsel <= max_hart; hartsel++) {
|
||||
select_hart(hartsel);
|
||||
int dmstatus = read(DMI_DMSTATUS);
|
||||
if (get_field(dmstatus, DMI_DMSTATUS_ANYNONEXISTENT))
|
||||
int dmstatus = read(DM_DMSTATUS);
|
||||
if (get_field(dmstatus, DM_DMSTATUS_ANYNONEXISTENT))
|
||||
break;
|
||||
}
|
||||
return hartsel;
|
||||
|
@ -103,44 +99,44 @@ int dtm_t::enumerate_harts() {
|
|||
void dtm_t::halt(int hartsel)
|
||||
{
|
||||
if (running) {
|
||||
write(DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||
write(DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
|
||||
// Read dmstatus to avoid back-to-back writes to dmcontrol.
|
||||
read(DMI_DMSTATUS);
|
||||
read(DM_DMSTATUS);
|
||||
}
|
||||
|
||||
int dmcontrol = DMI_DMCONTROL_HALTREQ | DMI_DMCONTROL_DMACTIVE;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSEL, hartsel);
|
||||
write(DMI_DMCONTROL, dmcontrol);
|
||||
int dmcontrol = DM_DMCONTROL_HALTREQ | DM_DMCONTROL_DMACTIVE;
|
||||
dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, hartsel);
|
||||
write(DM_DMCONTROL, dmcontrol);
|
||||
int dmstatus;
|
||||
do {
|
||||
dmstatus = read(DMI_DMSTATUS);
|
||||
} while(get_field(dmstatus, DMI_DMSTATUS_ALLHALTED) == 0);
|
||||
dmcontrol &= ~DMI_DMCONTROL_HALTREQ;
|
||||
write(DMI_DMCONTROL, dmcontrol);
|
||||
dmstatus = read(DM_DMSTATUS);
|
||||
} while(get_field(dmstatus, DM_DMSTATUS_ALLHALTED) == 0);
|
||||
dmcontrol &= ~DM_DMCONTROL_HALTREQ;
|
||||
write(DM_DMCONTROL, dmcontrol);
|
||||
// Read dmstatus to avoid back-to-back writes to dmcontrol.
|
||||
read(DMI_DMSTATUS);
|
||||
read(DM_DMSTATUS);
|
||||
current_hart = hartsel;
|
||||
}
|
||||
|
||||
void dtm_t::resume(int hartsel)
|
||||
{
|
||||
int dmcontrol = DMI_DMCONTROL_RESUMEREQ | DMI_DMCONTROL_DMACTIVE;
|
||||
dmcontrol = set_field(dmcontrol, DMI_DMCONTROL_HARTSEL, hartsel);
|
||||
write(DMI_DMCONTROL, dmcontrol);
|
||||
int dmcontrol = DM_DMCONTROL_RESUMEREQ | DM_DMCONTROL_DMACTIVE;
|
||||
dmcontrol = set_field(dmcontrol, DM_DMCONTROL_HASEL, hartsel);
|
||||
write(DM_DMCONTROL, dmcontrol);
|
||||
int dmstatus;
|
||||
do {
|
||||
dmstatus = read(DMI_DMSTATUS);
|
||||
} while (get_field(dmstatus, DMI_DMSTATUS_ALLRESUMEACK) == 0);
|
||||
dmcontrol &= ~DMI_DMCONTROL_RESUMEREQ;
|
||||
write(DMI_DMCONTROL, dmcontrol);
|
||||
dmstatus = read(DM_DMSTATUS);
|
||||
} while (get_field(dmstatus, DM_DMSTATUS_ALLRESUMEACK) == 0);
|
||||
dmcontrol &= ~DM_DMCONTROL_RESUMEREQ;
|
||||
write(DM_DMCONTROL, dmcontrol);
|
||||
// Read dmstatus to avoid back-to-back writes to dmcontrol.
|
||||
read(DMI_DMSTATUS);
|
||||
read(DM_DMSTATUS);
|
||||
current_hart = hartsel;
|
||||
|
||||
if (running) {
|
||||
write(DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||
write(DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
|
||||
// Read dmstatus to avoid back-to-back writes to dmcontrol.
|
||||
read(DMI_DMSTATUS);
|
||||
read(DM_DMSTATUS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -182,32 +178,32 @@ uint32_t dtm_t::run_abstract_command(uint32_t command,
|
|||
assert(data_n <= data_words);
|
||||
|
||||
for (size_t i = 0; i < program_n; i++) {
|
||||
write(DMI_PROGBUF0 + i, program[i]);
|
||||
write(DM_PROGBUF0 + i, program[i]);
|
||||
}
|
||||
|
||||
if (get_field(command, AC_ACCESS_REGISTER_WRITE) &&
|
||||
get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
|
||||
for (size_t i = 0; i < data_n; i++) {
|
||||
write(DMI_DATA0 + i, data[i]);
|
||||
write(DM_DATA0 + i, data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
write(DMI_COMMAND, command);
|
||||
write(DM_COMMAND, command);
|
||||
|
||||
// Wait for not busy and then check for error.
|
||||
uint32_t abstractcs;
|
||||
do {
|
||||
abstractcs = read(DMI_ABSTRACTCS);
|
||||
} while (abstractcs & DMI_ABSTRACTCS_BUSY);
|
||||
abstractcs = read(DM_ABSTRACTCS);
|
||||
} while (abstractcs & DM_ABSTRACTCS_BUSY);
|
||||
|
||||
if ((get_field(command, AC_ACCESS_REGISTER_WRITE) == 0) &&
|
||||
get_field(command, AC_ACCESS_REGISTER_TRANSFER)) {
|
||||
for (size_t i = 0; i < data_n; i++){
|
||||
data[i] = read(DMI_DATA0 + i);
|
||||
data[i] = read(DM_DATA0 + i);
|
||||
}
|
||||
}
|
||||
|
||||
return get_field(abstractcs, DMI_ABSTRACTCS_CMDERR);
|
||||
return get_field(abstractcs, DM_ABSTRACTCS_CMDERR);
|
||||
|
||||
}
|
||||
|
||||
|
@ -317,24 +313,24 @@ void dtm_t::write_chunk(uint64_t taddr, size_t len, const void* src)
|
|||
uint32_t abstractcs;
|
||||
for (size_t i = 1; i < (len * 8 / xlen); i++){
|
||||
if (i == 1) {
|
||||
write(DMI_ABSTRACTAUTO, 1 << DMI_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
|
||||
write(DM_ABSTRACTAUTO, 1 << DM_ABSTRACTAUTO_AUTOEXECDATA_OFFSET);
|
||||
}
|
||||
memcpy(data, curr, xlen/8);
|
||||
curr += xlen/8;
|
||||
if (xlen == 64) {
|
||||
write(DMI_DATA0 + 1, data[1]);
|
||||
write(DM_DATA0 + 1, data[1]);
|
||||
}
|
||||
write(DMI_DATA0, data[0]); //Triggers a command w/ autoexec.
|
||||
write(DM_DATA0, data[0]); //Triggers a command w/ autoexec.
|
||||
|
||||
do {
|
||||
abstractcs = read(DMI_ABSTRACTCS);
|
||||
} while (abstractcs & DMI_ABSTRACTCS_BUSY);
|
||||
if ( get_field(abstractcs, DMI_ABSTRACTCS_CMDERR)) {
|
||||
die(get_field(abstractcs, DMI_ABSTRACTCS_CMDERR));
|
||||
abstractcs = read(DM_ABSTRACTCS);
|
||||
} while (abstractcs & DM_ABSTRACTCS_BUSY);
|
||||
if ( get_field(abstractcs, DM_ABSTRACTCS_CMDERR)) {
|
||||
die(get_field(abstractcs, DM_ABSTRACTCS_CMDERR));
|
||||
}
|
||||
}
|
||||
if ((len * 8 / xlen) > 1) {
|
||||
write(DMI_ABSTRACTAUTO, 0);
|
||||
write(DM_ABSTRACTAUTO, 0);
|
||||
}
|
||||
|
||||
restore_reg(S0, s0);
|
||||
|
@ -360,7 +356,7 @@ void dtm_t::die(uint32_t cmderr)
|
|||
//throw std::runtime_error("Debug Abstract Command Error #" + std::to_string(cmderr) + "(" + msg + ")");
|
||||
printf("ERROR: %s:%d, Debug Abstract Command Error #%d (%s)", __FILE__, __LINE__, cmderr, msg);
|
||||
printf("ERROR: %s:%d, Should die, but allowing simulation to continue and fail.", __FILE__, __LINE__);
|
||||
write(DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||
write(DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
|
||||
|
||||
}
|
||||
|
||||
|
@ -458,9 +454,9 @@ uint64_t dtm_t::modify_csr(unsigned which, uint64_t data, uint32_t type)
|
|||
|
||||
RUN_AC_OR_DIE(command, prog, sizeof(prog) / sizeof(*prog), adata, xlen/(4*8));
|
||||
|
||||
uint64_t res = read(DMI_DATA0);//adata[0];
|
||||
uint64_t res = read(DM_DATA0);//adata[0];
|
||||
if (xlen == 64)
|
||||
res |= read(DMI_DATA0 + 1);//((uint64_t) adata[1]) << 32;
|
||||
res |= read(DM_DATA0 + 1);//((uint64_t) adata[1]) << 32;
|
||||
|
||||
resume(current_hart);
|
||||
return res;
|
||||
|
@ -490,13 +486,13 @@ uint32_t dtm_t::get_xlen()
|
|||
abort();
|
||||
return 128;
|
||||
}
|
||||
write(DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||
write(DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
|
||||
|
||||
cmderr = run_abstract_command(command | AC_AR_SIZE(64), prog, 0, data, 0);
|
||||
if (cmderr == 0){
|
||||
return 64;
|
||||
}
|
||||
write(DMI_ABSTRACTCS, DMI_ABSTRACTCS_CMDERR);
|
||||
write(DM_ABSTRACTCS, DM_ABSTRACTCS_CMDERR);
|
||||
|
||||
cmderr = run_abstract_command(command | AC_AR_SIZE(32), prog, 0, data, 0);
|
||||
if (cmderr == 0){
|
||||
|
@ -545,7 +541,7 @@ void dtm_t::reset()
|
|||
// In theory any hart can handle the memory accesses,
|
||||
// this will enforce that hart 0 handles them.
|
||||
select_hart(0);
|
||||
read(DMI_DMSTATUS);
|
||||
read(DM_DMSTATUS);
|
||||
}
|
||||
|
||||
void dtm_t::idle()
|
||||
|
@ -560,23 +556,23 @@ void dtm_t::producer_thread()
|
|||
// depend on in this code.
|
||||
|
||||
// Enable the debugger.
|
||||
write(DMI_DMCONTROL, DMI_DMCONTROL_DMACTIVE);
|
||||
write(DM_DMCONTROL, DM_DMCONTROL_DMACTIVE);
|
||||
// Poll until the debugger agrees it's enabled.
|
||||
while ((read(DMI_DMCONTROL) & DMI_DMCONTROL_DMACTIVE) == 0) ;
|
||||
while ((read(DM_DMCONTROL) & DM_DMCONTROL_DMACTIVE) == 0) ;
|
||||
|
||||
// These are checked every time we run an abstract command.
|
||||
uint32_t abstractcs = read(DMI_ABSTRACTCS);
|
||||
ram_words = get_field(abstractcs, DMI_ABSTRACTCS_PROGSIZE);
|
||||
data_words = get_field(abstractcs, DMI_ABSTRACTCS_DATACOUNT);
|
||||
uint32_t abstractcs = read(DM_ABSTRACTCS);
|
||||
ram_words = get_field(abstractcs, DM_ABSTRACTCS_PROGBUFSIZE);
|
||||
data_words = get_field(abstractcs, DM_ABSTRACTCS_DATACOUNT);
|
||||
|
||||
// These things are only needed for the 'modify_csr' function.
|
||||
// That could be re-written to not use these at some performance
|
||||
// overhead.
|
||||
uint32_t hartinfo = read(DMI_HARTINFO);
|
||||
assert(get_field(hartinfo, DMI_HARTINFO_NSCRATCH) > 0);
|
||||
assert(get_field(hartinfo, DMI_HARTINFO_DATAACCESS));
|
||||
uint32_t hartinfo = read(DM_HARTINFO);
|
||||
assert(get_field(hartinfo, DM_HARTINFO_NSCRATCH) > 0);
|
||||
assert(get_field(hartinfo, DM_HARTINFO_DATAACCESS));
|
||||
|
||||
data_base = get_field(hartinfo, DMI_HARTINFO_DATAADDR);
|
||||
data_base = get_field(hartinfo, DM_HARTINFO_DATAADDR);
|
||||
|
||||
num_harts = enumerate_harts();
|
||||
halt(0);
|
||||
|
|
18
vendor/riscv/riscv-isa-sim/fesvr/dtm.h
vendored
18
vendor/riscv/riscv-isa-sim/fesvr/dtm.h
vendored
|
@ -64,6 +64,16 @@ class dtm_t : public htif_t
|
|||
virtual void reset() override;
|
||||
virtual void idle() override;
|
||||
|
||||
uint32_t run_abstract_command(uint32_t command, const uint32_t program[], size_t program_n,
|
||||
uint32_t data[], size_t data_n);
|
||||
|
||||
void die(uint32_t cmderr);
|
||||
void halt(int);
|
||||
int enumerate_harts();
|
||||
void select_hart(int);
|
||||
void resume(int);
|
||||
uint32_t get_data_base() { return data_base; };
|
||||
|
||||
private:
|
||||
context_t host;
|
||||
context_t* target;
|
||||
|
@ -76,14 +86,6 @@ class dtm_t : public htif_t
|
|||
resp resp_buf;
|
||||
bool running;
|
||||
|
||||
uint32_t run_abstract_command(uint32_t command, const uint32_t program[], size_t program_n,
|
||||
uint32_t data[], size_t data_n);
|
||||
|
||||
void die(uint32_t cmderr);
|
||||
void halt(int);
|
||||
int enumerate_harts();
|
||||
void select_hart(int);
|
||||
void resume(int);
|
||||
uint64_t save_reg(unsigned regno);
|
||||
void restore_reg(unsigned regno, uint64_t val);
|
||||
|
||||
|
|
21
vendor/riscv/riscv-isa-sim/fesvr/elfloader.cc
vendored
21
vendor/riscv/riscv-isa-sim/fesvr/elfloader.cc
vendored
|
@ -1,5 +1,6 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "config.h"
|
||||
#include "elf.h"
|
||||
#include "memif.h"
|
||||
#include "byteorder.h"
|
||||
|
@ -16,22 +17,28 @@
|
|||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t* entry)
|
||||
std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0)
|
||||
{
|
||||
int fd = open(fn, O_RDONLY);
|
||||
struct stat s;
|
||||
assert(fd != -1);
|
||||
if (fd == -1)
|
||||
throw std::invalid_argument(std::string("Specified ELF can't be opened: ") + strerror(errno));
|
||||
if (fstat(fd, &s) < 0)
|
||||
abort();
|
||||
size_t size = s.st_size;
|
||||
|
||||
char* buf = (char*)mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
assert(buf != MAP_FAILED);
|
||||
if (buf == MAP_FAILED)
|
||||
throw std::invalid_argument(std::string("Specified ELF can't be mapped: ") + strerror(errno));
|
||||
close(fd);
|
||||
|
||||
assert(size >= sizeof(Elf64_Ehdr));
|
||||
const Elf64_Ehdr* eh64 = (const Elf64_Ehdr*)buf;
|
||||
assert(IS_ELF32(*eh64) || IS_ELF64(*eh64));
|
||||
unsigned xlen = IS_ELF32(*eh64) ? 32 : 64;
|
||||
if (required_xlen != 0 && required_xlen != xlen) {
|
||||
throw incompat_xlen(required_xlen, xlen);
|
||||
}
|
||||
assert(IS_ELFLE(*eh64) || IS_ELFBE(*eh64));
|
||||
assert(IS_ELF_EXEC(*eh64));
|
||||
assert(IS_ELF_RISCV(*eh64) || IS_ELF_EM_NONE(*eh64));
|
||||
|
@ -94,7 +101,9 @@ std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t*
|
|||
} while (0)
|
||||
|
||||
if (IS_ELFLE(*eh64)) {
|
||||
memif->set_target_endianness(memif_endianness_little);
|
||||
if (memif->get_target_endianness() != endianness_little) {
|
||||
throw std::invalid_argument("Specified ELF is little endian, but system uses a big-endian memory system. Rerun without --big-endian");
|
||||
}
|
||||
if (IS_ELF32(*eh64))
|
||||
LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_le);
|
||||
else
|
||||
|
@ -103,7 +112,9 @@ std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t*
|
|||
#ifndef RISCV_ENABLE_DUAL_ENDIAN
|
||||
throw std::invalid_argument("Specified ELF is big endian. Configure with --enable-dual-endian to enable support");
|
||||
#else
|
||||
memif->set_target_endianness(memif_endianness_big);
|
||||
if (memif->get_target_endianness() != endianness_big) {
|
||||
throw std::invalid_argument("Specified ELF is big endian, but system uses a little-endian memory system. Rerun with --big-endian");
|
||||
}
|
||||
if (IS_ELF32(*eh64))
|
||||
LOAD_ELF(Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Sym, from_be);
|
||||
else
|
||||
|
|
2
vendor/riscv/riscv-isa-sim/fesvr/elfloader.h
vendored
2
vendor/riscv/riscv-isa-sim/fesvr/elfloader.h
vendored
|
@ -8,6 +8,6 @@
|
|||
#include <string>
|
||||
|
||||
class memif_t;
|
||||
std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t* entry);
|
||||
std::map<std::string, uint64_t> load_elf(const char* fn, memif_t* memif, reg_t* entry, unsigned required_xlen = 0);
|
||||
|
||||
#endif
|
||||
|
|
4
vendor/riscv/riscv-isa-sim/fesvr/fesvr.mk.in
vendored
4
vendor/riscv/riscv-isa-sim/fesvr/fesvr.mk.in
vendored
|
@ -1,4 +1,4 @@
|
|||
fesvr_hdrs = \
|
||||
fesvr_install_hdrs = \
|
||||
byteorder.h \
|
||||
elf.h \
|
||||
elfloader.h \
|
||||
|
@ -15,8 +15,6 @@ fesvr_hdrs = \
|
|||
rfb.h \
|
||||
tsi.h \
|
||||
|
||||
fesvr_install_hdrs = $(fesvr_hdrs)
|
||||
|
||||
fesvr_install_config_hdr = yes
|
||||
|
||||
fesvr_install_lib = yes
|
||||
|
|
126
vendor/riscv/riscv-isa-sim/fesvr/htif.cc
vendored
126
vendor/riscv/riscv-isa-sim/fesvr/htif.cc
vendored
|
@ -1,16 +1,20 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "config.h"
|
||||
#include "htif.h"
|
||||
#include "rfb.h"
|
||||
#include "elfloader.h"
|
||||
#include "platform.h"
|
||||
#include "byteorder.h"
|
||||
#include "trap.h"
|
||||
#include "../riscv/common.h"
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <iomanip>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
@ -80,12 +84,25 @@ htif_t::~htif_t()
|
|||
|
||||
void htif_t::start()
|
||||
{
|
||||
if (!targs.empty() && targs[0] != "none")
|
||||
if (!targs.empty() && targs[0] != "none") {
|
||||
try {
|
||||
load_program();
|
||||
} catch (const incompat_xlen & err) {
|
||||
fprintf(stderr, "Error: cannot execute %d-bit program on RV%d hart\n", err.actual_xlen, err.expected_xlen);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
reset();
|
||||
}
|
||||
|
||||
static void bad_address(const std::string& situation, reg_t addr)
|
||||
{
|
||||
std::cerr << "Access exception occurred while " << situation << ":\n";
|
||||
std::cerr << "Memory address 0x" << std::hex << addr << " is invalid\n";
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload, reg_t* entry)
|
||||
{
|
||||
std::string path;
|
||||
|
@ -96,6 +113,12 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
|
|||
std::string test_path = PREFIX TARGET_DIR + payload;
|
||||
if (access(test_path.c_str(), F_OK) == 0)
|
||||
path = test_path;
|
||||
else
|
||||
throw std::runtime_error(
|
||||
"could not open " + payload + "; searched paths:\n" +
|
||||
"\t. (current directory)\n" +
|
||||
"\t" + PREFIX TARGET_DIR + " (based on configured --prefix and --with-target)"
|
||||
);
|
||||
}
|
||||
|
||||
if (path.empty())
|
||||
|
@ -119,7 +142,12 @@ std::map<std::string, uint64_t> htif_t::load_payload(const std::string& payload,
|
|||
htif_t* htif;
|
||||
} preload_aware_memif(this);
|
||||
|
||||
return load_elf(path.c_str(), &preload_aware_memif, entry);
|
||||
try {
|
||||
return load_elf(path.c_str(), &preload_aware_memif, entry, expected_xlen);
|
||||
} catch (mem_trap_t& t) {
|
||||
bad_address("loading payload " + payload, t.get_tval());
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
void htif_t::load_program()
|
||||
|
@ -134,26 +162,39 @@ void htif_t::load_program()
|
|||
}
|
||||
|
||||
// detect torture tests so we can print the memory signature at the end
|
||||
if (symbols.count("begin_signature") && symbols.count("end_signature"))
|
||||
{
|
||||
if (symbols.count("begin_signature") && symbols.count("end_signature")) {
|
||||
sig_addr = symbols["begin_signature"];
|
||||
sig_len = symbols["end_signature"] - sig_addr;
|
||||
}
|
||||
|
||||
for (auto payload : payloads)
|
||||
{
|
||||
for (auto payload : payloads) {
|
||||
reg_t dummy_entry;
|
||||
load_payload(payload, &dummy_entry);
|
||||
}
|
||||
|
||||
for (auto i : symbols)
|
||||
{
|
||||
auto it = addr2symbol.find(i.second);
|
||||
if ( it == addr2symbol.end())
|
||||
addr2symbol[i.second] = i.first;
|
||||
}
|
||||
class nop_memif_t : public memif_t {
|
||||
public:
|
||||
nop_memif_t(htif_t* htif) : memif_t(htif), htif(htif) {}
|
||||
void read(addr_t UNUSED addr, size_t UNUSED len, void UNUSED *bytes) override {}
|
||||
void write(addr_t UNUSED taddr, size_t UNUSED len, const void UNUSED *src) override {}
|
||||
private:
|
||||
htif_t* htif;
|
||||
} nop_memif(this);
|
||||
|
||||
return;
|
||||
reg_t nop_entry;
|
||||
for (auto &s : symbol_elfs) {
|
||||
std::map<std::string, uint64_t> other_symbols = load_elf(s.c_str(), &nop_memif, &nop_entry,
|
||||
expected_xlen);
|
||||
symbols.merge(other_symbols);
|
||||
}
|
||||
|
||||
for (auto i : symbols) {
|
||||
auto it = addr2symbol.find(i.second);
|
||||
if ( it == addr2symbol.end())
|
||||
addr2symbol[i.second] = i.first;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
const char* htif_t::get_symbol(uint64_t addr)
|
||||
|
@ -218,19 +259,37 @@ int htif_t::run()
|
|||
|
||||
while (!signal_exit && exitcode == 0)
|
||||
{
|
||||
if (auto tohost = from_target(mem.read_uint64(tohost_addr))) {
|
||||
mem.write_uint64(tohost_addr, target_endian<uint64_t>::zero);
|
||||
command_t cmd(mem, tohost, fromhost_callback);
|
||||
device_list.handle_command(cmd);
|
||||
} else {
|
||||
idle();
|
||||
uint64_t tohost;
|
||||
|
||||
try {
|
||||
if ((tohost = from_target(mem.read_uint64(tohost_addr))) != 0)
|
||||
mem.write_uint64(tohost_addr, target_endian<uint64_t>::zero);
|
||||
} catch (mem_trap_t& t) {
|
||||
bad_address("accessing tohost", t.get_tval());
|
||||
}
|
||||
|
||||
device_list.tick();
|
||||
try {
|
||||
if (tohost != 0) {
|
||||
command_t cmd(mem, tohost, fromhost_callback);
|
||||
device_list.handle_command(cmd);
|
||||
} else {
|
||||
idle();
|
||||
}
|
||||
|
||||
if (!fromhost_queue.empty() && !mem.read_uint64(fromhost_addr)) {
|
||||
mem.write_uint64(fromhost_addr, to_target(fromhost_queue.front()));
|
||||
fromhost_queue.pop();
|
||||
device_list.tick();
|
||||
} catch (mem_trap_t& t) {
|
||||
std::stringstream tohost_hex;
|
||||
tohost_hex << std::hex << tohost;
|
||||
bad_address("host was accessing memory on behalf of target (tohost = 0x" + tohost_hex.str() + ")", t.get_tval());
|
||||
}
|
||||
|
||||
try {
|
||||
if (!fromhost_queue.empty() && !mem.read_uint64(fromhost_addr)) {
|
||||
mem.write_uint64(fromhost_addr, to_target(fromhost_queue.front()));
|
||||
fromhost_queue.pop();
|
||||
}
|
||||
} catch (mem_trap_t& t) {
|
||||
bad_address("accessing fromhost", t.get_tval());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,7 +341,12 @@ void htif_t::parse_arguments(int argc, char ** argv)
|
|||
break;
|
||||
case HTIF_LONG_OPTIONS_OPTIND + 5:
|
||||
line_size = atoi(optarg);
|
||||
|
||||
break;
|
||||
case HTIF_LONG_OPTIONS_OPTIND + 6:
|
||||
targs.push_back(optarg);
|
||||
break;
|
||||
case HTIF_LONG_OPTIONS_OPTIND + 7:
|
||||
symbol_elfs.push_back(optarg);
|
||||
break;
|
||||
case '?':
|
||||
if (!opterr)
|
||||
|
@ -318,9 +382,17 @@ void htif_t::parse_arguments(int argc, char ** argv)
|
|||
c = HTIF_LONG_OPTIONS_OPTIND + 4;
|
||||
optarg = optarg + 9;
|
||||
}
|
||||
else if(arg.find("+signature-granularity=")==0){
|
||||
c = HTIF_LONG_OPTIONS_OPTIND + 5;
|
||||
optarg = optarg + 23;
|
||||
else if (arg.find("+signature-granularity=") == 0) {
|
||||
c = HTIF_LONG_OPTIONS_OPTIND + 5;
|
||||
optarg = optarg + 23;
|
||||
}
|
||||
else if (arg.find("+target-argument=") == 0) {
|
||||
c = HTIF_LONG_OPTIONS_OPTIND + 6;
|
||||
optarg = optarg + 17;
|
||||
}
|
||||
else if (arg.find("+symbol-elf=") == 0) {
|
||||
c = HTIF_LONG_OPTIONS_OPTIND + 7;
|
||||
optarg = optarg + 12;
|
||||
}
|
||||
else if (arg.find("+permissive-off") == 0) {
|
||||
if (opterr)
|
||||
|
|
39
vendor/riscv/riscv-isa-sim/fesvr/htif.h
vendored
39
vendor/riscv/riscv-isa-sim/fesvr/htif.h
vendored
|
@ -26,33 +26,28 @@ class htif_t : public chunked_memif_t
|
|||
int run();
|
||||
bool done();
|
||||
int exit_code();
|
||||
|
||||
void set_expected_xlen(unsigned int m) { expected_xlen = m; }
|
||||
virtual memif_t& memif() { return mem; }
|
||||
|
||||
template<typename T> inline T from_target(target_endian<T> n) const
|
||||
{
|
||||
#ifdef RISCV_ENABLE_DUAL_ENDIAN
|
||||
memif_endianness_t endianness = get_target_endianness();
|
||||
assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
|
||||
endianness_t endianness = get_target_endianness();
|
||||
assert(endianness == endianness_little || endianness == endianness_big);
|
||||
|
||||
return endianness == memif_endianness_big? n.from_be() : n.from_le();
|
||||
#else
|
||||
return n.from_le();
|
||||
#endif
|
||||
return endianness == endianness_big? n.from_be() : n.from_le();
|
||||
}
|
||||
|
||||
template<typename T> inline target_endian<T> to_target(T n) const
|
||||
{
|
||||
#ifdef RISCV_ENABLE_DUAL_ENDIAN
|
||||
memif_endianness_t endianness = get_target_endianness();
|
||||
assert(endianness == memif_endianness_little || endianness == memif_endianness_big);
|
||||
endianness_t endianness = get_target_endianness();
|
||||
assert(endianness == endianness_little || endianness == endianness_big);
|
||||
|
||||
return endianness == memif_endianness_big? target_endian<T>::to_be(n) : target_endian<T>::to_le(n);
|
||||
#else
|
||||
return target_endian<T>::to_le(n);
|
||||
#endif
|
||||
return endianness == endianness_big? target_endian<T>::to_be(n) : target_endian<T>::to_le(n);
|
||||
}
|
||||
|
||||
addr_t get_tohost_addr() { return tohost_addr; }
|
||||
addr_t get_fromhost_addr() { return fromhost_addr; }
|
||||
|
||||
protected:
|
||||
virtual void reset() = 0;
|
||||
|
||||
|
@ -68,12 +63,13 @@ class htif_t : public chunked_memif_t
|
|||
virtual void idle() {}
|
||||
|
||||
const std::vector<std::string>& host_args() { return hargs; }
|
||||
const std::vector<std::string>& target_args() { return targs; }
|
||||
|
||||
reg_t get_entry_point() { return entry; }
|
||||
|
||||
// indicates that the initial program load can skip writing this address
|
||||
// range to memory, because it has already been loaded through a sideband
|
||||
virtual bool is_address_preloaded(addr_t taddr, size_t len) { return false; }
|
||||
virtual bool is_address_preloaded(addr_t, size_t) { return false; }
|
||||
|
||||
// Given an address, return symbol from addr2symbol map
|
||||
const char* get_symbol(uint64_t addr);
|
||||
|
@ -82,7 +78,7 @@ class htif_t : public chunked_memif_t
|
|||
void parse_arguments(int argc, char ** argv);
|
||||
void register_devices();
|
||||
void usage(const char * program_name);
|
||||
|
||||
unsigned int expected_xlen = 0;
|
||||
memif_t mem;
|
||||
reg_t entry;
|
||||
bool writezeros;
|
||||
|
@ -103,8 +99,7 @@ class htif_t : public chunked_memif_t
|
|||
std::vector<device_t*> dynamic_devices;
|
||||
std::vector<std::string> payloads;
|
||||
|
||||
const std::vector<std::string>& target_args() { return targs; }
|
||||
|
||||
std::vector<std::string> symbol_elfs;
|
||||
std::map<uint64_t, std::string> addr2symbol;
|
||||
|
||||
friend class memif_t;
|
||||
|
@ -133,6 +128,8 @@ class htif_t : public chunked_memif_t
|
|||
+chroot=PATH\n\
|
||||
--payload=PATH Load PATH memory as an additional ELF payload\n\
|
||||
+payload=PATH\n\
|
||||
--symbol-elf=PATH Populate the symbol table with the ELF file at PATH\n\
|
||||
+symbol-elf=PATH\n\
|
||||
\n\
|
||||
HOST OPTIONS (currently unsupported)\n\
|
||||
--disk=DISK Add DISK device. Use a ramdisk since this isn't\n\
|
||||
|
@ -150,7 +147,9 @@ TARGET (RISC-V BINARY) OPTIONS\n\
|
|||
{"signature", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 2 }, \
|
||||
{"chroot", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 3 }, \
|
||||
{"payload", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 4 }, \
|
||||
{"signature-granularity", optional_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 5 }, \
|
||||
{"signature-granularity", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 5 }, \
|
||||
{"target-argument", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 6 }, \
|
||||
{"symbol-elf", required_argument, 0, HTIF_LONG_OPTIONS_OPTIND + 7 }, \
|
||||
{0, 0, 0, 0}
|
||||
|
||||
#endif // __HTIF_H
|
||||
|
|
|
@ -21,7 +21,7 @@ protected:
|
|||
|
||||
void read_chunk(addr_t taddr, size_t len, void* dst);
|
||||
void write_chunk(addr_t taddr, size_t len, const void* src);
|
||||
void clear_chunk(addr_t taddr, size_t len) {}
|
||||
void clear_chunk(addr_t, size_t) {}
|
||||
|
||||
size_t chunk_max_size() { return width; }
|
||||
size_t chunk_align() { return width; }
|
||||
|
|
27
vendor/riscv/riscv-isa-sim/fesvr/memif.h
vendored
27
vendor/riscv/riscv-isa-sim/fesvr/memif.h
vendored
|
@ -5,18 +5,14 @@
|
|||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdexcept>
|
||||
#include "byteorder.h"
|
||||
#include "../riscv/cfg.h"
|
||||
|
||||
typedef uint64_t reg_t;
|
||||
typedef int64_t sreg_t;
|
||||
typedef reg_t addr_t;
|
||||
|
||||
typedef enum {
|
||||
memif_endianness_undecided,
|
||||
memif_endianness_little,
|
||||
memif_endianness_big
|
||||
} memif_endianness_t;
|
||||
|
||||
class chunked_memif_t
|
||||
{
|
||||
public:
|
||||
|
@ -27,10 +23,11 @@ public:
|
|||
virtual size_t chunk_align() = 0;
|
||||
virtual size_t chunk_max_size() = 0;
|
||||
|
||||
virtual void set_target_endianness(memif_endianness_t endianness) {}
|
||||
virtual memif_endianness_t get_target_endianness() const {
|
||||
return memif_endianness_undecided;
|
||||
virtual endianness_t get_target_endianness() const {
|
||||
return endianness_little;
|
||||
}
|
||||
|
||||
virtual ~chunked_memif_t() = default;
|
||||
};
|
||||
|
||||
class memif_t
|
||||
|
@ -68,10 +65,7 @@ public:
|
|||
virtual void write_int64(addr_t addr, target_endian<int64_t> val);
|
||||
|
||||
// endianness
|
||||
virtual void set_target_endianness(memif_endianness_t endianness) {
|
||||
cmemif->set_target_endianness(endianness);
|
||||
}
|
||||
virtual memif_endianness_t get_target_endianness() const {
|
||||
virtual endianness_t get_target_endianness() const {
|
||||
return cmemif->get_target_endianness();
|
||||
}
|
||||
|
||||
|
@ -79,4 +73,11 @@ protected:
|
|||
chunked_memif_t* cmemif;
|
||||
};
|
||||
|
||||
class incompat_xlen : public std::exception {
|
||||
public:
|
||||
const unsigned expected_xlen;
|
||||
const unsigned actual_xlen;
|
||||
incompat_xlen(unsigned _expected_xlen, unsigned _actual_xlen) : expected_xlen(_expected_xlen), actual_xlen(_actual_xlen) {}
|
||||
};
|
||||
|
||||
#endif // __MEMIF_H
|
||||
|
|
4
vendor/riscv/riscv-isa-sim/fesvr/rfb.cc
vendored
4
vendor/riscv/riscv-isa-sim/fesvr/rfb.cc
vendored
|
@ -119,7 +119,7 @@ void rfb_t::set_pixel_format(const std::string& s)
|
|||
throw std::runtime_error("bad pixel format");
|
||||
}
|
||||
|
||||
void rfb_t::fb_update(const std::string& s)
|
||||
void rfb_t::fb_update()
|
||||
{
|
||||
std::string u;
|
||||
u += str(uint8_t(0));
|
||||
|
@ -153,7 +153,7 @@ void rfb_t::tick()
|
|||
std::swap(fb1, fb2);
|
||||
if (pthread_mutex_trylock(&lock) == 0)
|
||||
{
|
||||
fb_update("");
|
||||
fb_update();
|
||||
pthread_mutex_unlock(&lock);
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/riscv/riscv-isa-sim/fesvr/rfb.h
vendored
2
vendor/riscv/riscv-isa-sim/fesvr/rfb.h
vendored
|
@ -25,7 +25,7 @@ class rfb_t : public device_t
|
|||
void thread_main();
|
||||
friend void* rfb_thread_main(void*);
|
||||
std::string pixel_format();
|
||||
void fb_update(const std::string& s);
|
||||
void fb_update();
|
||||
void set_encodings(const std::string& s);
|
||||
void set_pixel_format(const std::string& s);
|
||||
void write(const std::string& s);
|
||||
|
|
18
vendor/riscv/riscv-isa-sim/fesvr/syscall.cc
vendored
18
vendor/riscv/riscv-isa-sim/fesvr/syscall.cc
vendored
|
@ -1,5 +1,6 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "config.h"
|
||||
#include "syscall.h"
|
||||
#include "htif.h"
|
||||
#include "byteorder.h"
|
||||
|
@ -17,6 +18,10 @@ using namespace std::placeholders;
|
|||
|
||||
#define RISCV_AT_FDCWD -100
|
||||
|
||||
#ifdef __GNUC__
|
||||
# pragma GCC diagnostic ignored "-Wunused-parameter"
|
||||
#endif
|
||||
|
||||
struct riscv_stat
|
||||
{
|
||||
target_endian<uint64_t> dev;
|
||||
|
@ -169,9 +174,16 @@ syscall_t::syscall_t(htif_t* htif)
|
|||
if (stdin_fd < 0 || stdout_fd0 < 0 || stdout_fd1 < 0)
|
||||
throw std::runtime_error("could not dup stdin/stdout");
|
||||
|
||||
fds.alloc(stdin_fd); // stdin -> stdin
|
||||
fds.alloc(stdout_fd0); // stdout -> stdout
|
||||
fds.alloc(stdout_fd1); // stderr -> stdout
|
||||
fds_index.push_back(fds.alloc(stdin_fd)); // stdin -> stdin
|
||||
fds_index.push_back(fds.alloc(stdout_fd0)); // stdout -> stdout
|
||||
fds_index.push_back(fds.alloc(stdout_fd1)); // stderr -> stdout
|
||||
}
|
||||
|
||||
syscall_t::~syscall_t() {
|
||||
for (auto i: fds_index) {
|
||||
close(fds.lookup(i));
|
||||
fds.dealloc(i);
|
||||
}
|
||||
}
|
||||
|
||||
std::string syscall_t::do_chroot(const char* fn)
|
||||
|
|
2
vendor/riscv/riscv-isa-sim/fesvr/syscall.h
vendored
2
vendor/riscv/riscv-isa-sim/fesvr/syscall.h
vendored
|
@ -28,6 +28,7 @@ class syscall_t : public device_t
|
|||
{
|
||||
public:
|
||||
syscall_t(htif_t*);
|
||||
~syscall_t();
|
||||
|
||||
void set_chroot(const char* where);
|
||||
|
||||
|
@ -38,6 +39,7 @@ class syscall_t : public device_t
|
|||
memif_t* memif;
|
||||
std::vector<syscall_func_t> table;
|
||||
fds_t fds;
|
||||
std::vector<reg_t> fds_index;
|
||||
|
||||
void handle_syscall(command_t cmd);
|
||||
void dispatch(addr_t mm);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@prefix@
|
||||
libdir=${prefix}/@libdir@
|
||||
includedir=${prefix}/@includedir@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: riscv-disasm
|
||||
Description: RISC-V disassembler
|
||||
|
|
4
vendor/riscv/riscv-isa-sim/riscv-fesvr.pc.in
vendored
4
vendor/riscv/riscv-isa-sim/riscv-fesvr.pc.in
vendored
|
@ -1,7 +1,7 @@
|
|||
prefix=@prefix@
|
||||
exec_prefix=@prefix@
|
||||
libdir=${prefix}/@libdir@
|
||||
includedir=${prefix}/@includedir@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: riscv-fesvr
|
||||
Description: RISC-V front-end server
|
||||
|
|
14
vendor/riscv/riscv-isa-sim/riscv/abstract_interrupt_controller.h
vendored
Normal file
14
vendor/riscv/riscv-isa-sim/riscv/abstract_interrupt_controller.h
vendored
Normal file
|
@ -0,0 +1,14 @@
|
|||
#ifndef _RISCV_ABSTRACT_INTERRUPT_CONTROLLER_H
|
||||
#define _RISCV_ABSTRACT_INTERRUPT_CONTROLLER_H
|
||||
|
||||
#include "decode.h"
|
||||
#include <cstdint>
|
||||
#include <cstddef>
|
||||
|
||||
class abstract_interrupt_controller_t {
|
||||
public:
|
||||
virtual void set_interrupt_level(uint32_t interrupt_id, int level) = 0;
|
||||
virtual ~abstract_interrupt_controller_t() {}
|
||||
};
|
||||
|
||||
#endif
|
10
vendor/riscv/riscv-isa-sim/riscv/arith.h
vendored
10
vendor/riscv/riscv-isa-sim/riscv/arith.h
vendored
|
@ -20,7 +20,6 @@ inline uint64_t mulhu(uint64_t a, uint64_t b)
|
|||
y2 = t >> 32;
|
||||
|
||||
t = a0*b1 + y1;
|
||||
y1 = t;
|
||||
|
||||
t = a1*b1 + y2 + (t >> 32);
|
||||
y2 = t;
|
||||
|
@ -188,6 +187,15 @@ static inline int clz(uint64_t val)
|
|||
return res;
|
||||
}
|
||||
|
||||
// Count number of contiguous 1 bits starting from the LSB.
|
||||
static inline int cto(uint64_t val)
|
||||
{
|
||||
int res = 0;
|
||||
while ((val & 1) == 1)
|
||||
val >>= 1, res++;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int log2(uint64_t val)
|
||||
{
|
||||
if (!val)
|
||||
|
|
32
vendor/riscv/riscv-isa-sim/riscv/cachesim.cc
vendored
32
vendor/riscv/riscv-isa-sim/riscv/cachesim.cc
vendored
|
@ -39,9 +39,9 @@ cache_sim_t* cache_sim_t::construct(const char* config, const char* name)
|
|||
|
||||
void cache_sim_t::init()
|
||||
{
|
||||
if(sets == 0 || (sets & (sets-1)))
|
||||
if (sets == 0 || (sets & (sets-1)))
|
||||
help();
|
||||
if(linesz < 8 || (linesz & (linesz-1)))
|
||||
if (linesz < 8 || (linesz & (linesz-1)))
|
||||
help();
|
||||
|
||||
idx_shift = 0;
|
||||
|
@ -76,9 +76,6 @@ cache_sim_t::~cache_sim_t()
|
|||
|
||||
void cache_sim_t::print_stats()
|
||||
{
|
||||
if(read_accesses + write_accesses == 0)
|
||||
return;
|
||||
|
||||
float mr = 100.0f*(read_misses+write_misses)/(read_accesses+write_accesses);
|
||||
|
||||
std::cout << std::setprecision(3) << std::fixed;
|
||||
|
@ -159,6 +156,31 @@ void cache_sim_t::access(uint64_t addr, size_t bytes, bool store)
|
|||
*check_tag(addr) |= DIRTY;
|
||||
}
|
||||
|
||||
void cache_sim_t::clean_invalidate(uint64_t addr, size_t bytes, bool clean, bool inval)
|
||||
{
|
||||
uint64_t start_addr = addr & ~(linesz-1);
|
||||
uint64_t end_addr = (addr + bytes + linesz-1) & ~(linesz-1);
|
||||
uint64_t cur_addr = start_addr;
|
||||
while (cur_addr < end_addr) {
|
||||
uint64_t* hit_way = check_tag(cur_addr);
|
||||
if (likely(hit_way != NULL))
|
||||
{
|
||||
if (clean) {
|
||||
if (*hit_way & DIRTY) {
|
||||
writebacks++;
|
||||
*hit_way &= ~DIRTY;
|
||||
}
|
||||
}
|
||||
|
||||
if (inval)
|
||||
*hit_way &= ~VALID;
|
||||
}
|
||||
cur_addr += linesz;
|
||||
}
|
||||
if (miss_handler)
|
||||
miss_handler->clean_invalidate(addr, bytes, clean, inval);
|
||||
}
|
||||
|
||||
fa_cache_sim_t::fa_cache_sim_t(size_t ways, size_t linesz, const char* name)
|
||||
: cache_sim_t(1, ways, linesz, name)
|
||||
{
|
||||
|
|
20
vendor/riscv/riscv-isa-sim/riscv/cachesim.h
vendored
20
vendor/riscv/riscv-isa-sim/riscv/cachesim.h
vendored
|
@ -4,6 +4,7 @@
|
|||
#define _RISCV_CACHE_SIM_H
|
||||
|
||||
#include "memtracer.h"
|
||||
#include "common.h"
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
@ -27,6 +28,7 @@ class cache_sim_t
|
|||
virtual ~cache_sim_t();
|
||||
|
||||
void access(uint64_t addr, size_t bytes, bool store);
|
||||
void clean_invalidate(uint64_t addr, size_t bytes, bool clean, bool inval);
|
||||
void print_stats();
|
||||
void set_miss_handler(cache_sim_t* mh) { miss_handler = mh; }
|
||||
void set_log(bool _log) { log = _log; }
|
||||
|
@ -90,10 +92,18 @@ class cache_memtracer_t : public memtracer_t
|
|||
{
|
||||
cache->set_miss_handler(mh);
|
||||
}
|
||||
void clean_invalidate(uint64_t addr, size_t bytes, bool clean, bool inval)
|
||||
{
|
||||
cache->clean_invalidate(addr, bytes, clean, inval);
|
||||
}
|
||||
void set_log(bool log)
|
||||
{
|
||||
cache->set_log(log);
|
||||
}
|
||||
void print_stats()
|
||||
{
|
||||
cache->print_stats();
|
||||
}
|
||||
|
||||
protected:
|
||||
cache_sim_t* cache;
|
||||
|
@ -102,8 +112,9 @@ class cache_memtracer_t : public memtracer_t
|
|||
class icache_sim_t : public cache_memtracer_t
|
||||
{
|
||||
public:
|
||||
icache_sim_t(const char* config) : cache_memtracer_t(config, "I$") {}
|
||||
bool interested_in_range(uint64_t begin, uint64_t end, access_type type)
|
||||
icache_sim_t(const char* config, const char* name = "I$")
|
||||
: cache_memtracer_t(config, name) {}
|
||||
bool interested_in_range(uint64_t UNUSED begin, uint64_t UNUSED end, access_type type)
|
||||
{
|
||||
return type == FETCH;
|
||||
}
|
||||
|
@ -116,8 +127,9 @@ class icache_sim_t : public cache_memtracer_t
|
|||
class dcache_sim_t : public cache_memtracer_t
|
||||
{
|
||||
public:
|
||||
dcache_sim_t(const char* config) : cache_memtracer_t(config, "D$") {}
|
||||
bool interested_in_range(uint64_t begin, uint64_t end, access_type type)
|
||||
dcache_sim_t(const char* config, const char* name = "D$")
|
||||
: cache_memtracer_t(config, name) {}
|
||||
bool interested_in_range(uint64_t UNUSED begin, uint64_t UNUSED end, access_type type)
|
||||
{
|
||||
return type == LOAD || type == STORE;
|
||||
}
|
||||
|
|
27
vendor/riscv/riscv-isa-sim/riscv/cfg.cc
vendored
Normal file
27
vendor/riscv/riscv-isa-sim/riscv/cfg.cc
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "cfg.h"
|
||||
#include "mmu.h"
|
||||
#include "decode.h"
|
||||
|
||||
mem_cfg_t::mem_cfg_t(reg_t base, reg_t size) : base(base), size(size)
|
||||
{
|
||||
assert(mem_cfg_t::check_if_supported(base, size));
|
||||
}
|
||||
|
||||
bool mem_cfg_t::check_if_supported(reg_t base, reg_t size)
|
||||
{
|
||||
// The truth of these conditions should be ensured by whatever is creating
|
||||
// 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.
|
||||
//
|
||||
// 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 > 0) &&
|
||||
((base + size > base) || (base + size == 0));
|
||||
}
|
109
vendor/riscv/riscv-isa-sim/riscv/cfg.h
vendored
Normal file
109
vendor/riscv/riscv-isa-sim/riscv/cfg.h
vendored
Normal file
|
@ -0,0 +1,109 @@
|
|||
// See LICENSE for license details.
|
||||
#ifndef _RISCV_CFG_H
|
||||
#define _RISCV_CFG_H
|
||||
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
#include "decode.h"
|
||||
#include <cassert>
|
||||
|
||||
typedef enum {
|
||||
endianness_little,
|
||||
endianness_big
|
||||
} endianness_t;
|
||||
|
||||
template <typename T>
|
||||
class cfg_arg_t {
|
||||
public:
|
||||
cfg_arg_t(T default_val)
|
||||
: value(default_val), was_set(false) {}
|
||||
|
||||
bool overridden() const { return was_set; }
|
||||
|
||||
T operator()() const { return value; }
|
||||
|
||||
T operator=(const T v) {
|
||||
value = v;
|
||||
was_set = true;
|
||||
return value;
|
||||
}
|
||||
|
||||
private:
|
||||
T value;
|
||||
bool was_set;
|
||||
};
|
||||
|
||||
// Configuration that describes a memory region
|
||||
class mem_cfg_t
|
||||
{
|
||||
public:
|
||||
static bool check_if_supported(reg_t base, reg_t size);
|
||||
|
||||
mem_cfg_t(reg_t base, reg_t size);
|
||||
|
||||
reg_t get_base() const {
|
||||
return base;
|
||||
}
|
||||
|
||||
reg_t get_size() const {
|
||||
return size;
|
||||
}
|
||||
|
||||
reg_t get_inclusive_end() const {
|
||||
return base + size - 1;
|
||||
}
|
||||
|
||||
private:
|
||||
reg_t base;
|
||||
reg_t size;
|
||||
};
|
||||
|
||||
class cfg_t
|
||||
{
|
||||
public:
|
||||
cfg_t(std::pair<reg_t, reg_t> default_initrd_bounds,
|
||||
const char *default_bootargs,
|
||||
const char *default_isa, const char *default_priv,
|
||||
const char *default_varch,
|
||||
const bool default_misaligned,
|
||||
const endianness_t default_endianness,
|
||||
const reg_t default_pmpregions,
|
||||
const std::vector<mem_cfg_t> &default_mem_layout,
|
||||
const std::vector<size_t> default_hartids,
|
||||
bool default_real_time_clint,
|
||||
const reg_t default_trigger_count)
|
||||
: initrd_bounds(default_initrd_bounds),
|
||||
bootargs(default_bootargs),
|
||||
isa(default_isa),
|
||||
priv(default_priv),
|
||||
varch(default_varch),
|
||||
misaligned(default_misaligned),
|
||||
endianness(default_endianness),
|
||||
pmpregions(default_pmpregions),
|
||||
mem_layout(default_mem_layout),
|
||||
hartids(default_hartids),
|
||||
explicit_hartids(false),
|
||||
real_time_clint(default_real_time_clint),
|
||||
trigger_count(default_trigger_count)
|
||||
{}
|
||||
|
||||
cfg_arg_t<std::pair<reg_t, reg_t>> initrd_bounds;
|
||||
cfg_arg_t<const char *> bootargs;
|
||||
cfg_arg_t<const char *> isa;
|
||||
cfg_arg_t<const char *> priv;
|
||||
cfg_arg_t<const char *> varch;
|
||||
bool misaligned;
|
||||
endianness_t endianness;
|
||||
reg_t pmpregions;
|
||||
cfg_arg_t<std::vector<mem_cfg_t>> mem_layout;
|
||||
std::optional<reg_t> start_pc;
|
||||
cfg_arg_t<std::vector<size_t>> hartids;
|
||||
bool explicit_hartids;
|
||||
cfg_arg_t<bool> real_time_clint;
|
||||
reg_t trigger_count;
|
||||
|
||||
size_t nprocs() const { return hartids().size(); }
|
||||
size_t max_hartid() const { return hartids().back(); }
|
||||
};
|
||||
|
||||
#endif
|
83
vendor/riscv/riscv-isa-sim/riscv/clint.cc
vendored
83
vendor/riscv/riscv-isa-sim/riscv/clint.cc
vendored
|
@ -1,9 +1,10 @@
|
|||
#include <sys/time.h>
|
||||
#include "devices.h"
|
||||
#include "processor.h"
|
||||
#include "simif.h"
|
||||
|
||||
clint_t::clint_t(std::vector<processor_t*>& procs, uint64_t freq_hz, bool real_time)
|
||||
: procs(procs), freq_hz(freq_hz), real_time(real_time), mtime(0), mtimecmp(procs.size())
|
||||
clint_t::clint_t(simif_t* sim, uint64_t freq_hz, bool real_time)
|
||||
: sim(sim), freq_hz(freq_hz), real_time(real_time), mtime(0)
|
||||
{
|
||||
struct timeval base;
|
||||
|
||||
|
@ -11,6 +12,7 @@ clint_t::clint_t(std::vector<processor_t*>& procs, uint64_t freq_hz, bool real_t
|
|||
|
||||
real_time_ref_secs = base.tv_sec;
|
||||
real_time_ref_usecs = base.tv_usec;
|
||||
increment(0);
|
||||
}
|
||||
|
||||
/* 0000 msip hart 0
|
||||
|
@ -29,16 +31,29 @@ clint_t::clint_t(std::vector<processor_t*>& procs, uint64_t freq_hz, bool real_t
|
|||
|
||||
bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
|
||||
{
|
||||
if (len > 8)
|
||||
return false;
|
||||
|
||||
increment(0);
|
||||
if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
|
||||
std::vector<msip_t> msip(procs.size());
|
||||
for (size_t i = 0; i < procs.size(); ++i)
|
||||
msip[i] = !!(procs[i]->state.mip->read() & MIP_MSIP);
|
||||
memcpy(bytes, (uint8_t*)&msip[0] + addr - MSIP_BASE, len);
|
||||
} else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
|
||||
memcpy(bytes, (uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, len);
|
||||
} else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
|
||||
memcpy(bytes, (uint8_t*)&mtime + addr - MTIME_BASE, len);
|
||||
|
||||
if (addr >= MSIP_BASE && addr < MTIMECMP_BASE) {
|
||||
if (len == 8) {
|
||||
// Implement double-word loads as a pair of word loads
|
||||
return load(addr, 4, bytes) && load(addr + 4, 4, bytes + 4);
|
||||
}
|
||||
|
||||
const auto hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
|
||||
const msip_t res = sim->get_harts().count(hart_id) && (sim->get_harts().at(hart_id)->state.mip->read() & MIP_MSIP);
|
||||
read_little_endian_reg(res, addr, len, bytes);
|
||||
return true;
|
||||
} else if (addr >= MTIMECMP_BASE && addr < MTIME_BASE) {
|
||||
const auto hart_id = (addr - MTIMECMP_BASE) / sizeof(mtimecmp_t);
|
||||
const mtime_t res = sim->get_harts().count(hart_id) ? mtimecmp[hart_id] : 0;
|
||||
read_little_endian_reg(res, addr, len, bytes);
|
||||
} else if (addr >= MTIME_BASE && addr < MTIME_BASE + sizeof(mtime_t)) {
|
||||
read_little_endian_reg(mtime, addr, len, bytes);
|
||||
} else if (addr + len <= CLINT_SIZE) {
|
||||
memset(bytes, 0, len);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -47,21 +62,31 @@ bool clint_t::load(reg_t addr, size_t len, uint8_t* bytes)
|
|||
|
||||
bool clint_t::store(reg_t addr, size_t len, const uint8_t* bytes)
|
||||
{
|
||||
if (addr >= MSIP_BASE && addr + len <= MSIP_BASE + procs.size()*sizeof(msip_t)) {
|
||||
std::vector<msip_t> msip(procs.size());
|
||||
std::vector<msip_t> mask(procs.size(), 0);
|
||||
memcpy((uint8_t*)&msip[0] + addr - MSIP_BASE, bytes, len);
|
||||
memset((uint8_t*)&mask[0] + addr - MSIP_BASE, 0xff, len);
|
||||
for (size_t i = 0; i < procs.size(); ++i) {
|
||||
if (!(mask[i] & 0xFF)) continue;
|
||||
procs[i]->state.mip->backdoor_write_with_mask(MIP_MSIP, 0);
|
||||
if (!!(msip[i] & 1))
|
||||
procs[i]->state.mip->backdoor_write_with_mask(MIP_MSIP, MIP_MSIP);
|
||||
if (len > 8)
|
||||
return false;
|
||||
|
||||
if (addr >= MSIP_BASE && addr < MTIMECMP_BASE) {
|
||||
if (len == 8) {
|
||||
// Implement double-word stores as a pair of word stores
|
||||
return store(addr, 4, bytes) && store(addr + 4, 4, bytes + 4);
|
||||
}
|
||||
} else if (addr >= MTIMECMP_BASE && addr + len <= MTIMECMP_BASE + procs.size()*sizeof(mtimecmp_t)) {
|
||||
memcpy((uint8_t*)&mtimecmp[0] + addr - MTIMECMP_BASE, bytes, len);
|
||||
} else if (addr >= MTIME_BASE && addr + len <= MTIME_BASE + sizeof(mtime_t)) {
|
||||
memcpy((uint8_t*)&mtime + addr - MTIME_BASE, bytes, len);
|
||||
|
||||
if (addr % sizeof(msip_t) == 0) { // ignore in-between bytes
|
||||
msip_t msip = 0;
|
||||
write_little_endian_reg(&msip, addr, len, bytes);
|
||||
|
||||
const auto hart_id = (addr - MSIP_BASE) / sizeof(msip_t);
|
||||
if (sim->get_harts().count(hart_id))
|
||||
sim->get_harts().at(hart_id)->state.mip->backdoor_write_with_mask(MIP_MSIP, msip & 1 ? MIP_MSIP : 0);
|
||||
}
|
||||
} else if (addr >= MTIMECMP_BASE && addr < MTIME_BASE) {
|
||||
const auto hart_id = (addr - MTIMECMP_BASE) / sizeof(mtimecmp_t);
|
||||
if (sim->get_harts().count(hart_id))
|
||||
write_little_endian_reg(&mtimecmp[hart_id], addr, len, bytes);
|
||||
} else if (addr >= MTIME_BASE && addr < MTIME_BASE + sizeof(mtime_t)) {
|
||||
write_little_endian_reg(&mtime, addr, len, bytes);
|
||||
} else if (addr + len <= CLINT_SIZE) {
|
||||
// Do nothing
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -81,9 +106,9 @@ void clint_t::increment(reg_t inc)
|
|||
} else {
|
||||
mtime += inc;
|
||||
}
|
||||
for (size_t i = 0; i < procs.size(); i++) {
|
||||
procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, 0);
|
||||
if (mtime >= mtimecmp[i])
|
||||
procs[i]->state.mip->backdoor_write_with_mask(MIP_MTIP, MIP_MTIP);
|
||||
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
hart->state.time->sync(mtime);
|
||||
hart->state.mip->backdoor_write_with_mask(MIP_MTIP, mtime >= mtimecmp[hart_id] ? MIP_MTIP : 0);
|
||||
}
|
||||
}
|
||||
|
|
4
vendor/riscv/riscv-isa-sim/riscv/common.h
vendored
4
vendor/riscv/riscv-isa-sim/riscv/common.h
vendored
|
@ -8,11 +8,15 @@
|
|||
# define unlikely(x) __builtin_expect(x, 0)
|
||||
# define NOINLINE __attribute__ ((noinline))
|
||||
# define NORETURN __attribute__ ((noreturn))
|
||||
# define ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
# define UNUSED __attribute__ ((unused))
|
||||
#else
|
||||
# define likely(x) (x)
|
||||
# define unlikely(x) (x)
|
||||
# define NOINLINE
|
||||
# define NORETURN
|
||||
# define ALWAYS_INLINE
|
||||
# define UNUSED
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
782
vendor/riscv/riscv-isa-sim/riscv/csrs.cc
vendored
782
vendor/riscv/riscv-isa-sim/riscv/csrs.cc
vendored
File diff suppressed because it is too large
Load diff
288
vendor/riscv/riscv-isa-sim/riscv/csrs.h
vendored
288
vendor/riscv/riscv-isa-sim/riscv/csrs.h
vendored
|
@ -2,12 +2,15 @@
|
|||
#ifndef _RISCV_CSRS_H
|
||||
#define _RISCV_CSRS_H
|
||||
|
||||
#include "common.h"
|
||||
#include "encoding.h"
|
||||
// For reg_t:
|
||||
#include "decode.h"
|
||||
// For std::shared_ptr
|
||||
#include <memory>
|
||||
// For access_type:
|
||||
#include "memtracer.h"
|
||||
#include <cassert>
|
||||
|
||||
class processor_t;
|
||||
struct state_t;
|
||||
|
@ -52,23 +55,29 @@ class csr_t {
|
|||
private:
|
||||
const unsigned csr_priv;
|
||||
const bool csr_read_only;
|
||||
|
||||
// For access to written_value() and unlogged_write():
|
||||
friend class rv32_high_csr_t;
|
||||
friend class rv32_low_csr_t;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<csr_t> csr_t_p;
|
||||
|
||||
|
||||
// Basic CSRs, with XLEN bits fully readable and writable.
|
||||
class basic_csr_t: public csr_t {
|
||||
public:
|
||||
basic_csr_t(processor_t* const proc, const reg_t addr, const reg_t init);
|
||||
virtual reg_t read() const noexcept override;
|
||||
|
||||
virtual reg_t read() const noexcept override {
|
||||
return val;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
reg_t val;
|
||||
};
|
||||
|
||||
|
||||
class pmpaddr_csr_t: public csr_t {
|
||||
public:
|
||||
pmpaddr_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -84,6 +93,11 @@ class pmpaddr_csr_t: public csr_t {
|
|||
// Is the specified access allowed given the pmpcfg privileges?
|
||||
bool access_ok(access_type type, reg_t mode) const noexcept;
|
||||
|
||||
// To check lock bit status from outside like mseccfg
|
||||
bool is_locked() const noexcept {
|
||||
return cfg & PMP_L;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
|
@ -112,11 +126,24 @@ typedef std::shared_ptr<pmpaddr_csr_t> pmpaddr_csr_t_p;
|
|||
class pmpcfg_csr_t: public csr_t {
|
||||
public:
|
||||
pmpcfg_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;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
class mseccfg_csr_t: public basic_csr_t {
|
||||
public:
|
||||
mseccfg_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
bool get_mml() const noexcept;
|
||||
bool get_mmwp() const noexcept;
|
||||
bool get_rlb() const noexcept;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<mseccfg_csr_t> mseccfg_csr_t_p;
|
||||
|
||||
// For CSRs that have a virtualized copy under another name. Each
|
||||
// instance of virtualized_csr_t will read/write one of two CSRs,
|
||||
|
@ -153,7 +180,6 @@ class epc_csr_t: public csr_t {
|
|||
reg_t val;
|
||||
};
|
||||
|
||||
|
||||
// For mtvec, stvec, and vstvec
|
||||
class tvec_csr_t: public csr_t {
|
||||
public:
|
||||
|
@ -166,7 +192,6 @@ class tvec_csr_t: public csr_t {
|
|||
reg_t val;
|
||||
};
|
||||
|
||||
|
||||
// For mcause, scause, and vscause
|
||||
class cause_csr_t: public basic_csr_t {
|
||||
public:
|
||||
|
@ -175,13 +200,15 @@ class cause_csr_t: public basic_csr_t {
|
|||
virtual reg_t read() const noexcept override;
|
||||
};
|
||||
|
||||
|
||||
// For *status family of CSRs
|
||||
class base_status_csr_t: public csr_t {
|
||||
public:
|
||||
base_status_csr_t(processor_t* const proc, const reg_t addr);
|
||||
// Return true if the specified bits are not 00 (Off)
|
||||
bool enabled(const reg_t which);
|
||||
|
||||
bool field_exists(const reg_t which) {
|
||||
return (sstatus_write_mask & which) != 0;
|
||||
}
|
||||
|
||||
protected:
|
||||
reg_t adjust_sd(const reg_t val) const noexcept;
|
||||
void maybe_flush_tlb(const reg_t newval) noexcept;
|
||||
|
@ -194,13 +221,16 @@ class base_status_csr_t: public csr_t {
|
|||
|
||||
typedef std::shared_ptr<base_status_csr_t> base_status_csr_t_p;
|
||||
|
||||
|
||||
// For vsstatus, which is its own separate architectural register
|
||||
// (unlike sstatus)
|
||||
class vsstatus_csr_t: public base_status_csr_t {
|
||||
class vsstatus_csr_t final: public base_status_csr_t {
|
||||
public:
|
||||
vsstatus_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
|
||||
reg_t read() const noexcept override {
|
||||
return val;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
|
@ -209,75 +239,107 @@ class vsstatus_csr_t: public base_status_csr_t {
|
|||
|
||||
typedef std::shared_ptr<vsstatus_csr_t> vsstatus_csr_t_p;
|
||||
|
||||
|
||||
class sstatus_proxy_csr_t: public base_status_csr_t {
|
||||
public:
|
||||
sstatus_proxy_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mstatus);
|
||||
virtual reg_t read() const noexcept override;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
csr_t_p mstatus;
|
||||
};
|
||||
|
||||
|
||||
class mstatus_csr_t: public base_status_csr_t {
|
||||
class mstatus_csr_t final: public base_status_csr_t {
|
||||
public:
|
||||
mstatus_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
|
||||
reg_t read() const noexcept override {
|
||||
return val;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
reg_t compute_mstatus_initial_value() const noexcept;
|
||||
reg_t val;
|
||||
friend class mstatush_csr_t;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<mstatus_csr_t> mstatus_csr_t_p;
|
||||
|
||||
|
||||
class mstatush_csr_t: public csr_t {
|
||||
class mnstatus_csr_t final: public basic_csr_t {
|
||||
public:
|
||||
mstatush_csr_t(processor_t* const proc, const reg_t addr, mstatus_csr_t_p mstatus);
|
||||
mnstatus_csr_t(processor_t* const proc, const reg_t addr);
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
// For RV32 CSRs that are split into two, e.g. mstatus/mstatush
|
||||
// CSRW should only modify the lower half
|
||||
class rv32_low_csr_t: public csr_t {
|
||||
public:
|
||||
rv32_low_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
|
||||
virtual 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;
|
||||
virtual reg_t written_value() const noexcept override;
|
||||
private:
|
||||
csr_t_p orig;
|
||||
};
|
||||
|
||||
class rv32_high_csr_t: public csr_t {
|
||||
public:
|
||||
rv32_high_csr_t(processor_t* const proc, const reg_t addr, csr_t_p orig);
|
||||
virtual 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;
|
||||
virtual reg_t written_value() const noexcept override;
|
||||
private:
|
||||
csr_t_p orig;
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
mstatus_csr_t_p mstatus;
|
||||
const reg_t mask;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<sstatus_proxy_csr_t> sstatus_proxy_csr_t_p;
|
||||
|
||||
class sstatus_csr_t: public virtualized_csr_t {
|
||||
public:
|
||||
sstatus_csr_t(processor_t* const proc, base_status_csr_t_p orig, base_status_csr_t_p virt);
|
||||
sstatus_csr_t(processor_t* const proc, sstatus_proxy_csr_t_p orig, vsstatus_csr_t_p virt);
|
||||
|
||||
// Set FS, VS, or XS bits to dirty
|
||||
void dirty(const reg_t dirties);
|
||||
// Return true if the specified bits are not 00 (Off)
|
||||
bool enabled(const reg_t which);
|
||||
private:
|
||||
base_status_csr_t_p orig_sstatus;
|
||||
base_status_csr_t_p virt_sstatus;
|
||||
sstatus_proxy_csr_t_p orig_sstatus;
|
||||
vsstatus_csr_t_p virt_sstatus;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<sstatus_csr_t> sstatus_csr_t_p;
|
||||
|
||||
|
||||
class misa_csr_t: public basic_csr_t {
|
||||
class misa_csr_t final: public basic_csr_t {
|
||||
public:
|
||||
misa_csr_t(processor_t* const proc, const reg_t addr, const reg_t max_isa);
|
||||
bool extension_enabled(unsigned char ext) const noexcept;
|
||||
|
||||
bool extension_enabled(unsigned char ext) const noexcept {
|
||||
assert(ext >= 'A' && ext <= 'Z');
|
||||
return (read() >> (ext - 'A')) & 1;
|
||||
}
|
||||
|
||||
bool extension_enabled_const(unsigned char ext) const noexcept;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
const reg_t max_isa;
|
||||
const reg_t write_mask;
|
||||
reg_t dependency(const reg_t val, const char feature, const char depends_on) const noexcept;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<misa_csr_t> misa_csr_t_p;
|
||||
|
||||
|
||||
class mip_or_mie_csr_t: public csr_t {
|
||||
public:
|
||||
mip_or_mie_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -292,7 +354,6 @@ class mip_or_mie_csr_t: public csr_t {
|
|||
virtual reg_t write_mask() const noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
// mip is special because some of the bits are driven by hardware pins
|
||||
class mip_csr_t: public mip_or_mie_csr_t {
|
||||
public:
|
||||
|
@ -306,7 +367,6 @@ class mip_csr_t: public mip_or_mie_csr_t {
|
|||
|
||||
typedef std::shared_ptr<mip_csr_t> mip_csr_t_p;
|
||||
|
||||
|
||||
class mie_csr_t: public mip_or_mie_csr_t {
|
||||
public:
|
||||
mie_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -316,7 +376,6 @@ class mie_csr_t: public mip_or_mie_csr_t {
|
|||
|
||||
typedef std::shared_ptr<mie_csr_t> mie_csr_t_p;
|
||||
|
||||
|
||||
// For sip, hip, hvip, vsip, sie, hie, vsie which are all just (masked
|
||||
// & shifted) views into mip or mie. Each pair will have one of these
|
||||
// objects describing the view, e.g. one for sip+sie, one for hip+hie,
|
||||
|
@ -348,7 +407,6 @@ class generic_int_accessor_t {
|
|||
|
||||
typedef std::shared_ptr<generic_int_accessor_t> generic_int_accessor_t_p;
|
||||
|
||||
|
||||
// For all CSRs that are simply (masked & shifted) views into mip
|
||||
class mip_proxy_csr_t: public csr_t {
|
||||
public:
|
||||
|
@ -371,8 +429,6 @@ class mie_proxy_csr_t: public csr_t {
|
|||
generic_int_accessor_t_p accr;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class mideleg_csr_t: public basic_csr_t {
|
||||
public:
|
||||
mideleg_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -382,7 +438,6 @@ class mideleg_csr_t: public basic_csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
|
||||
class medeleg_csr_t: public basic_csr_t {
|
||||
public:
|
||||
medeleg_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -393,7 +448,6 @@ class medeleg_csr_t: public basic_csr_t {
|
|||
const reg_t hypervisor_exceptions;
|
||||
};
|
||||
|
||||
|
||||
// For CSRs with certain bits hardwired
|
||||
class masked_csr_t: public basic_csr_t {
|
||||
public:
|
||||
|
@ -404,6 +458,22 @@ class masked_csr_t: public basic_csr_t {
|
|||
const reg_t mask;
|
||||
};
|
||||
|
||||
// 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
|
||||
class henvcfg_csr_t final: public masked_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_HADE)) & masked_csr_t::read();
|
||||
}
|
||||
|
||||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
|
||||
private:
|
||||
csr_t_p menvcfg;
|
||||
};
|
||||
|
||||
// For satp and vsatp
|
||||
// These are three classes in order to handle the [V]TVM bits permission checks
|
||||
|
@ -435,17 +505,15 @@ class virtualized_satp_csr_t: public virtualized_csr_t {
|
|||
satp_csr_t_p orig_satp;
|
||||
};
|
||||
|
||||
|
||||
// For minstret, which is always 64 bits, but in RV32 is split into
|
||||
// high and low halves. The first class always holds the full 64-bit
|
||||
// value.
|
||||
class minstret_csr_t: public csr_t {
|
||||
// For minstret and mcycle, which are always 64 bits, but in RV32 are
|
||||
// split into high and low halves. The first class always holds the
|
||||
// full 64-bit value.
|
||||
class wide_counter_csr_t: public csr_t {
|
||||
public:
|
||||
minstret_csr_t(processor_t* const proc, const reg_t addr);
|
||||
wide_counter_csr_t(processor_t* const proc, const reg_t addr);
|
||||
// Always returns full 64-bit value
|
||||
virtual reg_t read() const noexcept override;
|
||||
void bump(const reg_t howmuch) noexcept;
|
||||
void write_upper_half(const reg_t val) noexcept;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
virtual reg_t written_value() const noexcept override;
|
||||
|
@ -453,22 +521,22 @@ class minstret_csr_t: public csr_t {
|
|||
reg_t val;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<minstret_csr_t> minstret_csr_t_p;
|
||||
typedef std::shared_ptr<wide_counter_csr_t> wide_counter_csr_t_p;
|
||||
|
||||
|
||||
// A simple proxy to read/write the upper half of minstret
|
||||
class minstreth_csr_t: public csr_t {
|
||||
class time_counter_csr_t: public csr_t {
|
||||
public:
|
||||
minstreth_csr_t(processor_t* const proc, const reg_t addr, minstret_csr_t_p minstret);
|
||||
time_counter_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
|
||||
void sync(const reg_t val) noexcept;
|
||||
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
virtual bool unlogged_write(const reg_t UNUSED val) noexcept override { return false; };
|
||||
private:
|
||||
minstret_csr_t_p minstret;
|
||||
reg_t shadow_val;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<minstreth_csr_t> minstreth_csr_t_p;
|
||||
|
||||
typedef std::shared_ptr<time_counter_csr_t> time_counter_csr_t_p;
|
||||
|
||||
// For a CSR that is an alias of another
|
||||
class proxy_csr_t: public csr_t {
|
||||
|
@ -481,7 +549,6 @@ class proxy_csr_t: public csr_t {
|
|||
csr_t_p delegate;
|
||||
};
|
||||
|
||||
|
||||
// For a CSR with a fixed, unchanging value
|
||||
class const_csr_t: public csr_t {
|
||||
public:
|
||||
|
@ -493,7 +560,6 @@ class const_csr_t: public csr_t {
|
|||
const reg_t val;
|
||||
};
|
||||
|
||||
|
||||
// For a CSR that is an unprivileged accessor of a privileged counter
|
||||
class counter_proxy_csr_t: public proxy_csr_t {
|
||||
public:
|
||||
|
@ -503,6 +569,12 @@ class counter_proxy_csr_t: public proxy_csr_t {
|
|||
bool myenable(csr_t_p counteren) const noexcept;
|
||||
};
|
||||
|
||||
class mevent_csr_t: public basic_csr_t {
|
||||
public:
|
||||
mevent_csr_t(processor_t* const proc, const reg_t addr);
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
// For machine-level CSRs that only exist with Hypervisor
|
||||
class hypervisor_csr_t: public basic_csr_t {
|
||||
|
@ -511,7 +583,6 @@ class hypervisor_csr_t: public basic_csr_t {
|
|||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
};
|
||||
|
||||
|
||||
class hideleg_csr_t: public masked_csr_t {
|
||||
public:
|
||||
hideleg_csr_t(processor_t* const proc, const reg_t addr, csr_t_p mideleg);
|
||||
|
@ -520,7 +591,6 @@ class hideleg_csr_t: public masked_csr_t {
|
|||
csr_t_p mideleg;
|
||||
};
|
||||
|
||||
|
||||
class hgatp_csr_t: public basic_csr_t {
|
||||
public:
|
||||
hgatp_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -529,7 +599,6 @@ class hgatp_csr_t: public basic_csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
|
||||
class tselect_csr_t: public basic_csr_t {
|
||||
public:
|
||||
tselect_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -537,7 +606,6 @@ class tselect_csr_t: public basic_csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
|
||||
class tdata1_csr_t: public csr_t {
|
||||
public:
|
||||
tdata1_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -548,13 +616,26 @@ class tdata1_csr_t: public csr_t {
|
|||
|
||||
class tdata2_csr_t: public csr_t {
|
||||
public:
|
||||
tdata2_csr_t(processor_t* const proc, const reg_t addr, const size_t count);
|
||||
tdata2_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
reg_t read(const size_t idx) const noexcept;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
std::vector<reg_t> vals;
|
||||
};
|
||||
|
||||
class tdata3_csr_t: public csr_t {
|
||||
public:
|
||||
tdata3_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
class tinfo_csr_t: public csr_t {
|
||||
public:
|
||||
tinfo_csr_t(processor_t* const proc, const reg_t addr);
|
||||
virtual reg_t read() const noexcept override;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t UNUSED val) noexcept override { return false; };
|
||||
};
|
||||
|
||||
// For CSRs that are only writable from debug mode
|
||||
|
@ -564,9 +645,6 @@ class debug_mode_csr_t: public basic_csr_t {
|
|||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<tdata2_csr_t> tdata2_csr_t_p;
|
||||
|
||||
|
||||
class dpc_csr_t: public epc_csr_t {
|
||||
public:
|
||||
dpc_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -594,8 +672,7 @@ class dcsr_csr_t: public csr_t {
|
|||
|
||||
typedef std::shared_ptr<dcsr_csr_t> dcsr_csr_t_p;
|
||||
|
||||
|
||||
class float_csr_t: public masked_csr_t {
|
||||
class float_csr_t final: public masked_csr_t {
|
||||
public:
|
||||
float_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;
|
||||
|
@ -603,6 +680,7 @@ class float_csr_t: public masked_csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<float_csr_t> float_csr_t_p;
|
||||
|
||||
// For a CSR like FCSR, that is actually a view into multiple
|
||||
// underlying registers.
|
||||
|
@ -620,7 +698,6 @@ class composite_csr_t: public csr_t {
|
|||
const unsigned upper_lsb;
|
||||
};
|
||||
|
||||
|
||||
class seed_csr_t: public csr_t {
|
||||
public:
|
||||
seed_csr_t(processor_t* const proc, const reg_t addr);
|
||||
|
@ -630,7 +707,6 @@ class seed_csr_t: public csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
|
||||
class vector_csr_t: public basic_csr_t {
|
||||
public:
|
||||
vector_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init=0);
|
||||
|
@ -645,7 +721,6 @@ class vector_csr_t: public basic_csr_t {
|
|||
|
||||
typedef std::shared_ptr<vector_csr_t> vector_csr_t_p;
|
||||
|
||||
|
||||
// For CSRs shared between Vector and P extensions (vxsat)
|
||||
class vxsat_csr_t: public masked_csr_t {
|
||||
public:
|
||||
|
@ -655,4 +730,59 @@ class vxsat_csr_t: public masked_csr_t {
|
|||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
class hstateen_csr_t: public masked_csr_t {
|
||||
public:
|
||||
hstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, uint8_t index);
|
||||
virtual 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;
|
||||
protected:
|
||||
uint8_t index;
|
||||
};
|
||||
|
||||
class sstateen_csr_t: public hstateen_csr_t {
|
||||
public:
|
||||
sstateen_csr_t(processor_t* const proc, const reg_t addr, const reg_t mask, const reg_t init, uint8_t index);
|
||||
virtual 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 senvcfg_csr_t final: public masked_csr_t {
|
||||
public:
|
||||
senvcfg_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;
|
||||
};
|
||||
|
||||
class stimecmp_csr_t: public basic_csr_t {
|
||||
public:
|
||||
stimecmp_csr_t(processor_t* const proc, const reg_t addr, const reg_t imask);
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
private:
|
||||
reg_t intr_mask;
|
||||
};
|
||||
|
||||
class virtualized_stimecmp_csr_t: public virtualized_csr_t {
|
||||
public:
|
||||
virtualized_stimecmp_csr_t(processor_t* const proc, csr_t_p orig, csr_t_p virt);
|
||||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
};
|
||||
|
||||
class scountovf_csr_t: public csr_t {
|
||||
public:
|
||||
scountovf_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;
|
||||
protected:
|
||||
virtual bool unlogged_write(const reg_t val) noexcept override;
|
||||
};
|
||||
|
||||
class jvt_csr_t: public basic_csr_t {
|
||||
public:
|
||||
jvt_csr_t(processor_t* const proc, const reg_t addr, const reg_t init);
|
||||
virtual void verify_permissions(insn_t insn, bool write) const override;
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
//
|
||||
// Original Author: Zbigniew CHAMSKI <zbigniew.chamski@thalesgroup.com>
|
||||
|
||||
#define DECODE_MACRO_USAGE_LOGGED 1
|
||||
#include "decode_macros.h"
|
||||
#include "cvxif.h"
|
||||
#include "trap.h"
|
||||
#include <cstdlib>
|
||||
|
|
4189
vendor/riscv/riscv-isa-sim/riscv/debug_defines.h
vendored
4189
vendor/riscv/riscv-isa-sim/riscv/debug_defines.h
vendored
File diff suppressed because it is too large
Load diff
418
vendor/riscv/riscv-isa-sim/riscv/debug_module.cc
vendored
418
vendor/riscv/riscv-isa-sim/riscv/debug_module.cc
vendored
|
@ -1,6 +1,7 @@
|
|||
#include <cassert>
|
||||
|
||||
#include "sim.h"
|
||||
#include "simif.h"
|
||||
#include "devices.h"
|
||||
#include "debug_module.h"
|
||||
#include "debug_defines.h"
|
||||
#include "opcodes.h"
|
||||
|
@ -31,26 +32,29 @@ static unsigned field_width(unsigned n)
|
|||
|
||||
///////////////////////// debug_module_t
|
||||
|
||||
debug_module_t::debug_module_t(sim_t *sim, const debug_module_config_t &config) :
|
||||
nprocs(sim->nprocs()),
|
||||
debug_module_t::debug_module_t(simif_t *sim, const debug_module_config_t &config) :
|
||||
config(config),
|
||||
program_buffer_bytes((config.support_impebreak ? 4 : 0) + 4*config.progbufsize),
|
||||
debug_progbuf_start(debug_data_start - program_buffer_bytes),
|
||||
debug_abstract_start(debug_progbuf_start - debug_abstract_size*4),
|
||||
custom_base(0),
|
||||
hartsellen(field_width(sim->nprocs())),
|
||||
sim(sim),
|
||||
// The spec lets a debugger select nonexistent harts. Create hart_state for
|
||||
// them because I'm too lazy to add the code to just ignore accesses.
|
||||
hart_state(1 << field_width(sim->nprocs())),
|
||||
hart_array_mask(sim->nprocs()),
|
||||
hart_state(1 << field_width(sim->get_cfg().max_hartid() + 1)),
|
||||
hart_array_mask(sim->get_cfg().max_hartid() + 1),
|
||||
rti_remaining(0)
|
||||
{
|
||||
D(fprintf(stderr, "debug_data_start=0x%x\n", debug_data_start));
|
||||
D(fprintf(stderr, "debug_progbuf_start=0x%x\n", debug_progbuf_start));
|
||||
D(fprintf(stderr, "debug_abstract_start=0x%x\n", debug_abstract_start));
|
||||
|
||||
assert(nprocs <= 1024);
|
||||
const unsigned max_procs = 1024;
|
||||
if (sim->get_cfg().max_hartid() >= max_procs) {
|
||||
fprintf(stderr, "Hart IDs must not exceed %u (%zu harts with max hart ID %zu requested)\n",
|
||||
max_procs - 1, sim->get_cfg().nprocs(), sim->get_cfg().max_hartid());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
program_buffer = new uint8_t[program_buffer_bytes];
|
||||
|
||||
|
@ -80,11 +84,8 @@ debug_module_t::~debug_module_t()
|
|||
|
||||
void debug_module_t::reset()
|
||||
{
|
||||
assert(sim->nprocs() > 0);
|
||||
for (unsigned i = 0; i < sim->nprocs(); i++) {
|
||||
processor_t *proc = sim->get_core(i);
|
||||
if (proc)
|
||||
proc->halt_request = proc->HR_NONE;
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
hart->halt_request = hart->HR_NONE;
|
||||
}
|
||||
|
||||
memset(&dmcontrol, 0, sizeof(dmcontrol));
|
||||
|
@ -165,18 +166,18 @@ bool debug_module_t::load(reg_t addr, size_t len, uint8_t* bytes)
|
|||
bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
|
||||
{
|
||||
D(
|
||||
switch (len) {
|
||||
case 4:
|
||||
fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
|
||||
"hartsel=0x%x\n", addr, (unsigned) len, *(uint32_t *) bytes,
|
||||
dmcontrol.hartsel);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=...); "
|
||||
"hartsel=0x%x\n", addr, (unsigned) len, dmcontrol.hartsel);
|
||||
break;
|
||||
}
|
||||
);
|
||||
switch (len) {
|
||||
case 4:
|
||||
fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=0x%08x); "
|
||||
"hartsel=0x%x\n", addr, (unsigned) len, *(uint32_t *) bytes,
|
||||
dmcontrol.hartsel);
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "store(addr=0x%lx, len=%d, bytes=...); "
|
||||
"hartsel=0x%x\n", addr, (unsigned) len, dmcontrol.hartsel);
|
||||
break;
|
||||
}
|
||||
);
|
||||
|
||||
uint8_t id_bytes[4];
|
||||
uint32_t id = 0;
|
||||
|
@ -203,23 +204,20 @@ bool debug_module_t::store(reg_t addr, size_t len, const uint8_t* bytes)
|
|||
if (!hart_state[id].halted) {
|
||||
hart_state[id].halted = true;
|
||||
if (hart_state[id].haltgroup) {
|
||||
for (unsigned i = 0; i < nprocs; i++) {
|
||||
if (!hart_state[i].halted &&
|
||||
hart_state[i].haltgroup == hart_state[id].haltgroup) {
|
||||
processor_t *proc = sim->get_core(i);
|
||||
proc->halt_request = proc->HR_GROUP;
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
if (!hart_state[hart_id].halted &&
|
||||
hart_state[hart_id].haltgroup == hart_state[id].haltgroup) {
|
||||
hart->halt_request = hart->HR_GROUP;
|
||||
// TODO: What if the debugger comes and writes dmcontrol before the
|
||||
// halt occurs?
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dmcontrol.hartsel == id) {
|
||||
if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))){
|
||||
if (dmcontrol.hartsel == id) {
|
||||
abstract_command_completed = true;
|
||||
}
|
||||
}
|
||||
if (selected_hart_id() == id) {
|
||||
if (0 == (debug_rom_flags[id] & (1 << DEBUG_ROM_FLAG_GO))) {
|
||||
abstract_command_completed = true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -269,23 +267,9 @@ uint32_t debug_module_t::read32(uint8_t *memory, unsigned int index)
|
|||
return value;
|
||||
}
|
||||
|
||||
processor_t *debug_module_t::processor(unsigned hartid) const
|
||||
{
|
||||
processor_t *proc = NULL;
|
||||
try {
|
||||
proc = sim->get_core(hartid);
|
||||
} catch (const std::out_of_range&) {
|
||||
}
|
||||
return proc;
|
||||
}
|
||||
|
||||
bool debug_module_t::hart_selected(unsigned hartid) const
|
||||
{
|
||||
if (dmcontrol.hasel) {
|
||||
return hartid == dmcontrol.hartsel || hart_array_mask[hartid];
|
||||
} else {
|
||||
return hartid == dmcontrol.hartsel;
|
||||
}
|
||||
return hartid == selected_hart_id() || (dmcontrol.hasel && hart_array_mask[hartid]);
|
||||
}
|
||||
|
||||
unsigned debug_module_t::sb_access_bits()
|
||||
|
@ -318,13 +302,13 @@ void debug_module_t::sb_read()
|
|||
reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
|
||||
try {
|
||||
if (sbcs.sbaccess == 0 && config.max_sba_data_width >= 8) {
|
||||
sbdata[0] = sim->debug_mmu->load_uint8(address);
|
||||
sbdata[0] = sim->debug_mmu->load<uint8_t>(address);
|
||||
} else if (sbcs.sbaccess == 1 && config.max_sba_data_width >= 16) {
|
||||
sbdata[0] = sim->debug_mmu->load_uint16(address);
|
||||
sbdata[0] = sim->debug_mmu->load<uint16_t>(address);
|
||||
} else if (sbcs.sbaccess == 2 && config.max_sba_data_width >= 32) {
|
||||
sbdata[0] = sim->debug_mmu->load_uint32(address);
|
||||
sbdata[0] = sim->debug_mmu->load<uint32_t>(address);
|
||||
} else if (sbcs.sbaccess == 3 && config.max_sba_data_width >= 64) {
|
||||
uint64_t value = sim->debug_mmu->load_uint64(address);
|
||||
uint64_t value = sim->debug_mmu->load<uint64_t>(address);
|
||||
sbdata[0] = value;
|
||||
sbdata[1] = value >> 32;
|
||||
} else {
|
||||
|
@ -340,13 +324,13 @@ void debug_module_t::sb_write()
|
|||
reg_t address = ((uint64_t) sbaddress[1] << 32) | sbaddress[0];
|
||||
D(fprintf(stderr, "sb_write() 0x%x @ 0x%lx\n", sbdata[0], address));
|
||||
if (sbcs.sbaccess == 0 && config.max_sba_data_width >= 8) {
|
||||
sim->debug_mmu->store_uint8(address, sbdata[0]);
|
||||
sim->debug_mmu->store<uint8_t>(address, sbdata[0]);
|
||||
} else if (sbcs.sbaccess == 1 && config.max_sba_data_width >= 16) {
|
||||
sim->debug_mmu->store_uint16(address, sbdata[0]);
|
||||
sim->debug_mmu->store<uint16_t>(address, sbdata[0]);
|
||||
} else if (sbcs.sbaccess == 2 && config.max_sba_data_width >= 32) {
|
||||
sim->debug_mmu->store_uint32(address, sbdata[0]);
|
||||
sim->debug_mmu->store<uint32_t>(address, sbdata[0]);
|
||||
} else if (sbcs.sbaccess == 3 && config.max_sba_data_width >= 64) {
|
||||
sim->debug_mmu->store_uint64(address,
|
||||
sim->debug_mmu->store<uint64_t>(address,
|
||||
(((uint64_t) sbdata[1]) << 32) | sbdata[0]);
|
||||
} else {
|
||||
sbcs.error = 3;
|
||||
|
@ -357,8 +341,8 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
|
|||
{
|
||||
uint32_t result = 0;
|
||||
D(fprintf(stderr, "dmi_read(0x%x) -> ", address));
|
||||
if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
|
||||
unsigned i = address - DMI_DATA0;
|
||||
if (address >= DM_DATA0 && address < DM_DATA0 + abstractcs.datacount) {
|
||||
unsigned i = address - DM_DATA0;
|
||||
result = read32(dmdata, i);
|
||||
if (abstractcs.busy) {
|
||||
result = -1;
|
||||
|
@ -372,8 +356,8 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
|
|||
if (!abstractcs.busy && ((abstractauto.autoexecdata >> i) & 1)) {
|
||||
perform_abstract_command();
|
||||
}
|
||||
} else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + config.progbufsize) {
|
||||
unsigned i = address - DMI_PROGBUF0;
|
||||
} else if (address >= DM_PROGBUF0 && address < DM_PROGBUF0 + config.progbufsize) {
|
||||
unsigned i = address - DM_PROGBUF0;
|
||||
result = read32(program_buffer, i);
|
||||
if (abstractcs.busy) {
|
||||
result = -1;
|
||||
|
@ -385,37 +369,37 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
|
|||
|
||||
} else {
|
||||
switch (address) {
|
||||
case DMI_DMCONTROL:
|
||||
case DM_DMCONTROL:
|
||||
{
|
||||
result = set_field(result, DMI_DMCONTROL_HALTREQ, dmcontrol.haltreq);
|
||||
result = set_field(result, DMI_DMCONTROL_RESUMEREQ, dmcontrol.resumereq);
|
||||
result = set_field(result, DMI_DMCONTROL_HARTSELHI,
|
||||
dmcontrol.hartsel >> DMI_DMCONTROL_HARTSELLO_LENGTH);
|
||||
result = set_field(result, DMI_DMCONTROL_HASEL, dmcontrol.hasel);
|
||||
result = set_field(result, DMI_DMCONTROL_HARTSELLO, dmcontrol.hartsel);
|
||||
result = set_field(result, DMI_DMCONTROL_HARTRESET, dmcontrol.hartreset);
|
||||
result = set_field(result, DMI_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
|
||||
result = set_field(result, DMI_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
|
||||
result = set_field(result, DM_DMCONTROL_HALTREQ, dmcontrol.haltreq);
|
||||
result = set_field(result, DM_DMCONTROL_RESUMEREQ, dmcontrol.resumereq);
|
||||
result = set_field(result, DM_DMCONTROL_HARTSELHI,
|
||||
dmcontrol.hartsel >> DM_DMCONTROL_HARTSELLO_LENGTH);
|
||||
result = set_field(result, DM_DMCONTROL_HASEL, dmcontrol.hasel);
|
||||
result = set_field(result, DM_DMCONTROL_HARTSELLO, dmcontrol.hartsel);
|
||||
result = set_field(result, DM_DMCONTROL_HARTRESET, dmcontrol.hartreset);
|
||||
result = set_field(result, DM_DMCONTROL_NDMRESET, dmcontrol.ndmreset);
|
||||
result = set_field(result, DM_DMCONTROL_DMACTIVE, dmcontrol.dmactive);
|
||||
}
|
||||
break;
|
||||
case DMI_DMSTATUS:
|
||||
case DM_DMSTATUS:
|
||||
{
|
||||
dmstatus.allhalted = true;
|
||||
dmstatus.allhalted = true;
|
||||
dmstatus.anyhalted = false;
|
||||
dmstatus.allrunning = true;
|
||||
dmstatus.allrunning = true;
|
||||
dmstatus.anyrunning = false;
|
||||
dmstatus.allnonexistant = true;
|
||||
dmstatus.allresumeack = true;
|
||||
dmstatus.anyresumeack = false;
|
||||
for (unsigned i = 0; i < nprocs; i++) {
|
||||
if (hart_selected(i)) {
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
if (hart_selected(hart_id)) {
|
||||
dmstatus.allnonexistant = false;
|
||||
if (hart_state[i].resumeack) {
|
||||
if (hart_state[hart_id].resumeack) {
|
||||
dmstatus.anyresumeack = true;
|
||||
} else {
|
||||
dmstatus.allresumeack = false;
|
||||
}
|
||||
if (hart_state[i].halted) {
|
||||
if (hart_state[hart_id].halted) {
|
||||
dmstatus.allrunning = false;
|
||||
dmstatus.anyhalted = true;
|
||||
} else {
|
||||
|
@ -428,93 +412,91 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
|
|||
// We don't allow selecting non-existant harts through
|
||||
// hart_array_mask, so the only way it's possible is by writing a
|
||||
// non-existant hartsel.
|
||||
dmstatus.anynonexistant = (dmcontrol.hartsel >= nprocs);
|
||||
dmstatus.anynonexistant = dmcontrol.hartsel >= sim->get_cfg().nprocs();
|
||||
|
||||
dmstatus.allunavail = false;
|
||||
dmstatus.anyunavail = false;
|
||||
dmstatus.allunavail = false;
|
||||
dmstatus.anyunavail = false;
|
||||
|
||||
result = set_field(result, DMI_DMSTATUS_IMPEBREAK,
|
||||
result = set_field(result, DM_DMSTATUS_IMPEBREAK,
|
||||
dmstatus.impebreak);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLHAVERESET,
|
||||
hart_state[dmcontrol.hartsel].havereset);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYHAVERESET,
|
||||
hart_state[dmcontrol.hartsel].havereset);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLHALTED, dmstatus.allhalted);
|
||||
result = set_field(result, DMI_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
|
||||
result = set_field(result, DMI_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
|
||||
result = set_field(result, DMI_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
|
||||
result = set_field(result, DMI_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
|
||||
result = set_field(result, DMI_DMSTATUS_VERSION, dmstatus.version);
|
||||
result = set_field(result, DM_DMSTATUS_ALLHAVERESET, selected_hart_state().havereset);
|
||||
result = set_field(result, DM_DMSTATUS_ANYHAVERESET, selected_hart_state().havereset);
|
||||
result = set_field(result, DM_DMSTATUS_ALLNONEXISTENT, dmstatus.allnonexistant);
|
||||
result = set_field(result, DM_DMSTATUS_ALLUNAVAIL, dmstatus.allunavail);
|
||||
result = set_field(result, DM_DMSTATUS_ALLRUNNING, dmstatus.allrunning);
|
||||
result = set_field(result, DM_DMSTATUS_ALLHALTED, dmstatus.allhalted);
|
||||
result = set_field(result, DM_DMSTATUS_ALLRESUMEACK, dmstatus.allresumeack);
|
||||
result = set_field(result, DM_DMSTATUS_ANYNONEXISTENT, dmstatus.anynonexistant);
|
||||
result = set_field(result, DM_DMSTATUS_ANYUNAVAIL, dmstatus.anyunavail);
|
||||
result = set_field(result, DM_DMSTATUS_ANYRUNNING, dmstatus.anyrunning);
|
||||
result = set_field(result, DM_DMSTATUS_ANYHALTED, dmstatus.anyhalted);
|
||||
result = set_field(result, DM_DMSTATUS_ANYRESUMEACK, dmstatus.anyresumeack);
|
||||
result = set_field(result, DM_DMSTATUS_AUTHENTICATED, dmstatus.authenticated);
|
||||
result = set_field(result, DM_DMSTATUS_AUTHBUSY, dmstatus.authbusy);
|
||||
result = set_field(result, DM_DMSTATUS_VERSION, dmstatus.version);
|
||||
}
|
||||
break;
|
||||
case DMI_ABSTRACTCS:
|
||||
result = set_field(result, DMI_ABSTRACTCS_CMDERR, abstractcs.cmderr);
|
||||
result = set_field(result, DMI_ABSTRACTCS_BUSY, abstractcs.busy);
|
||||
result = set_field(result, DMI_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
|
||||
result = set_field(result, DMI_ABSTRACTCS_PROGBUFSIZE,
|
||||
case DM_ABSTRACTCS:
|
||||
result = set_field(result, DM_ABSTRACTCS_CMDERR, abstractcs.cmderr);
|
||||
result = set_field(result, DM_ABSTRACTCS_BUSY, abstractcs.busy);
|
||||
result = set_field(result, DM_ABSTRACTCS_DATACOUNT, abstractcs.datacount);
|
||||
result = set_field(result, DM_ABSTRACTCS_PROGBUFSIZE,
|
||||
abstractcs.progbufsize);
|
||||
break;
|
||||
case DMI_ABSTRACTAUTO:
|
||||
result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
|
||||
result = set_field(result, DMI_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
|
||||
case DM_ABSTRACTAUTO:
|
||||
result = set_field(result, DM_ABSTRACTAUTO_AUTOEXECPROGBUF, abstractauto.autoexecprogbuf);
|
||||
result = set_field(result, DM_ABSTRACTAUTO_AUTOEXECDATA, abstractauto.autoexecdata);
|
||||
break;
|
||||
case DMI_COMMAND:
|
||||
case DM_COMMAND:
|
||||
result = 0;
|
||||
break;
|
||||
case DMI_HARTINFO:
|
||||
result = set_field(result, DMI_HARTINFO_NSCRATCH, 1);
|
||||
result = set_field(result, DMI_HARTINFO_DATAACCESS, 1);
|
||||
result = set_field(result, DMI_HARTINFO_DATASIZE, abstractcs.datacount);
|
||||
result = set_field(result, DMI_HARTINFO_DATAADDR, debug_data_start);
|
||||
case DM_HARTINFO:
|
||||
result = set_field(result, DM_HARTINFO_NSCRATCH, 1);
|
||||
result = set_field(result, DM_HARTINFO_DATAACCESS, 1);
|
||||
result = set_field(result, DM_HARTINFO_DATASIZE, abstractcs.datacount);
|
||||
result = set_field(result, DM_HARTINFO_DATAADDR, debug_data_start);
|
||||
break;
|
||||
case DMI_HAWINDOWSEL:
|
||||
case DM_HAWINDOWSEL:
|
||||
result = hawindowsel;
|
||||
break;
|
||||
case DMI_HAWINDOW:
|
||||
case DM_HAWINDOW:
|
||||
{
|
||||
unsigned base = hawindowsel * 32;
|
||||
for (unsigned i = 0; i < 32; i++) {
|
||||
unsigned n = base + i;
|
||||
if (n < nprocs && hart_array_mask[n]) {
|
||||
if (n < sim->get_cfg().nprocs() && hart_array_mask[sim->get_cfg().hartids()[n]]) {
|
||||
result |= 1 << i;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case DMI_SBCS:
|
||||
result = set_field(result, DMI_SBCS_SBVERSION, sbcs.version);
|
||||
result = set_field(result, DMI_SBCS_SBREADONADDR, sbcs.readonaddr);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS, sbcs.sbaccess);
|
||||
result = set_field(result, DMI_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
|
||||
result = set_field(result, DMI_SBCS_SBREADONDATA, sbcs.readondata);
|
||||
result = set_field(result, DMI_SBCS_SBERROR, sbcs.error);
|
||||
result = set_field(result, DMI_SBCS_SBASIZE, sbcs.asize);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS128, sbcs.access128);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS64, sbcs.access64);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS32, sbcs.access32);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS16, sbcs.access16);
|
||||
result = set_field(result, DMI_SBCS_SBACCESS8, sbcs.access8);
|
||||
case DM_SBCS:
|
||||
result = set_field(result, DM_SBCS_SBVERSION, sbcs.version);
|
||||
result = set_field(result, DM_SBCS_SBREADONADDR, sbcs.readonaddr);
|
||||
result = set_field(result, DM_SBCS_SBACCESS, sbcs.sbaccess);
|
||||
result = set_field(result, DM_SBCS_SBAUTOINCREMENT, sbcs.autoincrement);
|
||||
result = set_field(result, DM_SBCS_SBREADONDATA, sbcs.readondata);
|
||||
result = set_field(result, DM_SBCS_SBERROR, sbcs.error);
|
||||
result = set_field(result, DM_SBCS_SBASIZE, sbcs.asize);
|
||||
result = set_field(result, DM_SBCS_SBACCESS128, sbcs.access128);
|
||||
result = set_field(result, DM_SBCS_SBACCESS64, sbcs.access64);
|
||||
result = set_field(result, DM_SBCS_SBACCESS32, sbcs.access32);
|
||||
result = set_field(result, DM_SBCS_SBACCESS16, sbcs.access16);
|
||||
result = set_field(result, DM_SBCS_SBACCESS8, sbcs.access8);
|
||||
break;
|
||||
case DMI_SBADDRESS0:
|
||||
case DM_SBADDRESS0:
|
||||
result = sbaddress[0];
|
||||
break;
|
||||
case DMI_SBADDRESS1:
|
||||
case DM_SBADDRESS1:
|
||||
result = sbaddress[1];
|
||||
break;
|
||||
case DMI_SBADDRESS2:
|
||||
case DM_SBADDRESS2:
|
||||
result = sbaddress[2];
|
||||
break;
|
||||
case DMI_SBADDRESS3:
|
||||
case DM_SBADDRESS3:
|
||||
result = sbaddress[3];
|
||||
break;
|
||||
case DMI_SBDATA0:
|
||||
case DM_SBDATA0:
|
||||
result = sbdata[0];
|
||||
if (sbcs.error == 0) {
|
||||
if (sbcs.readondata) {
|
||||
|
@ -525,21 +507,20 @@ bool debug_module_t::dmi_read(unsigned address, uint32_t *value)
|
|||
}
|
||||
}
|
||||
break;
|
||||
case DMI_SBDATA1:
|
||||
case DM_SBDATA1:
|
||||
result = sbdata[1];
|
||||
break;
|
||||
case DMI_SBDATA2:
|
||||
case DM_SBDATA2:
|
||||
result = sbdata[2];
|
||||
break;
|
||||
case DMI_SBDATA3:
|
||||
case DM_SBDATA3:
|
||||
result = sbdata[3];
|
||||
break;
|
||||
case DMI_AUTHDATA:
|
||||
case DM_AUTHDATA:
|
||||
result = challenge;
|
||||
break;
|
||||
case DMI_DMCS2:
|
||||
result = set_field(result, DMI_DMCS2_HALTGROUP,
|
||||
hart_state[dmcontrol.hartsel].haltgroup);
|
||||
case DM_DMCS2:
|
||||
result = set_field(result, DM_DMCS2_GROUP, selected_hart_state().haltgroup);
|
||||
break;
|
||||
default:
|
||||
result = 0;
|
||||
|
@ -583,7 +564,7 @@ bool debug_module_t::perform_abstract_command()
|
|||
bool write = get_field(command, AC_ACCESS_REGISTER_WRITE);
|
||||
unsigned regno = get_field(command, AC_ACCESS_REGISTER_REGNO);
|
||||
|
||||
if (!hart_state[dmcontrol.hartsel].halted) {
|
||||
if (!selected_hart_state().halted) {
|
||||
abstractcs.cmderr = CMDERR_HALTRESUME;
|
||||
return true;
|
||||
}
|
||||
|
@ -672,7 +653,7 @@ bool debug_module_t::perform_abstract_command()
|
|||
write32(debug_abstract, i++, csrw(S0, CSR_DSCRATCH0));
|
||||
}
|
||||
|
||||
} else if (regno >= 0x1020 && regno < 0x1040) {
|
||||
} else if (regno >= 0x1020 && regno < 0x1040 && config.support_abstract_fpr_access) {
|
||||
unsigned fprnum = regno - 0x1020;
|
||||
|
||||
if (write) {
|
||||
|
@ -738,7 +719,7 @@ bool debug_module_t::perform_abstract_command()
|
|||
write32(debug_abstract, i++, ebreak());
|
||||
}
|
||||
|
||||
debug_rom_flags[dmcontrol.hartsel] |= 1 << DEBUG_ROM_FLAG_GO;
|
||||
debug_rom_flags[selected_hart_id()] |= 1 << DEBUG_ROM_FLAG_GO;
|
||||
rti_remaining = config.abstract_rti;
|
||||
abstract_command_completed = false;
|
||||
|
||||
|
@ -753,14 +734,14 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
|
|||
{
|
||||
D(fprintf(stderr, "dmi_write(0x%x, 0x%x)\n", address, value));
|
||||
|
||||
if (!dmstatus.authenticated && address != DMI_AUTHDATA &&
|
||||
address != DMI_DMCONTROL)
|
||||
if (!dmstatus.authenticated && address != DM_AUTHDATA &&
|
||||
address != DM_DMCONTROL)
|
||||
return false;
|
||||
|
||||
if (address >= DMI_DATA0 && address < DMI_DATA0 + abstractcs.datacount) {
|
||||
unsigned i = address - DMI_DATA0;
|
||||
if (address >= DM_DATA0 && address < DM_DATA0 + abstractcs.datacount) {
|
||||
unsigned i = address - DM_DATA0;
|
||||
if (!abstractcs.busy)
|
||||
write32(dmdata, address - DMI_DATA0, value);
|
||||
write32(dmdata, address - DM_DATA0, value);
|
||||
|
||||
if (abstractcs.busy && abstractcs.cmderr == CMDERR_NONE) {
|
||||
abstractcs.cmderr = CMDERR_BUSY;
|
||||
|
@ -771,8 +752,8 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
|
|||
}
|
||||
return true;
|
||||
|
||||
} else if (address >= DMI_PROGBUF0 && address < DMI_PROGBUF0 + config.progbufsize) {
|
||||
unsigned i = address - DMI_PROGBUF0;
|
||||
} else if (address >= DM_PROGBUF0 && address < DM_PROGBUF0 + config.progbufsize) {
|
||||
unsigned i = address - DM_PROGBUF0;
|
||||
|
||||
if (!abstractcs.busy)
|
||||
write32(program_buffer, i, value);
|
||||
|
@ -784,112 +765,108 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
|
|||
|
||||
} else {
|
||||
switch (address) {
|
||||
case DMI_DMCONTROL:
|
||||
case DM_DMCONTROL:
|
||||
{
|
||||
if (!dmcontrol.dmactive && get_field(value, DMI_DMCONTROL_DMACTIVE))
|
||||
if (!dmcontrol.dmactive && get_field(value, DM_DMCONTROL_DMACTIVE))
|
||||
reset();
|
||||
dmcontrol.dmactive = get_field(value, DMI_DMCONTROL_DMACTIVE);
|
||||
dmcontrol.dmactive = get_field(value, DM_DMCONTROL_DMACTIVE);
|
||||
if (!dmstatus.authenticated || !dmcontrol.dmactive)
|
||||
return true;
|
||||
|
||||
dmcontrol.haltreq = get_field(value, DMI_DMCONTROL_HALTREQ);
|
||||
dmcontrol.resumereq = get_field(value, DMI_DMCONTROL_RESUMEREQ);
|
||||
dmcontrol.hartreset = get_field(value, DMI_DMCONTROL_HARTRESET);
|
||||
dmcontrol.ndmreset = get_field(value, DMI_DMCONTROL_NDMRESET);
|
||||
dmcontrol.haltreq = get_field(value, DM_DMCONTROL_HALTREQ);
|
||||
dmcontrol.resumereq = get_field(value, DM_DMCONTROL_RESUMEREQ);
|
||||
dmcontrol.hartreset = get_field(value, DM_DMCONTROL_HARTRESET);
|
||||
dmcontrol.ndmreset = get_field(value, DM_DMCONTROL_NDMRESET);
|
||||
if (config.support_hasel)
|
||||
dmcontrol.hasel = get_field(value, DMI_DMCONTROL_HASEL);
|
||||
dmcontrol.hasel = get_field(value, DM_DMCONTROL_HASEL);
|
||||
else
|
||||
dmcontrol.hasel = 0;
|
||||
dmcontrol.hartsel = get_field(value, DMI_DMCONTROL_HARTSELHI) <<
|
||||
DMI_DMCONTROL_HARTSELLO_LENGTH;
|
||||
dmcontrol.hartsel |= get_field(value, DMI_DMCONTROL_HARTSELLO);
|
||||
dmcontrol.hartsel &= (1L<<hartsellen) - 1;
|
||||
for (unsigned i = 0; i < nprocs; i++) {
|
||||
if (hart_selected(i)) {
|
||||
if (get_field(value, DMI_DMCONTROL_ACKHAVERESET)) {
|
||||
hart_state[i].havereset = false;
|
||||
dmcontrol.hartsel = get_field(value, DM_DMCONTROL_HARTSELHI) <<
|
||||
DM_DMCONTROL_HARTSELLO_LENGTH;
|
||||
dmcontrol.hartsel |= get_field(value, DM_DMCONTROL_HARTSELLO);
|
||||
dmcontrol.hartsel = std::min(size_t(dmcontrol.hartsel), sim->get_cfg().nprocs() - 1);
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
if (hart_selected(hart_id)) {
|
||||
if (get_field(value, DM_DMCONTROL_ACKHAVERESET)) {
|
||||
hart_state[hart_id].havereset = false;
|
||||
}
|
||||
processor_t *proc = processor(i);
|
||||
if (proc) {
|
||||
proc->halt_request = dmcontrol.haltreq ? proc->HR_REGULAR : proc->HR_NONE;
|
||||
if (dmcontrol.haltreq) {
|
||||
D(fprintf(stderr, "halt hart %d\n", i));
|
||||
}
|
||||
if (dmcontrol.resumereq) {
|
||||
D(fprintf(stderr, "resume hart %d\n", i));
|
||||
debug_rom_flags[i] |= (1 << DEBUG_ROM_FLAG_RESUME);
|
||||
hart_state[i].resumeack = false;
|
||||
}
|
||||
if (dmcontrol.hartreset) {
|
||||
proc->reset();
|
||||
}
|
||||
hart->halt_request = dmcontrol.haltreq ? hart->HR_REGULAR : hart->HR_NONE;
|
||||
if (dmcontrol.haltreq) {
|
||||
D(fprintf(stderr, "halt hart %d\n", hart_id));
|
||||
}
|
||||
if (dmcontrol.resumereq) {
|
||||
D(fprintf(stderr, "resume hart %d\n", hart_id));
|
||||
debug_rom_flags[hart_id] |= (1 << DEBUG_ROM_FLAG_RESUME);
|
||||
hart_state[hart_id].resumeack = false;
|
||||
}
|
||||
if (dmcontrol.hartreset) {
|
||||
hart->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (dmcontrol.ndmreset) {
|
||||
for (size_t i = 0; i < sim->nprocs(); i++) {
|
||||
processor_t *proc = sim->get_core(i);
|
||||
proc->reset();
|
||||
for (const auto& [hart_id, hart] : sim->get_harts()) {
|
||||
hart->reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case DMI_COMMAND:
|
||||
case DM_COMMAND:
|
||||
command = value;
|
||||
return perform_abstract_command();
|
||||
|
||||
case DMI_HAWINDOWSEL:
|
||||
hawindowsel = value & ((1U<<field_width(nprocs))-1);
|
||||
case DM_HAWINDOWSEL:
|
||||
hawindowsel = value & ((1U<<field_width(hart_array_mask.size()))-1);
|
||||
return true;
|
||||
|
||||
case DMI_HAWINDOW:
|
||||
case DM_HAWINDOW:
|
||||
{
|
||||
unsigned base = hawindowsel * 32;
|
||||
for (unsigned i = 0; i < 32; i++) {
|
||||
unsigned n = base + i;
|
||||
if (n < nprocs) {
|
||||
hart_array_mask[n] = (value >> i) & 1;
|
||||
if (n < sim->get_cfg().nprocs()) {
|
||||
hart_array_mask[sim->get_cfg().hartids()[n]] = (value >> i) & 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
case DMI_ABSTRACTCS:
|
||||
abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DMI_ABSTRACTCS_CMDERR))));
|
||||
case DM_ABSTRACTCS:
|
||||
abstractcs.cmderr = (cmderr_t) (((uint32_t) (abstractcs.cmderr)) & (~(uint32_t)(get_field(value, DM_ABSTRACTCS_CMDERR))));
|
||||
return true;
|
||||
|
||||
case DMI_ABSTRACTAUTO:
|
||||
case DM_ABSTRACTAUTO:
|
||||
abstractauto.autoexecprogbuf = get_field(value,
|
||||
DMI_ABSTRACTAUTO_AUTOEXECPROGBUF);
|
||||
DM_ABSTRACTAUTO_AUTOEXECPROGBUF);
|
||||
abstractauto.autoexecdata = get_field(value,
|
||||
DMI_ABSTRACTAUTO_AUTOEXECDATA);
|
||||
DM_ABSTRACTAUTO_AUTOEXECDATA);
|
||||
return true;
|
||||
case DMI_SBCS:
|
||||
sbcs.readonaddr = get_field(value, DMI_SBCS_SBREADONADDR);
|
||||
sbcs.sbaccess = get_field(value, DMI_SBCS_SBACCESS);
|
||||
sbcs.autoincrement = get_field(value, DMI_SBCS_SBAUTOINCREMENT);
|
||||
sbcs.readondata = get_field(value, DMI_SBCS_SBREADONDATA);
|
||||
sbcs.error &= ~get_field(value, DMI_SBCS_SBERROR);
|
||||
case DM_SBCS:
|
||||
sbcs.readonaddr = get_field(value, DM_SBCS_SBREADONADDR);
|
||||
sbcs.sbaccess = get_field(value, DM_SBCS_SBACCESS);
|
||||
sbcs.autoincrement = get_field(value, DM_SBCS_SBAUTOINCREMENT);
|
||||
sbcs.readondata = get_field(value, DM_SBCS_SBREADONDATA);
|
||||
sbcs.error &= ~get_field(value, DM_SBCS_SBERROR);
|
||||
return true;
|
||||
case DMI_SBADDRESS0:
|
||||
case DM_SBADDRESS0:
|
||||
sbaddress[0] = value;
|
||||
if (sbcs.error == 0 && sbcs.readonaddr) {
|
||||
sb_read();
|
||||
sb_autoincrement();
|
||||
}
|
||||
return true;
|
||||
case DMI_SBADDRESS1:
|
||||
case DM_SBADDRESS1:
|
||||
sbaddress[1] = value;
|
||||
return true;
|
||||
case DMI_SBADDRESS2:
|
||||
case DM_SBADDRESS2:
|
||||
sbaddress[2] = value;
|
||||
return true;
|
||||
case DMI_SBADDRESS3:
|
||||
case DM_SBADDRESS3:
|
||||
sbaddress[3] = value;
|
||||
return true;
|
||||
case DMI_SBDATA0:
|
||||
case DM_SBDATA0:
|
||||
sbdata[0] = value;
|
||||
if (sbcs.error == 0) {
|
||||
sb_write();
|
||||
|
@ -898,16 +875,16 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
|
|||
}
|
||||
}
|
||||
return true;
|
||||
case DMI_SBDATA1:
|
||||
case DM_SBDATA1:
|
||||
sbdata[1] = value;
|
||||
return true;
|
||||
case DMI_SBDATA2:
|
||||
case DM_SBDATA2:
|
||||
sbdata[2] = value;
|
||||
return true;
|
||||
case DMI_SBDATA3:
|
||||
case DM_SBDATA3:
|
||||
sbdata[3] = value;
|
||||
return true;
|
||||
case DMI_AUTHDATA:
|
||||
case DM_AUTHDATA:
|
||||
D(fprintf(stderr, "debug authentication: got 0x%x; 0x%x unlocks\n", value,
|
||||
challenge + secret));
|
||||
if (config.require_authentication) {
|
||||
|
@ -919,10 +896,11 @@ bool debug_module_t::dmi_write(unsigned address, uint32_t value)
|
|||
}
|
||||
}
|
||||
return true;
|
||||
case DMI_DMCS2:
|
||||
if (config.support_haltgroups && get_field(value, DMI_DMCS2_HGWRITE)) {
|
||||
hart_state[dmcontrol.hartsel].haltgroup = get_field(value,
|
||||
DMI_DMCS2_HALTGROUP);
|
||||
case DM_DMCS2:
|
||||
if (config.support_haltgroups &&
|
||||
get_field(value, DM_DMCS2_HGWRITE) &&
|
||||
get_field(value, DM_DMCS2_GROUPTYPE) == 0) {
|
||||
selected_hart_state().haltgroup = get_field(value, DM_DMCS2_GROUP);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -936,3 +914,13 @@ void debug_module_t::proc_reset(unsigned id)
|
|||
hart_state[id].halted = false;
|
||||
hart_state[id].haltgroup = 0;
|
||||
}
|
||||
|
||||
hart_debug_state_t& debug_module_t::selected_hart_state()
|
||||
{
|
||||
return hart_state[selected_hart_id()];
|
||||
}
|
||||
|
||||
size_t debug_module_t::selected_hart_id() const
|
||||
{
|
||||
return sim->get_cfg().hartids().at(dmcontrol.hartsel);
|
||||
}
|
||||
|
|
51
vendor/riscv/riscv-isa-sim/riscv/debug_module.h
vendored
51
vendor/riscv/riscv-isa-sim/riscv/debug_module.h
vendored
|
@ -3,24 +3,26 @@
|
|||
#define _RISCV_DEBUG_MODULE_H
|
||||
|
||||
#include <set>
|
||||
#include <vector>
|
||||
|
||||
#include "abstract_device.h"
|
||||
#include "mmu.h"
|
||||
|
||||
class sim_t;
|
||||
class simif_t;
|
||||
class bus_t;
|
||||
class processor_t;
|
||||
|
||||
typedef struct {
|
||||
// Size of program_buffer in 32-bit words, as exposed to the rest of the
|
||||
// world.
|
||||
unsigned progbufsize;
|
||||
unsigned max_sba_data_width;
|
||||
bool require_authentication;
|
||||
unsigned abstract_rti;
|
||||
bool support_hasel;
|
||||
bool support_abstract_csr_access;
|
||||
bool support_haltgroups;
|
||||
bool support_impebreak;
|
||||
// Size of program_buffer in 32-bit words, as exposed to the rest of the
|
||||
// world.
|
||||
unsigned progbufsize;
|
||||
unsigned max_sba_data_width;
|
||||
bool require_authentication;
|
||||
unsigned abstract_rti;
|
||||
bool support_hasel;
|
||||
bool support_abstract_csr_access;
|
||||
bool support_abstract_fpr_access;
|
||||
bool support_haltgroups;
|
||||
bool support_impebreak;
|
||||
} debug_module_config_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -54,12 +56,12 @@ typedef struct {
|
|||
} dmstatus_t;
|
||||
|
||||
typedef enum cmderr {
|
||||
CMDERR_NONE = 0,
|
||||
CMDERR_BUSY = 1,
|
||||
CMDERR_NOTSUP = 2,
|
||||
CMDERR_EXCEPTION = 3,
|
||||
CMDERR_HALTRESUME = 4,
|
||||
CMDERR_OTHER = 7
|
||||
CMDERR_NONE = 0,
|
||||
CMDERR_BUSY = 1,
|
||||
CMDERR_NOTSUP = 2,
|
||||
CMDERR_EXCEPTION = 3,
|
||||
CMDERR_HALTRESUME = 4,
|
||||
CMDERR_OTHER = 7
|
||||
} cmderr_t;
|
||||
|
||||
typedef struct {
|
||||
|
@ -108,7 +110,7 @@ class debug_module_t : public abstract_device_t
|
|||
* abstract_rti is extra run-test/idle cycles that each abstract command
|
||||
* takes to execute. Useful for testing OpenOCD.
|
||||
*/
|
||||
debug_module_t(sim_t *sim, const debug_module_config_t &config);
|
||||
debug_module_t(simif_t *sim, const debug_module_config_t &config);
|
||||
~debug_module_t();
|
||||
|
||||
void add_device(bus_t *bus);
|
||||
|
@ -130,7 +132,6 @@ class debug_module_t : public abstract_device_t
|
|||
|
||||
private:
|
||||
static const unsigned datasize = 2;
|
||||
unsigned nprocs;
|
||||
debug_module_config_t config;
|
||||
// Actual size of the program buffer, which is 1 word bigger than we let on
|
||||
// to implement the implicit ebreak at the end.
|
||||
|
@ -144,11 +145,7 @@ class debug_module_t : public abstract_device_t
|
|||
// functionality.
|
||||
unsigned custom_base;
|
||||
|
||||
// We only support 1024 harts currently. More requires at least resizing
|
||||
// the arrays below, and their corresponding special memory regions.
|
||||
unsigned hartsellen = 10;
|
||||
|
||||
sim_t *sim;
|
||||
simif_t *sim;
|
||||
|
||||
uint8_t debug_rom_whereto[4];
|
||||
uint8_t debug_abstract[debug_abstract_size * 4];
|
||||
|
@ -181,13 +178,15 @@ class debug_module_t : public abstract_device_t
|
|||
uint32_t challenge;
|
||||
const uint32_t secret = 1;
|
||||
|
||||
processor_t *processor(unsigned hartid) const;
|
||||
bool hart_selected(unsigned hartid) const;
|
||||
void reset();
|
||||
bool perform_abstract_command();
|
||||
|
||||
bool abstract_command_completed;
|
||||
unsigned rti_remaining;
|
||||
|
||||
size_t selected_hart_id() const;
|
||||
hart_debug_state_t& selected_hart_state();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
2957
vendor/riscv/riscv-isa-sim/riscv/decode.h
vendored
2957
vendor/riscv/riscv-isa-sim/riscv/decode.h
vendored
File diff suppressed because it is too large
Load diff
312
vendor/riscv/riscv-isa-sim/riscv/decode_macros.h
vendored
Normal file
312
vendor/riscv/riscv-isa-sim/riscv/decode_macros.h
vendored
Normal file
|
@ -0,0 +1,312 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#ifndef _RISCV_DECODE_MACROS_H
|
||||
#define _RISCV_DECODE_MACROS_H
|
||||
|
||||
#include "config.h"
|
||||
#include "decode.h"
|
||||
#include "encoding.h"
|
||||
#include "common.h"
|
||||
#include "softfloat_types.h"
|
||||
#include "specialize.h"
|
||||
|
||||
// helpful macros, etc
|
||||
#define MMU (*p->get_mmu())
|
||||
#define STATE (*p->get_state())
|
||||
#define FLEN (p->get_flen())
|
||||
#define CHECK_REG(reg) ((void) 0)
|
||||
#define READ_REG(reg) (CHECK_REG(reg), STATE.XPR[reg])
|
||||
#define READ_FREG(reg) STATE.FPR[reg]
|
||||
#define RD READ_REG(insn.rd())
|
||||
#define RS1 READ_REG(insn.rs1())
|
||||
#define RS2 READ_REG(insn.rs2())
|
||||
#define RS3 READ_REG(insn.rs3())
|
||||
#define WRITE_RD(value) WRITE_REG(insn.rd(), value)
|
||||
|
||||
/* 0 : int
|
||||
* 1 : floating
|
||||
* 2 : vector reg
|
||||
* 3 : vector hint
|
||||
* 4 : csr
|
||||
*/
|
||||
#define WRITE_REG(reg, value) ({ \
|
||||
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) ({ \
|
||||
freg_t wdata = freg(value); /* value may have side effects */ \
|
||||
if (DECODE_MACRO_USAGE_LOGGED) STATE.log_reg_write[((reg) << 4) | 1] = wdata; \
|
||||
DO_WRITE_FREG(reg, wdata); \
|
||||
})
|
||||
#define WRITE_VSTATUS STATE.log_reg_write[3] = {0, 0};
|
||||
|
||||
// RVC macros
|
||||
#define WRITE_RVC_RS1S(value) WRITE_REG(insn.rvc_rs1s(), value)
|
||||
#define WRITE_RVC_RS2S(value) WRITE_REG(insn.rvc_rs2s(), value)
|
||||
#define WRITE_RVC_FRS2S(value) WRITE_FREG(insn.rvc_rs2s(), value)
|
||||
#define RVC_RS1 READ_REG(insn.rvc_rs1())
|
||||
#define RVC_RS2 READ_REG(insn.rvc_rs2())
|
||||
#define RVC_RS1S READ_REG(insn.rvc_rs1s())
|
||||
#define RVC_RS2S READ_REG(insn.rvc_rs2s())
|
||||
#define RVC_FRS2 READ_FREG(insn.rvc_rs2())
|
||||
#define RVC_FRS2S READ_FREG(insn.rvc_rs2s())
|
||||
#define RVC_SP READ_REG(X_SP)
|
||||
|
||||
// Zc* macros
|
||||
#define RVC_R1S (Sn(insn.rvc_r1sc()))
|
||||
#define RVC_R2S (Sn(insn.rvc_r2sc()))
|
||||
#define SP READ_REG(X_SP)
|
||||
#define RA READ_REG(X_RA)
|
||||
|
||||
// FPU macros
|
||||
#define READ_ZDINX_REG(reg) (xlen == 32 ? f64(READ_REG_PAIR(reg)) : f64(STATE.XPR[reg] & (uint64_t)-1))
|
||||
#define READ_FREG_H(reg) (p->extension_enabled(EXT_ZFINX) ? f16(STATE.XPR[reg] & (uint16_t)-1) : f16(READ_FREG(reg)))
|
||||
#define READ_FREG_F(reg) (p->extension_enabled(EXT_ZFINX) ? f32(STATE.XPR[reg] & (uint32_t)-1) : f32(READ_FREG(reg)))
|
||||
#define READ_FREG_D(reg) (p->extension_enabled(EXT_ZFINX) ? READ_ZDINX_REG(reg) : f64(READ_FREG(reg)))
|
||||
#define FRS1 READ_FREG(insn.rs1())
|
||||
#define FRS2 READ_FREG(insn.rs2())
|
||||
#define FRS3 READ_FREG(insn.rs3())
|
||||
#define FRS1_H READ_FREG_H(insn.rs1())
|
||||
#define FRS1_F READ_FREG_F(insn.rs1())
|
||||
#define FRS1_D READ_FREG_D(insn.rs1())
|
||||
#define FRS2_H READ_FREG_H(insn.rs2())
|
||||
#define FRS2_F READ_FREG_F(insn.rs2())
|
||||
#define FRS2_D READ_FREG_D(insn.rs2())
|
||||
#define FRS3_H READ_FREG_H(insn.rs3())
|
||||
#define FRS3_F READ_FREG_F(insn.rs3())
|
||||
#define FRS3_D READ_FREG_D(insn.rs3())
|
||||
#define dirty_fp_state STATE.sstatus->dirty(SSTATUS_FS)
|
||||
#define dirty_ext_state STATE.sstatus->dirty(SSTATUS_XS)
|
||||
#define dirty_vs_state STATE.sstatus->dirty(SSTATUS_VS)
|
||||
#define DO_WRITE_FREG(reg, value) (STATE.FPR.write(reg, value), dirty_fp_state)
|
||||
#define WRITE_FRD(value) WRITE_FREG(insn.rd(), value)
|
||||
#define WRITE_FRD_H(value) \
|
||||
do { \
|
||||
if (p->extension_enabled(EXT_ZFINX)) \
|
||||
WRITE_REG(insn.rd(), sext_xlen((int16_t)((value).v))); \
|
||||
else { \
|
||||
WRITE_FRD(value); \
|
||||
} \
|
||||
} while (0)
|
||||
#define WRITE_FRD_F(value) \
|
||||
do { \
|
||||
if (p->extension_enabled(EXT_ZFINX)) \
|
||||
WRITE_REG(insn.rd(), sext_xlen((value).v)); \
|
||||
else { \
|
||||
WRITE_FRD(value); \
|
||||
} \
|
||||
} while (0)
|
||||
#define WRITE_FRD_D(value) \
|
||||
do { \
|
||||
if (p->extension_enabled(EXT_ZFINX)) { \
|
||||
if (xlen == 32) { \
|
||||
uint64_t val = (value).v; \
|
||||
WRITE_RD_PAIR(val); \
|
||||
} else { \
|
||||
WRITE_REG(insn.rd(), (value).v); \
|
||||
} \
|
||||
} else { \
|
||||
WRITE_FRD(value); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SHAMT (insn.i_imm() & 0x3F)
|
||||
#define BRANCH_TARGET (pc + insn.sb_imm())
|
||||
#define JUMP_TARGET (pc + insn.uj_imm())
|
||||
#define RM ({ int rm = insn.rm(); \
|
||||
if (rm == 7) rm = STATE.frm->read(); \
|
||||
if (rm > 4) throw trap_illegal_instruction(insn.bits()); \
|
||||
rm; })
|
||||
|
||||
|
||||
#define require_privilege(p) require(STATE.prv >= (p))
|
||||
#define require_novirt() (unlikely(STATE.v) ? throw trap_virtual_instruction(insn.bits()) : (void) 0)
|
||||
#define require_hs_qualified(cond) (STATE.v && !(cond) ? require_novirt() : require(cond))
|
||||
#define require_privilege_hs_qualified(p) require_hs_qualified(STATE.prv >= (p))
|
||||
#define require_rv64 require(xlen == 64)
|
||||
#define require_rv32 require(xlen == 32)
|
||||
#define require_extension(s) require(p->extension_enabled(s))
|
||||
#define require_either_extension(A,B) require(p->extension_enabled(A) || p->extension_enabled(B));
|
||||
#define require_impl(s) require(p->supports_impl(s))
|
||||
#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(alu) \
|
||||
do { \
|
||||
require_vector_vs; \
|
||||
require_extension('V'); \
|
||||
require(!P.VU.vill); \
|
||||
if (alu && !P.VU.vstart_alu) \
|
||||
require(P.VU.vstart->read() == 0); \
|
||||
WRITE_VSTATUS; \
|
||||
dirty_vs_state; \
|
||||
} while (0);
|
||||
#define require_vector_novtype(is_log) \
|
||||
do { \
|
||||
require_vector_vs; \
|
||||
require_extension('V'); \
|
||||
if (is_log) \
|
||||
WRITE_VSTATUS; \
|
||||
dirty_vs_state; \
|
||||
} while (0);
|
||||
#define require_align(val, pos) require(is_aligned(val, pos))
|
||||
#define require_noover(astart, asize, bstart, bsize) \
|
||||
require(!is_overlapped(astart, asize, bstart, bsize))
|
||||
#define require_noover_widen(astart, asize, bstart, bsize) \
|
||||
require(!is_overlapped_widen(astart, asize, bstart, bsize))
|
||||
#define require_vm do { if (insn.v_vm() == 0) require(insn.rd() != 0); } while (0);
|
||||
#define require_envcfg(field) \
|
||||
do { \
|
||||
if (((STATE.prv != PRV_M) && (m##field == 0)) || \
|
||||
((STATE.prv == PRV_U && !STATE.v) && (s##field == 0))) \
|
||||
throw trap_illegal_instruction(insn.bits()); \
|
||||
else if (STATE.v && ((h##field == 0) || \
|
||||
((STATE.prv == PRV_U) && (s##field == 0)))) \
|
||||
throw trap_virtual_instruction(insn.bits()); \
|
||||
} while (0);
|
||||
|
||||
#define require_zcmp_pushpop \
|
||||
do { \
|
||||
require_extension(EXT_ZCMP); \
|
||||
reg_t rlist = insn.rvc_rlist(); \
|
||||
require(rlist >= 4); \
|
||||
\
|
||||
if (p->extension_enabled('E')) { \
|
||||
require(rlist <= 6); \
|
||||
} \
|
||||
} while (0);
|
||||
|
||||
#define set_fp_exceptions ({ if (softfloat_exceptionFlags) { \
|
||||
STATE.fflags->write(STATE.fflags->read() | softfloat_exceptionFlags); \
|
||||
} \
|
||||
softfloat_exceptionFlags = 0; })
|
||||
|
||||
#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 zext(x, pos) (((reg_t)(x) << (64 - (pos))) >> (64 - (pos)))
|
||||
#define zext_xlen(x) zext(x, xlen)
|
||||
|
||||
#define set_pc(x) \
|
||||
do { p->check_pc_alignment(x); \
|
||||
npc = sext_xlen(x); \
|
||||
} while (0)
|
||||
|
||||
#define set_pc_and_serialize(x) \
|
||||
do { reg_t __npc = (x) & p->pc_alignment_mask(); \
|
||||
npc = PC_SERIALIZE_AFTER; \
|
||||
STATE.pc = __npc; \
|
||||
} while (0)
|
||||
|
||||
class wait_for_interrupt_t {};
|
||||
|
||||
#define wfi() \
|
||||
do { set_pc_and_serialize(npc); \
|
||||
throw wait_for_interrupt_t(); \
|
||||
} while (0)
|
||||
|
||||
#define serialize() set_pc_and_serialize(npc)
|
||||
|
||||
/* Sentinel PC values to serialize simulator pipeline */
|
||||
#define PC_SERIALIZE_BEFORE 3
|
||||
#define PC_SERIALIZE_AFTER 5
|
||||
#define invalid_pc(pc) ((pc) & 1)
|
||||
|
||||
/* Convenience wrappers to simplify softfloat code sequences */
|
||||
#define isBoxedF16(r) (isBoxedF32(r) && ((uint64_t)((r.v[0] >> 16) + 1) == ((uint64_t)1 << 48)))
|
||||
#define unboxF16(r) (isBoxedF16(r) ? (uint16_t)r.v[0] : defaultNaNF16UI)
|
||||
#define isBoxedF32(r) (isBoxedF64(r) && ((uint32_t)((r.v[0] >> 32) + 1) == 0))
|
||||
#define unboxF32(r) (isBoxedF32(r) ? (uint32_t)r.v[0] : defaultNaNF32UI)
|
||||
#define isBoxedF64(r) ((r.v[1] + 1) == 0)
|
||||
#define unboxF64(r) (isBoxedF64(r) ? r.v[0] : defaultNaNF64UI)
|
||||
inline float16_t f16(uint16_t v) { return { v }; }
|
||||
inline float32_t f32(uint32_t v) { return { v }; }
|
||||
inline float64_t f64(uint64_t v) { return { v }; }
|
||||
inline float16_t f16(freg_t r) { return f16(unboxF16(r)); }
|
||||
inline float32_t f32(freg_t r) { return f32(unboxF32(r)); }
|
||||
inline float64_t f64(freg_t r) { return f64(unboxF64(r)); }
|
||||
inline float128_t f128(freg_t r) { return r; }
|
||||
inline freg_t freg(float16_t f) { return { ((uint64_t)-1 << 16) | f.v, (uint64_t)-1 }; }
|
||||
inline freg_t freg(float32_t f) { return { ((uint64_t)-1 << 32) | f.v, (uint64_t)-1 }; }
|
||||
inline freg_t freg(float64_t f) { return { f.v, (uint64_t)-1 }; }
|
||||
inline freg_t freg(float128_t f) { return f; }
|
||||
#define F16_SIGN ((uint16_t)1 << 15)
|
||||
#define F32_SIGN ((uint32_t)1 << 31)
|
||||
#define F64_SIGN ((uint64_t)1 << 63)
|
||||
#define fsgnj16(a, b, n, x) \
|
||||
f16((f16(a).v & ~F16_SIGN) | ((((x) ? f16(a).v : (n) ? F16_SIGN : 0) ^ f16(b).v) & F16_SIGN))
|
||||
#define fsgnj32(a, b, n, x) \
|
||||
f32((f32(a).v & ~F32_SIGN) | ((((x) ? f32(a).v : (n) ? F32_SIGN : 0) ^ f32(b).v) & F32_SIGN))
|
||||
#define fsgnj64(a, b, n, x) \
|
||||
f64((f64(a).v & ~F64_SIGN) | ((((x) ? f64(a).v : (n) ? F64_SIGN : 0) ^ f64(b).v) & F64_SIGN))
|
||||
|
||||
#define isNaNF128(x) isNaNF128UI(x.v[1], x.v[0])
|
||||
inline float128_t defaultNaNF128()
|
||||
{
|
||||
float128_t nan;
|
||||
nan.v[1] = defaultNaNF128UI64;
|
||||
nan.v[0] = defaultNaNF128UI0;
|
||||
return nan;
|
||||
}
|
||||
inline freg_t fsgnj128(freg_t a, freg_t b, bool n, bool x)
|
||||
{
|
||||
a.v[1] = (a.v[1] & ~F64_SIGN) | (((x ? a.v[1] : n ? F64_SIGN : 0) ^ b.v[1]) & F64_SIGN);
|
||||
return a;
|
||||
}
|
||||
inline freg_t f128_negate(freg_t a)
|
||||
{
|
||||
a.v[1] ^= F64_SIGN;
|
||||
return a;
|
||||
}
|
||||
|
||||
#define validate_csr(which, write) ({ \
|
||||
if (!STATE.serialized) return PC_SERIALIZE_BEFORE; \
|
||||
STATE.serialized = false; \
|
||||
/* permissions check occurs in get_csr */ \
|
||||
(which); })
|
||||
|
||||
/* For debug only. This will fail if the native machine's float types are not IEEE */
|
||||
inline float to_f(float32_t f) { float r; memcpy(&r, &f, sizeof(r)); return r; }
|
||||
inline double to_f(float64_t f) { double r; memcpy(&r, &f, sizeof(r)); return r; }
|
||||
inline long double to_f(float128_t f) { long double r; memcpy(&r, &f, sizeof(r)); return r; }
|
||||
|
||||
// Vector macros
|
||||
#define e8 8 // 8b elements
|
||||
#define e16 16 // 16b elements
|
||||
#define e32 32 // 32b elements
|
||||
#define e64 64 // 64b elements
|
||||
#define e128 128 // 128b elements
|
||||
#define e256 256 // 256b elements
|
||||
#define e512 512 // 512b elements
|
||||
#define e1024 1024 // 1024b elements
|
||||
|
||||
#define vsext(x, sew) (((sreg_t)(x) << (64 - sew)) >> (64 - sew))
|
||||
#define vzext(x, sew) (((reg_t)(x) << (64 - sew)) >> (64 - sew))
|
||||
|
||||
#define DEBUG_RVV 0
|
||||
|
||||
#if DEBUG_RVV
|
||||
#define DEBUG_RVV_FP_VV \
|
||||
printf("vfp(%lu) vd=%f vs1=%f vs2=%f\n", i, to_f(vd), to_f(vs1), to_f(vs2));
|
||||
#define DEBUG_RVV_FP_VF \
|
||||
printf("vfp(%lu) vd=%f vs1=%f vs2=%f\n", i, to_f(vd), to_f(rs1), to_f(vs2));
|
||||
#define DEBUG_RVV_FMA_VV \
|
||||
printf("vfma(%lu) vd=%f vs1=%f vs2=%f vd_old=%f\n", i, to_f(vd), to_f(vs1), to_f(vs2), to_f(vd_old));
|
||||
#define DEBUG_RVV_FMA_VF \
|
||||
printf("vfma(%lu) vd=%f vs1=%f vs2=%f vd_old=%f\n", i, to_f(vd), to_f(rs1), to_f(vs2), to_f(vd_old));
|
||||
#else
|
||||
#define DEBUG_RVV_FP_VV 0
|
||||
#define DEBUG_RVV_FP_VF 0
|
||||
#define DEBUG_RVV_FMA_VV 0
|
||||
#define DEBUG_RVV_FMA_VF 0
|
||||
#endif
|
||||
|
||||
#define DECLARE_XENVCFG_VARS(field) \
|
||||
reg_t m##field = get_field(STATE.menvcfg->read(), MENVCFG_##field); \
|
||||
reg_t s##field = get_field(STATE.senvcfg->read(), SENVCFG_##field); \
|
||||
reg_t h##field = get_field(STATE.henvcfg->read(), HENVCFG_##field)
|
||||
|
||||
#endif
|
13
vendor/riscv/riscv-isa-sim/riscv/devices.cc
vendored
13
vendor/riscv/riscv-isa-sim/riscv/devices.cc
vendored
|
@ -137,3 +137,16 @@ char* mem_t::contents(reg_t addr) {
|
|||
}
|
||||
return search->second + pgoff;
|
||||
}
|
||||
|
||||
void mem_t::dump(std::ostream& o) {
|
||||
const char empty[PGSIZE] = {0};
|
||||
for (reg_t i = 0; i < sz; i += PGSIZE) {
|
||||
reg_t ppn = i >> PGSHIFT;
|
||||
auto search = sparse_memory_map.find(ppn);
|
||||
if (search == sparse_memory_map.end()) {
|
||||
o.write(empty, PGSIZE);
|
||||
} else {
|
||||
o.write(sparse_memory_map[ppn], PGSIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
115
vendor/riscv/riscv-isa-sim/riscv/devices.h
vendored
115
vendor/riscv/riscv-isa-sim/riscv/devices.h
vendored
|
@ -4,12 +4,16 @@
|
|||
#include "decode.h"
|
||||
#include "mmio_plugin.h"
|
||||
#include "abstract_device.h"
|
||||
#include "abstract_interrupt_controller.h"
|
||||
#include "platform.h"
|
||||
#include <map>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cassert>
|
||||
|
||||
class processor_t;
|
||||
class simif_t;
|
||||
|
||||
class bus_t : public abstract_device_t {
|
||||
public:
|
||||
|
@ -43,6 +47,7 @@ class mem_t : public abstract_device_t {
|
|||
bool store(reg_t addr, size_t len, const uint8_t* bytes) { return load_store(addr, len, const_cast<uint8_t*>(bytes), true); }
|
||||
char* contents(reg_t addr);
|
||||
reg_t size() { return sz; }
|
||||
void dump(std::ostream& o);
|
||||
|
||||
private:
|
||||
bool load_store(reg_t addr, size_t len, uint8_t* bytes, bool store);
|
||||
|
@ -53,22 +58,104 @@ class mem_t : public abstract_device_t {
|
|||
|
||||
class clint_t : public abstract_device_t {
|
||||
public:
|
||||
clint_t(std::vector<processor_t*>&, uint64_t freq_hz, bool real_time);
|
||||
clint_t(simif_t*, uint64_t freq_hz, bool real_time);
|
||||
bool load(reg_t addr, size_t len, uint8_t* bytes);
|
||||
bool store(reg_t addr, size_t len, const uint8_t* bytes);
|
||||
size_t size() { return CLINT_SIZE; }
|
||||
void increment(reg_t inc);
|
||||
uint64_t get_mtimecmp(reg_t hartid) { return mtimecmp[hartid]; }
|
||||
uint64_t get_mtime() { return mtime; }
|
||||
private:
|
||||
typedef uint64_t mtime_t;
|
||||
typedef uint64_t mtimecmp_t;
|
||||
typedef uint32_t msip_t;
|
||||
std::vector<processor_t*>& procs;
|
||||
simif_t* sim;
|
||||
uint64_t freq_hz;
|
||||
bool real_time;
|
||||
uint64_t real_time_ref_secs;
|
||||
uint64_t real_time_ref_usecs;
|
||||
mtime_t mtime;
|
||||
std::vector<mtimecmp_t> mtimecmp;
|
||||
std::map<size_t, mtimecmp_t> mtimecmp;
|
||||
};
|
||||
|
||||
#define PLIC_MAX_DEVICES 1024
|
||||
|
||||
struct plic_context_t {
|
||||
plic_context_t(processor_t* proc, bool mmode)
|
||||
: proc(proc), mmode(mmode)
|
||||
{}
|
||||
|
||||
processor_t *proc;
|
||||
bool mmode;
|
||||
|
||||
uint8_t priority_threshold {};
|
||||
uint32_t enable[PLIC_MAX_DEVICES/32] {};
|
||||
uint32_t pending[PLIC_MAX_DEVICES/32] {};
|
||||
uint8_t pending_priority[PLIC_MAX_DEVICES] {};
|
||||
uint32_t claimed[PLIC_MAX_DEVICES/32] {};
|
||||
};
|
||||
|
||||
class plic_t : public abstract_device_t, public abstract_interrupt_controller_t {
|
||||
public:
|
||||
plic_t(simif_t*, uint32_t ndev);
|
||||
bool load(reg_t addr, size_t len, uint8_t* bytes);
|
||||
bool store(reg_t addr, size_t len, const uint8_t* bytes);
|
||||
void set_interrupt_level(uint32_t id, int lvl);
|
||||
size_t size() { return PLIC_SIZE; }
|
||||
private:
|
||||
std::vector<plic_context_t> contexts;
|
||||
uint32_t num_ids;
|
||||
uint32_t num_ids_word;
|
||||
uint32_t max_prio;
|
||||
uint8_t priority[PLIC_MAX_DEVICES];
|
||||
uint32_t level[PLIC_MAX_DEVICES/32];
|
||||
uint32_t context_best_pending(const plic_context_t *c);
|
||||
void context_update(const plic_context_t *context);
|
||||
uint32_t context_claim(plic_context_t *c);
|
||||
bool priority_read(reg_t offset, uint32_t *val);
|
||||
bool priority_write(reg_t offset, uint32_t val);
|
||||
bool pending_read(reg_t offset, uint32_t *val);
|
||||
bool context_enable_read(const plic_context_t *context,
|
||||
reg_t offset, uint32_t *val);
|
||||
bool context_enable_write(plic_context_t *context,
|
||||
reg_t offset, uint32_t val);
|
||||
bool context_read(plic_context_t *context,
|
||||
reg_t offset, uint32_t *val);
|
||||
bool context_write(plic_context_t *context,
|
||||
reg_t offset, uint32_t val);
|
||||
};
|
||||
|
||||
class ns16550_t : public abstract_device_t {
|
||||
public:
|
||||
ns16550_t(class bus_t *bus, abstract_interrupt_controller_t *intctrl,
|
||||
uint32_t interrupt_id, uint32_t reg_shift, uint32_t reg_io_width);
|
||||
bool load(reg_t addr, size_t len, uint8_t* bytes);
|
||||
bool store(reg_t addr, size_t len, const uint8_t* bytes);
|
||||
void tick(void);
|
||||
size_t size() { return NS16550_SIZE; }
|
||||
private:
|
||||
class bus_t *bus;
|
||||
abstract_interrupt_controller_t *intctrl;
|
||||
uint32_t interrupt_id;
|
||||
uint32_t reg_shift;
|
||||
uint32_t reg_io_width;
|
||||
std::queue<uint8_t> rx_queue;
|
||||
uint8_t dll;
|
||||
uint8_t dlm;
|
||||
uint8_t iir;
|
||||
uint8_t ier;
|
||||
uint8_t fcr;
|
||||
uint8_t lcr;
|
||||
uint8_t mcr;
|
||||
uint8_t lsr;
|
||||
uint8_t msr;
|
||||
uint8_t scr;
|
||||
void update_interrupt(void);
|
||||
uint8_t rx_byte(void);
|
||||
void tx_byte(uint8_t val);
|
||||
|
||||
int backoff_counter;
|
||||
static const int MAX_BACKOFF = 16;
|
||||
};
|
||||
|
||||
class mmio_plugin_device_t : public abstract_device_t {
|
||||
|
@ -84,4 +171,26 @@ class mmio_plugin_device_t : public abstract_device_t {
|
|||
void* user_data;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
void write_little_endian_reg(T* word, reg_t addr, size_t len, const uint8_t* bytes)
|
||||
{
|
||||
assert(len <= sizeof(T));
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const int shift = 8 * ((addr + i) % sizeof(T));
|
||||
*word = (*word & ~(T(0xFF) << shift)) | (T(bytes[i]) << shift);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void read_little_endian_reg(T word, reg_t addr, size_t len, uint8_t* bytes)
|
||||
{
|
||||
assert(len <= sizeof(T));
|
||||
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
const int shift = 8 * ((addr + i) % sizeof(T));
|
||||
bytes[i] = word >> shift;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
6
vendor/riscv/riscv-isa-sim/riscv/disasm.h
vendored
6
vendor/riscv/riscv-isa-sim/riscv/disasm.h
vendored
|
@ -3,7 +3,9 @@
|
|||
#ifndef _RISCV_DISASM_H
|
||||
#define _RISCV_DISASM_H
|
||||
|
||||
#include "common.h"
|
||||
#include "decode.h"
|
||||
#include "isa_parser.h"
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
@ -80,7 +82,7 @@ class disasm_insn_t
|
|||
class disassembler_t
|
||||
{
|
||||
public:
|
||||
disassembler_t(int xlen);
|
||||
disassembler_t(const isa_parser_t *isa);
|
||||
~disassembler_t();
|
||||
|
||||
std::string disassemble(insn_t insn) const;
|
||||
|
@ -92,6 +94,8 @@ class disassembler_t
|
|||
static const int HASH_SIZE = 255;
|
||||
std::vector<const disasm_insn_t*> chain[HASH_SIZE+1];
|
||||
|
||||
void add_instructions(const isa_parser_t* isa);
|
||||
|
||||
const disasm_insn_t* probe_once(insn_t insn, size_t idx) const;
|
||||
|
||||
static const unsigned int MASK1 = 0x7f;
|
||||
|
|
115
vendor/riscv/riscv-isa-sim/riscv/dts.cc
vendored
115
vendor/riscv/riscv-isa-sim/riscv/dts.cc
vendored
|
@ -1,8 +1,10 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "config.h"
|
||||
#include "dts.h"
|
||||
#include "libfdt.h"
|
||||
#include "platform.h"
|
||||
#include <cassert>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <signal.h>
|
||||
|
@ -13,6 +15,7 @@
|
|||
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,
|
||||
std::vector<processor_t*> procs,
|
||||
std::vector<std::pair<reg_t, mem_t*>> mems)
|
||||
{
|
||||
|
@ -25,15 +28,16 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
|
|||
" #size-cells = <2>;\n"
|
||||
" compatible = \"ucbbar,spike-bare-dev\";\n"
|
||||
" model = \"ucbbar,spike-bare\";\n"
|
||||
" chosen {\n";
|
||||
" chosen {\n"
|
||||
" stdout-path = &SERIAL0;\n";
|
||||
if (initrd_start < initrd_end) {
|
||||
s << " linux,initrd-start = <" << (size_t)initrd_start << ">;\n"
|
||||
" linux,initrd-end = <" << (size_t)initrd_end << ">;\n";
|
||||
if (!bootargs)
|
||||
bootargs = "root=/dev/ram console=hvc0 earlycon=sbi";
|
||||
bootargs = "root=/dev/ram " DEFAULT_KERNEL_BOOTARGS;
|
||||
} else {
|
||||
if (!bootargs)
|
||||
bootargs = "console=hvc0 earlycon=sbi";
|
||||
bootargs = DEFAULT_KERNEL_BOOTARGS;
|
||||
}
|
||||
s << " bootargs = \"";
|
||||
for (size_t i = 0; i < strlen(bootargs); i++) {
|
||||
|
@ -54,10 +58,10 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
|
|||
" reg = <" << i << ">;\n"
|
||||
" status = \"okay\";\n"
|
||||
" compatible = \"riscv\";\n"
|
||||
" riscv,isa = \"" << procs[i]->get_isa_string() << "\";\n"
|
||||
" mmu-type = \"riscv," << (procs[i]->get_max_xlen() <= 32 ? "sv32" : "sv48") << "\";\n"
|
||||
" riscv,pmpregions = <16>;\n"
|
||||
" riscv,pmpgranularity = <4>;\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,pmpregions = <" << pmpregions << ">;\n"
|
||||
" riscv,pmpgranularity = <" << (1 << PMP_SHIFT) << ">;\n"
|
||||
" clock-frequency = <" << cpu_hz << ">;\n"
|
||||
" CPU" << i << "_intc: interrupt-controller {\n"
|
||||
" #address-cells = <2>;\n"
|
||||
|
@ -92,6 +96,35 @@ std::string make_dts(size_t insns_per_rtc_tick, size_t cpu_hz,
|
|||
" reg = <0x" << (clintbs >> 32) << " 0x" << (clintbs & (uint32_t)-1) <<
|
||||
" 0x" << (clintsz >> 32) << " 0x" << (clintsz & (uint32_t)-1) << ">;\n"
|
||||
" };\n"
|
||||
" PLIC: plic@" << PLIC_BASE << " {\n"
|
||||
" compatible = \"riscv,plic0\";\n"
|
||||
" #address-cells = <2>;\n"
|
||||
" interrupts-extended = <" << std::dec;
|
||||
for (size_t i = 0; i < procs.size(); i++)
|
||||
s << "&CPU" << i << "_intc 11 &CPU" << i << "_intc 9 ";
|
||||
reg_t plicbs = PLIC_BASE;
|
||||
reg_t plicsz = PLIC_SIZE;
|
||||
s << std::hex << ">;\n"
|
||||
" reg = <0x" << (plicbs >> 32) << " 0x" << (plicbs & (uint32_t)-1) <<
|
||||
" 0x" << (plicsz >> 32) << " 0x" << (plicsz & (uint32_t)-1) << ">;\n"
|
||||
" riscv,ndev = <0x" << PLIC_NDEV << ">;\n"
|
||||
" riscv,max-priority = <0x" << ((1U << PLIC_PRIO_BITS) - 1) << ">;\n"
|
||||
" #interrupt-cells = <1>;\n"
|
||||
" interrupt-controller;\n"
|
||||
" };\n"
|
||||
" SERIAL0: ns16550@" << NS16550_BASE << " {\n"
|
||||
" compatible = \"ns16550a\";\n"
|
||||
" clock-frequency = <" << std::dec << (cpu_hz/insns_per_rtc_tick) << ">;\n"
|
||||
" interrupt-parent = <&PLIC>;\n"
|
||||
" interrupts = <" << std::dec << NS16550_INTERRUPT_ID;
|
||||
reg_t ns16550bs = NS16550_BASE;
|
||||
reg_t ns16550sz = NS16550_SIZE;
|
||||
s << std::hex << ">;\n"
|
||||
" reg = <0x" << (ns16550bs >> 32) << " 0x" << (ns16550bs & (uint32_t)-1) <<
|
||||
" 0x" << (ns16550sz >> 32) << " 0x" << (ns16550sz & (uint32_t)-1) << ">;\n"
|
||||
" reg-shift = <0x" << NS16550_REG_SHIFT << ">;\n"
|
||||
" reg-io-width = <0x" << NS16550_REG_IO_WIDTH << ">;\n"
|
||||
" };\n"
|
||||
" };\n"
|
||||
" htif {\n"
|
||||
" compatible = \"ucb,htif0\";\n"
|
||||
|
@ -143,7 +176,7 @@ std::string dts_compile(const std::string& dts)
|
|||
close(dts_pipe[1]);
|
||||
close(dtb_pipe[0]);
|
||||
close(dtb_pipe[1]);
|
||||
execlp(DTC, DTC, "-O", "dtb", 0);
|
||||
execlp(DTC, DTC, "-O", "dtb", (char *)0);
|
||||
std::cerr << "Failed to run " DTC ": " << strerror(errno) << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
@ -182,7 +215,6 @@ std::string dts_compile(const std::string& dts)
|
|||
return dtb.str();
|
||||
}
|
||||
|
||||
|
||||
static int fdt_get_node_addr_size(void *fdt, int node, reg_t *addr,
|
||||
unsigned long *size, const char *field)
|
||||
{
|
||||
|
@ -244,7 +276,6 @@ static int check_cpu_node(void *fdt, int cpu_offset)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int fdt_get_offset(void *fdt, const char *field)
|
||||
{
|
||||
return fdt_path_offset(fdt, field);
|
||||
|
@ -276,6 +307,64 @@ int fdt_parse_clint(void *fdt, reg_t *clint_addr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fdt_parse_plic(void *fdt, reg_t *plic_addr, uint32_t *ndev,
|
||||
const char *compatible)
|
||||
{
|
||||
int nodeoffset, len, rc;
|
||||
const fdt32_t *ndev_p;
|
||||
|
||||
nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compatible);
|
||||
if (nodeoffset < 0)
|
||||
return nodeoffset;
|
||||
|
||||
rc = fdt_get_node_addr_size(fdt, nodeoffset, plic_addr, NULL, "reg");
|
||||
if (rc < 0 || !plic_addr)
|
||||
return -ENODEV;
|
||||
|
||||
ndev_p = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "riscv,ndev", &len);
|
||||
if (!ndev || !ndev_p)
|
||||
return -ENODEV;
|
||||
*ndev = fdt32_to_cpu(*ndev_p);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_parse_ns16550(void *fdt, reg_t *ns16550_addr,
|
||||
uint32_t *reg_shift, uint32_t *reg_io_width,
|
||||
const char *compatible)
|
||||
{
|
||||
int nodeoffset, len, rc;
|
||||
const fdt32_t *reg_p;
|
||||
|
||||
nodeoffset = fdt_node_offset_by_compatible(fdt, -1, compatible);
|
||||
if (nodeoffset < 0)
|
||||
return nodeoffset;
|
||||
|
||||
rc = fdt_get_node_addr_size(fdt, nodeoffset, ns16550_addr, NULL, "reg");
|
||||
if (rc < 0 || !ns16550_addr)
|
||||
return -ENODEV;
|
||||
|
||||
reg_p = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "reg-shift", &len);
|
||||
if (reg_shift) {
|
||||
if (reg_p) {
|
||||
*reg_shift = fdt32_to_cpu(*reg_p);
|
||||
} else {
|
||||
*reg_shift = NS16550_REG_SHIFT;
|
||||
}
|
||||
}
|
||||
|
||||
reg_p = (fdt32_t *)fdt_getprop(fdt, nodeoffset, "reg-io-width", &len);
|
||||
if (reg_io_width) {
|
||||
if (reg_p) {
|
||||
*reg_io_width = fdt32_to_cpu(*reg_p);
|
||||
} else {
|
||||
*reg_io_width = NS16550_REG_IO_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fdt_parse_pmp_num(void *fdt, int cpu_offset, reg_t *pmp_num)
|
||||
{
|
||||
int rc;
|
||||
|
@ -306,8 +395,10 @@ int fdt_parse_pmp_alignment(void *fdt, int cpu_offset, reg_t *pmp_align)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int fdt_parse_mmu_type(void *fdt, int cpu_offset, char *mmu_type)
|
||||
int fdt_parse_mmu_type(void *fdt, int cpu_offset, const char **mmu_type)
|
||||
{
|
||||
assert(mmu_type);
|
||||
|
||||
int len, rc;
|
||||
const void *prop;
|
||||
|
||||
|
@ -318,7 +409,7 @@ int fdt_parse_mmu_type(void *fdt, int cpu_offset, char *mmu_type)
|
|||
if (!prop || !len)
|
||||
return -EINVAL;
|
||||
|
||||
strcpy(mmu_type, (char *)prop);
|
||||
*mmu_type = (const char *)prop;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
8
vendor/riscv/riscv-isa-sim/riscv/dts.h
vendored
8
vendor/riscv/riscv-isa-sim/riscv/dts.h
vendored
|
@ -10,6 +10,7 @@
|
|||
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,
|
||||
std::vector<processor_t*> procs,
|
||||
std::vector<std::pair<reg_t, mem_t*>> mems);
|
||||
|
||||
|
@ -21,7 +22,12 @@ int fdt_get_next_subnode(void *fdt, int node);
|
|||
|
||||
int fdt_parse_clint(void *fdt, reg_t *clint_addr,
|
||||
const char *compatible);
|
||||
int fdt_parse_plic(void *fdt, reg_t *plic_addr, uint32_t *ndev,
|
||||
const char *compatible);
|
||||
int fdt_parse_ns16550(void *fdt, reg_t *ns16550_addr,
|
||||
uint32_t *reg_shift, uint32_t *reg_io_width,
|
||||
const char *compatible);
|
||||
int fdt_parse_pmp_num(void *fdt, int cpu_offset, reg_t *pmp_num);
|
||||
int fdt_parse_pmp_alignment(void *fdt, int cpu_offset, reg_t *pmp_align);
|
||||
int fdt_parse_mmu_type(void *fdt, int cpu_offset, char *mmu_type);
|
||||
int fdt_parse_mmu_type(void *fdt, int cpu_offset, const char **mmu_type);
|
||||
#endif
|
||||
|
|
7579
vendor/riscv/riscv-isa-sim/riscv/encoding.h
vendored
7579
vendor/riscv/riscv-isa-sim/riscv/encoding.h
vendored
File diff suppressed because it is too large
Load diff
|
@ -2,7 +2,7 @@
|
|||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include "internals.h"
|
||||
#include "common.h"
|
||||
|
||||
//
|
||||
// Used to model the cryptography extension entropy source.
|
||||
|
@ -30,13 +30,12 @@ public:
|
|||
// seed register
|
||||
// ------------------------------------------------------------
|
||||
|
||||
void set_seed(reg_t val) {
|
||||
void set_seed(reg_t UNUSED val) {
|
||||
// Always ignore writes to seed.
|
||||
// This CSR is strictly read only. It occupies a RW CSR address
|
||||
// to handle the side-effect of the changing seed value on a read.
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// The format of seed is described in Section 4.1 of
|
||||
// the scalar cryptography specification.
|
||||
|
@ -50,27 +49,27 @@ public:
|
|||
// the bare minimum.
|
||||
uint32_t return_status = OPST_ES16;
|
||||
|
||||
if(return_status == OPST_ES16) {
|
||||
if (return_status == OPST_ES16) {
|
||||
|
||||
// Add some sampled entropy into the low 16 bits
|
||||
uint16_t entropy = this -> get_two_random_bytes();
|
||||
result |= entropy;
|
||||
// Add some sampled entropy into the low 16 bits
|
||||
uint16_t entropy = this -> get_two_random_bytes();
|
||||
result |= entropy;
|
||||
|
||||
} else if(return_status == OPST_BIST) {
|
||||
} else if (return_status == OPST_BIST) {
|
||||
|
||||
// Do nothing.
|
||||
// Do nothing.
|
||||
|
||||
} else if(return_status == OPST_WAIT) {
|
||||
} else if (return_status == OPST_WAIT) {
|
||||
|
||||
// Do nothing.
|
||||
// Do nothing.
|
||||
|
||||
} else if(return_status == OPST_DEAD) {
|
||||
} else if (return_status == OPST_DEAD) {
|
||||
|
||||
// Do nothing. Stay dead.
|
||||
// Do nothing. Stay dead.
|
||||
|
||||
} else {
|
||||
|
||||
// Unreachable.
|
||||
// Unreachable.
|
||||
|
||||
}
|
||||
|
||||
|
@ -93,25 +92,25 @@ public:
|
|||
// Read two random bytes from the entropy source file.
|
||||
uint16_t get_two_random_bytes() {
|
||||
|
||||
std::ifstream fh(this -> randomness_source, std::ios::binary);
|
||||
std::ifstream fh(this -> randomness_source, std::ios::binary);
|
||||
|
||||
if(fh.is_open()) {
|
||||
if (fh.is_open()) {
|
||||
|
||||
uint16_t random_bytes;
|
||||
uint16_t random_bytes;
|
||||
|
||||
fh.read((char*)(&random_bytes), 2);
|
||||
fh.read((char*)(&random_bytes), 2);
|
||||
|
||||
fh.close();
|
||||
fh.close();
|
||||
|
||||
return random_bytes;
|
||||
return random_bytes;
|
||||
|
||||
} else {
|
||||
} else {
|
||||
|
||||
fprintf(stderr, "Could not open randomness source file:\n\t");
|
||||
fprintf(stderr, "%s", randomness_source.c_str());
|
||||
abort();
|
||||
fprintf(stderr, "Could not open randomness source file:\n\t");
|
||||
fprintf(stderr, "%s", randomness_source.c_str());
|
||||
abort();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
136
vendor/riscv/riscv-isa-sim/riscv/execute.cc
vendored
136
vendor/riscv/riscv-isa-sim/riscv/execute.cc
vendored
|
@ -1,11 +1,12 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "config.h"
|
||||
#include "processor.h"
|
||||
#include "mmu.h"
|
||||
#include "disasm.h"
|
||||
#include "decode_macros.h"
|
||||
#include <cassert>
|
||||
|
||||
#ifdef RISCV_ENABLE_COMMITLOG
|
||||
static void commit_log_reset(processor_t* p)
|
||||
{
|
||||
p->get_state()->log_reg_write.clear();
|
||||
|
@ -27,7 +28,7 @@ static void commit_log_print_value(FILE *log_file, int width, const void *data)
|
|||
|
||||
switch (width) {
|
||||
case 8:
|
||||
fprintf(log_file, "0x%01" PRIx8, *(const uint8_t *)data);
|
||||
fprintf(log_file, "0x%02" PRIx8, *(const uint8_t *)data);
|
||||
break;
|
||||
case 16:
|
||||
fprintf(log_file, "0x%04" PRIx16, *(const uint16_t *)data);
|
||||
|
@ -59,11 +60,6 @@ static void commit_log_print_value(FILE *log_file, int width, uint64_t val)
|
|||
commit_log_print_value(log_file, width, &val);
|
||||
}
|
||||
|
||||
const char* processor_t::get_symbol(uint64_t addr)
|
||||
{
|
||||
return sim->get_symbol(addr);
|
||||
}
|
||||
|
||||
static void commit_log_print_insn(processor_t *p, reg_t pc, insn_t insn)
|
||||
{
|
||||
FILE *log_file = p->get_log_file();
|
||||
|
@ -122,10 +118,10 @@ static void commit_log_print_insn(processor_t *p, reg_t pc, insn_t insn)
|
|||
|
||||
if (!show_vec && (is_vreg || is_vec)) {
|
||||
fprintf(log_file, " e%ld %s%ld l%ld",
|
||||
p->VU.vsew,
|
||||
(long)p->VU.vsew,
|
||||
p->VU.vflmul < 1 ? "mf" : "m",
|
||||
p->VU.vflmul < 1 ? (reg_t)(1 / p->VU.vflmul) : (reg_t)p->VU.vflmul,
|
||||
p->VU.vl->read());
|
||||
p->VU.vflmul < 1 ? (long)(1 / p->VU.vflmul) : (long)p->VU.vflmul,
|
||||
(long)p->VU.vl->read());
|
||||
show_vec = true;
|
||||
}
|
||||
|
||||
|
@ -133,7 +129,7 @@ static void commit_log_print_insn(processor_t *p, reg_t pc, insn_t insn)
|
|||
if (prefix == 'c')
|
||||
fprintf(log_file, " c%d_%s ", rd, csr_name(rd));
|
||||
else
|
||||
fprintf(log_file, " %c%2d ", prefix, rd);
|
||||
fprintf(log_file, " %c%-2d ", prefix, rd);
|
||||
if (is_vreg)
|
||||
commit_log_print_value(log_file, size, &p->VU.elt<uint8_t>(rd, 0));
|
||||
else
|
||||
|
@ -154,40 +150,34 @@ static void commit_log_print_insn(processor_t *p, reg_t pc, insn_t insn)
|
|||
}
|
||||
fprintf(log_file, "\n");
|
||||
}
|
||||
#else
|
||||
static void commit_log_reset(processor_t* p) {}
|
||||
static void commit_log_stash_privilege(processor_t* p) {}
|
||||
static void commit_log_print_insn(processor_t* p, reg_t pc, insn_t insn) {}
|
||||
#endif
|
||||
|
||||
inline void processor_t::update_histogram(reg_t pc)
|
||||
{
|
||||
#ifdef RISCV_ENABLE_HISTOGRAM
|
||||
pc_histogram[pc]++;
|
||||
#endif
|
||||
if (histogram_enabled)
|
||||
pc_histogram[pc]++;
|
||||
}
|
||||
|
||||
// This is expected to be inlined by the compiler so each use of execute_insn
|
||||
// includes a duplicated body of the function to get separate fetch.func
|
||||
// function calls.
|
||||
static inline reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
|
||||
// These two functions are expected to be inlined by the compiler separately in
|
||||
// the processor_t::step() loop. The logged variant is used in the slow path
|
||||
static inline reg_t execute_insn_fast(processor_t* p, reg_t pc, insn_fetch_t fetch) {
|
||||
return fetch.func(p, fetch.insn, pc);
|
||||
}
|
||||
static inline reg_t execute_insn_logged(processor_t* p, reg_t pc, insn_fetch_t fetch)
|
||||
{
|
||||
commit_log_reset(p);
|
||||
commit_log_stash_privilege(p);
|
||||
if (p->get_log_commits_enabled()) {
|
||||
commit_log_reset(p);
|
||||
commit_log_stash_privilege(p);
|
||||
}
|
||||
|
||||
reg_t npc;
|
||||
|
||||
try {
|
||||
npc = fetch.func(p, fetch.insn, pc);
|
||||
if (npc != PC_SERIALIZE_BEFORE) {
|
||||
|
||||
#ifdef RISCV_ENABLE_COMMITLOG
|
||||
if (p->get_log_commits_enabled()) {
|
||||
commit_log_print_insn(p, pc, fetch.insn);
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
#ifdef RISCV_ENABLE_COMMITLOG
|
||||
} catch (wait_for_interrupt_t &t) {
|
||||
if (p->get_log_commits_enabled()) {
|
||||
commit_log_print_insn(p, pc, fetch.insn);
|
||||
|
@ -204,7 +194,6 @@ static inline reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
|
|||
}
|
||||
}
|
||||
throw;
|
||||
#endif
|
||||
} catch(...) {
|
||||
throw;
|
||||
}
|
||||
|
@ -215,7 +204,8 @@ static inline reg_t execute_insn(processor_t* p, reg_t pc, insn_fetch_t fetch)
|
|||
|
||||
bool processor_t::slow_path()
|
||||
{
|
||||
return debug || state.single_step != state.STEP_NONE || state.debug_mode;
|
||||
return debug || state.single_step != state.STEP_NONE || state.debug_mode ||
|
||||
log_commits_enabled || histogram_enabled || in_wfi || check_triggers_icount;
|
||||
}
|
||||
|
||||
// fetch/decode/execute loop
|
||||
|
@ -238,19 +228,18 @@ void processor_t::step(size_t n)
|
|||
mmu_t* _mmu = mmu;
|
||||
|
||||
#define advance_pc() \
|
||||
if (unlikely(invalid_pc(pc))) { \
|
||||
switch (pc) { \
|
||||
case PC_SERIALIZE_BEFORE: state.serialized = true; break; \
|
||||
case PC_SERIALIZE_AFTER: ++instret; break; \
|
||||
case PC_SERIALIZE_WFI: n = ++instret; break; \
|
||||
default: abort(); \
|
||||
} \
|
||||
pc = state.pc; \
|
||||
break; \
|
||||
} else { \
|
||||
state.pc = pc; \
|
||||
instret++; \
|
||||
}
|
||||
if (unlikely(invalid_pc(pc))) { \
|
||||
switch (pc) { \
|
||||
case PC_SERIALIZE_BEFORE: state.serialized = true; break; \
|
||||
case PC_SERIALIZE_AFTER: ++instret; break; \
|
||||
default: abort(); \
|
||||
} \
|
||||
pc = state.pc; \
|
||||
break; \
|
||||
} else { \
|
||||
state.pc = pc; \
|
||||
instret++; \
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
|
@ -274,10 +263,24 @@ void processor_t::step(size_t n)
|
|||
state.single_step = state.STEP_STEPPED;
|
||||
}
|
||||
|
||||
if (!state.serialized && check_triggers_icount) {
|
||||
auto match = TM.detect_icount_match();
|
||||
if (match.has_value()) {
|
||||
assert(match->timing == triggers::TIMING_BEFORE);
|
||||
throw triggers::matched_t((triggers::operation_t)0, 0, match->action);
|
||||
}
|
||||
}
|
||||
|
||||
// debug mode wfis must nop
|
||||
if (unlikely(in_wfi && !state.debug_mode)) {
|
||||
throw wait_for_interrupt_t();
|
||||
}
|
||||
|
||||
in_wfi = false;
|
||||
insn_fetch_t fetch = mmu->load_insn(pc);
|
||||
if (debug && !state.serialized)
|
||||
disasm(fetch.insn);
|
||||
pc = execute_insn(this, pc, fetch);
|
||||
pc = execute_insn_logged(this, pc, fetch);
|
||||
advance_pc();
|
||||
}
|
||||
}
|
||||
|
@ -286,7 +289,7 @@ 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;
|
||||
pc = execute_insn(this, pc, fetch);
|
||||
pc = execute_insn_fast(this, pc, fetch);
|
||||
ic_entry = ic_entry->next;
|
||||
if (unlikely(ic_entry->tag != pc))
|
||||
break;
|
||||
|
@ -304,38 +307,26 @@ void processor_t::step(size_t n)
|
|||
take_trap(t, pc);
|
||||
n = instret;
|
||||
|
||||
if (unlikely(state.single_step == state.STEP_STEPPED)) {
|
||||
// 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);
|
||||
else if (unlikely(state.single_step == state.STEP_STEPPED)) {
|
||||
state.single_step = state.STEP_NONE;
|
||||
enter_debug_mode(DCSR_CAUSE_STEP);
|
||||
}
|
||||
}
|
||||
catch (trigger_matched_t& t)
|
||||
catch (triggers::matched_t& t)
|
||||
{
|
||||
if (mmu->matched_trigger) {
|
||||
// This exception came from the MMU. That means the instruction hasn't
|
||||
// fully executed yet. We start it again, but this time it won't throw
|
||||
// an exception because matched_trigger is already set. (All memory
|
||||
// instructions are idempotent so restarting is safe.)
|
||||
|
||||
insn_fetch_t fetch = mmu->load_insn(pc);
|
||||
pc = execute_insn(this, pc, fetch);
|
||||
advance_pc();
|
||||
|
||||
delete mmu->matched_trigger;
|
||||
mmu->matched_trigger = NULL;
|
||||
}
|
||||
switch (state.mcontrol[t.index].action) {
|
||||
case ACTION_DEBUG_MODE:
|
||||
enter_debug_mode(DCSR_CAUSE_HWBP);
|
||||
break;
|
||||
case ACTION_DEBUG_EXCEPTION: {
|
||||
trap_breakpoint trap(state.v, t.address);
|
||||
take_trap(trap, pc);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
take_trigger_action(t.action, t.address, pc);
|
||||
}
|
||||
catch(trap_debug_mode&)
|
||||
{
|
||||
enter_debug_mode(DCSR_CAUSE_SWBP);
|
||||
}
|
||||
catch (wait_for_interrupt_t &t)
|
||||
{
|
||||
|
@ -346,9 +337,14 @@ void processor_t::step(size_t n)
|
|||
// allows us to switch to other threads only once per idle loop in case
|
||||
// there is activity.
|
||||
n = ++instret;
|
||||
in_wfi = true;
|
||||
}
|
||||
|
||||
state.minstret->bump(instret);
|
||||
|
||||
// Model a hart whose CPI is 1.
|
||||
state.mcycle->bump(instret);
|
||||
|
||||
n -= instret;
|
||||
}
|
||||
}
|
||||
|
|
2
vendor/riscv/riscv-isa-sim/riscv/extension.h
vendored
2
vendor/riscv/riscv-isa-sim/riscv/extension.h
vendored
|
@ -15,7 +15,7 @@ class extension_t
|
|||
virtual std::vector<disasm_insn_t*> get_disasms() = 0;
|
||||
virtual const char* name() = 0;
|
||||
virtual void reset() {};
|
||||
virtual void set_debug(bool value) {};
|
||||
virtual void set_debug(bool UNUSED value) {}
|
||||
virtual ~extension_t();
|
||||
|
||||
void set_processor(processor_t* _p) { p = _p; }
|
||||
|
|
|
@ -4,6 +4,6 @@
|
|||
// These conflict with Boost headers so can't be included from insn_template.h
|
||||
#define P (*p)
|
||||
|
||||
#define require(x) do { if (unlikely(!(x))) throw trap_illegal_instruction(insn.bits()); } while (0)
|
||||
#define require(x) (unlikely(!(x)) ? throw trap_illegal_instruction(insn.bits()) : (void) 0)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3,7 +3,9 @@
|
|||
#include "insn_template.h"
|
||||
#include "insn_macros.h"
|
||||
|
||||
reg_t rv32i_NAME(processor_t* p, insn_t insn, reg_t pc)
|
||||
#define DECODE_MACRO_USAGE_LOGGED 0
|
||||
|
||||
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));
|
||||
|
@ -13,7 +15,30 @@ reg_t rv32i_NAME(processor_t* p, insn_t insn, reg_t pc)
|
|||
return npc;
|
||||
}
|
||||
|
||||
reg_t rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
|
||||
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));
|
||||
#include "insns/NAME.h"
|
||||
trace_opcode(p, OPCODE, insn);
|
||||
#undef xlen
|
||||
return npc;
|
||||
}
|
||||
|
||||
#undef DECODE_MACRO_USAGE_LOGGED
|
||||
#define DECODE_MACRO_USAGE_LOGGED 1
|
||||
|
||||
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));
|
||||
#include "insns/NAME.h"
|
||||
trace_opcode(p, OPCODE, insn);
|
||||
#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));
|
||||
|
@ -26,7 +51,10 @@ reg_t rv64i_NAME(processor_t* p, insn_t insn, reg_t pc)
|
|||
#undef CHECK_REG
|
||||
#define CHECK_REG(reg) require((reg) < 16)
|
||||
|
||||
reg_t rv32e_NAME(processor_t* p, insn_t insn, reg_t pc)
|
||||
#undef DECODE_MACRO_USAGE_LOGGED
|
||||
#define DECODE_MACRO_USAGE_LOGGED 0
|
||||
|
||||
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));
|
||||
|
@ -36,7 +64,30 @@ reg_t rv32e_NAME(processor_t* p, insn_t insn, reg_t pc)
|
|||
return npc;
|
||||
}
|
||||
|
||||
reg_t rv64e_NAME(processor_t* p, insn_t insn, reg_t pc)
|
||||
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));
|
||||
#include "insns/NAME.h"
|
||||
trace_opcode(p, OPCODE, insn);
|
||||
#undef xlen
|
||||
return npc;
|
||||
}
|
||||
|
||||
#undef DECODE_MACRO_USAGE_LOGGED
|
||||
#define DECODE_MACRO_USAGE_LOGGED 1
|
||||
|
||||
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));
|
||||
#include "insns/NAME.h"
|
||||
trace_opcode(p, OPCODE, insn);
|
||||
#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));
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
// See LICENSE for license details.
|
||||
|
||||
#include "decode_macros.h"
|
||||
#include "arith.h"
|
||||
#include "mmu.h"
|
||||
#include "softfloat.h"
|
||||
#include "internals.h"
|
||||
#include "specialize.h"
|
||||
#include "tracer.h"
|
||||
#include "p_ext_macros.h"
|
||||
#include "v_ext_macros.h"
|
||||
#include <assert.h>
|
||||
|
|
|
@ -10,16 +10,13 @@ uint8_t round_consts [10] = {
|
|||
|
||||
uint8_t enc_rcon = insn.rcon() ;
|
||||
|
||||
if(enc_rcon > 0xA) {
|
||||
// Invalid opcode.
|
||||
throw trap_illegal_instruction(0);
|
||||
}
|
||||
require(enc_rcon <= 0xA);
|
||||
|
||||
uint32_t temp = (RS1 >> 32) & 0xFFFFFFFF ;
|
||||
uint8_t rcon = 0 ;
|
||||
uint64_t result ;
|
||||
|
||||
if(enc_rcon != 0xA) {
|
||||
if (enc_rcon != 0xA) {
|
||||
temp = (temp >> 8) | (temp << 24); // Rotate right by 8
|
||||
rcon = round_consts[enc_rcon];
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
uint8_t AES_ENC_SBOX[]= {
|
||||
static uint8_t UNUSED AES_ENC_SBOX[]= {
|
||||
0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5,
|
||||
0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
|
||||
0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0,
|
||||
|
@ -34,7 +34,7 @@ uint8_t AES_ENC_SBOX[]= {
|
|||
0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
|
||||
};
|
||||
|
||||
uint8_t AES_DEC_SBOX[] = {
|
||||
static uint8_t UNUSED AES_DEC_SBOX[] = {
|
||||
0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38,
|
||||
0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
|
||||
0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87,
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs + RS2; }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs + RS2; }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs + RS2; })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs + RS2; })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs & RS2; }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs & RS2; }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs & RS2; })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs & RS2; })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::max(lhs, int64_t(RS2)); }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](int64_t lhs) { return std::max(lhs, int64_t(RS2)); }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::max(lhs, int32_t(RS2)); })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](int32_t lhs) { return std::max(lhs, int32_t(RS2)); })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::max(lhs, RS2); }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return std::max(lhs, RS2); }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::max(lhs, uint32_t(RS2)); })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return std::max(lhs, uint32_t(RS2)); })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](int64_t lhs) { return std::min(lhs, int64_t(RS2)); }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](int64_t lhs) { return std::min(lhs, int64_t(RS2)); }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](int32_t lhs) { return std::min(lhs, int32_t(RS2)); })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](int32_t lhs) { return std::min(lhs, int32_t(RS2)); })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return std::min(lhs, RS2); }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return std::min(lhs, RS2); }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return std::min(lhs, uint32_t(RS2)); })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return std::min(lhs, uint32_t(RS2)); })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return lhs | RS2; }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t lhs) { return lhs | RS2; }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return lhs | RS2; })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t lhs) { return lhs | RS2; })));
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
require_extension('A');
|
||||
require_rv64;
|
||||
WRITE_RD(MMU.amo_uint64(RS1, [&](uint64_t lhs) { return RS2; }));
|
||||
WRITE_RD(MMU.amo<uint64_t>(RS1, [&](uint64_t UNUSED lhs) { return RS2; }));
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
require_extension('A');
|
||||
WRITE_RD(sext32(MMU.amo_uint32(RS1, [&](uint32_t lhs) { return RS2; })));
|
||||
WRITE_RD(sext32(MMU.amo<uint32_t>(RS1, [&](uint32_t UNUSED lhs) { return RS2; })));
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue