A CEF component is a software analogy to the hardware components of a computer, such as the CPU, memory, IO devices, and buses. A CEF component serves up a standard interface that allows the various devices to be connected in either a dynamic or static way (or some combination thereof). The CEF application marshalls the various components, initializing instances of them and connecting the instances to each other to configure an emulated computer environment. Components are described in greater detail in the section titled "Components".
There are two relationships that components have with each other: connections and ownership. A connection indicates an emulated connection between two components through which data is transferred, but implies no hierarchy or ownership. An ownership relationship indicates that one component "owns" another. An owner component (hereinafter referred to as the parent component) creates its owned component (hereinafter referred to as the child component), terminates it, and manages connections to it. For instance, a bus and a memory component are connected, but a motherboard owns a CPU.
Data transfer size
All data transfers between components are byte-aligned. This refers to the actual CEF architecture and has no effect on the emulation. A component which implements a word size not exactly equal to a multiple of 8 bits will transfer data using the number of bytes necessary to contain all of the bits, with the extra bits being unused and undefined. For instance, a CPU with a word size of 36 bits would transfer data in 5-byte quantities with the uppermost 4 bits of the last byte ignored. From an emulation standpoint, the transfer is 36 bits, but the actual implementation code uses bytes for consistency.
Address Space is a concept that is supported by CEF, but not required. The idea is that a component may support several address "spaces", each of which can be accessed via a 64-bit integer value. Space 0 is the default. All other address spaces are optional and defined by the component. For instance, a CPU may support both a Code segment and a Data segment - each with the same range of addresses. Both segments represent different address spaces. This is used in breakpoints, profiling, and other cases where it is necessary to distinguish between the different spaces.
Signals and States
Signals are inputs and outputs that are unique to a specific component implementation. For instance, an Interrupt signal on a CPU. Signals for a component have a textual name, an integer index, a state (true for High, false for Low), and an indication of whether or not the signal is active low. When signals change, a notice is sent to the UI, which passes it on to any component which has requested to be notified of signal changes.
States are flags indicating the internal state of a component. States have textual names, an integer index, and a state (true or false). Like Signals, State changes are only reported to the UI. Unlike Signals, State changes are not passed to other components by the UI. Examples of states are "Fetch", "Handling Interrupt", and "Priority".
All component providers (eg DLLs) provide three API functions. The API definition is:
This function returns a UEH facility code for the component class provided by Make_Instance.
pointer Make_Instance( integer Serial_Number, TUI_Interface* UI )
Make_Instance is responsible for creating an instance of the component and associating the UI Interface with the component. This instance is an object which is a descendant of the TComponent class. Serial_Number is a numeric value which is accessible via the Tcomponent's Serial_Number method. This can be used for any purpose desired and need not be unique.
Returns the version of the CEF specification that the API adheres to. This is the major.minor version times 10. For instance, a value of 20 indicates version 2.0.
Request information about the component without actually constructing an instance of it.
6.1 TComponent referenec