-
Notifications
You must be signed in to change notification settings - Fork 203
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
Processor doesn't park itself in a know good state prior to going to sleep #744
Comments
I never thought about using the sleep signal for some clock gating... but I like the idea! How do you do the clock gating? If you turn off the CPU's clock during sleep mode then it won't be able to wake up again since the internal interrupt logic would also be shut down?! 🤔
This makes sense. I will add this "feature" to the CPU. Thanks for that!
I can see that 😅 The fetch engine (and also the execute engine) got a whole make-over resulting in a smaller size and even higher f_max. Maybe you should consider an update. 😉 |
Working on on-boarding the update, will get there :) As you said the processor doesn't have the ability to go out of sleep with no clock, but thats where the "magic" happens. Its a fundamentally simple combinatorial function that you can apply inside the cpu_control block. Something like this: The clock gating circuit can either use a library cell or just use a plain old gate function:
|
That's a really smart solution! But there is one big problem: the FIRQs are high for just a single cycle when firing. And this single cycle is to short to bring the CPU out of sleep mode and to re-enable the clock. One possible solution would be to split the CPU's clock domain into a switchable one and an always-on one (just for the the interrupt logic). However, I would like to keep all the CPU logic inside one clock domain - otherwise we would need at least two FPGA clock tiles for all the logic that might increase critical path length. However, I really like the idea to turn of the CPU clock while being in sleep mode. So I would suggest to move the "clock enable" logic outside of the CPU: disable the CPU clock when the sleep signals gets high and re-enable the clock as soon as there is a rising-edge on any of the interrupt lines (FIRQ, non-FIRQs and debug-mode entry-IRQ. |
Describe the bug
When utilizing clock gating driven be the sleep signal the processor hangs on wakeup. This is root caused to be because the fetch engine ends up hanging in the IF_PENDING state which it never exists as the response from the memory system never arrives.
In sleep state the fetch engine is holding the RE signal on the instruction bus high, which prevents non-processor bus managers from taking the bus.
To Reproduce
Implement clock gating for the riscv and peripherals as seperate controls. Have the riscv clock gate but have the memories still run. This happens in systems where the processor can go to sleep but an external port like I2C access the memories while the processor is asleep.
This will allow the memories to respond and move on, locking out the riscv fetch engine.
Expected behavior
When going to sleep the processor should park itself in a know good state from which it can safely resume.
Environment:
Additional context
As I'm still on the older version of the core I can't push the implemented fix. The fix is somewhat simple and involves touch the fetch engine and execute engine in neorv32_cpu_control.vhd.
With the provided the changes the processor safely parks itself prior to issuing sleep and safely resumes at PC+4 after going out of sleep.
Changes to the cpu_sleep indicator. We only assert sleep when the processor is in CPU_SLEEP and the fetch engine is safely parked in IF_WAIT.
Changes to the fetch engine. This ensures that IF_PENDING goes to IF_WAIT to park the fetch engine when we go to sleep. We are using the execute engine current and next state being CPU_SLEEP to prevent IF_PENDING for going back to IF_REQUEST when the next processor state is sleep.
In IF_WAIT we hang around until the processor is out of sleep.
The text was updated successfully, but these errors were encountered: