FPGA開発日記

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

階層トレースモードにおいて、途中からトレースの表示を省略するモードを設ける

例えば、printfとかは内部で大量の関数を呼び出しており、関数の呼出関係のトレース図を作ると大変なことになる。 下の例では、Coremarkにおいて、cmp_complexから先を全て階層トレースとして出力した場合の結果だ。

        <FunctionCall 51052: cmp_complex(0x80000180)>
          <FunctionCall 51061: calc_func(0x80000058)>
            <FunctionCall 51085: crcu16(0x800015c0)>
            <Return: crcu16>
          <Return: calc_func>
          <FunctionCall 51266: calc_func(0x80000058)>
            <FunctionCall 51290: crcu16(0x800015c0)>
            <Return: crcu16>
          <Return: calc_func>
        <Return: cmp_complex>

そこで、任意の関数の呼出から先のトレースは、階層トレースのログから省略する機能を実装した。 Luaスクリプトで以下のように記述しておくと、ee_printfから先の階層呼び出しのトレース表示を省略する。

skip_hier (mips, "cmp_complex", "debug_skip")

階層トレースの結果は以下のようになる。cmp_complexから先の階層は表示が省略される。

        <FunctionCall 51052: cmp_complex(0x80000180) ...>
        <Return: cmp_complex>

また、オプションとして"debug_skip"を指定すると、デバッグ表示モードにおいて、命令トレースの表示も省略させることができる。 詳細を解析したいが、不必要な部分の命令トレースを省略したいときに利用できる。

トレース表示省略機能の実装

github.com

実際には、上記のhier_skipが実行されると、ISSの実行環境にリストが存在しており、そこに関数名が登録される。 階層トレースは、命令の実行中に、自分のPCが関数の先頭かどうかを探索するが、その際に、当該関数名がそのリストに 登録されていると、そこから先は関数トレースを表示しないようにフラグを上げる。 また、関数から戻ってきたときにフラグを解除することで、当該関数から戻ってきた瞬間からトレース表示を再開するようにしている。

■ trace.cpp の実装

  • 関数に入ってきたときに、当該関数が省略対象かを探索し、対象であればスイッチ m_hier_func_in_skipを有効にする。
void TraceInfo::HierFunctionCall (Addr_t fetch_pc)
...
        // find skip list
        std::vector<PairSkipFunc *>::iterator it = m_hier_skip_func.begin ();
        while (it != m_hier_skip_func.end ()) {
            if ((*it)->first == func_symbol) {
                m_hier_func_in_skip = true;
                if ((*it)->second == InstSkip) {
                    m_hier_debug_in_skip = true;
                }
                fprintf (GetTraceHierFp(), " ...");
                break;
            }
            it++;
        }
        fprintf (GetTraceHierFp(), ">\n");
...
  • 関数から脱出する場合には、フラグを落として、そこから先は関数トレースを表示させるようにする。
void TraceInfo::HierReturn (Addr_t fetch_pc)
...
        if (is_found_pc == true) {
            while (pop_count-- >= 0) {
                m_hier_stack.pop_back();
                SetHierDepth (GetHierDepth()-1);
            }
            for (int i = 0; i < GetHierDepth (); i++) {
                fprintf (GetTraceHierFp(), "  ");
            }
            fprintf (GetTraceHierFp(), "<Return: %s>\n", (*trace_it)->second.c_str());

            m_hier_func_in_skip  = false;
            m_hier_debug_in_skip = false;
        }

...