Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RISC-V Co Pro: Pass elapsed_us into emulator so that RISC-V timer interrupts work #198

Closed
hoglet67 opened this issue Sep 19, 2023 · 0 comments

Comments

@hoglet67
Copy link
Owner

hoglet67 commented Sep 19, 2023

Currently the emulator is stepped with this call:

      MiniRV32IMAStep(
                      riscv_state,   // struct MiniRV32IMAState * state
                      memory,        // uint8_t * image
                      0,             // uint32_t vProcAddress
                      0,             // uint32_t elapsedUs
                      1              // int count
                      );

elapsedUs is always 0.

This means the timer CSR is never updated:

   uint32_t new_timer = CSR( timerl ) + elapsedUs;
   if( new_timer < CSR( timerl ) ) CSR( timerh )++;
   CSR( timerl ) = new_timer;

So it's not possible to use RISC-V timer interrupts.

What's needed here is to somehow map the arm cycle counter register (CCNT) which increments at the ARM clock rate into elapsed_us increments.

Something like:

static inline uint32_t get_arm_cycle_count (void)
{
  uint32_t value;
  // Read CCNT Register
  asm volatile ("MRC p15, 0, %0, c9, c13, 0\t\n": "=r"(value));  
  return value;
}

Then in the main loop of the RISC-V emulator:

// ARM clock ticks in 1us
uint32_t arm_cycles_per_us = get_clock_rates(ARM_CLK_ID)->rate / 1000000,

// Last arm cycle count
uint32_t last_arm_cycle_count = get_arm_cycle_count(); 

while(1) { // main emulator loop

      uint32_t arm_cycle_count = get_arm_cycle_count();
      uint32_t elapsed_cycles = last_arm_cycle_count - arm_cycle_count;
      uint32_t elapsed_us = 0;
      if (elapsed_cycles >= arm_cycles_per_us) {
          elapsed_us = elapsed_cycles / arm_cycles_per_us;
          last_arm_cycle_count += elapsed_us * arm_cycles_per_us;
      }
      MiniRV32IMAStep(
                      riscv_state,   // struct MiniRV32IMAState * state
                      memory,        // uint8_t * image
                      0,             // uint32_t vProcAddress
                      elapsed_us,     // uint32_t elapsedUs
                      1              // int count
                      );

}

I think the above pattern should prevent rounding errors accumulating, though there may be a simpler way!

hoglet67 added a commit that referenced this issue Sep 21, 2023
Change-Id: I19f2361692a841af08540f771360f9f03f41bb5c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant