vintagepc / MK404

A functional Simulator for Prusa (Mini/Einsy) Rambo based printers
https://vintagepc.github.io/MK404/
GNU General Public License v3.0
69 stars 9 forks source link

[FEATURE] Save-states #256

Open wavexx opened 3 years ago

wavexx commented 3 years ago

Just throwing this absurd idea in here =)

It would be nice to implement save-states, with Ctrl+[index] saving the state to slot [i] and Alt+[i] to restore it (btw, this is not inspired at all by console emulators ;)).

simavr doesn't implement a way to serialize the avr structure out of the box, but you definitely played now with simavr internals quite a bit so maybe it's not completely out of reach. I guess the internal AVR state is not that hard to save, but the interface to the timers might be tricky to restore.

It doesn't even need to be persistent on disk to be useful either. My main idea was to save the current state, issue a gcode command, restore the original state, try another one to compare the result.

vintagepc commented 3 years ago

Interesting idea... though I am not sure how well this would work in practice. Part of the issue is the way SimAVR handles the callbacks. It's not impossible, but probably even more complex than PrusaSlicer undo/redo to get right ;-). There are a lot of independent stateful parts, each of which would need to be serialized correctly.

That said... GDB might natively support doing this through its snapshots feature, perhaps that's worth a try - and if it works I don't have to do anything :rofl: :

https://sourceware.org/gdb/current/onlinedocs/gdb/Checkpoint_002fRestart.html

especially considering it is in a much better position to grab the program state than we are down in the execution code.

wavexx commented 3 years ago

On Sun, Oct 04 2020, vintagepc wrote:

That said... GDB might natively support doing this through its snapshots feature, perhaps that's worth a try - and if it works I don't have to do anything :rofl: :

I somehow doubt, gdb support in simavr is pretty decent, but not ultra comprehensive :).

It doesn't support reverse execution for example, along with several forms of hw breakpoints/watchpoints (don't remember which ones right now). But at least those can be worked around with sw ones.

avr-gdb 8 in debian doesn't have "checkpoint" yet (but maybe I just need to see if gdb 9 supports avr out of the box already).

Checkpoints also probably need the same kind of support required for saved states to work in a somewhat useful way. One simple example, you'd need to restore the axis positions according to the checkpointed position.

vintagepc commented 3 years ago

Well, you wouldn't be able to use AVR-gdb, you'd need to use regular GDB on the full MK404 executable. (this wouldn't work trying to snapshot just the running AVR code).

I'd imagine the way it works is just snapshotting the entire program register and memory state - which, in theory, should work just fine. Alas, I just tried it and it doesn't work because we have multiple threads. (AVR, GUI, serial...). There's no real way to make this a single-threaded application if we want any sort of external input or UI... so there goes that idea.

wavexx commented 3 years ago

On Sun, Oct 04 2020, vintagepc wrote:

Well, you wouldn't be able to use AVR-gdb, you'd need to use regular GDB on the full MK404 executable. (this wouldn't work trying to snapshot just the running AVR code).

Uuuh ok, I didn't think of doing that ;)

threads. (AVR, GUI, serial...). There's no real way to make this a single-threaded application if we want any sort of external input or UI... so there goes that idea.

Even "plain" reverse execution has such a limited use-case scenario that I can count on my fingers the number of times I could make use of it :)

vintagepc commented 3 years ago

Fair enough - I only did think of it because I probably spend more time debugging the simulator code, whereas you use avr-gdb to debug the firmware :wink:

vintagepc commented 3 years ago

I've contemplated this a bit; I think the right (and lowest-overhead) way to do it (in addition to the SimAVR core state) is to define stream operators for the various components.

It would be session-only; I'm not going to deal with storing this to file and reading back an arbitrary version in the future when the stored contents might no longer represent the contents of the fake device, or storing the state of all the callbacks and connections.

Then we can just << the object into a temporary buffer, and >> it when we want to restore.

I have no idea how well this will work in practice, but I suppose I'll take a crack at it.