-
Notifications
You must be signed in to change notification settings - Fork 81
/
WinAMDTweak.cpp
3365 lines (3314 loc) · 106 KB
/
WinAMDTweak.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
#define WIN32_LEAN_AND_MEAN
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "IOMap.h"
typedef WORD u16;
typedef DWORD u32;
typedef unsigned __int64 u64;
#define strcasecmp _strcmpi
#define VERSION "AMD Memory Tweak Windows CLI version 0.1.9\n"
#define AMD_TIMING_REGS_BASE_1 0x50200
#define AMD_TIMING_REGS_BASE_2 0x52200
#define AMD_TIMING_REGS_BASE_3 0x54200
#define AMD_TIMING_REGS_BASE_4 0x56200
typedef union {
u32 value;
struct {
u32 /*Reserved*/ : 8;
u32 MAN : 4;
u32 VEN : 4;
u32 : 16;
} rx;
struct {
u32 /*Reserved*/ : 24;
u32 MAN : 8;
} hbm;
} MANUFACTURER;
#define MANUFACTURER_ID 0x2A00
#define MANUFACTURER_ID_HBM 0x29C4
#define MANUFACTURER_ID_HBM2 0x5713C
typedef struct {
u32 frequency;
// TIMING1
u32 CL : 8;
u32 RAS : 8;
u32 RCDRD : 8;
u32 RCDWR : 8;
// TIMING2
u32 RCAb : 8;
u32 RCPb : 8;
u32 RPAb : 8;
u32 RPPb : 8;
// TIMING3
u32 RRDS : 8;
u32 RRDL : 8;
u32 /*Reserved*/ : 8;
u32 RTP : 8;
// TIMING4
u32 FAW : 8;
u32 /*Reserved*/ : 24;
// TIMING5
u32 CWL : 8;
u32 WTRS : 8;
u32 WTRL : 8;
u32 /*Reserved*/ : 8;
// TIMING6
u32 WR : 8;
u32 /*Reserved*/ : 24;
// TIMING7
u32 /*Reserved*/ : 8;
u32 RREFD : 8;
u32 /*Reserved*/ : 8;
u32 /*Reserved*/ : 8;
// TIMING8
u32 RDRDDD : 8;
u32 RDRDSD : 8;
u32 RDRDSC : 8;
u32 RDRDSCL : 6;
u32 /*Reserved*/ : 2;
// TIMING9
u32 WRWRDD : 8;
u32 WRWRSD : 8;
u32 WRWRSC : 8;
u32 WRWRSCL : 6;
u32 /*Reserved*/ : 2;
// TIMING10
u32 WRRD : 8;
u32 RDWR : 8;
u32 /*Reserved*/ : 16;
// PADDING
u32 /*Reserved*/ : 32;
// TIMING12
u32 REF : 16; // Determines at what rate refreshes will be executed. Vega RXboost :p
u32 /*Reserved*/ : 16;
// TIMING13
u32 MRD : 8;
u32 MOD : 8;
u32 /*Reserved*/ : 16;
// TIMING14
u32 XS : 16; // self refresh exit period
u32 /*Reserved*/ : 16;
// PADDING
u32 /*Reserved*/ : 32;
// TIMING16
u32 XSMRS : 16;
u32 /*Reserved*/ : 16;
// TIMING17
u32 PD : 4;
u32 CKSRE : 6;
u32 CKSRX : 6;
u32 /*Reserved*/ : 16;
// PADDING
u32 /*Reserved*/ : 32;
// PADDING
u32 /*Reserved*/ : 32;
// TIMING20
u32 RFCPB : 16;
u32 STAG : 8;
u32 /*Reserved*/ : 8;
// TIMING21
u32 XP : 8;
u32 /*Reserved*/ : 8;
u32 CPDED : 8;
u32 CKE : 8;
// TIMING22
u32 RDDATA : 8;
u32 WRLAT : 8;
u32 RDLAT : 8;
u32 WRDATA : 4;
u32 /*Reserved*/ : 4;
// TIMING23
u32 /*Reserved*/ : 16;
u32 CKESTAG : 8;
u32 /*Reserved*/ : 8;
// RFC
u32 RFC : 16;
u32 /*Reserved*/ : 16;
} HBM2_TIMINGS;
typedef union {
u32 value;
struct {
u32 DAT_DLY : 4; // Data output latency
u32 DQS_DLY : 4; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 DAT_2Y_DLY : 1; // Delay data (QDR Mode!) (ON/OFF)
u32 ADR_2Y_DLY : 1; // Delay addr (QDR Mode!) (ON/OFF)
u32 CMD_2Y_DLY : 1; // Delay cmd (QDR Mode!) (ON/OFF)
u32 OEN_DLY : 4; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 /*Reserved*/ : 2;
u32 ODT_DLY : 4; // On-Die-Termination latency
u32 ODT_EXT : 1; // On-Die-Termination enable after burst
u32 ADR_DLY : 1;
u32 CMD_DLY : 1;
u32 /*Reserved*/ : 1;
} rx;
struct {
u32 DAT_DLY : 5; // Data output latency
u32 DQS_DLY : 5; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 OEN_DLY : 5; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 CMD_DLY : 1;
u32 ADR_DLY : 1;
u32 /*Reserved*/ : 8;
} hbm;
} SEQ_WR_CTL_D0;
#define MC_SEQ_WR_CTL_D0 0x28bc // Chan 0 write commands
#define MC_SEQ_WR_CTL_D0_HBM 0x28EC
typedef union {
u32 value;
struct {
u32 DAT_DLY : 4; // Data output latency
u32 DQS_DLY : 4; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 DAT_2Y_DLY : 1; // Delay data (QDR Mode!) (ON/OFF)
u32 ADR_2Y_DLY : 1; // Delay addr (QDR Mode!) (ON/OFF)
u32 CMD_2Y_DLY : 1; // Delay cmd (QDR Mode!) (ON/OFF)
u32 OEN_DLY : 4; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 /*Reserved*/ : 2;
u32 ODT_DLY : 4; // On-Die-Termination latency
u32 ODT_EXT : 1; // On-Die-Termination enable after burst
u32 ADR_DLY : 1;
u32 CMD_DLY : 1;
u32 : 1;
} rx;
struct {
u32 DAT_DLY : 5; // Data output latency
u32 DQS_DLY : 5; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 OEN_DLY : 5; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 CMD_DLY : 1;
u32 ADR_DLY : 1;
u32 /*Reserved*/ : 8;
} hbm;
} SEQ_WR_CTL_D1;
#define MC_SEQ_WR_CTL_D1 0x28c0 // Chan 1 write commands
#define MC_SEQ_WR_CTL_D1_HBM 0x28F4
typedef union {
u32 value;
struct {
u32 DAT_DLY : 5; // Data output latency
u32 DQS_DLY : 5; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 OEN_DLY : 5; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 CMD_DLY : 1;
u32 ADR_DLY : 1;
u32 /*Reserved*/ : 8;
};
} SEQ_WR_CTL_D2;
#define MC_SEQ_WR_CTL_D2_HBM 0x28FC
typedef union {
u32 value;
struct {
u32 DAT_DLY : 5; // Data output latency
u32 DQS_DLY : 5; // DQS Latency
u32 DQS_XTR : 1; // Write Preamble (ON/OFF)
u32 OEN_DLY : 5; // Write cmd enable Latency
u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..)
u32 OEN_SEL : 2;
u32 CMD_DLY : 1;
u32 ADR_DLY : 1;
u32 /*Reserved*/ : 8;
};
} SEQ_WR_CTL_D3;
#define MC_SEQ_WR_CTL_D3_HBM 0x2904
typedef union {
u32 value;
struct {
u32 THRESH : 3; // Threshold
u32 /*Reserved*/ : 1;
u32 LEVEL : 3; // Level
u32 PWRDOWN : 1; // PWRDOWN
u32 SHUTDOWN : 3; // SHUTDOWN
u32 EN_SHUTDOWN : 1; // EN_SHUTDOWN
u32 OVERSAMPLE : 2;
u32 AVG_SAMPLE : 1;
u32 /*Reserved*/ : 17;
};
} THERMAL_THROTTLE;
#define MC_THERMAL_THROTTLE 0x2ACC // Thermal Throttle Control
typedef union {
u32 value;
struct {
u32 CKSRE : 3; // Valid clock requirement after CKSRE
u32 /*Reserved*/ : 1;
u32 CKSRX : 3; // Valid clock requirement before CKSRX
u32 /*Reserved*/ : 1;
u32 CKE_PULSE : 4; // Minimum CKE pulse
u32 CKE : 6;
u32 SEQ_IDLE : 3; // idle before deassert rdy to arb
u32 /*Reserved*/ : 2;
u32 CKE_PULSE_MSB : 1; // Minimum CKE pulse msb
u32 SEQ_IDLE_SS : 8; // idle before deassert rdy to arb at ss
} rx;
struct {
u32 CKSRE : 3; // Valid clock requirement after CKSRE
u32 CKSRX : 3; // Valid clock requirement before CKSRX
u32 CKE_PULSE : 5; // Minimum CKE pulse
u32 CKE : 8;
u32 SEQ_IDLE : 3; // idle before deassert rdy to arb
u32 SEQ_IDLE_SS : 8; // idle before deassert rdy to arb at ss
u32 /*Reserved*/ : 2;
} hbm;
} SEQ_PMG_TIMING;
#define MC_SEQ_PMG_TIMING 0x28B0 // Power Management
#define MC_SEQ_PMG_TIMING_HBM 0x28C4 // Power Management
typedef union {
u32 value;
struct {
u32 RCDW : 5; // # of cycles from active to write
u32 RCDWA : 5; // # of cycles from active to write with auto-precharge
u32 RCDR : 5; // # of cycles from active to read
u32 RCDRA : 5; // # of cycles from active to read with auto-precharge
u32 RRD : 4; // # of cycles from active bank a to active bank b
u32 RC : 7; // # of cycles from active to active/auto refresh
u32 /*Reserved*/ : 1;
};
} SEQ_RAS_TIMING;
#define MC_SEQ_RAS_TIMING 0x28A0
#define MC_SEQ_RAS_TIMING_HBM 0x28A4
typedef union {
u32 value;
struct {
u32 NOPW : 2; // Extra cycle(s) between successive write bursts
u32 NOPR : 2; // Extra cycle(s) between successive read bursts
u32 R2W : 5; // Read to write turn around time
u32 CCDL : 3; // Cycles between r/w from bank A to r/w bank B
u32 R2R : 4; // Read to read time
u32 W2R : 5; // Write to read turn around time
u32 /*Reserved*/ : 3;
u32 CL : 5; // CAS to data return latency (0 - 20)
u32 /*Reserved*/ : 3;
} rx;
struct {
u32 NOPW : 2; // Extra cycle(s) between successive write bursts
u32 NOPR : 2; // Extra cycle(s) between successive read bursts
u32 R2W : 5; // Read to write turn
u32 CCDL : 3; // Cycles between r/w from bank A to r/w bank B
u32 R2R : 4; // Read to read time
u32 W2R : 5; // Write to read turn
u32 CL : 5; // CAS to data return latency
u32 /*Reserved*/ : 6;
} hbm;
} SEQ_CAS_TIMING;
#define MC_SEQ_CAS_TIMING 0x28A4
#define MC_SEQ_CAS_TIMING_HBM 0x28AC
typedef union {
u32 value;
struct {
u32 RP_WRA : 6; // From write with auto-precharge to active
u32 /*Reserved*/ : 2;
u32 RP_RDA : 6; // From read with auto-precharge to active
u32 /*Reserved*/ : 1;
u32 TRP : 5; // Precharge command period
u32 RFC : 9; // Auto-refresh command period
u32 /*Reserved*/ : 3;
} rx;
struct {
u32 RP_WRA : 8; // From write with auto-precharge to active
u32 RP_RDA : 7; // From read with auto-precharge to active
u32 TRP : 5; // Precharge command period
u32 RFC : 9; // Auto-refresh command period
u32 /*Reserved*/ : 3;
} r9;
struct {
u32 RP_WRA : 6; // From write with auto-precharge to active
u32 RP_RDA : 6; // From read with auto-precharge to active
u32 TRP : 5; // Precharge command period
u32 RFC : 7; // Auto-refresh command period
u32 RRDL : 4;
u32 MRD : 4;
} hbm;
} SEQ_MISC_TIMING;
#define MC_SEQ_MISC_TIMING 0x28A8
#define MC_SEQ_MISC_TIMING_HBM 0x28B4
typedef union {
u32 value;
struct {
u32 PA2RDATA : 3; // DDR4
u32 /*Reserved*/ : 1;
u32 PA2WDATA : 3; // DDR4
u32 /*Reserved*/ : 1;
u32 FAW : 5; // The time window in wich four activates are allowed in the same rank
u32 REDC : 3; // Min 0, Max 7
u32 WEDC : 5; // Min 0, Max 7
u32 T32AW : 4; // Max 12
u32 /*Reserved*/ : 3;
u32 WDATATR : 4; // WCMD timing for write training
} rx;
struct {
u32 PA2RDATA : 3;
u32 PA2WDATA : 3;
u32 FAW : 5; // The time window in wich four activates are allowed in the same rank
u32 WPAR : 3;
u32 RPAR : 3;
u32 T32AW : 4;
u32 WDATATR : 4;
u32 /*Reserved*/ : 7;
} hbm;
} SEQ_MISC_TIMING2;
#define MC_SEQ_MISC_TIMING2 0x28AC
#define MC_SEQ_MISC_TIMING2_HBM 0x28BC
// Mode Registers (JESD212 for more info)
typedef union {
u32 value;
struct {
// MR0
u32 WL : 3; // Write Latency
u32 CL : 4; // CAS Latency
u32 TM : 1;
u32 WR : 4; // Write Recovery
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
// MR1
u32 DS : 2; // Driver Strength (0 = Auto Calibration)
u32 DT : 2; // Data Termination (0 = Disabled)
u32 ADR : 2; // ADR CMD Termination (0 = CKE value at Reset)
u32 CAL : 1; // Calibration Update
u32 PLL : 1;
u32 RDBI : 1; // Read DBI (ON/OFF)
u32 WDBI : 1; // Write DBI (ON/OFF)
u32 ABI : 1; // (ON/OFF)
u32 RESET : 1; // PLL Reset
u32 BA_0 : 1;
u32 BA_1 : 1;
u32 BA_2 : 1;
u32 BA_3 : 1;
} rx;
struct {
// MR0
u32 DBR : 1; // Read DBIac (OFF/ON)
u32 DBW : 1; // Write DBIac (OFF/ON)
u32 TCSR : 1; // Temperature Compensated Self Refresh (OFF/ON)
u32 /*Reserved*/ : 1;
u32 DQR : 1; // DQ Bus Read Parity (OFF/ON)
u32 DQW : 1; // DQ Bus Write Parity (OFF/ON)
u32 ADD_PAR : 1; // Address, Command Bus Parity for Row, Column Bus (OFF/ON)
u32 TM : 1; // Vendor Specific (NORMAL/TEST)
// MR1
u32 WR : 5; // Write Recovery
u32 NDS : 3; // Nominal Driver Strength
// MR2
u32 WL : 3; // Write Latency
u32 RL : 5; // Read Latency
// MR3
u32 APRAS : 6; // Activate to Precharge RAS
u32 BG : 1; // Bank Group
u32 BL : 1; // Burst Length
} hbm;
} SEQ_MISC1;
#define MC_SEC_MISC1 0x2A04
#define MC_SEC_MISC1_HBM 0x29C8 // Beta (untested)
typedef union {
u32 value;
struct {
// MR2
u32 OCD_DWN : 3; // OCD Pulldown Driver Offset
u32 OCD_UP : 3; // OCD Pullup Driver Offset
u32 WCK : 3; // Data and WCK Termination Offset
u32 ADR : 3; // ADR/CMD Termination Offset
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
// MR3
u32 SR : 2; // Self Refresh (0 = 32ms)
u32 WCK01 : 1; // (OFF/ON)
u32 WCK23 : 1; // (OFF/ON)
u32 WCK2CK : 1; // (OFF/ON)
u32 RDQS : 1; // (OFF/ON)
u32 INFO : 2; // Dram Info (0=Off)
u32 WCK2 : 2; // WCK Termination
u32 BG : 2; // Bank Groups
u32 BA_0 : 1;
u32 BA_1 : 1;
u32 BA_2 : 1;
u32 BA_3 : 1;
};
} SEQ_MISC2;
#define MC_SEC_MISC2 0x2A08
typedef union {
u32 value;
struct {
// MR4
u32 EDCHP : 4; // EDC Hold Pattern
u32 CRCWL : 3; // CRC Write Latency
u32 CRCRL : 2; // CRC Read Latency
u32 RDCRC : 1; // (ON/OFF)
u32 WRCRC : 1; // (ON/OFF)
u32 EDC : 1; // (OFF/ON)
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
// MR5
u32 LP1 : 1; // (OFF/ON)
u32 LP2 : 1; // (OFF/ON)
u32 LP3 : 1; // (OFF/ON)
u32 PLL : 3; // PLL/DLL Band-Width (0 = Vendor Specific)
u32 RAS : 6;
u32 BA_0 : 1;
u32 BA_1 : 1;
u32 BA_2 : 1;
u32 BA_3 : 1;
};
} SEQ_MISC3;
#define MC_SEC_MISC3 0x2A2C
typedef union {
u32 value;
struct {
// MR6
u32 WCK : 1; // WCK2CK Pin
u32 VREFD_M : 1; // VREFD Merge
u32 A_VREFD : 1; // Auto VREFD Training
u32 VREFD : 1;
u32 VREFD_O : 4; // Offset rows M-U
u32 VREFD_0_2 : 4; // Offset rows A-F
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
// MR7
u32 PLL_STD : 1; // PLL Standby (OFF/ON)
u32 PLL_FL : 1; // PLL Fast Lock (OFF/ON)
u32 PLL_DEL : 1; // PLL Delay Compensation (OFF/ON)
u32 LF_MOD : 1; // Low Frequency Mode (OFF/ON)
u32 AUTO : 1; // WCK2CK Auto Sync (OFF/ON)
u32 DQ : 1; // DQ Preamble (OFF/ON)
u32 TEMP : 1; // Temp Sensor (OFF/ON)
u32 HALF : 1; // Half VREFD
u32 VDD_R : 2; // VDD Range
u32 RFU : 2;
u32 BA_0 : 1;
u32 BA_1 : 1;
u32 BA_2 : 1;
u32 BA_3 : 1;
};
} SEQ_MISC4;
#define MC_SEC_MISC4 0x2A30
typedef union {
u32 value;
struct {
// MR15
u32 /*Reserved*/ : 8;
u32 MRE0 : 1; // Mode Register 0-14 Enable MF=0 (ON/OFF)
u32 MRE1 : 1; // Mode Register 0-14 Enable MF=1 (ON/OFF)
u32 ADT : 1; // Address Training (OFF/ON)
u32 RFU : 1;
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
u32 /*Reserved*/ : 16;
};
} SEQ_MISC7;
#define MC_SEC_MISC7 0x2A64
typedef union {
u32 value;
struct {
// MR8
u32 CLEHF : 1; // Cas Latency Extra High Frequency (0 = normal range, 1 = Extended)
u32 WREHF : 1; // Write Recovery Extra High Frequency (0 = normal range, 1 = Extended)
u32 RFU : 10;
u32 BA0 : 1;
u32 BA1 : 1;
u32 BA2 : 1;
u32 BA3 : 1;
u32 /*Reserved*/ : 16;
};
} SEQ_MISC8;
#define MC_SEC_MISC8 0x297C
typedef union {
u32 value;
struct {
u32 ACTRD : 8;
u32 ACTWR : 8;
u32 RASMACTRD : 8;
u32 RASMACTWR : 8;
};
} ARB_DRAM_TIMING;
#define MC_ARB_DRAM_TIMING 0x2774
typedef union {
u32 value;
struct {
u32 RAS2RAS : 8;
u32 RP : 8;
u32 WRPLUSRP : 8;
u32 BUS_TURN : 8;
};
} ARB_DRAM_TIMING2;
#define MC_ARB_DRAM_TIMING2 0x2778
typedef union {
u32 value;
struct {
u32 REF : 16;
u32 /*Reserved*/ : 16;
};
} ARB_RFSH_RATE;
#define MC_ARB_RFSH_RATE 0x27b0 // The famous RXBoost :p
typedef union {
u32 value;
struct {
u32 TWT2RT : 5; // # of cycles from write to read train command
u32 TARF2T : 5; // # of cycles from auto refresh to train command
u32 TT2ROW : 5; // # of cycles between row charge command
u32 TLD2LD : 5; // # of cycles between LDFF command
u32 /*Reserved*/ : 12;
};
} SEQ_TRAINING;
#define MC_SEQ_TRAINING 0x2900
typedef union {
u32 value;
struct {
u32 ENB : 1;
u32 CNT : 5;
u32 TRC : 16;
u32 /*Reserved*/ : 10;
};
} SEQ_ROW_HAMMER;
#define MC_SEQ_ROW_HAMMER 0x27b0
static const char* LookupDeviceName(u16 device_id)
{
struct {
u16 vendor_id;
u16 device_id;
const char* name;
} KnownGPUs[] = {
{ 0x1002, 0x66af, "Radeon VII" },
{ 0x1002, 0x687f, "Vega 10 XL/XT [Radeon RX Vega 56/64]" },
{ 0x1002, 0x6867, "Vega 10 XL [Radeon Pro Vega 56]" },
{ 0x1002, 0x6863, "Vega 10 XTX [Radeon Vega Frontier Edition]" },
{ 0x1002, 0x67df, "Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]" },
{ 0x1002, 0x67c4, "Ellesmere [Radeon Pro WX 7100]" },
{ 0x1002, 0x67c7, "Ellesmere [Radeon Pro WX 5100]" },
{ 0x1002, 0x67ef, "Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X]" },
{ 0x1002, 0x67ff, "Baffin [Radeon RX 550 640SP / RX 560/560X]" },
{ 0x1002, 0x7300, "Fiji [Radeon R9 FURY / NANO Series]" },
{ 0x1002, 0x67b0, "Hawaii XT / Grenada XT [Radeon R9 290X/390X]" },
{ 0x1002, 0x67b1, "Hawaii PRO [Radeon R9 290/390]" },
{ 0x1002, 0x6798, "Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X]" },
{ 0x1002, 0x679a, "Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]" },
};
for (int i = 0; i < _countof(KnownGPUs); i++)
{
if (/*(KnownGPUs[i].vendor_id == dev->vendor_id) && */(KnownGPUs[i].device_id == device_id))
{
return KnownGPUs[i].name;
}
}
return "";
}
static bool IsRelevantDeviceID(u16 device_id)
{
return
(device_id == 0x66af) || // Radeon VII
(device_id == 0x687f) || // Vega 10 XL/XT [Radeon RX Vega 56/64]
(device_id == 0x6867) || // Vega 10 XL [Radeon Pro Vega 56]
(device_id == 0x6863) || // Vega 10 XTX [Radeon Vega Frontier Edition]
(device_id == 0x67df) || // Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]
(device_id == 0x67c4) || // Ellesmere [Radeon Pro WX 7100]
(device_id == 0x67c7) || // Ellesmere [Radeon Pro WX 5100]
(device_id == 0x67ef) || // Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X]
(device_id == 0x67ff) || // Baffin [Radeon RX 550 640SP / RX 560/560X]
(device_id == 0x7300) || // Fiji [Radeon R9 FURY / NANO Series]
(device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X]
(device_id == 0x67b1) || // Hawaii PRO [Radeon R9 290/390]
(device_id == 0x6798) || // Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X]
(device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
}
static bool IsR9(u16 device_id)
{
return
(device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X]
(device_id == 0x67b1) || // Hawaii PRO [Radeon R9 290/390]
(device_id == 0x6798) || // Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X]
(device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]
}
typedef enum { GDDR5, HBM, HBM2 } MemoryType;
static MemoryType DetermineMemoryType(u16 device_id)
{
struct {
u16 vendor_id;
u16 device_id;
MemoryType memory_type;
} KnownGPUs[] = {
/* Vega20 - Radeon VII */
{ 0x1002, 0x66a0, HBM2 }, // "Radeon Instinct", CHIP_VEGA20
{ 0x1002, 0x66a1, HBM2 }, // "Radeon Vega20", CHIP_VEGA20
{ 0x1002, 0x66a2, HBM2 }, // "Radeon Vega20", CHIP_VEGA20
{ 0x1002, 0x66a3, HBM2 }, // "Radeon Vega20", CHIP_VEGA20
{ 0x1002, 0x66a4, HBM2 }, // "Radeon Vega20", CHIP_VEGA20
{ 0x1002, 0x66a7, HBM2 }, // "Radeon Pro Vega20", CHIP_VEGA20
{ 0x1002, 0x66af, HBM2 }, // "Radeon VII", CHIP_VEGA20
/* Vega */
{ 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega", CHIP_VEGA10
{ 0x1002, 0x6863, HBM2 }, // "Radeon Vega Frontier Edition", CHIP_VEGA10
/* Fury/Nano Support will Follow later */
{ 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI
};
for (int i = 0; i < _countof(KnownGPUs); i++)
{
if (/*(KnownGPUs[i].vendor_id == dev->vendor_id) && */(KnownGPUs[i].device_id == device_id))
{
return KnownGPUs[i].memory_type;
}
}
return GDDR5;
}
typedef struct {
char log[1000];
bool modify[25];
MANUFACTURER man;
// HBM2
HBM2_TIMINGS hbm2;
// GDDR5 && HBM1
SEQ_WR_CTL_D0 ctl1;
SEQ_WR_CTL_D1 ctl2;
SEQ_PMG_TIMING pmg;
SEQ_RAS_TIMING ras;
SEQ_CAS_TIMING cas;
SEQ_MISC_TIMING misc;
SEQ_MISC_TIMING2 misc2;
SEQ_MISC1 smisc1;
SEQ_MISC2 smisc2;
SEQ_MISC3 smisc3;
SEQ_MISC4 smisc4;
SEQ_MISC7 smisc7;
SEQ_MISC8 smisc8;
ARB_DRAM_TIMING dram1;
ARB_DRAM_TIMING2 dram2;
ARB_RFSH_RATE ref;
SEQ_TRAINING train;
// HBM1 Specific
SEQ_ROW_HAMMER ham;
THERMAL_THROTTLE throt;
SEQ_WR_CTL_D2 ctl3;
SEQ_WR_CTL_D3 ctl4;
} GPU;
static u64 ParseIndicesArg(const char* arg)
{
char buffer[1000];
strcpy(buffer, arg);
u64 mask = 0;
char* token = strtok(buffer, ",");
while (token)
{
while (*token && isspace(*token)) token++;
char* endptr;
unsigned long index = strtoul(token, &endptr, 10);
while (*endptr && isspace(*endptr)) endptr++;
int err = errno;
if ((endptr == token) || *endptr || (errno == EINVAL) || (errno == ERANGE) || (index >= 64))
{
printf("Invalid GPU index specified.\n");
exit(EXIT_FAILURE);
}
mask |= ((u64)1 << index);
token = strtok(NULL, ",");
}
return mask;
}
static bool ParseNumericArg(int argc, const char* argv[], int& i, const char* arg, u32 & value)
{
if (!strcasecmp(arg, argv[i]))
{
if (i == (argc - 1))
{
printf("Argument \"%s\" requires a parameter.\n", argv[i]);
exit(EXIT_FAILURE);
}
i++;
value = strtoul(argv[i], 0, 10);
if ((errno == EINVAL) || (errno == ERANGE))
{
printf("Failed to parse parameter %s %s\n", argv[i - 1], argv[i]);
exit(EXIT_FAILURE);
}
return true;
}
return false;
}
static void PrintCurrentValues(VGAChip * chip, GPU * gpu)
{
if (DetermineMemoryType(chip->device_id) == HBM2)
{
HBM2_TIMINGS current = gpu->hbm2;
MANUFACTURER man = gpu->man;
printf("Memory state: ");
printf((current.frequency == 0x118) ? "800MHz" :
(current.frequency == 0x11C) ? "1000MHz" :
(current.frequency == 0x11E) ? "1200MHz" : "unknown");
printf("Memory: ");
printf((man.hbm.MAN == 0x63) ? " Hynix HBM2" :
(man.hbm.MAN == 0x61) ? " Samsung HBM2" : " unknown");
printf("Timing 1\t");
printf(" CL: %d\t", current.CL);
printf(" RAS: %d\t", current.RAS);
printf(" RCDRD: %d\t", current.RCDRD);
printf(" RCDWR: %d\n", current.RCDWR);
printf("Timing 2\t");
printf(" RCAb (RC): %d\t", current.RCAb);
printf(" RCPb (RC): %d\t", current.RCPb);
printf(" RPAb (RP): %d\t", current.RPAb);
printf(" RPPb (RP): %d\n", current.RPPb);
printf("Timing 3\t");
printf(" RRDS: %d\t", current.RRDS);
printf(" RRDL: %d\t", current.RRDL);
printf(" RTP: %d\n", current.RTP);
printf("Timing 4\t");
printf(" FAW: %d\n", current.FAW);
printf("Timing 5\t");
printf(" CWL: %d\t", current.CWL);
printf(" WTRS: %d\t", current.WTRS);
printf(" WTRL: %d\n", current.WTRL);
printf("Timing 6\t");
printf(" WR: %d\n", current.WR);
printf("Timing 7\t");
printf(" RREFD: %d\n", current.RREFD);
printf("Timing 8\t");
printf(" RDRDDD: %d\t", current.RDRDDD);
printf(" RDRDSD: %d\t", current.RDRDSD);
printf(" RDRDSC: %d\t", current.RDRDSC);
printf(" RDRDSCL: %d\n", current.RDRDSCL);
printf("Timing 9\t");
printf(" WRWRDD: %d\t", current.WRWRDD);
printf(" WRWRSD: %d\t", current.WRWRSD);
printf(" WRWRSC: %d\t", current.WRWRSC);
printf(" WRWRSCL: %d\n", current.WRWRSCL);
printf("Timing 10\t");
printf(" WRRD: %d\t", current.WRRD);
printf(" RDWR: %d\n", current.RDWR);
printf("Timing 12\t");
printf(" REF: %d\n", current.REF);
printf("Timing 13\t");
printf(" MRD: %d\t", current.MRD);
printf(" MOD: %d\n", current.MOD);
printf("Timing 14\t");
printf(" XS: %d\n", current.XS);
printf("Timing 16\t");
printf(" XSMRS: %d\n", current.XSMRS);
printf("Timing 17\t");
printf(" PD: %d\t", current.PD);
printf(" CKSRE: %d\t", current.CKSRE);
printf(" CKSRX: %d\n", current.CKSRX);
printf("Timing 20\t");
printf(" RFCPB: %d\t", current.RFCPB);
printf(" STAG: %d\n", current.STAG);
printf("Timing 21\t");
printf(" XP: %d\t", current.XP);
printf(" CPDED: %d\t", current.CPDED);
printf(" CKE: %d\n", current.CKE);
printf("Timing 22\t");
printf(" RDDATA: %d\t", current.RDDATA);
printf(" WRLAT: %d\t", current.WRLAT);
printf(" RDLAT: %d\t", current.RDLAT);
printf(" WRDATA: %d\n", current.WRDATA);
printf("Timing 23\t");
printf(" CKESTAG: %d\n", current.CKESTAG);
printf("RFC Timing\t");
printf(" RFC: %d\n", current.RFC);
printf("\n");
}
else if (DetermineMemoryType(chip->device_id) == HBM) {
MANUFACTURER man = gpu->man;
printf((man.hbm.MAN == 0x63) ? " Hynix HBM" :
(man.hbm.MAN == 0x61) ? " Samsung HBM" : " Unknown");
printf("\n\nChannel 0's write command parameters:\n");
printf(" \t DAT_DLY: %d\t", gpu->ctl1.hbm.DAT_DLY);
printf(" DQS_DLY: %d\t", gpu->ctl1.hbm.DQS_DLY);
printf(" DQS_XTR: %d\t", gpu->ctl1.hbm.DQS_XTR);
printf(" OEN_DLY: %d\n", gpu->ctl1.hbm.OEN_DLY);
printf(" \t OEN_EXT: %d\t", gpu->ctl1.hbm.OEN_EXT);
printf(" OEN_SEL: %d\t", gpu->ctl1.hbm.OEN_SEL);
printf(" CMD_DLY: %d\t", gpu->ctl1.hbm.CMD_DLY);
printf(" ADR_DLY: %d\n", gpu->ctl1.hbm.ADR_DLY);
printf("Channel 1's write command parameters:\n");
printf(" \t DAT_DLY: %d\t", gpu->ctl2.hbm.DAT_DLY);
printf(" DQS_DLY: %d\t", gpu->ctl2.hbm.DQS_DLY);
printf(" DQS_XTR: %d\t", gpu->ctl2.hbm.DQS_XTR);
printf(" OEN_DLY: %d\n", gpu->ctl2.hbm.OEN_DLY);
printf(" \t OEN_EXT: %d\t", gpu->ctl2.hbm.OEN_EXT);
printf(" OEN_SEL: %d\t", gpu->ctl2.hbm.OEN_SEL);
printf(" CMD_DLY: %d\t", gpu->ctl2.hbm.CMD_DLY);
printf(" ADR_DLY: %d\n", gpu->ctl2.hbm.ADR_DLY);
printf("Power Mangement related timings:\n");
printf(" \t CKSRE: %d\t", gpu->pmg.hbm.CKSRE);
printf(" CKSRX: %d\t", gpu->pmg.hbm.CKSRX);
printf(" CKE_PULSE: %d\t", gpu->pmg.hbm.CKE_PULSE);
printf(" CKE: %d\t", gpu->pmg.hbm.CKE);
printf(" SEQ_IDLE: %d\n", gpu->pmg.hbm.SEQ_IDLE);
printf("RAS related timings:\n");
printf(" \t RC: %d\t", gpu->ras.RC);
printf(" RRD: %d\t", gpu->ras.RRD);
printf(" RCDRA: %d\t", gpu->ras.RCDRA);
printf(" RCDR: %d\t", gpu->ras.RCDR);
printf(" RCDWA: %d\t", gpu->ras.RCDWA);
printf(" RCDW: %d\n", gpu->ras.RCDW);
printf("CAS related timings:\n");
printf(" \t CL: %d\t", gpu->cas.hbm.CL);
printf(" W2R: %d\t", gpu->cas.hbm.W2R);
printf(" R2R: %d\t", gpu->cas.hbm.R2R);
printf(" CCDL: %d\t", gpu->cas.hbm.CCDL);
printf(" R2W: %d\t", gpu->cas.hbm.R2W);
printf(" NOPR: %d\t", gpu->cas.hbm.NOPR);
printf(" NOPW: %d\n", gpu->cas.hbm.NOPW);
printf("Misc. DRAM timings:\n");
printf(" \t MRD: %d\t", gpu->misc.hbm.MRD);
printf(" RRDL: %d\t", gpu->misc.hbm.RRDL);
printf(" RFC: %d\t", gpu->misc.hbm.RFC);
printf(" TRP: %d\t", gpu->misc.hbm.TRP);
printf(" RP_RDA: %d\t", gpu->misc.hbm.RP_RDA);
printf(" RP_WRA: %d\n", gpu->misc.hbm.RP_WRA);
printf("Misc2. DRAM timings:\n");
printf(" \t WDATATR: %d\t", gpu->misc2.hbm.WDATATR);
printf(" T32AW: %d\t", gpu->misc2.hbm.T32AW);
printf(" RPAR: %d\t", gpu->misc2.hbm.RPAR);
printf(" WPAR: %d\t", gpu->misc2.hbm.WPAR);
printf(" FAW: %d\t", gpu->misc2.hbm.FAW);
printf(" PA2WDATA: %d\t", gpu->misc2.hbm.PA2WDATA);
printf(" PA2RDATA: %d\n", gpu->misc2.hbm.PA2RDATA);
printf("Mode Register 0:\n");
printf(" \t DBR: %d\t", gpu->smisc1.hbm.DBR);
printf(" DBW: %d\t", gpu->smisc1.hbm.DBW);
printf(" TCSR: %d\t", gpu->smisc1.hbm.TCSR);
printf(" DQR: %d\n", gpu->smisc1.hbm.DQR);
printf(" \t DQW: %d\t ", gpu->smisc1.hbm.DQW);
printf(" ADD_PAR: %d\t ", gpu->smisc1.hbm.ADD_PAR);
printf(" TM: %d\n", gpu->smisc1.hbm.TM);
printf("Mode Register 1:\n");
printf(" \t WR: %d \t", gpu->smisc1.hbm.WR);
printf(" NDS: %d\n", gpu->smisc1.hbm.NDS);
printf("Mode Register 2:\n");
printf(" \t WL: %d \t", gpu->smisc1.hbm.WL);
printf(" RL: %d\n", gpu->smisc1.hbm.RL);
printf("Mode Register 3:\n");
printf(" \t APRAS: %d \t", gpu->smisc1.hbm.APRAS);
printf(" BG: %d \t", gpu->smisc1.hbm.BG);
printf(" BL: %d\n", gpu->smisc1.hbm.BL);
printf("Refresh Interval:\n");
printf(" \t REF: %d\n", gpu->ref.REF);
printf("Thermal Throttle Control:\n");
printf(" \t THRESH: %d\t", gpu->throt.THRESH);
printf(" LEVEL: %d\t", gpu->throt.LEVEL);
printf(" PWRDOWN: %d\t", gpu->throt.PWRDOWN);
printf(" SHUTDOWN: %d\t", gpu->throt.SHUTDOWN);
printf(" EN_SHUTDOWN: %d\t", gpu->throt.EN_SHUTDOWN);
printf(" OVERSAMPLE: %d\t", gpu->throt.OVERSAMPLE);
printf(" AVG_SAMPLE: %d\n", gpu->throt.AVG_SAMPLE);
printf("Hammer:\n");
printf(" \t ENB: %d\t", gpu->ham.ENB);
printf(" CNT: %d\t", gpu->ham.CNT);
printf(" TRC: %d\n", gpu->ham.TRC);
}
else // GDDR5
{
MANUFACTURER man = gpu->man;
printf((man.rx.MAN == 0x1) ? " Samsung GDDR5" :
(man.rx.MAN == 0x3) ? " Elpida GDDR5" :
(man.rx.MAN == 0x6) ? " Hynix GDDR5" :
(man.rx.MAN == 0xf) ? " Micron GDDR5" : " Unknown");
printf("\n\nChannel 0's write command parameters:\n");
printf(" \t DAT_DLY: %d\t", gpu->ctl1.rx.DAT_DLY);
printf(" DQS_DLY: %d\t", gpu->ctl1.rx.DQS_DLY);
printf(" DQS_XTR: %d\t", gpu->ctl1.rx.DQS_XTR);
printf(" DAT_2Y_DLY: %d\t", gpu->ctl1.rx.DAT_2Y_DLY);
printf(" ADR_2Y_DLY: %d\t", gpu->ctl1.rx.ADR_2Y_DLY);
printf(" CMD_2Y_DLY: %d\t", gpu->ctl1.rx.CMD_2Y_DLY);
printf(" OEN_DLY: %d\n", gpu->ctl1.rx.OEN_DLY);
printf(" \t OEN_EXT: %d\t", gpu->ctl1.rx.OEN_EXT);
printf(" OEN_SEL: %d\t", gpu->ctl1.rx.OEN_SEL);
printf(" ODT_DLY: %d\t", gpu->ctl1.rx.ODT_DLY);
printf(" ODT_EXT: %d\t", gpu->ctl1.rx.ODT_EXT);
printf(" ADR_DLY: %d\t", gpu->ctl1.rx.ADR_DLY);
printf(" CMD_DLY: %d\n", gpu->ctl1.rx.CMD_DLY);
printf("Channel 1's write command parameters:\n");
printf(" \t DAT_DLY: %d\t", gpu->ctl2.rx.DAT_DLY);
printf(" DQS_DLY: %d\t", gpu->ctl2.rx.DQS_DLY);
printf(" DQS_XTR: %d\t", gpu->ctl2.rx.DQS_XTR);
printf(" DAT_2Y_DLY: %d\t", gpu->ctl2.rx.DAT_2Y_DLY);
printf(" ADR_2Y_DLY: %d\t", gpu->ctl2.rx.ADR_2Y_DLY);
printf(" CMD_2Y_DLY: %d\t", gpu->ctl2.rx.CMD_2Y_DLY);
printf(" OEN_DLY: %d\n", gpu->ctl2.rx.OEN_DLY);
printf(" \t OEN_EXT: %d\t", gpu->ctl2.rx.OEN_EXT);
printf(" OEN_SEL: %d\t", gpu->ctl2.rx.OEN_SEL);
printf(" ODT_DLY: %d\t", gpu->ctl2.rx.ODT_DLY);
printf(" ODT_EXT: %d\t", gpu->ctl2.rx.ODT_EXT);
printf(" ADR_DLY: %d\t", gpu->ctl2.rx.ADR_DLY);
printf(" CMD_DLY: %d\n", gpu->ctl2.rx.CMD_DLY);
printf("Power Mangement related timings:\n");
printf(" \t CKSRE: %d\t", gpu->pmg.rx.CKSRE);
printf(" CKSRX: %d\t", gpu->pmg.rx.CKSRX);
printf(" CKE_PULSE: %d\t", gpu->pmg.rx.CKE_PULSE);
printf(" CKE: %d\t", gpu->pmg.rx.CKE);
printf(" SEQ_IDLE: %d\n", gpu->pmg.rx.SEQ_IDLE);
printf("RAS related timings:\n");
printf(" \t RC: %d\t", gpu->ras.RC);
printf(" RRD: %d\t", gpu->ras.RRD);
printf(" RCDRA: %d\t", gpu->ras.RCDRA);
printf(" RCDR: %d\t", gpu->ras.RCDR);
printf(" RCDWA: %d\t", gpu->ras.RCDWA);
printf(" RCDW: %d\n", gpu->ras.RCDW);