FPGA開発日記

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

RISC-V BOOMプロセッサのRTLシミュレーションを実行したい(Veritakで挑戦→解析中)

RISC-Vのアウトオブオーダ実装であるBOOM (Berkeley Out-of-Order Machine)のRTLシミュレーションは、基本的にverilatorを使って実行されている。

それもそのはず、BOOMはオープンソースハードウェアであるため、オープンソースのシミュレータを使わないと万人が利用できない。

しかし、波形を観測したり、デバッグをしたりするのにverilatorだけでは不便だ。今回は僕がいつも(趣味なFPGA開発のときに)利用しているVeritakに移植してみよう。

BOOM のハードウェアを改造してRTLシミュレーション用に変更する

BOOMのRTL実装は1ファイルにまとめられており、boomのリポジトリをビルドすると、rocketchip.BOOMConfig.v というファイルにまとめられている。 昨日のブログでも紹介したとおり、これは80万行超の膨大なファイルであり、全体を見渡すのはなかなかやっかいだ。

msyksphinz.hatenablog.com

トップに存在するのはTestHarness()というモジュールだ。ここにはどうやらCPUの本体と、外部周辺RAM、モニタ、インターコネクトなどが接続されているらしい。

この部分はまだテストベンチとしての役割ではなさそうだ。Verilatorの場合、さらに上にC++のラッパーを被せるのだろう。今回はVeritakで動作させるため、Verilogで記述されたテストベンチを記述する必要がある。

module TestHarness(
  input   clock,
  input   reset,
  output  io_success
);
  wire  dut_clock;
  wire  dut_reset;
  wire  dut_io_success;
  wire  dut_io_debug_req_ready;
  wire  dut_io_debug_req_valid;
...

まず、TestHarnessを動作させるためのテストベンチを作成した。

`timescale 100ps / 1ps

module tb;

  parameter STEP     = 100000;
  parameter H_STEP   = 50000;
  parameter H2_STEP  = 25000;

  reg CPU_CLK;
  reg CPU_RESET;

  integer step_count;

  TestHarness
  u_TestHarness
    (
     .clock (CPU_CLK),
     .reset (CPU_RESET),
     .io_success ()
    );
  always # (H_STEP) begin
    CPU_CLK <= ~CPU_CLK;
  end

  initial begin
    CPU_CLK   = 1'b1;
    CPU_RESET = 1'b1;

    #(STEP * 10);
    CPU_RESET = 1'b0;

    for (step_count = 0; step_count < 100; step_count = step_count) begin
      #(STEP * 20000);
      $display ("%t", $time);
    end
    $display ("<Info: Simulation TimeOut %t>", $time);
    $finish;
    // $stop;
  end

endmodule // tb_rocketchip

Veritakでコンパイルしてみると、rocketchip.BOOMConfig.v には$Fatalというシステムタスクが呼ばれており、これがVeritakには無いと怒られてしまった。ここの部分は改造するしか無さそうだ。

        if (T_41 & T_45) begin
          $Fatal;
        end

改造する。

        if (T_41 & T_45) begin
          $display ("Fatal error. Exit"); $finish;
        end

一応コンパイルは通るようになったのだが、シミュレーションが開始されない。いくつかトップモジュールを変更して試行してみたのだが、正しく動作させるまでには至らなかった。まだ解析が必要そうだ。

f:id:msyksphinz:20161102010927p:plain

備考: BOOMはどこから命令をフェッチするのか?

rocketchip.BOOMConfig.v を探索していると、bootrom というモジュールを見つけた。 探ってみると、内部の1000ワード近くを、RAMモデルを使わずすべてワイヤで記述してある...!

BOOMのモデルの中には、こういう部分が多量にあるはずだ。これを律儀にVeritakで動作させようとしたから、重かったのかなあ。。。?

module bootrom(
  input   clock,
  input   reset,
  output  io_in_0_a_ready,
  input   io_in_0_a_valid,
...
  input   io_in_0_e_bits_sink
);
  wire [31:0] rom_0;
  wire [31:0] rom_1;
  wire [31:0] rom_2;
...
  reg [31:0] GEN_1030;
  reg [31:0] GEN_1037;
  assign io_in_0_a_ready = io_in_0_d_ready;
  assign io_in_0_b_valid = 1'h0;
  assign io_in_0_b_bits_opcode = GEN_1024;
  assign io_in_0_b_bits_param = GEN_1025;
  assign io_in_0_b_bits_size = GEN_1026;
  assign io_in_0_b_bits_source = GEN_1027;
  assign io_in_0_b_bits_addr_hi = GEN_1028;
  assign io_in_0_b_bits_mask = GEN_1029;
  assign io_in_0_b_bits_data = GEN_1030;
  assign io_in_0_c_ready = 1'h1;
  assign io_in_0_d_valid = io_in_0_a_valid;
  assign io_in_0_d_bits_opcode = T_2371_opcode;
  assign io_in_0_d_bits_param = T_2371_param;
  assign io_in_0_d_bits_size = T_2371_size;
  assign io_in_0_d_bits_source = T_2371_source;
  assign io_in_0_d_bits_sink = T_2371_sink;
  assign io_in_0_d_bits_addr_lo = T_2371_addr_lo;
  assign io_in_0_d_bits_data = T_2371_data;
  assign io_in_0_d_bits_error = T_2371_error;
  assign io_in_0_e_ready = 1'h1;
  assign rom_0 = 32'h6f;
  assign rom_1 = 32'h0;
  assign rom_2 = 32'h0;
  assign rom_3 = 32'h1020;
  assign rom_4 = 32'h0;
  assign rom_5 = 32'h0;
  assign rom_6 = 32'h0;
  assign rom_7 = 32'h0;
  assign rom_8 = 32'h63696c70;
  assign rom_9 = 32'h200a7b20;
  assign rom_10 = 32'h69727020;
  assign rom_11 = 32'h7469726f;
  assign rom_12 = 32'h78302079;
...

RISC-VプロセッサBOOMを分解 (vhierによる内部構造把握)

f:id:msyksphinz:20161101020618p:plain

RISC-Vプロセッサの実装バリエーションのうち、性能重視のプロセッサであるBOOM (Barkeley Out-of-Order Machine)は、どのような構造で実装されているのだろう。

git clone https://github.com/ucb-bar/rocket-chip.git
cd rocket-chip
git checkout boom
git submodule update --init
cd emulator; make run CONFIG=BOOMConfig

BOOMのビルドが完了すると、一通りBOOMのVerilogモデルが生成される。これは1つのファイルで形成されていて、rocketchip.BOOMConfig.vというファイルが生成されていた。

全てのモジュールを一つのファイルでまとめているらしい。こりゃ、解析する気にならないな...

wc rocketchip.BOOMConfig.v
  860267  2870793 32449520 rocketchip.BOOMConfig.v

86万行もあるぜ!

Verilog-Perlのツールであるvhierを使って構成を把握する

これは本ブログでも以前紹介した、Verilog-Perlの機能の一つであるvhierを使うものだ。vhierを使えば、Verilogファイルをコンパイルすることなく、内部構成を把握することができる。

msyksphinz.hatenablog.com

今回のvhierのオプションは簡単だ。1つしかファイルが存在しないため、そのまま指定すれば良い。

$ vhier rocketchip.BOOMConfig.v -o rocketchip.hier --cells --forest --instance
%Error: rocketchip.BOOMConfig.v:860145: Cannot find SimDTM
%Error: rocketchip.BOOMConfig.v:860145: Module/Program/Interface reference not found: SimDTM
Exiting due to errors

ありゃ、失敗してしまった。SimDTMというファイルが無いらしい。検索してみると、../../vsrc/SimDTM.vに存在したので、追加でオプション指定する。

$ vhier rocketchip.BOOMConfig.v ../../vsrc/SimDTM.v -o rocketchip.hier --cells --forest --instance

rocketchip.hierに階層構成が生成された。

  TestHarness TestHarness
  |--LatencyPipe_1_1 LatencyPipe_1
  |--LatencyPipe_2 LatencyPipe
  |--SimAXIMem_1 SimAXIMem
  |--SimDTM_1 SimDTM
  \--dut ExampleTop
     |--NastiIOTileLinkIOConverter_1 NastiIOTileLinkIOConverter
     |  |--get_id_mapper IdMapper
     |  |--gnt_arb LockingArbiter_2
     |  |--put_id_mapper IdMapper
     |  \--roq ReorderQueue_2
...

ずいぶんと長いが、まずはトップモジュールとしてTestHarnessが定義されていた。そこからduvとしてsoc階層が定義されている。プロセッサのコア部はさらに奥だ。

  • BOOMCore
    • ALUExeUnit_1
    • ALUExeUnit_2
    • MemExeUnit_1
    • bpd_stage
    • csr
    • dec_brmask_logic
    • dec_serializer
    • decode_units_0
    • decode_units_1
    • fetch_unit
    • issue_unit
  BOOMCore BOOMCore
  |--ALUExeUnit_1_1 ALUExeUnit_1
  |  |--fu_units_0 ALUUnit_1
  |  |  \--alu ALU
  |  |--fu_units_1 FDivSqrtUnit
  |  |  |--RecFNToRecFN_2_1 RecFNToRecFN_1
  |  |  |--RecFNToRecFN_3_1 RecFNToRecFN_1
  |  |  |--divsqrt DivSqrtRecF64
  |  |  |  |--ds DivSqrtRecF64_mulAddZ31
  |  |  |  \--mul Mul54
  |  |  |--downvert_d2s RecFNToRecFN_4
  |  |  |  \--RoundRawFNToRecFN_1_1 RoundRawFNToRecFN
  |  |  \--fdiv_decoder UOPCodeFDivDecoder
  |  \--muldiv MulDivUnit
  |     \--muldiv MulDiv
  |--ALUExeUnit_2 ALUExeUnit
  |  |--fu_units_0 ALUUnit
  |  |  \--alu ALU
  |  |--fu_units_2 FPUUnit
  |  |  \--fpu FPU
  |  |     |--dfma FPUFMAPipe
  |  |     |  \--fma MulAddRecFN
  |  |     |     |--mulAddRecFN_postMul MulAddRecFN_postMul
  |  |     |     \--mulAddRecFN_preMul MulAddRecFN_preMul
  |  |     |--fp_decoder UOPCodeFPUDecoder
  |  |     |--fpiu FPToInt
  |  |     |  |--RecFNToIN_1_1 RecFNToIN_1
  |  |     |  |--RecFNToIN_2 RecFNToIN
  |  |     |  \--dcmp CompareRecFN
  |  |     |--fpmu FPToFP
  |  |     |  |--RecFNToRecFN_1_1 RecFNToRecFN_1
  |  |     |  \--RecFNToRecFN_2 RecFNToRecFN
  |  |     |     \--RoundRawFNToRecFN_1 RoundRawFNToRecFN
  |  |     |--ifpu IntToFP
  |  |     |  |--INToRecFN_1_1 INToRecFN_1
  |  |     |  \--INToRecFN_2 INToRecFN
  |  |     \--sfma FPUFMAPipe_1
  |  |        \--fma MulAddRecFN_1
  |  |           |--mulAddRecFN_postMul MulAddRecFN_postMul_1
  |  |           \--mulAddRecFN_preMul MulAddRecFN_preMul_1
  |  \--imul PipelinedMulUnit
  |     \--imul IMul
  |--MemExeUnit_1 MemExeUnit
  |  |--lsu LoadStoreUnit
  |  |  |--dtlb TLB
  |  |  \--forwarding_age_logic ForwardingAgeLogic
  |  \--maddrcalc MemAddrCalcUnit
  |--bpd_stage BranchPredictionStage
  |  |--BranchDecode_1_1 BranchDecode
  |  |--BranchDecode_2 BranchDecode
  |  \--br_predictor GShareBrPredictor
  |     |--brob BranchReorderBuffer
  |     \--counters TwobcCounterTable
  |        |--h_table HTable
  |        |  \--hwq Queue_4
  |        |--p_table PTableBanked
  |        \--pwq Queue_5
  |--csr CSRFile
  |--dec_brmask_logic BranchMaskGenerationLogic
  |--dec_serializer FetchSerializerNtoM
  |--decode_units_0 DecodeUnit
  |--decode_units_1 DecodeUnit_1
  |--fetch_unit FetchUnit
  |  \--FetchBuffer Queue_3
  |--issue_unit IssueUnitCollasping
  |  |--IssueSlot_10_1 IssueSlot
  |  |--IssueSlot_11_1 IssueSlot
  |  |--IssueSlot_12_1 IssueSlot
  |  |--IssueSlot_13_1 IssueSlot

森美術館「宇宙と芸術展」に行ってきた

森美術館は毎回おもしろい、もしくは分かりにくテーマで企画展示をしていることが多いが、今回は宇宙だ。

正直、公式サイトの正面にあるスペースシャトルに釣られたと言わざるをえない。

www.mori.art.museum

これ見てみたい、それだけだ。

感想としては、半分ぐらいは意味不明というか、直接宇宙とは関係なさそうなものもあるし、現代美術すぎて良く分からない展示もたくさんあった。 さすがは森美術館といったところか。

で今日の最大の収穫はこれ。

テンヨー|メタリック ナノパズル|オンラインカタログ

メタリックナノパズルというもので、はやぶさ版を売っていたので買ってみた。

f:id:msyksphinz:20161030235228j:plain

完成までそれなりに時間がかかるし指が痛くなるが、なかなか面白い。

これスターウォーズシリーズもあるな。欲しくなってきた。

5th RISC-V workshop @ Google Mountain View のアジェンダが公開されました

f:id:msyksphinz:20160727005840p:plain

5th RISC-V Workshop @ Google Mountain View のアジェンダが公開されました。

riscv.org

  • 日時 : November 29-30, 2016
  • 場所 : Google’s Quad campus (468 Ellis Street, Mountain View, CA 94043)

Mountain Viewなんて行けないけど、イベント後には毎回資料はアップロードされているし、発表風景もYoutubeで公開されているので参照してみると良いのではないでしょうか。

(個人的な)興味のある分野。

  • Extending RISC-V for Application-Specific Requirements : Steve Cox, Synopsys。シノプシスの人が発表、何故?
  • A memory model for RISC-V, A Memory Consistency Model for RISC-V: MITおよびPrincetonの人が発表、公式な仕様では無いのかな。
  • “V” Vector Extension Proposal : SIMD拡張命令の発表?
  • A Fast Instruction Set Simulator for RISC-V : 同業者っぽいので気になる。

Chef-soloによるRISC-VのRocket-Chip向け環境自動ビルド

f:id:msyksphinz:20161006012100p:plain

いろいろとVagrantの環境を仕込んでいるが、今回はRISC-V向けのRocket-Chip向け環境をVagrantとChef-soloでビルドする。

github.com

参照しているのは単純に以下のRocket向けgithubに書いてあるビルド手順をChef-soloに落としただけだ。

github.com

問題は、4GB近くのメモリを必要とすること、本当にGCCのビルドにはメモリが必要だな!

あとは、FPGA向けのビルド環境を立ち上げていこう。

Chef-SoloによるVivadoの自動インストールとADV7511向けデザインの自動ビルド

f:id:msyksphinz:20161006012100p:plain

前回はVagrant上のUbuntuにVivadoをインストールする途中だった。 何度か試行を繰替えしているが、どうにかなりそうだ。

msyksphinz.hatenablog.com

msyksphinz.hatenablog.com

Vivadoのインストールと、ZedBoard向けLinuxの立ち上げに必要なデザインの構築を自動化しておきたい。

VivadoのインストールをChef-soloで自動化する

これは自動化というと語弊があるような手法だけども、あらかじめWindowsの共有ディレクトリに、Vivadoのオールインワンの圧縮ファイル(11GBもある!)と、バッチモードでのインストールに必要なinstall_config.txtおよびライセンスファイルを用意しておく。

github.com

.
├── riscv-repo
│   └── site-cookbooks
│       └── riscv-tools
│           ├── CHANGELOG.md
│           ├── metadata.rb
│           ├── README.md
│           └── recipes
│               └── default.rb
├── shared
│   ├── install_config.txt
│   ├── install_config.txt~
│   ├── Xilinx.lic
│   ├── Xilinx_Vivado_SDK_2015.2.1_0805_1.tar.gz
│   ├── Xilinx_Vivado_SDK_2016.2_0605_1.tar.gz
│   └── Xilinx_Vivado_SDK_Lin_2015.2_0626_1.tar.gz
└── Vagrantfile

とりあえずは、いろいろ試行した結果、Vivado 2015.2が良い気がしている。このためにいくつかsedでプロジェクトファイルを変更する必要があるのだが、それは後で行う。

Vagrantfileには、jsonのattributeを使って、Vivadoのバージョンを変更できるようにしている。

  config.vm.provision "chef_solo" do |chef|
...
    # You may also specify custom JSON attributes:
    chef.json = {
      vivado: {
        version: "2015.2",
        date: "0626",
        file_head: "Xilinx_Vivado_SDK_Lin"
      }
    }
  end

default.rbには、Vagrantfileで指定したattributeを使って変数を指定している。

execute "Installing Vivado (1)" do
  command "tar xfz /vagrant/shared/#{node['vivado']['file_head']}_#{node['vivado']['version']}_#{node['vivado']['date']}_1.tar.gz -C /home/vagrant/"
  action :run
  user "vagrant"
  group "vagrant"
end

ビルドには、Vivadoのバッチモードを利用してインストールしている。あらかじめinstall_config.txtも用意しておく。詳細は過去のブログ記事を参照。

msyksphinz.hatenablog.com

execute "Installing Vivado (2)" do
  cwd "/home/vagrant/#{node['vivado']['file_head']}_#{node['vivado']['version']}_#{node['vivado']['date']}_1"
  command "./xsetup --agree XilinxEULA,3rdPartyEULA,WebTalkTerms --batch Install --config /vagrant/shared/install_config.txt"
  action :run
end

ZedBoard向けADV7511デザインのビルド

これもChef-soloで自動化しておきたい。ADV7511のgitリポジトリのダウンロードとビルドも自動化しておきたい。

git "/home/vagrant/hdl" do
  repository "https://github.com/analogdevicesinc/hdl.git"
  revision "hdl_2015_r2"
  enable_submodules true
  action :sync
  user "vagrant"
  group "vagrant"
end

sedでライブラリとプロジェクトのバージョンを少し変更しておく。Vivado 2015.2を利用しているので、それにバージョンを合わせる。詳細は以下のQiitaの記事を参照。

qiita.com

execute "Sed IP version (1)" do
  cwd "/home/vagrant/hdl/"
  command "sed -i 's/2015.2.1/2015.2/g' library/scripts/adi_ip.tcl"
  action :run
  user  "vagrant"
  group "vagrant"
end


execute "Sed IP version (2)" do
  cwd "/home/vagrant/hdl/"
  command "sed -i 's/2015.2.1/2015.2/g' projects/scripts/adi_project.tcl"
  action :run
  user  "vagrant"
  group "vagrant"
end

最後にリポジトリをビルドする。

bash "make project" do
  cwd "/home/vagrant/hdl/projects/adv7511/zed"
  code <<-EOS
       source /opt/Xilinx/Vivado/#{node['vivado']['version']}/settings64.sh
       unset LD_LIBRARY_PATH
       make
   EOS
  action :run
  user  "vagrant"
  group "vagrant"
end

ZedBoard向けデザインを構築するスクリプトを自動化する(途中)

f:id:msyksphinz:20160903173001j:plain

msyksphinz.hatenablog.com

前回で、Linuxをブートするためのローダのビルドは完了したので、今度はVagrant上のCUIだけでZedBoard用デザインのビルドに挑戦する。

参考にしたのは以下のサイトだ。

qiita.com

あとはVivadoをCUIでインストールするのには、自分のブログを参考にした。

msyksphinz.hatenablog.com

いろいろ試行して分かったのだが、

  • Vivado 2016.2, 2016.3 はまだ対応していない (IPのバージョンが合わないので失敗する)
  • Vivado 2015.2.1 をサポートしているが、Vivado 2015.2 を2015.2.1にバージョンアップするためのCUI構築方法が分からなかったので未実施。

ということで、おそらくはVivado 2016.1を使うのが最適ではなかろうか。今日は時間切れなので、明日再試行する。