Skip to content

Commit

Permalink
Rename some important VM vars for move to ZP
Browse files Browse the repository at this point in the history
This definitely breaks upstream compatibility and is just a messy
adhoc optimization for testing right now.
  • Loading branch information
onnokort committed Aug 28, 2023
1 parent d8feef3 commit 60151e4
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 57 deletions.
12 changes: 6 additions & 6 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ static void handle_sbi_ecall(vm_t *vm)
vm->x_regs[RV_R_A1] = (uint32_t) ret.value;

/* Clear error to allow execution to continue */
vm->error = ERR_NONE;
_zp_vm_error = ERR_NONE;
}

#if !C64
Expand Down Expand Up @@ -468,8 +468,8 @@ static int semu_start(int argc, char **argv)
if (emu.vblk.InterruptStatus)
emu_update_vblk_interrupts(&vm);
#endif
if (vm.insn_count_hi > emu.timer_hi ||
(vm.insn_count_hi == emu.timer_hi && vm.insn_count > emu.timer_lo))
if (_zp_vm_insn_count_hi > emu.timer_hi ||
(_zp_vm_insn_count_hi == emu.timer_hi && _zp_vm_insn_count > emu.timer_lo))
vm.sip |= RV_INT_STI_BIT;
else
vm.sip &= ~RV_INT_STI_BIT;
Expand All @@ -480,15 +480,15 @@ static int semu_start(int argc, char **argv)
}

vm_step(&vm);
if (likely(!vm.error))
if (likely(!_zp_vm_error))
continue;

if (vm.error == ERR_EXCEPTION && vm.exc_cause == RV_EXC_ECALL_S) {
if (_zp_vm_error == ERR_EXCEPTION && vm.exc_cause == RV_EXC_ECALL_S) {
handle_sbi_ecall(&vm);
continue;
}

if (vm.error == ERR_EXCEPTION) {
if (_zp_vm_error == ERR_EXCEPTION) {
vm_trap(&vm);
continue;
}
Expand Down
85 changes: 46 additions & 39 deletions riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ static bool mmu_fetch_cache_valid = false;
static bool mmu_load_cache_valid = false;
static bool mmu_store_cache_valid = false;

vm_error_t _zp_vm_error __attribute__((section(".zp.bss")));
uint32_t _zp_vm_current_pc __attribute__((section(".zp.bss")));
uint32_t _zp_vm_pc __attribute__((section(".zp.bss")));
uint32_t _zp_vm_insn_count __attribute__((section(".zp.bss")));
uint32_t _zp_vm_insn_count_hi;


/* Return the string representation of an error code identifier */
static const char *vm_error_str(vm_error_t err)
{
Expand Down Expand Up @@ -49,10 +56,10 @@ static const char *vm_exc_cause_str(uint32_t err)
void vm_error_report(const vm_t *vm)
{
#if C64
printf("vm error %s: %s. val=%#lx\n", vm_error_str(vm->error),
printf("vm error %s: %s. val=%#lx\n", vm_error_str(_zp_vm_error),
vm_exc_cause_str(vm->exc_cause), vm->exc_val);
#else
fprintf(stderr, "vm error %s: %s. val=%#x\n", vm_error_str(vm->error),
fprintf(stderr, "vm error %s: %s. val=%#x\n", vm_error_str(_zp_vm_error),
vm_exc_cause_str(vm->exc_cause), vm->exc_val);
#endif
}
Expand Down Expand Up @@ -321,7 +328,7 @@ static void mmu_fetch(vm_t *vm, uint32_t addr, uint32_t *value)
addr_from = addr & ~MASK(RV_PAGE_SHIFT);
mmu_translate(vm, &addr, (1 << 3), (1 << 6), false, RV_EXC_FETCH_FAULT,
RV_EXC_FETCH_PFAULT);
if (vm->error)
if (_zp_vm_error)
return;
mmu_fetch_cache_valid = true;
addr_to = addr & ~MASK(RV_PAGE_SHIFT);
Expand All @@ -346,13 +353,13 @@ static void mmu_load(vm_t *vm,
mmu_translate(vm, &addr, (1 << 1) | (vm->sstatus_mxr ? (1 << 3) : 0),
(1 << 6), vm->sstatus_sum && vm->s_mode, RV_EXC_LOAD_FAULT,
RV_EXC_LOAD_PFAULT);
if (vm->error)
if (_zp_vm_error)
return;
mmu_load_cache_valid = true;
addr_to = addr & ~MASK(RV_PAGE_SHIFT);
}
vm->mem_load(vm, addr, width, value);
if (vm->error)
if (_zp_vm_error)
return;

if (unlikely(reserved))
Expand All @@ -375,7 +382,7 @@ static bool mmu_store(vm_t *vm,
mmu_translate(vm, &addr, (1 << 2), (1 << 6) | (1 << 7),
vm->sstatus_sum && vm->s_mode, RV_EXC_STORE_FAULT,
RV_EXC_STORE_PFAULT);
if (vm->error)
if (_zp_vm_error)
return false;
mmu_store_cache_valid = true;
addr_to = addr & ~MASK(RV_PAGE_SHIFT);
Expand All @@ -397,7 +404,7 @@ static bool mmu_store(vm_t *vm,

void vm_set_exception(vm_t *vm, uint32_t cause, uint32_t val)
{
vm->error = ERR_EXCEPTION;
_zp_vm_error = ERR_EXCEPTION;
vm->exc_cause = cause;
vm->exc_val = val;
}
Expand All @@ -411,22 +418,22 @@ void vm_trap(vm_t *vm)
/* Save to stack */
vm->sstatus_spie = vm->sstatus_sie;
vm->sstatus_spp = vm->s_mode;
vm->sepc = vm->current_pc;
vm->sepc = _zp_vm_current_pc;

/* Set */
vm->sstatus_sie = false;
vm->s_mode = true;
vm->pc = vm->stvec_addr;
_zp_vm_pc = vm->stvec_addr;
if (vm->stvec_vectored)
vm->pc += (vm->scause & MASK(31)) * 4;
_zp_vm_pc += (vm->scause & MASK(31)) * 4;

vm->error = ERR_NONE;
_zp_vm_error = ERR_NONE;
}

static void op_sret(vm_t *vm)
{
/* Restore from stack */
vm->pc = vm->sepc;
_zp_vm_pc = vm->sepc;
vm->s_mode = vm->sstatus_spp;
vm->sstatus_sie = vm->sstatus_spie;

Expand All @@ -447,7 +454,7 @@ static void op_privileged(vm_t *vm, uint32_t insn)
}
switch (decode_i_unsigned(insn)) {
case 0b000000000001: /* PRIV_EBREAK */
vm_set_exception(vm, RV_EXC_BREAKPOINT, vm->current_pc);
vm_set_exception(vm, RV_EXC_BREAKPOINT, _zp_vm_current_pc);
break;
case 0b000000000000: /* PRIV_ECALL */
vm_set_exception(vm, vm->s_mode ? RV_EXC_ECALL_S : RV_EXC_ECALL_U, 0);
Expand Down Expand Up @@ -490,7 +497,7 @@ static void csr_read(vm_t *vm, uint16_t addr, uint32_t *value)
* and writes should set the value after the increment. However,
* we do not expose any way to write the counters.
*/
*value = (addr & (1 << 7)) ? vm->insn_count_hi : vm->insn_count;
*value = (addr & (1 << 7)) ? _zp_vm_insn_count_hi : _zp_vm_insn_count;
}
return;
}
Expand Down Expand Up @@ -600,7 +607,7 @@ static void op_csr_rw(vm_t *vm, uint32_t insn, uint16_t csr, uint32_t wvalue)
if (decode_rd(insn)) {
uint32_t value;
csr_read(vm, csr, &value);
if (unlikely(vm->error))
if (unlikely(_zp_vm_error))
return;
set_dest(vm, insn, value);
}
Expand All @@ -615,7 +622,7 @@ static void op_csr_cs(vm_t *vm,
{
uint32_t value;
csr_read(vm, csr, &value);
if (unlikely(vm->error))
if (unlikely(_zp_vm_error))
return;
set_dest(vm, insn, value);
if (decode_rs1(insn))
Expand Down Expand Up @@ -740,24 +747,24 @@ static void do_jump(vm_t *vm, uint32_t addr)
if (unlikely(addr & 0b11))
vm_set_exception(vm, RV_EXC_PC_MISALIGN, addr);
else
vm->pc = addr;
_zp_vm_pc = addr;
}

static void op_jump_link(vm_t *vm, uint32_t insn, uint32_t addr)
{
if (unlikely(addr & 0b11)) {
vm_set_exception(vm, RV_EXC_PC_MISALIGN, addr);
} else {
set_dest(vm, insn, vm->pc);
vm->pc = addr;
set_dest(vm, insn, _zp_vm_pc);
_zp_vm_pc = addr;
}
}

#define AMO_OP(STORED_EXPR) \
do { \
value2 = read_rs2(vm, insn); \
mmu_load(vm, addr, RV_MEM_LW, &value, false); \
if (vm->error) \
if (_zp_vm_error) \
return; \
set_dest(vm, insn, value); \
mmu_store(vm, addr, RV_MEM_SW, (STORED_EXPR), false); \
Expand All @@ -776,15 +783,15 @@ static void op_amo(vm_t *vm, uint32_t insn)
if (decode_rs2(insn))
return vm_set_exception(vm, RV_EXC_ILLEGAL_INSTR, 0);
mmu_load(vm, addr, RV_MEM_LW, &value, true);
if (vm->error)
if (_zp_vm_error)
return;
set_dest(vm, insn, value);
break;
case 0b00011: /* AMO_SC */
if (addr & 0b11)
return vm_set_exception(vm, RV_EXC_STORE_MISALIGN, addr);
bool ok = mmu_store(vm, addr, RV_MEM_SW, read_rs2(vm, insn), true);
if (vm->error)
if (_zp_vm_error)
return;
set_dest(vm, insn, ok ? 0 : 1);
break;
Expand Down Expand Up @@ -824,10 +831,10 @@ static void op_amo(vm_t *vm, uint32_t insn)

void vm_step(vm_t *vm)
{
if (unlikely(vm->error))
if (unlikely(_zp_vm_error))
return;

vm->current_pc = vm->pc;
_zp_vm_current_pc = _zp_vm_pc;

if ((vm->sstatus_sie || !vm->s_mode) && (vm->sip & vm->sie)) {
uint32_t applicable = (vm->sip & vm->sie);
Expand All @@ -838,24 +845,24 @@ void vm_step(vm_t *vm)
}

uint32_t insn;
mmu_fetch(vm, vm->pc, &insn);
if (unlikely(vm->error))
mmu_fetch(vm, _zp_vm_pc, &insn);
if (unlikely(_zp_vm_error))
return;

uint8_t* pcl = (uint8_t*)(&vm->pc);
uint8_t* pcl = (uint8_t*)(&_zp_vm_pc);
*pcl+=4;
if (!*pcl) vm->pc+=256;
if (!*pcl) _zp_vm_pc+=256;

//vm->pc += 4;
//_zp_vm_pc += 4;
//
uint8_t* icl = (uint8_t*)(&vm->insn_count);
uint8_t* icl = (uint8_t*)(&_zp_vm_insn_count);
(*icl)++;
if(!*icl) {
vm->insn_count+=256;
if (!vm->insn_count)
vm->insn_count_hi++;
_zp_vm_insn_count+=256;
if (!_zp_vm_insn_count)
_zp_vm_insn_count_hi++;
}
//vm->insn_count++;
//_zp_vm_insn_count++;

uint32_t insn_opcode = insn & MASK(7), value;
switch (insn_opcode) {
Expand All @@ -876,29 +883,29 @@ void vm_step(vm_t *vm)
set_dest(vm, insn, decode_u(insn));
break;
case RV32_AUIPC:
set_dest(vm, insn, decode_u(insn) + vm->current_pc);
set_dest(vm, insn, decode_u(insn) + _zp_vm_current_pc);
break;
case RV32_JAL:
op_jump_link(vm, insn, decode_j(insn) + vm->current_pc);
op_jump_link(vm, insn, decode_j(insn) + _zp_vm_current_pc);
break;
case RV32_JALR:
op_jump_link(vm, insn, (decode_i(insn) + read_rs1(vm, insn)) & ~1);
break;
case RV32_BRANCH:
if (op_jmp(vm, insn, read_rs1(vm, insn), read_rs2(vm, insn)))
do_jump(vm, decode_b(insn) + vm->current_pc);
do_jump(vm, decode_b(insn) + _zp_vm_current_pc);
break;
case RV32_LOAD:
mmu_load(vm, read_rs1(vm, insn) + decode_i(insn), decode_func3(insn),
&value, false);
if (unlikely(vm->error))
if (unlikely(_zp_vm_error))
return;
set_dest(vm, insn, value);
break;
case RV32_STORE:
mmu_store(vm, read_rs1(vm, insn) + decode_s(insn), decode_func3(insn),
read_rs2(vm, insn), false);
if (unlikely(vm->error))
if (unlikely(_zp_vm_error))
return;
break;
case RV32_MISC_MEM:
Expand Down
28 changes: 17 additions & 11 deletions riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* advanced, environment calls can be handled by simply clearing the
* error after completing the operation.
* - Faults: when handling faults, it is important to set
* vm->pc = vm->current_pc so that the instruction can be retried.
* _zp_vm_pc = _zp_vm_current_pc so that the instruction can be retried.
* - Traps: exceptions can be delegated to the emulated code in the form
* of S-mode traps by invoking "vm_trap()". This function takes care
* of clearing the error.
Expand All @@ -37,9 +37,9 @@ typedef enum {
* Once the emulator is set up, execute the emulation loop by calling
* "vm_step()" repeatedly. Each call attempts to execute a single instruction.
*
* If the execution completes successfully, the "vm->error" field will be set
* If the execution completes successfully, the "_zp_vm_error" field will be set
* to ERR_NONE. However, if an error occurs during execution, the emulator will
* halt and the "vm->error" field will provide information about the error. It
* halt and the "_zp_vm_error" field will provide information about the error. It
* is important to handle the emulation error before calling "vm_step()" again;
* otherwise, it will not execute any instructions. The possible errors are
* described above for reference.
Expand All @@ -53,23 +53,23 @@ struct __vm_internal {
uint32_t lr_reservation;

/* Assumed to contain an aligned address at all times */
uint32_t pc;
//uint32_t pc;

/* Address of last instruction that began execution */
uint32_t current_pc;
//uint32_t current_pc;

/* 'instructions executed' 64-bit counter serves as a real-time clock,
* instruction-retired counter, and cycle counter. It is currently
* utilized in these capacities and should not be modified between logical
* resets.
*/
uint32_t insn_count, insn_count_hi;
//uint32_t insn_count, insn_count_hi;

/* Instruction execution state must be set to "NONE" for instruction
* execution to continue. If the state is not "NONE," the vm_step()
* function will exit.
*/
vm_error_t error;
//vm_error_t error;

/* If the error value is ERR_EXCEPTION, the specified values will be used
* for the scause and stval registers if they are turned into a trap.
Expand Down Expand Up @@ -98,7 +98,7 @@ struct __vm_internal {

void *priv; /**< environment supplied */

/* Memory access sets the vm->error to indicate failure. On successful
/* Memory access sets the _zp_vm_error to indicate failure. On successful
* access, it reads or writes the specified "value".
*/
void (*mem_fetch)(vm_t *vm, uint32_t addr, uint32_t *value);
Expand All @@ -109,18 +109,24 @@ struct __vm_internal {
/* Emulate the next instruction. This is a no-op if the error is already set. */
void vm_step(vm_t *vm);

/* Raise a RISC-V exception. This is equivalent to setting vm->error to
/* Raise a RISC-V exception. This is equivalent to setting _zp_vm_error to
* ERR_EXCEPTION and setting the accompanying fields. It is provided as
* a function for convenience and to prevent mistakes such as forgetting to
* set a field.
*/
void vm_set_exception(vm_t *vm, uint32_t cause, uint32_t val);

/* Delegate the currently set exception to S-mode as a trap. This function does
* not check if vm->error is EXC_EXCEPTION; it assumes that "exc_cause" and
* "exc_val" are correctly set. It sets vm->error to ERR_NONE.
* not check if _zp_vm_error is EXC_EXCEPTION; it assumes that "exc_cause" and
* "exc_val" are correctly set. It sets _zp_vm_error to ERR_NONE.
*/
void vm_trap(vm_t *vm);

/* Return a readable description for a RISC-V exception cause */
void vm_error_report(const vm_t *vm);

extern vm_error_t _zp_vm_error;
extern uint32_t _zp_vm_current_pc;
extern uint32_t _zp_vm_pc;
extern uint32_t _zp_vm_insn_count;
extern uint32_t _zp_vm_insn_count_hi;
2 changes: 1 addition & 1 deletion uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ static void login_stop(uint8_t value) {
ptr++;
} else ptr = login_stop_test;
if (!*ptr) {
printf("\n\nVM RISCV insn count: %lu\n", (long unsigned)(vm.insn_count));
printf("\n\nVM RISCV insn count: %lu\n", (long unsigned)(_zp_vm_insn_count));
#if C64
void (*reset_vect)() = (void*)0xfce2;
reset_vect();
Expand Down

0 comments on commit 60151e4

Please sign in to comment.