Skip to content

Commit f00d40c

Browse files
committed
Handle System Timer with mtimecmp
1 parent 29e5c96 commit f00d40c

File tree

2 files changed

+38
-10
lines changed

2 files changed

+38
-10
lines changed

riscv_cpu.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@
3333
#include "iomem.h"
3434
#include "riscv_cpu.h"
3535

36-
// #define _info(...) {} ////
37-
#define _info printf ////
36+
#define _info(...) {} ////
37+
// #define _info printf ////
3838

3939
#ifndef MAX_XLEN
4040
#error MAX_XLEN must be defined
@@ -58,6 +58,7 @@ extern uint64_t ecall_addr;
5858
extern uint64_t rdtime_addr;
5959
extern uint64_t dcache_iall_addr;
6060
extern uint64_t sync_s_addr;
61+
extern uint64_t real_time;
6162

6263
#if FLEN > 0
6364
#include "softfp.h"
@@ -1173,12 +1174,19 @@ static void raise_exception2(RISCVCPUState *s, uint32_t cause,
11731174
_info(" reg %s=%p\n", reg_name[10], s->reg[10]); //// A0 is X10 (parm0)
11741175
riscv_cpu_reset_mip(s, MIP_STIP);
11751176

1177+
// If parm0 is not -1, set the System Timer (timecmp)
1178+
uint64_t timecmp = s->reg[10]; // A0 is X10 (parm0)
1179+
if (timecmp != (uint64_t) -1) {
1180+
void set_timecmp(void *machine0, uint64_t timecmp);
1181+
set_timecmp(NULL, timecmp);
1182+
}
11761183
} else if (s->pc == rdtime_addr) {
11771184
// For RDTIME: Return the time
11781185
// https://five-embeddev.com/riscv-isa-manual/latest/counters.html#zicntr-standard-extension-for-base-counters-and-timers
11791186
_info("Get Time\n");
1180-
static uint64_t t = 0;
1181-
s->reg[10] = t++; // Not too much or usleep will hang
1187+
// static uint64_t t = 0;
1188+
// s->reg[10] = t++; // Not too much or usleep will hang
1189+
s->reg[10] = real_time;
11821190
_info(" Return reg %s=%p\n", reg_name[10], s->reg[10]); //// A0 is X10
11831191
}
11841192

riscv_machine.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,14 @@ typedef struct RISCVMachine {
8383
#define RTC_FREQ_DIV 16 /* arbitrary, relative to CPU freq to have a
8484
10 MHz frequency */
8585

86+
void set_timecmp(RISCVMachine *machine0, uint64_t timecmp);
87+
void print_console(RISCVMachine *machine0, const char *buf, int len);
88+
8689
uint64_t ecall_addr = 0;
8790
uint64_t rdtime_addr = 0;
8891
uint64_t dcache_iall_addr = 0;
8992
uint64_t sync_s_addr = 0;
93+
uint64_t real_time = 0;
9094

9195
static uint64_t rtc_get_real_time(RISCVMachine *s)
9296
{
@@ -1042,7 +1046,6 @@ static VirtMachine *riscv_machine_init(const VirtMachineParams *p)
10421046
if (p->console) {
10431047
//// Begin Test: Save the Console
10441048
const char *msg = "TinyEMU Emulator for Ox64 BL808 RISC-V SBC\r\n";
1045-
void print_console(RISCVMachine *machine0, const char *buf, int len);
10461049
print_console(s, msg, strlen(msg));
10471050
//// End Test
10481051
vbus->irq = &s->plic_irq[irq_num];
@@ -1131,6 +1134,7 @@ static VirtMachine *riscv_machine_init(const VirtMachineParams *p)
11311134
p->cmdline,
11321135
p->files[VM_FILE_INITRD].buf, p->files[VM_FILE_INITRD].len);
11331136

1137+
set_timecmp(s, 0); //// Init the System Timer
11341138
return (VirtMachine *)s;
11351139
}
11361140

@@ -1167,10 +1171,16 @@ static int riscv_machine_get_sleep_duration(VirtMachine *s1, int delay)
11671171
delay = 0;
11681172

11691173
//// Begin Test: Trigger the Supervisor-Mode Timer Interrupt
1170-
static uint64_t t = 0;
1171-
if (t++ % 100 == 0) {
1172-
riscv_cpu_set_mip(s, MIP_STIP);
1173-
} ////
1174+
real_time = rtc_get_time(m);
1175+
if (!(riscv_cpu_get_mip(s) & MIP_STIP)) {
1176+
const int64_t delay2 = m->timecmp - rtc_get_time(m);
1177+
if (delay2 <= 0) {
1178+
static uint64_t t = 0;
1179+
if (t++ % 100 == 0) {
1180+
riscv_cpu_set_mip(s, MIP_STIP);
1181+
}
1182+
}
1183+
}
11741184
//// End Test
11751185
return delay;
11761186
}
@@ -1216,7 +1226,17 @@ const VirtMachineClass riscv_machine_class = {
12161226
riscv_vm_send_key_event,
12171227
};
12181228

1219-
//// Begin Test: Print to Console
1229+
//// Begin Test
1230+
// Set Timer
1231+
void set_timecmp(RISCVMachine *machine0, uint64_t timecmp) {
1232+
static RISCVMachine *machine = NULL;
1233+
if (machine0 != NULL) { machine = machine0; return; }
1234+
if (machine == NULL) { puts("set_timecmp: machine is null"); return; }
1235+
machine->timecmp = timecmp;
1236+
printf("set_timecmp: timecmp=%p\n", timecmp);
1237+
}
1238+
1239+
// Print to Console
12201240
void print_console(RISCVMachine *machine0, const char *buf, int len) {
12211241
static RISCVMachine *machine = NULL;
12221242
if (machine0 != NULL) { machine = machine0; }

0 commit comments

Comments
 (0)