アセンブラを用いたシミュレーション(期待値比較)


先の例では、アセンブラによるプログラムを実行して実行結果の波形を表示し ました。しかし、この場合でも、どこに誤りがあるのかを見つけるのは至難の 技です。そこで、今度はシミュレータが出力した結果とシミュレーション結果 の期待値とを比較する方法について紹介します。


"testadd.asm" のアセンブル後の実行イメージである "testadd.hex" を KITE シミュレータ("~ai2/bin/kite2sim")にかけると以下のような情報を得ること ができます。 現在 "~ai2/bin/kite2sim" は、jackal, cms21, cms02 でしか動作しません。rlogin してお使い下さい。


Start address = 000
  ---- acc=0000 ixr=000 ssp=000 out=0000 pc=000     c108 ld      #0x08
  ---- acc=0008 ixr=000 ssp=000 out=0000 pc=001     bc00 swp     
  ---- acc=0800 ixr=000 ssp=000 out=0000 pc=002     9100 or      #0x00
  ---- acc=0800 ixr=000 ssp=000 out=0000 pc=003     f004 mv      sp, acc
  ---- acc=0800 ixr=000 ssp=800 out=0000 pc=004     c800 in      0x00
	中略
  ---- acc=0037 ixr=7fd ssp=800 out=0000 pc=008     cc00 out     0x00
  ---- acc=0037 ixr=7fd ssp=800 out=0037 pc=009     f800 halt    
  ---- acc=0037 ixr=7fd ssp=800 out=0037 pc=00a     f009 mv      ixr, sp

これは命令実行のトレースを意味します。すなわち、この命令実行トレースは 皆さんが作成したプロセッサをシミュレーションした際の実行期待値となるわ けです。論理シミュレータが、この期待値と同じ書式で実行結果を出力できれ ば、UNIX の "diff" コマンドにより一気に一致比較を行うことができます。

では、論理シミュレータは、この期待値と同じ書式で実行結果を出力できるの でしょうか? 実は、できます。シミュレーションを行う際の "testfixture.new"ファイルとして、以下の内容を使用します。


//
// CLOCK : 1MHz infinite loop
//
initial
begin
    CLOCK = 1'b1;
    while(1)
        CLOCK = #5000 ~CLOCK;
end

//
// I_A : 2MHz infinite loop
//
integer i1;
initial
begin
    I_A = 1'b1;
    while(1)
        I_A = #2500 ~I_A;
end

//
// Condition for Termination : IR = HALT and HALT = TRUE
//
always @( ACC_IR or HALT )
  if( ACC_IR == 16'hF800 && HALT == 1'b0 )
    #10000 $finish;

//
//  RESET, EXEC, CLKM, INSTM
//

initial
begin
    RESET = # 0 1;	//     0ns 
    RESET = # 15000 0;	//  1500 
    RESET = # 10000 1;	//  2500 
end

initial
begin
    EXEC = # 0 1;	//     0ns 
end

initial
begin
    CLKM = # 0 1;	//     0ns 
end

initial
begin
    INSTM = # 0 1;	//     0ns 
end


//
// Load instructions on Memory
//

reg [15:0] MEM[0:4095];	// Memory Image

initial
begin
	$readmemh("/user/staff/kuga/work/cadence/4bit/testadd.ram", MEM);
end

//
// Memory and I/O Transactions
//
initial
begin
    ACK  = # 0 1;	//     0ns 
end

reg [15:0] OUTR;	// OUT port

initial
begin
    OUTR  = # 0 16'h0000;	//     0ns 
end

always @( MREQ )
begin
  if ( MREQ == 1'b0 && RW == 1'b1 )
    begin
      io_DATA = MEM[ADDR];
      ACK     = 1'b0;
//      $display("MEM Transaction READ  : ADDR=%x  DATA=%x", ADDR, MEM[ADDR]);
    end
  else if ( MREQ == 1'b1 && RW == 1'b1 )
    begin
      io_DATA = 16'hZZZZ;
      ACK     = 1'b1;
    end
  else if ( MREQ == 1'b0 && RW == 1'b0 )
    begin
      MEM[ADDR] = DATA[15:0];
      ACK     = 1'b0;
//      $display("MEM Transaction WRITE : ADDR=%x  DATA=%x", ADDR, DATA);
    end
  else if ( MREQ == 1'b1 && RW == 1'b0 )
    begin
      ACK     = 1'b1;
    end
end

always @( IORQ )
begin
  if ( IORQ == 1'b0 && RW == 1'b1 )
    begin
      io_DATA = 16'h000a;				// Input Value
      ACK     = 1'b0;
//      $display("I/O Transaction INPUT : ADDR=%x  DATA=%x", ADDR, io_DATA);
    end
  else if ( IORQ == 1'b1 && RW == 1'b1 )
    begin
      io_DATA = 16'hZZZZ;
      ACK     = 1'b1;
    end
  else if ( IORQ == 1'b0 && RW == 1'b0 )
    begin
      ACK     = 1'b0;
      OUTR    = DATA;
//      $display("I/O Transaction OUT   : ADDR=%x  DATA=%x", ADDR, DATA);
    end
  else if ( IORQ == 1'b1 && RW == 1'b0 )
    begin
      ACK     = 1'b1;
    end
end

//
// Execution Trace
//
always @( test.top.I70.ICS or I_A or CLOCK)
begin
  if ( test.top.I70.ICS == 1'b1 && I_A == 1'b0 && CLOCK == 1'b0 )
      #675 $display("  %s%s%s%s acc=%x ixr=%x ssp=%x out=%x pc=%x     %x",
	( S == 1'b0 ) ? "M" : "-",
	( V == 1'b0 ) ? "V" : "-",
	( Z == 1'b0 ) ? "Z" : "-",
	( C == 1'b0 ) ? "C" : "-",
	ACC_IR, IXR, SP, OUTR, PC, MEM[PC]);
end

"Execution Trace" と書かれている部分が実行結果をログとして出力する部分 です。命令の実行終了時のイベントを検出するために ICS を必要とします。 もし、最上位階層まで ICS を取り出していない場合は、"test.top.I70.ICS" の様に階層を明示的に記述しておく必要があります。"I70" は KITE プロセッ サの第2階層図面のインスタンス名を表します。皆さんの回路図に合わせて下 さい。

上記の "testfixture.new" を用いてシミュレーションを行うと、シミュレー ション時のログである "simout.tmp" の中に以下のようなログが出力されます。


	中略
  ---- acc=0008 ixr=000 ssp=000 out=0000 pc=001     bc00
  ---- acc=0800 ixr=000 ssp=000 out=0000 pc=002     9100
  ---- acc=0800 ixr=000 ssp=000 out=0000 pc=003     f004
	中略
  ---- acc=0037 ixr=7fd ssp=800 out=0037 pc=009     f800
  ---- acc=0037 ixr=7fd ssp=800 out=0037 pc=00a     f009
	中略

KITE シミュレータの出力と比較して見ればわかるように、KITE シミュレータ の出力からアセンブリ記述を省いた書式で出力されていることがわかります。

したがって、KITE シミュレータの出力からアセンブリ記述を省いた部分のファ イルを期待値ファイルとして用意し、また、"simout.tmp" ファイルから期待 値に対応する部分だけをコピーして一つのファイルにしておきます。あとは、 この二つのファイルを比較するだけです。

期待値のファイル名を "testadd.sim"、論理シミュレータのファイル名を "simout.tmp" としたとき、"diff" コマンドの出力は以下のようになります。


[panther]~/work/cadence/4bit[1413]% diff testadd.sim simout.tmp
1d0
<   ---- acc=0000 ixr=000 ssp=000 out=0000 pc=000     c108

ファイルに違う部分がなければ、何もメッセージを出力しません。ここでは出 力していますが、実は論理シミュレータ側の実行ログでは、KITEシミュレータ が出力する1行目のリストはどうしても出力できません。その違いが現れてる のです。それ以外には違いが報告されていませんから、設計したプロセッサが 期待値通りの動作をしていることが確認できます。


My mail address is kuga@cms.kyutech.ac.jp .
Last modified on