Berzerk Benchmark Source Code





; Berzerk Benchmark tester
; -----------------------
;
; JROK 2013
;
; Purpose
; -------
;
; Run a series of tests on the berzerk hardware to count # of op-codes 
; can be executed in a given frame.
; 
; Use the internal 1/2 frame interrupts as a fixed time references
; and R register as the counter  (R is incremented after each op-code )
;
; Actual values are not as significant as the values are for comparison
; to FPGA based hardware.
;
; The other use is to compare against a bus execution dump of the two
; hardwares boards and compare how the code is executed.
;
;  
; What this does
; --------------
;
; Each area of memory had a different z80 /WAIT characterstic
;
; 1. Video frame memory
; 2. Color RAM memory
; 3. CMOS ( aka. NVRAM ) memory
;
; When accessing 1 & 2 the CPU will be halted when the video generation
; logic needs the memory for the display, so the number of opcodes that
; can be executed in the fixed 1/2 frame time period is reduced because
; of the forced wait.
;
;
; for area 3 the CPU has free unrestricted access
;
;
; Results
; -------
;
; When used for comparison purposes, the results of the counts 
; from memory access must be identical. Otherwise bus timings 
; are incorrectly implemented. 
;
; THERE CAN BE NO VARIANCE OR SOMETHING IS VERY WRONG !!!!!
; 
;
; This can be compiled TASM Z80 Assembler.Version 3.1
; http://home.comcast.net/~tasm/
;
; all the source needed is here, just burn to 2716 EPROM or
; DS1220 and replace "ROM0" on a berzerk boardset
;


CMOS_base	.equ	$0000


timing_ptr	.equ	$B00+CMOS_base
irq_flag	.equ	$B02+CMOS_base
nmi_count	.equ	$B04+CMOS_base
run_count	.equ	$B06+CMOS_base


timer_ptr_start	.equ	$a00+CMOS_base
stack_start	.equ	$bff+CMOS_base


IRQ_ACK		.equ	$4e

NMI_TEST_COUNT	.equ	24





	.org $0
	
	di
	xor	a
	out 	($4d),a ; -- Clear NMI
	out 	($67),a ; -- Clear LED

	jp	start_up


	; ------------
	; Interrupt
	; ------------

	.org $38

	push	af
	push	hl

	ld	a, ( irq_flag )
	xor	1
	ld	(irq_flag),a



	in	a, ( IRQ_ACK )


	pop	hl
	pop	af

	; enable ints
	ei

	reti


	.org	$66

	; -----------------
	; NMI testing code
	; -----------------


	push	af
	push	hl

	ld	a, ( nmi_count )
	cp	NMI_TEST_COUNT 	; do a number of NMI counts
	jr	z, 	nmi_all_done

	inc	a
	ld	(nmi_count),a


	ld 	hl, ( timing_ptr )
	ld	a,r
	ld	(hl), a
	inc	l
	inc	l
	ld	( timing_ptr), hl

	; reset R
	xor	a
	ld	r,a

nmi_all_done:

	pop 	hl
	pop 	af
	retn



	; ------------
	; main code
	; ------------

	.org $100
start_up:
	ld	sp, stack_start ; end of SRAM area


	ld	hl, $4000
	ld	de, $4001
	ld	bc, $2000
	ld	(hl),$aa
	ldir


	ld	hl, $8000
	ld	de, $8001
	ld	bc, $1000
	ld	(hl),$FF
	ldir


	; uncomment for looping version
	;
	;ld	hl, 0
	;ld	(run_count), hl

RESTART_TESTING:


	; 256 entry circular buffer
	ld	hl, timer_ptr_start
	ld	( timing_ptr), hl

	ld	b,0
	xor	a
clr_record_mem:	
	ld	(hl),a
	inc	hl
	djnz	clr_record_mem


	; wait for BoF 
	; as the next IRQ would then be Top of Frame

wt_BOF:	
	in	a, ( IRQ_ACK ) ; ALSO include frame V256
	rra
	jr 	nc,	wt_BOF
	; bottom of frame start up IRQ's


	im 	1
	ld	a, $ff
	out 	($4f),a  ; IRQ's are a go
	ei

	; interrupts are ON
	; Next IRQ will be the mid screen ( line 128 interrupt )
	
	halt
	nop

	; mid screen IRQ has happened
	; next interrupt will be the lower 'blanking' end of display IRQ
	; at line 256


	; system is now at the starting point for comparison purposes
	; any comparisons should by synchronized by this point

	



	; out to a dummy port for easier triggering of the analyzer
	out	($98),a



	; -----------------------------
	; test 1
	; ------------------------------
	; memory access includes timing of hitting
	; display fetch /WAIT condition
	; the video frame buffer VRAM test


	ld	hl,( timing_ptr )
	ld	(hl),$AA
	inc	hl
	ld	(hl),$AA
	inc	hl
	ld	( timing_ptr),hl


	ld	b,8 ; 8 tests

test1_lop1:

	ld	a,( irq_flag )
	ld	c,a		

	xor	a
	ld	r,a

	; each loop takes 35 cycles
	; waiting for the 1/2 frame interrupt

test1_EOF:

	ld	de,( $4400 ) ; in VRAM space


	ld	a,( irq_flag )
	cp	c
	jr	z, test1_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl
	
	halt	; skip second IRQ in the frame
	djnz	test1_lop1


	ld	( timing_ptr ),hl

	; -----------------------------
	; test 1A
	; ------------------------------
	; test the mid-screen IRQ

	halt ; skip End-of-frame IRQ

	; now waiting for mid-screen IRQ

	ld	hl,( timing_ptr )
	ld	(hl),$5A
	inc	hl
	ld	(hl),$5A
	inc	hl
	ld	( timing_ptr),hl

	ld	b,8 ; 8 tests

test1a_lop1:

	ld	a,( irq_flag )
	ld	c,a
	xor	a
	ld	r,a

test1a_EOF:

	ld	de,( $4400 ) ; in VRAM space
	

	ld	a, ( irq_flag )
	cp	c
	jr	z, test1a_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl

	halt
	djnz	test1a_lop1
	ld	(timing_ptr),hl



	; -------------------------------
	; test 2
	; memory access CMOS ram
	; will not incur timing penalty
	; --------------------------------

	halt ; skip mid-screen, back to EoF irq



	ld	hl,( timing_ptr )
	ld	(hl),$44
	inc	hl
	ld	(hl),$44
	inc	hl
	ld	( timing_ptr),hl

	ld	b,8 ; 8 tests

test2_lop1:

	ld	a,( irq_flag )
	ld	c,a
	xor	a
	ld	r,a

test2_EOF:

	ld	de,( $0800 ) ; in CMOS
	

	ld	a, ( irq_flag )
	cp	c
	jr	z, test2_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl

	halt
	djnz	test2_lop1

	ld	( timing_ptr),hl


	; -------------------------------
	; test 2A mid IRQ
	; memory access CMOS ram
	; will not incur timing penalty
	; --------------------------------

	halt ; skip EOF, back to mid-screen



	ld	hl,( timing_ptr )
	ld	(hl),$4A
	inc	hl
	ld	(hl),$4A
	inc	hl
	ld	( timing_ptr),hl

	ld	b,8 ; 8 tests

test2a_lop1:

	ld	a,( irq_flag )
	ld	c,a
	xor	a
	ld	r,a

test2a_EOF:

	ld	de,( $0800 ) ; in CMOS
	

	ld	a, ( irq_flag )
	cp	c
	jr	z, test2a_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl

	halt
	djnz	test2a_lop1

	ld	( timing_ptr),hl



	; -----------------------------
	; test 3
	; ------------------------------

	; memory access includes timing of hitting
	; COLOR RAM display fetch /WAIT
	; testing the BSC board


	halt ; skip mid-screen, back to EoF irq



	ld	hl,( timing_ptr )
	ld	(hl),$66
	inc	hl
	ld	(hl),$66
	inc	hl
	ld	( timing_ptr),hl

	out 	($98),a

	ld	b,8 ; 8 tests

test3_lop1:

	ld	a,( irq_flag )
	ld	c,a
	xor	a
	ld	r,a

test3_EOF:

	ld	de,( $8800 )  ; in Color RAM ( BSC board )


	ld	a, ( irq_flag )
	cp	c
	jr	z, test3_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl

	halt
	djnz	test3_lop1

	ld	( timing_ptr),hl


	; -------------------------------
	; test 3A odd
	; --------------------------------

	halt ; skip EOF, back to mid-screen



	ld	hl,( timing_ptr )
	ld	(hl),$6C
	inc	hl
	ld	(hl),$6C
	inc	hl
	ld	( timing_ptr),hl

	ld	b,8 ; 8 tests

test3a_lop1:

	ld	a,( irq_flag )
	ld	c,a
	xor	a
	ld	r,a

test3a_EOF:

	ld	de,( $8800 ) ; in Color RAM ( BSC board )

	ld	a, ( irq_flag )
	cp	c
	jr	z, test3a_EOF

	ld	a,r
	ld	(hl),a
	inc	hl
	inc	hl

	halt
	djnz	test3a_lop1

	ld	( timing_ptr),hl


	; -------------------------------
	; test NMI
	; NMI counting
	; --------------------------------

	; # of instructions that can execute 
	; during each NMI period

	; NMI every 32 vertical lines
	; except for the 7th & 8th which is 37 lines

	; test 18 NMI's



	; NMI timer stuff
	di ; kill normal interrupts


	; dummy port for analyzer triggering
	out ($97),a


	ld	(hl), $FF
	inc	hl
	ld	(hl), $FF
	inc	hl

	ld	( timing_ptr),hl


	; # of nmi's to record
	xor	a
	ld	(nmi_count),a
	

	; wait for bottom of frame
wt_BOF2:	
	in	a, ( IRQ_ACK ) ; ALSO include frame V256
	rra
	jr 	nc,	wt_BOF2

	
	out 	($4c),a ; -- power up the NMI

	xor	a
	ld	r,a


test7_wt_nmi_end:
	ld	a, ( nmi_count)
	cp	NMI_TEST_COUNT
	jr	nz,test7_wt_nmi_end


	xor	a
	out 	($4d),a ; -- no more NMI's







	
done_testing:

	; ------------------------
	; display the results
	; ------------------------

	di

	ld	l, $23 ; 2nd line of display area
	ld	de, timer_ptr_start + 2


	ld	b,3

dt_show_lop:
	ld	h, $45 ; screen upper

	push	hl

	ld	a,8
	call	show_results_hex
	ld	h, $4F ; lower screen
	
	inc	de
	inc 	de

	
	ld	a,8
	call	show_results_hex
	pop 	hl

	inc	de
	inc 	de

	ld	a,l
	add	a, $06
	ld	l,a
	ld	h, $45

	djnz	dt_show_lop


	; show the NMI results

	ld	a, NMI_TEST_COUNT
	call	show_results_hex
	pop 	hl



	; VRAM
	ld	hl, $4421
	ld	de, Vtxt
	call	print_str
	
	; vRAM
	ld	hl, $4e21
	ld	de, Vtxt
	call	print_str

	; CMOS
	ld	hl, $4427
	ld	de, Ctxt
	call	print_str
	
	; CMOS
	ld	hl, $4e27
	ld	de, Ctxt
	call	print_str


	; BSC color RAM
	ld	hl, $442d
	ld	de, Btxt
	call	print_str
	
	; BSC color RAM
	ld	hl, $4e2d
	ld	de, Btxt
	call	print_str

	; NMI
	ld	hl, $4433
	ld	de, Ntxt
	call	print_str

	ld	hl,(run_count)
	inc	hl
	ld	(run_count),hl

	; uncomment for loopin version
	; results come out the same...
	; 
	; 
	;ld	de, run_count
	;ld	hl, $5a03 ; lower screen
	;ld	a,1
	;call	show_results_hex


lopit:			         


	; uncomment for loopin version
	; results come out the same...
	; 
	; jp	RESTART_TESTING

	jr	lopit

; -----------------------------------------
show_results_hex:
; -----------------------------------------

	push	hl
	push	bc

	ld	b, a

dis_all_vals:

	push	hl

	ld	a,(de)
	call	print_hex
	dec	hl
	dec	hl
	dec	hl

	inc	de
	ld	a,(de)
	call	print_hex


	inc	de

	pop	hl
	inc	h
	
	djnz	dis_all_vals

	pop 	bc
	pop 	hl

	ret

; -----------------------------------------
print_hex:
; -----------------------------------------
	push 	af
	rra	
	rra
	rra
	rra
	and	$0f	
	call 	print_char
	pop 	af
	and	$0f	
	inc	hl
	call 	print_char
	ret


; -----------------------------------------
print_str:
; -----------------------------------------

	; HL = position
	; DE = string (Zero terminated )
	

	ld	a,(de)
	and	a
	ret	z

	call 	print_char
	inc	hl
	inc	de
	jr	print_str





; -----------------------------------------
print_char:
; -----------------------------------------
	push af
	push bc
	push de
	push hl


	; HL = position on screen
	; A  = character to print 
	;
	; (font) = 8 bytes

	ld	b,0
	ld	c,a

	ex	de,hl
	ld	hl, font
	add	hl,bc
	add	hl,bc
	add	hl,bc
	add	hl,bc
	add	hl,bc
	add	hl,bc
	add	hl,bc
	add	hl,bc


	ld bc,32 ; add value
	
	ex	de,hl


	ld a,8

	
pc_nc1_wr_NR:
	push	af
	ld	a,(de)
	ld	(hl),a
	inc	de
	add	hl,bc
	pop	af

	dec a
	jr nz, pc_nc1_wr_NR


	pop hl
	pop de
	pop bc
	pop af

	ret

Vtxt:	.db "VRAM",0
Btxt:	.db "BSC ",0
Ctxt:	.db "CMOS",0
Ntxt:	.db "NMI ",0
	


font:

          .db  $00, $3C, $66, $6E, $76, $66, $3C, $00, $00, $18, $78, $18, $18, $18, $7E, $00 ; 0 1  = 0x30
          .db  $00, $3C, $66, $06, $3C, $60, $7E, $00, $00, $3C, $66, $1C, $06, $66, $3C, $00 ; 2 3
          .db  $00, $6C, $6C, $6C, $6C, $3E, $0C, $00, $00, $7E, $60, $7C, $06, $66, $3C, $00 ; 4 5
          .db  $00, $3C, $60, $7C, $66, $66, $3C, $00, $00, $7E, $06, $0C, $18, $18, $18, $00 ; 6 7
          .db  $00, $3C, $66, $3C, $66, $66, $3C, $00, $00, $3C, $66, $66, $3E, $06, $3C, $00 ; 8 9
	  .db  $00, $3C, $66, $66, $7E, $66, $66, $00, $00, $7C, $66, $7C, $66, $66, $7C, $00 ; A B
	  .db  $00, $3C, $66, $60, $60, $66, $3C, $00, $00, $7C, $66, $66, $66, $66, $7C, $00 ; C D 
	  .db  $00, $7E, $60, $78, $60, $60, $7E, $00, $00, $7E, $60, $78, $60, $60, $60, $00 ; E F

	  ; @10
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $10
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $12
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $14
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $16
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $18
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $1A
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $1C
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00 ; $1E


	  ; @20
          .db  $00, $00, $00, $00, $00, $00, $00, $00, $18, $18, $18, $18, $00, $18, $18, $00 ; space !
          .db  $36, $36, $6C, $00, $00, $00, $00, $00, $00, $36, $7F, $36, $7F, $36, $00, $00 ; " #
          .db  $00, $18, $3E, $60, $3C, $06, $7C, $18, $00, $22, $74, $28, $14, $2E, $44, $00 ; $ %
          .db  $00, $3C, $60, $3F, $66, $66, $3C, $00, $18, $18, $30, $00, $00, $00, $00, $00 ; & '
          .db  $0C, $10, $30, $30, $30, $30, $10, $0C, $30, $08, $0C, $0C, $0C, $0C, $08, $30 ; ( )
          .db  $00, $24, $18, $7E, $18, $24, $00, $00, $00, $18, $18, $7E, $18, $18, $00, $00 ; * +
          .db  $00, $00, $00, $00, $00, $18, $18, $30, $00, $00, $00, $7E, $00, $00, $00, $00 ; ` -
          .db  $00, $00, $00, $00, $00, $18, $18, $00, $02, $06, $0C, $18, $30, $60, $40, $00 ; . /

          .db  $00, $3C, $66, $6E, $76, $66, $3C, $00, $00, $18, $78, $18, $18, $18, $7E, $00 ; 0 1  = 0x30
          .db  $00, $3C, $66, $06, $3C, $60, $7E, $00, $00, $3C, $66, $1C, $06, $66, $3C, $00 ; 2 3
          .db  $00, $6C, $6C, $6C, $6C, $3E, $0C, $00, $00, $7E, $60, $7C, $06, $66, $3C, $00 ; 4 5
          .db  $00, $3C, $60, $7C, $66, $66, $3C, $00, $00, $7E, $06, $0C, $18, $18, $18, $00 ; 6 7
          .db  $00, $3C, $66, $3C, $66, $66, $3C, $00, $00, $3C, $66, $66, $3E, $06, $3C, $00 ; 8 9
          .db  $00, $00, $18, $18, $00, $18, $18, $00, $00, $00, $18, $18, $00, $18, $18, $30 ; : ;
          .db  $00, $0C, $18, $30, $18, $0C, $00, $00, $00, $00, $7E, $00, $7E, $00, $00, $00 ; < =
          .db  $00, $30, $18, $0C, $18, $30, $00, $00, $3C, $66, $06, $1C, $00, $18, $18, $00 ; > ?
												    
          .db  $00, $1E, $23, $4F, $5B, $4F, $20, $1E, $00, $3C, $66, $66, $7E, $66, $66, $00 ; @ A  = 0x40
          .db  $00, $7C, $66, $7C, $66, $66, $7C, $00, $00, $3C, $66, $60, $60, $66, $3C, $00 ; B C
          .db  $00, $7C, $66, $66, $66, $66, $7C, $00, $00, $7E, $60, $78, $60, $60, $7E, $00 ; D E
          .db  $00, $7E, $60, $78, $60, $60, $60, $00, $00, $3C, $66, $60, $6E, $66, $3C, $00 ; F G
          .db  $00, $66, $66, $7E, $66, $66, $66, $00, $00, $7E, $18, $18, $18, $18, $7E, $00 ; H I
          .db  $00, $06, $06, $06, $06, $66, $3C, $00, $00, $66, $6C, $78, $78, $6C, $66, $00 ; J K
          .db  $00, $60, $60, $60, $60, $60, $7E, $00, $00, $63, $77, $7F, $6B, $63, $63, $00 ; L M
          .db  $00, $66, $76, $7E, $6E, $66, $66, $00, $00, $3C, $66, $66, $66, $66, $3C, $00 ; N O

          .db  $00, $7C, $66, $66, $7C, $60, $60, $00, $00, $3C, $66, $66, $66, $6E, $3C, $06 ; P Q = 0x50
          .db  $00, $7C, $66, $66, $7C, $6C, $66, $00, $00, $3C, $60, $3C, $06, $66, $3C, $00 ; R S
          .db  $00, $7E, $18, $18, $18, $18, $18, $00, $00, $66, $66, $66, $66, $66, $3C, $00 ; T U
          .db  $00, $66, $66, $66, $66, $3C, $18, $00, $00, $63, $63, $63, $6B, $7F, $36, $00 ; V W
          .db  $00, $66, $3C, $18, $18, $3C, $66, $00, $00, $66, $66, $3C, $18, $18, $18, $00 ; X Y
          .db  $00, $7E, $0C, $18, $30, $60, $7E, $00, $3C, $30, $30, $30, $30, $30, $30, $3C ; Z [
          .db  $40, $60, $30, $18, $0C, $06, $02, $00, $3C, $0C, $0C, $0C, $0C, $0C, $0C, $3C ; \ ]
          .db  $18, $2C, $46, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $00, $7E ; ^ _

          .db  $00, $1C, $30, $7C, $30, $32, $7C, $00, $00, $00, $3C, $06, $3E, $66, $3E, $00 ; ` a
          .db  $60, $60, $7C, $66, $66, $66, $7C, $00, $00, $00, $3C, $66, $60, $66, $3C, $00 ; b c
          .db  $06, $06, $3E, $66, $66, $66, $3E, $00, $00, $00, $3C, $66, $7C, $60, $3C, $00
          .db  $1C, $36, $30, $7E, $30, $30, $30, $00, $00, $00, $3C, $66, $66, $3E, $06, $3C
          .db  $60, $60, $7C, $66, $66, $66, $66, $00, $18, $00, $38, $18, $18, $18, $3C, $00
          .db  $0C, $00, $0C, $0C, $0C, $0C, $6C, $38, $60, $60, $66, $6C, $78, $6C, $66, $00
          .db  $18, $18, $18, $18, $18, $18, $0E, $00, $00, $00, $FE, $DB, $DB, $DB, $DB, $00
          .db  $00, $00, $7C, $66, $66, $66, $66, $00, $00, $00, $3C, $66, $66, $66, $3C, $00
          .db  $00, $00, $7C, $66, $66, $7C, $60, $60, $00, $00, $3E, $66, $66, $3E, $06, $06
          .db  $00, $00, $3C, $66, $60, $60, $60, $00, $00, $00, $3C, $60, $3C, $06, $7C, $00
          .db  $00, $30, $7E, $30, $30, $36, $1C, $00, $00, $00, $66, $66, $66, $66, $3C, $00
          .db  $00, $00, $66, $66, $66, $3C, $18, $00, $00, $00, $DB, $DB, $DB, $DB, $7E, $00
          .db  $00, $00, $66, $3C, $18, $3C, $66, $00, $00, $00, $66, $66, $66, $3E, $06, $3C
          .db  $00, $00, $7E, $0C, $18, $30, $7E, $00, $1C, $30, $30, $60, $30, $30, $30, $1C
          .db  $08, $08, $08, $08, $08, $08, $08, $00, $38, $0C, $0C, $06, $0C, $0C, $0C, $38
          .db  $00, $00, $30, $5A, $0C, $00, $00, $00, $00, $1C, $22, $5D, $71, $5D, $22, $1C

	  ;  char 128 onwares
	  ;  DIP off

	  .db  $ff,$ff,$ff,$ff,$ff,$ff,$ff,$ff

	  .end