LoginSignup
0
0

More than 5 years have passed since last update.

[SystemVerilog]svlibでCPUオペコードっぽいものを定義しようと試みた。

Last updated at Posted at 2014-07-03

はじめに

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」は逆の出力が出てくる。
その後、定義したオペコード一覧が出力される。

今後に期待

毎回書いているような気もするが…。

今回は応用の利きそうなクラスに出会えたので、個人的にはもうちょっと他もみていこうかと思う。

0
0
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
0
0