Pseudo-reflection

I’ve implemented what I call “pseudo-reflection” in Nonpareil. Each processor architecture has a unique C structure defined which represents the architecturally visible register state of a simulated processor, and in order for general-purpose state save/restore and debugging access to be possible, the GUI thread needs to be able to ask the simulator thread what fields (registers) exist in the structure, their characteristics (name, element size, array bounds), and function calls to read and write those registers.

If I was writing this in Java, Smalltalk, or Lisp, I could use a native reflection API provided by the language to get that information. In C and C++ there is no equivalent, although there do exist some incredibly kludgy hacks to do it in C++.

Anyhow, fundamentally all that is needed is to declare an array of “meta structures”: structures that define the characteristics of the fields of the structures of interest. I’ve now done almost completely for the Nut (HP-41C) architecture, and for a few registers of the Classic and Woodstock architectures. I’ve implemented the API that the simulator thread will use: sim_get_register_info(), sim_read_register(), and sim_write_register().

sim_get_register_info() takes a numeric index (from 0 up) and returns a pointer to a substructure containing public information about a register. Since the data is static, it can execute in any thread, and will generally execute in the GUI thread.

sim_read_register() and sim_write_register() are contending for access to the registers with the simulation thread, so to get coherenet reads and writes, there needs to be some mutual exclcusion. This could be a lock per register or a big lock for the whole structure, but either way, it would require a *very* large number of code sequences in the simulator thread to acquire and release locks, which is not a good idea. So instead, these functions send a request through the async message queue to tell the simulator thread that the GUI (or debugger) thread wants to read or write a register, and the work is done in the simulator thread. This is how a lot of other simulator interface functions already work.

The next steps will be to attach the XML state save/restore code to this API, and to build a register display window that uses it as well.

This entry was posted in Calculators, Nonpareil. Bookmark the permalink.

Leave a Reply