45 Commits

Author SHA1 Message Date
a58e0241b4 Update Readme.md 2026-05-14 15:03:48 +02:00
712e9cfcab improved overall diagnostics, and specifically TMU-FBI BUS. 2026-03-16 18:12:11 +01:00
c363aa6284 implement no-mem test and start validating / tuning with real hardware 2026-03-15 22:18:42 +01:00
3ba8a3a985 bump version 2026-03-09 17:54:53 +01:00
7cc2e47d07 fix tmu1 on data-huge test
fix CAS/RAS/WE fault detect on data-huge test
fix data test Fault assignment
fix comment
fix shutdown
2026-03-09 17:53:35 +01:00
c4a91ad3ac bump version 2026-03-09 17:36:29 +01:00
6863990336 fix bit count ! 2026-03-09 17:35:41 +01:00
cc484d9458 integrate and clean 2026-03-09 16:43:04 +01:00
cde38d3f75 integration on real hardware 2026-03-09 01:10:56 +01:00
c54b332e8d build in dedicated folder 2026-03-09 01:10:26 +01:00
ace00297ef remove unittest for now 2026-03-09 01:10:09 +01:00
3ff1c1e724 update readme 2026-03-09 01:09:49 +01:00
9f8c39ca17 update gitignore 2026-03-09 01:09:39 +01:00
d2373e1be3 work 2026-03-07 16:40:29 +01:00
43ba0c7c18 work 2026-03-07 15:10:59 +01:00
da3e3e31c9 force 32bit build 2026-02-28 23:28:39 +00:00
chacha
8b0b027335 . 2026-02-27 22:15:46 +00:00
chacha
9a22d9a0d5 . 2026-02-27 22:09:15 +00:00
chacha
7fa980e834 . 2026-02-27 22:07:16 +00:00
chacha
304737cd90 . 2026-02-27 22:06:35 +00:00
chacha
1ff171316b . 2026-02-27 22:04:00 +00:00
chacha
6055524845 . 2026-02-27 22:01:39 +00:00
chacha
a06950fae8 . 2026-02-27 21:58:41 +00:00
chacha
28831ac8ad . 2026-02-27 21:57:08 +00:00
chacha
555988294e . 2026-02-27 21:56:17 +00:00
chacha
03f9449e17 . 2026-02-27 21:54:36 +00:00
chacha
26217dc08e . 2026-02-27 21:51:49 +00:00
chacha
4d705a8fcf . 2026-02-27 21:50:42 +00:00
chacha
5a3247f527 . 2026-02-27 21:49:27 +00:00
chacha
fda192dab5 . 2026-02-27 21:47:33 +00:00
chacha
cfee13d4e3 . 2026-02-27 21:46:46 +00:00
chacha
b4822085ec . 2026-02-27 21:45:43 +00:00
chacha
496f032734 . 2026-02-27 21:44:24 +00:00
chacha
a0faa8661d . 2026-02-25 00:57:00 +00:00
chacha
c4d02de1d7 . 2026-02-25 00:50:48 +00:00
chacha
cdd611a94d . 2026-02-25 00:47:23 +00:00
chacha
b9692565af . 2026-02-25 00:45:04 +00:00
chacha
9dbd2c2498 improve data type and inlining (static) 2026-02-25 00:42:27 +00:00
chacha
57fd93f513 really draw a square 2026-02-25 00:42:00 +00:00
f6d19c682d Update Readme.md 2026-02-24 22:46:35 +01:00
chacha
3fdad6a5ad add npp workspace 2026-02-24 21:35:00 +00:00
chacha
801d287e1f . 2026-02-24 01:11:09 +00:00
chacha
9ee50425ab . 2026-02-24 01:09:45 +00:00
chacha
9a87a0d19d Merge branch 'master' of https://chacha.ddns.net/gitea/chacha/V2TMUMemTester.git 2026-02-24 01:08:49 +00:00
chacha
ce3bbd57c3 . 2026-02-24 01:08:16 +00:00
29 changed files with 5759 additions and 2432 deletions

3
.gitignore vendored
View File

@@ -1,4 +1,5 @@
*~ *~
*.o *.o
*.log *.log
V2MemTest v2-tmu-memtester
OBJ/*.o

7
.vscode/launch.json vendored Normal file
View File

@@ -0,0 +1,7 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": []
}

1
.vscode/settings.json vendored Normal file
View File

@@ -0,0 +1 @@
{}

180
Draw.c
View File

@@ -21,31 +21,165 @@
#include "Draw.h" #include "Draw.h"
static inline uint32_t f32u(const float f)
{
const union { float f; uint32_t u;} v = {.f = f};
return v.u;
}
void
drawRect( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY)
{
ISET(sstregs->sSetupMode, 0x0020);
ISET(SST_TREX(sstregs,ucNumTMU)->sARGB,0xFFFFFFFF);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sOowfbi,f32u(1.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0,f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0,f32u(0.0f));
/* 0b10 0000 (Update only S0/T0), doc page 76 */
ISET(sstregs->sBeginTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)(x+tSizeX)));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0,f32u((float)tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0,f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y+tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0,f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0,f32u((float)tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x+tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y+tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0,f32u((float)tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0,f32u((float)tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(sstregs->nopCMD, 0x1);
}
void
drawRect2( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY)
{
ISET(sstregs->sSetupMode, 0x0020);
//ISET(SST_TREX(sstregs,ucNumTMU)->sARGB,0xFF55AA55);
ISET(SST_TREX(sstregs,ucNumTMU)->sOowfbi, f32u(1.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u(0.0f));
/* 0b10 0000 (Update only S0/T0), doc page 76 */
ISET(sstregs->sBeginTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)(x+tSizeX)));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u((float)tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y+tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u((float)tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x+tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y+tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u((float)tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u((float)tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(sstregs->nopCMD, 0x1);
}
void
clearScreen( const SstRegs * const sstregs,
const uint32_t u32Color,
const int16_t u16SizeX,
const int16_t u16SizeY)
{
ISET(sstregs->clipLeftRight, u16SizeX);
ISET(sstregs->clipBottomTop, u16SizeY);
ISET(sstregs->zaColor, u32Color);
//ISET(sstregs->zaColor, 0x0000);
const uint32_t fbz_saved = IGET(sstregs->fbzMode);
ISET(sstregs->c1,u32Color);
ISET(sstregs->c0,0x0);
ISET(sstregs->zaColor,0x0F);
ISET(sstregs->fbzMode, SST_RGBWRMASK | SST_ZAWRMASK);
ISET(sstregs->fastfillCMD, 0);
ISET(sstregs->nopCMD, 0x1);
ISET(sstregs->fbzMode, fbz_saved);
}
#define XY_ONE (1<<SST_XY_FRACBITS) #define XY_ONE (1<<SST_XY_FRACBITS)
void void
drawTriangle( const SstRegs *sst, drawPixel( const SstRegs *sstregs,
const int x, const unsigned char ucNumTMU,
const int y, const int x,
const int tSize) const int y)
{ {
ISET(sst->vA.x,x); ISET( SST_TREX(sstregs,ucNumTMU)->vA.x,x*XY_ONE);
ISET(sst->vA.y,y); ISET(SST_TREX(sstregs,ucNumTMU)->vA.y,y*XY_ONE);
ISET(sst->vB.x,x+XY_ONE*tSize);
ISET(sst->vB.y,y); ISET(SST_TREX(sstregs,ucNumTMU)->vB.x,(x+2)*XY_ONE);
ISET(sst->vC.x,x); ISET(SST_TREX(sstregs,ucNumTMU)->vB.y,y*XY_ONE);
ISET(sst->vC.y,y+XY_ONE*tSize);
ISET(sst->s,0); ISET(SST_TREX(sstregs,ucNumTMU)->vC.x,x*XY_ONE);
ISET(sst->t,0); ISET(SST_TREX(sstregs,ucNumTMU)->vC.y,(y+1)*XY_ONE);
ISET(sst->w,0);
ISET(sst->dsdx,1<<SST_ST_FRACBITS); ISET(SST_TREX(sstregs,ucNumTMU)->triangleCMD,0);
ISET(sst->dtdx,0);
ISET(sst->dwdx,0);
ISET(sst->dsdy,0);
ISET(sst->dtdy,1<<SST_ST_FRACBITS);
ISET(sst->dwdy,0);
ISET(sst->triangleCMD,0);
ISET(sst->vB.x, (x<<SST_XY_FRACBITS));
ISET(sst->vB.y, ((y+tSize)<<SST_XY_FRACBITS));
ISET(sst->triangleCMD, 0xFFFFFFFF);
} }
void
drawTriangle( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY)
{
ISET(sstregs->sSetupMode, 0x0020);
//ISET(SST_TREX(sstregs,ucNumTMU)->sARGB,0xFF55AA55);
ISET(SST_TREX(sstregs,ucNumTMU)->sOowfbi, f32u(1.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u(0.0f));
/* 0b10 0000 (Update only S0/T0), doc page 76 */
ISET(sstregs->sBeginTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)(x+tSizeX)));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u((float)tSizeX));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(SST_TREX(sstregs,ucNumTMU)->sVx, f32u((float)x));
ISET(SST_TREX(sstregs,ucNumTMU)->sVy, f32u((float)y+tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sSow0, f32u(0.0f));
ISET(SST_TREX(sstregs,ucNumTMU)->sTow0, f32u((float)tSizeY));
ISET(SST_TREX(sstregs,ucNumTMU)->sDrawTriCMD, 1);
ISET(sstregs->nopCMD, 0x1);
}

52
Draw.h
View File

@@ -18,10 +18,52 @@
#ifndef _DEF_DRAW_H_ #ifndef _DEF_DRAW_H_
#define _DEF_DRAW_H_ #define _DEF_DRAW_H_
void #include <stdint.h>
drawTriangle( const SstRegs *sst,
const int x,
const int y,
const int tSize);
void
drawRect( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY);
void
drawRect2( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY);
void
drawTriangle( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSizeX,
const int16_t tSizeY);
void
drawPixel( const SstRegs *sstregs,
const unsigned char ucNumTMU,
const int x,
const int y);
static inline void
drawSquare( const SstRegs * const sstregs,
const unsigned char ucNumTMU,
const int16_t x,
const int16_t y,
const int16_t tSize)
{
drawRect(sstregs,ucNumTMU, x, y, tSize, tSize);
}
void
clearScreen( const SstRegs * const sstregs,
const uint32_t u32Color,
const int16_t u16SizeX,
const int16_t u16SizeY);
#endif //_DEF_DRAW_H_ #endif //_DEF_DRAW_H_

View File

@@ -21,103 +21,161 @@
#include "FaultSources.h" #include "FaultSources.h"
#include "Utils.h" #include "Utils.h"
def_sFaultSourceScoreRec ar_dFaultScores[NB_FAULT_SOURCE] = const def_sFaultSourceScoreRec
_ar_dFaultScores[NB_FAULT_SOURCE] =
{ {
{ {
.eThisFaultSource = VOODOO_BOARD, .eThisFaultSource = VOODOO_BOARD,
.szName = "VOODOO_BOARD", .szName = "VOODOO_BOARD",
.szLoc = "Main Board", .szLoc = "Main Board",
.eParrentFaultSource = _INVALID_FAULT_SOURCE_, .eParrentFaultSource = _INVALID_FAULT_SOURCE_,
.dScore = 0.0 .dScore = 0.0,
.dWeight = 1.0,
}, },
FAULT_SOURCES(GEN_FAULT_SOURCES_ARRAY) FAULT_SOURCES(GEN_FAULT_SOURCES_ARRAY)
}; };
def_sFaultSourceScoreRec ar_dFaultScores_sorted[NB_FAULT_SOURCE];
void void
FaultSource_Reset() FaultSource_reset(def_sFaultSourceScoreRec* const pCtx)
{ {
for(def_eFaultSource idx = 0; idx < NB_FAULT_SOURCE; idx++ ) memcpy( pCtx,
ar_dFaultScores[idx].dScore = 0.0; _ar_dFaultScores,
sizeof(_ar_dFaultScores));
} }
static unsigned long static unsigned long
FaultSource_getNbDeps(const def_eFaultSource eFaultSource) FaultSource_getNbDeps( const def_sFaultSourceScoreRec* const pCtx,
const def_eFaultSource eFaultSource)
{ {
unsigned long res = 0; unsigned long res = 0;
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; idx++ ) for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
if(ar_dFaultScores[idx].eParrentFaultSource == eFaultSource) if(pCtx[idx].eParrentFaultSource == eFaultSource)
res++; res++;
return res; return res;
} }
void void
FaultSource_AddScore( def_eFaultSource eFaultSource, FaultSource_addScore( def_sFaultSourceScoreRec* const pCtx,
def_eFaultSource eFaultSource,
double dScore) double dScore)
{ {
double dDivider = 1.0; double dDivider = 1.0;
do do
{ {
//if(dDivider==1.0)
// printf("set Score %f to %s\n",dScore,pCtx[eFaultSource].szName);
dScore /= dDivider; dScore /= dDivider;
ar_dFaultScores[eFaultSource].dScore += dScore; pCtx[eFaultSource].dScore += dScore;
eFaultSource = ar_dFaultScores[eFaultSource].eParrentFaultSource; eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
dDivider = FaultSource_getNbDeps(eFaultSource); dDivider *= 5;
if(dDivider <= 0)
dDivider = 1.0;
}while(eFaultSource != _INVALID_FAULT_SOURCE_); }while(eFaultSource != _INVALID_FAULT_SOURCE_);
} }
static unsigned long void
FaultSource_Sort_GetIdx(const def_eFaultSource eFaultSource) FaultSource_nomalize( def_sFaultSourceScoreRec* const pCtx)
{ {
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; idx++ ) double dSum = 0.0;
if(ar_dFaultScores_sorted[idx].eThisFaultSource == eFaultSource) for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
dSum+= pCtx[idx].dScore;
if(dSum != 0)
FaultSource_divideAll(pCtx,dSum);
}
// This function can only be used on non-sorted Rec (is relies on indexes)!
void
FaultSource_sum( def_sFaultSourceScoreRec** const pCtxRef,
const unsigned int uNbRef,
def_sFaultSourceScoreRec* const pCtx)
{
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
{
for(unsigned long idxRef = 0; idxRef < uNbRef; ++idxRef )
{
pCtx[idx].dScore += pCtxRef[idxRef][idx].dScore;
}
}
FaultSource_divideAll(pCtx,uNbRef);
}
void
FaultSource_divideAll( def_sFaultSourceScoreRec* const pCtx,
const double dDivider)
{
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
pCtx[idx].dScore /= dDivider;
}
static unsigned long
FaultSource_GetIdx( const def_sFaultSourceScoreRec* const pCtx,
const def_eFaultSource eFaultSource)
{
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
if(pCtx[idx].eThisFaultSource == eFaultSource)
return idx; return idx;
return _INVALID_FAULT_SOURCE_; return _INVALID_FAULT_SOURCE_;
} }
static inline void static inline void
FaultSource_Sort_Swap( const def_eFaultSource eFaultSourceCurrentA, FaultSource_Swap( def_sFaultSourceScoreRec* const pCtx,
const def_eFaultSource eFaultSourceCurrentB) const def_eFaultSource A,
const def_eFaultSource B)
{ {
static def_sFaultSourceScoreRec tmp; def_sFaultSourceScoreRec tmp;
memcpy(&tmp, &ar_dFaultScores_sorted[eFaultSourceCurrentA], sizeof(def_sFaultSourceScoreRec)); memcpy( &tmp,
memcpy(&ar_dFaultScores_sorted[eFaultSourceCurrentA], &ar_dFaultScores_sorted[eFaultSourceCurrentB], sizeof(def_sFaultSourceScoreRec)); &pCtx[A],
memcpy(&ar_dFaultScores_sorted[eFaultSourceCurrentB], &tmp, sizeof(def_sFaultSourceScoreRec)); sizeof(def_sFaultSourceScoreRec));
memcpy( &pCtx[A],
&pCtx[B],
sizeof(def_sFaultSourceScoreRec));
memcpy( &pCtx[B],
&tmp,
sizeof(def_sFaultSourceScoreRec));
} }
void void
FaultSource_Sort() FaultSource_getSorted( def_sFaultSourceScoreRec* const pDst,
const def_sFaultSourceScoreRec* const pCtx)
{ {
unsigned char bSwapped = 1; unsigned char bSwapped = 1;
memcpy(ar_dFaultScores_sorted,ar_dFaultScores,sizeof(ar_dFaultScores_sorted));
// shaker sort memcpy( pDst,
pCtx,
sizeof(_ar_dFaultScores));
for(unsigned long idx = 0;
idx < NB_FAULT_SOURCE;
++idx )
pDst[idx].dScore *= pDst[idx].dWeight;
// shaker sort FixMe: use qsort()
while(bSwapped) while(bSwapped)
{ {
bSwapped = 0; bSwapped = 0;
for(long eFaultSourceCurrentComp=0; for(unsigned long idx=0;
eFaultSourceCurrentComp < (NB_FAULT_SOURCE - 1); idx < (NB_FAULT_SOURCE - 1);
eFaultSourceCurrentComp++ ) ++idx )
{ {
if( ar_dFaultScores_sorted[eFaultSourceCurrentComp].dScore if( pDst[idx].dScore
< ar_dFaultScores_sorted[eFaultSourceCurrentComp + 1].dScore) < pDst[idx + 1].dScore)
{ {
FaultSource_Sort_Swap(eFaultSourceCurrentComp, eFaultSourceCurrentComp + 1); FaultSource_Swap( pDst,
idx,
idx + 1);
bSwapped = 1; bSwapped = 1;
break; break;
} }
} }
for(long eFaultSourceCurrentComp = (NB_FAULT_SOURCE-2); for(long idx = (NB_FAULT_SOURCE-2);
eFaultSourceCurrentComp >= 0; idx >= 0;
eFaultSourceCurrentComp-- ) --idx )
{ {
if( ar_dFaultScores_sorted[eFaultSourceCurrentComp].dScore if( pDst[idx].dScore
< ar_dFaultScores_sorted[eFaultSourceCurrentComp + 1].dScore) < pDst[idx + 1].dScore)
{ {
FaultSource_Sort_Swap(eFaultSourceCurrentComp, eFaultSourceCurrentComp + 1); FaultSource_Swap( pDst,
idx,
idx + 1);
bSwapped = 1; bSwapped = 1;
break; break;
} }
@@ -125,134 +183,209 @@ FaultSource_Sort()
} }
// updating refs // updating refs
for(long eFaultSourceIdx = 0; for(unsigned long idx = 0;
eFaultSourceIdx < NB_FAULT_SOURCE; idx < NB_FAULT_SOURCE;
eFaultSourceIdx++ ) ++idx )
{ pDst[idx].eParrentFaultSource =
unsigned long idx = FaultSource_Sort_GetIdx(ar_dFaultScores_sorted[eFaultSourceIdx].eParrentFaultSource); FaultSource_GetIdx(
ar_dFaultScores_sorted[eFaultSourceIdx].eParrentFaultSource = idx; pDst,
} pDst[idx].eParrentFaultSource);
for(long eFaultSourceIdx = 0;
eFaultSourceIdx < NB_FAULT_SOURCE; for(unsigned long idx = 0;
eFaultSourceIdx++ ) idx < NB_FAULT_SOURCE;
ar_dFaultScores_sorted[eFaultSourceIdx].eThisFaultSource = eFaultSourceIdx; ++idx )
pDst[idx].eThisFaultSource = idx;
} }
void void
FaultSource_GetLoc(def_eFaultSource eFaultSource, char* loc) FaultSource_getLoc( const def_sFaultSourceScoreRec* const pCtx,
def_eFaultSource eFaultSource,
char* const loc)
{ {
loc[0]='\0'; loc[0]='\0';
strcpy(loc, ar_dFaultScores_sorted[eFaultSource].szLoc); strcpy(loc, pCtx[eFaultSource].szLoc);
eFaultSource = ar_dFaultScores_sorted[eFaultSource].eParrentFaultSource; eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
while(eFaultSource != _INVALID_FAULT_SOURCE_) while(eFaultSource != _INVALID_FAULT_SOURCE_)
{ {
static char buff[1024]; static char buff[1024];
sprintf(buff, "%s->%s", ar_dFaultScores_sorted[eFaultSource].szLoc, loc); sprintf(buff, "%s->%s", pCtx[eFaultSource].szLoc, loc);
strcpy(loc, buff); strcpy(loc, buff);
eFaultSource = ar_dFaultScores_sorted[eFaultSource].eParrentFaultSource; eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
} }
} }
void void
FaultSource_Display() FaultSource_display(const def_sFaultSourceScoreRec* const pCtx)
{ {
double dScoreSum = 0;
for(def_eFaultSource eFaultSourceCurrent = 0;
eFaultSourceCurrent < NB_FAULT_SOURCE && ar_dFaultScores_sorted[eFaultSourceCurrent].dScore > 0;
eFaultSourceCurrent++ )
dScoreSum += ar_dFaultScores_sorted[eFaultSourceCurrent].dScore;
printf("------------------------------------------------\n"); printf("------------------------------------------------\n");
printf("\nDefects list:\n\n"); printf("\ndefects list:\n\n");
printf("Score\tElement [Loc]\n"); printf("score\telement [Loc]\n");
printf("------------------------------------------------\n"); printf("------------------------------------------------\n");
for(def_eFaultSource eFaultSourceCurrent = 0; for(unsigned long idx = 0;
eFaultSourceCurrent < NB_FAULT_SOURCE (idx < NB_FAULT_SOURCE)
&& (ar_dFaultScores_sorted[eFaultSourceCurrent].dScore > 0); && (pCtx[idx].dScore > 0);
eFaultSourceCurrent++ ) ++idx )
{ {
static char buff[1024]; static char buff[1024] = {0};
FaultSource_GetLoc(eFaultSourceCurrent, buff); buff[0]='\0';
FaultSource_getLoc(pCtx,idx, buff);
printf("%02.3f\t%s [%s]\n", printf("%02.3f\t%s [%s]\n",
100 * ar_dFaultScores_sorted[eFaultSourceCurrent].dScore / dScoreSum, pCtx[idx].dScore,
ar_dFaultScores_sorted[eFaultSourceCurrent].szName, pCtx[idx].szName,
buff ); buff );
} }
} }
void
void ByteBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
WordBitFaultSet( const unsigned long ErrorMark, const uint8_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSourceL,
const def_eFaultSource eFaultSourceH)
{
for(unsigned long bitPos = 0; bitPos <= 31 ; bitPos++)
if(ErrorMark & (1 << bitPos))
{
if(bitPos < 16)
FaultSource_AddScore(eFaultSourceL + bitPos, dScore);
else
FaultSource_AddScore(eFaultSourceH + bitPos - 16, dScore);
}
}
void
QuartetBitFaultSet( const unsigned long ErrorMark,
const double dScore, const double dScore,
const def_eFaultSource eFaultSource) const def_eFaultSource eFaultSource)
{ {
for(unsigned char bitPos = 0; bitPos <= 4 ; bitPos++)
if(ErrorMark & (1 << bitPos)) for(unsigned char bitPos = 0; bitPos <= 7 ; ++bitPos)
FaultSource_AddScore(eFaultSource + bitPos, dScore); if(ErrorMark & (1u << bitPos))
{
FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore);
}
} }
void
WordBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const uint16_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSource)
{
inline void for(unsigned char bitPos = 0; bitPos <= 15 ; ++bitPos)
MemChipDQFaultSet( const unsigned long ErrorMark, if(ErrorMark & (1u << bitPos))
{
FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore);
}
}
void
LWordBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const uint32_t ErrorMark,
const double dScore, const double dScore,
const def_eFaultSource eFaultSourceL, const def_eFaultSource eFaultSourceL,
const def_eFaultSource eFaultSourceH) const def_eFaultSource eFaultSourceH)
{ {
WordBitFaultSet(ErrorMark, dScore, eFaultSourceL + 1, eFaultSourceH + 1);
for(unsigned char bitPos = 0; bitPos <= 31 ; ++bitPos)
if(ErrorMark & (1u << bitPos))
{
if(bitPos < 16)
FaultSource_addScore(pCtx, eFaultSourceL + bitPos, dScore);
else
FaultSource_addScore(pCtx, eFaultSourceH + bitPos - 16, dScore);
}
} }
inline void void
TMUTexDataFaultSet( const unsigned long ErrorMark_w0w1, QuartetBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const unsigned long ErrorMark_w2w3, const uint8_t ErrorMark,
const double dScore, const double dScore,
const def_eFaultSource eTMUFaultSource) const def_eFaultSource eFaultSource)
{ {
WordBitFaultSet(ErrorMark_w0w1, dScore, eTMUFaultSource + 0 + 1, eTMUFaultSource + 16 + 1); for(uint8_t bitPos = 0; bitPos < 4 ; ++bitPos)
WordBitFaultSet(ErrorMark_w2w3, dScore, eTMUFaultSource + 32 + 1, eTMUFaultSource + 48 + 1); if(ErrorMark & (1u << bitPos))
FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore);
} }
void
inline void RGBToBus_Fault( def_sFaultSourceScoreRec* const pCtx,
TMUTexDataCtrlFaultSet( const unsigned long ErrorMark, const uint32_t ErrorMark,
double dScore, const double dScore,
const def_eFaultSource eFaultSourceCASL, const def_eFaultSource eFaultSource)
const def_eFaultSource eFaultSourceCASH,
const def_eFaultSource eFaultSourceRAS,
const def_eFaultSource eFaultSourceWE
)
{ {
if( ErrorMark && (count_bit32(ErrorMark) > 16) ) const uint16_t u16pix1 = ErrorMark & 0xFFFF;
{ const uint16_t u16pix2 = (ErrorMark>>16) & 0xFFFF;
if(ErrorMark & 0x000000FF)
FaultSource_AddScore(eFaultSourceCASL,dScore); uint16_t u16Bus_r8 = ((u16pix1>>11) & 0x1F) << 3;
if(ErrorMark & 0x0000FF00) uint16_t u16Bus_g8 = ((u16pix1>>5) & 0x3F) << 2;
FaultSource_AddScore(eFaultSourceCASH,dScore); uint16_t u16Bus_b8 = ((u16pix1>>0) & 0x1F) << 3;
if(ErrorMark & 0x00FF0000) uint16_t u16Bus_a8 = 0;
FaultSource_AddScore(eFaultSourceCASL,dScore); /*
if(ErrorMark & 0xFF000000) uint16_t u16Fault_W1 = (u16Bus_g8<<8) + u16Bus_b8;
FaultSource_AddScore(eFaultSourceCASH,dScore); uint16_t u16Fault_W2 = (u16Bus_a8<<8) + u16Bus_r8;
*/
FaultSource_AddScore(eFaultSourceRAS,dScore / 2);
FaultSource_AddScore(eFaultSourceWE,dScore / 2); /* Incoming data wont have Alpha channel, so we must normalize
} * Fault weight */
ByteBitFaultSet(pCtx, u16Bus_b8, dScore/2, eFaultSource);
ByteBitFaultSet(pCtx, u16Bus_g8, dScore, eFaultSource + 8);
ByteBitFaultSet(pCtx, u16Bus_r8, dScore/2, eFaultSource);
//ByteBitFaultSet(pCtx, u16Bus_a8, dScore, eFaultSource + 8);
u16Bus_r8 = ((u16pix2>>11) & 0x1F) << 3;
u16Bus_g8 = ((u16pix2>>5) & 0x3F) << 2;
u16Bus_b8 = ((u16pix2>>0) & 0x1F) << 3;
u16Bus_a8 = 0;
/*
uint16_t u16Fault_W3 = (u16Bus_g8<<8) + u16Bus_b8;
uint16_t u16Fault_W4 = (u16Bus_a8<<8) + u16Bus_r8;
*/
/* Incoming data wont have Alpha channel, so we must normalize
* Fault weight */
ByteBitFaultSet(pCtx, u16Bus_b8, dScore/2, eFaultSource);
ByteBitFaultSet(pCtx, u16Bus_g8, dScore, eFaultSource + 8);
ByteBitFaultSet(pCtx, u16Bus_r8, dScore/2, eFaultSource);
//ByteBitFaultSet(pCtx, u16Bus_a8, dScore, eFaultSource + 8);
} }
void
RGBToBus_Fault_Quartets( def_sFaultSourceScoreRec* const pCtx,
const uint32_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSource1,
const def_eFaultSource eFaultSource2,
const def_eFaultSource eFaultSource3,
const def_eFaultSource eFaultSource4)
{
const uint16_t u16pix1 = ErrorMark & 0xFFFF;
const uint16_t u16pix2 = (ErrorMark>>16) & 0xFFFF;
uint16_t u16Bus_r8 = ((u16pix1>>11) & 0x1F) << 3;
uint16_t u16Bus_g8 = ((u16pix1>>5) & 0x3F) << 2;
uint16_t u16Bus_b8 = ((u16pix1>>0) & 0x1F) << 3;
uint16_t u16Bus_a8 = 0;
/*
uint16_t u16Fault_W1 = (u16Bus_g8<<8) + u16Bus_b8;
uint16_t u16Fault_W2 = (u16Bus_a8<<8) + u16Bus_r8;
*/
/* Incoming data wont have Alpha channel, so we must normalize
* Fault weight */
QuartetBitFaultSet(pCtx, u16Bus_b8 & 0xF, dScore/2, eFaultSource1);
QuartetBitFaultSet(pCtx, (u16Bus_b8<<4) & 0xF, dScore/2, eFaultSource2);
QuartetBitFaultSet(pCtx, u16Bus_g8 & 0xF, dScore, eFaultSource3);
QuartetBitFaultSet(pCtx, (u16Bus_g8<<4) & 0xF, dScore, eFaultSource4);
QuartetBitFaultSet(pCtx, u16Bus_r8 & 0xF, dScore/2, eFaultSource1);
QuartetBitFaultSet(pCtx, (u16Bus_r8<<4) & 0xF, dScore/2, eFaultSource2);
//QuartetBitFaultSet(pCtx, u16Bus_a8 & 0xF, dScore, eFaultSource3);
//QuartetBitFaultSet(pCtx, (u16Bus_a8<<4) & 0xF, dScore, eFaultSource4);
u16Bus_r8 = ((u16pix2>>11) & 0x1F) << 3;
u16Bus_g8 = ((u16pix2>>5) & 0x3F) << 2;
u16Bus_b8 = ((u16pix2>>0) & 0x1F) << 3;
u16Bus_a8 = 0;
/*
uint16_t u16Fault_W3 = (u16Bus_g8<<8) + u16Bus_b8;
uint16_t u16Fault_W4 = (u16Bus_a8<<8) + u16Bus_r8;
*/
/* Incoming data wont have Alpha channel, so we must normalize
* Fault weight */
QuartetBitFaultSet(pCtx, u16Bus_b8 & 0xF, dScore/2, eFaultSource1);
QuartetBitFaultSet(pCtx, (u16Bus_b8<<4) & 0xF, dScore/2, eFaultSource2);
QuartetBitFaultSet(pCtx, u16Bus_g8 & 0xF, dScore, eFaultSource3);
QuartetBitFaultSet(pCtx, (u16Bus_g8<<4) & 0xF, dScore, eFaultSource4);
QuartetBitFaultSet(pCtx, u16Bus_r8 & 0xF, dScore/2, eFaultSource1);
QuartetBitFaultSet(pCtx, (u16Bus_r8<<4) & 0xF, dScore/2, eFaultSource2);
//QuartetBitFaultSet(pCtx, u16Bus_a8 & 0xF, dScore, eFaultSource3);
//QuartetBitFaultSet(pCtx, (u16Bus_a8<<4) & 0xF, dScore, eFaultSource4);
}

File diff suppressed because it is too large Load Diff

2
Jenkinsfile vendored
View File

@@ -9,7 +9,7 @@ pipeline {
stage('SaveBin') stage('SaveBin')
{ {
steps { steps {
archiveArtifacts artifacts: 'v2memtest' archiveArtifacts artifacts: 'v2-tmu-memtester'
} }
} }
} }

View File

@@ -1,25 +1,31 @@
CC=gcc CC=gcc
CFLAGS= -Wall -std=gnu99 -O6 -march=pentium3 -fomit-frame-pointer -funroll-loops \
-fexpensive-optimizations -ffast-math -fno-strict-aliasing
CFLAGS+=-I. -I./glide/headers -I/usr/include/glide
CFLAGS+=-DCVG
# -funroll-loops
CFLAGS= -Wall -std=gnu99 -O6 -m32 -march=pentium3 -fomit-frame-pointer \
-fexpensive-optimizations -ffast-math -fno-strict-aliasing \
-I. -I./glide/headers -I/usr/include/glide \
-DCVG
LFLAGS=-L./glide/lib -lglide LFLAGS=-L./glide/lib -lglide
OBJ=main.o \ OBJ=OBJs/main.o \
FaultSources.o \ OBJs/FaultSources.o \
Utils.o \ OBJs/Utils.o \
Draw.o \ OBJs/Draw.o \
Test_Address.o \ OBJs/Test_Common.o \
Test_Data.o \ OBJs/Test_Control.o \
Test_Data_Huge.o OBJs/Test_Address.o \
OBJs/Test_Data.o \
OBJs/Test_Data_NoMem_TestPatterns.o \
OBJs/Test_Data_NoMem.o \
OBJs/Test_Data_Huge.o
%.o: %.c HEADERS := $(notdir $(wildcard *.h))
OBJs/%.o: %.c $(HEADERS)
$(CC) -c -o $@ $< $(CFLAGS) $(CC) -c -o $@ $< $(CFLAGS)
v2memtest : $(OBJ) v2-tmu-memtester : $(OBJ)
$(CC) -o $@ $(LFLAGS) $^ $(CC) -o $@ $(LFLAGS) $^
all: v2memtest all: v2-tmu-memtester

0
OBJs/.gitkeep Normal file
View File

View File

@@ -1,7 +1,7 @@
--- ---
include_toc: true include_toc: true
--- ---
# Voodoo 2 (TMU) MemTest # Voodoo 2 TMU MemTester
## Introduction ## Introduction
@@ -27,6 +27,12 @@ As this is an open-source tool, feel free to Fork, Raise Tickets or to send Pull
## Requirements ## Requirements
### The Easiest way :
[RetroDebian Live](https://gitea.chacha.ddns.net/chacha/RetroDebian)
### The Hard way :
To build this tool you need GNU Make, GCC and Glide 2.x SDK. To build this tool you need GNU Make, GCC and Glide 2.x SDK.
Requirement to run this tools depends on the build platform and options. Requirement to run this tools depends on the build platform and options.
@@ -59,16 +65,16 @@ Here is the [hopefully updated] project status.
- [X] test data (bit move) - [X] test data (bit move)
- [X] test data (random pattern) - [X] test data (random pattern)
- [X] test address - [X] test address
- [ ] test data (huge block) - [X] test data (huge block)
- [ ] test draw triangle shape (no texture) - [X] test draw no-mem (no texture)
- [ ] CLI options - [ ] CLI options
- [ ] help - [X] help
- [ ] single test run - [X] single test run
- [ ] output failure results to file (TSV) - [ ] output failure results to file (TSV)
- [ ] log level - [X] log level
- [ ] log to file - [ ] log to file
- [ ] fault analysis - [X] fault analysis
- [ ] autonomous test delivery (.exe or iso) - [X] standalone easy tool (.exe or iso)
- [ ] Chore (might never be done...) - [ ] Chore (might never be done...)
- [ ] use fixed size types (***e.g. FxUINT32 or uint32_t instead of unsigned long***) - [ ] use fixed size types (***e.g. FxUINT32 or uint32_t instead of unsigned long***)
- [ ] port / test on more modern build system - [ ] port / test on more modern build system
@@ -82,8 +88,8 @@ Here is the [hopefully updated] project status.
- [ ] any RAM ICs - [ ] any RAM ICs
- [ ] DQx - [ ] DQx
- [X] short - [X] short
- [ ] force 0 - [X] force 0
- [ ] force 1 - [X] force 1
- [ ] floating - [ ] floating
- [ ] addresses - [ ] addresses
- [X] short - [X] short
@@ -105,20 +111,20 @@ Here is the [hopefully updated] project status.
- [ ] force 0 - [ ] force 0
- [ ] force 1 - [ ] force 1
- [ ] floating - [ ] floating
- [ ] 1MB TMU test (faulty) - [X] 1MB TMU test (= faulty voodoo2)
- [ ] 2MB TMU test (= 8MB Voodoo2) - [X] 2MB TMU test (= 8MB Voodoo2)
- [ ] 4MB TMU test (= 12MB Voodoo2) - [X] 4MB TMU test (= 12MB Voodoo2)
- [ ] TMU0 or TMU1 only* - [X] TMU0 or TMU1 only*
- [ ] FBI to TMU1 fault - [ ] FBI to TMU1 fault
- [ ] FBI to TMU0 fault - [ ] FBI to TMU0 fault
- [ ] TMU1 to TMU0 fault - [X] TMU1 to TMU0 fault
- [ ] TMU0 to FBI fault - [X] TMU0 to FBI fault
- [ ] Documentation - [ ] Documentation
- [ ] CLI help - [X] CLI help (integrated in the bin)
- [ ] short youtube video - [ ] short youtube video
- [ ] better explanation on how memory is accessed - [ ] better explanation on how memory is accessed
- [ ] Other / Ideas - [ ] Other / Ideas
- [ ] integration with (or in) Witchery ? - [ ] integration with Witchery ?
## TMU0 Memory test ## TMU0 Memory test
@@ -155,7 +161,7 @@ Here is a simplified data flow diagram:
1. CPU configures texture base address and sends data to the FBI 1. CPU configures texture base address and sends data to the FBI
2. The FBI streams the texture to TMU0 2. The FBI streams the texture to TMU0
3. TMU0 writes the texture into his private memory 3. TMU0 writes the texture into his private memory
4. The CPU sends a request to TMU0 (through the FBI) to render a triangle using this texture (double the size triangle) 4. The CPU sends a request to TMU0 (through the FBI) to draw a square
5. TMU0 streams the rendered pixels to the FBI 5. TMU0 streams the rendered pixels to the FBI
6. The FBI writes the pixel to the frame buffer 6. The FBI writes the pixel to the frame buffer
7. The CPU requests the pixels using the Linear Frame Buffer access 7. The CPU requests the pixels using the Linear Frame Buffer access
@@ -201,20 +207,17 @@ Here is a simplified data flow diagram:
1. CPU configures texture base address and sends data to the FBI 1. CPU configures texture base address and sends data to the FBI
2. The FBI streams the texture to TMU1 2. The FBI streams the texture to TMU1
3. TMU1 writes the texture into his private memory 3. TMU1 writes the texture into his private memory
4. The CPU sends a request to TMU1 (through the FBI) to render a triangle using this texture (double the size triangle) 4. The CPU sends a request to TMU1 (through the FBI) to draw a square
5. TMU1 streams the rendered pixels to TMU0 5. TMU1 streams the rendered pixels to TMU0
6. TMU0 streams the rendered pixels to the FBI 6. TMU0 streams the rendered pixels to the FBI
7. The FBI writes the pixel to the frame buffer 7. The FBI writes the pixel to the frame buffer
8. The CPU requests the pixels using the Linear Frame Buffer access 8. The CPU requests the pixels using the Linear Frame Buffer access
9. The CPU can compare the rendered value with the original texture 9. The CPU can compare the rendered value with the original texture
## Accessing different memory regions
TBD
## Note on driver aspect ## Note on driver aspect
This tool requires access to low level registers / structures that are not exposed from outside Glide drivers. This tool requires access to low level registers / structures that are not exposed outside Glide drivers.
For this reason, it is compiled using driver-internal headers. For this reason, it is compiled using driver-internal headers.
@@ -224,4 +227,4 @@ It is possible that this tool will only work with the driver it is build accross
## Licence ## Licence
**GPL-3.0-or-later** **GPL-3.0-or-later**

View File

@@ -15,11 +15,16 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <stdint.h>
#include <stdio.h>
#include "cvg.h" #include "cvg.h"
#include <glide.h> #include <glide.h>
#include "sst1init.h" #include "sst1init.h"
#include "fxpci.h" #include "fxpci.h"
#include "Utils.h"
#include "V2MemTest.h"
#include "FaultSources.h" #include "FaultSources.h"
#include "Utils.h" #include "Utils.h"
#include "Draw.h" #include "Draw.h"
@@ -28,42 +33,34 @@
typedef struct _def_sTestAddress { typedef struct _def_sTestAddress {
FxU32 u32Addr; FxU32 u32Addr;
unsigned char nBank; // RAS0 and RAS1 (Front/Back) unsigned char nBank; /* RAS0 and RAS1 (Front/Back) */
unsigned char nColBit; unsigned char nColBit;
unsigned char nRowBit; unsigned char nRowBit;
}def_sTestAddress; }def_sTestAddress;
unsigned long unsigned long
RenderTestAddress( sst1DeviceInfoStruct* devInfo, RenderTestAddress( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const char ucNumTMU, const char ucNumTMU,
const unsigned char RamSizeMB) const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{ {
devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ; unsigned long NbErr=0;
sst1InitIdle(sst); 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]); ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);
/*
sst1InitIdle(sst);
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, 0x5000 | (devInfo->tmuInit0[(int)ucNumTMU] & ~0x7000));
sst1InitIdle(sst);
*/
// set downstream TMUs to passthrough /* set downstream TMUs to passthrough */
for (int i=0; i<ucNumTMU; i++) for (int i=0; i<ucNumTMU; i++)
ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS); ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS);
unsigned long NbErr=0;
//long TestVal1;
//long TestVal2;
//long TestValBlank1;
//long TestValBlank2;
const def_sTestAddress add_list[] = const def_sTestAddress add_list[] =
{ {
// Bank0 /* Bank0 */
{0x000000,0,0,0}, {0x000000,0,0,0},
/* not addressable because its a 64bit bus /* not addressable because its a 64bit bus
{0x000001,0,0,0,0} {0x000001,0,0,0,0}
@@ -71,93 +68,150 @@ RenderTestAddress( sst1DeviceInfoStruct* devInfo,
{0x000004,0,0,0,0} {0x000004,0,0,0,0}
*/ */
{0x000008,0,1,0}, {0x000008,0,1,0},
{0x000010,0,2,0}, {0x000018,0,2,0}, // target + adjacent pin /* {target pin} */
{0x000020,0,3,0}, {0x000030,0,3,0}, {0x000010,0,2,0},
{0x000040,0,4,0}, {0x000060,0,4,0}, {0x000020,0,3,0},
{0x000080,0,5,0}, {0x0000C0,0,5,0}, {0x000040,0,4,0},
{0x000100,0,6,0}, {0x000180,0,6,0}, {0x000080,0,5,0},
{0x000200,0,7,0}, {0x000300,0,7,0}, {0x000100,0,6,0},
{0x000400,0,8,0}, {0x000600,0,8,0}, {0x000200,0,7,0},
{0x000800,0,9,0}, {0x000C00,0,9,0}, // => Ignoring adjacent for now {0x000400,0,8,0},
{0x001000,0,0,1}, {0x001800,0,0,1}, // It seems useless {0x000800,0,9,0},
{0x002000,0,0,2}, {0x003000,0,0,2}, {0x001000,0,0,1},
{0x004000,0,0,3}, {0x006000,0,0,3}, {0x002000,0,0,2},
{0x008000,0,0,4}, {0x00C000,0,0,4}, {0x004000,0,0,3},
{0x010000,0,0,5}, {0x018000,0,0,5}, {0x008000,0,0,4},
{0x020000,0,0,6}, {0x030000,0,0,6}, {0x010000,0,0,5},
{0x040000,0,0,7}, {0x060000,0,0,7}, {0x020000,0,0,6},
{0x080000,0,0,8}, {0x0C0000,0,0,8}, {0x040000,0,0,7},
{0x100000,0,0,9}, {0x180000,0,0,9}, {0x080000,0,0,8},
{0x100000,0,0,9},
// Bank1
/* Bank1 */
{0x200000,1,0,0}, {0x200000,1,0,0},
/* not addressable because its a 64bit bus /* not addressable because its a 64bit bus
{0x200001,0,0,0,0} {0x200001,1,0,0,0}
{0x200002,0,0,0,0} {0x200002,1,0,0,0}
{0x200004,0,0,0,0} {0x200004,1,0,0,0}
*/ */
{0x200008,1,1,0}, {0x200008,1,1,0},
{0x200010,1,2,0}, {0x200018,1,2,0}, /* {target pin} */
{0x200020,1,3,0}, {0x200030,1,3,0}, {0x200010,1,2,0},
{0x200040,1,4,0}, {0x200060,1,4,0}, {0x200020,1,3,0},
{0x200080,1,5,0}, {0x2000C0,1,5,0}, {0x200040,1,4,0},
{0x200100,1,6,0}, {0x200180,1,6,0}, {0x200080,1,5,0},
{0x200200,1,7,0}, {0x200300,1,7,0}, {0x200100,1,6,0},
{0x200400,1,8,0}, {0x200600,1,8,0}, {0x200200,1,7,0},
{0x200800,1,9,0}, {0x200C00,1,9,0}, {0x200400,1,8,0},
{0x201000,1,0,1}, {0x201800,1,0,1}, {0x200800,1,9,0},
{0x202000,1,0,2}, {0x203000,1,0,2}, {0x201000,1,0,1},
{0x204000,1,0,3}, {0x206000,1,0,3}, {0x202000,1,0,2},
{0x208000,1,0,4}, {0x20C000,1,0,4}, {0x204000,1,0,3},
{0x210000,1,0,5}, {0x218000,1,0,5}, {0x208000,1,0,4},
{0x220000,1,0,6}, {0x230000,1,0,6}, {0x210000,1,0,5},
{0x240000,1,0,7}, {0x260000,1,0,7}, {0x220000,1,0,6},
{0x280000,1,0,8}, {0x2C0000,1,0,8}, {0x240000,1,0,7},
{0x300000,1,0,9}, {0x380000,1,0,9}, {0x280000,1,0,8},
{0x300000,1,0,9},
}; };
logT("testing %d MB of memory\n",RamSizeMB);
for(unsigned char idx=0; for(unsigned char idx=0;
idx < sizeof(add_list)/sizeof(def_sTestAddress); idx < (sizeof(add_list)/sizeof(def_sTestAddress));
idx++) idx++)
{ {
/* Skipping unsupported addresses */
if(RamSizeMB<4 && add_list[idx].u32Addr >= 0x300000) continue; if(RamSizeMB<4 && add_list[idx].u32Addr >= 0x300000) continue;
if(RamSizeMB<3 && add_list[idx].u32Addr >= 0x200000) continue; if(RamSizeMB<3 && add_list[idx].u32Addr >= 0x200000) continue;
if(RamSizeMB<2 && add_list[idx].u32Addr >= 0x100000) continue; if(RamSizeMB<2 && add_list[idx].u32Addr >= 0x100000) continue;
const FxU32 TestVal1 = get_notnull_random_balanced_mByte(); logT("idx = %d\n",idx);
const FxU32 TestVal2 = get_notnull_random_balanced_mByte(); logT("u32Addr = 0x%08X\n",add_list[idx].u32Addr);
const FxU32 TestValBlank1 = get_notnull_random_balanced_mByte();
const FxU32 TestValBlank2 = get_notnull_random_balanced_mByte();
// Clearing memory targets const uint32_t TestVal1 = get_notnull_random_balanced_mByte();
logT("TestVal1 = %08X\n",TestVal1);
uint32_t TestVal2 = 0;
do
{
TestVal2 = get_notnull_random_balanced_mByte();
}
while((count_bit32((TestVal2 ^ TestVal1)) < 12));
logT("TestVal2 = %08X\n",TestVal2);
uint32_t TestValBlank1 = 0;
do
{
TestValBlank1 = get_notnull_random_balanced_mByte();
}
while( (count_bit32((TestValBlank1 ^ TestVal1) & 0x0000FFFF) < 6)
|| (count_bit32((TestValBlank1 ^ TestVal1) & 0xFFFF0000) < 6)
|| (count_bit32((TestValBlank1 ^ TestVal2)) < 12));
logT("TestValBlank1 = %08X\n",TestValBlank1);
uint32_t TestValBlank2 = 0;
do
{
TestValBlank2 = get_notnull_random_balanced_mByte();
}
while( (count_bit32((TestValBlank2 ^ TestVal2) & 0x0000FFFF) < 6)
|| (count_bit32((TestValBlank2 ^ TestVal2) & 0xFFFF0000) < 6)
|| (count_bit32((TestValBlank2 ^ TestValBlank1)) < 12)
|| (count_bit32((TestValBlank2 ^ TestVal1)) < 12));
logT("TestValBlank2 = %08X\n",TestValBlank2);
/* Clearing memory targets */
for(unsigned char idxclr=0; for(unsigned char idxclr=0;
idxclr < sizeof(add_list)/sizeof(def_sTestAddress); idxclr < sizeof(add_list)/sizeof(def_sTestAddress);
idxclr++) idxclr++)
{ {
/* Skipping unsupported addresses */
if(RamSizeMB<4 && add_list[idxclr].u32Addr >= 0x300000) continue; if(RamSizeMB<4 && add_list[idxclr].u32Addr >= 0x300000) continue;
if(RamSizeMB<3 && add_list[idxclr].u32Addr >= 0x200000) continue; if(RamSizeMB<3 && add_list[idxclr].u32Addr >= 0x200000) continue;
if(RamSizeMB<2 && add_list[idxclr].u32Addr >= 0x100000) continue; if(RamSizeMB<2 && add_list[idxclr].u32Addr >= 0x100000) continue;
/* set to mem addr */ /* set base mem @ */
ISET(sstregs->texBaseAddr, (add_list[idxclr].u32Addr>>3)); ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (add_list[idxclr].u32Addr>>3));
/* First line, using bits 00..31*/
volatile const FxU32 *texAddrBlank = (ucNumTMU<<(21-2)) + (((FxU32)0/*LOD0*/)<<(17-2)) + (FxU32 *)SST_TEX_ADDRESS(sst); /* set @ to first line, using bits 00..31*/
ISET(texAddrBlank[0], TestValBlank1); /* write a value */ volatile const FxU32 *texAddrBlank
/* Second line, to use bits 32..63*/ = (ucNumTMU<<(21-2))
volatile const FxU32 *texAddrBlank2 = (ucNumTMU<<(21-2)) + (((FxU32)0/*LOD0*/)<<(17-2)) + (1<<(9-2))+ (FxU32 *)SST_TEX_ADDRESS(sst); + (((FxU32)0)<<(17-2)) /*LOD0*/
ISET(texAddrBlank2[0], TestValBlank2); /* write a value */ + (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddrBlank[0], TestValBlank1);
/* set @ to second line, to use bits 32..63*/
volatile const FxU32 *texAddrBlank2
= (ucNumTMU<<(21-2))
+ (((FxU32)0)<<(17-2)) /*LOD0*/
+ (1<<(9-2))
+ (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddrBlank2[0], TestValBlank2);
} }
/* set to mem addr */ /* set base mem @ */
ISET(sstregs->texBaseAddr, (add_list[idx].u32Addr>>3)); ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (add_list[idx].u32Addr>>3));
/* First line, using bits 00..31*/
volatile const FxU32 *texAddr = (ucNumTMU<<(21-2)) + (((FxU32)0/*LOD0*/)<<(17-2)) + (FxU32 *)SST_TEX_ADDRESS(sst); /* set @ to first line, using bits 00..31*/
ISET(texAddr[0], TestVal1); /* write a value */ volatile const FxU32 *texAddr
/* Second line, to use bits 32..63*/ = (ucNumTMU<<(21-2))
volatile const FxU32 *texAddr2 = (ucNumTMU<<(21-2)) + (((FxU32)0/*LOD0*/)<<(17-2)) + (1<<(9-2))+ (FxU32 *)SST_TEX_ADDRESS(sst); + (((FxU32)0)<<(17-2)) /*LOD0*/
ISET(texAddr2[0], TestVal2); /* write a value */ + (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddr[0], TestVal1);
/* set @ to second line, to use bits 32..63*/
volatile const FxU32 *texAddr2
= (ucNumTMU<<(21-2))
+ (((FxU32)0)<<(17-2)) /*LOD0*/
+ (1<<(9-2))
+ (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddr2[0], TestVal2);
// Checking expected memory map is there /* Checking expected memory map is there */
for(unsigned char idxdraw=0; for(unsigned char idxdraw=0;
idxdraw < sizeof(add_list) / sizeof(def_sTestAddress); idxdraw < sizeof(add_list) / sizeof(def_sTestAddress);
idxdraw++) idxdraw++)
@@ -165,110 +219,55 @@ RenderTestAddress( sst1DeviceInfoStruct* devInfo,
if(RamSizeMB<4 && add_list[idxdraw].u32Addr >= 0x300000) continue; if(RamSizeMB<4 && add_list[idxdraw].u32Addr >= 0x300000) continue;
if(RamSizeMB<3 && add_list[idxdraw].u32Addr >= 0x200000) continue; if(RamSizeMB<3 && add_list[idxdraw].u32Addr >= 0x200000) continue;
if(RamSizeMB<2 && add_list[idxdraw].u32Addr >= 0x100000) continue; if(RamSizeMB<2 && add_list[idxdraw].u32Addr >= 0x100000) continue;
logT("idxdraw = %d, row = %d; col = %d\n",idxdraw,add_list[idxdraw].nRowBit,add_list[idxdraw].nColBit);
// testing copy beyond tested bit is useless & can raise //if(idxdraw > idx) break;
// false positive
if(idxdraw > idx) break; clearScreen(sstregs,0x00000000,2,2);
/* set to mem addr */ /* set to mem addr */
ISET(sstregs->texBaseAddr, (add_list[idxdraw].u32Addr >> 3)); ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (add_list[idxdraw].u32Addr >> 3));
drawTriangle(sstregs, 0, 0, 4); /* draw a 4x4 triangle */
// First line, to use bits 00..31
const FxU32 L1 = IGET(sst[(SST_LFB_ADDR>>2) + 0]);
// Second line,to use bits 32..63
const FxU32 L2 = IGET(sst[(SST_LFB_ADDR>>2) + (2048>>2) + 0]);
const unsigned long ErrorMark_L1 = (idxdraw == idx) ? (L1 ^ TestVal1) : (L1 ^ TestValBlank1); /* draw a 2x2 square */
const unsigned long ErrorMark_L2 = (idxdraw == idx) ? (L2 ^ TestVal2) : (L2 ^ TestValBlank2); drawSquare(sstregs, ucNumTMU, 0, 0, 2);
sst1InitIdle(sst);
/* first line, to use bits 00..31 */
const uint32_t L1 = IGET(sst[(SST_LFB_ADDR>>2) + 0]);
/* second line, to use bits 32..63 */
const uint32_t L2 = IGET(sst[(SST_LFB_ADDR>>2) + (2048>>2) + 0]);
const uint32_t ErrorMark_L1 = (idxdraw == idx) ? (L1 ^ TestVal1) : (L1 ^ TestValBlank1);
const uint32_t ErrorMark_L2 = (idxdraw == idx) ? (L2 ^ TestVal2) : (L2 ^ TestValBlank2);
const uint32_t ErrorMarkOther_L1 = (idxdraw == idx) ? (L1 ^ TestValBlank1) : (L1 ^ TestVal1);
const uint32_t ErrorMarkOther_L2 = (idxdraw == idx) ? (L2 ^ TestValBlank2) : (L2 ^ TestVal2);
const unsigned long ErrorMarkBlank_L1 = (idxdraw == idx) ? (L1 ^ TestValBlank1) : (L1 ^ TestVal1);
const unsigned long ErrorMarkBlank_L2 = (idxdraw == idx) ? (L2 ^ TestValBlank2) : (L2 ^ TestVal2) ;
if(ErrorMark_L1 || ErrorMark_L2) if(ErrorMark_L1 || ErrorMark_L2)
{ {
const def_eFaultSource TMUTexADDR_0_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_0_0 : U8_TMU1_TEX_ADDR_0_0; const def_eFaultSource TMUTexADDR_0_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_0_0 : U8_TMU1_TEX_ADDR_0_0;
const def_eFaultSource TMUTexADDR_1_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_1_0 : U8_TMU1_TEX_ADDR_1_0; const def_eFaultSource TMUTexADDR_1_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_1_0 : U8_TMU1_TEX_ADDR_1_0;
const def_eFaultSource TMUTexADDR_2_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_2_0 : U8_TMU1_TEX_ADDR_2_0; const def_eFaultSource TMUTexADDR_2_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_2_0 : U8_TMU1_TEX_ADDR_2_0;
const def_eFaultSource TMUTexADDR_3_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_3_0 : U8_TMU1_TEX_ADDR_3_0; const def_eFaultSource TMUTexADDR_3_0 = (ucNumTMU == 0) ? U9_TMU0_TEX_ADDR_3_0 : U8_TMU1_TEX_ADDR_3_0;
const def_eFaultSource TMUTexWE = (ucNumTMU == 0) ? U9_TMU0_TEX_WE : U8_TMU1_TEX_WE; const def_eFaultSource _MEMChip_B0_0_A0 = (ucNumTMU == 0) ? U14_A0 : U13_A0;
const def_eFaultSource TMUTexCAS0 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS0 : U8_TMU1_TEX_CAS0; const def_eFaultSource _MEMChip_B0_1_A0 = (ucNumTMU == 0) ? U12_A0 : U11_A0;
const def_eFaultSource TMUTexCAS1 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS1 : U8_TMU1_TEX_CAS1; const def_eFaultSource _MEMChip_B0_2_A0 = (ucNumTMU == 0) ? U18_A0 : U16_A0;
const def_eFaultSource TMUTexCAS2 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS2 : U8_TMU1_TEX_CAS2; const def_eFaultSource _MEMChip_B0_3_A0 = (ucNumTMU == 0) ? U17_A0 : U15_A0;
const def_eFaultSource TMUTexCAS3 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS3 : U8_TMU1_TEX_CAS3; const def_eFaultSource _MEMChip_B1_0_A0 = (ucNumTMU == 0) ? U23_A0 : U27_A0;
const def_eFaultSource _TMUTexRAS0 = (ucNumTMU == 0) ? U9_TMU0_TEX_RAS0 : U8_TMU1_TEX_RAS0; const def_eFaultSource _MEMChip_B1_1_A0 = (ucNumTMU == 0) ? U24_A0 : U28_A0;
const def_eFaultSource _TMUTexRAS1 = (ucNumTMU == 0) ? U9_TMU0_TEX_RAS1 : U8_TMU1_TEX_RAS1; const def_eFaultSource _MEMChip_B1_2_A0 = (ucNumTMU == 0) ? U25_A0 : U29_A0;
const def_eFaultSource TMUTexRASCurrent = (add_list[idxdraw].nBank == 0) ? _TMUTexRAS0 : _TMUTexRAS1; const def_eFaultSource _MEMChip_B1_3_A0 = (ucNumTMU == 0) ? U26_A0 : U30_A0;
const def_eFaultSource _MEMChip_B0_0_A0 = (ucNumTMU == 0) ? U14_A0 : U13_A0;
const def_eFaultSource _MEMChip_B0_1_A0 = (ucNumTMU == 0) ? U12_A0 : U11_A0;
const def_eFaultSource _MEMChip_B0_2_A0 = (ucNumTMU == 0) ? U18_A0 : U16_A0;
const def_eFaultSource _MEMChip_B0_3_A0 = (ucNumTMU == 0) ? U17_A0 : U15_A0;
const def_eFaultSource _MEMChip_B1_0_A0 = (ucNumTMU == 0) ? U23_A0 : U27_A0;
const def_eFaultSource _MEMChip_B1_1_A0 = (ucNumTMU == 0) ? U24_A0 : U28_A0;
const def_eFaultSource _MEMChip_B1_2_A0 = (ucNumTMU == 0) ? U25_A0 : U29_A0;
const def_eFaultSource _MEMChip_B1_3_A0 = (ucNumTMU == 0) ? U26_A0 : U30_A0;
const def_eFaultSource MEMChip_0_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_A0 : _MEMChip_B1_0_A0; const def_eFaultSource MEMChip_0_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_A0 : _MEMChip_B1_0_A0;
const def_eFaultSource MEMChip_1_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_A0 : _MEMChip_B1_1_A0; const def_eFaultSource MEMChip_1_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_A0 : _MEMChip_B1_1_A0;
const def_eFaultSource MEMChip_2_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_A0 : _MEMChip_B1_2_A0; const def_eFaultSource MEMChip_2_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_A0 : _MEMChip_B1_2_A0;
const def_eFaultSource MEMChip_3_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_A0 : _MEMChip_B1_3_A0; const def_eFaultSource MEMChip_3_A0 = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_A0 : _MEMChip_B1_3_A0;
const def_eFaultSource _MEMChip_B0_0_CASL = (ucNumTMU == 0) ? U14_CASL : U13_CASL;
const def_eFaultSource _MEMChip_B0_1_CASL = (ucNumTMU == 0) ? U12_CASL : U11_CASL;
const def_eFaultSource _MEMChip_B0_2_CASL = (ucNumTMU == 0) ? U18_CASL : U16_CASL;
const def_eFaultSource _MEMChip_B0_3_CASL = (ucNumTMU == 0) ? U17_CASL : U15_CASL;
const def_eFaultSource _MEMChip_B1_0_CASL = (ucNumTMU == 0) ? U23_CASL : U27_CASL;
const def_eFaultSource _MEMChip_B1_1_CASL = (ucNumTMU == 0) ? U24_CASL : U28_CASL;
const def_eFaultSource _MEMChip_B1_2_CASL = (ucNumTMU == 0) ? U25_CASL : U29_CASL;
const def_eFaultSource _MEMChip_B1_3_CASL = (ucNumTMU == 0) ? U26_CASL : U30_CASL;
const def_eFaultSource MEMChip_0_CASL = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_CASL : _MEMChip_B1_0_CASL;
const def_eFaultSource MEMChip_1_CASL = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_CASL : _MEMChip_B1_1_CASL;
const def_eFaultSource MEMChip_2_CASL = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_CASL : _MEMChip_B1_2_CASL;
const def_eFaultSource MEMChip_3_CASL = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_CASL : _MEMChip_B1_3_CASL;
const def_eFaultSource _MEMChip_B0_0_CASH = (ucNumTMU == 0) ? U14_CASH : U13_CASH;
const def_eFaultSource _MEMChip_B0_1_CASH = (ucNumTMU == 0) ? U12_CASH : U11_CASH; const def_eFaultSource MEMChip_0_A0_Other = (add_list[idxdraw].nBank == 1) ? _MEMChip_B0_0_A0 : _MEMChip_B1_0_A0;
const def_eFaultSource _MEMChip_B0_2_CASH = (ucNumTMU == 0) ? U18_CASH : U16_CASH; const def_eFaultSource MEMChip_1_A0_Other = (add_list[idxdraw].nBank == 1) ? _MEMChip_B0_1_A0 : _MEMChip_B1_1_A0;
const def_eFaultSource _MEMChip_B0_3_CASH = (ucNumTMU == 0) ? U17_CASH : U15_CASH; const def_eFaultSource MEMChip_2_A0_Other = (add_list[idxdraw].nBank == 1) ? _MEMChip_B0_2_A0 : _MEMChip_B1_2_A0;
const def_eFaultSource _MEMChip_B1_0_CASH = (ucNumTMU == 0) ? U23_CASH : U27_CASH; const def_eFaultSource MEMChip_3_A0_Other = (add_list[idxdraw].nBank == 1) ? _MEMChip_B0_3_A0 : _MEMChip_B1_3_A0;
const def_eFaultSource _MEMChip_B1_1_CASH = (ucNumTMU == 0) ? U24_CASH : U28_CASH;
const def_eFaultSource _MEMChip_B1_2_CASH = (ucNumTMU == 0) ? U25_CASH : U29_CASH;
const def_eFaultSource _MEMChip_B1_3_CASH = (ucNumTMU == 0) ? U26_CASH : U30_CASH;
const def_eFaultSource MEMChip_0_CASH = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_CASH : _MEMChip_B1_0_CASH;
const def_eFaultSource MEMChip_1_CASH = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_CASH : _MEMChip_B1_1_CASH;
const def_eFaultSource MEMChip_2_CASH = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_CASH : _MEMChip_B1_2_CASH;
const def_eFaultSource MEMChip_3_CASH = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_CASH : _MEMChip_B1_3_CASH;
const def_eFaultSource _MEMChip_B0_0_RAS = (ucNumTMU == 0) ? U14_RAS : U13_RAS;
const def_eFaultSource _MEMChip_B0_1_RAS = (ucNumTMU == 0) ? U12_RAS : U11_RAS;
const def_eFaultSource _MEMChip_B0_2_RAS = (ucNumTMU == 0) ? U18_RAS : U16_RAS;
const def_eFaultSource _MEMChip_B0_3_RAS = (ucNumTMU == 0) ? U17_RAS : U15_RAS;
const def_eFaultSource _MEMChip_B1_0_RAS = (ucNumTMU == 0) ? U23_RAS : U27_RAS;
const def_eFaultSource _MEMChip_B1_1_RAS = (ucNumTMU == 0) ? U24_RAS : U28_RAS;
const def_eFaultSource _MEMChip_B1_2_RAS = (ucNumTMU == 0) ? U25_RAS : U29_RAS;
const def_eFaultSource _MEMChip_B1_3_RAS = (ucNumTMU == 0) ? U26_RAS : U30_RAS;
const def_eFaultSource MEMChip_0_RAS = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_RAS : _MEMChip_B1_0_RAS;
const def_eFaultSource MEMChip_1_RAS = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_RAS : _MEMChip_B1_1_RAS;
const def_eFaultSource MEMChip_2_RAS = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_RAS : _MEMChip_B1_2_RAS;
const def_eFaultSource MEMChip_3_RAS = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_RAS : _MEMChip_B1_3_RAS;
const def_eFaultSource _MEMChip_B0_0_WE = (ucNumTMU == 0) ? U14_WE : U13_WE;
const def_eFaultSource _MEMChip_B0_1_WE = (ucNumTMU == 0) ? U12_WE : U11_WE;
const def_eFaultSource _MEMChip_B0_2_WE = (ucNumTMU == 0) ? U18_WE : U16_WE;
const def_eFaultSource _MEMChip_B0_3_WE = (ucNumTMU == 0) ? U17_WE : U15_WE;
const def_eFaultSource _MEMChip_B1_0_WE = (ucNumTMU == 0) ? U23_WE : U27_WE;
const def_eFaultSource _MEMChip_B1_1_WE = (ucNumTMU == 0) ? U24_WE : U28_WE;
const def_eFaultSource _MEMChip_B1_2_WE = (ucNumTMU == 0) ? U25_WE : U29_WE;
const def_eFaultSource _MEMChip_B1_3_WE = (ucNumTMU == 0) ? U26_WE : U30_WE;
const def_eFaultSource MEMChip_0_WE = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_0_WE : _MEMChip_B1_0_WE;
const def_eFaultSource MEMChip_1_WE = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_1_WE : _MEMChip_B1_1_WE;
const def_eFaultSource MEMChip_2_WE = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_2_WE : _MEMChip_B1_2_WE;
const def_eFaultSource MEMChip_3_WE = (add_list[idxdraw].nBank == 0) ? _MEMChip_B0_3_WE : _MEMChip_B1_3_WE;
const def_eFaultSource _RES_RAS0 = (ucNumTMU == 0) ? R118 : R115;
const def_eFaultSource _RES_RAS1 = (ucNumTMU == 0) ? R149 : R150;
const def_eFaultSource RES_RAS = (add_list[idxdraw].nBank == 0) ? _RES_RAS0 : _RES_RAS1;
const def_eFaultSource RES_CAS = (ucNumTMU == 0) ? RA36 : RA32;
const def_eFaultSource RES_WE = (ucNumTMU == 0) ? R117 : R114;
const def_eFaultSource RES_TEXADDR_0_L = (ucNumTMU == 0) ? RA35 : RA31; const def_eFaultSource RES_TEXADDR_0_L = (ucNumTMU == 0) ? RA35 : RA31;
const def_eFaultSource RES_TEXADDR_0_H = (ucNumTMU == 0) ? RA34 : RA30; const def_eFaultSource RES_TEXADDR_0_H = (ucNumTMU == 0) ? RA34 : RA30;
@@ -283,302 +282,178 @@ RenderTestAddress( sst1DeviceInfoStruct* devInfo,
const def_eFaultSource RES_TEXADDR_3_H = (ucNumTMU == 0) ? RA21 : RA19; const def_eFaultSource RES_TEXADDR_3_H = (ucNumTMU == 0) ? RA21 : RA19;
const def_eFaultSource RES_TEXADDR_3_8 = (ucNumTMU == 0) ? R98 : R97; const def_eFaultSource RES_TEXADDR_3_8 = (ucNumTMU == 0) ? R98 : R97;
/* This test is simpler than I wanteed it to be. It focuses
if(count_bit32(ErrorMark_L1 & 0x0000FFFF) > 2) * only on address lines. I thought that reading a totally
{ * unknown value can mean we have a control line issue but it
NbErr++; * is more complex. In case of 2 addresses lines shorted,
/* * the value we will get wont necessary be the one we wrote,
printf("1: %08x %d\n", * at any place. I am not 100% sure why, but it might be
ErrorMark_L1 & 0x0000FFFF, * because of EDO Ram Page mode... Or maybe lines are also used
count_bit32(ErrorMark_L1 & 0x0000FFFF));*/ * internally by the TMU.. or maybe I just missed something !
if((idxdraw == idx) && count_bit32(ErrorMark_L1 & 0x0000FFFF) > 6) *
{ * Anyway, this test should do the job for @ lines (including
FaultSource_AddScore( TMUTexWE, 1.0/4); * shorted). And the Control lines will be tested in a different
FaultSource_AddScore( RES_WE, 1.0/4); * Module where @ lines wont change.
FaultSource_AddScore( MEMChip_0_WE, 1.0/1);
}
if(count_bit32(ErrorMarkBlank_L1 & 0x0000FFFF) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_AddScore( MEMChip_0_A0 + add_list[idx].nColBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_0_0 + add_list[idx].nColBit, 1.0/1);
if(add_list[idx].nColBit < 4)
FaultSource_AddScore( RES_TEXADDR_0_L + add_list[idx].nColBit + 1, 1.0/2);
else if(add_list[idx].nColBit < 8)
FaultSource_AddScore( RES_TEXADDR_0_H + add_list[idx].nColBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_0_8 + 1, 1.0/2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_AddScore( MEMChip_0_A0 + add_list[idx].nRowBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_0_0 + add_list[idx].nRowBit, 1.0/1);
if(add_list[idx].nRowBit < 4)
FaultSource_AddScore( RES_TEXADDR_0_L + add_list[idx].nRowBit + 1, 1.0/2);
else if(add_list[idx].nRowBit < 8)
FaultSource_AddScore( RES_TEXADDR_0_H + add_list[idx].nRowBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_0_8 + 1, 1.0/2);
}
}
else
{
FaultSource_AddScore( TMUTexRASCurrent, 1.0/8);
FaultSource_AddScore( RES_RAS, 1.0/8);
FaultSource_AddScore( MEMChip_0_RAS, 1.0/4);
if(ErrorMark_L1 & 0x000000FF)
{
FaultSource_AddScore( TMUTexCAS0, 1.0/16);
FaultSource_AddScore( RES_CAS+1, 1.0/16);
FaultSource_AddScore( MEMChip_0_CASL, 1.0/8);
}
if(ErrorMark_L1 & 0x0000FF00)
{
FaultSource_AddScore( TMUTexCAS1, 1.0/16);;
FaultSource_AddScore( RES_CAS+2, 1.0/16);
FaultSource_AddScore( MEMChip_0_CASH, 1.0/8);
}
}
}
// Error only if more than 6/16 bits are in error
if(count_bit32(ErrorMark_L1 & 0xFFFF0000) > 2)
{
NbErr++;/*
printf("2: %08x %d\n",
ErrorMark_L1 & 0xFFFF0000,
count_bit32(ErrorMark_L1 & 0xFFFF0000));*/
if((idxdraw == idx) && count_bit32(ErrorMark_L1 & 0xFFFF0000) > 6)
{
FaultSource_AddScore( TMUTexWE, 1.0/4);
FaultSource_AddScore( RES_WE, 1.0/4);
FaultSource_AddScore( MEMChip_1_WE, 1.0/1);
}
if(count_bit32(ErrorMarkBlank_L1 & 0xFFFF0000) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_AddScore( MEMChip_1_A0 + add_list[idx].nColBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_1_0 + add_list[idx].nColBit, 1.0/1);
if(add_list[idx].nColBit < 4)
FaultSource_AddScore( RES_TEXADDR_1_L + add_list[idx].nColBit + 1, 1.0/2);
else if(add_list[idx].nColBit < 8)
FaultSource_AddScore( RES_TEXADDR_1_H + add_list[idx].nColBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_1_8 + 1, 1.0/2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_AddScore( MEMChip_1_A0 + add_list[idx].nRowBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_1_0 + add_list[idx].nRowBit, 1.0/1);
if(add_list[idx].nRowBit < 4)
FaultSource_AddScore( RES_TEXADDR_1_L + add_list[idx].nRowBit + 1, 1.0/2);
else if(add_list[idx].nRowBit < 8)
FaultSource_AddScore( RES_TEXADDR_1_H + add_list[idx].nRowBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_1_8 + 1, 1.0/2);
}
}
else
{
FaultSource_AddScore( TMUTexRASCurrent, 1.0/8);
FaultSource_AddScore( RES_RAS, 1.0/8);
FaultSource_AddScore( MEMChip_1_RAS, 1.0/4);
if(ErrorMark_L1 & 0x00FF0000)
{
FaultSource_AddScore( TMUTexCAS0, 1.0/16);
FaultSource_AddScore( RES_CAS+1, 1.0/16);
FaultSource_AddScore( MEMChip_1_CASL, 1.0/8);
}
if(ErrorMark_L1 & 0xFF000000)
{
FaultSource_AddScore( TMUTexCAS1, 1.0/16);
FaultSource_AddScore( RES_CAS+2, 1.0/16);
FaultSource_AddScore( MEMChip_1_CASH, 1.0/8);
}
}
}
if(count_bit32(ErrorMark_L2 & 0x0000FFFF) > 2)
{
NbErr++;/*
printf("3: %08x %d\n",
ErrorMark_L2 & 0x0000FFFF,
count_bit32(ErrorMark_L2 & 0x0000FFFF));*/
if((idxdraw == idx) && count_bit32(ErrorMark_L2 & 0x0000FFFF) > 6)
{
FaultSource_AddScore( TMUTexWE, 1.0/4);
FaultSource_AddScore( RES_WE, 1.0/4);
FaultSource_AddScore( MEMChip_2_WE, 1.0);
}
if(count_bit32(ErrorMarkBlank_L2 & 0x0000FFFF) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_AddScore( MEMChip_2_A0 + add_list[idx].nColBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_2_0 + add_list[idx].nColBit, 1.0/1);
if(add_list[idx].nColBit < 4)
FaultSource_AddScore( RES_TEXADDR_2_L + add_list[idx].nColBit + 1, 1.0/2);
else if(add_list[idx].nColBit < 8)
FaultSource_AddScore( RES_TEXADDR_2_H + add_list[idx].nColBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_2_8 + 1, 1.0/2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_AddScore( MEMChip_2_A0 + add_list[idx].nRowBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_2_0 + add_list[idx].nRowBit, 1.0/1);
if(add_list[idx].nRowBit < 4)
FaultSource_AddScore( RES_TEXADDR_2_L + add_list[idx].nRowBit + 1, 1.0/2);
else if(add_list[idx].nRowBit < 8)
FaultSource_AddScore( RES_TEXADDR_2_H + add_list[idx].nRowBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_2_8 + 1, 1.0/2);
}
}
else
{
FaultSource_AddScore( TMUTexRASCurrent, 1.0/8);
FaultSource_AddScore( RES_RAS, 1.0/8);
FaultSource_AddScore( MEMChip_2_RAS, 1.0/4);
if(ErrorMark_L2 & 0x000000FF)
{
FaultSource_AddScore( TMUTexCAS2, 1.0/16);
FaultSource_AddScore( RES_CAS+3, 1.0/16);
FaultSource_AddScore( MEMChip_2_CASL, 1.0/8);
}
if(ErrorMark_L2 & 0x0000FF00)
{
FaultSource_AddScore( TMUTexCAS3, 1.0/16);
FaultSource_AddScore( RES_CAS+4, 1.0/16);
FaultSource_AddScore( MEMChip_2_CASH, 1.0/8);
}
}
}
if(count_bit32(ErrorMark_L2 & 0xFFFF0000) > 2)
{
NbErr++;/*
printf("4: %08x %d\n",
ErrorMark_L2 & 0xFFFF0000,
count_bit32(ErrorMark_L2 & 0xFFFF0000));*/
if((idxdraw == idx) && count_bit32(ErrorMark_L2 & 0xFFFF0000) > 6)
{
FaultSource_AddScore( TMUTexWE, 1.0/4);
FaultSource_AddScore( RES_WE, 1.0/4);
FaultSource_AddScore( MEMChip_3_WE, 1.0);
}
if(count_bit32(ErrorMarkBlank_L2 & 0xFFFF0000) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_AddScore( MEMChip_3_A0 + add_list[idx].nColBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_3_0 + add_list[idx].nColBit, 1.0/1);
if(add_list[idx].nColBit < 4)
FaultSource_AddScore( RES_TEXADDR_3_L + add_list[idx].nColBit + 1, 1.0/2);
else if(add_list[idx].nColBit < 8)
FaultSource_AddScore( RES_TEXADDR_3_H + add_list[idx].nColBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_3_8 + 1, 1.0/2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_AddScore( MEMChip_3_A0 + add_list[idx].nRowBit, 1.0/1);
FaultSource_AddScore( TMUTexADDR_3_0 + add_list[idx].nRowBit, 1.0/1);
if(add_list[idx].nRowBit < 4)
FaultSource_AddScore( RES_TEXADDR_3_L + add_list[idx].nRowBit + 1, 1.0/2);
else if(add_list[idx].nRowBit < 8)
FaultSource_AddScore( RES_TEXADDR_3_H + add_list[idx].nRowBit + 1, 1.0/2);
else
FaultSource_AddScore( RES_TEXADDR_3_8 + 1, 1.0/2);
}
}
else
{
FaultSource_AddScore( TMUTexRASCurrent, 1.0/8);
FaultSource_AddScore( RES_RAS, 1.0/8);
FaultSource_AddScore( MEMChip_3_RAS, 1.0/4);
if(ErrorMark_L2 & 0x00FF0000)
{
FaultSource_AddScore( TMUTexCAS2, 1.0/16);
FaultSource_AddScore( RES_CAS+3, 1.0/16);
FaultSource_AddScore( MEMChip_3_CASL, 1.0/8);
}
if(ErrorMark_L2 & 0xFF000000)
{
FaultSource_AddScore( TMUTexCAS3, 1.0/16);
FaultSource_AddScore( RES_CAS+4, 1.0/16);
FaultSource_AddScore( MEMChip_3_CASH, 1.0/8);
}
}
}
/*
if(idxdraw == idx)
{
if(ErrorMark_L1)
{
printf("E (31..00): @%08x, read %08x, expected %08x !\n" ,
add_list[idxdraw].u32Addr,
L1 ,
TestVal1);
}
if(ErrorMark_L2)
{
printf("E (63..32): @%08x, read %08x, expected %08x !\n" ,
add_list[idxdraw].u32Addr,
L2 ,
TestVal2);
}
}
else
{
if(ErrorMark_L1)
{
printf("E (31..00)(trash) : @%08x, read %08x, expected %08x !\n" ,
add_list[idxdraw].u32Addr,
L1 ,
TestValBlank1);
}
if(ErrorMark_L2)
{
printf("E (63..32)(trash) : @%08x, read %08x, expected %08x !\n" ,
add_list[idxdraw].u32Addr,
L2 ,
TestValBlank2);
}
}
if(!ErrorMark_L1 && !ErrorMark_L2)
{
printf("OK !!\n");
}
*/ */
//printf("@ %08x done\n",add_list[idx]); /* Considering error only if more than 3 over 16 bits
* are wrong, because we are only testing addresses
* lines here */
if(count_bit32(ErrorMark_L1 & 0x0000FFFF) > 3)
{
NbErr++;
/* If it matches the Other value with less than
* 3 error bits */
if(count_bit32(ErrorMarkOther_L1 & 0x0000FFFF) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_A0 + add_list[idx].nColBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_A0_Other + add_list[idx].nColBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_0_0 + add_list[idx].nColBit - 1, 1.0 / 2);
if(add_list[idx].nColBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_L + add_list[idx].nColBit - 2, 1.0 / 2);
else if(add_list[idx].nColBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_H + add_list[idx].nColBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_8, 1.0 / 2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_A0 + add_list[idx].nRowBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_A0_Other + add_list[idx].nRowBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_0_0 + add_list[idx].nRowBit - 1, 1.0 / 2);
if(add_list[idx].nRowBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_L + add_list[idx].nRowBit - 2, 1.0 / 2);
else if(add_list[idx].nRowBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_H + add_list[idx].nRowBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_0_8, 1.0 / 2);
}
}
}
if(count_bit32(ErrorMark_L1 & 0xFFFF0000) > 3)
{
NbErr++;
if(count_bit32(ErrorMarkOther_L1 & 0xFFFF0000) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_A0 + add_list[idx].nColBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_A0_Other + add_list[idx].nColBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_1_0 + add_list[idx].nColBit - 1, 1.0 / 2);
if(add_list[idx].nColBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_L + add_list[idx].nColBit - 2, 1.0 / 2);
else if(add_list[idx].nColBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_H + add_list[idx].nColBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_8, 1.0 / 2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_A0 + add_list[idx].nRowBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_A0_Other + add_list[idx].nRowBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_1_0 + add_list[idx].nRowBit - 1, 1.0 / 2);
if(add_list[idx].nRowBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_L + add_list[idx].nRowBit - 2, 1.0 / 2);
else if(add_list[idx].nRowBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_H + add_list[idx].nRowBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_1_8, 1.0 / 2);
}
}
}
if(count_bit32(ErrorMark_L2 & 0x0000FFFF) > 3)
{
NbErr++;
if(count_bit32(ErrorMarkOther_L2 & 0x0000FFFF) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_A0 + add_list[idx].nColBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_A0_Other + add_list[idx].nColBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_2_0 + add_list[idx].nColBit - 1, 1.0 / 2);
if(add_list[idx].nColBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_L + add_list[idx].nColBit - 2, 1.0 / 2);
else if(add_list[idx].nColBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_H + add_list[idx].nColBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_8, 1.0 / 2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_A0 + add_list[idx].nRowBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_A0_Other + add_list[idx].nRowBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_2_0 + add_list[idx].nRowBit - 1, 1.0 / 2);
if(add_list[idx].nRowBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_L + add_list[idx].nRowBit - 2, 1.0 / 2);
else if(add_list[idx].nRowBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_H + add_list[idx].nRowBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_2_8, 1.0 / 2);
}
}
}
if(count_bit32(ErrorMark_L2 & 0xFFFF0000) > 3)
{
NbErr++;
if(count_bit32(ErrorMarkOther_L2 & 0xFFFF0000) < 3)
{
if(add_list[idx].nColBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_A0 + add_list[idx].nColBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_A0_Other + add_list[idx].nColBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_3_0 + add_list[idx].nColBit - 1, 1.0 / 2);
if(add_list[idx].nColBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_L + add_list[idx].nColBit - 2, 1.0 / 2);
else if(add_list[idx].nColBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_H + add_list[idx].nColBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_8, 1.0 / 2);
}
if(add_list[idx].nRowBit!=0)
{
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_A0 + add_list[idx].nRowBit - 1, 1.0 / 1);
if(RamSizeMB>=2)
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_A0_Other + add_list[idx].nRowBit - 1, 1.0 / 2);
FaultSource_addScore(pFaultSrcCtx, TMUTexADDR_3_0 + add_list[idx].nRowBit - 1, 1.0 / 2);
if(add_list[idx].nRowBit < 4)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_L + add_list[idx].nRowBit - 2, 1.0 / 2);
else if(add_list[idx].nRowBit < 8)
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_H + add_list[idx].nRowBit - 6, 1.0 / 2);
else
FaultSource_addScore(pFaultSrcCtx, RES_TEXADDR_3_8, 1.0 / 2);
}
}
}
} }
} }
} }
clearScreen(sstregs,0x00000000,2,2);
sst1InitIdle(sst); sst1InitIdle(sst);
devInfo->tmuInit0[(int)ucNumTMU] = _trexInit0;
ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]); ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);
return NbErr; return NbErr;
} }

View File

@@ -19,10 +19,11 @@
#define _DEF_TEST_ADDRESS_H_ #define _DEF_TEST_ADDRESS_H_
unsigned long unsigned long
RenderTestAddress( sst1DeviceInfoStruct* devInfo, RenderTestAddress( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const char ucNumTMU, const char ucNumTMU,
const unsigned char RamSizeMB); const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx);
#endif //_DEF_TEST_ADDRESS_H_ #endif //_DEF_TEST_ADDRESS_H_

84
Test_Common.c Normal file
View File

@@ -0,0 +1,84 @@
/* 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 "Draw.h"
#include "Test_Common.h"
#define _DEF_PREHEAT_TIME_S 5
#define _DEF_PREHEAT_NB_PIXEL_ROW 256
#define _DEF_PREHEAT_NB_PIXEL_COL 256
void
HeatMemAndTMU( sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const char ucNumTMU,
const FxU32 mem)
{
/* set downstream TMUs to passthrough */
for (int i=0; i<ucNumTMU; i++)
ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS);
/* Setting texture base address window
*/
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);
for(unsigned short iter_row = 0; iter_row < _DEF_PREHEAT_NB_PIXEL_ROW; iter_row++)
{
for(unsigned short iter_col = 0; iter_col < _DEF_PREHEAT_NB_PIXEL_COL; iter_col+=2)
{
ISET(texRowAddr[iter_col/2], 0x55AA);
}
/* move to next line */
texRowAddr += (1<<(9-2));
}
clock_t begin = clock();
do
{
if(((sst1InitReturnStatus(sst) & SST_FIFOLEVEL)) >= 0x20)
{
/* draw a 256x256 square */
drawSquare(sstregs, ucNumTMU, 0, 0, 256);
}
}
while(((double)(clock() - begin)/CLOCKS_PER_SEC) < _DEF_PREHEAT_TIME_S );
sst1InitIdle(sst);
}

29
Test_Common.h Normal file
View File

@@ -0,0 +1,29 @@
/* 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/>.
*/
#ifndef _DEF_TEST_COMMON_H_
#define _DEF_TEST_COMMON_H_
void
HeatMemAndTMU( sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const char ucNumTMU,
const FxU32 mem);
#endif //_DEF_TEST_COMMON_H_

457
Test_Control.c Normal file
View File

@@ -0,0 +1,457 @@
/* 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/>.
*/
#include <stdint.h>
#include <stdio.h>
#include "cvg.h"
#include <glide.h>
#include "sst1init.h"
#include "fxpci.h"
#include "Utils.h"
#include "V2MemTest.h"
#include "FaultSources.h"
#include "Utils.h"
#include "Draw.h"
#include "Test_Control.h"
static void
WriteTex( FxU32 * const sst,
SstRegs * const sstregs,
const uint32_t baseAddr,
const char ucNumTMU,
const uint32_t Val1,
const uint32_t Val2)
{
/* set base mem @ */
ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (baseAddr>>3));
/* set @ to first line, using bits 00..31*/
volatile const FxU32 *texAddrBlank
= (ucNumTMU<<(21-2))
+ (((FxU32)0)<<(17-2)) /*LOD0*/
+ (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddrBlank[0], Val1);
/* set @ to second line, to use bits 32..63*/
volatile const FxU32 *texAddrBlank2
= (ucNumTMU<<(21-2))
+ (((FxU32)0)<<(17-2)) /*LOD0*/
+ (1<<(9-2))
+ (FxU32 *)SST_TEX_ADDRESS(sst);
/* write the value */
ISET(texAddrBlank2[0], Val2);
}
unsigned long
CheckRead( FxU32 * const sst,
SstRegs * const sstregs,
const uint32_t baseAddr,
const char ucNumTMU,
const unsigned char bNominal,
const uint32_t Val1,
const uint32_t Val2,
const uint32_t ValOther1,
const uint32_t ValOther2,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{
unsigned long NbErr=0;
const unsigned char nBank = (baseAddr<0x200000) ? 0 : 1;
const def_eFaultSource TMUTexWE = (ucNumTMU == 0) ? U9_TMU0_TEX_WE : U8_TMU1_TEX_WE;
const def_eFaultSource TMUTexCAS0 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS0 : U8_TMU1_TEX_CAS0;
const def_eFaultSource TMUTexCAS1 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS1 : U8_TMU1_TEX_CAS1;
const def_eFaultSource TMUTexCAS2 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS2 : U8_TMU1_TEX_CAS2;
const def_eFaultSource TMUTexCAS3 = (ucNumTMU == 0) ? U9_TMU0_TEX_CAS3 : U8_TMU1_TEX_CAS3;
const def_eFaultSource _TMUTexRAS0 = (ucNumTMU == 0) ? U9_TMU0_TEX_RAS0 : U8_TMU1_TEX_RAS0;
const def_eFaultSource _TMUTexRAS1 = (ucNumTMU == 0) ? U9_TMU0_TEX_RAS1 : U8_TMU1_TEX_RAS1;
const def_eFaultSource TMUTexRASCurrent = (nBank == 0) ? _TMUTexRAS0 : _TMUTexRAS1;
const def_eFaultSource _MEMChip_B0_0_CASL = (ucNumTMU == 0) ? U14_CASL : U13_CASL;
const def_eFaultSource _MEMChip_B0_1_CASL = (ucNumTMU == 0) ? U12_CASL : U11_CASL;
const def_eFaultSource _MEMChip_B0_2_CASL = (ucNumTMU == 0) ? U18_CASL : U16_CASL;
const def_eFaultSource _MEMChip_B0_3_CASL = (ucNumTMU == 0) ? U17_CASL : U15_CASL;
const def_eFaultSource _MEMChip_B1_0_CASL = (ucNumTMU == 0) ? U23_CASL : U27_CASL;
const def_eFaultSource _MEMChip_B1_1_CASL = (ucNumTMU == 0) ? U24_CASL : U28_CASL;
const def_eFaultSource _MEMChip_B1_2_CASL = (ucNumTMU == 0) ? U25_CASL : U29_CASL;
const def_eFaultSource _MEMChip_B1_3_CASL = (ucNumTMU == 0) ? U26_CASL : U30_CASL;
const def_eFaultSource MEMChip_0_CASL = (nBank == 0) ? _MEMChip_B0_0_CASL : _MEMChip_B1_0_CASL;
const def_eFaultSource MEMChip_1_CASL = (nBank == 0) ? _MEMChip_B0_1_CASL : _MEMChip_B1_1_CASL;
const def_eFaultSource MEMChip_2_CASL = (nBank == 0) ? _MEMChip_B0_2_CASL : _MEMChip_B1_2_CASL;
const def_eFaultSource MEMChip_3_CASL = (nBank == 0) ? _MEMChip_B0_3_CASL : _MEMChip_B1_3_CASL;
const def_eFaultSource _MEMChip_B0_0_CASH = (ucNumTMU == 0) ? U14_CASH : U13_CASH;
const def_eFaultSource _MEMChip_B0_1_CASH = (ucNumTMU == 0) ? U12_CASH : U11_CASH;
const def_eFaultSource _MEMChip_B0_2_CASH = (ucNumTMU == 0) ? U18_CASH : U16_CASH;
const def_eFaultSource _MEMChip_B0_3_CASH = (ucNumTMU == 0) ? U17_CASH : U15_CASH;
const def_eFaultSource _MEMChip_B1_0_CASH = (ucNumTMU == 0) ? U23_CASH : U27_CASH;
const def_eFaultSource _MEMChip_B1_1_CASH = (ucNumTMU == 0) ? U24_CASH : U28_CASH;
const def_eFaultSource _MEMChip_B1_2_CASH = (ucNumTMU == 0) ? U25_CASH : U29_CASH;
const def_eFaultSource _MEMChip_B1_3_CASH = (ucNumTMU == 0) ? U26_CASH : U30_CASH;
const def_eFaultSource MEMChip_0_CASH = (nBank == 0) ? _MEMChip_B0_0_CASH : _MEMChip_B1_0_CASH;
const def_eFaultSource MEMChip_1_CASH = (nBank == 0) ? _MEMChip_B0_1_CASH : _MEMChip_B1_1_CASH;
const def_eFaultSource MEMChip_2_CASH = (nBank == 0) ? _MEMChip_B0_2_CASH : _MEMChip_B1_2_CASH;
const def_eFaultSource MEMChip_3_CASH = (nBank == 0) ? _MEMChip_B0_3_CASH : _MEMChip_B1_3_CASH;
const def_eFaultSource _MEMChip_B0_0_RAS = (ucNumTMU == 0) ? U14_RAS : U13_RAS;
const def_eFaultSource _MEMChip_B0_1_RAS = (ucNumTMU == 0) ? U12_RAS : U11_RAS;
const def_eFaultSource _MEMChip_B0_2_RAS = (ucNumTMU == 0) ? U18_RAS : U16_RAS;
const def_eFaultSource _MEMChip_B0_3_RAS = (ucNumTMU == 0) ? U17_RAS : U15_RAS;
const def_eFaultSource _MEMChip_B1_0_RAS = (ucNumTMU == 0) ? U23_RAS : U27_RAS;
const def_eFaultSource _MEMChip_B1_1_RAS = (ucNumTMU == 0) ? U24_RAS : U28_RAS;
const def_eFaultSource _MEMChip_B1_2_RAS = (ucNumTMU == 0) ? U25_RAS : U29_RAS;
const def_eFaultSource _MEMChip_B1_3_RAS = (ucNumTMU == 0) ? U26_RAS : U30_RAS;
const def_eFaultSource MEMChip_0_RAS = (nBank == 0) ? _MEMChip_B0_0_RAS : _MEMChip_B1_0_RAS;
const def_eFaultSource MEMChip_1_RAS = (nBank == 0) ? _MEMChip_B0_1_RAS : _MEMChip_B1_1_RAS;
const def_eFaultSource MEMChip_2_RAS = (nBank == 0) ? _MEMChip_B0_2_RAS : _MEMChip_B1_2_RAS;
const def_eFaultSource MEMChip_3_RAS = (nBank == 0) ? _MEMChip_B0_3_RAS : _MEMChip_B1_3_RAS;
const def_eFaultSource _MEMChip_B0_0_WE = (ucNumTMU == 0) ? U14_WE : U13_WE;
const def_eFaultSource _MEMChip_B0_1_WE = (ucNumTMU == 0) ? U12_WE : U11_WE;
const def_eFaultSource _MEMChip_B0_2_WE = (ucNumTMU == 0) ? U18_WE : U16_WE;
const def_eFaultSource _MEMChip_B0_3_WE = (ucNumTMU == 0) ? U17_WE : U15_WE;
const def_eFaultSource _MEMChip_B1_0_WE = (ucNumTMU == 0) ? U23_WE : U27_WE;
const def_eFaultSource _MEMChip_B1_1_WE = (ucNumTMU == 0) ? U24_WE : U28_WE;
const def_eFaultSource _MEMChip_B1_2_WE = (ucNumTMU == 0) ? U25_WE : U29_WE;
const def_eFaultSource _MEMChip_B1_3_WE = (ucNumTMU == 0) ? U26_WE : U30_WE;
const def_eFaultSource MEMChip_0_WE = (nBank == 0) ? _MEMChip_B0_0_WE : _MEMChip_B1_0_WE;
const def_eFaultSource MEMChip_1_WE = (nBank == 0) ? _MEMChip_B0_1_WE : _MEMChip_B1_1_WE;
const def_eFaultSource MEMChip_2_WE = (nBank == 0) ? _MEMChip_B0_2_WE : _MEMChip_B1_2_WE;
const def_eFaultSource MEMChip_3_WE = (nBank == 0) ? _MEMChip_B0_3_WE : _MEMChip_B1_3_WE;
const def_eFaultSource _RES_RAS0 = (ucNumTMU == 0) ? R118 : R115;
const def_eFaultSource _RES_RAS1 = (ucNumTMU == 0) ? R149 : R150;
const def_eFaultSource RES_RAS = (nBank == 0) ? _RES_RAS0 : _RES_RAS1;
const def_eFaultSource RES_CAS = (ucNumTMU == 0) ? RA36 : RA32;
const def_eFaultSource RES_WE = (ucNumTMU == 0) ? R117 : R114;
clearScreen(sstregs,0x00000000,2,2);
/* set to mem addr */
ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (baseAddr >> 3));
/* draw a 2x2 square */
drawSquare(sstregs, ucNumTMU, 0, 0, 2);
sst1InitIdle(sst);
/* first line, to use bits 00..31 */
const uint32_t L1 = IGET(sst[(SST_LFB_ADDR>>2) + 0]);
/* second line, to use bits 32..63 */
const uint32_t L2 = IGET(sst[(SST_LFB_ADDR>>2) + (2048>>2) + 0]);
const uint32_t ErrorMark_L1 = (L1 ^ Val1);
const uint32_t ErrorMark_L2 = (L2 ^ Val2);
const uint32_t ErrorMark_L1_Other = (L1 ^ ValOther1);
const uint32_t ErrorMark_L2_Other = (L2 ^ ValOther2);
if(count_bit32(ErrorMark_L1 & 0x0000FFFF) > 4)
{
NbErr++;
/* If we are reading the value of the other Bank
* then it has to be a bank select problem*/
if(!bNominal && count_bit32(ErrorMark_L1_Other & 0x0000FFFF) < 4)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_RAS, 2.0);
}
else
{
/* WE can fail only in case of plain failure */
if(count_bit32(ErrorMark_L1 & 0x0000FFFF) > 8)
{
/*WE are shared accross all memory chips so
* we divide the weight by 4.*/
FaultSource_addScore(pFaultSrcCtx, TMUTexWE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, RES_WE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_WE, 1.0);
}
unsigned char bLSBFailed = false;
unsigned char bMSBFailed = false;
if(count_bit32(ErrorMark_L1 & 0x000000FF) > 2)
{
/*CAS are shared accross multiple memory chips so
* we divide the weight by 2.*/
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS0, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_CAS+1, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_CASL, 1.0);
bLSBFailed = true;
}
if(count_bit32(ErrorMark_L1 & 0x0000FF00) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS1, 1.0/2);;
FaultSource_addScore(pFaultSrcCtx, RES_CAS+2, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_CASH, 1.0);
bMSBFailed = true;
}
/* RAS is declared failed only if both CAS failed */
if(bLSBFailed && bMSBFailed)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0);
FaultSource_addScore(pFaultSrcCtx, MEMChip_0_RAS, 4.0);
}
}
}
if(count_bit32(ErrorMark_L1 & 0xFFFF0000) > 4)
{
NbErr++;
if(!bNominal && count_bit32(ErrorMark_L1_Other & 0xFFFF0000) < 4)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_RAS, 2.0);
}
else
{
if(count_bit32(ErrorMark_L1 & 0xFFFF0000) > 8)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexWE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, RES_WE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_WE, 1.0);
}
unsigned char bLSBFailed = false;
unsigned char bMSBFailed = false;
if(count_bit32(ErrorMark_L1 & 0x00FF0000) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS0, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_CAS+1, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_CASL, 1.0);
bLSBFailed = true;
}
if(count_bit32(ErrorMark_L1 & 0xFF000000) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS1, 1.0/2);;
FaultSource_addScore(pFaultSrcCtx, RES_CAS+2, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_CASH, 1.0);
bMSBFailed = true;
}
if(bLSBFailed && bMSBFailed)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0);
FaultSource_addScore(pFaultSrcCtx, MEMChip_1_RAS, 4.0);
}
}
}
if(count_bit32(ErrorMark_L2 & 0x0000FFFF) > 4)
{
NbErr++;
if(!bNominal && count_bit32(ErrorMark_L2_Other & 0x0000FFFF) < 4)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_RAS, 2.0);
}
else
{
if(count_bit32(ErrorMark_L2 & 0x0000FFFF) > 8)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexWE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, RES_WE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_WE, 1.0);
}
unsigned char bLSBFailed = false;
unsigned char bMSBFailed = false;
if(count_bit32(ErrorMark_L2 & 0x000000FF) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS2, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_CAS+3, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_CASL, 1.0);
bLSBFailed = true;
}
if(count_bit32(ErrorMark_L2 & 0x0000FF00) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS3, 1.0/2);;
FaultSource_addScore(pFaultSrcCtx, RES_CAS+4, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_CASH, 1.0);
bMSBFailed = true;
}
if(bLSBFailed && bMSBFailed)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0);
FaultSource_addScore(pFaultSrcCtx, MEMChip_2_RAS, 4.0);
}
}
}
if(count_bit32(ErrorMark_L2 & 0xFFFF0000) > 4)
{
NbErr++;
if(!bNominal && count_bit32(ErrorMark_L2_Other & 0xFFFF0000) < 4)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_RAS, 2.0);
}
else
{
if(count_bit32(ErrorMark_L2 & 0xFFFF0000) > 8)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexWE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, RES_WE, 1.0/4);
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_WE, 1.0);
}
unsigned char bLSBFailed = false;
unsigned char bMSBFailed = false;
if(count_bit32(ErrorMark_L2 & 0x00FF0000) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS2, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, RES_CAS+3, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_CASL, 1.0);
bLSBFailed = true;
}
if(count_bit32(ErrorMark_L2 & 0xFF000000) > 2)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexCAS3, 1.0/2);;
FaultSource_addScore(pFaultSrcCtx, RES_CAS+4, 1.0/2);
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_CASH, 1.0);
bMSBFailed = true;
}
if(bLSBFailed && bMSBFailed)
{
FaultSource_addScore(pFaultSrcCtx, TMUTexRASCurrent, 1.0);
FaultSource_addScore(pFaultSrcCtx, RES_RAS, 1.0);
FaultSource_addScore(pFaultSrcCtx, MEMChip_3_RAS, 4.0);
}
}
}
return NbErr;
}
unsigned long
TestControl( sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const char ucNumTMU,
const unsigned char RamSizeMB,
def_sFaultSourceScoreRec * const pFaultSrcCtx)
{
unsigned long NbErr=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);
const uint32_t TestVal1 = get_notnull_random_balanced_mByte();
logT("TestVal1 = %08X\n",TestVal1);
uint32_t TestVal2 = 0;
do
{
TestVal2 = get_notnull_random_balanced_mByte();
}
while((count_bit32((TestVal2 ^ TestVal1)) < 12));
logT("TestVal2 = %08X\n",TestVal2);
uint32_t TestValBlank1 = 0;
do
{
TestValBlank1 = get_notnull_random_balanced_mByte();
}
while( (count_bit32((TestValBlank1 ^ TestVal1) & 0x0000FFFF) < 6)
|| (count_bit32((TestValBlank1 ^ TestVal1) & 0xFFFF0000) < 6)
|| (count_bit32((TestValBlank1 ^ TestVal2)) < 12));
logT("TestValBlank1 = %08X\n", TestValBlank1);
uint32_t TestValBlank2 = 0;
do
{
TestValBlank2 = get_notnull_random_balanced_mByte();
}
while( (count_bit32((TestValBlank2 ^ TestVal2) & 0x0000FFFF) < 6)
|| (count_bit32((TestValBlank2 ^ TestVal2) & 0xFFFF0000) < 6)
|| (count_bit32((TestValBlank2 ^ TestValBlank1)) < 12)
|| (count_bit32((TestValBlank2 ^ TestVal1)) < 12));
logT("TestValBlank2 = %08X\n", TestValBlank2);
/* write initial Values */
/* Bank 0*/
WriteTex(sst, sstregs, 0x000000, ucNumTMU, TestValBlank1, TestValBlank2);
/* Bank 1*/
if(RamSizeMB>2)
{
WriteTex(sst, sstregs, 0x200000, ucNumTMU, TestValBlank1, TestValBlank2);
}
/* write to Bank 0 */
WriteTex(sst, sstregs, 0x000000, ucNumTMU, TestVal1, TestVal2);
/* read and check Bank 0 (nominal check)*/
NbErr += CheckRead(sst, sstregs, 0x000000, ucNumTMU,
true, TestVal1, TestVal2, TestValBlank1, TestValBlank2, pFaultSrcCtx);
/* if Bank 1 available*/
if(RamSizeMB>2)
{
/* read and check Bank 1(no modification check)*/
NbErr += CheckRead(sst, sstregs, 0x200000, ucNumTMU,
false, TestValBlank1, TestValBlank2, TestVal1, TestVal2, pFaultSrcCtx);
/* write initial Values */
/* Bank 0*/
WriteTex(sst, sstregs, 0x000000, ucNumTMU, TestValBlank1, TestValBlank2);
/* Bank 1*/
if(RamSizeMB>2)
{
WriteTex(sst, sstregs, 0x200000, ucNumTMU, TestValBlank1, TestValBlank2);
}
/* write to Bank 1 */
WriteTex(sst, sstregs, 0x200000, ucNumTMU, TestVal1, TestVal2);
/* read and check Bank 1 (nominal check)*/
NbErr += CheckRead(sst, sstregs, 0x200000, ucNumTMU,
true, TestVal1, TestVal2, TestValBlank1, TestValBlank2, pFaultSrcCtx);
/* read and check Bank 0 (no modification check)*/
NbErr += CheckRead(sst, sstregs, 0x000000, ucNumTMU,
false, TestValBlank1, TestValBlank2, TestVal1, TestVal2, pFaultSrcCtx);
}
clearScreen(sstregs,0x00000000,2,2);
sst1InitIdle(sst);
devInfo->tmuInit0[(int)ucNumTMU] = _trexInit0;
ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst);
return NbErr;
}

29
Test_Control.h Normal file
View File

@@ -0,0 +1,29 @@
/* 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/>.
*/
#ifndef _DEF_TEST_CONTROL_H_
#define _DEF_TEST_CONTROL_H_
unsigned long
TestControl(sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const char ucNumTMU,
const unsigned char RamSizeMB,
def_sFaultSourceScoreRec * const pFaultSrcCtx);
#endif //_DEF_TEST_CONTROL_H_

View File

@@ -15,6 +15,12 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#define _BSD_SOURCE 1
#include <stdint.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include "cvg.h" #include "cvg.h"
#include <glide.h> #include <glide.h>
#include "sst1init.h" #include "sst1init.h"
@@ -24,426 +30,150 @@
#include "Utils.h" #include "Utils.h"
#include "Draw.h" #include "Draw.h"
#include "Test_Common.h"
#include "Test_Data.h" #include "Test_Data.h"
static unsigned long long static unsigned long long
RenderTest( sst1DeviceInfoStruct* devInfo, RenderTest( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const char ucNumTMU, const char ucNumTMU,
const FxU32 mem, const FxU32 mem,
const FxU32 value1, const FxU32 value1,
const FxU32 value2) const FxU32 value2,
const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{ {
unsigned long long NbErr = 0;
static char szBuff[1024];
sst1InitIdle(sst); sst1InitIdle(sst);
unsigned long _trexInit0 = IGET(SST_TREX(sstregs,ucNumTMU)->trexInit0);
devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ; devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ;
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]); ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);
ISET(sstregs->texBaseAddr, mem>>3); ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, mem>>3);
/* Writing to first texture line, to use RAM bits 0..31 */ /* Writing to first texture line, to use RAM bits 0..31 */
volatile FxU32 *texAddr = (ucNumTMU<<(21-2)) /* NUM_TMU */ volatile FxU32 *texAddr
+ (((FxU32)0)<<(17-2)) /* LOD_0 */ = (ucNumTMU<<(21-2)) /* NUM_TMU */
+ (FxU32 *)SST_TEX_ADDRESS(sst); /* tex base address */ + (((FxU32)0)<<(17-2)) /* LOD_0 */
ISET(texAddr[0], value1); ISET(texAddr[1], value1 + 1); + (FxU32 *)SST_TEX_ADDRESS(sst); /* tex base address */
ISET(texAddr[2], value1 + 2); ISET(texAddr[3], value1 + 3);
ISET(texAddr[0], value1);
/* writing to second texture line, to use RAM bits 32..63 */ /* writing to second texture line, to use RAM bits 32..63 */
texAddr += (1<<(9-2)); texAddr += (1<<(9-2));
ISET(texAddr[0], value2); ISET(texAddr[1], value2 + 1); ISET(texAddr[0], value2);
ISET(texAddr[2], value2 + 2); ISET(texAddr[3], value2 + 3);
/* draw a 8x8triangle */ clearScreen(sstregs,0x00000000,8,2);
drawTriangle(sstregs,0,0,8);
/* draw a 2x2 rectangle */
drawRect(sstregs, ucNumTMU, 0, 0, 2, 2);
sst1InitIdle(sst);
const double dScoreFront = (mem >= 0x200000) ? 1.0 / 2 : 1.0 / 1;
const double dScoreBack = (mem >= 0x200000) ? 1.0 / 1 : 1.0 / 2;
/* reading back first line pixels addresses */ /* reading back first line pixels addresses */
const FxU32 L1_1 = IGET(sst[(SST_LFB_ADDR >> 2) + 0]); const uint32_t L1_1 = IGET(sst[(SST_LFB_ADDR >> 2) + 0]);
const FxU32 L1_2 = IGET(sst[(SST_LFB_ADDR >> 2) + 1]); const uint32_t ErrorMark_L1 = L1_1 ^ ( value1 + 0 );
const FxU32 L1_3 = IGET(sst[(SST_LFB_ADDR >> 2) + 2]); if(ErrorMark_L1)
const FxU32 L1_4 = IGET(sst[(SST_LFB_ADDR >> 2) + 3]);
/* reading back second line pixels addresses */
const FxU32 L2_1 = IGET(sst[(SST_LFB_ADDR >> 2) + (2048 >> 2) + 0]);
const FxU32 L2_2 = IGET(sst[(SST_LFB_ADDR >> 2) + (2048 >> 2) + 1]);
const FxU32 L2_3 = IGET(sst[(SST_LFB_ADDR >> 2) + (2048 >> 2) + 2]);
const FxU32 L2_4 = IGET(sst[(SST_LFB_ADDR >> 2) + (2048 >> 2) + 3]);
unsigned long long NbErr = 0;
const unsigned long ErrorMark_L1_1 = L1_1 ^ ( value1 + 0 );
const unsigned long ErrorMark_L1_2 = L1_2 ^ ( value1 + 1 );
const unsigned long ErrorMark_L1_3 = L1_3 ^ ( value1 + 2 );
const unsigned long ErrorMark_L1_4 = L1_4 ^ ( value1 + 3 );
const unsigned long ErrorMark_L2_1 = L2_1 ^ ( value2 + 0 );
const unsigned long ErrorMark_L2_2 = L2_2 ^ ( value2 + 1 );
const unsigned long ErrorMark_L2_3 = L2_3 ^ ( value2 + 2 );
const unsigned long ErrorMark_L2_4 = L2_4 ^ ( value2 + 3 );
if( ErrorMark_L1_1 || ErrorMark_L1_2 || ErrorMark_L1_3 || ErrorMark_L1_4
|| ErrorMark_L2_1 || ErrorMark_L2_2 || ErrorMark_L2_3 || ErrorMark_L2_4)
{ {
NbErr++; NbErr++;
logD("===========================================================\n");
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); logD( "# fault on 1st line, value : 0x%04X [expected 0x%04X] !\n",
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); value1, L1_1);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U9_TMU0_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U3_FBI_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); RGBToBus_Fault_Quartets(pFaultSrcCtx, ErrorMark_L1, 1.0/2,
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0); RA10_1, RA11_1, RA12_1, RA13_1);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, U9_TMU0_TF_DATA_0, U9_TMU0_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, TT_TDATA_R131, TT_TDATA_R131);
QuartetBitFaultSet(ErrorMark_L1_1 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_1 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_2 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_3 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L1_4 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_1 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_2 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_3 >> 28, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 0, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 4, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 8, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 12, 1.0 / 16, RA13_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 16, 1.0 / 16, RA10_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 20, 1.0 / 16, RA11_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 24, 1.0 / 16, RA12_1);
QuartetBitFaultSet(ErrorMark_L2_4 >> 28, 1.0 / 16, RA13_1);
const double dScoreFront = (mem >= 0x200000) ? 1.0 / 8 : 1.0 / 4;
const double dScoreBack = (mem >= 0x200000) ? 1.0 / 4 : 1.0 / 8;
if(ucNumTMU == 0) if(ucNumTMU == 0)
{ {
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/ 2, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L1, dScoreFront, U14, U12);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); if(RamSizeMB>2)
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L1, dScoreBack, U23, U24);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); LWordBitFaultSet(pFaultSrcCtx,ErrorMark_L1, 1.0 / 1, U9_TMU0 + 1, U9_TMU0 + 16 + 1);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
MemChipDQFaultSet(ErrorMark_L1_1, dScoreFront, U14, U12);
MemChipDQFaultSet(ErrorMark_L1_2, dScoreFront, U14, U12);
MemChipDQFaultSet(ErrorMark_L1_3, dScoreFront, U14, U12);
MemChipDQFaultSet(ErrorMark_L1_4, dScoreFront, U14, U12);
MemChipDQFaultSet(ErrorMark_L2_1, dScoreFront, U18, U17);
MemChipDQFaultSet(ErrorMark_L2_2, dScoreFront, U18, U17);
MemChipDQFaultSet(ErrorMark_L2_3, dScoreFront, U18, U17);
MemChipDQFaultSet(ErrorMark_L2_4, dScoreFront, U18, U17);
MemChipDQFaultSet(ErrorMark_L1_1, dScoreBack, U23, U24);
MemChipDQFaultSet(ErrorMark_L1_2, dScoreBack, U23, U24);
MemChipDQFaultSet(ErrorMark_L1_3, dScoreBack, U23, U24);
MemChipDQFaultSet(ErrorMark_L1_4, dScoreBack, U23, U12);
MemChipDQFaultSet(ErrorMark_L2_1, dScoreBack, U25, U26);
MemChipDQFaultSet(ErrorMark_L2_2, dScoreBack, U25, U26);
MemChipDQFaultSet(ErrorMark_L2_3, dScoreBack, U25, U26);
MemChipDQFaultSet(ErrorMark_L2_4, dScoreBack, U25, U26);
TMUTexDataFaultSet(ErrorMark_L1_1, ErrorMark_L2_1, 1.0 / 4, U9_TMU0);
TMUTexDataFaultSet(ErrorMark_L1_2, ErrorMark_L2_2, 1.0 / 4, U9_TMU0);
TMUTexDataFaultSet(ErrorMark_L1_3, ErrorMark_L2_3, 1.0 / 4, U9_TMU0);
TMUTexDataFaultSet(ErrorMark_L1_4, ErrorMark_L2_4, 1.0 / 4, U9_TMU0);
TMUTexDataCtrlFaultSet( ErrorMark_L1_1,
1.0 / 8,
U9_TMU0_TEX_CAS0,
U9_TMU0_TEX_CAS1,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_2,
1.0 / 8,
U9_TMU0_TEX_CAS0,
U9_TMU0_TEX_CAS1,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_3,
1.0 / 8,
U9_TMU0_TEX_CAS0,
U9_TMU0_TEX_CAS1,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_4,
1.0 / 8,
U9_TMU0_TEX_CAS0,
U9_TMU0_TEX_CAS1,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_1,
1.0 / 8,
U9_TMU0_TEX_CAS2,
U9_TMU0_TEX_CAS3,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_2,
1.0 / 8,
U9_TMU0_TEX_CAS2,
U9_TMU0_TEX_CAS3,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_3,
1.0 / 8,
U9_TMU0_TEX_CAS2,
U9_TMU0_TEX_CAS3,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_4,
1.0 / 8,
U9_TMU0_TEX_CAS2,
U9_TMU0_TEX_CAS3,
mem < 0x200000 ? U9_TMU0_TEX_RAS0 : U9_TMU0_TEX_RAS1,
U9_TMU0_TEX_WE);
} }
else if(ucNumTMU == 1) else
{ {
/* during TMU1 test, TMU0 doesnt receive any textures => ignoring these /* during TMU1 test, TMU0 doesnt receive any textures => ignoring these
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 2, U9_TMU0_FT_DATA_0, U9_TMU0_FT_DATA_0);
*/ */
/* U9_TMU0_TT_DATA_x is only tested when using TMU1 */ /* U9_TMU0_TT_DATA_x is only tested when using TMU1 */
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U9_TMU0_TT_DATA_0);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, TT_TDATA_R131);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L1, 1.0/2, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L1, dScoreFront, U13, U11);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); if(RamSizeMB>2)
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L1, dScoreBack, U27, U28);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, U9_TMU0_TT_DATA_0, U9_TMU0_TT_DATA_0); LWordBitFaultSet(pFaultSrcCtx,ErrorMark_L1, 1.0 / 1, U8_TMU1 + 1, U8_TMU1 + 16 + 1);
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, U8_TMU1_TF_DATA_0, U8_TMU1_TF_DATA_0);
WordBitFaultSet(ErrorMark_L1_1, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_2, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_3, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L1_4, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_1, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_2, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_3, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
WordBitFaultSet(ErrorMark_L2_4, 1.0 / 16, U8_TMU1_FT_DATA_0, U8_TMU1_FT_DATA_0);
MemChipDQFaultSet(ErrorMark_L1_1, dScoreFront, U13, U11);
MemChipDQFaultSet(ErrorMark_L1_2, dScoreFront, U13, U11);
MemChipDQFaultSet(ErrorMark_L1_3, dScoreFront, U13, U11);
MemChipDQFaultSet(ErrorMark_L1_4, dScoreFront, U13, U11);
MemChipDQFaultSet(ErrorMark_L2_1, dScoreFront, U16, U15);
MemChipDQFaultSet(ErrorMark_L2_2, dScoreFront, U16, U15);
MemChipDQFaultSet(ErrorMark_L2_3, dScoreFront, U16, U15);
MemChipDQFaultSet(ErrorMark_L2_4, dScoreFront, U16, U15);
MemChipDQFaultSet(ErrorMark_L1_1, dScoreBack, U27, U28);
MemChipDQFaultSet(ErrorMark_L1_2, dScoreBack, U27, U28);
MemChipDQFaultSet(ErrorMark_L1_3, dScoreBack, U27, U28);
MemChipDQFaultSet(ErrorMark_L1_4, dScoreBack, U27, U28);
MemChipDQFaultSet(ErrorMark_L2_1, dScoreBack, U29, U30);
MemChipDQFaultSet(ErrorMark_L2_2, dScoreBack, U29, U30);
MemChipDQFaultSet(ErrorMark_L2_3, dScoreBack, U29, U30);
MemChipDQFaultSet(ErrorMark_L2_4, dScoreBack, U29, U30);
TMUTexDataFaultSet(ErrorMark_L1_1, ErrorMark_L2_1, 1.0 / 4, U8_TMU1);
TMUTexDataFaultSet(ErrorMark_L1_2, ErrorMark_L2_2, 1.0 / 4, U8_TMU1);
TMUTexDataFaultSet(ErrorMark_L1_3, ErrorMark_L2_3, 1.0 / 4, U8_TMU1);
TMUTexDataFaultSet(ErrorMark_L1_4, ErrorMark_L2_4, 1.0 / 4, U8_TMU1);
TMUTexDataCtrlFaultSet( ErrorMark_L1_1,
1.0 / 8,
U8_TMU1_TEX_CAS0,
U8_TMU1_TEX_CAS1,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_2,
1.0 / 8,
U8_TMU1_TEX_CAS0,
U8_TMU1_TEX_CAS1,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_3,
1.0 / 8,
U8_TMU1_TEX_CAS0,
U8_TMU1_TEX_CAS1,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L1_4,
1.0 / 8,
U8_TMU1_TEX_CAS0,
U8_TMU1_TEX_CAS1,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_1,
1.0 / 8,
U8_TMU1_TEX_CAS2,
U8_TMU1_TEX_CAS3,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_2,
1.0 / 8,
U8_TMU1_TEX_CAS2,
U8_TMU1_TEX_CAS3,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_3,
1.0 / 8,
U8_TMU1_TEX_CAS2,
U8_TMU1_TEX_CAS3,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE);
TMUTexDataCtrlFaultSet( ErrorMark_L2_4,
1.0 / 8,
U8_TMU1_TEX_CAS2,
U8_TMU1_TEX_CAS3,
mem < 0x200000 ? U8_TMU1_TEX_RAS0 : U8_TMU1_TEX_RAS1,
U8_TMU1_TEX_WE );
}
/*
printf("== Quick Report ==\n");
if(ErrorMark_L1_1)
{
printf( "LFB[0][0] is 0x%08x [expected 0x%08x] !\n", L1_1, value1+0);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L1_1, 31, 0);
printf( "\n");
}
if(ErrorMark_L1_2)
{
printf( "LFB[0][1] is 0x%08x [expected 0x%08x] !\n", L1_2, value1+1);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L1_2, 31, 0);
printf( "\n");
}
if(ErrorMark_L1_3)
{
printf( "LFB[0][2] is 0x%08x [expected 0x%08x] !\n", L1_3, value1+2);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L1_3, 31, 0);
printf( "\n");
}
if(ErrorMark_L1_4)
{
printf( "LFB[0][3] is 0x%08x [expected 0x%08x] !\n", L1_4, value1+3);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L1_4, 31, 0);
printf( "\n");
} }
if(ErrorMark_L2_1) logD("## overall fault LW bit-map : \n");
if(sOptions.eLogLevel >= E_LOGLEVEL__DEBUG)
{ {
printf( "LFB[1][0] is 0x%08x [expected 0x%08x] !\n", L2_1, value2+0); sprintbin32Info(szBuff,ErrorMark_L1, 31, 0);
printf( "Faulty bits :\n"); logD("%s\n",szBuff);
printbin32Info(ErrorMark_L2_1, 63, 21);
printf( "\n");
} }
if(ErrorMark_L2_2)
{
printf( "LFB[1][1] is 0x%08x [expected 0x%08x] !\n", L2_2, value2+1);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L2_2, 63, 21);
printf( "\n");
}
if(ErrorMark_L2_3)
{
printf( "LFB[1][2] is 0x%08x [expected 0x%08x] !\n", L2_3, value2+2);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L2_3, 63, 21);
printf( "\n");
}
if(ErrorMark_L2_4)
{
printf( "LFB[1][3] is 0x%08x [expected 0x%08x] !\n", L2_4, value2+3);
printf( "Faulty bits :\n");
printbin32Info(ErrorMark_L2_4, 63, 21);
printf( "\n");
}
*/
} }
/* reading back second line pixels addresses */
const uint32_t L2_1 = IGET(sst[(SST_LFB_ADDR >> 2) + (2048 >> 2) + 0]);
const uint32_t ErrorMark_L2 = L2_1 ^ ( value2 + 0 );
if(ErrorMark_L2)
{
NbErr++;
logD("===========================================================\n");
logD( "# fault on 2nd line, value : 0x%04X [expected 0x%04X] !\n",
value2, L2_1);
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U9_TMU0_TF_DATA_0);
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U3_FBI_TF_DATA_0);
RGBToBus_Fault_Quartets(pFaultSrcCtx, ErrorMark_L2, 1.0/2,
RA10_1, RA11_1, RA12_1, RA13_1);
if(ucNumTMU == 0)
{
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U9_TMU0_FT_DATA_0);
MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L2, dScoreFront, U18, U17);
if(RamSizeMB>2)
MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L2, dScoreBack, U25, U26);
LWordBitFaultSet(pFaultSrcCtx,ErrorMark_L2, 1.0 / 1, U9_TMU0 + 32 + 1, U9_TMU0 + 48 + 1);
}
else
{
/* during TMU1 test, TMU0 doesnt receive any textures => ignoring these
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U9_TMU0_FT_DATA_0);
*/
/* U9_TMU0_TT_DATA_x is only tested when using TMU1 */
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U9_TMU0_TT_DATA_0);
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, TT_TDATA_R131);
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U8_TMU1_TF_DATA_0);
RGBToBus_Fault(pFaultSrcCtx, ErrorMark_L2, 1.0/2, U8_TMU1_FT_DATA_0);
MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L2, dScoreFront, U16, U15);
if(RamSizeMB>2)
MemChipDQFaultSet(pFaultSrcCtx, ErrorMark_L2, dScoreBack, U29, U30);
LWordBitFaultSet(pFaultSrcCtx,ErrorMark_L2, 1.0 / 1, U8_TMU1 + 32 + 1, U8_TMU1 + 48 + 1);
}
logD("## overall fault LW bit-map : \n");
if(sOptions.eLogLevel >= E_LOGLEVEL__DEBUG)
{
sprintbin32Info(szBuff,ErrorMark_L2, 31, 0);
logD("%s\n",szBuff);
}
}
clearScreen(sstregs,0x00000000,8,2);
/* reset the Init0 register back to its previous value */ /* reset the Init0 register back to its previous value */
sst1InitIdle(sst); sst1InitIdle(sst);
devInfo->tmuInit0[(int)ucNumTMU] = _trexInit0;
ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]); ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);
@@ -451,17 +181,18 @@ RenderTest( sst1DeviceInfoStruct* devInfo,
} }
unsigned long long unsigned long long
test_TMU_datalines( sst1DeviceInfoStruct* devInfo, test_TMU_datalines( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const unsigned char ucNumTMU, const unsigned char ucNumTMU,
const unsigned char bRandom, const unsigned char bRandom,
const unsigned char RamSizeMB) const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{ {
typedef struct _def_sMemBlock{ typedef struct _def_sMemBlock{
unsigned long ulAddStart; uint32_t ulAddStart;
unsigned long ulAddEnd; uint32_t ulAddEnd;
unsigned long ulAddLength; uint32_t ulAddLength;
}def_sMemBlock; }def_sMemBlock;
const def_sMemBlock ar_memBlocks[] = { const def_sMemBlock ar_memBlocks[] = {
@@ -484,21 +215,21 @@ test_TMU_datalines( sst1DeviceInfoStruct* devInfo,
/* set downstream TMUs to only passthrough */ /* set downstream TMUs to only passthrough */
for (int i=0; i<ucNumTMU; i++) for (int i=0; i<ucNumTMU; i++)
ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS); ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS);
for( int iMemBlock = 0; for( int iMemBlock = 0;
iMemBlock <= sizeof(ar_memBlocks)/sizeof(def_sMemBlock); iMemBlock < sizeof(ar_memBlocks)/sizeof(def_sMemBlock);
iMemBlock++) iMemBlock++)
{ {
const def_sMemBlock* pMemBlk = &ar_memBlocks[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;
if(RamSizeMB<4 && pMemBlk->ulAddStart >= 0x300000) continue;
if(RamSizeMB<3 && pMemBlk->ulAddStart >= 0x200000) continue; logT("Testing @ 0x%08x to 0x%08x ...\n",
if(RamSizeMB<2 && pMemBlk->ulAddStart >= 0x100000) continue;
/*
printf("Testing memory block 0x%08x to 0x%08x ...\n",
pMemBlk->ulAddStart, pMemBlk->ulAddStart,
pMemBlk->ulAddStart + pMemBlk->ulAddLength -4); pMemBlk->ulAddStart + pMemBlk->ulAddLength -4);
*/
unsigned char ucAddMovingBit = 0; unsigned char ucAddMovingBit = 0;
for( FxU32 addrTest = pMemBlk->ulAddStart ; for( FxU32 addrTest = pMemBlk->ulAddStart ;
addrTest < (pMemBlk->ulAddStart + pMemBlk->ulAddLength); addrTest < (pMemBlk->ulAddStart + pMemBlk->ulAddLength);
@@ -506,6 +237,7 @@ test_TMU_datalines( sst1DeviceInfoStruct* devInfo,
{ {
FxU32 bitTest = 1u; FxU32 bitTest = 1u;
FxU32 bitTest2 = 1u << 31; FxU32 bitTest2 = 1u << 31;
for(unsigned long nloop=0;; nloop++) for(unsigned long nloop=0;; nloop++)
{ {
unsigned long ulNbError; unsigned long ulNbError;
@@ -515,20 +247,25 @@ test_TMU_datalines( sst1DeviceInfoStruct* devInfo,
ucNumTMU, ucNumTMU,
addrTest, addrTest,
bitTest, bitTest,
bitTest2); bitTest2,
RamSizeMB,
pFaultSrcCtx);
ullNbErrorAll += ulNbError; ullNbErrorAll += ulNbError;
if((bRandom && (nloop > 32)) || bitTest == 0) if((bRandom && (nloop > 64)) || bitTest == 0)
{
break; break;
}
bitTest = bRandom ? get_notnull_random_balanced_mByte() : (bitTest << 1); bitTest = bRandom ?
bitTest2 = bRandom ? get_notnull_random_balanced_mByte() : (bitTest2 >> 1); get_notnull_random_balanced_mByte()
: (bitTest << 1);
bitTest2 = bRandom ?
get_notnull_random_balanced_mByte()
: (bitTest2 >> 1);
} }
//printf("Done @ 0x%08x\n",dataTest); logT("Done @ 0x%08x\n",addrTest);
const FxU32 new_addrTest = pMemBlk->ulAddStart | (1 << ucAddMovingBit); const FxU32 new_addrTest = pMemBlk->ulAddStart | (1u << ucAddMovingBit);
if(new_addrTest == pMemBlk->ulAddStart) break; if(new_addrTest == pMemBlk->ulAddStart) break;
addrTest = new_addrTest; addrTest = new_addrTest;
} }

View File

@@ -19,11 +19,12 @@
#define _DEF_TEST_DATA_H_ #define _DEF_TEST_DATA_H_
unsigned long long unsigned long long
test_TMU_datalines( sst1DeviceInfoStruct* devInfo, test_TMU_datalines( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const unsigned char ucNumTMU, const unsigned char ucNumTMU,
const unsigned char bRandom, const unsigned char bRandom,
const unsigned char RamSizeMB); const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx);
#endif //_DEF_TEST_DATA_H_ #endif //_DEF_TEST_DATA_H_

View File

@@ -15,6 +15,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#define _BSD_SOURCE 1
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
@@ -29,6 +31,7 @@
#include "Utils.h" #include "Utils.h"
#include "Draw.h" #include "Draw.h"
#include "Test_Common.h"
#include "Test_Data_Huge.h" #include "Test_Data_Huge.h"
#define _DEF_NB_PIXEL_ROW 256 #define _DEF_NB_PIXEL_ROW 256
@@ -36,33 +39,330 @@
#define _NB_CHECK_LOOP 3 #define _NB_CHECK_LOOP 3
//#define _PROFILING //#define _PROFILING
static unsigned long long typedef struct _def_sFaultSheet{
RenderTest( sst1DeviceInfoStruct* devInfo, unsigned char ucNumTMU;
FxU32* sst, unsigned char bEvenRow;
SstRegs *sstregs, def_eFaultSource Ux_MEMChip_MainMSB;
const char ucNumTMU, def_eFaultSource Ux_MEMChip_MainLSB;
const FxU32 mem) 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] =
{ {
unsigned long NbErr = 0; { /*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 = _relbitIdxQuartet;
const unsigned char relbitIdx = _relbitIdx;
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);
/* We need to remap the faulty bit to the ARGB Bus, from the RGB565 Value.
* Based on this code:
* uint16_t u16Bus_r8 = ((u16pix1>>11) & 0x1F) << 3;
* uint16_t u16Bus_g8 = ((u16pix1>>5) & 0x3F) << 2;
* uint16_t u16Bus_b8 = ((u16pix1>>0) & 0x1F) << 3;
* uint16_t u16Bus_a8 = 0;
*
* //uint16_t u16Fault_W1 = (u16Bus_g8<<8) + u16Bus_b8;
* //uint16_t u16Fault_W2 = (u16Bus_a8<<8) + u16Bus_r8;
*
*/
uint8_t ARGBrelbitIdx;
double dARGBScore = 1.0/4.0;
if(relbitIdxWord>=11) //RED
{
ARGBrelbitIdx = relbitIdxWord -11 +3;
//There is no Alpha channel so score shouldnt be divided by 2
}
else if(relbitIdxWord>=5) //GREEN
{
ARGBrelbitIdx = relbitIdxWord -5 +2 +8;
dARGBScore /= 2;
}
else //BLUE
{
ARGBrelbitIdx = relbitIdxWord +3;
dARGBScore /= 2;
}
logD("## ARGB Bus bit: %d\n",ARGBrelbitIdx);
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
+ ARGBrelbitIdx,
dARGBScore);
/* Output path, TMU0 to FBI*/
FaultSource_addScore( pFaultSrcCtx,
U9_TMU0
+ 97 //U9_TMU0_TF_DATA_x
+ ARGBrelbitIdx,
dARGBScore);
FaultSource_addScore( pFaultSrcCtx,
U3_FBI_TF_DATA_0
+ ARGBrelbitIdx,
dARGBScore);
if(ARGBrelbitIdx>=12)
{
logD("- RA13_x : %s\n",pFaultSrcCtx[RA13_1+ARGBrelbitIdx-12].szName);
FaultSource_addScore( pFaultSrcCtx,
RA13_1
+ ARGBrelbitIdx -12,
dARGBScore);
}
else if(ARGBrelbitIdx>=8)
{
logD("- RA12_x : %s\n",pFaultSrcCtx[RA12_1+ARGBrelbitIdx-8].szName);
FaultSource_addScore( pFaultSrcCtx,
RA12_1
+ ARGBrelbitIdx -8,
dARGBScore);
}
else if(ARGBrelbitIdx>=4)
{
logD("- RA11_x : %s\n",pFaultSrcCtx[RA11_1+ARGBrelbitIdx-4].szName);
FaultSource_addScore( pFaultSrcCtx,
RA11_1
+ ARGBrelbitIdx -4,
dARGBScore);
}
else
{
logD("- RA10_x : %s\n",pFaultSrcCtx[RA10_1+ARGBrelbitIdx].szName);
FaultSource_addScore( pFaultSrcCtx,
RA10_1
+ ARGBrelbitIdx,
dARGBScore);
}
/* Transfert path, TMU1 to TMU0*/
if(psCurFaultSheet->ucNumTMU == 1)
{
/* TMU1 output */
FaultSource_addScore( pFaultSrcCtx,
U8_TMU1
+ 97 //U8_TMU1_TF_DATA_x
+ ARGBrelbitIdx,
dARGBScore);
/* line adaptation resistors */
FaultSource_addScore( pFaultSrcCtx,
TT_TDATA_R131
+ 0
+ ARGBrelbitIdx,
dARGBScore);
/* 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
+ ARGBrelbitIdx,
dARGBScore);
}
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 #ifdef _PROFILING
clock_t begin = clock(); clock_t begin = clock();
#endif #endif
ISET(sstregs->texBaseAddr, (mem>>3)); /* set to mem addr */
static unsigned short /* precomputing a pseudo-random texture data chunk.
*/
static uint16_t
ar_u16Pixels[_DEF_NB_PIXEL_ROW][_DEF_NB_PIXEL_COL]; ar_u16Pixels[_DEF_NB_PIXEL_ROW][_DEF_NB_PIXEL_COL];
static unsigned long
ar_u16PixelsRaw[_DEF_NB_PIXEL_ROW][_DEF_NB_PIXEL_COL/2];
static unsigned short
ar_u16PixelsReRead[_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_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) for(unsigned short iter_col = 0; iter_col < _DEF_NB_PIXEL_COL; iter_col+=2)
{ {
const unsigned long NewData = get_notnull_random_balanced_mByte(); const uint32_t NewData = get_notnull_random_balanced_mByte();
ar_u16PixelsRaw[iter_row][iter_col/2] = NewData;
ar_u16Pixels[iter_row][iter_col] = NewData >>16; ar_u16Pixels[iter_row][iter_col] = NewData >>16;
ar_u16Pixels[iter_row][iter_col+1] = NewData & 0xFFFF; ar_u16Pixels[iter_row][iter_col+1] = NewData & 0xFFFF;
} }
@@ -72,18 +372,31 @@ RenderTest( sst1DeviceInfoStruct* devInfo,
clock_t after_create = clock(); clock_t after_create = clock();
#endif #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 volatile FxU32 *texRowAddr
= (ucNumTMU<<(21-2)) + (((FxU32)0/*LOD0*/)<<(17-2)) = (ucNumTMU<<(21-2))
+ (((FxU32)0)<<(17-2)) /*LOD0*/
+ (FxU32 *)SST_TEX_ADDRESS(sst); + (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++) 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/2; iter_col++) mmio_fastwrite32( texRowAddr,
{ (uint32_t*)ar_u16Pixels[iter_row],
//printf("writing %d\n",ar_u16PixelsRaw[iter_row][iter_col]); _DEF_NB_PIXEL_COL/2);
ISET(texRowAddr[iter_col], ar_u16PixelsRaw[iter_row][iter_col]); /* move to next line */
} texRowAddr += (1<<(9-2));
texRowAddr += (1<<(9-2)); //jump to next line
} }
#ifdef _PROFILING #ifdef _PROFILING
@@ -94,123 +407,235 @@ RenderTest( sst1DeviceInfoStruct* devInfo,
clock_t after_check[_NB_CHECK_LOOP]; clock_t after_check[_NB_CHECK_LOOP];
#endif #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++) for(unsigned int i = 0; i<_NB_CHECK_LOOP; i++)
{ {
//printf("draw/checking\n");
#ifdef _PROFILING #ifdef _PROFILING
before_draw[i] = clock(); before_draw[i] = clock();
#endif #endif
drawTriangle(sstregs, 0, 0, 512); /* draw a 252x512 triangle */ /* draw a 256x256 square */
drawSquare(sstregs, ucNumTMU, 0, 0, 256);
sst1InitIdle(sst);
#ifdef _PROFILING #ifdef _PROFILING
after_draw[i] = clock(); after_draw[i] = clock();
#endif #endif
/*
printf("rdy.\n");
GrLfbInfo_t info;
if(grLfbLock( GR_LFB_READ_ONLY,
GR_BUFFER_BACKBUFFER,
GR_LFBWRITEMODE_ANY,
GR_ORIGIN_UPPER_LEFT,
FXFALSE,
&info)
)
{
printf("got LFB access.\n");
FxU32 *rptr;
rptr = info.lfbPtr;
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+=8)
{
ar_u16PixelsReRead[iter_row][iter_col] = *rptr >> 16;
ar_u16PixelsReRead[iter_row][iter_col+1] = *rptr & 0xFFFF;
rptr+=1;
}
rptr+=info.strideInBytes>>2;
}
grLfbUnlock(GR_LFB_READ_ONLY,GR_BUFFER_FRONTBUFFER);
}
else
{
printf("NOT LFB access.\n");
}
*/
volatile FxU32* pLFB = sst + (SST_LFB_ADDR>>2); volatile FxU32* pLFB = sst + (SST_LFB_ADDR>>2);
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; iter_row++)
/* 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);
//printf("reading row %d\n",iter_row); mmio_fastread32((uint32_t*)&ar_u16PixelsReRead[iter_row],
for(unsigned short iter_col = 0; iter_col < _DEF_NB_PIXEL_COL; iter_col+=2) pLFB,
{ _DEF_NB_PIXEL_COL/2);
const FxU32 u32Data = *pLFB++; logT("copy done\n");
ar_u16PixelsReRead[iter_row][iter_col] = u32Data >> 16; pLFB += ((2048)>>2) ;
ar_u16PixelsReRead[iter_row][iter_col+1] = u32Data & 0xFFFF;
//printf("read: %d\n",u32Data);
}
pLFB += ((2048)>>2) - ((_DEF_NB_PIXEL_COL*2) >>2) ;
} }
#ifdef _PROFILING #ifdef _PROFILING
after_read[i] = clock(); after_read[i] = clock();
#endif #endif
for(unsigned short iter_row = 0; iter_row < _DEF_NB_PIXEL_ROW; iter_row++)
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)
{ {
//printf("checking row %d\n",iter_row); 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) for(unsigned short iter_col = 0; iter_col < _DEF_NB_PIXEL_COL; iter_col+=2)
{ {
if(ar_u16PixelsReRead[iter_row][iter_col] != ar_u16Pixels[iter_row][iter_col]) logT("checking col %d\n",iter_col);
{/* const uint32_t ErrorMark_Lx = ar_u32ErrorMark_Lx[(iter_row*_DEF_NB_PIXEL_COL+iter_col)/2];
printf("Error pix1 on row %d, col %d: expected %04x, got %04x\n",
iter_row, iter_col, /* There are just too much data to do a naive bunch of check on
ar_u16Pixels[iter_row][iter_col], * every possible FaultSource. So we need to do an ErrorMark's
ar_u16PixelsReRead[iter_row][iter_col]);*/ * bit driven check. So we will check every bit once and only
NbErr++; * 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.
if(ar_u16PixelsReRead[iter_row][iter_col+1] != ar_u16Pixels[iter_row][iter_col+1]) *
{/* * To speed up things, we are also using a LUT-like preset
printf("Error pix2 on row %d, col %d: expected %04x, got %04x\n", * FaultSource array (psCurFaultSheet).
iter_row, iter_col, */
ar_u16Pixels[iter_row][iter_col+1],
ar_u16PixelsReRead[iter_row][iter_col+1]);*/ const def_sFaultSheet* psCurFaultSheet = &sFaultSheet[(int)ucNumTMU][iter_row%2];
if(ErrorMark_Lx)
{
NbErr++; 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 #ifdef _PROFILING
after_check[i] = clock(); after_check[i] = clock();
#endif #endif
} }
#ifdef _PROFILING #ifdef _PROFILING
clock_t end = clock(); clock_t end = clock();
printf("time to create: %f\n",(double)(after_create-begin)/CLOCKS_PER_SEC); logI("time to create: %f\n",
printf("time to write: %f\n",(double)(after_write-after_create)/CLOCKS_PER_SEC); (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++) for(unsigned int i = 0; i<_NB_CHECK_LOOP; i++)
{ {
printf("time to draw [%d]: %f\n",i,(double)(after_draw[i]-before_draw[i])/CLOCKS_PER_SEC); logI("time to draw [%d]: %f\n",
printf("time to read [%d]: %f\n",i,(double)(after_read[i]-after_draw[i])/CLOCKS_PER_SEC); i, (double)(after_draw[i]-before_draw[i])/CLOCKS_PER_SEC);
printf("time to check [%d]: %f\n",i,(double)(after_check[i]-after_read[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);
} }
printf("overall: %f\n",(double)(end-begin)/CLOCKS_PER_SEC); logI("overall: %f\n",(double)(end-begin)/CLOCKS_PER_SEC);
#endif #endif
return NbErr; return NbErr;
} }
unsigned long long unsigned long long
test_TMU_datalines_Huge( sst1DeviceInfoStruct* devInfo, test_TMU_datalines_Huge( sst1DeviceInfoStruct * const
FxU32* sst, devInfo,
SstRegs *sstregs, FxU32 * const sst,
SstRegs * const sstregs,
const unsigned char ucNumTMU, const unsigned char ucNumTMU,
const unsigned char RamSizeMB) const unsigned char RamSizeMB,
def_sFaultSourceScoreRec * const
pFaultSrcCtx)
{ {
typedef struct _def_sMemBlock{ typedef struct _def_sMemBlock{
unsigned long ulAddStart; uint32_t ulAddStart;
unsigned long ulAddEnd; uint32_t ulAddEnd;
unsigned long ulAddLength; uint32_t ulAddLength;
}def_sMemBlock; }def_sMemBlock;
const def_sMemBlock ar_memBlocks[] = { const def_sMemBlock ar_memBlocks[] = {
@@ -229,42 +654,54 @@ test_TMU_datalines_Huge( sst1DeviceInfoStruct* devInfo,
}; };
unsigned long long ullNbErrorAll = 0; unsigned long long ullNbErrorAll = 0;
devInfo->tmuInit0[(int)ucNumTMU] = SST_TREXINIT0_DEFAULT ;
sst1InitIdle(sst); 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]); ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);
// set downstream TMUs to passthrough /* set downstream TMUs to passthrough */
for (int i=0; i<ucNumTMU; i++) for (int i=0; i<ucNumTMU; i++)
ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS); ISET(SST_TREX(sstregs,i)->textureMode, SST_TC_PASS | SST_TCA_PASS);
for( int iMemBlock = 0; for( int iMemBlock = 0;
iMemBlock <= sizeof(ar_memBlocks)/sizeof(def_sMemBlock); iMemBlock < sizeof(ar_memBlocks)/sizeof(def_sMemBlock);
iMemBlock++) iMemBlock++)
{ {
const def_sMemBlock* pMemBlk = &ar_memBlocks[iMemBlock]; const def_sMemBlock* pMemBlk = &ar_memBlocks[iMemBlock];
if(RamSizeMB<4 && pMemBlk->ulAddStart >= 0x300000) continue; if(RamSizeMB<4 && pMemBlk->ulAddStart >= 0x300000) continue;
if(RamSizeMB<3 && pMemBlk->ulAddStart >= 0x200000) continue; if(RamSizeMB<3 && pMemBlk->ulAddStart >= 0x200000) continue;
if(RamSizeMB<2 && pMemBlk->ulAddStart >= 0x100000) continue; if(RamSizeMB<2 && pMemBlk->ulAddStart >= 0x100000) continue;
//printf("RamSizeMB= %d, ulAddStart=%08x\n", RamSizeMB,pMemBlk->ulAddStart); logT("RamSizeMB= %d, ulAddStart=%08x\n", RamSizeMB,pMemBlk->ulAddStart);
for( FxU32 addrTest = pMemBlk->ulAddStart ; for( FxU32 addrTest = pMemBlk->ulAddStart ;
addrTest < (pMemBlk->ulAddStart + pMemBlk->ulAddLength); addrTest < (pMemBlk->ulAddStart + pMemBlk->ulAddLength);
addrTest += 65536) //256x256x2 (16bit pixels texture) addrTest += 131072) /* 256x256x2 (16bit pixels texture) */
{ {
//printf("Testing memory block 0x%08x ...\n", addrTest); logT("Testing memory block 0x%08x ...\n", addrTest);
ullNbErrorAll += RenderTest( devInfo, const unsigned long long
ullNbError = RenderTest( devInfo,
sst, sst,
sstregs, sstregs,
ucNumTMU, ucNumTMU,
addrTest); 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 */ /* reset the Init0 register back to its previous value */
sst1InitIdle(sst); sst1InitIdle(sst);
devInfo->tmuInit0[(int)ucNumTMU] = _trexInit0;
ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]); ISET(SST_TREX(sst,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst); sst1InitIdle(sst);

View File

@@ -19,10 +19,11 @@
#define _DEF_TEST_DATA_HUGE_H_ #define _DEF_TEST_DATA_HUGE_H_
unsigned long long unsigned long long
test_TMU_datalines_Huge( sst1DeviceInfoStruct* devInfo, test_TMU_datalines_Huge( sst1DeviceInfoStruct * const devInfo,
FxU32* sst, FxU32 * const sst,
SstRegs *sstregs, SstRegs * const sstregs,
const unsigned char ucNumTMU, const unsigned char ucNumTMU,
const unsigned char RamSizeMB); const unsigned char RamSizeMB,
def_sFaultSourceScoreRec* const pFaultSrcCtx);
#endif //_DEF_TEST_DATA_HUGE_H_ #endif //_DEF_TEST_DATA_HUGE_H_

659
Test_Data_NoMem.c Normal file
View File

@@ -0,0 +1,659 @@
/* 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 <math.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"
#include "Test_Data_NoMem.h"
extern const def_sTestPattern ar_sExpectedPattern_Test3[];
extern const unsigned int uNbPattern_Test3;
extern const def_sTestPattern ar_sExpectedPattern_Test3_Dither[];
extern const unsigned int uNbPattern_Test3_Dither;
extern const def_sFaultSourceLineMap ar_sFaultSourceLineMap[];
void DisplayPattern(const def_sTestPattern * const pREF)
{
printf("RGB: %04X %04X %04X %04X\n",
pREF->data.access.u16Pix[0][0],
pREF->data.access.u16Pix[0][1],
pREF->data.access.u16Pix[0][2],
pREF->data.access.u16Pix[0][3]);
printf("RGB: %04X %04X %04X %04X\n",
pREF->data.access.u16Pix[1][0],
pREF->data.access.u16Pix[1][1],
pREF->data.access.u16Pix[1][2],
pREF->data.access.u16Pix[1][3]);
printf("RGB: %04X %04X %04X %04X\n",
pREF->data.access.u16Pix[2][0],
pREF->data.access.u16Pix[2][1],
pREF->data.access.u16Pix[2][2],
pREF->data.access.u16Pix[2][3]);
printf("RGB: %04X %04X %04X %04X\n",
pREF->data.access.u16Pix[3][0],
pREF->data.access.u16Pix[3][1],
pREF->data.access.u16Pix[3][2],
pREF->data.access.u16Pix[3][3]);
printf("Alpha: %02X %02X %02X %02X\n",
pREF->data.access.u8APix[0][0],
pREF->data.access.u8APix[0][1],
pREF->data.access.u8APix[0][2],
pREF->data.access.u8APix[0][3]);
printf("Alpha: %02X %02X %02X %02X\n",
pREF->data.access.u8APix[1][0],
pREF->data.access.u8APix[1][1],
pREF->data.access.u8APix[1][2],
pREF->data.access.u8APix[1][3]);
printf("Alpha: %02X %02X %02X %02X\n",
pREF->data.access.u8APix[2][0],
pREF->data.access.u8APix[2][1],
pREF->data.access.u8APix[2][2],
pREF->data.access.u8APix[2][3]);
printf("Alpha: %02X %02X %02X %02X\n",
pREF->data.access.u8APix[3][0],
pREF->data.access.u8APix[3][1],
pREF->data.access.u8APix[3][2],
pREF->data.access.u8APix[3][3]);
}
// Returns the distance between A & B, normalized between 0 and 1.
// 0 means they are perfectly identicals.
// 1 means they are entirely diferents.
double ComputePatternDistance( const def_sTestPattern * const pA,
const def_sTestPattern * const pB)
{
double dDistance = 0;
logT("========================\n");
logT("Compare A|B:\n");
for (unsigned int i = 0; i <12; i=i+4)
{
logT("%08X\t%08X\n",pA->data.raw[i],pB->data.raw[i]);
logT("%08X\t%08X\n",pA->data.raw[i+1],pB->data.raw[i+1]);
logT("%08X\t%08X\n",pA->data.raw[i+2],pB->data.raw[i+2]);
logT("%08X\t%08X\n",pA->data.raw[i+3],pB->data.raw[i+3]);
dDistance += dComputeDistance32(pA->data.raw[i], pB->data.raw[i]);
dDistance += dComputeDistance32(pA->data.raw[i+1],pB->data.raw[i+1]);
dDistance += dComputeDistance32(pA->data.raw[i+2],pB->data.raw[i+2]);
dDistance += dComputeDistance32(pA->data.raw[i+3],pB->data.raw[i+3]);
}
dDistance /= 12*4*32;
logT("dDistance: %f\n",dDistance);
return dDistance;
}
typedef struct _def_sScoreSet{
double dScore;
const def_sTestPattern * pREF;
}def_sScoreSet;
int scoreSetCmp(const void * const first, const void * const second)
{
const double scoreFirst = ((def_sScoreSet*)first)->dScore;
const double scoreSecond = ((def_sScoreSet*)second)->dScore;
return scoreFirst > scoreSecond ? -1 :
(scoreFirst < scoreSecond ? 1 : 0);
}
double inline ScaleScore(const double dIn,const double dK)
{
return (1.0-exp(-dK*dIn))/(1.0-exp(-dK));
//return log(1.0+(dK*dIn))/log(1.0+dK);
}
/* returns a def_sScoreSet array, containing ordered reference to testPattern
* plus the corresponding score.
*/
void GetNearestIndexes( const def_sTestPattern * const pREF,
const def_sTestPattern * const pSet,
def_sScoreSet * const ScoreSet,
const unsigned int uNbPattern)
{
for (unsigned int i = 0; i < uNbPattern; i++)
{
ScoreSet[i].pREF = &pSet[i];
ScoreSet[i].dScore = (1 - ScaleScore(ComputePatternDistance(pREF,pSet+i),100));
logT("ScoreSet[%d].dScore = %f\n",i,ScoreSet[i].dScore);
}
qsort(ScoreSet,uNbPattern,sizeof(def_sScoreSet),scoreSetCmp);
double dFirstScore = -INFINITY;
for (unsigned int i = 0; i < uNbPattern; i++)
{
if(i==0)
dFirstScore = ScoreSet[i].dScore;
ScoreSet[i].dScore = (ScoreSet[i].dScore / dFirstScore) * 100;
}
}
unsigned char DistributeFaults( const def_sTestPattern * const pREF,
const def_sTestPattern * const pREFPatterns,
const unsigned int uNbREFPatterns,
const unsigned char ucNumTMU,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{
def_sScoreSet * const ScoreSet
= (def_sScoreSet*)malloc(uNbREFPatterns*sizeof(def_sScoreSet));
if(ScoreSet==NULL)
{
logE("Cannot allocate memory...");
return 1;
}
GetNearestIndexes(pREF,pREFPatterns,ScoreSet,uNbREFPatterns);
for( int i = 0 ; i < uNbREFPatterns ; i++)
{
if( ScoreSet[i].pREF->bReferenceSet && ScoreSet[i].dScore==100)
{
//logD("No Fault found\n");
free(ScoreSet);
return 0;
}
}
logD("==========================\n");
logD("Read:\n");
if( sOptions.eLogLevel >= E_LOGLEVEL__DEBUG)
DisplayPattern(pREF);
for( int i = 0 ; i < uNbREFPatterns ; i++)
{
logD("==========================\n");
if((!ScoreSet[i].pREF->bReferenceSet) && (ScoreSet[i].dScore>=80))
{
logD( "%d Score = %f\n",
ScoreSet[i].pREF->u8FaultLineIdx,ScoreSet[i].dScore);
FaultSource_addScore( pFaultSrcCtx,
ar_sFaultSourceLineMap
[ScoreSet[i].pREF->u8FaultLineIdx]
.eTMUFaultSource_TMU0_RES,
ScoreSet[i].dScore);
FaultSource_addScore( pFaultSrcCtx,
ar_sFaultSourceLineMap
[ScoreSet[i].pREF->u8FaultLineIdx]
.eTMUFaultSource_FBI,
ScoreSet[i].dScore);
FaultSource_addScore( pFaultSrcCtx,
ar_sFaultSourceLineMap
[ScoreSet[i].pREF->u8FaultLineIdx]
.eTMUFaultSource_TMU0_FBI,
ScoreSet[i].dScore);
if(ucNumTMU==1)
{
FaultSource_addScore( pFaultSrcCtx,
ar_sFaultSourceLineMap
[ScoreSet[i].pREF->u8FaultLineIdx]
.eTMUFaultSource_TMU0_TMU1,
ScoreSet[i].dScore);
FaultSource_addScore( pFaultSrcCtx,
ar_sFaultSourceLineMap
[ScoreSet[i].pREF->u8FaultLineIdx]
.eTMUFaultSource_TMU1,
ScoreSet[i].dScore);
}
}
}
free(ScoreSet);
return 1;
}
void TestStep_NoMem(FxU32 * const sst,
SstRegs * const sstregs,
const unsigned char ucNumTMU,
const uint8_t bEnableRGB,
const uint8_t bEnbleAlpha,
const uint8_t bEnableDitherValues,
def_sTestPattern * const psResultPattern)
{
ISET(SST_TREX(sstregs,ucNumTMU)->texBaseAddr, (0x000000>>3));
volatile const FxU32 * const pLFB1 = sst + (SST_LFB_ADDR>>2);
volatile const FxU32 * const pLFB2 = pLFB1 +((2048)>>2) ;
volatile const FxU32 * const pLFB3 = pLFB2 +((2048)>>2) ;
volatile const FxU32 * const pLFB4 = pLFB3 +((2048)>>2) ;
ISET( SST_TREX(sstregs,ucNumTMU)->textureMode,
SST_RGB565
| (bEnableRGB ? SST_TC_ONE : SST_TC_ZERO)
| (bEnbleAlpha ? SST_TCA_ONE :SST_TCA_ZERO));
if(bEnableDitherValues)
{
/* We are using dithering to detect lsb Faults.
* We need a non-zero original LFB value for dithering to happen.
* Drawing a triangle make detection easier.*/
clearScreen(sstregs,(1 << 11) | (0<<5) |(1),8,8);
drawTriangle(sstregs, ucNumTMU, 0, 0, 3, 4);
}
else
{
clearScreen(sstregs,0x00000000,8,8);
drawRect2(sstregs, ucNumTMU, 0, 0, 4, 4);
}
sst1InitIdle(sst);
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[0], pLFB1, 2);
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[1], pLFB2, 2);
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[2], pLFB3, 2);
mmio_fastread32((uint32_t*)psResultPattern->data.access.u16Pix[3], pLFB4, 2);
const uint32_t OldlfbMode = IGET(sstregs->lfbMode);
ISET(sstregs->lfbMode, (OldlfbMode & ~SST_LFB_READFRONTBUFFER) //SST_LFB_READBACKBUFFER
| SST_LFB_READDEPTHABUFFER);
psResultPattern->data.access.u8APix[0][0] = pLFB1[0] & 0xFF;
psResultPattern->data.access.u8APix[0][1] = (pLFB1[0]>>16) & 0xFF;
psResultPattern->data.access.u8APix[0][2] = pLFB1[1] & 0xFF;
psResultPattern->data.access.u8APix[0][3] = (pLFB1[1]>>16) & 0xFF;
psResultPattern->data.access.u8APix[1][0] = pLFB2[0] & 0xFF;
psResultPattern->data.access.u8APix[1][1] = (pLFB2[0]>>16) & 0xFF;
psResultPattern->data.access.u8APix[1][2] = pLFB2[1] & 0xFF;
psResultPattern->data.access.u8APix[1][3] = (pLFB2[1]>>16) & 0xFF;
psResultPattern->data.access.u8APix[2][0] = pLFB3[0] & 0xFF;
psResultPattern->data.access.u8APix[2][1] = (pLFB3[0]>>16) & 0xFF;
psResultPattern->data.access.u8APix[2][2] = pLFB3[1] & 0xFF;
psResultPattern->data.access.u8APix[2][3] = (pLFB3[1]>>16) & 0xFF;
psResultPattern->data.access.u8APix[3][0] = pLFB4[0] & 0xFF;
psResultPattern->data.access.u8APix[3][1] = (pLFB4[0]>>16) & 0xFF;
psResultPattern->data.access.u8APix[3][2] = pLFB4[1] & 0xFF;
psResultPattern->data.access.u8APix[3][3] = (pLFB4[1]>>16) & 0xFF;
ISET(sstregs->lfbMode, OldlfbMode);
ISET( SST_TREX(sstregs,ucNumTMU)->textureMode,
SST_RGB565 | SST_TC_REPLACE | SST_TCA_REPLACE);
}
#define N_LOOP_TEST 100
unsigned long long
test_TMU_datalines_NoMem( sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const unsigned char ucNumTMU,
def_sFaultSourceScoreRec* const pFaultSrcCtx)
{
unsigned long long ullNbErrorAll = 0;
static def_sTestPattern ar_ResultPattern[N_LOOP_TEST][8];
sst1InitIdle(sst);
const uint32_t OldlfbMode = IGET(sstregs->lfbMode);//SST_LFB_READBACKBUFFER
ISET(sstregs->lfbMode, SST_LFB_565 | SST_LFB_READFRONTBUFFER | SST_LFB_RGBALANES_ARGB);
const uint32_t OldfbzMode = IGET(sstregs->fbzMode);
ISET(sstregs->fbzMode,
// SST_DRAWBUFFER_BACK
SST_DRAWBUFFER_FRONT
| SST_RGBWRMASK
| SST_ZAWRMASK
| SST_ENALPHABUFFER // <-for NoMEM test ?? Not needed
| SST_ENALPHAMASK); // <-for NoMEM test; Needed
const uint32_t OldtrexInit0 = 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_RGB565 | SST_TC_PASS | SST_TCA_PASS);
}
/* Testing several time to exclude instabilities */
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
{
/* this test is using the only feature I found that can
* control TMUs output without using TMU's RAM. Using
* textureMode we can force a TMU to output RGB value to
* 0xFFFFFF or 0x000000 (only), and A(lpha) to 0xFF or 0x00 (Only).
* So we will try these 4 pattern and check what we get on the LFB.
* Then eventually we can make "smart" Fault recognition...
*
* To make things harder, the physical data bus is 16Bit (DDR?).
* So [AR] and [GB] or superposed.
* */
/***************/
/* RGB: 0, A: 0*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 0 ,0, 0,
&ar_ResultPattern[i][0]);*/
/***************/
/* RGB: 1, A: 0*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 0, 0,
&ar_ResultPattern[i][1]);*/
/***************/
/* RGB: 1, A: 1*/
/***************/
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 1 , 0,
&ar_ResultPattern[i][2]);
/***************/
/* RGB: 0, A: 1*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 0, 1 , 0,
&ar_ResultPattern[i][3]);*/
}
/* Same test but with dithering enabled to get bit 0-1 values */
ISET(sstregs->fbzMode,
// SST_DRAWBUFFER_BACK
SST_DRAWBUFFER_FRONT
| SST_ENDITHER // <- enabling Dithering for this test
| SST_RGBWRMASK
| SST_ZAWRMASK
| SST_ENALPHABUFFER
| SST_ENALPHAMASK);
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
{
/* this test is using the only feature I found that can
* control TMUs output without using TMU's RAM. Using
* textureMode we can force a TMU to output RGB value to
* 0xFFFFFF or 0x000000 (only), and A(lpha) to 0xFF or 0x00 (Only).
* So we will try these 4 pattern and check what we get on the LFB.
* Then eventually we can make "smart" Fault recognition...
*
* To make things harder, the physical data bus is 16Bit (DDR?).
* So [AR] and [GB] or superposed.
* */
/***************/
/* RGB: 0, A: 0*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 0 ,0, 1,
&ar_ResultPattern[i][4]);*/
/***************/
/* RGB: 1, A: 0*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 0, 1,
&ar_ResultPattern[i][5]);*/
/***************/
/* RGB: 1, A: 1*/
/***************/
TestStep_NoMem( sst, sstregs, ucNumTMU, 1, 1 , 1,
&ar_ResultPattern[i][6]);
/***************/
/* RGB: 0, A: 1*/
/***************/
/* Not implemented because the "all on" test should be enough for now
TestStep_NoMem( sst, sstregs, ucNumTMU, 0, 1 , 1,
&ar_ResultPattern[i][7]);*/
}
/* Post processing test results */
for(unsigned int i = 0; i < N_LOOP_TEST ; i++)
{ /* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][0],
ar_sExpectedPattern_Test1,
uNbPattern_Test1,
ucNumTMU,
pFaultSrcCtx);*/
/* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][1],
ar_sExpectedPattern_Test2,
uNbPattern_Test2,
ucNumTMU,
pFaultSrcCtx);*/
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][2],
ar_sExpectedPattern_Test3,
uNbPattern_Test3,
ucNumTMU,
pFaultSrcCtx);
/* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][3],
ar_sExpectedPattern_Test4,
uNbPattern_Test4,
ucNumTMU,
pFaultSrcCtx);*/
/* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][4],
ar_sExpectedPattern_Test1_Dither,
uNbPattern_Test1_Dither,
ucNumTMU,
pFaultSrcCtx);*/
/* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][5],
ar_sExpectedPattern_Test2_Dither,
uNbPattern_Test2_Dither,
ucNumTMU,
pFaultSrcCtx);*/
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][6],
ar_sExpectedPattern_Test3_Dither,
uNbPattern_Test3_Dither,
ucNumTMU,
pFaultSrcCtx);
/* Not implemented because the "all on" test should be enough for now
ullNbErrorAll +=
DistributeFaults( &ar_ResultPattern[i][7],
ar_sExpectedPattern_Test4_Dither,
uNbPattern_Test4_Dither,
ucNumTMU,
pFaultSrcCtx);*/
}
/* reset the Init0 register back to its previous value */
ISET(sstregs->lfbMode,OldlfbMode);
ISET(sstregs->fbzMode, OldfbzMode);
sst1InitIdle(sst);
devInfo->tmuInit0[(int)ucNumTMU] = OldtrexInit0;
ISET(SST_TREX(sstregs,ucNumTMU)->trexInit0, devInfo->tmuInit0[(int)ucNumTMU]);
sst1InitIdle(sst);
return ullNbErrorAll;
}
/* This is an attempt to simulate TMU->FBI->LFB values exchange and
* computation. It partially works for normal mode (no dithering, alpha buffer
* enabled), with two exception: Alpha bit XX seems to have a special behaviour
* that just zeros the output. And the colour mixing hasnt been reverse
* enginered. The dithering algorithm hasnt been reversed either.
* Then, because we are using pattern distance matching, this function is not
* used anymore. I let it here in case one day we want/need to implement a more
* accurate test
*
int simuFault_step( uint8_t bRGB,
uint8_t bA,
uint16_t u16CurrentPixel,
uint8_t u8CurrentAPixel,
uint16_t * const pu16RenderedPixel,
uint8_t * const pu8RenderedAPixel,
uint16_t u16BUSFaultMap )
{
// TMU Output force set
const uint8_t u8TMU_r8 = bRGB ? 0xFF : 0;
const uint8_t u8TMU_g8 = bRGB ? 0xFF : 0;
const uint8_t u8TMU_b8 = bRGB ? 0xFF : 0;
const uint8_t u8TMU_a8 = bA ? 0xFF : 0;
// TMU Output values packing (useless as its only all 0 or 1, but for brain model..)
const uint16_t u16Sent_W1 = (u8TMU_g8<<8) + u8TMU_b8;
const uint16_t u16Sent_W2 = (u8TMU_a8<<8) + u8TMU_r8;
// FBI receiving + Error aplication
const uint16_t u16received_W1 = u16Sent_W1 & ~u16BUSFaultMap;
const uint16_t u16received_W2 = u16Sent_W2 & ~u16BUSFaultMap;
// FBI received colours unpacking (!!! to be checked)
uint16_t u16FBI_Input_r8 = (u16received_W2 & 0xFF);
uint16_t u16FBI_Input_g8 = (u16received_W1 >> 8);
uint16_t u16FBI_Input_b8 = (u16received_W1 & 0xFF);
uint16_t u16FBI_Input_a8 = (u16received_W2 >> 8);
// FBI LFB current colours unpacking
const uint16_t u16FBI_Current_r8 = ((u16CurrentPixel>>11) & 0x1F) << 3;
const uint16_t u16FBI_Current_g8 = ((u16CurrentPixel>>5) & 0x3F) << 2;
const uint16_t u16FBI_Current_b8 = ((u16CurrentPixel>>0) & 0x1F) << 3;
const uint16_t u16FBI_Current_a8 = u8CurrentAPixel;
// Mixing current and new colours
//u16FBI_Input_r8 *= u16FBI_Input_a8;
// This does not work
//u16FBI_Input_r8 += u16FBI_Current_r8 * (255-u16FBI_Input_a8);
//u16FBI_Input_r8 >>=8;
//u16FBI_Input_g8 *= u16FBI_Input_a8;
//u16FBI_Input_g8 += u16FBI_Current_g8 * (255-u16FBI_Input_a8);
//u16FBI_Input_g8 >>=8;
//u16FBI_Input_b8 *= u16FBI_Input_a8;
//u16FBI_Input_b8 += u16FBI_Current_b8 * (255-u16FBI_Input_a8);
//u16FBI_Input_b8 >>=8;
//u16FBI_Input_a8 *= u16FBI_Input_a8;
//u16FBI_Input_a8 += u16FBI_Current_a8*(255-u16FBI_Input_a8);
//u16FBI_Input_a8 >>=8;
const uint16_t u16LFB_R5G6B5_r5 = (u16FBI_Input_r8>>3) & 0x1F;
const uint16_t u16LFB_R5G6B5_g6 = (u16FBI_Input_g8>>2) & 0x3F;
const uint16_t u16LFB_R5G6B5_b5 = (u16FBI_Input_b8>>3) & 0x1F;
const uint16_t u8LFB_R5G6B5_a8 = (u16FBI_Input_a8>>0) & 0xFF;
const uint16_t u16LBF_R5G6B5_Pixel = (u16LFB_R5G6B5_r5 <<11)
+ (u16LFB_R5G6B5_g6<<5)
+ (u16LFB_R5G6B5_b5);
const uint8_t u8LBF_R5G6B5_APixel = u8LFB_R5G6B5_a8;
*pu16RenderedPixel = u16LBF_R5G6B5_Pixel;
*pu8RenderedAPixel = u8LBF_R5G6B5_APixel;
return 0;
}
*/
/* In conjonction to the previous function, the idea here was to precompute all
* the possible fault pattern and use them as a comparison to find the actual
* one using real measurement. It is now deprecated in favor of the pattern
* distance matching.
*
void simuFault( uint8_t bRGB,
uint8_t bA )
{
uint16_t u16RenderedPixel;
uint8_t u8RenderedAPixel;
uint32_t u16PreviousPixel = 0;
uint16_t u8PreviousAPixel = 0;
//for(char bitPos1 = -1; bitPos1 <= 15 ; ++bitPos1)
//for(u8PreviousAPixel= 0; u8PreviousAPixel <= 0xFF ; ++u8PreviousAPixel)
{
//for(u16PreviousPixel= 0; u16PreviousPixel <= 0xFFFF ; ++u16PreviousPixel)
{
//u16PreviousPixel += (bitPos1 ==-1) ? 0 : (1u << bitPos1);
uint16_t Pattern_OK;
uint16_t APattern_OK;
for(char bitPos = -1; bitPos <= 15 ; ++bitPos)
{
const uint16_t u16FaultMap = (bitPos ==-1) ? 0 : (1u << bitPos);
simuFault_step( bRGB,
bA,
u16PreviousPixel,
u8PreviousAPixel,
&u16RenderedPixel,
&u8RenderedAPixel,
u16FaultMap);
//if(u16FaultMap==0)
//{
// Pattern_OK = u16RenderedPixel;
// APattern_OK = u8RenderedAPixel;
//}
//else if(u16FaultMap==0x100)
//{
// if((u16RenderedPixel!=Pattern_OK) && (u8RenderedAPixel!=APattern_OK))
// {
// printf("bRGB %d\n",bRGB);
// printf("bA, %d\n",bA);
// printf("u16PreviousPixel %04X\n",u16PreviousPixel);
// printf("u8PreviousAPixel %02X\n",u8PreviousAPixel);
// printf("SIMU: %04X\n",u16FaultMap);
// printf("\t0x%04X | 0x%02X %c\n",
// u16RenderedPixel,
// u8RenderedAPixel,
// (u16RenderedPixel==0xFFFF)
// && (u8RenderedAPixel==0xFF) ? '!' : ' ');
// }
//}
printf("bRGB %d\n",bRGB);
printf("bA, %d\n",bA);
printf("u16PreviousPixel %04X\n",u16PreviousPixel);
printf("u8PreviousAPixel %02X\n",u8PreviousAPixel);
printf("SIMU: %04X\n",u16FaultMap);
printf("\t0x%04X | 0x%02X %c\n",
u16RenderedPixel,
u8RenderedAPixel,
(u16RenderedPixel==0xFFFF)
&& (u8RenderedAPixel==0xFF) ? '!' : ' ');
}
}
}
}
*/

56
Test_Data_NoMem.h Normal file
View File

@@ -0,0 +1,56 @@
/* 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/>.
*/
#ifndef _DEF_TEST_DATA_NOMEM_H_
#define _DEF_TEST_DATA_NOMEM_H_
#include <stdint.h>
#include "cvg.h"
#include "FaultSources.h"
typedef union _def_uTestPatternData{
struct {
uint16_t u16Pix[4][4]; //value in LFB after Blend
uint8_t u8APix[4][4]; //value in LFB after Blend
}access;
uint32_t raw[8+4];
}def_uTestPatternData;
typedef struct _def_sFaultSourceLineMap
{
def_eFaultSource eTMUFaultSource_FBI;
def_eFaultSource eTMUFaultSource_TMU0_RES;
def_eFaultSource eTMUFaultSource_TMU0_FBI;
def_eFaultSource eTMUFaultSource_TMU0_TMU1;
def_eFaultSource eTMUFaultSource_TMU1;
}def_sFaultSourceLineMap;
typedef struct _def_sTestPattern
{
uint8_t bReferenceSet;
uint8_t u8FaultLineIdx;
def_uTestPatternData data; // expected value in LFB after Blend
}def_sTestPattern;
unsigned long long
test_TMU_datalines_NoMem( sst1DeviceInfoStruct * const devInfo,
FxU32 * const sst,
SstRegs * const sstregs,
const unsigned char ucNumTMU,
def_sFaultSourceScoreRec* const pFaultSrcCtx);
#endif //_DEF_TEST_DATA_NOMEM_H_

View File

@@ -0,0 +1,761 @@
/* 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/>.
*/
#include "Test_Data_NoMem.h"
const def_sFaultSourceLineMap ar_sFaultSourceLineMap[] =
{
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_0,
.eTMUFaultSource_TMU0_RES = RA10_1,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_0,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_0,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_0,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_1,
.eTMUFaultSource_TMU0_RES = RA10_2,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_1,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_1,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_1,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_2,
.eTMUFaultSource_TMU0_RES = RA10_3,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_2,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_2,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_2,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_3,
.eTMUFaultSource_TMU0_RES = RA10_4,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_3,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_3,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_3,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_4,
.eTMUFaultSource_TMU0_RES = RA11_1,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_4,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_4,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_4,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_5,
.eTMUFaultSource_TMU0_RES = RA11_2,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_5,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_5,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_5,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_6,
.eTMUFaultSource_TMU0_RES = RA11_3,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_6,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_6,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_6,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_7,
.eTMUFaultSource_TMU0_RES = RA11_4,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_7,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_7,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_7,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_8,
.eTMUFaultSource_TMU0_RES = RA12_1,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_8,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_8,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_8,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_9,
.eTMUFaultSource_TMU0_RES = RA12_2,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_9,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_9,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_9,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_10,
.eTMUFaultSource_TMU0_RES = RA12_3,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_10,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_10,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_10,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_11,
.eTMUFaultSource_TMU0_RES = RA12_4,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_11,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_11,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_11,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_12,
.eTMUFaultSource_TMU0_RES = RA13_1,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_12,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_12,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_12,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_13,
.eTMUFaultSource_TMU0_RES = RA13_2,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_13,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_13,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_13,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_14,
.eTMUFaultSource_TMU0_RES = RA13_3,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_14,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_14,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_14,
},
{
.eTMUFaultSource_FBI = U3_FBI_TF_DATA_15,
.eTMUFaultSource_TMU0_RES = RA13_4,
.eTMUFaultSource_TMU0_FBI = U9_TMU0_TF_DATA_15,
.eTMUFaultSource_TMU0_TMU1 = U9_TMU0_FT_DATA_15,
.eTMUFaultSource_TMU1 = U8_TMU1_TF_DATA_15,
},
};
const def_sTestPattern ar_sExpectedPattern_Test3[] =
{
{
.bReferenceSet = true, // Nominal set
.u8FaultLineIdx = 0,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 0,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 1,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 2,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 3,
.data = {
.access = {
.u16Pix = { {0xF7FE,0xF7FF,0xFFFF,0xFFFF},
{0xF7FE,0xF7FE,0xF7FF,0xFFFF},
{0xF7FE,0xF7FE,0xF7FE,0xF7FE},
{0xF7FE,0xF7FE,0xF7FE,0xF7FE}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 4,
.data = {
.access = {
.u16Pix = { {0xEFFD,0xEFFF,0xFFFF,0xFFFF},
{0xEFFD,0xEFFD,0xEFFF,0xFFFF},
{0xEFFD,0xEFFD,0xEFFD,0xEFFD},
{0xEFFD,0xEFFD,0xEFFD,0xEFFD}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 5,
.data = {
.access = {
.u16Pix = { {0xDFFB,0xDFFF,0xFFFF,0xFFFF},
{0xDFFB,0xDFFB,0xDFFF,0xFFFF},
{0xDFFB,0xDFFB,0xDFFB,0xDFFB},
{0xDFFB,0xDFFB,0xDFFB,0xDFFB}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 6,
.data = {
.access = {
.u16Pix = { {0xBFF7,0xBFFF,0xFFFF,0xFFFF},
{0xBFF7,0xBFF7,0xBFFF,0xFFFF},
{0xBFF7,0xBFF7,0xBFF7,0xBFF7},
{0xBFF7,0xBFF7,0xBFF7,0xBFF7}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 7,
.data = {
.access = {
.u16Pix = { {0x7FEF,0x7FFF,0xFFFF,0xFFFF},
{0x7FEF,0x7FEF,0x7FFF,0xFFFF},
{0x7FEF,0x7FEF,0x7FEF,0x7FEF},
{0x7FEF,0x7FEF,0x7FEF,0x7FEF}
},
.u8APix = { {0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF},
{0xFF,0xFF,0xFF,0xFF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 8,
.data = {
.access = {
.u16Pix = { {0x0000,0x0000,0xFFFF,0xFFFF},
{0x0000,0x0000,0x0000,0xFFFF},
{0x0000,0x0000,0x0000,0x0000},
{0x0000,0x0000,0x0000,0x0000}
},
.u8APix = { {0x00,0x00,0xFF,0xFF},
{0x00,0x00,0x00,0xFF},
{0x00,0x00,0x00,0x00},
{0x00,0x00,0x00,0x00}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 9,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF},
{0xFFFF,0xFFFF,0xFFFF,0xFFFF}
},
.u8APix = { {0xFD,0xFD,0xFF,0xFF},
{0xFD,0xFD,0xFD,0xFF},
{0xFD,0xFD,0xFD,0xFD},
{0xFD,0xFD,0xFD,0xFD}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 10,
.data = {
.access = {
.u16Pix = { {0xFFDF,0xFFFF,0xFFFF,0xFFFF},
{0xFFDF,0xFFDF,0xFFFF,0xFFFF},
{0xFFDF,0xFFDF,0xFFDF,0xFFFF},
{0xFFDF,0xFFDF,0xFFDF,0xFFDF}
},
.u8APix = { {0xFB,0xFB,0xFB,0xFB},
{0xFB,0xFB,0xFB,0xFB},
{0xFB,0xFB,0xFB,0xFB},
{0xFB,0xFB,0xFB,0xFB}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 11,
.data = {
.access = {
.u16Pix = { {0xFFBF,0xFFFF,0xFFFF,0xFFFF},
{0xFFBF,0xFFBF,0xFFFF,0xFFFF},
{0xFFBF,0xFFBF,0xFFBF,0xFFBF},
{0xFFBF,0xFFBF,0xFFBF,0xFFBF}
},
.u8APix = { {0xF7,0xF7,0xFF,0xFF},
{0xF7,0xF7,0xF7,0xFF},
{0xF7,0xF7,0xF7,0xF7},
{0xF7,0xF7,0xF7,0xF7}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 12,
.data = {
.access = {
.u16Pix = { {0xFF7F,0xFFFF,0xFFFF,0xFFFF},
{0xFF7F,0xFF7F,0xFFFF,0xFFFF},
{0xFF7F,0xFF7F,0xFF7F,0xFF7F},
{0xFF7F,0xFF7F,0xFF7F,0xFF7F}
},
.u8APix = { {0xEF,0xEF,0xFF,0xFF},
{0xEF,0xEF,0xEF,0xFF},
{0xEF,0xEF,0xEF,0xEF},
{0xEF,0xEF,0xEF,0xEF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 13,
.data = {
.access = {
.u16Pix = { {0xFEFF,0xFFFF,0xFFFF,0xFFFF},
{0xFEFF,0xFEFF,0xFFFF,0xFFFF},
{0xFEFF,0xFEFF,0xFEFF,0xFEFF},
{0xFEFF,0xFEFF,0xFEFF,0xFEFF}
},
.u8APix = { {0xDF,0xDF,0xFF,0xFF},
{0xDF,0xDF,0xDF,0xFF},
{0xDF,0xDF,0xDF,0xDF},
{0xDF,0xDF,0xDF,0xDF}
},
}
}
},
{ //OK
.bReferenceSet = false,
.u8FaultLineIdx = 14,
.data = {
.access = {
.u16Pix = { {0xFDFF,0xFFFF,0xFFFF,0xFFFF},
{0xFDFF,0xFDFF,0xFFFF,0xFFFF},
{0xFDFF,0xFDFF,0xFDFF,0xFDFF},
{0xFDFF,0xFDFF,0xFDFF,0xFDFF}
},
.u8APix = { {0xBF,0xBF,0xFF,0xFF},
{0xBF,0xBF,0xBF,0xFF},
{0xBF,0xBF,0xBF,0xBF},
{0xBF,0xBF,0xBF,0xBF}
},
}
}
},
{//OK
.bReferenceSet = false,
.u8FaultLineIdx = 15,
.data = {
.access = {
.u16Pix = { {0xFBFF,0xFFFF,0xFFFF,0xFFFF},
{0xFBFF,0xFBFF,0xFFFF,0xFFFF},
{0xFBFF,0xFBFF,0xFBFF,0xFBFF},
{0xFBFF,0xFBFF,0xFBFF,0xFBFF}
},
.u8APix = { {0x7F,0x7F,0xFF,0xFF},
{0x7F,0x7F,0x7F,0xFF},
{0x7F,0x7F,0x7F,0x7F},
{0x7F,0x7F,0x7F,0x7F}
},
}
}
},
};
const unsigned int uNbPattern_Test3 =
sizeof(ar_sExpectedPattern_Test3)/sizeof(def_sTestPattern);
const def_sTestPattern ar_sExpectedPattern_Test3_Dither[] =
{
{
.bReferenceSet = true, // Nominal set
.u8FaultLineIdx = 0,
.data = {
.access = {
.u16Pix = { {0xFFFF,0xFFFF,0xFFFF,0x0040},
{0xFFFF,0xFFFF,0x0040,0x0040},
{0xFFFF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 0,
.data = {
.access = {
.u16Pix = { {0xF7FE,0xFFFF,0xFFFF,0x0040},
{0xFFFF,0xFFFF,0x0040,0x0040},
{0xFFFF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 1,
.data = {
.access = {
.u16Pix = { {0xF7FE,0xFFFF,0xFFFF,0x0040},
{0xFFFF,0xFFFF,0x0040,0x0040},
{0xF7FE,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 2,
.data = {
.access = {
.u16Pix = { {0xF7FE,0xFFFF,0xFFFF,0x0040},
{0xFFFF,0xF7FE,0x0040,0x0040},
{0xF7FE,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 3,
.data = {
.access = {
.u16Pix = { {0xF7FE,0xF7FF,0xFFFF,0x0040},
{0xF7FE,0xF7FE,0x0040,0x0040},
{0xF7FE,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 4,
.data = {
.access = {
.u16Pix = { {0xEFFD,0xEFFF,0xFFFF,0x0040},
{0xEFFD,0xEFFD,0x0040,0x0040},
{0xEFFD,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 5,
.data = {
.access = {
.u16Pix = { {0xDFFB,0xDFFF,0xFFFF,0x0040},
{0xDFFB,0xDFFB,0x0040,0x0040},
{0xDFFB,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 6,
.data = {
.access = {
.u16Pix = { {0xBFF7,0xBFFF,0xFFFF,0x0040},
{0xC7F8,0xBFF7,0x0040,0x0040},
{0xBFF7,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 7,
.data = {
.access = {
.u16Pix = { {0x7FEF,0x7FEF,0xFFFF,0x0040},
{0x87F0,0x7FEF,0x0040,0x0040},
{0x7FEF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFF,0xFF,0xFF,0x0F},
{0xFF,0xFF,0x0F,0x0F},
{0xFF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 8,
.data = {
.access = {
.u16Pix = { {0x0040,0x0040,0xFFFF,0x0040},
{0x0040,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0x0F,0x0F,0xFF,0x0F},
{0x0F,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 9,
.data = {
.access = {
.u16Pix = { {0xFFDF,0xFFFF,0xFFFF,0x0040},
{0xFFFF,0xFFDF,0x0040,0x0040},
{0xFFDF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFD,0xFD,0xFF,0x0F},
{0xFD,0xFD,0x0F,0x0F},
{0xFD,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 10,
.data = {
.access = {
.u16Pix = { {0xFFDF,0xFFFF,0xFFFF,0x0040},
{0xFFDF,0xFFDF,0x0040,0x0040},
{0xFFDF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xFB,0xFB,0xFF,0x0F},
{0xFB,0xFB,0x0F,0x0F},
{0xFB,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 11,
.data = {
.access = {
.u16Pix = { {0xFFBF,0xFFFF,0xFFFF,0x0040},
{0xFFBF,0xFFBF,0x0040,0x0040},
{0xFFBF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xF7,0xF7,0xFF,0x0F},
{0xF7,0xF7,0x0F,0x0F},
{0xF7,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 12,
.data = {
.access = {
.u16Pix = { {0xFF7F,0xFFFF,0xFFFF,0x0040},
{0xFF7F,0xFF7F,0x0040,0x0040},
{0xFF7F,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xEF,0xEF,0xFF,0x0F},
{0xEF,0xEF,0x0F,0x0F},
{0xEF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 13,
.data = {
.access = {
.u16Pix = { {0xFEFF,0xFFFF,0xFFFF,0x0040},
{0xFEFF,0xFEFF,0x0040,0x0040},
{0xFEFF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xDF,0xDF,0xFF,0x0F},
{0xDF,0xDF,0x0F,0x0F},
{0xDF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{ //OK !
.bReferenceSet = false,
.u8FaultLineIdx = 14,
.data = {
.access = {
.u16Pix = { {0xFDFF,0xFFFF,0xFFFF,0x0040},
{0xFDFF,0xFDFF,0x0040,0x0040},
{0xFDFF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0xBF,0xBF,0xFF,0x0F},
{0xBF,0xBF,0x0F,0x0F},
{0xBF,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
{//OK
.bReferenceSet = false,
.u8FaultLineIdx = 15,
.data = {
.access = {
.u16Pix = { {0xFBFF,0xFFFF,0xFFFF,0x0040},
{0xFC1F,0xFBFF,0x0040,0x0040},
{0xFBFF,0x0040,0x0040,0x0040},
{0x0040,0x0040,0x0040,0x0040}
},
.u8APix = { {0x7F,0xFF,0xFF,0x0F},
{0x7F,0x7F,0x0F,0x0F},
{0x7F,0x0F,0x0F,0x0F},
{0x0F,0x0F,0x0F,0x0F}
},
}
}
},
};
const unsigned int uNbPattern_Test3_Dither =
sizeof(ar_sExpectedPattern_Test3_Dither)/sizeof(def_sTestPattern);

116
Utils.c
View File

@@ -18,98 +18,112 @@
#define _BSD_SOURCE 1 #define _BSD_SOURCE 1
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <string.h>
#include "Utils.h" #include "Utils.h"
inline void void
printbin32( const unsigned long ulVal, sprintbin32( char * szBuff,
const unsigned char bGroupByBytes) const uint32_t ulVal,
const unsigned char bGroupByBytes)
{ {
for(unsigned long idxBit = 1<<31;idxBit>0;idxBit>>=1) for(uint32_t idxBit = 1u<<31 ; idxBit > 0 ; idxBit >>= 1)
{ {
if(bGroupByBytes) if(bGroupByBytes)
switch(idxBit) switch(idxBit)
{ {
case 1<<23: case 1u << 23:
case 1<<15: case 1u << 15:
case 1<<7: case 1u << 7:
putchar(' '); *(szBuff++) = ' ';
} }
putchar(ulVal & idxBit ? '1' : '0'); *(szBuff++) = ulVal & idxBit ? '1' : '0';
} }
*szBuff = '\0';
}
void
printbin32( const uint32_t ulVal,
const unsigned char bGroupByBytes)
{
char szBuff[32 + 3 + 1 + 1];
sprintbin32(szBuff,ulVal,bGroupByBytes);
strcat(szBuff,"\n");
puts(szBuff);
} }
inline unsigned char void
count_bit32(const unsigned long ulVal) sprintbin32Info(char * szBuff,
{ const uint32_t ulVal,
unsigned char cpt = 0;
for(unsigned long idxBit = 1<<31;idxBit>0;idxBit>>=1)
if(ulVal & idxBit)
cpt++;
return cpt;
}
inline unsigned char
count_bit8(const unsigned char ulVal)
{
unsigned char cpt = 0;
for(unsigned char idxBit = 1<<7;idxBit>0;idxBit>>=1)
if(ulVal & idxBit)
cpt++;
return cpt;
}
inline void
printbin32Info( const unsigned long ulVal,
const unsigned short uhb, const unsigned short uhb,
const unsigned short ulb) const unsigned short ulb)
{ {
printbin32(ulVal,1); sprintbin32(szBuff, ulVal, 1);
putchar('\n'); szBuff += 32 + 3;
printf("%02d....%02d %02d....%02d %02d....%02d %02d....%02d\n",
*(szBuff++) = '\n';
*szBuff = '\0';
sprintf(szBuff,
"%02d....%02d %02d....%02d %02d....%02d %02d....%02d",
uhb, uhb,
3*(uhb+ulb+1)/4, 3*((uhb+ulb+1)/4)-1, 3 * (uhb + ulb + 1) / 4, 3 * ( (uhb + ulb + 1) / 4) - 1,
(uhb+ulb+1)/2, ((uhb+ulb+1)/2)-1, (uhb + ulb + 1) / 2, ( (uhb + ulb + 1) / 2) - 1,
(uhb+ulb+1)/4, ((uhb+ulb+1)/4)-1, (uhb + ulb + 1) / 4, ( (uhb + ulb + 1) / 4) - 1,
ulb); ulb);
} }
unsigned long get_notnull_random() void
printbin32Info( const uint32_t ulVal,
const unsigned short uhb,
const unsigned short ulb)
{ {
unsigned long val; char szBuff[2 * (32 + 3) + 2 + 1];
sprintbin32Info(szBuff, ulVal, uhb, ulb);
strcat(szBuff,"\n");
puts(szBuff);
}
uint32_t
get_notnull_random()
{
uint32_t val;
do do
val = random()<<1 ^ random(); val = ((uint32_t)random() << 1) ^ (uint32_t)random();
while(!val); while(!val);
return val; return val;
} }
unsigned long get_notnull_random_balanced() uint32_t
get_notnull_random_balanced()
{ {
unsigned long val; uint32_t val;
do do
val = random()<<1 ^ random(); val = ((uint32_t)random() << 1) ^ (uint32_t)random();
while(count_bit32(val) != 16); while(count_bit32(val) != 16);
return val; return val;
} }
unsigned char get_notnull8_random_balanced() uint8_t
get_notnull8_random_balanced()
{ {
unsigned char val; uint8_t val;
static unsigned char prev = 0; static uint8_t prev = 0;
do do
val = random()<<1 ^ random(); val = (uint8_t)random();
while((count_bit8(val) != 4) || (val == prev)); while((count_bit8(val) != 4) || (val == prev));
prev = val; prev = val;
return val; return val;
} }
unsigned long get_notnull_random_balanced_mByte() uint32_t
get_notnull_random_balanced_mByte()
{ {
unsigned long val; uint32_t val;
static unsigned long prev = 0; static uint32_t prev = 0;
do do
val = (get_notnull8_random_balanced() << 24) val = (get_notnull8_random_balanced() << 24)
| (get_notnull8_random_balanced() << 16) | (get_notnull8_random_balanced() << 16)
| (get_notnull8_random_balanced() << 8) | (get_notnull8_random_balanced() << 8)
| (get_notnull8_random_balanced() << 0); | (get_notnull8_random_balanced() << 0);

142
Utils.h
View File

@@ -18,13 +18,139 @@
#ifndef _DEF_UTILS_H_ #ifndef _DEF_UTILS_H_
#define _DEF_UTILS_H_ #define _DEF_UTILS_H_
inline void printbin32(const unsigned long ulVal,const unsigned char bGroupByBytes); #include <stdint.h>
inline unsigned char count_bit32(const unsigned long ulVal);
inline unsigned char count_bit8(const unsigned char ulVal); #include "V2MemTest.h"
inline void printbin32Info(const unsigned long ulVal, const unsigned short uhb, const unsigned short ulb);
unsigned long get_notnull_random(); #define ErrorCheck() \
unsigned long get_notnull_random_balanced(); do{ \
unsigned char get_notnull8_random_balanced(); if(Status < 0) \
unsigned long get_notnull_random_balanced_mByte(); { \
if(Status <= E_INVALID_ERROR_CODE) \
fprintf(stderr,"Error detected at %s:%d\t%s", \
__FILE__,__LINE__,szErrorMsg[DEF_UNKNOWN_ERROR_IDX]); \
else \
fprintf(stderr,"Error detected at %s:%d\t%s", \
__FILE__,__LINE__, \
szErrorMsg[DEF_GET_ERROR_IDX(Status)]); \
return Status; \
} \
}while(0)
#define ErrorCheck_gotoCleanUp() \
do{ \
if(Status < 0) \
{ \
if(Status <= E_INVALID_ERROR_CODE) \
fprintf(stderr,"Error detected at %s:%d\t%s", \
__FILE__,__LINE__,szErrorMsg[DEF_UNKNOWN_ERROR_IDX]); \
else \
fprintf(stderr,"Error detected at %s:%d\t%s", \
__FILE__,__LINE__, \
szErrorMsg[DEF_GET_ERROR_IDX(Status)]); \
goto CleanUp; \
} \
}while(0)
static inline unsigned char
count_bit32(const uint32_t ulVal)
{
/*
unsigned char cpt = 0;
for(uint32_t idxBit = 0x80000000u; idxBit != 0; idxBit >>= 1)
if(ulVal & idxBit)
cpt++;
return cpt;
*/
return __builtin_popcount(ulVal);
}
static inline unsigned char
count_bit8(const uint8_t ulVal)
{
/*
unsigned char cpt = 0;
for(uint8_t idxBit = 0x80u; idxBit != 0; idxBit >>= 1)
if(ulVal & idxBit)
cpt++;
return cpt;
*/
return __builtin_popcount(ulVal);
}
void
sprintbin32( char * const szBuff,
const uint32_t ulVal,
const unsigned char bGroupByBytes);
void
printbin32( const uint32_t ulVal,
const unsigned char bGroupByBytes);
void
sprintbin32Info(char * const szBuff,
const uint32_t ulVal,
const unsigned short uhb,
const unsigned short ulb);
void
printbin32Info( const uint32_t ulVal,
const unsigned short uhb,
const unsigned short ulb);
uint32_t
get_notnull_random();
uint32_t
get_notnull_random_balanced();
uint8_t
get_notnull8_random_balanced();
uint32_t
get_notnull_random_balanced_mByte();
static inline void
mmio_fastread32(uint32_t * dst,
volatile const uint32_t * src,
size_t words)
{
while(words>=4) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
words-=4;
src+=4;
dst+=4;
}
while(words--) {
*dst++ = *src++;
}
}
static inline void
mmio_fastwrite32( volatile uint32_t * dst,
const uint32_t * src,
size_t words)
{
while(words>=4) {
dst[0] = src[0];
dst[1] = src[1];
dst[2] = src[2];
dst[3] = src[3];
words-=4;
src+=4;
dst+=4;
}
while(words--) {
*dst++ = *src++;
}
}
static inline double dComputeDistance32(const uint32_t u32A,const uint32_t u32B)
{
return (double)__builtin_popcount( u32A ^ u32B);
}
#endif //_DEF_UTILS_H_ #endif //_DEF_UTILS_H_

View File

@@ -1,52 +1,110 @@
/* 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/>.
*/
#ifndef _DEF_V2MEMTEST_H_ #ifndef _DEF_V2MEMTEST_H_
#define _DEF_V2MEMTEST_H_ #define _DEF_V2MEMTEST_H_
#define V2MEMTEST__VERSION__MAJOR 0 #define V2MEMTEST__VERSION__MAJOR 0
#define V2MEMTEST__VERSION__MINOR 1 #define V2MEMTEST__VERSION__MINOR 5
#define V2MEMTEST__VERSION__PATCH 0 #define V2MEMTEST__VERSION__PATCH 0
typedef enum _def_eTestType { #include <stdbool.h>
E_TESTTYPE__ADDRESS, #include <stdlib.h>
E_TESTTYPE__DATA__BITMOVE,
E_TESTTYPE__DATA__RANDOM,
E_TESTTYPE__DATA__HUGE,
E_TESTTYPE__DATA__ALL,
}def_eTestType;
typedef enum _def_eTMUTarget {
E_TMUTARGET__0,
E_TMUTARGET__1,
E_TMUTARGET__BOTH,
}def_eTMUTarget;
typedef enum _def_eTMURamLimit { typedef enum _def_eTMURamLimit {
E_TMUTARGET__1MB, E_TMU_RAMSIZE__1MB = 1,
E_TMUTARGET__2MB, E_TMU_RAMSIZE__2MB = 2,
E_TMUTARGET__3MB, E_TMU_RAMSIZE__3MB = 3,
E_TMUTARGET__4MB, E_TMU_RAMSIZE__4MB = 4,
E_TMU_RAMSIZE__AUTO = -1,
}def_eTMURamLimit; }def_eTMURamLimit;
#define MAX_TMU 2
typedef enum _def_eLogLevel { typedef enum _def_eLogLevel {
E_LOGLEVEL__ERROR, E_LOGLEVEL__ERROR = 0,
E_LOGLEVEL__WARNING, E_LOGLEVEL__WARNING = 1,
E_LOGLEVEL__INFO, E_LOGLEVEL__INFO = 2,
E_LOGLEVEL__DEBUG, E_LOGLEVEL__DEBUG = 3,
E_LOGLEVEL__TRACE, E_LOGLEVEL__TRACE = 4,
}def_eLogLevel; }def_eLogLevel;
#define DEF_BASE_ERRROR -1000
#define DEF_NO_ERROR_IDX 0
#define DEF_UNKNOWN_ERROR_IDX 1
#define DEF_GET_ERROR_IDX(CODE) -(DEF_BASE_ERRROR-CODE)
typedef enum _def_eErrorCode {
E_ERROR__NO_ERROR = 0,
E_ERROR__UNKNOWN_ERROR = -1,
E_ERROR__UNKNOWN_ARGUMENT = DEF_BASE_ERRROR,
E_ERROR__BAD_ARGUMENT_VALUE,
E_ERROR__SST1_INIT,
E_ERROR__SST1_GET_INFO,
E_ERROR__NOT_ENOUGH_FBI_RAM,
E_ERROR__TMU_NOT_FOUND,
E_ERROR__NO_TMU_SELECTED,
E_ERROR__WRONG_TMU_SELECTED,
E_INVALID_ERROR_CODE,
}def_eErrorCode;
extern const char* szErrorMsg[];
typedef struct _def_sOptions typedef struct _def_sOptions
{ {
def_eLogLevel ucLogLevel;
unsigned char bLogStdOut;
char szLogFileName[2048];
char szTSVFile[2048];
unsigned short usNbLoops;
def_eTestType eTestType;
def_eTMUTarget eTMUTarget;
def_eLogLevel eLogLevel; def_eLogLevel eLogLevel;
def_eTMURamLimit eTMURamLimit; int bSilent;
long lNumLoops;
int bTestTMU0;
def_eTMURamLimit eTMU0RamLimit;
int bTestTMU1;
def_eTMURamLimit eTMU1RamLimit;
int bTestTMUControl;
int bTestTMUAddress;
int bTestTMUData;
int bTestTMUDataHuge;
int bTestNoMem;
int bQuick;
int bForce;
int bContinue;
} def_sOptions; } def_sOptions;
extern def_sOptions sOptions; extern def_sOptions sOptions;
#endif //_DEF_V2MEMTEST_H_
#define logE(...) _log(E_LOGLEVEL__ERROR, __VA_ARGS__)
#define logW(...) _log(E_LOGLEVEL__WARNING, __VA_ARGS__)
#define logI(...) _log(E_LOGLEVEL__INFO, __VA_ARGS__)
#define logD(...) _log(E_LOGLEVEL__DEBUG, __VA_ARGS__)
#define logT(...) _log(E_LOGLEVEL__TRACE, __VA_ARGS__)
#define _log(_E_LOGLEVEL,...) \
do { \
if( (sOptions.eLogLevel >= _E_LOGLEVEL) \
&& !sOptions.bSilent) {\
if(_E_LOGLEVEL==E_LOGLEVEL__ERROR) \
fprintf(stderr,__VA_ARGS__); \
else \
printf(__VA_ARGS__); \
} \
} \
while(0)
#endif //_DEF_V2MEMTEST_H_

850
main.c
View File

@@ -21,6 +21,8 @@
#include <stdint.h> #include <stdint.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <unistd.h>
#include <getopt.h>
#include "cvg.h" #include "cvg.h"
#include <glide.h> #include <glide.h>
@@ -32,12 +34,29 @@
#include "Utils.h" #include "Utils.h"
#include "Draw.h" #include "Draw.h"
#include "Test_Common.h"
#include "Test_Control.h"
#include "Test_Address.h" #include "Test_Address.h"
#include "Test_Data.h" #include "Test_Data.h"
#include "Test_Data_Huge.h" #include "Test_Data_Huge.h"
#include "Test_Data_NoMem.h"
const char* szErrorMsg[] =
{
"no error.", // E_ERROR__NO_ERROR
"unknown error.", // E_ERROR__UNKNOWN_ERROR
"unknown argument found in command line.", // E_ERROR__UNKNOWN_ARGUMENT
"wrong argument value.", // E_ERROR__BAD_ARGUMENT_VALUE
"error initializing Voodoo² board.", // E_ERROR__SST1_INIT,
"error getting Voodoo² board informations.", // E_ERROR__SST1_GET_INFO,
"not enough FBI RAM to process TMU tests.", // E_ERROR__NOT_ENOUGH_FBI_RAM,
"TMU not found.", // E_ERROR__TMU_NOT_FOUND,
"no TMU selected.", // E_ERROR__NO_TMU_SELECTED,
"wrong number of TMU selected.", // E_ERROR__WRONG_TMU_SELECTED
};
const char szTitle[] = const char szTitle[] =
"V2MemTest-%d.%d.%d - A CLI Tool to test & fix Voodoo² TMU System\n" "v2-tmu-memtester-%d.%d.%d - A CLI Tool to test & fix Voodoo² TMU System\n"
"Copyright (C) 2026 ChaCha\n"; "Copyright (C) 2026 ChaCha\n";
const char szLicence[] = const char szLicence[] =
@@ -47,175 +66,694 @@ const char szLicence[] =
"This program is distributed in the hope that it will be useful, but WITHOUT ANY\n" "This program is distributed in the hope that it will be useful, but WITHOUT ANY\n"
"WARRANTY !\n"; "WARRANTY !\n";
const char szHelp[] = const char szKool[] =
"Usage ./v2memtest <options>\n" "Oh nooo.... Have fun fixing your Holy Voodoo² !\n"
"\n" "Note: Do not forget to sleep though :) !\n";
"options:\n"
"\t-h :\tthis output\n"
"\n"
"\t-v <level> :\tset log level to the specified value.\n"
"\t\t 0: ERR, 1: INFO, 2: WARN, 3: DEBUG, 4: TRACE\n"
"\n"
"\t-fl <file> :\tset a log file path & name.\n"
"\n"
"\t-fd <file> :\tset a failure report path & base name.\n"
"\t\t Note that the test name will be appended to the file name.\n"
"\t\t eg: file name is 'foo' running 'data-bitmove' :\n"
"\t\t foo_data-bitmove.tsv\n"
"\n"
"\t :\t\n"
"\n"
"\t :\t\n"
"\n"
"\n"
"( -h | -v <level> | -fl <file> | -fd <file> |"; const char szKool2[] =
"Did it just worked ?!\n";
const char szHelp[] =
"Usage: ./v2-tmu-memtester [options]\n"
"\n"
"General options:\n"
" -h, --help Show this help and exit.\n"
" --version Print version (MAJOR.MINOR.PATCH) and exit.\n"
" -n, --num <N> Number of loops (default: 1).\n"
" -q, --quick Quicker test (no pre-heat).\n"
" -c, --continue Continue testing even when error found.\n"
" -f, --force Force test (not detected TMU / RAM).\n"
" --silent Silent mode (suppress normal output).\n"
"\n"
"Verbosity:\n"
" -v Increase log level by one step (repeatable).\n"
" Levels: 0=ERR, 1=WARN, 2=INFO, 3=DEBUG, 4=TRACE\n"
" Default: 2 (INFO). Example: -v -> DEBUG.\n"
"\n"
"Target selection:\n"
" --tmu0 Enable only tests for TMU0.\n"
" --tmu1 Enable only tests for TMU1.\n"
"\n"
"Test selection [ all if none set ] :\n"
" --no-mem Run no-mem test.\n"
" --control Run control lines tests.\n"
" --address Run address tests.\n"
" --data Run data tests.\n"
" --data-huge Run large/extended data tests.\n"
"\n"
"TMU RAM limit override:\n"
" --tmu0-ram <MB> Force TMU0 RAM size: -1=auto, 1..4=MB.\n"
" --tmu1-ram <MB> Force TMU1 RAM size: -1=auto, 1..4=MB.\n"
"\n"
"Examples:\n"
" ./v2-tmu-memtester --tmu0 --address -v\n"
" ./v2-tmu-memtester --tmu0-ram 2 --tmu1-ram -1 -n 10\n"
" ./v2-tmu-memtester --tmu1 --data-huge\n";
def_sOptions sOptions = { def_sOptions sOptions = {
.ucLogLevel = E_LOGLEVEL__WARNING, .eLogLevel = E_LOGLEVEL__INFO,
.bLogStdOut = 1, .bSilent = false,
.szLogFileName = {0}, .lNumLoops = 1,
.szTSVFile = {0}, .bTestTMU0 = false,
.usNbLoops = 1, .eTMU0RamLimit = E_TMU_RAMSIZE__AUTO,
.bTestTMU1 = false,
.eTMU1RamLimit = E_TMU_RAMSIZE__AUTO,
.bTestTMUAddress = false,
.bTestTMUControl = false,
.bTestTMUData = false,
.bTestTMUDataHuge = false,
.bTestNoMem = false,
.bQuick = false,
.bForce = false,
.bContinue = false,
};
static struct option long_args[] = {
/* {<NAME>, <HAS_ARG>, <FLAG>, <VAL> */
{"help", no_argument, NULL, 'h'},
{"num", required_argument, NULL, 'n'},
{"force", no_argument, NULL, 'f'},
{"continue", no_argument, NULL, 'c'},
{"silent", no_argument, &sOptions.bSilent, true},
{"quick", no_argument, NULL, 'q'},
{"tmu0", no_argument, &sOptions.bTestTMU0, true},
{"tmu1", no_argument, &sOptions.bTestTMU1, true},
{"control", no_argument, &sOptions.bTestTMUControl, true},
{"address", no_argument, &sOptions.bTestTMUAddress, true},
{"data", no_argument, &sOptions.bTestTMUData, true},
{"data-huge", no_argument, &sOptions.bTestTMUDataHuge, true},
{"no-mem", no_argument, &sOptions.bTestNoMem, true},
{"tmu0-ram", required_argument, NULL, 3},
{"tmu1-ram", required_argument, NULL, 1},
{"version", no_argument, NULL, 2},
}; };
int main(int argc, char **argv) static def_sFaultSourceScoreRec
ar_dFaultScores_no_mem[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_control[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_address[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_data[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_data_random[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_data_huge[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec*
ar_dFaultScores_Set[6];
const unsigned int uNb_dFaultScores_Set =
sizeof(ar_dFaultScores_Set)/sizeof(def_sFaultSourceScoreRec*);
static def_sFaultSourceScoreRec
ar_dFaultScores_ALL[NB_FAULT_SOURCE];
static def_sFaultSourceScoreRec
ar_dFaultScores_sorted[NB_FAULT_SOURCE];
#define _DEF_TEST_TIME_PER_MB_S 5
int main(const int argc, char ** const argv)
{ {
int Status = 0;
unsigned long long ullNbErrorAll = 0; unsigned long long ullNbErrorAll = 0;
const FxU32 boardNum = 0; const unsigned char boardNum = 0;
int option_index = 0;
int opt;
bool bQuit = false;
FxU32* sst = NULL;
sst1DeviceInfoStruct devInfo; ar_dFaultScores_Set[0] = ar_dFaultScores_no_mem;
FxU32* sst; ar_dFaultScores_Set[1] = ar_dFaultScores_control;
SstRegs *sstregs; ar_dFaultScores_Set[2] = ar_dFaultScores_address;
ar_dFaultScores_Set[3] = ar_dFaultScores_data;
ar_dFaultScores_Set[4] = ar_dFaultScores_data_random;
ar_dFaultScores_Set[5] = ar_dFaultScores_data_huge;
printf(szTitle, V2MEMTEST__VERSION__MAJOR, while((opt=getopt_long(argc,argv,"chvfqn:",long_args,&option_index)) != -1)
V2MEMTEST__VERSION__MINOR,
V2MEMTEST__VERSION__PATCH);
putchar('\n');
puts(szLicence);
putchar('\n');
srandom(time(NULL));
FaultSource_Reset();
for(int j=0; j<100; j++)
{ {
switch(opt)
if ((sst = sst1InitMapBoard(boardNum)) == NULL)
{ {
fprintf(stderr, "No Voodoo boards found\n"); /* other long options ? */
exit(-1); case 0:
} break;
/* Version */
sst1InitRegisters(sst); case 2:
printf("%d.%d.%d", V2MEMTEST__VERSION__MAJOR,
if (sst1InitGetDeviceInfo(sst, &devInfo) == FXFALSE) V2MEMTEST__VERSION__MINOR,
{ V2MEMTEST__VERSION__PATCH);
fprintf(stderr, "Couldn't get info for Voodoo # %d\n", boardNum); bQuit = true;
exit(-1); break;
} /* TMU0 long options */
/* case 3:
grGlideInit(); /* TMU1 long options */
GrHwConfiguration hwconfig; case 1:
if(!grSstQueryHardware(&hwconfig)) {
{ def_eTMURamLimit newRAMLimit;
fprintf(stderr, "Couldn't get glide info for Voodoo # %d\n", boardNum); switch(strtol(optarg, NULL, 10))
exit(-1); {
} case -1: newRAMLimit = E_TMU_RAMSIZE__AUTO; break;
grSstSelect(boardNum); case 1: newRAMLimit = E_TMU_RAMSIZE__1MB; break;
*/ case 2: newRAMLimit = E_TMU_RAMSIZE__2MB; break;
sstregs = (SstRegs *) sst; case 3: newRAMLimit = E_TMU_RAMSIZE__3MB; break;
case 4: newRAMLimit = E_TMU_RAMSIZE__4MB; break;
printf("FBI Memory: %d MB\n", devInfo.fbiMemSize); default:
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++) Status = E_ERROR__BAD_ARGUMENT_VALUE;
{ ErrorCheck_gotoCleanUp();
printf("TMU %d RAM: %d MB\n", tmu, devInfo.tmuMemSize[tmu]); break;
} }
putchar('\n'); if(opt==3) sOptions.eTMU0RamLimit = newRAMLimit;
else sOptions.eTMU1RamLimit = newRAMLimit;
ISET(sstregs->lfbMode, SST_LFB_RGBALANES_ARGB | SST_LFB_READFRONTBUFFER); }
ISET(sstregs->fbzMode, SST_DRAWBUFFER_FRONT | SST_RGBWRMASK); break;
ISET(sstregs->fbzColorPath, SST_RGBSEL_TREXOUT | SST_CC_PASS | SST_ENTEXTUREMAP);
ISET(sstregs->textureMode, SST_RGB565 | SST_TC_REPLACE | SST_TCA_REPLACE); case '?':
ISET(sstregs->tLOD, 0); puts(szHelp);
Status = E_ERROR__UNKNOWN_ARGUMENT;
//if(devInfo.tmuMemSize[1]==1) continue; ErrorCheck_gotoCleanUp();
//devInfo.numberTmus=1; break;
//devInfo.tmuMemSize[1]==1; case 'q':
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++) sOptions.bQuick = true;
{ break;
printf("Testing Board %d, TMU %d, %dMB \n\n",boardNum,tmu,devInfo.tmuMemSize[tmu]); case 'c':
sOptions.bContinue = true;
puts("# address & control lines test - cumulated"); break;
for(int j=0;j<100;j++) case 'f':
{ sOptions.bForce = true;
const unsigned long long err break;
= RenderTestAddress(&devInfo, case 'h':
sst, puts(szHelp);
sstregs, bQuit = true;
tmu, break;
devInfo.tmuMemSize[tmu]);
ullNbErrorAll += err; case 'n':
putchar( err ? 'E' : '-'); sOptions.lNumLoops = strtol(optarg, NULL, 10);
fflush(stdout); if( sOptions.lNumLoops < 0 )
} {
putchar('\n'); Status = E_ERROR__BAD_ARGUMENT_VALUE;
ErrorCheck_gotoCleanUp();
puts("# data test - single bit move"); }
for(int j=0;j<100;j++) break;
{
const unsigned long long err case 'v':
= test_TMU_datalines(&devInfo, if(sOptions.eLogLevel < E_LOGLEVEL__TRACE)
sst, sOptions.eLogLevel++;
sstregs, break;
tmu ,
0, //bit shift default:
devInfo.tmuMemSize[tmu]); Status = E_ERROR__UNKNOWN_ERROR;
ullNbErrorAll += err; ErrorCheck_gotoCleanUp();
putchar( err ? 'E' : '-'); break;
fflush(stdout);
}
putchar('\n');
puts("# data test - random pattern");
for(int j=0;j<100;j++)
{
const unsigned long long err
= test_TMU_datalines(&devInfo,
sst,
sstregs,
tmu ,
1, // random
devInfo.tmuMemSize[tmu]);
ullNbErrorAll += err;
putchar( err ? 'E' : '-');
fflush(stdout);
}
putchar('\n');
puts("# data test - huge data");
for(int j=0;j<10;j++)
{
const unsigned long long err
= test_TMU_datalines_Huge( &devInfo,
sst,
sstregs,
tmu ,
devInfo.tmuMemSize[tmu]);
ullNbErrorAll += err;
putchar( err ? 'E' : '-');
fflush(stdout);
}
putchar('\n');
} }
} }
FaultSource_Sort(); if(bQuit)
FaultSource_Display(); return 0;
printf("Test Complete, ullNbErrorAll = %lld\n",ullNbErrorAll); if(!sOptions.bTestTMU0 && !sOptions.bTestTMU1)
//grGlideShutdown(); {
pciClose(); sOptions.bTestTMU0 = true;
return 0; sOptions.bTestTMU1 = true;
}
if( !sOptions.bTestTMUAddress &&
!sOptions.bTestTMUData &&
!sOptions.bTestTMUDataHuge &&
!sOptions.bTestTMUControl&&
!sOptions.bTestNoMem)
{
sOptions.bTestTMUControl = true;
sOptions.bTestTMUAddress = true;
sOptions.bTestTMUData = true;
sOptions.bTestTMUDataHuge = true;
sOptions.bTestNoMem = true;
}
sst1DeviceInfoStruct devInfo;
memset(&devInfo,0,sizeof(sst1DeviceInfoStruct));
SstRegs *sstregs = NULL;
logI(szTitle, V2MEMTEST__VERSION__MAJOR,
V2MEMTEST__VERSION__MINOR,
V2MEMTEST__VERSION__PATCH);
logI("\n");
logI(szLicence);
logI("\n");
srandom(time(NULL));
FaultSource_reset(ar_dFaultScores_no_mem);
FaultSource_reset(ar_dFaultScores_control);
FaultSource_reset(ar_dFaultScores_address);
FaultSource_reset(ar_dFaultScores_data);
FaultSource_reset(ar_dFaultScores_data_random);
FaultSource_reset(ar_dFaultScores_data_huge);
FaultSource_reset(ar_dFaultScores_ALL);
FaultSource_reset(ar_dFaultScores_sorted);
for(long j=0; j < sOptions.lNumLoops; j++)
{
logI("# processing loop %ld of %ld\n",j+1,sOptions.lNumLoops);
if ((sst = sst1InitMapBoard(boardNum)) == NULL)
{
logE("no Voodoo boards found\n");
Status = E_ERROR__SST1_INIT;
ErrorCheck_gotoCleanUp();
}
sst1InitRegisters(sst);
sstregs = (SstRegs *) sst;
if (sst1InitGetDeviceInfo(sst, &devInfo) == FXFALSE)
{
logE("couldn't get info for Voodoo # %d\n", boardNum);
Status = E_ERROR__SST1_GET_INFO;
ErrorCheck_gotoCleanUp();
}
/* Enabling video output so the Board will
* be configured automatically (FIFO, GRXCLK...)*/
sst1InitVideo(sst,GR_RESOLUTION_800x600,GR_REFRESH_60Hz,0);
logI("FBI detected memory:\t%ld MB\n", (unsigned long)devInfo.fbiMemSize);
if(devInfo.fbiMemSize < 2)
{
logE("couldn't test Voodoo2 TMUs without minimum 2MB of FBI memory\n");
Status = E_ERROR__NOT_ENOUGH_FBI_RAM;
ErrorCheck_gotoCleanUp();
}
if(devInfo.numberTmus>2) //FixMe: This case can happen if U8_TMU1_TF_DATA_9 is wrong
{
logE("Only 2 TMUs are supported\n");
if(sOptions.bForce)
{
logW("Forcing one TMU");
devInfo.numberTmus = 1;
}
else
{
Status = E_ERROR__WRONG_TMU_SELECTED;
ErrorCheck_gotoCleanUp();
}
}
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++)
logI("TMU%d detected memory:\t%ld MB\n", tmu, (unsigned long)devInfo.tmuMemSize[tmu]);
if((sOptions.eTMU0RamLimit >= 0) && (devInfo.numberTmus>=1))
devInfo.tmuMemSize[0] = sOptions.eTMU0RamLimit;
if((sOptions.eTMU1RamLimit >= 0) && (devInfo.numberTmus==2))
devInfo.tmuMemSize[1] = sOptions.eTMU1RamLimit;
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++)
logI("TMU%d tested memory:\t%ld MB\n", tmu, (unsigned long)devInfo.tmuMemSize[tmu]);
putchar('\n');
if(sOptions.bTestTMU0 && devInfo.numberTmus<1)
{
logE("TMU0 not Found\n");
if(sOptions.bForce)
{
logW("Forcing TMU0 test");
}
else
{
Status = E_ERROR__TMU_NOT_FOUND;
ErrorCheck_gotoCleanUp();
}
}
if(sOptions.bTestTMU1 && devInfo.numberTmus<2)
{
logE("TMU1 not Found\n");
if(sOptions.bForce)
{
logW("Forcing TMU1 test");
}
else
{
Status = E_ERROR__TMU_NOT_FOUND;
ErrorCheck_gotoCleanUp();
}
}
const bool bTestTMU0 = ( (devInfo.numberTmus > 0)
|| sOptions.bForce)
&& sOptions.bTestTMU0;
const bool bTestTMU1 = ( (devInfo.numberTmus > 1)
|| sOptions.bForce)
&& sOptions.bTestTMU1;
if(!bTestTMU0 && !bTestTMU1)
{
logE("no TMU selected.\n");
Status = E_ERROR__NO_TMU_SELECTED;
ErrorCheck_gotoCleanUp();
}
if(bTestTMU1 && !bTestTMU0)
{
logW("/!\\ make sure you did test TMU0 BEFORE TMU1.\n\n");
}
ISET(sstregs->lfbMode,
SST_LFB_RGBALANES_ARGB
| SST_LFB_READFRONTBUFFER);
ISET(sstregs->fbzMode,
SST_DRAWBUFFER_FRONT
| SST_RGBWRMASK); // <-for NoMEM test
ISET( sstregs->fbzColorPath,
SST_RGBSEL_TMUOUT
| SST_ASEL_TMUOUT // <-for NoMEM test
| SST_ENTEXTUREMAP);
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++)
{
ISET( SST_TREX(sstregs,tmu)->textureMode,
SST_RGB565
| SST_TC_REPLACE
| SST_TCA_REPLACE);
}
ISET(sstregs->tLOD, 0);
for (int tmu = 0; tmu < devInfo.numberTmus; tmu++)
{
if((tmu == 0) && !bTestTMU0) continue;
if((tmu == 1) && !bTestTMU1) continue;
logI("## testing Board %d, TMU %d, %ldMB \n",
boardNum,tmu,(unsigned long)devInfo.tmuMemSize[tmu]);
if(sOptions.bTestNoMem)
{
unsigned long long err=0;
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu, 0x000000);
}
logI("### data test - no mem\n");
clearScreen(sstregs, 0x00000000, 256, 256);
clock_t test_begin = clock();
do
{
err = test_TMU_datalines_NoMem( &devInfo,
sst,
sstregs,
tmu ,
ar_dFaultScores_no_mem);
ullNbErrorAll += err;
logI( err ? "E" : ".");
fflush(stdout);
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< _DEF_TEST_TIME_PER_MB_S));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_no_mem);
if(err)
{
logW("error detected on TMUs tex lines (no-mem test) !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
}
logI("\n");
ISET(sstregs->lfbMode,
SST_LFB_RGBALANES_ARGB
| SST_LFB_READFRONTBUFFER);
if(sOptions.bTestTMUControl && (devInfo.tmuMemSize[tmu]>0))
{
unsigned long long err=0;
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu, 0x000000);
}
logI("### control lines test - simple\n");
clearScreen(sstregs, 0x00000000, 256, 256);
clock_t test_begin = clock();
int i=0;
do
{
err = TestControl(&devInfo,
sst,
sstregs,
tmu,
devInfo.tmuMemSize[tmu],
ar_dFaultScores_control);
ullNbErrorAll += err;
if(err || (((i++)%1000)==0))
{
logI( err ? "E" : ".");
fflush(stdout);
}
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< _DEF_TEST_TIME_PER_MB_S));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_control);
if(err)
{
logW("error detected on control line !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
}
if(sOptions.bTestTMUAddress && (devInfo.tmuMemSize[tmu]>0))
{
unsigned long long err=0;
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu,0x000000);
}
logI("### address lines test - cumulated\n");
clearScreen(sstregs, 0x00000000, 256, 256);
clock_t test_begin = clock();
int i=0;
do
{
err = 0;
for( unsigned char stepMemSize=1;
(stepMemSize <= devInfo.tmuMemSize[tmu]) && !err;
stepMemSize++)
{
err = RenderTestAddress(&devInfo,
sst,
sstregs,
tmu,
stepMemSize,
ar_dFaultScores_address);
ullNbErrorAll += err;
if(err || (((i++)%28)==0))
{
logI( err ? "E" : ".");
fflush(stdout);
}
}
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< (devInfo.tmuMemSize[tmu]*_DEF_TEST_TIME_PER_MB_S)));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_address);
if(err)
{
logW("error detected on address line !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
}
if(sOptions.bTestTMUData && (devInfo.tmuMemSize[tmu]>0))
{
unsigned long long err=0;
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu, 0x000000);
}
logI("### data test - single bit move\n");
clearScreen(sstregs, 0x00000000, 256, 256);
clock_t test_begin = clock();
do
{
err = test_TMU_datalines(&devInfo,
sst,
sstregs,
tmu ,
0, /* bit shift mode */
devInfo.tmuMemSize[tmu],
ar_dFaultScores_data);
ullNbErrorAll += err;
logI( err ? "E" : ".");
fflush(stdout);
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< (devInfo.tmuMemSize[tmu]*_DEF_TEST_TIME_PER_MB_S)));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_data);
if(err)
{
logW("error detected on data line (single bit move) !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu, 0x000000);
}
logI("### data test - random patterns\n");
clearScreen(sstregs, 0x00000000, 256, 256);
test_begin = clock();
do
{
err = test_TMU_datalines(&devInfo,
sst,
sstregs,
tmu ,
1, /* random mode */
devInfo.tmuMemSize[tmu],
ar_dFaultScores_data_random);
ullNbErrorAll += err;
logI( err ? "E" : ".");
fflush(stdout);
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< (devInfo.tmuMemSize[tmu]*_DEF_TEST_TIME_PER_MB_S)));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_data_random);
if(err)
{
logW("error detected on data line (random patterns) !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
}
if(sOptions.bTestTMUDataHuge && (devInfo.tmuMemSize[tmu]>0))
{
unsigned long long err=0;
if(!sOptions.bQuick)
{
logI("### pre-heating\n");
HeatMemAndTMU(&devInfo, sst, sstregs, tmu, 0x000000);
}
logI("### data test - huge data set\n");
clearScreen(sstregs, 0x00000000, 256, 256);
clock_t test_begin = clock();
do
{
err = test_TMU_datalines_Huge( &devInfo,
sst,
sstregs,
tmu ,
devInfo.tmuMemSize[tmu],
ar_dFaultScores_data_huge);
ullNbErrorAll += err;
logI( err ? "E" : ".");
fflush(stdout);
}
while( (!err || sOptions.bContinue) &&
(((double)(clock() - test_begin)/CLOCKS_PER_SEC)
< (devInfo.tmuMemSize[tmu]*_DEF_TEST_TIME_PER_MB_S)));
logI("\n");
FaultSource_nomalize(ar_dFaultScores_data_huge);
if(err)
{
logW("error detected on data line (huge data set) !\n");
if(!sOptions.bContinue)
{
logW("skiping next tests.\n\n");
continue;
}
}
}
logI("\n");
}
sst1InitShutdown(sst);
sst = NULL;
}
FaultSource_sum(ar_dFaultScores_Set,
uNb_dFaultScores_Set,
ar_dFaultScores_ALL);
FaultSource_getSorted(ar_dFaultScores_sorted,ar_dFaultScores_ALL);
FaultSource_nomalize(ar_dFaultScores_sorted);
FaultSource_divideAll(ar_dFaultScores_sorted,0.01);
FaultSource_display(ar_dFaultScores_sorted);
logI("test completed, ullNbErrorAll = %lld\n",ullNbErrorAll);
logI("\n");
if(ullNbErrorAll)
logI(szKool);
else
logI(szKool2);
logI("\n");
CleanUp:
if(sst)
sst1InitShutdown(sst);
return Status;
} }

2
nppws
View File

@@ -18,5 +18,7 @@
<File name="Utils.h" /> <File name="Utils.h" />
<File name="LICENSE.md" /> <File name="LICENSE.md" />
<File name="V2MemTest.h" /> <File name="V2MemTest.h" />
<File name="Dockerfile" />
<File name="Jenkinsfile" />
</Project> </Project>
</NotepadPlus> </NotepadPlus>