bluespec.com Forum Index bluespec.com
Bluespec Forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Aggressive Conditions (Bug?)

 
Post new topic   Reply to topic    bluespec.com Forum Index -> Designing with BSV's Rules, Interfaces, ...
View previous topic :: View next topic  
Author Message
chiraag



Joined: 06 Aug 2011
Posts: 29

PostPosted: Mon May 16, 2016 2:35 am    Post subject: Aggressive Conditions (Bug?) Reply with quote

I had a strange issue when using aggressive conditions with synthesized modules. I have attached sample code to reproduce the behavior.

Code:

import FIFO::*;

interface GuardConflict;
    method Action writeGuard(Bool d);
    method Action writeTrue(Bool d);
    method Action writeFalse(Bool d);
endinterface

(*synthesize*)
module mkGuardConflict(GuardConflict);
    Reg#(Bool) g <- mkReg(True);
    Reg#(Bool) t <- mkReg(True);

    method Action writeGuard(Bool d) = g._write(d);
    method Action writeTrue(Bool d) if (g) = t._write(d);
    method Action writeFalse(Bool d) if (!g) = t._write(d);
endmodule

interface FIFOWrap;
    method Action put(Bool d);
    method ActionValue#(Bool) get;
    method Bool peek;
endinterface

(*synthesize*)
module mkFIFOWrap(FIFOWrap);
    FIFO#(Bool) f <- mkFIFO;

    method Action put(Bool d) = f.enq(d);
    method ActionValue#(Bool) get;
        f.deq;
        return f.first;
    endmethod
    method Bool peek = f.first;
endmodule

(*synthesize*)
module mkBugTest(Empty);
    FIFOWrap fw <- mkFIFOWrap;
    GuardConflict gc <- mkGuardConflict;
    Reg#(UInt#(2)) count <- mkReg(0);

    rule setup(count == 0);
        fw.put(True);
        count <= count + 1;
    endrule

    rule fires_correctly(count == 1);
        let d <- fw.get;
        if(fw.peek) begin
           gc.writeTrue(True);
        end else begin
           gc.writeFalse(False);
        end
        count <= count + 1;
    endrule

    /*
    rule never_fires(count == 1);
        let d <- fw.get;
        if(d) begin
           gc.writeTrue(True);
        end else begin
           gc.writeFalse(False);
        end
        count <= count + 1;
    endrule
    */

    rule fin(count == 2);
        $display("Fin");
        $finish;
    endrule
endmodule


The behavior of this snippet changes based on whether the never_fires or fires_correctly is used. I expected the correctly fires behavior to be the default. This can be verified with the corresponding CAN_FIRE assignment in the generated verilog.

Code:

assign CAN_FIRE_RL_fires_correctly = fw$RDY_peek && fw_RDY_get_AND_IF_fw_peek_THEN_gc_RDY_writeTru_ETC___d12 && count == 2'd1 ;
assign fw_RDY_get_AND_IF_fw_peek_THEN_gc_RDY_writeTru_ETC___d12 = fw$RDY_get && (fw$peek ? gc$RDY_writeTrue : gc$RDY_writeFalse) ;

assign CAN_FIRE_RL_never_fires = fw$RDY_get && gc$RDY_writeTrue && gc$RDY_writeFalse && count == 2'd1 ;


Are the different behaviors intended?
Back to top
View user's profile Send private message
quark
Site Admin


Joined: 02 Nov 2007
Posts: 500

PostPosted: Tue May 17, 2016 2:46 pm    Post subject: Re: Aggressive Conditions (Bug?) Reply with quote

This behavior is expected.

The value of an ActionValue method, at a synthesis boundary, cannot be used in the predicate of a rule. The value of an ActionValue method is not available until the method has been called (the enable has been asserted), by definition. The predicate of a rule must be computed before its actions can be enabled, therefore it would create a causal loop to put an ActionValue value in the predicate.

When you specify aggressive implicit conditions, you're requesting that conditions inside the rule be lifted into the predicate. For example, with this rule:
Code:
rule r (c1);
  if (c2)
     f.enq(v);
endrule
Here, the conservative condition would be:
Code:
c1 && f.notFull
While the aggressive condition would be:
Code:
c1 && (c2 ? f.notFull : True)

This transformation is only performed if the expression "c2" is allowed to be lifted to the rule's predicate. If "c2" contains the value of an ActionValue method (at a synthesis boundary), then the condition will not be lifted, and the conservative transformation is used.

(In additional to ActionValue methods at synthesis boundaries, the value of an ActionValue system task can also not be lifted to the predicate.)

In your example, the return value of the ActionValue method does not happen to depend on its enable. But that implementation detail is not exposed outside of the module, so the parent module's scheduler has to assume that it could depend. Since it doesn't depend, you are able to write a separate "peek" method, which does not have a dependency on the enable of the action, and so BSC is able to lift it to the rule predicate with creating a causal loop. You should write your methods like that (with a separate "first" or "peek" method) if that's the meaning that you want. (Note that the GetPut library defines GetS and PutS interfaces, which are variations that split the protocol. Other interfaces are possible, and you can write your own.)
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    bluespec.com Forum Index -> Designing with BSV's Rules, Interfaces, ... All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You can attach files in this forum
You can download files in this forum
bluespec.com topic RSS feed 


Powered by phpBB © 2001, 2005 phpBB Group
Protected by Anti-Spam ACP