File: internals.tex

package info (click to toggle)
faumachine 20100527-2
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 53,836 kB
  • ctags: 20,552
  • sloc: ansic: 179,550; asm: 3,645; makefile: 3,611; perl: 2,103; sh: 1,529; python: 600; xml: 563; lex: 210; vhdl: 204
file content (1154 lines) | stat: -rw-r--r-- 35,945 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
%
% $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}