From 946a32f7cc037bd37886604743993226d2abff1f Mon Sep 17 00:00:00 2001 From: Michael Specht Date: Fri, 16 Feb 2018 15:05:05 +0100 Subject: [PATCH] documentation --- README.md | 115 ++++++++++++++++++++++++++++++++++------ champ.rb | 68 ++++++++++++++++++++++-- doc/example01_1.gif | Bin 0 -> 4274 bytes doc/example01_2.gif | Bin 0 -> 4257 bytes doc/example02_1.gif | Bin 0 -> 4353 bytes doc/example03_1.gif | Bin 0 -> 5889 bytes doc/example03_2.gif | Bin 0 -> 3338 bytes doc/example03_3.gif | Bin 0 -> 5117 bytes examples/example01.s | 13 +++++ examples/example01.yaml | 3 ++ examples/example02.s | 14 +++++ examples/example02.yaml | 3 ++ examples/example03.s | 21 ++++++++ examples/example03.yaml | 3 ++ examples/plot3d.yaml | 13 +++++ plot3d.yaml | 13 ----- 16 files changed, 235 insertions(+), 31 deletions(-) create mode 100644 doc/example01_1.gif create mode 100644 doc/example01_2.gif create mode 100644 doc/example02_1.gif create mode 100644 doc/example03_1.gif create mode 100644 doc/example03_2.gif create mode 100644 doc/example03_3.gif create mode 100644 examples/example01.s create mode 100644 examples/example01.yaml create mode 100644 examples/example02.s create mode 100644 examples/example02.yaml create mode 100644 examples/example03.s create mode 100644 examples/example03.yaml create mode 100644 examples/plot3d.yaml delete mode 100644 plot3d.yaml diff --git a/README.md b/README.md index 0b4da5c..07f9492 100644 --- a/README.md +++ b/README.md @@ -36,20 +36,6 @@ We specified some source files (which will get compiled automatically) and some Furthermore, we can disable subroutines by replacing the first opcode with a RTS (`instant_rts`). This is necessary in some cases because Champ does not emulate hardware and thus can not load data from disk, for example. -### Defining watches - -You can watch registers or variables at certain program counter addresses by inserting a _champ directive_ in a comment after the respective code line in your assembler source code. All champ directives start with an _at sign_ (@). Here's an example: - -``` -LDA #2 ; load 2 into accumulator -ASL ; multiply by two -STA SOMEWHERE ; store result @Au -``` - -With the `@Au` directive, we tell champ to monitor the A register and interpret it as an unsigned 8 bit integer (likewise, `@As` would treat the value as a signed 8 bit integer). - -By default, all champ values get recorded before the operation has been executed. To get the value after the operation, you can write: `@Au(post)`. - ### Running the profiler To start champ, type: @@ -64,6 +50,105 @@ This will run the emulator and write the HTML report to `report.html`. If you do ![Champ Screenshot](doc/screenshot.png?raw=true "Fig. 1 Champ Screenshot") +### Defining watches + +You can watch registers or variables at certain program counter addresses by inserting a _champ directive_ in a comment after the respective code line in your assembler source code. All champ directives start with an _at sign_ (`@`). Here's an example ([example01.yaml](example01.yaml) / [example01.s](example01.s)): + +``` + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 + + JSR TEST + RTS + +TEST LDA #64 ; load 64 into accumulator + ASL ; multiply by two @Au + STA FOO ; store result @Au + RTS +``` + +Running this example results in the following watch graphs: + +![A at PC 0x6006](doc/example01_1.gif?raw=true) +![A at PC 0x6007](doc/example01_2.gif?raw=true) + +Champ generates a graph for every watch. You can see the watched variable plotted against the cycles, and also the PC address, file name, and source line number of the watch as well as the subroutine in which the watch was defined. + +With the `@Au` directive, we tell champ to monitor the A register and interpret it as an unsigned 8 bit integer (likewise, `@As` would treat the value as a signed 8 bit integer). + +By default, all champ values get recorded before the operation has been executed. To get the value after the operation, you can write: `@Au(post)`. Feel free to add as many champ directives as you need in a single line, each starting with a new at sign. + +### Global variables + +In addition to watching individual registers, you can also watch global variables (([example02.yaml](example02.yaml) / [example02.s](example02.s))): + +``` + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 ; @u16 + + JSR TEST + RTS + +TEST LDA #0 + STA FOO + LDA #$40 + STA FOO+1 ; @FOO(post) + RTS +``` + +Here, we declare the type of the global variable in the same place the variable itself is declared, using @u8@, @s8@, @u16@, or @s16@. Later, we can just watch the variable by issuing a champ directive like `@FOO@`. In this example, we use the `(post)` option to see the variable contents after the `STA` operation. + +![FOO at PC 0x600b](doc/example02_1.gif?raw=true) + +Here's another example with some more interesting plots ([example03.yaml](example03.yaml) / [example03.s](example03.s)): + +``` + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 + + JSR TEST + RTS + +TEST LDX #$FF + LDA #1 +LOOP TAY + TXA + EOR #$FF + LSR + LSR + STA FOO + TYA + ADC FOO ; @Au(post) + DEX ; @Xu(post) + BNE LOOP +``` + +This is a small program which lets the accumulator grow quadratically while X decreases linearly: + +![A at PC 0x6012](doc/example03_1.gif?raw=true) +![X at PC 0x6015](doc/example03_2.gif?raw=true) + +### Two-dimensional watches + +We can also watch pairs of variables by separating them with a comma in the champ directive: + +``` + DEX ; @Xu(post) @Au,FOO(post) +``` + +This will plot FOO against X: + +![FOO against A at PC 0x6015](doc/example03_3.gif?raw=true) + ## Did you know? -By the way, there's a full-fledged, incremental, standalone, no-dependencies GIF encoder in `pgif.c` that writes animated GIFs and uses some optimizations to further minimize space. It's stream-friendly and as you feed pixels in via `stdin`, it dutifully writes GIF data to `stdout` until `stdin` gets closed. +By the way, there's a full-fledged, incremental, standalone, no-dependencies GIF encoder in [pgif.c](pgif.c) that writes animated GIFs and uses some optimizations to further minimize space. It's stream-friendly and as you feed pixels in via `stdin`, it dutifully writes GIF data to `stdout` until `stdin` gets closed. diff --git a/champ.rb b/champ.rb index 79448c9..b685a09 100755 --- a/champ.rb +++ b/champ.rb @@ -68,10 +68,18 @@ class Champ exit(1) end end - @config = YAML.load(File.read(args.shift)) + config_path = args.shift + @config = YAML.load(File.read(config_path)) @source_files = [] @config['load'].each_pair do |address, path| - @source_files << {:path => File.absolute_path(path), :address => address} + fixed_path = path.dup + unless fixed_path[0] == '/' + fixed_path = File.absolute_path(File.join(File.dirname(config_path), fixed_path)) + end + @source_files << { + :path => fixed_path, + :address => address + } end @highlight_color = '#fce98d' if @config['highlight'] @@ -363,11 +371,19 @@ class Champ histogram_max = histogram.values.max width = 276 - height = (watch[:components].size == 1) ? 286 : 286 + height = 286 canvas_top = 20 canvas_left = 40 canvas_width = width - 60 canvas_height = height - 70 + canvas_width = 256 + canvas_height = 256 + canvas_top = 10 + canvas_left = 30 + canvas_right = 10 + canvas_bottom = 50 + width = canvas_width + canvas_left + canvas_right + height = canvas_height + canvas_top + canvas_bottom pixels = [0] * width * height histogram.each_pair do |key, value| @@ -460,6 +476,52 @@ class Champ end.join(', ') label = "at #{label}" print_s(pixels, width, height, width / 2 - 3 * label.size, height - 10, label, 63) + + if watch[:components].size == 1 + # this watch is 1D, add X axis labels for cycles + labels = [] + labels << [0.0, '0'] + format_str = '%d' + divisor = 1 + if @max_cycle_count >= 1e6 + format_str = '%1.1fM' + divisor = 1e6 + elsif @max_cycle_count > 1e3 + format_str = '%1.1fk' + divisor = 1e3 + end + +# labels << [1.0, sprintf(format_str, (@max_cycle_count.to_f / divisor)).sub('.0', '')] + + remaining_space = canvas_width - labels.inject(0) { |a, b| a + b.size * 6 } + space_per_label = sprintf(format_str, (@max_cycle_count.to_f / divisor)).sub('.0', '').size * 6 * 2 + max_tween_labels = remaining_space / space_per_label + step = ((@max_cycle_count / max_tween_labels).to_f / divisor).ceil + step = 1 if step == 0 # prevent infinite loop! + x = step + while x < @max_cycle_count / divisor + labels << [x.to_f * divisor / @max_cycle_count, sprintf(format_str, x).sub('.0', '')] + x += step + end + labels.each do |label| + s = label[1] + x = (label[0] * canvas_width).to_i + canvas_left + print_s(pixels, width, height, + (x - s.size * (6 * label[0])).to_i, + canvas_top + canvas_height + 7, s, 63) + (0..(canvas_height + 3)).each do |y| + pixels[(y + canvas_top) * width + x] |= 0x40 + end + end + + (0..1).each do |offset| + component_label = 'cycles' + print_s(pixels, width, height, + (canvas_left + canvas_width * 0.5 - component_label.size * 3 + offset).to_i, + canvas_top + canvas_height + 18, + component_label, 63) + end + end tr = @highlight_color[1, 2].to_i(16) tg = @highlight_color[3, 2].to_i(16) diff --git a/doc/example01_1.gif b/doc/example01_1.gif new file mode 100644 index 0000000000000000000000000000000000000000..1ce4913e48a881ff52fe8611b01320c5227bd32e GIT binary patch literal 4274 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 D`ybiX literal 0 HcmV?d00001 diff --git a/doc/example02_1.gif b/doc/example02_1.gif new file mode 100644 index 0000000000000000000000000000000000000000..03a8dd53e54af7faa65ebdce7de367694eeeba3d GIT binary patch literal 4353 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 literal 0 HcmV?d00001 diff --git a/examples/example01.s b/examples/example01.s new file mode 100644 index 0000000..6e8c1fd --- /dev/null +++ b/examples/example01.s @@ -0,0 +1,13 @@ + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 + + JSR TEST + RTS + +TEST LDA #64 ; load 64 into accumulator + ASL ; multiply by two @Au + STA FOO ; store result @Au + RTS diff --git a/examples/example01.yaml b/examples/example01.yaml new file mode 100644 index 0000000..c061f2e --- /dev/null +++ b/examples/example01.yaml @@ -0,0 +1,3 @@ +load: + 0x6000: example01.s +entry: 0x6000 diff --git a/examples/example02.s b/examples/example02.s new file mode 100644 index 0000000..c6ead78 --- /dev/null +++ b/examples/example02.s @@ -0,0 +1,14 @@ + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 ; @u16 + + JSR TEST + RTS + +TEST LDA #0 + STA FOO + LDA #$40 + STA FOO+1 ; @FOO(post) + RTS diff --git a/examples/example02.yaml b/examples/example02.yaml new file mode 100644 index 0000000..65bf1cc --- /dev/null +++ b/examples/example02.yaml @@ -0,0 +1,3 @@ +load: + 0x6000: example02.s +entry: 0x6000 diff --git a/examples/example03.s b/examples/example03.s new file mode 100644 index 0000000..ba58ff7 --- /dev/null +++ b/examples/example03.s @@ -0,0 +1,21 @@ + DSK test + MX %11 + ORG $6000 + +FOO EQU $8000 ; @u8 + + JSR TEST + RTS + +TEST LDX #$FF + LDA #1 +LOOP TAY + TXA + EOR #$FF + LSR + LSR + STA FOO + TYA + ADC FOO ; @Au(post) + DEX ; @Xu(post) @Au,FOO(post) + BNE LOOP diff --git a/examples/example03.yaml b/examples/example03.yaml new file mode 100644 index 0000000..ee928d2 --- /dev/null +++ b/examples/example03.yaml @@ -0,0 +1,3 @@ +load: + 0x6000: example03.s +entry: 0x6000 diff --git a/examples/plot3d.yaml b/examples/plot3d.yaml new file mode 100644 index 0000000..d0134d9 --- /dev/null +++ b/examples/plot3d.yaml @@ -0,0 +1,13 @@ +load: + 0x6000: ../plot3d/plot3d242.s + 0x1200: ../plot3d/multtab.s + 0x8400: ../plot3d/ldrwtab.s + 0x8900: ../plot3d/SINETABLE + 0x8b00: ../plot3d/object2.s + 0x9000: ../plot3d/object1.s + 0x9500: ../plot3d/FONT + 0xb600: ../plot3d/projtab.s +entry: ENTRY +# highlight: '#c3def1' +instant_rts: + - LOAD1 diff --git a/plot3d.yaml b/plot3d.yaml deleted file mode 100644 index dbf56a7..0000000 --- a/plot3d.yaml +++ /dev/null @@ -1,13 +0,0 @@ -load: - 0x6000: plot3d/plot3d242.s - 0x1200: plot3d/multtab.s - 0x8400: plot3d/ldrwtab.s - 0x8900: plot3d/SINETABLE - 0x8b00: plot3d/object2.s - 0x9000: plot3d/object1.s - 0x9500: plot3d/FONT - 0xb600: plot3d/projtab.s -entry: ENTRY -# highlight: '#c3def1' -instant_rts: - - LOAD1