【问题标题】:Using C++ Emulator fails when calling printf syscall from a RISC-V baremetal program从 RISC-V 裸机程序调用 printf 系统调用时,使用 C++ 仿真器失败
【发布时间】:2018-04-11 18:13:00
【问题描述】:

我正在开发一个基于 Rocket-Chip 工具的项目。我制作了一个简单的裸机程序,在 Spike 上运行良好(即使有多个内核......等等)。

问题是当我在 C++ 模拟器中运行它时,后者在第一次 printf 调用中停止。

我的问题是:是否可以从 C 模拟器调用系统调用(如 printf、putchar ..)?或者有什么方法可以从模拟中打印程序的结果,比如获取数据存储器之类的? (我为此苦苦挣扎,但没有找到它保存数据变量的位置)。

PS:该程序基于riscv-tests/benchmarks,系统调用已在那里定义。

【问题讨论】:

  • 什么是C++ 模拟器
  • 如果你使用C++,C语言标签的作用是什么?请不要使用不相关的标签。
  • @VTT C++ Emulator 是 CABA(周期精确位精确)模拟器,用于模拟软件并考虑您的个性化硬件。 Spike 只是一个功能模拟器,并没有考虑到你的硬件。
  • @Gerhardh 因为模拟器是用 C++ 编写的,但运行在上面的程序是用 C 编写的。

标签: c++ c riscv bare-metal chisel


【解决方案1】:

是否可以从 C 调用系统调用(如 printf、putchar ..) 模拟器?

是的,这些函数已经在代码库中定义了here

根据代码库,全局外部变量指向的数据地址,需要从这个地址读取4个64位数据的索引

extern volatile uint64_t tohost;
extern volatile uint64_t fromhost;

使用此syscall 实现的printf(), putchar()

static uintptr_t syscall(uintptr_t which, uint64_t arg0, uint64_t arg1, uint64_t arg2)
{
  volatile uint64_t magic_mem[8] __attribute__((aligned(64)));
  magic_mem[0] = which;
  magic_mem[1] = arg0;
  magic_mem[2] = arg1;
  magic_mem[3] = arg2;
  __sync_synchronize();

  tohost = (uintptr_t)magic_mem;
  while (fromhost == 0)
    ;
  fromhost = 0;

  __sync_synchronize();
  return magic_mem[0];
}

【讨论】:

  • 我知道这一点。我在这里做了一个小例子:github.com/noureddine-as/riscv-baremetal-DefaultConfig 在模拟器上执行这个可以正确打印 hello 消息。然后我又做了一个,但这一次它在 C++ 模拟器中给了我*** FAILED *** (tohost = 1337) *** FAILED *** via dtm (code = 1337, seed 1523460801) after 208588 cycles,即使它在 Spike 模拟中运行良好!有什么想法吗?
  • 这里uint64_t magic_mem[8] __attribute__((aligned(64)));数组大小是8 * 8,所以可能是溢出导致208588循环后失败
  • 我解决了这个问题。我说,如果我把 printf("something"); 放在没有 \n 的情况下,它在 pk 或裸机的两种情况下都不会打印。我没有调查真正的来源,但我认为这是因为 printf 在系统调用中重新实现,我不使用标准的。此外,我猜 Spike 仍在等待 \n 打印文本。无论如何,它现在有效。我想知道@Thiru 是如何使用 Spike 尤其是 C++ Emulator 调试程序?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-17
  • 1970-01-01
  • 1970-01-01
  • 2012-02-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多