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 * @brief Perform a destructive 32-bit wide memory test.
71 * @param Addr: pointer to the region of memory to be tested.
72 * @param Words: length of the block.
73 * @param Pattern: constant used for the constant pattern test, if 0,
75 * @param Subtest: test type selected. See xil_testmem.h for possible
79 * - 0 is returned for a pass
80 * - 1 is returned for a failure
83 * Used for spaces where the address range of the region is smaller than
84 * the data width. If the memory range is greater than 2 ** Width,
85 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
86 * repeat on a boundry of a power of two making it more difficult to detect
87 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
88 * tests suffer the same problem. Ideally, if large blocks of memory are to be
89 * tested, break them up into smaller regions of memory to allow the test
90 * patterns used not to repeat over the region tested.
92 *****************************************************************************/
93 s32 Xil_TestMem32(u32 *Addr, u32 Words, u32 Pattern, u8 Subtest)
102 Xil_AssertNonvoid(Words != (u32)0);
103 Xil_AssertNonvoid(Subtest <= (u8)XIL_TESTMEM_MAXTEST);
104 Xil_AssertNonvoid(Addr != NULL);
107 * variable initialization
109 Val = XIL_TESTMEM_INIT_VALUE;
110 FirtVal = XIL_TESTMEM_INIT_VALUE;
113 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
115 * Fill the memory with incrementing
116 * values starting from 'FirtVal'
118 for (I = 0U; I < Words; I++) {
124 * Restore the reference 'Val' to the
130 * Check every word within the words
131 * of tested memory and compare it
132 * with the incrementing reference
136 for (I = 0U; I < Words; I++) {
137 WordMem32 = *(Addr+I);
139 if (WordMem32 != Val) {
148 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
150 * set up to cycle through all possible initial
151 * test Patterns for walking ones test
154 for (j = 0U; j < (u32)32; j++) {
156 * Generate an initial value for walking ones test
157 * to test for bad data bits
163 * START walking ones test
164 * Write a one to each data bit indifferent locations
167 for (I = 0U; I < (u32)32; I++) {
168 /* write memory location */
170 Val = (u32) RotateLeft(Val, 32U);
174 * Restore the reference 'val' to the
179 /* Read the values from each location that was
181 for (I = 0U; I < (u32)32; I++) {
182 /* read memory location */
184 WordMem32 = *(Addr+I);
186 if (WordMem32 != Val) {
191 Val = (u32)RotateLeft(Val, 32U);
196 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
198 * set up to cycle through all possible
199 * initial test Patterns for walking zeros test
202 for (j = 0U; j < (u32)32; j++) {
205 * Generate an initial value for walking ones test
206 * to test for bad data bits
212 * START walking zeros test
213 * Write a one to each data bit indifferent locations
216 for (I = 0U; I < (u32)32; I++) {
217 /* write memory location */
219 Val = ~((u32)RotateLeft(~Val, 32U));
223 * Restore the reference 'Val' to the
229 /* Read the values from each location that was
231 for (I = 0U; I < (u32)32; I++) {
232 /* read memory location */
233 WordMem32 = *(Addr+I);
234 if (WordMem32 != Val) {
238 Val = ~((u32)RotateLeft(~Val, 32U));
244 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
245 /* Fill the memory with inverse of address */
246 for (I = 0U; I < Words; I++) {
247 /* write memory location */
248 Val = (u32) (~((INTPTR) (&Addr[I])));
253 * Check every word within the words
257 for (I = 0U; I < Words; I++) {
258 /* Read the location */
259 WordMem32 = *(Addr+I);
260 Val = (u32) (~((INTPTR) (&Addr[I])));
262 if ((WordMem32 ^ Val) != 0x00000000U) {
269 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
271 * Generate an initial value for
275 if (Pattern == (u32)0) {
283 * Fill the memory with fixed Pattern
286 for (I = 0U; I < Words; I++) {
287 /* write memory location */
292 * Check every word within the words
293 * of tested memory and compare it
294 * with the fixed Pattern
297 for (I = 0U; I < Words; I++) {
299 /* read memory location */
301 WordMem32 = *(Addr+I);
302 if (WordMem32 != Val) {
313 /*****************************************************************************/
316 * @brief Perform a destructive 16-bit wide memory test.
318 * @param Addr: pointer to the region of memory to be tested.
319 * @param Words: length of the block.
320 * @param Pattern: constant used for the constant Pattern test, if 0,
321 * 0xDEADBEEF is used.
322 * @param Subtest: type of test selected. See xil_testmem.h for possible
327 * - -1 is returned for a failure
328 * - 0 is returned for a pass
331 * Used for spaces where the address range of the region is smaller than
332 * the data width. If the memory range is greater than 2 ** Width,
333 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
334 * repeat on a boundry of a power of two making it more difficult to detect
335 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
336 * tests suffer the same problem. Ideally, if large blocks of memory are to be
337 * tested, break them up into smaller regions of memory to allow the test
338 * patterns used not to repeat over the region tested.
340 *****************************************************************************/
341 s32 Xil_TestMem16(u16 *Addr, u32 Words, u16 Pattern, u8 Subtest)
350 Xil_AssertNonvoid(Words != (u32)0);
351 Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST);
352 Xil_AssertNonvoid(Addr != NULL);
355 * variable initialization
357 Val = XIL_TESTMEM_INIT_VALUE;
358 FirtVal = XIL_TESTMEM_INIT_VALUE;
361 * selectthe proper Subtest(s)
364 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
366 * Fill the memory with incrementing
367 * values starting from 'FirtVal'
369 for (I = 0U; I < Words; I++) {
370 /* write memory location */
375 * Restore the reference 'Val' to the
381 * Check every word within the words
382 * of tested memory and compare it
383 * with the incrementing reference val
386 for (I = 0U; I < Words; I++) {
387 /* read memory location */
388 WordMem16 = *(Addr+I);
389 if (WordMem16 != Val) {
397 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
399 * set up to cycle through all possible initial test
400 * Patterns for walking ones test
403 for (j = 0U; j < (u32)16; j++) {
405 * Generate an initial value for walking ones test
406 * to test for bad data bits
409 Val = (u16)((u32)1 << j);
411 * START walking ones test
412 * Write a one to each data bit indifferent locations
415 for (I = 0U; I < (u32)16; I++) {
416 /* write memory location */
418 Val = (u16)RotateLeft(Val, 16U);
421 * Restore the reference 'Val' to the
424 Val = (u16)((u32)1 << j);
425 /* Read the values from each location that was written */
426 for (I = 0U; I < (u32)16; I++) {
427 /* read memory location */
428 WordMem16 = *(Addr+I);
429 if (WordMem16 != Val) {
433 Val = (u16)RotateLeft(Val, 16U);
438 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
440 * set up to cycle through all possible initial
441 * test Patterns for walking zeros test
444 for (j = 0U; j < (u32)16; j++) {
446 * Generate an initial value for walking ones
447 * test to test for bad
453 * START walking zeros test
454 * Write a one to each data bit indifferent locations
457 for (I = 0U; I < (u32)16; I++) {
458 /* write memory location */
460 Val = ~((u16)RotateLeft(~Val, 16U));
463 * Restore the reference 'Val' to the
467 /* Read the values from each location that was written */
468 for (I = 0U; I < (u32)16; I++) {
469 /* read memory location */
470 WordMem16 = *(Addr+I);
471 if (WordMem16 != Val) {
475 Val = ~((u16)RotateLeft(~Val, 16U));
481 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
482 /* Fill the memory with inverse of address */
483 for (I = 0U; I < Words; I++) {
484 /* write memory location */
485 Val = (u16) (~((INTPTR)(&Addr[I])));
489 * Check every word within the words
493 for (I = 0U; I < Words; I++) {
494 /* read memory location */
495 WordMem16 = *(Addr+I);
496 Val = (u16) (~((INTPTR) (&Addr[I])));
497 if ((WordMem16 ^ Val) != 0x0000U) {
504 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
506 * Generate an initial value for
509 if (Pattern == (u16)0) {
517 * Fill the memory with fixed pattern
520 for (I = 0U; I < Words; I++) {
521 /* write memory location */
526 * Check every word within the words
527 * of tested memory and compare it
528 * with the fixed pattern
531 for (I = 0U; I < Words; I++) {
532 /* read memory location */
533 WordMem16 = *(Addr+I);
534 if (WordMem16 != Val) {
546 /*****************************************************************************/
549 * @brief Perform a destructive 8-bit wide memory test.
551 * @param Addr: pointer to the region of memory to be tested.
552 * @param Words: length of the block.
553 * @param Pattern: constant used for the constant pattern test, if 0,
554 * 0xDEADBEEF is used.
555 * @param Subtest: type of test selected. See xil_testmem.h for possible
559 * - -1 is returned for a failure
560 * - 0 is returned for a pass
563 * Used for spaces where the address range of the region is smaller than
564 * the data width. If the memory range is greater than 2 ** Width,
565 * the patterns used in XIL_TESTMEM_WALKONES and XIL_TESTMEM_WALKZEROS will
566 * repeat on a boundry of a power of two making it more difficult to detect
567 * addressing errors. The XIL_TESTMEM_INCREMENT and XIL_TESTMEM_INVERSEADDR
568 * tests suffer the same problem. Ideally, if large blocks of memory are to be
569 * tested, break them up into smaller regions of memory to allow the test
570 * patterns used not to repeat over the region tested.
572 *****************************************************************************/
573 s32 Xil_TestMem8(u8 *Addr, u32 Words, u8 Pattern, u8 Subtest)
582 Xil_AssertNonvoid(Words != (u32)0);
583 Xil_AssertNonvoid(Subtest <= XIL_TESTMEM_MAXTEST);
584 Xil_AssertNonvoid(Addr != NULL);
587 * variable initialization
589 Val = XIL_TESTMEM_INIT_VALUE;
590 FirtVal = XIL_TESTMEM_INIT_VALUE;
593 * select the proper Subtest(s)
596 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INCREMENT)) {
598 * Fill the memory with incrementing
599 * values starting from 'FirtVal'
601 for (I = 0U; I < Words; I++) {
602 /* write memory location */
607 * Restore the reference 'Val' to the
612 * Check every word within the words
613 * of tested memory and compare it
614 * with the incrementing reference
618 for (I = 0U; I < Words; I++) {
619 /* read memory location */
620 WordMem8 = *(Addr+I);
621 if (WordMem8 != Val) {
629 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKONES)) {
631 * set up to cycle through all possible initial
632 * test Patterns for walking ones test
635 for (j = 0U; j < (u32)8; j++) {
637 * Generate an initial value for walking ones test
638 * to test for bad data bits
640 Val = (u8)((u32)1 << j);
642 * START walking ones test
643 * Write a one to each data bit indifferent locations
645 for (I = 0U; I < (u32)8; I++) {
646 /* write memory location */
648 Val = (u8)RotateLeft(Val, 8U);
651 * Restore the reference 'Val' to the
654 Val = (u8)((u32)1 << j);
655 /* Read the values from each location that was written */
656 for (I = 0U; I < (u32)8; I++) {
657 /* read memory location */
658 WordMem8 = *(Addr+I);
659 if (WordMem8 != Val) {
663 Val = (u8)RotateLeft(Val, 8U);
668 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_WALKZEROS)) {
670 * set up to cycle through all possible initial test
671 * Patterns for walking zeros test
674 for (j = 0U; j < (u32)8; j++) {
676 * Generate an initial value for walking ones test to test
681 * START walking zeros test
682 * Write a one to each data bit indifferent locations
684 for (I = 0U; I < (u32)8; I++) {
685 /* write memory location */
687 Val = ~((u8)RotateLeft(~Val, 8U));
690 * Restore the reference 'Val' to the
694 /* Read the values from each location that was written */
695 for (I = 0U; I < (u32)8; I++) {
696 /* read memory location */
697 WordMem8 = *(Addr+I);
698 if (WordMem8 != Val) {
703 Val = ~((u8)RotateLeft(~Val, 8U));
708 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_INVERSEADDR)) {
709 /* Fill the memory with inverse of address */
710 for (I = 0U; I < Words; I++) {
711 /* write memory location */
712 Val = (u8) (~((INTPTR) (&Addr[I])));
717 * Check every word within the words
721 for (I = 0U; I < Words; I++) {
722 /* read memory location */
723 WordMem8 = *(Addr+I);
724 Val = (u8) (~((INTPTR) (&Addr[I])));
725 if ((WordMem8 ^ Val) != 0x00U) {
732 if((Subtest == XIL_TESTMEM_ALLMEMTESTS) || (Subtest == XIL_TESTMEM_FIXEDPATTERN)) {
734 * Generate an initial value for
738 if (Pattern == (u8)0) {
745 * Fill the memory with fixed Pattern
747 for (I = 0U; I < Words; I++) {
748 /* write memory location */
752 * Check every word within the words
753 * of tested memory and compare it
754 * with the fixed Pattern
757 for (I = 0U; I < Words; I++) {
758 /* read memory location */
759 WordMem8 = *(Addr+I);
760 if (WordMem8 != Val) {
772 /*****************************************************************************/
775 * @brief Rotates the provided value to the left one bit position
777 * @param Input is value to be rotated to the left
778 * @param Width is the number of bits in the input data
781 * The resulting unsigned long value of the rotate left
784 *****************************************************************************/
785 static u32 RotateLeft(u32 Input, u8 Width)
791 u32 LocalInput = Input;
794 * set up the WidthMask and the MsbMask
797 MsbMask = 1U << (Width - 1U);
799 WidthMask = (MsbMask << (u32)1) - (u32)1;
802 * set the Width of the Input to the correct width
805 LocalInput = LocalInput & WidthMask;
807 Msb = LocalInput & MsbMask;
809 ReturnVal = LocalInput << 1U;
811 if (Msb != 0x00000000U) {
812 ReturnVal = ReturnVal | (u32)0x00000001;
815 ReturnVal = ReturnVal & WidthMask;
822 /*****************************************************************************/
825 * @brief Rotates the provided value to the right one bit position
827 * @param Input: value to be rotated to the right
828 * @param Width: number of bits in the input data
831 * The resulting u32 value of the rotate right
833 *****************************************************************************/
834 static u32 RotateRight(u32 Input, u8 Width)
840 u32 LocalInput = Input;
842 * set up the WidthMask and the MsbMask
845 MsbMask = 1U << (Width - 1U);
847 WidthMask = (MsbMask << 1U) - 1U;
850 * set the width of the input to the correct width
853 LocalInput = LocalInput & WidthMask;
855 ReturnVal = LocalInput >> 1U;
857 Lsb = LocalInput & 0x00000001U;
859 if (Lsb != 0x00000000U) {
860 ReturnVal = ReturnVal | MsbMask;
863 ReturnVal = ReturnVal & WidthMask;
868 #endif /* ROTATE_RIGHT */