Re: Blitter on H5 Test
Posted: 14 Dec 2022 22:14
Thanks @exxos. That confirms with the 1K pull-up on the H5 with TOS 1.04 or higher it matches the STE numbers. As per @ijor summation previously.
We welcome retro users & hardware gurus alike! Come and join the party :)
https://www.exxosforum.co.uk/forum/
I wonder if all the versions of the H4 / H5 ended up with 2.2K pullups. Though I guess up until now there was really no need to change them to 1K anyway.Icky wrote: 14 Dec 2022 22:14 Thanks @exxos. That confirms with the 1K pull-up on the H5 with TOS 1.04 or higher it matches the STE numbers. As per @ijor summation previously.
Thanks a lot Exxos, just perfect! Yes, that confirms the behavior of the pull-up and the relation between all TOS versions.exxos wrote: 14 Dec 2022 21:26 TOS104 on a H5C1. 1K and 2.2K tests.
TOS206 on a H5C1. 1K and 2.2K tests.
I re-posted 102 here edited to align with the above tests.
TOS102 on a H5C1. 1K and 2.2K tests.
I think it's difficult to decide which is the correct pull-up value to use. On one hand, a stronger pull-up might be better from the electronic point of view, and I think it also produces the intended design behavior. Obviously they didn't design Blitter to release BGACK on one cycle and then be delayed because of the weaker pull-up. That was just a motherboard buglet that was finally corrected in the STE.I wonder if all the versions of the H4 / H5 ended up with 2.2K pullups. Though I guess up until now there was really no need to change them to 1K anyway.
Indeed. But also we have the master oscillator speed in the mix as well ?ijor wrote: 15 Dec 2022 01:39 I think it's difficult to decide which is the correct pull-up value to use. On one hand, a stronger pull-up might be better from the electronic point of view, and I think it also produces the intended design behavior. Obviously they didn't design Blitter to release BGACK on one cycle and then be delayed because of the weaker pull-up. That was just a motherboard buglet that was finally corrected in the STE.
On the other hand, a weaker pull-up produces the exact same timing as the original ST/STFM. So, arguably, it is more correct in terms of accuracy and compatibility.
The difference is too small for GB to detect. It is just 4 cycles per blit operation, and only on some operations, not all.exxos wrote: 15 Dec 2022 11:54 Out of interest I did try GB6 with and without the BGACK pullup. Unfortunately I could not see any difference in tests. I just don't think the system timer is accurate enough to measure such things with such subtle changes.
We were just talking with Icky about this. The reason is that GB is not cycle exact and it depends on some random factors:Though GB6 does intermittently switch between 99% and 100% intermittently anyway on some tests occasionally (not sure why)
You need a test that will perform a few thousand blit operations to be able to detect the difference consistently. But each blit operation can be very small, so it doesn't necessarily have to take a very long time. But yeah, probably not worth either way.I guess if there was some specific test run for long enough it could flag up as a difference but is not really worth going down that road.
Sure. If you want, give me a few days and I will clean it up and adapt it for that purpose.It is basically solved with your program anyway. I guess it could be useful to do a more official release and put it in the software section. Indeed more testing is needed at this point, but your program could be adapted to compare known results to the machine it is running on, and just simply output the machine needs a "1K fix" on BGACK.
Are you referring to GB4 here ?ijor wrote: 15 Dec 2022 17:15 1 - GB, as I can see, performs a rough synchronization with the timer interrupt. But this is not an exact synchronization. Then sometimes you start a few cycles later, or a few cycles earlier in relation to the previous timer interrupt.
2 - The vertical blank interrupt is not disabled. And of course, there is no synchronization with the video timing at all. Then the number of times the code will be interrupted is not always exactly the same.
......
Code: Select all
call loc testcode&,sys_sleep
call loc testcode&,sys_acia_off
call loc testcode&,sys_tstart ' start asm timer routine
For A=0 to 2
..... (run test loop)
Next A
call loc testcode&,sys_tstop,varptr(t&),varptr(var1&),varptr(var2&) ' get test time from ASM code
TEST11&= t&*5 ' returns test time from function
call loc testcode&,sys_wake : call loc testcode&,sys_acia_on ' system wake up
Code: Select all
*-----------------------------------------------------------------------------*
sys_sleep:
*-----------------------------------------------------------------------------*
lea sys_state(pc),a0
ori.w #$0700,sr
move.l $70.w,(a0)+
move.l $114.w,(a0)+
lea new_vbi(pc),a1
move.l a1,$70.w
lea new_tc(pc),a1
move.l a1,timerc.w
andi.w #$f3ff,sr
rts
*-----------------------------------------------------------------------------*
sys_wake:
*-----------------------------------------------------------------------------*
lea sys_state(pc),a0
ori.w #$0700,sr
move.l (a0)+,$70.w
move.l (a0)+,timerc.w
andi.w #$f3ff,sr
rts
*-----------------------------------------------------------------------------*
sys_tstart:
*-----------------------------------------------------------------------------*
lea starttime(pc),a0
move.l $4ba.w,d0
.wait: move.l $4ba.w,d1
cmp.l d1,d0
beq.s .wait
move.l d1,(a0)
rts
*-----------------------------------------------------------------------------*
sys_tstop:
*-----------------------------------------------------------------------------*
move.l arguments(pc),a6
;
; calculate time difference (currenttime-starttime)
;
move.l $4ba.w,d0
sub.l starttime(pc),d0
;
; return result
;
move.l arg_0(a6),a0 ; a0 = first argument = BASIC varptr
move.l d0,(a0) ; write result to BASIC var, through (varptr)
;
move.l arg_1(a6),a1 ; a1 = second argument = BASIC varptr
move.l #1234,(a1) ; write #1234 to BASIC var, through (varptr)
;
move.l arg_2(a6),a2 ; a2 = third argument = BASIC varptr
move.l #5678,(a2) ; write #5678 to BASIC var, through (varptr)
rts
*-----------------------------------------------------------------------------*
*-------------------------------------------------------*
_ST_FlushInput:
*-------------------------------------------------------*
lea $fffffc00.w,a0
bra.s .read
.next: btst #0,(a0)
bne.s .read
subq.w #1,d0
bne.s .next
bra.s .end
.read: move.b 2(a0),d0
move.w #$12c,d0
bra.s .next
.end: rts
*-------------------------------------------------------*
write_acia:
*-------------------------------------------------------*
.wait: btst #1,$fffffc00.w
beq.s .wait
move.b d0,$fffffc02.w
rts
*-------------------------------------------------------*
sys_acia_on:
;_ST_EnableInput:
*-------------------------------------------------------*
movem.l d0-a6,-(sp)
bsr _ST_FlushInput
lea enable_ikbd_seq(pc),a0
.next: move.b (a0)+,d0
bmi.s .end
bsr write_acia
bra.s .next
.end: bsr _ST_FlushInput
movem.l (sp)+,d0-a6
rts
*-------------------------------------------------------*
sys_acia_off:
;_ST_DisableInput:
*-------------------------------------------------------*
movem.l d0-a6,-(sp)
bsr _ST_FlushInput
lea disable_ikbd_seq(pc),a0
.next: move.b (a0)+,d0
bmi.s .end
bsr write_acia
bra.s .next
.end: bsr _ST_FlushInput
movem.l (sp)+,d0-a6
rts
*-------------------------------------------------------*
sys_acia_reset:
;_ST_ResetInput:
*-------------------------------------------------------*
movem.l d0-a6,-(sp)
bsr _ST_FlushInput
lea reset_ikbd_seq(pc),a0
.next: move.b (a0)+,d0
bmi.s .end
bsr write_acia
bra.s .next
.end: bsr _ST_FlushInput
movem.l (sp)+,d0-a6
rts
*-------------------------------------------------------*
disable_ikbd_seq: dc.b $13,$1a,$12,-1 ; reporting off, joystick events off, mouse events off
enable_ikbd_seq: dc.b $11,$14,$8,-1 ; resume reporting, joystick events on, mouse events on
reset_ikbd_seq: dc.b $80,$1,-1
even
*-----------------------------------------------------------------------------*
new_vbi:
*-----------------------------------------------------------------------------*
addq.l #1,$462.w
addq.l #1,$466.w
rte
Indeed. Using the system timer is never going to be 100% accurate. GB6 while still occasionally hits 99% scores, it is a lot more accurate than GB4 was. That could easily have a 5% variation.ijor wrote: 15 Dec 2022 17:15 And this is precisely the reason I implemented the test. To avoid all the random non-deterministic factors and to get a constant cycle exact result. Of course, counting system cycles is not suitable for many applications. If you want to benchmark an accelerator that might use a completely difference frequency, then comparing CPU cycles has no meaning. In our case, we wanted to check the accuracy of the Blitter FPGA core, so a cycle exact test is perfect for this purpose.
Great thanks, certainly no rush.ijor wrote: 15 Dec 2022 17:15 Sure. If you want, give me a few days and I will clean it up and adapt it for that purpose.
No, I am talking about GB6.31exxos wrote: 15 Dec 2022 18:59Are you referring to GB4 here ?ijor wrote: 15 Dec 2022 17:15 1 - GB, as I can see, performs a rough synchronization with the timer interrupt. But this is not an exact synchronization. Then sometimes you start a few cycles later, or a few cycles earlier in relation to the previous timer interrupt.
2 - The vertical blank interrupt is not disabled. And of course, there is no synchronization with the video timing at all. Then the number of times the code will be interrupted is not always exactly the same.
......
It does synchronize to the timer interrupt. But as I was saying, it is an approximate synchronization, not an exact one. It will have some, small, jitter.GB6 synchronises the start time in assembly code and also synchronises to the VBL.
Yeah, that was a very good thing to implement.It also disables interrupts as moving the mouse can cause a huge speed difference of like 20% etc. @dml write those routines way back when I started developing GB6.
This code replaces the system vertical interrupt. But there is no attempt to synchronize with the vertical blank at all. Again, synchronizing with both the timer and the vertical blank interrupts is not really feasible unless you alter sync or modify the system timer, and even then it will never be 100% exact.Code: Select all
sys_sleep: *-----------------------------------------------------------------------------* lea sys_state(pc),a0 ori.w #$0700,sr move.l $70.w,(a0)+ move.l $114.w,(a0)+ lea new_vbi(pc),a1 move.l a1,$70.w lea new_tc(pc),a1 move.l a1,timerc.w andi.w #$f3ff,sr rts ... new_vbi: addq.l #1,$462.w addq.l #1,$466.w rte
I think they do are doing what they are supposed to do. They are not 100% exact because that was never the goal, and indeed, they don't need to be exact for benchmarking purposes.Of course if you are saying these routines are not doing what they are supposed to be doing then they can be modified of course. They not exactly been checked since they were written years ago.
I don't think there is much to do. It might be possible to implement some very minor improvements in terms of accuracy. But again, a benchmarking tool needs to be flexible more than being 100% accurate. Or otherwise you might get compatibility problems.Indeed. Using the system timer is never going to be 100% accurate. GB6 while still occasionally hits 99% scores, it is a lot more accurate than GB4 was. That could easily have a 5% variation. I'm not sure anything else could really be improved upon unless there is some way of generating a more accurate / faster timer to compare to ?
I will see if I can find the original emails where we was discussing it. I think he waited for the vbl and the next time a tick as the reference point but this is going back some years to don't exactly remember. I do remember during development it was tested both ways and did not seem to make any difference. I thought that code was left in place.ijor wrote: 15 Dec 2022 19:35 It doesn't synchronize to VBL at all. It is actually not feasible to synchronize to both interrupts at the same time because they are asynchronous one from the other.
Indeed it I did not take that as a criticism. It just somewhat puzzled me over your comments. As sounded like you was referring to GB4, which does not make any attempt to sync or turn off interrupts IIRC.I don't think there is much to do. It might be possible to implement some very minor improvements in terms of accuracy. But again, a benchmarking tool needs to be flexible more than being 100% accurate. Or otherwise you might get compatibility problems.
I wasn't criticizing GB at all. I think it is a great tool. I was just elaborating about why occasionally you get a 1% score variation.
sys_sleep replaces the TOS VBL (50hz display refresh) interrupt and the TimerC (200Hz timer) interrupt with a dummy one that simply returns immediately. This eliminates the cost of both of those interrupts - since they are not free and steal a few % CPU each, all the time. So turning them off gains you a few % CPU plus increased short-term timing stability.
However turning off these timers is probably not wise when running AES/VDI tests because those systems may actually wait on one or both timers in some areas of their code. If some VDI/AES benchmarks seem to freeze with sys_sleep in use, that'll be why. It was provided mainly for getting accurate times on low-level processes like RAM tests and integer/float calculations....
sys_acia_off disables the intelligent keyboard device, which listens for hardware mouse and keyboard events. It does this by writing commands to the IKBD processor via one of the two 6850 ACIAs. The commands are in small tables, and can be found in any book on the Atari ST covering IKBD functions.
sys_acia_off, sys_acia_reset, sys_acia_on are more or less identical functions but they write different data - there's one table for each of them.
When you use sys_acia_off, you must restore the system later with sys_acia_on (it may be best to issue a sys_acia_reset before turning back on but its probably not required). Failing to turn the IKBD back on with sys_acia_on means no more mouse or keyboard input until you power cycle the machine ;)
These functions were provided to stop accidental mouse movements from throwing benchmark timings out, by up to 5%.
Forgot to add, for the 'hardware' side of things:
sys_sleep only interacts with the CPU & MFP exception vectors, which are all stored at low addresses $8-$200 or thereabouts. These are also stored in normal ram - so I can't imagine writing them (as this function does) would fail at 16mhz, as its no different from writing any other RAM location.
It does not interact at all with the MFP's hardware register address space. So I can't see how it would lead to problems with the MFP itself. It continues doing what it was doing before - the only difference is the CPU responds by calling different code, when an MFP interrupt calls the TimerC/$114 interrupt vector.
The VBL interrupt vector ($70) isn't even managed by the MFP - it's a CPU autovector IIRC, so the signal goes direct from the shifter to the CPU. And its not disturbed by this function - it continues to do that, but the CPU calls a different interrupt routine in response.
sys_acia_off is a bit different - it's writing commands to the 6850 ACIA through its control/data ports - these are 8-bit memory-mapped ports in the hardware register address space $FFFF8C00, $FFFF8C02. Communication with this chip is slow and probably asynchronous - the device is fed by a 500KHz clock (IIRC?) which is divided off the system clock by the GLUE/MMU. So an overclocked machine might have issues talking to that chip reliably and the consequence would be unreliable or no keyboard/mouse function, even when reset/restored properly.
The 99% issue can still be rounding-related. Its more likely to happen on wobbly tests such as VDI,AES which is big and complex with unclear initial conditions. The asm tests are less likely to flake but still could, if rounding downwards without an offset.
> my_timer&=SPEEKL(&h4ba)
Yes this should *probably* be done in asm because it is time-critical -. If we can fix sys_tstart and sys_tstop to return the time properly, it should work ok. However I suspect rounding will be the main source of wobbly numbers.
You want to do the sync-lock before recording the start time, and before calling the test.
You don't want to do it after the test, as it would just add 0.005s guaranteed.
However regardless of this, it's not the only source of wobble or imprecision - rounding could be more of an issue overall.
I do recommend though that if you decide to stick with the BASIC version, make sure you do the sync-lock (i.e. wait for counter to change) before recording the start time and calling the test. It makes the difference of up to 0.005 secs (1/200th sec).
The *5 is "result&=SPEEKL(&h4ba)*5&" Though it does /1000 to get the seconds for GB6 results. I don't know if there is a better way of doing that calculation.Yes if you look at the ASM code right near the bottom sys_tstart - it reads the $4D2 timer/counter address and waits for it to change - then it saves the timer value and returns immediately. Same as you described in your email below.
The sys_tstop call just recovers the new $4D2 counter and subtracts the start counter, to get the delta - stuffs it in the params field, and returns. This is all done very quickly.
You can do this in BASIC and it will probably be ok - but there is some small delay involved. I can't guess what it is or whether it will affect you or not. I provided the ASM versions in case they improve precision but you can ignore if the BASIC version is fine and stable.
I don't quite understand your *5 correction calculation there but I can explain what I do in my own benchmark program to get accurate results. It should translate to BASIC without hassles. You just need the TimerC counter delta and a bit of arithmetic....
Code: Select all
FORMATS$(result&/1000!,"###.###")EDIT2:* if you're going to use the extra timing functions I suggest this pattern:
sys_sleep
sys_tstart
<test>
sys_tstop <- returns elapsed 200Hz ticks in the 'params' field i.e. where you passed the loopcount for the call
sys_wake
...and if you have any problems with sys_sleep/wake, just take them out and let me know. It should be fine for the ASM tests but you might have problems with lockups if you use them with the AES/VDI. mileage may vary!
* sys_tstart performs a synchronize with TimerC before starting the test. this involves an artificial delay (it waits until the counter changes once before proceeding to get a sync-lock), so don't use it if you're doing your own timing around it. Use sys_tstart/tstop OR use your own timer, not both together - or results will be skewed by a random short delay. One thing I'm not very sure about is the latency time for SUPEXEC() calls from BASIC, to start/stop the timer.... I'm assuming its negligible but if not, we can bake the timing calls around the tests directly and skip that whole issue.
* make sure you know how your BASIC language is rounding floating point / mixed numbers. usually they round downwards (to zero), not to nearest or to negative. (subtle difference between rounding to 0 and rounding to negative - the former rounds negative numbers upwards, the latter rounds them downwards! but in your case with +ve numbers you only care about round-to-nearest vs any other).
* Once you know for sure what rounding scheme you are using, you need to deal with the rounding of your %age timing before displaying results. e.g. with round-to-zero/-to-negative, the result 99.999999 will still round to 99% - which you don't want. So you need to add effective 0.5% before rounding this way (for no decimal places - a smaller offset is needed for more decimal places).
* IMO you're far better avoiding calculations using %age ranges completely and work with unit range displaced by digits needed e.g. 10000(.0) = 5 digits = 100.00%, which makes rounding safe & natural when you convert to percent for the final figure. This is far less confusing to work with than messing with percentages in calculations - not least because %age has potentially two different meanings when multiplied... easy to make mistakes with it. Moreso if you're trying to deal with rounding in the same calculations.
* IMO you need at least 2 hidden digits which are never shown, to allow rounding to work properly at all. So for a value of 100.00% represented, you'd best use a range of 100[00].00 in calculations (if you have floating point) or 100[00]00 (if you only have integers to work with). The final 2 digits help with rounding and are thrown away for the final result.