# GXemul: Description of the framework

Back to the index.

- Introduction
- Components
- Machine templates

### Introduction:

Starting with GXemul 0.6.x, a completely redesigned framework is being worked on, compared to the 0.4.x series. The emulator thus contains two completely different frameworks. This chapter of the documentation describes the core concepts of the new framework. The framework is still being designed and implemented, so what you are reading can be considered an early draft, or a work-in-progress.

Almost all of the emulation modes in GXemul are implemented using the earlier (pre-0.6) framework, but newly implemented emulation modes may use the new framework instead.

### Components:

The most important concept in the new framework is that of the component. A component can have sub-components (children) and a parent, so the components make up a configuration tree:

Component classes are registered in a component registry.

Each component in the emulation setup has a path, e.g. `root.machine1.mainbus0.cpu0` for the CPU in the right-most machine in the example above. Often, shorter paths can be used, such as `machine1` instead of `root.machine1`, if there is no ambiguity.

Each component has state, which is a collection of variables. For e.g. a CPU component, the state is usually a set of registers. Each component also has a set of methods which can be executed. A CPU may disassemble instructions using its unassemble method:

    GXemul> root
      root
      \-- machine0  [testm88k]
          \-- mainbus0
              |-- cpu0  (88100, 50 MHz)
              |-- ram0  (32 MB at offset 0)
              |-- fb_videoram0  (15 MB at offset 0x12000000)
              \-- rom0  (4 MB at offset 0xff800000)

      accuracy = cycle
      step     = 0
    GXemul> cpu0.unassemble
    <_f>
    0x12b8 <- 67ff0020   subu    r31,r31,0x20
    0x12bc    27df0010   st      r30,r31,0x10
    0x12c0    63df0010   addu    r30,r31,0x10
    0x12c4    58400320   or      r2,r0,0x320
    0x12c8    58600258   or      r3,r0,0x258
    0x12cc    243f0014   st      r1,r31,0x14
    0x12d0    231f0008   st.d    r24,r31,0x8
    0x12d4    cfffffe7   bsr.n   0x1270          ; <_change_resolution>
    0x12d8    f6c0201f   st.d    r22,r0,r31
    0x12dc    cbffff89   bsr     0x1100          ; <_my_random>
    0x12e0    f6c05802   or      r22,r0,r2
    ...

When single-stepping, all state change is displayed. (In the old framework, it was up to individual device/component implementations to print debug messages.)

    GXemul> step
    step 0: cpu0: <_f>
                  0x12b8    67ff0020   subu   r31,r31,0x20
            => cpu0.pc: 0x12b8 -> 0x12bc
            => cpu0.r31: 0xff0 -> 0xfd0
    GXemul>
    step 1: cpu0: 0x12bc    27df0010   st   r30,r31,0x10
            => cpu0.pc: 0x12bc -> 0x12c0
    GXemul>

The example above may not be that interesting, but imagine that the CPU reads from a device which has a zero-on-read status register. Then the output may look something like this: (this is a made-up example, for now)

    GXemul> step
    step 2: cpu0: 0xffffffff800101f4    12345678   lw   t3,256(a1)
            => cpu0.pc: 0xffffffff800101f4 -> 0xffffffff800101f8
            => cpu0.t3: 0 -> 0x2200
            => intcontroller.status: 0x2200 -> 0
    GXemul>

Components that have a frequency are executed in steps. Those that do not have a frequency only do things if triggered by some other means (i.e. another component). The components' relative frequencies determine how many steps they will run at a time. For example, if we have component A running at 100 MHz, and component B running at 1 MHz, then in 100 steps A will be executing 100 cycles and B only 1. The GXemul framework makes sure that the exact sequence of cycles is the same nomatter if the user is single-stepping, or running the simulation continuously.

The frequency mentioned above does not have anything at all to do with how fast a particular host executes the simulation. The frequencies are only relative to each other.

Is the new framework cycle-accurate? Both yes and no. The framework itself aims to be step accurate, but it is up to the implementation of individual components to also be cycle accurate. For example, the CPU components that are available out-of-the-box in GXemul do not try to simulate out-of-order execution, or pipe-line stalls, or other effects that happen in a real processor, so even though the aim is that the implementation should be cycle accurate, it does not simulate any existing real-world processor in a cycle-accurate manner.

Is it theoretically possible to implement pipe-lined and/or out-of-order CPU models for GXemul's new framework? Maybe. But that has not been done.

Note that the component framework described on this page should not be confused with the dyntrans mechanism (sometimes referred to as "the dyntrans framework"). The dyntrans framework is a helper mechanism (or, to use C++ terminology, a base class) for implementing specific CPUs.

### Machine templates:

Although the framework is generic enough to simulate/emulate many kinds of components, the focus is on emulating components found in electronic computers, such as processors, RAM, caches, graphics cards, etc. In most cases, these components are naturally contained in a machine.

Machines are registered in a machine registry. The end-user can list the available machines in the registry by running `gxemul -H` (or by reading the documentation built by `make documentation`).

In the older framework, machines were a special type of entity in the emulator, which held one or more CPUs of a particular architecture, e.g. MIPS. In fact, the entire machine was of that architecture. The machine also had hardcoded RAM. While this worked well, it was not generic enough to support some cases that occur in the real world:

- Processors of different architectures in the same machine. An example of this is the Dreamcast, which has an SH4 main CPU, and an ARM CPU as a sound processor. Other examples could be GPUs in modern workstations being considered as CPUs.
- Hardcoded RAM required hacks for those architectures that do not have RAM at offset 0, for example some SGI machines, or the Dreamcast.

The 0.6.0 framework, however, has a somewhat generalized view of what a machine is. Machines are simply templates for how components are configured. When adding such a template machine to the configuration tree, the result is a complete tree of components:

    	GXemul> add testm88k
    	GXemul> root
    	  root
    	  \-- machine0  [testm88k]
    	      \-- mainbus0
    	          |-- cpu0  (88100, 50 MHz)
    	          |-- ram0  (32 MB at offset 0)
    	          |-- fb_videoram0  (15 MB at offset 0x12000000)
    	          \-- rom0  (4 MB at offset 0xff800000)

Here, a `testm88k` machine template was added (to the `root` component). Adding something without specifying where to add it always assumes that the `root` component is the target. The name of the machine in the component tree is `root.machine0`. The tree dump shows that it was created using the `testm88k` template.

To make it easier to start a new emulation from the command line (and to be more or less backward compatible with pre-0.6.x command line syntax), the `-e` option can be used to start an emulation based on a template machine:

    	$ ./gxemul -V -e testm88k
    	GXemul (unknown version)      Copyright (C) 2003-2019  Anders Gavare

    	  mainbus0
    	  |-- cpu0  (88100, 50 MHz)
    	  |-- ram0  (32 MB at offset 0)
    	  |-- fb_videoram0  (15 MB at offset 0x12000000)
    	  \-- rom0  (4 MB at offset 0xff800000)

    	GXemul>

(When starting a single emulated machine from the command line, only the emulated machine is shown, not the entire tree from the `root` node.)

The same machine configuration can be set up by hand as well:

    	GXemul> add machine root
    	GXemul> add mainbus machine0
    	GXemul> add ram mainbus0
    	GXemul> ram0.memoryMappedSize = 0x2000000
    	GXemul> add m88k_cpu mainbus0
    	GXemul> root
    	  root
    	  \-- machine0
    	      \-- mainbus0
    	          |-- ram0  (32 MB at offset 0)
    	          \-- cpu0  (88100, 50 MHz)

(Omitting `rom0` and `fb_videoram0` for brevity.)