Debugging gem5
原英文版在https://www.gem5.org/documentation/learning_gem5/part2/debugging
Using debug flags
调试标志用于debug。通常在gem5,不能使用 std::cout
,而应借助调试标志进行输出。
gem5通过可选的调试标志(--debug-flag
)提供printf风格的跟踪/调试支持。
用--debug-help
可获取调试标志说明(启用多种调试标志用逗号隔开)。
下面以Exec介绍一个例子
build/RISCV/gem5.opt --debug-flags=Exec configs/learning_gem5/part1/simple-riscv.py | head -n 50
Exec本身就是很多调试标志的集合
因为,debug输出信息很多,所以这里只取前面一部分
Adding a new debug flag
-
创建新调试标记时,我们首先要在 SConscript 文件中声明它。 将以下内容添加到包含 hello 对象代码的目录(src/learning_gem5/SConscript中)。
DebugFlag('HelloExample')
-
通过在 SConscript 文件中声明调试标志,调试头文件会自动生成,允许我们使用调试标志。头文件在./build/{ISA}/debug/HelloExample.hh调试目录中,其名称(和大小写)与我们在 SConscript 文件中声明的名称相同。 因此,我们需要在任何计划使用调试标记的文件中包含自动生成的头文件。(记得修改后要重新构建一下
scons build/X86/gem5.opt
)#include "base/trace.hh" #include "debug/HelloExample.hh"
-
通过宏
DPRINTF
使用DPRINTF(HelloExample, "Created the hello object\n");
这里需要解释一下
DPRINTF
,宏展开如下。每次执行动态 DPRINTF 时,都会向 stdout 打印三项内容。 第一,执行 DPRINTF 时的当前刻度curTick()
。 第二,调用 DPRINTF 的模拟对象的名称name()
。 该名称通常是 Python 配置文件中实例的名字,即SimObject name()
函数返回的名称。 第三,是传递给 DPRINTF 函数的格式字符串。#define DPRINTF(x,__VA_ARGS__...) do { if (GEM5_UNLIKELY(TRACING_ON && ::gem5::debug::x)) { ::gem5::trace::getDebugLogger()->dprintf_flag( ::gem5::curTick(), name(), #x, __VA_ARGS__); } } while (0) 扩展到: do { if (__builtin_expect(!!(TRACING_ON && ::gem5::debug::HelloExample), 0)) { ::gem5::trace::getDebugLogger()->dprintf_flag( ::gem5::curTick(), name(), "HelloExample", "Created the hello object\n"); } } while (0)
Debug output
默认情况下,所有调试输出都打印到 stdout。 也可以使用--debug-file
参数控制调试输出的位置,比如用以下命令
build/X86/gem5.opt --debug-flags=HelloExample --debug-file debug.txt xxx.py
输出会重定向到./m5out/debug.txt
中。
Using functions other than DPRINTF
DPRINTF
是最常用的。此外gem5还有其他调试功能,参考见https://doxygen.gem5.org/release/current/base_2trace_8hh.html
这些函数与之前的 :cppDDUMP、:cppDPRINTF 和 :cppDPRINTFR
函数类似,只是它们不将标志作为参数。所有这些函数只有在以 "opt"或 "debug"模式编译 gem5 时才会启用。 所有其他模式都为上述函数使用空占位符宏,因此,如果要使用调试标记,必须使用 "gem5.opt "或 "gem5.debug"。