XJEase Exercises

This exercise will demonstrate the use of some features of the XJEase language. XJEase has many features, not all of which are covered in this exercise. For more details look at the XJEase Language section of this help system. The exercise builds on the completed demo project: CompletedTutorial4.zip.

  • Extract the zip file CompletedTutorial4.zip to a new empty directory of your choice.
  • Navigate into the Board Test directory.
  • Open the XJDemo Board.xjd project using XJDeveloper.

The exercise is divided into sections:

Unlike most of the other exercises in this tutorial, this exercise does not give full step-by-step instructions. It tells you what each function should do and gives you information about the language features needed to implement that functionality. There are example functions at the end of each section in case you have any problems getting your version running correctly.

  • A blue box has instructions in it for you to follow.
  • An orange box has a task for you to complete. There may be multiple ways to accomplish the task.

After each section of the exercise, sample solutions are provided for each of the tasks in the section, with a button to reveal them. The sample solution is unlikely to be the only way to accomplish the task but if you get stuck then it shows you a way it could be done. And even when you succeed at the task, the example may be worth checking to see if there was an easier way to do it.

XJEase is used to write functions in two sections of XJDeveloper:

  • Test Device Files – functions in these files are used to interact with the functionality of individual devices that don’t implement boundary scan, such as memory devices, sensors, LEDs etc.
  • Circuit Code Files – functions in these files have a wider scope than those in Test Device Files. Importantly, they cannot directly control the pins of devices on the board.

Section 1: Circuit Code File Function

The first function that you are going to create will be in a Circuit Code File. This code that you write will first demonstrate how to print text to the Test Output pane on the Run Tests screen. You will then move on to add looping and conditional branching language features.

  • Click the Circuit Code Files screen button under the Setup header on the left of XJDeveloper.
  • At the top of the Circuit Code Files screen, click the button and select New... from the dropdown menu.
  • Name the file CircuitTest.xje and click Save.

A new GLOBAL function will have been automatically created in your new file to show you the structure of a function in XJEase. This function can be used as a template or directly modified to contain your code.

More generally XJEase functions take the form:

FunctionName(inputParameterList)(outputParameterList)
    // XJEase Statements
END;

The parameter lists are comma-separated and specify both the Type and Name of each parameter. Input parameters are passed by value so any changes you make to those in your function have no effect in the calling function. Output parameters are passed by reference so that any changes you make will be reflected in the variable specified in the calling function.

Functions that you need to call directly in XJRunner must have a single integer output parameter that defines whether the test has passed or failed. Most commonly such functions will have no input parameters, but it is possible to use functions that do have them.

When developing XJEase code, the editor will use multiple colours. Language keywords, such as END in the case of the example function that has been added to your file, and items such as comments or string and integer values, will show as different colours to improve clarity when reading code.

To get help on language keywords you can press F1 with the text cursor on that word.

You will notice that RESULT_FAIL in the example function is not a reserved word, it is a GLOBAL constant defined in another Circuit Code File, Globals.xje.

The assignment of RESULT_FAIL to the result variable is done with the := operator. In XJEase := is used for assignment and = is used for comparison.

The first function you are going to create will simply print some text to the Test Output pane.

Task 1a

  • Add a function to your Circuit Code File called MyCircuitCodeFunction and add a line of code to print Hello World.
    • Required keyword(s): PRINT.
  • Check that you have no syntax errors in your code by looking in the Errors Pane at the bottom of the screen.
  • Once there are no errors click the Save button on the Circuit Code Files screen's menu bar.

Now that the function exists, it can be added to the XJRunner Setup screen's XJRunner Tests list

  • Click XJRunner Setup under Run and Deploy in the screen selector.
  • Click Add Group... at the bottom of the XJRunner Tests section.
  • Set the Name of the test group to XJEase tutorial functions.
  • Click the Add Global Function button.
  • Select MyCircuitCodeFunction.
  • Click OK in the Available Global Functions dialog.
  • Click OK in the New Test Group dialog to confirm the creation of the test group.
  • Click the Save button on the main XJDeveloper toolbar.

To run your function do the following:

  • Click the Run Tests screen button under the Run and Deploy header.
  • Deselect all the currently selected tests by clicking on Presets at the bottom of the test list on the right of the screen and select None.
  • Click on the XJEase tutorial functions test group to tell XJDeveloper that you want to run the functions in that group.
  • Click the Run button.

You should see that that Hello World is printed when the function runs.

Now that you have some text being output you are going to start to introduce some additional XJEase language features by making yout code output that text multiple times.

Task 1b

  • Modify your MyCircuitCodeFunction to print the text 10 times, with a newline at the end of each line.
    • Required keyword(s): FOR, END.
  • Go to the Run Tests screen and re-run your function to make sure you see the results that are expected.

The next modification is to format the text that is being output.

Task 1c

  • Modify your MyCircuitCodeFunction to print the output text in red and enlarged to 150% of normal size.
    • Required keyword(s): PRINT_FORMAT.
  • Go to the Run Tests screen and re-run your function to make sure you see the results that are expected.

To show a different type of looping, modify your code to repeated print Hello World until the operator presses a key on the keyboard.

Task 1d

  • Modify your MyCircuitCodeFunction to loop until a key is pressed on the keyboard.
    • Required keyword(s): DO, WHILE, END, GETKEY.
    • N.B. You will also need to use SLEEP in your loop to allow your PC time to service the keypress, without this all the processor time would be taken updating the screen.
  • Go to the Run Tests screen and re-run your function to make sure you see the results that are expected.

The previous modification varied the behaviour of the function depending on user feedback but the result was the same whichever key they pressed. For the next modification change the result returned depending on whether the spacebar or a different key is pressed.

Task 1e

  • Modify your MyCircuitCodeFunction to check which key was pressed and return pass if it was the spacebar, or fail if any other key is pressed.
    • Required keyword(s): IF, THEN, ELSE, END.
    • N.B. A pass result when running tests is the value 0 and a failure is indicated by any value greater than 0. Use RESULT_PASS and RESULT_FAIL (these are defined in globals.xje) to set the return value.
  • Go to the Run Tests screen and re-run your function to make sure you see the results that are expected.

So far you have always been printing the same text, for the next modification print strings stored in an array.

Task 1f

  • Modify your MyCircuitCodeFunction to print the content of a jagged array.
    • Required keyword(s): Use either FOREACH or WIDTHOF
    • N.B. you will also need to use [] to declare the array and {..} to set its contents as shown:
      STRING[][] jaggedArray := {{"Hello World Test\n"}, {"Hello ", "World Test\n"}, {"Hello ", "World ", "Test\n"}};
      		  
  • Use nested FOREACH loops to iterate over the contents of the array and print each element to the screen. Alternatively you could use FOR loops, in which case you would need to Use WIDTHOF to know how many iterations should happen in each FOR loop.
  • Go to the Run Tests screen and re-run your function to make sure you see the results that are expected.

That completes section 1 of this exercise. Click the button to see example functions that perform the operations described in each task section above.

Section 2: Test Device File Function

This section of the exercise focuses on creating functions in Test Device Files; however, it will also introduce interacting with functions in Test Device Files from Circuit Code functions.

The first function you are going to create will again simply print some text to the Test Output pane.

  • Click the Test Device Files screen under Setup in the screen selector.
  • Double-click on the test device file assigned to the eight LEDs – LED (pin 2).xje. You will notice that there is a + sign next to this file. This indicates that the file makes use of one, or more, Additional Code Files. These are used to contain functions you want to have available from different files in your project. You are not going to use these files now but you will a little later in this exercise.

Task 2a

  • Add a new function called HelloWorld to print the text “Hello World”. Remember it will need to have no input parameters and one integer output so it can be called from the XJRunner Test List.
  • Click Save to make sure you don’t have any syntax errors.

Add your function to the XJRunner test list for each of the LEDs (because all the LEDs are categorised unit the same file the function will be available to run against all the devices):

  • Click XJRunner Setup under Run and Deploy in the screen selector.
  • Select your existing XJEase tutorial functions test group from the list of XJRunner Tests.
  • Click the Edit... button.
  • Expand the list of Suggested Diodes in the Test Device Selector.
  • Using shift-click, select all 8 LEDs.
  • Select HelloWorld from the Function Name section below the list of devices.
  • Click OK in the Edit Test Group dialog to confirm the addition of these tests.
  • Click the Save button on the main XJDeveloper toolbar.
  • Run these new functions on the Run Tests screen. You will have your previous Circuit Code function also selected but you should have 8 new sets of output, one for each of the LEDs.

At the moment all the LEDs are printing the same message. The next modification is to change the output generated by the function depending on the device that the function is being run against.

Task 2b

  • On the Test Device Files screen update your PRINT statement to say which device is printing the message.
    • New keywords: DEVICE_REF

You will need to use the system variable DEVICE_REF. To add this to your printed output you could have a second PRINT statement, or you could concatenate two STRINGs in a single PRINT statement using either of the string concatenation operators ':' or '+'. Alternatively, the PRINT statement can take multiple input parameters that it will automatically concatenate, so separating strings with commas ',' in the PRINT statement will also work.

  • Run your modified function and check that you now get output in the form Hello world from D1 etc.

To link up the first section of this exercise with this section you are now going to update your Circuit Code File function MyCircuitCodeFunction to run the LED versions you have just created.

Task 2c

  • On the Circuit Code Files screen edit your MyCircuitCodeFunction function so that it does not print anything itself but rather runs the HelloWorld function for LED D1.
    • New keyword(s): CALL.
    • N.B. You will need to make sure that the HelloWorld function in LED (pin2).xje is configured to be GLOBAL or you will get a syntax error.
  • Run your modified function and check that the MyCircuitCodeFunction function now prints Hello world from D1.

It was mentioned above that LED (pin 2).xje used an Additional Code File. The next task is to move your HelloWorld function from LED (pin 2).xje and put it in its own Additional Code File. This will then allow you add this functionality to any device simply by adding your Additional Code File to the device's Test Device File.

  • On the Test Device Files screen click on the Additional Code Files tab at the bottom of the right-hand pane, below where you have added your HelloWorld function.
  • Click the Add... button and then select New.... Set the name of your new file to Hello World and then click Save. This will create the new file and add it as an Additional Code file to your Test Device File, but will not open it for editing.
  • Select all the text of your HelloWorld function in LED (pin 2).xje and cut it to the clipboard. The project will show errors at this stage, because the entries in the Test List for running this function are no longer valid now the function has been removed.
  • Double-click on the HelloWorld.xje file name in the list of Additional Code Files at the bottom right of the screen to open that file in the editor.
  • Paste the function you have on your clipboard into this file.
  • Click on the Save All icon on the Test Device Files toolbar to save your changes to both LED (pin 2).xje and the new Additional Code File, HelloWorld.xje.
  • Run your modified project and check that you still get output in the form Hello world from D1.
  • Go back to the Test Device Files screen and add the HelloWorld.xje additional code file to Pushbutton.xje.
  • Go to the XJRunner Setup screen and add the HelloWorld function for SW1.
  • Run this new test and see that it now prints "Hello world from SW1.

That completes section 2 of this exercise. Click the button to see example functions that perform the operations described in each task section above.

Section 3: Integer operations

This section of the exercise will introduce you to integer variables in XJEase and how they can be manipulated. Please review the help about the Integer variable type as XJEase integers a different to those you may have worked with before.

You will use integer operators including bit manipulation, arithmetic, comparison, bitwise and Boolean operations.

Task 3

  • Create a new Circuit Code function called IntegerExample that loops through the numbers 0 to 9, printing out each number on a new line.
  • Add your function to the XJRunner Test List and run your function on the Run Tests screen to make sure it produces the expected output.

Task 3 (continued)

  • Modify your function to print the numbers as four bit binary rather than decimal.
    • New keyword(s): BIN, WIDTH.
    • N.B. XJEase also includes the HEX keyword to format an integer as a hexadecimal string.
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.
  • To make it clear that the values displayed are binary, modify your function to prefix the binary value with 0b.
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.
  • Modify your function to print the number 1 bit shifted left by your loop counter.
    • New operator(s): << - left shift.
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.
  • Modify your function so it doesn’t display the least significant bit of the value.
    • New operator(s): [x..y] - bit selection.
    • N.B. Bit selection indexing is 0-based not 1-based.
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.
  • Modify your function so that it displays the bitwise complement of the value.
    • New operator(s): ~ - bitwise complement
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.
  • Modify your function so that it uses a bit mask and prints a message if bit 2 is set to 1.
    • New operator(s): & - bitwise AND.
    • N.B. You will also need to use parentheses, (..), to control the sequence of operations.
    • Run your modified function on the Run Tests screen to make sure it produces the expected output.

There are a significant number of integer operations that have not been used in this section of the exercise. You can find the full set of the available operators in the main XJTAG help.

That completes section 3 of this exercise. Click the button to see an example function that performs all of the different operations described in the task sections above.

Section 4: Simple Memory Testing

Up to this point all the functions you have developed could have been written in almost any programming language. The main reason why you are learning to write XJEase is to be able to control and monitor the states of pins/nets on a physical PCBA. In this section of the exercise, you will write functions that do interact with the hardware.

The Test Device File used to categorise the SRAM during the tutorial performs a comprehensive test of all the signals on that device. Your first task is to use the read and write cycles from the existing files to implement a much simpler, 'walking ones', test of the pins on the data bus.

  • Open the file SRAM 48Pin BGA 4Mb x16.xje on the Test Device Files screen
  • From the Additional Code Files tab open SRAM_Bank_Testing.xje and review the ReadCycle and WriteCycle functions to understand how they work (take some time to read the help for the SET keyword).
    • N.B. The XJEaseDocs (triple slash comments) define the what the parameters do in each function.

Task 4a

  • Go back to SRAM 48Pin BGA 4Mb x16.xje and create a new function called MySRAMTest that uses ReadCycle and WriteCycle to perform a "walking ones" test across the data bus. You will need to use a lot of the syntax from earlier in this exercise to complete this function. The suggested structure is:
    • Create a loop with one pass for each of the bits of the data bus (using the WIDTHOF keyword). For each bit in the bus:
      • Write 1 shifted left by the bit number to address 0
      • Read back the data from the address that was written
      • Verify that the data read matches the data written.
  • Add your function to the XJRunner Test List.
  • Run your function on the Run Tests screen to make sure it produces the expected output – >>>> PASSED <<<<.
  • Use the jumper on the demo board to create a stuck at 1 fault on net D3.
  • Run your function on the Run Tests screen to make sure it produces the expected output – >>>> FAILED <<<<.

Testing an address bus is more complicated than testing a data bus. If you follow the same process as used for the data bus test, i.e. write and then immediately read, then the expected value will almost certainly be read even if there is an issue with an address bus pin. This is because the fault on the address bus will result in the same incorrect address being used for both reading and writing.

To overcome this an address bus test must, as its first stage, write unique data values to the set of addresses resulting from performing a walking one’s pattern across the address bus.

An additional test is needed at address 0 to help find all open circuit faults. If these values can be read back then there will not be any faults with the address bus pins.

Task 4b

  • Modify your MySRAMTest to perform an address bus test as well as a data bus test.
  • Run your function on the Run Tests screen to make sure it produces the expected output – >>>> PASSED <<<<.
  • Use the jumper on the demo board to create an open circuit fault on A8.
  • Run your function on the Run Tests screen to make sure it produces the expected output – >>>> FAILED <<<<.

That completes section 4 of this exercise. Click the button to see example functions that perform the tests described in the task sections above.

Section 5: Multiple Device Testing

There are times when you will need to write a test that involves multiple non-JTAG devices. This section of the exercise deals with creating such a test.

Task 5a

  • Create a new Circuit Code function called LEDPushButtonTest that flashes LED D1 until the operator presses the push button on the board to indicate a pass or a key on the keyboard to indicate a failure.
    • N.B. There are no new required keywords for this function; however, you will need to CALL to functions in the Test Device Files for both the LED and the push button inside your control loop, along with checking for keyboard input. You will need to look in those Test Device Files to know what functions to CALL. Make sure you return the correct result to indicate pass or fail.
  • Add your function to the XJRunner Test List.
  • Run your function on the Run Tests screen to make sure it produces the expected output.

It is good practice to add documentation to your functions. In XJEase this is best done using XJEaseDocs. This documentation is useful for anybody maintaining your code (think of the engineer to come after you). It is also used when generating a Test Coverage Summary Report from the Test Coverage screen.

Task 5b

  • Add XJEaseDocs for the LEDPushButtonTest function.
    • N.B. There are no new keywords needed for this modification, but you will need to use /// XJEaseDocs comment marks. The description of the function is simply prefixed with the /// and can span multiple lines. For the other documentation you will need to use the following specific syntax:
      • @param – one line per parameter specifying the parameter name and giving a description.
      • @devices – one line per function specifying the devices tested by the function as a comma separated list.
      • @testfunction – one line per function specifying if a function should be automatically added to XJRunner Test List, and whether a test should be set to run by default.
      • @groupname – one line per function specifying the name of the Test Group in the XJRunner Test List to which the test function should be added.
  • Go to the Test Coverage screen and generate a Test Coverage Summary Report to check that the function description is correctly reported.

That completes section 5 of this exercise. Click the button to see example functions that perform the tasks described in the sections above.