Files
V2TMUMemTester/FaultSources.c

392 lines
11 KiB
C

/* V2MemTest - A CLI Tool to test & fix Voodoo² TMU System
* Copyright (C) 2026 ChaCha
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
#include <stdio.h>
#include <string.h>
#include "FaultSources.h"
#include "Utils.h"
const def_sFaultSourceScoreRec
_ar_dFaultScores[NB_FAULT_SOURCE] =
{
{
.eThisFaultSource = VOODOO_BOARD,
.szName = "VOODOO_BOARD",
.szLoc = "Main Board",
.eParrentFaultSource = _INVALID_FAULT_SOURCE_,
.dScore = 0.0,
.dWeight = 1.0,
},
FAULT_SOURCES(GEN_FAULT_SOURCES_ARRAY)
};
void
FaultSource_reset(def_sFaultSourceScoreRec* const pCtx)
{
memcpy( pCtx,
_ar_dFaultScores,
sizeof(_ar_dFaultScores));
}
static unsigned long
FaultSource_getNbDeps( const def_sFaultSourceScoreRec* const pCtx,
const def_eFaultSource eFaultSource)
{
unsigned long res = 0;
for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; ++idx )
if(pCtx[idx].eParrentFaultSource == eFaultSource)
res++;
return res;
}
void
FaultSource_addScore( def_sFaultSourceScoreRec* const pCtx,
def_eFaultSource eFaultSource,
double dScore)
{
double dDivider = 1.0;
do
{
//if(dDivider==1.0)
// printf("set Score %f to %s\n",dScore,pCtx[eFaultSource].szName);
dScore /= dDivider;
pCtx[eFaultSource].dScore += dScore;
eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
dDivider *= 5;
}while(eFaultSource != _INVALID_FAULT_SOURCE_);
}
void
FaultSource_nomalize( def_sFaultSourceScoreRec* const pCtx)
{
double dSum = 0.0;
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 _INVALID_FAULT_SOURCE_;
}
static inline void
FaultSource_Swap( def_sFaultSourceScoreRec* const pCtx,
const def_eFaultSource A,
const def_eFaultSource B)
{
def_sFaultSourceScoreRec tmp;
memcpy( &tmp,
&pCtx[A],
sizeof(def_sFaultSourceScoreRec));
memcpy( &pCtx[A],
&pCtx[B],
sizeof(def_sFaultSourceScoreRec));
memcpy( &pCtx[B],
&tmp,
sizeof(def_sFaultSourceScoreRec));
}
void
FaultSource_getSorted( def_sFaultSourceScoreRec* const pDst,
const def_sFaultSourceScoreRec* const pCtx)
{
unsigned char bSwapped = 1;
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)
{
bSwapped = 0;
for(unsigned long idx=0;
idx < (NB_FAULT_SOURCE - 1);
++idx )
{
if( pDst[idx].dScore
< pDst[idx + 1].dScore)
{
FaultSource_Swap( pDst,
idx,
idx + 1);
bSwapped = 1;
break;
}
}
for(long idx = (NB_FAULT_SOURCE-2);
idx >= 0;
--idx )
{
if( pDst[idx].dScore
< pDst[idx + 1].dScore)
{
FaultSource_Swap( pDst,
idx,
idx + 1);
bSwapped = 1;
break;
}
}
}
// updating refs
for(unsigned long idx = 0;
idx < NB_FAULT_SOURCE;
++idx )
pDst[idx].eParrentFaultSource =
FaultSource_GetIdx(
pDst,
pDst[idx].eParrentFaultSource);
for(unsigned long idx = 0;
idx < NB_FAULT_SOURCE;
++idx )
pDst[idx].eThisFaultSource = idx;
}
void
FaultSource_getLoc( const def_sFaultSourceScoreRec* const pCtx,
def_eFaultSource eFaultSource,
char* const loc)
{
loc[0]='\0';
strcpy(loc, pCtx[eFaultSource].szLoc);
eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
while(eFaultSource != _INVALID_FAULT_SOURCE_)
{
static char buff[1024];
sprintf(buff, "%s->%s", pCtx[eFaultSource].szLoc, loc);
strcpy(loc, buff);
eFaultSource = pCtx[eFaultSource].eParrentFaultSource;
}
}
void
FaultSource_display(const def_sFaultSourceScoreRec* const pCtx)
{
printf("------------------------------------------------\n");
printf("\ndefects list:\n\n");
printf("score\telement [Loc]\n");
printf("------------------------------------------------\n");
for(unsigned long idx = 0;
(idx < NB_FAULT_SOURCE)
&& (pCtx[idx].dScore > 0);
++idx )
{
static char buff[1024] = {0};
buff[0]='\0';
FaultSource_getLoc(pCtx,idx, buff);
printf("%02.3f\t%s [%s]\n",
pCtx[idx].dScore,
pCtx[idx].szName,
buff );
}
}
void
ByteBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const uint8_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSource)
{
for(unsigned char bitPos = 0; bitPos <= 7 ; ++bitPos)
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)
{
for(unsigned char bitPos = 0; bitPos <= 15 ; ++bitPos)
if(ErrorMark & (1u << bitPos))
{
FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore);
}
}
void
LWordBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const uint32_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSourceL,
const def_eFaultSource eFaultSourceH)
{
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);
}
}
void
QuartetBitFaultSet( def_sFaultSourceScoreRec* const pCtx,
const uint8_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSource)
{
for(uint8_t bitPos = 0; bitPos < 4 ; ++bitPos)
if(ErrorMark & (1u << bitPos))
FaultSource_addScore(pCtx, eFaultSource + bitPos, dScore);
}
void
RGBToBus_Fault( def_sFaultSourceScoreRec* const pCtx,
const uint32_t ErrorMark,
const double dScore,
const def_eFaultSource eFaultSource)
{
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 */
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);
}