自作CPUでのCLINTの実装をやりたくて、仕様を調査している。
テストケースを動かしてみたくて、いくつか調査していた。
とりあえずこちらのテストケースを移植してみることにした。かなりの数のincludeファイルが必要で、必要な部分だけ切り出している。
CLINTのテストパタンでは、タイマーの設定として以下のようなコードとなっていた。
/* enable timer interrupts */ SET_TIMER_INTERVAL_MS(DEMO_TIMER_INTERVAL); interrupt_timer_enable();
SET_TIMER_INTERVAL_MS()
では、MTIMECMPを設定して次にタイマ割込みが鳥がするタイミングを設定している。
#define NUM_TICKS_ONE_S RTC_FREQ // it takes this many ticks of mtime for 1s to elapse #define NUM_TICKS_ONE_MS (RTC_FREQ/1000) // it takes this many ticks of mtime for 1ms to elapse #define DEMO_TIMER_INTERVAL 50000 // 5s timer interval #define SET_TIMER_INTERVAL_MS(ms_ticks) write_dword(MTIMECMP_BASE_ADDR(read_csr(mhartid)), (read_dword(MTIME_BASE_ADDR) + (ms_ticks * NUM_TICKS_ONE_MS)))
次に、MIEを設定してローカルのマシンモードタイマ割込みを有効化している。
void interrupt_timer_enable (void) { uintptr_t m; __asm__ volatile ("csrrs %0, mie, %1" : "=r"(m) : "r"(METAL_LOCAL_INTERRUPT_TMR)); }
これにより、Spikeシミュレーションでタイマ割込みが動作するようになった。
spike --isa=rv64imafdc test.elf Waiting for 5s Timer interrupt to fire... Timer Handler! Interrupt ID: 7, Count: 1 Timer Handler! Interrupt ID: 7, Count: 2 Timer Handler! Interrupt ID: 7, Count: 3 Timer Handler! Interrupt ID: 7, Count: 4