電気回路/HDL/Verilator で DPI-C のバックアップソース(No.1)

更新

[[公開メモ]]

#contents

* DPI-C とは [#ze1b51ac]

SystemVerilog の機能で、SystemVerilog で書かれたテストベンチから
C あるいは C++ で書かれたルーチンを呼び出したり、その呼び出された
C あるいは C++ で書かれたルーチンから SystemVerilog の task や
function を呼び出したりするための規格です。

ModelSim XE を使ってやってみた結果は
[[電気回路/HDL/ModelSim XE を使った SystemVerilog DPI-C テスト]] 
にあります。

今回はこれをフリーのツールである Verilator でやろうという話。

* 関連記事 [#ab496977]

#ls2(電気回路/HDL/Verilator);
#ls2(電気回路/HDL/System);

* SystemVerilog のソース [#o22e62cc]

dpic-test.sv
 LANG:verilog(linenumber)
 `timescale 1ns / 1ps
 
 // トップモジュール
 module hello_top;
 
    // verilog で書いた task
    task verilog_task(input int i, output int o);
        $display("Hello from verilog_task(%d)", i);
        o = 2 * i;
    endtask
 
    // C から使うためにエクスポートする
    export "<strong class="word0">DPI-C</strong>" task verilog_task;
 
    // C で書かれた関数をインポートする
    import "<strong class="word0">DPI-C</strong>" context task c_task(input int i, output int o);
 
    // C で書かれた関数を呼び出す
    int ret;
    initial begin
        c_task(1, ret);  // c_task は verilog_task を呼び出す
        $display("ret = %d", ret);
    end
 
 endmodule

* C++ モードでやってみる [#b03e129e]

 LANG:console
 $ ls
 dpic-test.sv
 $ verilator dpic-test.sv
 $ ls
 dpic_test.sv  obj_dir/
 $ ls obj_dir/
 Vdpic_test.cpp  Vdpic_test__Dpi.cpp   Vdpic_test__Syms.h        Vdpic_test_classes.mk
 Vdpic_test.h    Vdpic_test__Dpi.h     Vdpic_test__ver.d
 Vdpic_test.mk   Vdpic_test__Syms.cpp  Vdpic_test__verFiles.dat
 $ less Vdpic_test.h

としてみた結果は以下の通り。

obj_dir/Vdpic_test.h
 LANG:cpp(linenumber)
 // Verilated -*- C++ -*-
 // DESCRIPTION: Verilator output: Primary design header
 //
 // This header should be included by all source files instantiating the design.
 // The class here is then constructed to instantiate the design.
 // See the Verilator manual for examples.
 
 #ifndef _Vdpic_test_H_
 #define _Vdpic_test_H_
 
 #include "verilated.h"
 class Vdpic_test__Syms;
 
 //----------
 
 VL_MODULE(Vdpic_test) {
   public:
     // CELLS
     // Public to allow access to /*verilator_public*/ items;
     // otherwise the application code can consider these internals.
     
     // PORTS
     // The application code writes and reads these signals to
     // propagate new values into/out from the Verilated model.
     
     // LOCAL SIGNALS
     // Internals; generally not touched by application code
     VL_SIG(v__DOT__ret,31,0);
     
     // LOCAL VARIABLES
     // Internals; generally not touched by application code
     
     // INTERNAL VARIABLES
     // Internals; generally not touched by application code
     Vdpic_test__Syms*	__VlSymsp;		// Symbol table
     
     // PARAMETERS
     // Parameters marked /*verilator public*/ for use by application code
     
     // CONSTRUCTORS
   private:
     Vdpic_test& operator= (const Vdpic_test&);	///< Copying not allowed
     Vdpic_test(const Vdpic_test&);	///< Copying not allowed
   public:
     /// Construct the model; called by application code
     /// The special name  may be used to make a wrapper with a
     /// single model invisible WRT DPI scope names.
     Vdpic_test(const char* name="TOP");
     /// Destroy the model; called (often implicitly) by application code
     ~Vdpic_test();
     
     // USER METHODS
     
     // API METHODS
     /// Evaluate the model.  Application must call when inputs change.
     void eval();
     /// Simulation complete, run final blocks.  Application must call on completion.
     void final();
     
     // INTERNAL METHODS
   private:
     static void _eval_initial_loop(Vdpic_test__Syms* __restrict vlSymsp);
   public:
     void __Vconfigure(Vdpic_test__Syms* symsp, bool first);
     static void	__Vdpiexp_v__DOT__verilog_task_TOP(Vdpic_test__Syms* __restrict vlSymsp, IData i, IData& o);
     void	__Vdpiimwrap_v__DOT__c_task_TOP(const VerilatedScope* __Vscopep, const char* __Vfilenamep, IData __Vlineno, IData i, IData& o);
   private:
     static IData	_change_request(Vdpic_test__Syms* __restrict vlSymsp);
   public:
     static void	_eval(Vdpic_test__Syms* __restrict vlSymsp);
     static void	_eval_initial(Vdpic_test__Syms* __restrict vlSymsp);
     static void	_eval_settle(Vdpic_test__Syms* __restrict vlSymsp);
     static void	_initial__TOP(Vdpic_test__Syms* __restrict vlSymsp);
     static void	verilog_task(int i, int* o);
 } VL_ATTR_ALIGNED(64);
 
 #endif  /*guard*/

Counter: 16376 (from 2010/06/03), today: 6, yesterday: 0