Bennett/Requirements

From Engineering Wiki
Jump to navigation Jump to search

Base Requirements

  • Multiplatform (Linux/Windows. Mac if possible, but has serious challenges) - use C++/Qt
  • Needs to support different different architectures: ARM, RISC-V, [others]
    • Needs to be configurable to 8, 12, 16, 24, 32, or 64 bit architecture
    • Needs to support different memory models, different register configurations, etc
    • Needs be able to work with simulators, or to communicate with a lab board
  • Display of CPU registers (which registers are available will depend on architecture)
  • Display of Status Flags (which flags are available will depend on architecture)
  • Memory view, with optional disassembly.
    • View should be configurable to show memory in different ways: single word, multiple words, ascii characters, disassembly (word size and disassembly will depend on architecture) and if an address matches the value in a register, the register name should be highlighted next to that address.
  • Multiple memory views need to be available, and individually configurable.
  • Breakpoints (stop on PC reaching memory address)
  • Watchpoint (stop on value at address being changed/set to value)
  • CPU controls: step [single, multiple], run, halt, reset - is continue just another form of 'run', is 'run' just unconstrained 'step'?
  • Needs to be extensible to support different simulated memory-mapped peripherals. Peripherals separate from architecture?
  • avoid using linux-specific mechanisms for IPC: sockets instead of pipes, for example. Dynamic loading of extensions will need thought (QLibrary system in Qt provides portable option here).

Extras

  • Compilers/assemblers for target architectures
    • How much needs to be scratch-written? Can anything be done off-the-shelf?

Design thoughts

Top-level architecture

These are general thoughts about the design, expect these to changed/be refined as things progress.

  • First, and most important concept: the design of the system is split so that there is a 'monitor core' and a number of 'system modules', with a controlled interface between the two.
    • The core handles module discovery, module selection and loading, and the behaviour of the common monitor UI.
    • System modules contain AND FULLY ENCAPSULATE individual simulators or hardware interfaces.
    • System modules should expose a set of 'capabilities' that describe the configuration of UI elements in the core.
    • The core should have absolutely no system-specific logic inside it: it should be as completely architecture and implementation agnostic as possible. It should be just a user interface that is capable of enabling/disabling/configuring the interface elements presented to the user based on the selected system module capabilities [NOTE: Means we need to decide on an appropriate superset of possible elements that may be needed for each interface element]
    • The core needs to provide a mechanism whereby system modules can register UI extensions. These allow specific UI elements or windows implemented in the system module to be shown to the user. For example, a simulator system module may provide a separate console output window, or a simulated 'screen' and keyboard. Note again: everything about such extensions - from UI definition to callbacks - should happen inside the module, all the core should care about is providing a way to register/add the UI elements!
  • endianness is a problem. All current and future planned architectures are little-endian, but if the system can be made endian-agnostic, if might have wider application.

Interface Elements

The two key features a monitor needs to provide are CPU view and control, and memory view and control. Below are summaries of the interface elements and features needed to provide CPU and memory view and control, followed by additional elements the rest of the monitor should support.

Memory

The memory view and control should provide:

  • Multiple independently configurable memory views (with pop in/ pop out to separate windows?)
  • Means to select which memory to show if there are multiple memories (system module capabilities should give names and address ranges).
  • Memory address display.
  • A means to set the current address shown in the memory view.
  • Word size is determined by the capabilities information from the system module.
  • A way to configure the number of words shown per line in the memory display (note that having more than one word per line will mean hiding disassembly/source views).
  • Optional indication of whether a CPU register contains a current address.
    • Allow the user to 'lock' the memory display to a register address and update the contents of the memory view as the address in the register changes. Default to PC following, but allow other register following.
  • Memory contents display: hex, ascii equivalent, disassembly/source view.
  • Set the value stored in memory if allowed.
  • Show breakpoint locations, allow set/clear.
  • Show watchpoint locations, allow set/clear.

Notes:

  • the memory view window logic should not include code to attempt disassembly!
  • Things that can be handled by the memory view code in the core:
    • hex display of memory contents (simple conversion from bytes, number of bytes depends on word size).
    • ascii equivalent of memory contents (simple conversion from bytes, number of bytes depends on word size).
    • metadata display, if appropriate. This is a display of data provided by the system module for that address. The memory view shouldn't care what this is, just show it.
    • display of breakpoints/watchpoints.
  • Data from the system module should contain the word data as bytes (Endianness issues!)
  • Data from the system module should contain metadata to show for an address. This is typically either the disassembly or source for that address.
  • Data from the system module should include whether an address has a watchpoint or breakpoint set on it.
  • Setting the value at an address in the memory view should tell the system module that the value has been updated. The system module should update its memory, and send back revised data to show in the memory view. The monitor core should not assume it has been set successfully until the system module says so.
  • setting/clearing breakpoints and watchpoints is like setting memory: tell the system module that the action has happened, system module sends back revised memory data with the setting updated. Monitor should not assume breakpoint/watchpoint has been set or cleared until the system module says. Note that system modules may have a limit to the number of breakpoints or watchpoints supported, core should determine this from the capabilities and adjust the UI as needed.

Thoughts:

  • Endianness is a real problem when displaying data in memory. For example, take the ARM instruction ADD R0,R0,#&5 at address 0x00000014. As a word this could be shown as
   00000014    E2800005

But as individual bytes that is

     Offset   00  01  02  03
   00000014   05  00  80  E2  
  • How complex does breakpoint and watchpoint handling need to be? KMD provides a fairly convoluted breakpoint system (described here) that allows for address masks and fancy operations to break on certain instructions or registers. Is this level of complexity needed at all? Watchpoints could conceivably potentially support breaking on read or write or both, and possibly breaking on certain values being set - but again, is that level needed?

CPU

The CPU view should provide:

  • Potentially multiple banks of registers (needs to be specified by system module capabilities).
  • Multiple registers per bank (again set by capabilities).
  • Register display should give register name, hex value, and optional ascii equivalent.
  • Do we need to treat the Status Register/CCR/CPSR/SPSR specially and provide a decoded flags field? Komodo and Perentie both do this.
  • need to be able to set values in the registers. As with memory, should be done by telling the system module to set register X in bank Y to a value, and then updating based on the value returned from the system module.
  • Support making registers read-only and displaying them in a way that makes it clear they can not be changed by the UI.
  • control buttons for the processor:
    • step (possibly with multi-step counter) if the system module supports it. Multi-step should be done inside the core, as it's just repeatedly calling single step in the system module.
    • run/continue
    • halt
    • reset

Notes:

  • The list of register banks and registers in each bank should be given to the core by the system module. The core should make no assumption other than that there is one or more banks of registers, with one or more registers in it (MU0 just has one bank with PC, Accumulator, and a status register, but more complex processors will have more registers in more banks)
  • Core needs to have a way to ask the system module to tell it what values are stored in each register, and which bank should be considered active at a given time.
  • If a decoded status register display is needed, the system module needs to tell the core
    • how many status registers there are
    • what possible flags there are in the status
    • which flags are set or cleared in each register - the core should not attempt to decode the flags itself, the system module should do the decode and give the core a list of flags and their states!
  • Do all system modules provide all controls? Possibly a control module might not support single stepping, so that may need to be part of the capabilities.
  • Komodo provides a "walk" feature - essentially a step function that does X steps, pauses for a configurable time, does another X steps and so on until halted. Do we want that?

Other interface elements

  • A breakpoints window listing all defined breakpoints, allow for easy definition/removal. If the system module does not support breakpoints, the option to open this should be disabled.
  • A watchpoint window listing all defined watchpoints. If the system module does not support watchpoints, the option to open this should be disabled.
  • As noted above, the core must provide a mechanism to allow system modules to show their own interface elements.
  • Need a way for system modules to show error dialogs via the core. Trigger dialog via event added to the core event queue by the module?
  • Does the core need a console window to output log information into? No - log to log files.

Interface between core and system modules

System modules need to implement an interface to allow the core to:

  • Retrieve the capabilities of the system module.
    • returned value should be an object containing memory descriptions (ideally a list of memories, which may just be one entry), register and bank descriptions, whether single stepping is supported, whether breakpoints and watchpoints are supported (and if so, if there are limits on how many can be set).
    • returned value should also indicate if the system module is usable - for example, if external hardware is expected, is it present?
  • Determine the state of the system module and its CPU - is it alive, is it stopped or running, etc?
  • Request the value in memory at a given address, and the metadata associated with that memory (registers pointing to it, disassembly, source).
    • Potentially this should be a way to request data for a block of addresses, for efficiency, and get back a list of memory data objects.
  • Request the contents of the registers.
    • Result should contain the values stored in the registers, for each bank of register, and the decoded status flags to be shown in the UI.
  • Set the value in memory at a given address.
    • Result should be essentially the same as for requesting a value and flag indicating success or failure.
  • Set the value in a register, or set/clear a status flag.
    • Again, result should be the same as for requesting the contents of the register, and a flag indicating success/failure.
  • Ask the system module to single step the processor (if supported).
  • Ask the system module to run the processor until halted (by breakpoint, watchpoint, or halt instruction of some kind).
  • Ask the system module to halt the processor.
  • Tell the system module to load a specific file - this should be the ELF/KMD file to load. System module may reject the load if it doesn't understand the file.

The core needs to provide a way for the system module to tell it that an event has happened - this will need to be able to include data (for example, error message information). Is this possible?

Authors

  • gravatar Mbasscp2 [userbureaucrateditorinterface-adminsysopPHRhYmxlIGNsYXNzPSJ0d3BvcHVwIj48dHI+PHRkIGNsYXNzPSJ0d3BvcHVwLWVudHJ5dGl0bGUiPkdyb3Vwczo8L3RkPjx0ZD51c2VyPGJyIC8+YnVyZWF1Y3JhdDxiciAvPmVkaXRvcjxiciAvPmludGVyZmFjZS1hZG1pbjxiciAvPnN5c29wPGJyIC8+PC90ZD48L3RyPjwvdGFibGU+]