以下の内容はhttps://msyksphinz.hatenablog.com/entry/2025/07/31/040000より取得しました。


SystemVerilogのchandleについてまとめる

SystemVerilogに登場するchandleについて知らなかったので調査してみることにした。 要約するとchandleC/C++のポインタをSystemVerilogから扱うためのデータ型である。 DPI(Direct Programming Interface)を使用してC/C++の関数を呼び出す際に、特に使われるものだ。

chandleの基本概念

chandleとは

chandleは、C/C++のポインタ値を格納するための不透明なハンドルと定義することができる。 SystemVerilogからは、このハンドルの値自体を直接操作することはできないが、DPI関数を通じてC/C++の関数に渡すことができる。

chandleの宣言と使用方法

基本的な宣言

SystemVerilogからは以下のようにして宣言する。最初はnullを割り当てておく。

// chandle変数の宣言
chandle my_handle;

// 初期化(nullポインタ)
initial begin
    my_handle = null;
end

DPI関数との組み合わせ

C++の関数がポインタを渡すときに、chandleで受け取るようにする。 chandleの中身は直接SystemVerilogからはアクセスできないので、chandleの値を取得するのに、get_value()をさらに定義している。

// C/C++関数の宣言
import "DPI-C" function chandle create_object(input string name);
import "DPI-C" function void destroy_object(input chandle obj);
import "DPI-C" function int get_value(input chandle obj);

module testbench;
    chandle obj_handle;
    
    initial begin
        // オブジェクトの作成
        obj_handle = create_object("test_object");
        
        // オブジェクトの使用
        if (obj_handle != null) begin
            int value = get_value(obj_handle);
            $display("Value: %d", value);
        end
        
        // オブジェクトの破棄
        destroy_object(obj_handle);
        obj_handle = null;
    end
endmodule

例えばの例だが、create_object()destroy_object()get_value()は以下のようにしてDPI-Cの関数として定義される。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

// 任意の構造体
typedef struct {
    char name[256];
    int value;
} MyObject;

// オブジェクトの生成
void* create_object(const char* name) {
    MyObject* obj = (MyObject*)malloc(sizeof(MyObject));
    if (obj) {
        strncpy(obj->name, name, sizeof(obj->name));
        obj->name[sizeof(obj->name) - 1] = '\0';
        obj->value = 42; // 仮の値
    }
    return (void*)obj;
}

// オブジェクトの破棄
void destroy_object(void* obj) {
    free(obj);
}

// 値の取得
int get_value(void* obj) {
    if (obj == NULL) return -1;
    MyObject* myobj = (MyObject*)obj;
    return myobj->value;
}

実用的な使用例

1. リファレンスモデルの管理

RISC-Vプロセッサの検証において、RVVI-APIを使用した例:

module rvvi_testbench;
    import "DPI-C" function chandle rvviRefModelCreate(
        input string config,
        input string isa,
        input string options
    );
    import "DPI-C" function void rvviRefModelDestroy(
        input chandle ref
    );
    import "DPI-C" function longint unsigned rvviRefModelGetGPR(
        input chandle ref,
        input int hart,
        input int reg
    );
    
    chandle ref_model;
    
    initial begin
        // リファレンスモデルの作成
        ref_model = rvviRefModelCreate("config.json", "rv64gc", "");
        
        if (ref_model == null) begin
            $error("Failed to create reference model");
            $finish;
        end
        
        // テスト実行...
        
        // リファレンスモデルの破棄
        rvviRefModelDestroy(ref_model);
        ref_model = null;
    end
endmodule

2. メモリ管理の例

module memory_test;
    import "DPI-C" function chandle malloc(input int size);
    import "DPI-C" function void free(input chandle ptr);
    import "DPI-C" function void write_memory(
        input chandle ptr,
        input int offset,
        input int data
    );
    import "DPI-C" function int read_memory(
        input chandle ptr,
        input int offset
    );
    
    chandle memory_ptr;
    
    initial begin
        // メモリの確保
        memory_ptr = malloc(1024);
        
        if (memory_ptr != null) begin
            // メモリへの書き込み
            write_memory(memory_ptr, 0, 0x12345678);
            
            // メモリからの読み出し
            int data = read_memory(memory_ptr, 0);
            $display("Read data: 0x%x", data);
            
            // メモリの解放
            free(memory_ptr);
            memory_ptr = null;
        end
    end
endmodule

3. オブジェクト指向的な使用例

module object_test;
    import "DPI-C" function chandle create_counter();
    import "DPI-C" function void increment(input chandle counter);
    import "DPI-C" function int get_count(input chandle counter);
    import "DPI-C" function void reset_counter(input chandle counter);
    import "DPI-C" function void delete_counter(input chandle counter);
    
    chandle counter1, counter2;
    
    initial begin
        // カウンターオブジェクトの作成
        counter1 = create_counter();
        counter2 = create_counter();
        
        // カウンターの操作
        increment(counter1);
        increment(counter1);
        increment(counter2);
        
        $display("Counter1: %d", get_count(counter1));
        $display("Counter2: %d", get_count(counter2));
        
        // カウンターのリセット
        reset_counter(counter1);
        $display("After reset, Counter1: %d", get_count(counter1));
        
        // オブジェクトの破棄
        delete_counter(counter1);
        delete_counter(counter2);
        counter1 = null;
        counter2 = null;
    end
endmodule



以上の内容はhttps://msyksphinz.hatenablog.com/entry/2025/07/31/040000より取得しました。
このページはhttp://font.textar.tv/のウェブフォントを使用してます

不具合報告/要望等はこちらへお願いします。
モバイルやる夫Viewer Ver0.14