
							Zyklenberechner

Der Speicherzugriff auf einen Teil des RAM's des Amigas erfolgt über den Agnus-
Chip über ein komplexes System von Prioritäten und teilweise fest zugeordneten
Zeitschlitzen. (Dieser RAM-Bereich wird auch als Chip-RAM bezeichnet.)

Das Amiga Bild (long frame) hat 313 Zeilen (von 0 bis 312) mit jeweils
227 Slots (von 0 bis $e2 bzw. von 0 bis 226). Die Slots werden auch CCKs (Color
Clocks) oder Chip-Zyklen genannt. Die Chip-Zyklen entsprechen genau dem halben
CPU-Takt.

227-4=223	- wegen 4 Refresh-Slots bleiben 223 Zyklen für den Speicherzugriff

Es gibt folgende DMA-Kanäle mit höchster Priorität, die über DMACON eingestellt
werden können. Diese nutzen die ungeraden Zyklen.

Disk: 3 Kanäle					- feste Plätze (höchste Priorität)
Audio: 4x1 Kanal				- feste Plätze (höchste Priorität)
Sprite: 8x2 Kanäle				- feste Plätze (höchste Priorität)
Bitplane: 1 bis 6 Bitebenen		- feste Plätze (höchste Priorität)

Refresh:
R0 - $3  - 3	(RFS0)
R1 - $5  - 5	(RFS1)
R2 - $7  - 7	(RFS2)
R3 - $9  - 9	(RFS3)

Disk:
D1 - $B  - 11	(DSK0)
D2 - $D  - 13	(DSK1)
D3 - $F  - 15	(DSK2)

Audio:
A1 - $11 - 17	(AUD0)
A2 - $13 - 19	(AUD1)
A3 - $15 - 21	(AUD2)
A4 - $17 - 23	(AUD3)

Sprite: 
S0 - 25,27 $19,$1B (SPR0)
S1 - 29,31 $1D,$1F (SPR1)
S2 - 33,35 $21,$23 (SPR2)
S3 - 37,39 $25,$27 (SPR3)
S4 - 41,43 $29,$2B (SPR4)
S5 - 45,47 $2D,$2F (SPR5)
S6 - 49,51 $31,$33 (SPR6)
S7 - 53,55 $35,$37 (SPR7)

Es gibt eine Besonderheit, bei der ein früheres Bitplane Datafetch den Sprites
DMA-Zugriffe angefangen mit Spritekanal 7 wegnimmt.

Der Copper hat Vorrang vor CPU und der Blitter und führt seine Befehle nach
einem festen Schema aus, bis alle Zugriffe erfolgt sind. Der Copper belegt alle
geraden Zyklen.

Speicherzugriffszyklen der  CPU und zwischen CPU und Blitter:

CPU:
===============================================================================
Im Normalbetrieb (ohne Blitter) greift die CPU jeden zweiten Zyklus auf den 
RAM zu. Man könnte es sich so vorstellen iZiZiZ. Wobei 'i' für einen 
internen Zyklus der CPU steht und 'Z' für Zugriff. Man hätte also jeden zweiten
Zyklus einen Speicherzugriff -C-C-C. Gewöhnlich werden die freien Slots '-' 
dabei von anderen besetzt. z.B. Bitplane. dCdCdC  (d - display, C - CPU)
Die CPU greift selbstverständlich nur auf den Speicher zu, wenn der Speicher
angefordert wird. Für gewöhnlich sind bei einem Befehl die 
Speicherzugriffszyklen genau die Hälfte der Taktzyklen. Mitunter wird aber
nicht in allen möglichen Chip-Zyklen auf den Speicher zugegriffen, weil der
Befehl dies nicht verlangt.
Es ist also der "schlimmstmögliche Fall", dass in der Hälfte der Taktzyklen
auch immer auf den Speicher zugegriffen wird.

Bsp.:
CPU-Zyklen sind in den meisten Fällen das doppelte wie die Chip-Zyklen
mit Speicherzugriff: 

12(3/0) 6 - lea	bitplane,a0				3*2=6 Chip-Zyklen	12 CPU-Zyklen	ok
 8(2/0) 4 - and.w  #$000f,d0		    2*2=4 Chip			 8 CPU	ok
12(2/1) 4 - move.w d0,$40(a5)		(2+1)*2=6 Chip			12 CPU  ok

aber nicht immer
46(2/0) 4 - mulu #40,d0			2*2=4 Chip-cycles with memory access
 8(1/0) 2 - add.w  d1,a0		1*2=2 Chip					 8 CPU-Zyklen
12(1/0) 2 - lsr.w #3,d1			1*2=2 Chip					12 CPU-Zyklen

https://68kcounter.grahambates.com/ (12(1/0) 2 --> cycles(reads/writes) bytes)

CPU und Blitter:
===============================================================================
Wenn der Blitter aktiv ist, dann gibt es folgende Dinge zu beachten.
 - Blitpri=0, Blitter hat Vorrang vor CPU, Blitter gewährt CPU aber einige
 freie Zyklen. (nach 3x Warten bzw. jeden 5. Zyklus)
 - Blitpri=1, Blitter hat absoluten Vorrang vor CPU, Blitter gewährt der CPU
 keine freien Zyklen
 - Blitter-Zugriffssequencen sind zu berücksichtigen, d.h. die als Wartezyklen,
 d.h. Idle-Zyklen = '-' gekennzeichneten Zyklen können von der CPU genutzt 
 werden auch wenn Blitpri=1 ist.
 
 Wenn Blitpri=0 eingestellt ist, greift die CPU nach 3 Wartezyklen auf den 
 Speicher zu. z.B. CBBBBC (C-CPU, B-Blitter)
 Die CPU bekommt also mit dem 5. Zyklus den Speicherzugriff. Erklärt wird das
 durch folgendes Schema:

 ZiWWWZ	(Z - Zugriff, i - interner Zyklus, W - 3x Warten, Z-Zugriff)
 CBBBBC (C-CPU, B-Blitter)

 In einer Umgebung mit viel Speicherzugriff durch z.B. Bitebenen, gilt diese
 Regel immer noch.

z.B. CDBDBDDDC	(D-Display -hat höchste Priorität) 5 Bitplanes
     CiWWW		Normalerweise würde die CPU nach diesem Muster nach 3x warten
wieder auf den Speicher zugreifen. Die CPU muss allerdings nun auf den nächsten
freien Zyklus warten, denn Bitplane 'D' hat Vorrang vor der CPU. 

Bei den Blitter-Speicherzugriffszyklen muss beachtet werden, dass der Blitter
Speicherzugriff in einer zweistufigen Pipeline erfolgt. Am Anfang gibt es also
ein Füllen und am Ende ein Leeren der Pipeline. Der Einfachheit halber könnte
man sich also auf das "normale" Zugriffsmuster beschränken. Die "besonderen"
Zugriffsmuster gibt es sowieso nur wenn auch der Kanal D eingeschaltet ist.

Auszug aus WinUAE Debugger:

>v$63 $90
Line: 63  99 HPOS 90 144:
 [90     0]   [91     0]   [92     0]   [93     0]   [94     0]   [95     0]   [96     0]   [97     0]
    CPU-RWD   BLT-D   00   BLT-A   74   BLT-B   72   BLT-C   70      CPU-RWD   BLT-D   00      CPU-RWI
  S    8000         0000         0000         0000         0000    Sb   6396         0000         000F
   00DFF004     0002075E     0001FB5A     0001FA5E     0001F962     00DFF006     00020760     00C2C69A

  102   1F8    1AF   003    0AD   0FD    02F   0FD    0B1   0FC    103   1F8    1B0   003    14D   063

 [98     0] A [99     0]   [9A     0]   [9B     0]   [9C     0]   [9D     0]   [9E     0]   [9F     0]
 BLT-D   00 N    CPU-RWI                   CPU-RWI                   CPU-RWI
  D    0000 D       FF00                      0C80                      0000
   00020762     00C2C69C                  00C2C69E                  00C2C6A0

  1B1   003    14E   063                 14F   063                 150   063
  

 [80 128]  [81 129]  [82 130]  [83 131]  [84 132]  [85 133]  [86 134]  [87 135]
 BLT-D 00    CPU-RW  BLT-A 74  BLT-B 72  BLT-C 70  BLT-D 00    CPU-RW  BLT-A 74
     FF80  S   8000      0000      0000      0000      0000  S   6387      0000
 0002073A  00DFF004  0001FB58  0001FA5C  0001F960  0002075E  00DFF006  0001FB5A
 BBF76800  BBF76A00  BBF76C00  BBF76E00  BBF77000  BBF77200  BBF77400  BBF77600

 [88 136]  [89 137]  [8A 138]  [8B 139]  [8C 140]  [8D 141]  [8E 142]  [8F 143]
 BLT-B 72  BLT-C 70  BLT-D 00    CPU-RW  BLT-D 00    CPU-RW              CPU-RW
     0000  b   0000      0000  S   000F  D   0000      FF00                0C80
 0001FA5E  0001F962  00020760  00C2C69A  00020762  00C2C69C            00C2C69E
 BBF77800  BBF77A00  BBF77C00  BBF77E00  BBF78000  BBF78200  BBF78400  BBF78600

b - Blitter finished Bit (danach werden keine Daten mehr durch den Blitter
    gelesen)
D = blitter's final D write. (marked because it is special cycle, blitter
    finished bit was set 2 cycles ago)

from EAB:

Because most 68000 instructions don't have idle cycles (=only memory cycles
back to back, cycle length is divisible by 4), refresh cycles basically
"forces" CPU to only use even cycles.

Shift instructions are easy test case, each shift by one takes 2 CPU cycles
(=1 DMA cycle).

Der Zyklus wird nicht verwendet, da der Zugriff auf den CPU-Speicher 4 Zyklen
dauert (=2 DMA-Slots). Es sind keine aufeinanderfolgenden Speicherzugriffe 
möglich, da zwischen den Zugriffen immer ein DMA-Zyklus liegt.

Der 68000-Speicherzugriff besteht grundsätzlich aus zwei Teilen: Die erste 
Hälfte sendet die Adresse, die zweite Hälfte überträgt Daten. Die CPU kann
immer auf den ersten Teil zugreifen, auch wenn der Bus gerade verwendet wird.
Wenn der zweite Teil beginnt und der Bus nicht verfügbar ist, schließt
Agnus/Gary den Zyklus nicht ab und die CPU geht einfach davon aus, dass sie
mit (möglicherweise vielen) Wartezuständen auf den Speicher zugreift.


Programm: Zyklenberechner (Processing-Sketch)
===============================================================================

Das Programm zeigt die Speicherzugriffsreihenfolge von CPU mit allen 
Blitterkombinationen und Bitplane und Refresh-Slots für eine Anzahl von
Zyklen bzw. berechnet die Anzahl der Zugriffe dieser. Auch eine Anzahl an 
Copperzyklen kann voreingestellt werden.
Das Programm lässt mögliche Disk, Audio und Sprite-DMA Zugriffe 
unberücksichtigt. Das Ergebnis ist auch nicht 100% das richtige, aber es kommt
dem wahren Ergebnis sehr nah. Zum Beispiel wird das Verhalten des Blitters am 
Ende nicht berücksichtigt.
Weiterhin kann die Anzahl der Pixelgruppen und ein DDFSTRT eingestellt werden.

Die möglichen Eingaben sind folgende:
- die Gesamtzyklenanzahl (227=1 Rasterzeile)
- die Blitterkanalkombination siehe [][] blit_cycle_diagram
- die Anzahl der Bitebenen von 0 bis 6
- Blitter Priorität  0 oder 1

- Optional: 
- Anzahl Copper DMA Zugriffe
- Anzahl CPU Zugriffe
- Größe des Blitts - Blittersize
- Anzahl der Pixelgruppen z.B. N=20 für 20*16=320Pixel

DDFSTRT $38 (56) und DDFSTOP=$d0 (216)	216-56=160 160*2=320  320/8=40  N=20
DDFSTRT $20 (40) und DDFSTOP=$d8 (224)	224-40=184 184*2=368  368/8=46	N=23

Z.B. Für eine Rasterzeile mit 227 Zyklen kann der Bereich innerhalb und 
außerhalb von einer Bitebene analysiert werden. Am Ende der Ausgabe werden
die Anzahl der CPU, Blitter und Bitplanespeicherzugriffe angezeigt.
Zudem die Anzahl der übrig gebliebenen Zugriffe (positives Vorzeichen) also
die Anzahl der Zyklen die noch offen sind.
Ist der Zähler dagegen negativ wurde die Aufgabe bereits vollständig 
abgearbeitet und die Zyklen wären frei.

Bsp.
cy: 0	 Rz: 0	  DMA: 0	 Hex 00	  COP 
cy: 1	 Rz: 0	  DMA: 1	 Hex 01	  BLT 1
cy: 2	 Rz: 0	  DMA: 2	 Hex 02	  COP 
cy: 3	 Rz: 0	  DMA: 3	 Hex 03	  REF 
cy: 4	 Rz: 0	  DMA: 4	 Hex 04	  COP 
cy: 5	 Rz: 0	  DMA: 5	 Hex 05	  REF 
cy: 6	 Rz: 0	  DMA: 6	 Hex 06	  COP 
cy: 7	 Rz: 0	  DMA: 7	 Hex 07	  REF 
cy: 8	 Rz: 0	  DMA: 8	 Hex 08	  COP 
cy: 9	 Rz: 0	  DMA: 9	 Hex 09	  REF 
cy: 10	 Rz: 0	  DMA: 10	 Hex 0A	  COP 
cy: 11	 Rz: 0	  DMA: 11	 Hex 0B	  CPU gewartet: 12
cy: 12	 Rz: 0	  DMA: 12	 Hex 0C	  COP 
cy: 13	 Rz: 0	  DMA: 13	 Hex 0D	  BLT 2
cy: 14	 Rz: 0	  DMA: 14	 Hex 0E	  COP 
cy: 15	 Rz: 0	  DMA: 15	 Hex 0F	  BLT 3
cy: 16	 Rz: 0	  DMA: 16	 Hex 10	  COP 
cy: 17	 Rz: 0	  DMA: 17	 Hex 11	  CPU gewartet: 6
cy: 18	 Rz: 0	  DMA: 18	 Hex 12	  COP 
cy: 19	 Rz: 0	  DMA: 19	 Hex 13	  BLT 0 frei für CPU, gewartet: 2
cy: 20	 Rz: 0	  DMA: 20	 Hex 14	  BLT 1
cy: 21	 Rz: 0	  DMA: 21	 Hex 15	  BLT 2
cy: 22	 Rz: 0	  DMA: 22	 Hex 16	  BLT 3
cy: 23	 Rz: 0	  DMA: 23	 Hex 17	  BLT 4
cy: 24	 Rz: 0	  DMA: 24	 Hex 18	  CPU gewartet: 5
...
cy: 56	 Rz: 0	  DMA: 56	 Hex 38	  BLT 2	 DDFSTRT
cy: 57	 Rz: 0	  DMA: 57	 Hex 39	  BLT 3
cy: 58	 Rz: 0	  DMA: 58	 Hex 3A	  BLT 4
cy: 59	 Rz: 0	  DMA: 59	 Hex 3B	  CPU gewartet: 5
cy: 60	 Rz: 0	  DMA: 60	 Hex 3C	  BLT 1
cy: 61	 Rz: 0	  DMA: 61	 Hex 3D	  BLT 2
cy: 62	 Rz: 0	  DMA: 62	 Hex 3E	  BLT 3
cy: 63	 Rz: 0	  DMA: 63	 Hex 3F	  BPL 1	 16 Pixelgruppe=1
cy: 64	 Rz: 0	  DMA: 64	 Hex 40	  CPU gewartet: 5

cy: 452	 Rz: 1	  DMA: 225	 Hex E1	  BLT 3
cy: 453	 Rz: 1	  DMA: 226	 Hex E2	  CPU gewartet: 5
Das waren: 86 CPU Speicherzugriffe, 310 Blitter Speicherzugriffe, 40 Bitplane Speicherzugriffe 
Blitter-Speicherzugriffe übrig: 331            CPU-Speicherzugriffe übrig: -57


oder mit Abbruchbedingungen:
      if((blitsize <0) || (cpusize<0)) {break;}    // einer ist eher fertig
      //if((blitsize <0))  {break;}                  // Blitter ist eher fertig
      //if((blitsize <0) && (cpusize<0)) {break;}    // beide sind fertig

cy: 154	 Rz: 0	  DMA: 154	 Hex 9A	  CPU gewartet: 5	 CPU Ende-------------------------------
Das waren: 29 CPU Speicherzugriffe, 100 Blitter Speicherzugriffe, 12 Bitplane Speicherzugriffe 
Blitter-Speicherzugriffe übrig: 541            CPU-Speicherzugriffe übrig: 0


 


