2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

SystemVerilogの4値型をRustから扱う

Last updated at Posted at 2021-09-13

はじめに

以前「SystemVerilogのDPIでRustを使ってみた」という記事を書きましたが、この時は主にRustのプリミティブ型で扱える範囲内の記述をざっと試しただけでした。
その後、SystemVerilogで書いたRTLの検証モデルをRustで書くことが増えてきて、SystemVerilogの4値型を扱いたくなってきました。SystemVerilogの4値型はそのままRustのプリミティブ型としては扱えないので、そのために作成したライブラリと併せてご紹介します。

4値型とは

一般的にソフトウェアでいうビットとは0か1かの2通りの値を取ります。すなわち2値型です。
これを実現するデジタル回路においても同様に、ある配線の電圧が示す値を0か1であるとして設計するのですが、デジタル回路設計においては0/1以外の値も考える必要があり、それを扱うのが4値型です。
SystemVerilogにおける4値型は以下のように定義されています。

  • 0: 0またはfalse
  • 1: 1またはtrue
  • x: 不定値
  • z: ハイ・インピーダンス

0と1はそのままですが、x/zという2つが追加されています。xすなわち不定値は「0か1か分からない」という意味です。例えば、電源投入直後のメモリの値は、そのメモリを構成する半導体素子の個体差によってビット毎に0だったり1だったりします。このような場合、0か1かを事前に決めて設計することはできないので「xという特別な値が入っている」として設計・検証します。同様にzは「配線がどこにもつながっていないので0でも1でもない」といった状況を示すのに使われます。

この4値型をDPI(SystemVerilogとC言語間のFFIみたいなもの)経由でSystemVerilogからRustへ受け渡すことを考えます。

DPIから見た4値型

DPIによって4値型をどのように受け渡すかは、SystemVerilogの言語仕様(IEEE 1800-2017)で以下のように決まっています。

/*
* DPI representation of packed arrays.
* 2-state and 4-state vectors, exactly the same as PLI's avalue/bvalue.
*/
# ifndef VPI_VECVAL
# define VPI_VECVAL
typedef struct t_vpi_vecval {
uint32_t aval;
uint32_t bval;
} s_vpi_vecval, *p_vpi_vecval;
# endif
/* (a chunk of) packed logic array */
typedef s_vpi_vecval svLogicVecVal;

svLogicVecValが32ビットの4値を表す型で、DPIからはこのsvLogicVecValの配列がRustに渡されます。すなわち

# [repr(C)]
pub struct svLogicVecVal {
    pub aval: u32,
    pub bval: u32,
}

# [no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
}

というようなget_dataをCの関数としてエクスポートすれば、SystemVerilogから4値型を受け取ることができます。
ここで&[svLogicVecVal; 4]と長さ4の配列にしているのでSystemVerilog側は 32 * 4 = 128 ビットを渡します。

import "DPI-C" function void get_data(
  input logic [127:0] data
);

Sv4State

規格上定義されているsvLogicVecValのままでは扱いにくいので、Rustから扱いやすいように Sv4State という型を用意しました。

例えば

# [no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
    let sv_u32 = Sv4State::<u32>::from_dpi(data);
    println!("{:x}", sv_u32[0]);
    println!("{:x}", sv_u32[1]);
    println!("{:x}", sv_u32[2]);
    println!("{:x}", sv_u32[3]);
}

のように使います。
Sv4Statestd::fmt::LowerHexを実装しているので {:x} でいい感じに16進数表示できます。

また、Sv4Statevで32bitの値(x/zのビットは0としたもの)を、xzでそれぞれx/zのビットフラグを得ることができます。

# [no_mangle]
pub extern "C" fn get_data(data: &[svLogicVecVal; 4]) {
    let sv_u32 = Sv4State::<u32>::from_dpi(data);
    println!("{:x}", sv_u32[0].v);
    println!("{:x}", sv_u32[0].x);
    println!("{:x}", sv_u32[0].z);
}

サンプル

以前の記事で紹介したサンプルに Sv4State を使ったものも追加しました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?