Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LLHD] Support drives with delta delay in mem2reg #8279

Merged
merged 1 commit into from
Feb 27, 2025

Conversation

fabianschuiki
Copy link
Contributor

Extend the LLHD Mem2Reg pass to also support non-blocking drives. These have a delay value of 1d instead of the 1e of blocking drives. To do so, add an additional bit to the slots associated with reaching definitions, indicating whether the definition for a slot is blocking/immediate or applies only after a delta delay. Blocking drives can then appropriately kill earlier non-blocking drives, and probes can only consider earlier blocking drives when resolving their value.

Copy link
Member

@maerhart maerhart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not very familiar with the semantics of blocking and delayed drives to the same signal, but otherwise LGTM.

@@ -884,10 +919,13 @@ void Promoter::propagateForward(LatticeNode *node, bool optimisticMerges) {
return;
}

// Drives propagate the driven value as a reaching def.
// Drives propagate the driven value as a reaching def. Blocking drives kill
// earlier non-blocking drives.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you elaborate a bit why that is? I'm not very familiar with the Verilog semantics related to that. Is there a specific paragraph in the standard to look at? One could think that the signal has the value of the blocking drive for the duration of 1d and is then overwritten by the value of the delayed drive.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Blocking drives kill earlier non-blocking drives." is wrong statement due to that fact from 10.4.2 SystemVerilog LRM section:

At the end of the time step means that the nonblocking assignments are the last assignments executed in a time step

Blocking drives values are need only for other blocking assignments in procedural flow and also for rvalues in right-hand sides of nonblocking assignemnt

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me tweak this comment a bit. Consider the following SV:

a <= #10ns 42;  // A
a <= 43;        // B
a = 44;         // C

Since writes with less delay override/kill already scheduled writes with longer delay, (A) schedules a change to 42 after 10ns, but then (B) schedules a change to 43 after a delta delay / at the end of the time step, which overrides the earlier (A), but then (C) applies an immediate change to 44, which overrides the earlier (B). To preserve this, it's important that blocking drives kill the reaching definitions of non-blocking drives to not schedule a later signal change.

// CHECK-NEXT: llhd.halt
llhd.halt
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If there are two delayed drives to the same signal some conflict resolution has to happen AFAIK, but in mem2reg we probably just want to leave it as is and not merge the drives. Can you add a test to check what mem2reg does in such a situation?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I remember correctly, this only happens on wires, where you cannot have procedural drives assign to them. If you have two drives to the same variable, the latter one should win and override the earlier one. Let me go check on the details

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

10.4.2 in IEEE the 1800-2007 standard indicates that driving the same variable from different processes will see one of the assignments win but no conflict resolution occurs:

Screen Shot 2025-02-27 at 08 53 23

In the same section, there's an example showing how delayed drives with a shorter delay override already scheduled delayed drives with a longer delay:

Screen Shot 2025-02-27 at 08 54 41

Extend the LLHD Mem2Reg pass to also support non-blocking drives. These
have a delay value of `1d` instead of the `1e` of blocking drives. To do
so, add an additional bit to the slots associated with reaching
definitions, indicating whether the definition for a slot is
blocking/immediate or applies only after a delta delay. Blocking drives
can then appropriately kill earlier non-blocking drives, and probes can
only consider earlier blocking drives when resolving their value.
@fabianschuiki fabianschuiki force-pushed the fschuiki/mem2reg-delayed-drives branch from 608535d to 1bb60b4 Compare February 27, 2025 17:52
@fabianschuiki fabianschuiki merged commit d897eea into main Feb 27, 2025
5 checks passed
@fabianschuiki fabianschuiki deleted the fschuiki/mem2reg-delayed-drives branch February 27, 2025 22:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants