NEMU ISA相关的API说明文档
为了提高性能, 这些API也可以通过宏定义实现, 但本文档还是以C变量或函数的方式列出, 以给出变量或函数的类型.
全局类型
word_t;
表示与ISA字长等长的无符号类型, 在32位的ISA中为uint32_t, 在64位的ISA中为uint64_t.
sword_t;
表示与ISA字长等长的有符号类型, 在32位的ISA中为int32_t, 在64位的ISA中为int64_t.
char *FMT_WORD;
word_t类型对应的十六进制格式化说明符, 在32位的ISA中为"0x%08x", 在64位的ISA中为"0x%016lx".
Monitor相关
char isa_logo[];
用于在未实现指令的报错信息中提示开发者阅读相关的手册.
word_t IMAGE_START;
表示镜像在内存中的位置距离内存起始地址的偏移.
void init_isa();
在monitor初始化时调用, 进行至少如下ISA相关的初始化工作:
- 设置必要的寄存器初值, 如
PC等 - 加载内置客户程序
寄存器相关
struct {
// ...
word_t pc;
} CPU_state;
寄存器结构的类型定义, 其中必须包含一个名为pc, 类型为word_t的成员.
CPU_state cpu;
寄存器结构的全局定义.
void isa_reg_display();
用于打印寄存器当前的值.
word_t isa_reg_str2val(const char *name, bool *success);
若存在名称为name的寄存器, 则返回其当前值, 并设置success为true;
否则设置success为false.
指令执行相关
struct {
// ...
} ISADecodeInfo;
用于存放ISA相关的译码信息, 会嵌入在译码状态结构体DecodeExecState的定义中.
vaddr_t isa_exec_once();
执行cpu.pc指向的指令, 并更新cpu.pc, 返回被执行指令的下一条静态指令的PC.
内存相关
word_t PMEM_BASE;
表示物理内存的起始地址.
int isa_vaddr_check(vaddr_t vaddr, int type, int len);
检查当前系统状态是否支持内存区间为[vaddr, vaddr + len), 类型为type的内存访问.
其中type可能为:
MEM_TYPE_IFETCH: 取指令MEM_TYPE_READ: 读数据MEM_TYPE_WRITE: 写数据
函数返回值可能为:
MEM_RET_OK: 该内存访问可以在物理内存上直接进行MEM_RET_NEED_TRANSLATE: 该内存访问需要经过地址转换MEM_RET_FAIL: 该内存访问失败, 需要抛出异常(如RISC架构不支持非对齐的内存访问)
paddr_t isa_mmu_translate(vaddr_t vaddr, int type, int len);
对内存区间为[vaddr, vaddr + len), 类型为type的内存访问进行地址转换.
函数返回值可能为:
pg_paddr|MEM_RET_OK: 地址转换成功, 其中pg_paddr为物理页面的地址(而不是vaddr翻译后的物理地址)MEM_RET_FAIL: 地址转换失败, 原因包括权限检查失败等不可恢复的原因, 一般需要抛出异常MEM_RET_CROSS_PAGE: 地址转换失败, 原因为访存请求跨越了页面的边界
bool isa_has_mem_exception();
查询当前是否有访存请求抛出异常, 如有则返回true, 否则返回false
DiffTest相关
NEMU作为DUT时使用
bool isa_difftest_checkregs(CPU_state *ref_r, vaddr_t pc);
检查当前的寄存器状态是否与ref_r相同, 其中pc为cpu.pc的上一条动态指令的PC, 即cpu.pc的旧值.
如果状态相同, 则返回true, 否则返回false.
void isa_difftest_attach();
将当前的所有状态同步到REF, 并在之后的执行中开启DiffTest.
NEMU作为REF时使用
void isa_difftest_getregs(void *r);
将当前的寄存器状态复制到r中.
void isa_difftest_setregs(const void *r);
将r中的寄存器状态复制到当前的寄存器中.
void isa_difftest_raise_intr(word_t NO);
触发一个编号为NO的中断/异常.