Dlouhou dobu jsem žil v představě, že časování videoprocesoru u PMD 85 je provedeno tak, aby s činností CPU nekolidovalo, tedy že videoprocesor CPU nebrzdí. Roman Bórik mě však upozornil, že podle příručky je procesor brzděn, a to o nějakých 8 %.

Začetl jsem se do schematu a vskutku, je tomu tak: na signál READY je přiváděn signál vzniklý jako XOR signálu VIDEO, což je signál o frekvenci jedné poloviny hodinového taktu a o střídě 50 %, indikující, že videoprocesor bude v daném T-stavu číst z paměti, a signálu vzniklého zalatchováním D1 z vnitřní datové sběrnice mezi 8080A a 8228 podle STSTB; to odpovídá stavovému signálu /WO. Ten je nulový (aktivní), pokud v daném M-cyklu bude procesor zapisovat, buď do paměti nebo na port.

To je ovšem málo logické: kdyby byl na READY přiveden přímo signál VIDEO, byl by čekací stav TW vložen do každého kolisního M-cyklu, ale protože je tento signál napřed XORován s /WO, znamená to, že se zpoždění vkládá nejen do zápisových cyklů, které kolidují s videoprocesorem, ale i do nezápisových, které s videoprocesorem nekolidují.

Což jest mi záhadou, protože si nedokážu představit, k čemu by to bylo dobré. K přístupu na vnější sběrnici dochází vždy ve stavu T3 (a nikdy jindy), a blokovat CPU v době, kdy videoprocesor tuto sběrnici nepotřebuje, to je pro mne nepochopitelné.

Abych ověřil, jestli se to v PMD opravdu takto děje anebo je to jinak – a já pouze nerozumím, jak – připravil jsem krátký testovací program v BASICu, který časování změří. Nedělá nic tajemného: vyplní zkušební pole dlouhou sekvencí identických instrukcí a ty pak spustí, přičemž podle údaje z 8253 zobrazí, jak dlouho jejich provedení trvalo (ASM). Z výsledku uvidím, jak brzdění procesoru probíhá v praxi.

Příkladmo instrukce NOP: ta by neměla být v dlouhé sekvenci brzděna téměř vůbec, protože pokud se vloží TW do prvního provedení, prodlouží se délka instrukce ze 4 na 5 T-stavů a tím se procesor s videoprocesorem synchronisuje. U instrukcí, které jsou pětistavové, tento efekt nevzniká, resp. je opačný. Tím, že jsem do testu zařadil čtecí i zápisové instrukce, zjistím, kdy a o kolik k brzdění dochází.

Praktickým problémem je, že sám PMDčko nevlastním a musím tedy požádat o pomoc své laskavé čtenáře. Pokud si program stáhnou (PTP, PMD, WAV), případně přepíší, spustí ho na fysickém stroji a napíšou mi, kolik vyšlo (tj. jaké hodnoty jsou v pravém sloupci, levý je kontrolní a měl by být stejný), pomohou mi emulátor zdokonalit a dále přiblížit originálu, přičemž odměnou jim bude jejich jméno provždy vytesané v hexadecimální podobě v mém kodu :-)

Mimochodem, ze zvědavosti jsem test spustil i v emulátoru bratří Bórikových. Ve windowsovské versi vyšly samé nuly (PIT není zřejmě emulován přesně, s ohledem na to, že daný čítač využívá i USART), ve versi pro Linux je patrné proporcionální brzdění, což, jak vysvětleno, velmi pravděpodobně neodpovídá originálu.

Aktualisováno.
A díky R. Bórikovi máme hotovo: shoda časování s fysickým PMD je nyní dokonalá; ani jsem netušil, že mám 8253/4 naemulovánu tak přesně (chcete-li se podívat, jak je časování provedeno, můžete zde). Potvrdila se hypothesa, že zapojení dělá přesně to, co jsem si myslel, aniž bych chápal, k jakému účelu vkládání wait-stavů do nekolidujících M-cyklů slouží. Videoprocesor tuto pausu nepotřebuje a nijak nevyužívá. Tedy se přikláním k variantě prosté konstruktérské chyby.

Pro zajímavost se můžeme přesvědčit, o kolik je CPU brzděn při provádění reálné aplikace, běžného programu v BASICu, např. grafického dema. S rychlým procesorem demo na PMD 85-1 trvá 71 sekund, s pomalým 83 sekund, rozdíl je tedy 15,5 %. To není úplně zanedbatelná ztráta výkonu. A ještě jeden experiment: vylistování dumpu celého basicu v monitoru PMD 85-2 (z počátečního stavu zaplněné obrazovky, tedy s rolováním od prvního řádku) zabere bez zpomalování 161 s, se zpomalováním 189 s, rozdíl = 16,0 %.

Přitom stačilo trochu víc přemýšlet a procesor se nemusel videem zpomalovat vůbec.

Komentáře   

+1 # Roman Bórik 2015-10-01 20:12
V technickej príručke je nasledujúca tabuľka, ktorá popisuje vytváranie signálu READY.
READY | /MW | /MR | VIDEO
0 | 0 | 1 | 0
1 | 1 | 0 | 0
1 | 1 | 1 | 0
1 | 0 | 1 | 1
0 | 1 | 0 | 1
1 | 1 | 1 | 1

Win verzia emulátora sa, na rozdiel od Linuxovej, stále vyvíja, robia sa rôzne o(ú)pravy, pridávajú sa ďalšie periférie a toto je dôsledok, že sa v PMD 85-1 nedostávajú hodiny na CT1 PIT 8253.
Chyba vznikla po pridaní emulácie Myši 602, ktorá tento čítač používa. Hodiny sa tak dostanú na CT1 iba ak je pripojená Myš 602 k PMD 85-1.
Ak si ale zvolíte iný model PMD 85, tak program funguje bez problémov.

Vyskúšal som testovací program na živom PMD 85-3 a tu je výsledok:
0 - NOP - 15512
3 - INX B - 23192
9 - DAD B - 38552
42 - LHLD nn - 25752
58 - LDA nn - 20632
70 - MOV B,M - 30872
112 - MOV M,B - 30872
Opakované spustenie programu vráti VŽDY rovnaké výsledky.
+1 # Tomáš Pecina 2015-10-02 03:24
Velice děkuji, již jsem analysoval a implementoval, viz aktualisace.
+1 # Tomáš Pecina 2015-10-02 03:45
Mimochodem, ta tabulka je špatně, protože /WO = /MW + /IOW = ~(/MR + /IOR), a poslední řádek nesouhlasí: ve skutečnosti je procesoru posíláno na /READY L, že není Tw vložen, je jen důsledkem chování procesoru (týká se to instrukcí DAD, které jsou zpomalovány jen v prvním M-cyklu).
0 # Roman Bórik 2015-10-02 20:13
Skvelá práca!
S Vašim dovolením by som rád implementoval Váš mechanizmus počítania T-cyklov do nášho emulátora.

Vo Vašej emulácii som si všimol, že pri spracovávaní prerušenia akceptujete iba inštrukcie RST a CALL. V skutočnosti je procesoru jedno, o akú inštrukciu sa jedná. Pre procesor je prevziatie kódu inštrukcie od periférie ekvivalentné strojovému cyklu FETCH (M1). Pri prerušení je rozdiel iba v tom, že ak inštrukcia potrebuje druhý, prípadne aj tretí byte, tak sa namiesto signálu /MEMR aktivuje opäť jeden alebo dva krát signál /INTA (na 8228).
0 # Tomáš Pecina 2015-10-02 20:28
S Vašim dovolením by som rád implementoval Váš mechanizmus počítania T-cyklov do nášho emulátora.

Samozřejmě!

Vo Vašej emulácii som si všimol, že pri spracovávaní prerušenia akceptujete iba inštrukcie RST a CALL. V skutočnosti je procesoru jedno, o akú inštrukciu sa jedná. Pre procesor je prevziatie kódu inštrukcie od periférie ekvivalentné strojovému cyklu FETCH (M1). Pri prerušení je rozdiel iba v tom, že ak inštrukcia potrebuje druhý, prípadne aj tretí byte, tak sa namiesto signálu /MEMR aktivuje opäť jeden alebo dva krát signál /INTA (na 8228).

To vím, ale rozhodl jsem se pro toto zjednodušené řešení s ohledem na přerušovací mody Z80 (ve skutečnosti jsem interrupty u 8080A moc neřešil a teď je provisorně "backportoval" ze Z80). Neumím si rozumně představit aplikaci, kde by se procesoru dodalo cokoli jiného než RST nebo CALL, kdybych na takovou narazil, musel bych s tím něco dělat.
0 # Roman Bórik 2015-10-03 22:10
Implementoval som do nášho emulátora brzdenie procesra použitím princípov z Vášho emulátora.
Keďže som to chcel overiť aj na iných inštrukciách, upravil som program TIMING a pridal doň ďalšie inštrukcie, v snahe pokryť všetky typy sekvencií strojových cyklov, tak ako ich máte Vy zadefinované (pri zachovaní pôvodného strojového kódu som musel vynechať TR4R3R3W3 (STA nn) a TR4R3R3W3W3 (SHLD nn), aby nedošlo k prepísaniu BASICu a časti kódu).
Upravený program je tu: pmd85.borik.net/_work/timing.ptp
Za inštrukciou je aktuálny počet taktov, počet taktov bez brzdenia a percento zdržania. Inštrukcia CNZ nn predstavuje prípad, kedy podmienka nie je splnená a k volaniu nedôjde. Inštrukcia CNC nn predstavuje prípad, kedy je podmienka splnená a k volaniu dôjde. Keďže je kód inštrukcie 0D4h, volanie je pochopiteľne na adresu 0D4D4h. Tam je preto zapísaná inštrukcia RET (to sa prejaví v obraze bodkami, ale ničomu to samozrejme nevadí). Pre volanie RST 7 je na adresu 38h opäť zapísaná inštrukcia RET.
Program som samozrejme skúšal aj na živom PMD 85-3 a jediná zo zvolených inštrukcií, ktorá mi nesedí, je práve RST 7. Na živom PMD 85-3 je výsledná hodnota 92312, v emulátore 99992. To je viac presne o 2T na jedno volanie. Možno mám niekde chybu, ale neviem kde.
Môžete to, prosím, skúsiť na Vašom emulátore? Pre úplnosť tabuľka z živého PMD 85-3:
0 - NOP - 15512 / 15491
1 - LXI B,## - 15512 / 12931
3 - INX B - 23192 / 19331
6 - MVI B,# - 15512 / 13571
9 - DAD B - 38552 / 38531
42 - LHLD ## - 25752 / 20611
52 - INR M - 38552 / 38531
58 - LDA ## - 20632 / 16771
70 - MOV B,M - 30872 / 27011
112 - MOV M,B - 30872 / 27011
196 - CNZ ## - 18072 / 14211
227 - XTHL - 76952 / 69251
212 - CNC ## - 41112 / 34691
255 - RST 7 - 92312 / 80771
0 # Tomáš Pecina 2015-10-04 00:33
Vyšlo mi to stejně jako vám. Chyba odhalena a zneškodněna. Děkuji za upozornění.
0 # Tomáš Pecina 2015-10-04 09:00
Jinak, můj program sloužil k zjištění, jak funguje skutečná 8080A, pro váš druh testu se příliš nehodí (modifikuje Basic, píše do videopaměti apod.).

Pokud by se mělo otestovat časování všech instrukcí, resp. všech jejích typů, bylo by potřeba každou testovanou instrukci spustit ve stavu lichých i sudých systémových hodin, tj. s VIDEO=L a H. Toho lze dosáhnout např. tak, že se před testovanou instrukci vloží jednou NOP, jednou MOV A,A.
0 # Roman Bórik 2015-10-04 12:25
Vďaka. Už to chodí správne aj nám.

BASIC, ako taký, modifikovaný nebol. "Modifikácia" pamäti spočívala iba v tom, že som "podstrčil" na správne miesto návratovú inštrukciu RET, aby to nezhavarovalo pri volaní RST 7 a CNC nn.

Chápem Vašu poznámku k testom inštrukcií a možno si to v slabej chvíľke takto overím. Prakticky by to ani nemuselo byť pre skupinu rovnakých inštrukcií, ale len pre jednu konkrétnu.
0 # Tomáš Pecina 2015-10-04 12:41
Těch slabin bylo víc, např. jste netestovali výsledky při obou iniciálních stavech videoprocesoru.

Nicméně nedalo mi to a test všech instrukcí jsem si napsal (neumí pouze HLT :-) ). Momentálně dolaďuji a jsem zvědav, jak to pojede na skutečném stroji.
0 # Tomáš Pecina 2015-10-04 14:30
Výsledek je na githubu (timing-pmd-full.*), měl by dávat konečné CRC 0xecb22f1c (startuje se JUMP 0000, na -3 se vyžaduje kompatibilní modus).

Úplně dokonalý test to není, protože softwarově se přesná délka instrukce nezměří. Důvodem je, že M1 jakékoli další instrukce, včetně IN, změní časování tak, že se procesor a videoprocesor synchronisují (podle typu instrukce buď na lichou, nebo na sudou periodu, ale bez ohledu na počáteční stav).

Přesné měření by se tedy muselo udělat hardwarově, např. přivést některý signál z procesoru na GATE1 8253.
0 # Roman Bórik 2015-10-04 19:18
Vyskúšal som Váš nový testovací program. Konečné CRC sa ale líši.

PMD 85-3:
----------
00:17/1F-36AD6463
01:17/1F-8C8422EB
02:1B/1F-4CD42128
03:1F/1B-560B3552
04:1F/1B-99016A8C
05:1F/1B-7D6E0172
06:17/1F-E285DFEF
07:17/1F-47014B80
...
FF:23/27-FD15E92B

Emulator:
----------
00:19/1B-AF438DF4
01:18/1A-9CA01544
02:1D/1F-8BAC93A3
03:1B/1D-261C013B
04:1B/1D-81855EF1
05:1B/1D-4B448AC9
06:19/1B-06302D89
07:19/1B-BEFB19B3
...
FF:24/26-78174EB7

Aby som mohol pohodlne odsledovať aj prvé hodnoty testu, doplnil som doň možnosť pozastavenia. Pred návestie L2 som vložil nasledujúci kód.

l8: in kb
ani 20h
jz l8
in kb
ani 40h
jnz l2
l9: in kb
ani 20h
jnz l9

Kde symbol KB je definovaný na začiatku programu

kb equ 0f5h

Shiftom tak je možné výpis pozastaviť a Stopkou zastaviť. Opätovné rozbehnutíe je Shiftom.
0 # Tomáš Pecina 2015-10-04 19:41
Pozoruhodné! Toto je výpis z mého emulátoru, zajímalo by mě, kde se začíná odlišovat od vašeho. Ale ještě pozoruhodnější je chování skutečného PMD. Na chybu naprogramování 8253 to nevypadá, ta by se projevovala jinak, toto je zjevně odlišnost v časování.
0 # Roman Bórik 2015-10-04 20:00
Rozdiel začína od C0.
C0:1E/20-63B38F69
Pravdepodobne som niekde urobil chybu v kóde pre "vkladanie" W-cyklov z pohľadu podmienených skokov. Ďalej sa už CRC "vezie"... Musím to preveriť.
0 # Tomáš Pecina 2015-10-05 01:40
První (poměrně subtilní) problém odhalen: emulátor (minimálně ten můj) nepočítá s tím, že instrukce IN může mít různou délku a stav 8253 čte až v posledním M-cyklu. Obdobně OUT. Pokusil jsem se tuto diskrepanci eliminovat, výsledek je opět na githubu. Nyní dává můj emulátor tento výsledek.

Celkově se ukazuje, že methoda softwarového měření časování není úplně nejšťastnější, protože měřený a měřicí kod se navzájem silně ovlivňují: téměř tu platí principy jako v kvantové fysice :-)
0 # Roman Bórik 2015-10-05 21:55
Novú verziu testera som opäť spustil na PMD 85-3 a aj v emulátore a opäť sa to diametrálne líši.
A čo je asi podstatnejšie, opätovné spustenie dáva rozdielne výsledky aj na PMD 85-3 a aj v emulátore.
Asi to fakt nevedie rozumnému SW riešeniu...

Keď som hľadal chybu v implementácii brzdenia CPU v našom emulátore, tak som zistil, že máte chybnú návratovú hodnotu pri inštrukcii 97 - SUB A.
0 # Tomáš Pecina 2015-10-05 22:10
Keď som hľadal chybu v implementácii brzdenia CPU v našom emulátore, tak som zistil, že máte chybnú návratovú hodnotu pri inštrukcii 97 - SUB A.

Díky, opraveno.

A čo je asi podstatnejšie, opätovné spustenie dáva rozdielne výsledky aj na PMD 85-3 a aj v emulátore.

Spokojím se tedy s tím, že předchozí verse timing-u chodí správně, takže shoda mezi emulátorem a "železem" je zřejmě téměř dokonalá, a kde není, je to vinou příliš hrubé granularity emulátorového času: jistě by se daly instrukce emulovat jemněji, na úrovni jednotlivých T-stavů, ale nevidím k tomu rozumný důvod, nehledě na zpomalení, které by to téměř určitě přineslo.

Testovat přesné časování by se nejjednodušeji dalo tak, že by se některé signály z aplikačního konektoru vyvedly na breadboard a tam z nich pomocí TTL logiky vytvořil impuls, který bude mít přesnou délku měřené instrukce. Opakuji ale, že důvod dál se v tom vrtat nevidím.

Momentálně už dělám druhý den něco jiného, konkrétně PMD-32 (a zároveň řeším problém s nahráváním z kasety u Pascalu 2.2).
0 # Roman Bórik 2015-10-03 21:54
Tento komentář byl odstraněn autorem.
0 # Zdeněk Šesták 2015-11-30 07:29
Dovolil bych si přispět s troškou do mlýna. Taky jsem kdysi takty analyzoval a dospěl jsem k trochu jednodušší implementaci počítání taktů. Bylo by to na delší vypisování a s obrázky, tak jsem rovnou založil stránky (stejně jsem to chtěl udělat, tak proč ne teď):
maximalne.8u.cz/.../
0 # Tomáš Pecina 2015-11-30 10:29
To je velmi pečlivě zpracováno, ale jeví se mi, že jsou výsledky identické jako ty naše (github.com/.../PMDIntel8080A.java): povšimněte si, že se instrukce buď prodlužuje nebo neprodlužuje o jeden T-stav v závislosti na stavu systémových hodin, ale základní doba není identická s tou, která odpovídá nebržděnému procesoru.

Komentovat články mohou pouze registrovaní uživatelé; prosím, zaregistrujte se (v pravém sloupci dole)