Learning BSV‎ > ‎

Rules

Definition

Bluespec SystemVerilog does not have always blocks like Verilog does. Instead, rules are used to describe how data is moved from state to state.

Rules are made up of two components:

Rule body 
a set of actions which describe state transitions
Rule conditions 
Boolean expressions which determine if the rule body will be enabled.

A primary feature of rules in Bluespec is that they are atomic, meaning the rules are indivisible and a state transition is described completely by the actions within a rule. Each enabled rule can be considered individually to understand how it maintains or transforms state. The functional correctness of a design can then be determined by looking at each of the rules in isolation, without considering the actions of other rules. The one-rule-at-a-time semantics greatly simplifies the process of determining the functional correctness of a design. The actual behavior in the hardware will execute multiple rules concurrently. The Bluespec compiler ensures the actual behavior is consistent with the logical behavior, thus preserving functional correctness while achieving performance goals.

Atomicity of Rules

What does atomic really mean?

  • The condition is a Boolean expression which is purely combinational and has no side effects; there can be no state updates within a condition.
  • All actions which must be run at the same time should be contained in a single rule.
  • All actions within a rule are simultaneous; a rule has no internal sequencing.
  • A rule either executes to completion or doesn't execute.
  • A rule when fires cannot interfere with actions within the body of any other rule. There cannot be any race conditions between rules.
  • The body of one rule does not feed into the condition of another rule.
  • The body of one rule does not feed into the body of another rule.
  • To understand the functionality of a rule, you only have to consider that rule alone. All state transitions and actions are contained within the single rule. The entire rule will execute in a given step, if the rule is enabled.
  • Bluespec will automatically generate control logic necessary to guarantee atomicity of rules.

Building Rules

When writing rules, the above concepts must be considered. Multiple actions may have to be combined into a single rule, or actions split into separate rules, to achieve the desired functional correctness.

There are times when two or more actions will conflict. One way to handle conflicts is to put the actions in different rules, and make sure the rule conditions preclude the rules from being enabled at the same time.

A rule body can contain multiple actions. Any actions which should be executed in the same clock cycle should be put in a single rule. There is no sequencing within a rule body - all actions happen in parallel. This is a difference from many programming languages, where a sequence of statements are processed sequentially. You cannot put conflicting actions in the body of a rule. If you try to put conflicting actions in the same rule, the compiler will flag it as an error. If you put them in separate rules, the scheduler will add control logic to prevent both rules from firing in the same cycle.

   rule example1;
x <= y + 1;
x <= y + 2;
endrule: example1

This rule is not allowed, because the register x cannot be written to different values at the same time. This rule could be broken into two separate rules. Either the conditions are written so they are never enabled at the same time, or the the scheduler will add control logic to ensure that they are never executed in the same clock cycle.

One way to determine whether or not actions conflict is to ask whether changing the order of execution would change the result. Given the following actions:

         x <= y + 1;
y <= y + 2;

Remember, reads are performed before writes in the clock cycle. Since y is read at the beginning of the clock cycle, it doesn't matter which line is executed first. These two actions could be put in the same rule if they should be executed together, or in separate rules. In either case, they could be executed in the same clock cycle.

In the following example, the order of execution will determine the result.

         x <= y + 1;
y <= x + 2;

In this case, the actions can not be put in the same rule. If put into different rules, the rules would conflict and scheduling logic would be added to prevent them from firing in the same clock cycle (unless the conditions were written to prevent it).

Another type of conflict is a resource conflict, as seen in the following example:

      fifo.enq(23);
fifo.enq(34);

In this case, there is only one enq<tt> port, but both actions are trying to access it. These actions could not be put into the same rule.

Because the actions in a rule are simultaneous, as opposed to sequential, you can swap register values within the body of a single rule.

   rule swapxy;
x <= y;
y <= x;
endrule:swapxy


Advanced Rules

For more detail on how rules really work, and scheduling of rules see Rules Of Rules

Comments