1. 10. 2015

Videoprocesor PMD 85

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.

20 komentářů:

  1. 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.

    OdpovědětVymazat
    Odpovědi
    1. Velice děkuji, již jsem analysoval a implementoval, viz aktualisace.

      Vymazat
    2. 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).

      Vymazat
    3. 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).

      Vymazat
    4. 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.

      Vymazat
    5. 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: http://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

      Vymazat
    6. Vyšlo mi to stejně jako vám. Chyba odhalena a zneškodněna. Děkuji za upozornění.

      Vymazat
    7. 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.

      Vymazat
    8. 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.

      Vymazat
    9. 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.

      Vymazat
    10. 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.

      Vymazat
    11. 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.

      Vymazat
    12. 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í.

      Vymazat
    13. 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ť.

      Vymazat
    14. 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 :-)

      Vymazat
    15. 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.

      Vymazat
    16. 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).

      Vymazat
  2. Tento komentář byl odstraněn autorem.

    OdpovědětVymazat
  3. 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ď):
    http://maximalne.8u.cz/jak-to-s-temi-takty-u-pmd85-vlastne-je/

    OdpovědětVymazat
    Odpovědi
    1. To je velmi pečlivě zpracováno, ale jeví se mi, že jsou výsledky identické jako ty naše (https://github.com/tompecina/retro/blob/master/src/cz/pecina/retro/pmd85/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.

      Vymazat