filename | test/testta.c |
changeset | 754:35c496703380 |
prev | 561:533f6b478071 |
author | nkeynes |
date | Mon Mar 05 11:41:03 2012 +1000 (12 years ago) |
permissions | -rw-r--r-- |
last change | Small cleanups: Refactor the post-windowing setup into gl_init_driver() in video_gl.c Move gl_sl.c into src/drivers and tidy up a bit. Fix OS X compiling plugins with -mdynamic-no-pic |
file | annotate | diff | log | raw |
nkeynes@185 | 1 | /** |
nkeynes@561 | 2 | * $Id$ |
nkeynes@185 | 3 | * |
nkeynes@185 | 4 | * Tile Accelerator test cases |
nkeynes@185 | 5 | * |
nkeynes@185 | 6 | * Copyright (c) 2006 Nathan Keynes. |
nkeynes@185 | 7 | * |
nkeynes@185 | 8 | * This program is free software; you can redistribute it and/or modify |
nkeynes@185 | 9 | * it under the terms of the GNU General Public License as published by |
nkeynes@185 | 10 | * the Free Software Foundation; either version 2 of the License, or |
nkeynes@185 | 11 | * (at your option) any later version. |
nkeynes@185 | 12 | * |
nkeynes@185 | 13 | * This program is distributed in the hope that it will be useful, |
nkeynes@185 | 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
nkeynes@185 | 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
nkeynes@185 | 16 | * GNU General Public License for more details. |
nkeynes@185 | 17 | */ |
nkeynes@185 | 18 | |
nkeynes@185 | 19 | #include <stdio.h> |
nkeynes@185 | 20 | #include "testdata.h" |
nkeynes@185 | 21 | #include "pvr.h" |
nkeynes@185 | 22 | #include "lib.h" |
nkeynes@185 | 23 | #include "asic.h" |
nkeynes@185 | 24 | |
nkeynes@185 | 25 | #define DMA_ALIGN(x) ((void *)((((unsigned int)(x))+0x1F)&0xFFFFFFE0)) |
nkeynes@185 | 26 | |
nkeynes@185 | 27 | #define OBJ_START 0x00010000 |
nkeynes@190 | 28 | #define OBJ_LENGTH 0x00010000 |
nkeynes@185 | 29 | #define TILE_START 0x00060000 |
nkeynes@190 | 30 | #define TILE_LENGTH 0x00010000 |
nkeynes@190 | 31 | |
nkeynes@190 | 32 | #define MEM_FILL 0xFE |
nkeynes@190 | 33 | |
nkeynes@190 | 34 | int ta_tile_sizes[4] = { 0, 32, 64, 128 }; |
nkeynes@190 | 35 | |
nkeynes@190 | 36 | #define TILE_SIZE(cfg, tile) ta_tile_sizes[((((cfg->ta_cfg) >> (4*tile))&0x03))] |
nkeynes@190 | 37 | |
nkeynes@190 | 38 | struct ta_config default_ta_config = { 0x00111111, GRID_SIZE(640,480), OBJ_START, |
nkeynes@190 | 39 | OBJ_START+OBJ_LENGTH, TILE_START+TILE_LENGTH, |
nkeynes@190 | 40 | TILE_START, TILE_START+TILE_LENGTH }; |
nkeynes@190 | 41 | |
nkeynes@190 | 42 | |
nkeynes@190 | 43 | int tile_sizes[5]; |
nkeynes@190 | 44 | int tile_events[5] = { EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE, |
nkeynes@190 | 45 | EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE, |
nkeynes@190 | 46 | EVENT_PVR_PUNCHOUT_DONE }; |
nkeynes@190 | 47 | char *tile_names[5] = { "Opaque", "Opaque Mod", "Trans", "Trans Mod", "Punch Out" }; |
nkeynes@185 | 48 | |
nkeynes@185 | 49 | #define FLOAT(p) *((float *)(p)) |
nkeynes@185 | 50 | |
nkeynes@190 | 51 | void make_expected_buffer( test_data_block_t expected_block, char *expect, int length ) |
nkeynes@190 | 52 | { |
nkeynes@190 | 53 | memset( expect, MEM_FILL,length ); |
nkeynes@190 | 54 | |
nkeynes@190 | 55 | if( expected_block != NULL ) { |
nkeynes@190 | 56 | if( expected_block->length > length ) { |
nkeynes@190 | 57 | fprintf( stderr, "Test data error: expected tile length is %d, but tile size is only %d\n", expected_block->length, length ); |
nkeynes@190 | 58 | return; |
nkeynes@190 | 59 | } |
nkeynes@190 | 60 | memcpy( expect, expected_block->data, expected_block->length ); |
nkeynes@190 | 61 | |
nkeynes@190 | 62 | if( expected_block->length <= length-4 ) { |
nkeynes@190 | 63 | *((unsigned int *)&expect[expected_block->length]) = 0xF0000000; |
nkeynes@190 | 64 | } |
nkeynes@190 | 65 | } |
nkeynes@190 | 66 | } |
nkeynes@190 | 67 | |
nkeynes@190 | 68 | int tilematrix_block_compare( test_data_block_t expected_block, char *tile_ptrs[], int tile_type, int offset ) |
nkeynes@190 | 69 | { |
nkeynes@190 | 70 | int tile_size = tile_sizes[tile_type]; |
nkeynes@190 | 71 | char expect[tile_size]; |
nkeynes@190 | 72 | |
nkeynes@190 | 73 | make_expected_buffer(expected_block, expect, tile_size); |
nkeynes@190 | 74 | return memcmp( expect, tile_ptrs[tile_type]+(offset*tile_sizes[tile_type]), tile_size ); |
nkeynes@190 | 75 | } |
nkeynes@190 | 76 | |
nkeynes@212 | 77 | /** |
nkeynes@212 | 78 | * Copy from vram, wrapping appropriately |
nkeynes@212 | 79 | */ |
nkeynes@212 | 80 | int memcpy_from_vram( char *dest, char *src, int len ) |
nkeynes@212 | 81 | { |
nkeynes@212 | 82 | while( len > 0 ) { |
nkeynes@212 | 83 | *dest++ = *src++; |
nkeynes@212 | 84 | src = (char *)( ((unsigned int)src) & 0xFF7FFFFF ); |
nkeynes@212 | 85 | len--; |
nkeynes@212 | 86 | } |
nkeynes@212 | 87 | } |
nkeynes@212 | 88 | |
nkeynes@185 | 89 | int test_ta( test_data_t test_case ) |
nkeynes@185 | 90 | { |
nkeynes@185 | 91 | char buf[1024]; |
nkeynes@185 | 92 | unsigned int *p = DMA_ALIGN(buf); |
nkeynes@185 | 93 | unsigned int *data = p; |
nkeynes@190 | 94 | int haveFailure = 0; |
nkeynes@190 | 95 | int checkedTile[5] = {0,0,0,0,0}; |
nkeynes@190 | 96 | int i; |
nkeynes@190 | 97 | int hsegs,vsegs; |
nkeynes@190 | 98 | char *tile_ptrs[5]; |
nkeynes@185 | 99 | |
nkeynes@185 | 100 | asic_clear(); |
nkeynes@185 | 101 | |
nkeynes@190 | 102 | memset( PVR_VRAM_BASE, MEM_FILL, 0x00090000 ); |
nkeynes@190 | 103 | test_data_block_t config_data = get_test_data( test_case, "config" ); |
nkeynes@190 | 104 | struct ta_config *config = &default_ta_config; |
nkeynes@190 | 105 | if( config_data != NULL ) { |
nkeynes@190 | 106 | if( config_data->length != sizeof(struct ta_config) ) { |
nkeynes@190 | 107 | fprintf( stderr, "Invalid config data length %d - aborting test %s\n", |
nkeynes@190 | 108 | config_data->length, test_case->test_name ); |
nkeynes@190 | 109 | return -1; |
nkeynes@190 | 110 | } |
nkeynes@190 | 111 | config = (struct ta_config *)config_data->data; |
nkeynes@190 | 112 | } |
nkeynes@212 | 113 | char *result = (char *)(PVR_VRAM_BASE+config->obj_start); |
nkeynes@212 | 114 | char *tilematrix = (char *)(PVR_VRAM_BASE+config->tile_start); |
nkeynes@212 | 115 | |
nkeynes@190 | 116 | ta_init(config); |
nkeynes@190 | 117 | for( i=0; i<5; i++ ) { |
nkeynes@190 | 118 | tile_sizes[i] = TILE_SIZE(config,i); |
nkeynes@190 | 119 | } |
nkeynes@190 | 120 | hsegs = (config->grid_size & 0xFFFF)+1; |
nkeynes@190 | 121 | vsegs = (config->grid_size >> 16) + 1; |
nkeynes@190 | 122 | tile_ptrs[0] = tilematrix; |
nkeynes@190 | 123 | tile_ptrs[1] = tile_ptrs[0] + (hsegs*vsegs*tile_sizes[0]); |
nkeynes@190 | 124 | tile_ptrs[2] = tile_ptrs[1] + (hsegs*vsegs*tile_sizes[1]); |
nkeynes@190 | 125 | tile_ptrs[3] = tile_ptrs[2] + (hsegs*vsegs*tile_sizes[2]); |
nkeynes@190 | 126 | tile_ptrs[4] = tile_ptrs[3] + (hsegs*vsegs*tile_sizes[3]); |
nkeynes@190 | 127 | |
nkeynes@185 | 128 | |
nkeynes@185 | 129 | test_data_block_t input = get_test_data(test_case, "input"); |
nkeynes@212 | 130 | test_data_block_t input2 = get_test_data(test_case, "input2"); |
nkeynes@185 | 131 | test_data_block_t output = get_test_data(test_case, "output"); |
nkeynes@190 | 132 | test_data_block_t error = get_test_data(test_case, "error"); |
nkeynes@754 | 133 | test_data_block_t sortconf = get_test_data(test_case, "sortconf"); |
nkeynes@754 | 134 | test_data_block_t sorttab = get_test_data(test_case, "sorttab"); |
nkeynes@754 | 135 | |
nkeynes@185 | 136 | if( input == NULL || output == NULL ) { |
nkeynes@185 | 137 | fprintf( stderr, "Skipping test case '%s': data incomplete\n", test_case->test_name ); |
nkeynes@185 | 138 | return -1; |
nkeynes@185 | 139 | } |
nkeynes@185 | 140 | |
nkeynes@754 | 141 | if( sortconf != NULL && sorttab != NULL ) { |
nkeynes@754 | 142 | if( sortconf->length != 8 ) { |
nkeynes@754 | 143 | fprintf( stderr, "Invalid sort config length: %d - abort test %s\n", |
nkeynes@754 | 144 | sortconf->length, test_case->test_name ); |
nkeynes@754 | 145 | return -1; |
nkeynes@754 | 146 | } |
nkeynes@754 | 147 | uint32_t *sc = (uint32_t *)sortconf->data; |
nkeynes@754 | 148 | if( sort_dma_write( sorttab->data, sorttab->length, input->data, input->length, *sc, *(sc+1) ) == -1 ){ |
nkeynes@754 | 149 | return -1; |
nkeynes@754 | 150 | } |
nkeynes@754 | 151 | } else { |
nkeynes@754 | 152 | if( pvr_dma_write( 0x10000000, input->data, input->length, 0 ) == -1 ) { |
nkeynes@754 | 153 | return -1; |
nkeynes@754 | 154 | } |
nkeynes@185 | 155 | } |
nkeynes@190 | 156 | |
nkeynes@212 | 157 | if( input2 != NULL ) { |
nkeynes@754 | 158 | ta_reinit(); |
nkeynes@754 | 159 | pvr_dma_write( 0x10000000, input2->data, input2->length, 0 ); |
nkeynes@212 | 160 | } |
nkeynes@212 | 161 | |
nkeynes@212 | 162 | |
nkeynes@190 | 163 | if( error != NULL ) { |
nkeynes@190 | 164 | for( i=0; i<error->length; i++ ) { |
nkeynes@190 | 165 | if( asic_wait( error->data[i] ) == -1 ) { |
nkeynes@190 | 166 | fprintf( stderr, "Test %s: failed (Timeout waiting for error event %d)\n", |
nkeynes@190 | 167 | test_case->test_name, error->data[i] ); |
nkeynes@190 | 168 | asic_dump( stderr ); |
nkeynes@190 | 169 | return -1; |
nkeynes@190 | 170 | } |
nkeynes@190 | 171 | } |
nkeynes@185 | 172 | } |
nkeynes@185 | 173 | |
nkeynes@190 | 174 | for( i=0; i<MAX_DATA_BLOCKS; i++ ) { |
nkeynes@190 | 175 | test_data_block_t data = &test_case->item[i]; |
nkeynes@190 | 176 | int tile, x, y, offset; |
nkeynes@190 | 177 | if( data->name != NULL ) { |
nkeynes@190 | 178 | int result = sscanf( data->name, "tile %d %dx%d", &tile, &x, &y ); |
nkeynes@190 | 179 | if( result == 1 ) { |
nkeynes@190 | 180 | x = y = 0; |
nkeynes@190 | 181 | } else if( result != 3 ) { |
nkeynes@190 | 182 | continue; |
nkeynes@190 | 183 | } |
nkeynes@190 | 184 | tile--; |
nkeynes@190 | 185 | offset = x + (y * hsegs); |
nkeynes@190 | 186 | |
nkeynes@190 | 187 | if( checkedTile[tile] == 0 ) { |
nkeynes@190 | 188 | if( asic_wait( tile_events[tile] ) == -1 ) { |
nkeynes@190 | 189 | fprintf( stderr, "Test %s: failed (Timeout waiting for %s done event)\n", |
nkeynes@190 | 190 | test_case->test_name, tile_names[tile] ); |
nkeynes@190 | 191 | ta_dump_regs(); |
nkeynes@190 | 192 | asic_dump( stderr ); |
nkeynes@190 | 193 | haveFailure = 1; |
nkeynes@190 | 194 | } |
nkeynes@190 | 195 | } |
nkeynes@190 | 196 | |
nkeynes@190 | 197 | if( tilematrix_block_compare( data, tile_ptrs, tile, offset ) != 0 ) { |
nkeynes@190 | 198 | fprintf( stderr, "Test %s: Failed (%s matrix %dx%d). ", |
nkeynes@190 | 199 | test_case->test_name, tile_names[tile], x, y ); |
nkeynes@190 | 200 | fwrite_diff32( stderr, data->data, data->length, |
nkeynes@190 | 201 | tile_ptrs[tile] + (tile_sizes[tile]*offset), tile_sizes[tile] ); |
nkeynes@190 | 202 | haveFailure = 1; |
nkeynes@190 | 203 | } |
nkeynes@190 | 204 | checkedTile[tile] = 1; |
nkeynes@190 | 205 | } |
nkeynes@190 | 206 | } |
nkeynes@190 | 207 | |
nkeynes@190 | 208 | /* Overflow */ |
nkeynes@190 | 209 | test_data_block_t plist = get_test_data(test_case, "plist" ); |
nkeynes@190 | 210 | if( plist != NULL ) { |
nkeynes@190 | 211 | unsigned int plist_posn, plist_end; |
nkeynes@190 | 212 | if( config->ta_cfg & 0x00100000 ) { /* Descending */ |
nkeynes@193 | 213 | plist_posn = pvr_get_plist_posn(); //+ tile_sizes[0]; |
nkeynes@190 | 214 | plist_end = config->plist_start; |
nkeynes@190 | 215 | } else { |
nkeynes@190 | 216 | plist_posn = config->plist_start; |
nkeynes@193 | 217 | plist_end = pvr_get_plist_posn() + tile_sizes[0]; |
nkeynes@190 | 218 | } |
nkeynes@190 | 219 | char *plist_data = (char *)(PVR_VRAM_BASE + plist_posn); |
nkeynes@190 | 220 | if( test_block_compare( plist, plist_data, plist_end-plist_posn ) != 0 ) { |
nkeynes@190 | 221 | fprintf( stderr, "Test %s: Failed (Plist buffer)", test_case->test_name ); |
nkeynes@190 | 222 | fwrite_diff32( stderr, plist->data, plist->length, (char *)plist_data, |
nkeynes@190 | 223 | plist_end - plist_posn ); |
nkeynes@190 | 224 | haveFailure = 1; |
nkeynes@190 | 225 | } |
nkeynes@193 | 226 | char block[tile_sizes[0]]; |
nkeynes@193 | 227 | memset( block, MEM_FILL, tile_sizes[0] ); |
nkeynes@193 | 228 | if( memcmp( block, plist_data - tile_sizes[0], tile_sizes[0] ) != 0 ) { |
nkeynes@193 | 229 | fprintf( stderr, "Test %s: Failed (Plist buffer)", test_case->test_name ); |
nkeynes@193 | 230 | fwrite_diff32( stderr, block, tile_sizes[0], plist_data - tile_sizes[0], |
nkeynes@193 | 231 | tile_sizes[0]); |
nkeynes@193 | 232 | haveFailure = 1; |
nkeynes@193 | 233 | } |
nkeynes@190 | 234 | } |
nkeynes@190 | 235 | |
nkeynes@190 | 236 | /* Vertex buffer */ |
nkeynes@185 | 237 | int result_length = pvr_get_objbuf_size(); |
nkeynes@212 | 238 | char tmp[result_length]; |
nkeynes@212 | 239 | memcpy_from_vram( tmp, result, result_length ); |
nkeynes@212 | 240 | if( test_block_compare( output, tmp, result_length ) != 0 ) { |
nkeynes@190 | 241 | fprintf( stderr, "Test %s: Failed (Vertex buffer). ", test_case->test_name ); |
nkeynes@212 | 242 | fwrite_diff32( stderr, output->data, output->length, tmp, result_length ); |
nkeynes@190 | 243 | haveFailure = 1; |
nkeynes@185 | 244 | } |
nkeynes@185 | 245 | |
nkeynes@190 | 246 | |
nkeynes@190 | 247 | for( i=0; i<5; i++ ) { |
nkeynes@190 | 248 | if( checkedTile[i] == 0 ) { |
nkeynes@190 | 249 | if( tilematrix_block_compare( NULL, tile_ptrs, i, 0 ) != 0 ) { |
nkeynes@190 | 250 | fprintf( stderr, "Test %s: Failed (%s matrix). ", test_case->test_name, tile_names[i] ); |
nkeynes@190 | 251 | fprintf( stderr, "Expected empty buffer at %08X, but was =>\n", |
nkeynes@190 | 252 | (unsigned int)(tile_ptrs[i]) ); |
nkeynes@190 | 253 | fwrite_dump( stderr, tile_ptrs[i], tile_sizes[i] ); |
nkeynes@190 | 254 | // fwrite_dump( stderr, tile_ptrs[i] - 128, 256 ); |
nkeynes@190 | 255 | |
nkeynes@190 | 256 | } |
nkeynes@190 | 257 | } |
nkeynes@190 | 258 | } |
nkeynes@193 | 259 | |
nkeynes@193 | 260 | if( error == NULL ) { |
nkeynes@193 | 261 | if( asic_check(EVENT_TA_ERROR) || asic_check(EVENT_PVR_PRIM_ALLOC_FAIL) || |
nkeynes@193 | 262 | asic_check(EVENT_PVR_MATRIX_ALLOC_FAIL) || asic_check(EVENT_PVR_BAD_INPUT) ) { |
nkeynes@193 | 263 | fprintf( stderr, "Test %s: Failed (unexpected error events)\n", test_case->test_name ); |
nkeynes@193 | 264 | asic_dump( stderr ); |
nkeynes@193 | 265 | haveFailure = 1; |
nkeynes@193 | 266 | } |
nkeynes@193 | 267 | } |
nkeynes@193 | 268 | |
nkeynes@190 | 269 | if( haveFailure ) |
nkeynes@190 | 270 | return -1; |
nkeynes@190 | 271 | |
nkeynes@190 | 272 | fprintf( stdout, "Test %s: OK\n", test_case->test_name ); |
nkeynes@190 | 273 | return 0; |
nkeynes@185 | 274 | } |
nkeynes@185 | 275 | |
nkeynes@185 | 276 | int main( int argc, char *argv[] ) |
nkeynes@185 | 277 | { |
nkeynes@185 | 278 | int test_cases = 0; |
nkeynes@185 | 279 | int test_failures = 0; |
nkeynes@185 | 280 | test_data_t test_data = load_test_dataset(stdin); |
nkeynes@185 | 281 | test_data_t test_case = test_data; |
nkeynes@185 | 282 | |
nkeynes@185 | 283 | asic_mask_all(); |
nkeynes@185 | 284 | pvr_init(); |
nkeynes@185 | 285 | |
nkeynes@185 | 286 | while( test_case != NULL ) { |
nkeynes@185 | 287 | test_cases++; |
nkeynes@185 | 288 | int result = test_ta(test_case); |
nkeynes@185 | 289 | if( result != 0 ) { |
nkeynes@185 | 290 | test_failures++; |
nkeynes@185 | 291 | } |
nkeynes@185 | 292 | test_case = test_case->next; |
nkeynes@185 | 293 | } |
nkeynes@185 | 294 | free_test_dataset(test_data); |
nkeynes@185 | 295 | if( test_failures != 0 ) { |
nkeynes@185 | 296 | fprintf( stderr, "%d/%d test failures!\n", test_failures, test_cases ); |
nkeynes@185 | 297 | return 1; |
nkeynes@185 | 298 | } else { |
nkeynes@185 | 299 | fprintf( stderr, "%d tests OK\n", test_cases ); |
nkeynes@185 | 300 | return 0; |
nkeynes@185 | 301 | } |
nkeynes@185 | 302 | } |
.