at v3.0-rc7 643 lines 17 kB view raw
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 */ 57static inline int 58sim_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 */ 70static __inline void 71sim_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 */ 91static __inline unsigned int 92sim_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 */ 117static __inline void 118sim_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 */ 145static __inline void 146sim_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 */ 157static __inline void 158sim_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 */ 175static __inline void 176sim_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 */ 199static __inline void 200sim_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 */ 223static __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 231static __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 239static __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 253static __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 264static __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 276static __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 310static __inline int 311sim_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 322static __inline int 323sim_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 */ 337struct 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 357static __inline struct SimQueryWatchpointStatus 358sim_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. */ 373static __inline void 374sim_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. */ 386static __inline long 387sim_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 */ 427static __inline int 428sim_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. */ 443static __inline void 444sim_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. */ 452static __inline void 453sim_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 */ 489static __inline void 490sim_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. */ 497static __inline void 498sim_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 */ 513static __inline void 514sim_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 */ 529static __inline int 530sim_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 */ 542static __inline void 543sim_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 */ 564static __inline void 565sim_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 */ 586static __inline void 587sim_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 */ 608static __inline void 609sim_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 621static __inline void 622sim_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 629static __inline void 630sim_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/** @} */