読者です 読者をやめる 読者になる 読者になる

FPGA開発日記

FPGAというより、コンピュータアーキテクチャかもね! カテゴリ別記事インデックス https://sites.google.com/site/fpgadevelopindex/

OpenSPARC T1の調査(2)

前回に引き続いて、OpenSPARC T1のシミュレーションを走らせていたが、それっぽい動作をしたものの、イマイチ有益なログを出さずにシミュレーションが終了してしまった。

f:id:msyksphinz:20170226082556p:plain

$ tree .
.
├── bypass_win:model_core1:core1_mini:0
│   ├── diag.s
│   ├── efuse.img
│   ├── flist
│   ├── history.sims
│   ├── perf.log
│   ├── raw_coverage
│   ├── sim.log
│   ├── sim.perf.log
│   ├── sim_command
│   ├── sims.log
│   ├── spd_single_dimm.data
│   ├── spd_stack_dimm.data
│   ├── status.log
│   ├── transcript
│   └── vlog.log
├── flist
├── history.sims
├── ihit_sameset:model_core1:core1_mini:0
│   ├── sim_command
│   └── sims.log
├── imiss_sameset:model_core1:core1_mini:0
├── lock
├── master_diaglist.core1_mini
├── sims.log
└── tre
    ├── sims.iver
    └── sims.tver_0

シミュレーション中に大量のエラーを出しているのが気になる。

# ** Error (suppressible): (vsim-12023) /home/masayuki/work/opensparc/t1//verif/env/cmp/ciop_iob.v(328): Cannot execute undefined system task/function '$iob_jdriver'
# ** Error (suppressible): (vsim-12023) /home/masayuki/work/opensparc/t1//verif/env/cmp/bw_sys.v(99): Cannot execute undefined system task/function '$pc_trigger_event'
# ** Error (suppressible): (vsim-12023) /home/masayuki/work/opensparc/t1//verif/env/cmp/ciop_iob.v(297): Cannot execute undefined system task/function '$iob_cdriver'
# ** Error (suppressible): (vsim-12023) /home/masayuki/work/opensparc/t1//verif/env/cmp/pcx_stall.v(93): Cannot execute undefined system task/function '$pc_trigger_event'
# ** Error (suppressible): (vsim-12023) /home/masayuki/work/opensparc/t1//verif/env/cmp/cpx_stall.v(100): Cannot execute undefined system task/function '$pc_trigger_event'

これはPLIを動かさないと駄目なのか。

$ ag pc_trigger_event

tools/pli/veriuser.c
173:    {usertask, 0, 0, 0, pc_trigger_call, 0, "$pc_trigger_event"},
  • tools/pli/iop/iop_main.cpp
void pc_trigger_call()
{
  switch(tf_getp(PC_TRIG_TY)){
  case 1 :// check for event
    int low, high;
    long long pc;
    low  = tf_getlongp(&high, PC_TRIG_PC);
    pc   = high;
    pc <<= 32;
    pc  |= low;
    if(pli_var.pc_event.hit_pc(pc)){
      while(pli_var.pc_event.which_event()){
        switch(pli_var.pc_event.one_event->type){
        case 1 :
          pli_var.pc_event.print(PC_TRIG_TH, PC_TRIG_WD);
          break;
        case 2 :
          pli_var.pc_event.print(PC_TRIG_TH, PC_TRIG_WD);
          break;
        case 3 :
          pli_var.l2.vld_counter  = pli_var.pc_event.one_event->wait;
          pli_var.l2.cpu          = tf_getp(PC_TRIG_CP);
          pli_var.l2.cpu_invalid  = 0;
          pli_var.l2.l2_bank      = 0xf;//set four bank
          pli_var.l2.cpu_invalid  = 0xff;//8 cpu
          pli_var.l2.cpu_invalid ^= tf_getp(PC_TRIG_AT);
          tf_putp(PC_TRIG_ST, 1);//start counter
          break;
        case WARMRST :
          pli_var.pc_event.set_warm();
          break;
        case EXTINT :
          pli_var.pc_event.set_extint(pli_var.pc_event.one_event->wait);
          break;
        case TEMPTRIG :
          pli_var.pc_event.set_temptrig(pli_var.pc_event.one_event->wait);
...

PLI群も整備しないと、何が起きているのか分からないなあ。。。

OpenSPARC T1の調査(1)

どうもOpenSPARC T2の調査が芳しくないので、一つ前に戻って、OpenSPARC T1について調査してみよう。

まず、simsコマンドについて調査していたのだが、VCS, NC-Verilog以外のシミュレータを使うための手段として、以下のサイトが参考になった。

abishekramdas.blogspot.jp

tar xjf OpenSPARCT1.1.7.tar.bz2
cp OpenSPARCT1.bash OpenSPARCT1.origin.bash
chmod +w OpenSPARCT1.bash
emacs OpenSPARCT1.bash
source OpenSPARCT1.bash

Emacsでの編集内容は以下。

export DV_ROOT=/home/masayuki/work/opensparc/t1/
export MODEL_DIR=/home/masayuki/work/opensparc/t1_model/

sims の実行は以下を利用する。

sims -sim_type=mti -group=core1_mini -sim_build_cmd=vlog -sim_run_cmd=vsim -sim_build_args="-work worklib" -sim_run_args=worklib.cmp_top -novera_build -novera_run -novcs_run

このままでは、ファイルリストが正しく生成できないので、bw_cppを訂正する。

#  cpp -E -traditional-cpp `/bin/echo $* | /bin/sed 's/-B/ /g' ` | \
  cpp -P -E -traditional-cpp `/bin/echo $* | /bin/sed 's/-B/ /g' ` | \

ここまで行くと、vlogを実行することが出来るようになるのだが、Intel ModelSim Starter Editionの影響だかよく分かっていないのだがエラーが発生する。どうもオプションが違うらしいのだが修正方法が分からない。

sims: LM_LICENSE_FILE : /import/EDAtools/licenses/synopsys_key:/import/EDAtools/licenses/ncverilog_key
sims: NOVAS_HOME not defined, Debussy will not be used.
sims: Building rtl model
sims: vlog -work worklib -f flist
Model Technology ModelSim - Intel FPGA Edition vlog 10.5b Compiler 2016.10 Oct  5 2016
Start time: 19:45:05 on Feb 25,2017
vlog -work worklib -f flist
** Error: (vlog-66) Execution of vlib failed. Please check the error log for more details.
sh: 1: /home/masayuki/intelFPGA/16.1/modelsim_ase/linuxpe/vlib: not found

最初に、vlib worklibを実行しておけば問題ないことは分かっているので、tools/src/sims/sims,1.262 line 2285.を修正してしまう。

  • 訂正前
    if (! $opt{dryrun})
    {
      system ($build_cmd) ;
      die ("DIE. failed building model") if ($?) ;
    }
  • 訂正後
    if (! $opt{dryrun})
    {
      system ("vlib worklib") ;
      system ($build_cmd) ;
      die ("DIE. failed building model") if ($?) ;
    }

ただし、このままではどうもperlのバージョンが合わないのか、うまく行かない。 どうもアセンブラコンパイルしている見たいのなのだが、Vector.soでエラーが発生している。

sims: Looking for diag under $DV_ROOT/verif/diag
sims: Found diag under /home/masayuki/work/opensparc/t1//verif/diag/assembly/arch/cache_buf/Dcache_war.s
sims: assembling diag
sims: midas -mmu=niagara -diag_root=/home/masayuki/work/opensparc/t1/ diag.s
/usr/bin/perl: symbol lookup error: /home/masayuki/work/opensparc/t1//tools/perlmod/Linux-x86_64/auto/Bit/Vector/Vector.so: undefined symbol: Perl_Gthr_key_ptr
sims: Caught a SIGDIE. midas compilation error at /home/masayuki/work/opensparc/t1//tools/src/sims/sims,1.262 line 4090.

/bin/rmdir: '/var/tmp/masayuki:dcache_war:model_core1:core1_mini:0:26202' を削除できません: そのようなファイルやディレクトリはありません
sims: imiss_branches:model_core1:core1_mini:0
Unescaped left brace in regex is deprecated, passed through in regex; marked by <-- HERE in m/\${ <-- HERE *(\w+)}*/ at /home/masayuki/work/opensparc/t1//tools/src/sims/sims,1.262 line 3980.

これ、かなりいろいろ調査して解消しようとしていたのだが、結局うまく行かない。

midas -mmu=niagara -diag_root=/home/masayuki/work/opensparc/t1/ diag.s

まずは先に進むために、この部分を省略してみよう。

    # my $waitstatus = call_program($cmd, "midas.log");
    my $waitstatus = 0;

続いて、 symbol.tbl の条件を削除する。

      # die ("DIE. could not find symbol.tbl file") if (!-f "symbol.tbl") ;

worklibの場所をどのように指定すれば良いのか分からないなあ。とりあえず絶対パスを渡しておく。

sims -nosimslog -sim_build -novera_build -sys=core1 -vcs_rel_name=core1_2017_02_25_4 -sim_build_cmd=vlog -sim_run_cmd=vsim -sim_build_args="-work worklib" -sim_
run_args=/home/masayuki/work/opensparc/t1_model/core1/core1_2017_02_25_3/worklib.cmp_top -novera_run -novcs_run -nosas -novcs_run

とりあえず動くようになったけど、ちゃんと命令フェッチは走り始めてるのかなあ。。。

要確認。

f:id:msyksphinz:20170225201753p:plain

追記:なんだかDRAMの初期化っぽいのが始まった気がする。もうちょっと様子を見てみよう。

f:id:msyksphinz:20170225215312p:plain

OpenSPARC T2の調査(2)

OpenSPARCの調査を引き続き行っている。前回のファイルリストを加工するために、OpenSPARCのシミュレーションスクリプトsimsをどうにかこうにか動かしながら、cmp1(SPARCコア1つ)を動作させるためのファイルリストを作った。

ちなみに、simsはOpenSPARCのシミュレーションを動作させるためのスクリプトなのだが、VCSが前提だったり、VERAというSynopsysのツールが必要だったりして到底個人では動かせないので、ファイルリストだけ作成してModelSimに突っ込むという作戦に出ている。

vlog -incr -mfcu -work worklib -f ../model/cmp1/rel-0.1/flist_compiled | tee vlog.log
vsim -l vsim.log +nowarn3040 -novopt -gui -voptargs="+acc" worklib.tb_top -do "do ./sim.tcl"

とりあえずエラーなしでシミュレーションを開始させるところまで動くようになったが、肝心のプログラムがうまく動かない。 というか、命令フェッチがどのユニットから出てくるのかまったく分からないので、hexファイルをどこに格納すればよいのかも分からないし、どこかリセットを制御しなければいけないのか、マニュアルを読んでも良く分からない。 マニュアルでは、simsを使ってリグレッションを動作させるようになっているので、VCS等のツールが動かせないと難しいなあ。 全く、フリーでVerilogを公開してるんだから、フリーのシミュレータでも動かせるようにしてくれればいいのに。。。

今のところ以下のような感じ。なんだかいろいろ情報は出ているが、肝心の命令フェッチが出てくれないので、もうちょっと調査する必要がある。

# do ./sim.tcl
# arg          0The VERILOG random generator initial seed is 1 (should match VERA)
# arg          0-------------------------------
# arg          0!!!!!                     !!!!!
# arg          0!!!!!                     !!!!!
# arg          0     Nas Checking Disabled
# arg          0!!!!!                     !!!!!
# arg          0!!!!!                     !!!!!
# arg          0-------------------------------
# arg          0NOTICE - Nas Q Rate is          20
# arg          0NOTICE - tlb_sync Disabled
# arg          0NOTICE - icache_sync Disabled
# arg          0NOTICE - ldst_sync Disabled
# arg          0NOTICE - int_sync Disabled
# arg          0NOTICE - err_sync Disabled
# arg          0dma_memchk Disabled
# arg          0soc_sync Enabled
# arg          0lsu_mon Enabled
# arg          0NOTICE - Global Chkr Enabled.
# arg          0Initial Thread Check Control (may change if SW startup): 0000000000000001 (th_check_enable/+thread)
# arg          0Thread Finish Mask, adjusted: 0000000000000001 (finish_mask/+finish_mask)
# arg          0
# arg          0!!! BE AWARE - timeout values are in # of Cycles, NOT # of ps/fs units
# arg          0Max Cycles          1000000 Cycles (Timeout if simulation reaches this cycle count)
# arg          0Global Timeout         1000 Cycles (Timeout if ALL threads are idle (i.e. no SSTEP))
# arg          0Thread Timeout         5000 Cycles (Timeout if ANY thread is idle (i.e. no SSTEP))
# arg          0Socket Timeout         5000 Cycles (Timeout if no socket msg from Riesling)
# arg          0
# arg         48WARNING - No good_trap address found!
#       Simulation may not terminate!
#
# arg         48WARNING - No bad_trap address found!
#       Simulation may not terminate!
#
# ** Error (suppressible): (vsim-12023) ../verif/env/cmp/../common/verilog/misc/misc_tasks.v(59): Cannot execute undefined system task/function '$enable_dispmon_finish'
# top          0If you build with -vcs_build_args=+define+RELEASE1=a+RELEASE2=nnn you will see your CDMS release version as: a.nnn
# top          0Running with build CDMS release version: UNKNOWN
# top          0------------BUILD_CMD-----------
#
# Sims Build Cmd: -sys=cmp1 -vcs_build
#
# top          0---------------------------------
#
# top          0------------BUILD_ARGS-----------
#
# Sims Build Args: -config_rtl CMP1 -config_rtl RTL_NO_SPC7 -config_rtl RTL_NO_SPC6 -config_rtl RTL_NO_SPC5 -config_rtl RTL_NO_SPC4 -config_rtl RTL_NO_SPC3 -config_rtl RTL_NO_SPC2 -config_rtl RTL_NO_SPC1 -config_rtl CORE_0 -config_rtl ZIN_CORE_SUBSET -config_rtl CORE_BENCH -config_rtl CMP_BENCH -config_rtl CMP -vcs_build_args -v $DV_ROOT/libs/cl/cl_rtl_ext.v -v $DV_ROOT/libs/cl/cl_dp1/cl_dp1.v -v $DV_ROOT/libs/cl/cl_u1/cl_u1.v -v $DV_ROOT/libs/cl/cl_sc1/cl_sc1.v -v $DV_ROOT/libs/cl/cl_a1/cl_a1.v -v $DV_ROOT/libs/cl/cl_mc1/cl_mc1.v -vcs_build_args +rad -vcs_build_args -Xstrict=0x1 -syslib -lpthread +nbaopt -O4 -cc gcc -cpp g++ -ld g++ -vcs_build_args -Mupdate -vcs_build_args +notimingcheck -vcs_build_args +nospecify -vcs_build_args +delay_mode_zero  -vcs_build_args +define+TOP=tb_top -vcs_build_args +define+LIB -vcs_build_args +define+INITLATZERO -vcs_build_args $DV_ROOT/verif/env/common/pli/global_chkr/libglobal_chkr.a -vcs_build_args $DV_ROOT/verif/env/common/pli/socket/libsocket_pli.a -vcs_build_args $DV_ROOT/verif/env/common/pli/monitor/libmonitor_pli.a -vcs_build_args -P $DV_ROOT/verif/env/common/pli/global_chkr/global_chkr.tab -vcs_build_args -P $DV_ROOT/verif/env/common/pli/socket/socket_pli.tab -vcs_build_args -P $DV_ROOT/verif/env/common/pli/monitor/monitor_pli.tab
#
# top          0---------------------------------
#
# top         30core and regreport clock period: 100 units

波形は取れるようになったが、イマイチだなあ。。。

f:id:msyksphinz:20170224010012p:plain

OpenSPARC T2の調査(1)

RISC-Vプロセッサの実装もちょっと手詰まりになってきたので、少し気分転換に、他のプロセッサはどのように実装されているんだろう、というのが気になった。

フリーで入手できるそこそこ高性能なプロセッサとしては、OpenSPARCか、RISC-VのBOOMが存在するが、内部を解析するということを考えるとBOOMは高位合成言語で記述されているということもあり不向きであると考えた。

そこで、ちょっとした気分転換にOpenSPARC T2を触ってみようと考えた。

OpenSPARCとは

Sun Microsystems(現在はOracle)のSPARCプロセッサのオープンコア版。2006年に公開されたT1、2008年に公開されたT2が存在しているが、今回はT2に焦点を当てる。

  • 8スレッドSMT
  • 最大8コア搭載で、合計64スレッド実行
  • 各コアについては
    • 整数ユニットは2
    • 浮動小数点ユニットは1
    • ロードストアユニットは2
    • 8-way 16kB命令キャッシュ
    • 4-way 8kBデータキャッシュ
    • 8 ステージ整数パイプライン
    • 12ステージ浮動小数点パイプライン

f:id:msyksphinz:20170223012639p:plain

OpenSPARCをダウンロードして中身を調査する

OpenSPARCは以下のサイトからダウンロードできる。

Overview of OpenSPARC Resources

で、肝心の中身なのだが、ほぼ10年前のデザインということもあり、趣味で扱うにはなかなか障壁が高い。

  • VCSとVERAが動作すること前提
  • Perlのバージョンも古い
  • cshで実行すること前提

などなど、実行させるまでにかなり時間がかかる。どうにかしてModelsimで動作させることが出来ないかと調査していたのだが、よくよく観察するとファイルリストがきちんと収録されている。

~/work/t2
$ find . -name "*flist"
./design/fpga/gate/fpga_gate_tb.flist
./design/fpga/gate/xilinx_lib.flist
./design/fpga/rtl/fpga_rtl.flist
./design/fpga/rtl/fpga_rtl_synth.flist
./design/sys/iop/ccu/ccu.flist
./design/sys/iop/ccx/ccx.flist
./design/sys/iop/ccx/ccx_rtl.flist
...

なるほど、これらを連結していって、Modelsimでオリジナルの環境を構成すればよい気がしている。./verif/env/cmp/cmp.flistがどうやら中心のファイルになるかな?

// Testbench Files for cmp Bench

+define+OPENSPARC_CMP+
+incdir++
+incdir+../common/verilog/checkers+
+incdir+../common/verilog/misc+
+incdir+../common/coverage+
+libext+.v+
cmp_top.v
verif_args.v
-y ../../../libs/analog/n2_esd_core_cust_l/n2_esd_core_cust/rtl
-y ../../../libs/analog/n2_pcmb_cust_l/n2_pcmb_cust/rtl
-y ../../../libs/analog/n2_pcma_cust_l/n2_pcma_cust/rtl
-y ../../../libs/analog/n2_tmpd_cust_l/n2_tmpd_cust/rtl
-y ../../../libs/analog/n2_rng_cust_l/n2_rng_cust/rtl
-y ../../../libs/analog/n2_revid_cust_l/n2_revid_cust/rtl
-y ../../../libs/clk/n2_clk_gl_cust_l/n2_clk_gl_cust/rtl
-y ../../../libs/clk/n2_clk_pgrid_cust_l/n2_clk_spc_cmp_cust/rtl
-y ../../../libs/n2sram/mp/n2_frf_mp_256x78_cust_l/n2_frf_mp_256x78_cust/rtl
-y ../../../libs/tisram/core/n2_icd_sp_16p5kb_cust_l/n2_icd_sp_16p5kb_cust/rtl
-y ../../../libs/tisram/core/n2_ict_sp_1920b_cust_l/n2_ict_sp_1920b_cust/rtl
-y ../../../libs/n2sram/dp/n2_dva_dp_32x32_cust_l/n2_dva_dp_32x32_cust/rtl
-y ../../../libs/n2sram/tlbs/n2_tlb_tl_64x59_cust_l/n2_tlb_tl_64x59_cust/rtl
-y ../../../libs/n2sram/mp/n2_irf_mp_128x72_cust_l/n2_irf_mp_128x72_cust/rtl

定義やオプションなども一通り含まれているので、とりあえずこれを使えば大丈夫そうだ。

TOEICの結果と感想2017

1/29に受験したTOEIC試験の結果が公開された。結果としては、前回受験よりも10点ダウン。 下がってしまったのはしょうがないけれども、思ったより下がり幅が小さかったので一安心。

TOEICの新形式になり始めての受験だったが、問題形式が変更になったことと、少し難易度が上がったような気がしていたのだが、TOEICはおそらく全体平均で配点が変わっているので、それで点が思ったより下がらなかったのかもしれない。

msyksphinz.hatenablog.com

前回の記事を眺めていると、結構いろいろやっていたんだな、と思った。 そもそも仕事で英語を使う機会がかなり減ってしまったのだが、

  • レアジョブ

継続中。週2回。

電車に乗る機会が減ってしまい止めてしまった。

  • 英会話カフェ

付近に無く止めてしまった。

あれー、ほとんど英語関係の活動を止めてしまっている。また何か再開するかなあ。

マラソン用イヤホン購入

今までマラソンに出るときは、ソニーBluetoothを使っていたのだけれど、レシーバが大きくてちょっと不便だった。

www.sonymobile.co.jp

そこでマラソン用のイヤホンを購入した。Amazonでたくさん調べて、ヨドバシカメラをぐるぐる回って、結局ヨドバシカメラのそれなりに安いやつにした。 Amazonで調査した意味とはいったい。。。

www2.elecom.co.jp

この色よ(笑)。

付け心地は、デフォルトのイヤーピースが大きくて痛かったので、付属の小型のイヤーピースに交換し、ちょうど良い。 実はこれつけてまだ走っていないんだけど、一日部屋の中で使い続けてみて、別に不自由は感じない。

ただ、バッテリーの持ちが4時間程度なので、マラソン限定かな。。。

f:id:msyksphinz:20170218124557j:plain

RISC-Vテストパタン VMモードの解析

RISC-V

前回に引き続き、Sv32で動作させるときのテストパタンの動作について解析している。

RISC-Vのテストパタンは、基本的なテストを行うxxx.Sのアセンブラリストと、それを囲むプロローグとエピローグから構成されている。

中心となる検証用アセンブラリストは、以下のようなものだ。

riscv-tests/add.S at master · riscv/riscv-tests · GitHub

  #-------------------------------------------------------------
  # Arithmetic tests
  #-------------------------------------------------------------

  TEST_RR_OP( 2,  add, 0x00000000, 0x00000000, 0x00000000 );
  TEST_RR_OP( 3,  add, 0x00000002, 0x00000001, 0x00000001 );
  TEST_RR_OP( 4,  add, 0x0000000a, 0x00000003, 0x00000007 );

  TEST_RR_OP( 5,  add, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 );
  TEST_RR_OP( 6,  add, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 );
  TEST_RR_OP( 7,  add, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 );

  TEST_RR_OP( 8,  add, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff );
  TEST_RR_OP( 9,  add, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 );
  TEST_RR_OP( 10, add, 0x0000000080007ffe, 0x000000007fffffff, 0x0000000000007fff );

  TEST_RR_OP( 11, add, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff );
  TEST_RR_OP( 12, add, 0x000000007fff7fff, 0x000000007fffffff, 0xffffffffffff8000 );

こんな感じのテストパタンが、ずらっと並んでいる。これを囲むのがプロローグ関数とエピローグ関数なのだが、まずはプロローグから見ていこう。

Sv32の変換モードを設定するプロローグ関数vm_boot()

env/v/vm.cに記述されているvm_boot()は、仮想メモリアドレスの変換設定をしている中心となコードだ。

void vm_boot(uintptr_t test_addr)
{
...

  write_csr(sptbr, (uintptr_t)l1pt >> PGSHIFT);
  // map kernel to uppermost megapage
  l1pt[PTES_PER_PT-1] = ((pte_t)kernel_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
  // map user to lowermost megapage
  l1pt[0] = ((pte_t)user_l2pt >> PGSHIFT << PTE_PPN_SHIFT) | PTE_V;
...

sptbrレジスタを指定しており、仮想メモリアドレスモードに入ったときのテーブルウォークを行うベースアドレスを設定している。 ここでは、l1pt = pt[0]を指しており、これはページテーブルの先頭に値する。ここからページテーブルをたどって行き、目的のアドレスに到達するわけだ。

...
  // set up supervisor trap handling
  write_csr(stvec, pa2kva(trap_entry));
  write_csr(sscratch, pa2kva(read_csr(mscratch)));
  write_csr(medeleg,
    (1 << CAUSE_USER_ECALL) |
    (1 << CAUSE_FAULT_FETCH) |
    (1 << CAUSE_FAULT_LOAD) |
    (1 << CAUSE_FAULT_STORE));

mscratchレジスタの値はtrap_vectorから少し先、トラップが発生したときのアドレスを格納しており、これをsscratchにコピーしている。 この際、スーパバイザモードでは仮想アドレスモードで動作するので、あらかじめpa2kvaで物理アドレスから仮想アドレスに値を変換して格納している。

さらに、権限委譲のためのレジスタを設定しており、ユーザモードからのトラップ、メモリアクセス関連の例外はすべてスーパバイザが処理するように設定された。

この後、テストパタンがなぜか指定のページに飛ばない問題をずっと追いかけていたのだが、どうもテストパタンのスタートアドレスを指定する方式に問題があるようだった。

  trapframe_t tf;
  memset(&tf, 0, sizeof(tf));
  tf.epc = test_addr - DRAM_BASE;
  pop_tf(&tf);

これ、test_addrからDRAM_BASE`を減算するだけでなぜOKなんだろう?そもそも仮想アドレスから物理アドレスへの変換は、

riscv-test-env/vm.c at 9e219c9ca70459bfda9067d637bb8bf52c5f0326 · riscv/riscv-test-env · GitHub

#define pa2kva(pa) ((void*)(pa) - DRAM_BASE - MEGAPAGE_SIZE)

で行われるはずだ。じゃあtest_addrの変換も、同様に変換しなければならないだろう。

  trapframe_t tf;
  memset(&tf, 0, sizeof(tf));
  // tf.epc = test_addr - DRAM_BASE;
  tf.epc = pa2kva(test_addr);
  pop_tf(&tf);

が、正解じゃないの?

テストが終了した後のエピローグ関数

テストが終了すると、テストがPassしたかFailしたかを判定しなければならないのだが、それをriscv-testsではコードとして管理している。

まずテストが終了すると、ECALL(Supervisor Trap)を発行させて、マシンモードに行こうする。(mdelegで"Ecall from Supervisor"は有効になっていないので、スーパバイザモードからマシンモードに素直に移行するはずだ。

つぎに最後のコードを見て、最終判断をするわけだが、最後の判定はhandle_trap()にて行われている。

void handle_trap(trapframe_t* tf)
{
  if (tf->cause == CAUSE_USER_ECALL)
  {
    int n = tf->gpr[10];

    for (long i = 1; i < MAX_TEST_PAGES; i++)
      evict(i*PGSIZE);

    terminate(n);
  }
  else if (tf->cause == CAUSE_ILLEGAL_INSTRUCTION)
  {
    assert(tf->epc % 4 == 0);
...

ユーザモードでないとterminateが実行されない仕組みになっている。そんなことないでしょ!これまでずっとスーパバイザモードでテストしてたのに!

という訳で、

  if (tf->cause == CAUSE_USER_ECALL)

は、

  if (tf->cause == CAUSE_SUPERVISOR_ECALL)

では無かろうか?これらを変更すると、無事に自作ISSでテストパタンがパスした。 これらの問題はRISC-Vのメーリングリストに投げて、質問している。