• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..--

arm/07-Feb-2025-24,27718,992

avr/07-Feb-2025-2,3961,835

bfin/07-Feb-2025-26,83420,823

common/07-Feb-2025-50,48334,876

cr16/07-Feb-2025-8,1976,258

cris/07-Feb-2025-62,64555,243

d10v/07-Feb-2025-7,7066,034

erc32/07-Feb-2025-8,2676,610

frv/07-Feb-2025-185,255167,332

h8300/07-Feb-2025-7,6485,823

igen/07-Feb-2025-14,67310,899

iq2000/07-Feb-2025-13,45510,886

lm32/07-Feb-2025-8,3456,260

m32c/07-Feb-2025-9,6737,552

m32r/07-Feb-2025-48,59641,120

m68hc11/07-Feb-2025-11,0607,938

mcore/07-Feb-2025-2,4321,790

microblaze/07-Feb-2025-2,0441,490

mips/07-Feb-2025-33,36326,743

mn10300/07-Feb-2025-23,06018,342

moxie/07-Feb-2025-2,2621,616

ppc/07-Feb-2025-67,09950,530

rl78/07-Feb-2025-3,7152,740

rx/07-Feb-2025-7,8506,078

sh/07-Feb-2025-8,6107,130

sh64/07-Feb-2025-

testsuite/07-Feb-2025-2,9742,278

v850/07-Feb-2025-11,2308,541

COPYINGD30-Jul-202334.3 KiB675553

ChangeLog-2021D30-Jul-202356.9 KiB1,9251,263

MAINTAINERSD07-Feb-20251.8 KiB5545

Makefile.amD12-Aug-20245.9 KiB228179

Makefile.inD07-Feb-2025275.5 KiB6,0325,402

README-HACKINGD07-Feb-202512.2 KiB338260

aclocal.m4D12-Aug-202443.2 KiB1,1971,090

config.h.inD12-Aug-202414.4 KiB566387

configureD07-Feb-2025560.1 KiB20,05716,713

configure.acD07-Feb-20255 KiB167149

gdbinit.inD30-Jul-2023364 1512

README-HACKING

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
10- C Language Assumptions
11- "dump" commands under gdb
12
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. common/local.mk)
21
22In addition "common" contains portions of the system call support
23(e.g. callback.c, target-newlib-*.c).
24
25TAGS support
26============
27
28Many files generate program symbols at compile time.
29Such symbols can't be found with grep nor do they normally appear in
30the TAGS file.  To get around this, source files can add the comment
31
32/* TAGS: foo1 foo2 */
33
34where foo1, foo2 are program symbols.  Symbols found in such comments
35are greppable and appear in the TAGS file.
36
37Generating "configure" files
38============================
39
40"configure" can be generated by running `autoreconf'.
41
42C Language Assumptions
43======================
44
45An ISO C11 compiler is required, as is an ISO C standard library.
46
47"dump" commands under gdb
48=========================
49
50gdbinit.in contains the following
51
52define dump
53set sim_debug_dump ()
54end
55
56Simulators that define the sim_debug_dump function can then have their
57internal state pretty printed from gdb.
58
59FIXME: This can obviously be made more elaborate.  As needed it will be.
60
61Rebuilding target-newlib-* files
62================================
63
64Checkout a copy of the SIM and LIBGLOSS modules (Unless you've already
65got one to hand):
66
67          $  mkdir /tmp/$$
68          $  cd /tmp/$$
69          $  cvs checkout sim-no-testsuite libgloss-no-testsuite newlib-no-testsuite
70
71Configure things for an arbitrary simulator target (d10v is used here for
72convenience):
73
74          $  mkdir /tmp/$$/build
75          $  cd /tmp/$$/build
76          $  /tmp/$$/devo/configure --target=d10v-elf
77
78In the sim/ directory rebuild the headers:
79
80          $  cd sim/
81          $  make nltvals
82
83If the target uses the common syscall table (libgloss/syscall.h), then you're
84all set!  If the target has a custom syscall table, you need to declare it:
85
86          devo/sim/common/gennltvals.py
87
88                    Add your new processor target (you'll need to grub
89                    around to find where your syscall.h lives).
90
91          devo/sim/<processor>/*.[ch]
92
93                    Include target-newlib-syscall.h instead of syscall.h.
94
95Tracing
96=======
97
98For ports based on CGEN, tracing instrumentation should largely be for free,
99so we will cover the basic non-CGEN setup here.  The assumption is that your
100target is using the common autoconf macros and so the build system already
101includes the sim-trace configure flag.
102
103The full tracing API is covered in sim-trace.h, so this section is an overview.
104
105Before calling any trace function, you should make a call to the trace_prefix()
106function.  This is usually done in the main sim_engine_run() loop before
107simulating the next instruction.  You should make this call before every
108simulated insn.  You can probably copy & paste this:
109  if (TRACE_ANY_P (cpu))
110    trace_prefix (sd, cpu, NULL_CIA, oldpc, TRACE_LINENUM_P (cpu), NULL, 0, "");
111
112You will then need to instrument your simulator code with calls to the
113trace_generic() function with the appropriate trace index.  Typically, this
114will take a form similar to the above snippet.  So to trace instructions, you
115would use something like:
116  if (TRACE_INSN_P (cpu))
117    trace_generic (sd, cpu, TRACE_INSN_IDX, "NOP;");
118
119The exact output format is up to you.  See the trace index enum in sim-trace.h
120to see the different tracing info available.
121
122To utilize the tracing features at runtime, simply use the --trace-xxx flags.
123  run --trace-insn ./some-program
124
125Profiling
126=========
127
128Similar to the tracing section, this is merely an overview for non-CGEN based
129ports.  The full API may be found in sim-profile.h.  Its API is also similar
130to the tracing API.
131
132Note that unlike the tracing command line options, in addition to the profile
133flags, you have to use the --verbose option to view the summary report after
134execution.  Tracing output is displayed on the fly, but the profile output is
135only summarized.
136
137To profile core accesses (such as data reads/writes and insn fetches), add
138calls to PROFILE_COUNT_CORE() to your read/write functions.  So in your data
139fetch function, you'd use something like:
140  PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_read);
141Then in your data write function:
142  PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_write);
143And in your insn fetcher:
144  PROFILE_COUNT_CORE (cpu, target_addr, size_in_bytes, map_exec);
145
146To use the PC profiling code, you simply have to tell the system where to find
147your simulator's PC.  So in your model initialization function:
148  CPU_PC_FETCH (cpu) = function_that_fetches_the_pc;
149
150To profile branches, in every location where a branch insn is executed, call
151one of the related helpers:
152  PROFILE_BRANCH_TAKEN (cpu);
153  PROFILE_BRANCH_UNTAKEN (cpu);
154If you have stall information, you can utilize the other helpers too.
155
156Environment Simulation
157======================
158
159The simplest simulator doesn't include environment support -- it merely
160simulates the Instruction Set Architecture (ISA).  Once you're ready to move
161on to the next level, it's time to start handling the --env option.  It's
162enabled by default for all ports already.
163
164This will support for the user, virtual, and operating environments.  See the
165sim-config.h header for a more detailed description of them.  The former are
166pretty straight forward as things like exceptions (making system calls) are
167handled in the simulator.  Which is to say, an exception does not trigger an
168exception handler in the simulator target -- that is what the operating env
169is about.  See the following userspace section for more information.
170
171Userspace System Calls
172======================
173
174By default, the libgloss userspace is simulated.  That means the system call
175numbers and calling convention matches that of libgloss.  Simulating other
176userspaces (such as Linux) is pretty straightforward, but let's first focus
177on the basics.  The basic API is covered in include/sim/callback.h.
178
179When an instruction is simulated that invokes the system call method (such as
180forcing a hardware trap or exception), your simulator code should set up the
181CB_SYSCALL data structure before calling the common cb_syscall() function.
182For example:
183static int
184syscall_read_mem (host_callback *cb, struct cb_syscall *sc,
185                      unsigned long taddr, char *buf, int bytes)
186{
187  SIM_DESC sd = (SIM_DESC) sc->p1;
188  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
189  return sim_core_read_buffer (sd, cpu, read_map, buf, taddr, bytes);
190}
191static int
192syscall_write_mem (host_callback *cb, struct cb_syscall *sc,
193                      unsigned long taddr, const char *buf, int bytes)
194{
195  SIM_DESC sd = (SIM_DESC) sc->p1;
196  SIM_CPU *cpu = (SIM_CPU *) sc->p2;
197  return sim_core_write_buffer (sd, cpu, write_map, buf, taddr, bytes);
198}
199void target_sim_syscall (SIM_CPU *cpu)
200{
201  SIM_DESC sd = CPU_STATE (cpu);
202  host_callback *cb = STATE_CALLBACK (sd);
203  CB_SYSCALL sc;
204
205  CB_SYSCALL_INIT (&sc);
206
207  sc.func = <fetch system call number>;
208  sc.arg1 = <fetch first system call argument>;
209  sc.arg2 = <fetch second system call argument>;
210  sc.arg3 = <fetch third system call argument>;
211  sc.arg4 = <fetch fourth system call argument>;
212  sc.p1 = (PTR) sd;
213  sc.p2 = (PTR) cpu;
214  sc.read_mem = syscall_read_mem;
215  sc.write_mem = syscall_write_mem;
216
217  cb_syscall (cb, &sc);
218
219  <store system call result from sc.result>;
220  <store system call error from sc.errcode>;
221}
222Some targets store the result and error code in different places, while others
223only store the error code when the result is an error.
224
225Keep in mind that the CB_SYS_xxx defines are normalized values with no real
226meaning with respect to the target.  They provide a unique map on the host so
227that it can parse things sanely.  For libgloss, the common/target-newlib-syscall
228file contains the target's system call numbers to the CB_SYS_xxx values.
229
230To simulate other userspace targets, you really only need to update the maps
231pointers that are part of the callback interface.  So create CB_TARGET_DEFS_MAP
232arrays for each set (system calls, errnos, open bits, etc...) and in a place
233you find useful, do something like:
234
235...
236static CB_TARGET_DEFS_MAP cb_linux_syscall_map[] = {
237# define TARGET_LINUX_SYS_open 5
238  { CB_SYS_open, TARGET_LINUX_SYS_open },
239  ...
240  { -1, -1 },
241};
242...
243  host_callback *cb = STATE_CALLBACK (sd);
244  cb->syscall_map = cb_linux_syscall_map;
245  cb->errno_map = cb_linux_errno_map;
246  cb->open_map = cb_linux_open_map;
247  cb->signal_map = cb_linux_signal_map;
248  cb->stat_map = cb_linux_stat_map;
249...
250
251Each of these cb_linux_*_map's are manually declared by the arch target.
252
253The target_sim_syscall() example above will then work unchanged (ignoring the
254system call convention) because all of the callback functions go through these
255mapping arrays.
256
257Events
258======
259
260Events are scheduled and executed on behalf of either a cpu or hardware devices.
261The API is pretty much the same and can be found in common/sim-events.h and
262common/hw-events.h.
263
264For simulator targets, you really just have to worry about the schedule and
265deschedule functions.
266
267Device Trees
268============
269
270The device tree model is based on the OpenBoot specification.  Since this is
271largely inherited from the psim code, consult the existing psim documentation
272for some in-depth details.
273          http://sourceware.org/psim/manual/
274
275Hardware Devices
276================
277
278The simplest simulator doesn't include hardware device support.  Once you're
279ready to move on to the next level, declare in your Makefile.in:
280SIM_EXTRA_HW_DEVICES = devone devtwo devthree
281
282The basic hardware API is documented in common/hw-device.h.
283
284Each device has to have a matching file name with a "dv-" prefix.  So there has
285to be a dv-devone.c, dv-devtwo.c, and dv-devthree.c files.  Further, each file
286has to have a matching hw_descriptor structure.  So the dv-devone.c file has to
287have something like:
288  const struct hw_descriptor dv_devone_descriptor[] = {
289    {"devone", devone_finish,},
290    {NULL, NULL},
291  };
292
293The "devone" string as well as the "devone_finish" function are not hard
294requirements, just common conventions.  The structure name is a hard
295requirement.
296
297The devone_finish() callback function is used to instantiate this device by
298parsing the corresponding properties in the device tree.
299
300Hardware devices typically attach address ranges to themselves.  Then when
301accesses to those addresses are made, the hardware will have its callback
302invoked.  The exact callback could be a normal I/O read/write access, as
303well as a DMA access.  This makes it easy to simulate memory mapped registers.
304
305Keep in mind that like a proper device driver, it may be instantiated many
306times over.  So any device state it needs to be maintained should be allocated
307during the finish callback and attached to the hardware device via set_hw_data.
308Any hardware functions can access this private data via the hw_data function.
309
310Ports (Interrupts / IRQs)
311=========================
312
313First, a note on terminology.  A "port" is an aspect of a hardware device that
314accepts or generates interrupts.  So devices with input ports may be the target
315of an interrupt (accept it), and/or they have output ports so that they may be
316the source of an interrupt (generate it).
317
318Each port has a symbolic name and a unique number.  These are used to identify
319the port in different contexts.  The output port name has no hard relationship
320to the input port name (same for the unique number).  The callback that accepts
321the interrupt uses the name/id of its input port, while the generator function
322uses the name/id of its output port.
323
324The device tree is used to connect the output port of a device to the input
325port of another device.  There are no limits on the number of inputs connected
326to an output, or outputs to an input, or the devices attached to the ports.
327In other words, the input port and output port could be the same device.
328
329The basics are:
330 - each hardware device declares an array of ports (hw_port_descriptor).
331   any mix of input and output ports is allowed.
332 - when setting up the device, attach the array (set_hw_ports).
333 - if the device accepts interrupts, it will have to attach a port callback
334   function (set_hw_port_event)
335 - connect ports with the device tree
336 - handle incoming interrupts with the callback
337 - generate outgoing interrupts with hw_port_event
338