OpenCores
URL https://opencores.org/ocsvn/ion/ion/trunk

Subversion Repositories ion

[/] [ion/] [trunk/] [doc/] [src/] [tex/] [simulation.tex] - Blame information for rev 250

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 210 ja_rd
\chapter{Logic Simulation}
2
\label{logic_simulation}
3
 
4
    The project has been simulated using Modelsim 6.3g. The test bench
5
    uses some features not present in earlier versions (namely library Signal
6
    Spy) so if you use some other simulator or some earlier version of Modelsim,
7
    see section on Modelsim dependencies (\ref{modelsim_dependencies}) below.\\
8
 
9
    In short, the simulation test bench is meant to run any of the code samples
10
    provided in directory /src, under a controlled environment, while logging
11
    the cpu state to a text log file.\\
12
 
13
    This log file can then be compared to a log file generated by a software
14 221 ja_rd
    simulator for the same code sample (see section \ref{sw_simulator}). The software
15 210 ja_rd
    simulator is the 'golden model' against which the cpu is tested, so any
16
    difference between both log files means trouble.\\
17
 
18
    This method is far easier than building a fully automated test bench, and
19
    much more convenient and reliable than a visual inspection of the simulation
20
    state.\\
21
 
22
    In addition to the main log file, there is a console log file to which all
23
    data written to the UART is logged (see section~\ref{uart_logging}).\\
24
 
25
 
26 221 ja_rd
    The simulation test bench can be found in file '/vhdl/tb/mips\_tb.vhdl'.
27
    This test bench is meant to be used with all the code samples.
28 210 ja_rd
 
29 221 ja_rd
    Each of the code samples configures the simulation test bench with certain
30
    parameters (such as simulation length or memory sizes) and of course each
31
    sample has a different object code to be run. The way to pass these
32
    parameters to the simulation is through a simulation package, in file
33
    '/vhdl/tb/sim\_params\_pkg.vhdl'.
34 210 ja_rd
 
35 221 ja_rd
    This file is generated from a template whenever you 'make' each code sample
36
    (see section~\ref{samples}). The package is built using oe of the
37
    provided tools, 'build\_pkg', explained in section ~\ref{build_pkg}.
38
 
39 210 ja_rd
 
40
    Note that all code samples share the same vhdl files: you need to run the
41
    makefile target 'sim' for the sample you want to simulate; that will
42 221 ja_rd
    overwrite the package file mentioned above. So there's no vhdl file that is
43 210 ja_rd
    specific to a particular code sample.\\
44 221 ja_rd
 
45 210 ja_rd
    While the test benches and sample code are good enough to catch MOST errors
46
    in the full system (i.e. cache included) they don't help with diagnostic;
47
    once you know there's an error, and the approximate address where it's
48
    triggered (approximate because of the cache) you have to dig into the
49 221 ja_rd
    simulation waveforms to find it.\\
50 210 ja_rd
 
51
\section{Running the Simulation}
52
\label{running_the_simulation}
53
 
54
    A simulation script can be found at '/sim/mips\_tb.do'. This script will
55
    simulate the test bench entity in file '/vhdl/tb/mips\_tb.vhdl'.\\
56
 
57
    All the code samples are run with the same script.\\
58
 
59
    The test bench files mentioned in the previous section are automatically
60
    generated for each of the sample programs. This is automatically done by the
61
    sample code makefile,
62 221 ja_rd
    assuming you have a MIPS cross-toolchain in your computer (see section~\ref{samples}).\\
63 210 ja_rd
 
64 221 ja_rd
    For convenience, a pre-generated file 'sim\_params\_pkg.vhdl' is included
65
    so you can launch a simulation without having to install toolchains, etc.
66
    The code is that of the 'hello world' sample.\\
67 210 ja_rd
 
68
    I guess that if you are interested in this sort of stuff then you probably
69
    know more about Modelsim than I do. Yet, here's a step-by-step guide to
70
    simulating the 'hello world' sample:
71
 
72
\begin{enumerate}
73
    \item Run 'make hello\_sim' from directory '/src/hello'.
74
        This will compile the program sources, build the necessary binary object
75 221 ja_rd
        files and then create the package file mentioned above.\\
76 210 ja_rd
        Read the makefile and comments in the python script '/src/bin2hdl.py'
77
        for details.\\
78
 
79
        ALTERNATIVELY, if you don't have a toolchain you can just skip this
80
        step and use the default vhdl files provided, which are those of the
81
        'hello world' sample.\\
82
 
83
    \item Within Modelsim, change directory to /syn. Modelsim will create its
84
        stuff in this directory. This includes the
85
        log file, which by default will be '/syn/hw\_sim\_log.txt', and the
86
        console log file '/syn/hw\_sim\_console.log'.\\
87
        (You could use any other directory, this is just a convenient place to
88
        put modelsim data out of the way. Just remember where the log files
89
        are.).
90
 
91
    \item Run script '/sim/mips\_tb.do' (menu tools-\textgreater tcl-\textgreater execute macro)
92
        The simulation will run to completion and print a message in Modelsim's
93
        transcript window when it's done. You can open the console log file
94
        to see the program output, in this case the 'Hello world' message.\\
95
 
96
\end{enumerate}
97
 
98
    The test bench terminates the simulation when:
99
 
100
\begin{enumerate}
101
 
102
    \item It detects two consecutive code fetches from the same address.
103
    \item The simulation timeout is reached.
104
 
105
\end{enumerate}
106
 
107
    Condition 1 is meant to detect single-instruction loops such as those
108
    commonly found after the invocation of the main() function in a C program.
109
    This is a convenient way for the software to signal its termination.\\
110
 
111
    The timeout is one of the simulation parameters which is defined in
112
    the makefiles. It is arbitrarily fixed for each sample by trial and error
113
    so that the program has time to execute. Change them if necessary.\\
114
 
115
\section{Simulation File Logging}
116
\label{sim_logging}
117
 
118
    The simulation test bench will log any of the following events:
119
 
120
    \begin{itemize}
121
    \item Changes in the register bank.
122
    \item Changes in registers HI and LO (implemented even if mul/div is not).
123
    \item Changes in registers EPC and SR.
124
    \item Data loads (any resulting register change is logged separately).
125
    \item Data stores.
126
    \end{itemize}
127
 
128
    Note that changes in other internal registers, including PC, are not logged.
129
    This means that for example a long chain of NOPs, or MOVEs that don't change
130
    register values, will not be seen in the log file. This is on purpose.\\
131
 
132
    Events are logged with the address of the instruction that triggered
133
    the change. This holds true even for load instructions.\\
134
 
135
    The simulation log file is stored by default in modelsim's working directory
136
    (see above). I don't provide any automated script to do the comparison, you
137
    should use whatever diff tool you like best.\\
138
 
139
\section{Log File Format}
140
\label{log_file_format}
141
 
142
    There is a text line for each of the following events:
143
 
144
    \begin{itemize}
145
    \item Register change
146
 
147
        "(pc) [reg\_num]=value"\\
148
 
149
        Where:
150
 
151
        \begin{tabular}{ l l }
152
            pc       & =\textgreater PC value (8-digit hex)\\
153
            reg\_num & =\textgreater Register index (2-digit hex), or any of {LO,HI,EP}\\
154
            value    & =\textgreater New register value (8-digit hex)\\
155
        \end{tabular}\\
156
 
157
 
158
    \item Write cycle (store)
159
 
160
        "(pc) [address] |mask|=value WR"\\
161
 
162
        Where:
163
 
164
        \begin{tabular}{ l l }
165
        pc      & =\textgreater PC value (8-digit hex)\\
166
        address & =\textgreater Write address\\
167
        mask    & =\textgreater Byte-enable mask (2-digit hex)\\
168
        value   & =\textgreater Write data\\
169
        \end{tabular}\\
170
 
171
        The PC value is the address of the instruction that caused the logged
172
        change, NOT the actual value of the PC at the time of the change.
173
        This is so to make the hardware logger's life easier -- the SW simulator
174
        and the real HW don't work exactly the same when the cache starts
175
        stalling the cpu (which the SW does not simulate) and the best reference
176
        point for all instructions is their own adddress.
177
 
178
        The mask will have a '1' at bits 3..0 for each byte write-enabled. MSB
179
        is bit 3, LSB is bit 0. Note that the data is big endian, so the MSB
180
        is actually the LOWER address. The upper nibble of the mask is always 0.
181
 
182
        The value will match the behavior of the ion cpu; the significant
183
        byte(s) will have the actual write data and the other bytes will not
184
        be relevant but will behave exactly as the real hardware (so that the
185
        logs are directly comparable).
186
 
187
        The WR at the end of the line is for visual reference only.
188
 
189
    \item Read cycle (load)
190
 
191
        "(pc) [address] \textless ** \textgreater =value RD"\\
192
 
193
        Where:
194
 
195
        \begin{tabular}{ l l }
196
        pc      & =\textgreater PC value (8-digit hex)\\
197
        address & =\textgreater Read address\\
198
        \textless ** \textgreater    & =\textgreater Padding (ignore)\\
199
        value   & =\textgreater Read data\\
200
        \end{tabular}\\
201
 
202
        Note that in the real machine, the data is read into the cpu one cycle
203
        after the address bus is output (because the memory is synchronous) so
204
        that the full read cycle spans 2 clock cycles (when proper interlocking
205
        is implemented, the load will overlap the next instruction; right now
206
        it just stalls the pipeline for 1 cycle). This is simplified in the log
207
        files for readability.
208
 
209
        Note that the size of the read (LH/LB/LW) instruction is not recorded:
210
        the CPU always reads 32-bit words.
211
 
212
        The RD at the end of the line is for visual reference only.
213
 
214
    \end{itemize}
215
 
216
 
217
    For example, these are lines 1153-1162 of the simulation log for the
218
    default 'hello world' test program:
219
 
220
                \begin{verbatim}
221
                ...
222
                (BFC009AC) [05]=20000000
223
                (BFC009B0) [20000020] <**>=00000003 RD
224
                (BFC009B0) [03]=00000003
225
                (BFC009B8) [03]=00000002
226
                (BFC009C0) [03]=20000000
227
                (BFC009C4) [20000000] |0F|=00000070 WR
228
                (BFC00E74) [12]=00000004
229
                (BFC00E78) [10]=BFC01048
230
                (BFC00E7C) [BFC01048] <**>=00000069 RD
231
                (BFC00E7C) [05]=00000069
232
                ...
233
                \end{verbatim}\\
234
 
235
    (NOTE: this example taken from revision 176, yours may vary)\\
236
 
237
    The read cycle at pc=0xbfc009b0 modifies register 0x03; that's why there
238
    are two lines with the same pc value.\\
239
 
240
    The code that produced that log is this (from hello.lst):
241
 
242
                \begin{verbatim}
243
                ...
244
                bfc009ac:    3c052000     lui   a1,0x2000
245
                bfc009b0:    8ca30020     lw    v1,32(a1)
246
                bfc009b4:    00000000     nop
247
                bfc009b8:    30630002     andi  v1,v1,0x2
248
                bfc009bc:    1060fffc     beqz  v1,0xbfc009b0
249
                bfc009c0:    3c032000     lui   v1,0x2000
250
                bfc009c4:    ac620000     sw    v0,0(v1)
251
                bfc009c8:    03e00008     jr    ra
252
                bfc009cc:    00000000     nop
253
                ...
254
                bfc00e74:    26520001     addiu  s2,s2,1
255
                bfc00e78:    26100001     addiu  s0,s0,1
256
                bfc00e7c:    92050000     lbu    a1,0(s0)
257
                bfc00e80:    00000000     nop
258
                ...
259
                \end{verbatim}\\
260
 
261
    (Remember the register numbers: \$v0=0x02, \$v1=0x03, \$a1=0x05, \$s0=0x10,
262
    \$s2=0x12)\\
263
 
264
    Note that, unlike previous versions of this project, all changes are logged
265
    with the address of the instruction that caused them.\\
266
 
267
    The log file format is hardcoded into vhdl package mips\_sim\_pkg
268
    and the software simulator C source that implement it. It will
269
    be probably modified as the project moves on so it is best if you verify
270
    all of this yourself with the project version you intend to use before
271
    using this information.\\
272
 
273
    Note that the software simulation log and the modelsim log need not be the
274
    same size even if both CPUs behave identically; the one that spans a longer
275
    simulated time will be longer.\\
276
    The point is that both need to be identical up to the last line of the
277
    shortest file.\\
278
 
279
\section{Console Output Logging}
280
\label{uart_logging}
281
 
282
    Every byte written to the UART TX register is logged (in ascii) to a text
283
    file which by default is '/syn/hw\_sim\_console.log'. Apart from the
284
    automatic insertion of a CR after every LF, the data is logged verbatim.\\
285
 
286
    Though the UART is included in the test bench, the actual UART operation is
287
    bypassed: The test bench forces the 'tx ready' high so that the CPU never has
288
    to wait for a character to be transmitted. This is a simplification that
289
    saves me the trouble to do a cycle-accurate simulation of the UART in the
290
    software simulator.\\
291
 
292
    The UART input is not simulated at all, for simplicity. So, for example, the
293
    Adventure sample, which does read the console input, can't be properly
294
    simulated past the first console input -- there is plenty of code to
295
    simulate before that so this is no problem for the moment.\\
296
 
297
 
298
\section{Use of Modelsim Features}
299
\label{modelsim_dependencies}
300
 
301
    Apart from the format of the simulation scripts, which would be easy to port
302
    to any other simulation tool, the simulation test bench uses a feature of
303
    Modelsim 6.3 that is not even present in earlier versions -- SignalSpy.\\
304
 
305
    The test bench uses SignalSpy to examine internal cpu signals from the top
306
    entity, including the whole register bank. There is no other way to examine
307
    those signals in vhdl, unless you want to add them to the module interface.\\
308
 
309
    The test bench needs to access those signals in order to detect changes in
310
    the internal cpu state that should be logged. That is, it really needs to
311
    look at those signals if it is to be of any use.\\
312
 
313
    If you are using any other simulation tool, look for an alternative method
314
    to get those internal signals or just add them to the core interface. I
315
    would suggest adding a debug port of type record to mips\_cpu -- and hope the
316
    synthesis tool does not choke on it. Adding individual debug ports would be
317
    a PITA.\\
318
    I guess this is why Mentor people took the trouble to write SygnalSpy.\\
319
 
320
    I plan to move to Symphony EDA eventually, so I'll have to fix this.\\
321
 
322
    Using GHDL would be an option, except because it only supports vhdl. The
323
    project will use a SDRAM model in verilog for which I could not find a
324
    vhdl replacement. If the project is to be ported to GHDL (a very desirable
325
    goal even if only because not everybody has access to Modelsim) this will
326
    have to be worked around.\\
327
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.