玄铁openC906仿真bug(printf不能输出)


前言

        本文主要解决C906在仿真过程中,Printf不可以正常在终端打印的BUG。

        (最近也在做基于C906的Linux系统,感兴趣的可以点个star

                https://github.com/sususjysjy/Linux-on-c906-with-litex.git


一、Open-C906

        最近要构建在Riscv上运行的Linux系统,开源的Riscv核本就不多,还需要同时满足有MMU的要求。Rocket Chip、Vexriscv、Xiangshan都是不错的选择,可惜都是Spinal或者Scala,实在是不太会,只能使用平头哥的开源CPU。

        开源的带有MMU的只有C开头的核,所以权衡资源,最终选择了C906.

二、C906仿真环境

        平头哥仿真平台的搭建别的博主已经讲解很详细了,我这里主要说一下搭建后的CASE例程。

1.脚本修改

        首先看MAKEFILE,C906默认的sim软件是iverilog,但是编译速度太慢了,所iverilog改为vcs进行编译。

################################################################################
# Simulation related
################################################################################
SIM = iverilog
DUMP = off

//修改后

################################################################################
# Simulation related
################################################################################
SIM = vcs
DUMP = on
 
 

2.CASE例程

        可以先看一下C906的CASE。

        我们跑一下coremark跑分,可以看到终端结果。

       

        可以看到,仿真成功,但是终端没有任何输出,去看一下coremark源文件,是否有printf内容。

  #define FREQ 100000000 
  
  vtimer_end= get_vtimer(); 
  vcycles = vtimer_end - vtimer_start;
  vcycles = vcycles/iterations;
  printf ("\nVCUNT_SIM: CoreMark has been run %d times, one times cost %d cycles !\n",iterations,vcycles);
  float score;
//  score = FREQ/(float)vcycles;
//  printf ("\nVCUNT_SIM: CoreMark 1.0 : %f iterations/sec\n",score); //CoreMark = iterations of a sec
  score = 1000000/(float)vcycles; //to relieve relations with FREQ
  printf ("\nVCUNT_SIM: CoreMark 1.0 : %f (iterations/sec)/MHz\n",score); //CoreMark = iterations of a sec
  sim_end();

        代码中是有对跑分结果做输出,但是终端没有正确打印,那么我们需要追溯printf底层定义的打印寄存器地址是什么。可以看到是0x6000fff8,同时,我们也需要找tb中规定的打印地址是否相同。

int fputc(int ch, FILE *stream)
{ 
  asm(
      "li   x13, 0x6000fff8 \n\t" 
      "sw   %0, 0(x13) \n\t"
      : :"r" (ch): "x13" );
}
  else if((cpu_awlen[3:0] == 4'b0) &&
     (cpu_awaddr[31:0] == 32'h10015000) &&
      cpu_wvalid)

         这里其实就发现有问题,底层lib定义的地址是  0x6000fff8,而axi总线读数据所监测的地址是  0x10015000,两个是无法对应的,所以执行printf时,没有去正确地址的寄存器去读地址,自然终端不会有输出。

3.BUG修改

        所以首先想到的是将两者地址改为相同即可,我们均改为0x10015000,重新运行CASE。

        很奇怪,任然没有打印。

        检查原因,打印的地址不能是tb中的地址,也不能是c910核心使用的地址。函数的写入fputc必须到达顶部,而不会在缓存处停止(因此它必须位于不可缓存区域)。手册上说,当不使用虚拟内存时,PMA设置可以在C906_RTL_FACTORY/gen_rtl/mmu/rtl/sysmap.h 在那里,我们看到直到0x8fffffff,该区域都是可缓存的(c910 的设置不同)。然后,直到0xbfffffff,它是不可缓存的。

        所以我们找到了原因,打印的地址要将其定义在不可缓存区域,所以大于0x8fffffff,我们将打印地址设置为0x90000000,重新运行CASE。

        

         ok,可以正常在终端输出!!

猜你喜欢

转载自blog.csdn.net/m0_45287781/article/details/133365665