[電子工作]Tang Primer:中国製FPGAでRISC-Vの設計に挑戦

ーーーー目次ーーーー

1.Tang Primerとは?

2.各種ツールのインストール

3.E203のソフト開発

4.RISC-Vの設計・開発をしよう

5.自作16bitマイコンの実装

6.自作RISC-Vマイコンの実装

ーーーーーーーーーー

1.Tang Primerとは?

  中国のANLOGIC社のFPGA EG4S20を搭載し、Sipeed社が開発したボードがTang Primerです。

  まず、EG4S20の主な仕様は次の通りです。

 

   LUTs:19,600(LUT4/LUT5)

   FFs:19,600

   BRAM:136KB (9kbit×64個、32kbit×16個、最大250MHz)

   DSPs:29(18x18、最大250MHz)

   PLL:4

   global clock:16

   IO:193(LVDS:90pair、最大800MHz)

   SDRAM:2M×32bit(最大200MHz)

   ADC:12bit×8ch(最大1Msps、変換器は1個でセレクタにてchを選択)

 

 回路規模は最大20万ゲート程度、動作速度は最大250MHz、最大800Mbpsの高速差動I/Fを持つので、

 結構、用途は広いと思います。特に、64MbitのSDRAMを内蔵し、FHD(1920x1080)の画像も格納

 できるのが、ポイント高いかと思います。但し、DSPが少ないので、複雑な画像処理はできません。

  ボードの特徴は次のとおりです。

   ・microSDカードスロット、RGB LED、40pin LCDコネクタ、24pin カメラコネクタを搭載。

   ・USBのJTAGチップを搭載。(但し、FPGAの書き込み専用で、RISC-Vのデバッグには使えません)

   ・Config用のQSPIフラッシュと、汎用のQSPIフラッシュ(16Mbit)を搭載。

 ディフォルトで、RISC-V(RV32IMAC)の回路が書き込まれています。フラッシュメモリにプログラムを

 格納できます。但し、16MHz動作で、メモリもSRAMのみで、SDRAMは使えません。

  という訳で、本ボードは、FPGAで簡単な回路の動作検証を行いたい方、RISC-Vのハード/ソフトの

 研究・評価・検証(!)を行いたい方に、お薦めします。

  なお、単にRISC-Vを使って高速処理を行いたいのであれば、絶対にMaix BitなどK210を使用した

 ボードをお薦めします。CPUは64bit、400MHz、デュアルコア、浮動小数点演算器を持ち、8MBのRAMや

 各種アクセラレータを内蔵し、各種I/Fも高速で動作しますので、処理能力は桁違いです。

  ちなみに、私は自作16bitマイコンRISC-V、各種画像処理IPなどの設計・開発を行っていますので、

 自宅でFPGAが使えると助かります。

 

2.各種ツールのインストール

 (1)FPGA開発ツールTang Dynasty IDEのインストール

   Tang Primerの説明にインストール方法が書かれていますが、そのままではインストールできなかった

   ので、下記に記載しておきます。

   <Linux(私はubuntu18.04)へのインストール>

     1. https://dl.sipeed.com/TANG/Primer/IDEから「TD_RELEASE_???_RHEL.zip」をダウンロード。

      参考.ANLOGIC社のHPから最新版もダウンロード可能ですが、現状、Ver.4.6.5が最も安定してます。

      https://dl.sipeed.com/TANG/Premier/IDEから最新の「Anlogic_???.lic」をダウンロード。

      (どちらかに統一して欲しい...)

     2. 開発ソフトを展開し、実行ファイルを準備。

        >>unzip TD_RELEASE_???_RHEL.zip

        >>sudo mv TD_??? /opt/

        >>cd /opt/TD_???/bin

        >>sudo chmod u+x td

        >>sudo ln -s /opt/TD_???/bin/td /usr/bin/td

     3. FPGAのデバイス情報を/usr/archにコピー。

      >>sudo cp -r /opt/TD_???/arch /usr/

     4. ライセンスファイルの設定。(最新のライセンスファイルを使用すること)

      >>sudo mkdir /usr/license

      >>cp Anlogic_???.lic /usr/license/Anlogic.lic

     5. TDを起動。

      >>sudo td -gui

 

   <Windowsへのインストール>

     1.インストーラを実行する。(但し、中国語なのでそれらしいボタンを押す)

     2.ライセンスファイル名を「anlogic.lic」に変え、インストールしたフォルダのlicenseフォルダにコピー。

  

 (2)JTAGのUSBドライバの設定(TangPrimer基板上のJTAGチップ用!)

   基本的には、Tang Primerの説明通りです。

     1. エディタで「/etc/udev/rules.d/91-anlogic-jtag.rules」を作成する。内容は次の通り。

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0547", ATTRS{idProduct}=="1002", \

GROUP="plugdev", \

MODE="0660"

     2. >>sudo service udev restart

   (1)でインストールしたTDを起動し、Downloadボタンを押して「EG4S20BG256」が認識されていればOK。

 

 (3)回路合成

   サンプル回路は、次の方法でダウンロード可能です。

    ・基本的なサンプル回路

     >>git clone --recursive https://github.com/Lichee-Pi/Tang_FPGA_Examples

 

    ・RISC-V(Tang_E203_Mini):Lichee-Piの純正ではなく、こちらを使う必要があるようです。

       問題は、「project/e203egmini_new.sdc」のクロック名の間違いのようです。

       なお、私が確認したところ、24MHzまでタイミングがメットしました。(ToolsーIP Generatorで

       PLLのクロック設定を変更し、制約ファイル「project/e203egmini_new.sdc」を書き換えること)

     >>git clone --recursive https://github.com/riktw/Tang_E203_Mini

 

   その後、ProjectーOpen Project で*.alファイルを開き、ProjectーCleanProjectで以前のデータを

   消去し、ProcessーRun 又は Runアイコンを押すと、回路合成可能です。

 

   新たにプロジェクトを作る場合は、ProjectーNewProjectで、プロジェクト名とフォルダーを選択し、

     DeviceFamily:EG4

     DeviceName:EG4S20BG256

   を選択し、SourceーAddSourceでソースファイルを選択し、Constraintsの上で右ボタンを押し、

   AddADCFile(ピンアサイン)やAddSDCFile(タイミング制約)で制約ファイルを読み込めばOKです。

   もちろん、Toolsの各機能で、ピンアサインやタイミング制約を決めることも可能です。

   また、ToolsーIP Generatorを選べば、PLL、ADC、SDRAMなどが使えるようになります。

   詳細は、こちらをご覧ください。

 

 (4)回路の書き込み

   Downloadアイコンを押し、Addで*.binファイルを選択します。

   ModeSelectionのModeがJTAGの場合、Fileを選んでRunを押すと、一時的にFPGAに回路を書き込み、

   実行することができます。でも、一時書き込みなので、電源を落とすと、Flashに格納されている元の回路

   が起動します。書き込み時間は短いので、動作検証はこちらで行います。

   ModeSelectionのModeをPROGRAM FLASHに変更し、Fileを選んでRunを押すと、Flashメモリに回路を

   書き込むことができます。この場合、電源を落としてもその回路が起動します。

 

 (5)実行時の注意

   ・基板のRESETボタンは、FPGAのPROGRAM_Bに繋がっていますので、Flashメモリからロードされます。

   ・基板のUSERボタンは、E203等では回路のリセットに繋がっていますので、一時書き込みでも回路を

    リセット可能です。

   ・サンプルのピンアサインは結構間違えていますので、実機や回路図を確認してつなぎ直しましょう。

    (例えば、LEDのGとBが入れ替わっているとか、標準のUART端子が違うとか...)

 

3.E203のソフト開発

 (0)最初に注意点

   私も、2021年3月になってJTAG/RISC-Vデバッガを購入しましたが、TangPrimerに搭載されている

   XTX社のQSPIフラッシュメモリがopenocdに登録されていないため書き込み時にエラーが発生します。

   しかし、下記の方法でWindows及びLinuxでプログラムを書き込む事ができました。

   ・RISC-V(Hummingbird E203)のプログラムを書き込むためには、SWITCH SCIENCE等で売っている

    Sipeed社のJTAG/RISC-Vデバッガが必要です。

   ・マニュアル通り実行しても、プログラムを書き込むことはできません。下記の手順で書き込みソフトを

    コンパイルし直す必要が有ります。

   ・Arduinoのシールドを使えるように、上記のようなボードを作っておくと便利です。

  

 (1)Windowsの場合

   Windowsの場合は、Arduino IDEでソフト開発が可能です。ただ、標準の書き込みソフトではQSPIフラッシュに

   書き込めないようです。こちらの記事を参照下さい。これで書き込めました。

   但し、サンプルプログラムは、Hifive社のボードに合わせているので、ピンアサインを変更する等の対応が

   必要です。

 

 (2)Linuxの場合

   Linuxの場合は、sirv-e-sdkでソフト開発が可能です。しかし、ここのページの通り行ってもうまく行きません。

    1. Cコンパイラのインストール

     sirv-e-sdk.tar.lrzをダウンロード

     >>sudo apt-get install lrzip libusb-0.1 libftdi1-2 libftdi1-dev

     >>lrzuntar sirv-e-sdk.tar.lrz

     >>whoami で<username>を調べる。

     >>sudo usermod -a -G plugdev <username>

 

    2. サンプルのコンパイル

     softwareフォルダのdemo_gpioをコンパイルする場合は次のようにします。

     >>cd sirv-e-sdk

     >>make software PROGRAM=demo_gpio BOARD=sirv-e203-lichee

 

    3. JTAG/RISC-Vデバッガのドライバ設定

     エディタで、「/etc/udev/rules.d/45-dt2232.rules」を作る。内容は次の通り。

SUBSYSTEMS=="usb", ATTRS{idVendor}=="0403", ATTRS{idProduct}=="6010", \

GROUP="plugdev", \

MODE="0660"

     >>sudo service udev restart

 

    4.QSPIフラッシュメモリへの書き込み

     上にも書いたように、openocdにXTX社のフラッシュメモリが登録されていないため、upload

     を行うとエラーが出ます。そのため、次の手順で、openocdを作り直す必要があります。

       >>git clone https://github.com/Lichee-Pi/LicheeTang_openocd.git

       >>cd LicheeTang_openocd

       >>./bootstrap

       >>./configure --enable-ftdi

       エディタで「src/flash/nor/spi.c」を開き、flash_devices[]に下記の設定を追加。

          FLASH_ID("xtx xt25f08", 0xd8, 0xc7, 0x0014400b, 0x100, 0x10000, 0x100000),

       >>make

       「src/openocd」を、sirv-e-sdk/work/build/openocd/prefix/bin/ にコピーする。

     この後、

      >>make upload PROGRAM=demo_gpio BOARD=sirv-e203-lichee

     を行うと、書き込みが成功し、E203が起動します。但し、ディフォルトのままだと、

     UART(115.2kbps)で文字が出るだけで、LEDの色は変化しません。

     「sirv-e-sdk/bsp/env/hifive1.h」のピンアサインを変更するとLEDの色が変わるようになります。

 

4.RISC-Vの設計・開発をしよう

 (1)RISC-Vとは?

   RISC-Vは、2010年に米国カリフォルニア大学バークレー校で開発を開始し、多くの学生や企業が

   参画し策定されたフリーでオープンなRISC(Reduced Instruction Set Computer) ISA

   (Instruction Set Architecture)です。

   ISAを私が見た感想は、多くの命令でイミーディエイト値を設定できる点、フラグレジスタが存在せず

   条件文にレジスタ名と大/小/一致の条件を記載できる点、が良いなと感じました。

   また、一般に知られているように回路規模を小さくできる、命令セットの拡張性、C命令によるコード量

   削減、そしてなんと言ってもロイヤリティ不要(!)という、組み込み用途に適した特徴も見逃せません。

   元々は学生の研究用に開発されたので、設計は容易です。私も1週間ほどで基本命令(RV32IM)が

   動作するCPUを設計できました。

   しかし、これに飛びついたのが中国です。中国では、多くの学生や企業がすぐに回路設計を行い、

   チップを製造しました。私も、Hummingbird E203のRTLをネットで見つけ、その上位であるE310を

   搭載したチップを開発したことを知って、自分で設計するのを止めてしまいました。

   しかし、2020年、コロナ禍の中、E203を越える仕様で完成させました。詳細はこちら

 

 (2)Hummingbird E203をIcarusVerilogでシミュレーションしよう

   Tang Primerに組み込まれているTang_E203_Miniをシミュレーションしましょう。使うのは、フリーの

   IcarusVerilog。但し、使えるのはWindows版の「iverilog-v11-20190809-x64_setup.exe」だけです。

   Linux版のv10では、実行しても無限ループに陥って終了しません。

   それ以外では、Modelsimで動作することを確認しています。但し、RTLに間違いがあり、下記のように

   RTLの修正が必要ですので、ご注意下さい。

 

   1. ネットを参考に、「iverilog-v11-20190809-x64_setup.exe」をダウンロードし、インストール。

   2. Tang_e203_Miniの中のsrcフォルダーを2.を展開したフォルダーにコピー。

   3. RTLに間違いがあり、次のように修正。これを行わないと、エラーが発生したり、無限ループに

     陥って終了しない事がある。

     src/e203_defines.v

      E203_FLEN_IS_32のdefineを追加するため、下記の記述に差し替え。

`ifdef E203_CFG_HAS_FPU

`ifdef E203_CFG_FPU_DOUBLE

`define E203_FPU_DOUBLE

`define E203_FLEN 64

`else

`define E203_FLEN 32

`define E203_FLEN_IS_32

`endif

`else

`define E203_FLEN 32

`define E203_FLEN_IS_32

`endif

     src/e203_soc_top.v

      moduleの前に、次の文を追加。

`include "e203_defines.v"

   私の方で、Windows版iverilog v11で検証済みのファイルは次の通りです。実行方法は次の通り。

    >>sim_cpu rv32ui-p-add

   テストパターン名(rv32ui-p-add)は、generatedフォルダにある「?.verilog」の名前を入れて下さい。

   シミュレーションは自動で停止し、gtkwaveで波形表示されます。

   但し、「dhrystone4sim」は、下記のSI-RISCVのhbird-e-sdkに含まれているもので、dhrystoneの

   シミュレーション結果が画面に表示されます。しかし、自動的に終了しないので、必ず、Ctrl-Cを

   押して、手で終了して下さい。

  Tang_E203_Mini.zip 1,208,360byte

 

 (3)シミュレーション用のソフト開発

   TangPrimerのE203用のコンパイラでもバイナリはできるのですが、シミュレーション用に

   RAMやFlashメモリのシミュレーションモデルで読み込むヘキサファイルを作成する時は、

   SI-RISCVのhbird-e-sdkを使った方が良いです。ちなみに、同じHPにオリジナルのe203コア

   の回路データも置かれています。

   hbird-e-sdk/softwareの中で、???4simがシミュレーション用です。

 

 なお、自作RISC-Vはメモリマップや割り込みの機構が異なるので開発環境が異なります。

 

5.自作16bitマイコン(RISC16)の実装

  (1)自作16bitプロセッサRISC16の仕様

    RISC16は、私が担当した電気製品に組み込むために作った、16bitのRISCプロセッサです。

    特徴は次の通り。

     ・インストラクションバスとデータバスを完全に分離したハーバードアーキテクチャ。

     ・インストラクションは、基本16bit、値を直接指定する命令は32bit。

      ロード/ストアとレジスタのインクリメント/デクリメントを1サイクルで実行。

      ディレイド分岐により、分岐によるオーバーヘッドを0にできる場合がある。

     ・インストラクションバスとデータバス共に、アドレス幅16bit、データ幅16bit。(容量は各128Kbyte)

     ・割り込み対応。

     ・回路規模は、15,000(乗算器なし)〜20,000ゲート(乗算器あり)程度と非常に小さい。

     ・自作のアセンブラ及び簡易Cコンパイラでソフト開発可能。(最適化も可)

    上記の特徴により、同じ周波数でも、一般的な組み込み用のRISCプロセッサと比べ

    平均2〜3倍高速に処理できます。

    残念ながら、仕事で作ったプロセッサなので、RTLは公開できません。

 

  (2)Tang Primerに実装したRISC16マイコンの仕様

    RISC16プロセッサを中心に周辺回路を組み込んで、Arduino互換のマイコンボードを作成

    しました。仕様は次の通り。(Arduinoコネクタに未接続の端子を含む)

     ・RISC16プロセッサ:36MHz、乗算器あり

       インストラクションメモリ:16bit×16K

       データメモリ:16bit×16K

     ・UART:2チャンネル

     ・SPIホスト/スレーブ:4チャンネル(汎用2ch、MicroSDカード1ch、QuadSPIフラッシュメモリ1ch)

     ・I2Cホスト/スレーブ:2チャンネル

     ・PWM:8チャンネル

     ・ADC:8チャンネル

     ・タイマ:4チャンネル

     ・GPIO:32チャンネル

     ・割り込みコントローラ:16入力(エッジ/レベル、極性設定可)

 

  (3)ソフトウェア

    現在、RISC16マイコンのソフトに次の機能を実装し、各回路の検証を行えます。

      タイマ割り込み

      UARTの送受信及びモニタ:PCのTeratermやscreenで、メモリや周辺回路のリード/ライトを実行

      SPIにLCDパネル(128x160):タイマ割り込みで書き換え

      SPIにフラッシュメモリ:フラッシュメモリのリード/ライト可能

      ADCにアナログジョイスティック

      GPIOにボタン

      PWMにスピーカ

 

6.自作RISC-Vマイコンの実装

  (1)自作RISC-Vの仕様

    2016年頃、自作RISC-Vの設計を開始し、RV32IMの基本命令が独自バス、ウェイト無し、割り込みなし

    で動くところまで作ったのですが、Hummingbird E203のRTLをネットで見つけて止めてしまいました。

    しかし、2020年、コロナ禍の中、TangPrimerを手に入れたこともあって開発を再開し、TangPrimerの

    FPGAに実装して動くところまで来ました。現在の仕様は次の通りで、E203を越えます。

     ・RV32IMAFCのインストラクションに対応。(16bit命令、CSR、A命令、単精度浮動小数点対応)

     ・命令バス、データバスを分離したハーバード・アーキテクチャで共に、32bitAHBバス。

      そのままハーバード・アーキテクチャで使っても良いし、AHBバスアービトレータを用いれば、

      ユニファイドバスにもできます。

     ・マシンモードの割り込みのみ対応。未定義命令やメモリアクセス違反などには非対応。

     ・乗算器はDSPによるマルチサイクルで3clk、除算器は2〜17clk。

     ・単精度浮動小数点演算は、加算が4clk、乗算が5clk、割り算が17clk、ルートが16clk、積和が7clk。

     ・Block RAMを使った大容量の命令キャッシュメモリを搭載できるようにしました。

      (容量やアドレス数はFPGAのリソースに依存。以前はFFで実現していたため小容量。)

 

  (2)RISC-Vマイコンの仕様

    RISC-Vプロセッサを中心に周辺回路を組み込んで、Arduino互換のマイコンボードを作成

    しました。SDRAMやADCも使っていて、TangPrimerの機能を全て使っています。

    <RV32IMAC版>

     仕様書はこちら

     ・RISC-Vプロセッサ:RV32IMAC、AHBバス(アービトレータによるユニファイドバス)

               2KB(4アドレス)命令キャッシュ

       実力使いで、32MHzで駆動(タイミングレポートでは、28〜31MHz)

     ・ブートROM:32bit×4K(0wait)

     ・SRAM:32bit×24K(0wait)

     ・SDRAM:32bit×2M(4〜5wait!、内部72MHz)

     ・DMA:4チャンネル(UART、SPI、メモリーメモリに使用可能)

     ・UART:2チャンネル

     ・SPIホスト/スレーブ:3チャンネル(汎用2ch、MicroSDカード1ch)

     ・QSPIフラッシュメモリI/F:1ポート

     ・I2Cホスト/スレーブ:2チャンネル

     ・PWM:8チャンネル

     ・ADC:8チャンネル

     ・タイマ:4チャンネル

     ・GPIO:32チャンネル

     ・割り込みコントローラ:16入力(エッジ/レベル、極性設定可)

    <RV32IMAFC版>

     仕様書はこちら

     ・RISC-Vプロセッサ:RV32IMAFC、AHBバス(アービトレータによるユニファイドバス)

               1KByte(4アドレス)命令キャッシュ

       実力使いで、32MHzで駆動(タイミングレポートでは、27〜28MHz)

     ・DMA:1チャンネル(UART、SPI、メモリーメモリに使用可能)

     ・UART:1チャンネル

     ・SPIホスト/スレーブ:1チャンネル(汎用1ch)

     ・I2Cホスト/スレーブ:無し

     その他はRV32IMACと同じ。TangPrimerのFPGAの使用率は97%を超えています。

 

  (3)ソフトウェア

    現在、RISC-VマイコンのブートROMに次の機能を持つプログラムを書き込んでいます。

      タイマ割り込み

      UARTの送受信及びモニタ:PCのTeratermやscreenで、メモリや周辺回路のリード/ライトと、

        ジャンプが可能。これにより、RAMにプログラムをロードし実行することも可能。

      SPIに128x160LCDパネル:タイマ割り込みで書き換え開始、DMAによる高速書き込み

      QSPIフラッシュメモリ:フラッシュメモリのリード/ライト機能搭載

      ADCにアナログジョイスティック

      GPIOにボタン

      PWMにスピーカ

    最初は自作のアセンブラでプログラムを作成し、現在はRISC-Vのクロスコンパイラgccを使ってます。

    RV32IMACアーキテクチャでは、16bit命令と32bit命令が混在して厳しい条件ですが、乗算、除算、

    浮動小数点演算ライブラリ(ソフトエミュレート)など含め、問題なく動いています。割り込み、DMA転送を

    有効にしても安定して動いているようです。

    RV32IMAFCアーキテクチャでは、浮動小数点演算もハードで問題なく計算できています。演算速度も

    RV32IMACとは桁違いです。

    RISC-Vのクロスコンパイラのインストール方法は次の通りです。

 

    (1)Cコンパイラをインストール

      >>mkdir ダウンロードするフォルダ

      >>cd ダウンロードするフォルダ

      >>sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

      >>git clone --recursive https://github.com/riscv/riscv-gnu-toolchain

      >>cd riscv-gnu-toolchain

      >>./configure --prefix=/opt/riscv32 --with-arch=rv32imac --with-abi=ilp32

      >>sudo make -j4

      >>export PATH=/opt/riscv32/bin:$PATH

 

    (2)初期化ルーチンの設定:「start.S」の作成

      割り込みなしで動作検証する場合、スタックポインタだけ設定して、main()を実行します。

      割り込みを使用する場合、今は、割り込み処理ルーチンや割り込みのエントリやイネーブル

      (CSRの書き換え)等もここに書いています。そしてグローバル変数を書き換えることで、

      メインコードに割り込み発生を知らせています。(メインコードの関数を呼び出すこともできるはず)

.section .text.init;

.globl _start

_start:

li sp, 0x80800000

jal main

    (3)リンク情報の設定:「link.ld」の作成

      ROM起動用のコード生成時は、コードをROM領域(0x20000000-)、データをSDRAM領域(0x80000000-)

      に格納できるように、次のような内容にしました。(初期値を持つグローバル変数に対応できるように修正)

      SRAMに書き込んで実行する場合は、コードをRAM領域(0x01000000-)に設定します。

OUTPUT_ARCH( "riscv" )

ENTRY(_start)

SECTIONS

{

. = 0x20000000;

.text.init : { *(.text.init) }

.tohost : { *(.tohost) }

.text : { *(.text) }

.data : { *(.data) }

. = 0x80000000;

.bss : { *(.bss) }

_end = .;

}

      SDRAMに書き込んで実行する場合は、SDRAM領域(0x80000000-)だけを設定します。

OUTPUT_ARCH( "riscv" )

ENTRY(_start)

SECTIONS

{

. = 0x80000000;

.text.init : { *(.text.init) }

.tohost : { *(.tohost) }

.text : { *(.text) }

.data : { *(.data) }

.bss : { *(.bss) }

_end = .;

}

    (4)コンパイルの実行:「make.sh」の作成

      <RV32IMAC仕様でコンパイルする場合>

      初期の動作検証は、最適化無しで、次のようにしてコンパイルします。

      FPGAやシミュレータで使用するHEXファイルと、逆アセンブルしたファイルも出力しています。

#!/bin/sh

riscv32-unknown-elf-gcc -march=rv32imac -c -o start.o start.S

riscv32-unknown-elf-gcc -march=rv32imac -c -o $1.o $1.c

riscv32-unknown-elf-ld $1.o start.o -L/opt/riscv32/riscv32-unknown-elf/lib/ -Tlink.ld -nostartfiles -static -o $1.elf

riscv32-unknown-elf-objcopy -O binary $1.elf $1.bin

hexdump -v -e '1/4 "%08x" "\n"' $1.bin > $1.hex

riscv32-unknown-elf-objdump -d $1.elf > $1.asm

      最適化を行う場合、memset等の組み込み関数が必要です。更に、浮動小数点ライブラリや

      sprintfやstring関係の関数も使いたい場合は、次のようにします。(見つけるのに苦労しました。)

      なお、SPIやUART等のレジスタアクセスで、ステータスをポーリングするコードが最適化で消えてしまう

      ので、関係する全ての変数に、「volatile」を付ける必要があります。

#!/bin/sh

riscv32-unknown-elf-gcc -march=rv32imac -c -o start.o start.S

riscv32-unknown-elf-gcc -Wall -march=rv32imac -mabi=ilp32 -nostartfiles -lm -o $1.o -c $1.c -O3

riscv32-unknown-elf-gcc -Wall -march=rv32imac -mabi=ilp32 -nostartfiles -Xlinker $1.o start.o -Tlink.ld -lgcc -L/opt/riscv32/riscv32-unknown-elf/lib/rv32imac/ilp32/ -lm -static -o $1.elf

riscv32-unknown-elf-objcopy -O binary $1.elf $1.bin

hexdump -v -e '1/4 "%08x" "\n"' $1.bin > $1.hex

riscv32-unknown-elf-objdump -d $1.elf > $1.asm

      以上の設定でSPI、UART、液晶パネルへの文字やグラフィック表示、浮動小数点演算(ソフトエミュレート)

      等を行うプログラムを作成し、問題なく動作しています。

      また、やや大規模なソフトとして自作ゲームをArduinoから移植しましたが、3Dポリゴン、

      PWMサウンド、ADC含め動作に問題はなく、最適化を行えば、整数演算だけならESP32並の

      速度で動作しました。但し、浮動小数点を使うと、ESP32に全く及びません。

      (ハード制御に関係する全ての変数に、「volatile」を付ける事)

 

      <RV32IMAFC仕様でコンパイルする場合>

      RV32IMAFCで浮動小数点演算命令(F命令)を使う場合は、次のように設定します。

      なお、組み込み関数は sin→sinf、cos→cosf のように変更が必要です。これによりソフト

      エミュレートに比べ格段に速くなります。

#!/bin/sh

riscv32-unknown-elf-gcc -march=rv32imafc -mabi=ilp32f -c -o start.o start.S

riscv32-unknown-elf-gcc -Wall -march=rv32imafc -mabi=ilp32f -nostartfiles -lm -o $1.o -c $1.c -O3

riscv32-unknown-elf-gcc -Wall -march=rv32imafc -mabi=ilp32f -nostartfiles -Xlinker $1.o start.o -Tlink.ld -lgcc -L/opt/riscv32/riscv32-unknown-elf/lib/rv32imafc/ilp32f/ -lm -static -o $1.elf

riscv32-unknown-elf-objcopy -O binary $1.elf $1.bin

hexdump -v -e '1/4 "%08x" "\n"' $1.bin > $1.hex

riscv32-unknown-elf-objdump -d $1.elf > $1.asm

Arduinoの紹介はこちら。 

 

「ESP32の使い方」はこちら。

 

「Sipeed Maix BitでA.I.を体験」はこちら。

 

「PYNQ:PythonでFPGAを動かそう」はこちら。