0

Background

It has been my understanding of the various BlueSpec presentations and docs that two rules can not be run in the same cycle if they both modify the same register.

For example, I've read from "BSV By Example" (Amazon, other),

Similarly, certain hardware resource constraints, such as the fact that a hardware wire can only be driven with one value in each clock, will preclude some pairs of rules from executing together in a clock because they both need that resource. We call this a "rule resource conflict".

Similarly, Arvind @ MIT seems to say that "double-write errors" are not allowed.

Then

Recently I was reading through lesson "8.6 RWires and atomicity" and encountered code similar to the following:

package Tb;
  import FIFO::*;
  // ----------------------------------------------------------------
  // A top-level module connecting the stimulus generator to the DUT
  (* synthesize *)
  module mkTb (Empty);
    FIFO#(int) f <- mkPipelineFIFO; // Instantiate a FIFO (see module def below)
    // ----------------
    // Step 'state' from 1 to 10
    Reg#(int) state <- mkReg (0);
    rule step_state;
      if (state > 9) $finish (0);
      state <= state + 1;
    endrule
    // ----------------
    // Enqueue and dequeue something on every cycle (in every state)
    rule e;
      let x = state * 10;
      f.enq (x);
      $display ("State %0d: Enqueue %0d", state, x);
    endrule
    rule d;
      let y = f.first ();
      f.deq ();
      $display ("State %0d: Dequeue %0d", state, y);
    endrule
    // ----------------
    // Also clear the FIFO in state 2
    rule clear_counter (state == 2);
      f.clear ();
      $display ("State %0d: Clearing", state);
    endrule
  endmodule: mkTb
  // ----------------------------------------------------------------
  // A 1-element "pipeline" FIFO
  (* synthesize *)
  module mkPipelineFIFO (FIFO#(int));
    // STATE ----------------
    // The FIFO
    Reg#(Bool) full <- mkReg (False);
    Reg#(int) data <- mkRegU;
    RWire#(int) rw_enq <- mkRWire; // enq method signal
    PulseWire pw_deq <- mkPulseWire; // deq method signal
    Bool enq_ok = ((! full) || pw_deq);
    Bool deq_ok = full;
    // RULES ----------------
    // This rule does all the work, taking into account that 'enq()' and
    // 'deq()' may be called simultaneously when the FIFO is already full
    rule rule_update_final (isValid(rw_enq.wget) || pw_deq);
      full <= isValid(rw_enq.wget);
      data <= fromMaybe (?, rw_enq.wget);
      $display("rule_update_final");
    endrule
    // INTERFACE ----------------
    method Action enq(v) if (enq_ok);
      rw_enq.wset(v);
    endmethod
    method Action deq() if (deq_ok);
      pw_deq.send ();
    endmethod
    method first() if (full);
      return data;
    endmethod
    method Action clear();
      full <= False;
    endmethod
  endmodule: mkPipelineFIFO
endpackage: Tb

Running this code results in:

State 0: Enqueue 0
rule_update_final
State 1: Dequeue 0
State 1: Enqueue 10
rule_update_final
State 2: Dequeue 10
State 2: Enqueue 20
State 2: Clearing
rule_update_final
State 3: Dequeue 20
State 3: Enqueue 30
rule_update_final
State 4: Dequeue 30
State 4: Enqueue 40
rule_update_final
State 5: Dequeue 40
State 5: Enqueue 50
rule_update_final
State 6: Dequeue 50
State 6: Enqueue 60
rule_update_final
State 7: Dequeue 60
State 7: Enqueue 70
rule_update_final
State 8: Dequeue 70
State 8: Enqueue 80
rule_update_final
State 9: Dequeue 80
State 9: Enqueue 90
rule_update_final
State 10: Dequeue 90
State 10: Enqueue 100

I believe the following Warning (not Error!) message appears to be relevant:

Warning: "Tb.bsv", line 38, column 10: (G0117)
  Rule `rule_update_final' shadows the effects of `clear' when they execute in
  the same clock cycle. Affected method calls:
    full.write
  To silence this warning, use the `-no-warn-action-shadowing' flag.

Question

How is it possible that two rules (rule_update_final and clear_counter) that modify the same full register are able to run in the same cycle?

4

0 回答 0