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のテストパタンをすべて通すようにした。一応、すべて通るようになった。
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
次に、性能確認と拡張を行っていく。