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

AR: Define mcontrol* triggers and multiple accesses #883

Merged
merged 1 commit into from
Oct 4, 2023

Conversation

timsifive
Copy link
Contributor

mcontrol: Behavior is undefined because it's deprecated.

mcontrol6: If a trigger reports hit=before then some memory accesses may have been performed. If it reports immediately after, then all accesses have already been performed.

@@ -378,6 +378,9 @@
though the load will not update its destination register. Debuggers
should consider this when setting such breakpoints on, for example,
memory-mapped I/O addresses.

It is undefined what should happen when the instruction in question
Copy link

Choose a reason for hiding this comment

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

Saying that the behavior is "undefined" means that the possibilities are architecturally unbounded. Any behavior would be allowed - which is both undesirable and useless to some debugging code with such instructions.

Conversely, I would expect people that care about the Zc* instructions would (rightly) object to freeze (let alone ratification) of Debug 1.0 since it would be unusuable on embedded software that makes use of these instructions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

What is the right term here? Unspecified?

mcontrol triggers are already deprecated, but debuggers should know about them so they're in the spec. New hardware implementations should implement mcontrol6 instead, where the behavior is specified. Is that OK, or should I invent something for people insisting on mcontrol triggers with Zc*?

before. This might mean that when the instruction is executed again
it will perform some of the same stores again (e.g. \tt{cbo.zero}),
or the instruction might have a mechanism that avoids duplicating the
stores (e.g. vector stores).
Copy link

Choose a reason for hiding this comment

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

The "vector store" reference leaves the crucial piece of information a mystery to the reader unless they are intimately familiar with RVV. The parenthetical should say:

(e.g. vector stores and the vstart mechanism).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done. Thanks.

Comment on lines 382 to 383
It is \unspecified what should happen when the instruction in question
performs multiple memory accesses.
Copy link
Collaborator

Choose a reason for hiding this comment

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

What should happen is only unspecified with respect to the memory accesses, not with respect to anything else.

Suggested change
It is \unspecified what should happen when the instruction in question
performs multiple memory accesses.
If an instruction matches this trigger and the instruction performs
multiple memory accesses, it is \unspecified which memory accesses
have completed before the trigger fires.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Much better. Thanks.

xml/hwbp_registers.xml Show resolved Hide resolved
before. This might mean that when the instruction is executed again
it will perform some of the same stores again (e.g. \tt{cbo.zero}),
or the instruction might have a mechanism that avoids duplicating the
stores (e.g. vector stores and the vstart mechanism).
Copy link

Choose a reason for hiding this comment

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

This focuses on stores, but what about register results of an instruction that performs multiple memory accesses?

Must any and all register results be performed only if the instruction completes, i.e. before timing disallows any register modifications (that might, for example, prevent restartability of the instruction aupon return from the debug handler), and after timing of course requires all such modifications to have been performed.

And what about loads? Are some allowed, like stores, to have been performed under before timing? And what if some of those loads are to non-idempotent memory?

Lastly, cbo.zero is not the best of example since it architecturally performs a single block-size memory write. (An implementation can choose to implement that as a series of smaller stores of some size, but the expected common implementation would be one memory write.)

It seems like this paragraph needs to cover read acesses, write accesses, and register writes. Whether the statement is common to all three, or is a separate statement for register writes and for memory accesses, or maybe different for all three, all three need to be covered explicitly in some way so that peopel know what are the bounds on allowed and disallowed behavior for before triggers and for after triggers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The first sentence is the important one. "If an instruction partially executed, the reported timing is still before." The rest is just example. I'll tweak the language to allow for more implementations. Do you have a suggestion for an instruction that performs multiple operations but that doesn't have a restart mechanism? I can't think of any.

Copy link

Choose a reason for hiding this comment

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

There's no obvious perfect statement one coudl make. But one needs to inform users what is and isn't possible. Obviously users prefer a more useful statement that will allow most instructions to be restartable.

For example (and I'm not trying to say that this is what should be specified - the TG needs to consider the pros and cons of whatever it would choose to specify), one could say that some of the memory accesses (loads and stores) may have been performed but no registers will have been modified. And one should also note that while most instructions will still always be restartable, some may not be (and accesses to non-idempotent memory may be repeated).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've rewritten almost all of the mcontrol6 before timing. Can you see if this is more clear?

@timsifive timsifive force-pushed the multi_access branch 2 times, most recently from 3183a7e to c606bfb Compare September 26, 2023 18:26
retired, but after all preceding instructions are retired.
The trigger fired before the instruction that matched it was
retired, but after all preceding instructions are retired. This
explicitly allows for instructions partially executing.
Copy link

Choose a reason for hiding this comment

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

"for instructions to be partially executed."

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done.

destination register.
An instruction that caused a trigger to fire might be executed
partially. In that case not all memory accesses may have been
performed, and some registers may not have been updated. Executing
Copy link

Choose a reason for hiding this comment

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

Is this trying to say that ALL registers will not have been updated, or that some registers may have been updated?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm trying to say that anything partial is OK, from 0% to 100%. E.g. if we had an instruction that pops 3 registers from the stack, any of those 3 registers (or none of them) may contain the new value. The important thing for the debugger is that nothing breaks if we now resume off that instruction by letting it execute again. (Can't account for non-idempotent memory, however.)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@gfavor Is this OK, or would you like to see the language tweaked more?

mcontrol: Behavior is undefined because it's deprecated.

mcontrol6: If a trigger reports hit=before then some memory accesses may
have been performed. If it reports immediately after, then all accesses
have already been performed.
Copy link
Collaborator

@pdonahue-ventana pdonahue-ventana left a comment

Choose a reason for hiding this comment

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

Technically, nobody can guarantee that executing an instruction the second time is equivalent to executing it the first time because some other hart (or DMA or whatever) could have modified memory in between. But I think that the spirit is clear and it would just add unnecessary confusion to add any additional verbiage about other harts. So this is fine.

@timsifive timsifive merged commit 9ddcbcb into master Oct 4, 2023
1 check passed
@timsifive timsifive deleted the multi_access branch October 4, 2023 16:29
timsifive added a commit that referenced this pull request Oct 4, 2023
Incorporate more feedback from AR. Moved this into a separate Sdtrig
section, since the discussion could also apply to instructions that
cause triggers beside memory access ones. (E.g. an instruction that
combines memory accesses with a trigger, and itrigger.)

Follow up to #883.
timsifive added a commit that referenced this pull request Oct 4, 2023
Incorporate more feedback from AR. Moved this into a separate Sdtrig
section, since the discussion could also apply to instructions that
cause triggers beside memory access ones. (E.g. an instruction that
combines memory accesses with a trigger, and itrigger.)

Follow up to #883.
@gfavor
Copy link

gfavor commented Oct 5, 2023

I assume Tim has now noticed that this PR probably wants to be reverted or replaced with a PR reflecting Oct 3rd AR feedback (email titled "Debug 1.0 AR next steps") about how best to more generally specify this issue.

@timsifive
Copy link
Contributor Author

Yes. #899 is the update to this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants