forum speccy.pl
ZX Spectrum => SOFTWARE => Wątek zaczęty przez: Dr Piotr w 2016.01.13, 00:18:39
-
Witam,
Nudzilem sie troche ostatnio i sklecilem sobie profiler dla z80 - sa moze chetni do przetestowania go?
-
Chętnie.
-
A do czego to służy ?
-
W dużym uproszczeniu profiler to narzędzie do analizy wykonania kodu, które pozwala ustalić które kawałki wykonują się nie dość optymalnie.
-
Może bym i potestował.
A co dokładnie ten konkretny profiler robi?
-
Może bym i potestował.
A co dokładnie ten konkretny profiler robi?
Wciaga binarke z kodem z80 i ja wykonuje, wypisujac na koncu ile sumarycznie zajelo wykonanie kazdej instrukcji i funkcji.
-
Ciekawe, to może ja spróbuje.
-
Ale jakąś tablicę symboli też bierze czy jedzie po czystej binarce? Profiluje ścieżki wykonania? I rozumiem, że podlicza tylko procesor nie symulując np. spectrumowej pamięci ekranu?
-
Ale jakąś tablicę symboli też bierze czy jedzie po czystej binarce? Profiluje ścieżki wykonania? I rozumiem, że podlicza tylko procesor nie symulując np. spectrumowej pamięci ekranu?
Tablicy symboli jeszcze nie wciaga, na razie sam ja sobie generuje. Czasy wykonania przelicza dla golego z80 oraz dla cpc i msx, z80 w Spectrum nie symuluje, bo z tego co czytalem jest to dosyc skomplikowane i nie chcialo mi sie tego implementowac.
-
Wciaga binarke z kodem z80 i ja wykonuje, wypisujac na koncu ile sumarycznie zajelo wykonanie kazdej instrukcji i funkcji.
Upewnię się czy dobrze rozumiem. To znaczy robi takie np takie zestawienie:
LD A,B 100 taktów
LD A,C 120 taktów
itp.
czyli dla wszystkich instrukcji sumuje łączne czasy ich wykonania?
A co do funkcji, to w asemblerze przecież tak naprawdę ich nie ma ;) Co rozumiemy przez funkcję? Zbiór instrukcji który został wywołany instrukcją CALL i zakończony instrukcją RET ?
-
Wciaga binarke z kodem z80 i ja wykonuje, wypisujac na koncu ile sumarycznie zajelo wykonanie kazdej instrukcji i funkcji.
Upewnię się czy dobrze rozumiem. To znaczy robi takie np takie zestawienie:
LD A,B 100 taktów
LD A,C 120 taktów
itp.
czyli dla wszystkich instrukcji sumuje łączne czasy ich wykonania?
A co do funkcji, to w asemblerze przecież tak naprawdę ich nie ma ;) Co rozumiemy przez funkcję? Zbiór instrukcji który został wywołany instrukcją CALL i zakończony instrukcją RET ?
Tak - funkcja to call, zakonczony ret.
Tu masz przykladowy output:
Z80 Profiler v 0.8, copyright 2015 Piotr Drapich
0000 di ; 4T F3
0001 call #0019 ; 17T CD 19 00
0019 xor a ; 4T AF
001a ret ; 10T C9
0004 call #000e ; 17T CD 0E 00
000e xor a ; 4T AF
000f call #0013 ; 17T CD 13 00
0013 and a ; 4T A7
0014 ret ; 10T C9
0012 ret ; 10T C9
0007 call #0013 ; 17T CD 13 00
0013 and a ; 4T A7
0014 ret ; 10T C9
000a call #0015 ; 17T CD 15 00
0015 call #000e ; 17T CD 0E 00
000e xor a ; 4T AF
000f call #0013 ; 17T CD 13 00
0013 and a ; 4T A7
0014 ret ; 10T C9
0012 ret ; 10T C9
0018 ret ; 10T C9
000d ret ; 10T C9
Profiling summary for test1.bin, loaded at 0x0000 and executed in 227 tstates.
0000 di ; 4T F3
0001 call #0019 ; 31T CD 19 00
0004 call #000e ; 66T CD 0E 00
0007 call #0013 ; 31T CD 13 00
000a call #0015 ; 34T CD 15 00
000d ret ; 10T C9
l000e:
000e xor a ; 8T AF
000f call #0013 ; 34T CD 13 00
0012 ret ; 20T C9
l0013:
0013 and a ; 12T A7
0014 ret ; 30T C9
l0015:
0015 call #000e ; 21T CD 0E 00
0018 ret ; 10T C9
l0019:
0019 xor a ; 4T AF
001a ret ; 10T C9
Executed calls:
0001 call #0019 31T (13.66%)
0004 call #000e 66T (29.07%)
0007 call #0013 31T (13.66%)
000a call #0015 34T (14.98%)
000f call #0013 34T (14.98%)
0015 call #000e 21T (9.25%)
btw: jest jeszcze jakis blad w podsumowaniu na koncu - jak go poprawie to bedzie gotowa wersja testowa.
-
Chętnie.
Na jaki mail Ci wyslac?
-
A czy do tego narzędzia możesz dodać wyliczanie czasu wykonania w milisekundach? Taktowanie Z80 można podać jako parametr...
Mail podałem na pw.
-
A czy do tego narzędzia możesz dodać wyliczanie czasu wykonania w milisekundach? Taktowanie Z80 można podać jako parametr...
Mail podałem na pw.
Dolozylem przeliczanie na ms, wlasnie wysylam wersje testowa.
Btw: ostatnia szansa na zalapanie sie na testowanie :) Zainteresowanych zapraszam na pw ze swoim mailem.
-
Dzięki, będę testować.
-
Odpaliłem profiler w następujący sposób:Z80Profiler.exe -c3.5 -la -ll -ld 48.ROM >48.lst
Wsadem jest ROM z ZX48.
Otrzymałem np takie wyniki:
.
.
.
.
l0d4d:
0d4d xor a ; 20T AF
0d4e ld hl,(05c8dh) ; 80T 2A 8D 5C
0d51 bit 0,(iy+002h) ; 100T FD CB 02 46
0d55 jr z,0d5bh ; 45T 28 04
0d57 ld h,a ; 12T 67
0d58 ld l,(iy+00eh) ; 57T FD 6E 0E
l0d5b:
0d5b ld (05c8fh),hl ; 80T 22 8F 5C
0d5e ld hl,05c91h ; 50T 21 91 5C
0d61 jr nz,0d65h ; 50T 20 02
0d63 ld a,(hl) ; 14T 7E
0d64 rrca ; 8T 0F
l0d65:
0d65 xor (hl) ; 35T AE
0d66 and 055h ; 35T E6 55
0d68 xor (hl) ; 35T AE
0d69 ld (hl),a ; 35T 77
0d6a ret ; 50T C9
l0d6b:
Ilość taktów dla xor, and i innych jest nieprawidłowa, przez co całość wyników zdaje się być mocno zawyżona.
-
Odpaliłem profiler w następujący sposób:Z80Profiler.exe -c3.5 -la -ll -ld 48.ROM >48.lst
Wsadem jest ROM z ZX48.
Otrzymałem np takie wyniki:
.
.
.
.
l0d4d:
0d4d xor a ; 20T AF
0d4e ld hl,(05c8dh) ; 80T 2A 8D 5C
0d51 bit 0,(iy+002h) ; 100T FD CB 02 46
0d55 jr z,0d5bh ; 45T 28 04
0d57 ld h,a ; 12T 67
0d58 ld l,(iy+00eh) ; 57T FD 6E 0E
l0d5b:
0d5b ld (05c8fh),hl ; 80T 22 8F 5C
0d5e ld hl,05c91h ; 50T 21 91 5C
0d61 jr nz,0d65h ; 50T 20 02
0d63 ld a,(hl) ; 14T 7E
0d64 rrca ; 8T 0F
l0d65:
0d65 xor (hl) ; 35T AE
0d66 and 055h ; 35T E6 55
0d68 xor (hl) ; 35T AE
0d69 ld (hl),a ; 35T 77
0d6a ret ; 50T C9
l0d6b:
Ilość taktów dla xor, and i innych jest nieprawidłowa, przez co całość wyników zdaje się być mocno zawyżona.
Profiler usiluje wykonac kod, ktory mu wrzucasz, stad tez ilosc tstates czy ms moze byc wieksza jesli dana sekwencja rozkazow zostanie wykonana wiecej niz 1 raz. Tam, gdzie nie dotarl bedziesz mial czas 0.
Profiler w zasadzie nie ma opcji samej deasemblacji z podaniem liczby taktow na rozkaz. Jak chcesz tylko zobaczyc ile taktow zajmuje wykonanie danej instrukcji, sprobuj parametru -d (oraz -ax0d4d aby zaczal wykonywac od tego adresu) ew. tylko opcji -a.
W sumie moze dodam opcje takiej deasemblacji, moze sie przydac.
-
Odpaliłem profiler w następujący sposób:Z80Profiler.exe -c3.5 -la -ll -ld 48.ROM >48.lst
Wsadem jest ROM z ZX48.
Aha, opcja -c3.5 bez opcji -lms nie ma sensu, bo wtedy wyniki sa wyswietlane w tstates, na co opcja -c nie ma wplywu.
-
Dopiero dziś tu wszedłem. Bardzo przydatne narzędzie.
Jakiś czas temu sam zamierzałem się za coś podobnego zabrać, bo akurat było mi potrzebne, ale jak pomyślałem, że to w zasadzie wymaga napisania jakby kompilatora to się "wystraszyłem";P.
To czekam na release:)
A tak to piszę, bo chciałem zapytać, czy w miarę nieskomplikowane byłoby umożliwienie dodania opóźnień na dostępach (odczyt i zapis) do określonych obszarów pamięci (wideo)?
-
A tak to piszę, bo chciałem zapytać, czy w miarę nieskomplikowane byłoby umożliwienie dodania opóźnień na dostępach (odczyt i zapis) do określonych obszarów pamięci (wideo)?
Na razie sa zaimplementowane dwie opcje tego rodzaju - dla amstrada cpc, rozciagajaca tstates do wartosci podzielnej przez 4 oraz dla msx dodatkowy tstate przy odczycie opcode. Mozliwe, ze zaimplementuje tez dla zx spectrum, ale to bardziej skomplikowane.
Do jakiego komputera to potrzebujesz?
-
Do Enterprise... Gdy jakiś czas temu pytałem autora emulatora jak można to sobie liczyć to otrzymałem poniższą informację:
Wait states generated by DAVE (if enabled on port BFh) are simple, they add 1 cycle to all memory accesses (00h) or only M1 reads (04h). The latter are the first byte of simple instructions with no prefix, or the first two bytes with CB/DD/ED/FDh prefix. Also, according to tests by Zozosoft, it seems that DAVE waits 2 cycles on turbo machines. But in programs where speed is important, wait states are disabled, so all the above does not matter.
Video memory and NICK I/O port timing are more complex: within each 889846 Hz "slot" (1 character), the Z80 is allowed access to one byte at a specific time, and it always needs to wait at least a certain amount of time (a few ns more than 5/16 of a character, and there is also few ns difference depending on the type of access - normal memory, M1 memory, and I/O). This is implemented by the NICK chip halting the Z80's clock, which it can do in 1/2 clock cycles (1/8000000 s on normal non-turbo machines). There is a test run on real machines here that measures the average time between video memory accesses at various intervals in Z80 cycles.
For the calculations in the sprite code, I used a simplified model: add 1.5 cycles to the time between the video memory accesses, and then round up the result to an integer multiple of 4.5 cycles, and that is the real amount of time, with the wait states (stopped Z80 clock) added. In other words, the best case is 1.5 cycles of wait, and the worst case is 5.5 cycles. This is not entirely accurate, but it gives a reasonable estimate.
When calculating video memory timing, it should also be taken into account exactly when the accesses occur within the instruction. This can be found in the Z80 documentation. For example, an LD (HL), A instruction is two memory accesses, an M1 read at 2 cycles, and a normal write at 6.5 cycles.
Chodziłoby o opóźnienia związane z dostępem do pamięci wideo.
-
Do Enterprise... Gdy jakiś czas temu pytałem autora emulatora jak można to sobie liczyć to otrzymałem poniższą informację:
Wait states generated by DAVE (if enabled on port BFh) are simple, they add 1 cycle to all memory accesses (00h) or only M1 reads (04h). The latter are the first byte of simple instructions with no prefix, or the first two bytes with CB/DD/ED/FDh prefix. Also, according to tests by Zozosoft, it seems that DAVE waits 2 cycles on turbo machines. But in programs where speed is important, wait states are disabled, so all the above does not matter.
Video memory and NICK I/O port timing are more complex: within each 889846 Hz "slot" (1 character), the Z80 is allowed access to one byte at a specific time, and it always needs to wait at least a certain amount of time (a few ns more than 5/16 of a character, and there is also few ns difference depending on the type of access - normal memory, M1 memory, and I/O). This is implemented by the NICK chip halting the Z80's clock, which it can do in 1/2 clock cycles (1/8000000 s on normal non-turbo machines). There is a test run on real machines here that measures the average time between video memory accesses at various intervals in Z80 cycles.
For the calculations in the sprite code, I used a simplified model: add 1.5 cycles to the time between the video memory accesses, and then round up the result to an integer multiple of 4.5 cycles, and that is the real amount of time, with the wait states (stopped Z80 clock) added. In other words, the best case is 1.5 cycles of wait, and the worst case is 5.5 cycles. This is not entirely accurate, but it gives a reasonable estimate.
When calculating video memory timing, it should also be taken into account exactly when the accesses occur within the instruction. This can be found in the Z80 documentation. For example, an LD (HL), A instruction is two memory accesses, an M1 read at 2 cycles, and a normal write at 6.5 cycles.
Chodziłoby o opóźnienia związane z dostępem do pamięci wideo.
Ten opis zawily troche jest, jakbys zorganizowal taka tabelke:
|start address| | end address| | M1 delay| | read delay| | write delay| | io read delay| | io write delay| |
To moglbym sprobowac to podlaczyc.
-
Zrobilem w weekend nowa wersje:
- laduje i wykorzystuje liste zmiennych, generowanych z assemblerow: maxam/winape, pasmo, sjasmplus
- opcja -d - tylko deasemblacja bez profilowania.
- opcja -t - wyswietlanie instrukcji w trakcie ich wykonywania
- opcja -ll - wyswietla liste wszystkich etykiet, zarowno tych wczytanych jak i automatycznie wygenerowanych w trakcie wykonywania
Nastepna wersja bedzie wczytywac pliki .cdb z kompilatora sdcc.
W kolejce czeka UI na windows, pluginy dla roznych procesorow, breakpointy itp :)
-
Nowa wersja beta, teraz juz jako The Profiler :)
- wersja UI dla windows xp/7/8/10
- ladowanie plikow bin oraz .cdb (sdcc)
- ladowanie plikow z symbolami w formatach
- maxam/winape
- pasmo
- sjasmplus
- noGMB
- obsluga wielu procesorow (kazdy procesor jako osobny plugin)
- profiler
- symulator/debugger
- disassembler
- monitor pamieci
- wbudowany jezyk skryptowy
- programowalne definiowanie urzadzen (procesor, pamiec ram/rom, porty wejscia)
- oprogramowanie obslugi np portow wejscia/wyjscia, ekranu, interpretacji pamieci itp.
-
Fajny kombajn 8)
-
Fajne, czy zatem jest szansa na moduł ZX dla profilera?
-
No widzę, że będzie z tego zaawansowane, profesjonalne narzędzie :)
-
Fajne, czy zatem jest szansa na moduł ZX dla profilera?
Zrobilem podstawowa konfiguracje urzadzenia dla zx spectrum - obsluguje tylko io port drukarki, ale mozna w ten sposob wywietlac teksty na konsoli :)
-
A jak mi/nam zdradzisz jak się robi taką konfigurację, to w pewnej nieodległej przyszłości mógłbym ja lub ktoś to ma akurat więcej czasu, taki konfig wykonać.
-
A jak mi/nam zdradzisz jak się robi taką konfigurację, to w pewnej nieodległej przyszłości mógłbym ja lub ktoś to ma akurat więcej czasu, taki konfig wykonać.
Jasne, konfiguracja jak i cala emulacja portow io jest robiona za pomoca kompilowanego skryptu, ktory mozna samemu napisac. W tej chwili kod do konfigu spectrum wyglada mniej wiecej tak:
#include "TheProfiler"
forward public ULAWrite(Address, Data);
forward public ULARead(Address, Data);
forward public PrinterWrite(Address, Data);
public InitScript()
{
SetDeviceName("ZX Spectrum 48k","1.0","Union Systems","Copyright 2016 Union Systems");
SetDeviceCPU("Z80", 3500000, DEVICE_GENERIC);
AddMemoryBlock("KERNEL ROM", 0x0000,0x4000, MEMORY_READONLY, 0, "", "Sinclair/48.rom");
AddMemoryBlock("Video RAM", 0x4000,0x1800, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("Video Attributes RAM", 0x5800,0x300, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("Base RAM", 0x5b00,0xa500, MEMORY_READWRITE, 0, "", "");
AddMemoryBlock("IO Ports", 0x00,0x100, IOMEMORY_READWRITE, 0, "", "");
AddIODriver(0x00fe,0x00fe, "ULARead", "ULAWrite");
AddIODriver(0x00fb,0x00fb, "", "PrinterWrite");
}
public FinishScript()
{
}
public AboutScript()
{
printf("ZX Spectrum 48k device configuration v 1.0. Copyright 2016 Union Systems.");
printf("Developed by Piotr Drapich.");
}
// ULA emulation
public ULAWrite(Address, Data)
{
//TODO
}
public ULARead(Address, Data)
{
//TODO
return Data;
}
// printer emulation
public PrinterWrite(Address, Data)
{
static textbuf[255];
static textbufptr=0;
if (Data==13)
{
textbuf[textbufptr]=0;
printf(textbuf);
textbufptr=0;
return;
}
textbuf[textbufptr]=Data;
textbufptr++;
}
Przy ladowaniu urzadzenia jest wywolywany InitScript, potem AboutScript, przy zamknieciu FinishScript.
Inne funkcje skryptu sa callbackami, podawanymi jako parametry np przy definiowaniu bloku pamieci czy portow io i wywolywanymi przy zapisie/odczycie do danego obszaru pamieci.
Np dodanie obslugi portu drukarki jest zdefiniowane w AddIODriver(0x00fb,0x00fb, "", "PrinterWrite");
Prototyp tej funkcji to AddIODriver(StartIOAddress,EndIOAddress, IOReadCallBack[], IOWriteCallBack[]);
Dodaje ona read albo write callback dla zakresu portow, zdefiniowanych przez StartIOAddress I EndIOAddress.
Przy profilowaniu programu, w momencie wykonania np out (#fb),a zostanie wywolany callback PrinterWrite z zawartoscia rejestru a jako Data, adresem #fb jako Address.
PrinterWrite jest prosta funkcja buforujaca znaki az do otrzymania LineFeed, wtedy zebrany tekst jest wyswietlany za pomoca printf w oknie konsoli programu (to na dole po lewej stronie na screenshocie :)
Analogiczne callbacki mozna dodac do kazdego bloku pamieci. Np. dodajac taki callback do bloku pamieci video ramu mozna za pomoca udostepnianego interfeju wyswietlac interpretacje zawartosci tej pamieci w oknie user view monitora pamieci. Dodajac obsluge pozostalych portow i pare innych rzeczy mozna stworzyc prosty emulator wybranego urzadzenia.
btw: W programie powyzszy kod jest dostepny tylko skompilowany w formie binarnej, ale jest mozliwosc pisania i kompilowania wlasnych skryptow.
-
Jak wygląda sytuacja z profilem? Wciąż jest rozwijany czy tez chwilowo poszedł w odstawkę?
-
Jak wygląda sytuacja z profilem? Wciąż jest rozwijany czy tez chwilowo poszedł w odstawkę?
Dobrze wyglada :) - mam jeszcze na liscie do zrobienia 3 features i ok. 10 bledow, z czego 2 istotne i bedzie gotowe...
-
Coś się z tym jeszcze dzieje? Bo temat zaciekawisty...