%
% $Id: internals.tex,v 1.40 2009-11-04 14:32:21 sand Exp $
% vim:tabstop=8:shiftwidth=8:textwidth=78  
%
% Copyright (C) 2002-2009 FAUmachine Team <info@faumachine.org>.
% This program is free software. You can redistribute it and/or modify it
% under the terms of the GNU General Public License, either version 2 of
% the License, or (at your option) any later version. See COPYING.
%

\documentclass[a4paper,10pt]{article}
\usepackage{listings}
\usepackage{pgf}
\parindent0pt
\parskip5pt

\title{FAUmachine Internals}
\author{FAUmachine Team
\\{\tt info@faumachine.org}}

\begin{document}
\maketitle
\tableofcontents

% ==================================================================== %
\section{Introduction}
% ==================================================================== %

This small documentation is written to give you an overview about
the internals of FAUmachine.

Due to the fact that FAUmachine is under development all the time
this documentation might be inaccurate\ldots

So, in doubt feel free to send an email to {\tt info@faumachine.org}
and ask questions! We'll be glad to help you!

% ==================================================================== %
\section{Overview}
% ==================================================================== %

FAUmachine is developed to be able to test how systems react on
hardware faults. To do this close to reality all components of the
system under test must be modeled very accurately. Likewise important
point is that the modeled system must consist of exactly the same
components (motherboard, CPU, memory, IDE disk, SCSI CD-ROM drive,
\ldots) as the real system. The system under test might even be a
workstation cluster with network cables, modem connections, serial
terminals and so on!

Therefore in FAUmachine it must be possible to build up very detailed
components and we must be able to configure the simulator with respect
to what components should be part of the simulation and what
components are not used. Components must be connected with other
components the very same way as in reality.

Standard modeling of hardware components and systems is done by
using a hardware description language. We don't use a language
like VHDL (or similar) here because of speed. Even the fastest VHDL
simulators are much too slow for our purpose. Using the FAUmachine
approach simulation is normally fast enough to use these machines in
real-time.

To be able to model each component independantly from each other
no component may have knowledge of another. They all communicate
using interconnects (''signals'') only.

So like using VHDL we have two very different types of objects:
\begin{itemize}
\item Signals
\item Components
\end{itemize}

Components are items like a CPU, a memory module, a north-bridge chip,
a motherboard, an IDE disk, or a network adapter. Items you can buy at
the local computer hardware dealer.

Signals are the interconnects that connect sockets of one component
with other sockets of other components. They describe the structure of
the virtual system.

% ==================================================================== %
\section{Examples}
% ==================================================================== %

Please note that the following examples look very simple. They're
used just to show you the internal software architecture of FAUmachine.

In FAUmachine much more sophisticated components and signals are used!

We're very confident that this approach
\begin{itemize}
\item leads to very clean code
\item makes sure that adding different types of components or signals
	is easy
\item has {\bf no} influence on simulation speed!
\end{itemize}

% -------------------------------------------------------------------- %
\subsection{Simple Example}
% -------------------------------------------------------------------- %

Simple example (Sound generator and speaker connected using a cable):
\begin{center}
\pgfimage[width=7cm]{simple}
\end{center}

To make sure that no simulation module has direct access to any other
simulation module, no module function can be called directly.
They might to be called indirectly using signals only.

The only global functions of any simulation module are the {\tt create}
and {\tt destroy} functions. These are called during startup/end of
simulation. They even might be called while simulation is in progress.
So it's possible to add/remove hardware components during run-time.

Remarks:
\begin{itemize}
\item Pointers to objects are passed as ''{\tt void *}'' to make
	sure that no component can access private elements of other
	components. The other effect is that components can be
	connected to any signal without having the signal need to
	know anything about the component. Components are just
	''objects'' of some kind.
\item Within the components the real pointer types are used. Therefore
	some casts within the components are necessary.
\end{itemize}

\pagebreak

To model the small example system in FAUmachine-style we would write
the following code:
\lstset{language=C}
\begin{lstlisting}
struct system {
	struct sig_boolean *sig_signal;

	void *comp_U1;
	void *comp_U2;
};
\end{lstlisting}

In the {\tt create} function of the system we create all necessary
signals and components:
\begin{lstlisting}
void *
system_create(const char *name)
{
    struct system *s;

    s = malloc(sizeof(*s));

    /* Create signals. */
    s->signal = sig_boolean_create("Signal");

    /* Create components and pass generics and signals. */
    s->comp_U1 = sound_generator_create("U1", 440, s->signal);
    s->comp_U2 = speaker_create("U2", s->signal);

    return s;
}
\end{lstlisting}
We pass the instance name of a component and its connected signals
when calling the component's {\tt create} function. The {\tt name}
parameter might be used for debugging for example. Not used here.

The created signals and components are destroyed again in system's
{\tt destroy} function:
\begin{lstlisting}
void *
system_destroy(void *_s)
{
    struct system *s = s;

    /* Destroy components. */
    sound_generator_destroy(s->comp_U1);
    speaker_destroy(s->comp_U2);

    /* Destroy signals. */
    sig_boolean_destroy(s->signal);

    free(s);
}
\end{lstlisting}

This works hierarchically. Any component used may itself be
modeled this way.

\pagebreak

% -------------------------------------------------------------------- %
\subsection{Simple Components}
% -------------------------------------------------------------------- %

In our example we use some very simple components modeled using
the programming language ''C''. All code should go into a file named
''{\tt sound\_generator.c}'' and the prototypes of the {\tt create} and
{\tt destroy} functions should be contained by file
''{\tt sound\_generator.h}''.

\lstset{language=C}
\begin{lstlisting}
struct sound_generator {
    unsigned int hz;
    struct sig_boolean *port_out;
    unsigned int state;
};
\end{lstlisting}

We define a function called periodically:
\begin{lstlisting}
static void
sound_generator_toggle(void *_s)
{
    struct sound_generator *s = _s;

    s->state ^= 1;
    sig_boolean_set(s->port_out, s, s->state);
    time_call_after(TIME_HZ / s->hz / 2, sound_generator_toggle, s);
}
\end{lstlisting}

The {\tt create} function might look like
\begin{lstlisting}
void *
sound_generator_create(char *name, int hz, struct sig_boolean *out)
{
    struct sound_generator *s;

    s = malloc(sizeof(*s));

    s->hz = hz;
    s->port_out = out;
    s->state = 0;

    time_call_after(TIME_HZ / s->hz / 2, sound_generator_toggle, s);

    return s;
}
\end{lstlisting}

This is the {\tt destroy} function:
\begin{lstlisting}
void
sound_generator_destroy(void *_s)
{
    struct sound_generator *s = _s;

    free(s);
}
\end{lstlisting}

\pagebreak

The speaker component will be modeled similarly:
\lstset{language=C}
\begin{lstlisting}
struct speaker {
    ...
};
\end{lstlisting}

We define a callback function called whenever the input signal changes
its value:
\begin{lstlisting}
static void
speaker_set(void *_s, unsigned int val)
{
    struct speaker *s = _s;

    /* Output value 'val' to local host's sound system... */
}
\end{lstlisting}

The {\tt create} function might look like
\begin{lstlisting}
void *
speaker_create(const char *name, struct sig_boolean *in)
{
    static const struct sig_boolean_funcs in_func = {
        .set = speaker_set,
    };
    struct speaker *s;

    s = malloc(sizeof(*s));

    sig_boolean_connect_in(in, s, &in_func);

    return s;
}
\end{lstlisting}

This is the {\tt destroy} function:
\begin{lstlisting}
void
speaker_destroy(void *_s)
{
    struct sound_generator *s = _s;

    free(s);
}
\end{lstlisting}

% -------------------------------------------------------------------- %
\subsection{Processes}
% -------------------------------------------------------------------- %

The simulation of the {\tt sound\_generator} component above is
event based. Another possiblity is to model it as a process:

\lstset{language=C}
\begin{lstlisting}
struct sound_generator {
    struct process process;
    unsigned int hz;
    struct sig_boolean *port_out;
};
\end{lstlisting}

We define a function called periodically:
\begin{lstlisting}
static void
sound_generator_run(void *_s)
{
    struct sound_generator *s = _s;
    unsigned int state;

    state = 0;
    for (;;) {
        sig_boolean_set(s->port_out, s, s->state);

        sched_delay(TIME_HZ / s->hz / 2);

        state ^= 1;
    }
    /*NOTREACHED*/
}
\end{lstlisting}

The {\tt create} function might look like
\begin{lstlisting}
void *
sound_generator_create(char *name, int hz, struct sig_boolean *out)
{
    struct sound_generator *s;

    s = malloc(sizeof(*s));

    s->hz = hz;
    s->port_out = out;

    sched_process_init(&s->process, sound_generator_run, s);

    return s;
}
\end{lstlisting}

The {\tt destroy} function is the same as in the example above.

These kind of ''processes'' are processes in the sense of co-routines.
They are started and they are executing until they call functions
like {\tt sched\_to\_scheduler} or {\tt sched\_delay}. In this
case they're stopped and other processes might run or events might
be triggered.

Such processes are much more efficient than functions triggered by
events, and components like CPUs or IDE disk/CDROM drives are much
easier to model using processes. In the example above you can see
that e.g. the variable {\tt state} becomes a standard local variable
and it is no longer a member of the {\tt sound\_generator} structure.
Access to such a variable is much faster as registers of the real
CPU might be used by the compiler.

\pagebreak

% -------------------------------------------------------------------- %
\subsection{Simple Signals}
% -------------------------------------------------------------------- %

In our tiny example we used only ''boolean'' signals. The code of these
objects look similar to the following:

The {\tt sig\_boolean\_create} and {\tt sig\_boolean\_destroy}
functions might be pretty simple:
\lstset{language=C}
\begin{lstlisting}
struct sig_boolean *
sig_boolean_create(const char *name)
{
    struct sig_boolean *b;

    b = malloc(sizeof(*b));

    b->member_count = 0;

    return b;
}
\end{lstlisting}

\begin{lstlisting}
void
sig_boolean_destroy(struct sig_boolean *b)
{
    free(b);
}
\end{lstlisting}

The {\tt sig\_boolean\_connect\_in} function registers a callback
function and a callback parameter of a component:
\begin{lstlisting}
void
sig_boolean_connect_in(
    struct sig_boolean *b,
    void *s,
    struct sig_boolean_funcs *f
)
{
    b->member[b->member_count].s = s;
    b->member[b->member_count].f = f;
    b->member_count++;
}
\end{lstlisting}

The {\tt sig\_boolean\_set} function calls {\em all} registered
{\tt set} callback functions and passes the callback parameter
registered previously:
\begin{lstlisting}
void
sig_boolean_set(struct sig_boolean *b, void *s, unsigned int val)
{
    unsigned int i;

    for (i = 0; i < b->member_count; i++) {
        (*b->member[i].f->set)(b->member[i].s, val);
    }
}
\end{lstlisting}

% ==================================================================== %
\section{Shadow Components}
% ==================================================================== %

The {\tt speaker\_set} function of the previous example might be used
to output the created sound to the user using the real systems sound
system (ALSA, ESD, ARTS, \ldots).

In FAUmachine we use a little different approach. All components
might have a GUI and/or an audio shadow component.

\begin{center}
\pgfimage[width=5cm]{shadow}
\end{center}

These shadow components have the very same input/output signals like
the component itself. The shadows are created/destroyed together with
their corresponding non-shadow component. The only purpose of these
components is to interact with the real environment. They might
do audio input/output or they might interact with the graphical
user interface.

Using this approach we have components which do the simulation and
shadow components which do the user interaction. In this example we
have a speaker component that converts the electrical input into
accustical output. (This accustical output might be the input of
a simulated ''microphone'' component!) The output is taken by the
shadow component to be made audible by the user.

A similar example would be a push-button. The push-button component
itself just translates the mechanical ''signal'' into an electrical
one. The GUI shadow component will interact with the GUI and will
receive e.g. mouse clicks. Mouse events will be translated into
mechanical ''signal'' changes.

A LED component will generate an optical ''signal'' from the
electrical signal (just forwarding the boolean value). The GUI
shadow component of the LED will then take this value and
will draw the appropriate image using the GUI interface.

FAUmachine does it this way to separate the simulation and the
graphical/audio interaction with the user. The simulation component
will be the same whatever GUI or audio subsystem is used. The
simulation environment will select the correct shadow component
depending on the GUI or audio subsystem used.

% ==================================================================== %
\section{Complex Signals and Busses}
% ==================================================================== %

% -------------------------------------------------------------------- %
\subsection{Signals}
% -------------------------------------------------------------------- %

FAUmachine knows about a set of different simple signals. ''Simple''
means that these signals have exactly one component which drives the
value of the signal. One component calls the {\tt set} function of
the signal object. This {\tt set} call is distributed to all registered
callback functions.

These signals are:
\begin{itemize}
\item boolean
\item integer
\item string
\end{itemize}

Some signals need ''resolution''. This means more than one component
might call the {\tt set} function of the signal. E.g. in a computer
system we might have more than one PCI adapter driving the very same
IRQ line. So the signal has to remember which component drives which
value and has to calculate a ''resolved'' value based on this set
of values. It might e.g. build the ''OR'' of all boolean values.
The resolved value is then distributed to all connected components.

Signals of this kind are:
\begin{itemize}
\item boolean\_or
\item std\_logic
\end{itemize}

Signals of type {\tt std\_logic} are used to model ''wired-or'' or
''wired-and'' circuits using resistors.

% -------------------------------------------------------------------- %
\subsection{Busses}
% -------------------------------------------------------------------- %

A standard PCI bus consists of very many signals. To execute one single
bus transaction (like doing an I/O-read or memory-write) many signal
changes must happen.

This is not feasable if performance is important. So FAUmachine
introduces bus signals. Using these bus signals it is possible
to call callback functions in connected modules which do the whole
bus transaction in one call.

Example:
\lstset{language=C}
\begin{lstlisting}
    sig_pci_bus_ior(bus, myself, port, byte_select, &val);
\end{lstlisting}
will do a whole I/O-read transaction on the PCI bus. It will call
all registered {\tt ior} functions of bus {\tt bus}. All connected
components check whether they are responsible to respond to I/O-reads
to the {\tt port} passed. The component in charge will use the
{\tt port} and {\tt byte\_select} parameters to do the correct access.
The return value is passed back using the address {\tt \&val} given by
the caller.

Similarly, we have for the host bus:
\begin{description}
\item [ior:] I/O read
\item [iow:] I/O write
\item [mr:] Memory read
\item [mw:] Memory write
\item [inta\_addr/inta\_data:] Interrupt acknowledge cycle
\end{description}

Similarly, we have for the PCI bus:
\begin{description}
\item [c0r:] Config space read (level 0)
\item [c0w:] Config space write (level 0)
\item [c1r:] Config space read (level 1)
\item [c1w:] Config space write (level 1)
\item [ior:] I/O read
\item [iow:] I/O write
\item [mr:] Memory read
\item [mw:] Memory write
\item [inta\_addr/inta\_data:] Interrupt acknowledge cycle
\end{description}

Similarly, we have for the ISA bus:
\begin{description}
\item [inb:] Input byte
\item [outb:] Output byte
\item [inw:] Input word
\item [outw:] Output word
\item [readb:] Read byte from memory
\item [writeb:] Write byte to memory
\item [readw:] Read word from memory
\item [writew:] Write word to memory
\item [ack:] Interrupt acknowledge cycle
\end{description}

Even the Shugart bus, SCSI bus, IDE bus, ethernet connections etc.
are modeled this way.

All FAUmachine signal sources are located in the {\tt lib} directory.
They all have a prefix of {\tt sig\_}.

% -------------------------------------------------------------------- %
\subsection{Bus Transaction Forwarding}
% -------------------------------------------------------------------- %

In reality the CPU starts bus transactions on the host bus. These go
to the north-bridge. The north-bridge decides whether to forward
these cycles to a memory module or to the PCI bus. The PCI bus
might forward this transaction to one of the PCI adapters or to the
south-bridge. The south-bridge might execute the cycles by itself
or it might forward it to the ISA bus. On the ISA bus the transaction
will be performed by any ISA adapter or by a component attached to
the bus directly (e.g. floppy controller, keyboard controller,
BIOS, ...).

As we can see transactions are forwarded, forwarded, \ldots

This will lead to an enormous overhead if implemented this way.

For this FAUmachine has introduced so called {\tt *\_info} and
{\tt *\_info\_flush} callback functions:
\begin{description}
\item[\tt info:] An {\tt info}-function might be used to get the
	pointer to a callback function registered for a specific
	I/O port. This pointer can be used once and again to call 
	I/O read and I/O write functions of a device by the CPU
	directly regardless on which bus this device was registered.
\item[\tt info\_flush:] If any device changes its own I/O address
	(e.g. during BIOS PCI configuration) it calls the
	{\tt info\_flush} function of its own bus. The bus will
	forward this call to all registered components of the bus.
	This way components which have called {\tt info} functions
	before and cached the pointers returned by these calls might
	flush their cached infos.
\end{description}

This way any I/O read or I/O write call of the CPU will result in
{\em one} {\tt info} call cascade through all busses once (slow)
and {\em many} direct calls of the corresponding device function
(fast).

{\bf This is where FAUmachine's simulation speed results from!}

Example how a CPU might use an {\tt info} bus function:
\lstset{language=C}
\begin{lstlisting}
typedef uint32_t (*inl_func_t)(void *, uint16_t);

struct cpu {
    ...
    inl_func_t inl_func[0x10000];
    void *inl_state[0x10000];
    ...
};
\end{lstlisting}

\begin{lstlisting}
uint32_t
cpu_inl(struct cpu *cpu, uint16_t port)
{
    if (! cpu->inl_func[port]) {
        sig_host_bus_ior_info(cpu->host_bus, port,
	        &cpu->inl_func[port], &cpu->inl_state[port]);
        if (! cpu->inl_func[port]) {
	    return 0;
        }
    }
    return (*cpu->inl_func[port])(cpu->inl_state[port], port);
}
\end{lstlisting}

\begin{lstlisting}
static void
cpu_inl_info_flush(void *_cpu, uint16_t port)
{
    struct cpu *cpu = _cpu;

    cpu->inl_func[port] = NULL;
    cpu->inl_state[port] = NULL;
}
\end{lstlisting}

% -------------------------------------------------------------------- %
\subsection{Memory Read/Write Bus Cycles}
% -------------------------------------------------------------------- %

If a CPU or any DMA device needs to read/write memory it calls the
{\tt memread}/{\tt memwrite} functions of the bus it is connected
with.

Even if cycle forwarding as described before is used simulation
speed will be very slow as memory read/write cycles occur
{\em very} often.

So in this case we use a similar approach like QEMU:
Busses offer a {\tt map} and an {\tt unmap} function. A CPU might
call the {\tt map} function of the bus to get a pointer to the
simulated memory region (might be part of a graphics adapter, too!).
This pointer can be used to read/write memory directly from within
the CPU or DMA device. If the mapping changes (e.g. during BIOS PCI
re-configuration or because of SMM switches) the devices or bridges
should call the bus' {\tt unmap} function. This way the change
request is broadcasted to all components which cached memory info
before.

% ==================================================================== %
\section{Components, Chips, Architectures}
% ==================================================================== %

% -------------------------------------------------------------------- %
\subsection{Components}
% -------------------------------------------------------------------- %

Components are the things you can buy at the local computer hardware
dealer in your city. Examples:
\begin{itemize}
\item motherboard (incl. chips and sockets)
\item CPU
\item chassis (incl. push buttons and LEDs)
\item power supply
\item IDE disk drive
\item IDE cdrom drive
\item SCSI disk drive
\item SCSI cdrom drive
\item VGA monitor
\item serial terminal
\item SCSI cable
\item serial cable
\item ...
\end{itemize}

Some of these components consist of sub-components. E.g. the
motherboard is formed by many chips, some sockets and many, many
signals connecting these parts. As some of these chips might be
used to build different motherboards, it makes sense to model them
separately.

So, generally each of the FAUmachine components consists of many
\begin{itemize}
\item chips/sockets/...
\item signals
\end{itemize}

How these low-level chips and sockets are modeled is described in
the next chapters. How to build higher level models will be shown in
the chapter thereafter.

% -------------------------------------------------------------------- %
\subsection{Sockets}
% -------------------------------------------------------------------- %

A PCI adapter is connected with the motherboard by about 50 signals.
Even if we use ''bus'' signals combining several of these discrete
signals we have to connect many signals to plug in a PCI adapter
into one PCI slot.

To ease plugging and to make sure pins (signals) are connected
correctly, FAUmachine introduces sockets. Sockets bundle a bunch of
signals forming {\em one} new signal.
\begin{center}
\pgfimage[height=5cm]{socket}
\end{center}

Sockets just forward signal changes from one side of the socket
to the other side. This requires one level of callback function
calls more. But if {\tt info} and {\tt info\_flush} functions
are used this doesn't matter.

% -------------------------------------------------------------------- %
\subsection{Chips and Architectures}
% -------------------------------------------------------------------- %

A south-bridge nowadays contains many functionality distributed over
many chips in former designs. In FAUmachine's chipset the south-bridge
(Intel~82371AB) has an IDE controller with two IDE channels, one USB
controller, two interrupt controllers, two DMA controllers, a real-time
clock, and a programmable interval timer bundled in one chip. In the
future even more functionality might go into the south-bridge chip.

Each of these parts of the chip is independant from the rest of the
chip. So in FAUmachine all these parts are modeled separately. This
might be done the way described above. Just use sub-components and
connect them using signals. The problem is -- speed. This approach
would introduce far too many levels of signals.

So each of these parts is modeled using the ''C'' programming language
and all parts are connected using function calls.
See the following example:
\begin{center}
\pgfimage[height=3cm]{architecture}
\end{center}

\lstset{language=C}
\begin{lstlisting}
struct chip {
    /*
     * The following includes will add the state info of
     * components A and B to the state of the chip.
     */
#define STATE
#include "A.c"
#include "B.c"
#undef STATE
};
\end{lstlisting}

\pagebreak

\begin{lstlisting}
/*forward*/ static void B_I_set(struct chip *, unsigned int);

/* Function usable by component A to output value. */
static void
A_Out_set(struct chip *s, unsigned int val)
{
    B_I_set(s, val);
}

/* Function usable by component B to output value. */
static void
B_O_set(struct chip *s, unsigned int val)
{
    sig_boolean_set(s->port_x, s, val);
}

/* Include behaviour model of conponents A and B. */
#define BEHAVIOUR
#include "A.c"
#include "B.c"
#undef BEHAVIOUR

static void
chip_x_set(void *_s, unsigned int val)
{
    struct chip *s = _s;

    A_In_set(s, val);
}

void *
chip_create(const char *name, struct sig_boolean *port_x)
{
    static const struct sig_boolean_funcs x_funcs = {
        .set = chip_x_set,
    };
    struct chip *s;

    s = malloc(sizeof(*s));

    A_create(s);
    B_create(s);

    sig_boolean_connect_in(port_x, s, &x_funcs);

    return s;
}
\end{lstlisting}

Procedures {\tt A\_Out\_set} and {\tt B\_O\_set} will be inlined by
the compiler. So they don't produce any simulation overhead!

Component parts included this way are called ''architectures'' in
FAUmachine. They have much in common with VHDL's architectures.

To be able to include such architectures more than once (south-bridge
needs two DMA and two interrupt controllers) the C preprocessor can
be used to rename function names. This avoids name clashes.

All FAUmachine architectures are located in the {\tt node-pc/simulator}
directory (for historical reasons).

% -------------------------------------------------------------------- %
\subsection{Structural Descriptions}
% -------------------------------------------------------------------- %

Like in VHDL it is possible create high-level components from lower
level ones. As an example chips and signals together might build up
a motherboard. In FAUmachine we can use components and signals like
in VHDL, too. Another option is to use schematic files produced by
the open-source tool {\tt gschem} which is part of GEDA tool suite.
This schematic files can be pre-processed by a FAUmachine tool called
{\tt faum-gnetlist} which generates a VHDL description of that file.
The VHDL files are used by the FAUmachine VHDL interpreter during
runtime.

This is what is drawn by the designer (Motherboard GA 686DLX):
\begin{center}
\pgfimage[height=9cm]{mb_ga_686dlx}
\end{center}

{\tt faum-gnetlist} produces the following VHDL files (excerpt):
\lstset{language=VHDL}
\begin{lstlisting}
ENTITY mb_ga_686dlx IS
    GENERIC (
	rtc_start : integer := -1
    );
    PORT (
        power : INOUT power_board;
        cpu0 : INOUT host_bus;
	...
	isa2 : INOUT isa_bus;
	...
    );
END mb_ga_686dlx;
\end{lstlisting}

\begin{lstlisting}
ARCHITECTURE structural OF mb_ga_686dlx IS
    SIGNAL XplusX5V : boolean;
    SIGNAL XplusX12V : boolean;
    ...
BEGIN
    U42 : conn_isa
        PORT MAP (
	    isa => isa2,
	    XplusX5V => XplusX5V,
	    ...
	);
    ...
    U15 : chip_sst_29EE020
        GENERIC MAP (
	    img => "bios.rom"
	)
	PORT MAP (
	    power => XplusX5V,
	    cs => tmp000042,
	    main => tmp000021
	);
    ...
END structural;
\end{lstlisting}

It would be possible to generate C-code from the schematic file very
easily, too!

Sources generated this way are located in the {\tt node-pc/simulator}
directory (for historical reasons).

% -------------------------------------------------------------------- %
\subsection{Generated Sources}
% -------------------------------------------------------------------- %

We use a modified version of GEDA's {\tt tragesym} utility to build
{\tt *.sym} files from {\tt *.src} files. These {\tt *.sym} files
can be used in schematic designs (see previous section). For a
description of these files see documentation of the GEDA project.

Look at the following example (Interrupt Controller Intel 8259A
 {\tt chip\_intel\_8259A.src}):
\begin{lstlisting}
[options]
wordswap=yes
rotate_labels=no
sort_labels=no
generate_pinseq=no
sym_width=1300
pinwidthvertical=300
pinwidthhorizontal=300
\end{lstlisting}

\begin{lstlisting}
[geda_attr]
version=20080904
name=8259A
device=chip_intel_8259A
refdes=U?
footprint=SO20
description=Interrupt Controller
documentation=http://
author=aures <aures@informatik.uni-erlangen.de>
numslots=0
\end{lstlisting}

\begin{lstlisting}
[pins]
#--------------------------------------------------------------------
#pinnr  seq     type    style   posit.  net     label   type
#--------------------------------------------------------------------
                        spacer  l
0       2       in      line    l               reset#  boolean
1       3       call    line    l               cs      cs
                        spacer  l
11..4   4       call    line    l               main    isa_bus_main
                        spacer  l
12..14  5       io      line    l               cas     integer
                        spacer  l
                        spacer  l
                        spacer  l
28      1       in      line    b               power   boolean
                        spacer  r
18      6       in      line    r               ir0     boolean_or
19      7       in      line    r               ir1     boolean_or
20      8       in      line    r               ir2     boolean_or
21      9       in      line    r               ir3     boolean_or
22      10      in      line    r               ir4     boolean_or
23      11      in      line    r               ir5     boolean_or
24      12      in      line    r               ir6     boolean_or
25      13      in      line    r               ir7     boolean_or
17      14      out     line    r               int     boolean_or
                        spacer  r
16      15      in      line    r               sp      boolean
                        spacer  r
\end{lstlisting}

Using the modified {\tt tragesym} utility ({\tt faum-tragesym}) we
will get the following graphical component
({\tt chip\_intel\_8259A.sym}; use {\tt gschem} for displaying):
\begin{center}
\pgfimage[height=5cm]{chip_intel_8259A}
\end{center}

This {\tt *.sym} file is parsed by {\tt faum-gnetlist}. This utility
will create a header file suitable for a model built in the C language
(file {\tt chip\_intel\_8259A.h}):
\lstset{language=C}
\begin{lstlisting}
#include "sig_boolean.h"
#include "sig_boolean_or.h"
#include "sig_cs.h"
#include "sig_integer.h"
#include "sig_isa_bus.h"
#include "sig_manage.h"
\end{lstlisting}

\begin{lstlisting}
extern void *
chip_intel_8259A_create(
        const char *name,
        struct sig_boolean *port_power,
        struct sig_boolean *port_resetXhashX,
        struct sig_cs *port_cs,
        struct sig_isa_bus_main *port_main,
        struct sig_integer *port_cas,
        struct sig_boolean_or *port_ir0,
        struct sig_boolean_or *port_ir1,
        struct sig_boolean_or *port_ir2,
        struct sig_boolean_or *port_ir3,
        struct sig_boolean_or *port_ir4,
        struct sig_boolean_or *port_ir5,
        struct sig_boolean_or *port_ir6,
        struct sig_boolean_or *port_ir7,
        struct sig_boolean_or *port_int,
        struct sig_boolean *port_sp
);
extern void
chip_intel_8259A_destroy(void *_cpssp);
\end{lstlisting}

In the same step C function stubs are produced
(file {\tt chip\_intel\_8259A.c.tmp}; excerpt):
\begin{lstlisting}
#include <...>
#include "chip_intel_8259A.h"

struct cpssp {
        struct sig_boolean_or *port_int;
        unsigned int state_power;
        unsigned int state_resetXhashX;
        ...
};
\end{lstlisting}

\begin{lstlisting}
void *
chip_intel_8259A_create(
        const char *name,
        struct sig_boolean *port_power,
        struct sig_boolean *port_resetXhashX,
        struct sig_cs *port_cs,
        struct sig_isa_bus_main *port_main,
        struct sig_integer *port_cas,
        struct sig_boolean_or *port_ir0,
        struct sig_boolean_or *port_ir1,
        struct sig_boolean_or *port_ir2,
        struct sig_boolean_or *port_ir3,
        struct sig_boolean_or *port_ir4,
        struct sig_boolean_or *port_ir5,
        struct sig_boolean_or *port_ir6,
        struct sig_boolean_or *port_ir7,
        struct sig_boolean_or *port_int,
        struct sig_boolean *port_sp
)
{
        static const struct sig_boolean_funcs power_funcs = {
                /* FIXME */
        };
        static const struct sig_boolean_funcs resetXhashX_funcs = {
                /* FIXME */
        };
        ...
        struct cpssp *cpssp;

        cpssp = malloc(sizeof(*cpssp));
        assert(cpssp);

        cpssp->state_power = 0;
        sig_boolean_connect_in(port_power, cpssp, &power_funcs);

        cpssp->state_resetXhashX = 0;
        sig_boolean_connect_in(port_resetXhashX, cpssp, &resetXhashX_funcs);

        ...

        return cpssp;
}
\end{lstlisting}

\begin{lstlisting}
void
chip_intel_8259A_destroy(void *_cpssp)
{
        struct cpssp *cpssp = _cpssp;

        /* FIXME */

        free(cpssp);
}
\end{lstlisting}

Only functions modeling the behavior of the component have to be
inserted. The structure of the sources is already prepared.

{\em All} FAUmachine components are generated this way!
Their sources are located in the {\tt node-pc/simulator} directory
(for historical reasons).

Creating components this way makes sure C models and structural
descriptions using these models will fit.

% ==================================================================== %
\section{Simulation Engine}
% ==================================================================== %

FAUmachine's simulation engine (sources are located in
{\tt lib/glue-main.[ch]}) has to
\begin{itemize}
\item call {\tt *\_create} functions on startup to configure system.
\end{itemize}

While simulation is in progress the following tasks have to be
repeated again and again:
\begin{itemize}
\item stop simulation if {\tt sim\_exit} function was called
\item call I/O callbacks if {\tt SIGIO} is received
\item synchronize real-time clock and simulation clock
\item call event-based callback functions at correct times
\item execute processes if nothing else has to be done.
\end{itemize}

After {\tt sim\_exit} has been called the simulation engine has to
\begin{itemize}
\item call {\tt *\_destroy} functions.
\end{itemize}

Execution of processes might be done using multiple real threads.
This way it is possible to run multiple CPUs, CDROM drives etc.
all at the same time.

% ==================================================================== %
\section{Conclusion}
% ==================================================================== %

FAUmachine has a very clean way to model huge virtual machines.

\end{document}
