When a rule contains an if statement, the compiler has the
option either of splitting the rule into two mutually exclusive rules,
or leaving it as one rule for scheduling but using MUXes in the
production of the action. Rule splitting can sometimes be desirable
because the two split rules are scheduled independently, so
non-conflicting branches of otherwise conflicting rules can be
scheduled concurrently. Splitting also allows the split fragments to
appear in different positions in the logical execution order, providing
effect of condition dependent scheduling.
Splitting is turned off by default for two reasons:
- When a rule contains many if statements, it can lead to an exponential explosion in the number of rules. A rule with 15 if statements might split into 215
rules, depending on how independent the statements (and their branch
conditions) are. An explosion in the number of rules can dramatically
slow down (and cause other problems) for later compiler phases,
- Splitting propagates the branch condition of each if
to the predicates of the split rules. Resources required to compute
rule predicates are reserved on every cycle. If a branch condition
requires a scarce resource, this can starve other parts of the design
that want to use that resource.
- The split and nosplit attributes are used to override the default and/or compiler flag (-split-if).
- The split attribute splits the statement immediately following the attribute statement, which must be an Action statement.
- A split immediately preceeding a binding (e.g. let) statement is not valid.
- If there are nested if statements within the split statement, it will continue splitting recursively through the branches of the statement.
- The nosplit attribute can be used to disable rule splitting within nested if statements.
module mkConditional#(Bit#(2) sel) ();
Reg#(Bit#(4)) a <- mkReg(0);
Reg#(Bool) done <- mkReg(False);
rule finish ;
if (a == 3)
done <= True;
if (a == 0)
done <= False;
a <= 1;
done <= False;
To enable rule splitting for an entire design, use the compiler flag -split-if
at compile time. You can enable rule splitting for an entire design with the -split-if flag and then disable the effect for specific rules, by specifying the nosplit attribute before the rules you do not want to split.