Skip to content

Commit

Permalink
Merge pull request #49 from chiangkd/master
Browse files Browse the repository at this point in the history
Replace mtime counter with realtime timer
  • Loading branch information
jserv authored Aug 1, 2024
2 parents 24f5c80 + 3cd64f3 commit 207a4d7
Show file tree
Hide file tree
Showing 10 changed files with 94 additions and 25 deletions.
9 changes: 8 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ CC ?= gcc
CFLAGS := -O2 -g -Wall -Wextra
CFLAGS += -include common.h

# clock frequency
CLOCK_FREQ ?= 65000000
DT_CFLAGS := -D CLOCK_FREQ=$(CLOCK_FREQ)
CFLAGS += $(DT_CFLAGS)

OBJS_EXTRA :=
# command line option
OPTS :=
Expand Down Expand Up @@ -42,6 +47,7 @@ all: $(BIN) minimal.dtb
OBJS := \
riscv.o \
ram.o \
utils.o \
plic.o \
uart.o \
main.o \
Expand Down Expand Up @@ -72,11 +78,12 @@ S := $E $E
SMP ?= 1
.PHONY: riscv-harts.dtsi
riscv-harts.dtsi:
$(Q)python3 scripts/gen-hart-dts.py $@ $(SMP)
$(Q)python3 scripts/gen-hart-dts.py $@ $(SMP) $(CLOCK_FREQ)

minimal.dtb: minimal.dts riscv-harts.dtsi
$(VECHO) " DTC\t$@\n"
$(Q)$(CC) -nostdinc -E -P -x assembler-with-cpp -undef \
$(DT_CFLAGS) \
$(subst ^,$S,$(filter -D^SEMU_FEATURE_%, $(subst -D$(S)SEMU_FEATURE,-D^SEMU_FEATURE,$(CFLAGS)))) $< \
| $(DTC) - > $@

Expand Down
15 changes: 9 additions & 6 deletions clint.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@

void clint_update_interrupts(hart_t *hart, clint_state_t *clint)
{
if (clint->mtime > clint->mtimecmp[hart->mhartid])
uint64_t time_delta =
clint->mtimecmp[hart->mhartid] - semu_timer_get(&hart->time);
if ((int64_t) time_delta <= 0)
hart->sip |= RV_INT_STI_BIT;
else
hart->sip &= ~RV_INT_STI_BIT;
Expand All @@ -31,7 +33,8 @@ static bool clint_reg_read(clint_state_t *clint, uint32_t addr, uint32_t *value)
}

if (addr < 0xBFFF) {
*value = clint->mtime >> (32 & -!!(addr & 0b100));
*value = (uint32_t) (semu_timer_get(&clint->mtime) >>
(32 & -!!(addr & 0b100)));
return true;
}
return false;
Expand All @@ -58,14 +61,14 @@ static bool clint_reg_write(clint_state_t *clint, uint32_t addr, uint32_t value)
}

if (addr < 0xBFFF) {
int32_t upper = clint->mtime >> 32;
int32_t lowwer = clint->mtime;
int32_t upper = clint->mtime.begin >> 32;
int32_t lower = clint->mtime.begin;
if (addr & 0b100)
upper = value;
else
lowwer = value;
lower = value;

clint->mtime = (uint64_t) upper << 32 | lowwer;
semu_timer_rebase(&clint->mtime, (uint64_t) upper << 32 | lower);
return true;
}
return false;
Expand Down
2 changes: 1 addition & 1 deletion device.h
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ uint32_t *virtio_blk_init(virtio_blk_state_t *vblk, char *disk_file);
typedef struct {
uint32_t msip[4096];
uint64_t mtimecmp[4095];
uint64_t mtime;
semu_timer_t mtime;
} clint_state_t;

void clint_update_interrupts(hart_t *vm, clint_state_t *clint);
Expand Down
10 changes: 1 addition & 9 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ static void emu_update_timer_interrupt(hart_t *hart)
clint_update_interrupts(hart, &data->clint);
}

static void emu_update_global_timer(vm_t *vm)
{
emu_state_t *data = PRIV(vm->hart[0]);
data->clint.mtime++;
return;
}

static void mem_load(hart_t *hart,
uint32_t addr,
uint8_t width,
Expand Down Expand Up @@ -523,6 +516,7 @@ static int semu_start(int argc, char **argv)
/* Initialize the emulator */
emu_state_t emu;
memset(&emu, 0, sizeof(emu));
semu_timer_init(&emu.clint.mtime, CLOCK_FREQ);

/* Set up RAM */
emu.ram = mmap(NULL, RAM_SIZE, PROT_READ | PROT_WRITE,
Expand Down Expand Up @@ -591,8 +585,6 @@ static int semu_start(int argc, char **argv)
/* Emulate */
uint32_t peripheral_update_ctr = 0;
while (!emu.stopped) {
emu_update_global_timer(&vm);

for (uint32_t i = 0; i < vm.n_hart; i++) {
if (peripheral_update_ctr-- == 0) {
peripheral_update_ctr = 64;
Expand Down
2 changes: 1 addition & 1 deletion minimal.dts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <65000000>;
timebase-frequency = <CLOCK_FREQ>;
};

sram: memory@0 {
Expand Down
4 changes: 2 additions & 2 deletions riscv.c
Original file line number Diff line number Diff line change
Expand Up @@ -434,10 +434,10 @@ static void csr_read(hart_t *vm, uint16_t addr, uint32_t *value)
{
switch (addr) {
case RV_CSR_TIME:
*value = vm->time;
*value = semu_timer_get(&vm->time);
return;
case RV_CSR_TIMEH:
*value = vm->time >> 32;
*value = semu_timer_get(&vm->time) >> 32;
return;
case RV_CSR_INSTRET:
*value = vm->instret;
Expand Down
5 changes: 3 additions & 2 deletions riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#include <stdbool.h>
#include <stdint.h>

#include "utils.h"

/* ERR_EXCEPTION indicates that the instruction has raised one of the
* exceptions defined in the specification. If this flag is set, the
* additional fields "exc_cause" and "exc_val" must also be set to values
Expand Down Expand Up @@ -70,8 +72,7 @@ struct __hart_internal {
* resets.
*/
uint64_t instret;
uint64_t time;

semu_timer_t time;
/* 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.
Expand Down
7 changes: 4 additions & 3 deletions scripts/gen-hart-dts.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,12 @@ def clint_irq_format(nums):
s += f"<&cpu{i}_intc 3 &cpu{i}_intc 7>, "
return s[:-2]

def dtsi_template (cpu_list: str, plic_list, clint_list):
def dtsi_template (cpu_list: str, plic_list, clint_list, clock_freq):
return f"""/{{
cpus {{
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <65000000>;
timebase-frequency = <{clock_freq}>;
{cpu_list}
}};
Expand Down Expand Up @@ -67,6 +67,7 @@ def dtsi_template (cpu_list: str, plic_list, clint_list):

dtsi = sys.argv[1]
harts = int(sys.argv[2])
clock_freq = int(sys.argv[3])

with open(dtsi, "w") as dts:
dts.write(dtsi_template(cpu_format(harts), plic_irq_format(harts), clint_irq_format(harts)))
dts.write(dtsi_template(cpu_format(harts), plic_irq_format(harts), clint_irq_format(harts), clock_freq))
52 changes: 52 additions & 0 deletions utils.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#include <time.h>

#include "utils.h"

#if defined(__APPLE__)
#define HAVE_MACH_TIMER
#include <mach/mach_time.h>
#elif !defined(_WIN32) && !defined(_WIN64)
#define HAVE_POSIX_TIMER

/*
* Use a faster but less precise clock source because we need quick
* timestamps rather than fine-grained precision.
*/
#ifdef CLOCK_MONOTONIC_COARSE
#define CLOCKID CLOCK_MONOTONIC_COARSE
#else
#define CLOCKID CLOCK_REALTIME_COARSE
#endif
#endif

void semu_timer_init(semu_timer_t *timer, uint64_t freq)
{
timer->freq = freq;
semu_timer_rebase(timer, 0);
}

static uint64_t semu_timer_clocksource(uint64_t freq)
{
#if defined(HAVE_POSIX_TIMER)
struct timespec t;
clock_gettime(CLOCKID, &t);
return (t.tv_sec * freq) + (t.tv_nsec * freq / 1e9);
#elif defined(HAVE_MACH_TIMER)
static mach_timebase_info_data_t t;
if (mach_clk.denom == 0)
(void) mach_timebase_info(&t);
return mach_absolute_time() * freq / t.denom * t.numer;
#else
return time(0) * freq;
#endif
}

uint64_t semu_timer_get(semu_timer_t *timer)
{
return semu_timer_clocksource(timer->freq) - timer->begin;
}

void semu_timer_rebase(semu_timer_t *timer, uint64_t time)
{
timer->begin = semu_timer_clocksource(timer->freq) - time;
}
13 changes: 13 additions & 0 deletions utils.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <stdint.h>

/* TIMER */
typedef struct {
uint64_t begin;
uint64_t freq;
} semu_timer_t;

void semu_timer_init(semu_timer_t *timer, uint64_t freq);
uint64_t semu_timer_get(semu_timer_t *timer);
void semu_timer_rebase(semu_timer_t *timer, uint64_t time);

0 comments on commit 207a4d7

Please sign in to comment.