1 /*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
12 * more details.
13 */
14
15 /**
16 * @file
17 *
18 * Provides an API for controlling the simulator at runtime.
19 */
20
21 /**
22 * @addtogroup arch_sim
23 * @{
24 *
25 * An API for controlling the simulator at runtime.
26 *
27 * The simulator's behavior can be modified while it is running.
28 * For example, human-readable trace output can be enabled and disabled
29 * around code of interest.
30 *
31 * There are two ways to modify simulator behavior:
32 * programmatically, by calling various sim_* functions, and
33 * interactively, by entering commands like "sim set functional true"
34 * at the tile-monitor prompt. Typing "sim help" at that prompt provides
35 * a list of interactive commands.
36 *
37 * All interactive commands can also be executed programmatically by
38 * passing a string to the sim_command function.
39 */
40
41 #ifndef __ARCH_SIM_H__
42 #define __ARCH_SIM_H__
43
44 #include <arch/sim_def.h>
45 #include <arch/abi.h>
46
47 #ifndef __ASSEMBLER__
48
49 #include <arch/spr_def.h>
50
51
52 /**
53 * Return true if the current program is running under a simulator,
54 * rather than on real hardware. If running on hardware, other "sim_xxx()"
55 * calls have no useful effect.
56 */
57 static inline int
sim_is_simulator(void)58 sim_is_simulator(void)
59 {
60 return __insn_mfspr(SPR_SIM_CONTROL) != 0;
61 }
62
63
64 /**
65 * Checkpoint the simulator state to a checkpoint file.
66 *
67 * The checkpoint file name is either the default or the name specified
68 * on the command line with "--checkpoint-file".
69 */
70 static __inline void
sim_checkpoint(void)71 sim_checkpoint(void)
72 {
73 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_CHECKPOINT);
74 }
75
76
77 /**
78 * Report whether or not various kinds of simulator tracing are enabled.
79 *
80 * @return The bitwise OR of these values:
81 *
82 * SIM_TRACE_CYCLES (--trace-cycles),
83 * SIM_TRACE_ROUTER (--trace-router),
84 * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
85 * SIM_TRACE_DISASM (--trace-disasm),
86 * SIM_TRACE_STALL_INFO (--trace-stall-info)
87 * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
88 * SIM_TRACE_L2_CACHE (--trace-l2)
89 * SIM_TRACE_LINES (--trace-lines)
90 */
91 static __inline unsigned int
sim_get_tracing(void)92 sim_get_tracing(void)
93 {
94 return __insn_mfspr(SPR_SIM_CONTROL) & SIM_TRACE_FLAG_MASK;
95 }
96
97
98 /**
99 * Turn on or off different kinds of simulator tracing.
100 *
101 * @param mask Either one of these special values:
102 *
103 * SIM_TRACE_NONE (turns off tracing),
104 * SIM_TRACE_ALL (turns on all possible tracing).
105 *
106 * or the bitwise OR of these values:
107 *
108 * SIM_TRACE_CYCLES (--trace-cycles),
109 * SIM_TRACE_ROUTER (--trace-router),
110 * SIM_TRACE_REGISTER_WRITES (--trace-register-writes),
111 * SIM_TRACE_DISASM (--trace-disasm),
112 * SIM_TRACE_STALL_INFO (--trace-stall-info)
113 * SIM_TRACE_MEMORY_CONTROLLER (--trace-memory-controller)
114 * SIM_TRACE_L2_CACHE (--trace-l2)
115 * SIM_TRACE_LINES (--trace-lines)
116 */
117 static __inline void
sim_set_tracing(unsigned int mask)118 sim_set_tracing(unsigned int mask)
119 {
120 __insn_mtspr(SPR_SIM_CONTROL, SIM_TRACE_SPR_ARG(mask));
121 }
122
123
124 /**
125 * Request dumping of different kinds of simulator state.
126 *
127 * @param mask Either this special value:
128 *
129 * SIM_DUMP_ALL (dump all known state)
130 *
131 * or the bitwise OR of these values:
132 *
133 * SIM_DUMP_REGS (the register file),
134 * SIM_DUMP_SPRS (the SPRs),
135 * SIM_DUMP_ITLB (the iTLB),
136 * SIM_DUMP_DTLB (the dTLB),
137 * SIM_DUMP_L1I (the L1 I-cache),
138 * SIM_DUMP_L1D (the L1 D-cache),
139 * SIM_DUMP_L2 (the L2 cache),
140 * SIM_DUMP_SNREGS (the switch register file),
141 * SIM_DUMP_SNITLB (the switch iTLB),
142 * SIM_DUMP_SNL1I (the switch L1 I-cache),
143 * SIM_DUMP_BACKTRACE (the current backtrace)
144 */
145 static __inline void
sim_dump(unsigned int mask)146 sim_dump(unsigned int mask)
147 {
148 __insn_mtspr(SPR_SIM_CONTROL, SIM_DUMP_SPR_ARG(mask));
149 }
150
151
152 /**
153 * Print a string to the simulator stdout.
154 *
155 * @param str The string to be written.
156 */
157 static __inline void
sim_print(const char * str)158 sim_print(const char* str)
159 {
160 for ( ; *str != '\0'; str++)
161 {
162 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
163 (*str << _SIM_CONTROL_OPERATOR_BITS));
164 }
165 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
166 (SIM_PUTC_FLUSH_BINARY << _SIM_CONTROL_OPERATOR_BITS));
167 }
168
169
170 /**
171 * Print a string to the simulator stdout.
172 *
173 * @param str The string to be written (a newline is automatically added).
174 */
175 static __inline void
sim_print_string(const char * str)176 sim_print_string(const char* str)
177 {
178 for ( ; *str != '\0'; str++)
179 {
180 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
181 (*str << _SIM_CONTROL_OPERATOR_BITS));
182 }
183 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
184 (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
185 }
186
187
188 /**
189 * Execute a simulator command string.
190 *
191 * Type 'sim help' at the tile-monitor prompt to learn what commands
192 * are available. Note the use of the tile-monitor "sim" command to
193 * pass commands to the simulator.
194 *
195 * The argument to sim_command() does not include the leading "sim"
196 * prefix used at the tile-monitor prompt; for example, you might call
197 * sim_command("trace disasm").
198 */
199 static __inline void
sim_command(const char * str)200 sim_command(const char* str)
201 {
202 int c;
203 do
204 {
205 c = *str++;
206 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_COMMAND |
207 (c << _SIM_CONTROL_OPERATOR_BITS));
208 }
209 while (c);
210 }
211
212
213
214 #ifndef __DOXYGEN__
215
216 /**
217 * The underlying implementation of "_sim_syscall()".
218 *
219 * We use extra "and" instructions to ensure that all the values
220 * we are passing to the simulator are actually valid in the registers
221 * (i.e. returned from memory) prior to the SIM_CONTROL spr.
222 */
_sim_syscall0(int val)223 static __inline long _sim_syscall0(int val)
224 {
225 long result;
226 __asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
227 : "=R00" (result) : "R00" (val));
228 return result;
229 }
230
_sim_syscall1(int val,long arg1)231 static __inline long _sim_syscall1(int val, long arg1)
232 {
233 long result;
234 __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
235 : "=R00" (result) : "R00" (val), "R01" (arg1));
236 return result;
237 }
238
_sim_syscall2(int val,long arg1,long arg2)239 static __inline long _sim_syscall2(int val, long arg1, long arg2)
240 {
241 long result;
242 __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
243 : "=R00" (result)
244 : "R00" (val), "R01" (arg1), "R02" (arg2));
245 return result;
246 }
247
248 /* Note that _sim_syscall3() and higher are technically at risk of
249 receiving an interrupt right before the mtspr bundle, in which case
250 the register values for arguments 3 and up may still be in flight
251 to the core from a stack frame reload. */
252
_sim_syscall3(int val,long arg1,long arg2,long arg3)253 static __inline long _sim_syscall3(int val, long arg1, long arg2, long arg3)
254 {
255 long result;
256 __asm__ __volatile__ ("{ and zero, r3, r3 };"
257 "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
258 : "=R00" (result)
259 : "R00" (val), "R01" (arg1), "R02" (arg2),
260 "R03" (arg3));
261 return result;
262 }
263
_sim_syscall4(int val,long arg1,long arg2,long arg3,long arg4)264 static __inline long _sim_syscall4(int val, long arg1, long arg2, long arg3,
265 long arg4)
266 {
267 long result;
268 __asm__ __volatile__ ("{ and zero, r3, r4 };"
269 "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
270 : "=R00" (result)
271 : "R00" (val), "R01" (arg1), "R02" (arg2),
272 "R03" (arg3), "R04" (arg4));
273 return result;
274 }
275
_sim_syscall5(int val,long arg1,long arg2,long arg3,long arg4,long arg5)276 static __inline long _sim_syscall5(int val, long arg1, long arg2, long arg3,
277 long arg4, long arg5)
278 {
279 long result;
280 __asm__ __volatile__ ("{ and zero, r3, r4; and zero, r5, r5 };"
281 "{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
282 : "=R00" (result)
283 : "R00" (val), "R01" (arg1), "R02" (arg2),
284 "R03" (arg3), "R04" (arg4), "R05" (arg5));
285 return result;
286 }
287
288 /**
289 * Make a special syscall to the simulator itself, if running under
290 * simulation. This is used as the implementation of other functions
291 * and should not be used outside this file.
292 *
293 * @param syscall_num The simulator syscall number.
294 * @param nr The number of additional arguments provided.
295 *
296 * @return Varies by syscall.
297 */
298 #define _sim_syscall(syscall_num, nr, args...) \
299 _sim_syscall##nr( \
300 ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, \
301 ##args)
302
303
304 /* Values for the "access_mask" parameters below. */
305 #define SIM_WATCHPOINT_READ 1
306 #define SIM_WATCHPOINT_WRITE 2
307 #define SIM_WATCHPOINT_EXECUTE 4
308
309
310 static __inline int
sim_add_watchpoint(unsigned int process_id,unsigned long address,unsigned long size,unsigned int access_mask,unsigned long user_data)311 sim_add_watchpoint(unsigned int process_id,
312 unsigned long address,
313 unsigned long size,
314 unsigned int access_mask,
315 unsigned long user_data)
316 {
317 return _sim_syscall(SIM_SYSCALL_ADD_WATCHPOINT, 5, process_id,
318 address, size, access_mask, user_data);
319 }
320
321
322 static __inline int
sim_remove_watchpoint(unsigned int process_id,unsigned long address,unsigned long size,unsigned int access_mask,unsigned long user_data)323 sim_remove_watchpoint(unsigned int process_id,
324 unsigned long address,
325 unsigned long size,
326 unsigned int access_mask,
327 unsigned long user_data)
328 {
329 return _sim_syscall(SIM_SYSCALL_REMOVE_WATCHPOINT, 5, process_id,
330 address, size, access_mask, user_data);
331 }
332
333
334 /**
335 * Return value from sim_query_watchpoint.
336 */
337 struct SimQueryWatchpointStatus
338 {
339 /**
340 * 0 if a watchpoint fired, 1 if no watchpoint fired, or -1 for
341 * error (meaning a bad process_id).
342 */
343 int syscall_status;
344
345 /**
346 * The address of the watchpoint that fired (this is the address
347 * passed to sim_add_watchpoint, not an address within that range
348 * that actually triggered the watchpoint).
349 */
350 unsigned long address;
351
352 /** The arbitrary user_data installed by sim_add_watchpoint. */
353 unsigned long user_data;
354 };
355
356
357 static __inline struct SimQueryWatchpointStatus
sim_query_watchpoint(unsigned int process_id)358 sim_query_watchpoint(unsigned int process_id)
359 {
360 struct SimQueryWatchpointStatus status;
361 long val = SIM_CONTROL_SYSCALL |
362 (SIM_SYSCALL_QUERY_WATCHPOINT << _SIM_CONTROL_OPERATOR_BITS);
363 __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
364 : "=R00" (status.syscall_status),
365 "=R01" (status.address),
366 "=R02" (status.user_data)
367 : "R00" (val), "R01" (process_id));
368 return status;
369 }
370
371
372 /* On the simulator, confirm lines have been evicted everywhere. */
373 static __inline void
sim_validate_lines_evicted(unsigned long long pa,unsigned long length)374 sim_validate_lines_evicted(unsigned long long pa, unsigned long length)
375 {
376 #ifdef __LP64__
377 _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 2, pa, length);
378 #else
379 _sim_syscall(SIM_SYSCALL_VALIDATE_LINES_EVICTED, 4,
380 0 /* dummy */, (long)(pa), (long)(pa >> 32), length);
381 #endif
382 }
383
384
385 /* Return the current CPU speed in cycles per second. */
386 static __inline long
sim_query_cpu_speed(void)387 sim_query_cpu_speed(void)
388 {
389 return _sim_syscall(SIM_SYSCALL_QUERY_CPU_SPEED, 0);
390 }
391
392 #endif /* !__DOXYGEN__ */
393
394
395
396
397 /**
398 * Modify the shaping parameters of a shim.
399 *
400 * @param shim The shim to modify. One of:
401 * SIM_CONTROL_SHAPING_GBE_0
402 * SIM_CONTROL_SHAPING_GBE_1
403 * SIM_CONTROL_SHAPING_GBE_2
404 * SIM_CONTROL_SHAPING_GBE_3
405 * SIM_CONTROL_SHAPING_XGBE_0
406 * SIM_CONTROL_SHAPING_XGBE_1
407 *
408 * @param type The type of shaping. This should be the same type of
409 * shaping that is already in place on the shim. One of:
410 * SIM_CONTROL_SHAPING_MULTIPLIER
411 * SIM_CONTROL_SHAPING_PPS
412 * SIM_CONTROL_SHAPING_BPS
413 *
414 * @param units The magnitude of the rate. One of:
415 * SIM_CONTROL_SHAPING_UNITS_SINGLE
416 * SIM_CONTROL_SHAPING_UNITS_KILO
417 * SIM_CONTROL_SHAPING_UNITS_MEGA
418 * SIM_CONTROL_SHAPING_UNITS_GIGA
419 *
420 * @param rate The rate to which to change it. This must fit in
421 * SIM_CONTROL_SHAPING_RATE_BITS bits or a warning is issued and
422 * the shaping is not changed.
423 *
424 * @return 0 if no problems were detected in the arguments to sim_set_shaping
425 * or 1 if problems were detected (for example, rate does not fit in 17 bits).
426 */
427 static __inline int
sim_set_shaping(unsigned shim,unsigned type,unsigned units,unsigned rate)428 sim_set_shaping(unsigned shim,
429 unsigned type,
430 unsigned units,
431 unsigned rate)
432 {
433 if ((rate & ~((1 << SIM_CONTROL_SHAPING_RATE_BITS) - 1)) != 0)
434 return 1;
435
436 __insn_mtspr(SPR_SIM_CONTROL, SIM_SHAPING_SPR_ARG(shim, type, units, rate));
437 return 0;
438 }
439
440 #ifdef __tilegx__
441
442 /** Enable a set of mPIPE links. Pass a -1 link_mask to enable all links. */
443 static __inline void
sim_enable_mpipe_links(unsigned mpipe,unsigned long link_mask)444 sim_enable_mpipe_links(unsigned mpipe, unsigned long link_mask)
445 {
446 __insn_mtspr(SPR_SIM_CONTROL,
447 (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
448 (mpipe << 8) | (1 << 16) | ((uint_reg_t)link_mask << 32)));
449 }
450
451 /** Disable a set of mPIPE links. Pass a -1 link_mask to disable all links. */
452 static __inline void
sim_disable_mpipe_links(unsigned mpipe,unsigned long link_mask)453 sim_disable_mpipe_links(unsigned mpipe, unsigned long link_mask)
454 {
455 __insn_mtspr(SPR_SIM_CONTROL,
456 (SIM_CONTROL_ENABLE_MPIPE_LINK_MAGIC_BYTE |
457 (mpipe << 8) | (0 << 16) | ((uint_reg_t)link_mask << 32)));
458 }
459
460 #endif /* __tilegx__ */
461
462
463 /*
464 * An API for changing "functional" mode.
465 */
466
467 #ifndef __DOXYGEN__
468
469 #define sim_enable_functional() \
470 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_ENABLE_FUNCTIONAL)
471
472 #define sim_disable_functional() \
473 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_DISABLE_FUNCTIONAL)
474
475 #endif /* __DOXYGEN__ */
476
477
478 /*
479 * Profiler support.
480 */
481
482 /**
483 * Turn profiling on for the current task.
484 *
485 * Note that this has no effect if run in an environment without
486 * profiling support (thus, the proper flags to the simulator must
487 * be supplied).
488 */
489 static __inline void
sim_profiler_enable(void)490 sim_profiler_enable(void)
491 {
492 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_ENABLE);
493 }
494
495
496 /** Turn profiling off for the current task. */
497 static __inline void
sim_profiler_disable(void)498 sim_profiler_disable(void)
499 {
500 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_DISABLE);
501 }
502
503
504 /**
505 * Turn profiling on or off for the current task.
506 *
507 * @param enabled If true, turns on profiling. If false, turns it off.
508 *
509 * Note that this has no effect if run in an environment without
510 * profiling support (thus, the proper flags to the simulator must
511 * be supplied).
512 */
513 static __inline void
sim_profiler_set_enabled(int enabled)514 sim_profiler_set_enabled(int enabled)
515 {
516 int val =
517 enabled ? SIM_CONTROL_PROFILER_ENABLE : SIM_CONTROL_PROFILER_DISABLE;
518 __insn_mtspr(SPR_SIM_CONTROL, val);
519 }
520
521
522 /**
523 * Return true if and only if profiling is currently enabled
524 * for the current task.
525 *
526 * This returns false even if sim_profiler_enable() was called
527 * if the current execution environment does not support profiling.
528 */
529 static __inline int
sim_profiler_is_enabled(void)530 sim_profiler_is_enabled(void)
531 {
532 return ((__insn_mfspr(SPR_SIM_CONTROL) & SIM_PROFILER_ENABLED_MASK) != 0);
533 }
534
535
536 /**
537 * Reset profiling counters to zero for the current task.
538 *
539 * Resetting can be done while profiling is enabled. It does not affect
540 * the chip-wide profiling counters.
541 */
542 static __inline void
sim_profiler_clear(void)543 sim_profiler_clear(void)
544 {
545 __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PROFILER_CLEAR);
546 }
547
548
549 /**
550 * Enable specified chip-level profiling counters.
551 *
552 * Does not affect the per-task profiling counters.
553 *
554 * @param mask Either this special value:
555 *
556 * SIM_CHIP_ALL (enables all chip-level components).
557 *
558 * or the bitwise OR of these values:
559 *
560 * SIM_CHIP_MEMCTL (enable all memory controllers)
561 * SIM_CHIP_XAUI (enable all XAUI controllers)
562 * SIM_CHIP_MPIPE (enable all MPIPE controllers)
563 */
564 static __inline void
sim_profiler_chip_enable(unsigned int mask)565 sim_profiler_chip_enable(unsigned int mask)
566 {
567 __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_ENABLE_SPR_ARG(mask));
568 }
569
570
571 /**
572 * Disable specified chip-level profiling counters.
573 *
574 * Does not affect the per-task profiling counters.
575 *
576 * @param mask Either this special value:
577 *
578 * SIM_CHIP_ALL (disables all chip-level components).
579 *
580 * or the bitwise OR of these values:
581 *
582 * SIM_CHIP_MEMCTL (disable all memory controllers)
583 * SIM_CHIP_XAUI (disable all XAUI controllers)
584 * SIM_CHIP_MPIPE (disable all MPIPE controllers)
585 */
586 static __inline void
sim_profiler_chip_disable(unsigned int mask)587 sim_profiler_chip_disable(unsigned int mask)
588 {
589 __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_DISABLE_SPR_ARG(mask));
590 }
591
592
593 /**
594 * Reset specified chip-level profiling counters to zero.
595 *
596 * Does not affect the per-task profiling counters.
597 *
598 * @param mask Either this special value:
599 *
600 * SIM_CHIP_ALL (clears all chip-level components).
601 *
602 * or the bitwise OR of these values:
603 *
604 * SIM_CHIP_MEMCTL (clear all memory controllers)
605 * SIM_CHIP_XAUI (clear all XAUI controllers)
606 * SIM_CHIP_MPIPE (clear all MPIPE controllers)
607 */
608 static __inline void
sim_profiler_chip_clear(unsigned int mask)609 sim_profiler_chip_clear(unsigned int mask)
610 {
611 __insn_mtspr(SPR_SIM_CONTROL, SIM_PROFILER_CHIP_CLEAR_SPR_ARG(mask));
612 }
613
614
615 /*
616 * Event support.
617 */
618
619 #ifndef __DOXYGEN__
620
621 static __inline void
sim_event_begin(unsigned int x)622 sim_event_begin(unsigned int x)
623 {
624 #if defined(__tile__) && !defined(__NO_EVENT_SPR__)
625 __insn_mtspr(SPR_EVENT_BEGIN, x);
626 #endif
627 }
628
629 static __inline void
sim_event_end(unsigned int x)630 sim_event_end(unsigned int x)
631 {
632 #if defined(__tile__) && !defined(__NO_EVENT_SPR__)
633 __insn_mtspr(SPR_EVENT_END, x);
634 #endif
635 }
636
637 #endif /* !__DOXYGEN__ */
638
639 #endif /* !__ASSEMBLER__ */
640
641 #endif /* !__ARCH_SIM_H__ */
642
643 /** @} */
644