Re: [hatari-devel] Debugger command improvements

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


Hi,

On 05/11/2018 06:01 PM, tin@xxxxxxxxx wrote:
four remarks:

1. DebugCpu_MemWrite does not check the maximum parameter count and might crash with >256 (>128, >64 respectively for w/l) values (if I didn't overlook anything) 2. DebugUI_ParseCommand only allows 64 parameters, so 1. is safe for the time being, but that might change

Right...  I was thinking that I would drop canceling the operation
if any of the values was invalid, and just skipping the invalid
values (with error message).  See attached patch.


3. I don't know if r should always output the temp registers > - I don't
mind it, but esp with lock it might add too much lines for people that don't use them. Could be an optional argument to r like "r full" or sth like that?

They're output only after they've been used.


4. For consistency between writemem/memdump It would be nice to have a m b|w|l like Bugaboo had

Good idea, I'll look into that (probably next week).


	- Eero

Works fine here, very useful.

Eero Tamminen <mailto:oak@xxxxxxxxxxxxxx>
6. Mai 2018 um 23:35
Hi,

Attached patch:
* add word & long write support to memwrite command
* implements temp / fake registers for debugger,
  (which can be used for user calculations)


For example, to accumulate a sum of values at address $ffff00
to fake register t0, and count of these increments in t1:
    r t0 = "t0 + ($ffff00)"
    r t1 = "t1 + 1"

One can then get average for the increments:
    e = t0 / t1

Or with rounding:
    r t0 = "t0 + t1/2"
    e = t0 / t1

Note: One cannot do rounding in single step because calculations
respect operation precedence, and there currently isn't any
support for changing the precedence ('()' is used for indirect
addressing, not precedence).


And to write that average back to the program, to a long
variable represented by symbol zzz:
    memwrite l zzz "t0 / t1"

Any thoughts?


    - Eero

PS. User variables which names user could specific himself
are likely to be nicer, but extra "registers" were much
easier to add to debugger.


Eero Tamminen <mailto:oak@xxxxxxxxxxxxxx>
4. Mai 2018 um 00:18
Hi,

On 05/03/2018 11:11 AM, tin@xxxxxxxxx wrote:
Note that this could be done with the debugger too, and that way
overhead would be zero cycles for the emulated code.
Had thought about that, but my main caveat was that I didn't see a way of having code output a a warning, if certain timing constraints are not met,

If your code has a symbol for address at which point the timing
constraint needs to be checked, and a symbol for a variable that
contains the constraint value, you can have breakpoint using that:
    b pc = _checkpoint && LineCycles > (_constraint) :trace


compute the average etc.

You can have a breakpoint that invokes debugger script
that outputs the value.  You then just extract the values
from saved debugger output and calculate their average with
something like python.

You could also have a counting breakpoint to trigger after
certain number of frames, e.g. 200:
    b pc = _checkpoint :200 :file average.ini

So the divisor is 200, and you can calculate the average
in "average.ini" if your program sums the value to be
averaged somewhere.


To help doing all of that in the debugger, I'm thinking that
I should add few new features to debugger:

* "register" command can assign values also to debugger
  internal "registers".  E.g. t0-t9 ("t" for "temp).

* or support to assigning values to arbitrarily named
  variables with "evaluate" command

* "w" command option to write words (w) and longs (l)
  to memory, in addition to bytes

So that things like this would be possible:
    r t0="(_some_value_addr) + ($200)"
    e sum = sum + (_counter)
    w l _average_addr "sum/200"

(It's a bit annoying that () is reserved for indirect
addressing so one cannot use that for precedence, and
using '"' chracters for indicating expressions to
evaluate might not have been best choice.)


    - Eero

"Never underestimate the Hatari debugger" as the saying goes - so I wouldn't be surprised at all if even that is possible atm with the current debugger implementation.

So the only thing speaking /for/ a new Natfeat here is the ability to compute sth with and react to the results. The debugger approach clearly beats NatFeats in the timing department.

Did I mention that the debugger is really awesome?
Eero Tamminen <mailto:oak@xxxxxxxxxxxxxx>
2. Mai 2018 um 23:48
Hi,



I don't think that in itself is a problem, as long as API doesn't
overlap with the other NF APIs, or other ways of doing the same.


Note that this could be done with the debugger too, and that way
overhead would be zero cycles for the emulated code.

One can just add a symbol to a place in the code where one
wants these values to be output, and them add tracing
breakpoint for that symbol in the debugger:
    b pc = show_values :quiet :lock

Breakpoint ":lock" option shows the info (that has been "locked"
to be show on debugger entry), without actually stopping:
CPU=$fc1572, VBL=413, FrameCycles=160334, HBL=0, LineCycles=78, DSP=$0


If that's not enough, one can use this instead:
    b pc = show_values :quiet :trace :file show-values.ini

And do the desired outputs in "show-values.ini" file, e.g:
    e VBL
    e HBL
    e LineCycles
    e FrameCycles
    e CycleCounter

If additional emulation state info variables are needed,
adding those isn't a problem.

Output of above isn't very concise though. If that's a problem,
I accept proposals on what to do to improve that. :-)


    - Eero



Thorsten Otto <mailto:admin@xxxxxxxxxxx>
2. Mai 2018 um 08:49
On Dienstag, 1. Mai 2018 20:59:34 CEST tin@xxxxxxxxx wrote:
Hi,

here's a proposal for two very handy NF calls I've patched into my
Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a
string on the ST.
There is already a more general version of something like this: DEBUGPRINTF. It takes a printf-like string and a variable number of arguments, just like printf. Drawback: since the natfeats interface requires all parameters to be
longs, you have to be careful that all arguments really fulfill that
requirement. Not a problem when using GCC, but maybe when using compilers like
Pure-C with 16-bit ints. Also, floating point is not supported by that
interface. So i normally take a different approach: provide a wrapper function nf_debugprintf(), that prints to a static string, then outputs that using
NF_STDERR.


NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame,
nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest
program. This makes it very easy to time code parts cycle-exact at
runtime and do a quick check on optimizations as well as the average
time a code part takes between frames. Also it's easier to check where
exactly a code runs (relative to the frame start).
That would be very Hatari specific.

Any objections?
Yes. Please don't  forget that there are other emulators around, and that the NatFeats interface is meant to be a general enhancements for those. So please don't wildly invent NatFeats that won't be documented, especially when they
duplicate already existing functionality.






tin@xxxxxxxxx <mailto:tin@xxxxxxxxx>
1. Mai 2018 um 20:59
Hi,

here's a proposal for two very handy NF calls I've patched into my Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a string on the ST. I often output internal state variables of a running programm using NF_STDERR (e.g. taken frames per render, clock-cycles of specific parts, control variables etc.). This way printing these taking almost no cpu time and the developed programs run-time behaviour isn't changed too much.

NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame, nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest program. This makes it very easy to time code parts cycle-exact at runtime and do a quick check on optimizations as well as the average time a code part takes between frames. Also it's easier to check where exactly a code runs (relative to the frame start).

Any objections?





tin@xxxxxxxxx <mailto:tin@xxxxxxxxx>
3. Mai 2018 um 10:11
Note that this could be done with the debugger too, and that way
overhead would be zero cycles for the emulated code.
Had thought about that, but my main caveat was that I didn't see a way of having code output a a warning, if certain timing constraints are not met, compute the average etc.

"Never underestimate the Hatari debugger" as the saying goes - so I wouldn't be surprised at all if even that is possible atm with the current debugger implementation.

So the only thing speaking /for/ a new Natfeat here is the ability to compute sth with and react to the results. The debugger approach clearly beats NatFeats in the timing department.

Did I mention that the debugger is really awesome?
Eero Tamminen <mailto:oak@xxxxxxxxxxxxxx>
2. Mai 2018 um 23:48
Hi,



I don't think that in itself is a problem, as long as API doesn't
overlap with the other NF APIs, or other ways of doing the same.


Note that this could be done with the debugger too, and that way
overhead would be zero cycles for the emulated code.

One can just add a symbol to a place in the code where one
wants these values to be output, and them add tracing
breakpoint for that symbol in the debugger:
    b pc = show_values :quiet :lock

Breakpoint ":lock" option shows the info (that has been "locked"
to be show on debugger entry), without actually stopping:
CPU=$fc1572, VBL=413, FrameCycles=160334, HBL=0, LineCycles=78, DSP=$0


If that's not enough, one can use this instead:
    b pc = show_values :quiet :trace :file show-values.ini

And do the desired outputs in "show-values.ini" file, e.g:
    e VBL
    e HBL
    e LineCycles
    e FrameCycles
    e CycleCounter

If additional emulation state info variables are needed,
adding those isn't a problem.

Output of above isn't very concise though. If that's a problem,
I accept proposals on what to do to improve that. :-)


    - Eero



Thorsten Otto <mailto:admin@xxxxxxxxxxx>
2. Mai 2018 um 08:49
On Dienstag, 1. Mai 2018 20:59:34 CESTtin@xxxxxxxxx  wrote:
Hi,

here's a proposal for two very handy NF calls I've patched into my
Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a
string on the ST.
There is already a more general version of something like this: DEBUGPRINTF. It takes a printf-like string and a variable number of arguments, just like printf. Drawback: since the natfeats interface requires all parameters to be
longs, you have to be careful that all arguments really fulfill that
requirement. Not a problem when using GCC, but maybe when using compilers like
Pure-C with 16-bit ints. Also, floating point is not supported by that
interface. So i normally take a different approach: provide a wrapper function nf_debugprintf(), that prints to a static string, then outputs that using
NF_STDERR.


NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame,
nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest
program. This makes it very easy to time code parts cycle-exact at
runtime and do a quick check on optimizations as well as the average
time a code part takes between frames. Also it's easier to check where
exactly a code runs (relative to the frame start).
That would be very Hatari specific.

Any objections?
Yes. Please don't  forget that there are other emulators around, and that the NatFeats interface is meant to be a general enhancements for those. So please don't wildly invent NatFeats that won't be documented, especially when they
duplicate already existing functionality.






tin@xxxxxxxxx <mailto:tin@xxxxxxxxx>
1. Mai 2018 um 20:59
Hi,

here's a proposal for two very handy NF calls I've patched into my Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a string on the ST. I often output internal state variables of a running programm using NF_STDERR (e.g. taken frames per render, clock-cycles of specific parts, control variables etc.). This way printing these taking almost no cpu time and the developed programs run-time behaviour isn't changed too much.

NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame, nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest program. This makes it very easy to time code parts cycle-exact at runtime and do a quick check on optimizations as well as the average time a code part takes between frames. Also it's easier to check where exactly a code runs (relative to the frame start).

Any objections?

Thorsten Otto <mailto:admin@xxxxxxxxxxx>
2. Mai 2018 um 08:49
On Dienstag, 1. Mai 2018 20:59:34 CEST tin@xxxxxxxxx wrote:
Hi,

here's a proposal for two very handy NF calls I've patched into my
Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a
string on the ST.
There is already a more general version of something like this: DEBUGPRINTF. It takes a printf-like string and a variable number of arguments, just like printf. Drawback: since the natfeats interface requires all parameters to be
longs, you have to be careful that all arguments really fulfill that
requirement. Not a problem when using GCC, but maybe when using compilers like
Pure-C with 16-bit ints. Also, floating point is not supported by that
interface. So i normally take a different approach: provide a wrapper function
nf_debugprintf(), that prints to a static string, then outputs that using
NF_STDERR.


NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame,
nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest
program. This makes it very easy to time code parts cycle-exact at
runtime and do a quick check on optimizations as well as the average
time a code part takes between frames. Also it's easier to check where
exactly a code runs (relative to the frame start).
That would be very Hatari specific.

Any objections?
Yes. Please don't  forget that there are other emulators around, and that the NatFeats interface is meant to be a general enhancements for those. So please don't wildly invent NatFeats that won't be documented, especially when they
duplicate already existing functionality.






tin@xxxxxxxxx <mailto:tin@xxxxxxxxx>
1. Mai 2018 um 20:59
Hi,

here's a proposal for two very handy NF calls I've patched into my Hatari branch for a while now:

NF_STDERR_NUM: output a number without the need to convert it to a string on the ST. I often output internal state variables of a running programm using NF_STDERR (e.g. taken frames per render, clock-cycles of specific parts, control variables etc.). This way printing these taking almost no cpu time and the developed programs run-time behaviour isn't changed too much.

NF_FRAMEPOSITION: copies frame info (nVBLs, nHBL, nScanlinesPerFrame, nCyclesPerLine and CyclesPerVBL) into a memory area given by the guest program. This makes it very easy to time code parts cycle-exact at runtime and do a quick check on optimizations as well as the average time a code part takes between frames. Also it's easier to check where exactly a code runs (relative to the frame start).

Any objections?


diff -r 60f2c003a3bb src/debug/debugcpu.c
--- a/src/debug/debugcpu.c	Fri May 11 18:29:34 2018 +0300
+++ b/src/debug/debugcpu.c	Sat May 12 01:07:06 2018 +0300
@@ -460,13 +460,8 @@
  */
 static int DebugCpu_MemWrite(int nArgc, char *psArgs[])
 {
-	int i, arg, values;
+	int i, arg, offset, skipped, truncated;
 	Uint32 write_addr, d;
-	union {
-		Uint8  bytes[256];
-		Uint16 words[128];
-		Uint32 longs[64];
-	} store;
 	char mode;
 
 	if (nArgc < 3)
@@ -498,55 +493,41 @@
 	}
 
 	/* get the data */
-	values = 0;
-	for (i = arg; i < nArgc; i++)
+	offset = truncated = skipped = 0;
+	for (i = arg; i < nArgc; i++, offset++)
 	{
 		if (!Eval_Number(psArgs[i], &d))
 		{
-			fprintf(stderr, "Bad value '%s'!\n", psArgs[i]);
-			return DEBUGGER_CMDDONE;
+			fprintf(stderr, "Skipping bad argument '%s' at offset %d!\n", psArgs[i], offset);
+			skipped++;
+			continue;
 		}
 		switch(mode)
 		{
 		case 'b':
 			if (d > 0xff)
 			{
-				fprintf(stderr, "Illegal byte argument: 0x%x!\n", d);
-				return DEBUGGER_CMDDONE;
+				fprintf(stderr, "Truncating too large byte value 0x%x at offset %d!\n", d, offset);
+				truncated++;
 			}
-			store.bytes[values] = (Uint8)d;
+			STMemory_WriteByte(write_addr + 1*offset, (Uint8)d);
 			break;
 		case 'w':
 			if (d > 0xffff)
 			{
-				fprintf(stderr, "Illegal word argument: 0x%x!\n", d);
-				return DEBUGGER_CMDDONE;
+				fprintf(stderr, "Truncating too large word value 0x%x at offset %d!\n", d, offset);
+				truncated++;
 			}
-			store.words[values] = (Uint16)d;
+			STMemory_WriteWord(write_addr + 2*offset, (Uint16)d);
 			break;
 		case 'l':
-			store.longs[values] = d;
-			break;
-		}
-		values++;
-	}
-
-	/* write the data */
-	for (i = 0; i < values; i++)
-	{
-		switch(mode)
-		{
-		case 'b':
-			STMemory_WriteByte(write_addr + i, store.bytes[i]);
-			break;
-		case 'w':
-			STMemory_WriteWord(write_addr + i*2, store.words[i]);
-			break;
-		case 'l':
-			STMemory_WriteLong(write_addr + i*4, store.longs[i]);
+			STMemory_WriteLong(write_addr + 4*offset, d);
 			break;
 		}
 	}
+	if (skipped || truncated)
+		fprintf(stderr, "Skipped %d, wrote %d values, of which %d were truncated.\n",
+			skipped, offset-skipped, truncated);
 	return DEBUGGER_CMDDONE;
 }
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/