27 |
RISC-Vプロセッサの設計 (25) |
次にパイプラインウェイトをテストします。具体的にはテストベンチにのwait信号を設け、途中でアサートします。
Tb.bsv
Tbにはその記述を追加します。
import StmtFSM::*;
import Processor::*;
(* synthesize *)
module mkTb();
Empty proc <- mkProcessor();
Stmt main = seq
proc.if_wait_load(False);
delay(10);
proc.if_wait_load(True);
delay(1); // ここでif_waitを2サイクルアサート
proc.if_wait_load(False);
delay(10);
$finish;
endseq;
mkAutoFSM(main);
endmodule
if_wait信号を1サイクルアサートをさせようとしてdelay(1);を挟みましたが、その前のload(True);により1サイクルアサートされるようです。そのため、1サイクルアサートさせるには以下の表のように、何も挟まないかdelay(0);と記述するようです。
BSV構文 | waitアサート期間 |
---|---|
proc.if_wait_load(True); proc.if_wait_load(False); |
1サイクル |
proc.if_wait_load(True); delay(0); proc.if_wait_load(False); |
1サイクル |
proc.if_wait_load(True); repeat(0) noAction; proc.if_wait_load(False); |
1サイクル |
proc.if_wait_load(True); noAction; proc.if_wait_load(False); |
2サイクル |
proc.if_wait_load(True); delay(1); proc.if_wait_load(False); |
2サイクル |
proc.if_wait_load(True); repeat(1) noAction; proc.if_wait_load(False); |
2サイクル |
Processor.bsv
PCパイプラインにインタフェースを設け、そこにif_wait入力を設けます。
Import FIFO::*;
interface Processor_ifc;
(* prefix="" *)
method Action if_wait_load(Bool in_if_wait);
endinterface
(* synthesize, always_ready *)
module mkProcessor(Processor_ifc);
if_waitはレジスタで宣言します。
Reg#(Bool) if_wait <- mkReg(False);
<IF>において、waitが来たら上位のdeqと下位のenqを停止します。
// <IF>
rule if_stage;
let pc_if = ifs.first;
if (!if_wait) begin
ifs.deq;
$display (" pc_if = %04h", pc_if);
ids.enq (pc_if);
end
endrule
コンパイルと起動コマンドは以下のとおりです。gtkwaveはここ。
$ bsc -u -sim Tb.bsv; bsc -sim -e mkTb -o mkTb.exe;
$ ./mkTb.exe -V;
$ gtkwave -A dump.vcd
以下はbsimシミュレーション波形です。if_waitを1サイクルアサートしようとして、delay(1);とすると2サイクルアサートされるので、1サイクルアサートするにはdelay(0);とするようです。
if_waitにより一旦はinvalidになりますが、そのデータを転送するとvalidになってしまうようです。
以下はverilogシミュレーション波形です。if_waitによりinvalidになることはありません。