nkeynes@185: /** nkeynes@212: * $Id: testta.c,v 1.4 2006-08-18 09:32:32 nkeynes Exp $ nkeynes@185: * nkeynes@185: * Tile Accelerator test cases nkeynes@185: * nkeynes@185: * Copyright (c) 2006 Nathan Keynes. nkeynes@185: * nkeynes@185: * This program is free software; you can redistribute it and/or modify nkeynes@185: * it under the terms of the GNU General Public License as published by nkeynes@185: * the Free Software Foundation; either version 2 of the License, or nkeynes@185: * (at your option) any later version. nkeynes@185: * nkeynes@185: * This program is distributed in the hope that it will be useful, nkeynes@185: * but WITHOUT ANY WARRANTY; without even the implied warranty of nkeynes@185: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nkeynes@185: * GNU General Public License for more details. nkeynes@185: */ nkeynes@185: nkeynes@185: #include nkeynes@185: #include "testdata.h" nkeynes@185: #include "pvr.h" nkeynes@185: #include "lib.h" nkeynes@185: #include "asic.h" nkeynes@185: nkeynes@185: #define DMA_ALIGN(x) ((void *)((((unsigned int)(x))+0x1F)&0xFFFFFFE0)) nkeynes@185: nkeynes@185: #define OBJ_START 0x00010000 nkeynes@190: #define OBJ_LENGTH 0x00010000 nkeynes@185: #define TILE_START 0x00060000 nkeynes@190: #define TILE_LENGTH 0x00010000 nkeynes@190: nkeynes@190: #define MEM_FILL 0xFE nkeynes@190: nkeynes@190: int ta_tile_sizes[4] = { 0, 32, 64, 128 }; nkeynes@190: nkeynes@190: #define TILE_SIZE(cfg, tile) ta_tile_sizes[((((cfg->ta_cfg) >> (4*tile))&0x03))] nkeynes@190: nkeynes@190: struct ta_config default_ta_config = { 0x00111111, GRID_SIZE(640,480), OBJ_START, nkeynes@190: OBJ_START+OBJ_LENGTH, TILE_START+TILE_LENGTH, nkeynes@190: TILE_START, TILE_START+TILE_LENGTH }; nkeynes@190: nkeynes@190: nkeynes@190: int tile_sizes[5]; nkeynes@190: int tile_events[5] = { EVENT_PVR_OPAQUE_DONE, EVENT_PVR_OPAQUEMOD_DONE, nkeynes@190: EVENT_PVR_TRANS_DONE, EVENT_PVR_TRANSMOD_DONE, nkeynes@190: EVENT_PVR_PUNCHOUT_DONE }; nkeynes@190: char *tile_names[5] = { "Opaque", "Opaque Mod", "Trans", "Trans Mod", "Punch Out" }; nkeynes@185: nkeynes@185: #define FLOAT(p) *((float *)(p)) nkeynes@185: nkeynes@190: void make_expected_buffer( test_data_block_t expected_block, char *expect, int length ) nkeynes@190: { nkeynes@190: memset( expect, MEM_FILL,length ); nkeynes@190: nkeynes@190: if( expected_block != NULL ) { nkeynes@190: if( expected_block->length > length ) { nkeynes@190: fprintf( stderr, "Test data error: expected tile length is %d, but tile size is only %d\n", expected_block->length, length ); nkeynes@190: return; nkeynes@190: } nkeynes@190: memcpy( expect, expected_block->data, expected_block->length ); nkeynes@190: nkeynes@190: if( expected_block->length <= length-4 ) { nkeynes@190: *((unsigned int *)&expect[expected_block->length]) = 0xF0000000; nkeynes@190: } nkeynes@190: } nkeynes@190: } nkeynes@190: nkeynes@190: int tilematrix_block_compare( test_data_block_t expected_block, char *tile_ptrs[], int tile_type, int offset ) nkeynes@190: { nkeynes@190: int tile_size = tile_sizes[tile_type]; nkeynes@190: char expect[tile_size]; nkeynes@190: nkeynes@190: make_expected_buffer(expected_block, expect, tile_size); nkeynes@190: return memcmp( expect, tile_ptrs[tile_type]+(offset*tile_sizes[tile_type]), tile_size ); nkeynes@190: } nkeynes@190: nkeynes@212: /** nkeynes@212: * Copy from vram, wrapping appropriately nkeynes@212: */ nkeynes@212: int memcpy_from_vram( char *dest, char *src, int len ) nkeynes@212: { nkeynes@212: while( len > 0 ) { nkeynes@212: *dest++ = *src++; nkeynes@212: src = (char *)( ((unsigned int)src) & 0xFF7FFFFF ); nkeynes@212: len--; nkeynes@212: } nkeynes@212: } nkeynes@212: nkeynes@185: int test_ta( test_data_t test_case ) nkeynes@185: { nkeynes@185: char buf[1024]; nkeynes@185: unsigned int *p = DMA_ALIGN(buf); nkeynes@185: unsigned int *data = p; nkeynes@190: int haveFailure = 0; nkeynes@190: int checkedTile[5] = {0,0,0,0,0}; nkeynes@190: int i; nkeynes@190: int hsegs,vsegs; nkeynes@190: char *tile_ptrs[5]; nkeynes@185: nkeynes@185: asic_clear(); nkeynes@185: nkeynes@190: memset( PVR_VRAM_BASE, MEM_FILL, 0x00090000 ); nkeynes@190: test_data_block_t config_data = get_test_data( test_case, "config" ); nkeynes@190: struct ta_config *config = &default_ta_config; nkeynes@190: if( config_data != NULL ) { nkeynes@190: if( config_data->length != sizeof(struct ta_config) ) { nkeynes@190: fprintf( stderr, "Invalid config data length %d - aborting test %s\n", nkeynes@190: config_data->length, test_case->test_name ); nkeynes@190: return -1; nkeynes@190: } nkeynes@190: config = (struct ta_config *)config_data->data; nkeynes@190: } nkeynes@212: char *result = (char *)(PVR_VRAM_BASE+config->obj_start); nkeynes@212: char *tilematrix = (char *)(PVR_VRAM_BASE+config->tile_start); nkeynes@212: nkeynes@190: ta_init(config); nkeynes@190: for( i=0; i<5; i++ ) { nkeynes@190: tile_sizes[i] = TILE_SIZE(config,i); nkeynes@190: } nkeynes@190: hsegs = (config->grid_size & 0xFFFF)+1; nkeynes@190: vsegs = (config->grid_size >> 16) + 1; nkeynes@190: tile_ptrs[0] = tilematrix; nkeynes@190: tile_ptrs[1] = tile_ptrs[0] + (hsegs*vsegs*tile_sizes[0]); nkeynes@190: tile_ptrs[2] = tile_ptrs[1] + (hsegs*vsegs*tile_sizes[1]); nkeynes@190: tile_ptrs[3] = tile_ptrs[2] + (hsegs*vsegs*tile_sizes[2]); nkeynes@190: tile_ptrs[4] = tile_ptrs[3] + (hsegs*vsegs*tile_sizes[3]); nkeynes@190: nkeynes@185: nkeynes@185: test_data_block_t input = get_test_data(test_case, "input"); nkeynes@212: test_data_block_t input2 = get_test_data(test_case, "input2"); nkeynes@185: test_data_block_t output = get_test_data(test_case, "output"); nkeynes@190: test_data_block_t error = get_test_data(test_case, "error"); nkeynes@185: if( input == NULL || output == NULL ) { nkeynes@185: fprintf( stderr, "Skipping test case '%s': data incomplete\n", test_case->test_name ); nkeynes@185: return -1; nkeynes@185: } nkeynes@185: nkeynes@185: if( pvr_dma_write( 0x10000000, input->data, input->length, 0 ) == -1 ) { nkeynes@185: return -1; nkeynes@185: } nkeynes@190: nkeynes@212: if( input2 != NULL ) { nkeynes@212: ta_reinit(); nkeynes@212: pvr_dma_write( 0x10000000, input2->data, input2->length, 0 ); nkeynes@212: } nkeynes@212: nkeynes@212: nkeynes@190: if( error != NULL ) { nkeynes@190: for( i=0; ilength; i++ ) { nkeynes@190: if( asic_wait( error->data[i] ) == -1 ) { nkeynes@190: fprintf( stderr, "Test %s: failed (Timeout waiting for error event %d)\n", nkeynes@190: test_case->test_name, error->data[i] ); nkeynes@190: asic_dump( stderr ); nkeynes@190: return -1; nkeynes@190: } nkeynes@190: } nkeynes@185: } nkeynes@185: nkeynes@190: for( i=0; iitem[i]; nkeynes@190: int tile, x, y, offset; nkeynes@190: if( data->name != NULL ) { nkeynes@190: int result = sscanf( data->name, "tile %d %dx%d", &tile, &x, &y ); nkeynes@190: if( result == 1 ) { nkeynes@190: x = y = 0; nkeynes@190: } else if( result != 3 ) { nkeynes@190: continue; nkeynes@190: } nkeynes@190: tile--; nkeynes@190: offset = x + (y * hsegs); nkeynes@190: nkeynes@190: if( checkedTile[tile] == 0 ) { nkeynes@190: if( asic_wait( tile_events[tile] ) == -1 ) { nkeynes@190: fprintf( stderr, "Test %s: failed (Timeout waiting for %s done event)\n", nkeynes@190: test_case->test_name, tile_names[tile] ); nkeynes@190: ta_dump_regs(); nkeynes@190: asic_dump( stderr ); nkeynes@190: haveFailure = 1; nkeynes@190: } nkeynes@190: } nkeynes@190: nkeynes@190: if( tilematrix_block_compare( data, tile_ptrs, tile, offset ) != 0 ) { nkeynes@190: fprintf( stderr, "Test %s: Failed (%s matrix %dx%d). ", nkeynes@190: test_case->test_name, tile_names[tile], x, y ); nkeynes@190: fwrite_diff32( stderr, data->data, data->length, nkeynes@190: tile_ptrs[tile] + (tile_sizes[tile]*offset), tile_sizes[tile] ); nkeynes@190: haveFailure = 1; nkeynes@190: } nkeynes@190: checkedTile[tile] = 1; nkeynes@190: } nkeynes@190: } nkeynes@190: nkeynes@190: /* Overflow */ nkeynes@190: test_data_block_t plist = get_test_data(test_case, "plist" ); nkeynes@190: if( plist != NULL ) { nkeynes@190: unsigned int plist_posn, plist_end; nkeynes@190: if( config->ta_cfg & 0x00100000 ) { /* Descending */ nkeynes@193: plist_posn = pvr_get_plist_posn(); //+ tile_sizes[0]; nkeynes@190: plist_end = config->plist_start; nkeynes@190: } else { nkeynes@190: plist_posn = config->plist_start; nkeynes@193: plist_end = pvr_get_plist_posn() + tile_sizes[0]; nkeynes@190: } nkeynes@190: char *plist_data = (char *)(PVR_VRAM_BASE + plist_posn); nkeynes@190: if( test_block_compare( plist, plist_data, plist_end-plist_posn ) != 0 ) { nkeynes@190: fprintf( stderr, "Test %s: Failed (Plist buffer)", test_case->test_name ); nkeynes@190: fwrite_diff32( stderr, plist->data, plist->length, (char *)plist_data, nkeynes@190: plist_end - plist_posn ); nkeynes@190: haveFailure = 1; nkeynes@190: } nkeynes@193: char block[tile_sizes[0]]; nkeynes@193: memset( block, MEM_FILL, tile_sizes[0] ); nkeynes@193: if( memcmp( block, plist_data - tile_sizes[0], tile_sizes[0] ) != 0 ) { nkeynes@193: fprintf( stderr, "Test %s: Failed (Plist buffer)", test_case->test_name ); nkeynes@193: fwrite_diff32( stderr, block, tile_sizes[0], plist_data - tile_sizes[0], nkeynes@193: tile_sizes[0]); nkeynes@193: haveFailure = 1; nkeynes@193: } nkeynes@190: } nkeynes@190: nkeynes@190: /* Vertex buffer */ nkeynes@185: int result_length = pvr_get_objbuf_size(); nkeynes@212: char tmp[result_length]; nkeynes@212: memcpy_from_vram( tmp, result, result_length ); nkeynes@212: if( test_block_compare( output, tmp, result_length ) != 0 ) { nkeynes@190: fprintf( stderr, "Test %s: Failed (Vertex buffer). ", test_case->test_name ); nkeynes@212: fwrite_diff32( stderr, output->data, output->length, tmp, result_length ); nkeynes@190: haveFailure = 1; nkeynes@185: } nkeynes@185: nkeynes@190: nkeynes@190: for( i=0; i<5; i++ ) { nkeynes@190: if( checkedTile[i] == 0 ) { nkeynes@190: if( tilematrix_block_compare( NULL, tile_ptrs, i, 0 ) != 0 ) { nkeynes@190: fprintf( stderr, "Test %s: Failed (%s matrix). ", test_case->test_name, tile_names[i] ); nkeynes@190: fprintf( stderr, "Expected empty buffer at %08X, but was =>\n", nkeynes@190: (unsigned int)(tile_ptrs[i]) ); nkeynes@190: fwrite_dump( stderr, tile_ptrs[i], tile_sizes[i] ); nkeynes@190: // fwrite_dump( stderr, tile_ptrs[i] - 128, 256 ); nkeynes@190: nkeynes@190: } nkeynes@190: } nkeynes@190: } nkeynes@193: nkeynes@193: if( error == NULL ) { nkeynes@193: if( asic_check(EVENT_TA_ERROR) || asic_check(EVENT_PVR_PRIM_ALLOC_FAIL) || nkeynes@193: asic_check(EVENT_PVR_MATRIX_ALLOC_FAIL) || asic_check(EVENT_PVR_BAD_INPUT) ) { nkeynes@193: fprintf( stderr, "Test %s: Failed (unexpected error events)\n", test_case->test_name ); nkeynes@193: asic_dump( stderr ); nkeynes@193: haveFailure = 1; nkeynes@193: } nkeynes@193: } nkeynes@193: nkeynes@190: if( haveFailure ) nkeynes@190: return -1; nkeynes@190: nkeynes@190: fprintf( stdout, "Test %s: OK\n", test_case->test_name ); nkeynes@190: return 0; nkeynes@185: } nkeynes@185: nkeynes@185: int main( int argc, char *argv[] ) nkeynes@185: { nkeynes@185: int test_cases = 0; nkeynes@185: int test_failures = 0; nkeynes@185: test_data_t test_data = load_test_dataset(stdin); nkeynes@185: test_data_t test_case = test_data; nkeynes@185: nkeynes@185: asic_mask_all(); nkeynes@185: pvr_init(); nkeynes@185: nkeynes@185: while( test_case != NULL ) { nkeynes@185: test_cases++; nkeynes@185: int result = test_ta(test_case); nkeynes@185: if( result != 0 ) { nkeynes@185: test_failures++; nkeynes@185: } nkeynes@185: test_case = test_case->next; nkeynes@185: } nkeynes@185: free_test_dataset(test_data); nkeynes@185: if( test_failures != 0 ) { nkeynes@185: fprintf( stderr, "%d/%d test failures!\n", test_failures, test_cases ); nkeynes@185: return 1; nkeynes@185: } else { nkeynes@185: fprintf( stderr, "%d tests OK\n", test_cases ); nkeynes@185: return 0; nkeynes@185: } nkeynes@185: }