├── LICENSE ├── README.md ├── gui ├── x64 │ ├── AMD Memory Tweak.exe │ ├── IOMap.sys │ └── IOMap64.sys └── x86 │ ├── AMD Memory Tweak.exe │ ├── IOMap.sys │ └── IOMap64.sys ├── linux └── AmdMemTweak.cpp └── win ├── .gitignore ├── EIO.dll ├── IOMap.cpp ├── IOMap.h ├── IOMap.sys ├── IOMap64.sys ├── WinAMDTweak.cpp └── WinAMDTweak.vcproj /LICENSE: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 3, 29 June 2007 3 | 4 | Copyright (C) 2007 Free Software Foundation, Inc. 5 | Everyone is permitted to copy and distribute verbatim copies 6 | of this license document, but changing it is not allowed. 7 | 8 | Preamble 9 | 10 | The GNU General Public License is a free, copyleft license for 11 | software and other kinds of works. 12 | 13 | The licenses for most software and other practical works are designed 14 | to take away your freedom to share and change the works. By contrast, 15 | the GNU General Public License is intended to guarantee your freedom to 16 | share and change all versions of a program--to make sure it remains free 17 | software for all its users. We, the Free Software Foundation, use the 18 | GNU General Public License for most of our software; it applies also to 19 | any other work released this way by its authors. You can apply it to 20 | your programs, too. 21 | 22 | When we speak of free software, we are referring to freedom, not 23 | price. Our General Public Licenses are designed to make sure that you 24 | have the freedom to distribute copies of free software (and charge for 25 | them if you wish), that you receive source code or can get it if you 26 | want it, that you can change the software or use pieces of it in new 27 | free programs, and that you know you can do these things. 28 | 29 | To protect your rights, we need to prevent others from denying you 30 | these rights or asking you to surrender the rights. Therefore, you have 31 | certain responsibilities if you distribute copies of the software, or if 32 | you modify it: responsibilities to respect the freedom of others. 33 | 34 | For example, if you distribute copies of such a program, whether 35 | gratis or for a fee, you must pass on to the recipients the same 36 | freedoms that you received. You must make sure that they, too, receive 37 | or can get the source code. And you must show them these terms so they 38 | know their rights. 39 | 40 | Developers that use the GNU GPL protect your rights with two steps: 41 | (1) assert copyright on the software, and (2) offer you this License 42 | giving you legal permission to copy, distribute and/or modify it. 43 | 44 | For the developers' and authors' protection, the GPL clearly explains 45 | that there is no warranty for this free software. For both users' and 46 | authors' sake, the GPL requires that modified versions be marked as 47 | changed, so that their problems will not be attributed erroneously to 48 | authors of previous versions. 49 | 50 | Some devices are designed to deny users access to install or run 51 | modified versions of the software inside them, although the manufacturer 52 | can do so. This is fundamentally incompatible with the aim of 53 | protecting users' freedom to change the software. The systematic 54 | pattern of such abuse occurs in the area of products for individuals to 55 | use, which is precisely where it is most unacceptable. Therefore, we 56 | have designed this version of the GPL to prohibit the practice for those 57 | products. If such problems arise substantially in other domains, we 58 | stand ready to extend this provision to those domains in future versions 59 | of the GPL, as needed to protect the freedom of users. 60 | 61 | Finally, every program is threatened constantly by software patents. 62 | States should not allow patents to restrict development and use of 63 | software on general-purpose computers, but in those that do, we wish to 64 | avoid the special danger that patents applied to a free program could 65 | make it effectively proprietary. To prevent this, the GPL assures that 66 | patents cannot be used to render the program non-free. 67 | 68 | The precise terms and conditions for copying, distribution and 69 | modification follow. 70 | 71 | TERMS AND CONDITIONS 72 | 73 | 0. Definitions. 74 | 75 | "This License" refers to version 3 of the GNU General Public License. 76 | 77 | "Copyright" also means copyright-like laws that apply to other kinds of 78 | works, such as semiconductor masks. 79 | 80 | "The Program" refers to any copyrightable work licensed under this 81 | License. Each licensee is addressed as "you". "Licensees" and 82 | "recipients" may be individuals or organizations. 83 | 84 | To "modify" a work means to copy from or adapt all or part of the work 85 | in a fashion requiring copyright permission, other than the making of an 86 | exact copy. The resulting work is called a "modified version" of the 87 | earlier work or a work "based on" the earlier work. 88 | 89 | A "covered work" means either the unmodified Program or a work based 90 | on the Program. 91 | 92 | To "propagate" a work means to do anything with it that, without 93 | permission, would make you directly or secondarily liable for 94 | infringement under applicable copyright law, except executing it on a 95 | computer or modifying a private copy. Propagation includes copying, 96 | distribution (with or without modification), making available to the 97 | public, and in some countries other activities as well. 98 | 99 | To "convey" a work means any kind of propagation that enables other 100 | parties to make or receive copies. Mere interaction with a user through 101 | a computer network, with no transfer of a copy, is not conveying. 102 | 103 | An interactive user interface displays "Appropriate Legal Notices" 104 | to the extent that it includes a convenient and prominently visible 105 | feature that (1) displays an appropriate copyright notice, and (2) 106 | tells the user that there is no warranty for the work (except to the 107 | extent that warranties are provided), that licensees may convey the 108 | work under this License, and how to view a copy of this License. If 109 | the interface presents a list of user commands or options, such as a 110 | menu, a prominent item in the list meets this criterion. 111 | 112 | 1. Source Code. 113 | 114 | The "source code" for a work means the preferred form of the work 115 | for making modifications to it. "Object code" means any non-source 116 | form of a work. 117 | 118 | A "Standard Interface" means an interface that either is an official 119 | standard defined by a recognized standards body, or, in the case of 120 | interfaces specified for a particular programming language, one that 121 | is widely used among developers working in that language. 122 | 123 | The "System Libraries" of an executable work include anything, other 124 | than the work as a whole, that (a) is included in the normal form of 125 | packaging a Major Component, but which is not part of that Major 126 | Component, and (b) serves only to enable use of the work with that 127 | Major Component, or to implement a Standard Interface for which an 128 | implementation is available to the public in source code form. A 129 | "Major Component", in this context, means a major essential component 130 | (kernel, window system, and so on) of the specific operating system 131 | (if any) on which the executable work runs, or a compiler used to 132 | produce the work, or an object code interpreter used to run it. 133 | 134 | The "Corresponding Source" for a work in object code form means all 135 | the source code needed to generate, install, and (for an executable 136 | work) run the object code and to modify the work, including scripts to 137 | control those activities. However, it does not include the work's 138 | System Libraries, or general-purpose tools or generally available free 139 | programs which are used unmodified in performing those activities but 140 | which are not part of the work. For example, Corresponding Source 141 | includes interface definition files associated with source files for 142 | the work, and the source code for shared libraries and dynamically 143 | linked subprograms that the work is specifically designed to require, 144 | such as by intimate data communication or control flow between those 145 | subprograms and other parts of the work. 146 | 147 | The Corresponding Source need not include anything that users 148 | can regenerate automatically from other parts of the Corresponding 149 | Source. 150 | 151 | The Corresponding Source for a work in source code form is that 152 | same work. 153 | 154 | 2. Basic Permissions. 155 | 156 | All rights granted under this License are granted for the term of 157 | copyright on the Program, and are irrevocable provided the stated 158 | conditions are met. This License explicitly affirms your unlimited 159 | permission to run the unmodified Program. The output from running a 160 | covered work is covered by this License only if the output, given its 161 | content, constitutes a covered work. This License acknowledges your 162 | rights of fair use or other equivalent, as provided by copyright law. 163 | 164 | You may make, run and propagate covered works that you do not 165 | convey, without conditions so long as your license otherwise remains 166 | in force. You may convey covered works to others for the sole purpose 167 | of having them make modifications exclusively for you, or provide you 168 | with facilities for running those works, provided that you comply with 169 | the terms of this License in conveying all material for which you do 170 | not control copyright. Those thus making or running the covered works 171 | for you must do so exclusively on your behalf, under your direction 172 | and control, on terms that prohibit them from making any copies of 173 | your copyrighted material outside their relationship with you. 174 | 175 | Conveying under any other circumstances is permitted solely under 176 | the conditions stated below. Sublicensing is not allowed; section 10 177 | makes it unnecessary. 178 | 179 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 180 | 181 | No covered work shall be deemed part of an effective technological 182 | measure under any applicable law fulfilling obligations under article 183 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 184 | similar laws prohibiting or restricting circumvention of such 185 | measures. 186 | 187 | When you convey a covered work, you waive any legal power to forbid 188 | circumvention of technological measures to the extent such circumvention 189 | is effected by exercising rights under this License with respect to 190 | the covered work, and you disclaim any intention to limit operation or 191 | modification of the work as a means of enforcing, against the work's 192 | users, your or third parties' legal rights to forbid circumvention of 193 | technological measures. 194 | 195 | 4. Conveying Verbatim Copies. 196 | 197 | You may convey verbatim copies of the Program's source code as you 198 | receive it, in any medium, provided that you conspicuously and 199 | appropriately publish on each copy an appropriate copyright notice; 200 | keep intact all notices stating that this License and any 201 | non-permissive terms added in accord with section 7 apply to the code; 202 | keep intact all notices of the absence of any warranty; and give all 203 | recipients a copy of this License along with the Program. 204 | 205 | You may charge any price or no price for each copy that you convey, 206 | and you may offer support or warranty protection for a fee. 207 | 208 | 5. Conveying Modified Source Versions. 209 | 210 | You may convey a work based on the Program, or the modifications to 211 | produce it from the Program, in the form of source code under the 212 | terms of section 4, provided that you also meet all of these conditions: 213 | 214 | a) The work must carry prominent notices stating that you modified 215 | it, and giving a relevant date. 216 | 217 | b) The work must carry prominent notices stating that it is 218 | released under this License and any conditions added under section 219 | 7. This requirement modifies the requirement in section 4 to 220 | "keep intact all notices". 221 | 222 | c) You must license the entire work, as a whole, under this 223 | License to anyone who comes into possession of a copy. This 224 | License will therefore apply, along with any applicable section 7 225 | additional terms, to the whole of the work, and all its parts, 226 | regardless of how they are packaged. This License gives no 227 | permission to license the work in any other way, but it does not 228 | invalidate such permission if you have separately received it. 229 | 230 | d) If the work has interactive user interfaces, each must display 231 | Appropriate Legal Notices; however, if the Program has interactive 232 | interfaces that do not display Appropriate Legal Notices, your 233 | work need not make them do so. 234 | 235 | A compilation of a covered work with other separate and independent 236 | works, which are not by their nature extensions of the covered work, 237 | and which are not combined with it such as to form a larger program, 238 | in or on a volume of a storage or distribution medium, is called an 239 | "aggregate" if the compilation and its resulting copyright are not 240 | used to limit the access or legal rights of the compilation's users 241 | beyond what the individual works permit. Inclusion of a covered work 242 | in an aggregate does not cause this License to apply to the other 243 | parts of the aggregate. 244 | 245 | 6. Conveying Non-Source Forms. 246 | 247 | You may convey a covered work in object code form under the terms 248 | of sections 4 and 5, provided that you also convey the 249 | machine-readable Corresponding Source under the terms of this License, 250 | in one of these ways: 251 | 252 | a) Convey the object code in, or embodied in, a physical product 253 | (including a physical distribution medium), accompanied by the 254 | Corresponding Source fixed on a durable physical medium 255 | customarily used for software interchange. 256 | 257 | b) Convey the object code in, or embodied in, a physical product 258 | (including a physical distribution medium), accompanied by a 259 | written offer, valid for at least three years and valid for as 260 | long as you offer spare parts or customer support for that product 261 | model, to give anyone who possesses the object code either (1) a 262 | copy of the Corresponding Source for all the software in the 263 | product that is covered by this License, on a durable physical 264 | medium customarily used for software interchange, for a price no 265 | more than your reasonable cost of physically performing this 266 | conveying of source, or (2) access to copy the 267 | Corresponding Source from a network server at no charge. 268 | 269 | c) Convey individual copies of the object code with a copy of the 270 | written offer to provide the Corresponding Source. This 271 | alternative is allowed only occasionally and noncommercially, and 272 | only if you received the object code with such an offer, in accord 273 | with subsection 6b. 274 | 275 | d) Convey the object code by offering access from a designated 276 | place (gratis or for a charge), and offer equivalent access to the 277 | Corresponding Source in the same way through the same place at no 278 | further charge. You need not require recipients to copy the 279 | Corresponding Source along with the object code. If the place to 280 | copy the object code is a network server, the Corresponding Source 281 | may be on a different server (operated by you or a third party) 282 | that supports equivalent copying facilities, provided you maintain 283 | clear directions next to the object code saying where to find the 284 | Corresponding Source. Regardless of what server hosts the 285 | Corresponding Source, you remain obligated to ensure that it is 286 | available for as long as needed to satisfy these requirements. 287 | 288 | e) Convey the object code using peer-to-peer transmission, provided 289 | you inform other peers where the object code and Corresponding 290 | Source of the work are being offered to the general public at no 291 | charge under subsection 6d. 292 | 293 | A separable portion of the object code, whose source code is excluded 294 | from the Corresponding Source as a System Library, need not be 295 | included in conveying the object code work. 296 | 297 | A "User Product" is either (1) a "consumer product", which means any 298 | tangible personal property which is normally used for personal, family, 299 | or household purposes, or (2) anything designed or sold for incorporation 300 | into a dwelling. In determining whether a product is a consumer product, 301 | doubtful cases shall be resolved in favor of coverage. For a particular 302 | product received by a particular user, "normally used" refers to a 303 | typical or common use of that class of product, regardless of the status 304 | of the particular user or of the way in which the particular user 305 | actually uses, or expects or is expected to use, the product. A product 306 | is a consumer product regardless of whether the product has substantial 307 | commercial, industrial or non-consumer uses, unless such uses represent 308 | the only significant mode of use of the product. 309 | 310 | "Installation Information" for a User Product means any methods, 311 | procedures, authorization keys, or other information required to install 312 | and execute modified versions of a covered work in that User Product from 313 | a modified version of its Corresponding Source. The information must 314 | suffice to ensure that the continued functioning of the modified object 315 | code is in no case prevented or interfered with solely because 316 | modification has been made. 317 | 318 | If you convey an object code work under this section in, or with, or 319 | specifically for use in, a User Product, and the conveying occurs as 320 | part of a transaction in which the right of possession and use of the 321 | User Product is transferred to the recipient in perpetuity or for a 322 | fixed term (regardless of how the transaction is characterized), the 323 | Corresponding Source conveyed under this section must be accompanied 324 | by the Installation Information. But this requirement does not apply 325 | if neither you nor any third party retains the ability to install 326 | modified object code on the User Product (for example, the work has 327 | been installed in ROM). 328 | 329 | The requirement to provide Installation Information does not include a 330 | requirement to continue to provide support service, warranty, or updates 331 | for a work that has been modified or installed by the recipient, or for 332 | the User Product in which it has been modified or installed. Access to a 333 | network may be denied when the modification itself materially and 334 | adversely affects the operation of the network or violates the rules and 335 | protocols for communication across the network. 336 | 337 | Corresponding Source conveyed, and Installation Information provided, 338 | in accord with this section must be in a format that is publicly 339 | documented (and with an implementation available to the public in 340 | source code form), and must require no special password or key for 341 | unpacking, reading or copying. 342 | 343 | 7. Additional Terms. 344 | 345 | "Additional permissions" are terms that supplement the terms of this 346 | License by making exceptions from one or more of its conditions. 347 | Additional permissions that are applicable to the entire Program shall 348 | be treated as though they were included in this License, to the extent 349 | that they are valid under applicable law. If additional permissions 350 | apply only to part of the Program, that part may be used separately 351 | under those permissions, but the entire Program remains governed by 352 | this License without regard to the additional permissions. 353 | 354 | When you convey a copy of a covered work, you may at your option 355 | remove any additional permissions from that copy, or from any part of 356 | it. (Additional permissions may be written to require their own 357 | removal in certain cases when you modify the work.) You may place 358 | additional permissions on material, added by you to a covered work, 359 | for which you have or can give appropriate copyright permission. 360 | 361 | Notwithstanding any other provision of this License, for material you 362 | add to a covered work, you may (if authorized by the copyright holders of 363 | that material) supplement the terms of this License with terms: 364 | 365 | a) Disclaiming warranty or limiting liability differently from the 366 | terms of sections 15 and 16 of this License; or 367 | 368 | b) Requiring preservation of specified reasonable legal notices or 369 | author attributions in that material or in the Appropriate Legal 370 | Notices displayed by works containing it; or 371 | 372 | c) Prohibiting misrepresentation of the origin of that material, or 373 | requiring that modified versions of such material be marked in 374 | reasonable ways as different from the original version; or 375 | 376 | d) Limiting the use for publicity purposes of names of licensors or 377 | authors of the material; or 378 | 379 | e) Declining to grant rights under trademark law for use of some 380 | trade names, trademarks, or service marks; or 381 | 382 | f) Requiring indemnification of licensors and authors of that 383 | material by anyone who conveys the material (or modified versions of 384 | it) with contractual assumptions of liability to the recipient, for 385 | any liability that these contractual assumptions directly impose on 386 | those licensors and authors. 387 | 388 | All other non-permissive additional terms are considered "further 389 | restrictions" within the meaning of section 10. If the Program as you 390 | received it, or any part of it, contains a notice stating that it is 391 | governed by this License along with a term that is a further 392 | restriction, you may remove that term. If a license document contains 393 | a further restriction but permits relicensing or conveying under this 394 | License, you may add to a covered work material governed by the terms 395 | of that license document, provided that the further restriction does 396 | not survive such relicensing or conveying. 397 | 398 | If you add terms to a covered work in accord with this section, you 399 | must place, in the relevant source files, a statement of the 400 | additional terms that apply to those files, or a notice indicating 401 | where to find the applicable terms. 402 | 403 | Additional terms, permissive or non-permissive, may be stated in the 404 | form of a separately written license, or stated as exceptions; 405 | the above requirements apply either way. 406 | 407 | 8. Termination. 408 | 409 | You may not propagate or modify a covered work except as expressly 410 | provided under this License. Any attempt otherwise to propagate or 411 | modify it is void, and will automatically terminate your rights under 412 | this License (including any patent licenses granted under the third 413 | paragraph of section 11). 414 | 415 | However, if you cease all violation of this License, then your 416 | license from a particular copyright holder is reinstated (a) 417 | provisionally, unless and until the copyright holder explicitly and 418 | finally terminates your license, and (b) permanently, if the copyright 419 | holder fails to notify you of the violation by some reasonable means 420 | prior to 60 days after the cessation. 421 | 422 | Moreover, your license from a particular copyright holder is 423 | reinstated permanently if the copyright holder notifies you of the 424 | violation by some reasonable means, this is the first time you have 425 | received notice of violation of this License (for any work) from that 426 | copyright holder, and you cure the violation prior to 30 days after 427 | your receipt of the notice. 428 | 429 | Termination of your rights under this section does not terminate the 430 | licenses of parties who have received copies or rights from you under 431 | this License. If your rights have been terminated and not permanently 432 | reinstated, you do not qualify to receive new licenses for the same 433 | material under section 10. 434 | 435 | 9. Acceptance Not Required for Having Copies. 436 | 437 | You are not required to accept this License in order to receive or 438 | run a copy of the Program. Ancillary propagation of a covered work 439 | occurring solely as a consequence of using peer-to-peer transmission 440 | to receive a copy likewise does not require acceptance. However, 441 | nothing other than this License grants you permission to propagate or 442 | modify any covered work. These actions infringe copyright if you do 443 | not accept this License. Therefore, by modifying or propagating a 444 | covered work, you indicate your acceptance of this License to do so. 445 | 446 | 10. Automatic Licensing of Downstream Recipients. 447 | 448 | Each time you convey a covered work, the recipient automatically 449 | receives a license from the original licensors, to run, modify and 450 | propagate that work, subject to this License. You are not responsible 451 | for enforcing compliance by third parties with this License. 452 | 453 | An "entity transaction" is a transaction transferring control of an 454 | organization, or substantially all assets of one, or subdividing an 455 | organization, or merging organizations. If propagation of a covered 456 | work results from an entity transaction, each party to that 457 | transaction who receives a copy of the work also receives whatever 458 | licenses to the work the party's predecessor in interest had or could 459 | give under the previous paragraph, plus a right to possession of the 460 | Corresponding Source of the work from the predecessor in interest, if 461 | the predecessor has it or can get it with reasonable efforts. 462 | 463 | You may not impose any further restrictions on the exercise of the 464 | rights granted or affirmed under this License. For example, you may 465 | not impose a license fee, royalty, or other charge for exercise of 466 | rights granted under this License, and you may not initiate litigation 467 | (including a cross-claim or counterclaim in a lawsuit) alleging that 468 | any patent claim is infringed by making, using, selling, offering for 469 | sale, or importing the Program or any portion of it. 470 | 471 | 11. Patents. 472 | 473 | A "contributor" is a copyright holder who authorizes use under this 474 | License of the Program or a work on which the Program is based. The 475 | work thus licensed is called the contributor's "contributor version". 476 | 477 | A contributor's "essential patent claims" are all patent claims 478 | owned or controlled by the contributor, whether already acquired or 479 | hereafter acquired, that would be infringed by some manner, permitted 480 | by this License, of making, using, or selling its contributor version, 481 | but do not include claims that would be infringed only as a 482 | consequence of further modification of the contributor version. For 483 | purposes of this definition, "control" includes the right to grant 484 | patent sublicenses in a manner consistent with the requirements of 485 | this License. 486 | 487 | Each contributor grants you a non-exclusive, worldwide, royalty-free 488 | patent license under the contributor's essential patent claims, to 489 | make, use, sell, offer for sale, import and otherwise run, modify and 490 | propagate the contents of its contributor version. 491 | 492 | In the following three paragraphs, a "patent license" is any express 493 | agreement or commitment, however denominated, not to enforce a patent 494 | (such as an express permission to practice a patent or covenant not to 495 | sue for patent infringement). To "grant" such a patent license to a 496 | party means to make such an agreement or commitment not to enforce a 497 | patent against the party. 498 | 499 | If you convey a covered work, knowingly relying on a patent license, 500 | and the Corresponding Source of the work is not available for anyone 501 | to copy, free of charge and under the terms of this License, through a 502 | publicly available network server or other readily accessible means, 503 | then you must either (1) cause the Corresponding Source to be so 504 | available, or (2) arrange to deprive yourself of the benefit of the 505 | patent license for this particular work, or (3) arrange, in a manner 506 | consistent with the requirements of this License, to extend the patent 507 | license to downstream recipients. "Knowingly relying" means you have 508 | actual knowledge that, but for the patent license, your conveying the 509 | covered work in a country, or your recipient's use of the covered work 510 | in a country, would infringe one or more identifiable patents in that 511 | country that you have reason to believe are valid. 512 | 513 | If, pursuant to or in connection with a single transaction or 514 | arrangement, you convey, or propagate by procuring conveyance of, a 515 | covered work, and grant a patent license to some of the parties 516 | receiving the covered work authorizing them to use, propagate, modify 517 | or convey a specific copy of the covered work, then the patent license 518 | you grant is automatically extended to all recipients of the covered 519 | work and works based on it. 520 | 521 | A patent license is "discriminatory" if it does not include within 522 | the scope of its coverage, prohibits the exercise of, or is 523 | conditioned on the non-exercise of one or more of the rights that are 524 | specifically granted under this License. You may not convey a covered 525 | work if you are a party to an arrangement with a third party that is 526 | in the business of distributing software, under which you make payment 527 | to the third party based on the extent of your activity of conveying 528 | the work, and under which the third party grants, to any of the 529 | parties who would receive the covered work from you, a discriminatory 530 | patent license (a) in connection with copies of the covered work 531 | conveyed by you (or copies made from those copies), or (b) primarily 532 | for and in connection with specific products or compilations that 533 | contain the covered work, unless you entered into that arrangement, 534 | or that patent license was granted, prior to 28 March 2007. 535 | 536 | Nothing in this License shall be construed as excluding or limiting 537 | any implied license or other defenses to infringement that may 538 | otherwise be available to you under applicable patent law. 539 | 540 | 12. No Surrender of Others' Freedom. 541 | 542 | If conditions are imposed on you (whether by court order, agreement or 543 | otherwise) that contradict the conditions of this License, they do not 544 | excuse you from the conditions of this License. If you cannot convey a 545 | covered work so as to satisfy simultaneously your obligations under this 546 | License and any other pertinent obligations, then as a consequence you may 547 | not convey it at all. For example, if you agree to terms that obligate you 548 | to collect a royalty for further conveying from those to whom you convey 549 | the Program, the only way you could satisfy both those terms and this 550 | License would be to refrain entirely from conveying the Program. 551 | 552 | 13. Use with the GNU Affero General Public License. 553 | 554 | Notwithstanding any other provision of this License, you have 555 | permission to link or combine any covered work with a work licensed 556 | under version 3 of the GNU Affero General Public License into a single 557 | combined work, and to convey the resulting work. The terms of this 558 | License will continue to apply to the part which is the covered work, 559 | but the special requirements of the GNU Affero General Public License, 560 | section 13, concerning interaction through a network will apply to the 561 | combination as such. 562 | 563 | 14. Revised Versions of this License. 564 | 565 | The Free Software Foundation may publish revised and/or new versions of 566 | the GNU General Public License from time to time. Such new versions will 567 | be similar in spirit to the present version, but may differ in detail to 568 | address new problems or concerns. 569 | 570 | Each version is given a distinguishing version number. If the 571 | Program specifies that a certain numbered version of the GNU General 572 | Public License "or any later version" applies to it, you have the 573 | option of following the terms and conditions either of that numbered 574 | version or of any later version published by the Free Software 575 | Foundation. If the Program does not specify a version number of the 576 | GNU General Public License, you may choose any version ever published 577 | by the Free Software Foundation. 578 | 579 | If the Program specifies that a proxy can decide which future 580 | versions of the GNU General Public License can be used, that proxy's 581 | public statement of acceptance of a version permanently authorizes you 582 | to choose that version for the Program. 583 | 584 | Later license versions may give you additional or different 585 | permissions. However, no additional obligations are imposed on any 586 | author or copyright holder as a result of your choosing to follow a 587 | later version. 588 | 589 | 15. Disclaimer of Warranty. 590 | 591 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 592 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 593 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 594 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 595 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 596 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 597 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 598 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 599 | 600 | 16. Limitation of Liability. 601 | 602 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 603 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 604 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 605 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 606 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 607 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 608 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 609 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 610 | SUCH DAMAGES. 611 | 612 | 17. Interpretation of Sections 15 and 16. 613 | 614 | If the disclaimer of warranty and limitation of liability provided 615 | above cannot be given local legal effect according to their terms, 616 | reviewing courts shall apply local law that most closely approximates 617 | an absolute waiver of all civil liability in connection with the 618 | Program, unless a warranty or assumption of liability accompanies a 619 | copy of the Program in return for a fee. 620 | 621 | END OF TERMS AND CONDITIONS 622 | 623 | How to Apply These Terms to Your New Programs 624 | 625 | If you develop a new program, and you want it to be of the greatest 626 | possible use to the public, the best way to achieve this is to make it 627 | free software which everyone can redistribute and change under these terms. 628 | 629 | To do so, attach the following notices to the program. It is safest 630 | to attach them to the start of each source file to most effectively 631 | state the exclusion of warranty; and each file should have at least 632 | the "copyright" line and a pointer to where the full notice is found. 633 | 634 | 635 | Copyright (C) 636 | 637 | This program is free software: you can redistribute it and/or modify 638 | it under the terms of the GNU General Public License as published by 639 | the Free Software Foundation, either version 3 of the License, or 640 | (at your option) any later version. 641 | 642 | This program is distributed in the hope that it will be useful, 643 | but WITHOUT ANY WARRANTY; without even the implied warranty of 644 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 645 | GNU General Public License for more details. 646 | 647 | You should have received a copy of the GNU General Public License 648 | along with this program. If not, see . 649 | 650 | Also add information on how to contact you by electronic and paper mail. 651 | 652 | If the program does terminal interaction, make it output a short 653 | notice like this when it starts in an interactive mode: 654 | 655 | Copyright (C) 656 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 657 | This is free software, and you are welcome to redistribute it 658 | under certain conditions; type `show c' for details. 659 | 660 | The hypothetical commands `show w' and `show c' should show the appropriate 661 | parts of the General Public License. Of course, your program's commands 662 | might be different; for a GUI interface, you would use an "about box". 663 | 664 | You should also get your employer (if you work as a programmer) or school, 665 | if any, to sign a "copyright disclaimer" for the program, if necessary. 666 | For more information on this, and how to apply and follow the GNU GPL, see 667 | . 668 | 669 | The GNU General Public License does not permit incorporating your program 670 | into proprietary programs. If your program is a subroutine library, you 671 | may consider it more useful to permit linking proprietary applications with 672 | the library. If this is what you want to do, use the GNU Lesser General 673 | Public License instead of this License. But first, please read 674 | . 675 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AMD Memory Tweak 2 | --- 3 | #### Read and modify memory timings "on the fly" 4 | --- 5 | 6 | # Please be cautious, this --> https://github.com/ELI0VP <-- is obviously a fake account and is most probably spreading spyware/viruses, etc.. 7 | 8 | # AMD Memory Tweak XL Released! 9 | [Link](https://github.com/Eliovp/AMDMemoryTweakXL) 10 | 11 | ### Support 12 | 13 | - GDDR5 Based AMD GPU's 14 | - HBM / HBM2 Based AMD GPU's 15 | - Linux 16 | - Windows (Beta) 17 | 18 | # Requirements 19 | 20 | - One or more AMD Radeon GPU's 21 | - amdgpu-pro | ROCM (Verified working on amdgpu-pro 18.30) 22 | - Adrenaline (Verified working on v19.4.1/v19.5.*) 23 | 24 | # Build (Linux) 25 | Prerequisites: 26 | - [pciutils-dev](https://pkgs.org/download/pciutils-dev) | [libpci-dev](https://pkgs.org/download/libpci-dev) 27 | - [build-essential](https://pkgs.org/download/build-essential) 28 | - [git]() 29 | 30 | Building: 31 | ```sh 32 | $ git clone https://github.com/Eliovp/amdmemorytweak 33 | $ cd amdmemorytweak/linux 34 | $ g++ AmdMemTweak.cpp -lpci -lresolv -o amdmemtweak 35 | ``` 36 | 37 | # Build (Windows) 38 | - Clone repo 39 | - Launch VS Project 40 | - Build! 41 | 42 | # Usage & Instructions 43 | 44 | ##### Global command line options 45 | ## 46 | 47 | | Command | User Input | Extra Info | 48 | | ------ | ------ | ------ | 49 | | - -help | | Show this output | 50 | | - -version\|--v | | Show version info | 51 | | - -gpu\|- -i | Comma-Seperated gpu indices | Selected device(s) | 52 | | - -current | | List current twiming values | 53 | 54 | ##### Command line options: (HBM2) 55 | ## 56 | | Command | User Input | Extra Info | 57 | | ------ | ------ | ------ | 58 | | - -CL\|- -cl | [value] | Cas Latency | 59 | | - -RAS\|- -ras | [value] | Active to PRECHARGE command period | 60 | | - -RCDRD\|- -rcdrd | [value] | Active to READ command delay | 61 | | - -RCDWR\|- -rcdwr | [value] | Active to WRITE command delay | 62 | | - -RC\|- -rc | [value] | Active to Active command period | 63 | | - -RP\|- -rp | [value] | Precharge command period | 64 | | - -RRDS\|- -rrds | [value] | Active bank A to Active or Single bank Refresh bank B command delay different bank group | 65 | | - -RRDL\|- -rrdl | [value] | Active bank A to Active or Single Bank Refresh bank B command delay same bank group | 66 | | - -RTP\|- -rtp | [value] | Read to precharge delay | 67 | | - -FAW\|- -faw | [value] | Four Active Window | 68 | | - -CWL\|- -cwl | [value] | | 69 | | - -WTRS\|- -wtrs | [value] | Write to read delay | 70 | | - -WTRL\|- -wtrl | [value] | tWTR = tWTRL when bank groups is enabled and both WRITE and READ | 71 | | - -WR\|- -wr | [value] | Write Recovery Time | 72 | | - -RREFD\|- -rrefd | [value] | | 73 | | - -RDRDDD\|- -rdrddd | [value] | | 74 | | - -RDRDSD\|- -rdrdsd | [value] | | 75 | | - -RDRDSC\|- -rdrdsc | [value] | | 76 | | - -RDRDSCL\|- -rdrdscl | [value] | | 77 | | - -WRWRDD\|- -wrwrdd | [value] | | 78 | | - -WRWRSD\|- -wrwrsd | [value] | | 79 | | - -WRWRSC\|- -wrwrsc | [value] | | 80 | | - -WRWRSCL\|- -wrwrscl | [value] | | 81 | | - -WRRD\|- -wrrd | [value] | | 82 | | - -RDWR\|- -rdwr | [value] | | 83 | | - -REF\|- -ref | [value] | Average Periodic Refresh Interval | 84 | | - -MRD\|- -mrd | [value] | Mode Register Set command cycle time | 85 | | - -MOD\|- -mod | [value] | Mode Register Set command update delay | 86 | | - -XS\|- -xs | [value] | Self refresh exit period | 87 | | - -XSMRS\|- -xsmrs | [value] | | 88 | | - -PD\|- -pd | [value] | Power down entry to exit time | 89 | | - -CKSRE\|- -cksre | [value] | Valid CK Clock required after self refresh or power-down entry | 90 | | - -CKSRX\|- -cksrx | [value] | Valid CK Clock required before self refresh power down exit | 91 | | - -RFCPB\|- -rfcpb | [value] | | 92 | | - -STAG\|- -stag | [value] | | 93 | | - -XP\|- -xp | [value] | | 94 | | - -CPDED\|- -cpded | [value] | | 95 | | - -CKE\|- -cke | [value] | | 96 | | - -RDDATA\|- -rddata | [value] | | 97 | | - -WRLAT\|- -wrlat | [value] | | 98 | | - -RDLAT\|- -rdlat | [value] | | 99 | | - -WRDATA\|- -wrdata | [value] | | 100 | | - -CKESTAG\|- -ckestag | [value] | | 101 | | - -RFC\|- -rfc | [value] | Auto Refresh Row Cycle Time | 102 | 103 | ##### Command line options: (HBM) 104 | ## 105 | | Command | User Input | Extra Info | 106 | | ------ | ------ | ------ | 107 | | - -CKSRE\|- -cksre | [value] | | 108 | | - -CKSRX\|- -cksrx | [value] | | 109 | | - -CKE_PULSE\|- -cke_pulse | [value] | | 110 | | - -CKE\|- -cke | [value] | | 111 | | - -SEQ_IDLE\|- -seq_idle | [value] | | 112 | | - -CL\|- -cl | [value] | CAS to data return latency | 113 | | - -W2R\|- -w2r | [value] | Write to read turn | 114 | | - -R2R\|- -r2r | [value] | Read to read time | 115 | | - -CCDL\|- -ccdl | [value] | Cycles between r/w from bank A to r/w bank B | 116 | | - -R2W\|- -r2w | [value] | Read to write turn | 117 | | - -NOPR\|- -nopr | [value] | Extra cycle(s) between successive read bursts | 118 | | - -NOPW\|- -nopw | [value] | Extra cycle(s) between successive write bursts | 119 | | - -RCDW\|- -rcdw | [value] | # of cycles from active to write | 120 | | - -RCDWA\|- -rcdwa | [value] | # of cycles from active to write with auto-precharge | 121 | | - -RCDR\|- -rcdr | [value] | # of cycles from active to read | 122 | | - -RCDRA\|- -rcdra | [value] | # of cycles from active to read with auto-precharge | 123 | | - -RRD\|- -rrd | [value] | # of cycles from active bank a to active bank b | 124 | | - -RC\|- -rc | [value] | # of cycles from active to active/auto refresh | 125 | | - -MRD\|- -mrd | [value] | | 126 | | - -RRDL\|- -rrdl | [value] | | 127 | | - -RFC\|- -rfc | [value] | Auto-refresh command period | 128 | | - -TRP\|- -trp | [value] | Precharge command period | 129 | | - -RP_WRA\|- -rp_wra | [value] | From write with auto-precharge to active | 130 | | - -RP_RDA\|- -rp_rda | [value] | From read with auto-precharge to active | 131 | | - -WDATATR\|- -wdatatr | [value] | | 132 | | - -T32AW\|- -t32aw | [value] | | 133 | | - -CRCWL\|- -crcwl | [value] | | 134 | | - -CRCRL\|- -crcrl | [value] | | 135 | | - -FAW\|- -faw | [value] | | 136 | | - -PA2WDATA\|- -pa2wdata | [value] | | 137 | | - -PA2RDATA\|- -pa2rdata | [value] | | 138 | | - -REF\|- -ref | [value] | Refresh Rate | 139 | | - -ENB\|- -enb | [value] | | 140 | | - -CNT\|- -cnt | [value] | | 141 | | - -TRC\|- -trc | [value] | | 142 | 143 | ##### Command line options: (GDDR5) 144 | ## 145 | | Command | User Input | Extra Info | 146 | | ------ | ------ | ------ | 147 | | - -CKSRE\|- -cksre | [value] | | 148 | | - -CKSRX\|- -cksrx | [value] | | 149 | | - -CKE_PULSE\|- -cke_pulse | [value] | | 150 | | - -CKE\|- -cke | [value] | | 151 | | - -SEQ_IDLE\|- -seq_idle | [value] | | 152 | | - -CL\|- -cl | [value] | CAS to data return latency | 153 | | - -W2R\|- -w2r | [value] | Write to read turn | 154 | | - -R2R\|- -r2r | [value] | Read to read time | 155 | | - -CCDL\|- -ccdl | [value] | Cycles between r/w from bank A to r/w bank B | 156 | | - -R2W\|- -r2w | [value] | Read to write turn | 157 | | - -NOPR\|- -nopr | [value] | Extra cycle(s) between successive read bursts | 158 | | - -NOPW\|- -nopw | [value] | Extra cycle(s) between successive write bursts | 159 | | - -RCDW\|- -rcdw | [value] | # of cycles from active to write | 160 | | - -RCDWA\|- -rcdwa | [value] | # of cycles from active to write with auto-precharge | 161 | | - -RCDR\|- -rcdr | [value] | # of cycles from active to read | 162 | | - -RCDRA\|- -rcdra | [value] | # of cycles from active to read with auto-precharge | 163 | | - -RRD\|- -rrd | [value] | # of cycles from active bank a to active bank b | 164 | | - -RC\|- -rc | [value] | # of cycles from active to active/auto refresh | 165 | | - -RFC\|- -rfc | [value] | Auto-refresh command period | 166 | | - -TRP\|- -trp | [value] | Precharge command period | 167 | | - -RP_WRA\|- -rp_wra | [value] | From write with auto-precharge to active | 168 | | - -RP_RDA\|- -rp_rda | [value] | From read with auto-precharge to active | 169 | | - -WDATATR\|- -wdatatr | [value] | | 170 | | - -T32AW\|- -t32aw | [value] | | 171 | | - -CRCWL\|- -crcwl | [value] | | 172 | | - -CRCRL\|- -crcrl | [value] | | 173 | | - -FAW\|- -faw | [value] | | 174 | | - -PA2WDATA\|- -pa2wdata | [value] | | 175 | | - -PA2RDATA\|- -pa2rdata | [value] | | 176 | | - -RAS\|- -ras | [value] | | 177 | | - -ACTRD\|- -actrd | [value] | | 178 | | - -ACTWR\|- -actwr | [value] | | 179 | | - -RASMACTRD\|- -rasmactrd | [value] | | 180 | | - -RASMACWTR\|- -rasmacwtr | [value] | | 181 | | - -RAS2RAS\|- -ras2ras | [value] | | 182 | | - -RP\|- -rp | [value] | | 183 | | - -WRPLUSRP\|- -wrplusrp | [value] | | 184 | | - -BUS_TURN\|- -bus_turn | [value] | | 185 | | - -REF\|- -ref | [value] | Refresh Rate | 186 | 187 | ##### Example Usage (Linux): 188 | ## 189 | ```sh 190 | $ sudo ./amdmemtool --i 0,3,5 --faw 100 --RFC 100 191 | ``` 192 | 193 | ##### Example Usage (Windows): 194 | ## 195 | C:\Users\You\Desktop\WinAMDTweak.exe --i 1,2,4 --rfc 100 --RC 100 196 | 197 | (These are just examples! Don't try these at home! :p) 198 | 199 | Make sure to run the program first with parameter --current to see what the current values are. 200 | Current values may change based on state of the GPU, 201 | in other words, make sure the GPU is under load when running --current. 202 | HBM2 Based GPU's do not need to be under load to apply timing changes. 203 | It is often better to apply new timings before starting a benchmark/mining tool. 204 | 205 | Hints: 206 | Some timings are stability timings, lowering these will lower stability. Such as tRC. 207 | Some timings might require a higher value for performance to improve. Such as tREF. 208 | Some timings have a min/max value, going outside this range will result into it defaulting back to original value. Such as tCL 209 | Some timings are dynamic, they change based on the vbios values and active clocks. Dram timings. 210 | ... 211 | 212 | Row Access Timings tRC, tRAS, tRCDRD, tRCDWR, tRRDL, tRRDS, tFAW, tRTP 213 | Column Access Timings tCCDL, tCCDS, tCCDR, tWTRL, tWTRS, tRTW, 214 | Refresh Timings tRFC, tRFCSB, tRREFD, tREFI 215 | 216 | ## Some extra info 217 | Still not all possible timings have been exposed. 218 | However, it's not such a big deal to add more of them in the tool. 219 | The ones available are more or like the most important ones. 220 | 221 | Some users have reported very nice results already, please continue to contribute to these results. 222 | [Example](https://bitcointalk.org/index.php?topic=5123724) 223 | 224 | Have fun! 225 | 226 | Cheers 227 | 228 | 229 | ## Tips 230 | - 3GBgapb49BZ7fBPXnbetqbnMn2KiGNzUXf 231 | - 0x8C77C212da3e12cad1AfB8824CF74b1CC04d2F7C 232 | 233 | > In the unlikely event of not owning either BTC or ETH and you do want to be an amazing person and tip, 234 | > shapeshift, changelly, simpleswap, ... are great ways to solve that "issue" ;-) 235 | 236 | ### Todos 237 | 238 | - Nothing 239 | 240 | License 241 | ---- 242 | 243 | ##### GPL 244 | -------------------------------------------------------------------------------- /gui/x64/AMD Memory Tweak.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x64/AMD Memory Tweak.exe -------------------------------------------------------------------------------- /gui/x64/IOMap.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x64/IOMap.sys -------------------------------------------------------------------------------- /gui/x64/IOMap64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x64/IOMap64.sys -------------------------------------------------------------------------------- /gui/x86/AMD Memory Tweak.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x86/AMD Memory Tweak.exe -------------------------------------------------------------------------------- /gui/x86/IOMap.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x86/IOMap.sys -------------------------------------------------------------------------------- /gui/x86/IOMap64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/gui/x86/IOMap64.sys -------------------------------------------------------------------------------- /win/.gitignore: -------------------------------------------------------------------------------- 1 | # Ignore the files and directories generated by VisualStudio. 2 | /Debug 3 | /Release 4 | /x64 5 | *.ncb 6 | *.suo 7 | *.user 8 | -------------------------------------------------------------------------------- /win/EIO.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/win/EIO.dll -------------------------------------------------------------------------------- /win/IOMap.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | AMD Memory Tweak by 3 | Elio VP 4 | A. Solodovnikov 5 | Copyright (c) 2019 Eliovp, BVBA. All rights reserved. 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute and/or sublicense 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 19 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 20 | THE SOFTWARE. 21 | */ 22 | 23 | #define WIN32_LEAN_AND_MEAN 24 | #define _CRT_SECURE_NO_WARNINGS 25 | #include 26 | #include 27 | #include 28 | #include "IOMap.h" 29 | 30 | typedef struct { 31 | WORD adapterIndex; 32 | WORD field_2; 33 | WORD field_4; 34 | char pad1[2]; 35 | DWORD field_8; 36 | char pad2[8]; 37 | WORD field_14; 38 | WORD field_16; 39 | WORD field_18; // 0 Byte, 1 Word, 2 Dword 40 | char pad3[6]; 41 | DWORD mmioRegister; 42 | DWORD field_24; 43 | char pad4[8]; 44 | } Ioctl_83002138_In; 45 | C_ASSERT(sizeof(Ioctl_83002138_In) == 0x30); 46 | 47 | typedef struct { 48 | char pad1[4]; 49 | DWORD field_4; 50 | char pad2[4]; 51 | } Ioctl_83002138_Out; 52 | C_ASSERT(sizeof(Ioctl_83002138_Out) == 0xC); 53 | 54 | SC_HANDLE hManager = NULL; 55 | SC_HANDLE hService = NULL; 56 | HANDLE g_hDevice = INVALID_HANDLE_VALUE; 57 | 58 | // Unloading is being a b*tch, revert to EIO to load/unload driver 59 | 60 | //void LoadDriver() 61 | //{ 62 | // hManager = OpenSCManagerA(NULL, NULL, SC_MANAGER_CONNECT | SC_MANAGER_CREATE_SERVICE); 63 | // if (!hManager) 64 | // { 65 | // printf("OpenSCManager() failed with error %u\n", GetLastError()); 66 | // exit(EXIT_FAILURE); 67 | // } 68 | // 69 | // hService = OpenServiceA(hManager, "IOMap", SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE); 70 | // if (!hService) 71 | // { 72 | // DWORD errorCode = GetLastError(); 73 | // if (errorCode == ERROR_SERVICE_DOES_NOT_EXIST) 74 | // { 75 | // char path[MAX_PATH]; 76 | // GetModuleFileNameA(NULL, path, sizeof(path)); 77 | // *strrchr(path, '\\') = '\0'; 78 | // bool is64bit; 79 | //#ifdef _WIN64 80 | // is64bit = true; 81 | //#else 82 | // BOOL isWow64; 83 | // if (!IsWow64Process(GetCurrentProcess(), &isWow64)) 84 | // { 85 | // printf("IsWow64Process() failed with error %u\n", GetLastError()); 86 | // exit(EXIT_FAILURE); 87 | // } 88 | // is64bit = (isWow64 == TRUE); 89 | //#endif 90 | // strcat(path, (is64bit ? "\\IOMap64.sys" : "\\IOMap.sys")); 91 | // hService = CreateServiceA(hManager, "IOMap", "IOMap", SERVICE_QUERY_STATUS | SERVICE_START | SERVICE_STOP | DELETE, SERVICE_KERNEL_DRIVER, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, path, NULL, NULL, NULL, NULL, NULL); 92 | // if (!hService) 93 | // { 94 | // printf("CreateService() failed with error %u\n", GetLastError()); 95 | // exit(EXIT_FAILURE); 96 | // } 97 | // } 98 | // else 99 | // { 100 | // printf("OpenService() failed with error %u\n", errorCode); 101 | // exit(EXIT_FAILURE); 102 | // } 103 | // } 104 | // 105 | // SERVICE_STATUS status; 106 | // if (!QueryServiceStatus(hService, &status)) 107 | // { 108 | // printf("QueryServiceStatus() failed with error %u\n", GetLastError()); 109 | // exit(EXIT_FAILURE); 110 | // } 111 | // 112 | // const char* StateNames[] = { "", "SERVICE_STOPPED", "SERVICE_START_PENDING", "SERVICE_STOP_PENDING", "SERVICE_RUNNING", "SERVICE_CONTINUE_PENDING", "SERVICE_PAUSE_PENDING", "SERVICE_PAUSED", }; 113 | //// printf("IOMap status: %s\n", StateNames[status.dwCurrentState]); 114 | // 115 | // if (status.dwCurrentState == SERVICE_RUNNING) 116 | // { 117 | // // already running 118 | // } 119 | // else if (status.dwCurrentState == SERVICE_STOPPED) 120 | // { 121 | // if (!StartServiceA(hService, 0, NULL)) 122 | // { 123 | // printf("StartService() failed with error %u\n", GetLastError()); 124 | // exit(EXIT_FAILURE); 125 | // } 126 | // do 127 | // { 128 | // Sleep(1); 129 | // } while (QueryServiceStatus(hService, &status) && (status.dwCurrentState == SERVICE_START_PENDING)); 130 | //// printf("IOMap status: %s\n", StateNames[status.dwCurrentState]); 131 | // } 132 | // else 133 | // { 134 | // printf("Unexpected driver state: %s\n", StateNames[status.dwCurrentState]); 135 | // exit(EXIT_FAILURE); 136 | // } 137 | // 138 | // g_hDevice = CreateFileA("\\\\.\\IOMap", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 139 | // if (g_hDevice == INVALID_HANDLE_VALUE) 140 | // { 141 | // printf("Failed to open IOMap device with error %u\n", GetLastError()); 142 | // exit(EXIT_FAILURE); 143 | // } 144 | //} 145 | // 146 | //void __cdecl UnloadDriver(void) 147 | //{ 148 | // if (g_hDevice != INVALID_HANDLE_VALUE) 149 | // { 150 | // CloseHandle(g_hDevice); 151 | // } 152 | // if (hService) 153 | // { 154 | // SERVICE_STATUS status; 155 | // if (!ControlService(hService, SERVICE_CONTROL_STOP, &status)) 156 | // { 157 | // printf("ControlService() failed with error %u\n", GetLastError()); 158 | // } 159 | // else 160 | // { 161 | // do 162 | // { 163 | // Sleep(1); 164 | // } while (QueryServiceStatus(hService, &status) && (status.dwCurrentState == SERVICE_STOP_PENDING)); 165 | // } 166 | // if (!DeleteService(hService)) 167 | // { 168 | // DWORD errorCode = GetLastError(); 169 | // if (errorCode != ERROR_SERVICE_MARKED_FOR_DELETE) 170 | // { 171 | // printf("DeleteService() failed with error %u\n", GetLastError()); 172 | // } 173 | // } 174 | // CloseServiceHandle(hService); 175 | // } 176 | // if (hManager) 177 | // { 178 | // CloseServiceHandle(hManager); 179 | // } 180 | //} 181 | 182 | static WORD sub_100037C4(DWORD InBuffer) 183 | { 184 | WORD OutBuffer; 185 | DWORD BytesReturned; 186 | 187 | DeviceIoControl(g_hDevice, 0x8300210C, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 188 | return OutBuffer; 189 | } 190 | static BOOL sub_1000334B(VGAChip *chip) 191 | { 192 | DWORD InBuffer[5]; 193 | char OutBuffer[20]; 194 | DWORD BytesReturned; 195 | 196 | memcpy(InBuffer, chip, 8); 197 | InBuffer[2] = 0xC0000; 198 | DeviceIoControl(g_hDevice, 0x83002104, InBuffer, sizeof(InBuffer), OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 199 | return (sub_100037C4(0) == 0xAA55); 200 | } 201 | int EnumerateGPUs(DWORD vendorId, VGAChip *OutBuffer, DWORD OutBufferSize) 202 | { 203 | DWORD BytesReturned; 204 | DeviceIoControl(g_hDevice, 0x830020D4, &vendorId, sizeof(vendorId), OutBuffer, OutBufferSize, &BytesReturned, NULL); 205 | int count = BytesReturned / sizeof(VGAChip); 206 | if (count > 0) 207 | { 208 | sub_1000334B(OutBuffer); 209 | } 210 | return count; 211 | } 212 | 213 | int GetVGAMMIOAddress(VGAChip *chip, WORD adapterIndex) 214 | { 215 | Ioctl_83002138_In InBuffer; 216 | Ioctl_83002138_Out OutBuffer; 217 | DWORD BytesReturned; 218 | 219 | InBuffer.adapterIndex = adapterIndex; 220 | InBuffer.field_2 = chip->field_0; 221 | InBuffer.field_4 = chip->field_4; 222 | InBuffer.field_8 = chip->field_14; 223 | InBuffer.field_14 = 0; 224 | InBuffer.field_16 = 0; 225 | if (InBuffer.field_8) 226 | { 227 | if (DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL)) 228 | { 229 | return OutBuffer.field_4; 230 | } 231 | } 232 | return 0; 233 | } 234 | 235 | WORD GetWORDVGABIOSData(int offset, WORD adapterIndex) 236 | { 237 | Ioctl_83002138_In InBuffer; 238 | Ioctl_83002138_Out OutBuffer; 239 | DWORD BytesReturned; 240 | 241 | InBuffer.adapterIndex = adapterIndex; 242 | InBuffer.field_14 = 1; 243 | InBuffer.field_16 = 1; 244 | InBuffer.field_18 = 1; 245 | InBuffer.mmioRegister = offset; 246 | DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 247 | return (WORD) OutBuffer.field_4; 248 | } 249 | 250 | int GetVGABIOSAddress(VGAChip *chip, WORD adapterIndex) 251 | { 252 | Ioctl_83002138_In InBuffer; 253 | Ioctl_83002138_Out OutBuffer; 254 | DWORD BytesReturned; 255 | 256 | InBuffer.adapterIndex = adapterIndex; 257 | InBuffer.field_2 = chip->field_0; 258 | InBuffer.field_4 = chip->field_4; 259 | InBuffer.field_8 = chip->field_18; 260 | InBuffer.field_14 = 1; 261 | InBuffer.field_16 = 0; 262 | if (InBuffer.field_8) 263 | { 264 | DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 265 | } 266 | if (GetWORDVGABIOSData(0, adapterIndex) == 0xAA55) 267 | { 268 | return OutBuffer.field_4; 269 | } 270 | if (adapterIndex) return 0; 271 | InBuffer.field_8 = 0xC0000; 272 | DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 273 | if (GetWORDVGABIOSData(0, 0) != 0xAA55) return 0; 274 | return OutBuffer.field_4; 275 | } 276 | 277 | DWORD ReadMMIODword(DWORD address, WORD adapterIndex) 278 | { 279 | Ioctl_83002138_In InBuffer; 280 | Ioctl_83002138_Out OutBuffer; 281 | DWORD BytesReturned; 282 | 283 | InBuffer.adapterIndex = adapterIndex; 284 | InBuffer.field_14 = 0; 285 | InBuffer.field_16 = 1; 286 | InBuffer.field_18 = 2; 287 | InBuffer.mmioRegister = address; 288 | DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 289 | return OutBuffer.field_4; 290 | } 291 | 292 | void WriteMMIODword(DWORD address, DWORD value, WORD adapterIndex) 293 | { 294 | Ioctl_83002138_In InBuffer; 295 | Ioctl_83002138_Out OutBuffer; 296 | DWORD BytesReturned; 297 | 298 | InBuffer.adapterIndex = adapterIndex; 299 | InBuffer.field_14 = 0; 300 | InBuffer.field_16 = 2; 301 | InBuffer.field_18 = 2; 302 | InBuffer.mmioRegister = address; 303 | InBuffer.field_24 = value; 304 | DeviceIoControl(g_hDevice, 0x83002138, &InBuffer, sizeof(InBuffer), &OutBuffer, sizeof(OutBuffer), &BytesReturned, NULL); 305 | } 306 | -------------------------------------------------------------------------------- /win/IOMap.h: -------------------------------------------------------------------------------- 1 | typedef struct { 2 | WORD field_0; 3 | char pad1[2]; 4 | WORD field_4; 5 | char pad2[2]; 6 | WORD device_id; 7 | char pad3[2]; 8 | WORD subdevice_id; 9 | char pad4[2]; 10 | WORD subvendor_id; 11 | char pad5[2]; 12 | DWORD field_14; 13 | DWORD field_18; 14 | DWORD field_1C; 15 | } VGAChip; 16 | C_ASSERT(sizeof(VGAChip) == 0x20); 17 | 18 | //void LoadDriver(); 19 | //void __cdecl UnloadDriver(void); 20 | int EnumerateGPUs(DWORD vendorId, VGAChip *OutBuffer, DWORD OutBufferSize); 21 | int GetVGAMMIOAddress(VGAChip *chip, WORD adapterIndex); 22 | int GetVGABIOSAddress(VGAChip *chip, WORD adapterIndex); 23 | DWORD ReadMMIODword(DWORD address, WORD adapterIndex); 24 | void WriteMMIODword(DWORD address, DWORD value, WORD adapterIndex); 25 | 26 | extern HANDLE g_hDevice; 27 | -------------------------------------------------------------------------------- /win/IOMap.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/win/IOMap.sys -------------------------------------------------------------------------------- /win/IOMap64.sys: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Eliovp/amdmemorytweak/616184b07bcae346f67c5d71d263e315d4b6b422/win/IOMap64.sys -------------------------------------------------------------------------------- /win/WinAMDTweak.cpp: -------------------------------------------------------------------------------- 1 | #define WIN32_LEAN_AND_MEAN 2 | #define _CRT_SECURE_NO_WARNINGS 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "IOMap.h" 8 | 9 | typedef WORD u16; 10 | typedef DWORD u32; 11 | typedef unsigned __int64 u64; 12 | #define strcasecmp _strcmpi 13 | 14 | #define VERSION "AMD Memory Tweak Windows CLI version 0.1.9\n" 15 | 16 | #define AMD_TIMING_REGS_BASE_1 0x50200 17 | #define AMD_TIMING_REGS_BASE_2 0x52200 18 | #define AMD_TIMING_REGS_BASE_3 0x54200 19 | #define AMD_TIMING_REGS_BASE_4 0x56200 20 | 21 | typedef union { 22 | u32 value; 23 | struct { 24 | u32 /*Reserved*/ : 8; 25 | u32 MAN : 4; 26 | u32 VEN : 4; 27 | u32 : 16; 28 | } rx; 29 | struct { 30 | u32 /*Reserved*/ : 24; 31 | u32 MAN : 8; 32 | } hbm; 33 | } MANUFACTURER; 34 | #define MANUFACTURER_ID 0x2A00 35 | #define MANUFACTURER_ID_HBM 0x29C4 36 | #define MANUFACTURER_ID_HBM2 0x5713C 37 | 38 | typedef struct { 39 | u32 frequency; 40 | // TIMING1 41 | u32 CL : 8; 42 | u32 RAS : 8; 43 | u32 RCDRD : 8; 44 | u32 RCDWR : 8; 45 | // TIMING2 46 | u32 RCAb : 8; 47 | u32 RCPb : 8; 48 | u32 RPAb : 8; 49 | u32 RPPb : 8; 50 | // TIMING3 51 | u32 RRDS : 8; 52 | u32 RRDL : 8; 53 | u32 /*Reserved*/ : 8; 54 | u32 RTP : 8; 55 | // TIMING4 56 | u32 FAW : 8; 57 | u32 /*Reserved*/ : 24; 58 | // TIMING5 59 | u32 CWL : 8; 60 | u32 WTRS : 8; 61 | u32 WTRL : 8; 62 | u32 /*Reserved*/ : 8; 63 | // TIMING6 64 | u32 WR : 8; 65 | u32 /*Reserved*/ : 24; 66 | // TIMING7 67 | u32 /*Reserved*/ : 8; 68 | u32 RREFD : 8; 69 | u32 /*Reserved*/ : 8; 70 | u32 /*Reserved*/ : 8; 71 | // TIMING8 72 | u32 RDRDDD : 8; 73 | u32 RDRDSD : 8; 74 | u32 RDRDSC : 8; 75 | u32 RDRDSCL : 6; 76 | u32 /*Reserved*/ : 2; 77 | // TIMING9 78 | u32 WRWRDD : 8; 79 | u32 WRWRSD : 8; 80 | u32 WRWRSC : 8; 81 | u32 WRWRSCL : 6; 82 | u32 /*Reserved*/ : 2; 83 | // TIMING10 84 | u32 WRRD : 8; 85 | u32 RDWR : 8; 86 | u32 /*Reserved*/ : 16; 87 | // PADDING 88 | u32 /*Reserved*/ : 32; 89 | // TIMING12 90 | u32 REF : 16; // Determines at what rate refreshes will be executed. Vega RXboost :p 91 | u32 /*Reserved*/ : 16; 92 | // TIMING13 93 | u32 MRD : 8; 94 | u32 MOD : 8; 95 | u32 /*Reserved*/ : 16; 96 | // TIMING14 97 | u32 XS : 16; // self refresh exit period 98 | u32 /*Reserved*/ : 16; 99 | // PADDING 100 | u32 /*Reserved*/ : 32; 101 | // TIMING16 102 | u32 XSMRS : 16; 103 | u32 /*Reserved*/ : 16; 104 | // TIMING17 105 | u32 PD : 4; 106 | u32 CKSRE : 6; 107 | u32 CKSRX : 6; 108 | u32 /*Reserved*/ : 16; 109 | // PADDING 110 | u32 /*Reserved*/ : 32; 111 | // PADDING 112 | u32 /*Reserved*/ : 32; 113 | // TIMING20 114 | u32 RFCPB : 16; 115 | u32 STAG : 8; 116 | u32 /*Reserved*/ : 8; 117 | // TIMING21 118 | u32 XP : 8; 119 | u32 /*Reserved*/ : 8; 120 | u32 CPDED : 8; 121 | u32 CKE : 8; 122 | // TIMING22 123 | u32 RDDATA : 8; 124 | u32 WRLAT : 8; 125 | u32 RDLAT : 8; 126 | u32 WRDATA : 4; 127 | u32 /*Reserved*/ : 4; 128 | // TIMING23 129 | u32 /*Reserved*/ : 16; 130 | u32 CKESTAG : 8; 131 | u32 /*Reserved*/ : 8; 132 | // RFC 133 | u32 RFC : 16; 134 | u32 /*Reserved*/ : 16; 135 | } HBM2_TIMINGS; 136 | 137 | typedef union { 138 | u32 value; 139 | struct { 140 | u32 DAT_DLY : 4; // Data output latency 141 | u32 DQS_DLY : 4; // DQS Latency 142 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 143 | u32 DAT_2Y_DLY : 1; // Delay data (QDR Mode!) (ON/OFF) 144 | u32 ADR_2Y_DLY : 1; // Delay addr (QDR Mode!) (ON/OFF) 145 | u32 CMD_2Y_DLY : 1; // Delay cmd (QDR Mode!) (ON/OFF) 146 | u32 OEN_DLY : 4; // Write cmd enable Latency 147 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 148 | u32 OEN_SEL : 2; 149 | u32 /*Reserved*/ : 2; 150 | u32 ODT_DLY : 4; // On-Die-Termination latency 151 | u32 ODT_EXT : 1; // On-Die-Termination enable after burst 152 | u32 ADR_DLY : 1; 153 | u32 CMD_DLY : 1; 154 | u32 /*Reserved*/ : 1; 155 | } rx; 156 | struct { 157 | u32 DAT_DLY : 5; // Data output latency 158 | u32 DQS_DLY : 5; // DQS Latency 159 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 160 | u32 OEN_DLY : 5; // Write cmd enable Latency 161 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 162 | u32 OEN_SEL : 2; 163 | u32 CMD_DLY : 1; 164 | u32 ADR_DLY : 1; 165 | u32 /*Reserved*/ : 8; 166 | } hbm; 167 | } SEQ_WR_CTL_D0; 168 | #define MC_SEQ_WR_CTL_D0 0x28bc // Chan 0 write commands 169 | #define MC_SEQ_WR_CTL_D0_HBM 0x28EC 170 | 171 | typedef union { 172 | u32 value; 173 | struct { 174 | u32 DAT_DLY : 4; // Data output latency 175 | u32 DQS_DLY : 4; // DQS Latency 176 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 177 | u32 DAT_2Y_DLY : 1; // Delay data (QDR Mode!) (ON/OFF) 178 | u32 ADR_2Y_DLY : 1; // Delay addr (QDR Mode!) (ON/OFF) 179 | u32 CMD_2Y_DLY : 1; // Delay cmd (QDR Mode!) (ON/OFF) 180 | u32 OEN_DLY : 4; // Write cmd enable Latency 181 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 182 | u32 OEN_SEL : 2; 183 | u32 /*Reserved*/ : 2; 184 | u32 ODT_DLY : 4; // On-Die-Termination latency 185 | u32 ODT_EXT : 1; // On-Die-Termination enable after burst 186 | u32 ADR_DLY : 1; 187 | u32 CMD_DLY : 1; 188 | u32 : 1; 189 | } rx; 190 | struct { 191 | u32 DAT_DLY : 5; // Data output latency 192 | u32 DQS_DLY : 5; // DQS Latency 193 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 194 | u32 OEN_DLY : 5; // Write cmd enable Latency 195 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 196 | u32 OEN_SEL : 2; 197 | u32 CMD_DLY : 1; 198 | u32 ADR_DLY : 1; 199 | u32 /*Reserved*/ : 8; 200 | } hbm; 201 | } SEQ_WR_CTL_D1; 202 | #define MC_SEQ_WR_CTL_D1 0x28c0 // Chan 1 write commands 203 | #define MC_SEQ_WR_CTL_D1_HBM 0x28F4 204 | 205 | typedef union { 206 | u32 value; 207 | struct { 208 | u32 DAT_DLY : 5; // Data output latency 209 | u32 DQS_DLY : 5; // DQS Latency 210 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 211 | u32 OEN_DLY : 5; // Write cmd enable Latency 212 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 213 | u32 OEN_SEL : 2; 214 | u32 CMD_DLY : 1; 215 | u32 ADR_DLY : 1; 216 | u32 /*Reserved*/ : 8; 217 | }; 218 | } SEQ_WR_CTL_D2; 219 | #define MC_SEQ_WR_CTL_D2_HBM 0x28FC 220 | 221 | typedef union { 222 | u32 value; 223 | struct { 224 | u32 DAT_DLY : 5; // Data output latency 225 | u32 DQS_DLY : 5; // DQS Latency 226 | u32 DQS_XTR : 1; // Write Preamble (ON/OFF) 227 | u32 OEN_DLY : 5; // Write cmd enable Latency 228 | u32 OEN_EXT : 4; // Output enable -> Data Burst (0 - 8 where 1 = 1 cycle, 5 = 5 cycles..) 229 | u32 OEN_SEL : 2; 230 | u32 CMD_DLY : 1; 231 | u32 ADR_DLY : 1; 232 | u32 /*Reserved*/ : 8; 233 | }; 234 | } SEQ_WR_CTL_D3; 235 | #define MC_SEQ_WR_CTL_D3_HBM 0x2904 236 | 237 | typedef union { 238 | u32 value; 239 | struct { 240 | u32 THRESH : 3; // Threshold 241 | u32 /*Reserved*/ : 1; 242 | u32 LEVEL : 3; // Level 243 | u32 PWRDOWN : 1; // PWRDOWN 244 | u32 SHUTDOWN : 3; // SHUTDOWN 245 | u32 EN_SHUTDOWN : 1; // EN_SHUTDOWN 246 | u32 OVERSAMPLE : 2; 247 | u32 AVG_SAMPLE : 1; 248 | u32 /*Reserved*/ : 17; 249 | }; 250 | } THERMAL_THROTTLE; 251 | #define MC_THERMAL_THROTTLE 0x2ACC // Thermal Throttle Control 252 | 253 | typedef union { 254 | u32 value; 255 | struct { 256 | u32 CKSRE : 3; // Valid clock requirement after CKSRE 257 | u32 /*Reserved*/ : 1; 258 | u32 CKSRX : 3; // Valid clock requirement before CKSRX 259 | u32 /*Reserved*/ : 1; 260 | u32 CKE_PULSE : 4; // Minimum CKE pulse 261 | u32 CKE : 6; 262 | u32 SEQ_IDLE : 3; // idle before deassert rdy to arb 263 | u32 /*Reserved*/ : 2; 264 | u32 CKE_PULSE_MSB : 1; // Minimum CKE pulse msb 265 | u32 SEQ_IDLE_SS : 8; // idle before deassert rdy to arb at ss 266 | } rx; 267 | struct { 268 | u32 CKSRE : 3; // Valid clock requirement after CKSRE 269 | u32 CKSRX : 3; // Valid clock requirement before CKSRX 270 | u32 CKE_PULSE : 5; // Minimum CKE pulse 271 | u32 CKE : 8; 272 | u32 SEQ_IDLE : 3; // idle before deassert rdy to arb 273 | u32 SEQ_IDLE_SS : 8; // idle before deassert rdy to arb at ss 274 | u32 /*Reserved*/ : 2; 275 | } hbm; 276 | } SEQ_PMG_TIMING; 277 | #define MC_SEQ_PMG_TIMING 0x28B0 // Power Management 278 | #define MC_SEQ_PMG_TIMING_HBM 0x28C4 // Power Management 279 | 280 | typedef union { 281 | u32 value; 282 | struct { 283 | u32 RCDW : 5; // # of cycles from active to write 284 | u32 RCDWA : 5; // # of cycles from active to write with auto-precharge 285 | u32 RCDR : 5; // # of cycles from active to read 286 | u32 RCDRA : 5; // # of cycles from active to read with auto-precharge 287 | u32 RRD : 4; // # of cycles from active bank a to active bank b 288 | u32 RC : 7; // # of cycles from active to active/auto refresh 289 | u32 /*Reserved*/ : 1; 290 | }; 291 | } SEQ_RAS_TIMING; 292 | #define MC_SEQ_RAS_TIMING 0x28A0 293 | #define MC_SEQ_RAS_TIMING_HBM 0x28A4 294 | 295 | typedef union { 296 | u32 value; 297 | struct { 298 | u32 NOPW : 2; // Extra cycle(s) between successive write bursts 299 | u32 NOPR : 2; // Extra cycle(s) between successive read bursts 300 | u32 R2W : 5; // Read to write turn around time 301 | u32 CCDL : 3; // Cycles between r/w from bank A to r/w bank B 302 | u32 R2R : 4; // Read to read time 303 | u32 W2R : 5; // Write to read turn around time 304 | u32 /*Reserved*/ : 3; 305 | u32 CL : 5; // CAS to data return latency (0 - 20) 306 | u32 /*Reserved*/ : 3; 307 | } rx; 308 | struct { 309 | u32 NOPW : 2; // Extra cycle(s) between successive write bursts 310 | u32 NOPR : 2; // Extra cycle(s) between successive read bursts 311 | u32 R2W : 5; // Read to write turn 312 | u32 CCDL : 3; // Cycles between r/w from bank A to r/w bank B 313 | u32 R2R : 4; // Read to read time 314 | u32 W2R : 5; // Write to read turn 315 | u32 CL : 5; // CAS to data return latency 316 | u32 /*Reserved*/ : 6; 317 | } hbm; 318 | } SEQ_CAS_TIMING; 319 | #define MC_SEQ_CAS_TIMING 0x28A4 320 | #define MC_SEQ_CAS_TIMING_HBM 0x28AC 321 | 322 | typedef union { 323 | u32 value; 324 | struct { 325 | u32 RP_WRA : 6; // From write with auto-precharge to active 326 | u32 /*Reserved*/ : 2; 327 | u32 RP_RDA : 6; // From read with auto-precharge to active 328 | u32 /*Reserved*/ : 1; 329 | u32 TRP : 5; // Precharge command period 330 | u32 RFC : 9; // Auto-refresh command period 331 | u32 /*Reserved*/ : 3; 332 | } rx; 333 | struct { 334 | u32 RP_WRA : 8; // From write with auto-precharge to active 335 | u32 RP_RDA : 7; // From read with auto-precharge to active 336 | u32 TRP : 5; // Precharge command period 337 | u32 RFC : 9; // Auto-refresh command period 338 | u32 /*Reserved*/ : 3; 339 | } r9; 340 | struct { 341 | u32 RP_WRA : 6; // From write with auto-precharge to active 342 | u32 RP_RDA : 6; // From read with auto-precharge to active 343 | u32 TRP : 5; // Precharge command period 344 | u32 RFC : 7; // Auto-refresh command period 345 | u32 RRDL : 4; 346 | u32 MRD : 4; 347 | } hbm; 348 | } SEQ_MISC_TIMING; 349 | #define MC_SEQ_MISC_TIMING 0x28A8 350 | #define MC_SEQ_MISC_TIMING_HBM 0x28B4 351 | 352 | typedef union { 353 | u32 value; 354 | struct { 355 | u32 PA2RDATA : 3; // DDR4 356 | u32 /*Reserved*/ : 1; 357 | u32 PA2WDATA : 3; // DDR4 358 | u32 /*Reserved*/ : 1; 359 | u32 FAW : 5; // The time window in wich four activates are allowed in the same rank 360 | u32 REDC : 3; // Min 0, Max 7 361 | u32 WEDC : 5; // Min 0, Max 7 362 | u32 T32AW : 4; // Max 12 363 | u32 /*Reserved*/ : 3; 364 | u32 WDATATR : 4; // WCMD timing for write training 365 | } rx; 366 | struct { 367 | u32 PA2RDATA : 3; 368 | u32 PA2WDATA : 3; 369 | u32 FAW : 5; // The time window in wich four activates are allowed in the same rank 370 | u32 WPAR : 3; 371 | u32 RPAR : 3; 372 | u32 T32AW : 4; 373 | u32 WDATATR : 4; 374 | u32 /*Reserved*/ : 7; 375 | } hbm; 376 | } SEQ_MISC_TIMING2; 377 | #define MC_SEQ_MISC_TIMING2 0x28AC 378 | #define MC_SEQ_MISC_TIMING2_HBM 0x28BC 379 | 380 | // Mode Registers (JESD212 for more info) 381 | typedef union { 382 | u32 value; 383 | struct { 384 | // MR0 385 | u32 WL : 3; // Write Latency 386 | u32 CL : 4; // CAS Latency 387 | u32 TM : 1; 388 | u32 WR : 4; // Write Recovery 389 | u32 BA0 : 1; 390 | u32 BA1 : 1; 391 | u32 BA2 : 1; 392 | u32 BA3 : 1; 393 | // MR1 394 | u32 DS : 2; // Driver Strength (0 = Auto Calibration) 395 | u32 DT : 2; // Data Termination (0 = Disabled) 396 | u32 ADR : 2; // ADR CMD Termination (0 = CKE value at Reset) 397 | u32 CAL : 1; // Calibration Update 398 | u32 PLL : 1; 399 | u32 RDBI : 1; // Read DBI (ON/OFF) 400 | u32 WDBI : 1; // Write DBI (ON/OFF) 401 | u32 ABI : 1; // (ON/OFF) 402 | u32 RESET : 1; // PLL Reset 403 | u32 BA_0 : 1; 404 | u32 BA_1 : 1; 405 | u32 BA_2 : 1; 406 | u32 BA_3 : 1; 407 | } rx; 408 | struct { 409 | // MR0 410 | u32 DBR : 1; // Read DBIac (OFF/ON) 411 | u32 DBW : 1; // Write DBIac (OFF/ON) 412 | u32 TCSR : 1; // Temperature Compensated Self Refresh (OFF/ON) 413 | u32 /*Reserved*/ : 1; 414 | u32 DQR : 1; // DQ Bus Read Parity (OFF/ON) 415 | u32 DQW : 1; // DQ Bus Write Parity (OFF/ON) 416 | u32 ADD_PAR : 1; // Address, Command Bus Parity for Row, Column Bus (OFF/ON) 417 | u32 TM : 1; // Vendor Specific (NORMAL/TEST) 418 | // MR1 419 | u32 WR : 5; // Write Recovery 420 | u32 NDS : 3; // Nominal Driver Strength 421 | // MR2 422 | u32 WL : 3; // Write Latency 423 | u32 RL : 5; // Read Latency 424 | // MR3 425 | u32 APRAS : 6; // Activate to Precharge RAS 426 | u32 BG : 1; // Bank Group 427 | u32 BL : 1; // Burst Length 428 | } hbm; 429 | } SEQ_MISC1; 430 | #define MC_SEC_MISC1 0x2A04 431 | #define MC_SEC_MISC1_HBM 0x29C8 // Beta (untested) 432 | 433 | typedef union { 434 | u32 value; 435 | struct { 436 | // MR2 437 | u32 OCD_DWN : 3; // OCD Pulldown Driver Offset 438 | u32 OCD_UP : 3; // OCD Pullup Driver Offset 439 | u32 WCK : 3; // Data and WCK Termination Offset 440 | u32 ADR : 3; // ADR/CMD Termination Offset 441 | u32 BA0 : 1; 442 | u32 BA1 : 1; 443 | u32 BA2 : 1; 444 | u32 BA3 : 1; 445 | // MR3 446 | u32 SR : 2; // Self Refresh (0 = 32ms) 447 | u32 WCK01 : 1; // (OFF/ON) 448 | u32 WCK23 : 1; // (OFF/ON) 449 | u32 WCK2CK : 1; // (OFF/ON) 450 | u32 RDQS : 1; // (OFF/ON) 451 | u32 INFO : 2; // Dram Info (0=Off) 452 | u32 WCK2 : 2; // WCK Termination 453 | u32 BG : 2; // Bank Groups 454 | u32 BA_0 : 1; 455 | u32 BA_1 : 1; 456 | u32 BA_2 : 1; 457 | u32 BA_3 : 1; 458 | }; 459 | } SEQ_MISC2; 460 | #define MC_SEC_MISC2 0x2A08 461 | 462 | typedef union { 463 | u32 value; 464 | struct { 465 | // MR4 466 | u32 EDCHP : 4; // EDC Hold Pattern 467 | u32 CRCWL : 3; // CRC Write Latency 468 | u32 CRCRL : 2; // CRC Read Latency 469 | u32 RDCRC : 1; // (ON/OFF) 470 | u32 WRCRC : 1; // (ON/OFF) 471 | u32 EDC : 1; // (OFF/ON) 472 | u32 BA0 : 1; 473 | u32 BA1 : 1; 474 | u32 BA2 : 1; 475 | u32 BA3 : 1; 476 | // MR5 477 | u32 LP1 : 1; // (OFF/ON) 478 | u32 LP2 : 1; // (OFF/ON) 479 | u32 LP3 : 1; // (OFF/ON) 480 | u32 PLL : 3; // PLL/DLL Band-Width (0 = Vendor Specific) 481 | u32 RAS : 6; 482 | u32 BA_0 : 1; 483 | u32 BA_1 : 1; 484 | u32 BA_2 : 1; 485 | u32 BA_3 : 1; 486 | }; 487 | } SEQ_MISC3; 488 | #define MC_SEC_MISC3 0x2A2C 489 | 490 | typedef union { 491 | u32 value; 492 | struct { 493 | // MR6 494 | u32 WCK : 1; // WCK2CK Pin 495 | u32 VREFD_M : 1; // VREFD Merge 496 | u32 A_VREFD : 1; // Auto VREFD Training 497 | u32 VREFD : 1; 498 | u32 VREFD_O : 4; // Offset rows M-U 499 | u32 VREFD_0_2 : 4; // Offset rows A-F 500 | u32 BA0 : 1; 501 | u32 BA1 : 1; 502 | u32 BA2 : 1; 503 | u32 BA3 : 1; 504 | // MR7 505 | u32 PLL_STD : 1; // PLL Standby (OFF/ON) 506 | u32 PLL_FL : 1; // PLL Fast Lock (OFF/ON) 507 | u32 PLL_DEL : 1; // PLL Delay Compensation (OFF/ON) 508 | u32 LF_MOD : 1; // Low Frequency Mode (OFF/ON) 509 | u32 AUTO : 1; // WCK2CK Auto Sync (OFF/ON) 510 | u32 DQ : 1; // DQ Preamble (OFF/ON) 511 | u32 TEMP : 1; // Temp Sensor (OFF/ON) 512 | u32 HALF : 1; // Half VREFD 513 | u32 VDD_R : 2; // VDD Range 514 | u32 RFU : 2; 515 | u32 BA_0 : 1; 516 | u32 BA_1 : 1; 517 | u32 BA_2 : 1; 518 | u32 BA_3 : 1; 519 | }; 520 | } SEQ_MISC4; 521 | #define MC_SEC_MISC4 0x2A30 522 | 523 | typedef union { 524 | u32 value; 525 | struct { 526 | // MR15 527 | u32 /*Reserved*/ : 8; 528 | u32 MRE0 : 1; // Mode Register 0-14 Enable MF=0 (ON/OFF) 529 | u32 MRE1 : 1; // Mode Register 0-14 Enable MF=1 (ON/OFF) 530 | u32 ADT : 1; // Address Training (OFF/ON) 531 | u32 RFU : 1; 532 | u32 BA0 : 1; 533 | u32 BA1 : 1; 534 | u32 BA2 : 1; 535 | u32 BA3 : 1; 536 | u32 /*Reserved*/ : 16; 537 | }; 538 | } SEQ_MISC7; 539 | #define MC_SEC_MISC7 0x2A64 540 | 541 | typedef union { 542 | u32 value; 543 | struct { 544 | // MR8 545 | u32 CLEHF : 1; // Cas Latency Extra High Frequency (0 = normal range, 1 = Extended) 546 | u32 WREHF : 1; // Write Recovery Extra High Frequency (0 = normal range, 1 = Extended) 547 | u32 RFU : 10; 548 | u32 BA0 : 1; 549 | u32 BA1 : 1; 550 | u32 BA2 : 1; 551 | u32 BA3 : 1; 552 | u32 /*Reserved*/ : 16; 553 | }; 554 | } SEQ_MISC8; 555 | #define MC_SEC_MISC8 0x297C 556 | 557 | typedef union { 558 | u32 value; 559 | struct { 560 | u32 ACTRD : 8; 561 | u32 ACTWR : 8; 562 | u32 RASMACTRD : 8; 563 | u32 RASMACTWR : 8; 564 | }; 565 | } ARB_DRAM_TIMING; 566 | #define MC_ARB_DRAM_TIMING 0x2774 567 | 568 | typedef union { 569 | u32 value; 570 | struct { 571 | u32 RAS2RAS : 8; 572 | u32 RP : 8; 573 | u32 WRPLUSRP : 8; 574 | u32 BUS_TURN : 8; 575 | }; 576 | } ARB_DRAM_TIMING2; 577 | #define MC_ARB_DRAM_TIMING2 0x2778 578 | 579 | typedef union { 580 | u32 value; 581 | struct { 582 | u32 REF : 16; 583 | u32 /*Reserved*/ : 16; 584 | }; 585 | } ARB_RFSH_RATE; 586 | #define MC_ARB_RFSH_RATE 0x27b0 // The famous RXBoost :p 587 | 588 | typedef union { 589 | u32 value; 590 | struct { 591 | u32 TWT2RT : 5; // # of cycles from write to read train command 592 | u32 TARF2T : 5; // # of cycles from auto refresh to train command 593 | u32 TT2ROW : 5; // # of cycles between row charge command 594 | u32 TLD2LD : 5; // # of cycles between LDFF command 595 | u32 /*Reserved*/ : 12; 596 | }; 597 | } SEQ_TRAINING; 598 | #define MC_SEQ_TRAINING 0x2900 599 | 600 | typedef union { 601 | u32 value; 602 | struct { 603 | u32 ENB : 1; 604 | u32 CNT : 5; 605 | u32 TRC : 16; 606 | u32 /*Reserved*/ : 10; 607 | }; 608 | } SEQ_ROW_HAMMER; 609 | #define MC_SEQ_ROW_HAMMER 0x27b0 610 | 611 | 612 | static const char* LookupDeviceName(u16 device_id) 613 | { 614 | struct { 615 | u16 vendor_id; 616 | u16 device_id; 617 | const char* name; 618 | } KnownGPUs[] = { 619 | { 0x1002, 0x66af, "Radeon VII" }, 620 | { 0x1002, 0x687f, "Vega 10 XL/XT [Radeon RX Vega 56/64]" }, 621 | { 0x1002, 0x6867, "Vega 10 XL [Radeon Pro Vega 56]" }, 622 | { 0x1002, 0x6863, "Vega 10 XTX [Radeon Vega Frontier Edition]" }, 623 | { 0x1002, 0x67df, "Ellesmere [Radeon RX 470/480/570/570X/580/580X/590]" }, 624 | { 0x1002, 0x67c4, "Ellesmere [Radeon Pro WX 7100]" }, 625 | { 0x1002, 0x67c7, "Ellesmere [Radeon Pro WX 5100]" }, 626 | { 0x1002, 0x67ef, "Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X]" }, 627 | { 0x1002, 0x67ff, "Baffin [Radeon RX 550 640SP / RX 560/560X]" }, 628 | { 0x1002, 0x7300, "Fiji [Radeon R9 FURY / NANO Series]" }, 629 | { 0x1002, 0x67b0, "Hawaii XT / Grenada XT [Radeon R9 290X/390X]" }, 630 | { 0x1002, 0x67b1, "Hawaii PRO [Radeon R9 290/390]" }, 631 | { 0x1002, 0x6798, "Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X]" }, 632 | { 0x1002, 0x679a, "Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280]" }, 633 | }; 634 | for (int i = 0; i < _countof(KnownGPUs); i++) 635 | { 636 | if (/*(KnownGPUs[i].vendor_id == dev->vendor_id) && */(KnownGPUs[i].device_id == device_id)) 637 | { 638 | return KnownGPUs[i].name; 639 | } 640 | } 641 | return ""; 642 | } 643 | 644 | static bool IsRelevantDeviceID(u16 device_id) 645 | { 646 | return 647 | (device_id == 0x66af) || // Radeon VII 648 | (device_id == 0x687f) || // Vega 10 XL/XT [Radeon RX Vega 56/64] 649 | (device_id == 0x6867) || // Vega 10 XL [Radeon Pro Vega 56] 650 | (device_id == 0x6863) || // Vega 10 XTX [Radeon Vega Frontier Edition] 651 | (device_id == 0x67df) || // Ellesmere [Radeon RX 470/480/570/570X/580/580X/590] 652 | (device_id == 0x67c4) || // Ellesmere [Radeon Pro WX 7100] 653 | (device_id == 0x67c7) || // Ellesmere [Radeon Pro WX 5100] 654 | (device_id == 0x67ef) || // Baffin [Radeon RX 460/560D / Pro 450/455/460/555/555X/560/560X] 655 | (device_id == 0x67ff) || // Baffin [Radeon RX 550 640SP / RX 560/560X] 656 | (device_id == 0x7300) || // Fiji [Radeon R9 FURY / NANO Series] 657 | (device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X] 658 | (device_id == 0x67b1) || // Hawaii PRO [Radeon R9 290/390] 659 | (device_id == 0x6798) || // Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] 660 | (device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] 661 | } 662 | 663 | static bool IsR9(u16 device_id) 664 | { 665 | return 666 | (device_id == 0x67b0) || // Hawaii XT / Grenada XT [Radeon R9 290X/390X] 667 | (device_id == 0x67b1) || // Hawaii PRO [Radeon R9 290/390] 668 | (device_id == 0x6798) || // Tahiti XT [Radeon HD 7970/8970 OEM / R9 280X] 669 | (device_id == 0x679a); // Tahiti PRO [Radeon HD 7950/8950 OEM / R9 280] 670 | } 671 | 672 | typedef enum { GDDR5, HBM, HBM2 } MemoryType; 673 | 674 | static MemoryType DetermineMemoryType(u16 device_id) 675 | { 676 | struct { 677 | u16 vendor_id; 678 | u16 device_id; 679 | MemoryType memory_type; 680 | } KnownGPUs[] = { 681 | /* Vega20 - Radeon VII */ 682 | { 0x1002, 0x66a0, HBM2 }, // "Radeon Instinct", CHIP_VEGA20 683 | { 0x1002, 0x66a1, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 684 | { 0x1002, 0x66a2, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 685 | { 0x1002, 0x66a3, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 686 | { 0x1002, 0x66a4, HBM2 }, // "Radeon Vega20", CHIP_VEGA20 687 | { 0x1002, 0x66a7, HBM2 }, // "Radeon Pro Vega20", CHIP_VEGA20 688 | { 0x1002, 0x66af, HBM2 }, // "Radeon VII", CHIP_VEGA20 689 | /* Vega */ 690 | { 0x1002, 0x687f, HBM2 }, // "Radeon RX Vega", CHIP_VEGA10 691 | { 0x1002, 0x6863, HBM2 }, // "Radeon Vega Frontier Edition", CHIP_VEGA10 692 | /* Fury/Nano Support will Follow later */ 693 | { 0x1002, 0x7300, HBM }, // "Radeon R9 Fury/Nano/X", CHIP_FIJI 694 | }; 695 | for (int i = 0; i < _countof(KnownGPUs); i++) 696 | { 697 | if (/*(KnownGPUs[i].vendor_id == dev->vendor_id) && */(KnownGPUs[i].device_id == device_id)) 698 | { 699 | return KnownGPUs[i].memory_type; 700 | } 701 | } 702 | return GDDR5; 703 | } 704 | 705 | typedef struct { 706 | char log[1000]; 707 | bool modify[25]; 708 | MANUFACTURER man; 709 | // HBM2 710 | HBM2_TIMINGS hbm2; 711 | // GDDR5 && HBM1 712 | SEQ_WR_CTL_D0 ctl1; 713 | SEQ_WR_CTL_D1 ctl2; 714 | SEQ_PMG_TIMING pmg; 715 | SEQ_RAS_TIMING ras; 716 | SEQ_CAS_TIMING cas; 717 | SEQ_MISC_TIMING misc; 718 | SEQ_MISC_TIMING2 misc2; 719 | SEQ_MISC1 smisc1; 720 | SEQ_MISC2 smisc2; 721 | SEQ_MISC3 smisc3; 722 | SEQ_MISC4 smisc4; 723 | SEQ_MISC7 smisc7; 724 | SEQ_MISC8 smisc8; 725 | ARB_DRAM_TIMING dram1; 726 | ARB_DRAM_TIMING2 dram2; 727 | ARB_RFSH_RATE ref; 728 | SEQ_TRAINING train; 729 | // HBM1 Specific 730 | SEQ_ROW_HAMMER ham; 731 | THERMAL_THROTTLE throt; 732 | SEQ_WR_CTL_D2 ctl3; 733 | SEQ_WR_CTL_D3 ctl4; 734 | } GPU; 735 | 736 | static u64 ParseIndicesArg(const char* arg) 737 | { 738 | char buffer[1000]; 739 | strcpy(buffer, arg); 740 | u64 mask = 0; 741 | char* token = strtok(buffer, ","); 742 | while (token) 743 | { 744 | while (*token && isspace(*token)) token++; 745 | char* endptr; 746 | unsigned long index = strtoul(token, &endptr, 10); 747 | while (*endptr && isspace(*endptr)) endptr++; 748 | int err = errno; 749 | if ((endptr == token) || *endptr || (errno == EINVAL) || (errno == ERANGE) || (index >= 64)) 750 | { 751 | printf("Invalid GPU index specified.\n"); 752 | exit(EXIT_FAILURE); 753 | } 754 | mask |= ((u64)1 << index); 755 | token = strtok(NULL, ","); 756 | } 757 | return mask; 758 | } 759 | 760 | static bool ParseNumericArg(int argc, const char* argv[], int& i, const char* arg, u32 & value) 761 | { 762 | if (!strcasecmp(arg, argv[i])) 763 | { 764 | if (i == (argc - 1)) 765 | { 766 | printf("Argument \"%s\" requires a parameter.\n", argv[i]); 767 | exit(EXIT_FAILURE); 768 | } 769 | i++; 770 | value = strtoul(argv[i], 0, 10); 771 | if ((errno == EINVAL) || (errno == ERANGE)) 772 | { 773 | printf("Failed to parse parameter %s %s\n", argv[i - 1], argv[i]); 774 | exit(EXIT_FAILURE); 775 | } 776 | return true; 777 | } 778 | return false; 779 | } 780 | 781 | static void PrintCurrentValues(VGAChip * chip, GPU * gpu) 782 | { 783 | if (DetermineMemoryType(chip->device_id) == HBM2) 784 | { 785 | HBM2_TIMINGS current = gpu->hbm2; 786 | MANUFACTURER man = gpu->man; 787 | printf("Memory state: "); 788 | printf((current.frequency == 0x118) ? "800MHz" : 789 | (current.frequency == 0x11C) ? "1000MHz" : 790 | (current.frequency == 0x11E) ? "1200MHz" : "unknown"); 791 | printf("Memory: "); 792 | printf((man.hbm.MAN == 0x63) ? " Hynix HBM2" : 793 | (man.hbm.MAN == 0x61) ? " Samsung HBM2" : " unknown"); 794 | printf("Timing 1\t"); 795 | printf(" CL: %d\t", current.CL); 796 | printf(" RAS: %d\t", current.RAS); 797 | printf(" RCDRD: %d\t", current.RCDRD); 798 | printf(" RCDWR: %d\n", current.RCDWR); 799 | printf("Timing 2\t"); 800 | printf(" RCAb (RC): %d\t", current.RCAb); 801 | printf(" RCPb (RC): %d\t", current.RCPb); 802 | printf(" RPAb (RP): %d\t", current.RPAb); 803 | printf(" RPPb (RP): %d\n", current.RPPb); 804 | printf("Timing 3\t"); 805 | printf(" RRDS: %d\t", current.RRDS); 806 | printf(" RRDL: %d\t", current.RRDL); 807 | printf(" RTP: %d\n", current.RTP); 808 | printf("Timing 4\t"); 809 | printf(" FAW: %d\n", current.FAW); 810 | printf("Timing 5\t"); 811 | printf(" CWL: %d\t", current.CWL); 812 | printf(" WTRS: %d\t", current.WTRS); 813 | printf(" WTRL: %d\n", current.WTRL); 814 | printf("Timing 6\t"); 815 | printf(" WR: %d\n", current.WR); 816 | printf("Timing 7\t"); 817 | printf(" RREFD: %d\n", current.RREFD); 818 | printf("Timing 8\t"); 819 | printf(" RDRDDD: %d\t", current.RDRDDD); 820 | printf(" RDRDSD: %d\t", current.RDRDSD); 821 | printf(" RDRDSC: %d\t", current.RDRDSC); 822 | printf(" RDRDSCL: %d\n", current.RDRDSCL); 823 | printf("Timing 9\t"); 824 | printf(" WRWRDD: %d\t", current.WRWRDD); 825 | printf(" WRWRSD: %d\t", current.WRWRSD); 826 | printf(" WRWRSC: %d\t", current.WRWRSC); 827 | printf(" WRWRSCL: %d\n", current.WRWRSCL); 828 | printf("Timing 10\t"); 829 | printf(" WRRD: %d\t", current.WRRD); 830 | printf(" RDWR: %d\n", current.RDWR); 831 | printf("Timing 12\t"); 832 | printf(" REF: %d\n", current.REF); 833 | printf("Timing 13\t"); 834 | printf(" MRD: %d\t", current.MRD); 835 | printf(" MOD: %d\n", current.MOD); 836 | printf("Timing 14\t"); 837 | printf(" XS: %d\n", current.XS); 838 | printf("Timing 16\t"); 839 | printf(" XSMRS: %d\n", current.XSMRS); 840 | printf("Timing 17\t"); 841 | printf(" PD: %d\t", current.PD); 842 | printf(" CKSRE: %d\t", current.CKSRE); 843 | printf(" CKSRX: %d\n", current.CKSRX); 844 | printf("Timing 20\t"); 845 | printf(" RFCPB: %d\t", current.RFCPB); 846 | printf(" STAG: %d\n", current.STAG); 847 | printf("Timing 21\t"); 848 | printf(" XP: %d\t", current.XP); 849 | printf(" CPDED: %d\t", current.CPDED); 850 | printf(" CKE: %d\n", current.CKE); 851 | printf("Timing 22\t"); 852 | printf(" RDDATA: %d\t", current.RDDATA); 853 | printf(" WRLAT: %d\t", current.WRLAT); 854 | printf(" RDLAT: %d\t", current.RDLAT); 855 | printf(" WRDATA: %d\n", current.WRDATA); 856 | printf("Timing 23\t"); 857 | printf(" CKESTAG: %d\n", current.CKESTAG); 858 | printf("RFC Timing\t"); 859 | printf(" RFC: %d\n", current.RFC); 860 | printf("\n"); 861 | } 862 | else if (DetermineMemoryType(chip->device_id) == HBM) { 863 | MANUFACTURER man = gpu->man; 864 | printf((man.hbm.MAN == 0x63) ? " Hynix HBM" : 865 | (man.hbm.MAN == 0x61) ? " Samsung HBM" : " Unknown"); 866 | printf("\n\nChannel 0's write command parameters:\n"); 867 | printf(" \t DAT_DLY: %d\t", gpu->ctl1.hbm.DAT_DLY); 868 | printf(" DQS_DLY: %d\t", gpu->ctl1.hbm.DQS_DLY); 869 | printf(" DQS_XTR: %d\t", gpu->ctl1.hbm.DQS_XTR); 870 | printf(" OEN_DLY: %d\n", gpu->ctl1.hbm.OEN_DLY); 871 | printf(" \t OEN_EXT: %d\t", gpu->ctl1.hbm.OEN_EXT); 872 | printf(" OEN_SEL: %d\t", gpu->ctl1.hbm.OEN_SEL); 873 | printf(" CMD_DLY: %d\t", gpu->ctl1.hbm.CMD_DLY); 874 | printf(" ADR_DLY: %d\n", gpu->ctl1.hbm.ADR_DLY); 875 | printf("Channel 1's write command parameters:\n"); 876 | printf(" \t DAT_DLY: %d\t", gpu->ctl2.hbm.DAT_DLY); 877 | printf(" DQS_DLY: %d\t", gpu->ctl2.hbm.DQS_DLY); 878 | printf(" DQS_XTR: %d\t", gpu->ctl2.hbm.DQS_XTR); 879 | printf(" OEN_DLY: %d\n", gpu->ctl2.hbm.OEN_DLY); 880 | printf(" \t OEN_EXT: %d\t", gpu->ctl2.hbm.OEN_EXT); 881 | printf(" OEN_SEL: %d\t", gpu->ctl2.hbm.OEN_SEL); 882 | printf(" CMD_DLY: %d\t", gpu->ctl2.hbm.CMD_DLY); 883 | printf(" ADR_DLY: %d\n", gpu->ctl2.hbm.ADR_DLY); 884 | printf("Power Mangement related timings:\n"); 885 | printf(" \t CKSRE: %d\t", gpu->pmg.hbm.CKSRE); 886 | printf(" CKSRX: %d\t", gpu->pmg.hbm.CKSRX); 887 | printf(" CKE_PULSE: %d\t", gpu->pmg.hbm.CKE_PULSE); 888 | printf(" CKE: %d\t", gpu->pmg.hbm.CKE); 889 | printf(" SEQ_IDLE: %d\n", gpu->pmg.hbm.SEQ_IDLE); 890 | printf("RAS related timings:\n"); 891 | printf(" \t RC: %d\t", gpu->ras.RC); 892 | printf(" RRD: %d\t", gpu->ras.RRD); 893 | printf(" RCDRA: %d\t", gpu->ras.RCDRA); 894 | printf(" RCDR: %d\t", gpu->ras.RCDR); 895 | printf(" RCDWA: %d\t", gpu->ras.RCDWA); 896 | printf(" RCDW: %d\n", gpu->ras.RCDW); 897 | printf("CAS related timings:\n"); 898 | printf(" \t CL: %d\t", gpu->cas.hbm.CL); 899 | printf(" W2R: %d\t", gpu->cas.hbm.W2R); 900 | printf(" R2R: %d\t", gpu->cas.hbm.R2R); 901 | printf(" CCDL: %d\t", gpu->cas.hbm.CCDL); 902 | printf(" R2W: %d\t", gpu->cas.hbm.R2W); 903 | printf(" NOPR: %d\t", gpu->cas.hbm.NOPR); 904 | printf(" NOPW: %d\n", gpu->cas.hbm.NOPW); 905 | printf("Misc. DRAM timings:\n"); 906 | printf(" \t MRD: %d\t", gpu->misc.hbm.MRD); 907 | printf(" RRDL: %d\t", gpu->misc.hbm.RRDL); 908 | printf(" RFC: %d\t", gpu->misc.hbm.RFC); 909 | printf(" TRP: %d\t", gpu->misc.hbm.TRP); 910 | printf(" RP_RDA: %d\t", gpu->misc.hbm.RP_RDA); 911 | printf(" RP_WRA: %d\n", gpu->misc.hbm.RP_WRA); 912 | printf("Misc2. DRAM timings:\n"); 913 | printf(" \t WDATATR: %d\t", gpu->misc2.hbm.WDATATR); 914 | printf(" T32AW: %d\t", gpu->misc2.hbm.T32AW); 915 | printf(" RPAR: %d\t", gpu->misc2.hbm.RPAR); 916 | printf(" WPAR: %d\t", gpu->misc2.hbm.WPAR); 917 | printf(" FAW: %d\t", gpu->misc2.hbm.FAW); 918 | printf(" PA2WDATA: %d\t", gpu->misc2.hbm.PA2WDATA); 919 | printf(" PA2RDATA: %d\n", gpu->misc2.hbm.PA2RDATA); 920 | printf("Mode Register 0:\n"); 921 | printf(" \t DBR: %d\t", gpu->smisc1.hbm.DBR); 922 | printf(" DBW: %d\t", gpu->smisc1.hbm.DBW); 923 | printf(" TCSR: %d\t", gpu->smisc1.hbm.TCSR); 924 | printf(" DQR: %d\n", gpu->smisc1.hbm.DQR); 925 | printf(" \t DQW: %d\t ", gpu->smisc1.hbm.DQW); 926 | printf(" ADD_PAR: %d\t ", gpu->smisc1.hbm.ADD_PAR); 927 | printf(" TM: %d\n", gpu->smisc1.hbm.TM); 928 | printf("Mode Register 1:\n"); 929 | printf(" \t WR: %d \t", gpu->smisc1.hbm.WR); 930 | printf(" NDS: %d\n", gpu->smisc1.hbm.NDS); 931 | printf("Mode Register 2:\n"); 932 | printf(" \t WL: %d \t", gpu->smisc1.hbm.WL); 933 | printf(" RL: %d\n", gpu->smisc1.hbm.RL); 934 | printf("Mode Register 3:\n"); 935 | printf(" \t APRAS: %d \t", gpu->smisc1.hbm.APRAS); 936 | printf(" BG: %d \t", gpu->smisc1.hbm.BG); 937 | printf(" BL: %d\n", gpu->smisc1.hbm.BL); 938 | printf("Refresh Interval:\n"); 939 | printf(" \t REF: %d\n", gpu->ref.REF); 940 | printf("Thermal Throttle Control:\n"); 941 | printf(" \t THRESH: %d\t", gpu->throt.THRESH); 942 | printf(" LEVEL: %d\t", gpu->throt.LEVEL); 943 | printf(" PWRDOWN: %d\t", gpu->throt.PWRDOWN); 944 | printf(" SHUTDOWN: %d\t", gpu->throt.SHUTDOWN); 945 | printf(" EN_SHUTDOWN: %d\t", gpu->throt.EN_SHUTDOWN); 946 | printf(" OVERSAMPLE: %d\t", gpu->throt.OVERSAMPLE); 947 | printf(" AVG_SAMPLE: %d\n", gpu->throt.AVG_SAMPLE); 948 | printf("Hammer:\n"); 949 | printf(" \t ENB: %d\t", gpu->ham.ENB); 950 | printf(" CNT: %d\t", gpu->ham.CNT); 951 | printf(" TRC: %d\n", gpu->ham.TRC); 952 | } 953 | else // GDDR5 954 | { 955 | MANUFACTURER man = gpu->man; 956 | printf((man.rx.MAN == 0x1) ? " Samsung GDDR5" : 957 | (man.rx.MAN == 0x3) ? " Elpida GDDR5" : 958 | (man.rx.MAN == 0x6) ? " Hynix GDDR5" : 959 | (man.rx.MAN == 0xf) ? " Micron GDDR5" : " Unknown"); 960 | printf("\n\nChannel 0's write command parameters:\n"); 961 | printf(" \t DAT_DLY: %d\t", gpu->ctl1.rx.DAT_DLY); 962 | printf(" DQS_DLY: %d\t", gpu->ctl1.rx.DQS_DLY); 963 | printf(" DQS_XTR: %d\t", gpu->ctl1.rx.DQS_XTR); 964 | printf(" DAT_2Y_DLY: %d\t", gpu->ctl1.rx.DAT_2Y_DLY); 965 | printf(" ADR_2Y_DLY: %d\t", gpu->ctl1.rx.ADR_2Y_DLY); 966 | printf(" CMD_2Y_DLY: %d\t", gpu->ctl1.rx.CMD_2Y_DLY); 967 | printf(" OEN_DLY: %d\n", gpu->ctl1.rx.OEN_DLY); 968 | printf(" \t OEN_EXT: %d\t", gpu->ctl1.rx.OEN_EXT); 969 | printf(" OEN_SEL: %d\t", gpu->ctl1.rx.OEN_SEL); 970 | printf(" ODT_DLY: %d\t", gpu->ctl1.rx.ODT_DLY); 971 | printf(" ODT_EXT: %d\t", gpu->ctl1.rx.ODT_EXT); 972 | printf(" ADR_DLY: %d\t", gpu->ctl1.rx.ADR_DLY); 973 | printf(" CMD_DLY: %d\n", gpu->ctl1.rx.CMD_DLY); 974 | printf("Channel 1's write command parameters:\n"); 975 | printf(" \t DAT_DLY: %d\t", gpu->ctl2.rx.DAT_DLY); 976 | printf(" DQS_DLY: %d\t", gpu->ctl2.rx.DQS_DLY); 977 | printf(" DQS_XTR: %d\t", gpu->ctl2.rx.DQS_XTR); 978 | printf(" DAT_2Y_DLY: %d\t", gpu->ctl2.rx.DAT_2Y_DLY); 979 | printf(" ADR_2Y_DLY: %d\t", gpu->ctl2.rx.ADR_2Y_DLY); 980 | printf(" CMD_2Y_DLY: %d\t", gpu->ctl2.rx.CMD_2Y_DLY); 981 | printf(" OEN_DLY: %d\n", gpu->ctl2.rx.OEN_DLY); 982 | printf(" \t OEN_EXT: %d\t", gpu->ctl2.rx.OEN_EXT); 983 | printf(" OEN_SEL: %d\t", gpu->ctl2.rx.OEN_SEL); 984 | printf(" ODT_DLY: %d\t", gpu->ctl2.rx.ODT_DLY); 985 | printf(" ODT_EXT: %d\t", gpu->ctl2.rx.ODT_EXT); 986 | printf(" ADR_DLY: %d\t", gpu->ctl2.rx.ADR_DLY); 987 | printf(" CMD_DLY: %d\n", gpu->ctl2.rx.CMD_DLY); 988 | printf("Power Mangement related timings:\n"); 989 | printf(" \t CKSRE: %d\t", gpu->pmg.rx.CKSRE); 990 | printf(" CKSRX: %d\t", gpu->pmg.rx.CKSRX); 991 | printf(" CKE_PULSE: %d\t", gpu->pmg.rx.CKE_PULSE); 992 | printf(" CKE: %d\t", gpu->pmg.rx.CKE); 993 | printf(" SEQ_IDLE: %d\n", gpu->pmg.rx.SEQ_IDLE); 994 | printf("RAS related timings:\n"); 995 | printf(" \t RC: %d\t", gpu->ras.RC); 996 | printf(" RRD: %d\t", gpu->ras.RRD); 997 | printf(" RCDRA: %d\t", gpu->ras.RCDRA); 998 | printf(" RCDR: %d\t", gpu->ras.RCDR); 999 | printf(" RCDWA: %d\t", gpu->ras.RCDWA); 1000 | printf(" RCDW: %d\n", gpu->ras.RCDW); 1001 | printf("CAS related timings:\n"); 1002 | printf(" \t CL: %d\t", gpu->cas.rx.CL); 1003 | printf(" W2R: %d\t", gpu->cas.rx.W2R); 1004 | printf(" R2R: %d\t", gpu->cas.rx.R2R); 1005 | printf(" CCDL: %d\t", gpu->cas.rx.CCDL); 1006 | printf(" R2W: %d\t", gpu->cas.rx.R2W); 1007 | printf(" NOPR: %d\t", gpu->cas.rx.NOPR); 1008 | printf(" NOPW: %d\n", gpu->cas.rx.NOPW); 1009 | printf("Misc. DRAM timings:\n"); 1010 | if (IsR9(chip->device_id)) 1011 | { 1012 | printf(" \t RFC: %d\t", gpu->misc.r9.RFC); 1013 | printf(" TRP: %d\t", gpu->misc.r9.TRP); 1014 | printf(" RP_RDA: %d\t", gpu->misc.r9.RP_RDA); 1015 | printf(" RP_WRA: %d\n", gpu->misc.r9.RP_WRA); 1016 | } 1017 | else 1018 | { 1019 | printf(" \t RFC: %d\t", gpu->misc.rx.RFC); 1020 | printf(" TRP: %d\t", gpu->misc.rx.TRP); 1021 | printf(" RP_RDA: %d\t", gpu->misc.rx.RP_RDA); 1022 | printf(" RP_WRA: %d\n", gpu->misc.rx.RP_WRA); 1023 | } 1024 | printf("Misc2. DRAM timings:\n"); 1025 | printf(" \t WDATATR: %d\t", gpu->misc2.rx.WDATATR); 1026 | printf(" T32AW: %d\t", gpu->misc2.rx.T32AW); 1027 | printf(" WEDC: %d\t", gpu->misc2.rx.WEDC); 1028 | printf(" REDC: %d\t", gpu->misc2.rx.REDC); 1029 | printf(" FAW: %d\t", gpu->misc2.rx.FAW); 1030 | printf(" PA2WDATA: %d\t", gpu->misc2.rx.PA2WDATA); 1031 | printf(" PA2RDATA: %d\n", gpu->misc2.rx.PA2RDATA); 1032 | printf("Mode Register 0:\n"); 1033 | printf(" \t WL: %d \t", gpu->smisc1.rx.WL); 1034 | printf(" CL: %d \t", gpu->smisc1.rx.CL); 1035 | printf(" TM: %d \t", gpu->smisc1.rx.TM); 1036 | printf(" WR: %d\n", gpu->smisc1.rx.WR); 1037 | printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA0); 1038 | printf(" BA1: %d\t ", gpu->smisc1.rx.BA1); 1039 | printf(" BA2: %d\t ", gpu->smisc1.rx.BA2); 1040 | printf(" BA3: %d\n", gpu->smisc1.rx.BA3); 1041 | printf("Mode Register 1:\n"); 1042 | printf(" \t DS: %d \t", gpu->smisc1.rx.DS); 1043 | printf(" DT: %d \t", gpu->smisc1.rx.DT); 1044 | printf(" ADR: %d\t ", gpu->smisc1.rx.ADR); 1045 | printf(" CAL: %d\t ", gpu->smisc1.rx.CAL); 1046 | printf(" PLL: %d\n ", gpu->smisc1.rx.PLL); 1047 | printf(" \t RDBI: %d\t", gpu->smisc1.rx.RDBI); 1048 | printf(" WDBI: %d\t", gpu->smisc1.rx.WDBI); 1049 | printf(" ABI: %d\t", gpu->smisc1.rx.ABI); 1050 | printf(" RESET: %d\n", gpu->smisc1.rx.RESET); 1051 | printf(" \t BA0: %d\t ", gpu->smisc1.rx.BA_0); 1052 | printf(" BA1: %d\t ", gpu->smisc1.rx.BA_1); 1053 | printf(" BA2: %d\t ", gpu->smisc1.rx.BA_2); 1054 | printf(" BA3: %d\n", gpu->smisc1.rx.BA_3); 1055 | printf("Mode Register 2:\n"); 1056 | printf(" \t OCD_DWN: %d\t", gpu->smisc2.OCD_DWN); 1057 | printf(" OCD_UP: %d\t", gpu->smisc2.OCD_UP); 1058 | printf(" WCK: %d\t ", gpu->smisc2.WCK); 1059 | printf(" ADR: %d\n ", gpu->smisc2.ADR); 1060 | printf(" \t BA0: %d\t ", gpu->smisc2.BA0); 1061 | printf(" BA1: %d\t ", gpu->smisc2.BA1); 1062 | printf(" BA2: %d\t ", gpu->smisc2.BA2); 1063 | printf(" BA3: %d\n", gpu->smisc2.BA3); 1064 | printf("Mode Register 3:\n"); 1065 | printf(" \t SR: %d \t", gpu->smisc2.SR); 1066 | printf(" WCK01: %d\t", gpu->smisc2.WCK01); 1067 | printf(" WCK23: %d\t", gpu->smisc2.WCK23); 1068 | printf(" WCK2CK: %d\t", gpu->smisc2.WCK2CK); 1069 | printf(" RDQS: %d\t", gpu->smisc2.RDQS); 1070 | printf(" INFO: %d\t", gpu->smisc2.INFO); 1071 | printf(" WCK2: %d\n", gpu->smisc2.WCK2); 1072 | printf(" \t BA0: %d\t ", gpu->smisc2.BA_0); 1073 | printf(" BA1: %d\t ", gpu->smisc2.BA_1); 1074 | printf(" BA2: %d\t ", gpu->smisc2.BA_2); 1075 | printf(" BA3: %d\n", gpu->smisc2.BA_3); 1076 | printf("Mode Register 4:\n"); 1077 | printf(" \t EDCHP: %d\t", gpu->smisc3.EDCHP); 1078 | printf(" CRCWL: %d\t", gpu->smisc3.CRCWL); 1079 | printf(" CRCRL: %d\t", gpu->smisc3.CRCRL); 1080 | printf(" RDCRC: %d\t", gpu->smisc3.RDCRC); 1081 | printf(" WRCRC: %d\t", gpu->smisc3.WRCRC); 1082 | printf(" EDC: %d\n ", gpu->smisc3.EDC); 1083 | printf(" \t BA0: %d\t ", gpu->smisc3.BA0); 1084 | printf(" BA1: %d\t ", gpu->smisc3.BA1); 1085 | printf(" BA2: %d\t ", gpu->smisc3.BA2); 1086 | printf(" BA3: %d\n", gpu->smisc3.BA3); 1087 | printf("Mode Register 5:\n"); 1088 | printf(" \t LP1: %d\t ", gpu->smisc3.LP1); 1089 | printf(" LP1: %d\t ", gpu->smisc3.LP1); 1090 | printf(" LP1: %d\t ", gpu->smisc3.LP1); 1091 | printf(" PLL: %d\t ", gpu->smisc3.PLL); 1092 | printf(" RAS: %d\n ", gpu->smisc3.RAS); 1093 | printf(" \t BA0: %d\t ", gpu->smisc3.BA_0); 1094 | printf(" BA1: %d\t ", gpu->smisc3.BA_1); 1095 | printf(" BA2: %d\t ", gpu->smisc3.BA_2); 1096 | printf(" BA3: %d\n", gpu->smisc3.BA_3); 1097 | printf("Mode Register 6:\n"); 1098 | printf(" \t WCK: %d\t ", gpu->smisc4.WCK); 1099 | printf(" VREFD_M: %d\t", gpu->smisc4.VREFD_M); 1100 | printf(" A_VREFD: %d\t", gpu->smisc4.A_VREFD); 1101 | printf(" VREFD: %d\t", gpu->smisc4.VREFD); 1102 | printf(" VREFD_O: %d\t", gpu->smisc4.VREFD_O); 1103 | printf(" VREFD_0_2: %d\n", gpu->smisc4.VREFD_0_2); 1104 | printf(" \t BA0: %d\t ", gpu->smisc4.BA0); 1105 | printf(" BA1: %d\t ", gpu->smisc4.BA1); 1106 | printf(" BA2: %d\t ", gpu->smisc4.BA2); 1107 | printf(" BA3: %d\n", gpu->smisc4.BA3); 1108 | printf("Mode Register 7:\n"); 1109 | printf(" \t PLL_STD: %d\t", gpu->smisc4.PLL_STD); 1110 | printf(" PLL_FL: %d\t", gpu->smisc4.PLL_FL); 1111 | printf(" PLL_DEL: %d\t", gpu->smisc4.PLL_DEL); 1112 | printf(" LF_MOD: %d\t", gpu->smisc4.LF_MOD); 1113 | printf(" AUTO: %d\t", gpu->smisc4.AUTO); 1114 | printf(" DQ: %d\n ", gpu->smisc4.DQ); 1115 | printf(" \t TEMP: %d\t", gpu->smisc4.TEMP); 1116 | printf(" HALF: %d\t", gpu->smisc4.HALF); 1117 | printf(" VDD_R: %d\t", gpu->smisc4.VDD_R); 1118 | printf(" RFU: %d\n ", gpu->smisc4.RFU); 1119 | printf(" \t BA0: %d\t ", gpu->smisc4.BA_0); 1120 | printf(" BA1: %d\t ", gpu->smisc4.BA_1); 1121 | printf(" BA2: %d\t ", gpu->smisc4.BA_2); 1122 | printf(" BA3: %d\n", gpu->smisc4.BA_3); 1123 | printf("Mode Register 15:\n"); 1124 | printf(" \t MRE0: %d\t", gpu->smisc7.MRE0); 1125 | printf(" MRE1: %d\t", gpu->smisc7.MRE1); 1126 | printf(" ADT: %d\t ", gpu->smisc7.ADT); 1127 | printf(" RFU: %d\n ", gpu->smisc7.RFU); 1128 | printf(" \t BA0: %d\t ", gpu->smisc7.BA0); 1129 | printf(" BA1: %d\t ", gpu->smisc7.BA1); 1130 | printf(" BA2: %d\t ", gpu->smisc7.BA2); 1131 | printf(" BA3: %d\n", gpu->smisc7.BA3); 1132 | printf("Mode Register 8:\n"); 1133 | printf(" \t CLEHF: %d\t", gpu->smisc8.CLEHF); 1134 | printf(" WREHF: %d\t", gpu->smisc8.WREHF); 1135 | printf(" RFU: %d\n ", gpu->smisc8.RFU); 1136 | printf(" \t BA0: %d\t ", gpu->smisc8.BA0); 1137 | printf(" BA1: %d\t ", gpu->smisc8.BA1); 1138 | printf(" BA2: %d\t ", gpu->smisc8.BA2); 1139 | printf(" BA3: %d\n", gpu->smisc8.BA3); 1140 | printf("DRAM Specific:\n"); 1141 | printf(" \t RASMACTWR: %d\t", gpu->dram1.RASMACTWR); 1142 | printf(" RASMACTRD: %d\t", gpu->dram1.RASMACTRD); 1143 | printf(" ACTWR: %d\t", gpu->dram1.ACTWR); 1144 | printf(" ACTRD: %d\n", gpu->dram1.ACTRD); 1145 | printf("DRAM2 Specific:\n"); 1146 | printf(" \t RAS2RAS: %d\t", gpu->dram2.RAS2RAS); 1147 | printf(" RP: %d\t", gpu->dram2.RP); 1148 | printf(" WRPLUSRP: %d\t", gpu->dram2.WRPLUSRP); 1149 | printf(" BUS_TURN: %d\n", gpu->dram2.BUS_TURN); 1150 | printf("Refresh Interval:\n"); 1151 | printf(" \t REF: %d\n", gpu->ref.REF); 1152 | printf("Training timings:\n"); 1153 | printf(" \t TWT2RT: %d\t", gpu->train.TWT2RT); 1154 | printf(" TARF2T: %d\t", gpu->train.TARF2T); 1155 | printf(" TT2ROW: %d\t", gpu->train.TT2ROW); 1156 | printf(" TLD2LD: %d\n", gpu->train.TLD2LD); 1157 | } 1158 | } 1159 | 1160 | HMODULE hEIO = NULL; 1161 | void LoadDriver() 1162 | { 1163 | hEIO = LoadLibraryA("EIO.dll"); 1164 | if (!hEIO) 1165 | { 1166 | printf("Failed to load EIO.dll\n"); 1167 | exit(EXIT_FAILURE); 1168 | } 1169 | g_hDevice = CreateFileA("\\\\.\\IOMap", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); 1170 | if (g_hDevice == INVALID_HANDLE_VALUE) 1171 | { 1172 | printf("Failed to open IOMap device\n"); 1173 | exit(EXIT_FAILURE); 1174 | } 1175 | } 1176 | void __cdecl UnloadDriver(void) 1177 | { 1178 | if (hEIO) 1179 | { 1180 | FreeLibrary(hEIO); 1181 | } 1182 | } 1183 | 1184 | int main(int argc, const char* argv[]) 1185 | { 1186 | if ((argc < 2) || (0 == strcasecmp("--help", argv[1])) || (0 == strcasecmp("--h", argv[1]))) 1187 | { 1188 | printf(" AMD Memory Tweak\n" 1189 | " Read and modify memory timings on the fly\n" 1190 | " By Eliovp & A.Solodovnikov\n\n" 1191 | " Global command line options:\n" 1192 | " --help|--h\tShow this output\n" 1193 | " --version|--v\tShow version info\n" 1194 | " --gpu|--i [comma-separated gpu indices]\tSelected device(s)\n" 1195 | " --current|--c\tList current timing values\n\n" 1196 | " Command line options: (HBM2)\n" 1197 | " --CL|--cl [value]\n" 1198 | " --RAS|--ras [value]\n" 1199 | " --RCDRD|--rcdrd [value]\n" 1200 | " --RCDWR|--rcdwr [value]\n" 1201 | " --RC|--rc [value]\n" 1202 | " --RP|--rp [value]\n" 1203 | " --RRDS|--rrds [value]\n" 1204 | " --RRDL|--rrdl [value]\n" 1205 | " --RTP|--rtp [value]\n" 1206 | " --FAW|--faw [value]\n" 1207 | " --CWL|--cwl [value]\n" 1208 | " --WTRS|--wtrs [value]\n" 1209 | " --WTRL|--wtrl [value]\n" 1210 | " --WR|--wr [value]\n" 1211 | " --RREFD|--rrefd [value]\n" 1212 | " --RDRDDD|--rdrddd [value]\n" 1213 | " --RDRDSD|--rdrdsd [value]\n" 1214 | " --RDRDSC|--rdrdsc [value]\n" 1215 | " --RDRDSCL|--rdrdscl [value]\n" 1216 | " --WRWRDD|--wrwrdd [value]\n" 1217 | " --WRWRSD|--wrwrsd [value]\n" 1218 | " --WRWRSC|--wrwrsc [value]\n" 1219 | " --WRWRSCL|--wrwrscl [value]\n" 1220 | " --WRRD|--wrrd [value]\n" 1221 | " --RDWR|--rdwr [value]\n" 1222 | " --REF|--ref [value]\n" 1223 | " --MRD|--mrd [value]\n" 1224 | " --MOD|--mod [value]\n" 1225 | " --XS|--xs [value]\n" 1226 | " --XSMRS|--xsmrs [value]\n" 1227 | " --PD|--pd [value]\n" 1228 | " --CKSRE|--cksre [value]\n" 1229 | " --CKSRX|--cksrx [value]\n" 1230 | " --RFCPB|--rfcpb [value]\n" 1231 | " --STAG|--stag [value]\n" 1232 | " --XP|--xp [value]\n" 1233 | " --CPDED|--cpded [value]\n" 1234 | " --CKE|--cke [value]\n" 1235 | " --RDDATA|--rddata [value]\n" 1236 | " --WRLAT|--wrlat [value]\n" 1237 | " --RDLAT|--rdlat [value]\n" 1238 | " --WRDATA|--wrdata [value]\n" 1239 | " --CKESTAG|--ckestag [value]\n" 1240 | " --RFC|--rfc [value]\n\n" 1241 | " Command line options: (HBM)\n" 1242 | " --DAT_DLY0|1|2|3 | --dat_dly0|1|2|3 [value]\n" 1243 | " --DQS_DLY0|1|2|3 | --dqs_dly0|1|2|3 [value]\n" 1244 | " --DQS_XTR0|1|2|3 | --dqs_xtr0|1|2|3 [value]\n" 1245 | " --OEN_DLY0|1|2|3 | --oen_dly0|1|2|3 [value]\n" 1246 | " --OEN_EXT0|1|2|3 | --oen_ext0|1|2|3 [value]\n" 1247 | " --OEN_SEL0|1|2|3 | --oen_sel0|1|2|3 [value]\n" 1248 | " --CMD_DLY0|1|2|3 | --cmd_dly0|1|2|3 [value]\n" 1249 | " --ADR_DLY0|1|2|3 | --adr_dly0|1|2|3 [value]\n" 1250 | " --CKSRE|--cksre [value]\n" 1251 | " --CKSRX|--cksrx [value]\n" 1252 | " --CKE_PULSE|--cke_pulse [value]\n" 1253 | " --CKE|--cke [value]\n" 1254 | " --SEQ_IDLE|--seq_idle [value]\n" 1255 | " --CL|--cl [value]\n" 1256 | " --W2R|--w2r [value]\n" 1257 | " --R2R|--r2r [value]\n" 1258 | " --CCDL|--ccdl [value]\n" 1259 | " --R2W|--r2w [value]\n" 1260 | " --NOPR|--nopr [value]\n" 1261 | " --NOPW|--nopw [value]\n" 1262 | " --RCDW|--rcdw [value]\n" 1263 | " --RCDWA|--rcdwa [value]\n" 1264 | " --RCDR|--rcdr [value]\n" 1265 | " --RCDRA|--rcdra [value]\n" 1266 | " --RRD|--rrd [value]\n" 1267 | " --RC|--rc [value]\n" 1268 | " --MRD|--mrd [value]\n" 1269 | " --RRDL|--rrdl [value]\n" 1270 | " --RFC|--rfc [value]\n" 1271 | " --TRP|--trp [value]\n" 1272 | " --RP_WRA|--rp_wra [value]\n" 1273 | " --RP_RDA|--rp_rda [value]\n" 1274 | " --WDATATR|--wdatatr [value]\n" 1275 | " --T32AW|--t32aw [value]\n" 1276 | " --CRCWL|--crcwl [value]\n" 1277 | " --CRCRL|--crcrl [value]\n" 1278 | " --FAW|--faw [value]\n" 1279 | " --PA2WDATA|--pa2wdata [value]\n" 1280 | " --PA2RDATA|--pa2rdata [value]\n" 1281 | " --DBR|--dbr [value]\n" 1282 | " --DBW|--dbw [value]\n" 1283 | " --TCSR|--tcsr [value]\n" 1284 | " --DQR|--dqr [value]\n" 1285 | " --DQW|--dqw [value]\n" 1286 | " --ADD_PAR|--add_par [value]\n" 1287 | " --TM|--tm [value]\n" 1288 | " --WR|--wr [value]\n" 1289 | " --NDS|--nds [value]\n" 1290 | " --WL|--wl [value]\n" 1291 | " --RL|--rl [value]\n" 1292 | " --APRAS|--apras [value]\n" 1293 | " --BG|--bg [value]\n" 1294 | " --BL|--bl [value]\n" 1295 | " --REF|--ref [value]\n" 1296 | " --ENB|--enb [value]\n" 1297 | " --CNT|--cnt [value]\n" 1298 | " --TRC|--trc [value]\n" 1299 | " --THRESH|--thresh [value]\n" 1300 | " --LEVEL|--level [value]\n" 1301 | " --PWRDOWN|--pwrdown [value]\n" 1302 | " --SHUTDOWN|--shutdown [value]\n" 1303 | " --EN_SHUTDOWN|--en_shutdown [value]\n" 1304 | " --OVERSAMPLE|--oversample [value]\n" 1305 | " --AVG_SAMPLE|--avg_sample [value]\n\n" 1306 | " Command line options: (GDDR5)\n" 1307 | " --DAT_DLY0|1 | --dat_dly0|1 [value]\n" 1308 | " --DQS_DLY0|1 | --dqs_dly0|1 [value]\n" 1309 | " --DQS_XTR0|1 | --dqs_xtr0|1 [value]\n" 1310 | " --DAT_2Y_DLY0|1 | --dat_2y_dly0|1 [value]\n" 1311 | " --ADR_2Y_DLY0|1 | --adr_2y_dly0|1 [value]\n" 1312 | " --CMD_2Y_DLY0|1 | --cmd_2y_dly0|1 [value]\n" 1313 | " --OEN_DLY0|1 | --oen_dly0|1 [value]\n" 1314 | " --OEN_EXT0|1 | --oen_ext0|1 [value]\n" 1315 | " --OEN_SEL0|1 | --oen_sel0|1 [value]\n" 1316 | " --ODT_DLY0|1 | --odt_dly0|1 [value]\n" 1317 | " --ODT_EXT0|1 | --odt_ext0|1 [value]\n" 1318 | " --ADR_DLY0|1 | --adr_dly0|1 [value]\n" 1319 | " --CMD_DLY0|1 | --cmd_dly0|1 [value]\n" 1320 | " --CKSRE|--cksre [value]\n" 1321 | " --CKSRX|--cksrx [value]\n" 1322 | " --CKE_PULSE|--cke_pulse [value]\n" 1323 | " --CKE|--cke [value]\n" 1324 | " --SEQ_IDLE|--seq_idle [value]\n" 1325 | " --CL|--cl [value]\n" 1326 | " --W2R|--w2r [value]\n" 1327 | " --R2R|--r2r [value]\n" 1328 | " --CCDL|--ccdl [value]\n" 1329 | " --R2W|--r2w [value]\n" 1330 | " --NOPR|--nopr [value]\n" 1331 | " --NOPW|--nopw [value]\n" 1332 | " --RCDW|--rcdw [value]\n" 1333 | " --RCDWA|--rcdwa [value]\n" 1334 | " --RCDR|--rcdr [value]\n" 1335 | " --RCDRA|--rcdra [value]\n" 1336 | " --RRD|--rrd [value]\n" 1337 | " --RC|--rc [value]\n" 1338 | " --RFC|--rfc [value]\n" 1339 | " --TRP|--trp [value]\n" 1340 | " --RP_WRA|--rp_wra [value]\n" 1341 | " --RP_RDA|--rp_rda [value]\n" 1342 | " --WDATATR|--wdatatr [value]\n" 1343 | " --T32AW|--t32aw [value]\n" 1344 | " --CRCWL|--crcwl [value]\n" 1345 | " --CRCRL|--crcrl [value]\n" 1346 | " --FAW|--faw [value]\n" 1347 | " --PA2WDATA|--pa2wdata [value]\n" 1348 | " --PA2RDATA|--pa2rdata [value]\n" 1349 | " --WL|--wl [value]\n" 1350 | " --MR0_CL|--mr0_cl [value]\n" 1351 | " --TM|--tm [value]\n" 1352 | " --WR|--wr [value]\n" 1353 | " --DS|--ds [value]\n" 1354 | " --DT|--dt [value]\n" 1355 | " --ADR|--adr [value]\n" 1356 | " --CAL|--cal [value]\n" 1357 | " --PLL|--pll [value]\n" 1358 | " --RDBI|--rdbi [value]\n" 1359 | " --WDBI|--wdbi [value]\n" 1360 | " --ABI|--abi [value]\n" 1361 | " --RESET|--reset [value]\n" 1362 | " --SR|--sr [value]\n" 1363 | " --WCK01|--wck01 [value]\n" 1364 | " --WCK23|--wck23 [value]\n" 1365 | " --WCK2CK|--wck2ck [value]\n" 1366 | " --RDQS|--rdqs [value]\n" 1367 | " --INFO|--info [value]\n" 1368 | " --WCK2|--wck2 [value]\n" 1369 | " --BG|--bg [value]\n" 1370 | " --EDCHP|--edchp [value]\n" 1371 | " --CRCWL|--crcwl [value]\n" 1372 | " --CRCRL|--crcrl [value]\n" 1373 | " --RDCRC|--rdcrc [value]\n" 1374 | " --WRCRC|--wrcrc [value]\n" 1375 | " --EDC|--edc [value]\n" 1376 | " --RAS|--ras [value]\n" 1377 | " --CLEHF|--clehf [value]\n" 1378 | " --WREHF|--wrehf [value]\n" 1379 | " --ACTRD|--actrd [value]\n" 1380 | " --ACTWR|--actwr [value]\n" 1381 | " --RASMACTRD|--rasmactrd [value]\n" 1382 | " --RASMACWTR|--rasmacwtr [value]\n" 1383 | " --RAS2RAS|--ras2ras [value]\n" 1384 | " --RP|--rp [value]\n" 1385 | " --WRPLUSRP|--wrplusrp [value]\n" 1386 | " --BUS_TURN|--bus_turn [value]\n" 1387 | " --REF|--ref [value]\n" 1388 | " --TWT2RT|--twt2rt [value]\n" 1389 | " --TARF2T|--tarf2t [value]\n" 1390 | " --TT2ROW|--tt2row [value]\n" 1391 | " --TLD2LD|--tld2ld [value]\n\n" 1392 | " HBM2 Example usage: ./amdmemtool --i 0,3,5 --faw 12 --RFC 208\n" 1393 | " HBM Example usage: ./amdmemtool --i 6 --ref 13\n" 1394 | " GDDR5 Example usage: ./amdmemtool --i 1,2,4 --RFC 43 --ras2ras 176\n\n" 1395 | " Make sure to run the program first with parameter --current to see what the current values are.\n" 1396 | " Current values may change based on state of the GPU,\n" 1397 | " in other words, make sure the GPU is under load when running --current\n" 1398 | " HBM2 Based GPU's do not need to be under load to apply timing changes.\n" 1399 | " Hint: Certain timings such as CL (Cas Latency) are stability timings, lowering these will lower stability.\n"); 1400 | return EXIT_SUCCESS; 1401 | } 1402 | 1403 | if (!strcasecmp("--version", argv[1]) || !strcasecmp("--v", argv[1])) 1404 | { 1405 | printf(VERSION); 1406 | return EXIT_SUCCESS; 1407 | } 1408 | 1409 | atexit(UnloadDriver); 1410 | LoadDriver(); 1411 | 1412 | const int PCI_VENDOR_ID_ATI = 0x1002; 1413 | VGAChip chips[64]; 1414 | int gpuCount = EnumerateGPUs(PCI_VENDOR_ID_ATI, chips, sizeof(chips)); 1415 | if (gpuCount <= 0) 1416 | { 1417 | printf("No AMD display devices have been found!\n"); 1418 | return EXIT_SUCCESS; 1419 | } 1420 | 1421 | GPU gpus[64]; 1422 | memset(gpus, 0, sizeof(gpus)); 1423 | for (int i = 0; i < gpuCount; i++) 1424 | { 1425 | GetVGAMMIOAddress(&chips[i], i); 1426 | GetVGABIOSAddress(&chips[i], i); 1427 | 1428 | GPU* gpu = &gpus[i]; 1429 | switch (DetermineMemoryType(chips[i].device_id)) 1430 | { 1431 | case HBM2: 1432 | for (int j = 0; j < sizeof(HBM2_TIMINGS) / 4; j++) 1433 | { 1434 | *((u32*)& gpu->hbm2 + j) = ReadMMIODword(AMD_TIMING_REGS_BASE_1 + j * sizeof(u32), i); 1435 | } 1436 | gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM2, i); 1437 | break; 1438 | case GDDR5: 1439 | gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0, i); 1440 | gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1, i); 1441 | gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING, i); 1442 | gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING, i); 1443 | gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING, i); 1444 | gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING, i); 1445 | gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2, i); 1446 | gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1, i); 1447 | gpu->smisc2.value = ReadMMIODword(MC_SEC_MISC2, i); 1448 | gpu->smisc3.value = ReadMMIODword(MC_SEC_MISC3, i); 1449 | gpu->smisc4.value = ReadMMIODword(MC_SEC_MISC4, i); 1450 | gpu->smisc7.value = ReadMMIODword(MC_SEC_MISC7, i); 1451 | gpu->smisc8.value = ReadMMIODword(MC_SEC_MISC8, i); 1452 | gpu->dram1.value = ReadMMIODword(MC_ARB_DRAM_TIMING, i); 1453 | gpu->dram2.value = ReadMMIODword(MC_ARB_DRAM_TIMING2, i); 1454 | gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, i); 1455 | gpu->train.value = ReadMMIODword(MC_SEQ_TRAINING, i); 1456 | gpu->man.value = ReadMMIODword(MANUFACTURER_ID, i); 1457 | break; 1458 | case HBM: 1459 | gpu->ctl1.value = ReadMMIODword(MC_SEQ_WR_CTL_D0_HBM, i); 1460 | gpu->ctl2.value = ReadMMIODword(MC_SEQ_WR_CTL_D1_HBM, i); 1461 | gpu->ctl3.value = ReadMMIODword(MC_SEQ_WR_CTL_D2_HBM, i); 1462 | gpu->ctl4.value = ReadMMIODword(MC_SEQ_WR_CTL_D3_HBM, i); 1463 | gpu->pmg.value = ReadMMIODword(MC_SEQ_PMG_TIMING_HBM, i); 1464 | gpu->ras.value = ReadMMIODword(MC_SEQ_RAS_TIMING_HBM, i); 1465 | gpu->cas.value = ReadMMIODword(MC_SEQ_CAS_TIMING_HBM, i); 1466 | gpu->misc.value = ReadMMIODword(MC_SEQ_MISC_TIMING_HBM, i); 1467 | gpu->misc2.value = ReadMMIODword(MC_SEQ_MISC_TIMING2_HBM, i); 1468 | gpu->smisc1.value = ReadMMIODword(MC_SEC_MISC1_HBM, i); 1469 | gpu->ref.value = ReadMMIODword(MC_ARB_RFSH_RATE, i); 1470 | gpu->ham.value = ReadMMIODword(MC_SEQ_ROW_HAMMER, i); 1471 | gpu->throt.value = ReadMMIODword(MC_THERMAL_THROTTLE, i); 1472 | gpu->man.value = ReadMMIODword(MANUFACTURER_ID_HBM, i); 1473 | break; 1474 | } 1475 | } 1476 | 1477 | // Scan some regs, you never know, you might find something useful ;-) 1478 | if (!strcasecmp("--scan", argv[1])) 1479 | { 1480 | if ((argc < 4) || memcmp(argv[2], "0x", 2) || memcmp(argv[3], "0x", 2)) 1481 | { 1482 | printf("--scan requires a range of addresses in hex format (for example 0x9A0290 0x9A02C4).\n"); 1483 | return EXIT_FAILURE; 1484 | } 1485 | u32 low = strtoul(argv[2] + 2, 0, 16); 1486 | if ((errno == EINVAL) || (errno == ERANGE)) 1487 | { 1488 | printf("Failed to parse %s as a hex number\n", argv[2]); 1489 | return EXIT_FAILURE; 1490 | } 1491 | u32 high = strtoul(argv[3] + 2, 0, 16); 1492 | if ((errno == EINVAL) || (errno == ERANGE)) 1493 | { 1494 | printf("Failed to parse %s as a hex number\n", argv[3]); 1495 | return EXIT_FAILURE; 1496 | } 1497 | 1498 | for (int index = 0; index < gpuCount; index++) 1499 | { 1500 | if (IsRelevantDeviceID(chips[index].device_id)) 1501 | { 1502 | printf("Scanning GPU %d\n", index); 1503 | for (u32 address = low; address <= high; address += sizeof(u32)) 1504 | { 1505 | u32 value = ReadMMIODword(address, index); 1506 | printf("0x%X: %08X\n", address, value); 1507 | Sleep(50); 1508 | } 1509 | } 1510 | } 1511 | return EXIT_SUCCESS; 1512 | } 1513 | 1514 | // Parses the command line arguments, and accumulates the changes. 1515 | for (int index = 0; index < gpuCount; index++) 1516 | { 1517 | GPU* gpu = &gpus[index]; 1518 | if (IsRelevantDeviceID(chips[index].device_id)) 1519 | { 1520 | u64 affectedGPUs = 0xFFFFFFFFFFFFFFFF; // apply to all GPUs by default 1521 | for (int i = 1; i < argc; i++) 1522 | { 1523 | if (!strcasecmp("--gpu", argv[i]) || !strcasecmp("--i", argv[i])) 1524 | { 1525 | if (i == (argc - 1)) 1526 | { 1527 | printf("Argument \"%s\" requires a parameter.\n", argv[i]); 1528 | return EXIT_FAILURE; 1529 | } 1530 | i++; 1531 | affectedGPUs = ParseIndicesArg(argv[i]); 1532 | } 1533 | else if (!strcasecmp("--current", argv[i]) || !strcasecmp("--c", argv[i])) 1534 | { 1535 | if (affectedGPUs & ((u64)1 << index)) 1536 | { 1537 | printf("GPU %d: %s\t", index, LookupDeviceName(chips[index].device_id)); 1538 | PrintCurrentValues(&chips[index], gpu); 1539 | } 1540 | } 1541 | else if (affectedGPUs & ((u64)1 << index)) 1542 | { 1543 | u32 value = 0; 1544 | if (DetermineMemoryType(chips[index].device_id) == HBM2) 1545 | { 1546 | if (ParseNumericArg(argc, argv, i, "--CL", value)) 1547 | { 1548 | gpu->hbm2.CL = value; 1549 | gpu->modify[0] = true; 1550 | gpu->modify[1] = true; 1551 | if (gpu->log[0]) strcat(gpu->log, ", "); 1552 | strcat(gpu->log, "CL"); 1553 | } 1554 | else if (ParseNumericArg(argc, argv, i, "--RAS", value)) 1555 | { 1556 | gpu->hbm2.RAS = value; 1557 | gpu->modify[0] = true; 1558 | gpu->modify[1] = true; 1559 | if (gpu->log[0]) strcat(gpu->log, ", "); 1560 | strcat(gpu->log, "RAS"); 1561 | } 1562 | else if (ParseNumericArg(argc, argv, i, "--RCDRD", value)) 1563 | { 1564 | gpu->hbm2.RCDRD = value; 1565 | gpu->modify[0] = true; 1566 | gpu->modify[1] = true; 1567 | if (gpu->log[0]) strcat(gpu->log, ", "); 1568 | strcat(gpu->log, "RCDRD"); 1569 | } 1570 | else if (ParseNumericArg(argc, argv, i, "--RCDWR", value)) 1571 | { 1572 | gpu->hbm2.RCDWR = value; 1573 | gpu->modify[0] = true; 1574 | gpu->modify[1] = true; 1575 | if (gpu->log[0]) strcat(gpu->log, ", "); 1576 | strcat(gpu->log, "RCDWR"); 1577 | } 1578 | else if (ParseNumericArg(argc, argv, i, "--RC", value)) 1579 | { 1580 | gpu->hbm2.RCAb = value; 1581 | gpu->hbm2.RCPb = value; 1582 | gpu->modify[0] = true; 1583 | gpu->modify[2] = true; 1584 | if (gpu->log[0]) strcat(gpu->log, ", "); 1585 | strcat(gpu->log, "RC"); 1586 | } 1587 | else if (ParseNumericArg(argc, argv, i, "--RP", value)) 1588 | { 1589 | gpu->hbm2.RPAb = value; 1590 | gpu->hbm2.RPPb = value; 1591 | gpu->modify[0] = true; 1592 | gpu->modify[2] = true; 1593 | if (gpu->log[0]) strcat(gpu->log, ", "); 1594 | strcat(gpu->log, "RP"); 1595 | } 1596 | else if (ParseNumericArg(argc, argv, i, "--RRDS", value)) 1597 | { 1598 | gpu->hbm2.RRDS = value; 1599 | gpu->modify[0] = true; 1600 | gpu->modify[3] = true; 1601 | if (gpu->log[0]) strcat(gpu->log, ", "); 1602 | strcat(gpu->log, "RRD"); 1603 | } 1604 | else if (ParseNumericArg(argc, argv, i, "--RRDL", value)) 1605 | { 1606 | gpu->hbm2.RRDL = value; 1607 | gpu->modify[0] = true; 1608 | gpu->modify[3] = true; 1609 | if (gpu->log[0]) strcat(gpu->log, ", "); 1610 | strcat(gpu->log, "RRD"); 1611 | } 1612 | else if (ParseNumericArg(argc, argv, i, "--RTP", value)) 1613 | { 1614 | gpu->hbm2.RTP = value; 1615 | gpu->modify[0] = true; 1616 | gpu->modify[3] = true; 1617 | if (gpu->log[0]) strcat(gpu->log, ", "); 1618 | strcat(gpu->log, "RTP"); 1619 | } 1620 | else if (ParseNumericArg(argc, argv, i, "--FAW", value)) 1621 | { 1622 | gpu->hbm2.FAW = value; 1623 | gpu->modify[0] = true; 1624 | gpu->modify[4] = true; 1625 | if (gpu->log[0]) strcat(gpu->log, ", "); 1626 | strcat(gpu->log, "FAW"); 1627 | } 1628 | else if (ParseNumericArg(argc, argv, i, "--CWL", value)) 1629 | { 1630 | gpu->hbm2.CWL = value; 1631 | gpu->modify[0] = true; 1632 | gpu->modify[5] = true; 1633 | if (gpu->log[0]) strcat(gpu->log, ", "); 1634 | strcat(gpu->log, "CWL"); 1635 | } 1636 | else if (ParseNumericArg(argc, argv, i, "--WTRS", value)) 1637 | { 1638 | gpu->hbm2.WTRS = value; 1639 | gpu->modify[0] = true; 1640 | gpu->modify[5] = true; 1641 | if (gpu->log[0]) strcat(gpu->log, ", "); 1642 | strcat(gpu->log, "WTRS"); 1643 | } 1644 | else if (ParseNumericArg(argc, argv, i, "--WTRL", value)) 1645 | { 1646 | gpu->hbm2.WTRL = value; 1647 | gpu->modify[0] = true; 1648 | gpu->modify[5] = true; 1649 | if (gpu->log[0]) strcat(gpu->log, ", "); 1650 | strcat(gpu->log, "WTRL"); 1651 | } 1652 | else if (ParseNumericArg(argc, argv, i, "--WR", value)) 1653 | { 1654 | gpu->hbm2.WR = value; 1655 | gpu->modify[0] = true; 1656 | gpu->modify[6] = true; 1657 | if (gpu->log[0]) strcat(gpu->log, ", "); 1658 | strcat(gpu->log, "WR"); 1659 | } 1660 | else if (ParseNumericArg(argc, argv, i, "--RREFD", value)) 1661 | { 1662 | gpu->hbm2.RREFD = value; 1663 | gpu->modify[0] = true; 1664 | gpu->modify[7] = true; 1665 | if (gpu->log[0]) strcat(gpu->log, ", "); 1666 | strcat(gpu->log, "RREFD"); 1667 | } 1668 | else if (ParseNumericArg(argc, argv, i, "--RDRDDD", value)) 1669 | { 1670 | gpu->hbm2.RDRDDD = value; 1671 | gpu->modify[0] = true; 1672 | gpu->modify[8] = true; 1673 | if (gpu->log[0]) strcat(gpu->log, ", "); 1674 | strcat(gpu->log, "RDRDDD"); 1675 | } 1676 | else if (ParseNumericArg(argc, argv, i, "--RDRDSD", value)) 1677 | { 1678 | gpu->hbm2.RDRDSD = value; 1679 | gpu->modify[0] = true; 1680 | gpu->modify[8] = true; 1681 | if (gpu->log[0]) strcat(gpu->log, ", "); 1682 | strcat(gpu->log, "RDRDSD"); 1683 | } 1684 | else if (ParseNumericArg(argc, argv, i, "--RDRDSC", value)) 1685 | { 1686 | gpu->hbm2.RDRDSC = value; 1687 | gpu->modify[0] = true; 1688 | gpu->modify[8] = true; 1689 | if (gpu->log[0]) strcat(gpu->log, ", "); 1690 | strcat(gpu->log, "RDRDSC"); 1691 | } 1692 | else if (ParseNumericArg(argc, argv, i, "--RDRDSCL", value)) 1693 | { 1694 | gpu->hbm2.RDRDSCL = value; 1695 | gpu->modify[0] = true; 1696 | gpu->modify[8] = true; 1697 | if (gpu->log[0]) strcat(gpu->log, ", "); 1698 | strcat(gpu->log, "RDRDSCL"); 1699 | } 1700 | else if (ParseNumericArg(argc, argv, i, "--WRWRDD", value)) 1701 | { 1702 | gpu->hbm2.WRWRDD = value; 1703 | gpu->modify[0] = true; 1704 | gpu->modify[9] = true; 1705 | if (gpu->log[0]) strcat(gpu->log, ", "); 1706 | strcat(gpu->log, "WRWRDD"); 1707 | } 1708 | else if (ParseNumericArg(argc, argv, i, "--WRWRSD", value)) 1709 | { 1710 | gpu->hbm2.WRWRSD = value; 1711 | gpu->modify[0] = true; 1712 | gpu->modify[9] = true; 1713 | if (gpu->log[0]) strcat(gpu->log, ", "); 1714 | strcat(gpu->log, "WRWRSD"); 1715 | } 1716 | else if (ParseNumericArg(argc, argv, i, "--WRWRSC", value)) 1717 | { 1718 | gpu->hbm2.WRWRSC = value; 1719 | gpu->modify[0] = true; 1720 | gpu->modify[9] = true; 1721 | if (gpu->log[0]) strcat(gpu->log, ", "); 1722 | strcat(gpu->log, "WRWRSC"); 1723 | } 1724 | else if (ParseNumericArg(argc, argv, i, "--WRWRSCL", value)) 1725 | { 1726 | gpu->hbm2.WRWRSCL = value; 1727 | gpu->modify[0] = true; 1728 | gpu->modify[9] = true; 1729 | if (gpu->log[0]) strcat(gpu->log, ", "); 1730 | strcat(gpu->log, "WRWRSCL"); 1731 | } 1732 | else if (ParseNumericArg(argc, argv, i, "--WRRD", value)) 1733 | { 1734 | gpu->hbm2.WRRD = value; 1735 | gpu->modify[0] = true; 1736 | gpu->modify[10] = true; 1737 | if (gpu->log[0]) strcat(gpu->log, ", "); 1738 | strcat(gpu->log, "WRRD"); 1739 | } 1740 | else if (ParseNumericArg(argc, argv, i, "--RDWR", value)) 1741 | { 1742 | gpu->hbm2.RDWR = value; 1743 | gpu->modify[0] = true; 1744 | gpu->modify[10] = true; 1745 | if (gpu->log[0]) strcat(gpu->log, ", "); 1746 | strcat(gpu->log, "RDWR"); 1747 | } 1748 | else if (ParseNumericArg(argc, argv, i, "--REF", value)) 1749 | { 1750 | gpu->hbm2.REF = value; 1751 | gpu->modify[0] = true; 1752 | gpu->modify[12] = true; 1753 | if (gpu->log[0]) strcat(gpu->log, ", "); 1754 | strcat(gpu->log, "REF"); 1755 | } 1756 | else if (ParseNumericArg(argc, argv, i, "--MRD", value)) 1757 | { 1758 | gpu->hbm2.MRD = value; 1759 | gpu->modify[0] = true; 1760 | gpu->modify[13] = true; 1761 | if (gpu->log[0]) strcat(gpu->log, ", "); 1762 | strcat(gpu->log, "MRD"); 1763 | } 1764 | else if (ParseNumericArg(argc, argv, i, "--MOD", value)) 1765 | { 1766 | gpu->hbm2.MOD = value; 1767 | gpu->modify[0] = true; 1768 | gpu->modify[13] = true; 1769 | if (gpu->log[0]) strcat(gpu->log, ", "); 1770 | strcat(gpu->log, "MOD"); 1771 | } 1772 | else if (ParseNumericArg(argc, argv, i, "--XS", value)) 1773 | { 1774 | gpu->hbm2.XS = value; 1775 | gpu->modify[0] = true; 1776 | gpu->modify[14] = true; 1777 | if (gpu->log[0]) strcat(gpu->log, ", "); 1778 | strcat(gpu->log, "XS"); 1779 | } 1780 | else if (ParseNumericArg(argc, argv, i, "--XSMRS", value)) 1781 | { 1782 | gpu->hbm2.XSMRS = value; 1783 | gpu->modify[0] = true; 1784 | gpu->modify[16] = true; 1785 | if (gpu->log[0]) strcat(gpu->log, ", "); 1786 | strcat(gpu->log, "XSMRS"); 1787 | } 1788 | else if (ParseNumericArg(argc, argv, i, "--PD", value)) 1789 | { 1790 | gpu->hbm2.PD = value; 1791 | gpu->modify[0] = true; 1792 | gpu->modify[17] = true; 1793 | if (gpu->log[0]) strcat(gpu->log, ", "); 1794 | strcat(gpu->log, "PD"); 1795 | } 1796 | else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) 1797 | { 1798 | gpu->hbm2.CKSRE = value; 1799 | gpu->modify[0] = true; 1800 | gpu->modify[17] = true; 1801 | if (gpu->log[0]) strcat(gpu->log, ", "); 1802 | strcat(gpu->log, "CKSRE"); 1803 | } 1804 | else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) 1805 | { 1806 | gpu->hbm2.CKSRX = value; 1807 | gpu->modify[0] = true; 1808 | gpu->modify[17] = true; 1809 | if (gpu->log[0]) strcat(gpu->log, ", "); 1810 | strcat(gpu->log, "CKSRX"); 1811 | } 1812 | else if (ParseNumericArg(argc, argv, i, "--RFCPB", value)) 1813 | { 1814 | gpu->hbm2.RFCPB = value; 1815 | gpu->modify[0] = true; 1816 | gpu->modify[20] = true; 1817 | if (gpu->log[0]) strcat(gpu->log, ", "); 1818 | strcat(gpu->log, "RFCPB"); 1819 | } 1820 | else if (ParseNumericArg(argc, argv, i, "--STAG", value)) 1821 | { 1822 | gpu->hbm2.STAG = value; 1823 | gpu->modify[0] = true; 1824 | gpu->modify[20] = true; 1825 | if (gpu->log[0]) strcat(gpu->log, ", "); 1826 | strcat(gpu->log, "STAG"); 1827 | } 1828 | else if (ParseNumericArg(argc, argv, i, "--XP", value)) 1829 | { 1830 | gpu->hbm2.XP = value; 1831 | gpu->modify[0] = true; 1832 | gpu->modify[21] = true; 1833 | if (gpu->log[0]) strcat(gpu->log, ", "); 1834 | strcat(gpu->log, "XP"); 1835 | } 1836 | else if (ParseNumericArg(argc, argv, i, "--CPDED", value)) 1837 | { 1838 | gpu->hbm2.CPDED = value; 1839 | gpu->modify[0] = true; 1840 | gpu->modify[21] = true; 1841 | if (gpu->log[0]) strcat(gpu->log, ", "); 1842 | strcat(gpu->log, "CPDED"); 1843 | } 1844 | else if (ParseNumericArg(argc, argv, i, "--CKE", value)) 1845 | { 1846 | gpu->hbm2.CKE = value; 1847 | gpu->modify[0] = true; 1848 | gpu->modify[21] = true; 1849 | if (gpu->log[0]) strcat(gpu->log, ", "); 1850 | strcat(gpu->log, "CKE"); 1851 | } 1852 | else if (ParseNumericArg(argc, argv, i, "--RDDATA", value)) 1853 | { 1854 | gpu->hbm2.RDDATA = value; 1855 | gpu->modify[0] = true; 1856 | gpu->modify[22] = true; 1857 | if (gpu->log[0]) strcat(gpu->log, ", "); 1858 | strcat(gpu->log, "RDDATA"); 1859 | } 1860 | else if (ParseNumericArg(argc, argv, i, "--WRLAT", value)) 1861 | { 1862 | gpu->hbm2.WRLAT = value; 1863 | gpu->modify[0] = true; 1864 | gpu->modify[22] = true; 1865 | if (gpu->log[0]) strcat(gpu->log, ", "); 1866 | strcat(gpu->log, "WRLAT"); 1867 | } 1868 | else if (ParseNumericArg(argc, argv, i, "--RDLAT", value)) 1869 | { 1870 | gpu->hbm2.RDLAT = value; 1871 | gpu->modify[0] = true; 1872 | gpu->modify[22] = true; 1873 | if (gpu->log[0]) strcat(gpu->log, ", "); 1874 | strcat(gpu->log, "RDLAT"); 1875 | } 1876 | else if (ParseNumericArg(argc, argv, i, "--WRDATA", value)) 1877 | { 1878 | gpu->hbm2.WRDATA = value; 1879 | gpu->modify[0] = true; 1880 | gpu->modify[22] = true; 1881 | if (gpu->log[0]) strcat(gpu->log, ", "); 1882 | strcat(gpu->log, "WRDATA"); 1883 | } 1884 | else if (ParseNumericArg(argc, argv, i, "--CKESTAG", value)) 1885 | { 1886 | gpu->hbm2.CKESTAG = value; 1887 | gpu->modify[0] = true; 1888 | gpu->modify[23] = true; 1889 | if (gpu->log[0]) strcat(gpu->log, ", "); 1890 | strcat(gpu->log, "CKESTAG"); 1891 | } 1892 | else if (ParseNumericArg(argc, argv, i, "--RFC", value)) 1893 | { 1894 | gpu->hbm2.RFC = value; 1895 | gpu->modify[0] = true; 1896 | gpu->modify[24] = true; 1897 | if (gpu->log[0]) strcat(gpu->log, ", "); 1898 | strcat(gpu->log, "RFC"); 1899 | } 1900 | } 1901 | else if (DetermineMemoryType(chips[index].device_id) == HBM) { 1902 | if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) 1903 | { 1904 | gpu->ctl1.hbm.DAT_DLY = value; 1905 | gpu->modify[0] = true; 1906 | if (gpu->log[0]) strcat(gpu->log, ", "); 1907 | strcat(gpu->log, "DAT_DLY0"); 1908 | } 1909 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) 1910 | { 1911 | gpu->ctl1.hbm.DQS_DLY = value; 1912 | gpu->modify[0] = true; 1913 | if (gpu->log[0]) strcat(gpu->log, ", "); 1914 | strcat(gpu->log, "DQS_DLY0"); 1915 | } 1916 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) 1917 | { 1918 | gpu->ctl1.hbm.DQS_XTR = value; 1919 | gpu->modify[0] = true; 1920 | if (gpu->log[0]) strcat(gpu->log, ", "); 1921 | strcat(gpu->log, "DQS_XTR0"); 1922 | } 1923 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) 1924 | { 1925 | gpu->ctl1.hbm.OEN_DLY = value; 1926 | gpu->modify[0] = true; 1927 | if (gpu->log[0]) strcat(gpu->log, ", "); 1928 | strcat(gpu->log, "OEN_DLY0"); 1929 | } 1930 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) 1931 | { 1932 | gpu->ctl1.hbm.OEN_EXT = value; 1933 | gpu->modify[0] = true; 1934 | if (gpu->log[0]) strcat(gpu->log, ", "); 1935 | strcat(gpu->log, "OEN_EXT0"); 1936 | } 1937 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) 1938 | { 1939 | gpu->ctl1.hbm.OEN_SEL = value; 1940 | gpu->modify[0] = true; 1941 | if (gpu->log[0]) strcat(gpu->log, ", "); 1942 | strcat(gpu->log, "OEN_SEL0"); 1943 | } 1944 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) 1945 | { 1946 | gpu->ctl1.hbm.CMD_DLY = value; 1947 | gpu->modify[0] = true; 1948 | if (gpu->log[0]) strcat(gpu->log, ", "); 1949 | strcat(gpu->log, "CMD_DLY0"); 1950 | } 1951 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) 1952 | { 1953 | gpu->ctl1.hbm.ADR_DLY = value; 1954 | gpu->modify[0] = true; 1955 | if (gpu->log[0]) strcat(gpu->log, ", "); 1956 | strcat(gpu->log, "ADR_DLY0"); 1957 | } 1958 | else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) 1959 | { 1960 | gpu->ctl2.hbm.DAT_DLY = value; 1961 | gpu->modify[1] = true; 1962 | if (gpu->log[0]) strcat(gpu->log, ", "); 1963 | strcat(gpu->log, "DAT_DLY1"); 1964 | } 1965 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) 1966 | { 1967 | gpu->ctl2.hbm.DQS_DLY = value; 1968 | gpu->modify[1] = true; 1969 | if (gpu->log[0]) strcat(gpu->log, ", "); 1970 | strcat(gpu->log, "DQS_DLY1"); 1971 | } 1972 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) 1973 | { 1974 | gpu->ctl2.hbm.DQS_XTR = value; 1975 | gpu->modify[1] = true; 1976 | if (gpu->log[0]) strcat(gpu->log, ", "); 1977 | strcat(gpu->log, "DQS_XTR1"); 1978 | } 1979 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) 1980 | { 1981 | gpu->ctl2.hbm.OEN_DLY = value; 1982 | gpu->modify[1] = true; 1983 | if (gpu->log[0]) strcat(gpu->log, ", "); 1984 | strcat(gpu->log, "OEN_DLY1"); 1985 | } 1986 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) 1987 | { 1988 | gpu->ctl2.hbm.OEN_EXT = value; 1989 | gpu->modify[1] = true; 1990 | if (gpu->log[0]) strcat(gpu->log, ", "); 1991 | strcat(gpu->log, "OEN_EXT1"); 1992 | } 1993 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) 1994 | { 1995 | gpu->ctl2.hbm.OEN_SEL = value; 1996 | gpu->modify[1] = true; 1997 | if (gpu->log[0]) strcat(gpu->log, ", "); 1998 | strcat(gpu->log, "OEN_SEL1"); 1999 | } 2000 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) 2001 | { 2002 | gpu->ctl2.hbm.CMD_DLY = value; 2003 | gpu->modify[1] = true; 2004 | if (gpu->log[0]) strcat(gpu->log, ", "); 2005 | strcat(gpu->log, "CMD_DLY1"); 2006 | } 2007 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) 2008 | { 2009 | gpu->ctl2.hbm.ADR_DLY = value; 2010 | gpu->modify[1] = true; 2011 | if (gpu->log[0]) strcat(gpu->log, ", "); 2012 | strcat(gpu->log, "ADR_DLY1"); 2013 | } 2014 | else if (ParseNumericArg(argc, argv, i, "--DAT_DLY2", value)) 2015 | { 2016 | gpu->ctl3.DAT_DLY = value; 2017 | gpu->modify[2] = true; 2018 | if (gpu->log[0]) strcat(gpu->log, ", "); 2019 | strcat(gpu->log, "DAT_DLY2"); 2020 | } 2021 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY2", value)) 2022 | { 2023 | gpu->ctl3.DQS_DLY = value; 2024 | gpu->modify[2] = true; 2025 | if (gpu->log[0]) strcat(gpu->log, ", "); 2026 | strcat(gpu->log, "DQS_DLY2"); 2027 | } 2028 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR2", value)) 2029 | { 2030 | gpu->ctl3.DQS_XTR = value; 2031 | gpu->modify[2] = true; 2032 | if (gpu->log[0]) strcat(gpu->log, ", "); 2033 | strcat(gpu->log, "DQS_XTR2"); 2034 | } 2035 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY2", value)) 2036 | { 2037 | gpu->ctl3.OEN_DLY = value; 2038 | gpu->modify[2] = true; 2039 | if (gpu->log[0]) strcat(gpu->log, ", "); 2040 | strcat(gpu->log, "OEN_DLY2"); 2041 | } 2042 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT2", value)) 2043 | { 2044 | gpu->ctl3.OEN_EXT = value; 2045 | gpu->modify[2] = true; 2046 | if (gpu->log[0]) strcat(gpu->log, ", "); 2047 | strcat(gpu->log, "OEN_EXT2"); 2048 | } 2049 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL2", value)) 2050 | { 2051 | gpu->ctl3.OEN_SEL = value; 2052 | gpu->modify[2] = true; 2053 | if (gpu->log[0]) strcat(gpu->log, ", "); 2054 | strcat(gpu->log, "OEN_SEL2"); 2055 | } 2056 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY2", value)) 2057 | { 2058 | gpu->ctl3.CMD_DLY = value; 2059 | gpu->modify[2] = true; 2060 | if (gpu->log[0]) strcat(gpu->log, ", "); 2061 | strcat(gpu->log, "CMD_DLY2"); 2062 | } 2063 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY2", value)) 2064 | { 2065 | gpu->ctl3.ADR_DLY = value; 2066 | gpu->modify[2] = true; 2067 | if (gpu->log[0]) strcat(gpu->log, ", "); 2068 | strcat(gpu->log, "ADR_DLY2"); 2069 | } 2070 | else if (ParseNumericArg(argc, argv, i, "--DAT_DLY3", value)) 2071 | { 2072 | gpu->ctl4.DAT_DLY = value; 2073 | gpu->modify[3] = true; 2074 | if (gpu->log[0]) strcat(gpu->log, ", "); 2075 | strcat(gpu->log, "DAT_DLY3"); 2076 | } 2077 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY3", value)) 2078 | { 2079 | gpu->ctl4.DQS_DLY = value; 2080 | gpu->modify[3] = true; 2081 | if (gpu->log[0]) strcat(gpu->log, ", "); 2082 | strcat(gpu->log, "DQS_DLY3"); 2083 | } 2084 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR3", value)) 2085 | { 2086 | gpu->ctl4.DQS_XTR = value; 2087 | gpu->modify[3] = true; 2088 | if (gpu->log[0]) strcat(gpu->log, ", "); 2089 | strcat(gpu->log, "DQS_XTR3"); 2090 | } 2091 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY3", value)) 2092 | { 2093 | gpu->ctl4.OEN_DLY = value; 2094 | gpu->modify[3] = true; 2095 | if (gpu->log[0]) strcat(gpu->log, ", "); 2096 | strcat(gpu->log, "OEN_DLY3"); 2097 | } 2098 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT3", value)) 2099 | { 2100 | gpu->ctl4.OEN_EXT = value; 2101 | gpu->modify[3] = true; 2102 | if (gpu->log[0]) strcat(gpu->log, ", "); 2103 | strcat(gpu->log, "OEN_EXT3"); 2104 | } 2105 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL3", value)) 2106 | { 2107 | gpu->ctl4.OEN_SEL = value; 2108 | gpu->modify[3] = true; 2109 | if (gpu->log[0]) strcat(gpu->log, ", "); 2110 | strcat(gpu->log, "OEN_SEL3"); 2111 | } 2112 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY3", value)) 2113 | { 2114 | gpu->ctl4.CMD_DLY = value; 2115 | gpu->modify[3] = true; 2116 | if (gpu->log[0]) strcat(gpu->log, ", "); 2117 | strcat(gpu->log, "CMD_DLY3"); 2118 | } 2119 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY3", value)) 2120 | { 2121 | gpu->ctl4.ADR_DLY = value; 2122 | gpu->modify[3] = true; 2123 | if (gpu->log[0]) strcat(gpu->log, ", "); 2124 | strcat(gpu->log, "ADR_DLY3"); 2125 | } 2126 | else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) 2127 | { 2128 | gpu->pmg.hbm.CKSRE = value; 2129 | gpu->modify[4] = true; 2130 | if (gpu->log[0]) strcat(gpu->log, ", "); 2131 | strcat(gpu->log, "CKSRE"); 2132 | } 2133 | else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) 2134 | { 2135 | gpu->pmg.hbm.CKSRX = value; 2136 | gpu->modify[4] = true; 2137 | if (gpu->log[0]) strcat(gpu->log, ", "); 2138 | strcat(gpu->log, "CKSRX"); 2139 | } 2140 | else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) 2141 | { 2142 | gpu->pmg.hbm.CKE_PULSE = value; 2143 | gpu->modify[4] = true; 2144 | if (gpu->log[0]) strcat(gpu->log, ", "); 2145 | strcat(gpu->log, "CKE_PULSE"); 2146 | } 2147 | else if (ParseNumericArg(argc, argv, i, "--CKE", value)) 2148 | { 2149 | gpu->pmg.hbm.CKE = value; 2150 | gpu->modify[4] = true; 2151 | if (gpu->log[0]) strcat(gpu->log, ", "); 2152 | strcat(gpu->log, "CKE"); 2153 | } 2154 | else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) 2155 | { 2156 | gpu->pmg.hbm.SEQ_IDLE = value; 2157 | gpu->modify[4] = true; 2158 | if (gpu->log[0]) strcat(gpu->log, ", "); 2159 | strcat(gpu->log, "SEQ_IDLE"); 2160 | } 2161 | else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) 2162 | { 2163 | gpu->ras.RCDW = value; 2164 | gpu->modify[5] = true; 2165 | if (gpu->log[0]) strcat(gpu->log, ", "); 2166 | strcat(gpu->log, "RCDW"); 2167 | } 2168 | else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) 2169 | { 2170 | gpu->ras.RCDWA = value; 2171 | gpu->modify[5] = true; 2172 | if (gpu->log[0]) strcat(gpu->log, ", "); 2173 | strcat(gpu->log, "RCDWA"); 2174 | } 2175 | else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) 2176 | { 2177 | gpu->ras.RCDR = value; 2178 | gpu->modify[5] = true; 2179 | if (gpu->log[0]) strcat(gpu->log, ", "); 2180 | strcat(gpu->log, "RCDR"); 2181 | } 2182 | else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) 2183 | { 2184 | gpu->ras.RCDRA = value; 2185 | gpu->modify[5] = true; 2186 | if (gpu->log[0]) strcat(gpu->log, ", "); 2187 | strcat(gpu->log, "RCDRA"); 2188 | } 2189 | else if (ParseNumericArg(argc, argv, i, "--RRD", value)) 2190 | { 2191 | gpu->ras.RRD = value; 2192 | gpu->modify[5] = true; 2193 | if (gpu->log[0]) strcat(gpu->log, ", "); 2194 | strcat(gpu->log, "RRD"); 2195 | } 2196 | else if (ParseNumericArg(argc, argv, i, "--RC", value)) 2197 | { 2198 | gpu->ras.RC = value; 2199 | gpu->modify[5] = true; 2200 | if (gpu->log[0]) strcat(gpu->log, ", "); 2201 | strcat(gpu->log, "RC"); 2202 | } 2203 | else if (ParseNumericArg(argc, argv, i, "--CL", value)) 2204 | { 2205 | gpu->cas.hbm.CL = value; 2206 | gpu->modify[6] = true; 2207 | if (gpu->log[0]) strcat(gpu->log, ", "); 2208 | strcat(gpu->log, "CL"); 2209 | } 2210 | else if (ParseNumericArg(argc, argv, i, "--W2R", value)) 2211 | { 2212 | gpu->cas.hbm.W2R = value; 2213 | gpu->modify[6] = true; 2214 | if (gpu->log[0]) strcat(gpu->log, ", "); 2215 | strcat(gpu->log, "W2R"); 2216 | } 2217 | else if (ParseNumericArg(argc, argv, i, "--R2R", value)) 2218 | { 2219 | gpu->cas.hbm.R2R = value; 2220 | gpu->modify[6] = true; 2221 | if (gpu->log[0]) strcat(gpu->log, ", "); 2222 | strcat(gpu->log, "R2R"); 2223 | } 2224 | else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) 2225 | { 2226 | gpu->cas.hbm.CCDL = value; 2227 | gpu->modify[6] = true; 2228 | if (gpu->log[0]) strcat(gpu->log, ", "); 2229 | strcat(gpu->log, "CCDL"); 2230 | } 2231 | else if (ParseNumericArg(argc, argv, i, "--R2W", value)) 2232 | { 2233 | gpu->cas.hbm.R2W = value; 2234 | gpu->modify[6] = true; 2235 | if (gpu->log[0]) strcat(gpu->log, ", "); 2236 | strcat(gpu->log, "R2W"); 2237 | } 2238 | else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) 2239 | { 2240 | gpu->cas.hbm.NOPR = value; 2241 | gpu->modify[6] = true; 2242 | if (gpu->log[0]) strcat(gpu->log, ", "); 2243 | strcat(gpu->log, "NOPR"); 2244 | } 2245 | else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) 2246 | { 2247 | gpu->cas.hbm.NOPW = value; 2248 | gpu->modify[6] = true; 2249 | if (gpu->log[0]) strcat(gpu->log, ", "); 2250 | strcat(gpu->log, "NOPW"); 2251 | } 2252 | else if (ParseNumericArg(argc, argv, i, "--MRD", value)) 2253 | { 2254 | gpu->misc.hbm.MRD = value; 2255 | gpu->modify[7] = true; 2256 | if (gpu->log[0]) strcat(gpu->log, ", "); 2257 | strcat(gpu->log, "MRD"); 2258 | } 2259 | else if (ParseNumericArg(argc, argv, i, "--RRDL", value)) 2260 | { 2261 | gpu->misc.hbm.RRDL = value; 2262 | gpu->modify[7] = true; 2263 | if (gpu->log[0]) strcat(gpu->log, ", "); 2264 | strcat(gpu->log, "RRDL"); 2265 | } 2266 | else if (ParseNumericArg(argc, argv, i, "--RFC", value)) 2267 | { 2268 | gpu->misc.hbm.RFC = value; 2269 | gpu->modify[7] = true; 2270 | if (gpu->log[0]) strcat(gpu->log, ", "); 2271 | strcat(gpu->log, "RFC"); 2272 | } 2273 | else if (ParseNumericArg(argc, argv, i, "--TRP", value)) 2274 | { 2275 | gpu->misc.hbm.TRP = value; 2276 | gpu->modify[7] = true; 2277 | if (gpu->log[0]) strcat(gpu->log, ", "); 2278 | strcat(gpu->log, "TRP"); 2279 | } 2280 | else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) 2281 | { 2282 | gpu->misc.hbm.RP_RDA = value; 2283 | gpu->modify[7] = true; 2284 | if (gpu->log[0]) strcat(gpu->log, ", "); 2285 | strcat(gpu->log, "RP_RDA"); 2286 | } 2287 | else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) 2288 | { 2289 | gpu->misc.hbm.RP_WRA = value; 2290 | gpu->modify[7] = true; 2291 | if (gpu->log[0]) strcat(gpu->log, ", "); 2292 | strcat(gpu->log, "RP_WRA"); 2293 | } 2294 | else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) 2295 | { 2296 | gpu->misc2.hbm.WDATATR = value; 2297 | gpu->modify[8] = true; 2298 | if (gpu->log[0]) strcat(gpu->log, ", "); 2299 | strcat(gpu->log, "WDATATR"); 2300 | } 2301 | else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) 2302 | { 2303 | gpu->misc2.hbm.T32AW = value; 2304 | gpu->modify[8] = true; 2305 | if (gpu->log[0]) strcat(gpu->log, ", "); 2306 | strcat(gpu->log, "T32AW"); 2307 | } 2308 | else if (ParseNumericArg(argc, argv, i, "--RPAR", value)) 2309 | { 2310 | gpu->misc2.hbm.RPAR = value; 2311 | gpu->modify[8] = true; 2312 | if (gpu->log[0]) strcat(gpu->log, ", "); 2313 | strcat(gpu->log, "RPAR"); 2314 | } 2315 | else if (ParseNumericArg(argc, argv, i, "--WPAR", value)) 2316 | { 2317 | gpu->misc2.hbm.WPAR = value; 2318 | gpu->modify[8] = true; 2319 | if (gpu->log[0]) strcat(gpu->log, ", "); 2320 | strcat(gpu->log, "WPAR"); 2321 | } 2322 | else if (ParseNumericArg(argc, argv, i, "--FAW", value)) 2323 | { 2324 | gpu->misc2.hbm.FAW = value; 2325 | gpu->modify[8] = true; 2326 | if (gpu->log[0]) strcat(gpu->log, ", "); 2327 | strcat(gpu->log, "FAW"); 2328 | } 2329 | else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) 2330 | { 2331 | gpu->misc2.hbm.PA2WDATA = value; 2332 | gpu->modify[8] = true; 2333 | if (gpu->log[0]) strcat(gpu->log, ", "); 2334 | strcat(gpu->log, "P2WDATA"); 2335 | } 2336 | else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) 2337 | { 2338 | gpu->misc2.hbm.PA2RDATA = value; 2339 | gpu->modify[8] = true; 2340 | if (gpu->log[0]) strcat(gpu->log, ", "); 2341 | strcat(gpu->log, "PA2RDATA"); 2342 | } 2343 | else if (ParseNumericArg(argc, argv, i, "--DBR", value)) 2344 | { 2345 | gpu->smisc1.hbm.DBR = value; 2346 | gpu->modify[9] = true; 2347 | if (gpu->log[0]) strcat(gpu->log, ", "); 2348 | strcat(gpu->log, "DBR"); 2349 | } 2350 | else if (ParseNumericArg(argc, argv, i, "--DBW", value)) 2351 | { 2352 | gpu->smisc1.hbm.DBW = value; 2353 | gpu->modify[9] = true; 2354 | if (gpu->log[0]) strcat(gpu->log, ", "); 2355 | strcat(gpu->log, "DBW"); 2356 | } 2357 | else if (ParseNumericArg(argc, argv, i, "--TCSR", value)) 2358 | { 2359 | gpu->smisc1.hbm.TCSR = value; 2360 | gpu->modify[9] = true; 2361 | if (gpu->log[0]) strcat(gpu->log, ", "); 2362 | strcat(gpu->log, "TCSR"); 2363 | } 2364 | else if (ParseNumericArg(argc, argv, i, "--DQR", value)) 2365 | { 2366 | gpu->smisc1.hbm.DQR = value; 2367 | gpu->modify[9] = true; 2368 | if (gpu->log[0]) strcat(gpu->log, ", "); 2369 | strcat(gpu->log, "DQR"); 2370 | } 2371 | else if (ParseNumericArg(argc, argv, i, "--DQW", value)) 2372 | { 2373 | gpu->smisc1.hbm.DQW = value; 2374 | gpu->modify[9] = true; 2375 | if (gpu->log[0]) strcat(gpu->log, ", "); 2376 | strcat(gpu->log, "DQW"); 2377 | } 2378 | else if (ParseNumericArg(argc, argv, i, "--ADD_PAR", value)) 2379 | { 2380 | gpu->smisc1.hbm.ADD_PAR = value; 2381 | gpu->modify[9] = true; 2382 | if (gpu->log[0]) strcat(gpu->log, ", "); 2383 | strcat(gpu->log, "ADD_PAR"); 2384 | } 2385 | else if (ParseNumericArg(argc, argv, i, "--TM", value)) 2386 | { 2387 | gpu->smisc1.hbm.TM = value; 2388 | gpu->modify[9] = true; 2389 | if (gpu->log[0]) strcat(gpu->log, ", "); 2390 | strcat(gpu->log, "TM"); 2391 | } 2392 | else if (ParseNumericArg(argc, argv, i, "--WR", value)) 2393 | { 2394 | gpu->smisc1.hbm.WR = value; 2395 | gpu->modify[9] = true; 2396 | if (gpu->log[0]) strcat(gpu->log, ", "); 2397 | strcat(gpu->log, "WR"); 2398 | } 2399 | else if (ParseNumericArg(argc, argv, i, "--NDS", value)) 2400 | { 2401 | gpu->smisc1.hbm.NDS = value; 2402 | gpu->modify[9] = true; 2403 | if (gpu->log[0]) strcat(gpu->log, ", "); 2404 | strcat(gpu->log, "NDS"); 2405 | } 2406 | else if (ParseNumericArg(argc, argv, i, "--WL", value)) 2407 | { 2408 | gpu->smisc1.hbm.WL = value; 2409 | gpu->modify[9] = true; 2410 | if (gpu->log[0]) strcat(gpu->log, ", "); 2411 | strcat(gpu->log, "WL"); 2412 | } 2413 | else if (ParseNumericArg(argc, argv, i, "--RL", value)) 2414 | { 2415 | gpu->smisc1.hbm.RL = value; 2416 | gpu->modify[9] = true; 2417 | if (gpu->log[0]) strcat(gpu->log, ", "); 2418 | strcat(gpu->log, "RL"); 2419 | } 2420 | else if (ParseNumericArg(argc, argv, i, "--APRAS", value)) 2421 | { 2422 | gpu->smisc1.hbm.APRAS = value; 2423 | gpu->modify[9] = true; 2424 | if (gpu->log[0]) strcat(gpu->log, ", "); 2425 | strcat(gpu->log, "APRAS"); 2426 | } 2427 | else if (ParseNumericArg(argc, argv, i, "--BG", value)) 2428 | { 2429 | gpu->smisc1.hbm.BG = value; 2430 | gpu->modify[9] = true; 2431 | if (gpu->log[0]) strcat(gpu->log, ", "); 2432 | strcat(gpu->log, "BG"); 2433 | } 2434 | else if (ParseNumericArg(argc, argv, i, "--BL", value)) 2435 | { 2436 | gpu->smisc1.hbm.BL = value; 2437 | gpu->modify[9] = true; 2438 | if (gpu->log[0]) strcat(gpu->log, ", "); 2439 | strcat(gpu->log, "BL"); 2440 | } 2441 | else if (ParseNumericArg(argc, argv, i, "--REF", value)) 2442 | { 2443 | gpu->ref.REF = value; 2444 | gpu->modify[10] = true; 2445 | if (gpu->log[0]) strcat(gpu->log, ", "); 2446 | strcat(gpu->log, "REF"); 2447 | } 2448 | else if (ParseNumericArg(argc, argv, i, "--ENB", value)) 2449 | { 2450 | gpu->ham.ENB = value; 2451 | gpu->modify[11] = true; 2452 | if (gpu->log[0]) strcat(gpu->log, ", "); 2453 | strcat(gpu->log, "ENB"); 2454 | } 2455 | else if (ParseNumericArg(argc, argv, i, "--CNT", value)) 2456 | { 2457 | gpu->ham.CNT = value; 2458 | gpu->modify[11] = true; 2459 | if (gpu->log[0]) strcat(gpu->log, ", "); 2460 | strcat(gpu->log, "CNT"); 2461 | } 2462 | else if (ParseNumericArg(argc, argv, i, "--TRC", value)) 2463 | { 2464 | gpu->ham.TRC = value; 2465 | gpu->modify[11] = true; 2466 | if (gpu->log[0]) strcat(gpu->log, ", "); 2467 | strcat(gpu->log, "TRC"); 2468 | } 2469 | else if (ParseNumericArg(argc, argv, i, "--THRESH", value)) 2470 | { 2471 | gpu->throt.THRESH = value; 2472 | gpu->modify[12] = true; 2473 | if (gpu->log[0]) strcat(gpu->log, ", "); 2474 | strcat(gpu->log, "THRESH"); 2475 | } 2476 | else if (ParseNumericArg(argc, argv, i, "--LEVEL", value)) 2477 | { 2478 | gpu->throt.LEVEL = value; 2479 | gpu->modify[12] = true; 2480 | if (gpu->log[0]) strcat(gpu->log, ", "); 2481 | strcat(gpu->log, "LEVEL"); 2482 | } 2483 | else if (ParseNumericArg(argc, argv, i, "--PWRDOWN", value)) 2484 | { 2485 | gpu->throt.PWRDOWN = value; 2486 | gpu->modify[12] = true; 2487 | if (gpu->log[0]) strcat(gpu->log, ", "); 2488 | strcat(gpu->log, "PWRDOWN"); 2489 | } 2490 | else if (ParseNumericArg(argc, argv, i, "--SHUTDOWN", value)) 2491 | { 2492 | gpu->throt.SHUTDOWN = value; 2493 | gpu->modify[12] = true; 2494 | if (gpu->log[0]) strcat(gpu->log, ", "); 2495 | strcat(gpu->log, "SHUTDOWN"); 2496 | } 2497 | else if (ParseNumericArg(argc, argv, i, "--EN_SHUTDOWN", value)) 2498 | { 2499 | gpu->throt.EN_SHUTDOWN = value; 2500 | gpu->modify[12] = true; 2501 | if (gpu->log[0]) strcat(gpu->log, ", "); 2502 | strcat(gpu->log, "EN_SHUTDOWN"); 2503 | } 2504 | else if (ParseNumericArg(argc, argv, i, "--OVERSAMPLE", value)) 2505 | { 2506 | gpu->throt.OVERSAMPLE = value; 2507 | gpu->modify[12] = true; 2508 | if (gpu->log[0]) strcat(gpu->log, ", "); 2509 | strcat(gpu->log, "OVERSAMPLE"); 2510 | } 2511 | else if (ParseNumericArg(argc, argv, i, "--AVG_SAMPLE", value)) 2512 | { 2513 | gpu->throt.AVG_SAMPLE = value; 2514 | gpu->modify[12] = true; 2515 | if (gpu->log[0]) strcat(gpu->log, ", "); 2516 | strcat(gpu->log, "AVG_SAMPLE"); 2517 | } 2518 | 2519 | } 2520 | else // GDDR5 2521 | { 2522 | if (ParseNumericArg(argc, argv, i, "--DAT_DLY0", value)) 2523 | { 2524 | gpu->ctl1.rx.DAT_DLY = value; 2525 | gpu->modify[0] = true; 2526 | if (gpu->log[0]) strcat(gpu->log, ", "); 2527 | strcat(gpu->log, "DAT_DLY0"); 2528 | } 2529 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY0", value)) 2530 | { 2531 | gpu->ctl1.rx.DQS_DLY = value; 2532 | gpu->modify[0] = true; 2533 | if (gpu->log[0]) strcat(gpu->log, ", "); 2534 | strcat(gpu->log, "DQS_DLY0"); 2535 | } 2536 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR0", value)) 2537 | { 2538 | gpu->ctl1.rx.DQS_XTR = value; 2539 | gpu->modify[0] = true; 2540 | if (gpu->log[0]) strcat(gpu->log, ", "); 2541 | strcat(gpu->log, "DQS_XTR0"); 2542 | } 2543 | else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY0", value)) 2544 | { 2545 | gpu->ctl1.rx.DAT_2Y_DLY = value; 2546 | gpu->modify[0] = true; 2547 | if (gpu->log[0]) strcat(gpu->log, ", "); 2548 | strcat(gpu->log, "DAT_2Y_DLY0"); 2549 | } 2550 | else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY0", value)) 2551 | { 2552 | gpu->ctl1.rx.ADR_2Y_DLY = value; 2553 | gpu->modify[0] = true; 2554 | if (gpu->log[0]) strcat(gpu->log, ", "); 2555 | strcat(gpu->log, "ADR_2Y_DLY0"); 2556 | } 2557 | else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY0", value)) 2558 | { 2559 | gpu->ctl1.rx.CMD_2Y_DLY = value; 2560 | gpu->modify[0] = true; 2561 | if (gpu->log[0]) strcat(gpu->log, ", "); 2562 | strcat(gpu->log, "CMD_2Y_DLY0"); 2563 | } 2564 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY0", value)) 2565 | { 2566 | gpu->ctl1.rx.OEN_DLY = value; 2567 | gpu->modify[0] = true; 2568 | if (gpu->log[0]) strcat(gpu->log, ", "); 2569 | strcat(gpu->log, "OEN_DLY0"); 2570 | } 2571 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT0", value)) 2572 | { 2573 | gpu->ctl1.rx.OEN_EXT = value; 2574 | gpu->modify[0] = true; 2575 | if (gpu->log[0]) strcat(gpu->log, ", "); 2576 | strcat(gpu->log, "OEN_EXT0"); 2577 | } 2578 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL0", value)) 2579 | { 2580 | gpu->ctl1.rx.OEN_SEL = value; 2581 | gpu->modify[0] = true; 2582 | if (gpu->log[0]) strcat(gpu->log, ", "); 2583 | strcat(gpu->log, "OEN_SEL0"); 2584 | } 2585 | else if (ParseNumericArg(argc, argv, i, "--ODT_DLY0", value)) 2586 | { 2587 | gpu->ctl1.rx.ODT_DLY = value; 2588 | gpu->modify[0] = true; 2589 | if (gpu->log[0]) strcat(gpu->log, ", "); 2590 | strcat(gpu->log, "ODT_DLY0"); 2591 | } 2592 | else if (ParseNumericArg(argc, argv, i, "--ODT_EXT0", value)) 2593 | { 2594 | gpu->ctl1.rx.ODT_EXT = value; 2595 | gpu->modify[0] = true; 2596 | if (gpu->log[0]) strcat(gpu->log, ", "); 2597 | strcat(gpu->log, "ODT_EXT0"); 2598 | } 2599 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY0", value)) 2600 | { 2601 | gpu->ctl1.rx.ADR_DLY = value; 2602 | gpu->modify[0] = true; 2603 | if (gpu->log[0]) strcat(gpu->log, ", "); 2604 | strcat(gpu->log, "ADR_DLY0"); 2605 | } 2606 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY0", value)) 2607 | { 2608 | gpu->ctl1.rx.CMD_DLY = value; 2609 | gpu->modify[0] = true; 2610 | if (gpu->log[0]) strcat(gpu->log, ", "); 2611 | strcat(gpu->log, "CMD_DLY0"); 2612 | } 2613 | else if (ParseNumericArg(argc, argv, i, "--DAT_DLY1", value)) 2614 | { 2615 | gpu->ctl2.rx.DAT_DLY = value; 2616 | gpu->modify[1] = true; 2617 | if (gpu->log[0]) strcat(gpu->log, ", "); 2618 | strcat(gpu->log, "DAT_DLY1"); 2619 | } 2620 | else if (ParseNumericArg(argc, argv, i, "--DQS_DLY1", value)) 2621 | { 2622 | gpu->ctl2.rx.DQS_DLY = value; 2623 | gpu->modify[1] = true; 2624 | if (gpu->log[0]) strcat(gpu->log, ", "); 2625 | strcat(gpu->log, "DQS_DLY1"); 2626 | } 2627 | else if (ParseNumericArg(argc, argv, i, "--DQS_XTR1", value)) 2628 | { 2629 | gpu->ctl2.rx.DQS_XTR = value; 2630 | gpu->modify[1] = true; 2631 | if (gpu->log[0]) strcat(gpu->log, ", "); 2632 | strcat(gpu->log, "DQS_XTR1"); 2633 | } 2634 | else if (ParseNumericArg(argc, argv, i, "--DAT_2Y_DLY1", value)) 2635 | { 2636 | gpu->ctl2.rx.DAT_2Y_DLY = value; 2637 | gpu->modify[1] = true; 2638 | if (gpu->log[0]) strcat(gpu->log, ", "); 2639 | strcat(gpu->log, "DAT_2Y_DLY1"); 2640 | } 2641 | else if (ParseNumericArg(argc, argv, i, "--ADR_2Y_DLY1", value)) 2642 | { 2643 | gpu->ctl2.rx.ADR_2Y_DLY = value; 2644 | gpu->modify[1] = true; 2645 | if (gpu->log[0]) strcat(gpu->log, ", "); 2646 | strcat(gpu->log, "ADR_2Y_DLY1"); 2647 | } 2648 | else if (ParseNumericArg(argc, argv, i, "--CMD_2Y_DLY1", value)) 2649 | { 2650 | gpu->ctl2.rx.CMD_2Y_DLY = value; 2651 | gpu->modify[1] = true; 2652 | if (gpu->log[0]) strcat(gpu->log, ", "); 2653 | strcat(gpu->log, "CMD_2Y_DLY1"); 2654 | } 2655 | else if (ParseNumericArg(argc, argv, i, "--OEN_DLY1", value)) 2656 | { 2657 | gpu->ctl2.rx.OEN_DLY = value; 2658 | gpu->modify[1] = true; 2659 | if (gpu->log[0]) strcat(gpu->log, ", "); 2660 | strcat(gpu->log, "OEN_DLY1"); 2661 | } 2662 | else if (ParseNumericArg(argc, argv, i, "--OEN_EXT1", value)) 2663 | { 2664 | gpu->ctl2.rx.OEN_EXT = value; 2665 | gpu->modify[1] = true; 2666 | if (gpu->log[0]) strcat(gpu->log, ", "); 2667 | strcat(gpu->log, "OEN_EXT1"); 2668 | } 2669 | else if (ParseNumericArg(argc, argv, i, "--OEN_SEL1", value)) 2670 | { 2671 | gpu->ctl2.rx.OEN_SEL = value; 2672 | gpu->modify[1] = true; 2673 | if (gpu->log[0]) strcat(gpu->log, ", "); 2674 | strcat(gpu->log, "OEN_SEL1"); 2675 | } 2676 | else if (ParseNumericArg(argc, argv, i, "--ODT_DLY1", value)) 2677 | { 2678 | gpu->ctl2.rx.ODT_DLY = value; 2679 | gpu->modify[1] = true; 2680 | if (gpu->log[0]) strcat(gpu->log, ", "); 2681 | strcat(gpu->log, "ODT_DLY1"); 2682 | } 2683 | else if (ParseNumericArg(argc, argv, i, "--ODT_EXT1", value)) 2684 | { 2685 | gpu->ctl2.rx.ODT_EXT = value; 2686 | gpu->modify[1] = true; 2687 | if (gpu->log[0]) strcat(gpu->log, ", "); 2688 | strcat(gpu->log, "ODT_EXT1"); 2689 | } 2690 | else if (ParseNumericArg(argc, argv, i, "--ADR_DLY1", value)) 2691 | { 2692 | gpu->ctl2.rx.ADR_DLY = value; 2693 | gpu->modify[1] = true; 2694 | if (gpu->log[0]) strcat(gpu->log, ", "); 2695 | strcat(gpu->log, "ADR_DLY2"); 2696 | } 2697 | else if (ParseNumericArg(argc, argv, i, "--CMD_DLY1", value)) 2698 | { 2699 | gpu->ctl2.rx.CMD_DLY = value; 2700 | gpu->modify[1] = true; 2701 | if (gpu->log[0]) strcat(gpu->log, ", "); 2702 | strcat(gpu->log, "CMD_DLY1"); 2703 | } 2704 | else if (ParseNumericArg(argc, argv, i, "--CKSRE", value)) 2705 | { 2706 | gpu->pmg.rx.CKSRE = value; 2707 | gpu->modify[2] = true; 2708 | if (gpu->log[0]) strcat(gpu->log, ", "); 2709 | strcat(gpu->log, "CKSRE"); 2710 | } 2711 | else if (ParseNumericArg(argc, argv, i, "--CKSRX", value)) 2712 | { 2713 | gpu->pmg.rx.CKSRX = value; 2714 | gpu->modify[2] = true; 2715 | if (gpu->log[0]) strcat(gpu->log, ", "); 2716 | strcat(gpu->log, "CKSRX"); 2717 | } 2718 | else if (ParseNumericArg(argc, argv, i, "--CKE_PULSE", value)) 2719 | { 2720 | gpu->pmg.rx.CKE_PULSE = value; 2721 | gpu->modify[2] = true; 2722 | if (gpu->log[0]) strcat(gpu->log, ", "); 2723 | strcat(gpu->log, "CKE_PULSE"); 2724 | } 2725 | else if (ParseNumericArg(argc, argv, i, "--CKE", value)) 2726 | { 2727 | gpu->pmg.rx.CKE = value; 2728 | gpu->modify[2] = true; 2729 | if (gpu->log[0]) strcat(gpu->log, ", "); 2730 | strcat(gpu->log, "CKE"); 2731 | } 2732 | else if (ParseNumericArg(argc, argv, i, "--SEQ_IDLE", value)) 2733 | { 2734 | gpu->pmg.rx.SEQ_IDLE = value; 2735 | gpu->modify[2] = true; 2736 | if (gpu->log[0]) strcat(gpu->log, ", "); 2737 | strcat(gpu->log, "SEQ_IDLE"); 2738 | } 2739 | else if (ParseNumericArg(argc, argv, i, "--RCDW", value)) 2740 | { 2741 | gpu->ras.RCDW = value; 2742 | gpu->modify[3] = true; 2743 | if (gpu->log[0]) strcat(gpu->log, ", "); 2744 | strcat(gpu->log, "RCDW"); 2745 | } 2746 | else if (ParseNumericArg(argc, argv, i, "--RCDWA", value)) 2747 | { 2748 | gpu->ras.RCDWA = value; 2749 | gpu->modify[3] = true; 2750 | if (gpu->log[0]) strcat(gpu->log, ", "); 2751 | strcat(gpu->log, "RCDWA"); 2752 | } 2753 | else if (ParseNumericArg(argc, argv, i, "--RCDR", value)) 2754 | { 2755 | gpu->ras.RCDR = value; 2756 | gpu->modify[3] = true; 2757 | if (gpu->log[0]) strcat(gpu->log, ", "); 2758 | strcat(gpu->log, "RCDR"); 2759 | } 2760 | else if (ParseNumericArg(argc, argv, i, "--RCDRA", value)) 2761 | { 2762 | gpu->ras.RCDRA = value; 2763 | gpu->modify[3] = true; 2764 | if (gpu->log[0]) strcat(gpu->log, ", "); 2765 | strcat(gpu->log, "RCDRA"); 2766 | } 2767 | else if (ParseNumericArg(argc, argv, i, "--RRD", value)) 2768 | { 2769 | gpu->ras.RRD = value; 2770 | gpu->modify[3] = true; 2771 | if (gpu->log[0]) strcat(gpu->log, ", "); 2772 | strcat(gpu->log, "RRD"); 2773 | } 2774 | else if (ParseNumericArg(argc, argv, i, "--RC", value)) 2775 | { 2776 | gpu->ras.RC = value; 2777 | gpu->modify[3] = true; 2778 | if (gpu->log[0]) strcat(gpu->log, ", "); 2779 | strcat(gpu->log, "RC"); 2780 | } 2781 | else if (ParseNumericArg(argc, argv, i, "--CL", value)) 2782 | { 2783 | gpu->cas.rx.CL = value; 2784 | gpu->modify[4] = true; 2785 | if (gpu->log[0]) strcat(gpu->log, ", "); 2786 | strcat(gpu->log, "CL"); 2787 | } 2788 | else if (ParseNumericArg(argc, argv, i, "--W2R", value)) 2789 | { 2790 | gpu->cas.rx.W2R = value; 2791 | gpu->modify[4] = true; 2792 | if (gpu->log[0]) strcat(gpu->log, ", "); 2793 | strcat(gpu->log, "W2R"); 2794 | } 2795 | else if (ParseNumericArg(argc, argv, i, "--R2R", value)) 2796 | { 2797 | gpu->cas.rx.R2R = value; 2798 | gpu->modify[4] = true; 2799 | if (gpu->log[0]) strcat(gpu->log, ", "); 2800 | strcat(gpu->log, "R2R"); 2801 | } 2802 | else if (ParseNumericArg(argc, argv, i, "--CCDL", value)) 2803 | { 2804 | gpu->cas.rx.CCDL = value; 2805 | gpu->modify[4] = true; 2806 | if (gpu->log[0]) strcat(gpu->log, ", "); 2807 | strcat(gpu->log, "CCDL"); 2808 | } 2809 | else if (ParseNumericArg(argc, argv, i, "--R2W", value)) 2810 | { 2811 | gpu->cas.rx.R2W = value; 2812 | gpu->modify[4] = true; 2813 | if (gpu->log[0]) strcat(gpu->log, ", "); 2814 | strcat(gpu->log, "R2W"); 2815 | } 2816 | else if (ParseNumericArg(argc, argv, i, "--NOPR", value)) 2817 | { 2818 | gpu->cas.rx.NOPR = value; 2819 | gpu->modify[4] = true; 2820 | if (gpu->log[0]) strcat(gpu->log, ", "); 2821 | strcat(gpu->log, "NOPR"); 2822 | } 2823 | else if (ParseNumericArg(argc, argv, i, "--NOPW", value)) 2824 | { 2825 | gpu->cas.rx.NOPW = value; 2826 | gpu->modify[4] = true; 2827 | if (gpu->log[0]) strcat(gpu->log, ", "); 2828 | strcat(gpu->log, "NOPW"); 2829 | } 2830 | else if (ParseNumericArg(argc, argv, i, "--RFC", value)) 2831 | { 2832 | if (IsR9(chips[index].device_id)) 2833 | gpu->misc.r9.RFC = value; 2834 | else 2835 | gpu->misc.rx.RFC = value; 2836 | gpu->modify[5] = true; 2837 | if (gpu->log[0]) strcat(gpu->log, ", "); 2838 | strcat(gpu->log, "RFC"); 2839 | } 2840 | else if (ParseNumericArg(argc, argv, i, "--TRP", value)) 2841 | { 2842 | if (IsR9(chips[index].device_id)) 2843 | gpu->misc.r9.TRP = value; 2844 | else 2845 | gpu->misc.rx.TRP = value; 2846 | gpu->modify[5] = true; 2847 | if (gpu->log[0]) strcat(gpu->log, ", "); 2848 | strcat(gpu->log, "TRP"); 2849 | } 2850 | else if (ParseNumericArg(argc, argv, i, "--RP_RDA", value)) 2851 | { 2852 | if (IsR9(chips[index].device_id)) 2853 | gpu->misc.r9.RP_RDA = value; 2854 | else 2855 | gpu->misc.rx.RP_RDA = value; 2856 | gpu->modify[5] = true; 2857 | if (gpu->log[0]) strcat(gpu->log, ", "); 2858 | strcat(gpu->log, "RP_RDA"); 2859 | } 2860 | else if (ParseNumericArg(argc, argv, i, "--RP_WRA", value)) 2861 | { 2862 | if (IsR9(chips[index].device_id)) 2863 | gpu->misc.r9.RP_WRA = value; 2864 | else 2865 | gpu->misc.rx.RP_WRA = value; 2866 | gpu->modify[5] = true; 2867 | if (gpu->log[0]) strcat(gpu->log, ", "); 2868 | strcat(gpu->log, "RP_WRA"); 2869 | } 2870 | else if (ParseNumericArg(argc, argv, i, "--WDATATR", value)) 2871 | { 2872 | gpu->misc2.rx.WDATATR = value; 2873 | gpu->modify[6] = true; 2874 | if (gpu->log[0]) strcat(gpu->log, ", "); 2875 | strcat(gpu->log, "WDATATR"); 2876 | } 2877 | else if (ParseNumericArg(argc, argv, i, "--T32AW", value)) 2878 | { 2879 | gpu->misc2.rx.T32AW = value; 2880 | gpu->modify[6] = true; 2881 | if (gpu->log[0]) strcat(gpu->log, ", "); 2882 | strcat(gpu->log, "T32AW"); 2883 | } 2884 | else if (ParseNumericArg(argc, argv, i, "--WEDC", value)) 2885 | { 2886 | gpu->misc2.rx.WEDC = value; 2887 | gpu->modify[6] = true; 2888 | if (gpu->log[0]) strcat(gpu->log, ", "); 2889 | strcat(gpu->log, "WEDC"); 2890 | } 2891 | else if (ParseNumericArg(argc, argv, i, "--REDC", value)) 2892 | { 2893 | gpu->misc2.rx.REDC = value; 2894 | gpu->modify[6] = true; 2895 | if (gpu->log[0]) strcat(gpu->log, ", "); 2896 | strcat(gpu->log, "REDC"); 2897 | } 2898 | else if (ParseNumericArg(argc, argv, i, "--FAW", value)) 2899 | { 2900 | gpu->misc2.rx.FAW = value; 2901 | gpu->modify[6] = true; 2902 | if (gpu->log[0]) strcat(gpu->log, ", "); 2903 | strcat(gpu->log, "FAW"); 2904 | } 2905 | else if (ParseNumericArg(argc, argv, i, "--PA2WDATA", value)) 2906 | { 2907 | gpu->misc2.rx.PA2WDATA = value; 2908 | gpu->modify[6] = true; 2909 | if (gpu->log[0]) strcat(gpu->log, ", "); 2910 | strcat(gpu->log, "P2WDATA"); 2911 | } 2912 | else if (ParseNumericArg(argc, argv, i, "--PA2RDATA", value)) 2913 | { 2914 | gpu->misc2.rx.PA2RDATA = value; 2915 | gpu->modify[6] = true; 2916 | if (gpu->log[0]) strcat(gpu->log, ", "); 2917 | strcat(gpu->log, "PA2RDATA"); 2918 | } 2919 | else if (ParseNumericArg(argc, argv, i, "--WL", value)) 2920 | { 2921 | gpu->smisc1.rx.WL = value; 2922 | gpu->modify[7] = true; 2923 | if (gpu->log[0]) strcat(gpu->log, ", "); 2924 | strcat(gpu->log, "WL"); 2925 | } 2926 | else if (ParseNumericArg(argc, argv, i, "--MR0_CL", value)) 2927 | { 2928 | gpu->smisc1.rx.CL = value; 2929 | gpu->modify[7] = true; 2930 | if (gpu->log[0]) strcat(gpu->log, ", "); 2931 | strcat(gpu->log, "MR0_CL"); 2932 | } 2933 | else if (ParseNumericArg(argc, argv, i, "--TM", value)) 2934 | { 2935 | gpu->smisc1.rx.TM = value; 2936 | gpu->modify[7] = true; 2937 | if (gpu->log[0]) strcat(gpu->log, ", "); 2938 | strcat(gpu->log, "TM"); 2939 | } 2940 | else if (ParseNumericArg(argc, argv, i, "--WR", value)) 2941 | { 2942 | gpu->smisc1.rx.WR = value; 2943 | gpu->modify[7] = true; 2944 | if (gpu->log[0]) strcat(gpu->log, ", "); 2945 | strcat(gpu->log, "WR"); 2946 | } 2947 | else if (ParseNumericArg(argc, argv, i, "--DS", value)) 2948 | { 2949 | gpu->smisc1.rx.DS = value; 2950 | gpu->modify[7] = true; 2951 | if (gpu->log[0]) strcat(gpu->log, ", "); 2952 | strcat(gpu->log, "DS"); 2953 | } 2954 | else if (ParseNumericArg(argc, argv, i, "--DT", value)) 2955 | { 2956 | gpu->smisc1.rx.DT = value; 2957 | gpu->modify[7] = true; 2958 | if (gpu->log[0]) strcat(gpu->log, ", "); 2959 | strcat(gpu->log, "DT"); 2960 | } 2961 | else if (ParseNumericArg(argc, argv, i, "--ADR", value)) 2962 | { 2963 | gpu->smisc1.rx.ADR = value; 2964 | gpu->modify[7] = true; 2965 | if (gpu->log[0]) strcat(gpu->log, ", "); 2966 | strcat(gpu->log, "ADR"); 2967 | } 2968 | else if (ParseNumericArg(argc, argv, i, "--CAL", value)) 2969 | { 2970 | gpu->smisc1.rx.CAL = value; 2971 | gpu->modify[7] = true; 2972 | if (gpu->log[0]) strcat(gpu->log, ", "); 2973 | strcat(gpu->log, "CAL"); 2974 | } 2975 | else if (ParseNumericArg(argc, argv, i, "--PLL", value)) 2976 | { 2977 | gpu->smisc1.rx.PLL = value; 2978 | gpu->modify[7] = true; 2979 | if (gpu->log[0]) strcat(gpu->log, ", "); 2980 | strcat(gpu->log, "PLL"); 2981 | } 2982 | else if (ParseNumericArg(argc, argv, i, "--RDBI", value)) 2983 | { 2984 | gpu->smisc1.rx.RDBI = value; 2985 | gpu->modify[7] = true; 2986 | if (gpu->log[0]) strcat(gpu->log, ", "); 2987 | strcat(gpu->log, "RDBI"); 2988 | } 2989 | else if (ParseNumericArg(argc, argv, i, "--WDBI", value)) 2990 | { 2991 | gpu->smisc1.rx.WDBI = value; 2992 | gpu->modify[7] = true; 2993 | if (gpu->log[0]) strcat(gpu->log, ", "); 2994 | strcat(gpu->log, "WDBI"); 2995 | } 2996 | else if (ParseNumericArg(argc, argv, i, "--ABI", value)) 2997 | { 2998 | gpu->smisc1.rx.ABI = value; 2999 | gpu->modify[7] = true; 3000 | if (gpu->log[0]) strcat(gpu->log, ", "); 3001 | strcat(gpu->log, "ABI"); 3002 | } 3003 | else if (ParseNumericArg(argc, argv, i, "--RESET", value)) 3004 | { 3005 | gpu->smisc1.rx.RESET = value; 3006 | gpu->modify[7] = true; 3007 | if (gpu->log[0]) strcat(gpu->log, ", "); 3008 | strcat(gpu->log, "RESET"); 3009 | } 3010 | else if (ParseNumericArg(argc, argv, i, "--SR", value)) 3011 | { 3012 | gpu->smisc2.SR = value; 3013 | gpu->modify[8] = true; 3014 | if (gpu->log[0]) strcat(gpu->log, ", "); 3015 | strcat(gpu->log, "SR"); 3016 | } 3017 | else if (ParseNumericArg(argc, argv, i, "--WCK01", value)) 3018 | { 3019 | gpu->smisc2.WCK01 = value; 3020 | gpu->modify[8] = true; 3021 | if (gpu->log[0]) strcat(gpu->log, ", "); 3022 | strcat(gpu->log, "WCK01"); 3023 | } 3024 | else if (ParseNumericArg(argc, argv, i, "--WCK23", value)) 3025 | { 3026 | gpu->smisc2.WCK23 = value; 3027 | gpu->modify[8] = true; 3028 | if (gpu->log[0]) strcat(gpu->log, ", "); 3029 | strcat(gpu->log, "WCK23"); 3030 | } 3031 | else if (ParseNumericArg(argc, argv, i, "--WCK2CK", value)) 3032 | { 3033 | gpu->smisc2.WCK2CK = value; 3034 | gpu->modify[8] = true; 3035 | if (gpu->log[0]) strcat(gpu->log, ", "); 3036 | strcat(gpu->log, "WCK2CK"); 3037 | } 3038 | else if (ParseNumericArg(argc, argv, i, "--RDQS", value)) 3039 | { 3040 | gpu->smisc2.RDQS = value; 3041 | gpu->modify[8] = true; 3042 | if (gpu->log[0]) strcat(gpu->log, ", "); 3043 | strcat(gpu->log, "RDQS"); 3044 | } 3045 | else if (ParseNumericArg(argc, argv, i, "--INFO", value)) 3046 | { 3047 | gpu->smisc2.INFO = value; 3048 | gpu->modify[8] = true; 3049 | if (gpu->log[0]) strcat(gpu->log, ", "); 3050 | strcat(gpu->log, "INFO"); 3051 | } 3052 | else if (ParseNumericArg(argc, argv, i, "--WCK2", value)) 3053 | { 3054 | gpu->smisc2.WCK2 = value; 3055 | gpu->modify[8] = true; 3056 | if (gpu->log[0]) strcat(gpu->log, ", "); 3057 | strcat(gpu->log, "WCK2"); 3058 | } 3059 | 3060 | else if (ParseNumericArg(argc, argv, i, "--BG", value)) 3061 | { 3062 | gpu->smisc2.BG = value; 3063 | gpu->modify[8] = true; 3064 | if (gpu->log[0]) strcat(gpu->log, ", "); 3065 | strcat(gpu->log, "BG"); 3066 | } 3067 | else if (ParseNumericArg(argc, argv, i, "--EDCHP", value)) 3068 | { 3069 | gpu->smisc3.EDCHP = value; 3070 | gpu->modify[9] = true; 3071 | if (gpu->log[0]) strcat(gpu->log, ", "); 3072 | strcat(gpu->log, "EDCHP"); 3073 | } 3074 | else if (ParseNumericArg(argc, argv, i, "--CRCWL", value)) 3075 | { 3076 | gpu->smisc3.CRCWL = value; 3077 | gpu->modify[9] = true; 3078 | if (gpu->log[0]) strcat(gpu->log, ", "); 3079 | strcat(gpu->log, "CRCWL"); 3080 | } 3081 | else if (ParseNumericArg(argc, argv, i, "--CRCRL", value)) 3082 | { 3083 | gpu->smisc3.CRCRL = value; 3084 | gpu->modify[9] = true; 3085 | if (gpu->log[0]) strcat(gpu->log, ", "); 3086 | strcat(gpu->log, "CRCRL"); 3087 | } 3088 | else if (ParseNumericArg(argc, argv, i, "--RDCRC", value)) 3089 | { 3090 | gpu->smisc3.RDCRC = value; 3091 | gpu->modify[9] = true; 3092 | if (gpu->log[0]) strcat(gpu->log, ", "); 3093 | strcat(gpu->log, "RDCRC"); 3094 | } 3095 | else if (ParseNumericArg(argc, argv, i, "--WRCRC", value)) 3096 | { 3097 | gpu->smisc3.WRCRC = value; 3098 | gpu->modify[9] = true; 3099 | if (gpu->log[0]) strcat(gpu->log, ", "); 3100 | strcat(gpu->log, "WRCRC"); 3101 | } 3102 | else if (ParseNumericArg(argc, argv, i, "--EDC", value)) 3103 | { 3104 | gpu->smisc3.EDC = value; 3105 | gpu->modify[9] = true; 3106 | if (gpu->log[0]) strcat(gpu->log, ", "); 3107 | strcat(gpu->log, "EDC"); 3108 | } 3109 | else if (ParseNumericArg(argc, argv, i, "--RAS", value)) 3110 | { 3111 | gpu->smisc3.RAS = value; 3112 | gpu->modify[9] = true; 3113 | if (gpu->log[0]) strcat(gpu->log, ", "); 3114 | strcat(gpu->log, "RAS"); 3115 | } 3116 | else if (ParseNumericArg(argc, argv, i, "--CLEHF", value)) 3117 | { 3118 | gpu->smisc8.CLEHF = value; 3119 | gpu->modify[12] = true; 3120 | if (gpu->log[0]) strcat(gpu->log, ", "); 3121 | strcat(gpu->log, "CLEHF"); 3122 | } 3123 | else if (ParseNumericArg(argc, argv, i, "--WREHF", value)) 3124 | { 3125 | gpu->smisc8.WREHF = value; 3126 | gpu->modify[12] = true; 3127 | if (gpu->log[0]) strcat(gpu->log, ", "); 3128 | strcat(gpu->log, "WREHF"); 3129 | } 3130 | else if (ParseNumericArg(argc, argv, i, "--ACTRD", value)) 3131 | { 3132 | gpu->dram1.ACTRD = value; 3133 | gpu->modify[13] = true; 3134 | if (gpu->log[0]) strcat(gpu->log, ", "); 3135 | strcat(gpu->log, "ACTRD"); 3136 | } 3137 | else if (ParseNumericArg(argc, argv, i, "--ACTWR", value)) 3138 | { 3139 | gpu->dram1.ACTWR = value; 3140 | gpu->modify[13] = true; 3141 | if (gpu->log[0]) strcat(gpu->log, ", "); 3142 | strcat(gpu->log, "ACTWR"); 3143 | } 3144 | else if (ParseNumericArg(argc, argv, i, "--RASMACTRD", value)) 3145 | { 3146 | gpu->dram1.RASMACTRD = value; 3147 | gpu->modify[13] = true; 3148 | if (gpu->log[0]) strcat(gpu->log, ", "); 3149 | strcat(gpu->log, "RASMACTRD"); 3150 | } 3151 | else if (ParseNumericArg(argc, argv, i, "--RASMACTWR", value)) 3152 | { 3153 | gpu->dram1.RASMACTWR = value; 3154 | gpu->modify[13] = true; 3155 | if (gpu->log[0]) strcat(gpu->log, ", "); 3156 | strcat(gpu->log, "RASMACTWR"); 3157 | } 3158 | else if (ParseNumericArg(argc, argv, i, "--RAS2RAS", value)) 3159 | { 3160 | gpu->dram2.RAS2RAS = value; 3161 | gpu->modify[14] = true; 3162 | if (gpu->log[0]) strcat(gpu->log, ", "); 3163 | strcat(gpu->log, "RAS2RAS"); 3164 | } 3165 | else if (ParseNumericArg(argc, argv, i, "--RP", value)) 3166 | { 3167 | gpu->dram2.RP = value; 3168 | gpu->modify[14] = true; 3169 | if (gpu->log[0]) strcat(gpu->log, ", "); 3170 | strcat(gpu->log, "RP"); 3171 | } 3172 | else if (ParseNumericArg(argc, argv, i, "--WRPLUSRP", value)) 3173 | { 3174 | gpu->dram2.WRPLUSRP = value; 3175 | gpu->modify[14] = true; 3176 | if (gpu->log[0]) strcat(gpu->log, ", "); 3177 | strcat(gpu->log, "WRPLUSRP"); 3178 | } 3179 | else if (ParseNumericArg(argc, argv, i, "--BUS_TURN", value)) 3180 | { 3181 | gpu->dram2.BUS_TURN = value; 3182 | gpu->modify[14] = true; 3183 | if (gpu->log[0]) strcat(gpu->log, ", "); 3184 | strcat(gpu->log, "BUS_TURN"); 3185 | } 3186 | else if (ParseNumericArg(argc, argv, i, "--REF", value)) 3187 | { 3188 | gpu->ref.REF = value; 3189 | gpu->modify[15] = true; 3190 | if (gpu->log[0]) strcat(gpu->log, ", "); 3191 | strcat(gpu->log, "REF"); 3192 | } 3193 | else if (ParseNumericArg(argc, argv, i, "--TWT2RT", value)) 3194 | { 3195 | gpu->train.TWT2RT = value; 3196 | gpu->modify[16] = true; 3197 | if (gpu->log[0]) strcat(gpu->log, ", "); 3198 | strcat(gpu->log, "TWT2RT"); 3199 | } 3200 | else if (ParseNumericArg(argc, argv, i, "--TARF2T", value)) 3201 | { 3202 | gpu->train.TARF2T = value; 3203 | gpu->modify[16] = true; 3204 | if (gpu->log[0]) strcat(gpu->log, ", "); 3205 | strcat(gpu->log, "TARF2T"); 3206 | } 3207 | else if (ParseNumericArg(argc, argv, i, "--TT2ROW", value)) 3208 | { 3209 | gpu->train.TT2ROW = value; 3210 | gpu->modify[16] = true; 3211 | if (gpu->log[0]) strcat(gpu->log, ", "); 3212 | strcat(gpu->log, "TT2ROW"); 3213 | } 3214 | else if (ParseNumericArg(argc, argv, i, "--TLD2LD", value)) 3215 | { 3216 | gpu->train.TLD2LD = value; 3217 | gpu->modify[16] = true; 3218 | if (gpu->log[0]) strcat(gpu->log, ", "); 3219 | strcat(gpu->log, "TLD2LD"); 3220 | } 3221 | } 3222 | } 3223 | } 3224 | } 3225 | } 3226 | 3227 | // Actually applies the changes, if any. 3228 | for (int index = 0; index < gpuCount; index++) 3229 | { 3230 | GPU* gpu = &gpus[index]; 3231 | for (int i = 0; i < _countof(gpu->modify); i++) 3232 | { 3233 | if (gpu->modify[i]) 3234 | { 3235 | switch (DetermineMemoryType(chips[index].device_id)) 3236 | { 3237 | case HBM2: 3238 | { 3239 | u32 value = ((u32*)& gpu->hbm2)[i]; 3240 | if (i == 0) // special logic for frequency 3241 | { 3242 | value = (gpu->hbm2.frequency == 0x118) ? 0x118 : 0x11C; 3243 | } 3244 | WriteMMIODword(AMD_TIMING_REGS_BASE_1 + (i * sizeof(u32)), value, index); 3245 | WriteMMIODword(AMD_TIMING_REGS_BASE_2 + (i * sizeof(u32)), value, index); 3246 | WriteMMIODword(AMD_TIMING_REGS_BASE_3 + (i * sizeof(u32)), value, index); 3247 | WriteMMIODword(AMD_TIMING_REGS_BASE_4 + (i * sizeof(u32)), value, index); 3248 | break; 3249 | } 3250 | case GDDR5: 3251 | switch (i) 3252 | { 3253 | case 0: 3254 | WriteMMIODword(MC_SEQ_WR_CTL_D0, gpu->ctl1.value, index); 3255 | break; 3256 | case 1: 3257 | WriteMMIODword(MC_SEQ_WR_CTL_D1, gpu->ctl2.value, index); 3258 | break; 3259 | case 2: 3260 | WriteMMIODword(MC_SEQ_PMG_TIMING, gpu->pmg.value, index); 3261 | break; 3262 | case 3: 3263 | WriteMMIODword(MC_SEQ_RAS_TIMING, gpu->ras.value, index); 3264 | break; 3265 | case 4: 3266 | WriteMMIODword(MC_SEQ_CAS_TIMING, gpu->cas.value, index); 3267 | break; 3268 | case 5: 3269 | WriteMMIODword(MC_SEQ_MISC_TIMING, gpu->misc.value, index); 3270 | break; 3271 | case 6: 3272 | WriteMMIODword(MC_SEQ_MISC_TIMING2, gpu->misc2.value, index); 3273 | break; 3274 | case 7: 3275 | WriteMMIODword(MC_SEC_MISC1, gpu->smisc1.value, index); 3276 | break; 3277 | case 8: 3278 | WriteMMIODword(MC_SEC_MISC2, gpu->smisc2.value, index); 3279 | break; 3280 | case 9: 3281 | WriteMMIODword(MC_SEC_MISC3, gpu->smisc3.value, index); 3282 | break; 3283 | case 10: 3284 | WriteMMIODword(MC_SEC_MISC4, gpu->smisc4.value, index); 3285 | break; 3286 | case 11: 3287 | WriteMMIODword(MC_SEC_MISC7, gpu->smisc7.value, index); 3288 | break; 3289 | case 12: 3290 | WriteMMIODword(MC_SEC_MISC8, gpu->smisc8.value, index); 3291 | break; 3292 | case 13: 3293 | WriteMMIODword(MC_ARB_DRAM_TIMING, gpu->dram1.value, index); 3294 | break; 3295 | case 14: 3296 | WriteMMIODword(MC_ARB_DRAM_TIMING2, gpu->dram2.value, index); 3297 | break; 3298 | case 15: 3299 | WriteMMIODword(MC_ARB_RFSH_RATE, gpu->ref.value, index); 3300 | break; 3301 | case 16: 3302 | WriteMMIODword(MC_SEQ_TRAINING, gpu->train.value, index); 3303 | break; 3304 | } 3305 | break; 3306 | case HBM: 3307 | switch (i) 3308 | { 3309 | case 0: 3310 | WriteMMIODword(MC_SEQ_WR_CTL_D0_HBM, gpu->ctl1.value, index); 3311 | break; 3312 | case 1: 3313 | WriteMMIODword(MC_SEQ_WR_CTL_D1_HBM, gpu->ctl2.value, index); 3314 | break; 3315 | case 2: 3316 | WriteMMIODword(MC_SEQ_WR_CTL_D2_HBM, gpu->ctl3.value, index); 3317 | break; 3318 | case 3: 3319 | WriteMMIODword(MC_SEQ_WR_CTL_D3_HBM, gpu->ctl4.value, index); 3320 | break; 3321 | case 4: 3322 | WriteMMIODword(MC_SEQ_PMG_TIMING_HBM, gpu->pmg.value, index); 3323 | break; 3324 | case 5: 3325 | WriteMMIODword(MC_SEQ_RAS_TIMING_HBM, gpu->ras.value, index); 3326 | break; 3327 | case 6: 3328 | WriteMMIODword(MC_SEQ_CAS_TIMING_HBM, gpu->cas.value, index); 3329 | break; 3330 | case 7: 3331 | WriteMMIODword(MC_SEQ_MISC_TIMING_HBM, gpu->misc.value, index); 3332 | break; 3333 | case 8: 3334 | WriteMMIODword(MC_SEQ_MISC_TIMING2_HBM, gpu->misc2.value, index); 3335 | break; 3336 | case 9: 3337 | WriteMMIODword(MC_SEC_MISC1_HBM, gpu->smisc1.value, index); 3338 | break; 3339 | case 10: 3340 | WriteMMIODword(MC_ARB_RFSH_RATE, gpu->ref.value, index); 3341 | break; 3342 | case 11: 3343 | WriteMMIODword(MC_SEQ_ROW_HAMMER, gpu->ham.value, index); 3344 | break; 3345 | case 12: 3346 | WriteMMIODword(MC_THERMAL_THROTTLE, gpu->throt.value, index); 3347 | break; 3348 | } 3349 | break; 3350 | } 3351 | } 3352 | } 3353 | } 3354 | 3355 | for (int index = 0; index < gpuCount; index++) 3356 | { 3357 | GPU* gpu = &gpus[index]; 3358 | if (gpu->log[0]) 3359 | { 3360 | printf("Successfully applied new %s settings to GPU %d.\n", gpu->log, index); 3361 | } 3362 | } 3363 | 3364 | return EXIT_SUCCESS; 3365 | } 3366 | -------------------------------------------------------------------------------- /win/WinAMDTweak.vcproj: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 15 | 18 | 19 | 20 | 21 | 22 | 29 | 32 | 35 | 38 | 41 | 44 | 55 | 58 | 61 | 64 | 72 | 75 | 78 | 81 | 84 | 87 | 90 | 93 | 94 | 101 | 104 | 107 | 110 | 113 | 117 | 128 | 131 | 134 | 137 | 145 | 148 | 151 | 154 | 157 | 160 | 163 | 166 | 167 | 175 | 178 | 181 | 184 | 187 | 190 | 205 | 208 | 211 | 214 | 224 | 227 | 230 | 233 | 236 | 239 | 242 | 245 | 246 | 254 | 257 | 260 | 263 | 266 | 270 | 284 | 287 | 290 | 293 | 303 | 306 | 309 | 312 | 315 | 318 | 321 | 324 | 325 | 326 | 327 | 328 | 329 | 334 | 337 | 338 | 341 | 342 | 343 | 348 | 351 | 352 | 353 | 358 | 359 | 363 | 364 | 368 | 369 | 373 | 374 | 375 | 376 | 377 | 378 | --------------------------------------------------------------------------------