685 lines
21 KiB
C
685 lines
21 KiB
C
/* V2MemTest - A CLI Tool to test & fix Voodoo² TMU System
|
|
* Copyright (C) 2026 ChaCha
|
|
*
|
|
* This program is free software: you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#define _BSD_SOURCE 1
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "cvg.h"
|
|
#include <glide.h>
|
|
#include "sst1init.h"
|
|
#include "fxpci.h"
|
|
|
|
#include "FaultSources.h"
|
|
#include "Utils.h"
|
|
#include "Draw.h"
|
|
|
|
#include "Test_Common.h"
|
|
#include "Test_Data_Huge.h"
|
|
|
|
#define _DEF_NB_PIXEL_ROW 256
|
|
#define _DEF_NB_PIXEL_COL 256
|
|
#define _NB_CHECK_LOOP 3
|
|
|
|
//#define _PROFILING
|
|
|
|
typedef struct _def_sFaultSheet{
|
|
unsigned char ucNumTMU;
|
|
unsigned char bEvenRow;
|
|
def_eFaultSource Ux_MEMChip_MainMSB;
|
|
def_eFaultSource Ux_MEMChip_MainLSB;
|
|
def_eFaultSource Ux_MEMChip_AltMSB;
|
|
def_eFaultSource Ux_MEMChip_AltLSB;
|
|
def_eFaultSource Ux_TMUx_CAS02;
|
|
def_eFaultSource Ux_TMUx_CAS13;
|
|
def_eFaultSource Ux_TMU;
|
|
def_eFaultSource Ux_TMUx_TEXDATA_x_0;
|
|
}def_sFaultSheet;
|
|
|
|
static const def_sFaultSheet sFaultSheet[MAX_TMU][2] =
|
|
{
|
|
{ /*TMU0*/
|
|
{ /*ODD row*/
|
|
.ucNumTMU = 0,
|
|
.bEvenRow = 0,
|
|
.Ux_MEMChip_MainMSB = U12,
|
|
.Ux_MEMChip_MainLSB = U14,
|
|
.Ux_MEMChip_AltMSB = U24,
|
|
.Ux_MEMChip_AltLSB = U23,
|
|
.Ux_TMUx_CAS02 = U9_TMU0_TEX_CAS0,
|
|
.Ux_TMUx_CAS13 = U9_TMU0_TEX_CAS1,
|
|
.Ux_TMU = U9_TMU0,
|
|
.Ux_TMUx_TEXDATA_x_0 = U9_TMU0+1+0,
|
|
},
|
|
{ /*EVEN row*/
|
|
.ucNumTMU = 0,
|
|
.bEvenRow = 1,
|
|
.Ux_MEMChip_MainMSB = U17,
|
|
.Ux_MEMChip_MainLSB = U18,
|
|
.Ux_MEMChip_AltMSB = U26,
|
|
.Ux_MEMChip_AltLSB = U25,
|
|
.Ux_TMUx_CAS02 = U9_TMU0_TEX_CAS2,
|
|
.Ux_TMUx_CAS13 = U9_TMU0_TEX_CAS3,
|
|
.Ux_TMU = U9_TMU0,
|
|
.Ux_TMUx_TEXDATA_x_0 = U9_TMU0+1+32,
|
|
},
|
|
},
|
|
{ /*TMU1*/
|
|
{ /*ODD row*/
|
|
.ucNumTMU = 1,
|
|
.bEvenRow = 0,
|
|
.Ux_MEMChip_MainMSB = U11,
|
|
.Ux_MEMChip_MainLSB = U13,
|
|
.Ux_MEMChip_AltMSB = U28,
|
|
.Ux_MEMChip_AltLSB = U27,
|
|
.Ux_TMUx_CAS02 = U8_TMU1_TEX_CAS0,
|
|
.Ux_TMUx_CAS13 = U8_TMU1_TEX_CAS1,
|
|
.Ux_TMU = U8_TMU1,
|
|
.Ux_TMUx_TEXDATA_x_0 = U8_TMU1+1+0,
|
|
},
|
|
{ /*EVEN row*/
|
|
.ucNumTMU = 1,
|
|
.bEvenRow = 1,
|
|
.Ux_MEMChip_MainMSB = U15,
|
|
.Ux_MEMChip_MainLSB = U16,
|
|
.Ux_MEMChip_AltMSB = U30,
|
|
.Ux_MEMChip_AltLSB = U29,
|
|
.Ux_TMUx_CAS02 = U8_TMU1_TEX_CAS2,
|
|
.Ux_TMUx_CAS13 = U8_TMU1_TEX_CAS3,
|
|
.Ux_TMU = U8_TMU1,
|
|
.Ux_TMUx_TEXDATA_x_0 = U8_TMU1+1+32,
|
|
},
|
|
}
|
|
};
|
|
|
|
static void
|
|
AssignFault(const def_sFaultSheet * const
|
|
psCurFaultSheet,
|
|
const FxU32 mem,
|
|
const unsigned char bitIdx,
|
|
const unsigned char _relbitIdx,
|
|
const unsigned char _relbitIdxWord,
|
|
const unsigned char _relbitIdxQuartet,
|
|
const unsigned char WordIdx,
|
|
const unsigned char RamSizeMB,
|
|
def_sFaultSourceScoreRec * const
|
|
pFaultSrcCtx)
|
|
{
|
|
//const unsigned char relbitIdxQuartet= bitIdx%4;
|
|
const unsigned char relbitIdxQuartet = _relbitIdxQuartet;
|
|
//const unsigned char relbitIdx = bitIdx%8;
|
|
const unsigned char relbitIdx = _relbitIdx;
|
|
//const unsigned char relbitIdxWord = bitIdx%16;
|
|
const unsigned char relbitIdxWord = _relbitIdxWord;
|
|
|
|
static unsigned char nbErrLWord = 0;
|
|
static unsigned char nbErrWord = 0;
|
|
|
|
if(bitIdx==0)
|
|
nbErrLWord = 1;
|
|
else
|
|
nbErrLWord++;
|
|
|
|
if(relbitIdxWord==0)
|
|
nbErrWord = 1;
|
|
else
|
|
nbErrWord++;
|
|
|
|
logD("## fault on LW bit: %d\n",bitIdx);
|
|
|
|
logD("- TMU : %s\n",pFaultSrcCtx[psCurFaultSheet->Ux_TMU].szName);
|
|
|
|
/* Texture Source path, FBI to TMUx*/
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMU
|
|
+ 81 //Ux_TMUx_FT_DATA_x
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
|
|
/* Output path, TMU0 to FBI*/
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
U9_TMU0
|
|
+ 97 //U9_TMU0_TF_DATA_x
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
U3_FBI_TF_DATA_0
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
|
|
switch(WordIdx)
|
|
{
|
|
case 0:
|
|
case 2:
|
|
if(relbitIdx<=3)
|
|
{
|
|
logD("- RA1x_x : %s\n",pFaultSrcCtx[RA10_1+relbitIdxQuartet].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
RA10_1
|
|
+ relbitIdxQuartet,
|
|
1.0/8);
|
|
}
|
|
else
|
|
{
|
|
logD("- RA1x_x : %s\n",pFaultSrcCtx[RA11_1+relbitIdxQuartet].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
RA11_1
|
|
+ relbitIdxQuartet,
|
|
1.0/8);
|
|
}
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
if(relbitIdx<=3)
|
|
{
|
|
logD("- RA1x_x : %s\n",pFaultSrcCtx[RA12_1+relbitIdxQuartet].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
RA12_1
|
|
+ relbitIdxQuartet,
|
|
1.0/8);
|
|
}
|
|
else
|
|
{
|
|
logD("- RA1x_x : %s\n",pFaultSrcCtx[RA13_1+relbitIdxQuartet].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
RA13_1
|
|
+ relbitIdxQuartet,
|
|
1.0/8);
|
|
}
|
|
break;
|
|
}
|
|
|
|
/* Transfert path, TMU1 to TMU0*/
|
|
if(psCurFaultSheet->ucNumTMU == 1)
|
|
{
|
|
/* TMU1 output */
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
U8_TMU1
|
|
+ 97 //U8_TMU1_TF_DATA_x
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
/* line adaptation resistors */
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
TT_TDATA_R131
|
|
+ 0
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
/* TMU0 input */
|
|
/* Note: U9_TMU0_TT_DATA_x is only tested when using TMU1 */
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
U9_TMU0
|
|
+ 65 //U9_TMU0_TT_DATA_x
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
}
|
|
|
|
if(WordIdx>=2)
|
|
{
|
|
logD( "- RAM chip/signal : %s\n",
|
|
pFaultSrcCtx[psCurFaultSheet->Ux_MEMChip_MainMSB
|
|
+ 1
|
|
+ relbitIdxWord].szName);
|
|
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_MEMChip_MainMSB
|
|
+ 1
|
|
+ relbitIdxWord,
|
|
1.0/2); //ok
|
|
if(RamSizeMB>2)
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_MEMChip_AltMSB
|
|
+ 1
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
}
|
|
else
|
|
{
|
|
logD( "- RAM chip/signal : %s\n",
|
|
pFaultSrcCtx[psCurFaultSheet->Ux_MEMChip_MainLSB
|
|
+ 1
|
|
+ relbitIdxWord].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_MEMChip_MainLSB
|
|
+ 1
|
|
+ relbitIdxWord,
|
|
1.0/2);
|
|
if(RamSizeMB>2)
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_MEMChip_AltLSB
|
|
+ 1
|
|
+ relbitIdxWord,
|
|
1.0/4);
|
|
}
|
|
|
|
logD( "- TMUx_TEXDATA_x_x : %s\n",
|
|
pFaultSrcCtx[psCurFaultSheet->Ux_TMUx_TEXDATA_x_0+bitIdx].szName);
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMUx_TEXDATA_x_0
|
|
+ bitIdx,
|
|
1.0/2);
|
|
|
|
if((relbitIdxWord==15) && (nbErrWord>8))
|
|
{
|
|
logD("- too many errors on this Word, suspecting CAS/RAS/WE.\n");
|
|
switch(WordIdx)
|
|
{
|
|
case 0:
|
|
case 2:
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMUx_CAS02,
|
|
1.0);
|
|
break;
|
|
case 1:
|
|
case 3:
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMUx_CAS13,
|
|
1.0);
|
|
break;
|
|
}
|
|
if(mem < 0x200000 )
|
|
{
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMU
|
|
+ 113, //Ux_TMUx_RAS0
|
|
1.0/2);
|
|
}
|
|
else
|
|
{
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMU
|
|
+ 114, //Ux_TMUx_RAS1
|
|
1.0/2);
|
|
}
|
|
FaultSource_addScore( pFaultSrcCtx,
|
|
psCurFaultSheet->Ux_TMU
|
|
+ 119, //Ux_TMUx_WE
|
|
1.0/2);
|
|
}
|
|
logD("-----------------------------------------------------------\n");
|
|
}
|
|
|
|
static unsigned long long
|
|
RenderTest( sst1DeviceInfoStruct * const
|
|
devInfo,
|
|
FxU32 * const sst,
|
|
SstRegs * const sstregs,
|
|
const char ucNumTMU,
|
|
const FxU32 mem,
|
|
const unsigned char RamSizeMB,
|
|
def_sFaultSourceScoreRec * const
|
|
pFaultSrcCtx)
|
|
{
|
|
unsigned long long NbErr = 0;
|
|
static char szBuff[1024];
|
|
|
|
#ifdef _PROFILING
|
|
clock_t begin = clock();
|
|
#endif
|
|
|
|
/* precomputing a pseudo-random texture data chunk.
|
|
*/
|
|
static uint16_t
|
|
ar_u16Pixels[_DEF_NB_PIXEL_ROW][_DEF_NB_PIXEL_COL];
|
|
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; iter_row++)
|
|
{
|
|
for(unsigned short iter_col = 0; iter_col < _DEF_NB_PIXEL_COL; iter_col+=2)
|
|
{
|
|
const uint32_t NewData = get_notnull_random_balanced_mByte();
|
|
ar_u16Pixels[iter_row][iter_col] = NewData >>16;
|
|
ar_u16Pixels[iter_row][iter_col+1] = NewData & 0xFFFF;
|
|
}
|
|
}
|
|
|
|
#ifdef _PROFILING
|
|
clock_t after_create = clock();
|
|
#endif
|
|
|
|
/* Setting texture base address window for both CPU and TMU
|
|
*/
|
|
ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (mem>>3));
|
|
|
|
/* Setting texture base address (to access it from CPU).
|
|
* We wont draw anything bigger than the texture so we can just use LOD0
|
|
* regardless of the actual size of the texture. And here its the maximum
|
|
* size (=LOD0) anyway.
|
|
*/
|
|
volatile FxU32 *texRowAddr
|
|
= (ucNumTMU<<(21-2))
|
|
+ (((FxU32)0)<<(17-2)) /*LOD0*/
|
|
+ (FxU32 *)SST_TEX_ADDRESS(sst);
|
|
|
|
/* Fast write of the texture memory, through PCI/FBI/TMU.
|
|
* we cannot use memcpy because it is not garented to do 32bit transfers.
|
|
* This code might not be portable on other architectures (=endianess)
|
|
*/
|
|
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; iter_row++)
|
|
{
|
|
mmio_fastwrite32( texRowAddr,
|
|
(uint32_t*)ar_u16Pixels[iter_row],
|
|
_DEF_NB_PIXEL_COL/2);
|
|
/* move to next line */
|
|
texRowAddr += (1<<(9-2));
|
|
}
|
|
|
|
#ifdef _PROFILING
|
|
clock_t after_write = clock();
|
|
clock_t before_draw[_NB_CHECK_LOOP];
|
|
clock_t after_draw[_NB_CHECK_LOOP];
|
|
clock_t after_read[_NB_CHECK_LOOP];
|
|
clock_t after_check[_NB_CHECK_LOOP];
|
|
#endif
|
|
|
|
clearScreen(sstregs,0x00000000,256,256);
|
|
|
|
/* Note: The checking phase is done several time without generating new
|
|
* data to allow better trouble-shooting in the future (bad write to good
|
|
* read). This particular check is not implemented yet (everything checked
|
|
* regardeless of the iteration).
|
|
* Also, the screen is only cleared before, to "hide" FBI memory glitches.
|
|
* It might or might not be a good idea... :)
|
|
*/
|
|
for(unsigned int i = 0; i<_NB_CHECK_LOOP; i++)
|
|
{
|
|
#ifdef _PROFILING
|
|
before_draw[i] = clock();
|
|
#endif
|
|
|
|
/* draw a 256x256 square */
|
|
drawSquare(sstregs, ucNumTMU, 0, 0, 256);
|
|
sst1InitIdle(sst);
|
|
|
|
#ifdef _PROFILING
|
|
after_draw[i] = clock();
|
|
#endif
|
|
volatile FxU32* pLFB = sst + (SST_LFB_ADDR>>2);
|
|
|
|
/* Fast read of the frame buffer from FBI/PCI, toward CPU memory to
|
|
* allow faster processing later and to prevent working on FBI memory
|
|
* for too long. We walk line by line because screen is not continuous
|
|
* in FBI memory.
|
|
*/
|
|
static uint16_t
|
|
ar_u16PixelsReRead[_DEF_NB_PIXEL_ROW][_DEF_NB_PIXEL_COL];
|
|
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; ++iter_row)
|
|
{
|
|
logT("reading row %d\n",iter_row);
|
|
mmio_fastread32((uint32_t*)&ar_u16PixelsReRead[iter_row],
|
|
pLFB,
|
|
_DEF_NB_PIXEL_COL/2);
|
|
logT("copy done\n");
|
|
pLFB += ((2048)>>2) ;
|
|
}
|
|
|
|
#ifdef _PROFILING
|
|
after_read[i] = clock();
|
|
#endif
|
|
|
|
logT("pre-analysing\n");
|
|
/* Computing ErrorMark for the whole array to improve cache usage and
|
|
* SuperScalar.
|
|
* Note: This could be merged with the previous read phase...
|
|
* But it seems fast enough ?
|
|
*/
|
|
static uint32_t
|
|
ar_u32ErrorMark_Lx[_DEF_NB_PIXEL_ROW*_DEF_NB_PIXEL_COL/2];
|
|
for(unsigned int iter = 0; iter < _DEF_NB_PIXEL_ROW*_DEF_NB_PIXEL_COL/2; iter+=2)
|
|
{
|
|
ar_u32ErrorMark_Lx[iter]
|
|
= (*((uint32_t*)ar_u16PixelsReRead+iter))
|
|
^ (*((uint32_t*)ar_u16Pixels+iter));
|
|
ar_u32ErrorMark_Lx[iter+1]
|
|
= (*((uint32_t*)ar_u16PixelsReRead+iter+1))
|
|
^ (*((uint32_t*)ar_u16Pixels+iter+1));
|
|
}
|
|
|
|
logT("analysing\n");
|
|
/* row index allows to know which memory chip we are reading
|
|
* this is why we cannot just walk the array as flat 32bit.
|
|
*/
|
|
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; ++iter_row)
|
|
{
|
|
logT("checking row %d\n",iter_row);
|
|
/* We will read 32bit words so we increase by 2 at every col loop.
|
|
* but as said, row/col index are used for Fault finding.
|
|
*/
|
|
for(unsigned short iter_col = 0; iter_col < _DEF_NB_PIXEL_COL; iter_col+=2)
|
|
{
|
|
logT("checking col %d\n",iter_col);
|
|
const uint32_t ErrorMark_Lx = ar_u32ErrorMark_Lx[(iter_row*_DEF_NB_PIXEL_COL+iter_col)/2];
|
|
|
|
/* There are just too much data to do a naive bunch of check on
|
|
* every possible FaultSource. So we need to do an ErrorMark's
|
|
* bit driven check. So we will check every bit once and only
|
|
* once, then we will assign the fault's Score to every target.
|
|
* This reduces the test time by 4 and allow to run more passes.
|
|
*
|
|
* To speed up things, we are also using a LUT-like preset
|
|
* FaultSource array (psCurFaultSheet).
|
|
*/
|
|
|
|
const def_sFaultSheet* psCurFaultSheet = &sFaultSheet[(int)ucNumTMU][iter_row%2];
|
|
if(ErrorMark_Lx)
|
|
{
|
|
NbErr++;
|
|
logD("===========================================================\n");
|
|
/*This is another layer of optimization, we partition ErrorMark
|
|
* in binary-like tree.*/
|
|
if(ErrorMark_Lx & 0x0000FFFFu)
|
|
{
|
|
logD("# fault detected, LFB[%d][%d] is 0x%04X [expected 0x%04X] !\n",
|
|
iter_row, iter_col,
|
|
ar_u16PixelsReRead[iter_row][iter_col],
|
|
ar_u16Pixels[iter_row][iter_col]);
|
|
if(ErrorMark_Lx & 0x000000FFu)
|
|
{
|
|
if(ErrorMark_Lx & 0x0000000Fu)
|
|
{
|
|
/*All calls have a lot of pre-computed const values to fast things up.*/
|
|
if(ErrorMark_Lx & 0x00000001u) AssignFault(psCurFaultSheet,mem,0,0,0,0,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000002u) AssignFault(psCurFaultSheet,mem,1,1,1,1,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000004u) AssignFault(psCurFaultSheet,mem,2,2,2,2,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000008u) AssignFault(psCurFaultSheet,mem,3,3,3,3,0,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
if(ErrorMark_Lx & 0x000000F0u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00000010u) AssignFault(psCurFaultSheet,mem,4,4,4,0,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000020u) AssignFault(psCurFaultSheet,mem,5,5,5,1,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000040u) AssignFault(psCurFaultSheet,mem,6,6,6,2,0,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000080u) AssignFault(psCurFaultSheet,mem,7,7,7,3,0,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
}
|
|
if(ErrorMark_Lx & 0x0000FF00u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00000F00u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00000100u) AssignFault(psCurFaultSheet,mem,8,0, 8, 0,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000200u) AssignFault(psCurFaultSheet,mem,9,1, 9, 1,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000400u) AssignFault(psCurFaultSheet,mem,10,2,10,2,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00000800u) AssignFault(psCurFaultSheet,mem,11,3,11,3,1,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
if(ErrorMark_Lx & 0x0000F000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00001000u) AssignFault(psCurFaultSheet,mem,12,4,12,0,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00002000u) AssignFault(psCurFaultSheet,mem,13,5,13,1,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00004000u) AssignFault(psCurFaultSheet,mem,14,6,14,2,1,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00008000u) AssignFault(psCurFaultSheet,mem,15,7,15,3,1,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
}
|
|
}
|
|
|
|
if(ErrorMark_Lx & 0xFFFF0000u)
|
|
{
|
|
logD("# fault detected, LFB[%d][%d] is 0x%04X [expected 0x%04X] !\n",
|
|
iter_row, iter_col+1,
|
|
ar_u16PixelsReRead[iter_row][iter_col+1],
|
|
ar_u16Pixels[iter_row][iter_col+1]);
|
|
if(ErrorMark_Lx & 0x00FF0000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x000F0000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00010000u) AssignFault(psCurFaultSheet,mem,16,0,0,0,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00020000u) AssignFault(psCurFaultSheet,mem,17,1,1,1,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00040000u) AssignFault(psCurFaultSheet,mem,18,2,2,2,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00080000u) AssignFault(psCurFaultSheet,mem,19,3,3,3,2,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
if(ErrorMark_Lx & 0x00F00000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x00100000u) AssignFault(psCurFaultSheet,mem,20,4,4,0,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00200000u) AssignFault(psCurFaultSheet,mem,21,5,5,1,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00400000u) AssignFault(psCurFaultSheet,mem,22,6,6,2,2,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x00800000u) AssignFault(psCurFaultSheet,mem,23,7,7,3,2,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
}
|
|
if(ErrorMark_Lx & 0xFF000000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x0F000000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x01000000u) AssignFault(psCurFaultSheet,mem,24,0,8, 0,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x02000000u) AssignFault(psCurFaultSheet,mem,25,1,9, 1,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x04000000u) AssignFault(psCurFaultSheet,mem,26,2,10,2,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x08000000u) AssignFault(psCurFaultSheet,mem,27,3,11,3,3,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
if(ErrorMark_Lx & 0xF0000000u)
|
|
{
|
|
if(ErrorMark_Lx & 0x10000000u) AssignFault(psCurFaultSheet,mem,28,4,12,0,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x20000000u) AssignFault(psCurFaultSheet,mem,29,5,13,1,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x40000000u) AssignFault(psCurFaultSheet,mem,30,6,14,2,3,RamSizeMB,pFaultSrcCtx);
|
|
if(ErrorMark_Lx & 0x80000000u) AssignFault(psCurFaultSheet,mem,31,7,15,3,3,RamSizeMB,pFaultSrcCtx);
|
|
}
|
|
}
|
|
}
|
|
logD("## overall fault LW bit-map : \n");
|
|
if(sOptions.eLogLevel >= E_LOGLEVEL__DEBUG)
|
|
{
|
|
sprintbin32Info(szBuff,ErrorMark_Lx, 31, 0);
|
|
logD("%s\n",szBuff);
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
//logI("Analysing Done\n");
|
|
#ifdef _PROFILING
|
|
after_check[i] = clock();
|
|
#endif
|
|
}
|
|
#ifdef _PROFILING
|
|
clock_t end = clock();
|
|
logI("time to create: %f\n",(double)(after_create-begin)/CLOCKS_PER_SEC);
|
|
logI("time to write: %f\n",(double)(after_write-after_create)/CLOCKS_PER_SEC);
|
|
for(unsigned int i = 0; i<_NB_CHECK_LOOP; i++)
|
|
{
|
|
logI("time to draw [%d]: %f\n",i,(double)(after_draw[i]-before_draw[i])/CLOCKS_PER_SEC);
|
|
logI("time to read [%d]: %f\n",i,(double)(after_read[i]-after_draw[i])/CLOCKS_PER_SEC);
|
|
logI("time to check [%d]: %f\n",i,(double)(after_check[i]-after_read[i])/CLOCKS_PER_SEC);
|
|
}
|
|
logI("overall: %f\n",(double)(end-begin)/CLOCKS_PER_SEC);
|
|
#endif
|
|
|
|
return NbErr;
|
|
}
|
|
|
|
unsigned long long
|
|
test_TMU_datalines_Huge( sst1DeviceInfoStruct * const
|
|
devInfo,
|
|
FxU32 * const sst,
|
|
SstRegs * const sstregs,
|
|
const unsigned char ucNumTMU,
|
|
const unsigned char RamSizeMB,
|
|
def_sFaultSourceScoreRec * const
|
|
pFaultSrcCtx)
|
|
{
|
|
typedef struct _def_sMemBlock{
|
|
uint32_t ulAddStart;
|
|
uint32_t ulAddEnd;
|
|
uint32_t ulAddLength;
|
|
}def_sMemBlock;
|
|
|
|
const def_sMemBlock ar_memBlocks[] = {
|
|
{ .ulAddStart = 0x000000,
|
|
.ulAddLength = 0x100000
|
|
},
|
|
{ .ulAddStart = 0x100000,
|
|
.ulAddLength = 0x100000
|
|
},
|
|
{ .ulAddStart = 0x200000,
|
|
.ulAddLength = 0x100000
|
|
},
|
|
{ .ulAddStart = 0x300000,
|
|
.ulAddLength = 0x100000
|
|
},
|
|
};
|
|
|
|
unsigned long long ullNbErrorAll = 0;
|
|
|
|
sst1InitIdle(sst);
|
|
unsigned long _trexInit0 = IGET(SST_TREX(sstregs,ucNumTMU)->trexInit0);
|
|
devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ;
|
|
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
|
|
sst1InitIdle(sst);
|
|
|
|
/* set downstream TMUs to passthrough */
|
|
for (int i=0; i<ucNumTMU; i++)
|
|
ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS);
|
|
|
|
for( int iMemBlock = 0;
|
|
iMemBlock < sizeof(ar_memBlocks)/sizeof(def_sMemBlock);
|
|
iMemBlock++)
|
|
{
|
|
const def_sMemBlock* pMemBlk = &ar_memBlocks[iMemBlock];
|
|
if(RamSizeMB<4 && pMemBlk->ulAddStart >= 0x300000) continue;
|
|
if(RamSizeMB<3 && pMemBlk->ulAddStart >= 0x200000) continue;
|
|
if(RamSizeMB<2 && pMemBlk->ulAddStart >= 0x100000) continue;
|
|
logT("RamSizeMB= %d, ulAddStart=%08x\n", RamSizeMB,pMemBlk->ulAddStart);
|
|
|
|
for( FxU32 addrTest = pMemBlk->ulAddStart ;
|
|
addrTest < (pMemBlk->ulAddStart + pMemBlk->ulAddLength);
|
|
addrTest += 131072) /* 256x256x2 (16bit pixels texture) */
|
|
{
|
|
logD("Testing memory block 0x%08x ...\n", addrTest);
|
|
const unsigned long long
|
|
ullNbError = RenderTest( devInfo,
|
|
sst,
|
|
sstregs,
|
|
ucNumTMU,
|
|
addrTest,
|
|
RamSizeMB,
|
|
pFaultSrcCtx);
|
|
ullNbErrorAll += ullNbError;
|
|
if(ullNbError)
|
|
logI("E");
|
|
else
|
|
logI(".");
|
|
fflush(stdout);
|
|
}
|
|
}
|
|
|
|
clearScreen(sstregs,0x00000000,256,256);
|
|
|
|
/* reset the Init0 register back to its previous value */
|
|
sst1InitIdle(sst);
|
|
devInfo->tmuInit0[(int)ucNumTMU] = _trexInit0;
|
|
ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
|
|
sst1InitIdle(sst);
|
|
|
|
return ullNbErrorAll;
|
|
}
|