From 11ddb2f767ceee25f8f782e7825afad71b45a686 Mon Sep 17 00:00:00 2001 From: Adamant Mischke Date: Tue, 23 Jul 2019 18:02:23 -0500 Subject: [PATCH 1/3] adds rx580 from china capability --- README.md | 73 +- gui/x64/AMD Memory Tweak.exe | Bin 0 -> 340480 bytes gui/x64/IOMap.sys | Bin 0 -> 32016 bytes gui/x64/IOMap64.sys | Bin 0 -> 34064 bytes gui/x86/AMD Memory Tweak.exe | Bin 0 -> 340992 bytes gui/x86/IOMap.sys | Bin 0 -> 32016 bytes gui/x86/IOMap64.sys | Bin 0 -> 34064 bytes linux/AmdMemTweak.cpp | 3195 +++++++++++++++++++++++++++------- win/WinAMDTweak.cpp | 2453 +++++++++++++++++++++++--- 9 files changed, 4814 insertions(+), 907 deletions(-) create mode 100644 gui/x64/AMD Memory Tweak.exe create mode 100644 gui/x64/IOMap.sys create mode 100644 gui/x64/IOMap64.sys create mode 100644 gui/x86/AMD Memory Tweak.exe create mode 100644 gui/x86/IOMap.sys create mode 100644 gui/x86/IOMap64.sys diff --git a/README.md b/README.md index 5018bae..63ecc8b 100644 --- a/README.md +++ b/README.md @@ -3,10 +3,12 @@ #### Read and modify memory timings "on the fly" --- +![alt text](http://eliovp.com/latestGUIR7incl.png) + ### Support - GDDR5 Based AMD GPU's - - ~~HBM~~(later) HBM2 Based AMD GPU's + - HBM / HBM2 Based AMD GPU's - Linux - Windows (Beta) @@ -14,7 +16,7 @@ - One or more AMD Radeon GPU's - amdgpu-pro | ROCM (Verified working on amdgpu-pro 18.30) - - Adrenaline (Verified working on v19.4.1) + - Adrenaline (Verified working on v19.4.1/v19.5.*) # Build (Linux) Prerequisites: @@ -42,6 +44,7 @@ $ g++ AmdMemTweak.cpp -lpci -lresolv -o amdmemtweak | Command | User Input | Extra Info | | ------ | ------ | ------ | | - -help | | Show this output | +| - -version\|--v | | Show version info | | - -gpu\|- -i | Comma-Seperated gpu indices | Selected device(s) | | - -current | | List current twiming values | @@ -94,6 +97,46 @@ $ g++ AmdMemTweak.cpp -lpci -lresolv -o amdmemtweak | - -CKESTAG\|- -ckestag | [value] | | | - -RFC\|- -rfc | [value] | Auto Refresh Row Cycle Time | +##### Command line options: (HBM) +## +| Command | User Input | Extra Info | +| ------ | ------ | ------ | +| - -CKSRE\|- -cksre | [value] | | +| - -CKSRX\|- -cksrx | [value] | | +| - -CKE_PULSE\|- -cke_pulse | [value] | | +| - -CKE\|- -cke | [value] | | +| - -SEQ_IDLE\|- -seq_idle | [value] | | +| - -CL\|- -cl | [value] | CAS to data return latency | +| - -W2R\|- -w2r | [value] | Write to read turn | +| - -R2R\|- -r2r | [value] | Read to read time | +| - -CCDL\|- -ccdl | [value] | Cycles between r/w from bank A to r/w bank B | +| - -R2W\|- -r2w | [value] | Read to write turn | +| - -NOPR\|- -nopr | [value] | Extra cycle(s) between successive read bursts | +| - -NOPW\|- -nopw | [value] | Extra cycle(s) between successive write bursts | +| - -RCDW\|- -rcdw | [value] | # of cycles from active to write | +| - -RCDWA\|- -rcdwa | [value] | # of cycles from active to write with auto-precharge | +| - -RCDR\|- -rcdr | [value] | # of cycles from active to read | +| - -RCDRA\|- -rcdra | [value] | # of cycles from active to read with auto-precharge | +| - -RRD\|- -rrd | [value] | # of cycles from active bank a to active bank b | +| - -RC\|- -rc | [value] | # of cycles from active to active/auto refresh | +| - -MRD\|- -mrd | [value] | | +| - -RRDL\|- -rrdl | [value] | | +| - -RFC\|- -rfc | [value] | Auto-refresh command period | +| - -TRP\|- -trp | [value] | Precharge command period | +| - -RP_WRA\|- -rp_wra | [value] | From write with auto-precharge to active | +| - -RP_RDA\|- -rp_rda | [value] | From read with auto-precharge to active | +| - -WDATATR\|- -wdatatr | [value] | | +| - -T32AW\|- -t32aw | [value] | | +| - -CRCWL\|- -crcwl | [value] | | +| - -CRCRL\|- -crcrl | [value] | | +| - -FAW\|- -faw | [value] | | +| - -PA2WDATA\|- -pa2wdata | [value] | | +| - -PA2RDATA\|- -pa2rdata | [value] | | +| - -REF\|- -ref | [value] | Refresh Rate | +| - -ENB\|- -enb | [value] | | +| - -CNT\|- -cnt | [value] | | +| - -TRC\|- -trc | [value] | | + ##### Command line options: (GDDR5) ## | Command | User Input | Extra Info | @@ -106,7 +149,7 @@ $ g++ AmdMemTweak.cpp -lpci -lresolv -o amdmemtweak | - -CL\|- -cl | [value] | CAS to data return latency | | - -W2R\|- -w2r | [value] | Write to read turn | | - -R2R\|- -r2r | [value] | Read to read time | -| - -CCLD\|- -ccld | [value] | Cycles between r/w from bank A to r/w bank B | +| - -CCDL\|- -ccdl | [value] | Cycles between r/w from bank A to r/w bank B | | - -R2W\|- -r2w | [value] | Read to write turn | | - -NOPR\|- -nopr | [value] | Extra cycle(s) between successive read bursts | | - -NOPW\|- -nopw | [value] | Extra cycle(s) between successive write bursts | @@ -136,6 +179,7 @@ $ g++ AmdMemTweak.cpp -lpci -lresolv -o amdmemtweak | - -RP\|- -rp | [value] | | | - -WRPLUSRP\|- -wrplusrp | [value] | | | - -BUS_TURN\|- -bus_turn | [value] | | +| - -REF\|- -ref | [value] | Refresh Rate | ##### Example Usage (Linux): ## @@ -149,14 +193,30 @@ $ sudo ./amdmemtool --i 0,3,5 --faw 100 --RFC 100 (These are just examples! Don't try these at home! :p) +Make sure to run the program first with parameter --current to see what the current values are. +Current values may change based on state of the GPU, +in other words, make sure the GPU is under load when running --current. +HBM2 Based GPU's do not need to be under load to apply timing changes. +It is often better to apply new timings before starting a benchmark/mining tool. + +Hints: +Some timings are stability timings, lowering these will lower stability. Such as tRC. +Some timings might require a higher value for performance to improve. Such as tREF. +Some timings have a min/max value, going outside this range will result into it defaulting back to original value. Such as tCL +Some timings are dynamic, they change based on the vbios values and active clocks. Dram timings. +... + +Row Access Timings tRC, tRAS, tRCDRD, tRCDWR, tRRDL, tRRDS, tFAW, tRTP +Column Access Timings tCCDL, tCCDS, tCCDR, tWTRL, tWTRS, tRTW, +Refresh Timings tRFC, tRFCSB, tRREFD, tREFI ## Some extra info -Not all possible timings have been exposed. +Still not all possible timings have been exposed. However, it's not such a big deal to add more of them in the tool. The ones available are more or like the most important ones. Some users have reported very nice results already, please continue to contribute to these results. -[Example](https://bitcointalk.org/index.php?topic=5123724.msg50562384#msg50562384) +[Example](https://bitcointalk.org/index.php?topic=5123724) Have fun! @@ -172,8 +232,7 @@ Cheers ### Todos - - Fix HBM gen1 - - ... + - Nothing License ---- diff --git a/gui/x64/AMD Memory Tweak.exe b/gui/x64/AMD Memory Tweak.exe new file mode 100644 index 0000000000000000000000000000000000000000..a3abef8521dce8f562d246a8221bae4545064fd4 GIT binary patch literal 340480 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 z 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
  • 1B}qDoXD=#Q#_y8{78-y}g@; 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

    wT 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 E0oNqljQ{`u literal 0 HcmV?d00001 diff --git a/gui/x86/IOMap.sys b/gui/x86/IOMap.sys new file mode 100644 index 0000000000000000000000000000000000000000..2c7b3558e8f2cb74a22a386a075a753a6d466d48 GIT binary patch literal 32016 zcmeHw2V7IlviL~|5NfE3iW)&INI6O9MM1h0>4=EbAiab{Kt%~bG)C;bf?)Tv7c3}< zQdI1{cY~;4M?v$SJplyu`@VbMd-uKf|Gmq1&pBIWXJ==3W@lzMUhnY>Fc}QPDDX%m z7*-Bn^yfgl|N3r;FG$5V6vG~{1J1>S#1e4Xzb8HK(s80JNi!!$HyLOWp|Vq}sMNdd!#A;P7lBO~Ff29E2_8A0||gH_zN%-E<2kG^>g*$h3Fa#Pxt;IOUJNy6HaUtHwwePLY^2qjG5pI%6I%Z zV3@m!6bvf^S}|XE5S$@A-ToXftj@#7BM=p>L5nF89@M81Jl+2281~qNlgWvJGJ+?- z8(=bq;qY|(bHK3CCLDHh8UXf1{pG=f@L9mq?au+=x@G^J{10js-}}5jKfAY91oKHxR>0P*Uhh6}j07T>*tdSj5CG zg8mEW!2$j6=t1Q_(^Jud9_K%yNAOB5Kom};9a0Jo5qeYO1Ygu>f>gi;+!n-HVYRMC zvM_#;6IJNaN;~AF6*sezHgh)=(GGnnva5IqJ&WXLR&rVKh)o?FVpR&|30>{t1i4faPhpU&^B`G7a*<1mZ;`8&FRRj5!fTaG#wC-DB-+Zr;zW!<*HNLJ z3`M9hCX^RCQFt09sM}vr(`N1hB1)bTy*U%#Qq)i53Mh^fw328u7Za3M6;WnJ`TPCh?#1g}f_m&k zCe0v>uu9O%jhGl#-??hZEZQMg#Ce`F?NF77G7}BINezvNH$hs0aKjjU zM0EhFBM@U;BX_R0JI`L^O0N==izs{;oGy|QeJHskE}}R>fesYV4plbMpiHI;3LH?u z!AhYkrGqS3zLf6r1ae6`L@bj`cAOwv3*$|s9jX^87a@{n)^mMnhkSJeFEK7-3|D6i z&ry;-Smf}7f?a>GIsXsvo9f~?g_=y5ouF9QK?T+{dQtbs_ zk(|(pkZ7mBl4vxSA;gR$iSC?nfdMMVLL}x0lf)e14G=fMURZ*XNTQwGr4j`5)Fsi0 zit$viJ0#i|P#cdENeW6TdxXM^$WtM|o7Blf>CE zOyq7SR6%kma(5Q0Ab}7$xDyMpX;`9KD68@WT0QT#L;3`oMqz&hEbNaUh5Zp{-ftJ# zBh6Q2wiW@14-m4zU%D5;WX;nr^ zC7G&b!AZ*N@RQ2F$ibh%i(IszNptu~HE9!K))8&LHYlQ0RXvoGanY)JNbcyTqtQ8O zD{qiD$6iRF`?_;!?pzSerape+w04Q4N!?F;sSUmg5}vZ3*yyW7(zP_Dtp%^NLyFU-gV3c#7~T%*BTKP-73{8!6tHZ9Lz-kn-XBD~_NwQyEQ!q9L~2NY z`2Kf^L{wKL)~RY#vy-9CJPy-ZP|sD(`$Fa_1ub6|GB7*D9;A#3>Lg7c zy4g^EerWBwQ$@bY0itn~U=a?cnHE?JB6l?*uN77j|2x8yP0g~0y}o{8mxM*5-2V@=S<^T z=rWN)!0!imSVUXYXa%!SsTona4oYbUTV{UZ@`8ziB82w5;E{}=5#tW_;A(kr6+L(Z zM6FfL%1z4XLv4~p9}52k+6S6sXa`#b5;9j6_5%Y{B5L97ZyH+UO7SHS+5tjA4VAzy zbon4Qg8V0!4^%D%Mn;mjwDNOXrPJI?B9Y8-k)Ua=?moZ32bP5ODG^kF_zh^0L@Fen zLE@+3)6wwzq2c#(6?~_2&b#p?2s5XeN!Tydi48a?6j!%qNB*<(Kq2xff>0d5L;Ei8#J_Z29( zVDaTIh&Pa^hs003VIkg_Al?jj19*@z&RJJzEfo#U5fCcawIU|68p6aRZM1PI!@>bv zxqwT`uDgk5kWYd94|YMp1St5Y*wvPo+or}1f;X8~fK2rtj01Eke~0dOj7vd`vxb+* zh4mSM+nc?FwJRVzjCaFo!I z(s%<@5#WB0mUoDR*CGxF%xHOo`W4-Tf)gk*r2jzd0_D(BzgF;2{!=xTYm!JFFH}b+ zu~LyEMM`9ohV4nn@Tj$*kx_48*Nd>mOz4Akd9+a7_9Ryon!!gtkpdr{tk93rL=i+$ zFcHw=32@!y1hgP56A%_~feLoPjtM@}%ulp}GL!@}YhonmT&!riu3#wgEN0%J6$qgU zLGuxatFjREDB($oz$XB^%?V0A6uG7_N%Og(G3hV&f-JMoo248_#nKsh~ zwGUG+rwqabwl`_B1|qdxK!!KJ?IIl$&__EfQ<2aWlL@QHwP{qI%lQg^;gx)q!_q zD;ZWD~SX>73*mP7t#~L|Mkw_V5?b6Os1M8y}vKUDy->44>Xsm)7hY^jD`bX$} zKcmf>Hg_bHg7F2gCXfO zI=@W|4Y1%W!13F3i1bDxZ3by>HowgZeS`RIcIa!)Z*xFjIxITanL0Kn3GV~gR$^^1 z1!0G7EQ9ulq$H4`#ta|>Wp2VkL}WdI)lw^u;%7}9XoRY)KS`_Vh$=vWHHCn;4ZAon z4g4%AyJ7iJYh_?05W)~@3WIf;Ms<$8t{IJ~!)k8?V*`5Z%?9BufNRh&{d|MAESrPUx=rV2ck2^`9sony7F* zo$w?czTepCR2+N1k+8#$qxB(l+0UvBP6Xq!T`Gn22^DbR3+B`IaIJUhD@p zo5*E9c#eLObc)0r6-u;y0Y+qx(t=YuW5>pc+{kWj$jkkhC>NS&m53c52mQxK0@n8% z#VQDgIr0w#r<99a9)iQL!&h=WQEj~FOgRb#o}dFJ@KjI^Bb_Kl&9<{DMQ1wP8%QAM z1fU_syf&fmuA6{KX9`GkP z(P5%^4-{@8@nn2>A0~F;AZnJQ8uCvy0jMfbZ68Uz2&xltu?Rlm-SG0^Dv4vIO+JA4 zcqdU!oCev6bE?BS@B(x=g3gCmB3f0gX!@J(CS3-jQ{16H-_VOmq376=FQ$OA5dnfOS z+U)Q)39n6D1FiC^>9Ak>ijP2A`~Y64;t%*KO@eZh*b5q<8HTPDVO%lH+nzjS# zQa}x?LpD$+7a->A2Q~T~og&(h21TvK(U2*qNE2XI zK|8;V5Y>SE_Ka;nOYk9}K1>wVMszikYA|ptwdVLLi>R}M z;Hxq_sC|wvWwtgF|2e+0!LzlIfQuZctWO@LNX>CIJ$MEZo(?f`s#pWY(4{%IU;#SV0T(-tHS|Q@S|Ww2Mu^bP1}jh(cqQ`I5t4v#sR_%1 zNL2^nQl1gMxE%z!Ixq}^fk@JoMGh#uBaQQ-D67at=LZ64{ST2bBl|L0bepC5#oz?~z4 ztjfWMTfo6$eX^~h&8mduODmWUZ$Z^7RIn44Gk3auB|y*$)>k4%5LcM01Bc zWm>^q#0V-B(F#gYQW=umRC_h_v9{Mm6*G}9*KrdvU*2OU;P+qBpEGd`E^>AL z(VuffDLNnfAnXofU;~+BubH>uJOn9@g$yfpw1K&(2^}xnr-dGg6 z@&q|wNO9mvfm$v+9DqUP-COl+1J(cj`)}qzYz&6^!!r_|!SH0mgZ@&ZFsu-sHSp|* z=Nvpw;c10OEgG(h!7~z`agdLLZ#Fy&;MoAr4tP$%a~_`O@U+4s2YB59)&d?n!U2yz zl>hFp^UfX_Dt+MD;Q-GtfDdpE;2*r7e&yLD??0RjH;w!FC7A^EF*Xwt(o&+*jVCiq z%p;gM!xA@RT1`lcPK@KQBeD`wEhDn6EG8td;N>yaJ1X5IJ@!w!25kSg{(PQ09Np9B zg!BKcQU80iJvdN;6#ikf6yQLdVq3-QTM`R;UW5@lK`F6m$cw6o#OI5pXp@iz+6a$I zTmc44c%xnwim#PL{=nP|WM0Ps?xJ=pTY~fpl>P4Se}gVMPVr51ib_s)<|IsJb1>{C z6jM9J0&O;RE|elKzdXR8^b=zc&C77>B@V``nxzfNBFzA zc?1Ny_(udexjXt}-anTHxR3RRd$V3YmwS!%al;JcL;O7gU4BM_4gIBDie|_!N=#nuL8Pd89eBli6H$Ku$_@T5>{+S3+tMhP{#X=O%lkCUApN z6Jp@5b^w=?kU9y&j*val;+)b_(oqwCb_S1~3D=B$Wjxt_JT@mMASaW{P6~rcNN;KiJ0&G;GO{sTvK^D* zS}?TgK9;cvB9jgDY=pi;q7t~SX`BEcJDEK;I*}a%)(4dP!)T*2I|zb%%AV}NgqS3! zG+rtfyGQn9kLFEsif6|pxn#rc$4$#j;-n^Q)n8k=7DYxS>V&=OQrSyOz76KNIc>-@?p}AzUV|d(zv{YYCS_~jf<6!QN zUM8{0$-fhke{mU!xH7H-cLaKNMBI5t*R+2rSD?VY4#1IM^zE1F*$ULkii6K9Ki-w=1O4Uj?Q4I~*Zlvhbk4&hIE9hpw?vu%FRuK>=JE1nZImR%j|V z39uz#$zW@GKrRk!R19kYBZ35!o55pEe527gFc>40I{{1zVWFl17G$4#VZFM_)4_U8 z#d3g3sTB*=m?QKT1WzFJ;)&5aFr;I=4jY$F^c{nl0Bk(ele%a^c5f!w%81rgC!AEq2E`av5f7Y1FZl=T_+z<4*4D! zjJDG+`7tKMH;DKVZ6^aH;>Kv0MYMimp)MYNI3cY^bHIan<96fHe|*kDpodhzn1*E$ zqc9=n4$<+WpPy&2`}|4i4gmhMfu;mv#NFw3CdL&E<(w`~{E!Cpa}W?%ST~5HsX#$8 zG4>y8QGv1>0sQ;#{|X1xz*mE@4#sWpFgym&#`ExncqzUW--92*PvTAZdz{KpV+>-j z7}g9&h8x45v5#?@ag}k4@rohG?87u<|*bm<^pq}`F!)G=4;K%%ukq~GrwxyY%XJ=VxeJSVBu*IY7uQQ!>)ZKQi3~R z377dzdxM z24*9(g{i{ASr#mNmIrGrE1VU>N@q=G@mb4QYgnbMU91DFYF0h#I_oY=0qCzcpKY<; z^13C}O2ewZmC$Oj)jBJ(wY#;z`iwQ%#?5A$jnL+#&3PNDEzLI2c9rclTV1x>6LFO8`U)Z$Dm62r6rUJlp62jYWq zW84fi|M%a&Iq+Y?0phoaWHN^5JCWoR3=7>0KdX@B$;J7j-{JYA-;hZph7ztICp$t_ zhTK;c!{g-?N63*Vq?lJDQaqgLl%|FWyjE+(m3g99BFqrZX)e&Xje7rkPbeCw8sE82YFVR&^6td z?#9IPNqXHGM3Tj1@<}w9Xp$m1pG3m;?AYfK=(${1L-D3T&O*Hq!?e5QLrytmCY?NC z;yb=g>*VBlP9y`T{Uwj#g7cxN)!cJ>H})^V$e+DmpV)uMd2muggp2JZ=krb)nZ5Hx z3HwK!T{&O}r{56ojDdR?_uBlT$N`(See^Jr&34&nDm?#U<%{ogABT*xuUT|=OzTwE z(;UUN7T#>fHImaZek-@#NM64*3>hp>W^<$5HOFW;2e|@I9*=YSXHvP)YW#YPN8-3iJ zC4C+{%P&&85nqrOo|ql$(h%u7J+Ml1+UcCP^;H>USgE8^{#Ts;nV8D{s+3+7t%y}0 zQzx7|$6a;xUT*WKJFmR*Ozz=KIVvoASy_1!i82I~uwG{#Cl&UJ=W^3+Oij~bGSf}C z#L_W|NlPKtSbt3tNkXCGa`1tRqxdM8!u|s(R=5RjR?IBM3r#v2$8eInwKbKlsO}5O z$&_G?#lz@M~2VGWE57<&uN|!if?Oc^C( zano?|mxLnyOeKvpx2-#^)mshstlr(XdR|lLGVG7@%HDe~GB!~s7*1(_Jf(k#*A}); zV~#_#!LroaTFXSiAnH8Fm-lXkjOw4|G0U)*+{8^*iFz8PetiVf590ZhQjmC2hs3L1 z_+VA{{e*ccnRzmwsBgh{Dv z4w7TDzm?++F-q3X&ufoaC9y)pIEq!xxgj3b}oALYSIgEWX)9SGLY5jMx<65+tX+9w(J7<@X zZx{|}@O*SH=2~wdGi>+7mE*Up9p)4glM{2`3+Zv>DoKFe?P6gn~Xz>$bN5(O{7s?qR(fA9IkRCSEjfNNg2{bPEMnrLxMUNLFWFH6CaF*#IT-v#HOe`ub!m(S+>kPd77|SP2=7NdmHc3YcgmJ zOSyLsPPkuTInXKldG>*ZVHA4lwzr~-|ttF!x~{S_3&M~f@VfjVxO=J;*EHSkE5L9@O)W4P*sW@YD&KJLR%m2)2+D)ez#MUZAd?> zsmz{gqQfpx)Kqp(n3RCb3c5#XOsAq&(p1aJ$})+CDp)04w8j`r9EVu~V`F$%3-^Rc z@pQ+`OdiA~W7uFT#DXyZYC~#$fO1E=%N)0cr_=rbHD-k~5HcJek8`^b6&TWK|4_mH ziAqRkCv-EDqy==R1a1yv0IrKDQPk9Sgdc|nvOS^alynI4a?lt|I_qWrr2cQU+17~~ zgXhbOBd@O%0}kiy3_IF_xSFA_C8dF>y>!~zbO7>xTSP%$%9^{ z5sZEoZ*T1~9pE{x`u*MX0}*R)eL7M6ej8Wi%DoF_h2QSWY%ko}a%y28hRHxD%3a2l zch`zXoYP%svL-Ivy=27a8B|uyekbwPS+5>bE_i7>FMGVQx2l5$yJb)2V^&10>PU@1 z1BDeSwxXQWl>=TEy>5S1_V|`^LG%>sSvUMFm)8m8TYNWNCw=Eps}>HmzqsL}*GKMz z1NYVrX|LEYLO2J{-)FK!ZTTjf>|m!8?uQBwlie%68D?7gI6Mx$+&DG%S(vl$h&{Wn z>G0lh`sbFIyscqhj-A&{wikT&XwmnW!QB{b{$Yb+ z%@>c87y9=!4M5K!d-x~&K?YAig##(kcqDF8Y*cJmIP8a2!s@XOP2;1CV=}>dU@)Qx zd*l~*v%iKPjk=;!Y;kMcQcfYV(4AEHEm?+y8-hCPFtNy_Ub?9NOt7hbmIG5K-vFFn z*a-^CdI|(A26yH`S?hF=PH5`xB82;PL6HlcI|m3yHymzePntU=3<+45d?E4bkS-@j zV+IVK`_oqQ8!Z`ieCL4=ID_i$Dr+g&gE-a>VdJ`Ber+gKyd|jd~L-d|91d zwes+TCLMRm+Qjliru7=~^iRx0`BA%sb;bpI(qi6-)24>W71WzeTR!PfYsm6ohx2CU z+hw0=o=6#8cX;xwQ_g3a>#O4j9SA%V(M!d&>R$HhS&MFu30={$;>5hWiK3WQvpEA* zrjTZcXHVX)=~ZF+A+f!661G=cjq)_{oXxhq%C`dfnI51sjEFqdy6QM(rQ`s#eHN zyBgg5iS>0!#7w(KdUJfgq=S~U1!GQMswEYp=-&GYpLOWZ`f)}#RRpe(Ca#Wj3{_Jx zBq}o=6dD)&Ej3~>gV!eS&yGz=OO5SRHK2;T6Jj`NnQ3v{9xl^xd?-RAqe<^x4{9=) z&FS*v=>BPGTtZhea5IKE!`jT8#X`PXN7fu=@#LNa{__fa1U_6!i(cpQqW`48U4jWx zkmvY!o?FeiXPM92t{#16Y|PyB;2D2ZeS?9=!3@LdYfH=~ZBW$R9g(ofVb7^Ud*@$V zQMT1F)aJ_FCD-llaIMP5obxuw|2$@6fQHqZ_Z}%33#Z2%+`cKIx~!meY_#9;*3+-< zSS@-Y_l&ww`P4ASptiH)h1%0I#O5cwISTg2ZLEC5vKak}_SFt{S+#jb3Z^xla_ER= zlb_-WM@Ky$cGN7sqwl7i3Bvn*#)Momc^c^t4|vmcWCyZ?007rw^(ggj6HcGE_`W0Rf)lXS>b(s zmFODh9FL|d`B{~Fp6&45&f@$!Vx@paQN+Q^lB0lf!Ehy{WN3slREX11hOh@^aTzcK zyJ^flBdZf+T2HuEq>P8E@C&K?vbM ziVyCEk12L9cKxADz+_A5T!?7bHcd}TFa<--6#hZ1SY8Y_)3j?HB6UKnLbUn_P5QI? z0C$l-w<`2?+L|Qesxc#Z{aw5qeRV7HUf$ZhNF-;dIVzynx?t_`waHU9a>%XBsD*=G?~adoxLjj< zTCv9KTk9|19%{GmY4DdzSNXJziqX?H3GX&st5~{W``g9px#As+;akGv(jC{f^Xjkd z>uYUzai*-VXve}crxu^h*toWAN!mE&uc`D?RK|gsYp3(ST(&#z06UEi2pp}J!bPk#Q^)Q58u4U^V9dBHw*%-AmFF6Hhd7YpVt3jf#^xHRRp^z?+Q z^X9ELtzvR3D%9CB@(s<0CXz#L7hdf<%xu?ekG&T*-pdb8i{Ga8I5hCP@my6Q% zBKc1Y^efk&qj~H#-!`t=rutT|C2DxS+(}TO+d7O)@~KPD=8TC~4lXLCOrP!@@v{>B z@6}Prx@6!?MyELm8q)%@5aE(qm;WOs@82oT(_i$TFBy6&Ppd4C8R1Y`l$Kuk%pxPh zhF7+&@1iBbi97T&&iYKsbsV+riRYoI$JbVEv6`P?YBRVoD^#O4j^cDuWk|lzq0c*` zmoL0tOq1t)gb}^C_cj%WDMg&&9{FW$qp;oGq@$veNM;cSE zJq#Xy{v|0ao*h;-YMei7t9g`<-dX+`i&BlVa@Q~P^VXSuc+p{v3l2kWuCkc9PkWo& z;({dkqsOl8yKjK03$ggB;dU=a8o%+~enS_R%eLF7rax(6hjA$buCh!(PvekO__XfP9ia92cWwcRC!qWD zmFs^NAV$s_nEs6m%h(Xl%^_C)FKSW(Uy+Dw9{6F2I`7c(W^0R#?oY%8S# z!TSS_WS|lq=T3sW^tvmTpxY5jI8e{-x>`Vo<6cC447};kE&*x~jnZ@!#K_UXGb%yj zMl_=4B3-y7<#(@!_xAeFgLBvBnfzCc@RK+4_ZUz}Um6Ggt+&-ZRPtNv;pbf(LM0we(;|=WY_6ZS@AMJR*ay859v6Nc ze(U~%Qe{CERiOW-EEVJDlf>7oE=)(HP5W?_N>IS8#jPJWFz!T)KqRz`~}ue@ZK4 z)CZ4X>0N6j9dtfFcmJ8$m!I}}^5WCuk&hHA*XB4m%?O$x`^RFn8Y7jY%5^WZpIy$n zUVeMkiWx_|7L8b2Q8s(eyBR71YmPc#mesn|nrS_6tV-uq}B0ure}KTfoY({Z(KCs@i16gTYCb+Du$!%*&4O@Z*oj{`6zhAMc0Kl0kR{*Q(f z1{^1td5-dr%-DAAJISK_!RIBHiyvw~?!IxusSIdVEVX{7-tvWpWnQ;8?7pvMc;zxF zERshxrOr;7U2Y7Wm+0di2Ht zBaS|wWmkOCME$CP_Z!2Sc7>ONWR^AP%a_b+ZZm%oQXHoIDp>7tkn#At7(2pfBXdf* zi`PE;KH4tj!Ee4*F4cS3IQ)|C$SE0dkH;FX@Oyc0RKmDnc^e!`@`niUe6sux?#VIo zNv*IUd_e1l^REu{lhuAXY3Q~>!f~A+gvl_Jx-#-4SPq?srV6qQ8W=^ExH-5raO8Kbc=mL{a2fM1ugG^Dw>m)WNdo< zG)AlP{FUBIlO`3D-zuC^SpU3tU3uc6e6`sX8vYX^Tdc(+S8)_F-&EkG59Uq0)0oKI z9XV&9&du)=#~mFzXC!lk^;TK4{^I%ScT}#O;F|O@95>Bkq3@Ei{-dJ8EgHrZ4)r9v zPHw6Fcxb!a#=Hk=rPCH3ySl9YO~{suZ9^D($`!h6$15z_hvyIG{tzn)iIG1z7Rn;K zc#RII2m3*hH!Ke#bV&r0*fJC{NEANdM`IGD7`bY_yOq#z1sOP`rfeYRVK{LJhRm6c zwiNo-+oSYbu9_^$&^UD|*QKSe9BF9=enS?!Ts(Q1)gcvHalXnkFwKh~{>zh^=9(-B zYv^pQ@wshfvp$Ciap-iPRV8#bJ+Eg7;lC)x0Y{0jWkHPNhi^#_Nl1-N%gUs~KgP_7 zrTfC&g$Riw9pZOpM99MuEOv7^3$$dKL&yWd!w@g-$m0Cse+j`VgnJIB z>J;y>zWxk|1WM^=cKOC#^t(rKVzZ(+D7KxF4yWMJ3CR$Fru*`ulM^!I;Q;0D%>9i| z1MVgD-MFVJ$M?jI+XGlC)Ej@8V)427yQK64tYQt;E9N%4g1chrlRK~9pU+$R!Dh0c z*Q0Xw?$*dN!m@scFR$}_9kzIbPuhm&EAA!F#oqL}Ph$$@UkZ=a@FgiNteP+P_YJ$q zQE~ONzf-ov$w>HhL~gUem1Xe-DOZn#=L~cvoqczf8-Hg;v*hGT-DW#?q6FFIKJJLX0jlM5k{DYMuG^-s4owAxEm@Fp4%yI;S8Dn7)6KidZ$3@2& zn^~JPjjdT0(Z(z$n_a=38BW~+@;8{V$7V8+@#-R$OFUgT>K!>%D; znq8}ru^{B-<|pE`a`O3T)rd=^Pp@U%^V)8j#GX4)>i44Lf=Tp6&Va9i?T^;kmaEFO z@oG=eOCMhkKJzJ7+b4AC)0#c+w5lKYL^Nl3y&mMFIK#HiC3LC$vWCSQ!ks=D)PFa< zVY=|Zu=vq-%RVM3jeNN`HzY6q!>8s{^Yz!gj7{Toj-SuHm`ZR2J!cB<0V{sc z%6;b_8R9!+rnX1inmbT-aj;tI!lTEtm3A5_Ppd2m7_{O{?0u)3q=_yg<#X6Wi$-gQ zD{ahF*RC`CLuRkhwUt_v^h*ZR1>W7`-}-Dv#oaeMO%e@1Rc5_-vDNs9+K8xfQq!vq z!xOf!H#)w)G}OaVOc{|>TbL%vWTf+5@RcVcO3|)7${atv(yOOZ+v@!A* zQ}f)~57125N)2;ArD&U+>>J(t@w+%Hqc4f@1FhTm@S+6IO zEVdY?GV9;x$))#Jy()J(^Gd6`q370Bj{9;N^yrJSqvmqFciI3Lc*xIQko& zFYgPnBCBp2l1hR~c=qCplOGTplFBa|((HeUe*bY&*(G-!acvL;Y1ExfcjR&7(>O?( zgOuUKR%8aDBiM>q45lTDzFSMPW+?l=Z|}?}|9Z8GjILIZ;c68~*wO7HMuc^Tpv;wo0czKo;F;Pb93Hu>pE6x$N-$9_2$r&8IsUD z<`;R5^?NyMgR9OSGCEYddVp!t+J_!C{XSS=?r znwRN}zZ1FT_=|6=c6_O{f0FAn=7JLY!Jx8?r+RvVcL9<9^ZfWW=EW}?+pBmFXP%UE zGFq&99Z7U=LWT0%QVl>`ktg3ti3PE>;zZ#O|flCYbrzIvD*jF z7l%Aln%HMc^b5+ShP{3KEjHo&zJdM1*2lN-^s>{oSf6eA{&dr%!%D6h-=|FHX^sqe z6zsdUbK~6#8}CMNFBLlWSZxxzp@ntZTz|XI#iD(VP6>w#*_~$^esankIJ^Y8;1M~( zU9uksrmVl)g`D9$)YQLc=nZ__4wPDCit+$O_)!ZFB1le{VI(wT>ic;sKPz?3-VMZ55y;O73M9f>`4*@0?X#=EIWB?Ck6ag8iv z_Z%x;{N+8%t?^6vyZ*utA?u!uQY#Jh)seN;8t!;-vuYTB!?}ur(N(98Un)3xszQ0L z+p&t-g>B=h%XS)>J~**Bu5<+bOu?K4m!YFF^_hzk^&2JMZt1)}FR4g!%q$97)4D&! zV}I-;$i&sS<4*67W5-Vsv0bKcG+Q_tGY zyEkQjM%a-N)wLIA>U&yhWNjQ{I-~EQn8VJYuNUFxo=#I(q@h00|KkAi!m=ATp3Tp5 zljy9TacPZQ#@+Xm`(!P+W=K1hta0kJGCl62s;Tedn`hc)JPUrUaC39Oo?63%?7J-y zFFff7cf}ldv}Zz|&zdP)`+I*L=9)c7ZmBo(UgYSf2m79S=W21^Jd<2?;911s5uq+q z7CGHG)fjWnV*cdXVQ02D_Y*Vw#x*>1pD;!-a)j$5xyWTJ?%rbE7?d?*cFGPn&g~7Z zsoP`YM_l$<(Pn;b#;Z}9DeBMeWWBDco<1;fj8^OZ&4X$(3MZvE-0V{tKCpQ8s%fXg zy*cx^@-sGjW9|3i2Ww;*2JwbAY&GgXZ(5%>2}bL=2CRJQ9jkNGYR4wqB%QQW&*pp& z3XP3qjWl_1%J_xRjW)%6gS7G+$^{!Ao#Lh%E@iGO{@$=(XZ{u2KbU*>tSV2Db!wBS z&=~pJaQj&MB@wyW^uKNwBLA7&+0C0R=AVTVQpJvI-3omu4A4KM|9E)Iw95lmpfL0( z^z7_uD?j$5$!^*`@{cQnX1udeiuxm{+4wNu^4|RfOK~#p)#YoDNy?0oxLvVPo+0)R z{~WADIZtuw*mPc|M`~PJZg(N=2%MGF+flZBYgrLKD!FA<(6F)Qk&`EFd^vpR{mV*~ zCnK&5%e>m?GQM|K+|cZ>{63NQ)Mk-fs}=etKDr>NROImV>I+mQwkC{0S}|V@RZJ#c zDfTNLbdbJnjmqkrqnF7;{kM4?%e}gPtG-sB=1r@fz2o|?n0WQLg5if$PV|=PRynWi zs9vr?Uk_=`KcaB^h}PDsaSdzl4mkbb+Bdf00gB;}V?$h)yqNcB0ygfl$-#}{hG}LC ze3m^hoVZE(T;zT~zxmI3-@gA*?zOskZr#r6yY-BghwIrK@yTUXUlqR;3!MsER1bOE z&3Qhum#y8s3s%Js<7TkNy%}mo({zgV26Sj#DG+%gmj1`(47NZ=q>?1HlwXv zoQzqxqnWWK!_16N5XyjnP^i@YR*X{MOaDKT z$lcd05eNF;Wp?AZB^=o@SQh3e0>m_zX3bC*pY|`A3%EZodVbmKRi z7#ztQ7wP(LoLeEYU;sC2(!vOS;GPSMy%trS+7x~%N;7p>P2Vqtc}E{awYydg?LT;u z2B+_!IlDY#g}%{y!oOt=v~LOF?WmYD+S|eJ5^as#$VoFk##PEJbDrLO(eqpCvsGvI zY8$PP5|2&rAtITfo1qzYfb1P9lqu$x25T z#raEd{vvcV*~uRh8Jy3@?K^EvIOJyhsjcbj>0ug+Y;CxxXd26oi{d47iF0m;uI6Oi zYygwqzuV8LBjD^9{XPnv4(Gtn;?WP{J9#>;KJmfF7cJQpwOiI1Jo$3$by8pm zb%bBOvqszDfVt;BL~6{Le9pnaarNB^y(JUAOzdsGVsNl0w|TT$-L4ZeYG%B%%pE^U z_ua~zF$?{%T~@T-A5C-k>|0w8Bt5M?|LM#WEX@;l9;|0~;kC@hW%EOaA3OMs@+f^h zbIj0hLAy-9AAB~Cbu>C+)twNB#<%BJ#x0mDNsOLx@AMd@g+m@&zv?q4BWCT?K`GU1 zN;lYjosqjNaY6Q`l*^CSeCgkAb#uvwnvIIf3d<_i_1#GsEhs;bw_4ANe!$>a?5oco zPE3ypHK0u~u@0HMA!D1|9GbA#k*Lk;XII@+bz7Bp`eMW8i_N)$mPfW33J=1$EA*&Q zw|DyvNUM1J2z&5?Az!xG<}=$ZTim+Eef#J8oas?XX<1wOXE!VCus-^#=IqV<{hWsW zAIfKv2IRH%6B-6u?+v?MrxLVs%B)OV>hl%GFN+?sOf-gntTYWAI_PuV4xih@%J*!& zvuy9?(HrV7^l|ilSopG>dL>c^FHO#9Ui+7)_W=Ur#J<-Qp=N-m!c zdXjKIr0UXryz<+*=iY59C&I@zt{u?F%JkTUak3`OD#gC$x0@A)>R#J7-FyJ`$Zd-| zS0d)$=g#)ffDPw1+~hdfE$Fj;(z^p&^yR{)5<#E!KdqYoVU>>V3|XM7zYI%r3o{hw zfg^_>+5bOx|G(X+4pZOiueo=MY)YP4QaW^b>=&6e8iAt%^2e8tY|2g5InAjWdM$mp za?3K$>+=h0ds#=XYulruU$Ef`{`oS`SLw>Fix=N~T~rYsVQJl3!%>eN!Q#8z@F`ra zwpcw955F{Rf5QZlVeXfPgx`4X+0g#&M*AO62HeU^()eccCTkx4&~`~o&Ha_?Ti0q-&Aer> zvWfInHQv78mX)J)@UQXbX_SekTUuuA`82Vg>3P1_AA{6cOzMnDLLC`pvM=0P78GH!w0fVhfhWIJ(T8jQ`IP2ZHcE>eUb;DO&XT0lg zY5#V4*@eBIVwU8YkM8@sq>3o-oxw{4>oF^|lsXg=E_T~H28|TCeYhNVa z3ihvbiTy?y_h!)>|IceJtG_7U5hawR-_M`0kG*GB{B_SI?J=B*6=N(%@B;Q{KE9b3 zJZLzj-~RJ!E@@@BRO7Mpa@HPQ^yKuptujGJGf$ATr>vCQS;Gr^ol$N%nClc=Wlal|B9fS=Air{qrxKJRYjU`_hN`3d`)|Rth`rKdSIp&W$eM+l} z`6qGyi8B5%oPYRVVtW6r8{`uhK)6BXmaZ1YP7D{^*xcOAiSgs|dQX#`9+1Z4z;BPd zqtLIb=}z!3GbMFj$?%&}vMhG@=$ryvPlwj!{=qMxS(rsYfMKhaA_9?l!zcMNT?UVun9{FCU#!wEFc*Fy?hi)wQ=Zv3uzeXCd9nfn?8 zj&C|}XMq0YBx-a(S@y-KYhjyq#Ft0OS^1iWEbYJj=8=crqUpvVl~JxAKVQD)=fB8h z9Z6>017r2~6t%lICVVWq{kk-zZTP2~wWp3-o__a|dy+J1f&Yj#vu4~F^1j!a#AS!R zY>Z8oU%ZGiX?i(R(P0YLYQveDX-9T1os*|x-p|2e-q5CVRmXG<&X*2b@W@imV$-n5 z(#37fj-k!w%=@|5n#K>_HR=26*(Bau*~XR&)w1_AE~)muWn5OWhpO_>Ja1p(DYMDr zUhdDf(qF#CZIjlLrLQAw$DjDD+Q)~HPyPs!_m+^n#s9NLgEY$Z8?&Z+lq;Xa#QS!I zJK)NeN{@gB{&U#MYLG_agw2(W8?U^uWR$%R6C~mBb@)Z8v?R2 zgMS(4U%>h2aQ+^O*6(B&=dZx|d1cf8H!=&Zp{dti*!6hj-TifE96xxqR4U4Sth4OC z@*y&TuAv#Fdn@5=|(oi8zq9xtxk))M;1kjF2+KiM=RNgcC&fFCI6r4Te?u%5W#F8}CC z+k&SfW<0udc&d2_dq3}LKfRZSUrdQgq+htTdaY@nT_4@nn|!r=8YqWP`=lDPY>X>K z&eEvn%?o>ve%DyoF#FUuu)U+&nwGkq4?l?)%6{L_*MQ#lgok(8`ey%-)QzdM)H^jn92UE{ V_K}_K>JSR$@nxI-=>J&m{{iT8+IRo} literal 0 HcmV?d00001 diff --git a/gui/x86/IOMap64.sys b/gui/x86/IOMap64.sys new file mode 100644 index 0000000000000000000000000000000000000000..12e3176301a9b780f7eff6ff859a0f4ce747fddf GIT binary patch literal 34064 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 OZ1EgBtCP{dMl%4VDxa1B literal 0 HcmV?d00001 diff --git a/linux/AmdMemTweak.cpp b/linux/AmdMemTweak.cpp index 4ad63c5..aff700a 100644 --- a/linux/AmdMemTweak.cpp +++ b/linux/AmdMemTweak.cpp @@ -1,6 +1,6 @@ /* AMD Memory Tweak by - Elio VP + Elio VP A. Solodovnikov Copyright (c) 2019 Eliovp, BVBA. All rights reserved. Permission is hereby granted, free of charge, to any person obtaining a copy @@ -44,7 +44,9 @@ extern "C" { #define PCI_VENDOR_ID_AMD 0x1022 #define PCI_VENDOR_ID_ATI 0x1002 -bool IsAmdDisplayDevice(struct pci_dev *dev) +#define VERSION "AMD Memory Tweak Linux CLI version 0.1.9\n" + +bool IsAmdDisplayDevice(struct pci_dev* dev) { if ((dev->device_class >> 8) == PCI_BASE_CLASS_DISPLAY) { @@ -61,26 +63,27 @@ bool IsAmdDisplayDevice(struct pci_dev *dev) return false; } -bool IsRelevantDeviceID(struct pci_dev *dev) +bool IsRelevantDeviceID(struct pci_dev* dev) { return (dev->device_id == 0x66af) || // Radeon VII (dev->device_id == 0x687f) || // Vega 10 XL/XT [Radeon RX Vega 56/64] (dev->device_id == 0x6867) || // Vega 10 XL [Radeon Pro Vega 56] (dev->device_id == 0x6863) || // Vega 10 XTX [Radeon Vega Frontier Edition] + (dev->device_id == 0x6fdf) || // RX 580 FAT (dev->device_id == 0x67df) || // Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (dev->device_id == 0x67c4) || // Ellesmere [Radeon Pro WX 7100] (dev->device_id == 0x67c7) || // Ellesmere [Radeon Pro WX 5100] (dev->device_id == 0x67ef) || // Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] (dev->device_id == 0x67ff) || // Baffin [Radeon RX 550 640SP / RX 560/560X] - // (dev->device_id == 0x7300) || // Fiji [Radeon R9 FURY / NANO Series] + (dev->device_id == 0x7300) || // Fiji [Radeon R9 FURY / NANO Series] (dev->device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X] (dev->device_id == 0x67b1) || // Hawaii PRO [Radeon R9 290/390] (dev->device_id == 0x6798) || // Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] (dev->device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] } -static bool IsR9(struct pci_dev *dev) +static bool IsR9(struct pci_dev* dev) { return (dev->device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X] @@ -91,7 +94,7 @@ static bool IsR9(struct pci_dev *dev) typedef enum { GDDR5, HBM, HBM2 } MemoryType; -static MemoryType DetermineMemoryType(struct pci_dev *dev) +static MemoryType DetermineMemoryType(struct pci_dev* dev) { struct { u16 vendor_id; @@ -108,17 +111,10 @@ static MemoryType DetermineMemoryType(struct pci_dev *dev) { 0x1002, 0x66af, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 { 0x1002, 0x66af, HBM2 }, // "Radeon VII", CHIP_VEGA20 /* Vega */ - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 64", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 64", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 56", CHIP_VEGA10 + { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 56/64", 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 - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI + /* Fury/Nano */ { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury", CHIP_FIJI */ }; for (int i = 0; i < _countof(KnownGPUs); i++) { @@ -135,7 +131,23 @@ static MemoryType DetermineMemoryType(struct pci_dev *dev) #define AMD_TIMING_REGS_BASE_3 0x54200 #define AMD_TIMING_REGS_BASE_4 0x56200 -// Split up AmdMemoryTweak to AmdMemoryTweakHBM & AmdMemoryTweakGDDR5 because the timings are different +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 @@ -151,73 +163,73 @@ typedef struct { // TIMING3 u32 RRDS : 8; u32 RRDL : 8; - u32 : 8; + u32 /*Reserved*/ : 8; u32 RTP : 8; // TIMING4 u32 FAW : 8; - u32 : 24; + u32 /*Reserved*/ : 24; // TIMING5 u32 CWL : 8; u32 WTRS : 8; u32 WTRL : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // TIMING6 u32 WR : 8; - u32 : 24; + u32 /*Reserved*/ : 24; // TIMING7 - u32 : 8; + u32 /*Reserved*/ : 8; u32 RREFD : 8; - u32 : 8; - u32 : 8; + u32 /*Reserved*/ : 8; + u32 /*Reserved*/ : 8; // TIMING8 u32 RDRDDD : 8; u32 RDRDSD : 8; u32 RDRDSC : 8; u32 RDRDSCL : 6; - u32 : 2; + u32 /*Reserved*/ : 2; // TIMING9 u32 WRWRDD : 8; u32 WRWRSD : 8; u32 WRWRSC : 8; u32 WRWRSCL : 6; - u32 : 2; + u32 /*Reserved*/ : 2; // TIMING10 u32 WRRD : 8; u32 RDWR : 8; - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING12 - u32 REF : 16; // Determines at what rate refreshes will be executed. - u32 : 16; + 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 : 16; + u32 /*Reserved*/ : 16; // TIMING14 u32 XS : 16; // self refresh exit period - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING16 u32 XSMRS : 16; - u32 : 16; + u32 /*Reserved*/ : 16; // TIMING17 u32 PD : 4; u32 CKSRE : 6; u32 CKSRX : 6; - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING20 u32 RFCPB : 16; u32 STAG : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // TIMING21 u32 XP : 8; - u32 : 8; + u32 /*Reserved*/ : 8; u32 CPDED : 8; u32 CKE : 8; // TIMING22 @@ -225,104 +237,435 @@ typedef struct { u32 WRLAT : 8; u32 RDLAT : 8; u32 WRDATA : 4; - u32 : 4; + u32 /*Reserved*/ : 4; // TIMING23 - u32 : 16; + u32 /*Reserved*/ : 16; u32 CKESTAG : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // RFC u32 RFC : 16; - u32 : 16; + u32 /*Reserved*/ : 16; } HBM2_TIMINGS; typedef union { - u32 value; - struct { - u32 CKSRE : 4; - u32 CKSRX : 4; - u32 CKE_PULSE : 4; - u32 CKE : 6; - u32 SEQ_IDLE : 3; - u32 : 11; - }; -} SEQ_PMG_TIMING; -#define MC_SEQ_PMG_TIMING 0x28B0 + 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 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 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 - u32 CCLD : 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 : 3; - u32 CL : 5; // CAS to data return latency - u32 : 3; - }; + 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 : 7; // From write with auto-precharge to active - u32 RP_RDA : 7; // From read with auto-precharge to active - u32 TRP : 6; // Precharge command period - u32 RFC : 9; // Auto-refresh command period - u32 : 3; + 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 : 3; + 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 : 1; u32 PA2WDATA : 3; - u32 : 1; - u32 FAW : 5; // The time window in wich four activates are allowed in the same rank - u32 CRCRL : 3; - u32 CRCWL : 5; + 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 : 3; 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 { - u32 : 22; + 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 : 4; - }; + u32 BA_0 : 1; + u32 BA_1 : 1; + u32 BA_2 : 1; + u32 BA_3 : 1; + }; } SEQ_MISC3; -#define MC_SEQ_MISC3 0x2a2c +#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; @@ -346,7 +689,39 @@ typedef union { } ARB_DRAM_TIMING2; #define MC_ARB_DRAM_TIMING2 0x2778 -static u64 ParseIndicesArg(const char *arg) +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 u64 ParseIndicesArg(const char* arg) { u64 mask = 0; std::istringstream ss(arg); @@ -365,7 +740,7 @@ static u64 ParseIndicesArg(const char *arg) return mask; } -static bool ParseNumericArg(int argc, const char *argv[], int &i, const char* arg, u32 &value) +static bool ParseNumericArg(int argc, const char* argv[], int& i, const char* arg, u32 & value) { if (!strcasecmp(arg, argv[i])) { @@ -386,23 +761,23 @@ static bool ParseNumericArg(int argc, const char *argv[], int &i, const char* ar return false; } -static int pci_find_instance(char *pci_string) +static int pci_find_instance(char* pci_string) { - DIR *dir = opendir("/sys/kernel/debug/dri"); + DIR* dir = opendir("/sys/kernel/debug/dri"); if (!dir) { perror("Couldn't open DRI under debugfs\n"); return -1; } - struct dirent *entry; + struct dirent* entry; while (entry = readdir(dir)) { if (!strcmp(entry->d_name, ".") || !strcmp(entry->d_name, "..")) continue; char name[300]; - snprintf(name, sizeof(name)-1, "/sys/kernel/debug/dri/%s/name", entry->d_name); - FILE *f = fopen(name, "r"); + snprintf(name, sizeof(name) - 1, "/sys/kernel/debug/dri/%s/name", entry->d_name); + FILE * f = fopen(name, "r"); if (!f) continue; char device[256]; @@ -429,28 +804,51 @@ static int pci_find_instance(char *pci_string) } typedef struct { - struct pci_dev *dev; + struct pci_dev* dev; int mmio; char log[1000]; bool modify[25]; + MANUFACTURER man; // HBM2 HBM2_TIMINGS hbm2; - // GDDR5 + // 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_MISC3 misc3; + 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 int gpu_compare(const void *A, const void *B) +static u32 ReadMMIODword(long address, GPU * gpu) +{ + u32 value; + lseek(gpu->mmio, address, SEEK_SET); + read(gpu->mmio, &value, sizeof(u32)); + return value; +} + +static int gpu_compare(const void* A, const void* B) { - const struct pci_dev *a = ((const GPU*)A)->dev; - const struct pci_dev *b = ((const GPU*)B)->dev; + const struct pci_dev* a = ((const GPU*)A)->dev; + const struct pci_dev* b = ((const GPU*)B)->dev; if (a->domain < b->domain) return -1; if (a->domain > b->domain) return 1; if (a->bus < b->bus) return -1; @@ -462,18 +860,23 @@ static int gpu_compare(const void *A, const void *B) return 0; } -static void PrintCurrentValues(GPU *gpu) +static void PrintCurrentValues(GPU * gpu) { fprintf(stdout, "pci:%04x:%02x:%02x.%d\n", gpu->dev->domain, gpu->dev->bus, gpu->dev->dev, gpu->dev->func); fflush(stdout); if (DetermineMemoryType(gpu->dev) == HBM2) { HBM2_TIMINGS current = gpu->hbm2; - std::cout << "Memory state: 0x" << std::hex << current.frequency << std::dec; + MANUFACTURER man = gpu->man; + std::cout << "Memory state: " << std::dec; + std::cout << + ((current.frequency == 0x118) ? "800MHz" : + (current.frequency == 0x11C) ? "1000MHz" : + (current.frequency == 0x11E) ? "1200MHz" : "Unknown") << std::endl; + std::cout << "Memory: " << std::dec; std::cout << - ((current.frequency == 0x118) ? " (800MHz)" : - (current.frequency == 0x11C) ? " (1000MHz)" : - (current.frequency == 0x11E) ? " (1200MHz)" : " (unknown)") << std::endl; + ((man.hbm.MAN == 0x63) ? "Hynix HBM2" : + (man.hbm.MAN == 0x61) ? "Samsung HBM2" : "Unknown") << std::endl; std::cout << "Timing 1:\t"; std::cout << " CL: " << current.CL << "\t"; std::cout << " RAS: " << current.RAS << "\t"; @@ -497,125 +900,365 @@ static void PrintCurrentValues(GPU *gpu) std::cout << "Timing 6:\t"; std::cout << " WR: " << current.WR << "\n"; std::cout << "Timing 7:\t"; - std::cout << " RREFD: " << current.RREFD << "\n"; + std::cout << " RREFD: " << current.RREFD << "\n"; std::cout << "Timing 8:\t"; - std::cout << " RDRDDD: " << current.RDRDDD << "\t"; - std::cout << " RDRDSD: " << current.RDRDSD << "\t"; + std::cout << " RDRDDD: " << current.RDRDDD << "\t"; + std::cout << " RDRDSD: " << current.RDRDSD << "\t"; std::cout << " RDRDSC: " << current.RDRDSC << "\t"; - std::cout << " RDRDSCL: " << current.RDRDSCL << "\n"; + std::cout << " RDRDSCL: " << current.RDRDSCL << "\n"; std::cout << "Timing 9:\t"; - std::cout << " WRWRDD: " << current.WRWRDD << "\t"; - std::cout << " WRWRSD: " << current.WRWRSD << "\t"; - std::cout << " WRWRSC: " << current.WRWRSC << "\t"; - std::cout << " WRWRSCL: " << current.WRWRSCL << "\n"; + std::cout << " WRWRDD: " << current.WRWRDD << "\t"; + std::cout << " WRWRSD: " << current.WRWRSD << "\t"; + std::cout << " WRWRSC: " << current.WRWRSC << "\t"; + std::cout << " WRWRSCL: " << current.WRWRSCL << "\n"; std::cout << "Timing 10:\t"; - std::cout << " WRRD: " << current.WRRD << "\t"; + std::cout << " WRRD: " << current.WRRD << "\t"; std::cout << " RDWR: " << current.RDWR << "\n"; std::cout << "Timing 12:\t"; - std::cout << " REF: " << current.REF << "\n"; + std::cout << " REF: " << current.REF << "\n"; std::cout << "Timing 13:\t"; - std::cout << " MRD: " << current.MRD << "\t"; + std::cout << " MRD: " << current.MRD << "\t"; std::cout << " MOD: " << current.MOD << "\n"; std::cout << "Timing 14:\t"; - std::cout << " XS: " << current.XS << "\n"; + std::cout << " XS: " << current.XS << "\n"; std::cout << "Timing 16:\t"; std::cout << " XSMRS: " << current.XSMRS << "\n"; std::cout << "Timing 17:\t"; - std::cout << " PD: " << current.PD << "\t"; - std::cout << " CKSRE: " << current.CKSRE << "\t"; + std::cout << " PD: " << current.PD << " \t"; + std::cout << " CKSRE: " << current.CKSRE << "\t"; std::cout << " CKSRX: " << current.CKSRX << "\n"; std::cout << "Timing 20:\t"; - std::cout << " RFCPB: " << current.RFCPB << "\t"; - std::cout << " STAG: " << current.STAG << "\n"; + std::cout << " RFCPB: " << current.RFCPB << "\t"; + std::cout << " STAG: " << current.STAG << "\n"; std::cout << "Timing 21:\t"; - std::cout << " XP: " << current.XP << "\t"; - std::cout << " CPDED: " << current.CPDED << "\t"; + std::cout << " XP: " << current.XP << " \t"; + std::cout << " CPDED: " << current.CPDED << "\t"; std::cout << " CKE: " << current.CKE << "\n"; std::cout << "Timing 22:\t"; - std::cout << " RDDATA: " << current.RDDATA << "\t"; - std::cout << " WRLAT: " << current.WRLAT << "\t"; - std::cout << " RDLAT: " << current.RDLAT << "\t"; + std::cout << " RDDATA: " << current.RDDATA << "\t"; + std::cout << " WRLAT: " << current.WRLAT << "\t"; + std::cout << " RDLAT: " << current.RDLAT << "\t"; std::cout << " WRDATA: " << current.WRDATA << "\n"; std::cout << "Timing 23:\t"; - std::cout << " CKESTAG: " << current.CKESTAG << "\n"; + std::cout << " CKESTAG: " << current.CKESTAG << "\n"; std::cout << "RFC Timing:\t"; std::cout << " RFC: " << current.RFC << "\n"; std::cout << "\n"; } + else if (DetermineMemoryType(gpu->dev) == 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 { - printf("PMG:\t"); - printf(" CKSRE: %d\t", gpu->pmg.CKSRE); - printf(" CKSRX: %d\t", gpu->pmg.CKSRX); - printf(" CKE_PULSE: %d\t", gpu->pmg.CKE_PULSE); - printf(" CKE: %d\t", gpu->pmg.CKE); - printf(" SEQ_IDLE: %d\n", gpu->pmg.SEQ_IDLE); - printf("CAS:\t"); - printf(" CL: %d\t", gpu->cas.CL); - printf(" W2R: %d\t", gpu->cas.W2R); - printf(" R2R: %d\t", gpu->cas.R2R); - printf(" CCLD: %d\t", gpu->cas.CCLD); - printf(" R2W: %d\t", gpu->cas.R2W); - printf(" NOPR: %d\t", gpu->cas.NOPR); - printf(" NOPW: %d\n", gpu->cas.NOPW); - printf("RAS:\t"); - printf(" RC: %d\t", gpu->ras.RC); + 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); - printf("MISC:\t"); + printf("CAS related timings:\n"); + printf(" \t CL: %d\t", gpu->cas.rx.CL); + printf(" W2R: %d\t", gpu->cas.rx.W2R); + printf(" R2R: %d\t", gpu->cas.rx.R2R); + printf(" CCDL: %d\t", gpu->cas.rx.CCDL); + printf(" R2W: %d\t", gpu->cas.rx.R2W); + printf(" NOPR: %d\t", gpu->cas.rx.NOPR); + printf(" NOPW: %d\n", gpu->cas.rx.NOPW); + printf("Misc. DRAM timings:\n"); if (IsR9(gpu->dev)) { - printf(" RFC: %d\t", gpu->misc.r9.RFC); + printf(" \t RFC: %d\t", gpu->misc.r9.RFC); printf(" TRP: %d\t", gpu->misc.r9.TRP); printf(" RP_RDA: %d\t", gpu->misc.r9.RP_RDA); printf(" RP_WRA: %d\n", gpu->misc.r9.RP_WRA); } else { - printf(" RFC: %d\t", gpu->misc.rx.RFC); + printf(" \t RFC: %d\t", gpu->misc.rx.RFC); printf(" TRP: %d\t", gpu->misc.rx.TRP); printf(" RP_RDA: %d\t", gpu->misc.rx.RP_RDA); printf(" RP_WRA: %d\n", gpu->misc.rx.RP_WRA); } - printf("MISC2:\t"); - printf(" WDATATR: %d\t", gpu->misc2.WDATATR); - printf(" T32AW: %d\t", gpu->misc2.T32AW); - printf(" CRCWL: %d\t", gpu->misc2.CRCWL); - printf(" CRCRL: %d\t", gpu->misc2.CRCRL); - printf(" FAW: %d\t", gpu->misc2.FAW); - printf(" PA2WDATA: %d\t", gpu->misc2.PA2WDATA); - printf(" PA2RDATA: %d\n", gpu->misc2.PA2RDATA); - printf("M3(MR4):\t"); - printf(" RAS: %d\n", gpu->misc3.RAS); - printf("DRAM1:\t"); - printf(" RASMACTWR: %d\t", gpu->dram1.RASMACTWR); + printf("Misc2. DRAM timings:\n"); + printf(" \t WDATATR: %d\t", gpu->misc2.rx.WDATATR); + printf(" T32AW: %d\t", gpu->misc2.rx.T32AW); + printf(" WEDC: %d\t", gpu->misc2.rx.WEDC); + printf(" REDC: %d\t", gpu->misc2.rx.REDC); + printf(" FAW: %d\t", gpu->misc2.rx.FAW); + printf(" PA2WDATA: %d\t", gpu->misc2.rx.PA2WDATA); + printf(" PA2RDATA: %d\n", gpu->misc2.rx.PA2RDATA); + printf("Mode Register 0:\n"); + printf(" \t WL: %d \t", gpu->smisc1.rx.WL); + printf(" CL: %d \t", gpu->smisc1.rx.CL); + printf(" TM: %d \t", gpu->smisc1.rx.TM); + printf(" WR: %d\n", gpu->smisc1.rx.WR); + printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA0); + printf(" BA1: %d\t ", gpu->smisc1.rx.BA1); + printf(" BA2: %d\t ", gpu->smisc1.rx.BA2); + printf(" BA3: %d\n", gpu->smisc1.rx.BA3); + printf("Mode Register 1:\n"); + printf(" \t DS: %d \t", gpu->smisc1.rx.DS); + printf(" DT: %d \t", gpu->smisc1.rx.DT); + printf(" ADR: %d\t ", gpu->smisc1.rx.ADR); + printf(" CAL: %d\t ", gpu->smisc1.rx.CAL); + printf(" PLL: %d\n ", gpu->smisc1.rx.PLL); + printf(" \t RDBI: %d\t", gpu->smisc1.rx.RDBI); + printf(" WDBI: %d\t", gpu->smisc1.rx.WDBI); + printf(" ABI: %d\t", gpu->smisc1.rx.ABI); + printf(" RESET: %d\n", gpu->smisc1.rx.RESET); + printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA_0); + printf(" BA1: %d\t ", gpu->smisc1.rx.BA_1); + printf(" BA2: %d\t ", gpu->smisc1.rx.BA_2); + printf(" BA3: %d\n", gpu->smisc1.rx.BA_3); + printf("Mode Register 2:\n"); + printf(" \t OCD_DWN: %d\t", gpu->smisc2.OCD_DWN); + printf(" OCD_UP: %d\t", gpu->smisc2.OCD_UP); + printf(" WCK: %d\t ", gpu->smisc2.WCK); + printf(" ADR: %d\n ", gpu->smisc2.ADR); + printf(" \t BA0: %d\t ", gpu->smisc2.BA0); + printf(" BA1: %d\t ", gpu->smisc2.BA1); + printf(" BA2: %d\t ", gpu->smisc2.BA2); + printf(" BA3: %d\n", gpu->smisc2.BA3); + printf("Mode Register 3:\n"); + printf(" \t SR: %d \t", gpu->smisc2.SR); + printf(" WCK01: %d\t", gpu->smisc2.WCK01); + printf(" WCK23: %d\t", gpu->smisc2.WCK23); + printf(" WCK2CK: %d\t", gpu->smisc2.WCK2CK); + printf(" RDQS: %d\t", gpu->smisc2.RDQS); + printf(" INFO: %d\t", gpu->smisc2.INFO); + printf(" WCK2: %d\n", gpu->smisc2.WCK2); + printf(" \t BA0: %d\t ", gpu->smisc2.BA_0); + printf(" BA1: %d\t ", gpu->smisc2.BA_1); + printf(" BA2: %d\t ", gpu->smisc2.BA_2); + printf(" BA3: %d\n", gpu->smisc2.BA_3); + printf("Mode Register 4:\n"); + printf(" \t EDCHP: %d\t", gpu->smisc3.EDCHP); + printf(" CRCWL: %d\t", gpu->smisc3.CRCWL); + printf(" CRCRL: %d\t", gpu->smisc3.CRCRL); + printf(" RDCRC: %d\t", gpu->smisc3.RDCRC); + printf(" WRCRC: %d\t", gpu->smisc3.WRCRC); + printf(" EDC: %d\n ", gpu->smisc3.EDC); + printf(" \t BA0: %d\t ", gpu->smisc3.BA0); + printf(" BA1: %d\t ", gpu->smisc3.BA1); + printf(" BA2: %d\t ", gpu->smisc3.BA2); + printf(" BA3: %d\n", gpu->smisc3.BA3); + printf("Mode Register 5:\n"); + printf(" \t LP1: %d\t ", gpu->smisc3.LP1); + printf(" LP1: %d\t ", gpu->smisc3.LP1); + printf(" LP1: %d\t ", gpu->smisc3.LP1); + printf(" PLL: %d\t ", gpu->smisc3.PLL); + printf(" RAS: %d\n ", gpu->smisc3.RAS); + printf(" \t BA0: %d\t ", gpu->smisc3.BA_0); + printf(" BA1: %d\t ", gpu->smisc3.BA_1); + printf(" BA2: %d\t ", gpu->smisc3.BA_2); + printf(" BA3: %d\n", gpu->smisc3.BA_3); + printf("Mode Register 6:\n"); + printf(" \t WCK: %d\t ", gpu->smisc4.WCK); + printf(" VREFD_M: %d\t", gpu->smisc4.VREFD_M); + printf(" A_VREFD: %d\t", gpu->smisc4.A_VREFD); + printf(" VREFD: %d\t", gpu->smisc4.VREFD); + printf(" VREFD_O: %d\t", gpu->smisc4.VREFD_O); + printf(" VREFD_0_2: %d\n", gpu->smisc4.VREFD_0_2); + printf(" \t BA0: %d\t ", gpu->smisc4.BA0); + printf(" BA1: %d\t ", gpu->smisc4.BA1); + printf(" BA2: %d\t ", gpu->smisc4.BA2); + printf(" BA3: %d\n", gpu->smisc4.BA3); + printf("Mode Register 7:\n"); + printf(" \t PLL_STD: %d\t", gpu->smisc4.PLL_STD); + printf(" PLL_FL: %d\t", gpu->smisc4.PLL_FL); + printf(" PLL_DEL: %d\t", gpu->smisc4.PLL_DEL); + printf(" LF_MOD: %d\t", gpu->smisc4.LF_MOD); + printf(" AUTO: %d\t", gpu->smisc4.AUTO); + printf(" DQ: %d\n ", gpu->smisc4.DQ); + printf(" \t TEMP: %d\t", gpu->smisc4.TEMP); + printf(" HALF: %d\t", gpu->smisc4.HALF); + printf(" VDD_R: %d\t", gpu->smisc4.VDD_R); + printf(" RFU: %d\n ", gpu->smisc4.RFU); + printf(" \t BA0: %d\t ", gpu->smisc4.BA_0); + printf(" BA1: %d\t ", gpu->smisc4.BA_1); + printf(" BA2: %d\t ", gpu->smisc4.BA_2); + printf(" BA3: %d\n", gpu->smisc4.BA_3); + printf("Mode Register 15:\n"); + printf(" \t MRE0: %d\t", gpu->smisc7.MRE0); + printf(" MRE1: %d\t", gpu->smisc7.MRE1); + printf(" ADT: %d\t ", gpu->smisc7.ADT); + printf(" RFU: %d\n ", gpu->smisc7.RFU); + printf(" \t BA0: %d\t ", gpu->smisc7.BA0); + printf(" BA1: %d\t ", gpu->smisc7.BA1); + printf(" BA2: %d\t ", gpu->smisc7.BA2); + printf(" BA3: %d\n", gpu->smisc7.BA3); + printf("Mode Register 8:\n"); + printf(" \t CLEHF: %d\t", gpu->smisc8.CLEHF); + printf(" WREHF: %d\t", gpu->smisc8.WREHF); + printf(" RFU: %d\n ", gpu->smisc8.RFU); + printf(" \t BA0: %d\t ", gpu->smisc8.BA0); + printf(" BA1: %d\t ", gpu->smisc8.BA1); + printf(" BA2: %d\t ", gpu->smisc8.BA2); + printf(" BA3: %d\n", gpu->smisc8.BA3); + printf("DRAM Specific:\n"); + printf(" \t RASMACTWR: %d\t", gpu->dram1.RASMACTWR); printf(" RASMACTRD: %d\t", gpu->dram1.RASMACTRD); printf(" ACTWR: %d\t", gpu->dram1.ACTWR); printf(" ACTRD: %d\n", gpu->dram1.ACTRD); - printf("DRAM2:\t"); - printf(" RAS2RAS: %d\t", gpu->dram2.RAS2RAS); + printf("DRAM2 Specific:\n"); + printf(" \t RAS2RAS: %d\t", gpu->dram2.RAS2RAS); printf(" RP: %d\t", gpu->dram2.RP); printf(" WRPLUSRP: %d\t", gpu->dram2.WRPLUSRP); printf(" BUS_TURN: %d\n", gpu->dram2.BUS_TURN); + printf("Refresh Interval:\n"); + printf(" \t REF: %d\n", gpu->ref.REF); + printf("Training timings:\n"); + printf(" \t TWT2RT: %d\t", gpu->train.TWT2RT); + printf(" TARF2T: %d\t", gpu->train.TARF2T); + printf(" TT2ROW: %d\t", gpu->train.TT2ROW); + printf(" TLD2LD: %d\n\n", gpu->train.TLD2LD); } } -int main(int argc, const char *argv[]) +void ReadMMIO(GPU * gpu); + +int main(int argc, const char* argv[]) { GPU gpus[64] = {}; - if ((argc < 2) || (0 == strcasecmp("--help", argv[1]))) + if ((argc < 2) || (0 == strcasecmp("--help", argv[1])) || (0 == strcasecmp("--h", argv[1]))) { - std::cout << " AMD Memory Tweak\n" + printf(" AMD Memory Tweak\n" " Read and modify memory timings on the fly\n" " By Eliovp & A.Solodovnikov\n\n" " Global command line options:\n" - " --help \tShow this output\n" + " --help|--h\tShow this output\n" + " --version|--v\tShow version info\n" " --gpu|--i [comma-separated gpu indices]\tSelected device(s)\n" - " --current \tList current timing values\n\n" + " --current|--c\tList current timing values\n\n" " Command line options: (HBM2)\n" " --CL|--cl [value]\n" " --RAS|--ras [value]\n" @@ -633,57 +1276,135 @@ int main(int argc, const char *argv[]) " --WR|--wr [value]\n" " --RREFD|--rrefd [value]\n" " --RDRDDD|--rdrddd [value]\n" - " --RDRDSD|--rdrdsd [value]\n" - " --RDRDSC|--rdrdsc [value]\n" - " --RDRDSCL|--rdrdscl [value]\n" - " --WRWRDD|--wrwrdd [value]\n" - " --WRWRSD|--wrwrsd [value]\n" - " --WRWRSC|--wrwrsc [value]\n" - " --WRWRSCL|--wrwrscl [value]\n" + " --RDRDSD|--rdrdsd [value]\n" + " --RDRDSC|--rdrdsc [value]\n" + " --RDRDSCL|--rdrdscl [value]\n" + " --WRWRDD|--wrwrdd [value]\n" + " --WRWRSD|--wrwrsd [value]\n" + " --WRWRSC|--wrwrsc [value]\n" + " --WRWRSCL|--wrwrscl [value]\n" " --WRRD|--wrrd [value]\n" " --RDWR|--rdwr [value]\n" " --REF|--ref [value]\n" " --MRD|--mrd [value]\n" " --MOD|--mod [value]\n" - " --XS|--xs [value]\n" - " --XSMRS|--xsmrs [value]\n" + " --XS|--xs [value]\n" + " --XSMRS|--xsmrs [value]\n" " --PD|--pd [value]\n" " --CKSRE|--cksre [value]\n" " --CKSRX|--cksrx [value]\n" - " --RFCPB|--rfcpb [value]\n" - " --STAG|--stag [value]\n" - " --XP|--xp [value]\n" - " --CPDED|--cpded [value]\n" - " --CKE|--cke [value]\n" - " --RDDATA|--rddata [value]\n" - " --WRLAT|--wrlat [value]\n" - " --RDLAT|--rdlat [value]\n" - " --WRDATA|--wrdata [value]\n" - " --CKESTAG|--ckestag [value]\n" + " --RFCPB|--rfcpb [value]\n" + " --STAG|--stag [value]\n" + " --XP|--xp [value]\n" + " --CPDED|--cpded [value]\n" + " --CKE|--cke [value]\n" + " --RDDATA|--rddata [value]\n" + " --WRLAT|--wrlat [value]\n" + " --RDLAT|--rdlat [value]\n" + " --WRDATA|--wrdata [value]\n" + " --CKESTAG|--ckestag [value]\n" " --RFC|--rfc [value]\n\n" + " Command line options: (HBM)\n" + " --DAT_DLY0|1|2|3 | --dat_dly0|1|2|3 [value]\n" + " --DQS_DLY0|1|2|3 | --dqs_dly0|1|2|3 [value]\n" + " --DQS_XTR0|1|2|3 | --dqs_xtr0|1|2|3 [value]\n" + " --OEN_DLY0|1|2|3 | --oen_dly0|1|2|3 [value]\n" + " --OEN_EXT0|1|2|3 | --oen_ext0|1|2|3 [value]\n" + " --OEN_SEL0|1|2|3 | --oen_sel0|1|2|3 [value]\n" + " --CMD_DLY0|1|2|3 | --cmd_dly0|1|2|3 [value]\n" + " --ADR_DLY0|1|2|3 | --adr_dly0|1|2|3 [value]\n" + " --CKSRE|--cksre [value]\n" + " --CKSRX|--cksrx [value]\n" + " --CKE_PULSE|--cke_pulse [value]\n" + " --CKE|--cke [value]\n" + " --SEQ_IDLE|--seq_idle [value]\n" + " --CL|--cl [value]\n" + " --W2R|--w2r [value]\n" + " --R2R|--r2r [value]\n" + " --CCDL|--ccdl [value]\n" + " --R2W|--r2w [value]\n" + " --NOPR|--nopr [value]\n" + " --NOPW|--nopw [value]\n" + " --RCDW|--rcdw [value]\n" + " --RCDWA|--rcdwa [value]\n" + " --RCDR|--rcdr [value]\n" + " --RCDRA|--rcdra [value]\n" + " --RRD|--rrd [value]\n" + " --RC|--rc [value]\n" + " --MRD|--mrd [value]\n" + " --RRDL|--rrdl [value]\n" + " --RFC|--rfc [value]\n" + " --TRP|--trp [value]\n" + " --RP_WRA|--rp_wra [value]\n" + " --RP_RDA|--rp_rda [value]\n" + " --WDATATR|--wdatatr [value]\n" + " --T32AW|--t32aw [value]\n" + " --CRCWL|--crcwl [value]\n" + " --CRCRL|--crcrl [value]\n" + " --FAW|--faw [value]\n" + " --PA2WDATA|--pa2wdata [value]\n" + " --PA2RDATA|--pa2rdata [value]\n" + " --DBR|--dbr [value]\n" + " --DBW|--dbw [value]\n" + " --TCSR|--tcsr [value]\n" + " --DQR|--dqr [value]\n" + " --DQW|--dqw [value]\n" + " --ADD_PAR|--add_par [value]\n" + " --TM|--tm [value]\n" + " --WR|--wr [value]\n" + " --NDS|--nds [value]\n" + " --WL|--wl [value]\n" + " --RL|--rl [value]\n" + " --APRAS|--apras [value]\n" + " --BG|--bg [value]\n" + " --BL|--bl [value]\n" + " --REF|--ref [value]\n" + " --ENB|--enb [value]\n" + " --CNT|--cnt [value]\n" + " --TRC|--trc [value]\n" + " --THRESH|--thresh [value]\n" + " --LEVEL|--level [value]\n" + " --PWRDOWN|--pwrdown [value]\n" + " --SHUTDOWN|--shutdown [value]\n" + " --EN_SHUTDOWN|--en_shutdown [value]\n" + " --OVERSAMPLE|--oversample [value]\n" + " --AVG_SAMPLE|--avg_sample [value]\n\n" " Command line options: (GDDR5)\n" + " --DAT_DLY0|1 | --dat_dly0|1 [value]\n" + " --DQS_DLY0|1 | --dqs_dly0|1 [value]\n" + " --DQS_XTR0|1 | --dqs_xtr0|1 [value]\n" + " --DAT_2Y_DLY0|1 | --dat_2y_dly0|1 [value]\n" + " --ADR_2Y_DLY0|1 | --adr_2y_dly0|1 [value]\n" + " --CMD_2Y_DLY0|1 | --cmd_2y_dly0|1 [value]\n" + " --OEN_DLY0|1 | --oen_dly0|1 [value]\n" + " --OEN_EXT0|1 | --oen_ext0|1 [value]\n" + " --OEN_SEL0|1 | --oen_sel0|1 [value]\n" + " --ODT_DLY0|1 | --odt_dly0|1 [value]\n" + " --ODT_EXT0|1 | --odt_ext0|1 [value]\n" + " --ADR_DLY0|1 | --adr_dly0|1 [value]\n" + " --CMD_DLY0|1 | --cmd_dly0|1 [value]\n" " --CKSRE|--cksre [value]\n" - " --CKSRX|--cksrx [value]\n" - " --CKE_PULSE|--cke_pulse [value]\n" - " --CKE|--cke [value]\n" - " --SEQ_IDLE|--seq_idle [value]\n" + " --CKSRX|--cksrx [value]\n" + " --CKE_PULSE|--cke_pulse [value]\n" + " --CKE|--cke [value]\n" + " --SEQ_IDLE|--seq_idle [value]\n" " --CL|--cl [value]\n" " --W2R|--w2r [value]\n" - " --R2R|--r2r [value]\n" - " --CCLD|--ccld [value]\n" - " --R2W|--r2w [value]\n" + " --R2R|--r2r [value]\n" + " --CCDL|--ccdl [value]\n" + " --R2W|--r2w [value]\n" " --NOPR|--nopr [value]\n" - " --NOPW|--nopw [value]\n" - " --RCDW|--rcdw [value]\n" - " --RCDWA|--rcdwa [value]\n" - " --RCDR|--rcdr [value]\n" - " --RCDRA|--rcdra [value]\n" - " --RRD|--rrd [value]\n" - " --RC|--rc [value]\n" - " --RFC|--rfc [value]\n" - " --TRP|--trp [value]\n" + " --NOPW|--nopw [value]\n" + " --RCDW|--rcdw [value]\n" + " --RCDWA|--rcdwa [value]\n" + " --RCDR|--rcdr [value]\n" + " --RCDRA|--rcdra [value]\n" + " --RRD|--rrd [value]\n" + " --RC|--rc [value]\n" + " --RFC|--rfc [value]\n" + " --TRP|--trp [value]\n" " --RP_WRA|--rp_wra [value]\n" - " --RP_RDA|--rp_rda [value]\n" + " --RP_RDA|--rp_rda [value]\n" " --WDATATR|--wdatatr [value]\n" " --T32AW|--t32aw [value]\n" " --CRCWL|--crcwl [value]\n" @@ -691,30 +1412,71 @@ int main(int argc, const char *argv[]) " --FAW|--faw [value]\n" " --PA2WDATA|--pa2wdata [value]\n" " --PA2RDATA|--pa2rdata [value]\n" + " --WL|--wl [value]\n" + " --MR0_CL|--mr0_cl [value]\n" + " --TM|--tm [value]\n" + " --WR|--wr [value]\n" + " --DS|--ds [value]\n" + " --DT|--dt [value]\n" + " --ADR|--adr [value]\n" + " --CAL|--cal [value]\n" + " --PLL|--pll [value]\n" + " --RDBI|--rdbi [value]\n" + " --WDBI|--wdbi [value]\n" + " --ABI|--abi [value]\n" + " --RESET|--reset [value]\n" + " --SR|--sr [value]\n" + " --WCK01|--wck01 [value]\n" + " --WCK23|--wck23 [value]\n" + " --WCK2CK|--wck2ck [value]\n" + " --RDQS|--rdqs [value]\n" + " --INFO|--info [value]\n" + " --WCK2|--wck2 [value]\n" + " --BG|--bg [value]\n" + " --EDCHP|--edchp [value]\n" + " --CRCWL|--crcwl [value]\n" + " --CRCRL|--crcrl [value]\n" + " --RDCRC|--rdcrc [value]\n" + " --WRCRC|--wrcrc [value]\n" + " --EDC|--edc [value]\n" " --RAS|--ras [value]\n" - " --ACTRD|--actrd [value]\n" - " --ACTWR|--actwr [value]\n" - " --RASMACTRD|--rasmactrd [value]\n" - " --RASMACWTR|--rasmacwtr [value]\n" - " --RAS2RAS|--ras2ras [value]\n" - " --RP|--rp [value]\n" - " --WRPLUSRP|--wrplusrp [value]\n" - " --BUS_TURN|--bus_turn [value]\n\n" - " HBM2 Example usage: ./amdmemtool -i 0,3,5 --faw 12 --RFC 208\n" - " GDDR5 Example usage: ./amdmemtool -i 1,2,4 --RFC 43 --ras2ras 176\n\n" + " --CLEHF|--clehf [value]\n" + " --WREHF|--wrehf [value]\n" + " --ACTRD|--actrd [value]\n" + " --ACTWR|--actwr [value]\n" + " --RASMACTRD|--rasmactrd [value]\n" + " --RASMACWTR|--rasmacwtr [value]\n" + " --RAS2RAS|--ras2ras [value]\n" + " --RP|--rp [value]\n" + " --WRPLUSRP|--wrplusrp [value]\n" + " --BUS_TURN|--bus_turn [value]\n" + " --REF|--ref [value]\n" + " --TWT2RT|--twt2rt [value]\n" + " --TARF2T|--tarf2t [value]\n" + " --TT2ROW|--tt2row [value]\n" + " --TLD2LD|--tld2ld [value]\n\n" + " HBM2 Example usage: ./amdmemtool --i 0,3,5 --faw 12 --RFC 208\n" + " HBM Example usage: ./amdmemtool --i 6 --ref 13\n" + " GDDR5 Example usage: ./amdmemtool --i 1,2,4 --RFC 43 --ras2ras 176\n\n" " Make sure to run the program first with parameter --current to see what the current values are.\n" " Current values may change based on state of the GPU,\n" " in other words, make sure the GPU is under load when running --current\n" " HBM2 Based GPU's do not need to be under load to apply timing changes.\n" - " Hint: Certain timings such as CL (Cas Latency) are stability timings, lowering these will lower stability.\n"; + " Hint: Certain timings such as CL (Cas Latency) are stability timings, lowering these will lower stability.\n"); return 0; } - struct pci_access *pci = pci_alloc(); + if (!strcasecmp("--version", argv[1]) || !strcasecmp("--v", argv[1])) + { + printf(VERSION); + return EXIT_SUCCESS; + } + + struct pci_access* pci = pci_alloc(); pci_init(pci); pci_scan_bus(pci); int gpuCount = 0; - for (struct pci_dev *dev = pci->devices; dev; dev = dev->next) + for (struct pci_dev* dev = pci->devices; dev; dev = dev->next) { pci_fill_info(dev, PCI_FILL_IDENT | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES | PCI_FILL_CLASS); if (IsAmdDisplayDevice(dev)) @@ -734,13 +1496,13 @@ int main(int argc, const char *argv[]) //printf("Detected GPU's\n"); for (int i = 0; i < gpuCount; i++) { - GPU *gpu = &gpus[i]; + GPU* gpu = &gpus[i]; char buffer[1024]; //char *name = pci_lookup_name(pci, buffer, sizeof(buffer), PCI_LOOKUP_DEVICE, gpu->dev->vendor_id, gpu->dev->device_id); //printf(" (%s)\n", name); - snprintf(buffer, sizeof(buffer)-1, "%04x:%02x:%02x.%d", gpu->dev->domain, gpu->dev->bus, gpu->dev->dev, gpu->dev->func); + snprintf(buffer, sizeof(buffer) - 1, "%04x:%02x:%02x.%d", gpu->dev->domain, gpu->dev->bus, gpu->dev->dev, gpu->dev->func); int instance = pci_find_instance(buffer); if (instance == -1) { @@ -748,7 +1510,7 @@ int main(int argc, const char *argv[]) return 1; } - snprintf(buffer, sizeof(buffer)-1, "/sys/kernel/debug/dri/%d/amdgpu_regs", instance); + snprintf(buffer, sizeof(buffer) - 1, "/sys/kernel/debug/dri/%d/amdgpu_regs", instance); gpu->mmio = open(buffer, O_RDWR); if (gpu->mmio == -1) { @@ -759,51 +1521,97 @@ int main(int argc, const char *argv[]) switch (DetermineMemoryType(gpu->dev)) { case HBM2: - lseek(gpu->mmio, AMD_TIMING_REGS_BASE_1, SEEK_SET); - read(gpu->mmio, &gpu->hbm2, sizeof(gpu->hbm2)); + for (int j = 0; j < sizeof(HBM2_TIMINGS) / 4; j++) + { + *((u32*)& gpu->hbm2 + j) = ReadMMIODword(AMD_TIMING_REGS_BASE_1 + j * sizeof(u32), gpu); + } + gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM2, gpu); break; case GDDR5: - lseek(gpu->mmio, MC_SEQ_PMG_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->pmg, sizeof(gpu->pmg)); - lseek(gpu->mmio, MC_SEQ_RAS_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->ras, sizeof(gpu->ras)); - lseek(gpu->mmio, MC_SEQ_CAS_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->cas, sizeof(gpu->cas)); - lseek(gpu->mmio, MC_SEQ_MISC_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->misc, sizeof(gpu->misc)); - lseek(gpu->mmio, MC_SEQ_MISC_TIMING2, SEEK_SET); - read(gpu->mmio, &gpu->misc2, sizeof(gpu->misc2)); - lseek(gpu->mmio, MC_SEQ_MISC3, SEEK_SET); - read(gpu->mmio, &gpu->misc3, sizeof(gpu->misc3)); - lseek(gpu->mmio, MC_ARB_DRAM_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->dram1, sizeof(gpu->dram1)); - lseek(gpu->mmio, MC_ARB_DRAM_TIMING2, SEEK_SET); - read(gpu->mmio, &gpu->dram2, sizeof(gpu->dram2)); + gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0, gpu); + gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1, gpu); + gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING, gpu); + gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING, gpu); + gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING, gpu); + gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING, gpu); + gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2, gpu); + gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1, gpu); + gpu->smisc2.value = ReadMMIODword(MC_SEC_MISC2, gpu); + gpu->smisc3.value = ReadMMIODword(MC_SEC_MISC3, gpu); + gpu->smisc4.value = ReadMMIODword(MC_SEC_MISC4, gpu); + gpu->smisc7.value = ReadMMIODword(MC_SEC_MISC7, gpu); + gpu->smisc8.value = ReadMMIODword(MC_SEC_MISC8, gpu); + gpu->dram1.value = ReadMMIODword(MC_ARB_DRAM_TIMING, gpu); + gpu->dram2.value = ReadMMIODword(MC_ARB_DRAM_TIMING2, gpu); + gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, gpu); + gpu->train.value = ReadMMIODword(MC_SEQ_TRAINING, gpu); + gpu->man.value = ReadMMIODword(MANUFACTURER_ID, gpu); + break; + case HBM: + gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0_HBM, gpu); + gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1_HBM, gpu); + gpu->ctl3.value = ReadMMIODword(MC_SEQ_WR_CTL_D2_HBM, gpu); + gpu->ctl4.value = ReadMMIODword(MC_SEQ_WR_CTL_D3_HBM, gpu); + gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING_HBM, gpu); + gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING_HBM, gpu); + gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING_HBM, gpu); + gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING_HBM, gpu); + gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2_HBM, gpu); + gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1_HBM, gpu); + gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, gpu); + gpu->ham.value = ReadMMIODword(MC_SEQ_ROW_HAMMER, gpu); + gpu->throt.value = ReadMMIODword(MC_THERMAL_THROTTLE, gpu); + gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM, gpu); break; - /* case HBM: - // maybe supported? - lseek(gpu->mmio, 0x28, SEEK_SET); - read(gpu->mmio, &gpu->ras, sizeof(gpu->ras)); - lseek(gpu->mmio, 0x28, SEEK_SET); - read(gpu->mmio, &gpu->cas, sizeof(gpu->cas)); - lseek(gpu->mmio, 0x28, SEEK_SET); - read(gpu->mmio, &gpu->misc, sizeof(gpu->misc)); - lseek(gpu->mmio, 0x28, SEEK_SET); - read(gpu->mmio, &gpu->misc2, sizeof(gpu->misc2)); - lseek(gpu->mmio, MC_ARB_DRAM_TIMING, SEEK_SET); - read(gpu->mmio, &gpu->dram1, sizeof(gpu->dram1)); - lseek(gpu->mmio, MC_ARB_DRAM_TIMING2, SEEK_SET); - read(gpu->mmio, &gpu->dram2, sizeof(gpu->dram2)); - break; */ } } + // Scan some regs, you never know, you might find something useful ;-) + if (!strcasecmp("--scan", argv[1])) + { + if ((argc < 4) || memcmp(argv[2], "0x", 2) || memcmp(argv[3], "0x", 2)) + { + printf("--scan requires a range of addresses in hex format (for example 0x9A0290 0x9A02C4).\n"); + return EXIT_FAILURE; + } + u32 low = strtoul(argv[2] + 2, 0, 16); + if ((errno == EINVAL) || (errno == ERANGE)) + { + printf("Failed to parse %s as a hex number\n", argv[2]); + return EXIT_FAILURE; + } + u32 high = strtoul(argv[3] + 2, 0, 16); + if ((errno == EINVAL) || (errno == ERANGE)) + { + printf("Failed to parse %s as a hex number\n", argv[3]); + return EXIT_FAILURE; + } + + for (int index = 0; index < gpuCount; index++) + { + GPU* gpu = &gpus[index]; + char buffer[1024]; + char* name = pci_lookup_name(pci, buffer, sizeof(buffer), PCI_LOOKUP_DEVICE, gpu->dev->vendor_id, gpu->dev->device_id); + if (gpu->dev && IsRelevantDeviceID(gpu->dev)) + { + printf("Scanning GPU %d\n", index); + for (u32 address = low; address <= high; address += sizeof(u32)) + { + u32 value = ReadMMIODword(address, gpu); + printf("0x%X: %08X\n", address, value); + usleep(50); + } + } + } + return EXIT_SUCCESS; + } + // Parses the command line arguments, and accumulates the changes. for (int index = 0; index < gpuCount; index++) { - GPU *gpu = &gpus[index]; + GPU* gpu = &gpus[index]; char buffer[1024]; - char *name = pci_lookup_name(pci, buffer, sizeof(buffer), PCI_LOOKUP_DEVICE, gpu->dev->vendor_id, gpu->dev->device_id); + char* name = pci_lookup_name(pci, buffer, sizeof(buffer), PCI_LOOKUP_DEVICE, gpu->dev->vendor_id, gpu->dev->device_id); if (gpu->dev && IsRelevantDeviceID(gpu->dev)) { u64 affectedGPUs = 0xFFFFFFFFFFFFFFFF; // apply to all GPUs by default @@ -819,7 +1627,7 @@ int main(int argc, const char *argv[]) i++; affectedGPUs = ParseIndicesArg(argv[i]); } - else if (!strcasecmp("--current", argv[i])) + else if (!strcasecmp("--current", argv[i]) || !strcasecmp("--c", argv[i])) { if (affectedGPUs & ((u64)1 << index)) { @@ -892,13 +1700,13 @@ int main(int argc, const char *argv[]) strcat(gpu->log, "RRD"); } else if (ParseNumericArg(argc, argv, i, "--RRDL", value)) - { - gpu->hbm2.RRDL = value; - gpu->modify[0] = true; - gpu->modify[3] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RRD"); - } + { + gpu->hbm2.RRDL = value; + gpu->modify[0] = true; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRD"); + } else if (ParseNumericArg(argc, argv, i, "--RTP", value)) { gpu->hbm2.RTP = value; @@ -940,101 +1748,101 @@ int main(int argc, const char *argv[]) strcat(gpu->log, "WTRL"); } else if (ParseNumericArg(argc, argv, i, "--WR", value)) - { - gpu->hbm2.WR = value; - gpu->modify[0] = true; - gpu->modify[6] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WR"); - } + { + gpu->hbm2.WR = value; + gpu->modify[0] = true; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WR"); + } else if (ParseNumericArg(argc, argv, i, "--RREFD", value)) - { - gpu->hbm2.RREFD = value; - gpu->modify[0] = true; - gpu->modify[7] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RREFD"); - } + { + gpu->hbm2.RREFD = value; + gpu->modify[0] = true; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RREFD"); + } else if (ParseNumericArg(argc, argv, i, "--RDRDDD", value)) - { - gpu->hbm2.RDRDDD = value; - gpu->modify[0] = true; - gpu->modify[8] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDRDDD"); - } + { + gpu->hbm2.RDRDDD = value; + gpu->modify[0] = true; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDRDDD"); + } else if (ParseNumericArg(argc, argv, i, "--RDRDSD", value)) - { - gpu->hbm2.RDRDSD = value; - gpu->modify[0] = true; - gpu->modify[8] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDRDSD"); - } - else if (ParseNumericArg(argc, argv, i, "--RDRDSC", value)) - { - gpu->hbm2.RDRDSC = value; - gpu->modify[0] = true; - gpu->modify[8] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDRDSC"); - } - else if (ParseNumericArg(argc, argv, i, "--RDRDSCL", value)) - { - gpu->hbm2.RDRDSCL = value; - gpu->modify[0] = true; - gpu->modify[8] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDRDSCL"); - } + { + gpu->hbm2.RDRDSD = value; + gpu->modify[0] = true; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDRDSD"); + } + else if (ParseNumericArg(argc, argv, i, "--RDRDSC", value)) + { + gpu->hbm2.RDRDSC = value; + gpu->modify[0] = true; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDRDSC"); + } + else if (ParseNumericArg(argc, argv, i, "--RDRDSCL", value)) + { + gpu->hbm2.RDRDSCL = value; + gpu->modify[0] = true; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDRDSCL"); + } else if (ParseNumericArg(argc, argv, i, "--WRWRDD", value)) - { - gpu->hbm2.WRWRDD = value; - gpu->modify[0] = true; - gpu->modify[9] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRWRDD"); - } - else if (ParseNumericArg(argc, argv, i, "--WRWRSD", value)) - { - gpu->hbm2.WRWRSD = value; - gpu->modify[0] = true; - gpu->modify[9] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRWRSD"); - } - else if (ParseNumericArg(argc, argv, i, "--WRWRSC", value)) - { - gpu->hbm2.WRWRSC = value; - gpu->modify[0] = true; - gpu->modify[9] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRWRSC"); - } - else if (ParseNumericArg(argc, argv, i, "--WRWRSCL", value)) - { - gpu->hbm2.WRWRSCL = value; - gpu->modify[0] = true; - gpu->modify[9] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRWRSCL"); - } + { + gpu->hbm2.WRWRDD = value; + gpu->modify[0] = true; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRWRDD"); + } + else if (ParseNumericArg(argc, argv, i, "--WRWRSD", value)) + { + gpu->hbm2.WRWRSD = value; + gpu->modify[0] = true; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRWRSD"); + } + else if (ParseNumericArg(argc, argv, i, "--WRWRSC", value)) + { + gpu->hbm2.WRWRSC = value; + gpu->modify[0] = true; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRWRSC"); + } + else if (ParseNumericArg(argc, argv, i, "--WRWRSCL", value)) + { + gpu->hbm2.WRWRSCL = value; + gpu->modify[0] = true; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRWRSCL"); + } else if (ParseNumericArg(argc, argv, i, "--WRRD", value)) - { - gpu->hbm2.WRRD = value; - gpu->modify[0] = true; - gpu->modify[10] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRRD"); - } + { + gpu->hbm2.WRRD = value; + gpu->modify[0] = true; + gpu->modify[10] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRRD"); + } else if (ParseNumericArg(argc, argv, i, "--RDWR", value)) - { - gpu->hbm2.RDWR = value; - gpu->modify[0] = true; - gpu->modify[10] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDWR"); - } + { + gpu->hbm2.RDWR = value; + gpu->modify[0] = true; + gpu->modify[10] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDWR"); + } else if (ParseNumericArg(argc, argv, i, "--REF", value)) { gpu->hbm2.REF = value; @@ -1060,21 +1868,21 @@ int main(int argc, const char *argv[]) strcat(gpu->log, "MOD"); } else if (ParseNumericArg(argc, argv, i, "--XS", value)) - { - gpu->hbm2.XS = value; - gpu->modify[0] = true; - gpu->modify[14] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "XS"); - } + { + gpu->hbm2.XS = value; + gpu->modify[0] = true; + gpu->modify[14] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "XS"); + } else if (ParseNumericArg(argc, argv, i, "--XSMRS", value)) - { - gpu->hbm2.XSMRS = value; - gpu->modify[0] = true; - gpu->modify[16] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "XSMRS"); - } + { + gpu->hbm2.XSMRS = value; + gpu->modify[0] = true; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "XSMRS"); + } else if (ParseNumericArg(argc, argv, i, "--PD", value)) { gpu->hbm2.PD = value; @@ -1100,362 +1908,1401 @@ int main(int argc, const char *argv[]) strcat(gpu->log, "CKSRX"); } else if (ParseNumericArg(argc, argv, i, "--RFCPB", value)) - { - gpu->hbm2.RFCPB = value; - gpu->modify[0] = true; - gpu->modify[20] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RFCPB"); - } - else if (ParseNumericArg(argc, argv, i, "--STAG", value)) - { - gpu->hbm2.STAG = value; - gpu->modify[0] = true; - gpu->modify[20] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "STAG"); - } - else if (ParseNumericArg(argc, argv, i, "--XP", value)) - { - gpu->hbm2.XP = value; - gpu->modify[0] = true; - gpu->modify[21] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "XP"); - } - else if (ParseNumericArg(argc, argv, i, "--CPDED", value)) - { - gpu->hbm2.CPDED = value; - gpu->modify[0] = true; - gpu->modify[21] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CPDED"); - } - else if (ParseNumericArg(argc, argv, i, "--CKE", value)) - { - gpu->hbm2.CKE = value; - gpu->modify[0] = true; - gpu->modify[21] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKE"); - } - else if (ParseNumericArg(argc, argv, i, "--RDDATA", value)) - { - gpu->hbm2.RDDATA = value; - gpu->modify[0] = true; - gpu->modify[22] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDDATA"); - } - else if (ParseNumericArg(argc, argv, i, "--WRLAT", value)) - { - gpu->hbm2.WRLAT = value; - gpu->modify[0] = true; - gpu->modify[22] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRLAT"); - } - else if (ParseNumericArg(argc, argv, i, "--RDLAT", value)) - { - gpu->hbm2.RDLAT = value; - gpu->modify[0] = true; - gpu->modify[22] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RDLAT"); - } - else if (ParseNumericArg(argc, argv, i, "--WRDATA", value)) - { - gpu->hbm2.WRDATA = value; - gpu->modify[0] = true; - gpu->modify[22] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WRDATA"); - } - else if (ParseNumericArg(argc, argv, i, "--CKESTAG", value)) - { - gpu->hbm2.CKESTAG = value; - gpu->modify[0] = true; - gpu->modify[23] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKESTAG"); - } - else if (ParseNumericArg(argc, argv, i, "--RFC", value)) { - gpu->hbm2.RFC = value; + gpu->hbm2.RFCPB = value; gpu->modify[0] = true; - gpu->modify[24] = true; + gpu->modify[20] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RFC"); + strcat(gpu->log, "RFCPB"); } - } - else // GDDR5 & HBM - { - if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) - { - gpu->pmg.CKSRE = value; - gpu->modify[0] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKSRE"); - } - else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) - { - gpu->pmg.CKSRX = value; - gpu->modify[0] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKSRX"); - } - else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) - { - gpu->pmg.CKE_PULSE = value; - gpu->modify[0] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKE_PULSE"); - } - else if (ParseNumericArg(argc, argv, i, "--CKE", value)) - { - gpu->pmg.CKE = value; - gpu->modify[0] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKE"); - } - else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) - { - gpu->pmg.SEQ_IDLE = value; - gpu->modify[0] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "SEQ_IDLE"); - } - else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + else if (ParseNumericArg(argc, argv, i, "--STAG", value)) { - gpu->ras.RCDW = value; - gpu->modify[1] = true; + gpu->hbm2.STAG = value; + gpu->modify[0] = true; + gpu->modify[20] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDW"); + strcat(gpu->log, "STAG"); } - else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + else if (ParseNumericArg(argc, argv, i, "--XP", value)) { - gpu->ras.RCDWA = value; - gpu->modify[1] = true; + gpu->hbm2.XP = value; + gpu->modify[0] = true; + gpu->modify[21] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDWA"); + strcat(gpu->log, "XP"); } - else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + else if (ParseNumericArg(argc, argv, i, "--CPDED", value)) { - gpu->ras.RCDR = value; - gpu->modify[1] = true; + gpu->hbm2.CPDED = value; + gpu->modify[0] = true; + gpu->modify[21] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDR"); + strcat(gpu->log, "CPDED"); } - else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + else if (ParseNumericArg(argc, argv, i, "--CKE", value)) { - gpu->ras.RCDRA = value; - gpu->modify[1] = true; + gpu->hbm2.CKE = value; + gpu->modify[0] = true; + gpu->modify[21] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDRA"); + strcat(gpu->log, "CKE"); } - else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + else if (ParseNumericArg(argc, argv, i, "--RDDATA", value)) { - gpu->ras.RRD = value; - gpu->modify[1] = true; + gpu->hbm2.RDDATA = value; + gpu->modify[0] = true; + gpu->modify[22] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RRD"); + strcat(gpu->log, "RDDATA"); } - else if (ParseNumericArg(argc, argv, i, "--RC", value)) + else if (ParseNumericArg(argc, argv, i, "--WRLAT", value)) { - gpu->ras.RC = value; - gpu->modify[1] = true; + gpu->hbm2.WRLAT = value; + gpu->modify[0] = true; + gpu->modify[22] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RC"); + strcat(gpu->log, "WRLAT"); + } + else if (ParseNumericArg(argc, argv, i, "--RDLAT", value)) + { + gpu->hbm2.RDLAT = value; + gpu->modify[0] = true; + gpu->modify[22] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDLAT"); + } + else if (ParseNumericArg(argc, argv, i, "--WRDATA", value)) + { + gpu->hbm2.WRDATA = value; + gpu->modify[0] = true; + gpu->modify[22] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--CKESTAG", value)) + { + gpu->hbm2.CKESTAG = value; + gpu->modify[0] = true; + gpu->modify[23] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKESTAG"); + } + else if (ParseNumericArg(argc, argv, i, "--RFC", value)) + { + gpu->hbm2.RFC = value; + gpu->modify[0] = true; + gpu->modify[24] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RFC"); + } + } + else if (DetermineMemoryType(gpu->dev) == HBM) { + if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) + { + gpu->ctl1.hbm.DAT_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) + { + gpu->ctl1.hbm.DQS_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) + { + gpu->ctl1.hbm.DQS_XTR = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) + { + gpu->ctl1.hbm.OEN_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) + { + gpu->ctl1.hbm.OEN_EXT = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) + { + gpu->ctl1.hbm.OEN_SEL = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) + { + gpu->ctl1.hbm.CMD_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) + { + gpu->ctl1.hbm.ADR_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) + { + gpu->ctl2.hbm.DAT_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) + { + gpu->ctl2.hbm.DQS_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) + { + gpu->ctl2.hbm.DQS_XTR = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) + { + gpu->ctl2.hbm.OEN_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) + { + gpu->ctl2.hbm.OEN_EXT = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) + { + gpu->ctl2.hbm.OEN_SEL = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL1"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) + { + gpu->ctl2.hbm.CMD_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) + { + gpu->ctl2.hbm.ADR_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY2", value)) + { + gpu->ctl3.DAT_DLY = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY2", value)) + { + gpu->ctl3.DQS_DLY = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR2", value)) + { + gpu->ctl3.DQS_XTR = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR2"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY2", value)) + { + gpu->ctl3.OEN_DLY = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT2", value)) + { + gpu->ctl3.OEN_EXT = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT2"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL2", value)) + { + gpu->ctl3.OEN_SEL = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL2"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY2", value)) + { + gpu->ctl3.CMD_DLY = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY2", value)) + { + gpu->ctl3.ADR_DLY = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY3", value)) + { + gpu->ctl4.DAT_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY3", value)) + { + gpu->ctl4.DQS_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR3", value)) + { + gpu->ctl4.DQS_XTR = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR3"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY3", value)) + { + gpu->ctl4.OEN_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT3", value)) + { + gpu->ctl4.OEN_EXT = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT3"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL3", value)) + { + gpu->ctl4.OEN_SEL = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL3"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY3", value)) + { + gpu->ctl4.CMD_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY3", value)) + { + gpu->ctl4.ADR_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) + { + gpu->pmg.hbm.CKSRE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) + { + gpu->pmg.hbm.CKSRX = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRX"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) + { + gpu->pmg.hbm.CKE_PULSE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE_PULSE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE", value)) + { + gpu->pmg.hbm.CKE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE"); + } + else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) + { + gpu->pmg.hbm.SEQ_IDLE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SEQ_IDLE"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + { + gpu->ras.RCDW = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDW"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + { + gpu->ras.RCDWA = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDWA"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + { + gpu->ras.RCDR = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDR"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + { + gpu->ras.RCDRA = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDRA"); + } + else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + { + gpu->ras.RRD = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RC", value)) + { + gpu->ras.RC = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RC"); + } + else if (ParseNumericArg(argc, argv, i, "--CL", value)) + { + gpu->cas.hbm.CL = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CL"); + } + else if (ParseNumericArg(argc, argv, i, "--W2R", value)) + { + gpu->cas.hbm.W2R = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "W2R"); + } + else if (ParseNumericArg(argc, argv, i, "--R2R", value)) + { + gpu->cas.hbm.R2R = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2R"); + } + else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) + { + gpu->cas.hbm.CCDL = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CCDL"); + } + else if (ParseNumericArg(argc, argv, i, "--R2W", value)) + { + gpu->cas.hbm.R2W = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2W"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) + { + gpu->cas.hbm.NOPR = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPR"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) + { + gpu->cas.hbm.NOPW = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPW"); + } + else if (ParseNumericArg(argc, argv, i, "--MRD", value)) + { + gpu->misc.hbm.MRD = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "MRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RRDL", value)) + { + gpu->misc.hbm.RRDL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRDL"); + } + else if (ParseNumericArg(argc, argv, i, "--RFC", value)) + { + gpu->misc.hbm.RFC = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RFC"); + } + else if (ParseNumericArg(argc, argv, i, "--TRP", value)) + { + gpu->misc.hbm.TRP = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TRP"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) + { + gpu->misc.hbm.RP_RDA = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RP_RDA"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) + { + gpu->misc.hbm.RP_WRA = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RP_WRA"); + } + else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) + { + gpu->misc2.hbm.WDATATR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WDATATR"); + } + else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) + { + gpu->misc2.hbm.T32AW = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "T32AW"); + } + else if (ParseNumericArg(argc, argv, i, "--RPAR", value)) + { + gpu->misc2.hbm.RPAR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RPAR"); + } + else if (ParseNumericArg(argc, argv, i, "--WPAR", value)) + { + gpu->misc2.hbm.WPAR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WPAR"); + } + else if (ParseNumericArg(argc, argv, i, "--FAW", value)) + { + gpu->misc2.hbm.FAW = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "FAW"); + } + else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) + { + gpu->misc2.hbm.PA2WDATA = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "P2WDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) + { + gpu->misc2.hbm.PA2RDATA = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PA2RDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--DBR", value)) + { + gpu->smisc1.hbm.DBR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DBR"); + } + else if (ParseNumericArg(argc, argv, i, "--DBW", value)) + { + gpu->smisc1.hbm.DBW = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DBW"); + } + else if (ParseNumericArg(argc, argv, i, "--TCSR", value)) + { + gpu->smisc1.hbm.TCSR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TCSR"); + } + else if (ParseNumericArg(argc, argv, i, "--DQR", value)) + { + gpu->smisc1.hbm.DQR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQR"); + } + else if (ParseNumericArg(argc, argv, i, "--DQW", value)) + { + gpu->smisc1.hbm.DQW = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQW"); + } + else if (ParseNumericArg(argc, argv, i, "--ADD_PAR", value)) + { + gpu->smisc1.hbm.ADD_PAR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADD_PAR"); + } + else if (ParseNumericArg(argc, argv, i, "--TM", value)) + { + gpu->smisc1.hbm.TM = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TM"); + } + else if (ParseNumericArg(argc, argv, i, "--WR", value)) + { + gpu->smisc1.hbm.WR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WR"); + } + else if (ParseNumericArg(argc, argv, i, "--NDS", value)) + { + gpu->smisc1.hbm.NDS = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NDS"); + } + else if (ParseNumericArg(argc, argv, i, "--WL", value)) + { + gpu->smisc1.hbm.WL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WL"); + } + else if (ParseNumericArg(argc, argv, i, "--RL", value)) + { + gpu->smisc1.hbm.RL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RL"); + } + else if (ParseNumericArg(argc, argv, i, "--APRAS", value)) + { + gpu->smisc1.hbm.APRAS = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "APRAS"); + } + else if (ParseNumericArg(argc, argv, i, "--BG", value)) + { + gpu->smisc1.hbm.BG = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BG"); + } + else if (ParseNumericArg(argc, argv, i, "--BL", value)) + { + gpu->smisc1.hbm.BL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BL"); + } + else if (ParseNumericArg(argc, argv, i, "--REF", value)) + { + gpu->ref.REF = value; + gpu->modify[10] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REF"); + } + else if (ParseNumericArg(argc, argv, i, "--ENB", value)) + { + gpu->ham.ENB = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ENB"); + } + else if (ParseNumericArg(argc, argv, i, "--CNT", value)) + { + gpu->ham.CNT = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CNT"); + } + else if (ParseNumericArg(argc, argv, i, "--TRC", value)) + { + gpu->ham.TRC = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TRC"); + } + else if (ParseNumericArg(argc, argv, i, "--THRESH", value)) + { + gpu->throt.THRESH = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "THRESH"); + } + else if (ParseNumericArg(argc, argv, i, "--LEVEL", value)) + { + gpu->throt.LEVEL = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "LEVEL"); + } + else if (ParseNumericArg(argc, argv, i, "--PWRDOWN", value)) + { + gpu->throt.PWRDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PWRDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--SHUTDOWN", value)) + { + gpu->throt.SHUTDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SHUTDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--EN_SHUTDOWN", value)) + { + gpu->throt.EN_SHUTDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EN_SHUTDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--OVERSAMPLE", value)) + { + gpu->throt.OVERSAMPLE = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OVERSAMPLE"); + } + else if (ParseNumericArg(argc, argv, i, "--AVG_SAMPLE", value)) + { + gpu->throt.AVG_SAMPLE = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "AVG_SAMPLE"); + } + } + else // GDDR5 + { + if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) + { + gpu->ctl1.rx.DAT_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) + { + gpu->ctl1.rx.DQS_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) + { + gpu->ctl1.rx.DQS_XTR = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY0", value)) + { + gpu->ctl1.rx.DAT_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY0", value)) + { + gpu->ctl1.rx.ADR_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY0", value)) + { + gpu->ctl1.rx.CMD_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) + { + gpu->ctl1.rx.OEN_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) + { + gpu->ctl1.rx.OEN_EXT = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) + { + gpu->ctl1.rx.OEN_SEL = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL0"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_DLY0", value)) + { + gpu->ctl1.rx.ODT_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_EXT0", value)) + { + gpu->ctl1.rx.ODT_EXT = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_EXT0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) + { + gpu->ctl1.rx.ADR_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) + { + gpu->ctl1.rx.CMD_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) + { + gpu->ctl2.rx.DAT_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) + { + gpu->ctl2.rx.DQS_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) + { + gpu->ctl2.rx.DQS_XTR = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR1"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY1", value)) + { + gpu->ctl2.rx.DAT_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY1", value)) + { + gpu->ctl2.rx.ADR_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY1", value)) + { + gpu->ctl2.rx.CMD_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) + { + gpu->ctl2.rx.OEN_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) + { + gpu->ctl2.rx.OEN_EXT = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) + { + gpu->ctl2.rx.OEN_SEL = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL1"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_DLY1", value)) + { + gpu->ctl2.rx.ODT_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_EXT1", value)) + { + gpu->ctl2.rx.ODT_EXT = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_EXT1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) + { + gpu->ctl2.rx.ADR_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) + { + gpu->ctl2.rx.CMD_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) + { + gpu->pmg.rx.CKSRE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) + { + gpu->pmg.rx.CKSRX = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRX"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) + { + gpu->pmg.rx.CKE_PULSE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE_PULSE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE", value)) + { + gpu->pmg.rx.CKE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE"); + } + else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) + { + gpu->pmg.rx.SEQ_IDLE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SEQ_IDLE"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + { + gpu->ras.RCDW = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDW"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + { + gpu->ras.RCDWA = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDWA"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + { + gpu->ras.RCDR = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDR"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + { + gpu->ras.RCDRA = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDRA"); + } + else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + { + gpu->ras.RRD = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RC", value)) + { + gpu->ras.RC = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RC"); } else if (ParseNumericArg(argc, argv, i, "--CL", value)) { - gpu->cas.CL = value; - gpu->modify[2] = true; + gpu->cas.rx.CL = value; + gpu->modify[4] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "CL"); } else if (ParseNumericArg(argc, argv, i, "--W2R", value)) { - gpu->cas.W2R = value; - gpu->modify[2] = true; + gpu->cas.rx.W2R = value; + gpu->modify[4] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "W2R"); } else if (ParseNumericArg(argc, argv, i, "--R2R", value)) { - gpu->cas.R2R = value; - gpu->modify[2] = true; + gpu->cas.rx.R2R = value; + gpu->modify[4] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "R2R"); } - else if (ParseNumericArg(argc, argv, i, "--CCLD", value)) + else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) { - gpu->cas.CCLD = value; - gpu->modify[2] = true; + gpu->cas.rx.CCDL = value; + gpu->modify[4] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CCLD"); + strcat(gpu->log, "CCDL"); } else if (ParseNumericArg(argc, argv, i, "--R2W", value)) { - gpu->cas.R2W = value; - gpu->modify[2] = true; + gpu->cas.rx.R2W = value; + gpu->modify[4] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "R2W"); } else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) - { - gpu->cas.NOPR = value; - gpu->modify[2] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "NOPR"); - } + { + gpu->cas.rx.NOPR = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPR"); + } else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) - { - gpu->cas.NOPW = value; - gpu->modify[2] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "NOPW"); - } + { + gpu->cas.rx.NOPW = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPW"); + } else if (ParseNumericArg(argc, argv, i, "--RFC", value)) { (IsR9(gpu->dev) ? gpu->misc.r9.RFC : gpu->misc.rx.RFC) = value; - gpu->modify[3] = true; + gpu->modify[5] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RFC"); } else if (ParseNumericArg(argc, argv, i, "--TRP", value)) { (IsR9(gpu->dev) ? gpu->misc.r9.TRP : gpu->misc.rx.TRP) = value; - gpu->modify[3] = true; + gpu->modify[5] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "TRP"); } else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) { (IsR9(gpu->dev) ? gpu->misc.r9.RP_RDA : gpu->misc.rx.RP_RDA) = value; - gpu->modify[3] = true; + gpu->modify[5] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RP_RDA"); } else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) { (IsR9(gpu->dev) ? gpu->misc.r9.RP_WRA : gpu->misc.rx.RP_WRA) = value; - gpu->modify[3] = true; + gpu->modify[5] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RP_WRA"); } else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) { - gpu->misc2.WDATATR = value; - gpu->modify[4] = true; + gpu->misc2.rx.WDATATR = value; + gpu->modify[6] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "WDATATR"); } else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) - { - gpu->misc2.T32AW = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "T32AW"); - } - else if (ParseNumericArg(argc, argv, i, "--CRCWL", value)) - { - gpu->misc2.CRCWL = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CRCWL"); - } - else if (ParseNumericArg(argc, argv, i, "--CRCRL", value)) - { - gpu->misc2.CRCRL = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CRCRL"); - } + { + gpu->misc2.rx.T32AW = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "T32AW"); + } + else if (ParseNumericArg(argc, argv, i, "--WEDC", value)) + { + gpu->misc2.rx.WEDC = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WEDC"); + } + else if (ParseNumericArg(argc, argv, i, "--REDC", value)) + { + gpu->misc2.rx.REDC = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REDC"); + } else if (ParseNumericArg(argc, argv, i, "--FAW", value)) - { - gpu->misc2.FAW = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "FAW"); - } + { + gpu->misc2.rx.FAW = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "FAW"); + } else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) - { - gpu->misc2.PA2WDATA = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "P2WDATA"); - } + { + gpu->misc2.rx.PA2WDATA = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "P2WDATA"); + } else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) - { - gpu->misc2.PA2RDATA = value; - gpu->modify[4] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "PA2RDATA"); - } + { + gpu->misc2.rx.PA2RDATA = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PA2RDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--WL", value)) + { + gpu->smisc1.rx.WL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WL"); + } + else if (ParseNumericArg(argc, argv, i, "--MR0_CL", value)) + { + gpu->smisc1.rx.CL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "MR0_CL"); + } + else if (ParseNumericArg(argc, argv, i, "--TM", value)) + { + gpu->smisc1.rx.TM = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TM"); + } + else if (ParseNumericArg(argc, argv, i, "--WR", value)) + { + gpu->smisc1.rx.WR = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WR"); + } + else if (ParseNumericArg(argc, argv, i, "--DS", value)) + { + gpu->smisc1.rx.DS = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DS"); + } + else if (ParseNumericArg(argc, argv, i, "--DT", value)) + { + gpu->smisc1.rx.DT = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DT"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR", value)) + { + gpu->smisc1.rx.ADR = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR"); + } + else if (ParseNumericArg(argc, argv, i, "--CAL", value)) + { + gpu->smisc1.rx.CAL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CAL"); + } + else if (ParseNumericArg(argc, argv, i, "--PLL", value)) + { + gpu->smisc1.rx.PLL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PLL"); + } + else if (ParseNumericArg(argc, argv, i, "--RDBI", value)) + { + gpu->smisc1.rx.RDBI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDBI"); + } + else if (ParseNumericArg(argc, argv, i, "--WDBI", value)) + { + gpu->smisc1.rx.WDBI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WDBI"); + } + else if (ParseNumericArg(argc, argv, i, "--ABI", value)) + { + gpu->smisc1.rx.ABI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ABI"); + } + else if (ParseNumericArg(argc, argv, i, "--RESET", value)) + { + gpu->smisc1.rx.RESET = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RESET"); + } + else if (ParseNumericArg(argc, argv, i, "--SR", value)) + { + gpu->smisc2.SR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SR"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK01", value)) + { + gpu->smisc2.WCK01 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK01"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK23", value)) + { + gpu->smisc2.WCK23 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK23"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK2CK", value)) + { + gpu->smisc2.WCK2CK = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK2CK"); + } + else if (ParseNumericArg(argc, argv, i, "--RDQS", value)) + { + gpu->smisc2.RDQS = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDQS"); + } + else if (ParseNumericArg(argc, argv, i, "--INFO", value)) + { + gpu->smisc2.INFO = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "INFO"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK2", value)) + { + gpu->smisc2.WCK2 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK2"); + } + + else if (ParseNumericArg(argc, argv, i, "--BG", value)) + { + gpu->smisc2.BG = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BG"); + } + else if (ParseNumericArg(argc, argv, i, "--EDCHP", value)) + { + gpu->smisc3.EDCHP = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EDCHP"); + } + else if (ParseNumericArg(argc, argv, i, "--CRCWL", value)) + { + gpu->smisc3.CRCWL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CRCWL"); + } + else if (ParseNumericArg(argc, argv, i, "--CRCRL", value)) + { + gpu->smisc3.CRCRL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CRCRL"); + } + else if (ParseNumericArg(argc, argv, i, "--RDCRC", value)) + { + gpu->smisc3.RDCRC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDCRC"); + } + else if (ParseNumericArg(argc, argv, i, "--WRCRC", value)) + { + gpu->smisc3.WRCRC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRCRC"); + } + else if (ParseNumericArg(argc, argv, i, "--EDC", value)) + { + gpu->smisc3.EDC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EDC"); + } else if (ParseNumericArg(argc, argv, i, "--RAS", value)) - { - gpu->misc3.RAS = value; - gpu->modify[5] = true; - if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "PA2RDATA"); - } + { + gpu->smisc3.RAS = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RAS"); + } + else if (ParseNumericArg(argc, argv, i, "--CLEHF", value)) + { + gpu->smisc8.CLEHF = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CLEHF"); + } + else if (ParseNumericArg(argc, argv, i, "--WREHF", value)) + { + gpu->smisc8.WREHF = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WREHF"); + } else if (ParseNumericArg(argc, argv, i, "--ACTRD", value)) { gpu->dram1.ACTRD = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "ACTRD"); } else if (ParseNumericArg(argc, argv, i, "--ACTWR", value)) { gpu->dram1.ACTWR = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "ACTWR"); } else if (ParseNumericArg(argc, argv, i, "--RASMACTRD", value)) { gpu->dram1.RASMACTRD = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RASMACTRD"); } else if (ParseNumericArg(argc, argv, i, "--RASMACTWR", value)) { gpu->dram1.RASMACTWR = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RASMACTWR"); } else if (ParseNumericArg(argc, argv, i, "--RAS2RAS", value)) { gpu->dram2.RAS2RAS = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RAS2RAS"); } else if (ParseNumericArg(argc, argv, i, "--RP", value)) { gpu->dram2.RP = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RP"); } else if (ParseNumericArg(argc, argv, i, "--WRPLUSRP", value)) { gpu->dram2.WRPLUSRP = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "WRPLUSRP"); } else if (ParseNumericArg(argc, argv, i, "--BUS_TURN", value)) { gpu->dram2.BUS_TURN = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "BUS_TURN"); } + else if (ParseNumericArg(argc, argv, i, "--REF", value)) + { + gpu->ref.REF = value; + gpu->modify[15] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REF"); + } + else if (ParseNumericArg(argc, argv, i, "--TWT2RT", value)) + { + gpu->train.TWT2RT = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TWT2RT"); + } + else if (ParseNumericArg(argc, argv, i, "--TARF2T", value)) + { + gpu->train.TARF2T = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TARF2T"); + } + else if (ParseNumericArg(argc, argv, i, "--TT2ROW", value)) + { + gpu->train.TT2ROW = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TT2ROW"); + } + else if (ParseNumericArg(argc, argv, i, "--TLD2LD", value)) + { + gpu->train.TLD2LD = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TLD2LD"); + } } } } @@ -1465,7 +3312,7 @@ int main(int argc, const char *argv[]) // Actually applies the changes, if any. for (int index = 0; index < gpuCount; index++) { - GPU *gpu = &gpus[index]; + GPU* gpu = &gpus[index]; for (int i = 0; i < _countof(gpu->modify); i++) { if (gpu->modify[i]) @@ -1473,66 +3320,156 @@ int main(int argc, const char *argv[]) switch (DetermineMemoryType(gpu->dev)) { case HBM2: + { + u32 value = ((u32*)& gpu->hbm2)[i]; + if (i == 0) // special logic for frequency { - u32 value = ((u32*)&gpu->hbm2)[i]; - if (i == 0) // special logic for frequency - { - value = (gpu->hbm2.frequency == 0x118) ? 0x118 : 0x11C; - } + value = (gpu->hbm2.frequency == 0x118) ? 0x118 : 0x11C; + } - lseek(gpu->mmio, AMD_TIMING_REGS_BASE_1 + (i * sizeof(u32)), SEEK_SET); - write(gpu->mmio, &value, sizeof(u32)); + lseek(gpu->mmio, AMD_TIMING_REGS_BASE_1 + (i * sizeof(u32)), SEEK_SET); + write(gpu->mmio, &value, sizeof(u32)); - lseek(gpu->mmio, AMD_TIMING_REGS_BASE_2 + (i * sizeof(u32)), SEEK_SET); - write(gpu->mmio, &value, sizeof(u32)); + lseek(gpu->mmio, AMD_TIMING_REGS_BASE_2 + (i * sizeof(u32)), SEEK_SET); + write(gpu->mmio, &value, sizeof(u32)); - lseek(gpu->mmio, AMD_TIMING_REGS_BASE_3 + (i * sizeof(u32)), SEEK_SET); - write(gpu->mmio, &value, sizeof(u32)); + lseek(gpu->mmio, AMD_TIMING_REGS_BASE_3 + (i * sizeof(u32)), SEEK_SET); + write(gpu->mmio, &value, sizeof(u32)); - lseek(gpu->mmio, AMD_TIMING_REGS_BASE_4 + (i * sizeof(u32)), SEEK_SET); - write(gpu->mmio, &value, sizeof(u32)); - break; - } + lseek(gpu->mmio, AMD_TIMING_REGS_BASE_4 + (i * sizeof(u32)), SEEK_SET); + write(gpu->mmio, &value, sizeof(u32)); + break; + } case GDDR5: switch (i) { case 0: - lseek(gpu->mmio, MC_SEQ_PMG_TIMING, SEEK_SET); - write(gpu->mmio, &gpu->pmg, sizeof(gpu->pmg)); - break; + lseek(gpu->mmio, MC_SEQ_WR_CTL_D0, SEEK_SET); + write(gpu->mmio, &gpu->ctl1, sizeof(gpu->ctl1.rx)); + break; case 1: - lseek(gpu->mmio, MC_SEQ_RAS_TIMING, SEEK_SET); - write(gpu->mmio, &gpu->ras, sizeof(gpu->ras)); + lseek(gpu->mmio, MC_SEQ_WR_CTL_D1, SEEK_SET); + write(gpu->mmio, &gpu->ctl2, sizeof(gpu->ctl2.rx)); break; case 2: - lseek(gpu->mmio, MC_SEQ_CAS_TIMING, SEEK_SET); - write(gpu->mmio, &gpu->cas, sizeof(gpu->cas)); + lseek(gpu->mmio, MC_SEQ_PMG_TIMING, SEEK_SET); + write(gpu->mmio, &gpu->pmg, sizeof(gpu->pmg.rx)); break; case 3: - lseek(gpu->mmio, MC_SEQ_MISC_TIMING, SEEK_SET); - write(gpu->mmio, &gpu->misc, sizeof(gpu->misc)); + lseek(gpu->mmio, MC_SEQ_RAS_TIMING, SEEK_SET); + write(gpu->mmio, &gpu->ras, sizeof(gpu->ras)); break; case 4: - lseek(gpu->mmio, MC_SEQ_MISC_TIMING2, SEEK_SET); - write(gpu->mmio, &gpu->misc2, sizeof(gpu->misc2)); + lseek(gpu->mmio, MC_SEQ_CAS_TIMING, SEEK_SET); + write(gpu->mmio, &gpu->cas, sizeof(gpu->cas.rx)); break; case 5: - lseek(gpu->mmio, MC_SEQ_MISC3, SEEK_SET); - write(gpu->mmio, &gpu->misc3, sizeof(gpu->misc3)); - break; + lseek(gpu->mmio, MC_SEQ_MISC_TIMING, SEEK_SET); + write(gpu->mmio, &gpu->misc, sizeof(gpu->misc.rx)); + break; case 6: + lseek(gpu->mmio, MC_SEQ_MISC_TIMING2, SEEK_SET); + write(gpu->mmio, &gpu->misc2, sizeof(gpu->misc2.rx)); + break; + case 7: + lseek(gpu->mmio, MC_SEC_MISC1, SEEK_SET); + write(gpu->mmio, &gpu->smisc1, sizeof(gpu->smisc1.rx)); + break; + case 8: + lseek(gpu->mmio, MC_SEC_MISC2, SEEK_SET); + write(gpu->mmio, &gpu->smisc2, sizeof(gpu->smisc2)); + break; + case 9: + lseek(gpu->mmio, MC_SEC_MISC3, SEEK_SET); + write(gpu->mmio, &gpu->smisc3, sizeof(gpu->smisc3)); + break; + case 10: + lseek(gpu->mmio, MC_SEC_MISC4, SEEK_SET); + write(gpu->mmio, &gpu->smisc4, sizeof(gpu->smisc4)); + break; + case 11: + lseek(gpu->mmio, MC_SEC_MISC7, SEEK_SET); + write(gpu->mmio, &gpu->smisc7, sizeof(gpu->smisc7)); + break; + case 12: + lseek(gpu->mmio, MC_SEC_MISC8, SEEK_SET); + write(gpu->mmio, &gpu->smisc8, sizeof(gpu->smisc8)); + break; + case 13: lseek(gpu->mmio, MC_ARB_DRAM_TIMING, SEEK_SET); write(gpu->mmio, &gpu->dram1, sizeof(gpu->dram1)); break; - case 7: + case 14: lseek(gpu->mmio, MC_ARB_DRAM_TIMING2, SEEK_SET); write(gpu->mmio, &gpu->dram2, sizeof(gpu->dram2)); break; + case 15: + lseek(gpu->mmio, MC_ARB_RFSH_RATE, SEEK_SET); + write(gpu->mmio, &gpu->ref, sizeof(gpu->ref)); + break; + case 16: + lseek(gpu->mmio, MC_SEQ_TRAINING, SEEK_SET); + write(gpu->mmio, &gpu->train, sizeof(gpu->train)); + break; } break; case HBM: - perror("HBM memory type is not supported yet\n"); - return 1; + switch (i) + { + case 0: + lseek(gpu->mmio, MC_SEQ_WR_CTL_D0_HBM, SEEK_SET); + write(gpu->mmio, &gpu->ctl1, sizeof(gpu->ctl1.hbm)); + break; + case 1: + lseek(gpu->mmio, MC_SEQ_WR_CTL_D1_HBM, SEEK_SET); + write(gpu->mmio, &gpu->ctl2, sizeof(gpu->ctl2.hbm)); + break; + case 2: + lseek(gpu->mmio, MC_SEQ_WR_CTL_D2_HBM, SEEK_SET); + write(gpu->mmio, &gpu->ctl3, sizeof(gpu->ctl3)); + break; + case 3: + lseek(gpu->mmio, MC_SEQ_WR_CTL_D3_HBM, SEEK_SET); + write(gpu->mmio, &gpu->ctl4, sizeof(gpu->ctl4)); + break; + case 4: + lseek(gpu->mmio, MC_SEQ_PMG_TIMING_HBM, SEEK_SET); + write(gpu->mmio, &gpu->pmg, sizeof(gpu->pmg.hbm)); + break; + case 5: + lseek(gpu->mmio, MC_SEQ_RAS_TIMING_HBM, SEEK_SET); + write(gpu->mmio, &gpu->ras, sizeof(gpu->ras)); + break; + case 6: + lseek(gpu->mmio, MC_SEQ_CAS_TIMING_HBM, SEEK_SET); + write(gpu->mmio, &gpu->cas, sizeof(gpu->cas.hbm)); + break; + case 7: + lseek(gpu->mmio, MC_SEQ_MISC_TIMING_HBM, SEEK_SET); + write(gpu->mmio, &gpu->misc, sizeof(gpu->misc.hbm)); + break; + case 8: + lseek(gpu->mmio, MC_SEQ_MISC_TIMING2_HBM, SEEK_SET); + write(gpu->mmio, &gpu->misc2, sizeof(gpu->misc2.hbm)); + break; + case 9: + lseek(gpu->mmio, MC_SEC_MISC1_HBM, SEEK_SET); + write(gpu->mmio, &gpu->smisc1, sizeof(gpu->smisc1.hbm)); + break; + case 10: + lseek(gpu->mmio, MC_ARB_RFSH_RATE, SEEK_SET); + write(gpu->mmio, &gpu->ref, sizeof(gpu->ref)); + break; + case 11: + lseek(gpu->mmio, MC_SEQ_ROW_HAMMER, SEEK_SET); + write(gpu->mmio, &gpu->ham, sizeof(gpu->ham)); + break; + case 12: + lseek(gpu->mmio, MC_THERMAL_THROTTLE, SEEK_SET); + write(gpu->mmio, &gpu->throt, sizeof(gpu->throt)); + break; + } + break; } } } @@ -1540,7 +3477,7 @@ int main(int argc, const char *argv[]) for (int index = 0; index < gpuCount; index++) { - GPU *gpu = &gpus[index]; + GPU* gpu = &gpus[index]; if (gpu->log[0]) { printf("Successfully applied new %s settings to GPU %d.\n", gpu->log, index); diff --git a/win/WinAMDTweak.cpp b/win/WinAMDTweak.cpp index 5db47f7..dfd1f61 100644 --- a/win/WinAMDTweak.cpp +++ b/win/WinAMDTweak.cpp @@ -11,11 +11,30 @@ 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 @@ -31,73 +50,73 @@ typedef struct { // TIMING3 u32 RRDS : 8; u32 RRDL : 8; - u32 : 8; + u32 /*Reserved*/ : 8; u32 RTP : 8; // TIMING4 u32 FAW : 8; - u32 : 24; + u32 /*Reserved*/ : 24; // TIMING5 u32 CWL : 8; u32 WTRS : 8; u32 WTRL : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // TIMING6 u32 WR : 8; - u32 : 24; + u32 /*Reserved*/ : 24; // TIMING7 - u32 : 8; + u32 /*Reserved*/ : 8; u32 RREFD : 8; - u32 : 8; - u32 : 8; + u32 /*Reserved*/ : 8; + u32 /*Reserved*/ : 8; // TIMING8 u32 RDRDDD : 8; u32 RDRDSD : 8; u32 RDRDSC : 8; u32 RDRDSCL : 6; - u32 : 2; + u32 /*Reserved*/ : 2; // TIMING9 u32 WRWRDD : 8; u32 WRWRSD : 8; u32 WRWRSC : 8; u32 WRWRSCL : 6; - u32 : 2; + u32 /*Reserved*/ : 2; // TIMING10 u32 WRRD : 8; u32 RDWR : 8; - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING12 - u32 REF : 16; // Determines at what rate refreshes will be executed. - u32 : 16; + 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 : 16; + u32 /*Reserved*/ : 16; // TIMING14 u32 XS : 16; // self refresh exit period - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING16 u32 XSMRS : 16; - u32 : 16; + u32 /*Reserved*/ : 16; // TIMING17 u32 PD : 4; u32 CKSRE : 6; u32 CKSRX : 6; - u32 : 16; + u32 /*Reserved*/ : 16; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // PADDING - u32 : 32; + u32 /*Reserved*/ : 32; // TIMING20 u32 RFCPB : 16; u32 STAG : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // TIMING21 u32 XP : 8; - u32 : 8; + u32 /*Reserved*/ : 8; u32 CPDED : 8; u32 CKE : 8; // TIMING22 @@ -105,104 +124,435 @@ typedef struct { u32 WRLAT : 8; u32 RDLAT : 8; u32 WRDATA : 4; - u32 : 4; + u32 /*Reserved*/ : 4; // TIMING23 - u32 : 16; + u32 /*Reserved*/ : 16; u32 CKESTAG : 8; - u32 : 8; + u32 /*Reserved*/ : 8; // RFC u32 RFC : 16; - u32 : 16; + u32 /*Reserved*/ : 16; } HBM2_TIMINGS; typedef union { u32 value; struct { - u32 CKSRE : 4; - u32 CKSRX : 4; - u32 CKE_PULSE : 4; - u32 CKE : 6; - u32 SEQ_IDLE : 3; - u32 : 11; + 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 +#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 : 1; + 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 - u32 CCLD : 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 : 3; - u32 CL : 5; // CAS to data return latency - u32 : 3; - }; + 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 : 7; // From write with auto-precharge to active - u32 RP_RDA : 7; // From read with auto-precharge to active - u32 TRP : 6; // Precharge command period - u32 RFC : 9; // Auto-refresh command period - u32 : 3; + 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 : 3; + 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 : 1; u32 PA2WDATA : 3; - u32 : 1; - u32 FAW : 5; // The time window in wich four activates are allowed in the same rank - u32 CRCRL : 3; - u32 CRCWL : 5; + 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 : 3; 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 { - u32 : 22; + // 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 : 4; + u32 BA_0 : 1; + u32 BA_1 : 1; + u32 BA_2 : 1; + u32 BA_3 : 1; }; } SEQ_MISC3; -#define MC_SEQ_MISC3 0x2a2c +#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; @@ -226,6 +576,38 @@ typedef union { } 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) { @@ -234,20 +616,20 @@ static const char* LookupDeviceName(u16 device_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]" }, + { 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++) { @@ -271,7 +653,7 @@ static bool IsRelevantDeviceID(u16 device_id) (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 == 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] @@ -303,20 +685,12 @@ static MemoryType DetermineMemoryType(u16 device_id) { 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 Vega20", CHIP_VEGA20 { 0x1002, 0x66af, HBM2 }, // "Radeon VII", CHIP_VEGA20 /* Vega */ { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 64", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 64", CHIP_VEGA10 - { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega 56", 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 - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI - { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury", CHIP_FIJI */ }; for (int i = 0; i < _countof(KnownGPUs); i++) { @@ -331,17 +705,32 @@ static MemoryType DetermineMemoryType(u16 device_id) typedef struct { char log[1000]; bool modify[25]; + MANUFACTURER man; // HBM2 HBM2_TIMINGS hbm2; - // GDDR5 + // 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_MISC3 misc3; + 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) @@ -394,10 +783,14 @@ static void PrintCurrentValues(VGAChip * chip, GPU * gpu) if (DetermineMemoryType(chip->device_id) == HBM2) { HBM2_TIMINGS current = gpu->hbm2; - printf("Memory state: 0x%X (%s)\n", current.frequency, - (current.frequency == 0x118) ? "800MHz" : + 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); @@ -466,64 +859,301 @@ static void PrintCurrentValues(VGAChip * chip, GPU * gpu) 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 { - printf("\nPMG:\t"); - printf(" CKSRE: %d\t", gpu->pmg.CKSRE); - printf(" CKSRX: %d\t", gpu->pmg.CKSRX); - printf(" CKE_PULSE: %d\t", gpu->pmg.CKE_PULSE); - printf(" CKE: %d\t", gpu->pmg.CKE); - printf(" SEQ_IDLE: %d\n", gpu->pmg.SEQ_IDLE); - printf("CAS:\t"); - printf(" CL: %d\t", gpu->cas.CL); - printf(" W2R: %d\t", gpu->cas.W2R); - printf(" R2R: %d\t", gpu->cas.R2R); - printf(" CCLD: %d\t", gpu->cas.CCLD); - printf(" R2W: %d\t", gpu->cas.R2W); - printf(" NOPR: %d\t", gpu->cas.NOPR); - printf(" NOPW: %d\n", gpu->cas.NOPW); - printf("RAS:\t"); - printf(" RC: %d\t", gpu->ras.RC); + 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); - printf("MISC:\t"); + printf("CAS related timings:\n"); + printf(" \t CL: %d\t", gpu->cas.rx.CL); + printf(" W2R: %d\t", gpu->cas.rx.W2R); + printf(" R2R: %d\t", gpu->cas.rx.R2R); + printf(" CCDL: %d\t", gpu->cas.rx.CCDL); + printf(" R2W: %d\t", gpu->cas.rx.R2W); + printf(" NOPR: %d\t", gpu->cas.rx.NOPR); + printf(" NOPW: %d\n", gpu->cas.rx.NOPW); + printf("Misc. DRAM timings:\n"); if (IsR9(chip->device_id)) { - printf(" RFC: %d\t", gpu->misc.r9.RFC); + printf(" \t RFC: %d\t", gpu->misc.r9.RFC); printf(" TRP: %d\t", gpu->misc.r9.TRP); printf(" RP_RDA: %d\t", gpu->misc.r9.RP_RDA); printf(" RP_WRA: %d\n", gpu->misc.r9.RP_WRA); } else { - printf(" RFC: %d\t", gpu->misc.rx.RFC); + printf(" \t RFC: %d\t", gpu->misc.rx.RFC); printf(" TRP: %d\t", gpu->misc.rx.TRP); printf(" RP_RDA: %d\t", gpu->misc.rx.RP_RDA); printf(" RP_WRA: %d\n", gpu->misc.rx.RP_WRA); } - printf("MISC2:\t"); - printf(" WDATATR: %d\t", gpu->misc2.WDATATR); - printf(" T32AW: %d\t", gpu->misc2.T32AW); - printf(" CRCWL: %d\t", gpu->misc2.CRCWL); - printf(" CRCRL: %d\t", gpu->misc2.CRCRL); - printf(" FAW: %d\t", gpu->misc2.FAW); - printf(" PA2WDATA: %d\t", gpu->misc2.PA2WDATA); - printf(" PA2RDATA: %d\n", gpu->misc2.PA2RDATA); - printf("M3(MR4):\t"); - printf(" RAS: %d\n", gpu->misc3.RAS); - printf("DRAM1:\t"); - printf(" RASMACTWR: %d\t", gpu->dram1.RASMACTWR); + printf("Misc2. DRAM timings:\n"); + printf(" \t WDATATR: %d\t", gpu->misc2.rx.WDATATR); + printf(" T32AW: %d\t", gpu->misc2.rx.T32AW); + printf(" WEDC: %d\t", gpu->misc2.rx.WEDC); + printf(" REDC: %d\t", gpu->misc2.rx.REDC); + printf(" FAW: %d\t", gpu->misc2.rx.FAW); + printf(" PA2WDATA: %d\t", gpu->misc2.rx.PA2WDATA); + printf(" PA2RDATA: %d\n", gpu->misc2.rx.PA2RDATA); + printf("Mode Register 0:\n"); + printf(" \t WL: %d \t", gpu->smisc1.rx.WL); + printf(" CL: %d \t", gpu->smisc1.rx.CL); + printf(" TM: %d \t", gpu->smisc1.rx.TM); + printf(" WR: %d\n", gpu->smisc1.rx.WR); + printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA0); + printf(" BA1: %d\t ", gpu->smisc1.rx.BA1); + printf(" BA2: %d\t ", gpu->smisc1.rx.BA2); + printf(" BA3: %d\n", gpu->smisc1.rx.BA3); + printf("Mode Register 1:\n"); + printf(" \t DS: %d \t", gpu->smisc1.rx.DS); + printf(" DT: %d \t", gpu->smisc1.rx.DT); + printf(" ADR: %d\t ", gpu->smisc1.rx.ADR); + printf(" CAL: %d\t ", gpu->smisc1.rx.CAL); + printf(" PLL: %d\n ", gpu->smisc1.rx.PLL); + printf(" \t RDBI: %d\t", gpu->smisc1.rx.RDBI); + printf(" WDBI: %d\t", gpu->smisc1.rx.WDBI); + printf(" ABI: %d\t", gpu->smisc1.rx.ABI); + printf(" RESET: %d\n", gpu->smisc1.rx.RESET); + printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA_0); + printf(" BA1: %d\t ", gpu->smisc1.rx.BA_1); + printf(" BA2: %d\t ", gpu->smisc1.rx.BA_2); + printf(" BA3: %d\n", gpu->smisc1.rx.BA_3); + printf("Mode Register 2:\n"); + printf(" \t OCD_DWN: %d\t", gpu->smisc2.OCD_DWN); + printf(" OCD_UP: %d\t", gpu->smisc2.OCD_UP); + printf(" WCK: %d\t ", gpu->smisc2.WCK); + printf(" ADR: %d\n ", gpu->smisc2.ADR); + printf(" \t BA0: %d\t ", gpu->smisc2.BA0); + printf(" BA1: %d\t ", gpu->smisc2.BA1); + printf(" BA2: %d\t ", gpu->smisc2.BA2); + printf(" BA3: %d\n", gpu->smisc2.BA3); + printf("Mode Register 3:\n"); + printf(" \t SR: %d \t", gpu->smisc2.SR); + printf(" WCK01: %d\t", gpu->smisc2.WCK01); + printf(" WCK23: %d\t", gpu->smisc2.WCK23); + printf(" WCK2CK: %d\t", gpu->smisc2.WCK2CK); + printf(" RDQS: %d\t", gpu->smisc2.RDQS); + printf(" INFO: %d\t", gpu->smisc2.INFO); + printf(" WCK2: %d\n", gpu->smisc2.WCK2); + printf(" \t BA0: %d\t ", gpu->smisc2.BA_0); + printf(" BA1: %d\t ", gpu->smisc2.BA_1); + printf(" BA2: %d\t ", gpu->smisc2.BA_2); + printf(" BA3: %d\n", gpu->smisc2.BA_3); + printf("Mode Register 4:\n"); + printf(" \t EDCHP: %d\t", gpu->smisc3.EDCHP); + printf(" CRCWL: %d\t", gpu->smisc3.CRCWL); + printf(" CRCRL: %d\t", gpu->smisc3.CRCRL); + printf(" RDCRC: %d\t", gpu->smisc3.RDCRC); + printf(" WRCRC: %d\t", gpu->smisc3.WRCRC); + printf(" EDC: %d\n ", gpu->smisc3.EDC); + printf(" \t BA0: %d\t ", gpu->smisc3.BA0); + printf(" BA1: %d\t ", gpu->smisc3.BA1); + printf(" BA2: %d\t ", gpu->smisc3.BA2); + printf(" BA3: %d\n", gpu->smisc3.BA3); + printf("Mode Register 5:\n"); + printf(" \t LP1: %d\t ", gpu->smisc3.LP1); + printf(" LP1: %d\t ", gpu->smisc3.LP1); + printf(" LP1: %d\t ", gpu->smisc3.LP1); + printf(" PLL: %d\t ", gpu->smisc3.PLL); + printf(" RAS: %d\n ", gpu->smisc3.RAS); + printf(" \t BA0: %d\t ", gpu->smisc3.BA_0); + printf(" BA1: %d\t ", gpu->smisc3.BA_1); + printf(" BA2: %d\t ", gpu->smisc3.BA_2); + printf(" BA3: %d\n", gpu->smisc3.BA_3); + printf("Mode Register 6:\n"); + printf(" \t WCK: %d\t ", gpu->smisc4.WCK); + printf(" VREFD_M: %d\t", gpu->smisc4.VREFD_M); + printf(" A_VREFD: %d\t", gpu->smisc4.A_VREFD); + printf(" VREFD: %d\t", gpu->smisc4.VREFD); + printf(" VREFD_O: %d\t", gpu->smisc4.VREFD_O); + printf(" VREFD_0_2: %d\n", gpu->smisc4.VREFD_0_2); + printf(" \t BA0: %d\t ", gpu->smisc4.BA0); + printf(" BA1: %d\t ", gpu->smisc4.BA1); + printf(" BA2: %d\t ", gpu->smisc4.BA2); + printf(" BA3: %d\n", gpu->smisc4.BA3); + printf("Mode Register 7:\n"); + printf(" \t PLL_STD: %d\t", gpu->smisc4.PLL_STD); + printf(" PLL_FL: %d\t", gpu->smisc4.PLL_FL); + printf(" PLL_DEL: %d\t", gpu->smisc4.PLL_DEL); + printf(" LF_MOD: %d\t", gpu->smisc4.LF_MOD); + printf(" AUTO: %d\t", gpu->smisc4.AUTO); + printf(" DQ: %d\n ", gpu->smisc4.DQ); + printf(" \t TEMP: %d\t", gpu->smisc4.TEMP); + printf(" HALF: %d\t", gpu->smisc4.HALF); + printf(" VDD_R: %d\t", gpu->smisc4.VDD_R); + printf(" RFU: %d\n ", gpu->smisc4.RFU); + printf(" \t BA0: %d\t ", gpu->smisc4.BA_0); + printf(" BA1: %d\t ", gpu->smisc4.BA_1); + printf(" BA2: %d\t ", gpu->smisc4.BA_2); + printf(" BA3: %d\n", gpu->smisc4.BA_3); + printf("Mode Register 15:\n"); + printf(" \t MRE0: %d\t", gpu->smisc7.MRE0); + printf(" MRE1: %d\t", gpu->smisc7.MRE1); + printf(" ADT: %d\t ", gpu->smisc7.ADT); + printf(" RFU: %d\n ", gpu->smisc7.RFU); + printf(" \t BA0: %d\t ", gpu->smisc7.BA0); + printf(" BA1: %d\t ", gpu->smisc7.BA1); + printf(" BA2: %d\t ", gpu->smisc7.BA2); + printf(" BA3: %d\n", gpu->smisc7.BA3); + printf("Mode Register 8:\n"); + printf(" \t CLEHF: %d\t", gpu->smisc8.CLEHF); + printf(" WREHF: %d\t", gpu->smisc8.WREHF); + printf(" RFU: %d\n ", gpu->smisc8.RFU); + printf(" \t BA0: %d\t ", gpu->smisc8.BA0); + printf(" BA1: %d\t ", gpu->smisc8.BA1); + printf(" BA2: %d\t ", gpu->smisc8.BA2); + printf(" BA3: %d\n", gpu->smisc8.BA3); + printf("DRAM Specific:\n"); + printf(" \t RASMACTWR: %d\t", gpu->dram1.RASMACTWR); printf(" RASMACTRD: %d\t", gpu->dram1.RASMACTRD); printf(" ACTWR: %d\t", gpu->dram1.ACTWR); printf(" ACTRD: %d\n", gpu->dram1.ACTRD); - printf("DRAM2:\t"); - printf(" RAS2RAS: %d\t", gpu->dram2.RAS2RAS); + printf("DRAM2 Specific:\n"); + printf(" \t RAS2RAS: %d\t", gpu->dram2.RAS2RAS); printf(" RP: %d\t", gpu->dram2.RP); printf(" WRPLUSRP: %d\t", gpu->dram2.WRPLUSRP); printf(" BUS_TURN: %d\n", gpu->dram2.BUS_TURN); + printf("Refresh Interval:\n"); + printf(" \t REF: %d\n", gpu->ref.REF); + printf("Training timings:\n"); + printf(" \t TWT2RT: %d\t", gpu->train.TWT2RT); + printf(" TARF2T: %d\t", gpu->train.TARF2T); + printf(" TT2ROW: %d\t", gpu->train.TT2ROW); + printf(" TLD2LD: %d\n", gpu->train.TLD2LD); } } @@ -553,15 +1183,16 @@ void __cdecl UnloadDriver(void) int main(int argc, const char* argv[]) { - if ((argc < 2) || (0 == strcasecmp("--help", argv[1]))) + if ((argc < 2) || (0 == strcasecmp("--help", argv[1])) || (0 == strcasecmp("--h", argv[1]))) { printf(" AMD Memory Tweak\n" " Read and modify memory timings on the fly\n" " By Eliovp & A.Solodovnikov\n\n" " Global command line options:\n" - " --help \tShow this output\n" + " --help|--h\tShow this output\n" + " --version|--v\tShow version info\n" " --gpu|--i [comma-separated gpu indices]\tSelected device(s)\n" - " --current \tList current timing values\n\n" + " --current|--c\tList current timing values\n\n" " Command line options: (HBM2)\n" " --CL|--cl [value]\n" " --RAS|--ras [value]\n" @@ -607,7 +1238,85 @@ int main(int argc, const char* argv[]) " --WRDATA|--wrdata [value]\n" " --CKESTAG|--ckestag [value]\n" " --RFC|--rfc [value]\n\n" + " Command line options: (HBM)\n" + " --DAT_DLY0|1|2|3 | --dat_dly0|1|2|3 [value]\n" + " --DQS_DLY0|1|2|3 | --dqs_dly0|1|2|3 [value]\n" + " --DQS_XTR0|1|2|3 | --dqs_xtr0|1|2|3 [value]\n" + " --OEN_DLY0|1|2|3 | --oen_dly0|1|2|3 [value]\n" + " --OEN_EXT0|1|2|3 | --oen_ext0|1|2|3 [value]\n" + " --OEN_SEL0|1|2|3 | --oen_sel0|1|2|3 [value]\n" + " --CMD_DLY0|1|2|3 | --cmd_dly0|1|2|3 [value]\n" + " --ADR_DLY0|1|2|3 | --adr_dly0|1|2|3 [value]\n" + " --CKSRE|--cksre [value]\n" + " --CKSRX|--cksrx [value]\n" + " --CKE_PULSE|--cke_pulse [value]\n" + " --CKE|--cke [value]\n" + " --SEQ_IDLE|--seq_idle [value]\n" + " --CL|--cl [value]\n" + " --W2R|--w2r [value]\n" + " --R2R|--r2r [value]\n" + " --CCDL|--ccdl [value]\n" + " --R2W|--r2w [value]\n" + " --NOPR|--nopr [value]\n" + " --NOPW|--nopw [value]\n" + " --RCDW|--rcdw [value]\n" + " --RCDWA|--rcdwa [value]\n" + " --RCDR|--rcdr [value]\n" + " --RCDRA|--rcdra [value]\n" + " --RRD|--rrd [value]\n" + " --RC|--rc [value]\n" + " --MRD|--mrd [value]\n" + " --RRDL|--rrdl [value]\n" + " --RFC|--rfc [value]\n" + " --TRP|--trp [value]\n" + " --RP_WRA|--rp_wra [value]\n" + " --RP_RDA|--rp_rda [value]\n" + " --WDATATR|--wdatatr [value]\n" + " --T32AW|--t32aw [value]\n" + " --CRCWL|--crcwl [value]\n" + " --CRCRL|--crcrl [value]\n" + " --FAW|--faw [value]\n" + " --PA2WDATA|--pa2wdata [value]\n" + " --PA2RDATA|--pa2rdata [value]\n" + " --DBR|--dbr [value]\n" + " --DBW|--dbw [value]\n" + " --TCSR|--tcsr [value]\n" + " --DQR|--dqr [value]\n" + " --DQW|--dqw [value]\n" + " --ADD_PAR|--add_par [value]\n" + " --TM|--tm [value]\n" + " --WR|--wr [value]\n" + " --NDS|--nds [value]\n" + " --WL|--wl [value]\n" + " --RL|--rl [value]\n" + " --APRAS|--apras [value]\n" + " --BG|--bg [value]\n" + " --BL|--bl [value]\n" + " --REF|--ref [value]\n" + " --ENB|--enb [value]\n" + " --CNT|--cnt [value]\n" + " --TRC|--trc [value]\n" + " --THRESH|--thresh [value]\n" + " --LEVEL|--level [value]\n" + " --PWRDOWN|--pwrdown [value]\n" + " --SHUTDOWN|--shutdown [value]\n" + " --EN_SHUTDOWN|--en_shutdown [value]\n" + " --OVERSAMPLE|--oversample [value]\n" + " --AVG_SAMPLE|--avg_sample [value]\n\n" " Command line options: (GDDR5)\n" + " --DAT_DLY0|1 | --dat_dly0|1 [value]\n" + " --DQS_DLY0|1 | --dqs_dly0|1 [value]\n" + " --DQS_XTR0|1 | --dqs_xtr0|1 [value]\n" + " --DAT_2Y_DLY0|1 | --dat_2y_dly0|1 [value]\n" + " --ADR_2Y_DLY0|1 | --adr_2y_dly0|1 [value]\n" + " --CMD_2Y_DLY0|1 | --cmd_2y_dly0|1 [value]\n" + " --OEN_DLY0|1 | --oen_dly0|1 [value]\n" + " --OEN_EXT0|1 | --oen_ext0|1 [value]\n" + " --OEN_SEL0|1 | --oen_sel0|1 [value]\n" + " --ODT_DLY0|1 | --odt_dly0|1 [value]\n" + " --ODT_EXT0|1 | --odt_ext0|1 [value]\n" + " --ADR_DLY0|1 | --adr_dly0|1 [value]\n" + " --CMD_DLY0|1 | --cmd_dly0|1 [value]\n" " --CKSRE|--cksre [value]\n" " --CKSRX|--cksrx [value]\n" " --CKE_PULSE|--cke_pulse [value]\n" @@ -616,7 +1325,7 @@ int main(int argc, const char* argv[]) " --CL|--cl [value]\n" " --W2R|--w2r [value]\n" " --R2R|--r2r [value]\n" - " --CCLD|--ccld [value]\n" + " --CCDL|--ccdl [value]\n" " --R2W|--r2w [value]\n" " --NOPR|--nopr [value]\n" " --NOPW|--nopw [value]\n" @@ -637,7 +1346,36 @@ int main(int argc, const char* argv[]) " --FAW|--faw [value]\n" " --PA2WDATA|--pa2wdata [value]\n" " --PA2RDATA|--pa2rdata [value]\n" + " --WL|--wl [value]\n" + " --MR0_CL|--mr0_cl [value]\n" + " --TM|--tm [value]\n" + " --WR|--wr [value]\n" + " --DS|--ds [value]\n" + " --DT|--dt [value]\n" + " --ADR|--adr [value]\n" + " --CAL|--cal [value]\n" + " --PLL|--pll [value]\n" + " --RDBI|--rdbi [value]\n" + " --WDBI|--wdbi [value]\n" + " --ABI|--abi [value]\n" + " --RESET|--reset [value]\n" + " --SR|--sr [value]\n" + " --WCK01|--wck01 [value]\n" + " --WCK23|--wck23 [value]\n" + " --WCK2CK|--wck2ck [value]\n" + " --RDQS|--rdqs [value]\n" + " --INFO|--info [value]\n" + " --WCK2|--wck2 [value]\n" + " --BG|--bg [value]\n" + " --EDCHP|--edchp [value]\n" + " --CRCWL|--crcwl [value]\n" + " --CRCRL|--crcrl [value]\n" + " --RDCRC|--rdcrc [value]\n" + " --WRCRC|--wrcrc [value]\n" + " --EDC|--edc [value]\n" " --RAS|--ras [value]\n" + " --CLEHF|--clehf [value]\n" + " --WREHF|--wrehf [value]\n" " --ACTRD|--actrd [value]\n" " --ACTWR|--actwr [value]\n" " --RASMACTRD|--rasmactrd [value]\n" @@ -645,9 +1383,15 @@ int main(int argc, const char* argv[]) " --RAS2RAS|--ras2ras [value]\n" " --RP|--rp [value]\n" " --WRPLUSRP|--wrplusrp [value]\n" - " --BUS_TURN|--bus_turn [value]\n\n" - " HBM2 Example usage: ./amdmemtool -i 0,3,5 --faw 12 --RFC 208\n" - " GDDR5 Example usage: ./amdmemtool -i 1,2,4 --RFC 43 --ras2ras 176\n\n" + " --BUS_TURN|--bus_turn [value]\n" + " --REF|--ref [value]\n" + " --TWT2RT|--twt2rt [value]\n" + " --TARF2T|--tarf2t [value]\n" + " --TT2ROW|--tt2row [value]\n" + " --TLD2LD|--tld2ld [value]\n\n" + " HBM2 Example usage: ./amdmemtool --i 0,3,5 --faw 12 --RFC 208\n" + " HBM Example usage: ./amdmemtool --i 6 --ref 13\n" + " GDDR5 Example usage: ./amdmemtool --i 1,2,4 --RFC 43 --ras2ras 176\n\n" " Make sure to run the program first with parameter --current to see what the current values are.\n" " Current values may change based on state of the GPU,\n" " in other words, make sure the GPU is under load when running --current\n" @@ -656,6 +1400,12 @@ int main(int argc, const char* argv[]) return EXIT_SUCCESS; } + if (!strcasecmp("--version", argv[1]) || !strcasecmp("--v", argv[1])) + { + printf(VERSION); + return EXIT_SUCCESS; + } + atexit(UnloadDriver); LoadDriver(); @@ -683,31 +1433,84 @@ int main(int argc, const char* argv[]) { *((u32*)& gpu->hbm2 + j) = ReadMMIODword(AMD_TIMING_REGS_BASE_1 + j * sizeof(u32), i); } + gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM2, i); break; case GDDR5: + gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0, i); + gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1, i); gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING, i); gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING, i); gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING, i); gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING, i); gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2, i); - gpu->misc3.value = ReadMMIODword(MC_SEQ_MISC3, i); + gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1, i); + gpu->smisc2.value = ReadMMIODword(MC_SEC_MISC2, i); + gpu->smisc3.value = ReadMMIODword(MC_SEC_MISC3, i); + gpu->smisc4.value = ReadMMIODword(MC_SEC_MISC4, i); + gpu->smisc7.value = ReadMMIODword(MC_SEC_MISC7, i); + gpu->smisc8.value = ReadMMIODword(MC_SEC_MISC8, i); gpu->dram1.value = ReadMMIODword(MC_ARB_DRAM_TIMING, i); gpu->dram2.value = ReadMMIODword(MC_ARB_DRAM_TIMING2, i); + gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, i); + gpu->train.value = ReadMMIODword(MC_SEQ_TRAINING, i); + gpu->man.value = ReadMMIODword(MANUFACTURER_ID, i); break; case HBM: - // only RAS gives correct values - //gpu->ras.value = ReadMMIODword(0x28, i); - /* - gpu->cas = ReadMMIODword(0x28, i); - gpu->misc = ReadMMIODword(0x28, i); - gpu->misc2 = ReadMMIODword(0x28, i); - gpu->dram1 = ReadMMIODword(MC_ARB_DRAM_TIMING, i); - gpu->dram2 = ReadMMIODword(MC_ARB_DRAM_TIMING2, i); - */ + gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0_HBM, i); + gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1_HBM, i); + gpu->ctl3.value = ReadMMIODword(MC_SEQ_WR_CTL_D2_HBM, i); + gpu->ctl4.value = ReadMMIODword(MC_SEQ_WR_CTL_D3_HBM, i); + gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING_HBM, i); + gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING_HBM, i); + gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING_HBM, i); + gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING_HBM, i); + gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2_HBM, i); + gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1_HBM, i); + gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, i); + gpu->ham.value = ReadMMIODword(MC_SEQ_ROW_HAMMER, i); + gpu->throt.value = ReadMMIODword(MC_THERMAL_THROTTLE, i); + gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM, i); break; } } + // Scan some regs, you never know, you might find something useful ;-) + if (!strcasecmp("--scan", argv[1])) + { + if ((argc < 4) || memcmp(argv[2], "0x", 2) || memcmp(argv[3], "0x", 2)) + { + printf("--scan requires a range of addresses in hex format (for example 0x9A0290 0x9A02C4).\n"); + return EXIT_FAILURE; + } + u32 low = strtoul(argv[2] + 2, 0, 16); + if ((errno == EINVAL) || (errno == ERANGE)) + { + printf("Failed to parse %s as a hex number\n", argv[2]); + return EXIT_FAILURE; + } + u32 high = strtoul(argv[3] + 2, 0, 16); + if ((errno == EINVAL) || (errno == ERANGE)) + { + printf("Failed to parse %s as a hex number\n", argv[3]); + return EXIT_FAILURE; + } + + for (int index = 0; index < gpuCount; index++) + { + if (IsRelevantDeviceID(chips[index].device_id)) + { + printf("Scanning GPU %d\n", index); + for (u32 address = low; address <= high; address += sizeof(u32)) + { + u32 value = ReadMMIODword(address, index); + printf("0x%X: %08X\n", address, value); + Sleep(50); + } + } + } + return EXIT_SUCCESS; + } + // Parses the command line arguments, and accumulates the changes. for (int index = 0; index < gpuCount; index++) { @@ -727,7 +1530,7 @@ int main(int argc, const char* argv[]) i++; affectedGPUs = ParseIndicesArg(argv[i]); } - else if (!strcasecmp("--current", argv[i])) + else if (!strcasecmp("--current", argv[i]) || !strcasecmp("--c", argv[i])) { if (affectedGPUs & ((u64)1 << index)) { @@ -1095,286 +1898,1326 @@ int main(int argc, const char* argv[]) strcat(gpu->log, "RFC"); } } - else // GDDR5 & HBM - { - if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) + else if (DetermineMemoryType(chips[index].device_id) == HBM) { + if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) { - gpu->pmg.CKSRE = value; + gpu->ctl1.hbm.DAT_DLY = value; gpu->modify[0] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKSRE"); + strcat(gpu->log, "DAT_DLY0"); } - else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) { - gpu->pmg.CKSRX = value; + gpu->ctl1.hbm.DQS_DLY = value; gpu->modify[0] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKSRX"); + strcat(gpu->log, "DQS_DLY0"); } - else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) { - gpu->pmg.CKE_PULSE = value; + gpu->ctl1.hbm.DQS_XTR = value; gpu->modify[0] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKE_PULSE"); + strcat(gpu->log, "DQS_XTR0"); } - else if (ParseNumericArg(argc, argv, i, "--CKE", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) { - gpu->pmg.CKE = value; + gpu->ctl1.hbm.OEN_DLY = value; gpu->modify[0] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CKE"); + strcat(gpu->log, "OEN_DLY0"); } - else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) { - gpu->pmg.SEQ_IDLE = value; + gpu->ctl1.hbm.OEN_EXT = value; gpu->modify[0] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "SEQ_IDLE"); + strcat(gpu->log, "OEN_EXT0"); } - else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) { - gpu->ras.RCDW = value; + gpu->ctl1.hbm.OEN_SEL = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) + { + gpu->ctl1.hbm.CMD_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) + { + gpu->ctl1.hbm.ADR_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) + { + gpu->ctl2.hbm.DAT_DLY = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDW"); + strcat(gpu->log, "DAT_DLY1"); } - else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) { - gpu->ras.RCDWA = value; + gpu->ctl2.hbm.DQS_DLY = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDWA"); + strcat(gpu->log, "DQS_DLY1"); } - else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) { - gpu->ras.RCDR = value; + gpu->ctl2.hbm.DQS_XTR = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDR"); + strcat(gpu->log, "DQS_XTR1"); } - else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) { - gpu->ras.RCDRA = value; + gpu->ctl2.hbm.OEN_DLY = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RCDRA"); + strcat(gpu->log, "OEN_DLY1"); } - else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) { - gpu->ras.RRD = value; + gpu->ctl2.hbm.OEN_EXT = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RRD"); + strcat(gpu->log, "OEN_EXT1"); } - else if (ParseNumericArg(argc, argv, i, "--RC", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) { - gpu->ras.RC = value; + gpu->ctl2.hbm.OEN_SEL = value; gpu->modify[1] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RC"); + strcat(gpu->log, "OEN_SEL1"); } - else if (ParseNumericArg(argc, argv, i, "--CL", value)) + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) + { + gpu->ctl2.hbm.CMD_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) + { + gpu->ctl2.hbm.ADR_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY2", value)) { - gpu->cas.CL = value; + gpu->ctl3.DAT_DLY = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CL"); + strcat(gpu->log, "DAT_DLY2"); } - else if (ParseNumericArg(argc, argv, i, "--W2R", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY2", value)) { - gpu->cas.W2R = value; + gpu->ctl3.DQS_DLY = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "W2R"); + strcat(gpu->log, "DQS_DLY2"); } - else if (ParseNumericArg(argc, argv, i, "--R2R", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR2", value)) { - gpu->cas.R2R = value; + gpu->ctl3.DQS_XTR = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "R2R"); + strcat(gpu->log, "DQS_XTR2"); } - else if (ParseNumericArg(argc, argv, i, "--CCLD", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY2", value)) { - gpu->cas.CCLD = value; + gpu->ctl3.OEN_DLY = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CCLD"); + strcat(gpu->log, "OEN_DLY2"); } - else if (ParseNumericArg(argc, argv, i, "--R2W", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT2", value)) { - gpu->cas.R2W = value; + gpu->ctl3.OEN_EXT = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "R2W"); + strcat(gpu->log, "OEN_EXT2"); } - else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL2", value)) { - gpu->cas.NOPR = value; + gpu->ctl3.OEN_SEL = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "NOPR"); + strcat(gpu->log, "OEN_SEL2"); } - else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY2", value)) { - gpu->cas.NOPW = value; + gpu->ctl3.CMD_DLY = value; gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "NOPW"); + strcat(gpu->log, "CMD_DLY2"); } - else if (ParseNumericArg(argc, argv, i, "--RFC", value)) + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY2", value)) { - if (IsR9(chips[index].device_id)) - gpu->misc.r9.RFC = value; - else - gpu->misc.rx.RFC = value; - gpu->modify[3] = true; + gpu->ctl3.ADR_DLY = value; + gpu->modify[2] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RFC"); + strcat(gpu->log, "ADR_DLY2"); } - else if (ParseNumericArg(argc, argv, i, "--TRP", value)) + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY3", value)) { - if (IsR9(chips[index].device_id)) - gpu->misc.r9.TRP = value; - else - gpu->misc.rx.TRP = value; + gpu->ctl4.DAT_DLY = value; gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "TRP"); + strcat(gpu->log, "DAT_DLY3"); } - else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY3", value)) { - if (IsR9(chips[index].device_id)) - gpu->misc.r9.RP_RDA = value; - else - gpu->misc.rx.RP_RDA = value; + gpu->ctl4.DQS_DLY = value; gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RP_RDA"); + strcat(gpu->log, "DQS_DLY3"); } - else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR3", value)) { - if (IsR9(chips[index].device_id)) - gpu->misc.r9.RP_WRA = value; - else - gpu->misc.rx.RP_WRA = value; + gpu->ctl4.DQS_XTR = value; gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "RP_WRA"); + strcat(gpu->log, "DQS_XTR3"); } - else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY3", value)) { - gpu->misc2.WDATATR = value; - gpu->modify[4] = true; + gpu->ctl4.OEN_DLY = value; + gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "WDATATR"); + strcat(gpu->log, "OEN_DLY3"); } - else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT3", value)) { - gpu->misc2.T32AW = value; - gpu->modify[4] = true; + gpu->ctl4.OEN_EXT = value; + gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "T32AW"); + strcat(gpu->log, "OEN_EXT3"); } - else if (ParseNumericArg(argc, argv, i, "--CRCWL", value)) + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL3", value)) { - gpu->misc2.CRCWL = value; - gpu->modify[4] = true; + gpu->ctl4.OEN_SEL = value; + gpu->modify[3] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CRCWL"); + strcat(gpu->log, "OEN_SEL3"); } - else if (ParseNumericArg(argc, argv, i, "--CRCRL", value)) + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY3", value)) { - gpu->misc2.CRCRL = value; - gpu->modify[4] = true; + gpu->ctl4.CMD_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY3", value)) + { + gpu->ctl4.ADR_DLY = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY3"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) + { + gpu->pmg.hbm.CKSRE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) + { + gpu->pmg.hbm.CKSRX = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRX"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) + { + gpu->pmg.hbm.CKE_PULSE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE_PULSE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE", value)) + { + gpu->pmg.hbm.CKE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE"); + } + else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) + { + gpu->pmg.hbm.SEQ_IDLE = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SEQ_IDLE"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + { + gpu->ras.RCDW = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDW"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + { + gpu->ras.RCDWA = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDWA"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + { + gpu->ras.RCDR = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDR"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + { + gpu->ras.RCDRA = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDRA"); + } + else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + { + gpu->ras.RRD = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RC", value)) + { + gpu->ras.RC = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RC"); + } + else if (ParseNumericArg(argc, argv, i, "--CL", value)) + { + gpu->cas.hbm.CL = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CL"); + } + else if (ParseNumericArg(argc, argv, i, "--W2R", value)) + { + gpu->cas.hbm.W2R = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "W2R"); + } + else if (ParseNumericArg(argc, argv, i, "--R2R", value)) + { + gpu->cas.hbm.R2R = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2R"); + } + else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) + { + gpu->cas.hbm.CCDL = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CCDL"); + } + else if (ParseNumericArg(argc, argv, i, "--R2W", value)) + { + gpu->cas.hbm.R2W = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2W"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) + { + gpu->cas.hbm.NOPR = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPR"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) + { + gpu->cas.hbm.NOPW = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPW"); + } + else if (ParseNumericArg(argc, argv, i, "--MRD", value)) + { + gpu->misc.hbm.MRD = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "MRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RRDL", value)) + { + gpu->misc.hbm.RRDL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRDL"); + } + else if (ParseNumericArg(argc, argv, i, "--RFC", value)) + { + gpu->misc.hbm.RFC = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RFC"); + } + else if (ParseNumericArg(argc, argv, i, "--TRP", value)) + { + gpu->misc.hbm.TRP = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TRP"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) + { + gpu->misc.hbm.RP_RDA = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RP_RDA"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) + { + gpu->misc.hbm.RP_WRA = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RP_WRA"); + } + else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) + { + gpu->misc2.hbm.WDATATR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WDATATR"); + } + else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) + { + gpu->misc2.hbm.T32AW = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "T32AW"); + } + else if (ParseNumericArg(argc, argv, i, "--RPAR", value)) + { + gpu->misc2.hbm.RPAR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RPAR"); + } + else if (ParseNumericArg(argc, argv, i, "--WPAR", value)) + { + gpu->misc2.hbm.WPAR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WPAR"); + } + else if (ParseNumericArg(argc, argv, i, "--FAW", value)) + { + gpu->misc2.hbm.FAW = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "FAW"); + } + else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) + { + gpu->misc2.hbm.PA2WDATA = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "P2WDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) + { + gpu->misc2.hbm.PA2RDATA = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PA2RDATA"); + } + else if (ParseNumericArg(argc, argv, i, "--DBR", value)) + { + gpu->smisc1.hbm.DBR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DBR"); + } + else if (ParseNumericArg(argc, argv, i, "--DBW", value)) + { + gpu->smisc1.hbm.DBW = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DBW"); + } + else if (ParseNumericArg(argc, argv, i, "--TCSR", value)) + { + gpu->smisc1.hbm.TCSR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TCSR"); + } + else if (ParseNumericArg(argc, argv, i, "--DQR", value)) + { + gpu->smisc1.hbm.DQR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQR"); + } + else if (ParseNumericArg(argc, argv, i, "--DQW", value)) + { + gpu->smisc1.hbm.DQW = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQW"); + } + else if (ParseNumericArg(argc, argv, i, "--ADD_PAR", value)) + { + gpu->smisc1.hbm.ADD_PAR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADD_PAR"); + } + else if (ParseNumericArg(argc, argv, i, "--TM", value)) + { + gpu->smisc1.hbm.TM = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TM"); + } + else if (ParseNumericArg(argc, argv, i, "--WR", value)) + { + gpu->smisc1.hbm.WR = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WR"); + } + else if (ParseNumericArg(argc, argv, i, "--NDS", value)) + { + gpu->smisc1.hbm.NDS = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NDS"); + } + else if (ParseNumericArg(argc, argv, i, "--WL", value)) + { + gpu->smisc1.hbm.WL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WL"); + } + else if (ParseNumericArg(argc, argv, i, "--RL", value)) + { + gpu->smisc1.hbm.RL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RL"); + } + else if (ParseNumericArg(argc, argv, i, "--APRAS", value)) + { + gpu->smisc1.hbm.APRAS = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "APRAS"); + } + else if (ParseNumericArg(argc, argv, i, "--BG", value)) + { + gpu->smisc1.hbm.BG = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BG"); + } + else if (ParseNumericArg(argc, argv, i, "--BL", value)) + { + gpu->smisc1.hbm.BL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BL"); + } + else if (ParseNumericArg(argc, argv, i, "--REF", value)) + { + gpu->ref.REF = value; + gpu->modify[10] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REF"); + } + else if (ParseNumericArg(argc, argv, i, "--ENB", value)) + { + gpu->ham.ENB = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ENB"); + } + else if (ParseNumericArg(argc, argv, i, "--CNT", value)) + { + gpu->ham.CNT = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CNT"); + } + else if (ParseNumericArg(argc, argv, i, "--TRC", value)) + { + gpu->ham.TRC = value; + gpu->modify[11] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TRC"); + } + else if (ParseNumericArg(argc, argv, i, "--THRESH", value)) + { + gpu->throt.THRESH = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "THRESH"); + } + else if (ParseNumericArg(argc, argv, i, "--LEVEL", value)) + { + gpu->throt.LEVEL = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "LEVEL"); + } + else if (ParseNumericArg(argc, argv, i, "--PWRDOWN", value)) + { + gpu->throt.PWRDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PWRDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--SHUTDOWN", value)) + { + gpu->throt.SHUTDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SHUTDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--EN_SHUTDOWN", value)) + { + gpu->throt.EN_SHUTDOWN = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EN_SHUTDOWN"); + } + else if (ParseNumericArg(argc, argv, i, "--OVERSAMPLE", value)) + { + gpu->throt.OVERSAMPLE = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OVERSAMPLE"); + } + else if (ParseNumericArg(argc, argv, i, "--AVG_SAMPLE", value)) + { + gpu->throt.AVG_SAMPLE = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "AVG_SAMPLE"); + } + + } + else // GDDR5 + { + if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) + { + gpu->ctl1.rx.DAT_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) + { + gpu->ctl1.rx.DQS_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) + { + gpu->ctl1.rx.DQS_XTR = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY0", value)) + { + gpu->ctl1.rx.DAT_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY0", value)) + { + gpu->ctl1.rx.ADR_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY0", value)) + { + gpu->ctl1.rx.CMD_2Y_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_2Y_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) + { + gpu->ctl1.rx.OEN_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) + { + gpu->ctl1.rx.OEN_EXT = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT0"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) + { + gpu->ctl1.rx.OEN_SEL = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL0"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_DLY0", value)) + { + gpu->ctl1.rx.ODT_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_EXT0", value)) + { + gpu->ctl1.rx.ODT_EXT = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_EXT0"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) + { + gpu->ctl1.rx.ADR_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) + { + gpu->ctl1.rx.CMD_DLY = value; + gpu->modify[0] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY0"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) + { + gpu->ctl2.rx.DAT_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) + { + gpu->ctl2.rx.DQS_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) + { + gpu->ctl2.rx.DQS_XTR = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DQS_XTR1"); + } + else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY1", value)) + { + gpu->ctl2.rx.DAT_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DAT_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY1", value)) + { + gpu->ctl2.rx.ADR_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY1", value)) + { + gpu->ctl2.rx.CMD_2Y_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_2Y_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) + { + gpu->ctl2.rx.OEN_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) + { + gpu->ctl2.rx.OEN_EXT = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_EXT1"); + } + else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) + { + gpu->ctl2.rx.OEN_SEL = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "OEN_SEL1"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_DLY1", value)) + { + gpu->ctl2.rx.ODT_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--ODT_EXT1", value)) + { + gpu->ctl2.rx.ODT_EXT = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ODT_EXT1"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) + { + gpu->ctl2.rx.ADR_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR_DLY2"); + } + else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) + { + gpu->ctl2.rx.CMD_DLY = value; + gpu->modify[1] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CMD_DLY1"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) + { + gpu->pmg.rx.CKSRE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) + { + gpu->pmg.rx.CKSRX = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKSRX"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) + { + gpu->pmg.rx.CKE_PULSE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE_PULSE"); + } + else if (ParseNumericArg(argc, argv, i, "--CKE", value)) + { + gpu->pmg.rx.CKE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CKE"); + } + else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) + { + gpu->pmg.rx.SEQ_IDLE = value; + gpu->modify[2] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SEQ_IDLE"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) + { + gpu->ras.RCDW = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDW"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) + { + gpu->ras.RCDWA = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDWA"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) + { + gpu->ras.RCDR = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDR"); + } + else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) + { + gpu->ras.RCDRA = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RCDRA"); + } + else if (ParseNumericArg(argc, argv, i, "--RRD", value)) + { + gpu->ras.RRD = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RRD"); + } + else if (ParseNumericArg(argc, argv, i, "--RC", value)) + { + gpu->ras.RC = value; + gpu->modify[3] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RC"); + } + else if (ParseNumericArg(argc, argv, i, "--CL", value)) + { + gpu->cas.rx.CL = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CL"); + } + else if (ParseNumericArg(argc, argv, i, "--W2R", value)) + { + gpu->cas.rx.W2R = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "W2R"); + } + else if (ParseNumericArg(argc, argv, i, "--R2R", value)) + { + gpu->cas.rx.R2R = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2R"); + } + else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) + { + gpu->cas.rx.CCDL = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CCDL"); + } + else if (ParseNumericArg(argc, argv, i, "--R2W", value)) + { + gpu->cas.rx.R2W = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "R2W"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) + { + gpu->cas.rx.NOPR = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPR"); + } + else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) + { + gpu->cas.rx.NOPW = value; + gpu->modify[4] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "NOPW"); + } + else if (ParseNumericArg(argc, argv, i, "--RFC", value)) + { + if (IsR9(chips[index].device_id)) + gpu->misc.r9.RFC = value; + else + gpu->misc.rx.RFC = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RFC"); + } + else if (ParseNumericArg(argc, argv, i, "--TRP", value)) + { + if (IsR9(chips[index].device_id)) + gpu->misc.r9.TRP = value; + else + gpu->misc.rx.TRP = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TRP"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) + { + if (IsR9(chips[index].device_id)) + gpu->misc.r9.RP_RDA = value; + else + gpu->misc.rx.RP_RDA = value; + gpu->modify[5] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "CRCRL"); + strcat(gpu->log, "RP_RDA"); + } + else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) + { + if (IsR9(chips[index].device_id)) + gpu->misc.r9.RP_WRA = value; + else + gpu->misc.rx.RP_WRA = value; + gpu->modify[5] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RP_WRA"); + } + else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) + { + gpu->misc2.rx.WDATATR = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WDATATR"); + } + else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) + { + gpu->misc2.rx.T32AW = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "T32AW"); + } + else if (ParseNumericArg(argc, argv, i, "--WEDC", value)) + { + gpu->misc2.rx.WEDC = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WEDC"); + } + else if (ParseNumericArg(argc, argv, i, "--REDC", value)) + { + gpu->misc2.rx.REDC = value; + gpu->modify[6] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REDC"); } else if (ParseNumericArg(argc, argv, i, "--FAW", value)) { - gpu->misc2.FAW = value; - gpu->modify[4] = true; + gpu->misc2.rx.FAW = value; + gpu->modify[6] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "FAW"); } else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) { - gpu->misc2.PA2WDATA = value; - gpu->modify[4] = true; + gpu->misc2.rx.PA2WDATA = value; + gpu->modify[6] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "P2WDATA"); } else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) { - gpu->misc2.PA2RDATA = value; - gpu->modify[4] = true; + gpu->misc2.rx.PA2RDATA = value; + gpu->modify[6] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "PA2RDATA"); } + else if (ParseNumericArg(argc, argv, i, "--WL", value)) + { + gpu->smisc1.rx.WL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WL"); + } + else if (ParseNumericArg(argc, argv, i, "--MR0_CL", value)) + { + gpu->smisc1.rx.CL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "MR0_CL"); + } + else if (ParseNumericArg(argc, argv, i, "--TM", value)) + { + gpu->smisc1.rx.TM = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TM"); + } + else if (ParseNumericArg(argc, argv, i, "--WR", value)) + { + gpu->smisc1.rx.WR = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WR"); + } + else if (ParseNumericArg(argc, argv, i, "--DS", value)) + { + gpu->smisc1.rx.DS = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DS"); + } + else if (ParseNumericArg(argc, argv, i, "--DT", value)) + { + gpu->smisc1.rx.DT = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "DT"); + } + else if (ParseNumericArg(argc, argv, i, "--ADR", value)) + { + gpu->smisc1.rx.ADR = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ADR"); + } + else if (ParseNumericArg(argc, argv, i, "--CAL", value)) + { + gpu->smisc1.rx.CAL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CAL"); + } + else if (ParseNumericArg(argc, argv, i, "--PLL", value)) + { + gpu->smisc1.rx.PLL = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "PLL"); + } + else if (ParseNumericArg(argc, argv, i, "--RDBI", value)) + { + gpu->smisc1.rx.RDBI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDBI"); + } + else if (ParseNumericArg(argc, argv, i, "--WDBI", value)) + { + gpu->smisc1.rx.WDBI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WDBI"); + } + else if (ParseNumericArg(argc, argv, i, "--ABI", value)) + { + gpu->smisc1.rx.ABI = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "ABI"); + } + else if (ParseNumericArg(argc, argv, i, "--RESET", value)) + { + gpu->smisc1.rx.RESET = value; + gpu->modify[7] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RESET"); + } + else if (ParseNumericArg(argc, argv, i, "--SR", value)) + { + gpu->smisc2.SR = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "SR"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK01", value)) + { + gpu->smisc2.WCK01 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK01"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK23", value)) + { + gpu->smisc2.WCK23 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK23"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK2CK", value)) + { + gpu->smisc2.WCK2CK = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK2CK"); + } + else if (ParseNumericArg(argc, argv, i, "--RDQS", value)) + { + gpu->smisc2.RDQS = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDQS"); + } + else if (ParseNumericArg(argc, argv, i, "--INFO", value)) + { + gpu->smisc2.INFO = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "INFO"); + } + else if (ParseNumericArg(argc, argv, i, "--WCK2", value)) + { + gpu->smisc2.WCK2 = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WCK2"); + } + + else if (ParseNumericArg(argc, argv, i, "--BG", value)) + { + gpu->smisc2.BG = value; + gpu->modify[8] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "BG"); + } + else if (ParseNumericArg(argc, argv, i, "--EDCHP", value)) + { + gpu->smisc3.EDCHP = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EDCHP"); + } + else if (ParseNumericArg(argc, argv, i, "--CRCWL", value)) + { + gpu->smisc3.CRCWL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CRCWL"); + } + else if (ParseNumericArg(argc, argv, i, "--CRCRL", value)) + { + gpu->smisc3.CRCRL = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CRCRL"); + } + else if (ParseNumericArg(argc, argv, i, "--RDCRC", value)) + { + gpu->smisc3.RDCRC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "RDCRC"); + } + else if (ParseNumericArg(argc, argv, i, "--WRCRC", value)) + { + gpu->smisc3.WRCRC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WRCRC"); + } + else if (ParseNumericArg(argc, argv, i, "--EDC", value)) + { + gpu->smisc3.EDC = value; + gpu->modify[9] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "EDC"); + } else if (ParseNumericArg(argc, argv, i, "--RAS", value)) { - gpu->misc3.RAS = value; - gpu->modify[5] = true; + gpu->smisc3.RAS = value; + gpu->modify[9] = true; if (gpu->log[0]) strcat(gpu->log, ", "); - strcat(gpu->log, "PA2RDATA"); + strcat(gpu->log, "RAS"); + } + else if (ParseNumericArg(argc, argv, i, "--CLEHF", value)) + { + gpu->smisc8.CLEHF = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "CLEHF"); + } + else if (ParseNumericArg(argc, argv, i, "--WREHF", value)) + { + gpu->smisc8.WREHF = value; + gpu->modify[12] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "WREHF"); } else if (ParseNumericArg(argc, argv, i, "--ACTRD", value)) { gpu->dram1.ACTRD = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "ACTRD"); } else if (ParseNumericArg(argc, argv, i, "--ACTWR", value)) { gpu->dram1.ACTWR = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "ACTWR"); } else if (ParseNumericArg(argc, argv, i, "--RASMACTRD", value)) { gpu->dram1.RASMACTRD = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RASMACTRD"); } else if (ParseNumericArg(argc, argv, i, "--RASMACTWR", value)) { gpu->dram1.RASMACTWR = value; - gpu->modify[6] = true; + gpu->modify[13] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RASMACTWR"); } else if (ParseNumericArg(argc, argv, i, "--RAS2RAS", value)) { gpu->dram2.RAS2RAS = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RAS2RAS"); } else if (ParseNumericArg(argc, argv, i, "--RP", value)) { gpu->dram2.RP = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "RP"); } else if (ParseNumericArg(argc, argv, i, "--WRPLUSRP", value)) { gpu->dram2.WRPLUSRP = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "WRPLUSRP"); } else if (ParseNumericArg(argc, argv, i, "--BUS_TURN", value)) { gpu->dram2.BUS_TURN = value; - gpu->modify[7] = true; + gpu->modify[14] = true; if (gpu->log[0]) strcat(gpu->log, ", "); strcat(gpu->log, "BUS_TURN"); } + else if (ParseNumericArg(argc, argv, i, "--REF", value)) + { + gpu->ref.REF = value; + gpu->modify[15] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "REF"); + } + else if (ParseNumericArg(argc, argv, i, "--TWT2RT", value)) + { + gpu->train.TWT2RT = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TWT2RT"); + } + else if (ParseNumericArg(argc, argv, i, "--TARF2T", value)) + { + gpu->train.TARF2T = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TARF2T"); + } + else if (ParseNumericArg(argc, argv, i, "--TT2ROW", value)) + { + gpu->train.TT2ROW = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TT2ROW"); + } + else if (ParseNumericArg(argc, argv, i, "--TLD2LD", value)) + { + gpu->train.TLD2LD = value; + gpu->modify[16] = true; + if (gpu->log[0]) strcat(gpu->log, ", "); + strcat(gpu->log, "TLD2LD"); + } } } } @@ -1408,34 +3251,102 @@ int main(int argc, const char* argv[]) switch (i) { case 0: - WriteMMIODword(MC_SEQ_PMG_TIMING, gpu->pmg.value, index); + WriteMMIODword(MC_SEQ_WR_CTL_D0, gpu->ctl1.value, index); break; case 1: - WriteMMIODword(MC_SEQ_RAS_TIMING, gpu->ras.value, index); + WriteMMIODword(MC_SEQ_WR_CTL_D1, gpu->ctl2.value, index); break; case 2: - WriteMMIODword(MC_SEQ_CAS_TIMING, gpu->cas.value, index); + WriteMMIODword(MC_SEQ_PMG_TIMING, gpu->pmg.value, index); break; case 3: - WriteMMIODword(MC_SEQ_MISC_TIMING, gpu->misc.value, index); + WriteMMIODword(MC_SEQ_RAS_TIMING, gpu->ras.value, index); break; case 4: - WriteMMIODword(MC_SEQ_MISC_TIMING2, gpu->misc2.value, index); + WriteMMIODword(MC_SEQ_CAS_TIMING, gpu->cas.value, index); break; case 5: - WriteMMIODword(MC_SEQ_MISC3, gpu->misc3.value, index); + WriteMMIODword(MC_SEQ_MISC_TIMING, gpu->misc.value, index); break; case 6: - WriteMMIODword(MC_ARB_DRAM_TIMING, gpu->dram1.value, index); + WriteMMIODword(MC_SEQ_MISC_TIMING2, gpu->misc2.value, index); break; case 7: + WriteMMIODword(MC_SEC_MISC1, gpu->smisc1.value, index); + break; + case 8: + WriteMMIODword(MC_SEC_MISC2, gpu->smisc2.value, index); + break; + case 9: + WriteMMIODword(MC_SEC_MISC3, gpu->smisc3.value, index); + break; + case 10: + WriteMMIODword(MC_SEC_MISC4, gpu->smisc4.value, index); + break; + case 11: + WriteMMIODword(MC_SEC_MISC7, gpu->smisc7.value, index); + break; + case 12: + WriteMMIODword(MC_SEC_MISC8, gpu->smisc8.value, index); + break; + case 13: + WriteMMIODword(MC_ARB_DRAM_TIMING, gpu->dram1.value, index); + break; + case 14: WriteMMIODword(MC_ARB_DRAM_TIMING2, gpu->dram2.value, index); break; + case 15: + WriteMMIODword(MC_ARB_RFSH_RATE, gpu->ref.value, index); + break; + case 16: + WriteMMIODword(MC_SEQ_TRAINING, gpu->train.value, index); + break; } break; case HBM: - printf("HBM memory type is not supported yet\n"); - return EXIT_FAILURE; + switch (i) + { + case 0: + WriteMMIODword(MC_SEQ_WR_CTL_D0_HBM, gpu->ctl1.value, index); + break; + case 1: + WriteMMIODword(MC_SEQ_WR_CTL_D1_HBM, gpu->ctl2.value, index); + break; + case 2: + WriteMMIODword(MC_SEQ_WR_CTL_D2_HBM, gpu->ctl3.value, index); + break; + case 3: + WriteMMIODword(MC_SEQ_WR_CTL_D3_HBM, gpu->ctl4.value, index); + break; + case 4: + WriteMMIODword(MC_SEQ_PMG_TIMING_HBM, gpu->pmg.value, index); + break; + case 5: + WriteMMIODword(MC_SEQ_RAS_TIMING_HBM, gpu->ras.value, index); + break; + case 6: + WriteMMIODword(MC_SEQ_CAS_TIMING_HBM, gpu->cas.value, index); + break; + case 7: + WriteMMIODword(MC_SEQ_MISC_TIMING_HBM, gpu->misc.value, index); + break; + case 8: + WriteMMIODword(MC_SEQ_MISC_TIMING2_HBM, gpu->misc2.value, index); + break; + case 9: + WriteMMIODword(MC_SEC_MISC1_HBM, gpu->smisc1.value, index); + break; + case 10: + WriteMMIODword(MC_ARB_RFSH_RATE, gpu->ref.value, index); + break; + case 11: + WriteMMIODword(MC_SEQ_ROW_HAMMER, gpu->ham.value, index); + break; + case 12: + WriteMMIODword(MC_THERMAL_THROTTLE, gpu->throt.value, index); + break; + } + break; } } } From 203a2a450218f1a7e03f9eb06614d80a6464ebb0 Mon Sep 17 00:00:00 2001 From: Adamant Mischke Date: Wed, 12 Feb 2020 22:41:20 -0600 Subject: [PATCH 2/3] add GDDR6 type and 5700xt ID --- linux/AmdMemTweak.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/linux/AmdMemTweak.cpp b/linux/AmdMemTweak.cpp index aff700a..2114bc7 100644 --- a/linux/AmdMemTweak.cpp +++ b/linux/AmdMemTweak.cpp @@ -66,6 +66,7 @@ bool IsAmdDisplayDevice(struct pci_dev* dev) bool IsRelevantDeviceID(struct pci_dev* dev) { return + (dev->device_id == 0x731F) || // Navi 14 [Radeon RX 5700 XT] (dev->device_id == 0x66af) || // Radeon VII (dev->device_id == 0x687f) || // Vega 10 XL/XT [Radeon RX Vega 56/64] (dev->device_id == 0x6867) || // Vega 10 XL [Radeon Pro Vega 56] @@ -92,7 +93,7 @@ static bool IsR9(struct pci_dev* dev) (dev->device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] } -typedef enum { GDDR5, HBM, HBM2 } MemoryType; +typedef enum { GDDR5, HBM, HBM2, GDDR6 } MemoryType; static MemoryType DetermineMemoryType(struct pci_dev* dev) { @@ -101,6 +102,8 @@ static MemoryType DetermineMemoryType(struct pci_dev* dev) u16 device_id; MemoryType memory_type; } KnownGPUs[] = { + /* Navi 14 */ + { 0x1002, 0x731f, GDDR6}, // "Radeon Navi14", CHIP_NAVI14 /* Vega20 - Radeon VII */ { 0x1002, 0x66a0, HBM2 }, // "Radeon Instinct", CHIP_VEGA20 { 0x1002, 0x66a1, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 From 4ae348efd231554d91da2a9602f132e78b2e2e26 Mon Sep 17 00:00:00 2001 From: Adamant Mischke Date: Wed, 12 Feb 2020 23:12:07 -0600 Subject: [PATCH 3/3] change name of device_id --- linux/AmdMemTweak.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/linux/AmdMemTweak.cpp b/linux/AmdMemTweak.cpp index 2114bc7..0793b84 100644 --- a/linux/AmdMemTweak.cpp +++ b/linux/AmdMemTweak.cpp @@ -71,7 +71,7 @@ bool IsRelevantDeviceID(struct pci_dev* dev) (dev->device_id == 0x687f) || // Vega 10 XL/XT [Radeon RX Vega 56/64] (dev->device_id == 0x6867) || // Vega 10 XL [Radeon Pro Vega 56] (dev->device_id == 0x6863) || // Vega 10 XTX [Radeon Vega Frontier Edition] - (dev->device_id == 0x6fdf) || // RX 580 FAT + (dev->device_id == 0x6fdf) || // Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (dev->device_id == 0x67df) || // Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] (dev->device_id == 0x67c4) || // Ellesmere [Radeon Pro WX 7100] (dev->device_id == 0x67c7) || // Ellesmere [Radeon Pro WX 5100]

  • 6A}_$`k8NKJO*EHX^^ zAhivy5N(C24;CHgCPR?ONLI_Wt%*O9^b| zLyn6zXQLJcOEqj1>J{xW+%cMQCcG-|_R>ajkIPxVF}%6~tZ<>;R4u;g)tT4ZY)#sl z9`#)(KJ#N)r{G%oE~qOJN86+LM#AibU3)$QW7H&P+=;H;`QFO1nMA|j2QNoH?y^I3 zZMyTYLUxdXsVeYVxh-GsNkNXb#&svU%4TMF?)npFx&jC6gc$%XkPZvLuVbNOjyC(r zWv~oA)lJ^W`;E>M3VlBKjhetXi%|H8pa^U|f2WD`z5G*fFz|tKY5zMcB z;0SQPP&MEP4hyy!>@R@vmAD`hoFb(j;A_$M3wIzs0bnTp;C?@rh4&)oGyF?_aR2Tf z+~50y`<>YVOAi*5-vSgP1WyWiMhFB3`W~Es>k{P_zKVer9Xo`3|O%98tNyy33L?tDsL?k4tgv8O?K`7@J6>Z`Z z5t#m6vx&W7|_<++R{udENJ@1#x#VNn3Qx2kR=(ClHCD9zL=DZ zg#ZNI0Q59K--FN_n-Z@{D`GzA=<9znHMh8`Z){Qz&YQ6W!aH#pSwBEi4#K6`P$eQE zSqS8q;u8_;0gr#!$b?uggHigRXJkBPWovs9q<_?qNW7%1rZy}tBexyUod@AK2xou{ znZjrZl7N`lG`}c>q+bKlZd`B6!E`E(%1FW^}M zKz^spc#-U`Z&u?f-al#C+w1bBv4DFsZIq`YF6gq#8h@?B_Ix!(ZYZ;-T1 zqo|~Gqlko57kHX9tUv<4 zu*7nHVKfrJIhq?hKPw0vPR>rK?c4YKsWSXm5+PWoNYDX+zUt^t2!q@^M;Ai^_}yR8 zAa&a^Q1u|S4pJjApmM-HH4A_YYyLxgM1;r8HgnXO{fAU{b5~}gfJ+k+_vf+T0E#X% z^b;71$RbP##^T&>6>vm?LE2#`MG*gcj7435FsKi5#GJ0;MjV31)ROu1zK7lTHNUkWXVwCa z05=%${u!J`E4qB%C@hd1Ngr`PLnKGk^uZuz<~b1OGsL+IaSKD7&k&ciFK%N#;F%Cx zJq(cGzohvs;vWj&CMtn@<^lqLyA0fKLN^D@U_^e6+c<+OXh@eL7^G{2vITc50m))O zK%rbwB7pus$8anKvVT9{=I|W>;4#>Y>GG`uc`)Nf_aiLEe<$Z!6gQCbYdk~?P%37S z98utX{c+hrWLZVe+pl?io5SDcuNs|37vvn`au^IsAo89dP)3m4{(`3YEnSd53+l;& z@A=J@YE7M(;2;Q~<3<8}0WCC62}VPt5U)^g03M-*rjUIwYG@s84o#29NK&w8P%H$X zqWpaTb{y~sUqAwwghYb-BSJJHz5GaE_<)($Z(;yYg@#9Duu>Ebt<3>Jn&b#dBpI0` z0sR~qo=ye`BLPxw1ejKja6vZBh#90`lD8#5`1KDW`H~`klBe=4PdXcM3wLNOM=LLq1fHOyf zH>1Qc&*V!Ue8XWTWi7M^n2!<_8c2#jLll1?9e^0tLi>0GMUv1Eb}lCu=H(CgAd>n= zkaWF+{X_gC$p9uS^#97z4|qp{qNE$;;UDDT83Y9So`my{ioAz!-U0wlMqs8PL-6t; zj}ULjisXw37Yo_>N02E91~nbd4Dtz$fIL0C0)dZ)H}n-pP&&iDIBbCT83K9Jv99S^ z{zvaeX`T-T^Aj0KF9}-c|1=*pvGX!~DdjWCX<`?C5t`Wf4-0&-*tsuO8>wafceZ~4 DYii6m literal 0 HcmV?d00001 diff --git a/gui/x64/IOMap.sys b/gui/x64/IOMap.sys new file mode 100644 index 0000000000000000000000000000000000000000..2c7b3558e8f2cb74a22a386a075a753a6d466d48 GIT binary patch literal 32016 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 V_K}_K>JSR$@nxI-=>J&m{{iT8+IRo} literal 0 HcmV?d00001 diff --git a/gui/x64/IOMap64.sys b/gui/x64/IOMap64.sys new file mode 100644 index 0000000000000000000000000000000000000000..12e3176301a9b780f7eff6ff859a0f4ce747fddf GIT binary patch literal 34064 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 OZ1EgBtCP{dMl%4VDxa1B literal 0 HcmV?d00001 diff --git a/gui/x86/AMD Memory Tweak.exe b/gui/x86/AMD Memory Tweak.exe new file mode 100644 index 0000000000000000000000000000000000000000..c83b9b7a7798284170f0b85360c729900926de08 GIT binary patch literal 340992 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