• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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