1 /******************************************************************************
3 * Copyright (C) 2009 - 2015 Xilinx, Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person obtaining a copy
6 * of this software and associated documentation files (the "Software"), to deal
7 * in the Software without restriction, including without limitation the rights
8 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the Software is
10 * 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.
15 * Use of the Software is limited solely to applications:
16 * (a) running on a Xilinx device, or
17 * (b) that interact with a Xilinx device through a bus or interconnect.
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
22 * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
24 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27 * Except as contained in this notice, the name of the Xilinx shall not be used
28 * in advertising or otherwise to promote the sale, use or other dealings in
29 * this Software without prior written authorization from Xilinx.
31 ******************************************************************************/
32 /*****************************************************************************/
37 * Contains the memory test utility functions.
40 * MODIFICATION HISTORY:
42 * Ver Who Date Changes
43 * ----- ---- -------- -----------------------------------------------
44 * 1.00a hbm 08/25/09 First release
47 *****************************************************************************/
49 /***************************** Include Files ********************************/
50 #include "xil_testmem.h"
52 #include "xil_assert.h"
54 /************************** Constant Definitions ****************************/
55 /************************** Function Prototypes *****************************/
57 static u32 RotateLeft(u32 Input, u8 Width);
59 /* define ROTATE_RIGHT to give access to this functionality */
60 /* #define ROTATE_RIGHT */
62 static u32 RotateRight(u32 Input, u8 Width);
63 #endif /* ROTATE_RIGHT */
66 /*****************************************************************************/
69 * Perform a destructive 32-bit wide memory test.
71 * @param Addr is a pointer to the region of memory to be tested.
72 * @param Words is the length of the block.
73 * @param Pattern is the constant used for the constant pattern test, if 0,
75 * @param Subtest is the test selected. See xil_testmem.h for possible
80 * - 0 is returned for a pass
81 * - -1 is returned for a failure
85 * Used for spaces where the address range of the region is smaller than
86 * the data width. If the memory range is greater than 2 ** Width,
87 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
88 * repeat on a boundry of a power of two making it more difficult to detect
89 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
90 * tests suffer the same problem. Ideally, if large blocks of memory are to be
91 * tested, break them up into smaller regions of memory to allow the test
92 * patterns used not to repeat over the region tested.
94 *****************************************************************************/
95 s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest)
104 Xil_AssertNonvoid(Words != (u32)0);
105 Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST);
106 Xil_AssertNonvoid(Addr != NULL);
109 * variable initialization
111 Val = XIL_TESTMEM_INIT_VALUE;
112 FirtVal = XIL_TESTMEM_INIT_VALUE;
115 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
117 * Fill the memory with incrementing
118 * values starting from 'FirtVal'
120 for (I = 0U; I < Words; I++) {
126 * Restore the reference 'Val' to the
132 * Check every word within the words
133 * of tested memory and compare it
134 * with the incrementing reference
138 for (I = 0U; I < Words; I++) {
139 WordMem32 = *(Addr+I);
141 if (WordMem32 != Val) {
150 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
152 * set up to cycle through all possible initial
153 * test Patterns for walking ones test
156 for (j = 0U; j < (u32)32; j++) {
158 * Generate an initial value for walking ones test
159 * to test for bad data bits
165 * START walking ones test
166 * Write a one to each data bit indifferent locations
169 for (I = 0U; I < (u32)32; I++) {
170 /* write memory location */
172 Val = (u32) RotateLeft(Val, 32U);
176 * Restore the reference 'val' to the
181 /* Read the values from each location that was
183 for (I = 0U; I < (u32)32; I++) {
184 /* read memory location */
186 WordMem32 = *(Addr+I);
188 if (WordMem32 != Val) {
193 Val = (u32)RotateLeft(Val, 32U);
198 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
200 * set up to cycle through all possible
201 * initial test Patterns for walking zeros test
204 for (j = 0U; j < (u32)32; j++) {
207 * Generate an initial value for walking ones test
208 * to test for bad data bits
214 * START walking zeros test
215 * Write a one to each data bit indifferent locations
218 for (I = 0U; I < (u32)32; I++) {
219 /* write memory location */
221 Val = ~((u32)RotateLeft(~Val, 32U));
225 * Restore the reference 'Val' to the
231 /* Read the values from each location that was
233 for (I = 0U; I < (u32)32; I++) {
234 /* read memory location */
235 WordMem32 = *(Addr+I);
236 if (WordMem32 != Val) {
240 Val = ~((u32)RotateLeft(~Val, 32U));
246 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
247 /* Fill the memory with inverse of address */
248 for (I = 0U; I < Words; I++) {
249 /* write memory location */
250 Val = (u32) (~((INTPTR) (&Addr[I])));
255 * Check every word within the words
259 for (I = 0U; I < Words; I++) {
260 /* Read the location */
261 WordMem32 = *(Addr+I);
262 Val = (u32) (~((INTPTR) (&Addr[I])));
264 if ((WordMem32 ^ Val) != 0x00000000U) {
271 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
273 * Generate an initial value for
277 if (Pattern == (u32)0) {
285 * Fill the memory with fixed Pattern
288 for (I = 0U; I < Words; I++) {
289 /* write memory location */
294 * Check every word within the words
295 * of tested memory and compare it
296 * with the fixed Pattern
299 for (I = 0U; I < Words; I++) {
301 /* read memory location */
303 WordMem32 = *(Addr+I);
304 if (WordMem32 != Val) {
315 /*****************************************************************************/
318 * Perform a destructive 16-bit wide memory test.
320 * @param Addr is a pointer to the region of memory to be tested.
321 * @param Words is the length of the block.
322 * @param Pattern is the constant used for the constant Pattern test, if 0,
323 * 0xDEADBEEF is used.
324 * @param Subtest is the test selected. See xil_testmem.h for possible
329 * - -1 is returned for a failure
330 * - 0 is returned for a pass
334 * Used for spaces where the address range of the region is smaller than
335 * the data width. If the memory range is greater than 2 ** Width,
336 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
337 * repeat on a boundry of a power of two making it more difficult to detect
338 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
339 * tests suffer the same problem. Ideally, if large blocks of memory are to be
340 * tested, break them up into smaller regions of memory to allow the test
341 * patterns used not to repeat over the region tested.
343 *****************************************************************************/
344 s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest)
353 Xil_AssertNonvoid(Words != (u32)0);
354 Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST);
355 Xil_AssertNonvoid(Addr != NULL);
358 * variable initialization
360 Val = XIL_TESTMEM_INIT_VALUE;
361 FirtVal = XIL_TESTMEM_INIT_VALUE;
364 * selectthe proper Subtest(s)
367 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
369 * Fill the memory with incrementing
370 * values starting from 'FirtVal'
372 for (I = 0U; I < Words; I++) {
373 /* write memory location */
378 * Restore the reference 'Val' to the
384 * Check every word within the words
385 * of tested memory and compare it
386 * with the incrementing reference val
389 for (I = 0U; I < Words; I++) {
390 /* read memory location */
391 WordMem16 = *(Addr+I);
392 if (WordMem16 != Val) {
400 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
402 * set up to cycle through all possible initial test
403 * Patterns for walking ones test
406 for (j = 0U; j < (u32)16; j++) {
408 * Generate an initial value for walking ones test
409 * to test for bad data bits
412 Val = (u16)((u32)1 << j);
414 * START walking ones test
415 * Write a one to each data bit indifferent locations
418 for (I = 0U; I < (u32)16; I++) {
419 /* write memory location */
421 Val = (u16)RotateLeft(Val, 16U);
424 * Restore the reference 'Val' to the
427 Val = (u16)((u32)1 << j);
428 /* Read the values from each location that was written */
429 for (I = 0U; I < (u32)16; I++) {
430 /* read memory location */
431 WordMem16 = *(Addr+I);
432 if (WordMem16 != Val) {
436 Val = (u16)RotateLeft(Val, 16U);
441 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
443 * set up to cycle through all possible initial
444 * test Patterns for walking zeros test
447 for (j = 0U; j < (u32)16; j++) {
449 * Generate an initial value for walking ones
450 * test to test for bad
456 * START walking zeros test
457 * Write a one to each data bit indifferent locations
460 for (I = 0U; I < (u32)16; I++) {
461 /* write memory location */
463 Val = ~((u16)RotateLeft(~Val, 16U));
466 * Restore the reference 'Val' to the
470 /* Read the values from each location that was written */
471 for (I = 0U; I < (u32)16; I++) {
472 /* read memory location */
473 WordMem16 = *(Addr+I);
474 if (WordMem16 != Val) {
478 Val = ~((u16)RotateLeft(~Val, 16U));
484 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
485 /* Fill the memory with inverse of address */
486 for (I = 0U; I < Words; I++) {
487 /* write memory location */
488 Val = (u16) (~((INTPTR)(&Addr[I])));
492 * Check every word within the words
496 for (I = 0U; I < Words; I++) {
497 /* read memory location */
498 WordMem16 = *(Addr+I);
499 Val = (u16) (~((INTPTR) (&Addr[I])));
500 if ((WordMem16 ^ Val) != 0x0000U) {
507 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
509 * Generate an initial value for
512 if (Pattern == (u16)0) {
520 * Fill the memory with fixed pattern
523 for (I = 0U; I < Words; I++) {
524 /* write memory location */
529 * Check every word within the words
530 * of tested memory and compare it
531 * with the fixed pattern
534 for (I = 0U; I < Words; I++) {
535 /* read memory location */
536 WordMem16 = *(Addr+I);
537 if (WordMem16 != Val) {
549 /*****************************************************************************/
552 * Perform a destructive 8-bit wide memory test.
554 * @param Addr is a pointer to the region of memory to be tested.
555 * @param Words is the length of the block.
556 * @param Pattern is the constant used for the constant pattern test, if 0,
557 * 0xDEADBEEF is used.
558 * @param Subtest is the test selected. See xil_testmem.h for possible
563 * - -1 is returned for a failure
564 * - 0 is returned for a pass
568 * Used for spaces where the address range of the region is smaller than
569 * the data width. If the memory range is greater than 2 ** Width,
570 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
571 * repeat on a boundry of a power of two making it more difficult to detect
572 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
573 * tests suffer the same problem. Ideally, if large blocks of memory are to be
574 * tested, break them up into smaller regions of memory to allow the test
575 * patterns used not to repeat over the region tested.
577 *****************************************************************************/
578 s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest)
587 Xil_AssertNonvoid(Words != (u32)0);
588 Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST);
589 Xil_AssertNonvoid(Addr != NULL);
592 * variable initialization
594 Val = XIL_TESTMEM_INIT_VALUE;
595 FirtVal = XIL_TESTMEM_INIT_VALUE;
598 * select the proper Subtest(s)
601 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
603 * Fill the memory with incrementing
604 * values starting from 'FirtVal'
606 for (I = 0U; I < Words; I++) {
607 /* write memory location */
612 * Restore the reference 'Val' to the
617 * Check every word within the words
618 * of tested memory and compare it
619 * with the incrementing reference
623 for (I = 0U; I < Words; I++) {
624 /* read memory location */
625 WordMem8 = *(Addr+I);
626 if (WordMem8 != Val) {
634 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
636 * set up to cycle through all possible initial
637 * test Patterns for walking ones test
640 for (j = 0U; j < (u32)8; j++) {
642 * Generate an initial value for walking ones test
643 * to test for bad data bits
645 Val = (u8)((u32)1 << j);
647 * START walking ones test
648 * Write a one to each data bit indifferent locations
650 for (I = 0U; I < (u32)8; I++) {
651 /* write memory location */
653 Val = (u8)RotateLeft(Val, 8U);
656 * Restore the reference 'Val' to the
659 Val = (u8)((u32)1 << j);
660 /* Read the values from each location that was written */
661 for (I = 0U; I < (u32)8; I++) {
662 /* read memory location */
663 WordMem8 = *(Addr+I);
664 if (WordMem8 != Val) {
668 Val = (u8)RotateLeft(Val, 8U);
673 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
675 * set up to cycle through all possible initial test
676 * Patterns for walking zeros test
679 for (j = 0U; j < (u32)8; j++) {
681 * Generate an initial value for walking ones test to test
686 * START walking zeros test
687 * Write a one to each data bit indifferent locations
689 for (I = 0U; I < (u32)8; I++) {
690 /* write memory location */
692 Val = ~((u8)RotateLeft(~Val, 8U));
695 * Restore the reference 'Val' to the
699 /* Read the values from each location that was written */
700 for (I = 0U; I < (u32)8; I++) {
701 /* read memory location */
702 WordMem8 = *(Addr+I);
703 if (WordMem8 != Val) {
708 Val = ~((u8)RotateLeft(~Val, 8U));
713 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
714 /* Fill the memory with inverse of address */
715 for (I = 0U; I < Words; I++) {
716 /* write memory location */
717 Val = (u8) (~((INTPTR) (&Addr[I])));
722 * Check every word within the words
726 for (I = 0U; I < Words; I++) {
727 /* read memory location */
728 WordMem8 = *(Addr+I);
729 Val = (u8) (~((INTPTR) (&Addr[I])));
730 if ((WordMem8 ^ Val) != 0x00U) {
737 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
739 * Generate an initial value for
743 if (Pattern == (u8)0) {
750 * Fill the memory with fixed Pattern
752 for (I = 0U; I < Words; I++) {
753 /* write memory location */
757 * Check every word within the words
758 * of tested memory and compare it
759 * with the fixed Pattern
762 for (I = 0U; I < Words; I++) {
763 /* read memory location */
764 WordMem8 = *(Addr+I);
765 if (WordMem8 != Val) {
777 /*****************************************************************************/
780 * Rotates the provided value to the left one bit position
782 * @param Input is value to be rotated to the left
783 * @param Width is the number of bits in the input data
787 * The resulting unsigned long value of the rotate left
793 *****************************************************************************/
794 static u32 RotateLeft(u32 Input, u8 Width)
800 u32 LocalInput = Input;
803 * set up the WidthMask and the MsbMask
806 MsbMask = 1U << (Width - 1U);
808 WidthMask = (MsbMask << (u32)1) - (u32)1;
811 * set the Width of the Input to the correct width
814 LocalInput = LocalInput & WidthMask;
816 Msb = LocalInput & MsbMask;
818 ReturnVal = LocalInput << 1U;
820 if (Msb != 0x00000000U) {
821 ReturnVal = ReturnVal | (u32)0x00000001;
824 ReturnVal = ReturnVal & WidthMask;
831 /*****************************************************************************/
834 * Rotates the provided value to the right one bit position
836 * @param Input is value to be rotated to the right
837 * @param Width is the number of bits in the input data
841 * The resulting u32 value of the rotate right
847 *****************************************************************************/
848 static u32 RotateRight(u32 Input, u8 Width)
854 u32 LocalInput = Input;
856 * set up the WidthMask and the MsbMask
859 MsbMask = 1U << (Width - 1U);
861 WidthMask = (MsbMask << 1U) - 1U;
864 * set the width of the input to the correct width
867 LocalInput = LocalInput & WidthMask;
869 ReturnVal = LocalInput >> 1U;
871 Lsb = LocalInput & 0x00000001U;
873 if (Lsb != 0x00000000U) {
874 ReturnVal = ReturnVal | MsbMask;
877 ReturnVal = ReturnVal & WidthMask;
882 #endif /* ROTATE_RIGHT */