FPGA開発日記

カテゴリ別記事インデックス https://msyksphinz.github.io/github_pages , English Version https://fpgadevdiary.hatenadiary.com/

Vivado-HLSを使って高位合成でCPUを作ってみる(8. RISC-VのテストベンチをすべてPassさせる)

Vivado-HLSを使って簡単なRISC-V CPUを作ってみている。

すべてのテストパタンを通したいのだが、バスをどのように作ればよいのか迷っている。

これまでは32bitでバスを作っていた。これは通常のLW/SW命令だとよいのだが、HalfWord, Byteのロードストアでは問題となる。 そこで、バスそのものを8bitに絞り、そこからアクセスサイズの分だけメモリに読み書きを行う、というのはどうだろう?

uint32_t mem[128];

// Store Word
mem[addr >> 2] = data;
// Store Halfword
uint16_t *mem_hword = (uint16_t *)mem;
mem_hword[addr >> 1] = data;
// Store Byte
uint8_t *mem_bword = (uint8_t *)mem;
mem_hword[addr] = data;

残念ながら、この方法は上手くいかなかった。Cosimulationの際に以下のようなエラーが出る。 どうやらこのようなキャストは許されないようだ。

INFO: [XFORM 203-602] Inlining function 'rv32_cpu::is_finish_cpu' into 'cpu_hls' (cpu_hls.cpp:19) automatically.
INFO: [XFORM 203-602] Inlining function 'rv32_cpu::get_tohost' into 'cpu_hls' (cpu_hls.cpp:21) automatically.
ERROR: [SYNCHK 200-41] rv32_cpu.cpp:25: unsupported pointer reinterpretation from type 'rv32_cpu' to type 'i32*' on variable 'data_mem'.
INFO: [SYNCHK 200-10] 1 error(s), 0 warning(s).
ERROR: [HLS 200-70] Synthesizability check failed.
command 'ap_source' returned error code
    while executing
"source script.tcl"

仕方がないので、LWの場合は8ビットのメモリに対して4回アクセスするような記述に直した。 このあたり、AXIにうまくフィットさせるためにはどのような記述をすればよいのだろう?

          case SIZE_BYTE  : {
            return (m_data_mem[addr] & 0x0ff);
          }
          case SIZE_HWORD : {
            return ((m_data_mem[addr + 1] << 8) |
                    (m_data_mem[addr + 0] << 0)) & 0x0ffff;
          }
          case SIZE_WORD : {
            return ((XLEN_t)(m_data_mem[addr + 3]) << 24) |
                   ((XLEN_t)(m_data_mem[addr + 2]) << 16) |
                   ((XLEN_t)(m_data_mem[addr + 1]) <<  8) |
                   ((XLEN_t)(m_data_mem[addr + 0]) <<  0);
          }

という訳で、一応rv32ui-p-xxxのテストパタンをすべて通すようにした。一応、すべて通るようになった。

github.com

make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-srai TEST_PATTERN=rv32ui-p-srai.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lw TEST_PATTERN=rv32ui-p-lw.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-fence_i TEST_PATTERN=rv32ui-p-fence_i.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lbu TEST_PATTERN=rv32ui-p-lbu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-jalr TEST_PATTERN=rv32ui-p-jalr.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-beq TEST_PATTERN=rv32ui-p-beq.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-ori TEST_PATTERN=rv32ui-p-ori.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-simple TEST_PATTERN=rv32ui-p-simple.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sltiu TEST_PATTERN=rv32ui-p-sltiu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sll TEST_PATTERN=rv32ui-p-sll.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-bgeu TEST_PATTERN=rv32ui-p-bgeu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-jal TEST_PATTERN=rv32ui-p-jal.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-add TEST_PATTERN=rv32ui-p-add.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lui TEST_PATTERN=rv32ui-p-lui.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-srli TEST_PATTERN=rv32ui-p-srli.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sw TEST_PATTERN=rv32ui-p-sw.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-xori TEST_PATTERN=rv32ui-p-xori.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lh TEST_PATTERN=rv32ui-p-lh.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-auipc TEST_PATTERN=rv32ui-p-auipc.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-srl TEST_PATTERN=rv32ui-p-srl.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sh TEST_PATTERN=rv32ui-p-sh.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-or TEST_PATTERN=rv32ui-p-or.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lb TEST_PATTERN=rv32ui-p-lb.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-slt TEST_PATTERN=rv32ui-p-slt.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sub TEST_PATTERN=rv32ui-p-sub.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-slli TEST_PATTERN=rv32ui-p-slli.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-and TEST_PATTERN=rv32ui-p-and.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-lhu TEST_PATTERN=rv32ui-p-lhu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-bltu TEST_PATTERN=rv32ui-p-bltu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sb TEST_PATTERN=rv32ui-p-sb.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-addi TEST_PATTERN=rv32ui-p-addi.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-slti TEST_PATTERN=rv32ui-p-slti.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sra TEST_PATTERN=rv32ui-p-sra.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-blt TEST_PATTERN=rv32ui-p-blt.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-andi TEST_PATTERN=rv32ui-p-andi.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-xor TEST_PATTERN=rv32ui-p-xor.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-sltu TEST_PATTERN=rv32ui-p-sltu.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-bge TEST_PATTERN=rv32ui-p-bge.hex > /dev/null
make -f ../common/csim.mk HLS_SOLUTION=rv32ui-p-bne TEST_PATTERN=rv32ui-p-bne.hex > /dev/null

次に、性能確認と拡張を行っていく。