/* 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 . */ #include #include #include "FaultSources.h" #include "Utils.h" def_sFaultSourceScoreRec ar_dFaultScores[NB_FAULT_SOURCE] = { { .eThisFaultSource = VOODOO_BOARD, .szName = "VOODOO_BOARD", .szLoc = "Main Board", .eParrentFaultSource = _INVALID_FAULT_SOURCE_, .dScore = 0.0 }, FAULT_SOURCES(GEN_FAULT_SOURCES_ARRAY) }; def_sFaultSourceScoreRec ar_dFaultScores_sorted[NB_FAULT_SOURCE]; void FaultSource_Reset() { for(def_eFaultSource idx = 0; idx < NB_FAULT_SOURCE; idx++ ) ar_dFaultScores[idx].dScore = 0.0; } static unsigned long FaultSource_getNbDeps(const def_eFaultSource eFaultSource) { unsigned long res = 0; for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; idx++ ) if(ar_dFaultScores[idx].eParrentFaultSource == eFaultSource) res++; return res; } void FaultSource_AddScore( def_eFaultSource eFaultSource, double dScore) { double dDivider = 1.0; do { dScore /= dDivider; ar_dFaultScores[eFaultSource].dScore += dScore; eFaultSource = ar_dFaultScores[eFaultSource].eParrentFaultSource; dDivider = FaultSource_getNbDeps(eFaultSource); if(dDivider <= 0) dDivider = 1.0; }while(eFaultSource != _INVALID_FAULT_SOURCE_); } static unsigned long FaultSource_Sort_GetIdx(const def_eFaultSource eFaultSource) { for(unsigned long idx = 0; idx < NB_FAULT_SOURCE; idx++ ) if(ar_dFaultScores_sorted[idx].eThisFaultSource == eFaultSource) return idx; return _INVALID_FAULT_SOURCE_; } static inline void FaultSource_Sort_Swap( const def_eFaultSource eFaultSourceCurrentA, const def_eFaultSource eFaultSourceCurrentB) { static def_sFaultSourceScoreRec tmp; memcpy(&tmp, &ar_dFaultScores_sorted[eFaultSourceCurrentA], sizeof(def_sFaultSourceScoreRec)); memcpy(&ar_dFaultScores_sorted[eFaultSourceCurrentA], &ar_dFaultScores_sorted[eFaultSourceCurrentB], sizeof(def_sFaultSourceScoreRec)); memcpy(&ar_dFaultScores_sorted[eFaultSourceCurrentB], &tmp, sizeof(def_sFaultSourceScoreRec)); } void FaultSource_Sort() { unsigned char bSwapped = 1; memcpy(ar_dFaultScores_sorted,ar_dFaultScores,sizeof(ar_dFaultScores_sorted)); // shaker sort while(bSwapped) { bSwapped = 0; for(long eFaultSourceCurrentComp=0; eFaultSourceCurrentComp < (NB_FAULT_SOURCE - 1); eFaultSourceCurrentComp++ ) { if( ar_dFaultScores_sorted[eFaultSourceCurrentComp].dScore < ar_dFaultScores_sorted[eFaultSourceCurrentComp + 1].dScore) { FaultSource_Sort_Swap(eFaultSourceCurrentComp, eFaultSourceCurrentComp + 1); bSwapped = 1; break; } } for(long eFaultSourceCurrentComp = (NB_FAULT_SOURCE-2); eFaultSourceCurrentComp >= 0; eFaultSourceCurrentComp-- ) { if( ar_dFaultScores_sorted[eFaultSourceCurrentComp].dScore < ar_dFaultScores_sorted[eFaultSourceCurrentComp + 1].dScore) { FaultSource_Sort_Swap(eFaultSourceCurrentComp, eFaultSourceCurrentComp + 1); bSwapped = 1; break; } } } // updating refs for(long eFaultSourceIdx = 0; eFaultSourceIdx < NB_FAULT_SOURCE; eFaultSourceIdx++ ) { unsigned long idx = FaultSource_Sort_GetIdx(ar_dFaultScores_sorted[eFaultSourceIdx].eParrentFaultSource); ar_dFaultScores_sorted[eFaultSourceIdx].eParrentFaultSource = idx; } for(long eFaultSourceIdx = 0; eFaultSourceIdx < NB_FAULT_SOURCE; eFaultSourceIdx++ ) ar_dFaultScores_sorted[eFaultSourceIdx].eThisFaultSource = eFaultSourceIdx; } void FaultSource_GetLoc(def_eFaultSource eFaultSource, char* loc) { loc[0]='\0'; strcpy(loc, ar_dFaultScores_sorted[eFaultSource].szLoc); eFaultSource = ar_dFaultScores_sorted[eFaultSource].eParrentFaultSource; while(eFaultSource != _INVALID_FAULT_SOURCE_) { static char buff[1024]; sprintf(buff, "%s->%s", ar_dFaultScores_sorted[eFaultSource].szLoc, loc); strcpy(loc, buff); eFaultSource = ar_dFaultScores_sorted[eFaultSource].eParrentFaultSource; } } void FaultSource_Display() { 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("\nDefects list:\n\n"); printf("Score\tElement [Loc]\n"); printf("------------------------------------------------\n"); for(def_eFaultSource eFaultSourceCurrent = 0; eFaultSourceCurrent < NB_FAULT_SOURCE && (ar_dFaultScores_sorted[eFaultSourceCurrent].dScore > 0); eFaultSourceCurrent++ ) { static char buff[1024]; FaultSource_GetLoc(eFaultSourceCurrent, buff); printf("%02.3f\t%s [%s]\n", 100 * ar_dFaultScores_sorted[eFaultSourceCurrent].dScore / dScoreSum, ar_dFaultScores_sorted[eFaultSourceCurrent].szName, buff ); } } void WordBitFaultSet( const unsigned long 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 def_eFaultSource eFaultSource) { for(unsigned char bitPos = 0; bitPos <= 4 ; bitPos++) if(ErrorMark & (1 << bitPos)) FaultSource_AddScore(eFaultSource + bitPos, dScore); } inline void MemChipDQFaultSet( const unsigned long ErrorMark, const double dScore, const def_eFaultSource eFaultSourceL, const def_eFaultSource eFaultSourceH) { WordBitFaultSet(ErrorMark, dScore, eFaultSourceL + 1, eFaultSourceH + 1); } inline void TMUTexDataFaultSet( const unsigned long ErrorMark_w0w1, const unsigned long ErrorMark_w2w3, const double dScore, const def_eFaultSource eTMUFaultSource) { WordBitFaultSet(ErrorMark_w0w1, dScore, eTMUFaultSource + 0 + 1, eTMUFaultSource + 16 + 1); WordBitFaultSet(ErrorMark_w2w3, dScore, eTMUFaultSource + 32 + 1, eTMUFaultSource + 48 + 1); } inline void TMUTexDataCtrlFaultSet( const unsigned long ErrorMark, double dScore, const def_eFaultSource eFaultSourceCASL, const def_eFaultSource eFaultSourceCASH, const def_eFaultSource eFaultSourceRAS, const def_eFaultSource eFaultSourceWE ) { if( ErrorMark && (count_bit32(ErrorMark) > 16) ) { if(ErrorMark & 0x000000FF) FaultSource_AddScore(eFaultSourceCASL,dScore); if(ErrorMark & 0x0000FF00) FaultSource_AddScore(eFaultSourceCASH,dScore); if(ErrorMark & 0x00FF0000) FaultSource_AddScore(eFaultSourceCASL,dScore); if(ErrorMark & 0xFF000000) FaultSource_AddScore(eFaultSourceCASH,dScore); FaultSource_AddScore(eFaultSourceRAS,dScore / 2); FaultSource_AddScore(eFaultSourceWE,dScore / 2); } }