Abstract:
A method and apparatus for testing one of a plurality of revisions of a microprocessor by creating an abstract base class which specifies the names of a plurality of tests or attributes, creating a derived class for each revision and defining each of the tests or attributes appropriately for each of the derived classes, instantiating an object from one of the derived classes and executing the tests by reference to the object. A computer system is configured to be coupled to a microprocessor which may be any one of a plurality of revisions. Upon execution of a debug/test application on the computer system, the revision of the microprocessor is determined and the object is instantiated from the derived class corresponding to the revision. The object is thereby dynamically bound to the tests defined for the derived class corresponding to the revision and references to each test via the object automatically execute the test code specific to the revision of the microprocessor. The microprocessor may be replaced with a second microprocessor having a second revision. A second object is instantiated from the derived class corresponding to the second revision and the tests are executed via reference to the second object, thereby automatically executing the test code specific to the second revision.

Description:
CROSS-REFERENCE TO RELATED APPLICATION 
     This application relates to co-pending application, Ser. No. 09/137,572 filed on the same day as the present application and entitled “METHOD FOR UTILIZING VIRTUAL HARDWARE DESCRIPTIONS TO ALLOW FOR MULTI-PROCESSOR DEBUGGING IN ENVIRONMENTS USING VARYING PROCESSOR REVISION LEVELS” by Michael Wisor, Travis Wheatley and James A. Treadway, which is incorporated herein by reference. 
    
    
     BACKGROUND OF THE INVENTION 
     1. Field of the Invention 
     The invention relates generally to methods for testing device designs and more particularly to object-oriented programming methods for performing revision-specific tests on several devices which may have differing designs and differing test requirements. 
     2. Description of the Relevant Art 
     Various problems are encountered in the development of integrated circuits (ICs), printed circuit boards and system level devices. As a result of the increasing speed and complexity, as well as the decreasing size of ICs, it is becoming more and more difficult to test and debug the design and operation of these products. (Debugging is the process of finding and eliminating problems, or bugs, in hardware or software.) When a new design is implemented, it must be debugged and tested to ensure that the device operates as expected. The complexity of debugging and testing has grown commensurately with the complexity of the devices themselves. The increased costs and time to debug and test can cause delays which disrupt manufacturing flows and hinder manufacturers&#39; efforts to bring the products to market. 
     A great deal of the time required to develop and implement new microprocessor designs is spent on debugging the design. The impact of debugging on the development cycle of a new microprocessor has resulted in the development of faster and more powerful debugging tools. These tools may include features internal to the microprocessor which facilitate debugging, as well as external tools such as logic analyzers and debug/test software. 
     Microprocessor debug and test systems in the prior art are typically implemented using a personal computer (PC) which is interfaced with the microprocessor under test. The PC is coupled to interface hardware, which is in turn coupled to the microprocessor. Software tools are executed on the PC to provide debug/test functionality. The debug/test setup may also be configured to be used with multiple processors. A multi-processor test system uses essentially the same setup as a uniprocessor test system but, in the multi-processor system, the interface hardware is required to detect signals generated by the debug/test software and determine which of the processors is the intended recipient of each signal. Likewise, the responsive signals produced by each of the processors must be identified to the debug/test software as originating from a particular processor. The interface hardware may therefore be very complex and expensive. 
     Software debug/test tools may also be very complex. Many individual tests must be conducted on a microprocessor to ensure that the device performs each of its functions properly. The testing of the microprocessor is made more complicated by the fact that there are normally a number of revisions of each processor design. The various revisions may have differences which require that a particular test be performed differently on each revision. Program code which correctly performs the test on one of the revisions of the microprocessor may therefore have to be modified before it can be performed on another of the revisions of the microprocessor. The revised test may use different data, or it may involve the execution of entirely different instructions. The test system should provide the capability to test a first processor of a first revision and then test a processor of a second revision without having to entirely reconfigure the system. A debug/test application must be programmed with the appropriate data and/or test procedures for each of the revisions. 
     There are several approaches to the problem of testing the different revisions of a microprocessor. The simplest approach is to determine the appropriate test for each feature of a particular revision and code these tests into a debug/test application which is designed specifically for that revision. A separate application is then created for each revision. This approach has several drawbacks: it necessitates a large amount of code; the code for one revision may be duplicative of a substantial portion of the code for another revision; and modifications to a test which is identical in the code for each revision must be made separately to the applications for each of the revisions. 
     A similar approach entails including all of the test code for each revision in a single application and using preprocessor directives (e.g., #if and #endif) to select portions of the test code to be retained in the compiled application. While this technique would simplify the maintenance of the debug/test code by avoiding duplication of some tests and modifications to those tests, the microprocessor revision must be determined at compile time, so the application must be recompiled each time a different revision is to be tested, or separate executable applications must be maintained for each revision. This approach therefore requires large amounts of resources, either for storage or compiling. 
     A somewhat less cumbersome approach is to develop a single application which uses branches in the program flow to execute the particular code which is appropriate to each revision of the processor. For each test which varies between the different revisions of the microprocessor, one or more branches are added to the application, each branch containing instructions specific to one of the revisions. When a branch is encountered in the application, the appropriate fork of the branch is selected and the corresponding instructions executed. These branches may be implemented using multiple “if-then” type statements. A pseudocode example illustrating the use of “if-then” statements is shown below. 
     
       
         
               
               
               
             
               
               
             
               
               
             
               
               
             
               
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 TEST1: 
                 {run test 1 (all processor revisions)} 
               
               
                   
                 TEST2: 
                 if(revision == A) 
               
             
          
           
               
                   
                 then {run test 2 for processor revision A} 
               
             
          
           
               
                   
                 if (revision == B) 
               
             
          
           
               
                   
                 then {run test 2 for processor revision B} 
               
             
          
           
               
                   
                   
                 else {run test 2 for processor revision C} 
               
               
                   
                 TEST3: 
                 {run test 3 (all processor revisions)} 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                   
               
             
          
         
       
     
     The increased complexity of the code is illustrated more graphically in FIG.  1 . FIG. 1 includes, on the left, a flow diagram of a series of three tests for a single revision and, on the right, a flow diagram of these same tests where one of the tests must be modified for each of three microprocessor revisions. With a single revision, each of the three tests is programmed and executed in a straightforward, sequential fashion. With the three separate test revisions, the test code becomes more complex. 
     The branches for the different versions of the test are also implemented in many cases using “switch” statements such as 
     
       
         
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 switch (revision) 
               
             
          
           
               
                   
                 case (A) 
               
             
          
           
               
                   
                 {run test for processor revision A} 
               
             
          
           
               
                   
                 case (B) 
               
             
          
           
               
                   
                 {run test for processor revision B} 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                   
               
             
          
         
       
     
     This method of coding the debug/test software can be very cumbersome. If several revisions must be provided for in a particular test within a debug/test application, the code for that test must be replaced with each of the several code variations corresponding to the several revisions. This replacement must be made for every occurrence of the test in the application. Likewise, if the application must be updated to account for a new revision of the microprocessor, the application programmer must not only write new test code, but must also locate each and every instance in the debug/test application in which one of the new tests may be executed. Each instance must then be individually updated for the new revision. 
     Because a microprocessor may have many hundreds of functions which must be tested, test variations necessitated by the different microprocessor revisions can cause the test application to become quite large and the complexity of the branch structure may make the application confusing and difficult to maintain. As mentioned above, the size of the application may tax the storage resources of the test system. The application will also be less efficient than a single-revision application as a result of the time which must be spent executing the control instructions that determine which branch will be taken and which test will be executed. 
     The size and complexity of the debug/test software is made even greater by the need to allow for concurrent testing of multiple processors. Just as the various levels of processor revisions necessitated additional branches in the application code, the concurrent testing of several processors can require additional, unwieldy program branches. The additional branches therefore compound the size and complexity problems found in single-processor debug/test applications. 
     SUMMARY OF THE INVENTION 
     These and other problems may be solved by various embodiments of an object-oriented method and system for performing tests on a microprocessor wherein the tests are specifically designed for a particular revision of the microprocessor. The method and system take advantage of software programming techniques involving pure virtual functions, abstract base classes, dynamic binding, inheritance and polymorphism and may result in reduced code size and increased maintainability. 
     A base class is used to enumerate various attributes of a device and various operations relating to the device. For each revision or variation of the device which is to be tested, a class is derived from the base class. The derived class may be used to define the enumerated operations and may also be used to define or assign values to the attributes. Several derived classes corresponding to different revisions will therefore have identically named functions, but the functions themselves may be different. 
     In one embodiment, the base class is an abstract base class. That is, the class provides names for the member operations and attributes, but does not define them. It is left to the derived classes to provide definition to the operations (i.e., provide code)and to assign values to the attributes. In another embodiment, the base class not only names the operations and attributes, but also defines one or more of them. In this manner, the base class provides defaults for the derived classes. If one of the derived classes requires an operation or attribute which differs from that of the base class, it can be defined in the derived class. This definition will override the default supplied by the base class. 
     When a device is tested, its revision or variation is determined and an object is instantiated from the class corresponding to the revision or variation. When a function (e.g., test) related to the device is to be performed, the function is called via a reference to the instantiated object. Likewise, when data relating to the device is needed, the data is referenced via the instantiated object. Because the only data and functions “known” to the object are those defined in the corresponding derived class, and because the derived class defines the revision-specific tests and data, the debug/test application automatically uses the revision-specific data and functions appropriate to the microprocessor under test. 
    
    
     BRIEF DESCRIPTION OF THE DRAWINGS 
     Other objects and advantages of the invention will become apparent upon reading the following detailed description and upon reference to the accompanying drawings in which: 
     FIG. 1 is a pair of flow diagrams illustrating a series of tests for a single revision of a microprocessor and a series of tests to accommodate several different revisions of the microprocessor. 
     FIG. 2 is a diagram of the debug and test system hardware for a single processor. 
     FIG. 3 is a diagram of the debug and test system hardware for multiple processors. 
     FIG. 4 is a top-level block diagram illustrating the steps for testing a microprocessor in accordance with one embodiment of the invention. 
     FIG. 5 is a diagram illustrating the inheritance of attributes and operations between a base class and a derived class, and the instantiation of an object from one of the derived classes. 
     While the invention is susceptible to various modifications and alternative forms, specific embodiments thereof are shown by way of example in the drawings and will herein be described in detail. It should be understood, however, that the drawing and detailed description thereto are not intended to limit the invention to the particular form disclosed, but on the contrary, the intention is to cover all modifications, equivalents and alternatives falling within the spirit and scope of the present invention as defined by the appended claims. 
    
    
     DETAILED DESCRIPTION OF THE PREFERRED EMBODIMENTS 
     One embodiment of the invention is described in detail below. This embodiment uses object oriented programming techniques to simplify the program flow of a debug/test application for a microprocessor. Alternate embodiments may be used to test other types of ICs, printed circuit boards or system level devices. The simplification of the program flow may result in reduced code size, improved readability and improved maintainability. 
     In one embodiment the debug and test system uses a computer system such as a PC to execute a debug/test software application. Referring to FIG. 2, a diagram of the debug and test system is shown. The system comprises a PC  10  which is coupled to interface hardware  12 , which is in turn coupled to microprocessor  13 . In one embodiment, interface hardware  12  is a simple, multiple-conductor cable which has a first end configured to be connected to an output port of PC  10  and a second end configured to be connected to a test port on microprocessor  13 . Debug/test application  11  is executed on PC  10  and test signals generated by the application are input to microprocessor  13  via interface hardware  12 . The output signals generated by the microprocessor as a result of the test are returned via interface hardware  12  to PC  10  for use by debug/test application  11 . 
     In one embodiment, the microprocessor under test is configured with a JTAG test access port. The JTAG port was designed by a group of manufacturers in the electronics industry who combined to develop a port to facilitate testing of microprocessors and other ICs. The JTAG standard was adopted by the Institute of Electrical and Electronics Engineers (IEEE) as IEEE Standard 1149.1-1990. Devices which implement this standard allow test data and instructions to be serially read into and out of the devices. 
     The debug/test setup may also be configured to be used with multiple microprocessors. Referring to FIG. 3, a diagram of a multi-processor debug/test system is shown. This system uses a PC  20  to execute debug/test application  21  and is coupled to microprocessors  23  and  24  through interface hardware  22 . In one embodiment, interface hardware  22  is a multiple-conductor cable, one end of which is configured to be connected to a parallel port of PC  20 , the other end of which has several connectors configured to be connected to test ports of microprocessors  23  and  24 . For example, a printer-type cable can be modified with connectors adapted to be connected to the JTAG ports of the microprocessors. Because this configuration utilizes a parallel (printer) output port and independent lines to each of the microprocessors, the output signals to the individual microprocessors can be directed to the appropriate lines by setting data within the objects representing the respective microprocessors. Likewise, input signals received from the microprocessors can be identified by the lines which carry the signals. Interface hardware  22  therefore need not incorporate any switching logic to route the signals between microprocessors  23 ,  24  and PC  20 . In other embodiments, however, more complicated interface hardware which itself routes signals between the PC and microprocessors may be used. For instance, if each microprocessor test port requires five lines and five microprocessors are to be tested, a standard parallel printer port does not have enough lines to assign each one to an individual microprocessor, so the interface hardware must provide for sharing of the lines. 
     As noted above, the test code generates signals which are applied to the inputs of the microprocessor to test performance of the microprocessor&#39;s functions and operations. The outputs of the microprocessor are then examined to determine whether the microprocessor functions properly. The various revisions of the design may use different inputs to perform identical functions, or the functions may produce different outputs. In one embodiment, the selection of the appropriate inputs and examination of the resulting outputs in accordance with the particular revision is achieved by using pure virtual functions, abstract base classes, dynamic binding, inheritance and polymorphism to automatically select the proper tests and test data for the microprocessor. 
     The debug/test application defines an abstract base class for the microprocessors to be tested. This base class defines various member operations and attributes. Classes for the various revisions of the microprocessor are derived from the abstract base class. The derived class for a particular revision defines the tests to be performed and the data to be used in the performance of the tests. Ordinarily, the operations and attributes of a derived class may either be explicit in the definition of the derived class or inherited from the base or intervening classes. In one embodiment, the base class is an abstract class (i.e., the member operations are not defined in the base class,) so the member operations must be defined explicitly in the derived class. In another embodiment, the base class may define certain member operations. The defined operations will serve as a default for any derived class which does not define the member operation and thereby override the base class&#39; definition of the operation. If most of the revisions of a microprocessor are expected to use the same code, this would likely be more efficient than using an abstract base class and defining each member operation for each derived class. 
     When a microprocessor is tested, an object corresponding to the microprocessor revision is instantiated. That is, an object of the type of the corresponding derived class is created. The object has the attributes of the derived class and is subject to the operations of the derived class. Among these operations are the revision-specific versions of the tests to be performed on the microprocessor. When the debug/test application is executed and a particular test is encountered, the test routine is called by reference to the object and, as a result of dynamic binding, the version of the test specific to the instantiated object is executed. For example, assume that each of several classes defines a test (“Test( )”) appropriately for a corresponding revision of a microprocessor. An object (“Object”) is instantiated from class Revision_B. The simple C++ reference “Object.Test( )” will execute Test( ) as defined in derived class Revision_B, from which Object was instantiated. 
     Referring to FIG. 4, a top-level block diagram illustrating the steps for testing a microprocessor in accordance with one embodiment of the invention is shown. The abstract base class is created 100, and one or more operations (tests) which may be provided for use with the microprocessor under test, as well as various attributes which the microprocessor may have, are declared. These may be referred to as the member operations and attributes of the class. The operations of the abstract base class include functions which are not defined by the abstract base class. In other words, they have names and possibly arguments, but they contain no code which defines the functions of the operations. These functions are referred to in the C++ programming language as pure virtual functions. It is left to the classes derived from the abstract base class to define these functions. (It should again be noted that other embodiments may define functions in the base class and then redefine the functions for revisions which deviate from the norm.) 
     After the abstract base class has been created, a derived class is created 110 for each revision of the microprocessor which may be tested. Each derived class inherits the attributes and operations of the abstract base class from which it is derived. Because the derived classes here inherit pure virtual (i.e., undefined) functions, these functions must be defined 120. Likewise, any of the attributes which are not initialized in the base class, or which vary from the initialized values of the base class must be assigned the proper values. The member operations for each derived class define the revision-specific tests which may be performed on microprocessors in that class. 
     An object from one of the classes can then be instantiated 130. That is, an object which contains the attributes and operations of the class can be created. In the debug/test application, the object represents a microprocessor having the characteristics (i.e., attributes and operations) of one of the derived classes (i.e., a microprocessor of a specific revision level.). When the debug/test application executes a particular test by reference to the instantiated object, the revision-specific tests defined by the derived class of the object microprocessor are executed 140. 
     Referring to FIG. 5, a diagram illustrating the hierarchy of base classes, derived classes and objects instantiated from the derived classes in one embodiment is shown. The attributes and operations of a base class are inherited by derived classes. Likewise, these attributes and operations are inherited by objects instantiated from the derived classes. Abstract base class  200  contains attributes  201  and operations  202 . Operations  202  are pure virtual functions, so they are named when the class is created, but they have no actual functionality. When a derived class  210 ,  220  is created, the derived class inherits the attributes and operations of the base class. One or more of the attributes and operations is modified to define a specific subset of the base class. In this case, the modifications include at least the implementation of the inherited functions which, in the base class, were purely virtual. That is to say that the operations must be given some functionality to go with their names. The derived classes are thus defined in accordance with the specific characteristics of the microprocessor revisions which they will be used to test. When an object  230  is instantiated from one of the derived classes, that object will be handled in accordance with the attributes and operations of that class. When the identified operation is called, the particular test functionality defined for the identified operation will be performed on the object. 
     By implementing the abstract base class and revision-specific derived classes, defining the revision-specific tests within the derived classes and instantiating an object from one of the derived classes, the debug/test application programmer is able to simplify and streamline the application code. The programmer simply references the test via the object rather than including a series of branches for each revision, one of which must be selected so that the subsequent instructions will be executed. The possibility of selecting the wrong branch is eliminated and the number of instructions is reduced. Further, when one of the revision-specific tests must be modified, the modification is contained within the definitions of the classes&#39; operations. There is no need to modify the portion of the application which references the operations. If the application must be updated to include a new revision, the user need only add the revision-specific tests in a new derived class and update the application to allow instantiation of objects from the new derived class. 
     In one embodiment, the classes and objects described above are implemented in the C++ programming language. The following is an example of a C++ implementation of the creation of the classes and instantiation of the in accordance with one embodiment of the invention. 
     A base class Revision which describes all of the revisions of the microprocessors to be tested is implemented as follows: 
     
       
         
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 class Revision 
               
               
                   
                 { 
               
               
                   
                 protected: 
               
             
          
           
               
                   
                 int TestData1; 
               
               
                   
                 float TestData2; 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 public: 
               
             
          
           
               
                   
                 virtual void ProcessorTest1 (void) = 0; 
               
               
                   
                 virtual void ProcessorTest2 (void) = 0; 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 } 
               
               
                   
                   
               
             
          
         
       
     
     The attributes of the class are the integer variable TestData 1 , floating point variable TestData 2 , etc. The operations are the virtual functions ProcessorTest 1 , ProcessorTest 2 , etc. In this embodiment, the attributes are protected, which means that they are accessible within the class, but not from outside the class. It is not necessary that the data be protected, but this is done as a means to safeguard the data from unwanted changes. The operations are public and can be accessed from outside the class. The Revision class leaves the implementation of the virtual functions to the classes which will be derived from it. A derived class, Revision_A, is created as follows: 
     
       
         
               
               
             
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 class Revision_A : Revision 
               
               
                   
                 { 
               
               
                   
                 public: 
               
             
          
           
               
                   
                 Revision_A( ) 
               
               
                   
                 virtual void ProcessorTest1(void); 
               
               
                   
                 virtual void ProcessorTest2(void); 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 } 
               
               
                   
                   
               
             
          
         
       
     
     Class Revision_A is thus derived from class Revision (“Revision_A: Revision”) Class Revision_A contains operations Revision_A( ), ProcessorTest 1 ( ), ProcessorTest 2 ( ), etc. Revision_A is the class constructor. It is called when an object is instantiated from class Revision_A. The class constructor may be used to initialize the object when it is instantiated. Although the attributes TestData 1 , TestData 2 , etc. do not appear in the instantiation of the object, they are contained in the object because it is derived from the base class. After the class Revision_A is created, the class constructor must be defined to perform the appropriate initialization. In this example, the constructor is used to initialize the TestData 1  attribute: 
     
       
         
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 Revision_A::Revision_A( ) 
               
               
                   
                 { 
               
             
          
           
               
                   
                 int TestData1 = 0x112; 
               
             
          
           
               
                   
                 } 
               
               
                   
                   
               
             
          
         
       
     
     Although the attributes may be conveniently initialized with the class constructor, it is not necessary to do so. Also, if desired, the constructor of a derived class may initialize an attribute to a value which is different from that used in the base class. In addition to implementing initialization in the constructor, the functionality of the formerly virtual operations must be implemented: 
     
       
         
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 Revision_A::ProcessorTest1(void) 
               
               
                   
                 { 
               
             
          
           
               
                   
                 [first test -- code to be used specifically on microprocessors 
               
               
                   
                 within the Class Revision_A is inserted here] 
               
             
          
           
               
                   
                 } 
               
               
                   
                 Revision_A::ProcessorTest2(void) 
               
               
                   
                 { 
               
             
          
           
               
                   
                 [second test -- code to be used specifically on microprocessors 
               
               
                   
                 within the class Revision_A is inserted here] 
               
             
          
           
               
                   
                 } 
               
               
                   
                   
               
             
          
         
       
     
     When the operations ProcessorTest 1  or ProcessorTest 2  are performed on a microprocessor within the Revision_A class, the test code above (which would be specified in the actual implementation) will be executed. 
     The steps outlined above illustrate the creation of a derived class for a single revision (revision A) of a microprocessor design. These steps are repeated for each of the revisions which may potentially be tested using the debug/test application, but using initializations and test code appropriate to each particular revision. In order to increase the readability and maintainability of the code, this embodiment groups the creation of the derived classes, then the definition of the class constructors, then the definition of the derived class attributes, then the definition of the derived class functions. Alternate groupings may also be selected. 
     The derived classes will all contain certain attributes and/or operations which are referenced in the body of the debug/test application. In the examples above, the class Revision_A contains the attribute TestData 1  and the operation ProcessorTest 1 ( ). A class Revision_B would also contain attributes and operations having these names, although the corresponding values and code might be different. These attributes and operations are referenced by setting a pointer to the derived class corresponding to the revision under test and then referencing the test code or data using the common name and the pointer. For example, if the microprocessor under test is a revision B, the pointer ProcessorUnderTest could be set to point to an object instantiated from class Revision_B. Then, the attributes and operations of the microprocessor under test can be referenced via the name of the pointer and the name of the attribute/operation, neither of which changes in the application code. The attributes and operations appropriate to the revision of the microprocessor under test are automatically selected because the pointer points to an object of the appropriate derived class. 
     When a derived class is set up for each potential revision of the microprocessor (i.e., the attributes and operations of each of the derived classes is defined,) the debug/test application code can use a simple if-then-else or switch statement to set the pointer. The remainder of the code can be written with simple references to the attributes and operations of the derived classes: 
     
       
         
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
               
               
             
           
               
                   
                   
               
             
             
               
                   
                 void main(void) 
               
               
                   
                 { 
               
             
          
           
               
                   
                 int revision; 
               
               
                   
                 revision = GetRevision( ); 
               
               
                   
                 if (revision == A) 
               
             
          
           
               
                   
                 ProcessorUnderTest = new Revision_A; 
               
             
          
           
               
                   
                 else if (revision == B) 
               
             
          
           
               
                   
                 ProcessorUnderTest = new Revision_B; 
               
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 ProcessorUnderTest−&gt;ProcessorTest1( ); 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 ProcessorUnderTest−&gt;ProcessorTest2( ); 
               
             
          
           
               
                   
                 . 
               
               
                   
                 . 
               
               
                   
                 . 
               
             
          
           
               
                   
                 } 
               
               
                   
                   
               
             
          
         
       
     
     If the microprocessor is under revision A, the tests specific to revision A are performed. If the microprocessor is under revision B, the tests specific to revision B are performed. The debug/test application thereby adapts itself to perform each test using code which is appropriate for the microprocessor under test. If it is necessary to modify the code of the debug/test application to incorporate additional revisions, the programmer need only create a new class as described above and modify the if-then-else or switch statement which sets the pointer to the proper revision object. There is no need to modify every occurrence of each value and each function in the application which varies from revision to revision. Likewise, if it is necessary to modify any of the test code, the modifications are made only where the corresponding function is defined. 
     The debug/test application is configured to allow replacement of the microprocessor with another microprocessor, to determine the revision of the new microprocessor and to instantiate a new object from the derived class corresponding to the new microprocessor&#39;s revision. If the revision of the new microprocessor is different from that of the first microprocessor, the identical reference (e.g., ProcessorUnderTest-&gt;ProcessorTest 1 ( )) will result in the execution of ProcessorTest 1 ( ) as defined in the derived class corresponding to the second revision. 
     While the present invention has been described with reference to particular embodiments, it will be understood that the embodiments described above are illustrative and that the scope of the invention is not limited to these embodiments. Many variations, modifications, additions and improvements to the described embodiments are possible. These variations, modifications, additions and improvements are intended to be within the scope of the invention as detailed within the following claims.