├── 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 |
--------------------------------------------------------------------------------