##はじめに
svlibのドキュメントを眺めていたら、使えそうなものがあったので試しにやってみた。
svlibに関してのこれまでの投稿記事はこちら。
今回は列挙型を拡張するクラスを使ってみる。
##Utilities for enumeration types
クラスはこんな感じで定義されている。
class EnumUtils #(type ENUM = int);
typedef ENUM qe[$];
typedef logic [$bits(ENUM)-1:0] BASE;
static function ENUM fromName (string s);
static function int pos (BASE b);
static function bit hasName (string s);
static function int maxNameLength();
static function bit hasValue (BASE b);
static function qe allValues ();
static function ENUM match (BASE b, bit requireUnique = 0);
endclass: EnumUtils
ドキュメントは、メソッド名がソースコードと微妙に 違っている。 要注意。
メソッドの機能の説明はここではドキュメントに譲る…といいたいが、まだまだドキュメントの説明は 荒っぽい。
##CPUオペコードっぽいものを定義
このクラスを使うと、列挙型の変数にいろいろ便利なユーティリティをつけることができる。
そこで、ドキュメントの例を参考に、某AVRのオペコードを模してみる。
オペコードは全ビット使い切って定義することはあまりないので、連想配列でもできるものの、このクラスを使った方が便利そう。
##コード
こんな感じで書いてみた。
// # r = source register id
// # d = destination register id
// #mnemonic opcode desc
// NOP 0000:0000:0000:0000 # no operation
// MOVW 0000:0001:dddd:rrrr # copy register word (pair to pair)
// MULS 0000:0010:dddd:rrrr # multiply signed, R1:R0 = Rd * Rr
// MULSU 0000:0011:0ddd:0rrr # multiply, s16 = s8 * u8
// FMUL 0000:0011:0ddd:1rrr # fractional multiply, unsigned
// FMULS 0000:0011:1ddd:0rrr # fractional multiply, signed
// FMULSU 0000:0011:1ddd:1rrr # fractional multiply, s16 = s8 * u8
`include "svlib_macros.svh"
module tb ();
import svlib_pkg::*;
typedef enum logic[15:0] {
NOP = 16'b0000_0000_0000_0000,
MOVW = 16'b0000_0001_xxxx_xxxx,
MULS = 16'b0000_0010_xxxx_xxxx,
MULSU = 16'b0000_0011_0xxx_0xxx,
FMUL = 16'b0000_0011_0xxx_1xxx,
FMULS = 16'b0000_0011_1xxx_0xxx,
FMULSU = 16'b0000_0011_1xxx_1xxx
} op_t;
typedef EnumUtils#(op_t) op_util;
task exists (string c);
if(op_util::hasName(c))
$display("%s op exists this model.", c);
else
$display("%s op DON'T exist in this model.", c);
endtask
task print_all_op();
op_t opq[$];
opq = op_util::allValues();
foreach(opq[i]) $display("%s", opq[i].name);
endtask
initial begin
exists("MOV");
exists("MOVW");
print_all_op();
$finish(1);
end
endmodule
ここでは、入力された文字列が存在するかどうかを行うタスク(extists)と定義されているオペコードを全部出力させるタスク(print_all_op)を書いてみた。
実行されると、「MOV」は定義されていないのでDON'Tが出力され、「MOVW」は逆の出力が出てくる。
その後、定義したオペコード一覧が出力される。
##今後に期待
毎回書いているような気もするが…。
今回は応用の利きそうなクラスに出会えたので、個人的にはもうちょっと他もみていこうかと思う。