NJU-ProjectN/nemu ics2023 initialized
NJU-ProjectN/nemu eb63cf3568dbf4e0c3c6ef462e6ec685550fabbc Merge pull request #76 from rijuyuezhu/master
This commit is contained in:
parent
1efe03efb9
commit
2824efad33
141 changed files with 19573 additions and 0 deletions
12
nemu/.gitignore
vendored
Normal file
12
nemu/.gitignore
vendored
Normal file
|
@ -0,0 +1,12 @@
|
|||
*.*
|
||||
*
|
||||
!*/
|
||||
!Makefile
|
||||
!*.mk
|
||||
!*.[cSh]
|
||||
!*.cc
|
||||
!.gitignore
|
||||
!README.md
|
||||
!Kconfig
|
||||
include/config
|
||||
include/generated
|
217
nemu/Kconfig
Normal file
217
nemu/Kconfig
Normal file
|
@ -0,0 +1,217 @@
|
|||
mainmenu "NEMU Configuration Menu"
|
||||
|
||||
choice
|
||||
prompt "Base ISA"
|
||||
default ISA_riscv
|
||||
config ISA_x86
|
||||
bool "x86"
|
||||
config ISA_mips32
|
||||
bool "mips32"
|
||||
config ISA_riscv
|
||||
bool "riscv"
|
||||
config ISA_loongarch32r
|
||||
bool "loongarch32r"
|
||||
endchoice
|
||||
|
||||
config ISA
|
||||
string
|
||||
default "x86" if ISA_x86
|
||||
default "mips32" if ISA_mips32
|
||||
default "riscv32" if ISA_riscv && !RV64
|
||||
default "riscv64" if ISA_riscv && RV64
|
||||
default "loongarch32r" if ISA_loongarch32r
|
||||
default "none"
|
||||
|
||||
config ISA64
|
||||
depends on ISA_riscv && RV64
|
||||
bool
|
||||
default y
|
||||
|
||||
|
||||
if ISA_riscv
|
||||
source "src/isa/riscv32/Kconfig"
|
||||
endif
|
||||
|
||||
choice
|
||||
prompt "NEMU execution engine"
|
||||
default ENGINE_INTERPRETER
|
||||
|
||||
config ENGINE_INTERPRETER
|
||||
bool "Interpreter"
|
||||
help
|
||||
Interpreter guest instructions one by one.
|
||||
endchoice
|
||||
|
||||
config ENGINE
|
||||
string
|
||||
default "interpreter" if ENGINE_INTERPRETER
|
||||
default "none"
|
||||
|
||||
choice
|
||||
prompt "Running mode"
|
||||
default MODE_SYSTEM
|
||||
|
||||
config MODE_SYSTEM
|
||||
bool "System mode"
|
||||
help
|
||||
Support full-system functionality, including privileged instructions, MMU and devices.
|
||||
endchoice
|
||||
|
||||
choice
|
||||
prompt "Build target"
|
||||
default TARGET_NATIVE_ELF
|
||||
config TARGET_NATIVE_ELF
|
||||
bool "Executable on Linux Native"
|
||||
config TARGET_SHARE
|
||||
bool "Shared object (used as REF for differential testing)"
|
||||
config TARGET_AM
|
||||
bool "Application on Abstract-Machine (DON'T CHOOSE)"
|
||||
endchoice
|
||||
|
||||
menu "Build Options"
|
||||
choice
|
||||
prompt "Compiler"
|
||||
default CC_GCC
|
||||
config CC_GCC
|
||||
bool "gcc"
|
||||
config CC_GPP
|
||||
bool "g++"
|
||||
config CC_CLANG
|
||||
depends on !TARGET_AM
|
||||
bool "clang"
|
||||
endchoice
|
||||
|
||||
config CC
|
||||
string
|
||||
default "gcc" if CC_GCC
|
||||
default "g++" if CC_GPP
|
||||
default "clang" if CC_CLANG
|
||||
default "none"
|
||||
|
||||
choice
|
||||
prompt "Optimization Level"
|
||||
default CC_O2
|
||||
config CC_O0
|
||||
bool "O0"
|
||||
config CC_O1
|
||||
bool "O1"
|
||||
config CC_O2
|
||||
bool "O2"
|
||||
config CC_O3
|
||||
bool "O3"
|
||||
endchoice
|
||||
|
||||
config CC_OPT
|
||||
string
|
||||
default "-O0" if CC_O0
|
||||
default "-O1" if CC_O1
|
||||
default "-O2" if CC_O2
|
||||
default "-O3" if CC_O3
|
||||
default "none"
|
||||
|
||||
config CC_LTO
|
||||
depends on !TARGET_AM
|
||||
bool "Enable link-time optimization"
|
||||
default n
|
||||
|
||||
config CC_DEBUG
|
||||
bool "Enable debug information"
|
||||
default n
|
||||
|
||||
config CC_ASAN
|
||||
depends on MODE_SYSTEM
|
||||
bool "Enable address sanitizer"
|
||||
default n
|
||||
endmenu
|
||||
|
||||
menu "Testing and Debugging"
|
||||
|
||||
|
||||
config TRACE
|
||||
bool "Enable tracer"
|
||||
default y
|
||||
|
||||
config TRACE_START
|
||||
depends on TRACE
|
||||
int "When tracing is enabled (unit: number of instructions)"
|
||||
default 0
|
||||
|
||||
config TRACE_END
|
||||
depends on TRACE
|
||||
int "When tracing is disabled (unit: number of instructions)"
|
||||
default 10000
|
||||
|
||||
config ITRACE
|
||||
depends on TRACE && TARGET_NATIVE_ELF && ENGINE_INTERPRETER
|
||||
bool "Enable instruction tracer"
|
||||
default y
|
||||
|
||||
config ITRACE_COND
|
||||
depends on ITRACE
|
||||
string "Only trace instructions when the condition is true"
|
||||
default "true"
|
||||
|
||||
|
||||
config DIFFTEST
|
||||
depends on TARGET_NATIVE_ELF
|
||||
bool "Enable differential testing"
|
||||
default n
|
||||
help
|
||||
Enable differential testing with a reference design.
|
||||
Note that this will significantly reduce the performance of NEMU.
|
||||
|
||||
choice
|
||||
prompt "Reference design"
|
||||
default DIFFTEST_REF_SPIKE if ISA_riscv
|
||||
default DIFFTEST_REF_KVM if ISA_x86
|
||||
default DIFFTEST_REF_QEMU
|
||||
depends on DIFFTEST
|
||||
config DIFFTEST_REF_QEMU
|
||||
bool "QEMU, communicate with socket"
|
||||
if ISA_riscv
|
||||
config DIFFTEST_REF_SPIKE
|
||||
bool "Spike"
|
||||
endif
|
||||
if ISA_x86
|
||||
config DIFFTEST_REF_KVM
|
||||
bool "KVM"
|
||||
endif
|
||||
endchoice
|
||||
|
||||
config DIFFTEST_REF_PATH
|
||||
string
|
||||
default "tools/qemu-diff" if DIFFTEST_REF_QEMU
|
||||
default "tools/kvm-diff" if DIFFTEST_REF_KVM
|
||||
default "tools/spike-diff" if DIFFTEST_REF_SPIKE
|
||||
default "none"
|
||||
|
||||
config DIFFTEST_REF_NAME
|
||||
string
|
||||
default "qemu" if DIFFTEST_REF_QEMU
|
||||
default "kvm" if DIFFTEST_REF_KVM
|
||||
default "spike" if DIFFTEST_REF_SPIKE
|
||||
default "none"
|
||||
endmenu
|
||||
|
||||
if MODE_SYSTEM
|
||||
source "src/memory/Kconfig"
|
||||
source "src/device/Kconfig"
|
||||
endif
|
||||
|
||||
|
||||
menu "Miscellaneous"
|
||||
choice
|
||||
depends on !TARGET_AM
|
||||
prompt "Host timer"
|
||||
default TIMER_GETTIMEOFDAY
|
||||
config TIMER_GETTIMEOFDAY
|
||||
bool "gettimeofday"
|
||||
config TIMER_CLOCK_GETTIME
|
||||
bool "clock_gettime"
|
||||
endchoice
|
||||
|
||||
config RT_CHECK
|
||||
bool "Enable runtime checking"
|
||||
default y
|
||||
|
||||
endmenu
|
61
nemu/Makefile
Normal file
61
nemu/Makefile
Normal file
|
@ -0,0 +1,61 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
# Sanity check
|
||||
ifeq ($(wildcard $(NEMU_HOME)/src/nemu-main.c),)
|
||||
$(error NEMU_HOME=$(NEMU_HOME) is not a NEMU repo)
|
||||
endif
|
||||
|
||||
# Include variables and rules generated by menuconfig
|
||||
-include $(NEMU_HOME)/include/config/auto.conf
|
||||
-include $(NEMU_HOME)/include/config/auto.conf.cmd
|
||||
|
||||
remove_quote = $(patsubst "%",%,$(1))
|
||||
|
||||
# Extract variabls from menuconfig
|
||||
GUEST_ISA ?= $(call remove_quote,$(CONFIG_ISA))
|
||||
ENGINE ?= $(call remove_quote,$(CONFIG_ENGINE))
|
||||
NAME = $(GUEST_ISA)-nemu-$(ENGINE)
|
||||
|
||||
# Include all filelist.mk to merge file lists
|
||||
FILELIST_MK = $(shell find -L ./src -name "filelist.mk")
|
||||
include $(FILELIST_MK)
|
||||
|
||||
# Filter out directories and files in blacklist to obtain the final set of source files
|
||||
DIRS-BLACKLIST-y += $(DIRS-BLACKLIST)
|
||||
SRCS-BLACKLIST-y += $(SRCS-BLACKLIST) $(shell find -L $(DIRS-BLACKLIST-y) -name "*.c")
|
||||
SRCS-y += $(shell find -L $(DIRS-y) -name "*.c")
|
||||
SRCS = $(filter-out $(SRCS-BLACKLIST-y),$(SRCS-y))
|
||||
|
||||
# Extract compiler and options from menuconfig
|
||||
CC = $(call remove_quote,$(CONFIG_CC))
|
||||
CFLAGS_BUILD += $(call remove_quote,$(CONFIG_CC_OPT))
|
||||
CFLAGS_BUILD += $(if $(CONFIG_CC_LTO),-flto,)
|
||||
CFLAGS_BUILD += $(if $(CONFIG_CC_DEBUG),-Og -ggdb3,)
|
||||
CFLAGS_BUILD += $(if $(CONFIG_CC_ASAN),-fsanitize=address,)
|
||||
CFLAGS_TRACE += -DITRACE_COND=$(if $(CONFIG_ITRACE_COND),$(call remove_quote,$(CONFIG_ITRACE_COND)),true)
|
||||
CFLAGS += $(CFLAGS_BUILD) $(CFLAGS_TRACE) -D__GUEST_ISA__=$(GUEST_ISA)
|
||||
LDFLAGS += $(CFLAGS_BUILD)
|
||||
|
||||
# Include rules for menuconfig
|
||||
include $(NEMU_HOME)/scripts/config.mk
|
||||
|
||||
ifdef CONFIG_TARGET_AM
|
||||
include $(AM_HOME)/Makefile
|
||||
LINKAGE += $(ARCHIVES)
|
||||
else
|
||||
# Include rules to build NEMU
|
||||
include $(NEMU_HOME)/scripts/native.mk
|
||||
endif
|
35
nemu/README.md
Normal file
35
nemu/README.md
Normal file
|
@ -0,0 +1,35 @@
|
|||
# NEMU
|
||||
|
||||
NEMU(NJU Emulator) is a simple but complete full-system emulator designed for teaching purpose.
|
||||
Currently it supports x86, mips32, riscv32 and riscv64.
|
||||
To build programs run above NEMU, refer to the [AM project](https://github.com/NJU-ProjectN/abstract-machine).
|
||||
|
||||
The main features of NEMU include
|
||||
* a small monitor with a simple debugger
|
||||
* single step
|
||||
* register/memory examination
|
||||
* expression evaluation without the support of symbols
|
||||
* watch point
|
||||
* differential testing with reference design (e.g. QEMU)
|
||||
* snapshot
|
||||
* CPU core with support of most common used instructions
|
||||
* x86
|
||||
* real mode is not supported
|
||||
* x87 floating point instructions are not supported
|
||||
* mips32
|
||||
* CP1 floating point instructions are not supported
|
||||
* riscv32
|
||||
* only RV32IM
|
||||
* riscv64
|
||||
* only RV64IM
|
||||
* memory
|
||||
* paging
|
||||
* TLB is optional (but necessary for mips32)
|
||||
* protection is not supported
|
||||
* interrupt and exception
|
||||
* protection is not supported
|
||||
* 5 devices
|
||||
* serial, timer, keyboard, VGA, audio
|
||||
* most of them are simplified and unprogrammable
|
||||
* 2 types of I/O
|
||||
* port-mapped I/O and memory-mapped I/O
|
1
nemu/configs/.gitignore
vendored
Normal file
1
nemu/configs/.gitignore
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
!*_defconfig
|
5
nemu/configs/mips32-am_defconfig
Normal file
5
nemu/configs/mips32-am_defconfig
Normal file
|
@ -0,0 +1,5 @@
|
|||
CONFIG_ISA_mips32=y
|
||||
CONFIG_TARGET_AM=y
|
||||
# CONFIG_TRACE is not set
|
||||
CONFIG_MSIZE=0x2000000
|
||||
CONFIG_DEVICE=y
|
4
nemu/configs/riscv32-am_defconfig
Normal file
4
nemu/configs/riscv32-am_defconfig
Normal file
|
@ -0,0 +1,4 @@
|
|||
CONFIG_TARGET_AM=y
|
||||
# CONFIG_TRACE is not set
|
||||
CONFIG_MSIZE=0x2000000
|
||||
CONFIG_DEVICE=y
|
5
nemu/configs/riscv64-am_defconfig
Normal file
5
nemu/configs/riscv64-am_defconfig
Normal file
|
@ -0,0 +1,5 @@
|
|||
CONFIG_ISA_riscv64=y
|
||||
CONFIG_TARGET_AM=y
|
||||
# CONFIG_TRACE is not set
|
||||
CONFIG_MSIZE=0x2000000
|
||||
CONFIG_DEVICE=y
|
49
nemu/include/common.h
Normal file
49
nemu/include/common.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __COMMON_H__
|
||||
#define __COMMON_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <generated/autoconf.h>
|
||||
#include <macro.h>
|
||||
|
||||
#ifdef CONFIG_TARGET_AM
|
||||
#include <klib.h>
|
||||
#else
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#endif
|
||||
|
||||
#if CONFIG_MBASE + CONFIG_MSIZE > 0x100000000ul
|
||||
#define PMEM64 1
|
||||
#endif
|
||||
|
||||
typedef MUXDEF(CONFIG_ISA64, uint64_t, uint32_t) word_t;
|
||||
typedef MUXDEF(CONFIG_ISA64, int64_t, int32_t) sword_t;
|
||||
#define FMT_WORD MUXDEF(CONFIG_ISA64, "0x%016" PRIx64, "0x%08" PRIx32)
|
||||
|
||||
typedef word_t vaddr_t;
|
||||
typedef MUXDEF(PMEM64, uint64_t, uint32_t) paddr_t;
|
||||
#define FMT_PADDR MUXDEF(PMEM64, "0x%016" PRIx64, "0x%08" PRIx32)
|
||||
typedef uint16_t ioaddr_t;
|
||||
|
||||
#include <debug.h>
|
||||
|
||||
#endif
|
29
nemu/include/cpu/cpu.h
Normal file
29
nemu/include/cpu/cpu.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __CPU_CPU_H__
|
||||
#define __CPU_CPU_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
void cpu_exec(uint64_t n);
|
||||
|
||||
void set_nemu_state(int state, vaddr_t pc, int halt_ret);
|
||||
void invalid_inst(vaddr_t thispc);
|
||||
|
||||
#define NEMUTRAP(thispc, code) set_nemu_state(NEMU_END, thispc, code)
|
||||
#define INV(thispc) invalid_inst(thispc)
|
||||
|
||||
#endif
|
102
nemu/include/cpu/decode.h
Normal file
102
nemu/include/cpu/decode.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __CPU_DECODE_H__
|
||||
#define __CPU_DECODE_H__
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
typedef struct Decode {
|
||||
vaddr_t pc;
|
||||
vaddr_t snpc; // static next pc
|
||||
vaddr_t dnpc; // dynamic next pc
|
||||
ISADecodeInfo isa;
|
||||
IFDEF(CONFIG_ITRACE, char logbuf[128]);
|
||||
} Decode;
|
||||
|
||||
// --- pattern matching mechanism ---
|
||||
__attribute__((always_inline))
|
||||
static inline void pattern_decode(const char *str, int len,
|
||||
uint64_t *key, uint64_t *mask, uint64_t *shift) {
|
||||
uint64_t __key = 0, __mask = 0, __shift = 0;
|
||||
#define macro(i) \
|
||||
if ((i) >= len) goto finish; \
|
||||
else { \
|
||||
char c = str[i]; \
|
||||
if (c != ' ') { \
|
||||
Assert(c == '0' || c == '1' || c == '?', \
|
||||
"invalid character '%c' in pattern string", c); \
|
||||
__key = (__key << 1) | (c == '1' ? 1 : 0); \
|
||||
__mask = (__mask << 1) | (c == '?' ? 0 : 1); \
|
||||
__shift = (c == '?' ? __shift + 1 : 0); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define macro2(i) macro(i); macro((i) + 1)
|
||||
#define macro4(i) macro2(i); macro2((i) + 2)
|
||||
#define macro8(i) macro4(i); macro4((i) + 4)
|
||||
#define macro16(i) macro8(i); macro8((i) + 8)
|
||||
#define macro32(i) macro16(i); macro16((i) + 16)
|
||||
#define macro64(i) macro32(i); macro32((i) + 32)
|
||||
macro64(0);
|
||||
panic("pattern too long");
|
||||
#undef macro
|
||||
finish:
|
||||
*key = __key >> __shift;
|
||||
*mask = __mask >> __shift;
|
||||
*shift = __shift;
|
||||
}
|
||||
|
||||
__attribute__((always_inline))
|
||||
static inline void pattern_decode_hex(const char *str, int len,
|
||||
uint64_t *key, uint64_t *mask, uint64_t *shift) {
|
||||
uint64_t __key = 0, __mask = 0, __shift = 0;
|
||||
#define macro(i) \
|
||||
if ((i) >= len) goto finish; \
|
||||
else { \
|
||||
char c = str[i]; \
|
||||
if (c != ' ') { \
|
||||
Assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f') || c == '?', \
|
||||
"invalid character '%c' in pattern string", c); \
|
||||
__key = (__key << 4) | (c == '?' ? 0 : (c >= '0' && c <= '9') ? c - '0' : c - 'a' + 10); \
|
||||
__mask = (__mask << 4) | (c == '?' ? 0 : 0xf); \
|
||||
__shift = (c == '?' ? __shift + 4 : 0); \
|
||||
} \
|
||||
}
|
||||
|
||||
macro16(0);
|
||||
panic("pattern too long");
|
||||
#undef macro
|
||||
finish:
|
||||
*key = __key >> __shift;
|
||||
*mask = __mask >> __shift;
|
||||
*shift = __shift;
|
||||
}
|
||||
|
||||
|
||||
// --- pattern matching wrappers for decode ---
|
||||
#define INSTPAT(pattern, ...) do { \
|
||||
uint64_t key, mask, shift; \
|
||||
pattern_decode(pattern, STRLEN(pattern), &key, &mask, &shift); \
|
||||
if ((((uint64_t)INSTPAT_INST(s) >> shift) & mask) == key) { \
|
||||
INSTPAT_MATCH(s, ##__VA_ARGS__); \
|
||||
goto *(__instpat_end); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define INSTPAT_START(name) { const void ** __instpat_end = &&concat(__instpat_end_, name);
|
||||
#define INSTPAT_END(name) concat(__instpat_end_, name): ; }
|
||||
|
||||
#endif
|
53
nemu/include/cpu/difftest.h
Normal file
53
nemu/include/cpu/difftest.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __CPU_DIFFTEST_H__
|
||||
#define __CPU_DIFFTEST_H__
|
||||
|
||||
#include <common.h>
|
||||
#include <difftest-def.h>
|
||||
|
||||
#ifdef CONFIG_DIFFTEST
|
||||
void difftest_skip_ref();
|
||||
void difftest_skip_dut(int nr_ref, int nr_dut);
|
||||
void difftest_set_patch(void (*fn)(void *arg), void *arg);
|
||||
void difftest_step(vaddr_t pc, vaddr_t npc);
|
||||
void difftest_detach();
|
||||
void difftest_attach();
|
||||
#else
|
||||
static inline void difftest_skip_ref() {}
|
||||
static inline void difftest_skip_dut(int nr_ref, int nr_dut) {}
|
||||
static inline void difftest_set_patch(void (*fn)(void *arg), void *arg) {}
|
||||
static inline void difftest_step(vaddr_t pc, vaddr_t npc) {}
|
||||
static inline void difftest_detach() {}
|
||||
static inline void difftest_attach() {}
|
||||
#endif
|
||||
|
||||
extern void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction);
|
||||
extern void (*ref_difftest_regcpy)(void *dut, bool direction);
|
||||
extern void (*ref_difftest_exec)(uint64_t n);
|
||||
extern void (*ref_difftest_raise_intr)(uint64_t NO);
|
||||
|
||||
static inline bool difftest_check_reg(const char *name, vaddr_t pc, word_t ref, word_t dut) {
|
||||
if (ref != dut) {
|
||||
Log("%s is different after executing instruction at pc = " FMT_WORD
|
||||
", right = " FMT_WORD ", wrong = " FMT_WORD ", diff = " FMT_WORD,
|
||||
name, pc, ref, dut, ref ^ dut);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
26
nemu/include/cpu/ifetch.h
Normal file
26
nemu/include/cpu/ifetch.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __CPU_IFETCH_H__
|
||||
|
||||
#include <memory/vaddr.h>
|
||||
|
||||
static inline uint32_t inst_fetch(vaddr_t *pc, int len) {
|
||||
uint32_t inst = vaddr_ifetch(*pc, len);
|
||||
(*pc) += len;
|
||||
return inst;
|
||||
}
|
||||
|
||||
#endif
|
43
nemu/include/debug.h
Normal file
43
nemu/include/debug.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __DEBUG_H__
|
||||
#define __DEBUG_H__
|
||||
|
||||
#include <common.h>
|
||||
#include <stdio.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define Log(format, ...) \
|
||||
_Log(ANSI_FMT("[%s:%d %s] " format, ANSI_FG_BLUE) "\n", \
|
||||
__FILE__, __LINE__, __func__, ## __VA_ARGS__)
|
||||
|
||||
#define Assert(cond, format, ...) \
|
||||
do { \
|
||||
if (!(cond)) { \
|
||||
MUXDEF(CONFIG_TARGET_AM, printf(ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__), \
|
||||
(fflush(stdout), fprintf(stderr, ANSI_FMT(format, ANSI_FG_RED) "\n", ## __VA_ARGS__))); \
|
||||
IFNDEF(CONFIG_TARGET_AM, extern FILE* log_fp; fflush(log_fp)); \
|
||||
extern void assert_fail_msg(); \
|
||||
assert_fail_msg(); \
|
||||
assert(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define panic(format, ...) Assert(0, format, ## __VA_ARGS__)
|
||||
|
||||
#define TODO() panic("please implement me")
|
||||
|
||||
#endif
|
24
nemu/include/device/alarm.h
Normal file
24
nemu/include/device/alarm.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __DEVICE_ALARM_H__
|
||||
#define __DEVICE_ALARM_H__
|
||||
|
||||
#define TIMER_HZ 60
|
||||
|
||||
typedef void (*alarm_handler_t) ();
|
||||
void add_alarm_handle(alarm_handler_t h);
|
||||
|
||||
#endif
|
56
nemu/include/device/map.h
Normal file
56
nemu/include/device/map.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __DEVICE_MAP_H__
|
||||
#define __DEVICE_MAP_H__
|
||||
|
||||
#include <cpu/difftest.h>
|
||||
|
||||
typedef void(*io_callback_t)(uint32_t, int, bool);
|
||||
uint8_t* new_space(int size);
|
||||
|
||||
typedef struct {
|
||||
const char *name;
|
||||
// we treat ioaddr_t as paddr_t here
|
||||
paddr_t low;
|
||||
paddr_t high;
|
||||
void *space;
|
||||
io_callback_t callback;
|
||||
} IOMap;
|
||||
|
||||
static inline bool map_inside(IOMap *map, paddr_t addr) {
|
||||
return (addr >= map->low && addr <= map->high);
|
||||
}
|
||||
|
||||
static inline int find_mapid_by_addr(IOMap *maps, int size, paddr_t addr) {
|
||||
int i;
|
||||
for (i = 0; i < size; i ++) {
|
||||
if (map_inside(maps + i, addr)) {
|
||||
difftest_skip_ref();
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void add_pio_map(const char *name, ioaddr_t addr,
|
||||
void *space, uint32_t len, io_callback_t callback);
|
||||
void add_mmio_map(const char *name, paddr_t addr,
|
||||
void *space, uint32_t len, io_callback_t callback);
|
||||
|
||||
word_t map_read(paddr_t addr, int len, IOMap *map);
|
||||
void map_write(paddr_t addr, int len, word_t data, IOMap *map);
|
||||
|
||||
#endif
|
24
nemu/include/device/mmio.h
Normal file
24
nemu/include/device/mmio.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __DEVICE_MMIO_H__
|
||||
#define __DEVICE_MMIO_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
word_t mmio_read(paddr_t addr, int len);
|
||||
void mmio_write(paddr_t addr, int len, word_t data);
|
||||
|
||||
#endif
|
40
nemu/include/difftest-def.h
Normal file
40
nemu/include/difftest-def.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __DIFFTEST_DEF_H__
|
||||
#define __DIFFTEST_DEF_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <macro.h>
|
||||
#include <generated/autoconf.h>
|
||||
|
||||
#define __EXPORT __attribute__((visibility("default")))
|
||||
enum { DIFFTEST_TO_DUT, DIFFTEST_TO_REF };
|
||||
|
||||
#if defined(CONFIG_ISA_x86)
|
||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 9) // GPRs + pc
|
||||
#elif defined(CONFIG_ISA_mips32)
|
||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 38) // GPRs + status + lo + hi + badvaddr + cause + pc
|
||||
#elif defined(CONFIG_ISA_riscv)
|
||||
#define RISCV_GPR_TYPE MUXDEF(CONFIG_RV64, uint64_t, uint32_t)
|
||||
#define RISCV_GPR_NUM MUXDEF(CONFIG_RVE , 16, 32)
|
||||
#define DIFFTEST_REG_SIZE (sizeof(RISCV_GPR_TYPE) * (RISCV_GPR_NUM + 1)) // GPRs + pc
|
||||
#elif defined(CONFIG_ISA_loongarch32r)
|
||||
# define DIFFTEST_REG_SIZE (sizeof(uint32_t) * 33) // GPRs + pc
|
||||
#else
|
||||
# error Unsupport ISA
|
||||
#endif
|
||||
|
||||
#endif
|
58
nemu/include/isa.h
Normal file
58
nemu/include/isa.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __ISA_H__
|
||||
#define __ISA_H__
|
||||
|
||||
// Located at src/isa/$(GUEST_ISA)/include/isa-def.h
|
||||
#include <isa-def.h>
|
||||
|
||||
// The macro `__GUEST_ISA__` is defined in $(CFLAGS).
|
||||
// It will be expanded as "x86" or "mips32" ...
|
||||
typedef concat(__GUEST_ISA__, _CPU_state) CPU_state;
|
||||
typedef concat(__GUEST_ISA__, _ISADecodeInfo) ISADecodeInfo;
|
||||
|
||||
// monitor
|
||||
extern unsigned char isa_logo[];
|
||||
void init_isa();
|
||||
|
||||
// reg
|
||||
extern CPU_state cpu;
|
||||
void isa_reg_display();
|
||||
word_t isa_reg_str2val(const char *name, bool *success);
|
||||
|
||||
// exec
|
||||
struct Decode;
|
||||
int isa_exec_once(struct Decode *s);
|
||||
|
||||
// memory
|
||||
enum { MMU_DIRECT, MMU_TRANSLATE, MMU_FAIL };
|
||||
enum { MEM_TYPE_IFETCH, MEM_TYPE_READ, MEM_TYPE_WRITE };
|
||||
enum { MEM_RET_OK, MEM_RET_FAIL, MEM_RET_CROSS_PAGE };
|
||||
#ifndef isa_mmu_check
|
||||
int isa_mmu_check(vaddr_t vaddr, int len, int type);
|
||||
#endif
|
||||
paddr_t isa_mmu_translate(vaddr_t vaddr, int len, int type);
|
||||
|
||||
// interrupt/exception
|
||||
vaddr_t isa_raise_intr(word_t NO, vaddr_t epc);
|
||||
#define INTR_EMPTY ((word_t)-1)
|
||||
word_t isa_query_intr();
|
||||
|
||||
// difftest
|
||||
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc);
|
||||
void isa_difftest_attach();
|
||||
|
||||
#endif
|
110
nemu/include/macro.h
Normal file
110
nemu/include/macro.h
Normal file
|
@ -0,0 +1,110 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __MACRO_H__
|
||||
#define __MACRO_H__
|
||||
|
||||
#include <string.h>
|
||||
|
||||
// macro stringizing
|
||||
#define str_temp(x) #x
|
||||
#define str(x) str_temp(x)
|
||||
|
||||
// strlen() for string constant
|
||||
#define STRLEN(CONST_STR) (sizeof(CONST_STR) - 1)
|
||||
|
||||
// calculate the length of an array
|
||||
#define ARRLEN(arr) (int)(sizeof(arr) / sizeof(arr[0]))
|
||||
|
||||
// macro concatenation
|
||||
#define concat_temp(x, y) x ## y
|
||||
#define concat(x, y) concat_temp(x, y)
|
||||
#define concat3(x, y, z) concat(concat(x, y), z)
|
||||
#define concat4(x, y, z, w) concat3(concat(x, y), z, w)
|
||||
#define concat5(x, y, z, v, w) concat4(concat(x, y), z, v, w)
|
||||
|
||||
// macro testing
|
||||
// See https://stackoverflow.com/questions/26099745/test-if-preprocessor-symbol-is-defined-inside-macro
|
||||
#define CHOOSE2nd(a, b, ...) b
|
||||
#define MUX_WITH_COMMA(contain_comma, a, b) CHOOSE2nd(contain_comma a, b)
|
||||
#define MUX_MACRO_PROPERTY(p, macro, a, b) MUX_WITH_COMMA(concat(p, macro), a, b)
|
||||
// define placeholders for some property
|
||||
#define __P_DEF_0 X,
|
||||
#define __P_DEF_1 X,
|
||||
#define __P_ONE_1 X,
|
||||
#define __P_ZERO_0 X,
|
||||
// define some selection functions based on the properties of BOOLEAN macro
|
||||
#define MUXDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, X, Y)
|
||||
#define MUXNDEF(macro, X, Y) MUX_MACRO_PROPERTY(__P_DEF_, macro, Y, X)
|
||||
#define MUXONE(macro, X, Y) MUX_MACRO_PROPERTY(__P_ONE_, macro, X, Y)
|
||||
#define MUXZERO(macro, X, Y) MUX_MACRO_PROPERTY(__P_ZERO_,macro, X, Y)
|
||||
|
||||
// test if a boolean macro is defined
|
||||
#define ISDEF(macro) MUXDEF(macro, 1, 0)
|
||||
// test if a boolean macro is undefined
|
||||
#define ISNDEF(macro) MUXNDEF(macro, 1, 0)
|
||||
// test if a boolean macro is defined to 1
|
||||
#define ISONE(macro) MUXONE(macro, 1, 0)
|
||||
// test if a boolean macro is defined to 0
|
||||
#define ISZERO(macro) MUXZERO(macro, 1, 0)
|
||||
// test if a macro of ANY type is defined
|
||||
// NOTE1: it ONLY works inside a function, since it calls `strcmp()`
|
||||
// NOTE2: macros defined to themselves (#define A A) will get wrong results
|
||||
#define isdef(macro) (strcmp("" #macro, "" str(macro)) != 0)
|
||||
|
||||
// simplification for conditional compilation
|
||||
#define __IGNORE(...)
|
||||
#define __KEEP(...) __VA_ARGS__
|
||||
// keep the code if a boolean macro is defined
|
||||
#define IFDEF(macro, ...) MUXDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is undefined
|
||||
#define IFNDEF(macro, ...) MUXNDEF(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is defined to 1
|
||||
#define IFONE(macro, ...) MUXONE(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
// keep the code if a boolean macro is defined to 0
|
||||
#define IFZERO(macro, ...) MUXZERO(macro, __KEEP, __IGNORE)(__VA_ARGS__)
|
||||
|
||||
// functional-programming-like macro (X-macro)
|
||||
// apply the function `f` to each element in the container `c`
|
||||
// NOTE1: `c` should be defined as a list like:
|
||||
// f(a0) f(a1) f(a2) ...
|
||||
// NOTE2: each element in the container can be a tuple
|
||||
#define MAP(c, f) c(f)
|
||||
|
||||
#define BITMASK(bits) ((1ull << (bits)) - 1)
|
||||
#define BITS(x, hi, lo) (((x) >> (lo)) & BITMASK((hi) - (lo) + 1)) // similar to x[hi:lo] in verilog
|
||||
#define SEXT(x, len) ({ struct { int64_t n : len; } __x = { .n = x }; (uint64_t)__x.n; })
|
||||
|
||||
#define ROUNDUP(a, sz) ((((uintptr_t)a) + (sz) - 1) & ~((sz) - 1))
|
||||
#define ROUNDDOWN(a, sz) ((((uintptr_t)a)) & ~((sz) - 1))
|
||||
|
||||
#define PG_ALIGN __attribute((aligned(4096)))
|
||||
|
||||
#if !defined(likely)
|
||||
#define likely(cond) __builtin_expect(cond, 1)
|
||||
#define unlikely(cond) __builtin_expect(cond, 0)
|
||||
#endif
|
||||
|
||||
// for AM IOE
|
||||
#define io_read(reg) \
|
||||
({ reg##_T __io_param; \
|
||||
ioe_read(reg, &__io_param); \
|
||||
__io_param; })
|
||||
|
||||
#define io_write(reg, ...) \
|
||||
({ reg##_T __io_param = (reg##_T) { __VA_ARGS__ }; \
|
||||
ioe_write(reg, &__io_param); })
|
||||
|
||||
#endif
|
41
nemu/include/memory/host.h
Normal file
41
nemu/include/memory/host.h
Normal file
|
@ -0,0 +1,41 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __MEMORY_HOST_H__
|
||||
#define __MEMORY_HOST_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
static inline word_t host_read(void *addr, int len) {
|
||||
switch (len) {
|
||||
case 1: return *(uint8_t *)addr;
|
||||
case 2: return *(uint16_t *)addr;
|
||||
case 4: return *(uint32_t *)addr;
|
||||
IFDEF(CONFIG_ISA64, case 8: return *(uint64_t *)addr);
|
||||
default: MUXDEF(CONFIG_RT_CHECK, assert(0), return 0);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void host_write(void *addr, int len, word_t data) {
|
||||
switch (len) {
|
||||
case 1: *(uint8_t *)addr = data; return;
|
||||
case 2: *(uint16_t *)addr = data; return;
|
||||
case 4: *(uint32_t *)addr = data; return;
|
||||
IFDEF(CONFIG_ISA64, case 8: *(uint64_t *)addr = data; return);
|
||||
IFDEF(CONFIG_RT_CHECK, default: assert(0));
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
37
nemu/include/memory/paddr.h
Normal file
37
nemu/include/memory/paddr.h
Normal file
|
@ -0,0 +1,37 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __MEMORY_PADDR_H__
|
||||
#define __MEMORY_PADDR_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
#define PMEM_LEFT ((paddr_t)CONFIG_MBASE)
|
||||
#define PMEM_RIGHT ((paddr_t)CONFIG_MBASE + CONFIG_MSIZE - 1)
|
||||
#define RESET_VECTOR (PMEM_LEFT + CONFIG_PC_RESET_OFFSET)
|
||||
|
||||
/* convert the guest physical address in the guest program to host virtual address in NEMU */
|
||||
uint8_t* guest_to_host(paddr_t paddr);
|
||||
/* convert the host virtual address in NEMU to guest physical address in the guest program */
|
||||
paddr_t host_to_guest(uint8_t *haddr);
|
||||
|
||||
static inline bool in_pmem(paddr_t addr) {
|
||||
return addr - CONFIG_MBASE < CONFIG_MSIZE;
|
||||
}
|
||||
|
||||
word_t paddr_read(paddr_t addr, int len);
|
||||
void paddr_write(paddr_t addr, int len, word_t data);
|
||||
|
||||
#endif
|
29
nemu/include/memory/vaddr.h
Normal file
29
nemu/include/memory/vaddr.h
Normal file
|
@ -0,0 +1,29 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __MEMORY_VADDR_H__
|
||||
#define __MEMORY_VADDR_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
word_t vaddr_ifetch(vaddr_t addr, int len);
|
||||
word_t vaddr_read(vaddr_t addr, int len);
|
||||
void vaddr_write(vaddr_t addr, int len, word_t data);
|
||||
|
||||
#define PAGE_SHIFT 12
|
||||
#define PAGE_SIZE (1ul << PAGE_SHIFT)
|
||||
#define PAGE_MASK (PAGE_SIZE - 1)
|
||||
|
||||
#endif
|
77
nemu/include/utils.h
Normal file
77
nemu/include/utils.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __UTILS_H__
|
||||
#define __UTILS_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
// ----------- state -----------
|
||||
|
||||
enum { NEMU_RUNNING, NEMU_STOP, NEMU_END, NEMU_ABORT, NEMU_QUIT };
|
||||
|
||||
typedef struct {
|
||||
int state;
|
||||
vaddr_t halt_pc;
|
||||
uint32_t halt_ret;
|
||||
} NEMUState;
|
||||
|
||||
extern NEMUState nemu_state;
|
||||
|
||||
// ----------- timer -----------
|
||||
|
||||
uint64_t get_time();
|
||||
|
||||
// ----------- log -----------
|
||||
|
||||
#define ANSI_FG_BLACK "\33[1;30m"
|
||||
#define ANSI_FG_RED "\33[1;31m"
|
||||
#define ANSI_FG_GREEN "\33[1;32m"
|
||||
#define ANSI_FG_YELLOW "\33[1;33m"
|
||||
#define ANSI_FG_BLUE "\33[1;34m"
|
||||
#define ANSI_FG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_FG_CYAN "\33[1;36m"
|
||||
#define ANSI_FG_WHITE "\33[1;37m"
|
||||
#define ANSI_BG_BLACK "\33[1;40m"
|
||||
#define ANSI_BG_RED "\33[1;41m"
|
||||
#define ANSI_BG_GREEN "\33[1;42m"
|
||||
#define ANSI_BG_YELLOW "\33[1;43m"
|
||||
#define ANSI_BG_BLUE "\33[1;44m"
|
||||
#define ANSI_BG_MAGENTA "\33[1;35m"
|
||||
#define ANSI_BG_CYAN "\33[1;46m"
|
||||
#define ANSI_BG_WHITE "\33[1;47m"
|
||||
#define ANSI_NONE "\33[0m"
|
||||
|
||||
#define ANSI_FMT(str, fmt) fmt str ANSI_NONE
|
||||
|
||||
#define log_write(...) IFDEF(CONFIG_TARGET_NATIVE_ELF, \
|
||||
do { \
|
||||
extern FILE* log_fp; \
|
||||
extern bool log_enable(); \
|
||||
if (log_enable()) { \
|
||||
fprintf(log_fp, __VA_ARGS__); \
|
||||
fflush(log_fp); \
|
||||
} \
|
||||
} while (0) \
|
||||
)
|
||||
|
||||
#define _Log(...) \
|
||||
do { \
|
||||
printf(__VA_ARGS__); \
|
||||
log_write(__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
|
||||
#endif
|
172
nemu/resource/debian/README.md
Normal file
172
nemu/resource/debian/README.md
Normal file
|
@ -0,0 +1,172 @@
|
|||
|
||||
# riscv64 debian镜像制作
|
||||
|
||||
制作需要`qemu-riscv64-static`, 建议在debian 10或ubuntu 19.04的系统(可尝试使用docker)中进行操作.
|
||||
|
||||
* 创建空镜像和分区
|
||||
```
|
||||
dd if=/dev/zero of=debian.img bs=1G count=16 # 此处镜像大小为16GB
|
||||
sudo cfdisk debian.img # 可创建两个分区, 第一个分区12GB作为rootfs, 第二个分区4GB作为swap
|
||||
sudo losetup --partscan --show --find debian.img # 将debian.img作为loop设备
|
||||
ls /dev/loop0* # 此时应该能看到/dev/loop0p1和/dev/loop0p2两个分区
|
||||
```
|
||||
|
||||
* 创建ext4和swap文件系统
|
||||
```
|
||||
sudo mkfs.ext4 /dev/loop0p1
|
||||
sudo mkswap /dev/loop0p2
|
||||
```
|
||||
|
||||
* 挂载ext4分区
|
||||
```
|
||||
sudo mount /dev/loop0p1 /mnt
|
||||
```
|
||||
|
||||
* 安装debian base system.
|
||||
下面两条命令的操作来自[debian社区的安装指南](https://wiki.debian.org/RISC-V#debootstrap).
|
||||
```
|
||||
sudo apt-get install debootstrap qemu-user-static binfmt-support debian-ports-archive-keyring
|
||||
sudo debootstrap --arch=riscv64 --keyring /usr/share/keyrings/debian-ports-archive-keyring.gpg --include=debian-ports-archive-keyring unstable /mnt http://deb.debian.org/debian-ports
|
||||
```
|
||||
若要安装x86系统, 则输入
|
||||
```
|
||||
sudo debootstrap --arch=i386 --keyring /usr/share/keyrings/debian-archive-keyring.gpg --include=debian-archive-keyring stable /mnt http://deb.debian.org/debian
|
||||
```
|
||||
|
||||
* 进入镜像
|
||||
```
|
||||
sudo chroot /mnt /bin/bash
|
||||
```
|
||||
此时实际上是通过`qemu-riscv64-static`来执行镜像中的riscv64可执行文件.
|
||||
|
||||
* 安装所需工具(根据实际情况选择)
|
||||
```
|
||||
apt-get update
|
||||
apt-get install systemd
|
||||
apt-get install gcc build-essential
|
||||
apt-get install tmux libreadline-dev
|
||||
apt-get install net-tools openssh-server
|
||||
# fix long delay of openssh server
|
||||
apt-get install haveged
|
||||
apt-get install sbt
|
||||
```
|
||||
|
||||
* 修复`NO_PUBKEY E852514F5DF312F6`错误, 见[这里](https://www.reddit.com/r/RISCV/comments/sn0cph/sipeed_debian_the_following_signatures_couldnt_be/)
|
||||
```
|
||||
curl https://www.ports.debian.org/archive_2022.key | apt-key add -
|
||||
```
|
||||
|
||||
* 同步时间
|
||||
```
|
||||
apt-get install ntpdate
|
||||
ntpdate 0.asia.pool.ntp.org
|
||||
```
|
||||
|
||||
* 在`/etc/fstab`中添加swap分区
|
||||
```
|
||||
/dev/mmcblk0p2 none swap sw 0 0
|
||||
```
|
||||
|
||||
* 添加/root/目录的写和执行权限, 使得host上的普通用户可以访问
|
||||
```
|
||||
chmod a+w,a+x /root
|
||||
```
|
||||
|
||||
* 在/root/目录下提前写入所需的测试文件, 如hello.c等.
|
||||
|
||||
* 在/root/.bashrc中添加如下内容, 可以实现登录后自动运行命令(根据实际情况修改测试的命令):
|
||||
```
|
||||
TMP_DIR=/run/mytest
|
||||
|
||||
cmd=(
|
||||
# enbale swap
|
||||
"swapon -a"
|
||||
|
||||
# show system information
|
||||
"uname -a"
|
||||
"cat /etc/issue"
|
||||
"cat /proc/cpuinfo"
|
||||
"df -ah"
|
||||
"free -h"
|
||||
|
||||
# show time
|
||||
"date"
|
||||
"uptime"
|
||||
|
||||
# create and switch to tmp directory
|
||||
"mkdir $TMP_DIR"
|
||||
"cd $TMP_DIR"
|
||||
|
||||
# compile and run hello
|
||||
"ls /root"
|
||||
"ls /root/hello"
|
||||
"cat /root/hello/hello.c"
|
||||
"gcc -time /root/hello/hello.c -o $TMP_DIR/hello"
|
||||
"ls -lh $TMP_DIR"
|
||||
"$TMP_DIR/hello"
|
||||
|
||||
# compile and run x86-nemu
|
||||
"ls /root/nemu"
|
||||
"cp -r /root/nemu $TMP_DIR"
|
||||
"export NEMU_HOME=$TMP_DIR/nemu"
|
||||
"make -C $TMP_DIR/nemu ISA=x86"
|
||||
"ls -lh /root/nemu-prog"
|
||||
"file /root/nemu-prog/amtest-x86-nemu.elf"
|
||||
"$TMP_DIR/nemu/build/x86-nemu --batch --mainargs=h /root/nemu-prog/amtest-x86-nemu.bin"
|
||||
"file /root/nemu-prog/microbench-x86-nemu.elf"
|
||||
"$TMP_DIR/nemu/build/x86-nemu --batch --mainargs=test /root/nemu-prog/microbench-x86-nemu.bin"
|
||||
|
||||
# compile and run riscv64-nemu
|
||||
"make -C $TMP_DIR/nemu clean"
|
||||
"make -C $TMP_DIR/nemu ISA=riscv64"
|
||||
"$TMP_DIR/nemu/build/riscv64-nemu --batch /root/nemu-prog/linux-hello-riscv64-nemu.bin"
|
||||
)
|
||||
|
||||
prompt="`whoami`@`hostname`:`pwd`#"
|
||||
|
||||
echo -e "\n============ Now running preset commands =============\n"
|
||||
|
||||
for ((i = 0; i < ${#cmd[@]}; i++)); do
|
||||
c=${cmd[$i]}
|
||||
echo "$prompt $c"
|
||||
$c
|
||||
echo ""
|
||||
done
|
||||
|
||||
echo -e "\n============ End of preset commands =============\n"
|
||||
|
||||
/root/nemutrap/good-trap
|
||||
```
|
||||
|
||||
* 若在不方便输入的环境(如NEMU, verilator仿真等)中测试, 可采用如下两种方式的其中一种, 避免登录时输入
|
||||
* 通过紧急模式登录
|
||||
```
|
||||
cd /lib/systemd/system
|
||||
# 通过紧急模式登录, 不启动非必须的服务, 节省将近一半的登录时间
|
||||
ln -sf emergency.target default.target
|
||||
# 跳过登录提示符, 直接运行bash
|
||||
vim emergency.service
|
||||
-ExecStart=-/lib/systemd/systemd-sulogin-shell emergency
|
||||
+ExecStart=-/bin/bash
|
||||
```
|
||||
* 免密码登录, 见[这里](https://superuser.com/questions/969923/automatic-root-login-in-debian-8-0-console-only)
|
||||
```
|
||||
cd /lib/systemd/system
|
||||
vim serial-getty@.service
|
||||
-ExecStart=-/sbin/agetty -o '-p -- \\u' --keep-baud 115200,57600,38400,9600 %I $TERM
|
||||
+ExecStart=-/sbin/agetty -a root --keep-baud 115200,57600,38400,9600 %I $TERM
|
||||
```
|
||||
|
||||
* 退出并卸载镜像
|
||||
```
|
||||
exit # 之前通过`chroot`方式进入
|
||||
sudo umount /mnt # 记得卸载! 在未卸载镜像的情况下通过可写方式再次打开`debian.img`(如作为qemu的文件系统), 镜像将会损坏!
|
||||
sudo losetup -d /dev/loop0 # 删除loop设备
|
||||
```
|
||||
|
||||
* 修改`nemu/src/device/sdcard.c`中`init_sdcard()`中打开的镜像文件路径, 即可使用制作的镜像.
|
||||
在i9-9900k上测试, 约90s后看到debian的登录提示符.
|
||||
|
||||
* 当以可写方式启动镜像时, NEMU遇到错误或通过Ctrl+C直接退出NEMU时, 可能会损坏镜像的崩溃一致性, 此时可以通过fsck命令修复分区.
|
||||
|
||||
* 更多命令可参考[这里](https://github.com/carlosedp/riscv-bringup/blob/master/Debian-Rootfs-Guide.md).
|
1
nemu/resource/mips-elf/README.md
Normal file
1
nemu/resource/mips-elf/README.md
Normal file
|
@ -0,0 +1 @@
|
|||
This is a dummy ELF file used by qemu-system-mips32 to start.
|
58
nemu/resource/sdcard/README.md
Normal file
58
nemu/resource/sdcard/README.md
Normal file
|
@ -0,0 +1,58 @@
|
|||
|
||||
# NEMU sdhost驱动
|
||||
|
||||
本驱动裁剪自`linux/drivers/mmc/host/bcm2835.c`, 去除了DMA和中断, 改成直接轮询, 处理器无需支持DMA和中断即可运行.
|
||||
|
||||
## 使用方法
|
||||
|
||||
* 将本目录下的`nemu.c`复制到`linux/drivers/mmc/host/`目录下
|
||||
* 在`linux/drivers/mmc/host/Makefile`中添加一行`obj-y += nemu.o`
|
||||
* 在menuconfig中取消`General setup -> Initial RAM filesystem and RAM disk (initramfs/initrd) support`
|
||||
* 在menuconfig中选中`Device Drivers -> MMC/SD/SDIO card support`
|
||||
* 在dts中加入以下节点
|
||||
```
|
||||
/ {
|
||||
soc {
|
||||
sdhci: mmc {
|
||||
compatible = "nemu-sdhost";
|
||||
reg = <0x0 0xa3000000 0x0 0x1000>;
|
||||
};
|
||||
};
|
||||
|
||||
chosen {
|
||||
bootargs = "root=/dev/mmcblk0p1 rootfstype=ext4 ro rootwait earlycon";
|
||||
};
|
||||
};
|
||||
```
|
||||
|
||||
## 在没有中断的处理器上访问SD卡
|
||||
|
||||
访问真实的SD卡需要等待一定的延迟, 这需要处理器的中断机制对内核支持计时的功能.
|
||||
在没有中断机制的处理器上, 我们可以修改内核的部分代码, 使得无需等待这些延迟,
|
||||
来达到确定性可重复的仿真效果.
|
||||
|
||||
具体只需修改以下文件:
|
||||
```diff
|
||||
--- linux/drivers/mmc/core/block.c
|
||||
+++ linux/drivers/mmc/core/block.c
|
||||
@@ -983,6 +983,7 @@ static int card_busy_detect(struct mmc_card *card, unsigned int timeout_ms,
|
||||
int err = 0;
|
||||
u32 status;
|
||||
|
||||
+ return err;
|
||||
do {
|
||||
bool done = time_after(jiffies, timeout);
|
||||
|
||||
--- linux/drivers/mmc/core/core.h
|
||||
+++ linux/drivers/mmc/core/core.h
|
||||
@@ -64,6 +64,7 @@ void mmc_set_initial_state(struct mmc_host *host);
|
||||
|
||||
static inline void mmc_delay(unsigned int ms)
|
||||
{
|
||||
+ return;
|
||||
if (ms <= 20)
|
||||
usleep_range(ms * 1000, ms * 1250);
|
||||
else
|
||||
```
|
||||
|
||||
注意: 上述修改仅能用于模拟和仿真, 修改后将不能在真实的SD卡上运行!!!
|
542
nemu/resource/sdcard/nemu.c
Normal file
542
nemu/resource/sdcard/nemu.c
Normal file
|
@ -0,0 +1,542 @@
|
|||
/*
|
||||
* NEMU (NJU Emulator) sdhost driver.
|
||||
*
|
||||
* Author: Zihao Yu <yuzihao@ict.ac.cn>
|
||||
*
|
||||
* Based on
|
||||
* bcm2835.c by Phil Elwell
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/dmaengine.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iopoll.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_irq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/workqueue.h>
|
||||
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
#include <linux/mmc/sd.h>
|
||||
|
||||
#define SDCMD 0x00 /* Command to SD card - 16 R/W */
|
||||
#define SDARG 0x04 /* Argument to SD card - 32 R/W */
|
||||
#define SDTOUT 0x08 /* Start value for timeout counter - 32 R/W */
|
||||
#define SDCDIV 0x0c /* Start value for clock divider - 11 R/W */
|
||||
#define SDRSP0 0x10 /* SD card response (31:0) - 32 R */
|
||||
#define SDRSP1 0x14 /* SD card response (63:32) - 32 R */
|
||||
#define SDRSP2 0x18 /* SD card response (95:64) - 32 R */
|
||||
#define SDRSP3 0x1c /* SD card response (127:96) - 32 R */
|
||||
#define SDHSTS 0x20 /* SD host status - 11 R/W */
|
||||
#define SDVDD 0x30 /* SD card power control - 1 R/W */
|
||||
#define SDEDM 0x34 /* Emergency Debug Mode - 13 R/W */
|
||||
#define SDHCFG 0x38 /* Host configuration - 2 R/W */
|
||||
#define SDHBCT 0x3c /* Host byte count (debug) - 32 R/W */
|
||||
#define SDDATA 0x40 /* Data to/from SD card - 32 R/W */
|
||||
#define SDHBLC 0x50 /* Host block count (SDIO/SDHC) - 9 R/W */
|
||||
|
||||
#define SDCMD_NEW_FLAG 0x8000
|
||||
#define SDCMD_FAIL_FLAG 0x4000
|
||||
#define SDCMD_BUSYWAIT 0x800
|
||||
#define SDCMD_NO_RESPONSE 0x400
|
||||
#define SDCMD_LONG_RESPONSE 0x200
|
||||
#define SDCMD_WRITE_CMD 0x80
|
||||
#define SDCMD_READ_CMD 0x40
|
||||
#define SDCMD_CMD_MASK 0x3f
|
||||
|
||||
#define SDCDIV_MAX_CDIV 0x7ff
|
||||
|
||||
#define SDDATA_FIFO_WORDS 16
|
||||
|
||||
#define FIFO_READ_THRESHOLD 4
|
||||
#define FIFO_WRITE_THRESHOLD 4
|
||||
#define SDDATA_FIFO_PIO_BURST 8
|
||||
|
||||
#define PIO_THRESHOLD 1 /* Maximum block count for PIO (0 = always DMA) */
|
||||
|
||||
struct nemu_host {
|
||||
spinlock_t lock;
|
||||
struct mutex mutex;
|
||||
|
||||
void __iomem *ioaddr;
|
||||
u32 phys_addr;
|
||||
|
||||
struct mmc_host *mmc;
|
||||
struct platform_device *pdev;
|
||||
|
||||
int clock; /* Current clock speed */
|
||||
unsigned int max_clk; /* Max possible freq */
|
||||
struct sg_mapping_iter sg_miter; /* SG state for PIO */
|
||||
unsigned int blocks; /* remaining PIO blocks */
|
||||
|
||||
struct mmc_request *mrq; /* Current request */
|
||||
struct mmc_command *cmd; /* Current command */
|
||||
struct mmc_data *data; /* Current data request */
|
||||
bool data_complete:1;/* Data finished before cmd */
|
||||
bool use_sbc:1; /* Send CMD23 */
|
||||
};
|
||||
|
||||
static void nemu_reset(struct mmc_host *mmc)
|
||||
{
|
||||
}
|
||||
|
||||
static void nemu_finish_command(struct nemu_host *host);
|
||||
|
||||
static void nemu_transfer_block_pio(struct nemu_host *host, bool is_read)
|
||||
{
|
||||
unsigned long flags;
|
||||
size_t blksize;
|
||||
|
||||
blksize = host->data->blksz;
|
||||
|
||||
local_irq_save(flags);
|
||||
|
||||
while (blksize) {
|
||||
int copy_words;
|
||||
size_t len;
|
||||
u32 *buf;
|
||||
|
||||
if (!sg_miter_next(&host->sg_miter)) {
|
||||
host->data->error = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
len = min(host->sg_miter.length, blksize);
|
||||
if (len % 4) {
|
||||
host->data->error = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
blksize -= len;
|
||||
host->sg_miter.consumed = len;
|
||||
|
||||
buf = (u32 *)host->sg_miter.addr;
|
||||
|
||||
copy_words = len / 4;
|
||||
|
||||
while (copy_words) {
|
||||
int burst_words, words;
|
||||
u32 edm;
|
||||
|
||||
burst_words = min(SDDATA_FIFO_PIO_BURST, copy_words);
|
||||
edm = (8 << 4);
|
||||
if (is_read)
|
||||
words = ((edm >> 4) & 0x1f);
|
||||
else
|
||||
words = SDDATA_FIFO_WORDS - ((edm >> 4) & 0x1f);
|
||||
|
||||
if (words < burst_words) {
|
||||
continue;
|
||||
} else if (words > copy_words) {
|
||||
words = copy_words;
|
||||
}
|
||||
|
||||
copy_words -= words;
|
||||
|
||||
while (words) {
|
||||
if (is_read)
|
||||
*(buf++) = readl(host->ioaddr + SDDATA);
|
||||
else
|
||||
writel(*(buf++), host->ioaddr + SDDATA);
|
||||
words--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sg_miter_stop(&host->sg_miter);
|
||||
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void nemu_transfer_pio(struct nemu_host *host)
|
||||
{
|
||||
bool is_read = (host->data->flags & MMC_DATA_READ) != 0;
|
||||
nemu_transfer_block_pio(host, is_read);
|
||||
}
|
||||
|
||||
static
|
||||
void nemu_prepare_data(struct nemu_host *host, struct mmc_command *cmd)
|
||||
{
|
||||
struct mmc_data *data = cmd->data;
|
||||
int flags = SG_MITER_ATOMIC;
|
||||
|
||||
WARN_ON(host->data);
|
||||
|
||||
host->data = data;
|
||||
if (!data)
|
||||
return;
|
||||
|
||||
host->data_complete = false;
|
||||
host->data->bytes_xfered = 0;
|
||||
|
||||
/* Use PIO */
|
||||
if (data->flags & MMC_DATA_READ)
|
||||
flags |= SG_MITER_TO_SG;
|
||||
else
|
||||
flags |= SG_MITER_FROM_SG;
|
||||
sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
|
||||
host->blocks = data->blocks;
|
||||
}
|
||||
|
||||
static void nemu_finish_request(struct nemu_host *host)
|
||||
{
|
||||
struct mmc_request *mrq;
|
||||
|
||||
mrq = host->mrq;
|
||||
|
||||
host->mrq = NULL;
|
||||
host->cmd = NULL;
|
||||
host->data = NULL;
|
||||
|
||||
mmc_request_done(host->mmc, mrq);
|
||||
}
|
||||
|
||||
static
|
||||
bool nemu_send_command(struct nemu_host *host, struct mmc_command *cmd)
|
||||
{
|
||||
u32 sdcmd;
|
||||
|
||||
WARN_ON(host->cmd);
|
||||
|
||||
host->cmd = cmd;
|
||||
|
||||
nemu_prepare_data(host, cmd);
|
||||
|
||||
writel(cmd->arg, host->ioaddr + SDARG);
|
||||
|
||||
sdcmd = cmd->opcode & SDCMD_CMD_MASK;
|
||||
|
||||
if (!(cmd->flags & MMC_RSP_PRESENT)) {
|
||||
sdcmd |= SDCMD_NO_RESPONSE;
|
||||
} else {
|
||||
if (cmd->flags & MMC_RSP_136)
|
||||
sdcmd |= SDCMD_LONG_RESPONSE;
|
||||
if (cmd->flags & MMC_RSP_BUSY) {
|
||||
sdcmd |= SDCMD_BUSYWAIT;
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd->data) {
|
||||
if (cmd->data->flags & MMC_DATA_WRITE) {
|
||||
sdcmd |= SDCMD_WRITE_CMD;
|
||||
}
|
||||
if (cmd->data->flags & MMC_DATA_READ)
|
||||
sdcmd |= SDCMD_READ_CMD;
|
||||
}
|
||||
|
||||
writel(sdcmd | SDCMD_NEW_FLAG, host->ioaddr + SDCMD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void nemu_transfer_complete(struct nemu_host *host)
|
||||
{
|
||||
struct mmc_data *data;
|
||||
|
||||
WARN_ON(!host->data_complete);
|
||||
|
||||
data = host->data;
|
||||
host->data = NULL;
|
||||
|
||||
/* Need to send CMD12 if -
|
||||
* a) open-ended multiblock transfer (no CMD23)
|
||||
* b) error in multiblock transfer
|
||||
*/
|
||||
if (host->mrq->stop && (data->error || !host->use_sbc)) {
|
||||
if (nemu_send_command(host, host->mrq->stop)) {
|
||||
nemu_finish_command(host);
|
||||
}
|
||||
} else {
|
||||
nemu_finish_request(host);
|
||||
}
|
||||
}
|
||||
|
||||
static void nemu_finish_data(struct nemu_host *host)
|
||||
{
|
||||
struct device *dev = &host->pdev->dev;
|
||||
struct mmc_data *data;
|
||||
|
||||
data = host->data;
|
||||
|
||||
data->bytes_xfered = data->error ? 0 : (data->blksz * data->blocks);
|
||||
|
||||
host->data_complete = true;
|
||||
|
||||
if (host->cmd) {
|
||||
/* Data managed to finish before the
|
||||
* command completed. Make sure we do
|
||||
* things in the proper order.
|
||||
*/
|
||||
dev_dbg(dev, "Finished early - HSTS %08x\n",
|
||||
readl(host->ioaddr + SDHSTS));
|
||||
} else {
|
||||
nemu_transfer_complete(host);
|
||||
}
|
||||
}
|
||||
|
||||
static void nemu_finish_command(struct nemu_host *host)
|
||||
{
|
||||
struct mmc_command *cmd = host->cmd;
|
||||
int i;
|
||||
|
||||
if (cmd->flags & MMC_RSP_PRESENT) {
|
||||
if (cmd->flags & MMC_RSP_136) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
cmd->resp[3 - i] =
|
||||
readl(host->ioaddr + SDRSP0 + i * 4);
|
||||
}
|
||||
} else {
|
||||
cmd->resp[0] = readl(host->ioaddr + SDRSP0);
|
||||
}
|
||||
}
|
||||
|
||||
if (cmd == host->mrq->sbc) {
|
||||
/* Finished CMD23, now send actual command. */
|
||||
host->cmd = NULL;
|
||||
if (nemu_send_command(host, host->mrq->cmd)) {
|
||||
if (host->data) {
|
||||
// start PIO right now
|
||||
for (i = 0; i < host->data->blocks; i ++) {
|
||||
nemu_transfer_pio(host);
|
||||
}
|
||||
|
||||
nemu_finish_data(host);
|
||||
}
|
||||
|
||||
nemu_finish_command(host);
|
||||
}
|
||||
} else if (cmd == host->mrq->stop) {
|
||||
/* Finished CMD12 */
|
||||
nemu_finish_request(host);
|
||||
} else {
|
||||
/* Processed actual command. */
|
||||
host->cmd = NULL;
|
||||
if (!host->data) {
|
||||
nemu_finish_request(host);
|
||||
}
|
||||
else if (host->data_complete) {
|
||||
nemu_transfer_complete(host);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void nemu_request(struct mmc_host *mmc, struct mmc_request *mrq)
|
||||
{
|
||||
struct nemu_host *host = mmc_priv(mmc);
|
||||
struct device *dev = &host->pdev->dev;
|
||||
|
||||
/* Reset the error statuses in case this is a retry */
|
||||
if (mrq->sbc)
|
||||
mrq->sbc->error = 0;
|
||||
if (mrq->cmd)
|
||||
mrq->cmd->error = 0;
|
||||
if (mrq->data)
|
||||
mrq->data->error = 0;
|
||||
if (mrq->stop)
|
||||
mrq->stop->error = 0;
|
||||
|
||||
if (mrq->data && !is_power_of_2(mrq->data->blksz)) {
|
||||
dev_err(dev, "unsupported block size (%d bytes)\n",
|
||||
mrq->data->blksz);
|
||||
|
||||
if (mrq->cmd)
|
||||
mrq->cmd->error = -EINVAL;
|
||||
|
||||
mmc_request_done(mmc, mrq);
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&host->mutex);
|
||||
|
||||
WARN_ON(host->mrq);
|
||||
host->mrq = mrq;
|
||||
|
||||
host->use_sbc = !!mrq->sbc && host->mrq->data &&
|
||||
(host->mrq->data->flags & MMC_DATA_READ);
|
||||
if (host->use_sbc) {
|
||||
if (nemu_send_command(host, mrq->sbc)) {
|
||||
nemu_finish_command(host);
|
||||
}
|
||||
} else if (mrq->cmd && nemu_send_command(host, mrq->cmd)) {
|
||||
if (host->data) {
|
||||
int i;
|
||||
// start PIO right now
|
||||
for (i = 0; i < host->data->blocks; i ++) {
|
||||
nemu_transfer_pio(host);
|
||||
}
|
||||
nemu_finish_data(host);
|
||||
}
|
||||
|
||||
nemu_finish_command(host);
|
||||
}
|
||||
|
||||
mutex_unlock(&host->mutex);
|
||||
}
|
||||
|
||||
static void nemu_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct mmc_host_ops nemu_ops = {
|
||||
.request = nemu_request,
|
||||
.set_ios = nemu_set_ios,
|
||||
.hw_reset = nemu_reset,
|
||||
};
|
||||
|
||||
static int nemu_add_host(struct nemu_host *host)
|
||||
{
|
||||
struct mmc_host *mmc = host->mmc;
|
||||
struct device *dev = &host->pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (!mmc->f_max || mmc->f_max > host->max_clk)
|
||||
mmc->f_max = host->max_clk;
|
||||
mmc->f_min = host->max_clk / SDCDIV_MAX_CDIV;
|
||||
|
||||
mmc->max_busy_timeout = ~0 / (mmc->f_max / 1000);
|
||||
|
||||
dev_dbg(dev, "f_max %d, f_min %d, max_busy_timeout %d\n",
|
||||
mmc->f_max, mmc->f_min, mmc->max_busy_timeout);
|
||||
|
||||
/* host controller capabilities */
|
||||
mmc->caps |= MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
|
||||
MMC_CAP_NEEDS_POLL | MMC_CAP_HW_RESET | MMC_CAP_ERASE |
|
||||
MMC_CAP_CMD23;
|
||||
|
||||
spin_lock_init(&host->lock);
|
||||
mutex_init(&host->mutex);
|
||||
|
||||
mmc->max_segs = 128;
|
||||
mmc->max_req_size = 524288;
|
||||
mmc->max_seg_size = mmc->max_req_size;
|
||||
mmc->max_blk_size = 1024;
|
||||
mmc->max_blk_count = 65535;
|
||||
|
||||
/* report supported voltage ranges */
|
||||
mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
|
||||
|
||||
ret = mmc_add_host(mmc);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
dev_info(dev, "loaded - DMA %s\n", "disabled");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nemu_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct resource *iomem;
|
||||
struct nemu_host *host;
|
||||
struct mmc_host *mmc;
|
||||
const __be32 *regaddr_p;
|
||||
int ret;
|
||||
|
||||
dev_dbg(dev, "%s\n", __func__);
|
||||
mmc = mmc_alloc_host(sizeof(*host), dev);
|
||||
if (!mmc)
|
||||
return -ENOMEM;
|
||||
|
||||
mmc->ops = &nemu_ops;
|
||||
host = mmc_priv(mmc);
|
||||
host->mmc = mmc;
|
||||
host->pdev = pdev;
|
||||
spin_lock_init(&host->lock);
|
||||
|
||||
iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
host->ioaddr = devm_ioremap_resource(dev, iomem);
|
||||
if (IS_ERR(host->ioaddr)) {
|
||||
ret = PTR_ERR(host->ioaddr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Parse OF address directly to get the physical address for
|
||||
* DMA to our registers.
|
||||
*/
|
||||
regaddr_p = of_get_address(pdev->dev.of_node, 0, NULL, NULL);
|
||||
if (!regaddr_p) {
|
||||
dev_err(dev, "Can't get phys address\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
host->phys_addr = be32_to_cpup(regaddr_p);
|
||||
|
||||
host->max_clk = 1000000; //clk_get_rate(clk);
|
||||
|
||||
ret = mmc_of_parse(mmc);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
ret = nemu_add_host(host);
|
||||
if (ret)
|
||||
goto err;
|
||||
|
||||
platform_set_drvdata(pdev, host);
|
||||
|
||||
dev_dbg(dev, "%s -> OK\n", __func__);
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
dev_dbg(dev, "%s -> err %d\n", __func__, ret);
|
||||
mmc_free_host(mmc);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int nemu_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct nemu_host *host = platform_get_drvdata(pdev);
|
||||
|
||||
mmc_remove_host(host->mmc);
|
||||
|
||||
mmc_free_host(host->mmc);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id nemu_match[] = {
|
||||
{ .compatible = "nemu-sdhost" },
|
||||
{ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, nemu_match);
|
||||
|
||||
static struct platform_driver nemu_driver = {
|
||||
.probe = nemu_probe,
|
||||
.remove = nemu_remove,
|
||||
.driver = {
|
||||
.name = "sdhost-nemu",
|
||||
.of_match_table = nemu_match,
|
||||
},
|
||||
};
|
||||
module_platform_driver(nemu_driver);
|
||||
|
||||
MODULE_ALIAS("platform:sdhost-nemu");
|
||||
MODULE_DESCRIPTION("NEMU SDHost driver");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_AUTHOR("Zihao Yu");
|
57
nemu/scripts/build.mk
Normal file
57
nemu/scripts/build.mk
Normal file
|
@ -0,0 +1,57 @@
|
|||
.DEFAULT_GOAL = app
|
||||
|
||||
# Add necessary options if the target is a shared library
|
||||
ifeq ($(SHARE),1)
|
||||
SO = -so
|
||||
CFLAGS += -fPIC -fvisibility=hidden
|
||||
LDFLAGS += -shared -fPIC
|
||||
endif
|
||||
|
||||
WORK_DIR = $(shell pwd)
|
||||
BUILD_DIR = $(WORK_DIR)/build
|
||||
|
||||
INC_PATH := $(WORK_DIR)/include $(INC_PATH)
|
||||
OBJ_DIR = $(BUILD_DIR)/obj-$(NAME)$(SO)
|
||||
BINARY = $(BUILD_DIR)/$(NAME)$(SO)
|
||||
|
||||
# Compilation flags
|
||||
ifeq ($(CC),clang)
|
||||
CXX := clang++
|
||||
else
|
||||
CXX := g++
|
||||
endif
|
||||
LD := $(CXX)
|
||||
INCLUDES = $(addprefix -I, $(INC_PATH))
|
||||
CFLAGS := -O2 -MMD -Wall -Werror $(INCLUDES) $(CFLAGS)
|
||||
LDFLAGS := -O2 $(LDFLAGS)
|
||||
|
||||
OBJS = $(SRCS:%.c=$(OBJ_DIR)/%.o) $(CXXSRC:%.cc=$(OBJ_DIR)/%.o)
|
||||
|
||||
# Compilation patterns
|
||||
$(OBJ_DIR)/%.o: %.c
|
||||
@echo + CC $<
|
||||
@mkdir -p $(dir $@)
|
||||
@$(CC) $(CFLAGS) -c -o $@ $<
|
||||
$(call call_fixdep, $(@:.o=.d), $@)
|
||||
|
||||
$(OBJ_DIR)/%.o: %.cc
|
||||
@echo + CXX $<
|
||||
@mkdir -p $(dir $@)
|
||||
@$(CXX) $(CFLAGS) $(CXXFLAGS) -c -o $@ $<
|
||||
$(call call_fixdep, $(@:.o=.d), $@)
|
||||
|
||||
# Depencies
|
||||
-include $(OBJS:.o=.d)
|
||||
|
||||
# Some convenient rules
|
||||
|
||||
.PHONY: app clean
|
||||
|
||||
app: $(BINARY)
|
||||
|
||||
$(BINARY):: $(OBJS) $(ARCHIVES)
|
||||
@echo + LD $@
|
||||
@$(LD) -o $@ $(OBJS) $(LDFLAGS) $(ARCHIVES) $(LIBS)
|
||||
|
||||
clean:
|
||||
-rm -rf $(BUILD_DIR)
|
70
nemu/scripts/config.mk
Normal file
70
nemu/scripts/config.mk
Normal file
|
@ -0,0 +1,70 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
COLOR_RED := $(shell echo "\033[1;31m")
|
||||
COLOR_END := $(shell echo "\033[0m")
|
||||
|
||||
ifeq ($(wildcard .config),)
|
||||
$(warning $(COLOR_RED)Warning: .config does not exists!$(COLOR_END))
|
||||
$(warning $(COLOR_RED)To build the project, first run 'make menuconfig'.$(COLOR_END))
|
||||
endif
|
||||
|
||||
Q := @
|
||||
KCONFIG_PATH := $(NEMU_HOME)/tools/kconfig
|
||||
FIXDEP_PATH := $(NEMU_HOME)/tools/fixdep
|
||||
Kconfig := $(NEMU_HOME)/Kconfig
|
||||
rm-distclean += include/generated include/config .config .config.old
|
||||
silent := -s
|
||||
|
||||
CONF := $(KCONFIG_PATH)/build/conf
|
||||
MCONF := $(KCONFIG_PATH)/build/mconf
|
||||
FIXDEP := $(FIXDEP_PATH)/build/fixdep
|
||||
|
||||
$(CONF):
|
||||
$(Q)$(MAKE) $(silent) -C $(KCONFIG_PATH) NAME=conf
|
||||
|
||||
$(MCONF):
|
||||
$(Q)$(MAKE) $(silent) -C $(KCONFIG_PATH) NAME=mconf
|
||||
|
||||
$(FIXDEP):
|
||||
$(Q)$(MAKE) $(silent) -C $(FIXDEP_PATH)
|
||||
|
||||
menuconfig: $(MCONF) $(CONF) $(FIXDEP)
|
||||
$(Q)$(MCONF) $(Kconfig)
|
||||
$(Q)$(CONF) $(silent) --syncconfig $(Kconfig)
|
||||
|
||||
savedefconfig: $(CONF)
|
||||
$(Q)$< $(silent) --$@=configs/defconfig $(Kconfig)
|
||||
|
||||
%defconfig: $(CONF) $(FIXDEP)
|
||||
$(Q)$< $(silent) --defconfig=configs/$@ $(Kconfig)
|
||||
$(Q)$< $(silent) --syncconfig $(Kconfig)
|
||||
|
||||
.PHONY: menuconfig savedefconfig defconfig
|
||||
|
||||
# Help text used by make help
|
||||
help:
|
||||
@echo ' menuconfig - Update current config utilising a menu based program'
|
||||
@echo ' savedefconfig - Save current config as configs/defconfig (minimal config)'
|
||||
|
||||
distclean: clean
|
||||
-@rm -rf $(rm-distclean)
|
||||
|
||||
.PHONY: help distclean
|
||||
|
||||
define call_fixdep
|
||||
@$(FIXDEP) $(1) $(2) unused > $(1).tmp
|
||||
@mv $(1).tmp $(1)
|
||||
endef
|
50
nemu/scripts/native.mk
Normal file
50
nemu/scripts/native.mk
Normal file
|
@ -0,0 +1,50 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
-include $(NEMU_HOME)/../Makefile
|
||||
include $(NEMU_HOME)/scripts/build.mk
|
||||
|
||||
include $(NEMU_HOME)/tools/difftest.mk
|
||||
|
||||
compile_git:
|
||||
$(call git_commit, "compile NEMU")
|
||||
$(BINARY):: compile_git
|
||||
|
||||
# Some convenient rules
|
||||
|
||||
override ARGS ?= --log=$(BUILD_DIR)/nemu-log.txt
|
||||
override ARGS += $(ARGS_DIFF)
|
||||
|
||||
# Command to execute NEMU
|
||||
IMG ?=
|
||||
NEMU_EXEC := $(BINARY) $(ARGS) $(IMG)
|
||||
|
||||
run-env: $(BINARY) $(DIFF_REF_SO)
|
||||
|
||||
run: run-env
|
||||
$(call git_commit, "run NEMU")
|
||||
$(NEMU_EXEC)
|
||||
|
||||
gdb: run-env
|
||||
$(call git_commit, "gdb NEMU")
|
||||
gdb -s $(BINARY) --args $(NEMU_EXEC)
|
||||
|
||||
clean-tools = $(dir $(shell find ./tools -maxdepth 2 -mindepth 2 -name "Makefile"))
|
||||
$(clean-tools):
|
||||
-@$(MAKE) -s -C $@ clean
|
||||
clean-tools: $(clean-tools)
|
||||
clean-all: clean distclean clean-tools
|
||||
|
||||
.PHONY: run gdb run-env clean-tools clean-all $(clean-tools)
|
22
nemu/src/am-bin.S
Normal file
22
nemu/src/am-bin.S
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
.section .rodata
|
||||
.globl bin_start, bin_end
|
||||
bin_start:
|
||||
#ifdef BIN_PATH
|
||||
.incbin BIN_PATH
|
||||
#endif
|
||||
bin_end:
|
128
nemu/src/cpu/cpu-exec.c
Normal file
128
nemu/src/cpu/cpu-exec.c
Normal file
|
@ -0,0 +1,128 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/decode.h>
|
||||
#include <cpu/difftest.h>
|
||||
#include <locale.h>
|
||||
|
||||
/* The assembly code of instructions executed is only output to the screen
|
||||
* when the number of instructions executed is less than this value.
|
||||
* This is useful when you use the `si' command.
|
||||
* You can modify this value as you want.
|
||||
*/
|
||||
#define MAX_INST_TO_PRINT 10
|
||||
|
||||
CPU_state cpu = {};
|
||||
uint64_t g_nr_guest_inst = 0;
|
||||
static uint64_t g_timer = 0; // unit: us
|
||||
static bool g_print_step = false;
|
||||
|
||||
void device_update();
|
||||
|
||||
static void trace_and_difftest(Decode *_this, vaddr_t dnpc) {
|
||||
#ifdef CONFIG_ITRACE_COND
|
||||
if (ITRACE_COND) { log_write("%s\n", _this->logbuf); }
|
||||
#endif
|
||||
if (g_print_step) { IFDEF(CONFIG_ITRACE, puts(_this->logbuf)); }
|
||||
IFDEF(CONFIG_DIFFTEST, difftest_step(_this->pc, dnpc));
|
||||
}
|
||||
|
||||
static void exec_once(Decode *s, vaddr_t pc) {
|
||||
s->pc = pc;
|
||||
s->snpc = pc;
|
||||
isa_exec_once(s);
|
||||
cpu.pc = s->dnpc;
|
||||
#ifdef CONFIG_ITRACE
|
||||
char *p = s->logbuf;
|
||||
p += snprintf(p, sizeof(s->logbuf), FMT_WORD ":", s->pc);
|
||||
int ilen = s->snpc - s->pc;
|
||||
int i;
|
||||
uint8_t *inst = (uint8_t *)&s->isa.inst.val;
|
||||
for (i = ilen - 1; i >= 0; i --) {
|
||||
p += snprintf(p, 4, " %02x", inst[i]);
|
||||
}
|
||||
int ilen_max = MUXDEF(CONFIG_ISA_x86, 8, 4);
|
||||
int space_len = ilen_max - ilen;
|
||||
if (space_len < 0) space_len = 0;
|
||||
space_len = space_len * 3 + 1;
|
||||
memset(p, ' ', space_len);
|
||||
p += space_len;
|
||||
|
||||
#ifndef CONFIG_ISA_loongarch32r
|
||||
void disassemble(char *str, int size, uint64_t pc, uint8_t *code, int nbyte);
|
||||
disassemble(p, s->logbuf + sizeof(s->logbuf) - p,
|
||||
MUXDEF(CONFIG_ISA_x86, s->snpc, s->pc), (uint8_t *)&s->isa.inst.val, ilen);
|
||||
#else
|
||||
p[0] = '\0'; // the upstream llvm does not support loongarch32r
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
static void execute(uint64_t n) {
|
||||
Decode s;
|
||||
for (;n > 0; n --) {
|
||||
exec_once(&s, cpu.pc);
|
||||
g_nr_guest_inst ++;
|
||||
trace_and_difftest(&s, cpu.pc);
|
||||
if (nemu_state.state != NEMU_RUNNING) break;
|
||||
IFDEF(CONFIG_DEVICE, device_update());
|
||||
}
|
||||
}
|
||||
|
||||
static void statistic() {
|
||||
IFNDEF(CONFIG_TARGET_AM, setlocale(LC_NUMERIC, ""));
|
||||
#define NUMBERIC_FMT MUXDEF(CONFIG_TARGET_AM, "%", "%'") PRIu64
|
||||
Log("host time spent = " NUMBERIC_FMT " us", g_timer);
|
||||
Log("total guest instructions = " NUMBERIC_FMT, g_nr_guest_inst);
|
||||
if (g_timer > 0) Log("simulation frequency = " NUMBERIC_FMT " inst/s", g_nr_guest_inst * 1000000 / g_timer);
|
||||
else Log("Finish running in less than 1 us and can not calculate the simulation frequency");
|
||||
}
|
||||
|
||||
void assert_fail_msg() {
|
||||
isa_reg_display();
|
||||
statistic();
|
||||
}
|
||||
|
||||
/* Simulate how the CPU works. */
|
||||
void cpu_exec(uint64_t n) {
|
||||
g_print_step = (n < MAX_INST_TO_PRINT);
|
||||
switch (nemu_state.state) {
|
||||
case NEMU_END: case NEMU_ABORT:
|
||||
printf("Program execution has ended. To restart the program, exit NEMU and run again.\n");
|
||||
return;
|
||||
default: nemu_state.state = NEMU_RUNNING;
|
||||
}
|
||||
|
||||
uint64_t timer_start = get_time();
|
||||
|
||||
execute(n);
|
||||
|
||||
uint64_t timer_end = get_time();
|
||||
g_timer += timer_end - timer_start;
|
||||
|
||||
switch (nemu_state.state) {
|
||||
case NEMU_RUNNING: nemu_state.state = NEMU_STOP; break;
|
||||
|
||||
case NEMU_END: case NEMU_ABORT:
|
||||
Log("nemu: %s at pc = " FMT_WORD,
|
||||
(nemu_state.state == NEMU_ABORT ? ANSI_FMT("ABORT", ANSI_FG_RED) :
|
||||
(nemu_state.halt_ret == 0 ? ANSI_FMT("HIT GOOD TRAP", ANSI_FG_GREEN) :
|
||||
ANSI_FMT("HIT BAD TRAP", ANSI_FG_RED))),
|
||||
nemu_state.halt_pc);
|
||||
// fall through
|
||||
case NEMU_QUIT: statistic();
|
||||
}
|
||||
}
|
132
nemu/src/cpu/difftest/dut.c
Normal file
132
nemu/src/cpu/difftest/dut.c
Normal file
|
@ -0,0 +1,132 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <memory/paddr.h>
|
||||
#include <utils.h>
|
||||
#include <difftest-def.h>
|
||||
|
||||
void (*ref_difftest_memcpy)(paddr_t addr, void *buf, size_t n, bool direction) = NULL;
|
||||
void (*ref_difftest_regcpy)(void *dut, bool direction) = NULL;
|
||||
void (*ref_difftest_exec)(uint64_t n) = NULL;
|
||||
void (*ref_difftest_raise_intr)(uint64_t NO) = NULL;
|
||||
|
||||
#ifdef CONFIG_DIFFTEST
|
||||
|
||||
static bool is_skip_ref = false;
|
||||
static int skip_dut_nr_inst = 0;
|
||||
|
||||
// this is used to let ref skip instructions which
|
||||
// can not produce consistent behavior with NEMU
|
||||
void difftest_skip_ref() {
|
||||
is_skip_ref = true;
|
||||
// If such an instruction is one of the instruction packing in QEMU
|
||||
// (see below), we end the process of catching up with QEMU's pc to
|
||||
// keep the consistent behavior in our best.
|
||||
// Note that this is still not perfect: if the packed instructions
|
||||
// already write some memory, and the incoming instruction in NEMU
|
||||
// will load that memory, we will encounter false negative. But such
|
||||
// situation is infrequent.
|
||||
skip_dut_nr_inst = 0;
|
||||
}
|
||||
|
||||
// this is used to deal with instruction packing in QEMU.
|
||||
// Sometimes letting QEMU step once will execute multiple instructions.
|
||||
// We should skip checking until NEMU's pc catches up with QEMU's pc.
|
||||
// The semantic is
|
||||
// Let REF run `nr_ref` instructions first.
|
||||
// We expect that DUT will catch up with REF within `nr_dut` instructions.
|
||||
void difftest_skip_dut(int nr_ref, int nr_dut) {
|
||||
skip_dut_nr_inst += nr_dut;
|
||||
|
||||
while (nr_ref -- > 0) {
|
||||
ref_difftest_exec(1);
|
||||
}
|
||||
}
|
||||
|
||||
void init_difftest(char *ref_so_file, long img_size, int port) {
|
||||
assert(ref_so_file != NULL);
|
||||
|
||||
void *handle;
|
||||
handle = dlopen(ref_so_file, RTLD_LAZY);
|
||||
assert(handle);
|
||||
|
||||
ref_difftest_memcpy = dlsym(handle, "difftest_memcpy");
|
||||
assert(ref_difftest_memcpy);
|
||||
|
||||
ref_difftest_regcpy = dlsym(handle, "difftest_regcpy");
|
||||
assert(ref_difftest_regcpy);
|
||||
|
||||
ref_difftest_exec = dlsym(handle, "difftest_exec");
|
||||
assert(ref_difftest_exec);
|
||||
|
||||
ref_difftest_raise_intr = dlsym(handle, "difftest_raise_intr");
|
||||
assert(ref_difftest_raise_intr);
|
||||
|
||||
void (*ref_difftest_init)(int) = dlsym(handle, "difftest_init");
|
||||
assert(ref_difftest_init);
|
||||
|
||||
Log("Differential testing: %s", ANSI_FMT("ON", ANSI_FG_GREEN));
|
||||
Log("The result of every instruction will be compared with %s. "
|
||||
"This will help you a lot for debugging, but also significantly reduce the performance. "
|
||||
"If it is not necessary, you can turn it off in menuconfig.", ref_so_file);
|
||||
|
||||
ref_difftest_init(port);
|
||||
ref_difftest_memcpy(RESET_VECTOR, guest_to_host(RESET_VECTOR), img_size, DIFFTEST_TO_REF);
|
||||
ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF);
|
||||
}
|
||||
|
||||
static void checkregs(CPU_state *ref, vaddr_t pc) {
|
||||
if (!isa_difftest_checkregs(ref, pc)) {
|
||||
nemu_state.state = NEMU_ABORT;
|
||||
nemu_state.halt_pc = pc;
|
||||
isa_reg_display();
|
||||
}
|
||||
}
|
||||
|
||||
void difftest_step(vaddr_t pc, vaddr_t npc) {
|
||||
CPU_state ref_r;
|
||||
|
||||
if (skip_dut_nr_inst > 0) {
|
||||
ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT);
|
||||
if (ref_r.pc == npc) {
|
||||
skip_dut_nr_inst = 0;
|
||||
checkregs(&ref_r, npc);
|
||||
return;
|
||||
}
|
||||
skip_dut_nr_inst --;
|
||||
if (skip_dut_nr_inst == 0)
|
||||
panic("can not catch up with ref.pc = " FMT_WORD " at pc = " FMT_WORD, ref_r.pc, pc);
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_skip_ref) {
|
||||
// to skip the checking of an instruction, just copy the reg state to reference design
|
||||
ref_difftest_regcpy(&cpu, DIFFTEST_TO_REF);
|
||||
is_skip_ref = false;
|
||||
return;
|
||||
}
|
||||
|
||||
ref_difftest_exec(1);
|
||||
ref_difftest_regcpy(&ref_r, DIFFTEST_TO_DUT);
|
||||
|
||||
checkregs(&ref_r, pc);
|
||||
}
|
||||
#else
|
||||
void init_difftest(char *ref_so_file, long img_size, int port) { }
|
||||
#endif
|
42
nemu/src/cpu/difftest/ref.c
Normal file
42
nemu/src/cpu/difftest/ref.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <difftest-def.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
__EXPORT void difftest_memcpy(paddr_t addr, void *buf, size_t n, bool direction) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
__EXPORT void difftest_regcpy(void *dut, bool direction) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
__EXPORT void difftest_exec(uint64_t n) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
__EXPORT void difftest_raise_intr(word_t NO) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
__EXPORT void difftest_init(int port) {
|
||||
void init_mem();
|
||||
init_mem();
|
||||
/* Perform ISA dependent initialization. */
|
||||
init_isa();
|
||||
}
|
154
nemu/src/device/Kconfig
Normal file
154
nemu/src/device/Kconfig
Normal file
|
@ -0,0 +1,154 @@
|
|||
menuconfig DEVICE
|
||||
depends on !TARGET_SHARE
|
||||
bool "Devices"
|
||||
default n
|
||||
help
|
||||
Provide device support for NEMU.
|
||||
|
||||
if DEVICE
|
||||
|
||||
config HAS_PORT_IO
|
||||
bool
|
||||
default y if ISA_x86
|
||||
default n
|
||||
|
||||
menuconfig HAS_SERIAL
|
||||
bool "Enable serial"
|
||||
default y
|
||||
|
||||
if HAS_SERIAL
|
||||
config SERIAL_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the serial controller"
|
||||
default 0x3f8
|
||||
|
||||
config SERIAL_MMIO
|
||||
hex "MMIO address of the serial controller"
|
||||
default 0xa00003f8
|
||||
|
||||
config SERIAL_INPUT_FIFO
|
||||
bool "Enable input FIFO with /tmp/nemu.serial"
|
||||
default n
|
||||
endif # HAS_SERIAL
|
||||
|
||||
menuconfig HAS_TIMER
|
||||
bool "Enable timer"
|
||||
default y
|
||||
|
||||
if HAS_TIMER
|
||||
config RTC_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the timer"
|
||||
default 0x48
|
||||
|
||||
config RTC_MMIO
|
||||
hex "MMIO address of the timer"
|
||||
default 0xa0000048
|
||||
endif # HAS_TIMER
|
||||
|
||||
menuconfig HAS_KEYBOARD
|
||||
bool "Enable keyboard"
|
||||
default y
|
||||
|
||||
if HAS_KEYBOARD
|
||||
config I8042_DATA_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the keyboard controller"
|
||||
default 0x60
|
||||
|
||||
config I8042_DATA_MMIO
|
||||
hex "MMIO address of the keyboard controller"
|
||||
default 0xa0000060
|
||||
endif # HAS_KEYBOARD
|
||||
|
||||
menuconfig HAS_VGA
|
||||
bool "Enable VGA"
|
||||
default y
|
||||
|
||||
if HAS_VGA
|
||||
config FB_ADDR
|
||||
hex "Physical address of the VGA frame buffer"
|
||||
default 0xa1000000
|
||||
|
||||
config VGA_CTL_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the VGA controller"
|
||||
default 0x100
|
||||
|
||||
config VGA_CTL_MMIO
|
||||
hex "MMIO address of the VGA controller"
|
||||
default 0xa0000100
|
||||
|
||||
config VGA_SHOW_SCREEN
|
||||
bool "Enable SDL SCREEN"
|
||||
default y
|
||||
|
||||
choice
|
||||
prompt "Screen Size"
|
||||
default VGA_SIZE_400x300
|
||||
config VGA_SIZE_400x300
|
||||
bool "400 x 300"
|
||||
config VGA_SIZE_800x600
|
||||
bool "800 x 600"
|
||||
endchoice
|
||||
endif # HAS_VGA
|
||||
|
||||
if !TARGET_AM
|
||||
menuconfig HAS_AUDIO
|
||||
bool "Enable audio"
|
||||
default y
|
||||
|
||||
if HAS_AUDIO
|
||||
config SB_ADDR
|
||||
hex "Physical address of the audio stream buffer"
|
||||
default 0xa1200000
|
||||
|
||||
config SB_SIZE
|
||||
hex "Size of the audio stream buffer"
|
||||
default 0x10000
|
||||
|
||||
config AUDIO_CTL_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the audio controller"
|
||||
default 0x200
|
||||
|
||||
config AUDIO_CTL_MMIO
|
||||
hex "MMIO address of the audio controller"
|
||||
default 0xa0000200
|
||||
endif # HAS_AUDIO
|
||||
|
||||
menuconfig HAS_DISK
|
||||
bool "Enable disk"
|
||||
default y
|
||||
|
||||
if HAS_DISK
|
||||
config DISK_CTL_PORT
|
||||
depends on HAS_PORT_IO
|
||||
hex "Port address of the disk controller"
|
||||
default 0x300
|
||||
|
||||
config DISK_CTL_MMIO
|
||||
hex "MMIO address of the disk controller"
|
||||
default 0xa0000300
|
||||
|
||||
config DISK_IMG_PATH
|
||||
string "The path of disk image"
|
||||
default ""
|
||||
endif # HAS_DISK
|
||||
|
||||
menuconfig HAS_SDCARD
|
||||
bool "Enable sdcard"
|
||||
default n
|
||||
|
||||
if HAS_SDCARD
|
||||
config SDCARD_CTL_MMIO
|
||||
hex "MMIO address of the sdcard controller"
|
||||
default 0xa3000000
|
||||
|
||||
config SDCARD_IMG_PATH
|
||||
string "The path of sdcard image"
|
||||
default ""
|
||||
endif # HAS_SDCARD
|
||||
endif
|
||||
|
||||
endif # DEVICE
|
51
nemu/src/device/alarm.c
Normal file
51
nemu/src/device/alarm.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
#include <device/alarm.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
|
||||
#define MAX_HANDLER 8
|
||||
|
||||
static alarm_handler_t handler[MAX_HANDLER] = {};
|
||||
static int idx = 0;
|
||||
|
||||
void add_alarm_handle(alarm_handler_t h) {
|
||||
assert(idx < MAX_HANDLER);
|
||||
handler[idx ++] = h;
|
||||
}
|
||||
|
||||
static void alarm_sig_handler(int signum) {
|
||||
int i;
|
||||
for (i = 0; i < idx; i ++) {
|
||||
handler[i]();
|
||||
}
|
||||
}
|
||||
|
||||
void init_alarm() {
|
||||
struct sigaction s;
|
||||
memset(&s, 0, sizeof(s));
|
||||
s.sa_handler = alarm_sig_handler;
|
||||
int ret = sigaction(SIGVTALRM, &s, NULL);
|
||||
Assert(ret == 0, "Can not set signal handler");
|
||||
|
||||
struct itimerval it = {};
|
||||
it.it_value.tv_sec = 0;
|
||||
it.it_value.tv_usec = 1000000 / TIMER_HZ;
|
||||
it.it_interval = it.it_value;
|
||||
ret = setitimer(ITIMER_VIRTUAL, &it, NULL);
|
||||
Assert(ret == 0, "Can not set timer");
|
||||
}
|
47
nemu/src/device/audio.c
Normal file
47
nemu/src/device/audio.c
Normal file
|
@ -0,0 +1,47 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
#include <device/map.h>
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
enum {
|
||||
reg_freq,
|
||||
reg_channels,
|
||||
reg_samples,
|
||||
reg_sbuf_size,
|
||||
reg_init,
|
||||
reg_count,
|
||||
nr_reg
|
||||
};
|
||||
|
||||
static uint8_t *sbuf = NULL;
|
||||
static uint32_t *audio_base = NULL;
|
||||
|
||||
static void audio_io_handler(uint32_t offset, int len, bool is_write) {
|
||||
}
|
||||
|
||||
void init_audio() {
|
||||
uint32_t space_size = sizeof(uint32_t) * nr_reg;
|
||||
audio_base = (uint32_t *)new_space(space_size);
|
||||
#ifdef CONFIG_HAS_PORT_IO
|
||||
add_pio_map ("audio", CONFIG_AUDIO_CTL_PORT, audio_base, space_size, audio_io_handler);
|
||||
#else
|
||||
add_mmio_map("audio", CONFIG_AUDIO_CTL_MMIO, audio_base, space_size, audio_io_handler);
|
||||
#endif
|
||||
|
||||
sbuf = (uint8_t *)new_space(CONFIG_SB_SIZE);
|
||||
add_mmio_map("audio-sbuf", CONFIG_SB_ADDR, sbuf, CONFIG_SB_SIZE, NULL);
|
||||
}
|
89
nemu/src/device/device.c
Normal file
89
nemu/src/device/device.c
Normal file
|
@ -0,0 +1,89 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
#include <utils.h>
|
||||
#include <device/alarm.h>
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
#include <SDL2/SDL.h>
|
||||
#endif
|
||||
|
||||
void init_map();
|
||||
void init_serial();
|
||||
void init_timer();
|
||||
void init_vga();
|
||||
void init_i8042();
|
||||
void init_audio();
|
||||
void init_disk();
|
||||
void init_sdcard();
|
||||
void init_alarm();
|
||||
|
||||
void send_key(uint8_t, bool);
|
||||
void vga_update_screen();
|
||||
|
||||
void device_update() {
|
||||
static uint64_t last = 0;
|
||||
uint64_t now = get_time();
|
||||
if (now - last < 1000000 / TIMER_HZ) {
|
||||
return;
|
||||
}
|
||||
last = now;
|
||||
|
||||
IFDEF(CONFIG_HAS_VGA, vga_update_screen());
|
||||
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event)) {
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
nemu_state.state = NEMU_QUIT;
|
||||
break;
|
||||
#ifdef CONFIG_HAS_KEYBOARD
|
||||
// If a key was pressed
|
||||
case SDL_KEYDOWN:
|
||||
case SDL_KEYUP: {
|
||||
uint8_t k = event.key.keysym.scancode;
|
||||
bool is_keydown = (event.key.type == SDL_KEYDOWN);
|
||||
send_key(k, is_keydown);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void sdl_clear_event_queue() {
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
SDL_Event event;
|
||||
while (SDL_PollEvent(&event));
|
||||
#endif
|
||||
}
|
||||
|
||||
void init_device() {
|
||||
IFDEF(CONFIG_TARGET_AM, ioe_init());
|
||||
init_map();
|
||||
|
||||
IFDEF(CONFIG_HAS_SERIAL, init_serial());
|
||||
IFDEF(CONFIG_HAS_TIMER, init_timer());
|
||||
IFDEF(CONFIG_HAS_VGA, init_vga());
|
||||
IFDEF(CONFIG_HAS_KEYBOARD, init_i8042());
|
||||
IFDEF(CONFIG_HAS_AUDIO, init_audio());
|
||||
IFDEF(CONFIG_HAS_DISK, init_disk());
|
||||
IFDEF(CONFIG_HAS_SDCARD, init_sdcard());
|
||||
|
||||
IFNDEF(CONFIG_TARGET_AM, init_alarm());
|
||||
}
|
19
nemu/src/device/disk.c
Normal file
19
nemu/src/device/disk.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
|
||||
void init_disk() {
|
||||
}
|
32
nemu/src/device/filelist.mk
Normal file
32
nemu/src/device/filelist.mk
Normal file
|
@ -0,0 +1,32 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
DIRS-y += src/device/io
|
||||
SRCS-$(CONFIG_DEVICE) += src/device/device.c src/device/alarm.c src/device/intr.c
|
||||
SRCS-$(CONFIG_HAS_SERIAL) += src/device/serial.c
|
||||
SRCS-$(CONFIG_HAS_TIMER) += src/device/timer.c
|
||||
SRCS-$(CONFIG_HAS_KEYBOARD) += src/device/keyboard.c
|
||||
SRCS-$(CONFIG_HAS_VGA) += src/device/vga.c
|
||||
SRCS-$(CONFIG_HAS_AUDIO) += src/device/audio.c
|
||||
SRCS-$(CONFIG_HAS_DISK) += src/device/disk.c
|
||||
SRCS-$(CONFIG_HAS_SDCARD) += src/device/sdcard.c
|
||||
|
||||
SRCS-BLACKLIST-$(CONFIG_TARGET_AM) += src/device/alarm.c
|
||||
|
||||
ifdef CONFIG_DEVICE
|
||||
ifndef CONFIG_TARGET_AM
|
||||
LIBS += -lSDL2
|
||||
endif
|
||||
endif
|
19
nemu/src/device/intr.c
Normal file
19
nemu/src/device/intr.c
Normal file
|
@ -0,0 +1,19 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
void dev_raise_intr() {
|
||||
}
|
70
nemu/src/device/io/map.c
Normal file
70
nemu/src/device/io/map.c
Normal file
|
@ -0,0 +1,70 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/host.h>
|
||||
#include <memory/vaddr.h>
|
||||
#include <device/map.h>
|
||||
|
||||
#define IO_SPACE_MAX (2 * 1024 * 1024)
|
||||
|
||||
static uint8_t *io_space = NULL;
|
||||
static uint8_t *p_space = NULL;
|
||||
|
||||
uint8_t* new_space(int size) {
|
||||
uint8_t *p = p_space;
|
||||
// page aligned;
|
||||
size = (size + (PAGE_SIZE - 1)) & ~PAGE_MASK;
|
||||
p_space += size;
|
||||
assert(p_space - io_space < IO_SPACE_MAX);
|
||||
return p;
|
||||
}
|
||||
|
||||
static void check_bound(IOMap *map, paddr_t addr) {
|
||||
if (map == NULL) {
|
||||
Assert(map != NULL, "address (" FMT_PADDR ") is out of bound at pc = " FMT_WORD, addr, cpu.pc);
|
||||
} else {
|
||||
Assert(addr <= map->high && addr >= map->low,
|
||||
"address (" FMT_PADDR ") is out of bound {%s} [" FMT_PADDR ", " FMT_PADDR "] at pc = " FMT_WORD,
|
||||
addr, map->name, map->low, map->high, cpu.pc);
|
||||
}
|
||||
}
|
||||
|
||||
static void invoke_callback(io_callback_t c, paddr_t offset, int len, bool is_write) {
|
||||
if (c != NULL) { c(offset, len, is_write); }
|
||||
}
|
||||
|
||||
void init_map() {
|
||||
io_space = malloc(IO_SPACE_MAX);
|
||||
assert(io_space);
|
||||
p_space = io_space;
|
||||
}
|
||||
|
||||
word_t map_read(paddr_t addr, int len, IOMap *map) {
|
||||
assert(len >= 1 && len <= 8);
|
||||
check_bound(map, addr);
|
||||
paddr_t offset = addr - map->low;
|
||||
invoke_callback(map->callback, offset, len, false); // prepare data to read
|
||||
word_t ret = host_read(map->space + offset, len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void map_write(paddr_t addr, int len, word_t data, IOMap *map) {
|
||||
assert(len >= 1 && len <= 8);
|
||||
check_bound(map, addr);
|
||||
paddr_t offset = addr - map->low;
|
||||
host_write(map->space + offset, len, data);
|
||||
invoke_callback(map->callback, offset, len, true);
|
||||
}
|
63
nemu/src/device/io/mmio.c
Normal file
63
nemu/src/device/io/mmio.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
#define NR_MAP 16
|
||||
|
||||
static IOMap maps[NR_MAP] = {};
|
||||
static int nr_map = 0;
|
||||
|
||||
static IOMap* fetch_mmio_map(paddr_t addr) {
|
||||
int mapid = find_mapid_by_addr(maps, nr_map, addr);
|
||||
return (mapid == -1 ? NULL : &maps[mapid]);
|
||||
}
|
||||
|
||||
static void report_mmio_overlap(const char *name1, paddr_t l1, paddr_t r1,
|
||||
const char *name2, paddr_t l2, paddr_t r2) {
|
||||
panic("MMIO region %s@[" FMT_PADDR ", " FMT_PADDR "] is overlapped "
|
||||
"with %s@[" FMT_PADDR ", " FMT_PADDR "]", name1, l1, r1, name2, l2, r2);
|
||||
}
|
||||
|
||||
/* device interface */
|
||||
void add_mmio_map(const char *name, paddr_t addr, void *space, uint32_t len, io_callback_t callback) {
|
||||
assert(nr_map < NR_MAP);
|
||||
paddr_t left = addr, right = addr + len - 1;
|
||||
if (in_pmem(left) || in_pmem(right)) {
|
||||
report_mmio_overlap(name, left, right, "pmem", PMEM_LEFT, PMEM_RIGHT);
|
||||
}
|
||||
for (int i = 0; i < nr_map; i++) {
|
||||
if (left <= maps[i].high && right >= maps[i].low) {
|
||||
report_mmio_overlap(name, left, right, maps[i].name, maps[i].low, maps[i].high);
|
||||
}
|
||||
}
|
||||
|
||||
maps[nr_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
|
||||
.space = space, .callback = callback };
|
||||
Log("Add mmio map '%s' at [" FMT_PADDR ", " FMT_PADDR "]",
|
||||
maps[nr_map].name, maps[nr_map].low, maps[nr_map].high);
|
||||
|
||||
nr_map ++;
|
||||
}
|
||||
|
||||
/* bus interface */
|
||||
word_t mmio_read(paddr_t addr, int len) {
|
||||
return map_read(addr, len, fetch_mmio_map(addr));
|
||||
}
|
||||
|
||||
void mmio_write(paddr_t addr, int len, word_t data) {
|
||||
map_write(addr, len, data, fetch_mmio_map(addr));
|
||||
}
|
49
nemu/src/device/io/port-io.c
Normal file
49
nemu/src/device/io/port-io.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
|
||||
#define PORT_IO_SPACE_MAX 65535
|
||||
|
||||
#define NR_MAP 16
|
||||
static IOMap maps[NR_MAP] = {};
|
||||
static int nr_map = 0;
|
||||
|
||||
/* device interface */
|
||||
void add_pio_map(const char *name, ioaddr_t addr, void *space, uint32_t len, io_callback_t callback) {
|
||||
assert(nr_map < NR_MAP);
|
||||
assert(addr + len <= PORT_IO_SPACE_MAX);
|
||||
maps[nr_map] = (IOMap){ .name = name, .low = addr, .high = addr + len - 1,
|
||||
.space = space, .callback = callback };
|
||||
Log("Add port-io map '%s' at [" FMT_PADDR ", " FMT_PADDR "]",
|
||||
maps[nr_map].name, maps[nr_map].low, maps[nr_map].high);
|
||||
|
||||
nr_map ++;
|
||||
}
|
||||
|
||||
/* CPU interface */
|
||||
uint32_t pio_read(ioaddr_t addr, int len) {
|
||||
assert(addr + len - 1 < PORT_IO_SPACE_MAX);
|
||||
int mapid = find_mapid_by_addr(maps, nr_map, addr);
|
||||
assert(mapid != -1);
|
||||
return map_read(addr, len, &maps[mapid]);
|
||||
}
|
||||
|
||||
void pio_write(ioaddr_t addr, int len, uint32_t data) {
|
||||
assert(addr + len - 1 < PORT_IO_SPACE_MAX);
|
||||
int mapid = find_mapid_by_addr(maps, nr_map, addr);
|
||||
assert(mapid != -1);
|
||||
map_write(addr, len, data, &maps[mapid]);
|
||||
}
|
100
nemu/src/device/keyboard.c
Normal file
100
nemu/src/device/keyboard.c
Normal file
|
@ -0,0 +1,100 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
#include <utils.h>
|
||||
|
||||
#define KEYDOWN_MASK 0x8000
|
||||
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
// Note that this is not the standard
|
||||
#define NEMU_KEYS(f) \
|
||||
f(ESCAPE) f(F1) f(F2) f(F3) f(F4) f(F5) f(F6) f(F7) f(F8) f(F9) f(F10) f(F11) f(F12) \
|
||||
f(GRAVE) f(1) f(2) f(3) f(4) f(5) f(6) f(7) f(8) f(9) f(0) f(MINUS) f(EQUALS) f(BACKSPACE) \
|
||||
f(TAB) f(Q) f(W) f(E) f(R) f(T) f(Y) f(U) f(I) f(O) f(P) f(LEFTBRACKET) f(RIGHTBRACKET) f(BACKSLASH) \
|
||||
f(CAPSLOCK) f(A) f(S) f(D) f(F) f(G) f(H) f(J) f(K) f(L) f(SEMICOLON) f(APOSTROPHE) f(RETURN) \
|
||||
f(LSHIFT) f(Z) f(X) f(C) f(V) f(B) f(N) f(M) f(COMMA) f(PERIOD) f(SLASH) f(RSHIFT) \
|
||||
f(LCTRL) f(APPLICATION) f(LALT) f(SPACE) f(RALT) f(RCTRL) \
|
||||
f(UP) f(DOWN) f(LEFT) f(RIGHT) f(INSERT) f(DELETE) f(HOME) f(END) f(PAGEUP) f(PAGEDOWN)
|
||||
|
||||
#define NEMU_KEY_NAME(k) NEMU_KEY_ ## k,
|
||||
|
||||
enum {
|
||||
NEMU_KEY_NONE = 0,
|
||||
MAP(NEMU_KEYS, NEMU_KEY_NAME)
|
||||
};
|
||||
|
||||
#define SDL_KEYMAP(k) keymap[SDL_SCANCODE_ ## k] = NEMU_KEY_ ## k;
|
||||
static uint32_t keymap[256] = {};
|
||||
|
||||
static void init_keymap() {
|
||||
MAP(NEMU_KEYS, SDL_KEYMAP)
|
||||
}
|
||||
|
||||
#define KEY_QUEUE_LEN 1024
|
||||
static int key_queue[KEY_QUEUE_LEN] = {};
|
||||
static int key_f = 0, key_r = 0;
|
||||
|
||||
static void key_enqueue(uint32_t am_scancode) {
|
||||
key_queue[key_r] = am_scancode;
|
||||
key_r = (key_r + 1) % KEY_QUEUE_LEN;
|
||||
Assert(key_r != key_f, "key queue overflow!");
|
||||
}
|
||||
|
||||
static uint32_t key_dequeue() {
|
||||
uint32_t key = NEMU_KEY_NONE;
|
||||
if (key_f != key_r) {
|
||||
key = key_queue[key_f];
|
||||
key_f = (key_f + 1) % KEY_QUEUE_LEN;
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
void send_key(uint8_t scancode, bool is_keydown) {
|
||||
if (nemu_state.state == NEMU_RUNNING && keymap[scancode] != NEMU_KEY_NONE) {
|
||||
uint32_t am_scancode = keymap[scancode] | (is_keydown ? KEYDOWN_MASK : 0);
|
||||
key_enqueue(am_scancode);
|
||||
}
|
||||
}
|
||||
#else // !CONFIG_TARGET_AM
|
||||
#define NEMU_KEY_NONE 0
|
||||
|
||||
static uint32_t key_dequeue() {
|
||||
AM_INPUT_KEYBRD_T ev = io_read(AM_INPUT_KEYBRD);
|
||||
uint32_t am_scancode = ev.keycode | (ev.keydown ? KEYDOWN_MASK : 0);
|
||||
return am_scancode;
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t *i8042_data_port_base = NULL;
|
||||
|
||||
static void i8042_data_io_handler(uint32_t offset, int len, bool is_write) {
|
||||
assert(!is_write);
|
||||
assert(offset == 0);
|
||||
i8042_data_port_base[0] = key_dequeue();
|
||||
}
|
||||
|
||||
void init_i8042() {
|
||||
i8042_data_port_base = (uint32_t *)new_space(4);
|
||||
i8042_data_port_base[0] = NEMU_KEY_NONE;
|
||||
#ifdef CONFIG_HAS_PORT_IO
|
||||
add_pio_map ("keyboard", CONFIG_I8042_DATA_PORT, i8042_data_port_base, 4, i8042_data_io_handler);
|
||||
#else
|
||||
add_mmio_map("keyboard", CONFIG_I8042_DATA_MMIO, i8042_data_port_base, 4, i8042_data_io_handler);
|
||||
#endif
|
||||
IFNDEF(CONFIG_TARGET_AM, init_keymap());
|
||||
}
|
439
nemu/src/device/mmc.h
Normal file
439
nemu/src/device/mmc.h
Normal file
|
@ -0,0 +1,439 @@
|
|||
/*
|
||||
* Header for MultiMediaCard (MMC)
|
||||
*
|
||||
* Copyright 2002 Hewlett-Packard Company
|
||||
*
|
||||
* Use consistent with the GNU GPL is permitted,
|
||||
* provided that this copyright notice is
|
||||
* preserved in its entirety in all copies and derived works.
|
||||
*
|
||||
* HEWLETT-PACKARD COMPANY MAKES NO WARRANTIES, EXPRESSED OR IMPLIED,
|
||||
* AS TO THE USEFULNESS OR CORRECTNESS OF THIS CODE OR ITS
|
||||
* FITNESS FOR ANY PARTICULAR PURPOSE.
|
||||
*
|
||||
* Many thanks to Alessandro Rubini and Jonathan Corbet!
|
||||
*
|
||||
* Based strongly on code by:
|
||||
*
|
||||
* Author: Yong-iL Joh <tolkien@mizi.com>
|
||||
*
|
||||
* Author: Andrew Christian
|
||||
* 15 May 2002
|
||||
*/
|
||||
|
||||
#ifndef LINUX_MMC_MMC_H
|
||||
#define LINUX_MMC_MMC_H
|
||||
|
||||
/* Standard MMC commands (4.1) type argument response */
|
||||
/* class 1 */
|
||||
#define MMC_GO_IDLE_STATE 0 /* bc */
|
||||
#define MMC_SEND_OP_COND 1 /* bcr [31:0] OCR R3 */
|
||||
#define MMC_ALL_SEND_CID 2 /* bcr R2 */
|
||||
#define MMC_SET_RELATIVE_ADDR 3 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SET_DSR 4 /* bc [31:16] RCA */
|
||||
#define MMC_SLEEP_AWAKE 5 /* ac [31:16] RCA 15:flg R1b */
|
||||
#define MMC_SWITCH 6 /* ac [31:0] See below R1b */
|
||||
#define MMC_SELECT_CARD 7 /* ac [31:16] RCA R1 */
|
||||
#define MMC_SEND_EXT_CSD 8 /* adtc R1 */
|
||||
#define MMC_SEND_CSD 9 /* ac [31:16] RCA R2 */
|
||||
#define MMC_SEND_CID 10 /* ac [31:16] RCA R2 */
|
||||
#define MMC_READ_DAT_UNTIL_STOP 11 /* adtc [31:0] dadr R1 */
|
||||
#define MMC_STOP_TRANSMISSION 12 /* ac R1b */
|
||||
#define MMC_SEND_STATUS 13 /* ac [31:16] RCA R1 */
|
||||
#define MMC_BUS_TEST_R 14 /* adtc R1 */
|
||||
#define MMC_GO_INACTIVE_STATE 15 /* ac [31:16] RCA */
|
||||
#define MMC_BUS_TEST_W 19 /* adtc R1 */
|
||||
#define MMC_SPI_READ_OCR 58 /* spi spi_R3 */
|
||||
#define MMC_SPI_CRC_ON_OFF 59 /* spi [0:0] flag spi_R1 */
|
||||
|
||||
/* class 2 */
|
||||
#define MMC_SET_BLOCKLEN 16 /* ac [31:0] block len R1 */
|
||||
#define MMC_READ_SINGLE_BLOCK 17 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_READ_MULTIPLE_BLOCK 18 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK 19 /* adtc R1 */
|
||||
#define MMC_SEND_TUNING_BLOCK_HS200 21 /* adtc R1 */
|
||||
|
||||
/* class 3 */
|
||||
#define MMC_WRITE_DAT_UNTIL_STOP 20 /* adtc [31:0] data addr R1 */
|
||||
|
||||
/* class 4 */
|
||||
#define MMC_SET_BLOCK_COUNT 23 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_BLOCK 24 /* adtc [31:0] data addr R1 */
|
||||
#define MMC_WRITE_MULTIPLE_BLOCK 25 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CID 26 /* adtc R1 */
|
||||
#define MMC_PROGRAM_CSD 27 /* adtc R1 */
|
||||
|
||||
/* class 6 */
|
||||
#define MMC_SET_WRITE_PROT 28 /* ac [31:0] data addr R1b */
|
||||
#define MMC_CLR_WRITE_PROT 29 /* ac [31:0] data addr R1b */
|
||||
#define MMC_SEND_WRITE_PROT 30 /* adtc [31:0] wpdata addr R1 */
|
||||
|
||||
/* class 5 */
|
||||
#define MMC_ERASE_GROUP_START 35 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE_GROUP_END 36 /* ac [31:0] data addr R1 */
|
||||
#define MMC_ERASE 38 /* ac R1b */
|
||||
|
||||
/* class 9 */
|
||||
#define MMC_FAST_IO 39 /* ac <Complex> R4 */
|
||||
#define MMC_GO_IRQ_STATE 40 /* bcr R5 */
|
||||
|
||||
/* class 7 */
|
||||
#define MMC_LOCK_UNLOCK 42 /* adtc R1b */
|
||||
|
||||
/* class 8 */
|
||||
#define MMC_APP_CMD 55 /* ac [31:16] RCA R1 */
|
||||
#define MMC_GEN_CMD 56 /* adtc [0] RD/WR R1 */
|
||||
|
||||
/* class 11 */
|
||||
#define MMC_QUE_TASK_PARAMS 44 /* ac [20:16] task id R1 */
|
||||
#define MMC_QUE_TASK_ADDR 45 /* ac [31:0] data addr R1 */
|
||||
#define MMC_EXECUTE_READ_TASK 46 /* adtc [20:16] task id R1 */
|
||||
#define MMC_EXECUTE_WRITE_TASK 47 /* adtc [20:16] task id R1 */
|
||||
#define MMC_CMDQ_TASK_MGMT 48 /* ac [20:16] task id R1b */
|
||||
|
||||
//static inline bool mmc_op_multi(u32 opcode)
|
||||
//{
|
||||
// return opcode == MMC_WRITE_MULTIPLE_BLOCK ||
|
||||
// opcode == MMC_READ_MULTIPLE_BLOCK;
|
||||
//}
|
||||
|
||||
/*
|
||||
* MMC_SWITCH argument format:
|
||||
*
|
||||
* [31:26] Always 0
|
||||
* [25:24] Access Mode
|
||||
* [23:16] Location of target Byte in EXT_CSD
|
||||
* [15:08] Value Byte
|
||||
* [07:03] Always 0
|
||||
* [02:00] Command Set
|
||||
*/
|
||||
|
||||
/*
|
||||
MMC status in R1, for native mode (SPI bits are different)
|
||||
Type
|
||||
e : error bit
|
||||
s : status bit
|
||||
r : detected and set for the actual command response
|
||||
x : detected and set during command execution. the host must poll
|
||||
the card by sending status command in order to read these bits.
|
||||
Clear condition
|
||||
a : according to the card state
|
||||
b : always related to the previous command. Reception of
|
||||
a valid command will clear it (with a delay of one command)
|
||||
c : clear by read
|
||||
*/
|
||||
|
||||
#define R1_OUT_OF_RANGE (1 << 31) /* er, c */
|
||||
#define R1_ADDRESS_ERROR (1 << 30) /* erx, c */
|
||||
#define R1_BLOCK_LEN_ERROR (1 << 29) /* er, c */
|
||||
#define R1_ERASE_SEQ_ERROR (1 << 28) /* er, c */
|
||||
#define R1_ERASE_PARAM (1 << 27) /* ex, c */
|
||||
#define R1_WP_VIOLATION (1 << 26) /* erx, c */
|
||||
#define R1_CARD_IS_LOCKED (1 << 25) /* sx, a */
|
||||
#define R1_LOCK_UNLOCK_FAILED (1 << 24) /* erx, c */
|
||||
#define R1_COM_CRC_ERROR (1 << 23) /* er, b */
|
||||
#define R1_ILLEGAL_COMMAND (1 << 22) /* er, b */
|
||||
#define R1_CARD_ECC_FAILED (1 << 21) /* ex, c */
|
||||
#define R1_CC_ERROR (1 << 20) /* erx, c */
|
||||
#define R1_ERROR (1 << 19) /* erx, c */
|
||||
#define R1_UNDERRUN (1 << 18) /* ex, c */
|
||||
#define R1_OVERRUN (1 << 17) /* ex, c */
|
||||
#define R1_CID_CSD_OVERWRITE (1 << 16) /* erx, c, CID/CSD overwrite */
|
||||
#define R1_WP_ERASE_SKIP (1 << 15) /* sx, c */
|
||||
#define R1_CARD_ECC_DISABLED (1 << 14) /* sx, a */
|
||||
#define R1_ERASE_RESET (1 << 13) /* sr, c */
|
||||
#define R1_STATUS(x) (x & 0xFFFFE000)
|
||||
#define R1_CURRENT_STATE(x) ((x & 0x00001E00) >> 9) /* sx, b (4 bits) */
|
||||
#define R1_READY_FOR_DATA (1 << 8) /* sx, a */
|
||||
#define R1_SWITCH_ERROR (1 << 7) /* sx, c */
|
||||
#define R1_EXCEPTION_EVENT (1 << 6) /* sr, a */
|
||||
#define R1_APP_CMD (1 << 5) /* sr, c */
|
||||
|
||||
#define R1_STATE_IDLE 0
|
||||
#define R1_STATE_READY 1
|
||||
#define R1_STATE_IDENT 2
|
||||
#define R1_STATE_STBY 3
|
||||
#define R1_STATE_TRAN 4
|
||||
#define R1_STATE_DATA 5
|
||||
#define R1_STATE_RCV 6
|
||||
#define R1_STATE_PRG 7
|
||||
#define R1_STATE_DIS 8
|
||||
|
||||
/*
|
||||
* MMC/SD in SPI mode reports R1 status always, and R2 for SEND_STATUS
|
||||
* R1 is the low order byte; R2 is the next highest byte, when present.
|
||||
*/
|
||||
#define R1_SPI_IDLE (1 << 0)
|
||||
#define R1_SPI_ERASE_RESET (1 << 1)
|
||||
#define R1_SPI_ILLEGAL_COMMAND (1 << 2)
|
||||
#define R1_SPI_COM_CRC (1 << 3)
|
||||
#define R1_SPI_ERASE_SEQ (1 << 4)
|
||||
#define R1_SPI_ADDRESS (1 << 5)
|
||||
#define R1_SPI_PARAMETER (1 << 6)
|
||||
/* R1 bit 7 is always zero */
|
||||
#define R2_SPI_CARD_LOCKED (1 << 8)
|
||||
#define R2_SPI_WP_ERASE_SKIP (1 << 9) /* or lock/unlock fail */
|
||||
#define R2_SPI_LOCK_UNLOCK_FAIL R2_SPI_WP_ERASE_SKIP
|
||||
#define R2_SPI_ERROR (1 << 10)
|
||||
#define R2_SPI_CC_ERROR (1 << 11)
|
||||
#define R2_SPI_CARD_ECC_ERROR (1 << 12)
|
||||
#define R2_SPI_WP_VIOLATION (1 << 13)
|
||||
#define R2_SPI_ERASE_PARAM (1 << 14)
|
||||
#define R2_SPI_OUT_OF_RANGE (1 << 15) /* or CSD overwrite */
|
||||
#define R2_SPI_CSD_OVERWRITE R2_SPI_OUT_OF_RANGE
|
||||
|
||||
/*
|
||||
* OCR bits are mostly in host.h
|
||||
*/
|
||||
#define MMC_CARD_BUSY 0x80000000 /* Card Power up status bit */
|
||||
|
||||
/*
|
||||
* Card Command Classes (CCC)
|
||||
*/
|
||||
#define CCC_BASIC (1<<0) /* (0) Basic protocol functions */
|
||||
/* (CMD0,1,2,3,4,7,9,10,12,13,15) */
|
||||
/* (and for SPI, CMD58,59) */
|
||||
#define CCC_STREAM_READ (1<<1) /* (1) Stream read commands */
|
||||
/* (CMD11) */
|
||||
#define CCC_BLOCK_READ (1<<2) /* (2) Block read commands */
|
||||
/* (CMD16,17,18) */
|
||||
#define CCC_STREAM_WRITE (1<<3) /* (3) Stream write commands */
|
||||
/* (CMD20) */
|
||||
#define CCC_BLOCK_WRITE (1<<4) /* (4) Block write commands */
|
||||
/* (CMD16,24,25,26,27) */
|
||||
#define CCC_ERASE (1<<5) /* (5) Ability to erase blocks */
|
||||
/* (CMD32,33,34,35,36,37,38,39) */
|
||||
#define CCC_WRITE_PROT (1<<6) /* (6) Able to write protect blocks */
|
||||
/* (CMD28,29,30) */
|
||||
#define CCC_LOCK_CARD (1<<7) /* (7) Able to lock down card */
|
||||
/* (CMD16,CMD42) */
|
||||
#define CCC_APP_SPEC (1<<8) /* (8) Application specific */
|
||||
/* (CMD55,56,57,ACMD*) */
|
||||
#define CCC_IO_MODE (1<<9) /* (9) I/O mode */
|
||||
/* (CMD5,39,40,52,53) */
|
||||
#define CCC_SWITCH (1<<10) /* (10) High speed switch */
|
||||
/* (CMD6,34,35,36,37,50) */
|
||||
/* (11) Reserved */
|
||||
/* (CMD?) */
|
||||
|
||||
/*
|
||||
* CSD field definitions
|
||||
*/
|
||||
|
||||
#define CSD_STRUCT_VER_1_0 0 /* Valid for system specification 1.0 - 1.2 */
|
||||
#define CSD_STRUCT_VER_1_1 1 /* Valid for system specification 1.4 - 2.2 */
|
||||
#define CSD_STRUCT_VER_1_2 2 /* Valid for system specification 3.1 - 3.2 - 3.31 - 4.0 - 4.1 */
|
||||
#define CSD_STRUCT_EXT_CSD 3 /* Version is coded in CSD_STRUCTURE in EXT_CSD */
|
||||
|
||||
#define CSD_SPEC_VER_0 0 /* Implements system specification 1.0 - 1.2 */
|
||||
#define CSD_SPEC_VER_1 1 /* Implements system specification 1.4 */
|
||||
#define CSD_SPEC_VER_2 2 /* Implements system specification 2.0 - 2.2 */
|
||||
#define CSD_SPEC_VER_3 3 /* Implements system specification 3.1 - 3.2 - 3.31 */
|
||||
#define CSD_SPEC_VER_4 4 /* Implements system specification 4.0 - 4.1 */
|
||||
|
||||
/*
|
||||
* EXT_CSD fields
|
||||
*/
|
||||
|
||||
#define EXT_CSD_CMDQ_MODE_EN 15 /* R/W */
|
||||
#define EXT_CSD_FLUSH_CACHE 32 /* W */
|
||||
#define EXT_CSD_CACHE_CTRL 33 /* R/W */
|
||||
#define EXT_CSD_POWER_OFF_NOTIFICATION 34 /* R/W */
|
||||
#define EXT_CSD_PACKED_FAILURE_INDEX 35 /* RO */
|
||||
#define EXT_CSD_PACKED_CMD_STATUS 36 /* RO */
|
||||
#define EXT_CSD_EXP_EVENTS_STATUS 54 /* RO, 2 bytes */
|
||||
#define EXT_CSD_EXP_EVENTS_CTRL 56 /* R/W, 2 bytes */
|
||||
#define EXT_CSD_DATA_SECTOR_SIZE 61 /* R */
|
||||
#define EXT_CSD_GP_SIZE_MULT 143 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SETTING_COMPLETED 155 /* R/W */
|
||||
#define EXT_CSD_PARTITION_ATTRIBUTE 156 /* R/W */
|
||||
#define EXT_CSD_PARTITION_SUPPORT 160 /* RO */
|
||||
#define EXT_CSD_HPI_MGMT 161 /* R/W */
|
||||
#define EXT_CSD_RST_N_FUNCTION 162 /* R/W */
|
||||
#define EXT_CSD_BKOPS_EN 163 /* R/W */
|
||||
#define EXT_CSD_BKOPS_START 164 /* W */
|
||||
#define EXT_CSD_SANITIZE_START 165 /* W */
|
||||
#define EXT_CSD_WR_REL_PARAM 166 /* RO */
|
||||
#define EXT_CSD_RPMB_MULT 168 /* RO */
|
||||
#define EXT_CSD_FW_CONFIG 169 /* R/W */
|
||||
#define EXT_CSD_BOOT_WP 173 /* R/W */
|
||||
#define EXT_CSD_ERASE_GROUP_DEF 175 /* R/W */
|
||||
#define EXT_CSD_PART_CONFIG 179 /* R/W */
|
||||
#define EXT_CSD_ERASED_MEM_CONT 181 /* RO */
|
||||
#define EXT_CSD_BUS_WIDTH 183 /* R/W */
|
||||
#define EXT_CSD_STROBE_SUPPORT 184 /* RO */
|
||||
#define EXT_CSD_HS_TIMING 185 /* R/W */
|
||||
#define EXT_CSD_POWER_CLASS 187 /* R/W */
|
||||
#define EXT_CSD_REV 192 /* RO */
|
||||
#define EXT_CSD_STRUCTURE 194 /* RO */
|
||||
#define EXT_CSD_CARD_TYPE 196 /* RO */
|
||||
#define EXT_CSD_DRIVER_STRENGTH 197 /* RO */
|
||||
#define EXT_CSD_OUT_OF_INTERRUPT_TIME 198 /* RO */
|
||||
#define EXT_CSD_PART_SWITCH_TIME 199 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_195 200 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_195 201 /* RO */
|
||||
#define EXT_CSD_PWR_CL_52_360 202 /* RO */
|
||||
#define EXT_CSD_PWR_CL_26_360 203 /* RO */
|
||||
#define EXT_CSD_SEC_CNT 212 /* RO, 4 bytes */
|
||||
#define EXT_CSD_S_A_TIMEOUT 217 /* RO */
|
||||
#define EXT_CSD_REL_WR_SEC_C 222 /* RO */
|
||||
#define EXT_CSD_HC_WP_GRP_SIZE 221 /* RO */
|
||||
#define EXT_CSD_ERASE_TIMEOUT_MULT 223 /* RO */
|
||||
#define EXT_CSD_HC_ERASE_GRP_SIZE 224 /* RO */
|
||||
#define EXT_CSD_BOOT_MULT 226 /* RO */
|
||||
#define EXT_CSD_SEC_TRIM_MULT 229 /* RO */
|
||||
#define EXT_CSD_SEC_ERASE_MULT 230 /* RO */
|
||||
#define EXT_CSD_SEC_FEATURE_SUPPORT 231 /* RO */
|
||||
#define EXT_CSD_TRIM_MULT 232 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_195 236 /* RO */
|
||||
#define EXT_CSD_PWR_CL_200_360 237 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_195 238 /* RO */
|
||||
#define EXT_CSD_PWR_CL_DDR_52_360 239 /* RO */
|
||||
#define EXT_CSD_BKOPS_STATUS 246 /* RO */
|
||||
#define EXT_CSD_POWER_OFF_LONG_TIME 247 /* RO */
|
||||
#define EXT_CSD_GENERIC_CMD6_TIME 248 /* RO */
|
||||
#define EXT_CSD_CACHE_SIZE 249 /* RO, 4 bytes */
|
||||
#define EXT_CSD_PWR_CL_DDR_200_360 253 /* RO */
|
||||
#define EXT_CSD_FIRMWARE_VERSION 254 /* RO, 8 bytes */
|
||||
#define EXT_CSD_PRE_EOL_INFO 267 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_A 268 /* RO */
|
||||
#define EXT_CSD_DEVICE_LIFE_TIME_EST_TYP_B 269 /* RO */
|
||||
#define EXT_CSD_CMDQ_DEPTH 307 /* RO */
|
||||
#define EXT_CSD_CMDQ_SUPPORT 308 /* RO */
|
||||
#define EXT_CSD_SUPPORTED_MODE 493 /* RO */
|
||||
#define EXT_CSD_TAG_UNIT_SIZE 498 /* RO */
|
||||
#define EXT_CSD_DATA_TAG_SUPPORT 499 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_WRITES 500 /* RO */
|
||||
#define EXT_CSD_MAX_PACKED_READS 501 /* RO */
|
||||
#define EXT_CSD_BKOPS_SUPPORT 502 /* RO */
|
||||
#define EXT_CSD_HPI_FEATURES 503 /* RO */
|
||||
|
||||
/*
|
||||
* EXT_CSD field definitions
|
||||
*/
|
||||
|
||||
#define EXT_CSD_WR_REL_PARAM_EN (1<<2)
|
||||
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_DIS (0x40)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_DIS (0x10)
|
||||
#define EXT_CSD_BOOT_WP_B_PERM_WP_EN (0x04)
|
||||
#define EXT_CSD_BOOT_WP_B_PWR_WP_EN (0x01)
|
||||
|
||||
#define EXT_CSD_PART_CONFIG_ACC_MASK (0x7)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_BOOT0 (0x1)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_RPMB (0x3)
|
||||
#define EXT_CSD_PART_CONFIG_ACC_GP0 (0x4)
|
||||
|
||||
#define EXT_CSD_PART_SETTING_COMPLETED (0x1)
|
||||
#define EXT_CSD_PART_SUPPORT_PART_EN (0x1)
|
||||
|
||||
#define EXT_CSD_CMD_SET_NORMAL (1<<0)
|
||||
#define EXT_CSD_CMD_SET_SECURE (1<<1)
|
||||
#define EXT_CSD_CMD_SET_CPSECURE (1<<2)
|
||||
|
||||
#define EXT_CSD_CARD_TYPE_HS_26 (1<<0) /* Card can run at 26MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS_52 (1<<1) /* Card can run at 52MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS (EXT_CSD_CARD_TYPE_HS_26 | \
|
||||
EXT_CSD_CARD_TYPE_HS_52)
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_8V (1<<2) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.8V or 3V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_1_2V (1<<3) /* Card can run at 52MHz */
|
||||
/* DDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_DDR_52 (EXT_CSD_CARD_TYPE_DDR_1_8V \
|
||||
| EXT_CSD_CARD_TYPE_DDR_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS200_1_8V (1<<4) /* Card can run at 200MHz */
|
||||
#define EXT_CSD_CARD_TYPE_HS200_1_2V (1<<5) /* Card can run at 200MHz */
|
||||
/* SDR mode @1.2V I/O */
|
||||
#define EXT_CSD_CARD_TYPE_HS200 (EXT_CSD_CARD_TYPE_HS200_1_8V | \
|
||||
EXT_CSD_CARD_TYPE_HS200_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS400_1_8V (1<<6) /* Card can run at 200MHz DDR, 1.8V */
|
||||
#define EXT_CSD_CARD_TYPE_HS400_1_2V (1<<7) /* Card can run at 200MHz DDR, 1.2V */
|
||||
#define EXT_CSD_CARD_TYPE_HS400 (EXT_CSD_CARD_TYPE_HS400_1_8V | \
|
||||
EXT_CSD_CARD_TYPE_HS400_1_2V)
|
||||
#define EXT_CSD_CARD_TYPE_HS400ES (1<<8) /* Card can run at HS400ES */
|
||||
|
||||
#define EXT_CSD_BUS_WIDTH_1 0 /* Card is in 1 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_4 1 /* Card is in 4 bit mode */
|
||||
#define EXT_CSD_BUS_WIDTH_8 2 /* Card is in 8 bit mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_4 5 /* Card is in 4 bit DDR mode */
|
||||
#define EXT_CSD_DDR_BUS_WIDTH_8 6 /* Card is in 8 bit DDR mode */
|
||||
#define EXT_CSD_BUS_WIDTH_STROBE BIT(7) /* Enhanced strobe mode */
|
||||
|
||||
#define EXT_CSD_TIMING_BC 0 /* Backwards compatility */
|
||||
#define EXT_CSD_TIMING_HS 1 /* High speed */
|
||||
#define EXT_CSD_TIMING_HS200 2 /* HS200 */
|
||||
#define EXT_CSD_TIMING_HS400 3 /* HS400 */
|
||||
#define EXT_CSD_DRV_STR_SHIFT 4 /* Driver Strength shift */
|
||||
|
||||
#define EXT_CSD_SEC_ER_EN BIT(0)
|
||||
#define EXT_CSD_SEC_BD_BLK_EN BIT(2)
|
||||
#define EXT_CSD_SEC_GB_CL_EN BIT(4)
|
||||
#define EXT_CSD_SEC_SANITIZE BIT(6) /* v4.5 only */
|
||||
|
||||
#define EXT_CSD_RST_N_EN_MASK 0x3
|
||||
#define EXT_CSD_RST_N_ENABLED 1 /* RST_n is enabled on card */
|
||||
|
||||
#define EXT_CSD_NO_POWER_NOTIFICATION 0
|
||||
#define EXT_CSD_POWER_ON 1
|
||||
#define EXT_CSD_POWER_OFF_SHORT 2
|
||||
#define EXT_CSD_POWER_OFF_LONG 3
|
||||
|
||||
#define EXT_CSD_PWR_CL_8BIT_MASK 0xF0 /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_4BIT_MASK 0x0F /* 8 bit PWR CLS */
|
||||
#define EXT_CSD_PWR_CL_8BIT_SHIFT 4
|
||||
#define EXT_CSD_PWR_CL_4BIT_SHIFT 0
|
||||
|
||||
#define EXT_CSD_PACKED_EVENT_EN BIT(3)
|
||||
|
||||
/*
|
||||
* EXCEPTION_EVENT_STATUS field
|
||||
*/
|
||||
#define EXT_CSD_URGENT_BKOPS BIT(0)
|
||||
#define EXT_CSD_DYNCAP_NEEDED BIT(1)
|
||||
#define EXT_CSD_SYSPOOL_EXHAUSTED BIT(2)
|
||||
#define EXT_CSD_PACKED_FAILURE BIT(3)
|
||||
|
||||
#define EXT_CSD_PACKED_GENERIC_ERROR BIT(0)
|
||||
#define EXT_CSD_PACKED_INDEXED_ERROR BIT(1)
|
||||
|
||||
/*
|
||||
* BKOPS status level
|
||||
*/
|
||||
#define EXT_CSD_BKOPS_LEVEL_2 0x2
|
||||
|
||||
/*
|
||||
* BKOPS modes
|
||||
*/
|
||||
#define EXT_CSD_MANUAL_BKOPS_MASK 0x01
|
||||
#define EXT_CSD_AUTO_BKOPS_MASK 0x02
|
||||
|
||||
/*
|
||||
* Command Queue
|
||||
*/
|
||||
#define EXT_CSD_CMDQ_MODE_ENABLED BIT(0)
|
||||
#define EXT_CSD_CMDQ_DEPTH_MASK GENMASK(4, 0)
|
||||
#define EXT_CSD_CMDQ_SUPPORTED BIT(0)
|
||||
|
||||
/*
|
||||
* MMC_SWITCH access modes
|
||||
*/
|
||||
#define MMC_SWITCH_MODE_CMD_SET 0x00 /* Change the command set */
|
||||
#define MMC_SWITCH_MODE_SET_BITS 0x01 /* Set bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_CLEAR_BITS 0x02 /* Clear bits which are 1 in value */
|
||||
#define MMC_SWITCH_MODE_WRITE_BYTE 0x03 /* Set target to value */
|
||||
|
||||
/*
|
||||
* Erase/trim/discard
|
||||
*/
|
||||
#define MMC_ERASE_ARG 0x00000000
|
||||
#define MMC_SECURE_ERASE_ARG 0x80000000
|
||||
#define MMC_TRIM_ARG 0x00000001
|
||||
#define MMC_DISCARD_ARG 0x00000003
|
||||
#define MMC_SECURE_TRIM1_ARG 0x80000001
|
||||
#define MMC_SECURE_TRIM2_ARG 0x80008000
|
||||
#define MMC_SECURE_ARGS 0x80000000
|
||||
#define MMC_TRIM_ARGS 0x00008001
|
||||
|
||||
#define mmc_driver_type_mask(n) (1 << (n))
|
||||
|
||||
#endif /* LINUX_MMC_MMC_H */
|
134
nemu/src/device/sdcard.c
Normal file
134
nemu/src/device/sdcard.c
Normal file
|
@ -0,0 +1,134 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
#include "mmc.h"
|
||||
|
||||
// http://www.files.e-shop.co.il/pdastore/Tech-mmc-samsung/SEC%20MMC%20SPEC%20ver09.pdf
|
||||
|
||||
// see page 26 of the manual above
|
||||
#define MEMORY_SIZE (16ull * 1024 * 1024 * 1024) // 16GB
|
||||
#define READ_BL_LEN 15
|
||||
#define BLOCK_LEN (1 << READ_BL_LEN)
|
||||
#define NR_BLOCK (MEMORY_SIZE / BLOCK_LEN)
|
||||
#define C_SIZE_MULT 7 // only 3 bits
|
||||
#define MULT (1 << (C_SIZE_MULT + 2))
|
||||
#define C_SIZE (NR_BLOCK / MULT - 1)
|
||||
|
||||
// This is a simple hardware implementation of linux/drivers/mmc/host/bcm2835.c
|
||||
// No DMA and IRQ is supported, so the driver must be modified to start PIO
|
||||
// right after sending the actual read/write commands.
|
||||
|
||||
enum {
|
||||
SDCMD, SDARG, SDTOUT, SDCDIV,
|
||||
SDRSP0, SDRSP1, SDRSP2, SDRSP3,
|
||||
SDHSTS, __PAD0, __PAD1, __PAD2,
|
||||
SDVDD, SDEDM, SDHCFG, SDHBCT,
|
||||
SDDATA, __PAD10, __PAD11, __PAD12,
|
||||
SDHBLC
|
||||
};
|
||||
|
||||
static FILE *fp = NULL;
|
||||
static uint32_t *base = NULL;
|
||||
static uint32_t blkcnt = 0;
|
||||
static long blk_addr = 0;
|
||||
static uint32_t addr = 0;
|
||||
static bool write_cmd = 0;
|
||||
static bool read_ext_csd = false;
|
||||
|
||||
static void prepare_rw(int is_write) {
|
||||
blk_addr = base[SDARG];
|
||||
addr = 0;
|
||||
if (fp) fseek(fp, blk_addr << 9, SEEK_SET);
|
||||
write_cmd = is_write;
|
||||
}
|
||||
|
||||
static void sdcard_handle_cmd(int cmd) {
|
||||
switch (cmd) {
|
||||
case MMC_GO_IDLE_STATE: break;
|
||||
case MMC_SEND_OP_COND: base[SDRSP0] = 0x80ff8000; break;
|
||||
case MMC_ALL_SEND_CID:
|
||||
base[SDRSP0] = 0x00000001;
|
||||
base[SDRSP1] = 0x00000000;
|
||||
base[SDRSP2] = 0x00000000;
|
||||
base[SDRSP3] = 0x15000000;
|
||||
break;
|
||||
case 52: // ???
|
||||
break;
|
||||
case MMC_SEND_CSD:
|
||||
base[SDRSP0] = 0x92404001;
|
||||
base[SDRSP1] = 0x124b97e3 | ((C_SIZE & 0x3) << 30);
|
||||
base[SDRSP2] = 0x0f508000 | (C_SIZE >> 2) | (READ_BL_LEN << 16);
|
||||
base[SDRSP3] = 0x9026012a;
|
||||
break;
|
||||
case MMC_SEND_EXT_CSD: read_ext_csd = true; addr = 0; break;
|
||||
case MMC_SLEEP_AWAKE: break;
|
||||
case MMC_APP_CMD: break;
|
||||
case MMC_SET_RELATIVE_ADDR: break;
|
||||
case MMC_SELECT_CARD: break;
|
||||
case MMC_SET_BLOCK_COUNT: blkcnt = base[SDARG] & 0xffff; break;
|
||||
case MMC_READ_MULTIPLE_BLOCK: prepare_rw(false); break;
|
||||
case MMC_WRITE_MULTIPLE_BLOCK: prepare_rw(true); break;
|
||||
case MMC_SEND_STATUS: base[SDRSP0] = 0x900; base[SDRSP1] = base[SDRSP2] = base[SDRSP3] = 0; break;
|
||||
case MMC_STOP_TRANSMISSION: break;
|
||||
default:
|
||||
panic("unhandled command = %d", cmd);
|
||||
}
|
||||
}
|
||||
|
||||
static void sdcard_io_handler(uint32_t offset, int len, bool is_write) {
|
||||
int idx = offset / 4;
|
||||
switch (idx) {
|
||||
case SDCMD: sdcard_handle_cmd(base[SDCMD] & 0x3f); break;
|
||||
case SDARG:
|
||||
case SDRSP0:
|
||||
case SDRSP1:
|
||||
case SDRSP2:
|
||||
case SDRSP3:
|
||||
break;
|
||||
case SDDATA:
|
||||
if (read_ext_csd) {
|
||||
// See section 8.1 JEDEC Standard JED84-A441
|
||||
uint32_t data;
|
||||
switch (addr) {
|
||||
case 192: data = 2; break; // EXT_CSD_REV
|
||||
case 212: data = MEMORY_SIZE / 512; break;
|
||||
default: data = 0;
|
||||
}
|
||||
base[SDDATA] = data;
|
||||
if (addr == 512 - 4) read_ext_csd = false;
|
||||
} else if (fp) {
|
||||
__attribute__((unused)) int ret;
|
||||
if (!write_cmd) { ret = fread(&base[SDDATA], 4, 1, fp); }
|
||||
else { ret = fwrite(&base[SDDATA], 4, 1, fp); }
|
||||
}
|
||||
addr += 4;
|
||||
break;
|
||||
default:
|
||||
Log("offset = 0x%x(idx = %d), is_write = %d, data = 0x%x", offset, idx, is_write, base[idx]);
|
||||
panic("unhandle offset = %d", offset);
|
||||
}
|
||||
}
|
||||
|
||||
void init_sdcard() {
|
||||
base = (uint32_t *)new_space(0x80);
|
||||
add_mmio_map("sdhci", CONFIG_SDCARD_CTL_MMIO, base, 0x80, sdcard_io_handler);
|
||||
|
||||
Assert(C_SIZE < (1 << 12), "shoule be fit in 12 bits");
|
||||
|
||||
const char *img = CONFIG_SDCARD_IMG_PATH;
|
||||
fp = fopen(img, "r+");
|
||||
if (fp == NULL) Log("Can not find sdcard image: %s", img);
|
||||
}
|
51
nemu/src/device/serial.c
Normal file
51
nemu/src/device/serial.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <utils.h>
|
||||
#include <device/map.h>
|
||||
|
||||
/* http://en.wikibooks.org/wiki/Serial_Programming/8250_UART_Programming */
|
||||
// NOTE: this is compatible to 16550
|
||||
|
||||
#define CH_OFFSET 0
|
||||
|
||||
static uint8_t *serial_base = NULL;
|
||||
|
||||
|
||||
static void serial_putc(char ch) {
|
||||
MUXDEF(CONFIG_TARGET_AM, putch(ch), putc(ch, stderr));
|
||||
}
|
||||
|
||||
static void serial_io_handler(uint32_t offset, int len, bool is_write) {
|
||||
assert(len == 1);
|
||||
switch (offset) {
|
||||
/* We bind the serial port with the host stderr in NEMU. */
|
||||
case CH_OFFSET:
|
||||
if (is_write) serial_putc(serial_base[0]);
|
||||
else panic("do not support read");
|
||||
break;
|
||||
default: panic("do not support offset = %d", offset);
|
||||
}
|
||||
}
|
||||
|
||||
void init_serial() {
|
||||
serial_base = new_space(8);
|
||||
#ifdef CONFIG_HAS_PORT_IO
|
||||
add_pio_map ("serial", CONFIG_SERIAL_PORT, serial_base, 8, serial_io_handler);
|
||||
#else
|
||||
add_mmio_map("serial", CONFIG_SERIAL_MMIO, serial_base, 8, serial_io_handler);
|
||||
#endif
|
||||
|
||||
}
|
48
nemu/src/device/timer.c
Normal file
48
nemu/src/device/timer.c
Normal file
|
@ -0,0 +1,48 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <device/map.h>
|
||||
#include <device/alarm.h>
|
||||
#include <utils.h>
|
||||
|
||||
static uint32_t *rtc_port_base = NULL;
|
||||
|
||||
static void rtc_io_handler(uint32_t offset, int len, bool is_write) {
|
||||
assert(offset == 0 || offset == 4);
|
||||
if (!is_write && offset == 4) {
|
||||
uint64_t us = get_time();
|
||||
rtc_port_base[0] = (uint32_t)us;
|
||||
rtc_port_base[1] = us >> 32;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
static void timer_intr() {
|
||||
if (nemu_state.state == NEMU_RUNNING) {
|
||||
extern void dev_raise_intr();
|
||||
dev_raise_intr();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void init_timer() {
|
||||
rtc_port_base = (uint32_t *)new_space(8);
|
||||
#ifdef CONFIG_HAS_PORT_IO
|
||||
add_pio_map ("rtc", CONFIG_RTC_PORT, rtc_port_base, 8, rtc_io_handler);
|
||||
#else
|
||||
add_mmio_map("rtc", CONFIG_RTC_MMIO, rtc_port_base, 8, rtc_io_handler);
|
||||
#endif
|
||||
IFNDEF(CONFIG_TARGET_AM, add_alarm_handle(timer_intr));
|
||||
}
|
92
nemu/src/device/vga.c
Normal file
92
nemu/src/device/vga.c
Normal file
|
@ -0,0 +1,92 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
#include <device/map.h>
|
||||
|
||||
#define SCREEN_W (MUXDEF(CONFIG_VGA_SIZE_800x600, 800, 400))
|
||||
#define SCREEN_H (MUXDEF(CONFIG_VGA_SIZE_800x600, 600, 300))
|
||||
|
||||
static uint32_t screen_width() {
|
||||
return MUXDEF(CONFIG_TARGET_AM, io_read(AM_GPU_CONFIG).width, SCREEN_W);
|
||||
}
|
||||
|
||||
static uint32_t screen_height() {
|
||||
return MUXDEF(CONFIG_TARGET_AM, io_read(AM_GPU_CONFIG).height, SCREEN_H);
|
||||
}
|
||||
|
||||
static uint32_t screen_size() {
|
||||
return screen_width() * screen_height() * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
static void *vmem = NULL;
|
||||
static uint32_t *vgactl_port_base = NULL;
|
||||
|
||||
#ifdef CONFIG_VGA_SHOW_SCREEN
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
#include <SDL2/SDL.h>
|
||||
|
||||
static SDL_Renderer *renderer = NULL;
|
||||
static SDL_Texture *texture = NULL;
|
||||
|
||||
static void init_screen() {
|
||||
SDL_Window *window = NULL;
|
||||
char title[128];
|
||||
sprintf(title, "%s-NEMU", str(__GUEST_ISA__));
|
||||
SDL_Init(SDL_INIT_VIDEO);
|
||||
SDL_CreateWindowAndRenderer(
|
||||
SCREEN_W * (MUXDEF(CONFIG_VGA_SIZE_400x300, 2, 1)),
|
||||
SCREEN_H * (MUXDEF(CONFIG_VGA_SIZE_400x300, 2, 1)),
|
||||
0, &window, &renderer);
|
||||
SDL_SetWindowTitle(window, title);
|
||||
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
|
||||
SDL_TEXTUREACCESS_STATIC, SCREEN_W, SCREEN_H);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
|
||||
static inline void update_screen() {
|
||||
SDL_UpdateTexture(texture, NULL, vmem, SCREEN_W * sizeof(uint32_t));
|
||||
SDL_RenderClear(renderer);
|
||||
SDL_RenderCopy(renderer, texture, NULL, NULL);
|
||||
SDL_RenderPresent(renderer);
|
||||
}
|
||||
#else
|
||||
static void init_screen() {}
|
||||
|
||||
static inline void update_screen() {
|
||||
io_write(AM_GPU_FBDRAW, 0, 0, vmem, screen_width(), screen_height(), true);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void vga_update_screen() {
|
||||
// TODO: call `update_screen()` when the sync register is non-zero,
|
||||
// then zero out the sync register
|
||||
}
|
||||
|
||||
void init_vga() {
|
||||
vgactl_port_base = (uint32_t *)new_space(8);
|
||||
vgactl_port_base[0] = (screen_width() << 16) | screen_height();
|
||||
#ifdef CONFIG_HAS_PORT_IO
|
||||
add_pio_map ("vgactl", CONFIG_VGA_CTL_PORT, vgactl_port_base, 8, NULL);
|
||||
#else
|
||||
add_mmio_map("vgactl", CONFIG_VGA_CTL_MMIO, vgactl_port_base, 8, NULL);
|
||||
#endif
|
||||
|
||||
vmem = new_space(screen_size());
|
||||
add_mmio_map("vmem", CONFIG_FB_ADDR, vmem, screen_size(), NULL);
|
||||
IFDEF(CONFIG_VGA_SHOW_SCREEN, init_screen());
|
||||
IFDEF(CONFIG_VGA_SHOW_SCREEN, memset(vmem, 0, screen_size()));
|
||||
}
|
17
nemu/src/engine/filelist.mk
Normal file
17
nemu/src/engine/filelist.mk
Normal file
|
@ -0,0 +1,17 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
INC_PATH += $(NEMU_HOME)/src/engine/$(ENGINE)
|
||||
DIRS-y += src/engine/$(ENGINE)
|
51
nemu/src/engine/interpreter/hostcall.c
Normal file
51
nemu/src/engine/interpreter/hostcall.c
Normal file
|
@ -0,0 +1,51 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <utils.h>
|
||||
#include <cpu/ifetch.h>
|
||||
#include <isa.h>
|
||||
#include <cpu/difftest.h>
|
||||
|
||||
void set_nemu_state(int state, vaddr_t pc, int halt_ret) {
|
||||
difftest_skip_ref();
|
||||
nemu_state.state = state;
|
||||
nemu_state.halt_pc = pc;
|
||||
nemu_state.halt_ret = halt_ret;
|
||||
}
|
||||
|
||||
__attribute__((noinline))
|
||||
void invalid_inst(vaddr_t thispc) {
|
||||
uint32_t temp[2];
|
||||
vaddr_t pc = thispc;
|
||||
temp[0] = inst_fetch(&pc, 4);
|
||||
temp[1] = inst_fetch(&pc, 4);
|
||||
|
||||
uint8_t *p = (uint8_t *)temp;
|
||||
printf("invalid opcode(PC = " FMT_WORD "):\n"
|
||||
"\t%02x %02x %02x %02x %02x %02x %02x %02x ...\n"
|
||||
"\t%08x %08x...\n",
|
||||
thispc, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], temp[0], temp[1]);
|
||||
|
||||
printf("There are two cases which will trigger this unexpected exception:\n"
|
||||
"1. The instruction at PC = " FMT_WORD " is not implemented.\n"
|
||||
"2. Something is implemented incorrectly.\n", thispc);
|
||||
printf("Find this PC(" FMT_WORD ") in the disassembling result to distinguish which case it is.\n\n", thispc);
|
||||
printf(ANSI_FMT("If it is the first case, see\n%s\nfor more details.\n\n"
|
||||
"If it is the second case, remember:\n"
|
||||
"* The machine is always right!\n"
|
||||
"* Every line of untested code is always wrong!\n\n", ANSI_FG_RED), isa_logo);
|
||||
|
||||
set_nemu_state(NEMU_ABORT, thispc, -1);
|
||||
}
|
27
nemu/src/engine/interpreter/init.c
Normal file
27
nemu/src/engine/interpreter/init.c
Normal file
|
@ -0,0 +1,27 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <cpu/cpu.h>
|
||||
|
||||
void sdb_mainloop();
|
||||
|
||||
void engine_start() {
|
||||
#ifdef CONFIG_TARGET_AM
|
||||
cpu_exec(-1);
|
||||
#else
|
||||
/* Receive commands from user. */
|
||||
sdb_mainloop();
|
||||
#endif
|
||||
}
|
28
nemu/src/filelist.mk
Normal file
28
nemu/src/filelist.mk
Normal file
|
@ -0,0 +1,28 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
SRCS-y += src/nemu-main.c
|
||||
DIRS-y += src/cpu src/monitor src/utils
|
||||
DIRS-$(CONFIG_MODE_SYSTEM) += src/memory
|
||||
DIRS-BLACKLIST-$(CONFIG_TARGET_AM) += src/monitor/sdb
|
||||
|
||||
SHARE = $(if $(CONFIG_TARGET_SHARE),1,0)
|
||||
LIBS += $(if $(CONFIG_TARGET_NATIVE_ELF),-lreadline -ldl -pie,)
|
||||
|
||||
ifdef mainargs
|
||||
ASFLAGS += -DBIN_PATH=\"$(mainargs)\"
|
||||
endif
|
||||
SRCS-$(CONFIG_TARGET_AM) += src/am-bin.S
|
||||
.PHONY: src/am-bin.S
|
17
nemu/src/isa/filelist.mk
Normal file
17
nemu/src/isa/filelist.mk
Normal file
|
@ -0,0 +1,17 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
INC_PATH += $(NEMU_HOME)/src/isa/$(GUEST_ISA)/include
|
||||
DIRS-y += src/isa/$(GUEST_ISA)
|
25
nemu/src/isa/loongarch32r/difftest/dut.c
Normal file
25
nemu/src/isa/loongarch32r/difftest/dut.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/difftest.h>
|
||||
#include "../local-include/reg.h"
|
||||
|
||||
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void isa_difftest_attach() {
|
||||
}
|
35
nemu/src/isa/loongarch32r/include/isa-def.h
Normal file
35
nemu/src/isa/loongarch32r/include/isa-def.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __ISA_LOONGARCH32R_H__
|
||||
#define __ISA_LOONGARCH32R_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
typedef struct {
|
||||
word_t gpr[32];
|
||||
vaddr_t pc;
|
||||
} loongarch32r_CPU_state;
|
||||
|
||||
// decode
|
||||
typedef struct {
|
||||
union {
|
||||
uint32_t val;
|
||||
} inst;
|
||||
} loongarch32r_ISADecodeInfo;
|
||||
|
||||
#define isa_mmu_check(vaddr, len, type) (MMU_DIRECT)
|
||||
|
||||
#endif
|
43
nemu/src/isa/loongarch32r/init.c
Normal file
43
nemu/src/isa/loongarch32r/init.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
// this is not consistent with uint8_t
|
||||
// but it is ok since we do not access the array directly
|
||||
static const uint32_t img [] = {
|
||||
0x1c00000c, // pcaddu12i $t0,0
|
||||
0x29804180, // st.w $zero,$t0,16
|
||||
0x28804184, // ld.w $a0,$t0,16
|
||||
0x002a0000, // break 0 (used as nemu_trap)
|
||||
0xdeadbeef, // some data
|
||||
};
|
||||
|
||||
static void restart() {
|
||||
/* Set the initial program counter. */
|
||||
cpu.pc = RESET_VECTOR;
|
||||
|
||||
/* The zero register is always 0. */
|
||||
cpu.gpr[0] = 0;
|
||||
}
|
||||
|
||||
void init_isa() {
|
||||
/* Load built-in image. */
|
||||
memcpy(guest_to_host(RESET_VECTOR), img, sizeof(img));
|
||||
|
||||
/* Initialize this virtual computer system. */
|
||||
restart();
|
||||
}
|
72
nemu/src/isa/loongarch32r/inst.c
Normal file
72
nemu/src/isa/loongarch32r/inst.c
Normal file
|
@ -0,0 +1,72 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include "local-include/reg.h"
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/ifetch.h>
|
||||
#include <cpu/decode.h>
|
||||
|
||||
#define R(i) gpr(i)
|
||||
#define Mr vaddr_read
|
||||
#define Mw vaddr_write
|
||||
|
||||
enum {
|
||||
TYPE_2RI12, TYPE_1RI20,
|
||||
TYPE_N, // none
|
||||
};
|
||||
|
||||
#define src1R() do { *src1 = R(rj); } while (0)
|
||||
#define simm12() do { *imm = SEXT(BITS(i, 21, 10), 12); } while (0)
|
||||
#define simm20() do { *imm = SEXT(BITS(i, 24, 5), 20) << 12; } while (0)
|
||||
|
||||
static void decode_operand(Decode *s, int *rd_, word_t *src1, word_t *src2, word_t *imm, int type) {
|
||||
uint32_t i = s->isa.inst.val;
|
||||
int rj = BITS(i, 9, 5);
|
||||
*rd_ = BITS(i, 4, 0);
|
||||
switch (type) {
|
||||
case TYPE_1RI20: simm20(); src1R(); break;
|
||||
case TYPE_2RI12: simm12(); src1R(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_exec(Decode *s) {
|
||||
int rd = 0;
|
||||
word_t src1 = 0, src2 = 0, imm = 0;
|
||||
s->dnpc = s->snpc;
|
||||
|
||||
#define INSTPAT_INST(s) ((s)->isa.inst.val)
|
||||
#define INSTPAT_MATCH(s, name, type, ... /* execute body */ ) { \
|
||||
decode_operand(s, &rd, &src1, &src2, &imm, concat(TYPE_, type)); \
|
||||
__VA_ARGS__ ; \
|
||||
}
|
||||
|
||||
INSTPAT_START();
|
||||
INSTPAT("0001110 ????? ????? ????? ????? ?????" , pcaddu12i, 1RI20 , R(rd) = s->pc + imm);
|
||||
INSTPAT("0010100010 ???????????? ????? ?????" , ld.w , 2RI12 , R(rd) = Mr(src1 + imm, 4));
|
||||
INSTPAT("0010100110 ???????????? ????? ?????" , st.w , 2RI12 , Mw(src1 + imm, 4, R(rd)));
|
||||
|
||||
INSTPAT("0000 0000 0010 10100 ????? ????? ?????", break , N , NEMUTRAP(s->pc, R(4))); // R(4) is $a0
|
||||
INSTPAT("????????????????? ????? ????? ?????" , inv , N , INV(s->pc));
|
||||
INSTPAT_END();
|
||||
|
||||
R(0) = 0; // reset $zero to 0
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isa_exec_once(Decode *s) {
|
||||
s->isa.inst.val = inst_fetch(&s->snpc, 4);
|
||||
return decode_exec(s);
|
||||
}
|
33
nemu/src/isa/loongarch32r/local-include/reg.h
Normal file
33
nemu/src/isa/loongarch32r/local-include/reg.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __LOONGARCH32R_REG_H__
|
||||
#define __LOONGARCH32R_REG_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
static inline int check_reg_idx(int idx) {
|
||||
IFDEF(CONFIG_RT_CHECK, assert(idx >= 0 && idx < 32));
|
||||
return idx;
|
||||
}
|
||||
|
||||
#define gpr(idx) cpu.gpr[check_reg_idx(idx)]
|
||||
|
||||
static inline const char* reg_name(int idx) {
|
||||
extern const char* regs[];
|
||||
return regs[check_reg_idx(idx)];
|
||||
}
|
||||
|
||||
#endif
|
16
nemu/src/isa/loongarch32r/logo.c
Normal file
16
nemu/src/isa/loongarch32r/logo.c
Normal file
|
@ -0,0 +1,16 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
unsigned char isa_logo[] = "loongarch32r manual";
|
31
nemu/src/isa/loongarch32r/reg.c
Normal file
31
nemu/src/isa/loongarch32r/reg.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include "local-include/reg.h"
|
||||
|
||||
const char *regs[] = {
|
||||
"$0", "ra", "tp", "sp", "a0", "a1", "a2", "a3",
|
||||
"a4", "a5", "a6", "a7", "t0", "t1", "t2", "t3",
|
||||
"t4", "t5", "t6", "t7", "t8", "rs", "fp", "s0",
|
||||
"s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8"
|
||||
};
|
||||
|
||||
void isa_reg_display() {
|
||||
}
|
||||
|
||||
word_t isa_reg_str2val(const char *s, bool *success) {
|
||||
return 0;
|
||||
}
|
28
nemu/src/isa/loongarch32r/system/intr.c
Normal file
28
nemu/src/isa/loongarch32r/system/intr.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
||||
/* TODO: Trigger an interrupt/exception with ``NO''.
|
||||
* Then return the address of the interrupt/exception vector.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
word_t isa_query_intr() {
|
||||
return INTR_EMPTY;
|
||||
}
|
22
nemu/src/isa/loongarch32r/system/mmu.c
Normal file
22
nemu/src/isa/loongarch32r/system/mmu.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
#include <memory/vaddr.h>
|
||||
|
||||
paddr_t isa_mmu_translate(vaddr_t vaddr, int len, int type) {
|
||||
return MEM_RET_FAIL;
|
||||
}
|
25
nemu/src/isa/mips32/difftest/dut.c
Normal file
25
nemu/src/isa/mips32/difftest/dut.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/difftest.h>
|
||||
#include "../local-include/reg.h"
|
||||
|
||||
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void isa_difftest_attach() {
|
||||
}
|
36
nemu/src/isa/mips32/include/isa-def.h
Normal file
36
nemu/src/isa/mips32/include/isa-def.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __ISA_MIPS32_H__
|
||||
#define __ISA_MIPS32_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
typedef struct {
|
||||
word_t gpr[32];
|
||||
word_t pad[5];
|
||||
vaddr_t pc;
|
||||
} mips32_CPU_state;
|
||||
|
||||
// decode
|
||||
typedef struct {
|
||||
union {
|
||||
uint32_t val;
|
||||
} inst;
|
||||
} mips32_ISADecodeInfo;
|
||||
|
||||
#define isa_mmu_check(vaddr, len, type) (MMU_DIRECT)
|
||||
|
||||
#endif
|
42
nemu/src/isa/mips32/init.c
Normal file
42
nemu/src/isa/mips32/init.c
Normal file
|
@ -0,0 +1,42 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
// this is not consistent with uint8_t
|
||||
// but it is ok since we do not access the array directly
|
||||
static const uint32_t img [] = {
|
||||
0x3c048000, // lui a0, 0x8000
|
||||
0xac800000, // sw zero, 0(a0)
|
||||
0x8c820000, // lw v0,0(a0)
|
||||
0x7000003f, // sdbbp (used as nemu_trap)
|
||||
};
|
||||
|
||||
static void restart() {
|
||||
/* Set the initial program counter. */
|
||||
cpu.pc = RESET_VECTOR;
|
||||
|
||||
/* The zero register is always 0. */
|
||||
cpu.gpr[0] = 0;
|
||||
}
|
||||
|
||||
void init_isa() {
|
||||
/* Load built-in image. */
|
||||
memcpy(guest_to_host(RESET_VECTOR), img, sizeof(img));
|
||||
|
||||
/* Initialize this virtual computer system. */
|
||||
restart();
|
||||
}
|
74
nemu/src/isa/mips32/inst.c
Normal file
74
nemu/src/isa/mips32/inst.c
Normal file
|
@ -0,0 +1,74 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include "local-include/reg.h"
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/ifetch.h>
|
||||
#include <cpu/decode.h>
|
||||
|
||||
#define R(i) gpr(i)
|
||||
#define Mr vaddr_read
|
||||
#define Mw vaddr_write
|
||||
|
||||
enum {
|
||||
TYPE_I, TYPE_U,
|
||||
TYPE_N, // none
|
||||
};
|
||||
|
||||
#define src1R() do { *src1 = R(rs); } while (0)
|
||||
#define src2R() do { *src2 = R(rt); } while (0)
|
||||
#define immI() do { *imm = SEXT(BITS(i, 15, 0), 16); } while(0)
|
||||
#define immU() do { *imm = BITS(i, 15, 0); } while(0)
|
||||
|
||||
static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2, word_t *imm, int type) {
|
||||
uint32_t i = s->isa.inst.val;
|
||||
int rt = BITS(i, 20, 16);
|
||||
int rs = BITS(i, 25, 21);
|
||||
*rd = (type == TYPE_U || type == TYPE_I) ? rt : BITS(i, 15, 11);
|
||||
switch (type) {
|
||||
case TYPE_I: src1R(); immI(); break;
|
||||
case TYPE_U: src1R(); immU(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_exec(Decode *s) {
|
||||
int rd = 0;
|
||||
word_t src1 = 0, src2 = 0, imm = 0;
|
||||
s->dnpc = s->snpc;
|
||||
|
||||
#define INSTPAT_INST(s) ((s)->isa.inst.val)
|
||||
#define INSTPAT_MATCH(s, name, type, ... /* execute body */ ) { \
|
||||
decode_operand(s, &rd, &src1, &src2, &imm, concat(TYPE_, type)); \
|
||||
__VA_ARGS__ ; \
|
||||
}
|
||||
|
||||
INSTPAT_START();
|
||||
INSTPAT("001111 ????? ????? ????? ????? ??????", lui , U, R(rd) = imm << 16);
|
||||
INSTPAT("100011 ????? ????? ????? ????? ??????", lw , I, R(rd) = Mr(src1 + imm, 4));
|
||||
INSTPAT("101011 ????? ????? ????? ????? ??????", sw , I, Mw(src1 + imm, 4, R(rd)));
|
||||
|
||||
INSTPAT("011100 ????? ????? ????? ????? 111111", sdbbp , N, NEMUTRAP(s->pc, R(2))); // R(2) is $v0;
|
||||
INSTPAT("?????? ????? ????? ????? ????? ??????", inv , N, INV(s->pc));
|
||||
INSTPAT_END();
|
||||
|
||||
R(0) = 0; // reset $zero to 0
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isa_exec_once(Decode *s) {
|
||||
s->isa.inst.val = inst_fetch(&s->snpc, 4);
|
||||
return decode_exec(s);
|
||||
}
|
33
nemu/src/isa/mips32/local-include/reg.h
Normal file
33
nemu/src/isa/mips32/local-include/reg.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __MIPS32_REG_H__
|
||||
#define __MIPS32_REG_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
static inline int check_reg_idx(int idx) {
|
||||
IFDEF(CONFIG_RT_CHECK, assert(idx >= 0 && idx < 32));
|
||||
return idx;
|
||||
}
|
||||
|
||||
#define gpr(idx) cpu.gpr[check_reg_idx(idx)]
|
||||
|
||||
static inline const char* reg_name(int idx) {
|
||||
extern const char* regs[];
|
||||
return regs[check_reg_idx(idx)];
|
||||
}
|
||||
|
||||
#endif
|
78
nemu/src/isa/mips32/logo.c
Normal file
78
nemu/src/isa/mips32/logo.c
Normal file
|
@ -0,0 +1,78 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
// refer to http://www.patorjk.com/software/taag/#p=display&f=Big&t=Type%20Something%20
|
||||
|
||||
/*
|
||||
_ ____ ___ __ __ _
|
||||
(_) |___ \__ \ | \/ | | |
|
||||
_ __ ___ _ _ __ ___ __) | ) | | \ / | __ _ _ __ _ _ __ _| |
|
||||
| '_ ` _ \| | '_ \/ __||__ < / / | |\/| |/ _` | '_ \| | | |/ _` | |
|
||||
| | | | | | | |_) \__ \___) / /_ | | | | (_| | | | | |_| | (_| | |
|
||||
|_| |_| |_|_| .__/|___/____/____| |_| |_|\__,_|_| |_|\__,_|\__,_|_|
|
||||
| |
|
||||
|_|
|
||||
|
||||
*/
|
||||
|
||||
unsigned char isa_logo[] = {
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x5f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x5f, 0x5f, 0x5f, 0x5f, 0x20, 0x5f, 0x5f, 0x5f, 0x20, 0x20, 0x20, 0x20,
|
||||
0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x5f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x20, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x28, 0x5f, 0x29,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7c, 0x5f, 0x5f,
|
||||
0x5f, 0x20, 0x5c, 0x5f, 0x5f, 0x20, 0x5c, 0x20, 0x20, 0x7c, 0x20, 0x20,
|
||||
0x5c, 0x2f, 0x20, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x7c, 0x20, 0x7c, 0x0a, 0x20, 0x20, 0x5f, 0x20,
|
||||
0x5f, 0x5f, 0x20, 0x5f, 0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x20, 0x5f, 0x20,
|
||||
0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x5f, 0x29,
|
||||
0x20, 0x7c, 0x20, 0x29, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x5c, 0x20, 0x20,
|
||||
0x2f, 0x20, 0x7c, 0x20, 0x5f, 0x5f, 0x20, 0x5f, 0x20, 0x5f, 0x20, 0x5f,
|
||||
0x5f, 0x20, 0x20, 0x5f, 0x20, 0x20, 0x20, 0x5f, 0x20, 0x20, 0x5f, 0x5f,
|
||||
0x20, 0x5f, 0x7c, 0x20, 0x7c, 0x0a, 0x20, 0x7c, 0x20, 0x27, 0x5f, 0x20,
|
||||
0x60, 0x20, 0x5f, 0x20, 0x5c, 0x7c, 0x20, 0x7c, 0x20, 0x27, 0x5f, 0x20,
|
||||
0x5c, 0x2f, 0x20, 0x5f, 0x5f, 0x7c, 0x7c, 0x5f, 0x5f, 0x20, 0x3c, 0x20,
|
||||
0x2f, 0x20, 0x2f, 0x20, 0x20, 0x7c, 0x20, 0x7c, 0x5c, 0x2f, 0x7c, 0x20,
|
||||
0x7c, 0x2f, 0x20, 0x5f, 0x60, 0x20, 0x7c, 0x20, 0x27, 0x5f, 0x20, 0x5c,
|
||||
0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x2f, 0x20, 0x5f, 0x60, 0x20,
|
||||
0x7c, 0x20, 0x7c, 0x0a, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c,
|
||||
0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x5f, 0x29, 0x20, 0x5c,
|
||||
0x5f, 0x5f, 0x20, 0x5c, 0x5f, 0x5f, 0x5f, 0x29, 0x20, 0x2f, 0x20, 0x2f,
|
||||
0x5f, 0x20, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x20, 0x7c, 0x20, 0x7c, 0x20,
|
||||
0x28, 0x5f, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20,
|
||||
0x7c, 0x5f, 0x7c, 0x20, 0x7c, 0x20, 0x28, 0x5f, 0x7c, 0x20, 0x7c, 0x20,
|
||||
0x7c, 0x0a, 0x20, 0x7c, 0x5f, 0x7c, 0x20, 0x7c, 0x5f, 0x7c, 0x20, 0x7c,
|
||||
0x5f, 0x7c, 0x5f, 0x7c, 0x20, 0x2e, 0x5f, 0x5f, 0x2f, 0x7c, 0x5f, 0x5f,
|
||||
0x5f, 0x2f, 0x5f, 0x5f, 0x5f, 0x5f, 0x2f, 0x5f, 0x5f, 0x5f, 0x5f, 0x7c,
|
||||
0x20, 0x7c, 0x5f, 0x7c, 0x20, 0x20, 0x7c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f,
|
||||
0x2c, 0x5f, 0x7c, 0x5f, 0x7c, 0x20, 0x7c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f,
|
||||
0x2c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f, 0x2c, 0x5f, 0x7c, 0x5f, 0x7c, 0x0a,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x7c, 0x20, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7c,
|
||||
0x5f, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x0a, '\0'
|
||||
};
|
31
nemu/src/isa/mips32/reg.c
Normal file
31
nemu/src/isa/mips32/reg.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include "local-include/reg.h"
|
||||
|
||||
const char *regs[] = {
|
||||
"$0", "at", "v0", "v1", "a0", "a1", "a2", "a3",
|
||||
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7",
|
||||
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"t8", "t9", "k0", "k1", "gp", "sp", "s8", "ra"
|
||||
};
|
||||
|
||||
void isa_reg_display() {
|
||||
}
|
||||
|
||||
word_t isa_reg_str2val(const char *s, bool *success) {
|
||||
return 0;
|
||||
}
|
28
nemu/src/isa/mips32/system/intr.c
Normal file
28
nemu/src/isa/mips32/system/intr.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
||||
/* TODO: Trigger an interrupt/exception with ``NO''.
|
||||
* Then return the address of the interrupt/exception vector.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
word_t isa_query_intr() {
|
||||
return INTR_EMPTY;
|
||||
}
|
22
nemu/src/isa/mips32/system/mmu.c
Normal file
22
nemu/src/isa/mips32/system/mmu.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
#include <memory/vaddr.h>
|
||||
|
||||
paddr_t isa_mmu_translate(vaddr_t vaddr, int len, int type) {
|
||||
return MEM_RET_FAIL;
|
||||
}
|
10
nemu/src/isa/riscv32/Kconfig
Normal file
10
nemu/src/isa/riscv32/Kconfig
Normal file
|
@ -0,0 +1,10 @@
|
|||
menu "ISA-dependent Options for riscv"
|
||||
|
||||
config RV64
|
||||
bool "64-bit RISC-V architecture"
|
||||
default n
|
||||
|
||||
config RVE
|
||||
bool "Use E extension"
|
||||
default n
|
||||
endmenu
|
25
nemu/src/isa/riscv32/difftest/dut.c
Normal file
25
nemu/src/isa/riscv32/difftest/dut.c
Normal file
|
@ -0,0 +1,25 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/difftest.h>
|
||||
#include "../local-include/reg.h"
|
||||
|
||||
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void isa_difftest_attach() {
|
||||
}
|
35
nemu/src/isa/riscv32/include/isa-def.h
Normal file
35
nemu/src/isa/riscv32/include/isa-def.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __ISA_RISCV_H__
|
||||
#define __ISA_RISCV_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
typedef struct {
|
||||
word_t gpr[MUXDEF(CONFIG_RVE, 16, 32)];
|
||||
vaddr_t pc;
|
||||
} MUXDEF(CONFIG_RV64, riscv64_CPU_state, riscv32_CPU_state);
|
||||
|
||||
// decode
|
||||
typedef struct {
|
||||
union {
|
||||
uint32_t val;
|
||||
} inst;
|
||||
} MUXDEF(CONFIG_RV64, riscv64_ISADecodeInfo, riscv32_ISADecodeInfo);
|
||||
|
||||
#define isa_mmu_check(vaddr, len, type) (MMU_DIRECT)
|
||||
|
||||
#endif
|
43
nemu/src/isa/riscv32/init.c
Normal file
43
nemu/src/isa/riscv32/init.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
// this is not consistent with uint8_t
|
||||
// but it is ok since we do not access the array directly
|
||||
static const uint32_t img [] = {
|
||||
0x00000297, // auipc t0,0
|
||||
0x00028823, // sb zero,16(t0)
|
||||
0x0102c503, // lbu a0,16(t0)
|
||||
0x00100073, // ebreak (used as nemu_trap)
|
||||
0xdeadbeef, // some data
|
||||
};
|
||||
|
||||
static void restart() {
|
||||
/* Set the initial program counter. */
|
||||
cpu.pc = RESET_VECTOR;
|
||||
|
||||
/* The zero register is always 0. */
|
||||
cpu.gpr[0] = 0;
|
||||
}
|
||||
|
||||
void init_isa() {
|
||||
/* Load built-in image. */
|
||||
memcpy(guest_to_host(RESET_VECTOR), img, sizeof(img));
|
||||
|
||||
/* Initialize this virtual computer system. */
|
||||
restart();
|
||||
}
|
76
nemu/src/isa/riscv32/inst.c
Normal file
76
nemu/src/isa/riscv32/inst.c
Normal file
|
@ -0,0 +1,76 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include "local-include/reg.h"
|
||||
#include <cpu/cpu.h>
|
||||
#include <cpu/ifetch.h>
|
||||
#include <cpu/decode.h>
|
||||
|
||||
#define R(i) gpr(i)
|
||||
#define Mr vaddr_read
|
||||
#define Mw vaddr_write
|
||||
|
||||
enum {
|
||||
TYPE_I, TYPE_U, TYPE_S,
|
||||
TYPE_N, // none
|
||||
};
|
||||
|
||||
#define src1R() do { *src1 = R(rs1); } while (0)
|
||||
#define src2R() do { *src2 = R(rs2); } while (0)
|
||||
#define immI() do { *imm = SEXT(BITS(i, 31, 20), 12); } while(0)
|
||||
#define immU() do { *imm = SEXT(BITS(i, 31, 12), 20) << 12; } while(0)
|
||||
#define immS() do { *imm = (SEXT(BITS(i, 31, 25), 7) << 5) | BITS(i, 11, 7); } while(0)
|
||||
|
||||
static void decode_operand(Decode *s, int *rd, word_t *src1, word_t *src2, word_t *imm, int type) {
|
||||
uint32_t i = s->isa.inst.val;
|
||||
int rs1 = BITS(i, 19, 15);
|
||||
int rs2 = BITS(i, 24, 20);
|
||||
*rd = BITS(i, 11, 7);
|
||||
switch (type) {
|
||||
case TYPE_I: src1R(); immI(); break;
|
||||
case TYPE_U: immU(); break;
|
||||
case TYPE_S: src1R(); src2R(); immS(); break;
|
||||
}
|
||||
}
|
||||
|
||||
static int decode_exec(Decode *s) {
|
||||
int rd = 0;
|
||||
word_t src1 = 0, src2 = 0, imm = 0;
|
||||
s->dnpc = s->snpc;
|
||||
|
||||
#define INSTPAT_INST(s) ((s)->isa.inst.val)
|
||||
#define INSTPAT_MATCH(s, name, type, ... /* execute body */ ) { \
|
||||
decode_operand(s, &rd, &src1, &src2, &imm, concat(TYPE_, type)); \
|
||||
__VA_ARGS__ ; \
|
||||
}
|
||||
|
||||
INSTPAT_START();
|
||||
INSTPAT("??????? ????? ????? ??? ????? 00101 11", auipc , U, R(rd) = s->pc + imm);
|
||||
INSTPAT("??????? ????? ????? 100 ????? 00000 11", lbu , I, R(rd) = Mr(src1 + imm, 1));
|
||||
INSTPAT("??????? ????? ????? 000 ????? 01000 11", sb , S, Mw(src1 + imm, 1, src2));
|
||||
|
||||
INSTPAT("0000000 00001 00000 000 00000 11100 11", ebreak , N, NEMUTRAP(s->pc, R(10))); // R(10) is $a0
|
||||
INSTPAT("??????? ????? ????? ??? ????? ????? ??", inv , N, INV(s->pc));
|
||||
INSTPAT_END();
|
||||
|
||||
R(0) = 0; // reset $zero to 0
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int isa_exec_once(Decode *s) {
|
||||
s->isa.inst.val = inst_fetch(&s->snpc, 4);
|
||||
return decode_exec(s);
|
||||
}
|
33
nemu/src/isa/riscv32/local-include/reg.h
Normal file
33
nemu/src/isa/riscv32/local-include/reg.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __RISCV_REG_H__
|
||||
#define __RISCV_REG_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
static inline int check_reg_idx(int idx) {
|
||||
IFDEF(CONFIG_RT_CHECK, assert(idx >= 0 && idx < MUXDEF(CONFIG_RVE, 16, 32)));
|
||||
return idx;
|
||||
}
|
||||
|
||||
#define gpr(idx) (cpu.gpr[check_reg_idx(idx)])
|
||||
|
||||
static inline const char* reg_name(int idx) {
|
||||
extern const char* regs[];
|
||||
return regs[check_reg_idx(idx)];
|
||||
}
|
||||
|
||||
#endif
|
63
nemu/src/isa/riscv32/logo.c
Normal file
63
nemu/src/isa/riscv32/logo.c
Normal file
|
@ -0,0 +1,63 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
// refer to http://www.patorjk.com/software/taag/#p=display&f=Big&t=Type%20Something%20
|
||||
|
||||
/*
|
||||
_ __ __ _
|
||||
(_) | \/ | | |
|
||||
_ __ _ ___ ___ ________ __ | \ / | __ _ _ __ _ _ __ _| |
|
||||
| '__| / __|/ __|______\ \ / / | |\/| |/ _` | '_ \| | | |/ _` | |
|
||||
| | | \__ \ (__ \ V / | | | | (_| | | | | |_| | (_| | |
|
||||
|_| |_|___/\___| \_/ |_| |_|\__,_|_| |_|\__,_|\__,_|_|
|
||||
|
||||
*/
|
||||
|
||||
unsigned char isa_logo[] = {
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x20,
|
||||
0x20, 0x5f, 0x5f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x5f, 0x20, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x28, 0x5f, 0x29, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x7c, 0x20, 0x20, 0x5c, 0x2f, 0x20, 0x20, 0x7c, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7c, 0x20,
|
||||
0x7c, 0x0a, 0x20, 0x20, 0x5f, 0x20, 0x5f, 0x5f, 0x20, 0x5f, 0x20, 0x5f,
|
||||
0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x5f, 0x5f, 0x20, 0x5f, 0x5f, 0x5f, 0x5f,
|
||||
0x5f, 0x5f, 0x5f, 0x5f, 0x20, 0x20, 0x20, 0x5f, 0x5f, 0x20, 0x7c, 0x20,
|
||||
0x5c, 0x20, 0x20, 0x2f, 0x20, 0x7c, 0x20, 0x5f, 0x5f, 0x20, 0x5f, 0x20,
|
||||
0x5f, 0x20, 0x5f, 0x5f, 0x20, 0x20, 0x5f, 0x20, 0x20, 0x20, 0x5f, 0x20,
|
||||
0x20, 0x5f, 0x5f, 0x20, 0x5f, 0x7c, 0x20, 0x7c, 0x0a, 0x20, 0x7c, 0x20,
|
||||
0x27, 0x5f, 0x5f, 0x7c, 0x20, 0x2f, 0x20, 0x5f, 0x5f, 0x7c, 0x2f, 0x20,
|
||||
0x5f, 0x5f, 0x7c, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5f, 0x5c, 0x20, 0x5c,
|
||||
0x20, 0x2f, 0x20, 0x2f, 0x20, 0x7c, 0x20, 0x7c, 0x5c, 0x2f, 0x7c, 0x20,
|
||||
0x7c, 0x2f, 0x20, 0x5f, 0x60, 0x20, 0x7c, 0x20, 0x27, 0x5f, 0x20, 0x5c,
|
||||
0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x2f, 0x20, 0x5f, 0x60, 0x20,
|
||||
0x7c, 0x20, 0x7c, 0x0a, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x20, 0x7c, 0x20,
|
||||
0x5c, 0x5f, 0x5f, 0x20, 0x5c, 0x20, 0x28, 0x5f, 0x5f, 0x20, 0x20, 0x20,
|
||||
0x20, 0x20, 0x20, 0x20, 0x20, 0x5c, 0x20, 0x56, 0x20, 0x2f, 0x20, 0x20,
|
||||
0x7c, 0x20, 0x7c, 0x20, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x28, 0x5f, 0x7c,
|
||||
0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x5f, 0x7c,
|
||||
0x20, 0x7c, 0x20, 0x28, 0x5f, 0x7c, 0x20, 0x7c, 0x20, 0x7c, 0x0a, 0x20,
|
||||
0x7c, 0x5f, 0x7c, 0x20, 0x20, 0x7c, 0x5f, 0x7c, 0x5f, 0x5f, 0x5f, 0x2f,
|
||||
0x5c, 0x5f, 0x5f, 0x5f, 0x7c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
|
||||
0x20, 0x5c, 0x5f, 0x2f, 0x20, 0x20, 0x20, 0x7c, 0x5f, 0x7c, 0x20, 0x20,
|
||||
0x7c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f, 0x2c, 0x5f, 0x7c, 0x5f, 0x7c, 0x20,
|
||||
0x7c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f, 0x2c, 0x5f, 0x7c, 0x5c, 0x5f, 0x5f,
|
||||
0x2c, 0x5f, 0x7c, 0x5f, 0x7c, 0x0a, '\0' /* Termination Character is indispensable! */
|
||||
};
|
31
nemu/src/isa/riscv32/reg.c
Normal file
31
nemu/src/isa/riscv32/reg.c
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include "local-include/reg.h"
|
||||
|
||||
const char *regs[] = {
|
||||
"$0", "ra", "sp", "gp", "tp", "t0", "t1", "t2",
|
||||
"s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5",
|
||||
"a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7",
|
||||
"s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6"
|
||||
};
|
||||
|
||||
void isa_reg_display() {
|
||||
}
|
||||
|
||||
word_t isa_reg_str2val(const char *s, bool *success) {
|
||||
return 0;
|
||||
}
|
28
nemu/src/isa/riscv32/system/intr.c
Normal file
28
nemu/src/isa/riscv32/system/intr.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
word_t isa_raise_intr(word_t NO, vaddr_t epc) {
|
||||
/* TODO: Trigger an interrupt/exception with ``NO''.
|
||||
* Then return the address of the interrupt/exception vector.
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
word_t isa_query_intr() {
|
||||
return INTR_EMPTY;
|
||||
}
|
22
nemu/src/isa/riscv32/system/mmu.c
Normal file
22
nemu/src/isa/riscv32/system/mmu.c
Normal file
|
@ -0,0 +1,22 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/vaddr.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
paddr_t isa_mmu_translate(vaddr_t vaddr, int len, int type) {
|
||||
return MEM_RET_FAIL;
|
||||
}
|
34
nemu/src/memory/Kconfig
Normal file
34
nemu/src/memory/Kconfig
Normal file
|
@ -0,0 +1,34 @@
|
|||
menu "Memory Configuration"
|
||||
|
||||
config MBASE
|
||||
hex "Memory base address"
|
||||
default 0x0 if ISA_x86
|
||||
default 0x80000000
|
||||
|
||||
config MSIZE
|
||||
hex "Memory size"
|
||||
default 0x8000000
|
||||
|
||||
config PC_RESET_OFFSET
|
||||
hex "Offset of reset vector from the base of memory"
|
||||
default 0x100000 if ISA_x86
|
||||
default 0
|
||||
|
||||
choice
|
||||
prompt "Physical memory definition"
|
||||
default PMEM_GARRAY
|
||||
config PMEM_MALLOC
|
||||
bool "Using malloc()"
|
||||
config PMEM_GARRAY
|
||||
depends on !TARGET_AM
|
||||
bool "Using global array"
|
||||
endchoice
|
||||
|
||||
config MEM_RANDOM
|
||||
depends on MODE_SYSTEM && !DIFFTEST && !TARGET_AM
|
||||
bool "Initialize the memory with random values"
|
||||
default y
|
||||
help
|
||||
This may help to find undefined behaviors.
|
||||
|
||||
endmenu #MEMORY
|
64
nemu/src/memory/paddr.c
Normal file
64
nemu/src/memory/paddr.c
Normal file
|
@ -0,0 +1,64 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <memory/host.h>
|
||||
#include <memory/paddr.h>
|
||||
#include <device/mmio.h>
|
||||
#include <isa.h>
|
||||
|
||||
#if defined(CONFIG_PMEM_MALLOC)
|
||||
static uint8_t *pmem = NULL;
|
||||
#else // CONFIG_PMEM_GARRAY
|
||||
static uint8_t pmem[CONFIG_MSIZE] PG_ALIGN = {};
|
||||
#endif
|
||||
|
||||
uint8_t* guest_to_host(paddr_t paddr) { return pmem + paddr - CONFIG_MBASE; }
|
||||
paddr_t host_to_guest(uint8_t *haddr) { return haddr - pmem + CONFIG_MBASE; }
|
||||
|
||||
static word_t pmem_read(paddr_t addr, int len) {
|
||||
word_t ret = host_read(guest_to_host(addr), len);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void pmem_write(paddr_t addr, int len, word_t data) {
|
||||
host_write(guest_to_host(addr), len, data);
|
||||
}
|
||||
|
||||
static void out_of_bound(paddr_t addr) {
|
||||
panic("address = " FMT_PADDR " is out of bound of pmem [" FMT_PADDR ", " FMT_PADDR "] at pc = " FMT_WORD,
|
||||
addr, PMEM_LEFT, PMEM_RIGHT, cpu.pc);
|
||||
}
|
||||
|
||||
void init_mem() {
|
||||
#if defined(CONFIG_PMEM_MALLOC)
|
||||
pmem = malloc(CONFIG_MSIZE);
|
||||
assert(pmem);
|
||||
#endif
|
||||
IFDEF(CONFIG_MEM_RANDOM, memset(pmem, rand(), CONFIG_MSIZE));
|
||||
Log("physical memory area [" FMT_PADDR ", " FMT_PADDR "]", PMEM_LEFT, PMEM_RIGHT);
|
||||
}
|
||||
|
||||
word_t paddr_read(paddr_t addr, int len) {
|
||||
if (likely(in_pmem(addr))) return pmem_read(addr, len);
|
||||
IFDEF(CONFIG_DEVICE, return mmio_read(addr, len));
|
||||
out_of_bound(addr);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void paddr_write(paddr_t addr, int len, word_t data) {
|
||||
if (likely(in_pmem(addr))) { pmem_write(addr, len, data); return; }
|
||||
IFDEF(CONFIG_DEVICE, mmio_write(addr, len, data); return);
|
||||
out_of_bound(addr);
|
||||
}
|
29
nemu/src/memory/vaddr.c
Normal file
29
nemu/src/memory/vaddr.c
Normal file
|
@ -0,0 +1,29 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
word_t vaddr_ifetch(vaddr_t addr, int len) {
|
||||
return paddr_read(addr, len);
|
||||
}
|
||||
|
||||
word_t vaddr_read(vaddr_t addr, int len) {
|
||||
return paddr_read(addr, len);
|
||||
}
|
||||
|
||||
void vaddr_write(vaddr_t addr, int len, word_t data) {
|
||||
paddr_write(addr, len, data);
|
||||
}
|
162
nemu/src/monitor/monitor.c
Normal file
162
nemu/src/monitor/monitor.c
Normal file
|
@ -0,0 +1,162 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <memory/paddr.h>
|
||||
|
||||
void init_rand();
|
||||
void init_log(const char *log_file);
|
||||
void init_mem();
|
||||
void init_difftest(char *ref_so_file, long img_size, int port);
|
||||
void init_device();
|
||||
void init_sdb();
|
||||
void init_disasm(const char *triple);
|
||||
|
||||
static void welcome() {
|
||||
Log("Trace: %s", MUXDEF(CONFIG_TRACE, ANSI_FMT("ON", ANSI_FG_GREEN), ANSI_FMT("OFF", ANSI_FG_RED)));
|
||||
IFDEF(CONFIG_TRACE, Log("If trace is enabled, a log file will be generated "
|
||||
"to record the trace. This may lead to a large log file. "
|
||||
"If it is not necessary, you can disable it in menuconfig"));
|
||||
Log("Build time: %s, %s", __TIME__, __DATE__);
|
||||
printf("Welcome to %s-NEMU!\n", ANSI_FMT(str(__GUEST_ISA__), ANSI_FG_YELLOW ANSI_BG_RED));
|
||||
printf("For help, type \"help\"\n");
|
||||
Log("Exercise: Please remove me in the source code and compile NEMU again.");
|
||||
assert(0);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
#include <getopt.h>
|
||||
|
||||
void sdb_set_batch_mode();
|
||||
|
||||
static char *log_file = NULL;
|
||||
static char *diff_so_file = NULL;
|
||||
static char *img_file = NULL;
|
||||
static int difftest_port = 1234;
|
||||
|
||||
static long load_img() {
|
||||
if (img_file == NULL) {
|
||||
Log("No image is given. Use the default build-in image.");
|
||||
return 4096; // built-in image size
|
||||
}
|
||||
|
||||
FILE *fp = fopen(img_file, "rb");
|
||||
Assert(fp, "Can not open '%s'", img_file);
|
||||
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long size = ftell(fp);
|
||||
|
||||
Log("The image is %s, size = %ld", img_file, size);
|
||||
|
||||
fseek(fp, 0, SEEK_SET);
|
||||
int ret = fread(guest_to_host(RESET_VECTOR), size, 1, fp);
|
||||
assert(ret == 1);
|
||||
|
||||
fclose(fp);
|
||||
return size;
|
||||
}
|
||||
|
||||
static int parse_args(int argc, char *argv[]) {
|
||||
const struct option table[] = {
|
||||
{"batch" , no_argument , NULL, 'b'},
|
||||
{"log" , required_argument, NULL, 'l'},
|
||||
{"diff" , required_argument, NULL, 'd'},
|
||||
{"port" , required_argument, NULL, 'p'},
|
||||
{"help" , no_argument , NULL, 'h'},
|
||||
{0 , 0 , NULL, 0 },
|
||||
};
|
||||
int o;
|
||||
while ( (o = getopt_long(argc, argv, "-bhl:d:p:", table, NULL)) != -1) {
|
||||
switch (o) {
|
||||
case 'b': sdb_set_batch_mode(); break;
|
||||
case 'p': sscanf(optarg, "%d", &difftest_port); break;
|
||||
case 'l': log_file = optarg; break;
|
||||
case 'd': diff_so_file = optarg; break;
|
||||
case 1: img_file = optarg; return 0;
|
||||
default:
|
||||
printf("Usage: %s [OPTION...] IMAGE [args]\n\n", argv[0]);
|
||||
printf("\t-b,--batch run with batch mode\n");
|
||||
printf("\t-l,--log=FILE output log to FILE\n");
|
||||
printf("\t-d,--diff=REF_SO run DiffTest with reference REF_SO\n");
|
||||
printf("\t-p,--port=PORT run DiffTest with port PORT\n");
|
||||
printf("\n");
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void init_monitor(int argc, char *argv[]) {
|
||||
/* Perform some global initialization. */
|
||||
|
||||
/* Parse arguments. */
|
||||
parse_args(argc, argv);
|
||||
|
||||
/* Set random seed. */
|
||||
init_rand();
|
||||
|
||||
/* Open the log file. */
|
||||
init_log(log_file);
|
||||
|
||||
/* Initialize memory. */
|
||||
init_mem();
|
||||
|
||||
/* Initialize devices. */
|
||||
IFDEF(CONFIG_DEVICE, init_device());
|
||||
|
||||
/* Perform ISA dependent initialization. */
|
||||
init_isa();
|
||||
|
||||
/* Load the image to memory. This will overwrite the built-in image. */
|
||||
long img_size = load_img();
|
||||
|
||||
/* Initialize differential testing. */
|
||||
init_difftest(diff_so_file, img_size, difftest_port);
|
||||
|
||||
/* Initialize the simple debugger. */
|
||||
init_sdb();
|
||||
|
||||
#ifndef CONFIG_ISA_loongarch32r
|
||||
IFDEF(CONFIG_ITRACE, init_disasm(
|
||||
MUXDEF(CONFIG_ISA_x86, "i686",
|
||||
MUXDEF(CONFIG_ISA_mips32, "mipsel",
|
||||
MUXDEF(CONFIG_ISA_riscv,
|
||||
MUXDEF(CONFIG_RV64, "riscv64",
|
||||
"riscv32"),
|
||||
"bad"))) "-pc-linux-gnu"
|
||||
));
|
||||
#endif
|
||||
|
||||
/* Display welcome message. */
|
||||
welcome();
|
||||
}
|
||||
#else // CONFIG_TARGET_AM
|
||||
static long load_img() {
|
||||
extern char bin_start, bin_end;
|
||||
size_t size = &bin_end - &bin_start;
|
||||
Log("img size = %ld", size);
|
||||
memcpy(guest_to_host(RESET_VECTOR), &bin_start, size);
|
||||
return size;
|
||||
}
|
||||
|
||||
void am_init_monitor() {
|
||||
init_rand();
|
||||
init_mem();
|
||||
init_isa();
|
||||
load_img();
|
||||
IFDEF(CONFIG_DEVICE, init_device());
|
||||
welcome();
|
||||
}
|
||||
#endif
|
125
nemu/src/monitor/sdb/expr.c
Normal file
125
nemu/src/monitor/sdb/expr.c
Normal file
|
@ -0,0 +1,125 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
|
||||
/* We use the POSIX regex functions to process regular expressions.
|
||||
* Type 'man regex' for more information about POSIX regex functions.
|
||||
*/
|
||||
#include <regex.h>
|
||||
|
||||
enum {
|
||||
TK_NOTYPE = 256, TK_EQ,
|
||||
|
||||
/* TODO: Add more token types */
|
||||
|
||||
};
|
||||
|
||||
static struct rule {
|
||||
const char *regex;
|
||||
int token_type;
|
||||
} rules[] = {
|
||||
|
||||
/* TODO: Add more rules.
|
||||
* Pay attention to the precedence level of different rules.
|
||||
*/
|
||||
|
||||
{" +", TK_NOTYPE}, // spaces
|
||||
{"\\+", '+'}, // plus
|
||||
{"==", TK_EQ}, // equal
|
||||
};
|
||||
|
||||
#define NR_REGEX ARRLEN(rules)
|
||||
|
||||
static regex_t re[NR_REGEX] = {};
|
||||
|
||||
/* Rules are used for many times.
|
||||
* Therefore we compile them only once before any usage.
|
||||
*/
|
||||
void init_regex() {
|
||||
int i;
|
||||
char error_msg[128];
|
||||
int ret;
|
||||
|
||||
for (i = 0; i < NR_REGEX; i ++) {
|
||||
ret = regcomp(&re[i], rules[i].regex, REG_EXTENDED);
|
||||
if (ret != 0) {
|
||||
regerror(ret, &re[i], error_msg, 128);
|
||||
panic("regex compilation failed: %s\n%s", error_msg, rules[i].regex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
typedef struct token {
|
||||
int type;
|
||||
char str[32];
|
||||
} Token;
|
||||
|
||||
static Token tokens[32] __attribute__((used)) = {};
|
||||
static int nr_token __attribute__((used)) = 0;
|
||||
|
||||
static bool make_token(char *e) {
|
||||
int position = 0;
|
||||
int i;
|
||||
regmatch_t pmatch;
|
||||
|
||||
nr_token = 0;
|
||||
|
||||
while (e[position] != '\0') {
|
||||
/* Try all rules one by one. */
|
||||
for (i = 0; i < NR_REGEX; i ++) {
|
||||
if (regexec(&re[i], e + position, 1, &pmatch, 0) == 0 && pmatch.rm_so == 0) {
|
||||
char *substr_start = e + position;
|
||||
int substr_len = pmatch.rm_eo;
|
||||
|
||||
Log("match rules[%d] = \"%s\" at position %d with len %d: %.*s",
|
||||
i, rules[i].regex, position, substr_len, substr_len, substr_start);
|
||||
|
||||
position += substr_len;
|
||||
|
||||
/* TODO: Now a new token is recognized with rules[i]. Add codes
|
||||
* to record the token in the array `tokens'. For certain types
|
||||
* of tokens, some extra actions should be performed.
|
||||
*/
|
||||
|
||||
switch (rules[i].token_type) {
|
||||
default: TODO();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NR_REGEX) {
|
||||
printf("no match at position %d\n%s\n%*.s^\n", position, e, position, "");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
word_t expr(char *e, bool *success) {
|
||||
if (!make_token(e)) {
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Insert codes to evaluate the expression. */
|
||||
TODO();
|
||||
|
||||
return 0;
|
||||
}
|
143
nemu/src/monitor/sdb/sdb.c
Normal file
143
nemu/src/monitor/sdb/sdb.c
Normal file
|
@ -0,0 +1,143 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <isa.h>
|
||||
#include <cpu/cpu.h>
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#include "sdb.h"
|
||||
|
||||
static int is_batch_mode = false;
|
||||
|
||||
void init_regex();
|
||||
void init_wp_pool();
|
||||
|
||||
/* We use the `readline' library to provide more flexibility to read from stdin. */
|
||||
static char* rl_gets() {
|
||||
static char *line_read = NULL;
|
||||
|
||||
if (line_read) {
|
||||
free(line_read);
|
||||
line_read = NULL;
|
||||
}
|
||||
|
||||
line_read = readline("(nemu) ");
|
||||
|
||||
if (line_read && *line_read) {
|
||||
add_history(line_read);
|
||||
}
|
||||
|
||||
return line_read;
|
||||
}
|
||||
|
||||
static int cmd_c(char *args) {
|
||||
cpu_exec(-1);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int cmd_q(char *args) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int cmd_help(char *args);
|
||||
|
||||
static struct {
|
||||
const char *name;
|
||||
const char *description;
|
||||
int (*handler) (char *);
|
||||
} cmd_table [] = {
|
||||
{ "help", "Display information about all supported commands", cmd_help },
|
||||
{ "c", "Continue the execution of the program", cmd_c },
|
||||
{ "q", "Exit NEMU", cmd_q },
|
||||
|
||||
/* TODO: Add more commands */
|
||||
|
||||
};
|
||||
|
||||
#define NR_CMD ARRLEN(cmd_table)
|
||||
|
||||
static int cmd_help(char *args) {
|
||||
/* extract the first argument */
|
||||
char *arg = strtok(NULL, " ");
|
||||
int i;
|
||||
|
||||
if (arg == NULL) {
|
||||
/* no argument given */
|
||||
for (i = 0; i < NR_CMD; i ++) {
|
||||
printf("%s - %s\n", cmd_table[i].name, cmd_table[i].description);
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (i = 0; i < NR_CMD; i ++) {
|
||||
if (strcmp(arg, cmd_table[i].name) == 0) {
|
||||
printf("%s - %s\n", cmd_table[i].name, cmd_table[i].description);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
printf("Unknown command '%s'\n", arg);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sdb_set_batch_mode() {
|
||||
is_batch_mode = true;
|
||||
}
|
||||
|
||||
void sdb_mainloop() {
|
||||
if (is_batch_mode) {
|
||||
cmd_c(NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
for (char *str; (str = rl_gets()) != NULL; ) {
|
||||
char *str_end = str + strlen(str);
|
||||
|
||||
/* extract the first token as the command */
|
||||
char *cmd = strtok(str, " ");
|
||||
if (cmd == NULL) { continue; }
|
||||
|
||||
/* treat the remaining string as the arguments,
|
||||
* which may need further parsing
|
||||
*/
|
||||
char *args = cmd + strlen(cmd) + 1;
|
||||
if (args >= str_end) {
|
||||
args = NULL;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_DEVICE
|
||||
extern void sdl_clear_event_queue();
|
||||
sdl_clear_event_queue();
|
||||
#endif
|
||||
|
||||
int i;
|
||||
for (i = 0; i < NR_CMD; i ++) {
|
||||
if (strcmp(cmd, cmd_table[i].name) == 0) {
|
||||
if (cmd_table[i].handler(args) < 0) { return; }
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == NR_CMD) { printf("Unknown command '%s'\n", cmd); }
|
||||
}
|
||||
}
|
||||
|
||||
void init_sdb() {
|
||||
/* Compile the regular expressions. */
|
||||
init_regex();
|
||||
|
||||
/* Initialize the watchpoint pool. */
|
||||
init_wp_pool();
|
||||
}
|
23
nemu/src/monitor/sdb/sdb.h
Normal file
23
nemu/src/monitor/sdb/sdb.h
Normal file
|
@ -0,0 +1,23 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#ifndef __SDB_H__
|
||||
#define __SDB_H__
|
||||
|
||||
#include <common.h>
|
||||
|
||||
word_t expr(char *e, bool *success);
|
||||
|
||||
#endif
|
43
nemu/src/monitor/sdb/watchpoint.c
Normal file
43
nemu/src/monitor/sdb/watchpoint.c
Normal file
|
@ -0,0 +1,43 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include "sdb.h"
|
||||
|
||||
#define NR_WP 32
|
||||
|
||||
typedef struct watchpoint {
|
||||
int NO;
|
||||
struct watchpoint *next;
|
||||
|
||||
/* TODO: Add more members if necessary */
|
||||
|
||||
} WP;
|
||||
|
||||
static WP wp_pool[NR_WP] = {};
|
||||
static WP *head = NULL, *free_ = NULL;
|
||||
|
||||
void init_wp_pool() {
|
||||
int i;
|
||||
for (i = 0; i < NR_WP; i ++) {
|
||||
wp_pool[i].NO = i;
|
||||
wp_pool[i].next = (i == NR_WP - 1 ? NULL : &wp_pool[i + 1]);
|
||||
}
|
||||
|
||||
head = NULL;
|
||||
free_ = wp_pool;
|
||||
}
|
||||
|
||||
/* TODO: Implement the functionality of watchpoint */
|
||||
|
35
nemu/src/nemu-main.c
Normal file
35
nemu/src/nemu-main.c
Normal file
|
@ -0,0 +1,35 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
void init_monitor(int, char *[]);
|
||||
void am_init_monitor();
|
||||
void engine_start();
|
||||
int is_exit_status_bad();
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
/* Initialize the monitor. */
|
||||
#ifdef CONFIG_TARGET_AM
|
||||
am_init_monitor();
|
||||
#else
|
||||
init_monitor(argc, argv);
|
||||
#endif
|
||||
|
||||
/* Start engine. */
|
||||
engine_start();
|
||||
|
||||
return is_exit_status_bad();
|
||||
}
|
109
nemu/src/utils/disasm.cc
Normal file
109
nemu/src/utils/disasm.cc
Normal file
|
@ -0,0 +1,109 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
|
||||
#endif
|
||||
|
||||
#include "llvm/MC/MCAsmInfo.h"
|
||||
#include "llvm/MC/MCContext.h"
|
||||
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
|
||||
#include "llvm/MC/MCInstPrinter.h"
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
#include "llvm/MC/TargetRegistry.h"
|
||||
#if LLVM_VERSION_MAJOR >= 15
|
||||
#include "llvm/MC/MCSubtargetInfo.h"
|
||||
#endif
|
||||
#else
|
||||
#include "llvm/Support/TargetRegistry.h"
|
||||
#endif
|
||||
#include "llvm/Support/TargetSelect.h"
|
||||
|
||||
#if defined(__GNUC__) && !defined(__clang__)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 11
|
||||
#error Please use LLVM with major version >= 11
|
||||
#endif
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static llvm::MCDisassembler *gDisassembler = nullptr;
|
||||
static llvm::MCSubtargetInfo *gSTI = nullptr;
|
||||
static llvm::MCInstPrinter *gIP = nullptr;
|
||||
|
||||
extern "C" void init_disasm(const char *triple) {
|
||||
llvm::InitializeAllTargetInfos();
|
||||
llvm::InitializeAllTargetMCs();
|
||||
llvm::InitializeAllAsmParsers();
|
||||
llvm::InitializeAllDisassemblers();
|
||||
|
||||
std::string errstr;
|
||||
std::string gTriple(triple);
|
||||
|
||||
llvm::MCInstrInfo *gMII = nullptr;
|
||||
llvm::MCRegisterInfo *gMRI = nullptr;
|
||||
auto target = llvm::TargetRegistry::lookupTarget(gTriple, errstr);
|
||||
if (!target) {
|
||||
llvm::errs() << "Can't find target for " << gTriple << ": " << errstr << "\n";
|
||||
assert(0);
|
||||
}
|
||||
|
||||
MCTargetOptions MCOptions;
|
||||
gSTI = target->createMCSubtargetInfo(gTriple, "", "");
|
||||
std::string isa = target->getName();
|
||||
if (isa == "riscv32" || isa == "riscv64") {
|
||||
gSTI->ApplyFeatureFlag("+m");
|
||||
gSTI->ApplyFeatureFlag("+a");
|
||||
gSTI->ApplyFeatureFlag("+c");
|
||||
gSTI->ApplyFeatureFlag("+f");
|
||||
gSTI->ApplyFeatureFlag("+d");
|
||||
}
|
||||
gMII = target->createMCInstrInfo();
|
||||
gMRI = target->createMCRegInfo(gTriple);
|
||||
auto AsmInfo = target->createMCAsmInfo(*gMRI, gTriple, MCOptions);
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
auto llvmTripleTwine = Twine(triple);
|
||||
auto llvmtriple = llvm::Triple(llvmTripleTwine);
|
||||
auto Ctx = new llvm::MCContext(llvmtriple,AsmInfo, gMRI, nullptr);
|
||||
#else
|
||||
auto Ctx = new llvm::MCContext(AsmInfo, gMRI, nullptr);
|
||||
#endif
|
||||
gDisassembler = target->createMCDisassembler(*gSTI, *Ctx);
|
||||
gIP = target->createMCInstPrinter(llvm::Triple(gTriple),
|
||||
AsmInfo->getAssemblerDialect(), *AsmInfo, *gMII, *gMRI);
|
||||
gIP->setPrintImmHex(true);
|
||||
gIP->setPrintBranchImmAsAddress(true);
|
||||
if (isa == "riscv32" || isa == "riscv64")
|
||||
gIP->applyTargetSpecificCLOption("no-aliases");
|
||||
}
|
||||
|
||||
extern "C" void disassemble(char *str, int size, uint64_t pc, uint8_t *code, int nbyte) {
|
||||
MCInst inst;
|
||||
llvm::ArrayRef<uint8_t> arr(code, nbyte);
|
||||
uint64_t dummy_size = 0;
|
||||
gDisassembler->getInstruction(inst, dummy_size, arr, pc, llvm::nulls());
|
||||
|
||||
std::string s;
|
||||
raw_string_ostream os(s);
|
||||
gIP->printInst(&inst, pc, "", *gSTI, os);
|
||||
|
||||
int skip = s.find_first_not_of('\t');
|
||||
const char *p = s.c_str() + skip;
|
||||
assert((int)s.length() - skip < size);
|
||||
strcpy(str, p);
|
||||
}
|
20
nemu/src/utils/filelist.mk
Normal file
20
nemu/src/utils/filelist.mk
Normal file
|
@ -0,0 +1,20 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
ifneq ($(CONFIG_ITRACE)$(CONFIG_IQUEUE),)
|
||||
CXXSRC = src/utils/disasm.cc
|
||||
CXXFLAGS += $(shell llvm-config --cxxflags) -fPIE
|
||||
LIBS += $(shell llvm-config --libs)
|
||||
endif
|
37
nemu/src/utils/log.c
Normal file
37
nemu/src/utils/log.c
Normal file
|
@ -0,0 +1,37 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
|
||||
extern uint64_t g_nr_guest_inst;
|
||||
|
||||
#ifndef CONFIG_TARGET_AM
|
||||
FILE *log_fp = NULL;
|
||||
|
||||
void init_log(const char *log_file) {
|
||||
log_fp = stdout;
|
||||
if (log_file != NULL) {
|
||||
FILE *fp = fopen(log_file, "w");
|
||||
Assert(fp, "Can not open '%s'", log_file);
|
||||
log_fp = fp;
|
||||
}
|
||||
Log("Log is written to %s", log_file ? log_file : "stdout");
|
||||
}
|
||||
|
||||
bool log_enable() {
|
||||
return MUXDEF(CONFIG_TRACE, (g_nr_guest_inst >= CONFIG_TRACE_START) &&
|
||||
(g_nr_guest_inst <= CONFIG_TRACE_END), false);
|
||||
}
|
||||
#endif
|
24
nemu/src/utils/state.c
Normal file
24
nemu/src/utils/state.c
Normal file
|
@ -0,0 +1,24 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <utils.h>
|
||||
|
||||
NEMUState nemu_state = { .state = NEMU_STOP };
|
||||
|
||||
int is_exit_status_bad() {
|
||||
int good = (nemu_state.state == NEMU_END && nemu_state.halt_ret == 0) ||
|
||||
(nemu_state.state == NEMU_QUIT);
|
||||
return !good;
|
||||
}
|
49
nemu/src/utils/timer.c
Normal file
49
nemu/src/utils/timer.c
Normal file
|
@ -0,0 +1,49 @@
|
|||
/***************************************************************************************
|
||||
* Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
*
|
||||
* NEMU is licensed under Mulan PSL v2.
|
||||
* You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
* You may obtain a copy of Mulan PSL v2 at:
|
||||
* http://license.coscl.org.cn/MulanPSL2
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
*
|
||||
* See the Mulan PSL v2 for more details.
|
||||
***************************************************************************************/
|
||||
|
||||
#include <common.h>
|
||||
#include MUXDEF(CONFIG_TIMER_GETTIMEOFDAY, <sys/time.h>, <time.h>)
|
||||
|
||||
IFDEF(CONFIG_TIMER_CLOCK_GETTIME,
|
||||
static_assert(CLOCKS_PER_SEC == 1000000, "CLOCKS_PER_SEC != 1000000"));
|
||||
IFDEF(CONFIG_TIMER_CLOCK_GETTIME,
|
||||
static_assert(sizeof(clock_t) == 8, "sizeof(clock_t) != 8"));
|
||||
|
||||
static uint64_t boot_time = 0;
|
||||
|
||||
static uint64_t get_time_internal() {
|
||||
#if defined(CONFIG_TARGET_AM)
|
||||
uint64_t us = io_read(AM_TIMER_UPTIME).us;
|
||||
#elif defined(CONFIG_TIMER_GETTIMEOFDAY)
|
||||
struct timeval now;
|
||||
gettimeofday(&now, NULL);
|
||||
uint64_t us = now.tv_sec * 1000000 + now.tv_usec;
|
||||
#else
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
|
||||
uint64_t us = now.tv_sec * 1000000 + now.tv_nsec / 1000;
|
||||
#endif
|
||||
return us;
|
||||
}
|
||||
|
||||
uint64_t get_time() {
|
||||
if (boot_time == 0) boot_time = get_time_internal();
|
||||
uint64_t now = get_time_internal();
|
||||
return now - boot_time;
|
||||
}
|
||||
|
||||
void init_rand() {
|
||||
srand(get_time_internal());
|
||||
}
|
28
nemu/tools/difftest.mk
Normal file
28
nemu/tools/difftest.mk
Normal file
|
@ -0,0 +1,28 @@
|
|||
#***************************************************************************************
|
||||
# Copyright (c) 2014-2022 Zihao Yu, Nanjing University
|
||||
#
|
||||
# NEMU is licensed under Mulan PSL v2.
|
||||
# You can use this software according to the terms and conditions of the Mulan PSL v2.
|
||||
# You may obtain a copy of Mulan PSL v2 at:
|
||||
# http://license.coscl.org.cn/MulanPSL2
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
|
||||
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
|
||||
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
|
||||
#
|
||||
# See the Mulan PSL v2 for more details.
|
||||
#**************************************************************************************/
|
||||
|
||||
ifdef CONFIG_DIFFTEST
|
||||
DIFF_REF_PATH = $(NEMU_HOME)/$(call remove_quote,$(CONFIG_DIFFTEST_REF_PATH))
|
||||
DIFF_REF_SO = $(DIFF_REF_PATH)/build/$(GUEST_ISA)-$(call remove_quote,$(CONFIG_DIFFTEST_REF_NAME))-so
|
||||
MKFLAGS = GUEST_ISA=$(GUEST_ISA) SHARE=1 ENGINE=interpreter
|
||||
ARGS_DIFF = --diff=$(DIFF_REF_SO)
|
||||
|
||||
ifndef CONFIG_DIFFTEST_REF_NEMU
|
||||
$(DIFF_REF_SO):
|
||||
$(MAKE) -s -C $(DIFF_REF_PATH) $(MKFLAGS)
|
||||
endif
|
||||
|
||||
.PHONY: $(DIFF_REF_SO)
|
||||
endif
|
3
nemu/tools/fixdep/Makefile
Normal file
3
nemu/tools/fixdep/Makefile
Normal file
|
@ -0,0 +1,3 @@
|
|||
NAME = fixdep
|
||||
SRCS = fixdep.c
|
||||
include $(NEMU_HOME)/scripts/build.mk
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue