Some prime examples of the value of this generality, as seen in the Appendix Section A.3, are the error detection test groups. These test groups needed to create some very unusual input patterns in order to determine if the error detection functions were working correctly. Without the ability to put any block of Verilog code in a test group, these tests could never have been integrated seamlessly with the rest of the system. Many subtle bugs were uncovered by the test groups that focused on errors.
Other good examples of tests that rely on the generality of this system are the JTAG tests, one of which is described in Appendix Section A.4. These tests did not integrate quite as seamlessly into the system as did the errors test groups, since special functions needed to be written for them, but they were relatively easy to write because of the structured framework they fit into. The JTAG tests uncovered several problems related to the stitching of the scan rings.
The random tester appears to be very general as well. Considerable effort has gone in to making it capable of generating a wide variety of inputs. Also, it is possible to determine types of bugs that the random tester has no chance of detecting, and focus directed testing on cases that have a good chance of detecting those bugs. This seems to be a very general, comprehensive approach to random testing.
I used this quick mode quite heavily whenever I found myself debugging portions of the chip that I did not design. By placing signal probes and re-simulating I was able to track down several typographical errors without any help from the implementors themselves. The time to re-simulate after changing probes was short enough to make this kind of debugging possible.
This does not mean that the system is impossible to use. Great effort was put into providing simple ways to specify common inputs, and generating a specific input pattern and checking for a specific output pattern was generally very easy to do, no matter how unusual the pattern was. For example, it would take about 30 minutes for someone familiar with the system to write a test group that disables output port 2 and sends, 3 cycles after disabling, a packet destined for port 2 with the value 057b3aff in the 14th word of its payload into port 1. This could be very useful if such an input pattern was believed to reveal a bug. Our hope was to make specification of such tests easy, and the system succeeds in this goal.
The main problem with this system is that normal cases are not much easier to specify than unusual cases, despite our efforts to simplify these cases. If the user wanted a test group that did something as simple as sending 100 different packets through the system each 10 cycles apart, this could take hours to create because the user has to specify every bit of every packet and define exactly what time each of these packets should be sent into the system, as well as exactly which output port each should emerge from. In most test groups, the user needs to send a large number of packets, but the system gives the user such precise control over these packets that it is impossible to send a packet unless it is described in every detail. Some solution to this problem was needed. We created some packet generation programs, but these were rather awkward and often generated an unmanageable number of packets. Perhaps this problem could have been solved by putting random packet generators in each input port's stub. Test groups could specify a few parameters for these random packets and let the system worry about generating them. Tests of this kind were called ``bashers'' by the team working on the Alewife cache controller, and apparently uncovered many bugs [7].
Another reason designing test groups was so difficult was that the structure of the files used in these test groups was very unintuitive. Remember that Verilog can only read in files with binary or hexadecimal data. That meant that every file that specified some detail of a test had to be encoded, adding an extra layer of confusion to the testing process. Imagine, for example, that the user wants to send packet 5 into port 1 at time 0. To do this, the user has to create a packet insertion file that looks like this.
00000000000000001 00000000000000052Since it would take an inhuman memory to recall the exact position of each of these bits, the user is forced to call up the testing system user's manual when this file is created, or whenever it needs to be modified. This slows the user down, and makes life very confusing. If the file instead contained the line ``Insert packet 5 into port 1 at time 0,'' the system might have been much easier to use. It would not have been easy to add this ability to the system, but it is possible it could have been supported as a pre-simulation step that would translate more easily understood descriptions like the one above into hexadecimal numbers before the simulation. A simpler and perhaps just as effective approach would be to make all test files a kind of table that the user would fill out. The pre-simulation step could then remove everything but the numbers, which would be input by the Verilog simulation.
It seems, then, that the only big problem with this functional testing system is its complexity. Indeed, many members of the team never learned to use the system at all because it takes so long to learn. Even those who do understand it avoid using it regularly.
Still, this system has been successfully used to carry out extensive testing of the Arctic chip. Countless bugs have been uncovered through directed testing with the original system. Many examples of these tests can be found in Appendix A. The random tester has found only one bug, but has the potential to find many more if it is completed. Also, beyond these practical concerns, this system has been a wonderful test bed for many ideas related to functional testing.