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

更新


公開メモ

DPI-C とは

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

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

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

関連記事

SystemVerilog のソース

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++ モードでやってみる

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: 16288 (from 2010/06/03), today: 4, yesterday: 1