Scalaの文法は少しわかってきたので、とりあえず今のタイミングでChiselの勉強も始めて行こうと思う。まずは環境構築!!ということになるが、それを行うにあたって情報収集を行った内容を記載していく。
- Chiselって
- サンプルコード
- GCD
- MaxN
- Mul
- Adder
- プログラミングを始めるにあたって
- サンプルコード
昨日の記事の結びで以下のように書いた。
ということは
ecall
命令がうまく処理されていないことになるが、そもそもecall
命令って何??な状態なので次回はecall
命令の中身を把握するところからやっていきたい。
ということでecall
命令の確認を行い、その後にaddi.Sがどのように最終アドレスである0xf4
に辿り着くのかを確認していく。
昨日の記事でVivadoシミュレータ上で実行したriscv-testsのaddiテストが正常に終了しない件についての調査を行い、テストベンチ上の$finish
に辿り着く条件を満たしていないことがわかった。
結構SCR1の中身を真面目に追っていかないとわからない感じがしたが、そもそもこのriscv-testsで何が実行されているのかをちゃんとは把握していないのでriscv-testsの中身の確認をしていく。ということもありタイトルもそれっぽく変更。
続きを読む前回のSCR1ネタではVivadoシミュレータを使用した際に$readmemh
がうまく行かない問題を解析していった。
今回はもうひとつ残っているシミュレーションが正常に終わらない問題について解析していく。
これね↓。
実はこのシミュレーションも正常に終わってなかったりしているので、引き続きもう少しシミュレーション環境の調査を行っていくつもり
前回のSCR1ネタ最後に以下のように書いた。
ここまでに記載したようにとりあえず...の対策をいくつか施して動かした部分もあるし、実はこのシミュレーションも正常に終わってなかったりしているので、引き続きもう少しシミュレーション環境の調査を行っていくつもりだが、今日はここまで。
ということで今日は、Vivado+SCR1+riscv-testsシミュレーション環境についてももう少し調べていく。今日は$readmemh
がうまく動かないという話題について。
表題の通りだが、前回の記事では読み込むRISC-VバイナリのHEXデータファイルを以下のようにして、直書き&フルパス指定することによって、実行していた。
always @(negedge rst_n) begin //memory = '{SIZE{'0}}; $readmemh("./scr1/build/addi.hex", memory); // 修正後 //if(stuff_file.len()>0) $readmemh(stuff_file,memory); end
これについて少し調べてみる。
いろいろ試してみたが、どうもSystem Verilogのstring
に入れると解釈できていないように見える。
試したのは以下の3つのケース
$readmemh
に直接ファイル名を指定reg
宣言した変数にファイルパスを設定して、その変数を$readmemh
に与えるソースコード的には以下のような物を用意して、コメントアウトする部分を切り替えて試してみた。
reg[1023:0] tmp; always @(negedge rst_n) begin //memory = '{SIZE{'0}}; // case 1 - original, but set file name on this always block directly stuff_file = "/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex"; $display("case1:%s", stuff_file); if(stuff_file.len()>0) $readmemh(stuff_file, memory); // case 2 - set file name directly to $readmemh task $display("case2:%s", "/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex"); $readmemh("/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex", memory); // case 3 - set file name to reg valuable and feed $readmemh task tmp = "/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex"; $display("case3:%s", tmp); $readmemh(tmp, memory); end
以下のようなメッセージが得られた。
case1:/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex WARNING: File õ referenced on /home/dnn-admin/workspace/hw/study/fpga-scr1/scr1/src/tb/scr1_memory_tb_axi.sv at line 154 cannot be opened for reading. Please ensure that this file is available in the current working directory.
ここで気になるのは警告文中のファイル名が謎の文字列"õh"に化けているように見えること。。。
なんかやっぱり、string
型の変数にファイル名設定するとVivadoでは読み込めてないように見える。$display
の出力は普通なのに。。
上記のようになっているので当然、読み出されるデータも不定になっていた。
こちらも既に試しているとおりではあるが、以下のメッセージが得られた。実行時間の情報を出しているのはcase1のように警告が出ていないことを示すため。
case2:/home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex relaunch_sim: Time (s): cpu = 00:00:05 ; elapsed = 00:00:07 . Memory (MB): peak = 6431.449 ; gain = 0.000 ; free physical = 10548 ; free virtual = 28752
警告が出ていないことからもわかるが、正常にメモリがデータが読み込まれているため、シミュレーション時の波形においても正しいでデータが読み込まれている。
reg
変数に設定した後、$readmemh得られた出力は以下のようになった。
case3: /home/dnn-admin/workspace/hw/study/1000_scr1/scr1/build/addi.hex relaunch_sim: Time (s): cpu = 00:00:05 ; elapsed = 00:00:06 . Memory (MB): peak = 6447.441 ; gain = 7.988 ; free physical = 10477 ; free virtual = 28689
"case2"という文字の直後にスペースが入っているのは、reg
変数のビット幅の関係。
こちららも特に警告は出ておらず、正常に$readmemh
により所望のファイルが読み込まれていた。
以上の結果からすると、やっぱりVivadoシミュレータにおいてはstring
変数に設定したファイルパスが$readmemh
の処理の上では認識されていないことになる。
ということで、この挙動についてverilogの仕様を追ってみることにする。
現在実行しているシミュレーションでこの$readmemh
が実行されているのはテストベンチ上のメモリモデルscr1_memory_tb_axi
である。このファイルはVivado上ではSystem Verilogのファイルとして認識されているので、エラボレーション時にもSystem Verilogの文法が適用されている。
そのため、まずはSystem Verilogにおける$readmemh
の定義を確認していく。確認したのはこのPDFでこれによると、$readmemh
の項目では以下の事項のみが触れられている。
22.14 $readmemb and $readmemh 22.14.1 Reading packed data $readmemb and $readmemh are extended to unpacked arrays of packed data, associative arrays of packed data, and dynamic arrays of packed data. In such cases, the system tasks treat each packed element as the vector equivalent and perform the normal operation.
When working with associative arrays, indexes must be of integral types. When an associative array’s index is of an enumerated type, address entries in the pattern file are in numeric format and correspond to the numeric values associated with the elements of the enumerated type.
22.14.2 Reading 2-state types $readmemb and $readmemh are extended to packed data of 2-state types, such as int or enumerated types. For 2-state integer types, reading proceeds the same as for conventional Verilog variable types (e.g., inte-ger), with the exception that X or Z data are converted to 0. For enumerated types, the file data represents the numeric values associated with each element of the enumerated type (see 4.10). If a numeric value is out of range for a given type, then an error shall be issued and no further reading shall take place.
この22.14で記載されているのはSystem Verilogにおいて拡張された部分のみで、ざっくり以下のことが書いてある。
実際に知りたいファイル指定部分の扱いは書いていなかったのでVerilog-HDLの方の仕様書(IEEE Std 1364-2001)で確認してみる。
"17.2.8 Loading memory data from a file"によると、以下のようになっている。
load_memory_tasks ::= $readmemb ( " file_name " , memory_name [ , start_addr [ , finish_addr ] ] ) ; | $readmemh ( " file_name " , memory_name [ , start_addr [ , finish_addr ] ] ) ;
今回知りたいのは上記の" file_name "が何を指しているのか、、、なのだが、ここには書いていないので、別の項目も探してみると以下の説明が$fopen
の項目である17.2.1で見つかる。
file_open_function ::= integer multi_channel_descriptor = $fopen ( " file_name " ); | integer fd = $fopen ( " file_name ", type );
ここには" file_name "についての説明が記載してあり、それは以下のようになっている。
filename is a character string, or a reg containing a character string that names the file to be opened.
ということで、verilog(IEEE Std 1364-2001)の仕様では" file_name "として許容されるのは
reg
変数に"a character string"を格納したものということになりそう。
上記で先に調べたとおりSystem Verilogにおいてはこの" file_name "についての扱いは拡張されていないように見えるので、$readmemh
でstring
型の文字列が扱えないのは一概にバグとは言えない感じに思える。VCSとかでは普通に扱えるからてっきり読めるんだと思ってた。
商用のシミュレータ使ってると結構ベンダ依存の拡張が存在してて、ツール切り替えるときに動いてた記述が動かなくなることがあるけど、これもその一つということなのか。因みに上記で$display
にstring
を与えると動いていたが、System Verilogの仕様でしっかり拡張されているようで以下の一文が書いてあった。
- $display , $write , $fdisplay , $fwrite , $swrite , and their variants
- The argument corresponding to a string % format specifier ( s ) may have the string data type.
ということで、結論としてはstring
で読めないのは仕方がなさそうなのでreg
変数で動くように書き換える(前項のcase3の対応)、、、ということになりそう。