<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>NSL on ck-dev</title><link>https://www.ck-dev.io/tags/nsl/</link><description>Recent content in NSL on ck-dev</description><generator>Hugo -- gohugo.io</generator><language>en-us</language><copyright>©2021 koyamanX</copyright><lastBuildDate>Mon, 15 Mar 2021 19:00:21 +0900</lastBuildDate><atom:link href="https://www.ck-dev.io/tags/nsl/index.xml" rel="self" type="application/rss+xml"/><item><title>Design of branch instruction issue for RISC-V OoO</title><link>https://www.ck-dev.io/blog/design_riscv_ooo_branch/</link><pubDate>Tue, 15 Feb 2022 00:41:52 +0900</pubDate><guid>https://www.ck-dev.io/blog/design_riscv_ooo_branch/</guid><description>&lt;p>趣味でRISC-Vのアウト・オブ・オーダープロセッサを実装している。
Tomasulo algorithmに基づいている。
今回は分岐命令の発行部分の検討をしていく。
Commit: df27bdc1b9382573458b5bf571ca32a9fa93325c&lt;/p>
&lt;h1 id="bru-pipe">BRU pipe&lt;/h1>
&lt;p>今回の実装では分岐命令はBRU(BRanch Unit) pipeで実行する。2-wayのデコードのスーパスカラな実装で、現状はALUパイプは2つある。
ここにBRUパイプとリザベーションステーションを追加する。&lt;/p>
&lt;h1 id="branch命令の実行">Branch命令の実行&lt;/h1>
&lt;p>今回はBranch命令を以下のように分類する。&lt;/p>
&lt;ul>
&lt;li>Branch(opcode == BRANCH)&lt;/li>
&lt;li>Jump(opcode == JAL || opcode == JALR)&lt;/li>
&lt;/ul>
&lt;p>現状の実装では、Jump命令は分岐のコンディションを計算する必要ないため、ALUパイプへ発行している。分岐パイプが実装できたら、こちらへ発行するようにする。&lt;/p>
&lt;h2 id="bru-rs">BRU RS&lt;/h2>
&lt;p>分岐パイプ用のリザベーションステーションは１つとする。（エントリではない）
フェッチパケット(命令フェッチの単位、今回は２命令同時フェッチ）内に分岐命令が２つある場合、デコードステージを２回行う。
一回目では先行の命令のみを発行をする。次のサイクルでは次の命令を発行する。&lt;/p>
&lt;p>issueステージでは、分岐命令が１つしか発行されないことを前提する。
issueステージでは、BRU用のリザベーションステーションへ発行する。&lt;/p>
&lt;p>オペランドが揃った時点で、BRUパイプへDispatchする。&lt;/p>
&lt;p>実行ステージでは、分岐命令の成否とターゲットアドレスを計算する。
つまり、必要なオペランドは以下のものとなる。&lt;/p>
&lt;ul>
&lt;li>PC&lt;/li>
&lt;li>Imm&lt;/li>
&lt;li>rs1&lt;/li>
&lt;li>rs2&lt;/li>
&lt;/ul>
&lt;p>ターゲットアドレスはissueステージで計算可能なので、事前にissueステージでpc+immを計算し、ROB.Targetへ格納しておく。
実行ステージではrs1 Branch Op rs2を計算し、write resultステージで、ROB.ValueへCDBを通してブロードキャストする
Jump命令の場合は常に、1を格納する。&lt;/p>
&lt;h2 id="bru-commit">BRU Commit&lt;/h2>
&lt;p>コミット時には、以下の条件で分岐をする。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">if&lt;/span>&lt;span class="p">((&lt;/span>&lt;span class="n">opcode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">JAL&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">opcode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">JALR&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">opcode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">BRANCH&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">opcode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">JAL&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="n">opcode&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">JALR&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">GPR&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">rd&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">PC4&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ROB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Value&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">])&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">Redirect&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ROB&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="c1">// Feedback to Branch prediction unit if it presents
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="c1">// Also check prediction and actual result
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="c1">// Normal commit
&lt;/span>&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>My RISC-V debug feature part8(implement suggested DMI signal interface)</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part8/</link><pubDate>Tue, 20 Jul 2021 22:28:05 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part8/</guid><description>&lt;p>独自のDMIインターフェースから推奨インターフェースに変更する。&lt;/p>
&lt;p>riscv-debugによると、以下の信号がインターフェースとして推奨されているようである。&lt;/p>
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./suggested_DMI_interface_from_spec.png"
target="_blank">&lt;img class="img" src="./suggested_DMI_interface_from_spec.png"/>&lt;/a>&lt;/span>
&lt;/span>
&lt;p>ちなみに、今回の実装ではABITSは32 bitとしている。&lt;/p></description></item><item><title>My RISC-V debug feature part7 (examine関数(riscv013)の読解, DMの実装)</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part7/</link><pubDate>Sun, 16 May 2021 20:56:07 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part7/</guid><description>&lt;p>今回から、&lt;code>examine&lt;/code>関数を読み、初期化のフローを理解する。
DMを実装をして、&lt;code>examine&lt;/code>で初期化をできるようにしていく。&lt;/p>
&lt;h2 id="examine関数">examine関数&lt;/h2>
&lt;p>&lt;code>examine&lt;/code>関数はriscv013用のインターフェイスより呼び出される。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv-013.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="n">riscv013_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">init_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">init_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deinit_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">deinit_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">examine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">examine&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">poll&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_openocd_poll&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">halt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_halt&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">step&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_openocd_step&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">assert_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assert_reset&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deassert_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">deassert_reset&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">write_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">write_memory&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">arch_state&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arch_state&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="examine関数の実体">examine関数の実体&lt;/h3>
&lt;p>&lt;code>src/target/riscv/riscv-013.c:examine&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="cm">/* Don&amp;#39;t need to select dbus, since the first thing we do is read dtmcontrol. */&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">dtmcontrol&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dtmcontrol_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;dtmcontrol=0x%x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; dmireset=%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_DMIRESET&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; idle=%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_IDLE&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; dmistat=%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_DMISTAT&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; abits=%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_ABITS&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; version=%d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_VERSION&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>まずは、&lt;code>dtmcontrol_scan&lt;/code>にて、DTM内の&lt;code>dtmcs&lt;/code>をスキャンする。&lt;/p>
&lt;h3 id="dmicsレジスタ">dmicsレジスタ&lt;/h3>
&lt;p>&lt;code>dtmcs&lt;/code>レジスタのフォーマットは以下の通り。
アドレス(IR)は&lt;code>0x10&lt;/code>である。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;p>各フィールドの意味を以下に示す。(riscv-debug-spec p.88)&lt;/p>
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image01.png"
target="_blank">&lt;img class="img" src="./image01.png"/>&lt;/a>&lt;/span>
&lt;/span>
&lt;h4 id="dmihardreset">dmihardreset&lt;/h4>
&lt;p>&lt;code>1&lt;/code>をこのフィールドに書き込むことで、DTMをハードリセットする。
ハードリセットは実行中のDMIトランザクションを終了させる。また、すべてのDTM内部状態、レジスタを初期状態にする。&lt;/p>
&lt;h4 id="dmireset">dmireset&lt;/h4>
&lt;p>&lt;code>1&lt;/code>を書き込むことで、&lt;code>sticky error&lt;/code>状態をクリアする。また、DMIトランザクションはキャンセルしない。&lt;/p>
&lt;h4 id="idle">idle&lt;/h4>
&lt;p>デバッカに与えるヒントで、DMI scan後に必要なRun-Test/Idleサイクル数を保持する。
必要に応じて、デバッカは&lt;code>dmics.dmistat&lt;/code>を確認する。&lt;/p>
&lt;pre>&lt;code>0: 不要
1: 1
2: 2
...
&lt;/code>&lt;/pre>&lt;h4 id="dmistat">dmistat&lt;/h4>
&lt;pre>&lt;code>0: no error
1: reserved(same as 2)
2: An operation failed
3: An operation was attempted while DMI access was still in progress
&lt;/code>&lt;/pre>&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image02.png"
target="_blank">&lt;img class="img" src="./image02.png"/>&lt;/a>&lt;/span>
&lt;/span>
&lt;h4 id="abits">abits&lt;/h4>
&lt;p>The size of address in dmi&lt;/p>
&lt;h4 id="version">version&lt;/h4>
&lt;pre>&lt;code>0: version 0.11
1: version 0.13 and 1.0
15: version not described in any spec
&lt;/code>&lt;/pre>&lt;h3 id="examine続き">examine続き&lt;/h3>
&lt;p>&lt;code>src/target/riscv/riscv-013.c:examine&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;dtmcontrol is 0. Check JTAG connectivity/board power.&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_VERSION&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Unsupported DTM version %d. (dtmcontrol=0x%x)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_VERSION&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>読み出した、&lt;code>dtmcontrol(dtmcs)&lt;/code>を確認する。
&lt;code>riscv013&lt;/code>では、versionが&lt;code>1&lt;/code>がリセット値であることが保証されているので、&lt;code>dtmcontrol&lt;/code>が0であるとき、正しく読み出せていないことになる。&lt;/p>
&lt;p>つぎに、&lt;code>dtmcs.version&lt;/code>を読み出し、&lt;code>1(version 0.13 and 1.0)&lt;/code>であるか確認している。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv-013.c:examine&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="n">riscv013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* TODO: This won&amp;#39;t be true if there are multiple DMs. */&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">coreid&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">abits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_ABITS&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtmcs_idle&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTM_DTMCS_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* Reset the Debug Module. */&lt;/span>
&lt;span class="n">dm013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">dm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_dm&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>読み出した、&lt;code>index&lt;/code>, &lt;code>abits&lt;/code>, &lt;code>idle&lt;/code>は&lt;code>info&lt;/code>構造体へ保存する。&lt;/p>
&lt;h4 id="get_info関数">get_info関数&lt;/h4>
&lt;p>&lt;code>get_info&lt;/code>関数では、&lt;code>riscv&lt;/code>のバージョン固有の&lt;code>info&lt;/code>構造体を取得する。
今回の場合は、&lt;code>riscv013&lt;/code>用のinfo構造体(&lt;code>riscv013_info_t&lt;/code>)を取得する。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv-013.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="n">riscv013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nf">get_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">riscv_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">arch_info&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">version_specific&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">riscv013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">version_specific&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/riscv/riscv-013.c&lt;/code>
&lt;code>riscv013_info_t&lt;/code>抜粋&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">typedef&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* The indexed used to address this hart in its DM. */&lt;/span>
&lt;span class="kt">unsigned&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Number of address bits in the dbus register. */&lt;/span>
&lt;span class="kt">unsigned&lt;/span> &lt;span class="n">abits&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Number of abstract command data registers. */&lt;/span>
&lt;span class="kt">unsigned&lt;/span> &lt;span class="n">datacount&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Number of words in the Program Buffer. */&lt;/span>
&lt;span class="kt">unsigned&lt;/span> &lt;span class="n">progbufsize&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* We cache the read-only bits of sbcs here. */&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">sbcs&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">...&lt;/span>
&lt;span class="n">dm013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">dm&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="n">riscv013_info_t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>DTMやDMの情報を保持する。&lt;/p>
&lt;h4 id="get_dm関数">get_dm関数&lt;/h4>
&lt;p>この関数では、ターゲットの&lt;code>DM&lt;/code>構造体を返す。
もし、見つからない場合は、作成し初期化する。
構造体としては、&lt;code>dm013_info_t&lt;/code>と同じである。&lt;/p>
&lt;h3 id="examine続き-1">examine続き&lt;/h3>
&lt;p>&lt;code>src/target/riscv/riscv-013.c:examine&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">dm&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">dm&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">was_reset&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">dmi_write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">dmi_write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL_DMACTIVE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">dm&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">was_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">dmi_write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL_HARTSELLO&lt;/span> &lt;span class="o">|&lt;/span>
&lt;span class="n">DM_DMCONTROL_HARTSELHI&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">DM_DMCONTROL_DMACTIVE&lt;/span> &lt;span class="o">|&lt;/span>
&lt;span class="n">DM_DMCONTROL_HASEL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">dmi_read&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL_DMACTIVE&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Debug Module did not become active. dmcontrol=0x%x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>dm&lt;/code>が初期化されていない場合は、初期化をする。
初期では、&lt;code>DM_DMCONTROL&lt;/code>(&lt;code>DTM&lt;/code>でないことに注意)をまず、0で初期化する。
&lt;code>dmi_write&lt;/code>は&lt;code>dbus(DMI)&lt;/code>を経由して、&lt;code>DM&lt;/code>のレジスタを書き込みする。
今回は、&lt;code>DM_DMCONTORL&lt;/code>アドレスに、&lt;code>0&lt;/code>を書き込む。&lt;/p>
&lt;p>その後、&lt;code>DMACTIVE&lt;/code>フィールドを1にする。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image03.png"
target="_blank">&lt;img class="img" src="./image03.png"/>&lt;/a>&lt;/span>
&lt;/span>
このフィールドはDMのリセット信号として機能する。
このフィールドに書き込みをした場合は、次のアクションを行う前に、書き込んだ値が反映されているかポーリングが必要。
このフィールドが&lt;code>0&lt;/code>の場合は、DMはすべて初期状態であることを示し、DMに対するアクセスはすべて失敗する。
また、&lt;code>version&lt;/code>フィールドは正しい値を返さないかもしれない。
&lt;code>1&lt;/code>の場合は、DMが正しく動作していることを示す。&lt;/p>
&lt;p>次に、&lt;code>DM_DMCONTROL_DMACTIVE&lt;/code>の他に、&lt;code>WARL&lt;/code>フィールドに&lt;code>-1&lt;/code>を書き込む。
読み出したっているビットを見ることで、DMがサポートする機能がわかる。
書き込むフィールドは&lt;code>DM_DMCONTROL_HARTSEL&lt;/code>、&lt;code>DM_DMCONTROL_HARTSELLO&lt;/code>、&lt;code>DM_DMCONTROL_HARTSELHI&lt;/code>である。
これらは、hartの選択方法を規定するものである。（詳しくは後ほど)&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="n">dmi_write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DM_DMCONTROL_HARTSELLO&lt;/span> &lt;span class="o">|&lt;/span>
&lt;span class="n">DM_DMCONTROL_HARTSELHI&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">DM_DMCONTROL_DMACTIVE&lt;/span> &lt;span class="o">|&lt;/span>
&lt;span class="n">DM_DMCONTROL_HASEL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>次に、&lt;code>dmi_read&lt;/code>にて&lt;code>DM_DMCONTROL&lt;/code>を読み出し、&lt;code>DMACTIVE&lt;/code>ビットが1であるか検査をする。
&lt;code>0&lt;/code>の場合は、DMはアクティブでない。&lt;/p>
&lt;h3 id="今日はここまで">今日はここまで&lt;/h3>
&lt;p>今回はここまで。
ちなみに、&lt;code>DMACTIVE&lt;/code>までは、DMを実装している。
そのため、&lt;code>examine&lt;/code>は途中まで成功している。
次回は、まだ実装していない&lt;code>hart&lt;/code>の選択方法から見ていく。
なんか、投稿のフォーマットがぐちゃぐちゃで見づらい説はある。
なんかいい方法ないかな。
あと、表をいい感じに書きたい。&lt;/p></description></item><item><title>My RISC-V debug feature part6 (target examine, riscv examine)</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part6/</link><pubDate>Thu, 13 May 2021 23:02:58 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part6/</guid><description>&lt;p>今回も引き続き、OpenOCDのコードを読んでいく。
&lt;code>target_examine&lt;/code>と&lt;code>riscv_examine&lt;/code>を読む。&lt;/p>
&lt;h2 id="target_examine">target_examine&lt;/h2>
&lt;p>&lt;code>src/target/target.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/* Targets that correctly implement init + examine, i.e.
&lt;/span>&lt;span class="cm"> * no communication with target during init:
&lt;/span>&lt;span class="cm"> *
&lt;/span>&lt;span class="cm"> * XScale
&lt;/span>&lt;span class="cm"> */&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="nf">target_examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">all_targets&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">next&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* defer examination, but don&amp;#39;t skip it */&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">enabled&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">jtag_register_event_callback&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">jtag_enable_callback&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">continue&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">defer_examine&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">continue&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_examine_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval2&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_WARNING&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;target %s examination failed&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target_name&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">retval2&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* Equivalent Tcl code arp_examine_one is in src/target/startup.tcl
&lt;/span>&lt;span class="cm"> * Keep in sync */&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="nf">target_examine_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">target_call_event_callbacks&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TARGET_EVENT_EXAMINE_START&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">target_call_event_callbacks&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TARGET_EVENT_EXAMINE_FAIL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">target_call_event_callbacks&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TARGET_EVENT_EXAMINE_END&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">jtag_enable_callback&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">enum&lt;/span> &lt;span class="n">jtag_event&lt;/span> &lt;span class="n">event&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">priv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">priv&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">event&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">JTAG_TAP_EVENT_ENABLE&lt;/span> &lt;span class="o">||&lt;/span> &lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">enabled&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_unregister_event_callback&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">jtag_enable_callback&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">target_examine_one&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>target_examine_one&lt;/code>にて、ターゲット固有の&lt;code>examine&lt;/code>を実行する。
RISC-Vの場合を見ていく。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="n">riscv_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">target_create&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_create_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">init_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_init_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deinit_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_deinit_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">examine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_examine&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>riscv用のtarget_type構造体の&lt;code>examine&lt;/code>の実態は&lt;code>riscv_examine&lt;/code>である。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">riscv_examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;riscv_examine()&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target_was_examined&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Target was already examined.&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">use_vjtag&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;use_vjtag is enabled&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">riscv_tap_vjtag_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* Don&amp;#39;t need to select dbus, since the first thing we do is read dtmcontrol. */&lt;/span>
&lt;span class="n">RISCV_INFO&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">dtmcontrol&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dtmcontrol_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;dtmcontrol=0x%x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtm_version&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_field&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTMCONTROL_VERSION&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; version=0x%x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtm_version&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">tt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_target_type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tt&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tt&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">init_target&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">tt&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>ここから、RISC-VのDMに対するアクセスが始まる。&lt;/p>
&lt;h2 id="dmへのアクセス">DMへのアクセス&lt;/h2>
&lt;p>なお、今回はVJTAGを用いてDMにアクセスをする。
まず最初にアクセスするのは、&lt;code>dtmcontrol&lt;/code>である。&lt;/p>
&lt;h3 id="dtmcontroldtmcs">dtmcontrol(dtmcs)&lt;/h3>
&lt;p>&lt;code>dtmcontrol&lt;/code>には&lt;code>dtmcontrol_scan&lt;/code>関数を用いてアクセスをする。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="n">uint8_t&lt;/span> &lt;span class="n">ir_dtmcontrol&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">DTMCONTROL&lt;/span>&lt;span class="p">};&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">scan_field&lt;/span> &lt;span class="n">select_dtmcontrol&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ir_dtmcontrol&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;span class="n">uint8_t&lt;/span> &lt;span class="n">ir_dbus&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">DBUS&lt;/span>&lt;span class="p">};&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">scan_field&lt;/span> &lt;span class="n">select_dbus&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ir_dbus&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="n">uint32_t&lt;/span> &lt;span class="nf">dtmcontrol_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">uint32_t&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">scan_field&lt;/span> &lt;span class="n">field&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">uint8_t&lt;/span> &lt;span class="n">in_value&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">uint8_t&lt;/span> &lt;span class="n">out_value&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">};&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">bscan_tunnel_ir_width&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">dtmcontrol_scan_via_bscan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">out_value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">use_vjtag&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">vjtag_vir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">select_dtmcontrol&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;span class="k">else&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">select_dtmcontrol&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">32&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">out_value&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">in_value&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">use_vjtag&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">vjtag_vir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">select_dbus&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;span class="k">else&lt;/span>
&lt;span class="cm">/* Always return to dbus. */&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">select_dbus&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;failed jtag scan: %d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">in&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">buf_get_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">32&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;DTMCONTROL: 0x%x -&amp;gt; 0x%x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">out&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">in&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">in&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>まずは、VIRへDTMCONTROLを転送する。
&lt;code>jtag_add_dr_scan(target-&amp;gt;tap, 1, &amp;amp;field, TAP_IDLE);&lt;/code>
にて、DR scanを行い、DTMCONTROLの値を取得する。(32 bit)
結果は、&lt;code>field&lt;/code>へ格納される。
なお、終了後のTAP状態はIDLEとなる。&lt;/p>
&lt;pre>&lt;code> if (use_vjtag)
vjtag_vir_scan(target-&amp;gt;tap, select_dbus.out_value[0]);
&lt;/code>&lt;/pre>&lt;p>この行では、DBUS(DMI)へVIRを変更している。
&lt;code>int retval = jtag_execute_queue();&lt;/code>でJTAGのコマンドを実行する。&lt;/p>
&lt;p>&lt;code>uint32_t in = buf_get_u32(field.in_value, 0, 32);&lt;/code>
この行で、取得した、DTMCONTROLを取り出す。&lt;/p>
&lt;p>&lt;code>dtmcs(dtmcontrol)&lt;/code>のレジスタの構成は以下のようになっている。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>
&lt;code>version&lt;/code>フィールドを&lt;code>get_field&lt;/code>にて取り出す。&lt;/p>
&lt;p>つぎに、&lt;code>get_target_type&lt;/code>を行い、ターゲットの種別を調べる。
&lt;code>src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="nf">get_target_type&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">riscv_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">arch_info&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Target has not been initialized&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">switch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtm_version&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">case&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv011_target&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">case&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">:&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_target&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">default&lt;/span>&lt;span class="o">:&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Unsupported DTM version: %d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtm_version&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>バージョンに応じて、&lt;code>riscv013_target&lt;/code>, &lt;code>riscv011_target&lt;/code>を選択する。
今回は、&lt;code>0b0001&lt;/code>としたので、riscv-debug-spec 0.13 and 1.0に準拠となる。&lt;/p>
&lt;p>&lt;code>riscv-debug/src/dtm.h&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cp">#define DTMCS_VERSION 4&amp;#39;b0001
&lt;/span>&lt;span class="cp">#define DTMCS_ABITS 6&amp;#39;b100000
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/riscv/riscv.c:riscv_examine&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="kt">int&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tt&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">init_target&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">tt&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">examine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>つぎに、ターゲット(&lt;code>riscv_013&lt;/code>)固有な初期化を行う。
その後、&lt;code>examine&lt;/code>をする。&lt;/p>
&lt;p>&lt;code>riscv-013&lt;/code>固有の&lt;code>target_type&lt;/code>構造体は以下のとおりである。
&lt;code>src/target/riscv/riscv-013.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="n">riscv013_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">init_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">init_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deinit_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">deinit_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">examine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">examine&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">poll&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_openocd_poll&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">halt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_halt&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">step&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_openocd_step&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">assert_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">assert_reset&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deassert_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">deassert_reset&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">write_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">write_memory&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">arch_state&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">arch_state&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/riscv/riscv-013.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">init_target&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">command_context&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">RISCV_INFO&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">generic_info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">get_register&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_get_register&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">set_register&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_set_register&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">get_register_buf&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_get_register_buf&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">set_register_buf&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_set_register_buf&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">select_current_hart&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_select_current_hart&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">is_halted&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_is_halted&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">resume_go&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_resume_go&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">step_current_hart&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_step_current_hart&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">on_halt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_on_halt&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">resume_prep&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_resume_prep&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">halt_prep&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_halt_prep&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">halt_go&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_halt_go&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">on_step&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_on_step&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">halt_reason&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_halt_reason&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">read_debug_buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_read_debug_buffer&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">write_debug_buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_write_debug_buffer&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">execute_debug_buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_execute_debug_buffer&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">fill_dmi_write_u64&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_fill_dmi_write_u64&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">fill_dmi_read_u64&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_fill_dmi_read_u64&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">fill_dmi_nop_u64&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_fill_dmi_nop_u64&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dmi_write_u64_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_dmi_write_u64_bits&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">authdata_read&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_authdata_read&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">authdata_write&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_authdata_write&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dmi_read&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">dmi_read&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dmi_write&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">dmi_write&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">read_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">read_memory&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">test_sba_config_reg&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_test_sba_config_reg&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">hart_count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_hart_count&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">data_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_data_bits&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">print_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv013_print_info&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">version_specific&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">calloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">riscv013_info_t&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">version_specific&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">generic_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">sample_memory&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sample_memory&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv013_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_info&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">progbufsize&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dmi_busy_delay&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">bus_master_read_delay&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">bus_master_write_delay&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ac_busy_delay&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Assume all these abstract commands are supported until we learn
&lt;/span>&lt;span class="cm"> * otherwise.
&lt;/span>&lt;span class="cm"> * TODO: The spec allows eg. one CSR to be able to be accessed abstractly
&lt;/span>&lt;span class="cm"> * while another one isn&amp;#39;t. We don&amp;#39;t track that this closely here, but in
&lt;/span>&lt;span class="cm"> * the future we probably should. */&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">abstract_read_csr_supported&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">abstract_write_csr_supported&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">abstract_read_fpr_supported&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">abstract_write_fpr_supported&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">has_aampostincrement&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">YNM_MAYBE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>init&lt;/code>では、&lt;code>riscv013&lt;/code>の処理用の関数を&lt;code>generic_info&lt;/code>構造体へセットしている。
&lt;code>generic_info&lt;/code>のRISC-V Debug specのバージョン非依存なインターフェイスを提供する。&lt;/p>
&lt;p>今日はここまで。
次回は&lt;code>examine&lt;/code>を読んで、&lt;code>examine&lt;/code>の処理が通るようなDMを実装していく。&lt;/p></description></item><item><title>My RISC-V debug feature part5</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part5/</link><pubDate>Mon, 10 May 2021 22:21:40 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part5/</guid><description>&lt;p>仕様を読んでいるが、よくわからない。
hartselとかwindowみたいなのがあってよく分かりづらい。
最小限の機能で、OpenOCDから制御できればいいので、
OpenOCDの初期化フローを読んで、それに応答するようなDM(Debug Module)を作ってみる。&lt;/p>
&lt;h2 id="openocdの初期化">OpenOCDの初期化&lt;/h2>
&lt;p>&lt;code>src/openocd.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/* normally this is the main() function entry, but if OpenOCD is linked
&lt;/span>&lt;span class="cm"> * into application, then this fn will not be invoked, but rather that
&lt;/span>&lt;span class="cm"> * application will have it&amp;#39;s own implementation of main(). */&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="nf">openocd_main&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">[])&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* initialize commandline interface */&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">command_context&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">cmd_ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">setup_command_handler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">NULL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">util_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">EXIT_FAILURE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ioutil_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">EXIT_FAILURE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">rtt_init&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">EXIT_FAILURE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">LOG_OUTPUT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;For bug reports, read&lt;/span>&lt;span class="se">\n\t&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;http://openocd.org/doc/doxygen/bugs.html&amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">command_context_mode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">command_set_output_handler&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">configuration_output_handler&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">server_host_os_entry&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="cm">/* Start the executable meat that can evolve into thread in future. */&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">openocd_thread&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">flash_free_all_banks&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">gdb_service_free&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">server_free&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">unregister_all_commands&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* free all DAP and CTI objects */&lt;/span>
&lt;span class="n">dap_cleanup_all&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">arm_cti_cleanup_all&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">adapter_quit&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">server_host_os_close&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="cm">/* Shutdown commandline interface */&lt;/span>
&lt;span class="n">command_exit&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">rtt_exit&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="n">free_config&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_FAIL&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">EXIT_FAILURE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">else&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">exit_on_signal&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ret&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/** OpenOCD runtime meat that can become single-thread in future. It parse
&lt;/span>&lt;span class="cm"> * commandline, reads configuration, sets up the target and starts server loop.
&lt;/span>&lt;span class="cm"> * Commandline arguments are passed into this function from openocd_main().
&lt;/span>&lt;span class="cm"> */&lt;/span>
&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">openocd_thread&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">[],&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">command_context&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">parse_cmdline_args&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">server_preinit&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">parse_config_file&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ret&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">ERROR_COMMAND_CLOSE_CONNECTION&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">server_quit&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="cm">/* gdb server may be initialized by -c init */&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ret&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">server_quit&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="cm">/* gdb server may be initialized by -c init */&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">server_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">init_at_startup&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">server_quit&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">server_loop&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">last_signal&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">server_quit&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">last_signal&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">last_signal&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ret&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>openocd_thread&lt;/code>がメインになる様子。
まず、command line argumentsをパースする。
その後、コンフィグファイルをパースする。
このコンフィグファイルは&lt;code>-f&lt;/code>オプションで渡されるものであり、コマンドを一行ずつ実行していく。&lt;/p>
&lt;h2 id="コンフィグファイルのパースおよび実行">コンフィグファイルのパースおよび実行&lt;/h2>
&lt;p>&lt;code>src/helper/configuration.c&lt;/code>&lt;/p>
&lt;pre>&lt;code>int parse_config_file(struct command_context *cmd_ctx)
{
int retval;
char **cfg;
if (!config_file_names) {
command_run_line(cmd_ctx, &amp;quot;script openocd.cfg&amp;quot;);
return ERROR_OK;
}
cfg = config_file_names;
while (*cfg) {
retval = command_run_line(cmd_ctx, *cfg);
if (retval != ERROR_OK)
return retval;
cfg++;
}
return ERROR_OK;
}
&lt;/code>&lt;/pre>&lt;p>&lt;code>tcl/target/rv32xsoc.cfg&lt;/code>の抜粋。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-bash" data-lang="bash">...
jtag newtap &lt;span class="nv">$_CHIPNAME&lt;/span> cpu -irlen &lt;span class="m">10&lt;/span> -expected-id &lt;span class="nv">$_FPGATAPID&lt;/span>
target create &lt;span class="nv">$_TARGETNAME&lt;/span> riscv -endian &lt;span class="nv">$_ENDIAN&lt;/span> -chain-position &lt;span class="nv">$_TARGETNAME&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>parse_config_file&lt;/code>によりパースされ、一行ずつ実行する。
ここでは、&lt;code>target_create&lt;/code>にフォーカスしてみていく。
&lt;code>target create&lt;/code>のハンドラは以下のようになっている。&lt;/p>
&lt;p>&lt;code>src/target/target.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">command_registration&lt;/span> &lt;span class="n">target_command_handlers&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;targets&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">handle_targets_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;change current default target (one parameter) &amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;or prints table of all targets (no parameters)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;[target]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;configure target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">chain&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_subcommand_handlers&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;enable_rtos_riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">handle_enable_rtos_riscv_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;enable_rtos_riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Allow the use of `-rtos riscv` for just a little longer, &amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;until it will be completely removed at the end of 2020.&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="n">COMMAND_REGISTRATION_DONE&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>つまり、&lt;code>target&lt;/code>命令の場合は次にくる引数がサブコマンドになる。
サブコマンドは以下の通り。&lt;/p>
&lt;p>&lt;code>src/target/target.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">command_registration&lt;/span> &lt;span class="n">target_subcommand_handlers&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;init&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">handle_target_init_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;initialize targets&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;create&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_target_create&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;name type &amp;#39;-chain-position&amp;#39; name [options ...]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Creates and selects a new target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;current&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_target_current&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Returns the currently selected target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;types&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_target_types&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Returns the available target types as &amp;#34;&lt;/span> &lt;span class="s">&amp;#34;a list of strings&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">},&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;names&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_target_names&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Returns the names of all targets as a list of strings&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;smp&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_target_smp&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;targetname1 targetname2 ...&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;gather several target in a smp list&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="n">COMMAND_REGISTRATION_DONE&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>今回は&lt;code>target create&lt;/code>なので、&lt;code>jim_target_create&lt;/code>関数が呼ばれることになる。
この関数では、命令の引数を準備し、&lt;code>target_create&lt;/code>を呼び出す。
&lt;code>src/target/target.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">jim_target_create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Jim_Interp&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Jim_Obj&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_GetOptInfo&lt;/span> &lt;span class="n">goi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">Jim_GetOpt_Setup&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argc&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">argv&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">argc&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_WrongNumArgs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">goi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">argc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">goi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="s">&amp;#34;&amp;lt;name&amp;gt; &amp;lt;target_type&amp;gt; [&amp;lt;target_options&amp;gt; ...]&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">target_create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>target create&lt;/code>の引数を処理する。
&lt;code>src/target/target.c:create_target&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">target_create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Jim_GetOptInfo&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_Obj&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">new_cmd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">Jim_Cmd&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cmd&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">const&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cp&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">command_context&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">cmd_ctx&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">current_command_context&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">assert&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">argc&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_WrongNumArgs&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">argv&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;?name? ?type? ..options...&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/target.c:create_target&lt;/code>続き&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="cm">/* now does target type exist */&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">;&lt;/span> &lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="p">;&lt;/span> &lt;span class="n">x&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">strcmp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* found */&lt;/span>
&lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* check for deprecated name */&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">deprecated_name&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">strcmp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">deprecated_name&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* found */&lt;/span>
&lt;span class="n">LOG_WARNING&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;target name is deprecated use: &lt;/span>&lt;span class="se">\&amp;#39;&lt;/span>&lt;span class="s">%s&lt;/span>&lt;span class="se">\&amp;#39;&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">break&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>この部分で、以下のtclのriscvを処理している。
&lt;code>target create $_TARGETNAME riscv -endian $_ENDIAN -chain-position $_TARGETNAME&lt;/code>
&lt;code>target_types[]&lt;/code>から&lt;code>riscv&lt;/code>に対応する、ターゲットを探し出す。&lt;/p>
&lt;p>&lt;code>src/target/target.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target_types&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">arm7tdmi_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">arm9tdmi_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">arm920t_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">arm720t_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">...&lt;/span>
&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">riscv_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">...&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/target.c:target_create&lt;/code>続き&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="cm">/* Create it */&lt;/span>
&lt;span class="n">target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">calloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Out of memory&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* set target number */&lt;/span>
&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">target_number&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">new_target_number&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="cm">/* allocate memory for each unique target type */&lt;/span>
&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">malloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Out of memory&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">memcpy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target_types&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>target_configure&lt;/code>関数で&lt;code>-endian&lt;/code>や&lt;code>-chain-position&lt;/code>を処理をする。&lt;/p>
&lt;p>&lt;code>src/target/target.c:target_create&lt;/code>続き&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_configure&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">JIM_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">has_dap&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dap_configured&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_SetResultString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;-dap ?name? required when creating target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap_configured&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">Jim_SetResultString&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;-chain-position ?name? required when creating target&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* tap must be set after target was configured */&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>また、この時点では(&lt;code>target_create&lt;/code>)、TAPが設定されていることが期待されている(&lt;code>-chain-position&lt;/code>で指定)。上のコードで確認している。&lt;/p>
&lt;p>&lt;code>src/target/target.c:target_create&lt;/code>続き&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">target_create&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">target_create&lt;/span>&lt;span class="p">))(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">goi&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">e&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;target_create failed&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">cmd_name&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">rtos_destroy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">gdb_port_override&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">trace_info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">free&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">JIM_ERR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cm">/* create the target specific commands */&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">e&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">register_commands&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">type&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">commands&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;unable to register &amp;#39;%s&amp;#39; commands&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">cp&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>ここで、ターゲット(riscv)の&lt;code>target_create&lt;/code>を呼び出す。
その後、ターゲットspecificなコマンドを登録する。&lt;/p>
&lt;p>riscv用の&lt;code>target_create&lt;/code>を読んで見る。&lt;/p>
&lt;p>以下が&lt;code>target_types&lt;/code>から取り出した、ターゲットspecificな構造体の実態である。
&lt;code>../src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">struct&lt;/span> &lt;span class="n">target_type&lt;/span> &lt;span class="n">riscv_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;riscv&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">target_create&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_create_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">init_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_init_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">deinit_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_deinit_target&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">examine&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_examine&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>riscv_create_target&lt;/code>が呼び出されることになる。
&lt;code>../src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">riscv_create_target&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Jim_Interp&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">interp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;riscv_create_target()&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">arch_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">calloc&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">riscv_info_t&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">arch_info&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_info_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">arch_info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>../src/target/riscv/riscv.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/*** RISC-V Interface ***/&lt;/span>
&lt;span class="kt">void&lt;/span> &lt;span class="nf">riscv_info_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">riscv_info_t&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">memset&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">dtm_version&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">registers_initialized&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">current_hartid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">coreid&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">version_specific&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">memset&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">trigger_unique_id&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mh">0xff&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="k">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">trigger_unique_id&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">xlen&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_methods&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RISCV_MEM_ACCESS_PROGBUF&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_methods&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RISCV_MEM_ACCESS_SYSBUS&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_methods&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">RISCV_MEM_ACCESS_ABSTRACT&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_progbuf_warn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_sysbus_warn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">mem_access_abstract_warn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">true&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">INIT_LIST_HEAD&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">expose_csr&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">INIT_LIST_HEAD&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">r&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">expose_custom&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="initコマンド">initコマンド&lt;/h2>
&lt;p>ターゲットの作成が終わったら、サーバーを建てる。
そのあと、&lt;code>init&lt;/code>コマンドを実行する。&lt;/p>
&lt;p>&lt;code>src/openocd.c:openocd_thread&lt;/code>抜粋&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c"> &lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">server_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">init_at_startup&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ret&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">cmd_ctx&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ret&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">server_quit&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/openocd.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">command_registration&lt;/span> &lt;span class="n">openocd_command_handlers&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;version&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">jim_handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jim_version_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;show program version&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;noinit&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">handle_noinit_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Prevent &amp;#39;init&amp;#39; from being called at startup.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;init&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">handle_init_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Initializes configured targets and servers. &amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;Changes command mode from CONFIG to EXEC. &amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;Unless &amp;#39;noinit&amp;#39; is called, this command is &amp;#34;&lt;/span>
&lt;span class="s">&amp;#34;called automatically at the end of startup.&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;add_script_search_dir&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">handle_add_script_search_dir_command&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;dir to search for config files and scripts&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;&amp;lt;directory&amp;gt;&amp;#34;&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;span class="n">COMMAND_REGISTRATION_DONE&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>init&lt;/code>コマンドは&lt;code>handle_init_command&lt;/code>が対処する。&lt;/p>
&lt;p>&lt;code>src/openocd.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/* OpenOCD can&amp;#39;t really handle failure of this command. Patches welcome! :-) */&lt;/span>
&lt;span class="n">COMMAND_HANDLER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle_init_command&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">CMD_ARGC&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_COMMAND_SYNTAX_ERROR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">static&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">initialized&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">initialized&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">initialized&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;target init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">adapter_init&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* we must be able to set up the debug adapter */&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Debug Adapter init complete&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* &amp;#34;transport init&amp;#34; verifies the expected devices are present;
&lt;/span>&lt;span class="cm"> * for JTAG, it checks the list of configured TAPs against
&lt;/span>&lt;span class="cm"> * what&amp;#39;s discoverable, possibly with help from the platform&amp;#39;s
&lt;/span>&lt;span class="cm"> * JTAG event handlers. (which require COMMAND_EXEC)
&lt;/span>&lt;span class="cm"> */&lt;/span>
&lt;span class="n">command_context_mode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">COMMAND_EXEC&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;transport init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;dap init&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ERROR_OK&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Examining targets...&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">target_examine&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;target examination failed&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">command_context_mode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">COMMAND_CONFIG&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;flash init&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;nand init&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">command_run_line&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;pld init&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_FAIL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">command_context_mode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">COMMAND_EXEC&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* initialize telnet subsystem */&lt;/span>
&lt;span class="n">gdb_target_add_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">all_targets&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">target_register_event_callback&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">log_target_callback_event_handler&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>ここでは、以下の順でコマンドと関数を実行する。&lt;/p>
&lt;ol start="0">
&lt;li>&lt;code>init&lt;/code>&lt;/li>
&lt;li>&lt;code>adapter_init();&lt;/code>&lt;/li>
&lt;li>&lt;code>transport init&lt;/code>&lt;/li>
&lt;li>&lt;code>dap init&lt;/code>&lt;/li>
&lt;li>&lt;code>target_examine();&lt;/code>&lt;/li>
&lt;li>&lt;code>flash init&lt;/code>&lt;/li>
&lt;li>&lt;code>nand init&lt;/code>&lt;/li>
&lt;li>&lt;code>pld init&lt;/code>&lt;/li>
&lt;/ol>
&lt;p>&lt;code>init&lt;/code>では、&lt;code>riscv&lt;/code>固有の初期化をする。
&lt;code>adapter_init()&lt;/code>, &lt;code>transport init&lt;/code>, &lt;code>dap init&lt;/code>でJTAGの初期化をしている？
&lt;code>target_examine&lt;/code>では、&lt;code>RISC-V Debug DM&lt;/code>が存在し、正しいステータスを返すかテストしているっぽい。
次は、これらを詳しくみていく。
なお、&lt;code>flash init&lt;/code>、&lt;code>nand init&lt;/code>、&lt;code>pld init&lt;/code>は見なくて良さそうなのでとりあえず放置する。&lt;/p></description></item><item><title>My RISC-V debug feature part4</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part4/</link><pubDate>Sun, 09 May 2021 23:05:20 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part4/</guid><description>&lt;p>これから、DM(Debug Module)の実装をおこない、VJTAGを通して、OpenOCDと情報をやりとりできるかを確認していく。
まずは、かんたんな実装から始める。
参照しているspecのバージョンは&lt;code>v0.13&lt;/code>である。&lt;/p>
&lt;h2 id="機能">機能&lt;/h2>
&lt;ul>
&lt;li>対象のHartsの選択&lt;/li>
&lt;li>Halt/Resume&lt;/li>
&lt;li>Abstracts commands&lt;/li>
&lt;li>Program buffer&lt;/li>
&lt;li>ステップ実行&lt;/li>
&lt;li>トリガー&lt;/li>
&lt;li>リセット
などが挙げられる。
なお、Debuggerが介入してきた場合は、hartはD-Mode(Debug Mode)で動作を行う。
D-Modeでは、基本的にはM-Modeと同じだが、割り込みが無効になり、例外はデバッガが対処を行う。また、デバッカーから命令が供給されるまで、haltする。&lt;/li>
&lt;/ul>
&lt;h2 id="全体像">全体像&lt;/h2>
&lt;p>&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>
実線で囲まれている部分は実装が必須であり、点線で囲まれている部分は実装するかは任意である。
今回は、実線の部分のみ実装する。
なお、DTMに関してはほとんど前回までで実装が完了している。
また、VJTAGおよびDTM、DMはTCK(VJTAGのクロックドメイン)で動作している。
そこで、hart &amp;lt;-&amp;gt; DM間にクロックドメインクロッシングの機構を用意する。
念の為記しておくが、System busへのアクセスは実装しないが、System busは&lt;code>m_clock&lt;/code>ドメインで動作している。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image01.png"
target="_blank">&lt;img class="img" src="./image01.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;h3 id="csrs">CSRs&lt;/h3>
&lt;ul>
&lt;li>dcsr&lt;/li>
&lt;li>dpc&lt;/li>
&lt;li>dscratch(0..N)&lt;/li>
&lt;/ul>
&lt;p>うち、&lt;code>dpc&lt;/code>, &lt;code>dscratch&lt;/code>はXLEN bitであり、&lt;code>dcsr&lt;/code>は最長&lt;code>2**3&lt;/code>ビットである。&lt;/p>
&lt;h2 id="今回実装する機能">今回実装する機能&lt;/h2>
&lt;h3 id="ver1">Ver1&lt;/h3>
&lt;ul>
&lt;li>hartの選択&lt;/li>
&lt;li>(halt中の)GPRsに対するアクセス&lt;/li>
&lt;li>hartのリセット(resetvectorからの再実行)&lt;/li>
&lt;li>いくつかのAbstarct Commands&lt;/li>
&lt;li>halt/resume&lt;/li>
&lt;/ul>
&lt;h3 id="ver2">ver2&lt;/h3>
&lt;ul>
&lt;li>ステップ実行&lt;/li>
&lt;li>Triggers&lt;/li>
&lt;li>Program Buffer&lt;/li>
&lt;/ul>
&lt;p>とりあえず、ver1を実装する。
Spikeや他のRTLによる実装を参考に実装していく。
次回からは、hartの選択、halt、GPRsへのアクセスを実装する。
内容が薄いが今回はここまで。&lt;/p>
&lt;h2 id="付録-spikeのビルド">付録 Spikeのビルド&lt;/h2>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-bash" data-lang="bash">git clone --recursive https://github.com/riscv/riscv-isa-sim
&lt;span class="nb">cd&lt;/span> riscv-isa-sim
mkdir build
&lt;span class="nb">cd&lt;/span> build
../configure --prefix&lt;span class="o">=&lt;/span>&lt;span class="nv">$RISCV&lt;/span> --enable-commitlog --enable-histogram
make -j &lt;span class="k">$(&lt;/span>nproc&lt;span class="k">)&lt;/span>
make install
&lt;/code>&lt;/pre>&lt;/div>&lt;p>これで、デバックモードの機能を扱うことができる。&lt;/p>
&lt;h2 id="参考">参考&lt;/h2>
&lt;ul>
&lt;li>ドキュメント・スペック
&lt;ul>
&lt;li>&lt;a href="https://sifive.cdn.prismic.io/sifive/fab000f6-0e07-48d0-9602-e437d5367806_sifive_U54MC_rtl_full_20G1.03.00_manual.pdf"target="_blank" rel="noopener noreferrer">SiFive E31/E51 Coreplex&lt;/a>
&lt;/li>
&lt;li>&lt;a href="https://riscv.org/wp-content/uploads/2017/05/Wed1445_Debug_WorkingGroup_Wachs.pdf"target="_blank" rel="noopener noreferrer">RISC-V Debug Spec Update&lt;/a>
&lt;/li>
&lt;li>&lt;a href="https://www.lauterbach.com/pdfnew/debugger_riscv.pdf"target="_blank" rel="noopener noreferrer">https://www.lauterbach.com/pdfnew/debugger_riscv.pdf&lt;/a>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>実装
&lt;ul>
&lt;li>&lt;a href="https://github.com/riscv/riscv-isa-sim"target="_blank" rel="noopener noreferrer">Spike&lt;/a>
&lt;/li>
&lt;li>&lt;a href="https://github.com/aquaxis/riscv_debug"target="_blank" rel="noopener noreferrer">https://github.com/aquaxis/riscv_debug&lt;/a>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>My RISC-V debug feature part3</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part3/</link><pubDate>Tue, 20 Apr 2021 22:55:05 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part3/</guid><description>&lt;p>OpenOCD RISC-VにVJTAGのサポートを行う。
OpenOCDにて、VJTAG on DE10-Liteにアクセスしてみる。&lt;/p>
&lt;h3 id="openocdのvjtagサポート状況">OpenOCDのVJTAGサポート状況&lt;/h3>
&lt;p>or1kはVJTAGに対応している。
この実装を理解して、OpenOCD RISC-Vへ移植をする。&lt;/p>
&lt;h3 id="openocd-vjtag-support-or1kの実装を読解する">OpenOCD VJTAG support (or1kの実装を読解する)&lt;/h3>
&lt;p>まず、or1kでどのようにVJTAGを使っているのか確かめる。
そのために、cfgファイルを読む。&lt;/p>
&lt;p>&lt;code>tcl/target/or1k.cfg&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-tcl" data-lang="tcl">&lt;span class="k">set&lt;/span> _ENDIAN big
&lt;span class="k">if&lt;/span> &lt;span class="k">{&lt;/span> &lt;span class="k">[&lt;/span>&lt;span class="nb">info&lt;/span> exists CHIPNAME&lt;span class="k">]&lt;/span> &lt;span class="k">}&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="k">set&lt;/span> _CHIPNAME &lt;span class="nv">$CHIPNAME&lt;/span>
&lt;span class="k">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="k">set&lt;/span> _CHIPNAME or1k
&lt;span class="k">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="k">{&lt;/span> &lt;span class="k">[&lt;/span>&lt;span class="nb">info&lt;/span> exists TAP_TYPE&lt;span class="k">]&lt;/span> &lt;span class="k">}&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="k">set&lt;/span> _TAP_TYPE &lt;span class="nv">$TAP_TYPE&lt;/span>
&lt;span class="k">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="nb">puts&lt;/span> &lt;span class="s2">&amp;#34;You need to select a tap type&amp;#34;&lt;/span>
&lt;span class="nv">shutdown&lt;/span>
&lt;span class="k">}&lt;/span>
&lt;span class="c"># Configure the target
&lt;/span>&lt;span class="c">&lt;/span>&lt;span class="k">if&lt;/span> &lt;span class="k">{&lt;/span> &lt;span class="k">[&lt;/span>&lt;span class="nb">string&lt;/span> compare &lt;span class="nv">$_TAP_TYPE&lt;/span> &lt;span class="s2">&amp;#34;VJTAG&amp;#34;&lt;/span>&lt;span class="k">]&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nv">0&lt;/span> &lt;span class="k">}&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="k">{&lt;/span> &lt;span class="k">[&lt;/span>&lt;span class="nb">info&lt;/span> exists FPGATAPID&lt;span class="k">]&lt;/span> &lt;span class="k">}&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="k">set&lt;/span> _FPGATAPID &lt;span class="nv">$FPGATAPID&lt;/span>
&lt;span class="k">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="k">{&lt;/span>
&lt;span class="nb">puts&lt;/span> &lt;span class="s2">&amp;#34;You need to set your FPGA JTAG ID&amp;#34;&lt;/span>
&lt;span class="nv">shutdown&lt;/span>
&lt;span class="k">}&lt;/span>
&lt;span class="nv">jtag&lt;/span> newtap &lt;span class="nv">$_CHIPNAME&lt;/span> cpu &lt;span class="o">-&lt;/span>irlen &lt;span class="mi">10&lt;/span> &lt;span class="o">-&lt;/span>expected-id &lt;span class="nv">$_FPGATAPID&lt;/span>
&lt;span class="k">set&lt;/span> _TARGETNAME &lt;span class="nv">$_CHIPNAME.cpu&lt;/span>
&lt;span class="nv">target&lt;/span> create &lt;span class="nv">$_TARGETNAME&lt;/span> or1k &lt;span class="o">-&lt;/span>endian &lt;span class="nv">$_ENDIAN&lt;/span> &lt;span class="o">-&lt;/span>chain-position &lt;span class="nv">$_TARGETNAME&lt;/span>
&lt;span class="c"># Select the TAP core we are using
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nv">tap_select&lt;/span> vjtag
&lt;span class="k">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>tap_select vjtag&lt;/code>にてVJTAGをTAPとして選択するようである。
&lt;code>tap_select&lt;/code>コマンドはor1k向けに定義されたものであるため、&lt;code>target&lt;/code>コマンドでor1kを選択してから
でないと使用することができない。&lt;/p>
&lt;p>&lt;code>tap_select&lt;/code>命令をまず、RISC-V向けに移植したい。&lt;/p>
&lt;h3 id="tap_select命令の移植">tap_select命令の移植&lt;/h3>
&lt;p>&lt;code>src/target/openrisc/or1k.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="k">static&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">command_registration&lt;/span> &lt;span class="n">or1k_hw_ip_command_handlers&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;tap_select&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">handler&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">or1k_tap_select_command_handler&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">mode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">COMMAND_ANY&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">usage&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;name&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">help&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Select the TAP core to use&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="p">},&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/openrisc/or1k.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="n">COMMAND_HANDLER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">or1k_tap_select_command_handler&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">target&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_current_target&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_CTX&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">or1k_common&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">or1k&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">target_to_or1k&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">target&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">or1k_jtag&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">jtag&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">or1k&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">jtag&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">or1k_tap_ip&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">or1k_tap&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">CMD_ARGC&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_COMMAND_SYNTAX_ERROR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">list_for_each_entry&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">or1k_tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">tap_list&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">list&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">or1k_tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="n">strcmp&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">CMD_ARGV&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">],&lt;/span> &lt;span class="n">or1k_tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">jtag&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap_ip&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">or1k_tap&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">LOG_INFO&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;%s tap selected&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">or1k_tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;%s unknown, no tap selected&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">CMD_ARGV&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">]);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">ERROR_COMMAND_SYNTAX_ERROR&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>tap_select&lt;/code>コマンドは、&lt;code>or1k_tap_select_command_handler&lt;/code>が対処する。
&lt;code>tap_select&lt;/code>コマンドの第一引数にあるインターフェースを使用する。
VJTAGを選択した場合を見てみる。&lt;/p>
&lt;p>&lt;code>src/target/openrisc/or1k_tap_vjtag.c&lt;/code>で実装されている。
&lt;code>or1k_tap_vjtag_init&lt;/code>が初期化用の処理である。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="n">jtag_add_tlr&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>まずは、TAPを初期状態にする。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="n">uint8_t&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">};&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">scan_field&lt;/span> &lt;span class="n">field&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">jtag_tap&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">tap&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jtag_info&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Select VIR */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>その後、sld_hubのIRを&lt;code>USER1&lt;/code>にする。
この操作で、Select_IRを行い、Shift_IRにて、sld_hubのIRに&lt;code>USER1&lt;/code>のコード(0xE, 10 bit)を書き込む。&lt;/p>
&lt;p>次に、DR Shiftを行う。
&lt;code>USER1&lt;/code>レジスタのフォーマットは以下のようになっている。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>
ただし、nはCEIL(log2(Number of SLD_nodes + 1))である。
mは各VIRの長さの最大値である。
&lt;code>sld_hub&lt;/code>には以下のレジスタがある。&lt;/p>
&lt;ul>
&lt;li>&lt;code>SLD HUB IP Configuration Register&lt;/code>
&lt;ul>
&lt;li>sld_hubに接続されているsld_nodeの情報や、USER1 DRの寸法がわかる。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>各&lt;code>sld_hub&lt;/code>の&lt;code>SLD_NODE_INFO&lt;/code>レジスタ
&lt;ul>
&lt;li>indexとアドレスのマッピングがわかる
&lt;code>HUB_INFO&lt;/code>命令を使用し、&lt;code>HUB IP Configuration Register&lt;/code>を読み出す。
また、各sld_nodeのアドレスマッピングを保持している、&lt;code>SLD_NODE_INFO&lt;/code>レジスタがある。
ただし、この時点でsld_hubに接続されたsld_nodeの数がわからない。
また、n, mについてもわからない状態である。
そこで、USER1 DRをゼロで埋める。
nがわからないが、64回シフトすれば大体の場合は十分である。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="cm">/* Select the SLD Hub */&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">64&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>次に、Select_DRにて、DR(&lt;code>SLD HUB Configuration register&lt;/code>)を選択する。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="cm">/* Select VDR */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>jtag_execute_queue&lt;/code>にて、JTAGコマンドを実行する。&lt;/p>
&lt;p>次に、&lt;code>SLD HUB Configuration register&lt;/code>を読み出す。
レジスタのフォーマットは以下のとおりである。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image01.png"
target="_blank">&lt;img class="img" src="./image01.png"/>&lt;/a>&lt;/span>
&lt;/span>
8つのnibbleのフィールドからなるレジスタであり、nibble単位での読み出しが必須となる。:w
次のnibbleを読み出す前に、UPDATE_DRをする必要がある。
そこで、読み出しごとに&lt;code>jtag_execute_queue&lt;/code>を行う。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="n">uint8_t&lt;/span> &lt;span class="n">nibble&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">hub_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">nibble&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">hub_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">hub_info&lt;/span> &lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">nibble&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="mh">0xf&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="mi">28&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">nb_nodes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">NB_NODES&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hub_info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">m_width&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">M_WIDTH&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hub_info&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;SLD HUB Configuration register&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;------------------------------&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;m_width = %d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;manufacturer_id = 0x%02&amp;#34;&lt;/span> &lt;span class="n">PRIx32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">MANUF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hub_info&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;nb_of_node = %d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">nb_nodes&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;version = %&amp;#34;&lt;/span> &lt;span class="n">PRIu32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">VER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">hub_info&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;VIR length = %d&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">guess_addr_width&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">nb_nodes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>これで、sld_nodeの数、m, nのサイズ、VIRのサイズなどがわかった。&lt;/p>
&lt;p>次に、インデックス(VJTAGのインスタンス時にユーザもしくはQuartusが割当)からアドレスへのマッピングを調べる。
&lt;code>SLD_NODE info Register&lt;/code>に情報が格納されており、sld_nodeの数分存在する。
このレジスタも同様に8つのnibbleからなる。
つまり、&lt;code>ノードの数 * (8 * nibble)&lt;/code>回シフトが必要である。&lt;/p>
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image02.png"
target="_blank">&lt;img class="img" src="./image02.png"/>&lt;/a>&lt;/span>
&lt;/span>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="kt">int&lt;/span> &lt;span class="n">vjtag_node_address&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">node_index&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">uint32_t&lt;/span> &lt;span class="n">node_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">node_index&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">node_index&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="n">nb_nodes&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">node_index&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="n">i&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">nibble&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">retval&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">retval&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">ERROR_OK&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">retval&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">node_info&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">node_info&lt;/span> &lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">nibble&lt;/span> &lt;span class="o">&amp;amp;&lt;/span> &lt;span class="mh">0xf&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="mi">28&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Node info register&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;--------------------&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;instance_id = %&amp;#34;&lt;/span> &lt;span class="n">PRIu32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ID&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;manufacturer_id = 0x%02&amp;#34;&lt;/span> &lt;span class="n">PRIx32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">MANUF&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;node_id = %&amp;#34;&lt;/span> &lt;span class="n">PRIu32&lt;/span> &lt;span class="s">&amp;#34; (%s)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ID&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="n">id_to_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ID&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">)));&lt;/span>
&lt;span class="n">LOG_DEBUG&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;version = %&amp;#34;&lt;/span> &lt;span class="n">PRIu32&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">VER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">));&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ID&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">node_info&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">VJTAG_NODE_ID&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">vjtag_node_address&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">node_index&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">vjtag_node_address&lt;/span> &lt;span class="o">&amp;lt;&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">LOG_ERROR&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;No VJTAG TAP instance found !&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>これでアドレスがわかった。
次に、sld_nodeのインスタンスのVIR, VDRにアクセスをする。&lt;/p>
&lt;p>まず、&lt;code>USER1&lt;/code>命令を発行する。
これにより、IR chainが選択される。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C"> &lt;span class="cm">/* Select VIR */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>次に、sld_nodeのVIRに命令を送る。
この場合はDEBUG命令を転送している。
これは、or1kのデバックモードの命令の様子。
なお、転送サイズは&lt;code>アドレスのサイズ+VIRのサイズ&lt;/code>である。
VIRの前に、Addressを付与する。
フォーマットを以下に示す。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image03.png"
target="_blank">&lt;img class="img" src="./image03.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cm">/* Send the DEBUG command to the VJTAG IR */&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">dr_length&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">guess_addr_width&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">nb_nodes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dr_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">vjtag_node_address&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">ALT_VJTAG_CMD_DEBUG&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dr_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>最後に、&lt;code>USER0&lt;/code>命令を発行して、DR chainに切り替える。
これにより、後続のShift_DEは、&lt;code>USER1&lt;/code>命令でセットした、Addrを用いてsld_nodeのインスタンスに転送される。
なお、or1kの場合では、VIRをDEBUGから変えることはないようである。
しかし、VIRを変える場合は、&lt;code>USER1&lt;/code>を発行して、ADDR+VIRを転送し、&lt;code>USER0&lt;/code>へ切り替えるという手順が必要となる。
この切り替え部分をRISC-VのOpenOCDへ追加する必要がある。
DRのアクセスは切り替えが正しくできていれば、問題ないはずである。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cm">/* Select the VJTAG DR */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="nf">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="openocd-vjtag-support">OpenOCD VJTAG support&lt;/h3>
&lt;p>詳しい追加は&lt;a href="https://github.com/koyamanX/riscv-openocd"target="_blank" rel="noopener noreferrer">koyamanX/riscv-openocd&lt;/a>
にある、
&lt;code>src/target/riscv/riscv_tap_vjtag.c&lt;/code>を確認してほしい。
初期化用のコードは、&lt;code>or1k_tap_vjtag_init&lt;/code>をそのまま流用する。
関数名を&lt;code>riscv_tap_vjtag_init&lt;/code>とする。
また、DEBUGレジスタの指定を、DTMCSレジスタの指定に変更する。
これで初期化は十分である。
一部、変数(nb_nodesなど)を雑にグローバル変数にした。
また、VIRの書き込み用の関数を別に定義した。&lt;/p>
&lt;p>&lt;code>src/target/riscv/riscv_tap_vjtag.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="kt">int&lt;/span> &lt;span class="nf">vjtag_vir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="n">jtag_tap&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">uint32_t&lt;/span> &lt;span class="n">vir_val&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="n">uint8_t&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="p">};&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">scan_field&lt;/span> &lt;span class="n">field&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* Select VIR chain */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* Set VIR Value to the VIR of sld_node determined by vjtag_node_address */&lt;/span>
&lt;span class="kt">int&lt;/span> &lt;span class="n">dr_length&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">guess_addr_width&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">nb_nodes&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dr_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">vjtag_node_address&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">m_width&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">|&lt;/span> &lt;span class="n">vir_val&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dr_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_dr_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/* Select the VJTAG DR chain */&lt;/span>
&lt;span class="n">buf_set_u32&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">t&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ALTERA_CYCLONE_CMD_USER0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">num_bits&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">tap&lt;/span>&lt;span class="o">-&amp;gt;&lt;/span>&lt;span class="n">ir_length&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">out_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">t&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">field&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">in_value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">jtag_add_ir_scan&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tap&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">field&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TAP_IDLE&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="n">jtag_execute_queue&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/target/riscv/riscv.c&lt;/code>を変更し、targetの初期化の際に、ついでに&lt;code>riscv_tap_vjtag_init&lt;/code>を呼び出すことにした。
また、&lt;code>use_vjtag&lt;/code>フラグで、VJTAGを使用するかをハードコードした。
本来は、このフラグを&lt;code>tap_select&lt;/code>のような命令で変更できるようにするべきである。
しかし、&lt;code>target&lt;/code>固有のコマンドは&lt;code>target&lt;/code>の初期化が終わっていこうに使えるようになる。
ただし、&lt;code>target&lt;/code>初期化の処理は、&lt;code>examine&lt;/code>(JTAGでDebug Moduleへアクセスし、dmactiveを取得する)が成功したら
正しく完了したこととなる。
VJTAGを用いたアクセスでないため、必ず失敗する。
そこで、とりあえず、動けばいいという適当な考えで、ハードコードしてしまった。
正しく動くことが確認できたら、しっかりと対応しテストしてPRを出したいね。&lt;/p>
&lt;h3 id="通信テスト">通信テスト&lt;/h3>
&lt;p>VJTAGとOpenOCDでやり取りをする。
適当なDebug Moduleのような回路を書く。
コードは&lt;a href="https://github.com/koyamanX/riscv-debug"target="_blank" rel="noopener noreferrer">koyamanX/riscv-openocd&lt;/a>
にある。
なお、DM(Debug Module)やDTM(Debug Transport Module)はJTAGのTCKのクロックドメインで動作していることに注意。
プロセッサと接続するためには、適切にCDC(Clock Domain Crossing)を行う必要がある。
また、DMに関しては、まだスタブである。&lt;/p>
&lt;p>&lt;code>src/dtm.nsl&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cp">#ifndef DTM_H
&lt;/span>&lt;span class="cp">#define DTM_H
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="cm">/* This module design to run in TCK in JTAG clock domain */&lt;/span>
&lt;span class="cm">/* m_clock must be connected to TCK of JTAG */&lt;/span>
&lt;span class="cp">#define IDCODE 5&amp;#39;b00001
&lt;/span>&lt;span class="cp">#define DTMCS 5&amp;#39;b10000
&lt;/span>&lt;span class="cp">#define DMI 5&amp;#39;b10001
&lt;/span>&lt;span class="cp">#define BYPASS 5&amp;#39;b11111
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="cp">#define DTMCS_VERSION 4&amp;#39;b0001
&lt;/span>&lt;span class="cp">#define DTMCS_ABITS 6&amp;#39;b100000
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="cp">#define DMI_NOP 2&amp;#39;b00
&lt;/span>&lt;span class="cp">#define DMI_READ 2&amp;#39;b01
&lt;/span>&lt;span class="cp">#define DMI_WRITE 2&amp;#39;b10
&lt;/span>&lt;span class="cp">#define DMI_RESERVED 2&amp;#39;b11
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="cp">#define DMI_STAT_SUCCESS 2&amp;#39;b00
&lt;/span>&lt;span class="cp">#define DMI_STAT_RESERVED 2&amp;#39;b01
&lt;/span>&lt;span class="cp">#define DMI_STAT_FAILURE 2&amp;#39;b10
&lt;/span>&lt;span class="cp">#define DMI_STAT_INPROGRESS 2&amp;#39;b11
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">dtmcs_t&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">zero1&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">14&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">dmihardreset&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">dmireset&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">zero0&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">idle&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">dmistat&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">abits&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">6&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">version&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;span class="k">struct&lt;/span> &lt;span class="n">dmi_t&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">addr&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">op&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="p">};&lt;/span>
&lt;span class="n">declare&lt;/span> &lt;span class="n">dtm&lt;/span> &lt;span class="n">interface&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">m_clock&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">p_reset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">ir_in&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">ir_out&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">tdi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">tdo&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_cdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_sdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_e1dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_pdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_e2dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_udr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_cir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="n">virtual_state_uir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* DMI */&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">addr&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">rdata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">wdata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="nf">read&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="nf">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">wdata&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="nf">ready&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="cp">#ifdef DEBUG
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">output&lt;/span> &lt;span class="n">debug_out&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/dtm.nsl&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;dtm.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="n">module&lt;/span> &lt;span class="n">dtm&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">ir&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IDCODE&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* IDECODE (defined by spec) */&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">idcode&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mh">0x10e31913&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="cm">/* same as SiFive&amp;#39;s */&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">bypass&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* DTMCS register */&lt;/span>
&lt;span class="n">dtmcs_t&lt;/span> &lt;span class="n">reg&lt;/span> &lt;span class="n">dtmcs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">14&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b00000000000000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b00&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTMCS_ABITS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTMCS_VERSION&lt;/span>&lt;span class="p">};&lt;/span>
&lt;span class="cm">/* DTMCS internal register for read via dtmcs(Capture-DR) */&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dtmcs_dmistat&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dtmcs_idle&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dtmcs_dmireset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dtmcs_dmihardreset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* DMI register */&lt;/span>
&lt;span class="n">dmi_t&lt;/span> &lt;span class="n">reg&lt;/span> &lt;span class="n">dmi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* DMI internal register for read via dmi(Capture-DR) */&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dmi_op_stat&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dmi_addr&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dmi_data&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">virtual_state_uir&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">ir&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">ir_in&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">virtual_state_cir&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ir_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IDCODE&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">virtual_state_udr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* At this point, we can issue abstarct command */&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DTMCS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="cm">/* TODO: Implement hardreset */&lt;/span>
&lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">dmihardreset&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">dtmcs_dmireset&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="k">if&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dtmcs&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">dmireset&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">dtmcs_dmireset&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="nl">dmi_op_stat&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI_NOP&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nl">dmi_op_stat&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">DMI_STAT_SUCCESS&lt;/span>&lt;span class="p">;}&lt;/span>
&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI_READ&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">dmi_addr&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">read&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI_WRITE&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">dmi_addr&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="nl">dmi_data&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">dmi&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">op&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI_RESERVED&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="nl">dmi_op_stat&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">DMI_STAT_FAILURE&lt;/span>&lt;span class="p">;}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">ready&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="nl">dmi_data&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">rdata&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="nl">dmi_op_stat&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">DMI_STAT_SUCCESS&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">virtual_state_cdr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DTMCS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">dtmcs&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">14&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">dtmcs_dmihardreset&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtmcs_dmireset&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="n">dtmcs_idle&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtmcs_dmistat&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTMCS_ABITS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">DTMCS_VERSION&lt;/span>&lt;span class="p">};&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">dmi&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">dmi_addr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dmi_data&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dmi_op_stat&lt;/span>&lt;span class="p">};&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">IDCODE&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">idcode&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mh">0x10e31913&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">BYPASS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">bypass&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nl">bypass&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="n">b0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">virtual_state_sdr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DTMCS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">dtmcs&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">tdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dtmcs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">31&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]};&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">dmi&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">tdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">65&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]};&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">IDCODE&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">idcode&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="n">tdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">idcode&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">31&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">]};&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">BYPASS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nl">bypass&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">tdi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nl">bypass&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">tdi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DTMCS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dtmcs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">DMI&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dmi&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">BYPASS&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">bypass&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">ir&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="nl">IDCODE&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">idcode&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">bypass&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cp">#ifdef DEBUG
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">debug_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dtmcs&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/dm.h&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cp">#ifndef DM_H
&lt;/span>&lt;span class="cp">#define DM_H
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="cm">/* Runs in same clock domain as DTM and output to hart must be
&lt;/span>&lt;span class="cm"> synchronized to hart&amp;#39;s clock domain */&lt;/span>
&lt;span class="n">declare&lt;/span> &lt;span class="n">dm&lt;/span> &lt;span class="n">interface&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">p_reset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">m_clock&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cm">/* DMI */&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">addr&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">wdata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">rdata&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="nf">read&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">func_in&lt;/span> &lt;span class="nf">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">wdata&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="nf">ready&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="cp">#ifdef DEBUG
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">output&lt;/span> &lt;span class="n">debug_out&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>src/dm.nsl&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;dm.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="n">module&lt;/span> &lt;span class="n">dm&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">reg&lt;/span> &lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">32&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">write&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">addr&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mh">0x10&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="nl">dmcontrol&lt;/span> &lt;span class="p">:&lt;/span>&lt;span class="o">=&lt;/span> &lt;span class="n">wdata&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">ready&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">read&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">addr&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mh">0x10&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="n">rdata&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">ready&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cp">#ifdef DEBUG
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">debug_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">dmcontrol&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-C" data-lang="C">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;vjtag.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;dtm.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;dm.h&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="n">declare&lt;/span> &lt;span class="n">DE10&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">SW&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">LEDR&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">module&lt;/span> &lt;span class="n">DE10&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">vjtag&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">dtm&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">dm&lt;/span> &lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">m_clock&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tck&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">p_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p_reset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ir_in&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ir_in&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ir_out&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ir_out&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tdi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tdi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tdo&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tdo&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">m_clock&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">tck&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">p_reset&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">p_reset&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cdr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cdr&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_sdr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_sdr&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_udr&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_udr&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cir&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cir&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">vjtag0&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_uir&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_uir&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">read&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">read&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">write&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">write&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">addr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">wdata&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="n">func&lt;/span> &lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ready&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">rdata&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">rdata&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">ready&lt;/span>&lt;span class="p">();&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cp">#ifdef DEBUG
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">any&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">SW&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="n">LEDR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_dtm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">debug_out&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">SW&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="n">LEDR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">riscv_dm&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">debug_out&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="k">else&lt;/span>&lt;span class="o">:&lt;/span> &lt;span class="n">LEDR&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mh">0xffffffff&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="動作確認">動作確認&lt;/h3>
&lt;p>&lt;a href="https://github.com/koyamanX/riscv-debug"target="_blank" rel="noopener noreferrer">koyamanX/riscv-openocd&lt;/a>
&lt;/p>
&lt;h4 id="ツールのビルド">ツールのビルド&lt;/h4>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-bash" data-lang="bash">sudo apt install libftdi1-dev
git clone --recursive https://github.com/koyamanX/riscv-debug &lt;span class="c1">#riscv-vjtag branch(by default)&lt;/span>
&lt;span class="nb">cd&lt;/span> riscv-debug/riscv-openocd
git submodule update --init --recursive
./bootstrap
mkdir build
&lt;span class="nb">cd&lt;/span> build
../configure --prefix&lt;span class="o">=&lt;/span>/opt/riscv-openocd
make -j &lt;span class="k">$(&lt;/span>nproc&lt;span class="k">)&lt;/span>
sudo make install
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>rv32xsoc.cfg&lt;/code>&lt;/p>
&lt;pre>&lt;code>set _ENDIAN little
set _CHIPNAME riscv
set _FPGATAPID 0x031050dd
set _TARGETNAME $_CHIPNAME.cpu
adapter driver usb_blaster
usb_blaster_lowlevel_driver ftdi
jtag newtap $_CHIPNAME cpu -irlen 10 -expected-id $_FPGATAPID
target create $_TARGETNAME riscv -endian $_ENDIAN -chain-position $_TARGETNAME
#use_vjtag
&lt;/code>&lt;/pre>&lt;h4 id="fpgade10-liteへ実装">FPGA(DE10-Lite)へ実装&lt;/h4>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="nb">cd&lt;/span> riscv-debug/fpga
make all
make download
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="テスト">テスト&lt;/h4>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-bash" data-lang="bash">sudo /opt/riscv-openocd/bin/openocd -f ../tcl/target/rv32xsoc.cfg
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="実行結果">実行結果&lt;/h4>
&lt;p>dmactiveに成功している。(dmcontrolの0ビット目)
dmstatusのリードに失敗しているが、実装していないので期待通り。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image04.png"
target="_blank">&lt;img class="img" src="./image04.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;p>次からは、DMの仕様読みと実装を行う。&lt;/p></description></item><item><title>My RISC-V debug feature part2</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part2/</link><pubDate>Sat, 17 Apr 2021 11:21:32 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part2/</guid><description>&lt;p>今回はIntel FPGAのVJTAGのIPを試してみる。
FPGAボードはDE10 Liteを使用する。&lt;/p>
&lt;h3 id="jtagjoint-test-action-group">JTAG(Joint Test Action Group)&lt;/h3>
&lt;p>JTAGについては以下のサイトがわかりやすい。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="http://www.tokudenkairo.co.jp/jtag/adv2018/01.php"target="_blank" rel="noopener noreferrer">12月1日 JTAGとは何か&lt;/a>
&lt;/li>
&lt;li>&lt;a href="http://www.tokudenkairo.co.jp/jtag/adv2018/02.php"target="_blank" rel="noopener noreferrer">12月2日 JTAGの信号線と波形&lt;/a>
&lt;/li>
&lt;li>&lt;a href="http://www.tokudenkairo.co.jp/jtag/adv2018/03.php"target="_blank" rel="noopener noreferrer">12月3日 データレジスタと命令レジスタ&lt;/a>
&lt;/li>
&lt;li>&lt;a href="http://www.tokudenkairo.co.jp/jtag/adv2018/04.php"target="_blank" rel="noopener noreferrer">12月4日 TAPステートマシン&lt;/a>
&lt;/li>
&lt;li>&lt;a href="http://www.tokudenkairo.co.jp/jtag/adv2018/05.php"target="_blank" rel="noopener noreferrer">12月5日 データレジスタの切り替えと、プライベート命令&lt;/a>
&lt;/li>
&lt;li>&lt;a href="https://www.cnblogs.com/shangdawei/p/4753682.html"target="_blank" rel="noopener noreferrer">JTAG – A technical overview and Timing&lt;/a>
&lt;/li>
&lt;/ul>
&lt;p>JTAGを用いると、ICの端子を操作したり、ICの内部と通信ができるようになる。
もともと、JTAGはICの端子を操作するバウンダリースキャンのために作られたようである。
IEEE1149.1は4本の信号線でIC内部と通信するための、プロトコルを定めた規格である。
今回は、バウンダリースキャンは行わない。プロセッサの内部の状態をriscv-debug-specに沿って操作することを目標とする。
なお、riscv-debug-specでは、Debug Transport(情報のやり取り)には規定はないが、JTAGの例が乗っている。
例に乗っ取り、今回は、JTAGを用いる。&lt;/p>
&lt;p>JTAGはIRレジスタとDRレジスタがある。
これらはシフトレジスタであり、Shift-IR, Shift-DRにてシフトする。
IRは主にDRの命令(アドレス)を保持する。
IRは最低2ビット必要である。&lt;/p>
&lt;h4 id="実装の必須な命令は以下である">実装の必須な命令は以下である。&lt;/h4>
&lt;ul>
&lt;li>BYPASS&lt;/li>
&lt;li>SAMPLE&lt;/li>
&lt;li>PRELOAD&lt;/li>
&lt;li>EXTEST&lt;/li>
&lt;/ul>
&lt;h4 id="オプションな命令">オプションな命令&lt;/h4>
&lt;ul>
&lt;li>IDCODE&lt;/li>
&lt;/ul>
&lt;h4 id="今回使用する命令">今回使用する命令&lt;/h4>
&lt;ul>
&lt;li>BYPASS&lt;/li>
&lt;li>IDCODE
なお、バウンダリースキャンはサポートしない。&lt;/li>
&lt;/ul>
&lt;p>なお、IRレジスタを読み出すときは、前回の値でなくステータスが帰る。
ステータスは下位２ビットが&lt;code>01&lt;/code>であること以外は実装定義である。
DRはIRによって選択する。
DRの長さは実装定義で、制御用のソフトウエアはシフト回数を適切に行う必要がある。
なお、仕様で規定されている必須のDRが存在する。&lt;/p>
&lt;ul>
&lt;li>IDCODE(IR: 任意)
&lt;ul>
&lt;li>JTAGのIDコードを保持する(32 bit)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>BYPASS(IR: すべてのビットが１)
&lt;ul>
&lt;li>1 bitのレジスタ&lt;/li>
&lt;li>実装していない命令などはこちらへ書き込むことが推奨されている&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="jtag信号線">JTAG信号線&lt;/h3>
&lt;ul>
&lt;li>TCK (Test Clock)
&lt;ul>
&lt;li>クロック信号&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>TMS (Test Mode Select)
&lt;ul>
&lt;li>次のステートを決める&lt;/li>
&lt;li>5回以上1を入力するとリセットすることができる&lt;/li>
&lt;li>TCKの立ち上がりエッジ&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>TDI (Test Data-In)
&lt;ul>
&lt;li>データ入力&lt;/li>
&lt;li>TCKの立ち上がりエッジ&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>TDO (Test Data-Out)
&lt;ul>
&lt;li>データ出力&lt;/li>
&lt;li>TCKの立ち下がりエッジ&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h3 id="state-machine-of-jtag-tap">State machine of JTAG TAP&lt;/h3>
&lt;p>JTAGの状態はTAP(Test Access Port)が管理する。
16のステートを持ち、現在の状態とTMSにより次のステートが決まる。
ステートマシン図を以下に示す。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image01.png"
target="_blank">&lt;img class="img" src="./image01.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;h4 id="select">Select&lt;/h4>
&lt;p>Select_IRの場合は、IRをオペレーション対象とする。
Select_DRの場合は、DR Chainを選択し、IRにて、各DRを選択する。&lt;/p>
&lt;h4 id="shift">Shift&lt;/h4>
&lt;p>Shift_DR, Shift_IRにてシフトレジスタをシフトする。
Shift_DRの場合は、IRの値に応じて、DRが選択され、シフトされる。
TDIはMSBへ、LSBはTDOへ接続される。
Shift_IRはIRをシフトする。
TDIはMSBへ、ステータス(IRの値ではないことに注意)のLSBはTDOへ接続される。&lt;/p>
&lt;h4 id="capture">Capture&lt;/h4>
&lt;p>Capture_DRでは、IRで選択する、DRにパラレルで値を代入する。
Capture_IRでは、IRへパラレルで値を代入する。
処理の結果やステート、初期値などをこのステートでDR/IRへ転送する。&lt;/p>
&lt;h4 id="update">Update&lt;/h4>
&lt;p>Updateでは、並列でDRもしくはIRの値を内部ロジックへコピーする。
なにか、処理をする場合はこのステートで実行する。(RISC-V DebugのDTMにおけるDMI Write・Readなど)&lt;/p>
&lt;p>重要なステートはUpdate, Capture, Shift、Selectである。
なお、アプリケーションはDRの長さや現在の値、ステートについてしっかり把握して制御する必要がある。
ステートに関して、どのステートからでも、TMSを５回以上1にしておくことで初期状態へ戻ることができる。&lt;/p>
&lt;h3 id="virtual-jtag">Virtual JTAG&lt;/h3>
&lt;p>今回はVJTAGのIPを使用する。
VJTAGを用いると、Download Cable(USB-Blaster)を用いて、FPGAとPC間のJTAG通信ができる。
VJTAGとJTAGの違いは、あまりなく、実際はJTAGと同じ制御をしている。
しかし、VJTAGのインスタンスは最大255個作成できるため、これらを識別する機能が必要である。
各インスタンスにはユニークなインデックス(アドレス)が割り当てられ(ユーザが指定可能、指定しない場合はQuartusが合成時に自動割当）
これを用いて、識別する。
FPGAのデザイン内で、通信のルーティングを行う仕組みとして、sld_hubがぞんざいする。
各VJTAGのインスタンスはsld_nodeとなり、sld_hubに接続される。
以下にブロック図を示す。
&lt;a href="https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_virtualjtag.pdf"target="_blank" rel="noopener noreferrer">ここより&lt;/a>
引用
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>
よって、アプリケーションはsld_hubを介して、ユーザロジックのVJTAGインスタンス(sld_node)へアクセスする。
なお、１つしかインスタンスが存在しない場合でも、sld_hubは生成される。
また、sld_node, sld_hubはLEs(Logic Element)を消費する。
JTAG TAPは物理ハードウェアとして実装されている。
以下に、sld_hubおよびsld_nodeの内部ブロック図を図示する。&lt;/p>
&lt;p>IPのドキュメントは以下のリンクより閲覧できる。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://www.intel.com/content/dam/www/programmable/us/en/pdfs/literature/ug/ug_virtualjtag.pdf"target="_blank" rel="noopener noreferrer">Virtual JTAG Intel® FPGA IP Core User Guide&lt;/a>
&lt;/li>
&lt;li>&lt;a href="https://www.intel.co.jp/content/www/jp/ja/programmable/documentation/bhc1411109490717.html"target="_blank" rel="noopener noreferrer">仮想JTAG（altera_virtual_jtag)IP コアのユーザーガイド&lt;/a>
&lt;/li>
&lt;/ul>
&lt;h4 id="virtual-jtagのインスタンスの作成">Virtual JTAGのインスタンスの作成&lt;/h4>
&lt;p>Quartus Megafunctionを使って、Virtual JTAGのインスタンスファイル？を作る。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-verilog" data-lang="verilog">&lt;span class="c1">// vjtag.v
&lt;/span>&lt;span class="c1">&lt;/span>
&lt;span class="c1">// Generated using ACDS version 20.1 711
&lt;/span>&lt;span class="c1">&lt;/span>
&lt;span class="no">`timescale&lt;/span> &lt;span class="mh">1&lt;/span> &lt;span class="n">ps&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mh">1&lt;/span> &lt;span class="n">ps&lt;/span>
&lt;span class="k">module&lt;/span> &lt;span class="n">vjtag&lt;/span> &lt;span class="p">(&lt;/span>
&lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">tdi&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// jtag.tdi
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">input&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">tdo&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .tdo
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mh">4&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mh">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">ir_in&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .ir_in
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">input&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mh">4&lt;/span>&lt;span class="o">:&lt;/span>&lt;span class="mh">0&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="n">ir_out&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .ir_out
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_cdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_cdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_sdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_sdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_e1dr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_e1dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_pdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_pdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_e2dr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_e2dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_udr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_udr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_cir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_cir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">virtual_state_uir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .virtual_state_uir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">tms&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .tms
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_tlr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_tlr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_rti&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_rti
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_sdrs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_sdrs
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_cdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_cdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_sdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_sdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_e1dr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_e1dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_pdr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_pdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_e2dr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_e2dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_udr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_udr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_sirs&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_sirs
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_cir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_cir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_sir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_sir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_e1ir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_e1ir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_pir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_pir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_e2ir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_e2ir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">jtag_state_uir&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1">// .jtag_state_uir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="k">output&lt;/span> &lt;span class="kt">wire&lt;/span> &lt;span class="n">tck&lt;/span> &lt;span class="c1">// tck.clk
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;span class="n">sld_virtual_jtag&lt;/span> &lt;span class="p">#(&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">sld_auto_instance_index&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;YES&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">sld_instance_index&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mh">0&lt;/span>&lt;span class="p">),&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">sld_ir_width&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="mh">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">)&lt;/span> &lt;span class="n">virtual_jtag_0&lt;/span> &lt;span class="p">(&lt;/span>
&lt;span class="p">.&lt;/span>&lt;span class="n">tdi&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tdi&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// jtag.tdi
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">tdo&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tdo&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .tdo
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">ir_in&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ir_in&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .ir_in
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">ir_out&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">ir_out&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .ir_out
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_cdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_cdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_sdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_sdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_sdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_e1dr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_e1dr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_e1dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_pdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_pdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_pdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_e2dr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_e2dr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_e2dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_udr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_udr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_udr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_cir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_cir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_cir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">virtual_state_uir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">virtual_state_uir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .virtual_state_uir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">tms&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tms&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .tms
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_tlr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_tlr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_tlr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_rti&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_rti&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_rti
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_sdrs&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_sdrs&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_sdrs
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_cdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_cdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_cdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_sdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_sdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_sdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_e1dr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_e1dr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_e1dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_pdr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_pdr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_pdr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_e2dr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_e2dr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_e2dr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_udr&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_udr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_udr
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_sirs&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_sirs&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_sirs
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_cir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_cir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_cir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_sir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_sir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_sir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_e1ir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_e1ir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_e1ir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_pir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_pir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_pir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_e2ir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_e2ir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_e2ir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">jtag_state_uir&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">jtag_state_uir&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1">// .jtag_state_uir
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">.&lt;/span>&lt;span class="n">tck&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tck&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1">// tck.clk
&lt;/span>&lt;span class="c1">&lt;/span> &lt;span class="p">);&lt;/span>
&lt;span class="k">endmodule&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>NSLから使えるようにヘッダーファイルを書く。
なお、クロック供給などは不要で、合成時にうまくやってくれる。
ちなみに、JTAGのコントローラーは別に実装されているらしく、クロックやtdi, tdoなどの信号は
sld_hubなどに供給されるようである。
しかし、VJTAGのインスタンス(sld_node)や(sld_hub)はロジックエレメントを消費する。
&lt;code>jtag_*&lt;/code>の信号はデバック用途であり、使用不可である。
この信号はJTAGのコントローラーから来ている。
&lt;code>virtual_*&lt;/code>の信号はVJTAGのステートマシンの状態である。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="n">declare&lt;/span> &lt;span class="n">vjtag&lt;/span> &lt;span class="n">interface&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">tdi&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">tdo&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">ir_in&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">input&lt;/span> &lt;span class="n">ir_out&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">];&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_cdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_sdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_e1dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_pdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_e2dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_udr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_cir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">virtual_state_uir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">tms&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_tlr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_rti&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_sdrs&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_cdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_sdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_e1dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_pdr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_e2dr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_udr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_sirs&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_cir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_sir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_e1ir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_pir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_e2ir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">func_out&lt;/span> &lt;span class="n">jtag_state_uir&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="n">output&lt;/span> &lt;span class="n">tck&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="vjtagとの通信">VJTAGとの通信&lt;/h3>
&lt;p>VJTAGのインスタンスと通信するには、まずsld_hubと通信をする必要がある。
sld_hubには２つのオペレーションが定義されている。
なお、sld_hubのIRはインスタンスによらず、10bitである。
sld_hubに接続されているインスタンスの情報を取り出すことができるが、今回は省略する。
ドキュメントおよび&lt;code>riscv-openocd/src/target/riscv/riscv_tap_vjtag.c&lt;/code>を見てほしい。
なお、VJTAGのインスタンスのIR/DRはsld_hubのサブセットという形な模様。
そのため、それぞれVIR(Virtual IR)およびVDR(Virtual DR)と呼ばれている。
ブロック図を以下に示す(仕様から書き起こしたので、もしかしたら間違いがあるかもしれない）。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image02.png"
target="_blank">&lt;img class="img" src="./image02.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;p>なお、sld_hubには、２つの命令がある。
これは、Shift_IRを用いてsld_hubのIR(10 bit)へ書き込むことで命令を発行できる。&lt;/p>
&lt;ul>
&lt;li>USER0
VDRのパスを選択する。&lt;/li>
&lt;li>USER1
VIRのパスを選択する。&lt;/li>
&lt;/ul>
&lt;p>OpenOCDでは、or1kのみVJTAGに対応している。
次からは、OpenOCDのRISC-VターゲットにVJTAGサポートを行う。
その後、実際にOpenOCDからVJTAG on DE10-Liteに通信ができるかテストをする。&lt;/p></description></item><item><title>My RISC-V debug feature part1</title><link>https://www.ck-dev.io/blog/my_riscv_debug_feature_part1/</link><pubDate>Tue, 06 Apr 2021 10:39:30 +0900</pubDate><guid>https://www.ck-dev.io/blog/my_riscv_debug_feature_part1/</guid><description>&lt;p>RISC-VプロセッサのシミュレータはVerilog HDLからVerilatorにてC++へ変換して、ソフトウエアとして構築している。
そろそろまともな実機テスト環境を整えたくなってきたので、FPGA上で検証できるシステムを構築する。&lt;/p>
&lt;h2 id="デバック環境の検討">デバック環境の検討&lt;/h2>
&lt;p>RISC-Vでは、RISC-V Debug Mode&lt;a href="https://github.com/riscv/riscv-debug-spec"target="_blank" rel="noopener noreferrer">RISC-V debug spec&lt;/a>
が定義されている。
この仕様では、デバック用の機能をまとめており、gdbなどはこの機能が実装されていることを前提としている。
オレオレの仕様でも良さそうではあるけれど、ツールをの移植など対応させるのが非常にめんどうくさい。
そこで、RISC-V Debugに沿った実装を行う。
これは、通信のプロトコルについては規定していない。
プロトコルはJTAGやSWDなどいろいろあるが、大体はOpenOCDが頑張ってくれる。
Intel FPGAの場合は、Virtual JTAGがあって、デザインの中でインスタンス化すると、USB Blasterケーブルを通してモジュールと通信できるよう。&lt;/p>
&lt;p>そこで、今回はUSBケーブルを通して、JTAG(VJTAG)にてFPAG &amp;lt;-&amp;gt; PC間の通信をする。
制御用のソフトウエアはOpenOCDを用いる。
デバッカはgdbを用いる。
今回実装すべきなのは、VJTAG &amp;lt;-&amp;gt; RISC-V間のデータパスと制御である。&lt;/p>
&lt;p>RISC-V Debugの仕様では、以下の図に対応する。
Debug Transport HardwareはUSBダウンロードケーブルとなる。
DTMでは、VJTAGで受け取ったデータをデバック用の命令に変換し、DMIというバスを通して、DMへ送る。
DMは命令をもとに、プロセッサの状態を制御する。
プロセッサはデバックモードの実装が必要となる。
なお、点線の部分は任意の実装となる。
とりあえず、最小限の実装をする。
&lt;span class="image-container">&lt;span class="link" >&lt;a href="./image00.png"
target="_blank">&lt;img class="img" src="./image00.png"/>&lt;/a>&lt;/span>
&lt;/span>&lt;/p>
&lt;h2 id="やること">やること&lt;/h2>
&lt;ul>
&lt;li>仕様の調査&lt;/li>
&lt;li>実装の調査&lt;/li>
&lt;li>VJTAGの調査とテスト&lt;/li>
&lt;li>OpenOCDを使った、VJTAGの制御&lt;/li>
&lt;li>Debug modeの実装&lt;/li>
&lt;li>DTM, DMの実装&lt;/li>
&lt;li>gdbによる実機テスト&lt;/li>
&lt;/ul>
&lt;p>こんな感じで進めていく。
まずは、Debug specをしっかり読んでいく。前に読んだときはさっぱりで諦めた(小声)&lt;/p></description></item><item><title>Reading linux kernel part6</title><link>https://www.ck-dev.io/blog/reading_linux_kernel_part6/</link><pubDate>Fri, 02 Apr 2021 13:59:10 +0900</pubDate><guid>https://www.ck-dev.io/blog/reading_linux_kernel_part6/</guid><description>&lt;p>&lt;code>handle_exception&lt;/code>の続きを読んでいく。&lt;/p>
&lt;h2 id="handle_exception">handle_exception&lt;/h2>
&lt;p>global pointerのロードから。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm"> &lt;span class="err">/*&lt;/span> &lt;span class="nf">Load&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">global&lt;/span> &lt;span class="no">pointer&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="na">.option&lt;/span> &lt;span class="no">push&lt;/span>
&lt;span class="na">.option&lt;/span> &lt;span class="no">norelax&lt;/span>
&lt;span class="nf">la&lt;/span> &lt;span class="no">gp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">__global_pointer$&lt;/span>
&lt;span class="na">.option&lt;/span> &lt;span class="no">pop&lt;/span>
&lt;span class="c">#ifdef CONFIG_TRACE_IRQFLAGS
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">call&lt;/span> &lt;span class="no">trace_hardirqs_off&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="c">#ifdef CONFIG_CONTEXT_TRACKING
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">/*&lt;/span> &lt;span class="nf">If&lt;/span> &lt;span class="no">previous&lt;/span> &lt;span class="no">state&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">user&lt;/span> &lt;span class="no">mode&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">call&lt;/span> &lt;span class="no">context_tracking_user_exit.&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">li&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">SR_PP&lt;/span>
&lt;span class="nf">and&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a0&lt;/span>
&lt;span class="nf">bnez&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">skip_context_tracking&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">context_tracking_user_exit&lt;/span>
&lt;span class="nl">skip_context_tracking:&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">MSB&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">cause&lt;/span> &lt;span class="no">differentiates&lt;/span> &lt;span class="no">between&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">interrupts&lt;/span> &lt;span class="no">and&lt;/span> &lt;span class="no">exceptions&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">bge&lt;/span> &lt;span class="no">s4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">zero&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="nf">la&lt;/span> &lt;span class="no">ra&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">ret_from_exception&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Handle&lt;/span> &lt;span class="no">interrupts&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">move&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sp&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">pt_regs&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">la&lt;/span> &lt;span class="no">a1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">handle_arch_irq&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="no">a1&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">jr&lt;/span> &lt;span class="no">a1&lt;/span>
&lt;span class="err">1:&lt;/span>
&lt;span class="c">#ifdef CONFIG_TRACE_IRQFLAGS
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">call&lt;/span> &lt;span class="no">trace_hardirqs_on&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Exceptions&lt;/span> &lt;span class="no">run&lt;/span> &lt;span class="no">with&lt;/span> &lt;span class="no">interrupts&lt;/span> &lt;span class="no">enabled&lt;/span> &lt;span class="no">or&lt;/span> &lt;span class="no">disabled&lt;/span> &lt;span class="no">depending&lt;/span> &lt;span class="no">on&lt;/span> &lt;span class="no">the&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">state&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">SR_PIE&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">m&lt;/span>&lt;span class="err">/&lt;/span>&lt;span class="no">sstatus.&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">andi&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">SR_PIE&lt;/span>
&lt;span class="nf">beqz&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="nf">csrs&lt;/span> &lt;span class="no">CSR_STATUS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">SR_IE&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>gp&lt;/code>をロードする。global pointerはリロケーション済みになる。
トラッキングについては省く。
次に、&lt;code>s4&lt;/code>レジスタ(&lt;code>scause&lt;/code>)の最上位ビットを調べる。
最上位ビットが立っているときは割込みである。
&lt;code>bge s4, zero, 1f&lt;/code>で確かめている。
例外の場合は、&lt;code>1:&lt;/code>である。&lt;/p>
&lt;p>まずは、例外の処理を見ていく。&lt;/p>
&lt;h3 id="例外の処理">例外の処理&lt;/h3>
&lt;p>sstatus(&lt;code>s1&lt;/code>)にpie(Previous Interrupt Enable)が立っているか調べる。
例外発生時に割込みが有効であったか調べる。
もし、&lt;code>sstatus.pie&lt;/code>が0であれば、&lt;code>sstatus.sie&lt;/code>をセットする。&lt;/p>
&lt;p>次にリターンアドレスをセットする。(&lt;code>ret_from_exception&lt;/code>)
&lt;code>s4&lt;/code>(&lt;code>scause&lt;/code>)が&lt;code>EXC_SYSCALL&lt;/code>であるか調べる。
その場合は、システムコールなので&lt;code>handle_syscall&lt;/code>へ分岐する。
その他の例外の場合は、&lt;code>excp_vect_table&lt;/code>を索引する。
&lt;code>s4&lt;/code>(&lt;code>scause&lt;/code>)を右に二回(RV32の場合は、&lt;code>RISCV_LGPTR&lt;/code>は&lt;code>2&lt;/code>、&lt;code>arch/riscv/include/asm/asm.h&lt;/code>)左にシフトする。
&lt;code>a0&lt;/code>に&lt;code>pt_regs&lt;/code>のポインタをセットし、&lt;code>excp_vect_table&lt;/code>〜&lt;code>excp_vect_table_end&lt;/code>の間にあるかをみて、索引する。
その後、レジスタ相対ジャンプを行う。&lt;/p>
&lt;p>&lt;code>excp_vect_table&lt;/code>〜&lt;code>excp_vect_table_end&lt;/code>の間にインデックス(&lt;code>t0&lt;/code>)が収まらない場合は、&lt;code>1:&lt;/code>へ分岐し、&lt;code>do_trap_unknown&lt;/code>を実行する。&lt;/p>
&lt;h4 id="excp_vect_table">excp_vect_table&lt;/h4>
&lt;p>システムコール以外の、各例外のハンドラは&lt;code>excp_vect_table&lt;/code>に登録されている。
索引する際に、範囲外であれば、&lt;code>do_trap_unknown&lt;/code>となる。
&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="c">#ifndef CONFIG_MMU
&lt;/span>&lt;span class="c">#define do_page_fault do_trap_unknown
&lt;/span>&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="na">.section&lt;/span> &lt;span class="s">&amp;#34;.rodata&amp;#34;&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Exception&lt;/span> &lt;span class="no">vector&lt;/span> &lt;span class="no">table&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">ENTRY&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">excp_vect_table&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_insn_misaligned&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_insn_fault&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_insn_illegal&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_break&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_load_misaligned&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_load_fault&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_store_misaligned&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_store_fault&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_ecall_u&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">system&lt;/span> &lt;span class="no">call&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">gets&lt;/span> &lt;span class="no">intercepted&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_ecall_s&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_unknown&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_ecall_m&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_page_fault&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">instruction&lt;/span> &lt;span class="no">page&lt;/span> &lt;span class="no">fault&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_page_fault&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">load&lt;/span> &lt;span class="no">page&lt;/span> &lt;span class="no">fault&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_trap_unknown&lt;/span>
&lt;span class="nf">RISCV_PTR&lt;/span> &lt;span class="no">do_page_fault&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">store&lt;/span> &lt;span class="no">page&lt;/span> &lt;span class="no">fault&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nl">excp_vect_table_end:&lt;/span>
&lt;span class="nf">END&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">excp_vect_table&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;h4 id="handle_syscall">handle_syscall&lt;/h4>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="nl">handle_syscall:&lt;/span>
&lt;span class="c">#if defined(CONFIG_TRACE_IRQFLAGS) || defined(CONFIG_CONTEXT_TRACKING)
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">/*&lt;/span> &lt;span class="nf">Recover&lt;/span> &lt;span class="no">a0&lt;/span> &lt;span class="p">-&lt;/span> &lt;span class="no">a7&lt;/span> &lt;span class="no">for&lt;/span> &lt;span class="no">system&lt;/span> &lt;span class="no">calls&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A3&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A4&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A6&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A7&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">/*&lt;/span> &lt;span class="nf">save&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">initial&lt;/span> &lt;span class="no">A0&lt;/span> &lt;span class="no">value&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="no">needed&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">signal&lt;/span> &lt;span class="no">handlers&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">REG_S&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_ORIG_A0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Advance&lt;/span> &lt;span class="no">SEPC&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">avoid&lt;/span> &lt;span class="no">executing&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">original&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">scall&lt;/span> &lt;span class="no">instruction&lt;/span> &lt;span class="no">on&lt;/span> &lt;span class="no">sret&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">addi&lt;/span> &lt;span class="no">s2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0x4&lt;/span>
&lt;span class="nf">REG_S&lt;/span> &lt;span class="no">s2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_EPC&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Trace&lt;/span> &lt;span class="no">syscalls&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">but&lt;/span> &lt;span class="no">only&lt;/span> &lt;span class="no">if&lt;/span> &lt;span class="no">requested&lt;/span> &lt;span class="no">by&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">user.&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">TASK_TI_FLAGS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">tp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">andi&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">_TIF_SYSCALL_WORK&lt;/span>
&lt;span class="nf">bnez&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">handle_syscall_trace_enter&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>a0&lt;/code>レジスタを&lt;code>pt_regs-&amp;gt;orig_a0&lt;/code>に保存する。
&lt;code>sepc&lt;/code>(&lt;code>s2&lt;/code>)を+4して、&lt;code>pt_regs-&amp;gt;epc&lt;/code>に保存する。&lt;/p>
&lt;p>次に、&lt;code>thread_info-&amp;gt;flags&lt;/code>を取り出し、システムコールをトレースが必要か調べる。&lt;/p>
&lt;p>&lt;code>arch/riscv/include/asm/thread_info.h&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">thread&lt;/span> &lt;span class="no">information&lt;/span> &lt;span class="no">flags&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">these&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">process&lt;/span> &lt;span class="no">state&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">that&lt;/span> &lt;span class="no">various&lt;/span> &lt;span class="no">assembly&lt;/span> &lt;span class="no">files&lt;/span> &lt;span class="no">may&lt;/span> &lt;span class="no">need&lt;/span> &lt;span class="no">to&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">access&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">pending&lt;/span> &lt;span class="no">work-to-be-done&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">lowest&lt;/span> &lt;span class="no">half-word&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">other&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">upper&lt;/span> &lt;span class="no">half-word&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="c">#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
&lt;/span>&lt;span class="c">#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
&lt;/span>&lt;span class="c">#define TIF_SIGPENDING 2 /* signal pending */
&lt;/span>&lt;span class="c">#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
&lt;/span>&lt;span class="c">#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
&lt;/span>&lt;span class="c">#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
&lt;/span>&lt;span class="c">#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
&lt;/span>&lt;span class="c">#define TIF_SYSCALL_AUDIT 7 /* syscall auditing */
&lt;/span>&lt;span class="c">#define TIF_SECCOMP 8 /* syscall secure computing */
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="c">#define _TIF_SYSCALL_TRACE (1 &amp;lt;&amp;lt; TIF_SYSCALL_TRACE)
&lt;/span>&lt;span class="c">#define _TIF_NOTIFY_RESUME (1 &amp;lt;&amp;lt; TIF_NOTIFY_RESUME)
&lt;/span>&lt;span class="c">#define _TIF_SIGPENDING (1 &amp;lt;&amp;lt; TIF_SIGPENDING)
&lt;/span>&lt;span class="c">#define _TIF_NEED_RESCHED (1 &amp;lt;&amp;lt; TIF_NEED_RESCHED)
&lt;/span>&lt;span class="c">#define _TIF_SYSCALL_TRACEPOINT (1 &amp;lt;&amp;lt; TIF_SYSCALL_TRACEPOINT)
&lt;/span>&lt;span class="c">#define _TIF_SYSCALL_AUDIT (1 &amp;lt;&amp;lt; TIF_SYSCALL_AUDIT)
&lt;/span>&lt;span class="c">#define _TIF_SECCOMP (1 &amp;lt;&amp;lt; TIF_SECCOMP)
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="c">#define _TIF_SYSCALL_WORK \
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">(&lt;/span>&lt;span class="nf">_TIF_SYSCALL_TRACE&lt;/span> &lt;span class="err">|&lt;/span> &lt;span class="no">_TIF_SYSCALL_TRACEPOINT&lt;/span> &lt;span class="err">|&lt;/span> &lt;span class="no">_TIF_SYSCALL_AUDIT&lt;/span> &lt;span class="err">|&lt;/span> &lt;span class="err">\&lt;/span>
&lt;span class="nf">_TIF_SECCOMP&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>トレースが必要な場合は&lt;code>handle_syscall_trace_enter&lt;/code>に分岐する。
このパスは&lt;code>ptrace&lt;/code>に用いられる。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="err">/*&lt;/span> &lt;span class="nf">Slow&lt;/span> &lt;span class="no">paths&lt;/span> &lt;span class="no">for&lt;/span> &lt;span class="no">ptrace.&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nl">handle_syscall_trace_enter:&lt;/span>
&lt;span class="nf">move&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sp&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">do_syscall_trace_enter&lt;/span>
&lt;span class="nf">move&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a0&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A3&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A4&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A6&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A7&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">bnez&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">ret_from_syscall_rejected&lt;/span>
&lt;span class="nf">j&lt;/span> &lt;span class="no">check_syscall_nr&lt;/span>
&lt;span class="nl">handle_syscall_trace_exit:&lt;/span>
&lt;span class="nf">move&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sp&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">do_syscall_trace_exit&lt;/span>
&lt;span class="nf">j&lt;/span> &lt;span class="no">ret_from_exception&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>この場合でも&lt;code>check_syscall_nr&lt;/code>を呼びだす。
よって、このパスはとりあえず無視する。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="nl">check_syscall_nr:&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Check&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">make&lt;/span> &lt;span class="no">sure&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">don&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="no">t&lt;/span> &lt;span class="no">jump&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">a&lt;/span> &lt;span class="no">bogus&lt;/span> &lt;span class="no">syscall&lt;/span> &lt;span class="no">number.&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">li&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">__NR_syscalls&lt;/span>
&lt;span class="nf">la&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sys_ni_syscall&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Syscall&lt;/span> &lt;span class="no">number&lt;/span> &lt;span class="no">held&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">a7.&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">If&lt;/span> &lt;span class="no">syscall&lt;/span> &lt;span class="no">number&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">above&lt;/span> &lt;span class="no">allowed&lt;/span> &lt;span class="no">value&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">redirect&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">ni_syscall.&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">bge&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Check&lt;/span> &lt;span class="no">if&lt;/span> &lt;span class="no">syscall&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">rejected&lt;/span> &lt;span class="no">by&lt;/span> &lt;span class="no">tracer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">i.e.&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a7&lt;/span> &lt;span class="err">==&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">.&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">If&lt;/span> &lt;span class="no">yes&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">pretend&lt;/span> &lt;span class="no">it&lt;/span> &lt;span class="no">was&lt;/span> &lt;span class="no">executed.&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">li&lt;/span> &lt;span class="no">t1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">-&lt;/span>&lt;span class="mi">1&lt;/span>
&lt;span class="nf">beq&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">t1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">ret_from_syscall_rejected&lt;/span>
&lt;span class="nf">blt&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">t1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Call&lt;/span> &lt;span class="no">syscall&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">la&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sys_call_table&lt;/span>
&lt;span class="nf">slli&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">RISCV_LGPTR&lt;/span>
&lt;span class="nf">add&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">t0&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">s0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">1:&lt;/span>
&lt;span class="nf">jalr&lt;/span> &lt;span class="no">s0&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>__NR_syscalls&lt;/code>はシステムコール番号の最大値である。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/syscall_table.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cp">#undef __SYSCALL
&lt;/span>&lt;span class="cp">#define __SYSCALL(nr, call) [nr] = (call),
&lt;/span>&lt;span class="cp">&lt;/span>
&lt;span class="kt">void&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">sys_call_table&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">__NR_syscalls&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span> &lt;span class="p">...&lt;/span> &lt;span class="n">__NR_syscalls&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">sys_ni_syscall&lt;/span>&lt;span class="p">,&lt;/span>
&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;asm/unistd.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;span class="cp">&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>sys_ni_syscall&lt;/code>は実装されていないシステムコールの処理である。
&lt;code>kernel/sys_ni.c&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="cm">/* we can&amp;#39;t #include &amp;lt;linux/syscalls.h&amp;gt; here,
&lt;/span>&lt;span class="cm"> but tell gcc to not warn with -Wmissing-prototypes */&lt;/span>
&lt;span class="n">asmlinkage&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">sys_ni_syscall&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="p">);&lt;/span>
&lt;span class="cm">/*
&lt;/span>&lt;span class="cm"> * Non-implemented system calls get redirected here.
&lt;/span>&lt;span class="cm"> */&lt;/span>
&lt;span class="n">asmlinkage&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">sys_ni_syscall&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="p">{&lt;/span>
&lt;span class="k">return&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="n">ENOSYS&lt;/span>&lt;span class="p">;&lt;/span>
&lt;span class="p">}&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>システムコール発行の引数(&lt;code>a7&lt;/code>)のシステムコール番号が&lt;code>__NR_syscalls&lt;/code>より以上の場合は実装されていない。(&lt;code>1:&lt;/code>)&lt;/p>
&lt;p>システムコール番号(&lt;code>a7&lt;/code>)が&lt;code>-1&lt;/code>の場合は&lt;code>ret_from_syscall_rejected&lt;/code>へ分岐する。&lt;/p>
&lt;p>次にシステムコール番号(&lt;code>a7&lt;/code>)で&lt;code>sys_call_table&lt;/code>を索引し、ジャンプする。&lt;/p>
&lt;h4 id="例外からの復帰">例外からの復帰&lt;/h4>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="nl">ret_from_syscall&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="cm">/* Set user a0 to kernel a0 */&lt;/span>
&lt;span class="n">REG_S&lt;/span> &lt;span class="n">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PT_A0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="cm">/*
&lt;/span>&lt;span class="cm"> * We didn&amp;#39;t execute the actual syscall.
&lt;/span>&lt;span class="cm"> * Seccomp already set return value for the current task pt_regs.
&lt;/span>&lt;span class="cm"> * (If it was configured with SECCOMP_RET_ERRNO/TRACE)
&lt;/span>&lt;span class="cm"> */&lt;/span>
&lt;span class="nl">ret_from_syscall_rejected&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="cm">/* Trace syscalls, but only if requested by the user. */&lt;/span>
&lt;span class="n">REG_L&lt;/span> &lt;span class="n">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">TASK_TI_FLAGS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">andi&lt;/span> &lt;span class="n">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">_TIF_SYSCALL_WORK&lt;/span>
&lt;span class="n">bnez&lt;/span> &lt;span class="n">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">handle_syscall_trace_exit&lt;/span>
&lt;span class="nl">ret_from_exception&lt;/span>&lt;span class="p">:&lt;/span>
&lt;span class="n">REG_L&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PT_STATUS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="n">csrc&lt;/span> &lt;span class="n">CSR_STATUS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">SR_IE&lt;/span>
&lt;span class="cp">#ifdef CONFIG_TRACE_IRQFLAGS
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">call&lt;/span> &lt;span class="n">trace_hardirqs_off&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">#ifdef CONFIG_RISCV_M_MODE
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="cm">/* the MPP value is too large to be used as an immediate arg for addi */&lt;/span>
&lt;span class="n">li&lt;/span> &lt;span class="n">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">SR_MPP&lt;/span>
&lt;span class="n">and&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">t0&lt;/span>
&lt;span class="cp">#else
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">andi&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">SR_SPP&lt;/span>
&lt;span class="cp">#endif
&lt;/span>&lt;span class="cp">&lt;/span> &lt;span class="n">bnez&lt;/span> &lt;span class="n">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">resume_kernel&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>次に、システムコールの戻り値を&lt;code>pt_regs-&amp;gt;a0&lt;/code>に保存し、割込みを無効にする。
次に移るモード(&lt;code>sstatus.spp&lt;/code>)をマスクする。
このモードが&lt;code>0&lt;/code>の場合はユーザーモードなので、&lt;code>resume_userspace&lt;/code>を実行する。
それ以外は&lt;code>resume_kernel&lt;/code>を実行する。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="c">#if IS_ENABLED(CONFIG_PREEMPTION)
&lt;/span>&lt;span class="c">&lt;/span>&lt;span class="nl">resume_kernel:&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">TASK_TI_PREEMPT_COUNT&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">tp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">bnez&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">restore_all&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">TASK_TI_FLAGS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">tp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">andi&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">_TIF_NEED_RESCHED&lt;/span>
&lt;span class="nf">beqz&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">restore_all&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">preempt_schedule_irq&lt;/span>
&lt;span class="nf">j&lt;/span> &lt;span class="no">restore_all&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>CONFIG_PREEMPTION&lt;/code>を定義すると、プロセスコンテキストにおいてカーネル内のコードを実行中であっても他のプロセスにCPUを手放す。&lt;/p>
&lt;ul>
&lt;li>&lt;a href="https://wiki.bit-hive.com/linuxkernelmemo/pg/%E3%83%97%E3%83%AA%E3%82%A8%E3%83%B3%E3%83%97%E3%82%B7%E3%83%A7%E3%83%B3"target="_blank" rel="noopener noreferrer">プリエンプション&lt;/a>
&lt;/li>
&lt;/ul>
&lt;p>今回は、&lt;code>CONFIG_PREEMPTION&lt;/code>を定義していないので、&lt;code>resume_kernel&lt;/code>の実体は&lt;code>restore_all&lt;/code>となる。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="c">#if !IS_ENABLED(CONFIG_PREEMPTION)
&lt;/span>&lt;span class="c">&lt;/span>&lt;span class="na">.set&lt;/span> &lt;span class="no">resume_kernel&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">restore_all&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="nl">restore_all:&lt;/span>
&lt;span class="c">#ifdef CONFIG_TRACE_IRQFLAGS
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">REG_L&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_STATUS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">andi&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">SR_PIE&lt;/span>
&lt;span class="nf">beqz&lt;/span> &lt;span class="no">t0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">trace_hardirqs_on&lt;/span>
&lt;span class="nf">j&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="no">f&lt;/span>
&lt;span class="err">1:&lt;/span>
&lt;span class="nf">call&lt;/span> &lt;span class="no">trace_hardirqs_off&lt;/span>
&lt;span class="err">2:&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>CONFIG_TRACE_IRQFLAGS&lt;/code>は定義していないので、スキップする。&lt;/p>
&lt;p>&lt;code>arch/riscv/kernel/entry.S&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm"> &lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_STATUS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">The&lt;/span> &lt;span class="no">current&lt;/span> &lt;span class="no">load&lt;/span> &lt;span class="no">reservation&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">effectively&lt;/span> &lt;span class="no">part&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">processor&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="no">s&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">state&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">sense&lt;/span> &lt;span class="no">that&lt;/span> &lt;span class="no">load&lt;/span> &lt;span class="no">reservations&lt;/span> &lt;span class="no">cannot&lt;/span> &lt;span class="no">be&lt;/span> &lt;span class="no">shared&lt;/span> &lt;span class="no">between&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">different&lt;/span> &lt;span class="no">hart&lt;/span> &lt;span class="no">contexts.&lt;/span> &lt;span class="no">We&lt;/span> &lt;span class="no">can&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="no">t&lt;/span> &lt;span class="no">actually&lt;/span> &lt;span class="no">save&lt;/span> &lt;span class="no">and&lt;/span> &lt;span class="no">restore&lt;/span> &lt;span class="no">a&lt;/span> &lt;span class="no">load&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">reservation&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">so&lt;/span> &lt;span class="no">instead&lt;/span> &lt;span class="no">here&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">clear&lt;/span> &lt;span class="no">any&lt;/span> &lt;span class="no">existing&lt;/span> &lt;span class="no">reservation&lt;/span> &lt;span class="p">--&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">it&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="no">s&lt;/span> &lt;span class="no">always&lt;/span> &lt;span class="no">legal&lt;/span> &lt;span class="no">for&lt;/span> &lt;span class="no">implementations&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">clear&lt;/span> &lt;span class="no">load&lt;/span> &lt;span class="no">reservations&lt;/span> &lt;span class="no">at&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">any&lt;/span> &lt;span class="no">point&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="no">as&lt;/span> &lt;span class="no">long&lt;/span> &lt;span class="no">as&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">forward&lt;/span> &lt;span class="no">progress&lt;/span> &lt;span class="no">guarantee&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">kept&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">but&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">we&lt;/span>&lt;span class="err">&amp;#39;&lt;/span>&lt;span class="no">ll&lt;/span> &lt;span class="no">ignore&lt;/span> &lt;span class="no">that&lt;/span> &lt;span class="no">here&lt;/span>&lt;span class="p">).&lt;/span>
&lt;span class="err">*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Dangling&lt;/span> &lt;span class="no">load&lt;/span> &lt;span class="no">reservations&lt;/span> &lt;span class="no">can&lt;/span> &lt;span class="no">be&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">result&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">taking&lt;/span> &lt;span class="no">a&lt;/span> &lt;span class="no">trap&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">the&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">middle&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">an&lt;/span> &lt;span class="no">LR&lt;/span>&lt;span class="err">/&lt;/span>&lt;span class="no">SC&lt;/span> &lt;span class="no">sequence&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">but&lt;/span> &lt;span class="no">can&lt;/span> &lt;span class="no">also&lt;/span> &lt;span class="no">be&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">result&lt;/span> &lt;span class="no">of&lt;/span> &lt;span class="no">a&lt;/span> &lt;span class="no">taken&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">forward&lt;/span> &lt;span class="no">branch&lt;/span> &lt;span class="no">around&lt;/span> &lt;span class="no">an&lt;/span> &lt;span class="no">SC&lt;/span> &lt;span class="p">--&lt;/span> &lt;span class="no">which&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">how&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">implement&lt;/span> &lt;span class="no">CAS.&lt;/span> &lt;span class="no">As&lt;/span> &lt;span class="no">a&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">result&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">need&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">clear&lt;/span> &lt;span class="no">reservations&lt;/span> &lt;span class="no">between&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">last&lt;/span> &lt;span class="no">CAS&lt;/span> &lt;span class="no">and&lt;/span> &lt;span class="no">the&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">jump&lt;/span> &lt;span class="no">back&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">new&lt;/span> &lt;span class="no">context.&lt;/span> &lt;span class="no">While&lt;/span> &lt;span class="no">it&lt;/span> &lt;span class="no">is&lt;/span> &lt;span class="no">unlikely&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">store&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">completes&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">implementations&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">allowed&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">expand&lt;/span> &lt;span class="no">reservations&lt;/span> &lt;span class="no">to&lt;/span> &lt;span class="no">be&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">arbitrarily&lt;/span> &lt;span class="no">large.&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">a2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_EPC&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_SC&lt;/span> &lt;span class="no">x0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_EPC&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">csrw&lt;/span> &lt;span class="no">CSR_STATUS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a0&lt;/span>
&lt;span class="nf">csrw&lt;/span> &lt;span class="no">CSR_EPC&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">a2&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_RA&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_GP&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_TP&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x6&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x7&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x9&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A0&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x11&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x12&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x13&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A3&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x14&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A4&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x15&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x16&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A6&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x17&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_A7&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x18&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x19&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S3&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x20&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S4&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x21&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x22&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S6&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x23&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S7&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x24&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S8&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x25&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S9&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x26&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S10&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x27&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_S11&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x28&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T3&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x29&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T4&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x30&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x31&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_T6&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">x2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_SP&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">sp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="c">#ifdef CONFIG_RISCV_M_MODE
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">mret&lt;/span>
&lt;span class="c">#else
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">sret&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>SC&lt;/code>(Store conditional)を発行して、&lt;code>reservation&lt;/code>をクリアする。
&lt;code>reservation&lt;/code>(&lt;code>load reserved&lt;/code>によりセット)はプロセッサのステートなので、復元が必要。（復元の代わりにSCを発行することでreservationをクリアする。
任意の大きさの場合は&lt;code>AMO fault&lt;/code>となるはず。)
&lt;code>sstatus&lt;/code>、&lt;code>sepc&lt;/code>、汎用レジスタを復元する。
システムコールの戻り値は&lt;code>pt_regs-&amp;gt;a0&lt;/code>に保存済みである。
最後に&lt;code>sp&lt;/code>を復元していることに注意。
その後、&lt;code>sret&lt;/code>を行い、例外元のカーネルへ復帰する。(&lt;code>sstatus.spp == S-mode&lt;/code>)&lt;/p>
&lt;p>次にユーザーモードへ戻る場合を見てみる。&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="nl">resume_userspace:&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Interrupts&lt;/span> &lt;span class="no">must&lt;/span> &lt;span class="no">be&lt;/span> &lt;span class="no">disabled&lt;/span> &lt;span class="no">here&lt;/span> &lt;span class="no">so&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">checked&lt;/span> &lt;span class="no">atomically&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">REG_L&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">TASK_TI_FLAGS&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">tp&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="err">/&lt;/span>&lt;span class="p">*&lt;/span> &lt;span class="no">current_thread_info-&lt;/span>&lt;span class="err">&amp;gt;&lt;/span>&lt;span class="no">flags&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">andi&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">_TIF_WORK_MASK&lt;/span>
&lt;span class="nf">bnez&lt;/span> &lt;span class="no">s1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">work_pending&lt;/span>
&lt;span class="c">#ifdef CONFIG_CONTEXT_TRACKING
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="nf">call&lt;/span> &lt;span class="no">context_tracking_user_enter&lt;/span>
&lt;span class="c">#endif
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="err">/*&lt;/span> &lt;span class="nf">Save&lt;/span> &lt;span class="no">unwound&lt;/span> &lt;span class="no">kernel&lt;/span> &lt;span class="no">stack&lt;/span> &lt;span class="no">pointer&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">thread_info&lt;/span> &lt;span class="p">*&lt;/span>&lt;span class="err">/&lt;/span>
&lt;span class="nf">addi&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">sp&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">PT_SIZE_ON_STACK&lt;/span>
&lt;span class="nf">REG_S&lt;/span> &lt;span class="no">s0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">TASK_TI_KERNEL_SP&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">tp&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">Save&lt;/span> &lt;span class="no">TP&lt;/span> &lt;span class="no">into&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">scratch&lt;/span> &lt;span class="no">register&lt;/span> &lt;span class="p">,&lt;/span> &lt;span class="no">so&lt;/span> &lt;span class="no">we&lt;/span> &lt;span class="no">can&lt;/span> &lt;span class="no">find&lt;/span> &lt;span class="no">the&lt;/span> &lt;span class="no">kernel&lt;/span> &lt;span class="no">data&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">structures&lt;/span> &lt;span class="no">again.&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="nf">csrw&lt;/span> &lt;span class="no">CSR_SCRATCH&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="no">tp&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;code>thread_info-&amp;gt;flags&lt;/code>を見て、シグナル、コールバック、リスケジュールが必要な際には&lt;code>work_pending&lt;/code>を実行する。
それ以外の場合は、&lt;code>s0&lt;/code>にスタックポインタを戻したものを作成し、&lt;code>task_struct&lt;/code>の&lt;code>kernel sp&lt;/code>へ保存する。
&lt;code>tp&lt;/code>を&lt;code>scratch&lt;/code>とスワップし、カーネルのデータ構造へのポインタを&lt;code>sscratch&lt;/code>へ保存する。
その後は&lt;code>restore_all&lt;/code>と同じである。ただし、&lt;code>sstatus-&amp;gt;spp == U-mode&lt;/code>なので、ユーザースペースへ復帰する。&lt;/p>
&lt;p>&lt;code>arch/riscv/include/asm/thread_info.h&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre class="chroma">&lt;code class="language-asm" data-lang="asm">&lt;span class="err">/*&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">thread&lt;/span> &lt;span class="no">information&lt;/span> &lt;span class="no">flags&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">these&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">process&lt;/span> &lt;span class="no">state&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">that&lt;/span> &lt;span class="no">various&lt;/span> &lt;span class="no">assembly&lt;/span> &lt;span class="no">files&lt;/span> &lt;span class="no">may&lt;/span> &lt;span class="no">need&lt;/span> &lt;span class="no">to&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="nf">access&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">pending&lt;/span> &lt;span class="no">work-to-be-done&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">are&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">lowest&lt;/span> &lt;span class="no">half-word&lt;/span>
&lt;span class="err">*&lt;/span> &lt;span class="err">-&lt;/span> &lt;span class="nf">other&lt;/span> &lt;span class="no">flags&lt;/span> &lt;span class="no">in&lt;/span> &lt;span class="no">upper&lt;/span> &lt;span class="no">half-word&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="no">s&lt;/span>&lt;span class="p">)&lt;/span>
&lt;span class="err">*/&lt;/span>
&lt;span class="c">#define TIF_SYSCALL_TRACE 0 /* syscall trace active */
&lt;/span>&lt;span class="c">#define TIF_NOTIFY_RESUME 1 /* callback before returning to user */
&lt;/span>&lt;span class="c">#define TIF_SIGPENDING 2 /* signal pending */
&lt;/span>&lt;span class="c">#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
&lt;/span>&lt;span class="c">#define TIF_RESTORE_SIGMASK 4 /* restore signal mask in do_signal() */
&lt;/span>&lt;span class="c">#define TIF_MEMDIE 5 /* is terminating due to OOM killer */
&lt;/span>&lt;span class="c">#define TIF_SYSCALL_TRACEPOINT 6 /* syscall tracepoint instrumentation */
&lt;/span>&lt;span class="c">#define TIF_SYSCALL_AUDIT 7 /* syscall auditing */
&lt;/span>&lt;span class="c">#define TIF_SECCOMP 8 /* syscall secure computing */
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="c">#define _TIF_SYSCALL_TRACE (1 &amp;lt;&amp;lt; TIF_SYSCALL_TRACE)
&lt;/span>&lt;span class="c">#define _TIF_NOTIFY_RESUME (1 &amp;lt;&amp;lt; TIF_NOTIFY_RESUME)
&lt;/span>&lt;span class="c">#define _TIF_SIGPENDING (1 &amp;lt;&amp;lt; TIF_SIGPENDING)
&lt;/span>&lt;span class="c">#define _TIF_NEED_RESCHED (1 &amp;lt;&amp;lt; TIF_NEED_RESCHED)
&lt;/span>&lt;span class="c">#define _TIF_SYSCALL_TRACEPOINT (1 &amp;lt;&amp;lt; TIF_SYSCALL_TRACEPOINT)
&lt;/span>&lt;span class="c">#define _TIF_SYSCALL_AUDIT (1 &amp;lt;&amp;lt; TIF_SYSCALL_AUDIT)
&lt;/span>&lt;span class="c">#define _TIF_SECCOMP (1 &amp;lt;&amp;lt; TIF_SECCOMP)
&lt;/span>&lt;span class="c">&lt;/span>
&lt;span class="c">#define _TIF_WORK_MASK \
&lt;/span>&lt;span class="c">&lt;/span> &lt;span class="err">(&lt;/span>&lt;span class="nf">_TIF_NOTIFY_RESUME&lt;/span> &lt;span class="err">|&lt;/span> &lt;span class="no">_TIF_SIGPENDING&lt;/span> &lt;span class="err">|&lt;/span> &lt;span class="no">_TIF_NEED_RESCHED&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/code>&lt;/pre>&lt;/div>&lt;p>これで、おおよそトラップ時の動作を見た。
トラップの処理自体を詳しく理解するには、&lt;code>excp_vect_table&lt;/code>、&lt;code>sys_call_table&lt;/code>、&lt;code>do_trap_unknown&lt;/code>、&lt;code>handle_arch_irq&lt;/code>を読む必要がある。
また、&lt;code>work_pending&lt;/code>や&lt;code>ptrace&lt;/code>関連のパスは読んでいないが、後に必要になるかもしれない。&lt;/p></description></item></channel></rss>