Skip to content

Commit d2e010c

Browse files
committed
added cx16.scnsiz (extapi call), describe profiler.py script
1 parent 15867ab commit d2e010c

File tree

5 files changed

+74
-19
lines changed

5 files changed

+74
-19
lines changed

compiler/res/prog8lib/cx16/syslib.p8

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,7 @@ const ubyte EXTAPI_ps2data_raw = $09
549549
const ubyte EXTAPI_cursor_blink = $0A
550550
const ubyte EXTAPI_led_update = $0B
551551
const ubyte EXTAPI_mouse_set_position = $0C
552+
const ubyte EXTAPI_scnsiz = $0D ; rom R48+
552553

553554
; extapi16 call numbers
554555
const ubyte EXTAPI16_test = $00
@@ -642,6 +643,15 @@ asmsub iso_cursor_char(ubyte character @X) clobbers(A,X,Y) {
642643
}}
643644
}
644645

646+
asmsub scnsiz(ubyte width @X, ubyte heigth @Y) clobbers(A,X,Y) {
647+
; -- sets the screen editor size dimensions (without changing the graphical screen mode itself)
648+
; (rom R48+)
649+
%asm {{
650+
lda #EXTAPI_scnsiz
651+
jmp cx16.extapi
652+
}}
653+
}
654+
645655
; TODO : implement shims for the remaining extapi calls.
646656

647657

docs/source/technical.rst

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,48 @@ Some notes and references into the compiler's source code modules:
134134
to convert the Ast into IR first. The VM target uses this, but the 6502 codegen doesn't right now.
135135

136136

137-
Upgrading from version 8
138-
------------------------
139-
Version 9 introduced several large, incompatible changes. If you still have programs
140-
written for Prog8 version 8 or earlier, it is likely that you'll have to modify them
141-
to be able to compile with version 9 or newer.
142-
143-
Information about this can be found in `older Prog8 documentation <https://github.com/irmen/prog8/blob/v9.2.1/docs/source/upgrading8.rst>`_ .
137+
Run-time memory profiling with the X16emulator
138+
----------------------------------------------
139+
The X16 emulator has a ``-memorystats`` option that enables it to keep track of memory access count statistics,
140+
and write the accumulated counts to a file on exit.
141+
Prog8 includes a Python script ``profiler.py`` (find it in the "scripts" subdirectory of the source code distribution)
142+
that can cross-reference that file with an assembly listing produced by the compiler with the ``-asmlist`` option.
143+
It then prints the top N lines in your (assembly) program source that perform the most reads and writes,
144+
which you can use to identify possible hot spots/bottlenecks/variables that should be better placed in zeropage etc.
145+
Note that the profiler just works with the number of accesses to memory locations, this is *not* the same
146+
as the most run-time (cpu instructions cycle times aren't taken into account at all).
147+
Here is an example of the output it generates::
148+
149+
$ scripts/profiler.py -n 10 cobramk3-gfx.list memstats.txt  ✔
150+
151+
number of actual lines in the assembly listing: 2134
152+
number of distinct addresses read from : 22006
153+
number of distinct addresses written to : 8179
154+
total number of reads : 375106285 (375M)
155+
total number of writes : 63601962 (63M)
156+
157+
top 10 most reads:
158+
$007f (7198687) : $007e 'P8ZP_SCRATCH_W2' (line 13), $007e 'remainder' (line 1855)
159+
$007e (6990527) : $007e 'P8ZP_SCRATCH_W2' (line 13), $007e 'remainder' (line 1855)
160+
$0265 (5029230) : unknown
161+
$007c (4455140) : $007c 'P8ZP_SCRATCH_W1' (line 12), $007c 'dividend' (line 1854), $007c 'result' (line 1856)
162+
$007d (4275195) : $007c 'P8ZP_SCRATCH_W1' (line 12), $007c 'dividend' (line 1854), $007c 'result' (line 1856)
163+
$0076 (3374800) : $0076 'label_asm_35_counter' (line 2082)
164+
$15d7 (3374800) : $15d7 '9c 23 9f stz cx16.VERA_DATA0' (line 2022), $15d7 'label_asm_34_repeat' (line 2021)
165+
$15d8 (3374800) : $15d7 '9c 23 9f stz cx16.VERA_DATA0' (line 2022), $15d7 'label_asm_34_repeat' (line 2021)
166+
$15d9 (3374800) : $15da '9c 23 9f stz cx16.VERA_DATA0' (line 2023)
167+
$15da (3374800) : $15da '9c 23 9f stz cx16.VERA_DATA0' (line 2023)
168+
169+
top 10 most writes:
170+
$9f23 (14748104) : $9f23 'VERA_DATA0' (line 1451)
171+
$0265 (5657743) : unknown
172+
$007e (4464393) : $007e 'P8ZP_SCRATCH_W2' (line 13), $007e 'remainder' (line 1855)
173+
$007f (4464393) : $007e 'P8ZP_SCRATCH_W2' (line 13), $007e 'remainder' (line 1855)
174+
$007c (4416537) : $007c 'P8ZP_SCRATCH_W1' (line 12), $007c 'dividend' (line 1854), $007c 'result' (line 1856)
175+
$007d (3820272) : $007c 'P8ZP_SCRATCH_W1' (line 12), $007c 'dividend' (line 1854), $007c 'result' (line 1856)
176+
$0076 (3375568) : $0076 'label_asm_35_counter' (line 2082)
177+
$01e8 (1310425) : cpu stack
178+
$01e7 (1280140) : cpu stack
179+
$0264 (1258159) : unknown
180+
181+
Apparently the most cpu activity while running this program is spent in a division routine.

docs/source/todo.rst

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
TODO
22
====
33

4-
See https://github.com/irmen/prog8/issues/134
5-
+ any other issues that got reported.
6-
7-
Document scripts/profiler.py in manual?
4+
https://github.com/irmen/prog8/issues/136 (string.find register order issue)
85

96
...
107

@@ -13,8 +10,9 @@ Future Things and Ideas
1310
^^^^^^^^^^^^^^^^^^^^^^^
1411
Compiler:
1512

13+
- Relax newline / bracket in parser so that you can put open and close brackets on the same line or on the next line if you so wish. For example be able to write a true one liner?
14+
- Can we support signed % (remainder) somehow?
1615
- IR: implement missing operators in AssignmentGen (array shifts etc)
17-
- can we support signed % (remainder) somehow?
1816
- instead of copy-pasting inline asmsubs, make them into a 64tass macro and use that instead.
1917
that will allow them to be reused from custom user written assembly code as well.
2018
- Multidimensional arrays and chained indexing, purely as syntactic sugar over regular arrays.

examples/test.p8

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
%zeropage basicsafe
2+
%option no_sysinit
23

34
main {
45
sub start() {
5-
uword @shared curr_sequence
6-
ubyte @shared sequence_curr_step
7-
8-
uword @shared sequence_offset = &curr_sequence[sequence_curr_step]
6+
cx16.scnsiz(20,8)
97
}
108
}

scripts/profiler.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,17 @@ def profile(number_of_lines: int, asmlist: str, memstats: str) -> None:
129129
stats = MemoryStats(memstats)
130130
asm.print_info()
131131
stats.print_info()
132+
133+
def print_unknown(address: int) -> None:
134+
if address < 0x100:
135+
print("unknown zp")
136+
elif address < 0x200:
137+
print("cpu stack")
138+
elif address in range(0x9f00, 0xa000):
139+
print("io")
140+
else:
141+
print("unknown")
142+
132143
print(f"\ntop {number_of_lines} most reads:")
133144
for (bank, address), count in stats.reads[:number_of_lines]:
134145
print(f"${address:04x} ({count}) : ", end="")
@@ -138,7 +149,7 @@ def profile(number_of_lines: int, asmlist: str, memstats: str) -> None:
138149
lines = [f"${address:04x} '{line}' (line {line_number})" for address, line, line_number in result]
139150
print(", ".join(lines))
140151
else:
141-
print("unknown")
152+
print_unknown(address)
142153
else:
143154
print(f"banked memory: {bank:02x}:{address:04x}")
144155
print(f"\ntop {number_of_lines} most writes:")
@@ -150,14 +161,14 @@ def profile(number_of_lines: int, asmlist: str, memstats: str) -> None:
150161
lines = [f"${address:04x} '{line}' (line {line_number})" for address, line, line_number in result]
151162
print(", ".join(lines))
152163
else:
153-
print("unknown")
164+
print_unknown(address)
154165
else:
155166
print(f"banked memory: {bank:02x}:{address:04x}")
156167

157168

158169
if __name__ == "__main__":
159170
parser = argparse.ArgumentParser(description="simple X16 assembly run time profiler")
160-
parser.add_argument("-n", dest="number", type=int, default=20, help="amount of reads and writes to print")
171+
parser.add_argument("-n", dest="number", type=int, default=20, help="amount of reads and writes to print (default 20)")
161172
parser.add_argument("asmlistfile", type=str, help="the 64tass/turbo assembler listing file to read")
162173
parser.add_argument("memorystatsfile", type=str, help="the X16 emulator memstats dump file to read")
163174
args = parser.parse_args()

0 commit comments

Comments
 (0)