]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - sim/README-HACKING
sim: clean up stale AC_PREREQ refs
[thirdparty/binutils-gdb.git] / sim / README-HACKING
CommitLineData
c906108c
SS
1This is a loose collection of notes for people hacking on simulators.
2If this document gets big enough it can be prettied up then.
3
4Contents
5
6- The "common" directory
7- Common Makefile Support
8- TAGS support
9- Generating "configure" files
c906108c
SS
10- C Language Assumptions
11- "dump" commands under gdb
12\f
13The "common" directory
14======================
15
16The common directory contains:
17
18- common documentation files (e.g. run.1, and maybe in time .texi files)
19- common source files (e.g. run.c)
20- common Makefile fragment and configury (e.g. Make-common.in, aclocal.m4).
21
22In addition "common" contains portions of the system call support
23(e.g. callback.c, nltvals.def).
24
25Even though no files are built in this directory, it is still configured
26so support for regenerating nltvals.def is present.
27\f
28Common Makefile Support
29=======================
30
31A common configuration framework is available for simulators that want
32to use it. The common framework exists to remove a lot of duplication
306f4178 33in configure.ac and Makefile.in, and it also provides a foundation for
c906108c
SS
34enhancing the simulators uniformly (e.g. the more they share in common
35the easier a feature added to one is added to all).
36
306f4178 37The configure.ac of a simulator using the common framework should look like:
c906108c
SS
38
39--- snip ---
40dnl Process this file with autoconf to produce a configure script.
41sinclude(../common/aclocal.m4)
c906108c
SS
42AC_INIT(Makefile.in)
43
44SIM_AC_COMMON
45
46... target specific additions ...
47
48SIM_AC_OUTPUT
49--- snip ---
50
51SIM_AC_COMMON:
52
53- invokes the autoconf macros most often used by the simulators
54- defines --enable/--with options usable by all simulators
55- initializes sim_link_files/sim_link_links as the set of symbolic links
56 to set up
57
58SIM_AC_OUTPUT:
59
60- creates the symbolic links defined in sim_link_{files,links}
61- creates config.h
62- creates the Makefile
63
64The Makefile.in of a simulator using the common framework should look like:
65
66--- snip ---
67# Makefile for blah ...
68# Copyright blah ...
69
70## COMMON_PRE_CONFIG_FRAG
71
72# These variables are given default values in COMMON_PRE_CONFIG_FRAG.
73# We override the ones we need to here.
74# Not all of these need to be mentioned, only the necessary ones.
75# In fact it is better to *not* mention ones if the value is the default.
76
77# List of object files, less common parts.
78SIM_OBJS =
79# List of extra dependencies.
80# Generally this consists of simulator specific files included by sim-main.h.
81SIM_EXTRA_DEPS =
82# List of flags to always pass to $(CC).
83SIM_EXTRA_CFLAGS =
84# List of extra libraries to link with.
85SIM_EXTRA_LIBS =
86# List of extra program dependencies.
87SIM_EXTRA_LIBDEPS =
88# List of main object files for `run'.
89SIM_RUN_OBJS = run.o
90# Dependency of `all' to build any extra files.
91SIM_EXTRA_ALL =
92# Dependency of `install' to install any extra files.
93SIM_EXTRA_INSTALL =
94# Dependency of `clean' to clean any extra files.
95SIM_EXTRA_CLEAN =
96
97## COMMON_POST_CONFIG_FRAG
98
99# Rules need to build $(SIM_OBJS), plus whatever else the target wants.
100
101... target specific rules ...
102--- snip ---
103
104COMMON_{PRE,POST}_CONFIG_FRAG are markers for SIM_AC_OUTPUT to tell it
105where to insert the two pieces of common/Make-common.in.
106The resulting Makefile is created by doing autoconf substitions on
107both the target's Makefile.in and Make-common.in, and inserting
108the two pieces of Make-common.in into the target's Makefile.in at
109COMMON_{PRE,POST}_CONFIG_FRAG.
110
111Note that SIM_EXTRA_{INSTALL,CLEAN} could be removed and "::" targets
112could be used instead. However, it's not clear yet whether "::" targets
113are portable enough.
114\f
115TAGS support
116============
117
118Many files generate program symbols at compile time.
119Such symbols can't be found with grep nor do they normally appear in
120the TAGS file. To get around this, source files can add the comment
121
122/* TAGS: foo1 foo2 */
123
124where foo1, foo2 are program symbols. Symbols found in such comments
125are greppable and appear in the TAGS file.
126\f
127Generating "configure" files
128============================
129
130For targets using the common framework, "configure" can be generated
131by running `autoconf'.
132
133To regenerate the configure files for all targets using the common framework:
134
135 $ cd devo/sim
136 $ make -f Makefile.in SHELL=/bin/sh autoconf-common
137
138To add a change-log entry to the ChangeLog file for each updated
139directory (WARNING - check the modified new-ChangeLog files before
140renaming):
141
142 $ make -f Makefile.in SHELL=/bin/sh autoconf-changelog
143 $ more */new-ChangeLog
144 $ make -f Makefile.in SHELL=/bin/sh autoconf-install
145
146In a similar vein, both the configure and config.in files can be
147updated using the sequence:
148
149 $ cd devo/sim
150 $ make -f Makefile.in SHELL=/bin/sh autoheader-common
151 $ make -f Makefile.in SHELL=/bin/sh autoheader-changelog
152 $ more */new-ChangeLog
153 $ make -f Makefile.in SHELL=/bin/sh autoheader-install
c93abbcc
AC
154
155To add the entries to an alternative ChangeLog file, use:
156
157 $ make ChangeLog=MyChangeLog ....
158
c906108c
SS
159\f
160C Language Assumptions
161======================
162
46f900c0 163An ISO C11 compiler is required, as is an ISO C standard library.
c906108c
SS
164\f
165"dump" commands under gdb
166=========================
167
168gdbinit.in contains the following
169
170define dump
171set sim_debug_dump ()
172end
173
174Simulators that define the sim_debug_dump function can then have their
175internal state pretty printed from gdb.
176
177FIXME: This can obviously be made more elaborate. As needed it will be.
178\f
179Rebuilding nltvals.def
180======================
181
182Checkout a copy of the SIM and LIBGLOSS modules (Unless you've already
183got one to hand):
184
185 $ mkdir /tmp/$$
186 $ cd /tmp/$$
187 $ cvs checkout sim-no-testsuite libgloss-no-testsuite newlib-no-testsuite
188
189Configure things for an arbitrary simulator target (I've d10v for
190convenience):
191
192 $ mkdir /tmp/$$/build
193 $ cd /tmp/$$/build
194 $ /tmp/$$/devo/configure --target=d10v-elf
195
196In the sim/common directory rebuild the headers:
197
198 $ cd sim/common
199 $ make headers
200
201To add a new target:
202
203 devo/sim/common/gennltvals.sh
204
205 Add your new processor target (you'll need to grub
206 around to find where your syscall.h lives).
207
208 devo/sim/<processor>/Makefile.in
209
210 Add the definition:
211
212 ``NL_TARGET = -DNL_TARGET_d10v''
213
214 just before the line COMMON_POST_CONFIG_FRAG.
215
216 devo/sim/<processor>/*.[ch]
217
218 Include targ-vals.h instead of syscall.h.
aba193a5
MF
219\f
220Tracing
221=======
222
223For ports based on CGEN, tracing instrumentation should largely be for free,
224so we will cover the basic non-CGEN setup here. The assumption is that your
225target is using the common autoconf macros and so the build system already
226includes the sim-trace configure flag.
227
228The full tracing API is covered in sim-trace.h, so this section is an overview.
229
230Before calling any trace function, you should make a call to the trace_prefix()
231function. This is usually done in the main sim_engine_run() loop before
232simulating the next instruction. You should make this call before every
233simulated insn. You can probably copy & paste this:
234 if (TRACE_ANY_P (cpu))
235 trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu), NULL, 0, "");
236
237You will then need to instrument your simulator code with calls to the
238trace_generic() function with the appropriate trace index. Typically, this
239will take a form similar to the above snippet. So to trace instructions, you
240would use something like:
241 if (TRACE_INSN_P (cpu))
242 trace_generic (sd, cpu, TRACE_INSN_IDX, "NOP;");
243
244The exact output format is up to you. See the trace index enum in sim-trace.h
245to see the different tracing info available.
246
247To utilize the tracing features at runtime, simply use the --trace-xxx flags.
248 run --trace-insn ./some-program
249\f
250Profiling
251=========
252
253Similar to the tracing section, this is merely an overview for non-CGEN based
254ports. The full API may be found in sim-profile.h. Its API is also similar
255to the tracing API.
256
257Note that unlike the tracing command line options, in addition to the profile
258flags, you have to use the --verbose option to view the summary report after
259execution. Tracing output is displayed on the fly, but the profile output is
260only summarized.
261
262To profile core accesses (such as data reads/writes and insn fetches), add
263calls to PROFILE_COUNT_CORE() to your read/write functions. So in your data
264fetch function, you'd use something like:
265 PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_read);
266Then in your data write function:
267 PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_write);
268And in your insn fetcher:
269 PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_exec);
270
271To use the PC profiling code, you simply have to tell the system where to find
272your simulator's PC and its size. So in your sim_open() function:
273 STATE_WATCHPOINTS (sd)->pc = address_of_cpu0_pc;
274 STATE_WATCHPOINTS (sd)->sizeof_pc = number_of_bytes_for_pc_storage;
275In a typical 32bit system, the sizeof_pc will be 4 bytes.
276
277To profile branches, in every location where a branch insn is executed, call
278one of the related helpers:
279 PROFILE_BRANCH_TAKEN (cpu);
280 PROFILE_BRANCH_UNTAKEN (cpu);
281If you have stall information, you can utilize the other helpers too.
282\f
283Environment Simulation
284======================
285
286The simplest simulator doesn't include environment support -- it merely
287simulates the Instruction Set Architecture (ISA). Once you're ready to move
288on to the next level, call the common macro in your configure.ac:
289SIM_AC_OPTION_ENVIRONMENT
290
291This will support for the user, virtual, and operating environments. See the
292sim-config.h header for a more detailed description of them. The former are
293pretty straight forward as things like exceptions (making system calls) are
294handled in the simulator. Which is to say, an exception does not trigger an
295exception handler in the simulator target -- that is what the operating env
296is about. See the following userspace section for more information.
297\f
298Userspace System Calls
299======================
300
301By default, the libgloss userspace is simulated. That means the system call
302numbers and calling convention matches that of libgloss. Simulating other
303userspaces (such as Linux) is pretty straightforward, but let's first focus
304on the basics. The basic API is covered in include/gdb/callback.h.
305
306When an instruction is simulated that invokes the system call method (such as
307forcing a hardware trap or exception), your simulator code should set up the
308CB_SYSCALL data structure before calling the common cb_syscall() function.
309For example:
310static int
311syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
312 unsigned long taddr, char *buf, int bytes)
313{
314 SIM_DESC sd = (SIM_DESC) sc->p1;
315 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
316 return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
317}
318static int
319syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
320 unsigned long taddr, const char *buf, int bytes)
321{
322 SIM_DESC sd = (SIM_DESC) sc->p1;
323 SIM_CPU *cpu = (SIM_CPU *) sc->p2;
324 return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
325}
326void target_sim_syscall (SIM_CPU *cpu)
327{
328 SIM_DESC sd = CPU_STATE (cpu);
329 host_callback *cb = STATE_CALLBACK (sd);
330 CB_SYSCALL sc;
331
332 CB_SYSCALL_INIT (&sc);
333
334 sc.func = <fetch system call number>;
335 sc.arg1 = <fetch first system call argument>;
336 sc.arg2 = <fetch second system call argument>;
337 sc.arg3 = <fetch third system call argument>;
338 sc.arg4 = <fetch fourth system call argument>;
339 sc.p1 = (PTR) sd;
340 sc.p2 = (PTR) cpu;
341 sc.read_mem = syscall_read_mem;
342 sc.write_mem = syscall_write_mem;
343
344 cb_syscall (cb, &sc);
345
346 <store system call result from sc.result>;
347 <store system call error from sc.errcode>;
348}
349Some targets store the result and error code in different places, while others
350only store the error code when the result is an error.
351
352Keep in mind that the CB_SYS_xxx defines are normalized values with no real
353meaning with respect to the target. They provide a unique map on the host so
354that it can parse things sanely. For libgloss, the common/nltvals.def file
355creates the target's system call numbers to the CB_SYS_xxx values.
356
357To simulate other userspace targets, you really only need to update the maps
358pointers that are part of the callback interface. So create CB_TARGET_DEFS_MAP
359arrays for each set (system calls, errnos, open bits, etc...) and in a place
360you find useful, do something like:
361
362...
363static CB_TARGET_DEFS_MAP cb_linux_syscall_map[] = {
364# define TARGET_LINUX_SYS_open 5
365 { CB_SYS_open, TARGET_LINUX_SYS_open },
366 ...
367 { -1, -1 },
368};
369...
370 host_callback *cb = STATE_CALLBACK (sd);
371 cb->syscall_map = cb_linux_syscall_map;
372 cb->errno_map = cb_linux_errno_map;
373 cb->open_map = cb_linux_open_map;
374 cb->signal_map = cb_linux_signal_map;
375 cb->stat_map = cb_linux_stat_map;
376...
377
378Each of these cb_linux_*_map's are manually declared by the arch target.
379
380The target_sim_syscall() example above will then work unchanged (ignoring the
381system call convention) because all of the callback functions go through these
382mapping arrays.
383\f
384Events
385======
386
387Events are scheduled and executed on behalf of either a cpu or hardware devices.
388The API is pretty much the same and can be found in common/sim-events.h and
389common/hw-events.h.
390
391For simulator targets, you really just have to worry about the schedule and
392deschedule functions.
393\f
394Device Trees
395============
396
397The device tree model is based on the OpenBoot specification. Since this is
398largely inherited from the psim code, consult the existing psim documentation
399for some in-depth details.
400 http://sourceware.org/psim/manual/
401\f
402Hardware Devices
403================
404
405The simplest simulator doesn't include hardware device support. Once you're
406ready to move on to the next level, call the common macro in your configure.ac:
407SIM_AC_OPTION_HARDWARE(yes,,devone devtwo devthree)
408
409The basic hardware API is documented in common/hw-device.h.
410
411Each device has to have a matching file name with a "dv-" prefix. So there has
412to be a dv-devone.c, dv-devtwo.c, and dv-devthree.c files. Further, each file
413has to have a matching hw_descriptor structure. So the dv-devone.c file has to
414have something like:
415 const struct hw_descriptor dv_devone_descriptor[] = {
416 {"devone", devone_finish,},
417 {NULL, NULL},
418 };
419
420The "devone" string as well as the "devone_finish" function are not hard
421requirements, just common conventions. The structure name is a hard
422requirement.
423
424The devone_finish() callback function is used to instantiate this device by
425parsing the corresponding properties in the device tree.
426
427Hardware devices typically attach address ranges to themselves. Then when
428accesses to those addresses are made, the hardware will have its callback
429invoked. The exact callback could be a normal I/O read/write access, as
430well as a DMA access. This makes it easy to simulate memory mapped registers.
431
432Keep in mind that like a proper device driver, it may be instantiated many
433times over. So any device state it needs to be maintained should be allocated
434during the finish callback and attached to the hardware device via set_hw_data.
435Any hardware functions can access this private data via the hw_data function.
436\f
437Ports (Interrupts / IRQs)
438=========================
c906108c 439
aba193a5
MF
440First, a note on terminology. A "port" is an aspect of a hardware device that
441accepts or generates interrupts. So devices with input ports may be the target
442of an interrupt (accept it), and/or they have output ports so that they may be
443the source of an interrupt (generate it).
444
445Each port has a symbolic name and a unique number. These are used to identify
446the port in different contexts. The output port name has no hard relationship
447to the input port name (same for the unique number). The callback that accepts
448the interrupt uses the name/id of its input port, while the generator function
449uses the name/id of its output port.
450
451The device tree is used to connect the output port of a device to the input
452port of another device. There are no limits on the number of inputs connected
453to an output, or outputs to an input, or the devices attached to the ports.
454In other words, the input port and output port could be the same device.
455
456The basics are:
457 - each hardware device declares an array of ports (hw_port_descriptor).
458 any mix of input and output ports is allowed.
459 - when setting up the device, attach the array (set_hw_ports).
460 - if the device accepts interrupts, it will have to attach a port callback
461 function (set_hw_port_event)
462 - connect ports with the device tree
463 - handle incoming interrupts with the callback
464 - generate outgoing interrupts with hw_port_event