I think trapping accesses to a CSR is a luxury.
Many effective debuggers don’t trap data accesses at all.
We all expect counters and timers to run the same with and without debugging.
One of the most unpleasant weeks I’ve ever spent was trying to find
a 3% timing error caused by a debugger that periodically halted timer clocks.
And, I never did find the issue myself; Fortunately I had access to the designer.
The designer made a lucky guess about what the problem was,
told me about the issue, and where it was documented.
--
You received this message because you are subscribed to the Google Groups "RISC-V Debug Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to
debug+un...@groups.riscv.org.
To post to this group, send email to de...@groups.riscv.org.
Visit this group at
https://groups.google.com/a/groups.riscv.org/group/debug/.
To view this discussion on the web visit
https://groups.google.com/a/groups.riscv.org/d/msgid/debug/4aae2efc-a1bb-4156-8da5-81d297b3c634%40groups.riscv.org.
A few questions/comments
The bit and register assignments inherently limit the number of maskable interrupts. I would rather see the interrupt enable/cause bits for maskableinterrupts in separate registers, with space left in the register addressing for more interrupts. I am working on a RISC-V design that allows up to 128maskable interrupts.
Is there any utility to allowing a breakpoint to be set on a particular CSR access?
Should there be control bits (perhaps in DBG_CTRL) to control disabling counters and timers?
Monte
On Tuesday, May 17, 2016 at 1:14:42 AM UTC-7, Richard Herveille wrote:Hi,
I’ve attached the (draft) specifications for a lightweight Debug Unit.It supports hardware break/watchpoints, single stepping, and simple branch tracing.It’s easy to implement and small. It’s been tested and is working together with the adv_dbg_sys with support for GDB and Eclipse.
Comments and suggestions are welcomed,Richard
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/debug/0104B590-8A65-4C94-B71D-5DAC93D9C27B%40roalogic.com.
1. For flexible integration it may be better to have the combinational
path from dbg_bp to dbg_stall configurable inside the debug unit.
Essentially this would be another register bit in DBG_CTRL:
bit 2: sob (stall-on-breakpoint). When asserted the debug unit stalls
the core. Reset value is 0.
Justification: It adds a register bit, an AND and an OR to the logic
(cpu_stall = dbg_stall | (sob & bp), but it can be used as a simple bus
interface without extra logic needed to drive the stall pin.
This would be like a master break-point enable.
The same can be achieved by enabling/disabling the individual breakpoints.
When I look at the commands GDB’s RSP generates, then this bit would never be used.
Yes, but I am thinking about a more generic use, such as really
attaching the MMIO interface to a bus. Then any extra wrapper logic may
already be obsolete by providing access to this functionality in the
register map.
2. Along the same lines it may be useful to add another bit to stall via
the bus interface in DBG_CTRL:
bit 3: stall. When asserted stalls the core. Reset value is 0.
Justification: It adds a register bit and another OR to the logic
(cpu_stall = dbg_stall | (sob & bp) | stall). It allows for asynchronous
stalls via the bus interface.
Currently this is implemented outside the debug unit.
The adv_dbg_sys (or any other debug controller) will have it’s own control registers.
GDB uses this, for example, to initially stall the CPU.
I agree, but adding it wouldn't harm this solution, right?
3. A signal named dbg_stall_ack may be useful for trace (cross-trigger)
logic. It is asserted by the core once the stall effectively took place.
This is already implemented, though slightly different.
dbg_bp_o is asserted when a breakpoint hit. As a result dbg_stall_i must be asserted immediately.
Yes, but in case of an asynchronous stall by the debug controller it can
take several cycles to actually halt the pipeline, right?
4. Why do NOPs not emit a single step trace? They are pretty rare and
its actual information getting lost.
True, but many CPUs insert bubbles (NOPs) in the pipe during a stall or to clean the pipe (after a stall).
Hitting on NOPs may cause false triggers.
I see. From an implementation standpoint, would it be too complicated to
mark bubbles in the pipeline? The bubbles probably don't have a valid PC
anyways. I was told by a debugging tool guy, that missing out a taken
instruction can lead to many issues.
5. Is NPC and PC still used for RISC-V? If so can you clarify the
meaning and what the state of the CPU must be, e.g., if the PC of the
breakpoint must not have fully executed (which can be troublesome for
memory watchpoints, but is better for debug).
I currently implemented both. Not sure how useful both are though …
Okay I see. How is it in your implementation, is the instruction at PC
already executed or not started? I think it should be defined. NPC
probably only makes sense if PC was executed, right?
Hi Richard, I discussed the spec with an expert and got some feedback: 1. For flexible integration it may be better to have the combinational path from dbg_bp to dbg_stall configurable inside the debug unit. Essentially this would be another register bit in DBG_CTRL: bit 2: sob (stall-on-breakpoint). When asserted the debug unit stalls the core. Reset value is 0. Justification: It adds a register bit, an AND and an OR to the logic (cpu_stall = dbg_stall | (sob & bp), but it can be used as a simple bus interface without extra logic needed to drive the stall pin.
Hi Stefan / Richard,Hi Richard, I discussed the spec with an expert and got some feedback: 1. For flexible integration it may be better to have the combinational path from dbg_bp to dbg_stall configurable inside the debug unit. Essentially this would be another register bit in DBG_CTRL: bit 2: sob (stall-on-breakpoint). When asserted the debug unit stalls the core. Reset value is 0. Justification: It adds a register bit, an AND and an OR to the logic (cpu_stall = dbg_stall | (sob & bp), but it can be used as a simple bus interface without extra logic needed to drive the stall pin.
Thanks for the work on the debug specification,
I am also working on a debug-interface for our Risc-V implementation, and I like the idea of making the debug unit a pure MMIO interface.
I see no point in having an extra 'debug controller' outside the core that only conditionally copies the dbg_bp to the dbg_stall signal (apart from translating JTAG commands to register writes, which is a more general problem)
However, when using just the proposed 'stall-on-breakpoint' bit, I wonder how would one be able to continue once the breakpoint is reached? One could set it to 'sob' to 0 and then back to 1, but in that case one would miss the next breakpoint, especially when single-stepping.
In general, it is unclear to me from the specifications how the dbg_bp signal works and how one would execute the Single-Step trace, even using the originally proposed interface. If dbg_stall is de-asserted, a few things can happen during the next clock cycle, depending on the implementation:
1) dbg_bp was already low since it is only asserted for one clock cycle anyway (?)
2) dbg_bp goes low because the next instruction is being fetched but it is not yet executed
3) dbg_bp is still high because the core is still idle (maybe a certain implementation is slow to 'resume')
4) dbg_bp is again high because the next Single-Step breakpoint is reached
Obviously 3 and 4 cannot be distinguished, but in 3), the debug unit shall not stall the core while in 4) it shall be stalled.
To avoid the ambiguity, you could specify that dbg_bp shall always go low the next clock cycle if dbg_stall is made low low (unless a new breakpoint is reached), or specify that dbg_bp is only high for one clock cycle anyway.
Can you elaborate on what the intended behavior of dbg_bp is?
In either case, I propose to add another bit to the register as follows:
bit 3: cont (Continue after breakpoint). When a '1' is written and the core
is stalled using the 'sob' bit, the debug unit allows the core to continue
until next breakpoint is reached. This bit will be cleared automatically in
the next clock cycle.
I look forward to your comments,
With kind regards,
Tom van Leeuwen System DesignerA Burgemeester Jamessingel 1, P.O. Box 2013, 2800 BD Gouda, The Netherlands | W technolution.comThis e-mail is intended exclusively for the addressee(s), and may not be passed on to, or made available for use by any person other than the addressee(s). Technolution B.V. rules out any and every liability resulting from any electronic transmission.
--
You received this message because you are subscribed to the Google Groups "RISC-V Debug Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to debug+un...@groups.riscv.org.
To post to this group, send email to de...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/debug/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/debug/57768456.3000902%40technolution.eu.
Hi Tom,(...)
There is no need for the Continue-after-breakpoint bit.The dbg_bp signal is a strobe signal; it is asserted for only 1 clock cycle. In my implementation that means taking into account memory and pipeline stalls.When dbg_bp is asserted it causes dbg_stall to be asserted in the same cycle (so combinatorial). That causes the CPU to stall; depending on the implementation anything from ID and above. Any instruction in the execute phase should complete.When the JTAG (or other interface) controller set dbg_stall to ‘0’, the CPU continues. Causing the current instruction to enter the execute phase and new instructions to be loaded. For single-stepping this means the CPU stalls immediately again, but since the previous instruction entered the execute phase, it will complete.
On 04 Jul 2016, at 10:02, Tom van Leeuwen <tom.van...@technolution.eu> wrote:Hi Richard,
On 03-07-16 09:05, Richard Herveille wrote:
Hi Tom,(...)
There is no need for the Continue-after-breakpoint bit.The dbg_bp signal is a strobe signal; it is asserted for only 1 clock cycle. In my implementation that means taking into account memory and pipeline stalls.When dbg_bp is asserted it causes dbg_stall to be asserted in the same cycle (so combinatorial). That causes the CPU to stall; depending on the implementation anything from ID and above. Any instruction in the execute phase should complete.When the JTAG (or other interface) controller set dbg_stall to ‘0’, the CPU continues. Causing the current instruction to enter the execute phase and new instructions to be loaded. For single-stepping this means the CPU stalls immediately again, but since the previous instruction entered the execute phase, it will complete.
Thanks for your reply, it is now clear to me how the dbg_bp signal works. Maybe you can clarify in the specifications document that dbg_bp is a strobe signal?
However, I think we are still confusing two different situations in the conversation.
Situation A is with the dbg_bp and dbg_stall signals controlled by adv_dbg_sys, and situation B is using only the register interface.
In case of situation A, we don't need a 'continue' signal since dbg_bp is a strobe signal, and we can simply assert stall as long as we don't want to continue. The original implementation as proposed in v0.1 can do this.
In case of situation B, with the proposed 'stall-on-breakpoint' register bit, I think we do need a way to continue using a register bit, and de-asserting 'stall-on-breakpoint' results in missing the next breakpoint(s). Or am I missing something?
(Optionally we can combine the two register bits, thus when a '1' is written in 'stall-on-breakpoint' when it is already stalled on a breakpoint, it will issue a continue.)
Maybe Stefan can clarify how he intended the 'stall-on-breakpoint' bit to be implemented w.r.t single stepping?
Thanks,
Tom
--
You received this message because you are subscribed to the Google Groups "RISC-V Debug Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to debug+un...@groups.riscv.org.
To post to this group, send email to de...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/debug/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/debug/ea546a0b-b78b-b29c-745a-2f4fc7467dde%40wallentowitz.de.
--
You received this message because you are subscribed to the Google Groups "RISC-V Debug Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to debug+unsubscribe@groups.riscv.org.
To post to this group, send email to de...@groups.riscv.org.
Visit this group at https://groups.google.com/a/groups.riscv.org/group/debug/.
To view this discussion on the web visit https://groups.google.com/a/groups.riscv.org/d/msgid/debug/3812742E-A82F-4FAD-AEEA-08D086B26FD2%40roalogic.com.
Ah yes, it's not in the spec.I will add it as an option. Basically you just write the opcode to a register and tell the Debug Unit to execute it; either by setting a bit in the BP_CTRL register or by executing upon each write to the register, whichever has the preference of the group.
Richard
Sent from my iPad
Hi Richard,
I still don't see how arbitrary instructions will be executed, although that is listed in the comparison document. Did I miss it?
Tim
On Mon, Nov 28, 2016 at 6:54 AM, Richard Herveille <richard.herveille@roalogic.com> wrote:
Hi all,
I finally found some time to update the specifications and add features requested by the community.
Richard
ROA LOGICDesign Services and Silicon Proven IP
Richard HerveilleManaging DirectorPhone +31 (45) 405 5681Cell +31 (6) 5207 2230
--
You received this message because you are subscribed to the Google Groups "RISC-V Debug Group" group.
To unsubscribe from this group and stop receiving emails from it, send an email to debug+un...@groups.riscv.org.