high ram oc

This commit is contained in:
souldbminersmwc
2025-09-09 16:39:28 -04:00
parent 06faabdddf
commit 962b8bc0a0
17 changed files with 333 additions and 449 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -103,22 +103,103 @@ volatile CustomizeTable C = {
.gpuVmax = 800,
.gpuVmin = 600,
.marikoEmcDvbShift = 0,
.ramTimingPresetOne = 0, // T1-3 EOS
.latency = 0, // Ram latency values. Goes from 0-6. Affects tWL and tRL
.ramTimingPresetTwo = 0, // T4
.BL = 16, // Keep at 16
.ramTimingPresetThree = 0, // Try all values from 0-6
// tRFCpb (refresh cycle time per bank) in ns for 8Gb density
.tRFCpb = 140,
.ramTimingPresetFour = 0, // EOS T5
// tRFCab (refresh cycle time all banks) in ns for 8Gb density
.tRFCab = 280, // tRFCpb * 2
.ramTimingPresetFive = 0, // EOS T7
// tRAS (row active time) in ns
.tRAS = 42,
.ramTimingPresetSix = 0, // EOS T8
// tRPpb (row precharge time per bank) in ns
.tRPpb = 18,
// tRPab (row precharge time all banks) in ns
.tRPab = 21, // tRPab + 3
// tRC (ACTIVATE-ACTIVATE command period same bank) in ns
.tRC = 60, // tRPpb + tRAS
// DQS output access time from CK_t/CK_c
.tDQSCK_min = 1.5,
// DQS output access time from CK_t/CK_c
.tDQSCK_max = 3.5,
// Write preamble (tCK)
.tWPRE = 1.8,
// Read postamble (tCK)
.tRPST = 0.4,
// WRITE command to first DQS transition(max) (tCK)
.tDQSS_max = 1.25,
// DQ-to-DQS offset(max) (ns)
.tDQS2DQ_max = 0.8,
// DQS_t, DQS_c to DQ skew total, per group, per access (DBI Disabled)
.tDQSQ = 0.18,
z
// Write-to-Read delay
.tWTR = 10,
// Internal READ-to-PRE-CHARGE command delay in ns
.tRTP = 7.5,
// write recovery time
.tWR = 18,
// Read to refresh delay
.tR2REF = 26, // Round down tRTP + tRPpb
// tRCD (RAS-CAS delay) in ns
.tRCD = 18,
// tRRD (Active bank-A to Active bank-B) in ns
.tRRD = 10.0,
// tREFpb (average refresh interval per bank) in ns for 8Gb density
.tREFpb = 488,
// tREFab (average refresh interval all 8 banks) in ns for 8Gb density
// const u32 tREFab = tREFpb * 8;
// tPDEX2WR, tPDEX2RD (timing delay from exiting powerdown mode to a write/read command) in ns
// const u32 tPDEX2 = 10;
// Exit power-down to next valid command delay
.tXP = 10,
// Delay from valid command to CKE input LOW in ns
.tCMDCKE = 1.75,
// tACT2PDEN (timing delay from an activate, MRS or EMRS command to power-down entry) in ns
// Valid clock and CS requirement after CKE input LOW after MRW command
.tMRWCKEL = 14,
// Valid CS requirement after CKE input LOW
.tCKELCS = 5,
// Valid CS requirement before CKE input HIGH
.tCSCKEH = 1.75,
// tXSR (SELF REFRESH exit to next valid command delay) in ns
.tXSR = 287.5, // tRFCab + 7.5
// tCKE (minimum pulse width(HIGH and LOW pulse width)) in ns
.tCKE = 7.5,
// Minimum self refresh time (entry to exit)
.tSR = 15,
// tFAW (Four-bank Activate Window) in ns
.tFAW = 40,
// Valid Clock requirement before CKE Input HIGH in ns
.tCKCKEH = 1.75,
.ramTimingPresetSeven = 0,
//
.marikoGpuVoltArray = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -61,15 +61,42 @@ typedef struct CustomizeTable {
u32 cpuMaxFreq;
u32 gpuMaxFreq;
u32 gpuVmax;
// advanced config
u32 gpuVmin;
u32 marikoEmcDvbShift;
u32 ramTimingPresetOne;
u32 ramTimingPresetTwo;
u32 ramTimingPresetThree;
u32 ramTimingPresetFour;
u32 ramTimingPresetFive;
u32 ramTimingPresetSix;
u32 ramTimingPresetSeven;
// ram timings
u32 latency;
u32 BL;
u32 tRFCpb;
u32 tRFCab;
u32 tRAS;
u32 tRPpb;
u32 tRPab;
u32 tRC;
double tDQSCK_min;
double tDQSCK_max;
double tWPRE;
double tRPST;
double tDQSS_max;
double tDQS2DQ_max;
double tDQSQ;
u32 tWTR;
double tRTP;
u32 tWR;
u32 tR2REF;
u32 tRCD;
double tRRD;
u32 tREFpb;
double tXP;
double tCMDCKE;
u32 tMRWCKEL;
double tCKELCS;
double tCSCKEH;
double tXSR;
double tCKE;
u32 tSR;
u32 tFAW;
double tCKCKEH;
//
u32 marikoGpuVoltArray[24];

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -23,211 +23,89 @@ namespace ams::ldr::oc {
#define MIN(A, B) std::min(A, B)
#define CEIL(A) std::ceil(A)
#define FLOOR(A) std::floor(A)
//Preset One
const std::array<u32, 6> tRCD_values = {18, 17, 16, 15, 14, 13};
const std::array<u32, 6> tRP_values = {18, 17, 16, 15, 14, 13};
const std::array<u32, 6> tRAS_values = {42, 39, 36, 34, 32, 30};
// Preset Two
const std::array<double, 5> tRRD_values = {10, 7.5, 6, 4, 3};
const std::array<double, 5> tFAW_values = {40, 30, 24, 16, 12};
// Preset Three
const std::array<u32, 6> tWR_values = {18, 15, 15, 12, 12, 8};
const std::array<double, 6> tRTP_values = {7.5, 7.5, 6, 6, 4, 4};
// Preset Four
const std::array<u32, 6> tRFC_values = {140, 120, 100, 80, 70, 60};
// Preset Five
const std::array<u32, 6> tWTR_values = {10, 8, 6, 4, 2, 1};
// Preset Six
const std::array<u32, 5> tREFpb_values = {488, 976, 1952, 3256, 9999};
const u32 TIMING_PRESET_ONE = C.ramTimingPresetOne;
const u32 TIMING_PRESET_TWO = C.ramTimingPresetTwo;
const u32 TIMING_PRESET_THREE = C.ramTimingPresetThree;
const u32 TIMING_PRESET_FOUR = C.ramTimingPresetFour;
const u32 TIMING_PRESET_FIVE = C.ramTimingPresetFive;
const u32 TIMING_PRESET_SIX = C.ramTimingPresetSix;
const u32 TIMING_PRESET_SEVEN = C.ramTimingPresetSeven;
// Burst Length
const u32 BL = 16;
// tRFCpb (refresh cycle time per bank) in ns for 8Gb density
const u32 tRFCpb = !TIMING_PRESET_FOUR ? 140 : tRFC_values[TIMING_PRESET_FOUR-1];
// tRFCab (refresh cycle time all banks) in ns for 8Gb density
const u32 tRFCab = !TIMING_PRESET_FOUR ? 280 : 2*tRFCpb;
// tRAS (row active time) in ns
const u32 tRAS = !TIMING_PRESET_ONE ? 42 : tRAS_values[TIMING_PRESET_ONE-1];
// tRPpb (row precharge time per bank) in ns
const u32 tRPpb = !TIMING_PRESET_ONE ? 18 : tRP_values[TIMING_PRESET_ONE-1];
// tRPab (row precharge time all banks) in ns
const u32 tRPab = !TIMING_PRESET_ONE ? 21 : tRPpb + 3;
// tRC (ACTIVATE-ACTIVATE command period same bank) in ns
const u32 tRC = tRPpb + tRAS;
// DQS output access time from CK_t/CK_c
const double tDQSCK_min = 1.5;
// DQS output access time from CK_t/CK_c
const double tDQSCK_max = 3.5;
// Write preamble (tCK)
const double tWPRE = 1.8;
// Read postamble (tCK)
const double tRPST = 0.4;
// WRITE command to first DQS transition(max) (tCK)
const double tDQSS_max = 1.25;
// DQ-to-DQS offset(max) (ns)
const double tDQS2DQ_max = 0.8;
// DQS_t, DQS_c to DQ skew total, per group, per access (DBI Disabled)
const double tDQSQ = 0.18;
// Write-to-Read delay
const u32 tWTR = !TIMING_PRESET_FIVE ? 10 : tWTR_values[TIMING_PRESET_FIVE-1];
// Internal READ-to-PRE-CHARGE command delay in ns
const double tRTP = !TIMING_PRESET_THREE ? 7.5 : tRTP_values[TIMING_PRESET_THREE-1];
// write recovery time
const u32 tWR = !TIMING_PRESET_THREE ? 18 : tWR_values[TIMING_PRESET_THREE-1];
// Read to refresh delay
const u32 tR2REF = tRTP + tRPpb;
// tRCD (RAS-CAS delay) in ns
const u32 tRCD = !TIMING_PRESET_ONE ? 18 : tRCD_values[TIMING_PRESET_ONE-1];
// tRRD (Active bank-A to Active bank-B) in ns
const double tRRD = !TIMING_PRESET_TWO ? 10. : tRRD_values[TIMING_PRESET_TWO-1];
// tREFpb (average refresh interval per bank) in ns for 8Gb density
const u32 tREFpb = !TIMING_PRESET_SIX ? 488 : tREFpb_values[TIMING_PRESET_SIX-1];
// tREFab (average refresh interval all 8 banks) in ns for 8Gb density
// const u32 tREFab = tREFpb * 8;
// tPDEX2WR, tPDEX2RD (timing delay from exiting powerdown mode to a write/read command) in ns
// const u32 tPDEX2 = 10;
// Exit power-down to next valid command delay
const double tXP = 10;
// Delay from valid command to CKE input LOW in ns
const double tCMDCKE = 1.75;
// tACT2PDEN (timing delay from an activate, MRS or EMRS command to power-down entry) in ns
// Valid clock and CS requirement after CKE input LOW after MRW command
const u32 tMRWCKEL = 14;
// Valid CS requirement after CKE input LOW
const double tCKELCS = 5;
// Valid CS requirement before CKE input HIGH
const double tCSCKEH = 1.75;
// tXSR (SELF REFRESH exit to next valid command delay) in ns
const double tXSR = tRFCab + 7.5;
// tCKE (minimum pulse width(HIGH and LOW pulse width)) in ns
const double tCKE = 7.5;
// Minimum self refresh time (entry to exit)
const u32 tSR = 15;
// tFAW (Four-bank Activate Window) in ns
const u32 tFAW = !TIMING_PRESET_TWO ? 40 : tFAW_values[TIMING_PRESET_TWO-1];
// Valid Clock requirement before CKE Input HIGH in ns
const double tCKCKEH = 1.75;
// p78 The first valid data is available RL × t CK + t DQSCK + t DQSQ
//const u32 QUSE = RL + CEIL(tDQSCK_min/tCK_avg + tDQSQ);
//const u32 QUSE = RL + CEIL(C.tDQSCK_min/tCK_avg + C.tDQSQ);
namespace pcv::erista {
// tCK_avg (average clock period) in ns
const double tCK_avg = 1000'000. / C.eristaEmcMaxClock;
// Write Latency
const u32 WL = 14 - 2*TIMING_PRESET_SEVEN;
const u32 WL = 14 - 2*C.latency;
// Read Latency
const u32 RL = 32 - 4*TIMING_PRESET_SEVEN;
const u32 RL = 32 - 4*C.latency;
// minimum number of cycles from any read command to any write command, irrespective of bank
const u32 R2W = CEIL (RL + CEIL(tDQSCK_max/tCK_avg) + BL/2 - WL + tWPRE + FLOOR(tRPST)) + 6;
const u32 R2W = CEIL (RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - WL + C.tWPRE + FLOOR(C.tRPST)) + 6;
// Delay Time From WRITE-to-READ
const u32 W2R = WL + BL/2 + 1 + CEIL(tWTR/tCK_avg) - 6;
const u32 W2R = WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg) - 6;
// write-to-precharge time for commands to the same bank in cycles
const u32 WTP = WL + BL/2 + 1 + CEIL(tWR/tCK_avg) - 8;
const u32 WTP = WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg) - 8;
// #_of_rows per die for 8Gb density
const u32 numOfRows = 65536;
// {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%]
// emc_clk_period = dram_clk / 2;
// 1600 MHz: 5894, but N' set to 6176 (~4.8% margin)
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.eristaEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFBW = MIN((u32)65536, REFRESH+64);
// Write With Auto Precharge to to Power-Down Entry
const u32 WTPDEN = WTP + 1 + CEIL(tDQSS_max/tCK_avg) + CEIL(tDQS2DQ_max/tCK_avg) + 6;
const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6;
// Additional time after t XP hasexpired until the MRR commandmay be issued
const double tMRRI = tRCD + 3 * tCK_avg;
const double tMRRI = C.tRCD + 3 * tCK_avg;
// tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns
const double tPDEX2MRR = tXP + tMRRI;
const double tPDEX2MRR = C.tXP + tMRRI;
}
namespace pcv::mariko {
// tCK_avg (average clock period) in ns
const double tCK_avg = 1000'000. / C.marikoEmcMaxClock;
// Write Latency
const u32 WL = 14 - 2*TIMING_PRESET_SEVEN;
const u32 WL = 14 - 2*C.latency;
// Read Latency
const u32 RL = 32 - 4*TIMING_PRESET_SEVEN;
const u32 RL = 32 - 4*C.latency;
// minimum number of cycles from any read command to any write command, irrespective of bank
const u32 R2W = CEIL (RL + CEIL(tDQSCK_max/tCK_avg) + BL/2 - WL + tWPRE + FLOOR(tRPST));
const u32 R2W = CEIL (RL + CEIL(C.tDQSCK_max/tCK_avg) + C.BL/2 - WL + C.tWPRE + FLOOR(C.tRPST));
// Delay Time From WRITE-to-READ
const u32 W2R = WL + BL/2 + 1 + CEIL(tWTR/tCK_avg);
const u32 W2R = WL + C.BL/2 + 1 + CEIL(C.tWTR/tCK_avg);
// write-to-precharge time for commands to the same bank in cycles
const u32 WTP = WL + BL/2 + 1 + CEIL(tWR/tCK_avg);
const u32 WTP = WL + C.BL/2 + 1 + CEIL(C.tWR/tCK_avg);
// Read-To-MRW delay
const u32 RTM = RL + BL/2 + CEIL(tDQSCK_max/tCK_avg) + FLOOR(tRPST) + CEIL(7.5/tCK_avg);
const u32 RTM = RL + C.BL/2 + CEIL(C.tDQSCK_max/tCK_avg) + FLOOR(C.tRPST) + CEIL(7.5/tCK_avg);
// Write-To-MRW/MRR delay
const u32 WTM = WL + 1 + BL/2 + CEIL(7.5/tCK_avg);
const u32 WTM = WL + 1 + C.BL/2 + CEIL(7.5/tCK_avg);
// Read With AP-To-MRW/MRR delay
const u32 RATM = RTM + CEIL(tRTP/tCK_avg) - 8;
const u32 RATM = RTM + CEIL(C.tRTP/ 1000/tCK_avg) - 8;
// Write With AP-To-MRW/MRR delay
const u32 WATM = WTM + CEIL(tWR/tCK_avg);
const u32 WATM = WTM + CEIL(C.tWR/tCK_avg);
// #_of_rows per die for 8Gb density
const u32 numOfRows = 65536;
// {REFRESH, REFRESH_LO} = max[(tREF/#_of_rows) / (emc_clk_period) - 64, (tREF/#_of_rows) / (emc_clk_period) * 97%]
// emc_clk_period = dram_clk / 2;
// 1600 MHz: 5894, but N' set to 6176 (~4.8% margin)
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFRESH = MIN((u32)65472, u32(std::ceil((double(C.tREFpb) * C.marikoEmcMaxClock / numOfRows * 1.048 / 2 - 64))) / 4 * 4);
const u32 REFBW = MIN((u32)65536, REFRESH+64);
// Write With Auto Precharge to to Power-Down Entry
const u32 WTPDEN = WTP + 1 + CEIL(tDQSS_max/tCK_avg) + CEIL(tDQS2DQ_max/tCK_avg) + 6;
const u32 WTPDEN = WTP + 1 + CEIL(C.tDQSS_max/tCK_avg) + CEIL(C.tDQS2DQ_max/tCK_avg) + 6;
// Additional time after t XP hasexpired until the MRR commandmay be issued
const double tMRRI = tRCD + 3 * tCK_avg;
const double tMRRI = C.tRCD + 3 * tCK_avg;
// tPDEX2MRR (timing delay from exiting powerdown mode to MRR command) in ns
const double tPDEX2MRR = tXP + tMRRI;
const double tPDEX2MRR = C.tXP + tMRRI;
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -350,12 +350,14 @@ namespace ams::ldr::oc::pcv
cvb_entry_t *entry = static_cast<cvb_entry_t *>(gpu_cvb_table_head);
for (size_t i = 0; i < customize_entry_count; i++)
{
if (C.marikoGpuVoltArray[i] != 0)
if (!(C.marikoGpuVoltArray[i] < C.gpuVmin))
{
u32 patched_voltage = C.marikoGpuVoltArray[i];
if(!C.gpuVmax) {
if(patched_voltage > C.gpuVmax) {
patched_voltage = C.gpuVmax;
}
}
PATCH_OFFSET(&(entry->cvb_pll_param.c0), patched_voltage * 1000);
PATCH_OFFSET(&(entry->cvb_pll_param.c1), 0);
PATCH_OFFSET(&(entry->cvb_pll_param.c2), 0);

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -83,57 +83,57 @@ void MemMtcTableAutoAdjust(EristaMtcTable* table) {
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP/ 1000));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(C.tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(tCKELCS));
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(C.tCKELCS));
WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(C.tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tCKE));
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab));
WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tCKE)+8);
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(C.tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(C.tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(C.tCKE)+8);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
#define WRITE_PARAM_BURST_MC_REG(TABLE, PARAM, VALUE) TABLE->burst_mc_regs.PARAM = VALUE;
constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2;
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP/ 1000) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
//table->burst_mc_regs.mc_emem_arb_timing_r2r = CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA;
//table->burst_mc_regs.mc_emem_arb_timing_w2w = CEIL(table->burst_regs.emc_wext / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV);
//table->burst_mc_regs.mc_emem_arb_timing_ccdmw = CEIL(tCCDMW / MC_ARB_DIV) -1 + MC_ARB_SFA;
}
@@ -144,69 +144,55 @@ void MemMtcTableCustomAdjust(EristaMtcTable* table) {
constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2;
if (TIMING_PRESET_ONE) {
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV - 2);
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV - 1);
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV - 1 + MC_ARB_SFA);
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV - 2);
}
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV - 2);
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV - 1);
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV - 1 + MC_ARB_SFA);
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV - 2);
if (TIMING_PRESET_TWO) {
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
}
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1;
if (TIMING_PRESET_THREE) {
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP/ 1000));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
}
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP/ 1000) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
if (TIMING_PRESET_FOUR) {
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
}
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV);
if (TIMING_PRESET_FIVE) {
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
if (TIMING_PRESET_SIX) {
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
}
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
if (TIMING_PRESET_SEVEN) {
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -187,44 +187,44 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
#define GET_CYCLE_CEIL(PARAM) u32(CEIL(double(PARAM) / tCK_avg))
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP/ 1000));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_trtm, RTM);
WRITE_PARAM_ALL_REG(table, emc_twtm, WTM);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
//WRITE_PARAM_ALL_REG(table, emc_tr2ref, GET_CYCLE_CEIL(tR2REF));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
//WRITE_PARAM_ALL_REG(table, emc_tr2ref, GET_CYCLE_CEIL(C.tR2REF));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
WRITE_PARAM_ALL_REG(table, emc_rext, 26);
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_pdex2wr, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pdex2rd, GET_CYCLE_CEIL(C.tXP));
WRITE_PARAM_ALL_REG(table, emc_pchg2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_act2pden, GET_CYCLE_CEIL(C.tMRWCKEL));
WRITE_PARAM_ALL_REG(table, emc_ar2pden, GET_CYCLE_CEIL(C.tCMDCKE));
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(tCKELCS));
//WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_cke2pden, GET_CYCLE_CEIL(C.tCKELCS));
//WRITE_PARAM_ALL_REG(table, emc_pdex2cke, GET_CYCLE_CEIL(C.tCSCKEH));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr, GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(tCKE) + 1);
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab));
//WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(tCKE) + 8);
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_tcke, GET_CYCLE_CEIL(C.tCKE) + 1);
WRITE_PARAM_ALL_REG(table, emc_tckesr, GET_CYCLE_CEIL(C.tSR));
WRITE_PARAM_ALL_REG(table, emc_tpd, GET_CYCLE_CEIL(C.tCKE));
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
//WRITE_PARAM_ALL_REG(table, emc_tclkstable, GET_CYCLE_CEIL(C.tCKCKEH));
WRITE_PARAM_ALL_REG(table, emc_tclkstop, GET_CYCLE_CEIL(C.tCKE) + 8);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
ADJUST_PARAM_ALL_REG(table, emc_dyn_self_ref_control, ref);
@@ -234,7 +234,7 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
BITS = BITS & ~( ((1u << HIGH) << 1u) - (1u << LOW) );
#define ADJUST(TARGET) (u32)CEIL(TARGET * (C.marikoEmcMaxClock / EmcClkOSLimit))
#define ADJUST_INVERSE(TARGET) (u32)(TARGET * (EmcClkOSLimit / 1000) / (C.marikoEmcMaxClock / 1000))
#define ADJUST_INVERSE(TARGET) (u32)(TARGET * (EmcClkOSLimit / 1000) / (C.marikoEmcMaxClock))
// Burst MC Regs
#define WRITE_PARAM_BURST_MC_REG(TABLE, PARAM, VALUE) TABLE->burst_mc_regs.PARAM = VALUE;
@@ -243,18 +243,18 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
constexpr u32 MC_ARB_SFA = 2;
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_cfg, C.marikoEmcMaxClock / (33.3 * 1000) / MC_ARB_DIV); //CYCLES_PER_UPDATE: The number of mcclk cycles per deadline timer update
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rcd, CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rp, CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rc, CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_ras, CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_faw, CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rrd, CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rap2pre, CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rcd, CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rp, CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rc, CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_ras, CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_faw, CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rrd, CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rap2pre, CEIL(GET_CYCLE_CEIL(C.tRTP/ 1000) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_wap2pre, CEIL((WTP) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2r, CEIL(table->burst_regs.emc_rext / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_r2w, CEIL((R2W) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_w2r, CEIL((W2R) / MC_ARB_DIV) - 1 + MC_ARB_SFA)
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rfcpb, CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV))
WRITE_PARAM_BURST_MC_REG(table, mc_emem_arb_timing_rfcpb, CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV))
u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN
@@ -323,8 +323,8 @@ void MemMtcTableAutoAdjust(MarikoMtcTable* table, const MarikoMtcTable* ref) {
table->pllmb_ss_ctrl1 = 0x0b55fe01;
table->pllmb_ss_ctrl2 = 0x10170b55;
table->dram_timings.t_rp = tRPpb;
table->dram_timings.t_rfc = tRFCab;
table->dram_timings.t_rp = C.tRPpb;
table->dram_timings.t_rfc = C.tRFCab;
//table->dram_timings.rl = 32;
table->emc_cfg_2 = 0x0011083d;
@@ -337,76 +337,62 @@ void MemMtcTableCustomAdjust(MarikoMtcTable* table) {
constexpr u32 MC_ARB_DIV = 4;
constexpr u32 MC_ARB_SFA = 2;
if (TIMING_PRESET_ONE) {
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(tRC));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(tRPpb));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(tRPab));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(tRCD));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR));
WRITE_PARAM_ALL_REG(table, emc_rc, GET_CYCLE_CEIL(C.tRC));
WRITE_PARAM_ALL_REG(table, emc_ras, GET_CYCLE_CEIL(C.tRAS));
WRITE_PARAM_ALL_REG(table, emc_rp, GET_CYCLE_CEIL(C.tRPpb));
WRITE_PARAM_ALL_REG(table, emc_trpab, GET_CYCLE_CEIL(C.tRPab));
WRITE_PARAM_ALL_REG(table, emc_rd_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_wr_rcd, GET_CYCLE_CEIL(C.tRCD));
WRITE_PARAM_ALL_REG(table, emc_pdex2mrr,GET_CYCLE_CEIL(tPDEX2MRR));
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(tRAS) / MC_ARB_DIV) - 2;
}
table->burst_mc_regs.mc_emem_arb_timing_rcd = CEIL(GET_CYCLE_CEIL(C.tRCD) / MC_ARB_DIV) - 2;
table->burst_mc_regs.mc_emem_arb_timing_rc = CEIL(GET_CYCLE_CEIL(C.tRC) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rp = CEIL(GET_CYCLE_CEIL(C.tRPpb) / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_ras = CEIL(GET_CYCLE_CEIL(C.tRAS) / MC_ARB_DIV) - 2;
if (TIMING_PRESET_TWO) {
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(tRRD));
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(tRRD) / MC_ARB_DIV) - 1;
}
WRITE_PARAM_ALL_REG(table, emc_tfaw, GET_CYCLE_CEIL(C.tFAW));
WRITE_PARAM_ALL_REG(table, emc_rrd, GET_CYCLE_CEIL(C.tRRD));
if (TIMING_PRESET_THREE) {
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(tRTP));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_faw = CEIL(GET_CYCLE_CEIL(C.tFAW) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rrd = CEIL(GET_CYCLE_CEIL(C.tRRD) / MC_ARB_DIV) - 1;
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(tRTP) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
}
WRITE_PARAM_ALL_REG(table, emc_r2p, GET_CYCLE_CEIL(C.tRTP/ 1000));
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
if (TIMING_PRESET_FOUR) {
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(tXSR), (u32)0x3fe));
table->burst_mc_regs.mc_emem_arb_timing_rap2pre = CEIL(GET_CYCLE_CEIL(C.tRTP/ 1000) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(tRFCpb) / MC_ARB_DIV);
}
WRITE_PARAM_ALL_REG(table, emc_rfc, GET_CYCLE_CEIL(C.tRFCab));
WRITE_PARAM_ALL_REG(table, emc_rfcpb, GET_CYCLE_CEIL(C.tRFCpb));
WRITE_PARAM_ALL_REG(table, emc_txsr, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
WRITE_PARAM_ALL_REG(table, emc_txsrdll, MIN(GET_CYCLE_CEIL(C.tXSR), (u32)0x3fe));
if (TIMING_PRESET_FIVE) {
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
table->burst_mc_regs.mc_emem_arb_timing_rfcpb = CEIL(GET_CYCLE_CEIL(C.tRFCpb) / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
if (TIMING_PRESET_SIX) {
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
}
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
if (TIMING_PRESET_SEVEN) {
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_trtm, RTM);
WRITE_PARAM_ALL_REG(table, emc_twtm, WTM);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
WRITE_PARAM_ALL_REG(table, emc_refresh, REFRESH);
WRITE_PARAM_ALL_REG(table, emc_pre_refresh_req_cnt, REFRESH / 4);
WRITE_PARAM_ALL_REG(table, emc_trefbw, REFBW);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
}
WRITE_PARAM_ALL_REG(table, emc_r2w, R2W);
WRITE_PARAM_ALL_REG(table, emc_w2r, W2R);
WRITE_PARAM_ALL_REG(table, emc_w2p, WTP);
WRITE_PARAM_ALL_REG(table, emc_trtm, RTM);
WRITE_PARAM_ALL_REG(table, emc_twtm, WTM);
WRITE_PARAM_ALL_REG(table, emc_tratm, RATM);
WRITE_PARAM_ALL_REG(table, emc_twatm, WATM);
WRITE_PARAM_ALL_REG(table, emc_rw2pden, WTPDEN);
table->burst_mc_regs.mc_emem_arb_timing_wap2pre = CEIL(WTP / MC_ARB_DIV);
table->burst_mc_regs.mc_emem_arb_timing_r2w = CEIL(R2W / MC_ARB_DIV) - 1 + MC_ARB_SFA;
table->burst_mc_regs.mc_emem_arb_timing_w2r = CEIL(W2R / MC_ARB_DIV) - 1 + MC_ARB_SFA;
u32 DA_TURNS = 0;
DA_TURNS |= u8(table->burst_mc_regs.mc_emem_arb_timing_r2w / 2) << 16; //R2W TURN

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -1,5 +1,5 @@
/*
* Copyright (C) Switch-OC-Suite
* Copyright (C) hanai3bi (meha) and Souldbminer
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,

View File

@@ -13,7 +13,7 @@
*
*/
#define __version__ "4.5.1-multithread"
#define __version__ "4.5.1-multithread-ocs2"
// Include the most common headers from the C standard library
#include <stddef.h>
@@ -241,9 +241,10 @@ int main(int argc, char* argv[])
bool isDevKit8GB = false;
printf("MemTesterNX version " __version__ " (%d-bit)\n"\
"Based on memtester. Copyright (C) 2001-2020 Charles Cazabon, 2021 KazushiMe.\n"\
"Based on memtester. Copyright (C) 2001-2020 Charles Cazabon, 2021 KazushiMe, 2025 Souldbminer.\n"\
"Licensed under the GNU General Public License version 2 (only).\n\n"\
"Support full RAM test (up to 8GB) with 3-4 threads.\n"\
"Ensure to set your CPU and GPU freq to maximum to get the best result.\n"\
"It will be looping forever until error occurs or user exits to HOME screen.\n\n"\
"Press A: long test\n"\
"Press X: fast test\n"\

View File

@@ -99,7 +99,7 @@ double ptoGetMHz(PTO_ID pto_id, u32 divider = 1, u32 presel_reg = 0, u32 presel_
val &= 0xFFFFFF;
val *= divider;
double rate_mhz = (u64)val * 32768. / cycle_count / 1000. / 1000.;
double rate_mhz = (u64)val * 32768. / cycle_count / 1000..;
usleep(10);
REG(clkrst_base + 0x60) = pre_val;
usleep(10);

View File

@@ -93,8 +93,11 @@ class AdvEntry extends CustEntry {
e.value = String(this.value)
}
}
class GpuEntry extends CustEntry {
constructor(e, t, i = CustPlatform.Mariko, n = 4, a = ["range: 480 ≤ x ≤ 960 (Zero is disabled)"], r = 480, s = [0, 960], l = 5, o = !1) {
constructor(e, t, i = CustPlatform.Mariko, n = 4, a = ["range: vMin ≤ x ≤ 960 (Zero is disabled)"], r = 480, s = [0, 960], l = 5, o = !1) {
super(e, t, i, n, a, r, s, l, o), this.id = e, this.name = t, this.platform = i, this.size = n, this.desc = a, this.defval = r, this.step = l, this.zeroable = o
}
createElement() {
@@ -214,6 +217,13 @@ var CustTable = [
"Anything above 800MV is considered UNSAFE (although it depends per frequency)"
], 800, [480, 1000], 1, !1),
new CustEntry("gpuVmin", "Mariko Minimum allowed GPU Voltage (mV)", CustPlatform.Mariko, 4, [
"Default: 600",
"This is the minimum voltage you can use in GPU UV3.",
"A higher Vmin is required for a higher max ram clock"
], 600, [480, 1000], 1, !1),
];
var AdvTable = [
@@ -222,96 +232,9 @@ var AdvTable = [
"Helps with stability at higher memory clock, with the only downside being slightly higher tempratures",
"Such functionality is completely useless on Erista units",
"Acceptable range : 0~9"
], 0, [0, 9], 1),
], 0, [0, 9], 1),
new AdvEntry("ramTimingPresetOne", "Primary RAM Timing Preset", CustPlatform.All, 4, [
"<b>WARNING</b>: Unstable timings can corrupt your nand",
"Select Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tRCD - tRP - tRAS (tRC = tRP + tRAS)",
"<b>0</b> : Do Not Adjust (2400Mhz: 12 - 12 - 28) (CUST_ADJ only)",
"<b>1</b> : 18 - 18 - 42 (Default timing)",
"<b>2</b> : 17 - 17 - 39",
"<b>3</b> : 16 - 16 - 36",
"<b>4</b> : 15 - 15 - 34",
"<b>5</b> : 14 - 14 - 32",
"<b>6</b> : 13 - 13 - 30"
], 1, [0, 6], 1),
new AdvEntry("ramTimingPresetTwo", "Secondary RAM Timing Preset", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tRRD - tFAW",
"<b>0</b> : Do Not Adjust (2400Mhz: 6.6 - 26.6) (CUST_ADJ only)",
"<b>1</b> : 10 - 40 (Default timing) (3733 specs)",
"<b>2</b> : 7.5 - 30 (4266 specs)",
"<b>3</b> : 6 - 24",
"<b>4</b> : 4 - 16",
"<b>5</b> : 3 - 12"
], 1, [0, 5], 1),
new AdvEntry("ramTimingPresetThree", "Secondary RAM Timing Preset", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tWR - tRTP",
"<b>0</b> : Do Not Adjust (2400Mhz: ?? - 5) (CUST_ADJ only)",
"<b>1</b> : 18 - 7.5 (Default timing)",
"<b>2</b> : 15 - 7.5",
"<b>3</b> : 15 - 6",
"<b>4</b> : 12 - 6",
"<b>5</b> : 12 - 4",
"<b>6</b> : 8 - 4"
], 1, [0, 6], 1),
new AdvEntry("ramTimingPresetFour", "Secondary RAM Timing Preset", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tRFC",
"<b>0</b> : Do Not Adjust (2400Mhz: 93.3) (CUST_ADJ only)",
"<b>1</b> : 140 (Default timing)",
"<b>2</b> : 120",
"<b>3</b> : 100",
"<b>4</b> : 80",
"<b>5</b> : 70",
"<b>6</b> : 60"
], 1, [0, 6], 1),
new AdvEntry("ramTimingPresetFive", "Secondary RAM Timing Preset", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Secondary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tWTR",
"<b>0</b> : Do Not Adjust (2400Mhz: ??) (CUST_ADJ only)",
"<b>1</b> : 10 (Default timing)",
"<b>2</b> : 8",
"<b>3</b> : 6",
"<b>4</b> : 4",
"<b>5</b> : 2",
"<b>6</b> : 1"
], 1, [0, 6], 1),
new AdvEntry("ramTimingPresetSix", "Tertiary RAM Timing Preset", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Tertiary Timing Preset for both AUTO_ADJ and CUSTOM_ADJ",
"Values are : tREFpb",
"<b>0</b> : Do Not Adjust (2400Mhz: 325) (CUST_ADJ only)",
"<b>1</b> : 488 (Default timing)",
"<b>2</b> : 976",
"<b>3</b> : 1952",
"<b>4</b> : 3256",
"<b>5</b> : MAX"
], 1, [0, 5], 1),
new AdvEntry("ramTimingPresetSeven", "Latency Decrement", CustPlatform.All, 4, [
"WARNING: Unstable timings can corrupt your nand",
"Latency decrement for both AUTO_ADJ and CUSTOM_ADJ",
"This preset decreases Write/Read related delays. Values are Write - Read",
"<b>0</b> : 0 - 0, Do Not Adjust for CUST_ADJ",
"<b>1</b> : '-2' - '-4'",
"<b>2</b> : '-4' - '-8'",
"<b>3</b> : '-6' - '-12'",
"<b>4</b> : '-8' - '-16'",
"<b>5</b> : '-10' - '-20'",
"<b>6</b> : '-12' - '-24'"
], 0, [0, 6], 1)
];
var GpuTable = [