ModelSim 用 PicoBlaze ディスアセンブラ のバックアップ差分(No.4)

更新


  • 追加された行はこの色です。
  • 削除された行はこの色です。
[[公開メモ]] ~
[[電気回路/HDL/ModelSim の radix define]]

* ModelSim を用いた PicoBlaze プログラムのデバッグ [#u0c14a4d]

PicoBlaze が実行中のコマンドを、数値ではなくアセンブラで表示する方法を考えてみました。

以下の手順で、こんな風にデバッグできます。

&attachref(picoblaze_debug.png);

注目は instruction の部分です。

* 結構簡単 [#m7a629a1]

やっているのは、kcpsm3 に繋いだ instruction 信号を SystemVerilog で書いた
function でディスアセンブルして、表示用の変数に代入しているだけ。

思った以上に簡単でした。

kcpsm3 と instructions:

 LANG:verilog
     /// **** instructions
     
     wire [9:0] pc ;
     reg [17:0] instruction ;
     reg [17:0] instructions[2**10-1:0];
     always @(posedge clk)
         instruction <= instructions[pc];
     initial
         $readmemh("instructions.mem", instructions, 0, 2**10-1);
 
     /// **** cpu
     
     wire [7:0] addr;
     wire [7:0] idata;
     wire [7:0] odata;
      wire we;
     
     kcpsm3 cpu (
         .clk(clk),
         .reset(rst),
         .interrupt(0),
 //      .interrupt_ack(ack),
         .address(pc),
         .instruction(instruction),
         .port_id(addr),
         .write_strobe(we),
         .out_port(odata),
 //      .read_strobe(re),
         .in_port(idata)
     );

テストベンチ:

 LANG:verilog
     `include "psm_disasm.inc"
     string instruction;
     always @(uut.instruction)
         instruction = psm_disasm(uut.instruction);

* ディスアセンブラ [#l0b8eae6]

インストラクションを渡すと、ディスアセンブルした結果を文字列として返す function です。

アセンブラは xilinx オリジナルの物ではなく、
よりコンパクトな pBlazIDE のものになっています。

読み替えは簡単だと思いますが、
ディスアセンブラの方を直すのもキーワードの置き換えだけなので簡単にできると思います。

psm_disasm.inc:

 LANG:verilog
 localparam opJump  = 5'b11010;
 localparam opCall  = 5'b11000;
 localparam opRet   = 5'b10101;
 
 localparam opLoad  = 5'b00000;
 localparam opAnd   = 5'b00101;
 localparam opOr    = 5'b00110;
 localparam opXor   = 5'b00111;
 localparam opTest  = 5'b01001;
 localparam opAdd   = 5'b01100;
 localparam opAddc  = 5'b01101;
 localparam opSub   = 5'b01110;
 localparam opSubc  = 5'b01111;
 localparam opComp  = 5'b01010;
 localparam opOut   = 5'b10110;
 localparam opStore = 5'b10111;
 localparam opIn    = 5'b00010;
 localparam opFetch = 5'b00011;
 
 localparam opRetIE = 17'b11100000000000001;
 localparam opRetID = 17'b11100000000000000;
 localparam opEInt  = 17'b11110000000000001;
 localparam opDInt  = 17'b11110000000000000;
 
 localparam opShift = 6'b100000;
 
 function string psm_disasm;
     input [17:0] inst;
     reg [4:0] code;
     string result, s;
     begin
         code = inst[17:13];
 
         result = "";
         
 		// 通常コマンド
         if ( code == opLoad ) result = "LOAD";
         if ( code == opAnd  ) result = "AND";
         if ( code == opOr   ) result = "OR";
         if ( code == opXor  ) result = "XOR";
         if ( code == opTest ) result = "TEST";
         if ( code == opAdd  ) result = "ADD";
         if ( code == opAddc ) result = "ADDC";
         if ( code == opSub  ) result = "SUB";
         if ( code == opSubc ) result = "SUBC";
         if ( code == opComp ) result = "COMP";
         if ( code == opOut  ) result = "OUT";
         if ( code == opStore) result = "STORE";
         if ( code == opIn   ) result = "IN";
         if ( code == opFetch) result = "FETCH";
 
 		// 分岐
         if ( code == opJump ) result = "JUMP";
         if ( code == opCall ) result = "CALL";
         result = {result, " "};
         if ( code == opRet  ) result = "RET";
 
 		// 特殊なコマンド
         if ( inst == opRetIE) result = "RETI ENABLE";
         if ( inst == opRetID) result = "RETI DISABLE";
         if ( inst == opEInt)  result = "EINT";
         if ( inst == opDInt)  result = "DINT";
 
 		// シフト&ローテート
         if ( inst[17:12] == opShift && inst[7:4] == 4'b0000 ) begin
             case ( inst[3:0] )
             5'b1110:    result = "SR0 ";
             5'b1111:    result = "SR1 ";
             5'b1010:    result = "SRX ";
             5'b1000:    result = "SRA ";
             5'b1100:    result = "RR ";
             5'b0110:    result = "SL0 ";
             5'b0111:    result = "SL1 ";
             5'b0010:    result = "SLX ";
             5'b0000:    result = "SLA ";
             5'b0100:    result = "RL ";
             endcase
             $sformat(s, "s%X", inst[11:8]);
             result = {result, s};
         end
 
         if (result=="" || result==" ") begin
 			// 未定義命令
             $sformat(s, "INST $%04x", inst);
             result = s;
         end else begin
 			// 分岐の引数
             if( code == opJump ||
                 code == opCall ||
                 code == opRet  ) begin
                 if ( inst[12] != 0 ) begin
                     if (inst[11:10] == 2'b00) result = {result, "Z"};
                     if (inst[11:10] == 2'b01) result = {result, "NZ"};
                     if (inst[11:10] == 2'b10) result = {result, "C"};
                     if (inst[11:10] == 2'b11) result = {result, "NC"};
                     if( code == opJump || code == opCall )
                         result = {result, ", "};
                 end
                 if( code == opJump || code == opCall ) begin
                     $sformat(s, "$%03x", inst[9:0]);
                     result = {result, s};
                 end
             end
 
 			// 通常命令の引数
             if( code == opLoad ||
                 code == opAnd  ||
                 code == opOr   ||
                 code == opXor  ||
                 code == opTest ||
                 code == opAdd  ||
                 code == opAddc ||
                 code == opSub  ||
                 code == opSubc ||
                 code == opComp ||
                 code == opOut  ||
                 code == opStore||
                 code == opIn   ||
                 code == opFetch ) begin
                 $sformat(s, "s%X, ", inst[11:8]);
                 result = {result, s};
                 if ( inst[12] != 0 ) begin
                     $sformat(s, "s%X", inst[7:4]);
                 end else begin
                     $sformat(s, "$%02x", inst[7:0]);
                 end
                 result = {result, s};
             end
         end
 
         psm_disasm = result;
     end
 endfunction

あまりちゃんとテストしていないので、動作がおかしかったら教えて下さい。
あまりちゃんとテストしていません。~
動作がおかしかったら教えて下さい。

* コメント [#r7b96274]

#comment_kcaptcha


Counter: 9018 (from 2010/06/03), today: 1, yesterday: 0