Posts Tagged with "BSV"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.
posted by sakurai on October 11, 2023 #676

モジュール内でデータを受け取るにはRegisterを設置する方法とWireを設置する方法があります。パイプラインプロセッサのwait信号を例にして、2つの違いを見てみます。

まず、Test-benchにおいてRegisterを設置するのは共通とします。例えば、

Tb.bsv:

import StmtFSM::*;
import Processor::*;

(* synthesize *)
module mkTb();
    Processor_ifc proc <- mkProcessor();
    Reg#(Bool) if_wait <- mkReg(True);
    Reg#(Bool) mc_wait <- mkReg(True);
    Reg#(Bool) ex_wait <- mkReg(True);
    Reg#(Bool) ma_wait <- mkReg(True);

    rule load_wait_values;
        proc.if_wait_load(if_wait);
        proc.mc_wait_load(mc_wait);
        proc.ex_wait_load(ex_wait);
        proc.ma_wait_load(ma_wait);
    endrule

    Stmt main = seq
        action
            if_wait <= False;
            mc_wait <= False;
            ex_wait <= False;
            ma_wait <= False;
        endaction
        delay(4);
        if_wait <= True;
        delay(0);
        if_wait <= False;
        delay(4);

(中略)

        $finish;
    endseq;
    mkAutoFSM(main);

endmodule

であり、下位のモジュールが、

Processor.bsv:

import FIFO::*;

interface Processor_ifc;
    (* prefix="" *)
    method Action if_wait_load(Bool in_if_wait);
    method Action mc_wait_load(Bool in_mc_wait);
    method Action ex_wait_load(Bool in_ex_wait);
    method Action ma_wait_load(Bool in_ma_wait);
endinterface

(* synthesize, always_ready *)
module mkProcessor(Processor_ifc);

    Reg#(int) pc <- mkReg(0);
    FIFO#(Maybe#(int)) ifs <- mkLFIFO;
    FIFO#(Maybe#(int)) ids <- mkLFIFO;
    FIFO#(Maybe#(int)) exs <- mkLFIFO;
    FIFO#(Maybe#(int)) mas <- mkLFIFO;
    FIFO#(Maybe#(int)) wbs <- mkLFIFO;
    Reg#(Bool) if_wait <- mkReg(False);
    Reg#(Bool) mc_wait <- mkReg(False);
    Reg#(Bool) ex_wait <- mkReg(False);
    Reg#(Bool) ma_wait <- mkReg(False);

    // <PC>
    rule pc_stage;
        if (pc > 100) $finish(0);
        $display("------");
        ifs.enq(tagged Valid pc);
        pc <= pc + 4;
    endrule

    // <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 else begin
            ids.enq (tagged Invalid);
        end
    endrule

    // <ID>
    rule id_stage;
        let pc_id = ids.first;
        if (!mc_wait) begin
            ids.deq;
            $display (" pc_id = %04h", pc_id);
            exs.enq (pc_id);
        end else begin
            exs.enq (tagged Invalid);
        end
    endrule

    // <EX>
    rule ex_stage;
        let pc_ex = exs.first;
        if (!ex_wait) begin
            exs.deq;
            $display (" pc_ex = %04h", pc_ex);
            mas.enq (pc_ex);
        end else begin
            mas.enq (tagged Invalid);
        end
    endrule

    // <MA>
    rule ma_stage;
        let pc_ma = mas.first;
        if (!ma_wait) begin
            mas.deq;
            $display (" pc_ma = %04h", pc_ma);
            wbs.enq (pc_ma);
        end else begin
            wbs.enq (tagged Invalid);
        end
    endrule

    // <WB>
    rule wb_stage;
        let pc_wb = wbs.first;
        wbs.deq;
        $display (" pc_wb = %04h", pc_wb);
    endrule

    method Action if_wait_load(Bool in_if_wait);
        if_wait <= in_if_wait;
    endmethod
    method Action mc_wait_load(Bool in_mc_wait);
        mc_wait <= in_mc_wait;
    endmethod
    method Action ex_wait_load(Bool in_ex_wait);
        ex_wait <= in_ex_wait;
    endmethod
    method Action ma_wait_load(Bool in_ma_wait);
        ma_wait <= in_ma_wait;
    endmethod

endmodule: mkProcessor

この場合は上位がレジスタであり、下位もレジスタであるため、信号の伝播が1サイクル遅れます。

図%%.1
図676.1 ウエイト伝播

左矢前のブログ 次のブログ右矢


ページ: