manila“. V . nun.“ . . $1 2.3:! .3 ‘ 1;, ; éww. .17. . Inc. ll Elkuafihrv. 1a.... .3. 2m“... 1 ‘ .5. . «3%.: C" an}! 1 . 3.. .\ a. . V 3.... an.“ i .. u... 5: 5:: giant»... 3 . , . 4‘3... a... fin . mar»? .muu. manic-9rf... .25. x. 323.»... 4...... .2 rmmisiw. x.‘ ‘5. «Ni Rmmmymfii Fun. .1 7 2 $1 . n (til I I; if: (E i. .- {tit ‘31 (3?. #315?!” 534. Lauri . 1t 1...? .3 v 11111111111111111111111111'111 3 1293 016880 This is to certify that the thesis entitled Fmrt EMQ LWCL {m PMALIIL VHDL Swab/flow presented by Mai VA»? has been accepted towards fulfillment of the requirements for M . é. degreein CmEJGw fiance, 5 EW'k/c Majonéwlsso Q/L—jr% Date 7/3 04?? 0-7639 MS U is an Affirmative Action/Equal Opportunity Institution LIBRARY M'chlaan State University PLACE IN RETURN BOX to remove this checkout from your record. To AVOID FINE-S return on or before date due. DATE DUE DATE DUE DATE DUE 1193 MM“ FRONT END INTERFACE FOR PARALLEL VHDL SIMULATIONS By M (12' Yang A THESIS Submitted to Michigan State University in partial fulfillment of the requirements for the degree of MASTER OF SCIENCE Computer Science Department 1998 ABSTRACT FRONT END INTERFACE FOR PARALLEL VHDL SIMULATIONS By Mai Yang The Parallel VHDL Simulation Project conducted by the Computer Science De- partment of Michigan State University attempts to implement an efficient paradigm for VHDL simulations on massively parallel machines. The Front End Interface of the project is in charge of the translation from VHDL descriptions into C++ code which is used to run parallel simulations. This document describes how the SAVANT software package is utilized and modified to implement the Front End Interface. ACKNOWLEDGMENTS I want to express my gratitude towards my advisor, Professor Moon J. Chung, for his support and direction throughout my involvement in this project. I am deeply impressed by his tenacity and perseverance towards his goals. I thank him for his encouragement and advice which helped me overcome lots of difficulties. Without his support, this thesis would not have been completed. I am also grateful to Pro- fessor Matt W. Mutka and Professor Anthony S. Wojcik for serving in my guidance committee and providing comments on my thesis. I owe special thanks to my partner Khashayar Rohanimanesh and Jinsheng Xu. I benefited a lot from our discussions and the helpful suggestions they gave me. It was a wonderful learning experience for me to have teamed up with these two nice fellows in this research project. iii TABLE OF CONTENTS LIST OF FIGURES vi LIST OF TABLES VII 1 Introduction 1 1.1 VHDL ..................................... 1 1.2 Parallel VHDL Simulation .................. 4 ........ 2 1.3 MSU Parallel VHDL Simulation Project .................. 3 1.3.1 Goal ..................................... 3 1.3.2 Extensibility ................................ 3 1.3.3 Major Tasks ................................. 4 1.3.4 Major Modules ............................... 5 1.4 Front End Interface .............................. 6 1.4.1 Function Description ............................ 6 1.4.2 Approach .................................. 7 1.4.3 Selected VHDL construct subset ..................... 8 2 SAVANT 10 2.1 Overview ................................... 10 2.1.1 Components of SAVANT .......................... 11 2.1.2 How to Use SAVANT ........................... 12 2.2 The AIRE Standard ............................. 14 2.2.1 Purpose ................................... 14 2.2.2 Approach .................................. 15 2.2.3 Class Hierarchy ............................... 15 2.2.4 Extensibility ................................ 17 2.3 The SAVANT Implementation of AIRE ................... 19 2.3.1 Class Derivation .............................. 19 2.3.2 Extensibility in SAVANT ......................... 20 2.4 How to Modify the SAVANT Publisher ................... 22 3 Translate VHDL Constructs into C++ 24 3.1 The Object Model .............................. 24 3.2 Implementation Details ............................ 31 3.2.1 How to Publish ............................... 31 3.2.2 Where to Publish .............................. 32 3.2.3 How to Insert an IIRthdl Class ..................... 33 3.2.4 The IIRthdlDesignFile Class ...................... 34 iv 3.2.5 3.2.6 3.2.7 3.2.8 3.2.9 3.2.10 3.2.11 3.2.12 3.2.13 3.2.14 3.2.15 3.2.16 3.2.17 3.2.18 3.2.19 The IIRthdlEntityDeclaration Class .................. The IIRthdl_ArchitectureDeclaration Class ............... The Process Statement ........................... Signal Assignment Statement ....................... Variable Assignment Statement ...................... Expressions ................................. The If Statement .............................. The Case Statement ............................ The For LOOp Statement .......................... The While Loop .............................. The Wait Statement ............................ Constant Declaration ............................ Enumeration Types ............................ Array Types ................................ Record Types ................................ 4 Conclusions 4.1 Summary ................................... 4.2 Future Work ................................. APPENDICES A IIRthdl Layer Class List B VHDL Source of an AND Gate C C++ Code of the AND Gate D SavantGlobals.h E IIRthdl.WaitStatement.hh F IIRthdl_WaitStatement.cc G thdlArray.h 35 36 37 52 55 56 59 61 65 86 86 88 89 92 93 94 97 LIST OF FIGURES 1.1 Structure of the Parallel Simulator ..................... 6 2.1 Components of SAVANT Project ...................... 13 2.2 Structure of HR and Applications ...................... 16 2.3 Example of the HR Derivation Hierarchy .................. 17 2.4 The SAVANT Derivation of AIRE ...................... 19 2.5 Implementation of IIR.Declaration ..................... 20 2.6 Insert IIRSavantGeekDeclaration Class into the Hierarchy ........ 21 2.7 The New thdl Layer ............................ 22 3.1 An Example C++ Class of the Object Model ............... 26 3.2 Naming Scheme of VHDL Singals ...................... 28 3.3 VHDL Source Code .............................. 53 3.4 Published C++ Code ............................. 53 3.5 Default Publishing Format of Signal Assignment .............. 53 3.6 Example on How to Publish Expressions .................. 58 3.7 The .publish_cc-0perator.name() Method of IIRthdLAndOperator . 58 3.8 Syntax of Wait Statement .......................... 68 3.9 Example of Wait For Timeout Clause .................... 72 3.10 Constant Declaration Syntax ........................ 74 3.11 Code of Constant Declaration ........................ 75 3.12 Overloading Assignment Operator for One Dimensional Array Class . . . 80 vi 3.1 3.2 3.3 3.4 LIST OF TABLES Basic VHDL Data Types and Their C++ Implementations ........ 27 Functions for Signal / Variable Registration ................. 29 System Defined Initial Values ........................ 29 Predefined Public Data Elements of IIREntityDeclaration ........ 36 vii Chapter 1 Introduction 1.1 VHDL VHDL stands for VHSIC (Very High Speed Integrated Circuits) Hardware Descrip— tion Language. It is an IEEE standard language used to describe the structure and behavior of digital electronic systems. It allows the designer to describe how the electronic system is decomposed into subsystems and how the subsystems are inter- connected. It uses programming language forms to specify the functions of a system. VHDL makes it much easier to describe very large circuits and systems [1]. A big advantage of VHDL is that it allows testing and verification of designs using simulations. The designer can simulate the behavior of a system using test inputs then compare the resulting outputs to the requirement model of the system. The mismatch in the comparison usually indicates design problems, thus enabling the designer to reexamine the design and correct the errors. 1 2 1.2 Parallel VHDL Simulation Many digital electronic systems used in current and future industrial and military systems are too large to be effectively simulated on even state-of-the-art workstations. Currently, performance simulation is extremely slow and is a major bottleneck for the development of micro-electronic systems. Research conducted at Lockheed Martin under DOD sponsorship has shown that simulation of only a portion of a digital signal processing system can take over 20 hours [4]. As should be expected, actually building systems or prototypes is prohibitively expensive. The power of parallel machines, along with appropriate software development, is therefore essential to the maintenance and upgrade of existing systems and the development of future systems. As a result, parallel simulation has attracted a considerable amount of inter- est. However, most research on parallel simulation is restricted to symmetric multi- processor machines or MIMD machines with a small number of processors. There are few benchmark results available based on actual simulations of large circuits. The few existing empirical results are based on MIMD machines with only a small number of processors, typically tens of processors. Thus, the speed-ups attained compared to sequential simulation are severely limited. To simulate a system with up to millions of processes, the computational power of massively parallel processors (MPP) with several hundred processors is necessary [4]. 3 1.3 MSU Parallel VHDL Simulation Project 1.3.1 Goal The goal of the Parallel VHDL Simulation Project at Michigan State University is to develop and implement a new and efficient paradigm for VHDL simulations on massively parallel machines (MPP) and enable simulation speed-ups of up to two orders of magnitude. The simulator will use MPI, a standard parallel communication protocol. The developed parallel program will be scalable and portable. From a user’s point of view, the output of this development effort will be a fast parallel program that will be able to simulate a large digital system with up—to 100,000 VHDL processes at the performance level. By using this simulator, designers may be able to prove the functional correctness of digital system, assess the performance of candidate architectures of a digital system, and select the best architecture that meets requirements. The design cycle thus can be shortened, and the number of real prototypes to be constructed can be reduced. In this project, a subset of VHDL constructs is selected to describe the perfor- mance and behavioral models. These selected VHDL constructs are powerful enough to describe the behavior and function of any hardware systems, yet simple enough so that models written using these constructs can be efficiently simulated in parallel. 1.3.2 Extensibility Another goal of this simulation project is to ensure the portability and extensibility of the simulations. The simulation kernel is completely separated from the simulation 4 Object model. The simulation kernel only contains simulation protocol objects, such as TimeWarp, SynchObj, and Chandyh‘lisraObj, etc. It does not know what object model is used to simulate the target system. On the other hand, the simulation object model does not know the simulation protocols at all. It only defines how target system objects should be translated into simulation objects. Thus once the target system has been translated into simulation objects using the object model, the resulting C++ code man be run on any parallel platforms. The end user only needs to select the parallel simulation protocol (TimeWarp, SynchOb j, etc.) and set up the initialization parameters. The simulation kernel will then talk to the selected simulation protocol and run the simulation. 1.3.3 Major Tasks The following is a list of major tasks to implement the parallel VHDL simulator: 0 Design and implement the Simulation Object Model. Simulation objects will inherit properties (such as member functions) from these objects. Select a subset of VHDL constructs that are critical to describe the performance and behavioral models. Develop the Front End Interface which generates C++ programs from VHDL descriptions using the object model. Design and develop the general structure of Cockpit, the main module of parallel Simulator. 0 Develop algorithms and data structures of event queue handling for parallel simulation. 0 Implement the Baseline programs to measure the efficiency of parallel programs. Implement and perform benchmark on SP2. 1.3.4 Major Modules The parallel VHDL simulator software suite is broken into five modules: 0 Front End Interface, which generates C++ classes and object interconnection information from VHDL descriptions. o Partitioner, which distributes C++ objects into processing elements of a par- allel computer. 0 Cockpit, which is the main program module of the parallel simulator. It reads input (test) vectors, initializes modules, starts simulation, orchestrates other modules, and detects the termination. 0 Event Scheduler, which manages events and schedules them according to parallel simulation protocols. For event handling and scheduling, it adopts a Time-Warp mechanism. 0 Communication Module, which sends and receive messages from other pro- CBSSOI'S . VHDL C++ Model Model C++ Model *——> // Code Generator 11 Parser GD 1 // Code Partitioner T C) Scheduler . ll V Savant IF Event Handler Cookpit V C-H- rocess . C++ Models ~ @ Tablels Commumcator Figure 1.1: Structure of the Parallel Simulator The Cockpit, Event Scheduler and Communication Module form the Simulation Kernel of the simulator. The structure of the simulator is Shown by Figure 1.1 on page 6. 1.4 Front End Interface The Front End Interface is the target of this thesis. The work I have done is only related to this part of this research project. To know more about other modules of the parallel simulator, please refer to [10] for details. 1.4.1 Function Description The simulation kernel of this project is designed to run general parallel simulations. It is not designed only for VHDL simulations. The kernel is implemented in C++. 7 To simulate any real world system, a C++ description of the target system must be provided. This description must include domain objects and their interconnection information. The function of the Front End Interface is to provide such C++ de- scriptions for the system to be simulated. The Front End Interface has to use the pre—defined object model to generate the C++ code. The object model is disCussed in details in Chapter 3. When simulating VHDL systems, the Front End Interface will generate C++ code from VHDL source code. It will generate C++ classes corresponding to VHDL objects and their interconnection information. This is basically a translation from one language to another. I am in charge of the C++ code generation part of the Front End Interface. Another research assistant of this project, Mr. Khashayar Rohanimanesh, implements the function of generating the interconnection information. Please refer to his research document [9] for details on this issue. 1.4.2 Approach To translate VHDL into C++, the Front End Interface has to face the following problems: 0 VHDL is a very complicated language. It is very hard to translate all its con- structs and features into C++. 0 There is no direct mapping between the two languages. Some intermediate form must be used to before the translation is performed. 8 0 AS a hardware description language, VHDL has some unique features, such as the “wait” statement. To keep the correct semantics of these features, the object model must implement mechanisms to support them. The Parse Tree approach is a common method used to solve the translation prob- lem. Generally, a parser is used to parse the source language and generate a parse tree. Translation is then performed by traversing the parse tree and taking publishing actions at each tree node. The parse tree can be constructed using either the source or the target language constructs, or some intermediate forms. This approach is also used in this project. The SAVANT software package is used as the basis to implement the Front End Interface. SAVANT has developed a VHDL parser (SCRAM) and a set of intermediate forms (the AIRE specs), which is used to generate the parse tree. Chapter 2 describes the SAVANT software package in detail. 1.4.3 Selected VHDL construct subset The following VHDL constructs have been selected as goals for the translation: 0 Delay Mechanism : transport delay and inertial delay. 0 Data Types: bit, integer, real, array types, record types, enumeration types, constants. C Sequential Statements : signal assignment statement, variable assignment state- ment, multiple waveforms in one Signal assignment, if-then-else, for loop, while loop, case statement, wait statement, logic / arithmetic Operations. 9 o Concurrent Statements : process statement with sensitivity list, concurrent sig— nal assignment statement, component instantiation statement, generate state- ment, conditional signal assignments. These selected VHDL constructs are powerful enough to describe the behavior and function of very complicated hardware systems, yet they are simple enough so that model written using these constructs may be efficiently simulated in parallel. The task of the Front End Interface is implement these VHDL constructs. Chapter 2 SAVANT 2. 1 Overview SAVANT stands for Standard Analyzer of VHDL Applications for Next-generation Technology. It is a joint effort between the University of Cincinnati and MTL Sys- tems, Inc. to build an extensible, object-oriented intermediate form (IIR) for the hardware description language VHDL. The project is sponsored by the USAF Wright Laboratory and will produce a suite of software to analyze VHDL, build the IIR, and to output C++ code suitable for execution with the T yVIS VHDL simulation kernel developed by the University of Cincinnati. The primary goal of SAVANT is to stimulate research among the VHDL commu- nity by providing an extensible, object-oriented, well-documented Intermediate Form (IIR) and a freely available analyzer to convert VHDL into the IIR. Because the IIR analyzer is released in source form, the additional derived classes can be inserted into the C++ class hierarchy. Thus, user actions can benefit fully from the fact that the 10 11 IIR is object-oriented. Consequently, no procedural interface is provided or needed [5]- 2.1.1 Components of SAVANT The SAVANT software suite contains the following components: 0 Scram: A VHDL Analyzer The SCRAM analyzer inputs a VHDL description, check it for syntactic and static semantic correctness, and stores it in the intermediate form (IIR). The SCRAM parser is constructed as an LL(2) grammar and uses the Purdue Com- piler Construction Tool Set (PCCTS) parser generator. SCRAM is written in C++ using g++ 2.7.2 for development. The Intermediate Form The intermediate forms are jointly developed with John Willis of F TL Systems, Inc. The intermediate form standard is called AIRE and includes definitions of two intermediates, a memory resident data structure called IIR and a machine- independent file data structure called FIR. 'I‘ransmute: Derived Classes that Implement Static Equivalence The transmute method is a collection of derived classes that support rewriting of the IIR into a reduced form. 0 Archiver: Derived Classes for Library Management The collection of archiver classes support library management. Within the 12 derived classes two methods are defined, namely: record() and playback(). record() writes the IIR to an FIR file and p1ayback() reads an FIR file into the IIR. 0 Publisher: Derived Classes for Output Generation Output generation in the SAVANT software suite is supported by the col- lection of publisher classes. Two overloaded methods, _publish_vhdl() and .publish_cc(), are defined for all nodes of the reduced IIR. The _publish..vhdl() method simply regenerates VHDL from the internal IIR. The -publish._cc() method produces C++ simulation code to link with the TyVIS VHDL sim- ulation kernel. The relationship between the components of SAVANT is described by figure 2.1 on page 13. For more details about these individual components, please refer to [5]. 2.1.2 How to Use SAVANT SAVANT has implemented the VHDL Analyzer and the Intermediate Form, which are needed by our parallel VHDL simulation project. On the other hand, SAVANT has also implemented a C++ Publisher, which makes use of the Analyzer to produce C++ code for the TyVIS VHDL simulation kernel [6]. TyVIS is a completely dif- ferent Simulation kernel from our simulation kernel, thus the C++ code generated by SAVANT can not be used by our simulation kernel at all. But we can modify the SAVANT publisher to generate code for our own kernel. By avoiding rewriting a separate C++ publisher, we can reuse lots of SAVANT code and save lots of time. 13 VHDL source Interactive Simulation Environment For Fee Enwkanmen! ANALYZER SAVANT Your CAD-in-VHDL Tools 1 ARCHIVER IF Files Intermediate Form (IF) Batch Simulation I Environment Figure 2.1: Components of SAVANT Project 14 The function of the Front End Interface can now be described as to modify the SAVANT Publisher to generate C++ code for our own parallel Simulation kernel. To modify the SAVANT Publisher, it is crucial to understand the structure of the AIRE standard and its implementation in the SAVANT project. 2.2 The AIRE Standard The AIRE Standard was initiated by the Wright Labs, FTL Systems, and the Univer- sity of Cincinnati. It is a Specification for a freely available, highly portable, extensible VHDL intermediate form. Its specification is defined by [7]. 2.2.1 Purpose The Advanced Intermediate Representation with Extensibility (AIRE) specifications address the HDL user’s need for efficient mechanisms for sharing of design informa- tion between tool components. The AIRE specification includes coordinated Internal Intermediate Representation (IIR) and File Intermediate Representation (FIR) spec- ifications. The AIRE representation is useful following source code analysis, integration of separately analyzed units, elaboration, in-line expansion, machine-independent Opti- mization, back-end code generation / synthesis and execution (simulation). Integration of component tools from different development groups should finally be realizable with modest effort using this intermediate representation. As a result both the research and design community benefit from stronger and more useful tools. 15 AIRE’S purpose is to meet the evolving needs of advanced VHDL tool develop- ers. Therefore, the specification is still evolving. Some changes to the core speci- fication are still being made as a result of experience with early implementations. Implementation-specific extensions are being added to the core specification. 2.2.2 Approach AIRE uses a collection of object (record or structure) instances linked by pointers to represent design information. These objects represent analyzed, elaborated, and exe- cutable instances of specific design information. In very general terms, the collection of objects represents a very generalized abstract syntax tree (AST), while methods associated with the classes (and thus objects) represent an integrated application programming interface (API). 2.2.3 Class Hierarchy The IIR class hierarchy is shown abstractly in Figure 2.2 on page 16. A base class, called IIR, is located at the top of the class hierarchy. Derived classes, descended from the base IIR class, are instantiated in order to form a specific design representation. There are total 227 classes defined by the standard. All the classes are single rooted at class IIR. Figure 2.3 on page 17 is an example of the IIR class derivations. An IIR—derived class may be instantiated by other IIR classes (such as declaration lists within a block declaration), by friends of an implementation-specific foundation (such as a source code analyzer intrinsic to the foundation), or by external application 16 Foundation IIR // Extensions - I l l Predefined Derived Class Layer 2 Application 1 Extensions L | Predefined Derived Class Layer 3 l l Extensions Predefined Derived Class Layer 4 Extensions Predefined Derived Class Layer 5 V V V V Applications (6. g. optimizer) Application (e.g.code generator) Figure 2.2: Structure of IIR and Applications 17 o IIR — IIR_DesignFile — IIR..Comment — IIRSequentialStatement :1: IIRAssertionStatement >1: IIRBreakStatement ll: — IIR_ConcurrentStatement Figure 2.3: Example of the IIR DerivationHierarchy code (such as the optimizer and code generator shown in Figure 2.2 ). The public methods and public data elements are sufficient to construct, get and set all language functionality defined by the associated system design language. 2.2.4 Extensibility Extension classes, shown in darker shading in Figure 2.2, may be interposed within the IIR inheritance hierarchy in order to add application-specific methods or (in instantiable classes) additional, application-specific data elements. Each extension layer begins derivation with a class named by pre—pending IIRBase_. The extension layer(s), if present, result in a final, predefined layer named by pre-pending IIR- to the class name. The predefined properties of this layer are explicitly specified in this document; the predefined properties of the base layer for each class may be readily (even automatically) derived. The names of any intervening extension classes Should assume the form IIREztensz'onDesz‘gnator.Specz'ficClassName. For example, 18 a synthesis application might interpose an extension class IIRSyn-ProcessStatement between IIRBase_ProcessStatement and IIRProcessStatement. Since a complete tool may be composed of more than one application, the darker Shaded extension layers actual represent zero or more layers within the class hierar- chy. For example, an elaborator application may add some extensions to the block and process declarations while a code generator adds its own extensions. In order to clearly delineate identifiers other than those predefined constructors, destructors or operators, such identifiers are prefaced by a leading underscore (_). Name con- flicts are inevitable when linking two applications which both use the same extension designator, such as “Syn” in the example above. All IIR class constructors don’t have arguments, but there are no constraints on the destructors. Some intermediate classes in the IIR derivation hierarchy are not directly instantiable, such as the IIRSequentialStatement class. These interior classes serve purely as parent classes for classes that process common characteristics. They are indirectly instantiated by the instantiation of their children classes. Whereas the specification is generally based on the C++ language and single- inheritance C++ classes, implementations using C, Ada or Pascal are very feasible. However since AIRE takes advantage of modern, object-oriented programming tech- niques which may not be present in older programming languages, AIRE can be a somewhat less convenient when other languages are used. 19 \ / IlRBase_ConcurrentSlatement ["3339 Pro 1 l — l l IIRScram IIRScram_ConcurrentStatement IIRScram_Pr Figure 2.4: The SAVANT Derivation of AIRE 2.3 The SAVANT Implementation of AIRE 2.3.1 Class Derivation The actual class derivation of AIRE in SAVANT is illustrated by Figure 2.4 on page 19. There are basically three layers in the derivation hierarchy: IIR layer, IIRBase layer, and the IIRScram layer. The IIRBase layer classes contain public interface (data and methods) defined in the AIRE specification. It also contains protected or private data and methods that support the public interface. The IIRScram layer classes implement the VHDL Analyzer (named “scram”) and the C++ publisher. It resides below the IIRBase layer and above the IIR layer. The IIRScram layer classes inherit the public data and methods defined by the IIRBase layer classes. The classes in this layer contain type checking routines and symbol table management functions for scram. They also contain methods, such as _publish_cc () 20 llRBase_Declaration set_declaratior(IIR_TextLiteral *) ll IIRScram_Declaration IIR_PortList *get_port_map() void _publish_vhdl() 11 IIR_Declaration Figure 2.5: Implementation of IIR.Declaration and -transmuteO, to implement the analyzer and the publisher, The [IR layer classes contain empty constructor and destructor. There is no other private, public and protected data or functions declared. The IIR layer is the bottom layer. The IIR layer classes inherit all the public data and methods declared by the classes in the other 2 layers. All AIRE classes occur as 3 SAVAN T Classes Definitions. Figure 2.5 on page 20 shows an example of this structure. 2.3.2 Extensibility in SAVANT There are several reasons why SAVAN T uses this structure. The most important one is to enable the extensibility without modifying code in the scram parser. Applica- tion specific functionality can be added by introducing extra layer(s) into the class hierarchy, thus avoiding changing code of the IIRScram layer completely. The scram “parser” instantiates concrete classes in IIR. Essentially, the user- 21 IIRBase_Declaration set_declaratior(IIR_TextLiteral *) V ' IIRScram_Declaration IIR_PortList *get_port_map() void _publish_vhdl() / IIRSavantGeek_Declaration void * _my_method_goes_here() \ IIR_Declaration Figure 2.6: Insert IIRSavantGeekDeclaration Class into the Hierarchy defined class must be derived from the layer just “above” the IIR layer (the IIRScram layer). In addition, the derivation of the IIR level must be modified in such a way that it inherits directly from the user defined class. Figure 2.6 on page 21 shows an example of how to insert a user defined class into this hierarchy. By inserting the IIRSavantGeekDeclaration class, the user now can define application-oriented functions of the IIR_Declaration class. If the user wants to shadow a function defined by the IIRScram layer, he can simply put a new definition of that function in the new class. For example, if the user defines the .publish-cc() function in IIRSavantGeek-Declaration, the same function in IIRScramDeclaration will be shadowed. IIRBase_ProcessStatement 11 IlRScram_ProcessStatement _publish_cc() \ IIRthdLProcessStatement void _publish_cc() / IIR_ProcessStatement Figure 2.7: The New thdl Layer 2.4 How to Modify the SAVANT Publisher The SAVANT Publisher is implemented in the IIRScram layer. The IIRScram class is the root class of the IIRScram layer. The way SAVANT implements the Publisher is by defining a virtual function .publish_cc() in the IIRScram class. Since all other IIRScram layer classes are child classes of the IIRScram class, they inherit the _publish_cc() function. This function is then overloaded by each IIRScram layer class to publish C++ code according to different semantics. After the scram parser generates the IIR parse tree, the C++ code is published by calling the _publish-cc() method from the root of the tree. The root will then call the .publish-cc () method of higher level nodes in the tree. This process is continued recursively until all the tree nodes have called the _publish_cc() function. The reason SAVANT implements the publisher as a virtual function is to ensure 23 polymorphism at. run time. \Vhen a virtual function is invoked via a pointer, the actual function to be executed is determined by the type of the object that is stored at the memory location being accessed, not by the type of the pointer. The deter- mination of which virtual function to use is thus made during run time [3, Chapter 15.6]. AS a result, when an IIR layer object needs to call the -publish_cc() function of another IIR layer object, it can simply use the base IIR pointer to reference that object. The correct .publish_cc() function will be determined at run time. This process greatly simplifies the programming. To modify the SAVANT Publisher, a new IIRthdl layer is introduced into the SAVANT hierarchy between the IIRScram layer and the IIR layer. The IIRthdl layer classes overload the .publish-cc () method to produce C++ code for the MSU parallel Simulation kernel. Since the IIRthdl layer sits between the IIRScram layer and the IIR layer, the .publish_cc () function in the IIRScram layer is showed. When the nodes in the IIR parse tree call the _publish_cc() function, the function defined in the IIRthdl is executed. This approach is illustrated in Figure 2.7. Chapter 3 Translate VHDL Constructs into C++ 3.1 The Object Model The Front End Interface needs to generate C++ according to the Simulation Object Model. This section describes the details about the Object Model. The object model defines a “BasicObject” class which characterizes the common features of all simulation objects. When translating a target system into simulation classes, the BasicObject class should be used as the parent class of all resulting simulation classes. The BasicObject class defines input signals, output signals, states, and a method called executeProcessO. Through the input and output signals, BasicObject classes can interact with each other. States are used by BasicObject to keep private information. The executeProcessO method describes the behavior of the object (how the output signals should be changed according to the input signals). 24 25 The input signal, output signal and state are [also classes defined by the Object model. All Signals and states must be “registered” before then can be used. Please refer to [10] for details about the BasicObject class, the Signal classes, and the state class. When translating a VHDL system into C++ code, each VHDL process is trans- lated into a simulation class. The “in” signals in the VHDL process are translated into the input signals in the Simulation class. The “out” signals are translated into output Signals. The process variables are translated into states. The sequential state- ments of the VHDL process are translated line by line into the executeProcessO method. Generally, each C++ class has the following items: 0 Declaration of input / output signals and states. 0 Registration of input / output signals and states. 0 Initialization of input / output signals and states. 0 The executeProcessO method. Format of Object Class Each simulation object class contains a data declaration section, a constructor, and a executeProcessO method. All data members and methods are defined as public (so that the simulation kernel can access them directly). In the constructor, signals and states are registered and initialized. Figure 3.1 on page 26 shows an example C++ class generated using the object model. This example only shows a template of the object model class. It is not the exact code generated by the Front End Interface. Appendix B shows the VHDL 26 class DFF : public BasicObject { public: InSignal D, CLK; // declarations OutSignal Q; State prev; DFF(): BasicObject() { // registrations registerInSignal (&D); registerInSignal (&CLK); registerOutSignal (&Q); registerState (&prev); D=X; CLK=X; prev=X; // initializations Q=Y; } void executeProcess () { // actions int val; if (hasEvent(&D) && (CLK == ’1’)) { val = D; if (prev != val) { prev = val; if (pre == ’0’) D = 0; else if (preve == ’1’) D =1; else D = val; } } } }; Figure 3.1: An Example C++ Class of the Object Model source code of an AND gate. The exact C++ code for this AND gate is shown in Appendix C. Basic Data Types VHDL has 3 basic data types: bit, real, integer. Table 3.1 on page 27 show their corresponding C++ implementation. Other complicated data types, such as array 27 [ VHDL Type C++ Type [Implementation ] bit SavantbitType typedef int SavantbitType real SavantrealType typedef double SavantrealType integer SavantintegerType typedef int SavantintegerType Table 3.1: Basic VHDL Data Types and Their C++ Implementations and record, are all derived from these basic types. Declaration of Signals and Variables In VHDL, signals are declared either in entity declaration or architecture declaration. In this project, the unit of publishing is neither entity nor architecture, but VHDL process. Each VHDL process is translated into a C++ class. It is possible that a VHDL process could use only several of all the signals declared by the architecture body embracing it. It is also possible that one architecture body contains several processes and they Share some signals together. The rule here is that each VHDL process class declares only those Signals it uses. As a result, it is possible one signal is declared in different process classes. As how these signals are resolved, please refer to [9]. For each VHDL process, there are only two kinds of signals: in signals and out 3 signals. When declaring these signals, prefix “in_’ is added to each in signal, and prefix “out-” is added to each out signal. If a signal is an “in.out” signal, two separate signals are declared. For example, a signal assignment statement may look like this: a <= not a after 3 ns. Signal a is on both sides of this signal assignment statement and is an “in..out” signal. As a result, there will be two signals declared for signal a, namely in-a and out-a. When generating the interconnection information, these two 28 Out_B — B = A ~—- In_A Simulation Kernel In_B l C = B Out_C Figure 3.2: Naming Scheme of VHDL Singals signals are connected directly [9]. The naming scheme of VHDL Signals is shown in Figure 3.2 on page 28. VHDL variables are declared within processes (global variable has not been im- plemented yet) and are translated into “states”. In contrast to signals, states are declared without a prefix. For example, if a VHDL process declares a variable as: variable a : bit, its C++ declaration is Savantbit'l‘ype a. Signals and variables can have initial values. It is in the constructor that their initial values are granted. Later sections will address the issue on how to find which signals and variables are used by a process and how to retrieve their initial values. The Constructor The class constructor will register signals and variables and set their initial values. To register signals and states, the constructor will call functions declared in the BasicObject class. Table 3.2 shows these functions. No special function needs to be called to initialize signals and states. The simple C++ assignment operator is used. For example, if the initial value of signal a is 0, 29 input signal registerInSignal (&signa1 , sizeof (signal) ) output signal registerDutSignal (81$ ignal , sizeof (signal) ) state registerState (Ecstate , sizeof (state)) Table 3.2: Functions for Signal/ Variable Registration [ signal/state initial value definition input signal X #define X -1 output signal Y #define Y -1 state X as above Table 3.3: System Defined Initial Values a is initialized by a = 0. If the signal or state doesn’t have an initial value, system defined initial values are used. Table 3.3 shows the predefined initial values. These initial values are defined in file SavantGloba1.h shown in Appendix D. The executeProcessO Method The executeProcess () method of the object class describes the actions of the VHDL process. It is a line to line translation of VHDL statements to C++ code . VHDL process is composed of VHDL sequential statements, such as signal as- signment statement, variable assignment statement, if statement, etc. These VHDL language constructs all have corresponding IIR representations. The way to trans- late these VHDL language constructs into C++ code is to call the .publish-cc() function in their corresponding IIR nodes in the IIR parse tree. Since each IIR class has its own .publish-cc(), different semantics of different VHDL constructs can be translated by implementing the _publish_cc() method differently. Later sections will describe this approach in detail. The executeProcessO method is defined in the BasicObject class. The simula- 30 tion kernel simulates the VHDL description by calling the executeProcess () method of each VHDL simulation object. Modification Guidelines In the SAVANT project, the IIRBase layer and the IIR layer are well defined by the AIRE standard. They are well documented by the AIRE standard [7]. The IIRScram layer implemented the VHDL Analyzer and the Publisher. This layer contains most of the programming tasks. However, this layer is very poorly documented. Actually their is no documentation at all which describe the programming details of the IIRScram layer. The C++ code is generated by traversing the IIR parse tree. The information collected by the Analyzer has to be used to perform the publication. Since the IIRScram layer has no documentation, the only way to find out all this information is to use a debugger to trace through the program. In this project, the GNU gdb is used to debug the SAVANT executable file, Scram. The basic debugging process is to first set a break point at the _publish_cc () method of the IIRScram class being modified , then trace into all pertinent sub-routines and relevant data members. There are 227 IIR classes defined and the size of the Scram file is about 35MB. Thus the process of using a debugger to debug the file to find out some information can be extremely time consuming and painful. The following are the general steps taken to modify the SAVANT publisher: 0 Look at the AIRE standard to find out what public data member and public functions are declared by the target IIRBase class. These data and functions 31 are will be used in generating the C++ code. 0 Debug the _publish_cc () function of the target IIRScram class to see how this information is used. 0 Create a new IIRthdl layer class which implements a new _publish_cc() method to shadow its corresponding IIRScram layer class. 3.2 Implementation Details This section discusses the details of how the IIRthdl layer classes are generated. As mentioned earlier, this project tries to handle only those VHDL constructs that are deemed as essential to VHDL simulation. It does not try to handle all VHDL language constructs. This section will use the VHDL construct as the unit of discussion. 3.2.1 How to Publish SAVANT defined a utility class called “switch_file”. This class deals with in- put/output streams. It defines a method void setiile(char *name, char *ext), which is used to set the name of the output file for the Publisher. If a file with the name “nameext” already exists, future outputs of the Publisher will be appended to the end of this file. Otherwise, a new file with that name is created and future outputs of the Publisher will be written to the new file. In IIRScramhh, two global variables are declared as follows: extern switch_file _vhdl_out; //file for vhdl output 32 extern switch_fi1e _cc_out; //file for C++ output The IIRScram class is the root of the IIRScram layer classes. Thus the above two global variables could be accessed by any IIRScram class. The _vhdl-out is only used to publish VHDL source code, while the _cc_out is only used to publish C++ code. For example, to publish code “ i += 1;” to file “test.cc”, you only need to do the following: _cc_out.set_fi1e("test”, “.cc”); -CC_0ut << “ i +2 1;)); Any IIRthdl layer class is derived directly from a IIRScram layer class. As a result, all IIRthdl layer classes can also access -cc_out and publish C++ code to a named file. 3.2.2 Where to Publish In SAVANT, each class corresponding to a VHDL process will generate two files, a “.hh” file and a “.cc” file. When all the C++ files have been generated, a “Makefile” is created to tell the TyVIS simulation kernel how to link all the files together. In this project, all C++ code is published in the file “Classes.h”. The constructor and the executeProcess () method are all inline functions. Thus there is no need to create a Makefile. The simulation kernel can simply include the “Classesh” file to get all class definitions. 33 3.2.3 How to Insert an IIRthdl Class The sole purpose of adding an IIRthdl layer is to shadow the _publish_cc() functions of the IIRScram layer classes. To do this, an IIRthdl layer class has to be derived directly from the IIRScram layer class. The IIR layer class will then be derived from the IIRthdl layer class instead. Thus when an IIR layer node calls the _publish_cc() function,lit will call the _publish_cc() declared in the IIRthdl layer class, not in the IIRScram layer class. Figure 2.6 on page 21 illustrated this scheme. As an example, let’s look at how to insert the IIRthlerocessStatement class between the IIRScramProcessStatement and the IIR_ProcessStatement class. The original IIR_ProcessStatement.hh is like this: #include "IIRScram_ProcessStatement.hh" class IIR_ProcessStatement : public IIRScram_ProcessStatement { After adding the IIRthdl-ProcessStatement class, the IIR_ProcessStatement needs to be derived from the IIRthlerocessStatement class. The IIR_ProcessStatement.hh is then modified like this: #include "IIRthd1_ProcessStatement.hh" class IIR_ProcessStatement : public IIRthd1_ProcessStatement { 34 On the other hand, the IIRthdl-ProcessStatement has to be derived directly from the IIRScram_ProcessStatement class. The IIRthdl-ProcessStatement.hh looks like this: #include "IIRScram_ProcessStatement.hh" class IIRthd1_ProcessStatement : public IIRScram_ProcessStatement { Other IIRthdl layer classes should be added to the class hierarchy in similar manner. 3.2.4 The IIRthdLDesignFile Class The predefined IIR.DesignFile class represents the textual contents of a design file. These contents may include one or more IIR_LibraryUnits and/or one or more IIR_Comments. The IIR_DesignFile class defines a public data member IIRiibraryUnitList 1ibrary-units. This data member is a list of entity dec- larations and architecture declarations which cluster all VHDL library units into a design file together, so that they could be accessed one by one. The IIRthdlDesignFile class has basically 3 functions: 1. Use preprocessor #ifndef . . . #define to protect the “Classesh” file. 2. Include some “.h” files and use “typedef” to define some data types, like SavantbitType, SavantintegerType, and SavantrealType. 35 3. Call library_units._publish_cc() to let the lower level tree node publish C++ code. The implementation of this class is pretty straightforward. Please refer to [13, IIRthdLDesignFilehh, IIRthdlDesignFile.cc] for details. The .publish-cc() method of IIRScramLibraryUnitList is not overloaded be- cause it has already done the correct things. This method goes through each library unit in the list and calls their _publish_cc () method. This is the desired behavior of the .publish..cc() for IIR_LibraryUnitList . As a result, there is no need to define an IIRthdlLibraryUnitList class to shadow the IIRScramLibraryUnitList class. For implementation detail of the IIRScramLibraryUnitList class, please refer to [12, IIRScramLibraryUnitList.hh, IIRScramLibraryUnitList.cc]. From here we can see that if the .publish_cc() function of an IIRScram layer class has implemented the desired functions, then there is no need to defined its corresponding IIRthdl layer class to shadow it. As a result, not every IIRScram layer class has a corresponding IIRthdl layer class. 3.2.5 The IIRthdl.EntityDeclaration Class The predefined IIREntityDeclaration class represents VHDL entities. It is a child class of the IIR.LibraryUnit class and contains several predefined public data elements shown in Table 3.4. These data elements are all lists which keep entity related information, such as generic declarations, ports, etc. The IIRScram_EntityDeclaration class uses all of 36 ] Data Member Type Data Member Name ] IIR_GenericList generic_clause IIR_PortList port-clause IIR_DeclarationList entity-declarative-part lIR_ConcurrentStatementList entitystatemeanart IIR_DesignUnitList architectures Table 3.4: Predefined Public Data Elements of IIR_EntityDeclaration them in its _publish_cc() method. None of them have been used in this project so far. The desired behavior of the IIREntityDeclaration is to publish nothing at all. Thus the _publish_cc() method of IIRthdLEntityDeclaration class is just empty. It is possible to make changes to this class if new features need to be implemented in the future, such as generic constants. It probably would require corresponding changes in other part of the front end interface. This is left to the decision of future participates of this project. 3.2.6 The IIRthdLArchitectureDeclaration Class The predefined IIR_ArchitectureDeclaration class represents one of several potential implementations of an entity. Like the IIR_EntityDeclaration class, it is also a child class of IIR.LibraryUnit. The IIR_ArchitectureDeclaration Class has several predefined public methods and public data elements. Among them, the IIR_EntityDeclaration * get-entity() method retrieves the pointer to the entity to which the architecture is associated. The IIR_ConcurrentStatementList architecture_statement_part data member is a list pointing to all the current statements in the architecture body. The IIRthdl_ArchitetureDeclaration class does two things. First, it prints a mes- 37 sage to the standard output Showing the name of the architecture being processed. Second, it calls the _publish_cc() method of architecture_statement_part which causes the higher lever nodes in the parse tree to publish. The first task is performed by printing the names to standard output “cerr”. To get the name of the architec- ture, the _get-dec1arator() function is called. This function is defined as a virtual function in the IIRScram class. It can be used by any node in the parse tree to get its declarator string. The implementation of this class is straightforward. For details please refer to [13, IIRthdLArchitectureDeclaration .cc]. 3.2.7 The Process Statement The SAVANT predefined IIR_ProcessStatement class represents a sequential declar- ative region and single thread of execution. Such processes must appear within an architecture, concurrent block statement or concurrent generate statement. The VHDL process is the translation unit of the C++ publisher. Each process will be translated into a simulation class. In the simulation class, signals and variables that are used in the VHDL process are translated into C++ data elements and registered to the simulation kernel. This section discusses how to translate VHDL process into simulation class. Data Elements There are two predefined public data elements in IIR.ProcesssStatement class: 38 o IIRjeclarationList process_declarative-part, which is a list of declara- tion items, such as local variables. 0 IIR-SequentialStatementList process-statement-part, which is a list of all sequential statement in the process. The IIRthdl_ProcessStatement.hh declares several public and private data ele- ments. There are two public data elements: 0 IIR-Char *classmame, which is a character pointer used to keep the name of this class. This information will be used when generating the interconnection information. o IIR-Int32 c1ass_id, which is a integer used to keep the ID of the class. In the -publish_cc() method of IIRthdl_ProcessStatement class, a variable static int type-id=0 is declared to generate an unique ID for each simulation class. The c1ass-id uses the value of type_id. It will be used in generating intercon- nection information. The IIRthdLProcessStatement.hh declares five private data elements. They are all used as local variables. These data elements are: set sig-in-1ist, which is the set for input signals. 0 set sig_out_1ist, which is the set for output signals. 0 int in_sig, which is used to count the total number of input signals. 0 int out_sig, which is used to count the total number of output signals. 39 0 int state_num, which is used to count the total number of states. These variables will be used when publishing the constructor of the BasicObject class, which needs to know the number of input/output signals and states in the VHDL process. Input / Output Signals Before further discussion, it is necessary to define “input” Signal and “output” signal first. In a VHDL process, if the value of a signal is referenced, this signal is an input signal. For example, signals appear on the right hand side of signal assignment statements or “if” statements are input signals. If a signal’s value is changed in the VHDL process, it is an output signal. For example, signals appear on the right hand side of signal assignment statements are output signals. It is possible that a signal is both an input signal and an output signal. For example, Signal a in VHDL statement ‘ ‘a <= not a’ ’ is both an input signal and an output signal. In VHDL, both entity declaration statement and architecture declaration state- ment declare signals. With in an architecture body, there could be several processes. This means a VHDL process may not cover all signals declared by the architecture. Only those signals that are covered by the process should be translated when trans- lating this process into a simulation class. This presents the problem of finding what signals are used by the process. The SAVANT VHDL Analyzer has solved this problem. In IIRScram.hh, a virtual function 40 void _get_1ist_of_input_signals(set* list) is declared. Its function is to add pointers of all input signals associated with an IIR node to “list”. Since “list” is defined as a set object, the same signal pointer will be added to the set only once (please refer to [12, set.hh] for details). This function is overloaded by all other IIRScram layer classes. The IIRScram_ProcessStatement class defines this function like this: void IIRScram_ProcessStatement:: -get_1ist_of_input_signals(set* list) { process_statement_part._get_list_of_input_signals(list); 'The process-statement-part data eknnent is of type IIR_SequentialStatementList. In the IIRScram_SequentialStatementList class, the above function is defined as follows: void IIRScram_SequentialStatementList:: _get_list_of_input_signals(set* list) { IIR_SequentialStatement* stmt = first();. for(; stmt != NULL; ) { stmt->_get_list_of_input_signals(list); stmt = successor(stmt); 41 As a result, each sequential statement in the VHDL process will call its _get-1ist-of_input_signals () to put its input signals into “list”. Similarly, another virtual function void _get_signal_source_info(set* siginfo) is defined in IIRScram.hh to collect output signals using set. The set utility class defines a function named make_list(). This function first creates a list that contains all data in the set then returns the pointer of the list. After the input signal set and the output signal set have been obtained, the two sets call the make-1ist() function to create two signal list. In file IIRthdl.hh, two global variables are declared to keep the two list: extern d1_list *_proc_in_sig_list; extern d1_list *_proc_out_sig-list; These two signal lists will be used by other IIRthdl layer classes, such as IIR- thdLIndexedName. In SAVANT, it is possible that the same array element appears more than once in the input or output signal list. The reason is that SAVANT generates an IIR_IndexedName node each time it encounters an array element signal. For other of signals, SAVANT generates only one IIR node, no matter how many times this signal appears. For example, for the following VHDL process: process begin a <= c and arr(1); b <= c or arr(1); end process; SAVANT generates only one IIR node for “c”, but two IIR nodes for “arr(l)”. When generating the input signal set, their is only one IIR node for “c” added to the set. But there are two “arr(1)” IIR nodes added. This seems strange, bUt this is SAVANT does handle this problem this way. It took me lots of effort to find out this problem. The reason is that TyVIS requires different object for different array element. Since the SAVANT publisher is TyVIS oriented, thus it handles this situation in this strange way. In our project, only one array element should be put in the signal list. As a result, a function named void _clean_sig_list_for_identical_e1ements(dl_list *list) is defined in IIRthdl.hh. The function of this method is to remove multiple copies of array elements from a signal list. Its implementation will be discussed in later sections. After calling make_1ist() to get the input signal list and the output signal list, the -clean_sig-1ist_for-identical-e1ements() function is called on both signal lists. Wait Statement List VHDL process usually contains wait statement. There is no language construct in C++ which directly corresponds to the semantics of the VHDL wait statement. As 43 a result, wait statement has to be implemented according to its semantics. In SAVANT, for each process, it is necessary to find out the number of wait statements and keep them in a list. To achieve this, SAVANT defines a virtual function void _build_wait_1ist (d1_list *) in the IIRScram_SequentialStatement class. Since IIRScram_SequentialStatement class is the root class of all sequential statement classes in the IIRScram layer, each se- quential statement class will inherit then overload this function. For example, both IIRScram_IfStatement class and IIRScram-WhileStatement class are child class of the IIRScram_SequentialStatement class. They may all contain wait statement. As a result, they all overload the _build_wait-1ist() function. The IIRScram_ProcessStatement class defines a public data element named dl_list .wait_stmt_list to keep the wait statement list. To build the list, a while loop is used to call the _build_wait_list() function of each sequential statement node in the process_statement-part data element. The code is as following: stmt = process_statement_part first(); while (Stmt != NULL) { stmt->_build_wait_list((d1_list*)&_wait_stmt_1ist) stmt = process_statement_part.successor(stmt); Details on how to handle wait statement will be discussed in later sections. 44 Name of Class Since each VHDL process is translated into a class, it is important that they all have different names. To achieve this, the _publish_cc() method of IIR- thlerocessStatement class defines a static integer type_id. The initial value of type_id is 0. Each time after publishing a class, the value of type_id is increased by one. Since type-id is used as part of the class’s name, each class will have a different name. The naming scheme of a class is like this : “current architecture name” plus “_of.” plus “current entity name” plus “_class” plus “type_id”. The name of the class is stored by the class_name data element described above. Also, each class name and its corresponding “type_id” is written to a file named “Classes.id” for examination purpose. Publishing Class Header As discussed in previous sections, _cc_out is used exclusively to publish C++ code. The first thing in publishing the code is to set the output file name to “Classesh”. The first line of code Should be the class header, like: class class_name : public BasicObject This could be done easily by the following code: _cc_out.set_fi1e("Classes", ".h"); _cc_out << "class " << class_name << " : public BasicObject" << "\n"; Other C++ code could be published in the same way. It is not necessary to set the publishing file to “Classes.h” each time new code is written to that file. It is 45 only when the publishing file name is changed, does it necessary to change the file name back to “Classesh”. Also, don’t forget to write “endl” to start a new line in “Classesh” . Signal Declarations Signal declarations in the class are not different from the common “type + name” format. There are two kinds of signals, input signals and output Signals. As de- scribed above, global variable _proc_in_sig-list is the list of input signals and _proc_out-sig-list is the list of output signals of the VHDL process being trans- lated. To publish these signals, it is necessary to go through the two lists to publish the type and name of each signal. The IIRthdLProcessStatement class has defined two functions, _publish_cc_in_sig_decl () and _publish-cc-out-sig_dec1(), to publish 1 input signals and output signals respectively. For input Signals, a prefix “in_’ is put to the name of each signal. For output signals, a prefix “out-” is put to the name of each signal. The reason for adding a prefix is that one signal could be both an input signal and an output Signal. In the simulation object model, these two types of signals are implemented differently. As a result, this signal has to be described by one input signal and one output signal. The prefix is used to distinguish the two signals. To publish the type of the signal, IIRScram.hh has defined a virtual function void _publish-cc-type.name(). For each signal declaration, this function will publish the type of the signal using _cc_out. In general, SAVANT puts a prefix “Savant” 46 and suffix “Type” to each VHDL type. For example, the VHDL “bit” type will be published as “SavantbitType”. Previous sections have discussed how to implement three basic VHDL data types in C++. Each time an input signal is published, it is necessary to increase the in- put signal counter in-sig by one. For array types, it is necessary to add the total number of elements in the array to the counter. To get the size of the array, the IIRthdLArraySubtypeDefinition class has defined a function int .get_array_tota1-e1ement_num(). This function simply multiplies each dimension of the array and returns the product. Details on implementing VHDL array types will be discussed later. SAVANT has defined a virtual function IIR.Boolean -is-array-type() in IIRScram.hh. Its function is to determine whether a IIR node is of array type. IIR nodes of array type will return a boolean value true, all other IIR nodes will return false. By calling this function for each signal, it can be determined if this signal is an array type. The last thing to mention is using single array elements as input signals. In SAVANT, if the value of an array element is referenced as an input signal, the whole array is put into the input signal list (not that particular array element). This is not the desired behavior in this project. As a result, the IIRthlendexedName class has overloaded the -get-list_of_input-signals () function so that single array element is put into the input signal list. Details about the IIRthdLIndexedName class will be covered in later sections. The problem here is how to publish name of the signal array element. The index of the array element is used as part of the name for that 47 Signal. For example, if array element arr(l,2) is in the input signal list, the name of this signal will be “in_arr_1.2”. To determine whether a signal is an array element, the IIR predefined get_kind() function can be used. If the return value of this function is “IIR_INDEXED_NAME”, the signal is an array element. We can then use the above naming scheme to publish it. Variable Declarations SAVANT did not implement a way to get a “variable list”. To find out what variables have been declared in a VHDL process, the process-dec1arative_part data element of IIR_ProcessStatement must be used. The type of “process_declarative.part” is “IIR_DeclarationList”. It is the list of declaration items in the process. It may contain type declarations and variable declarations. To see if an declaration item is a variable declaration, we can use the predefined “get_kind()” function to get its type. If the return value is “IIR_Variable_Declaration”, this item is a variable declaration. We can then publish this declaration item as a variable. Publishing variable declaration is similar to publishing signal declarations. The only difference is that no prefix is add to variable names. Also, each time after publishing a variable, the counter “state_num” must be increased. The same rule about array size applies for variable arrays. The Constructor After publishing signal and variable declarations, the next step is to publish the constructor. Since “BasicObject” is the parent class of each simulation class, it is 48 necessary to call the constructor of “BasicObject”. The constructor of BasicObject uses the number of input signal, output signal, and state in the VHDL process as parameters (this is why counters “in_sig”, “out_Sig” and “state_num” are declared). The constructor basically has two tasks: to register signals and variables, and to assign initial values to them. The way to publish signal registrations is similar to publishing the signal declarations. The -proc_in-sig_1ist data element is used ( to publish input signal registration, and the ‘_proc.out_sig_list” is used to publish output signal registrations. The process-declarative_part is used to publish state (variable) registrations. If there is an input signal in-a, an output signal out_b, and a variable c, then registerInSigna1(&in-a), registerOutSigna1(&out-b) and registerState (ac) should be published to register them respectively. These three functions are declared by the “BasicObject” class. To get the initial value of a signal, the predefined “get_value()” function is called. This function returns an IIR type pointer pointing to the initial value expression. If the returned pointer is not NULL, its _publish-cc() function can be called to publish the signal’s initial value. Otherwise, the rules discussed in previous sections to set the initial value of the signal. The same approach applies to setting variable initial values. The “wait for” signals Two extra signals, in-wait.for-signal and out-wait-for-signal are declared exclusively to handle the VHDL wait statement. The two signals are of type 49 SavantbitType. The first. signal is an input signal, the second signal is an out- put signal. Their initial values are both 0. These two signals are not signals declared by the VHDL process. They are extra add on signals for each simulation class. The reason to add them will be cleared up in later sections. It is important to know the registration of these two signals should be put to the last part of the signal registration section. As a result, they will be put to the end of the input and the output signal list of the simulation object. On the other hand, these two signals are connected directly when generating the interconnection information [9]- The executeProcess() Function The executeProcess() function is a line to line translation of the sequential statements in the VHDL process. To publish all the sequential statements, the -publish_cc() function of .process_statement-part is called. Before calling the process-statement_part._publish_cc(), the system- publishing prefix is set to “in.” by calling the void _set_pub1ish_prefix-string() function defined in IIRScram.hh. Once the system publishing prefix is set, all signals or variables names will contain this prefix when they are published. In most cases, the sequential statements in a process will reference an input sig- nal, thus the prefix is set to “in_”. When publishing the output signals, the system-publishing prefix need to be changed temporarily to “out_”. After calling process-statement-part._publish_cc(), the system publishing prefix needs to be restored to its original value. 50 In addition, a static integer “P” is also declared in executeProcess(). The purpose of this variable is to handle the V HDL “wait” statement. It will be covered in detail in the section discussing the VHDL wait statement. The IIRthdl Class The IIRthdl class is the root class of the IIRthdl layer. The reason to add this class is to declare some global data elements and public functions for the IIRthdl layer classes. The following data and functions are declared in the IIRthdl class: 0 d1_list *_proc-in_sig-1ist, which is a global variable used to keep the input signal list of the current VHDL process being published. 0 d1-list *_proc_out-sig_list which is a global variable used to keep the output signal list of the current VHDL process being published. The way how this and the above variable is used has been discussed in previous sections. 0 IIR_Boolean _is_identical_with(IIR *obj), which is a function used to test whether obj and the current IIR node (*this) have the same name. The way to determine this is to use strstream to print out the names of these two objects. If the names are the same, then the function returns “true”. Otherwise, the function returns “false”. 0 int _get_position_in-list(d1_list *list, IIR *obj), which is a function used to find the position of obj in list. If obj is found in list, then its position is returned. Otherwise, “-1” is returned. 51 This function will call the above _is_identica1_with(IIR *) function to test if obj has the same name of any node in list. 0 void _clean-sig-list_for_identical-elements (d1_list *list), which is a function used to get rid of redundant array entry element from list. In SAVANT, if an array entry appears several times in a VHDL process, there will be multiple IIR_IndexedName objects created for that array entry. Thus after the input or output signal list of the VHDL process is created, it is possible the same array entry could appear more than once in the two lists. Because each array entry object has a different memory address, the only way to tell two arrays elements are the same is to examine their names. This is the reason to define the _is_identical_with() function. It is also possible that the whole array is in the signal list, and one of its entry element appears in the list. If this happens, this array entry also must be deleted from the signal list. The .get.position_in_list() function is used to find out the position of the whole array signal(the prefix of the array entry). If the return value is “—1”, the whole array is not in the list. Otherwise, the whole array has already been put into the list and the array entry is deleted. For coding details of the IIRthdl class, please refer to [13, IIRthdl.cc]. 52 3.2.8 Signal Assignment Statement The predefined IIRSigrialAssignmentStatement class updates the projected waveform output of one or more signal drivers. It is a child class of the IIR_SequentialStatement class. The signal assignment may appear anywhere a sequential statement may appear. The IIRthdl_SignalAssignmentStatement class is defined to overload the .publish-cc() function of IIRScram_SignalAssignmentStatement class. Predefined Public Method and Data The IIRSignalAssignmentStatement has a predefined target method IIR* get-target(). Target method refers to the target of a signal assignment statement. After getting the IIR pointer of the target, its _publish_cc() method can be called to publish its name. The target is an output signal. Since the system publishing prefix is “in_”, and all output signals should have prefix “out.”, we need to change the system publishing prefix temporarily to “out-”. After the .publish-cc () method of the target is called, the system publishing prefix should be changed back to “in_”. Another useful predefined public method is IIR_DelayMechanism get_delay_mechanism(). A signal assignment statement ei- ther uses transport or inertial delay. The the return value of this method should be either “IIR_TRANSPORTDELAY” or “IIR.INERTIAL.DELAY”. The IIR.SignalAssignmentStatement has a predefined data element IIRJlaveformList waveform. It is the list of signal drivers (waveforms) associated with this signal assignment. We need to go through this list to publish all 53 a <= inertial b after 1 ns, c after 2 ns; Figure 3.3: VHDL Source Code out-a = in_b; assignDelay(&out_a, 1 NS, INERTIAL); out_a = in_c; assignDelay(&out_a, 2 NS, INERTIAL); Figure 3.4: Published C++ Code Figure 3.5: Default Publishing Format of Signal Assignment waveforms. Default Publishing Format The default format of signal assignment is to publish an C++ assignment statement and a assignDelay () function for each individual waveform. Figure 3.5 is an example of the publishing format. To publish the assigned value, the _publish_cc() method of the IIR-WaveformElement class should be called. Both “INERTIAL” and “TRANSPORT” are defined in SavantGlobal.h file. They are published according to the result of the get-delay.mechanism() function. If the return value is “IIR.INERTIAL-DELAY”, then “INERTIAL” is published. If the return value is “IIR.TRANSPORT.DELAY”, then “TRANSPORT” is published. The delay of the signal assignment can be retrieved by calling the predefined I~IR* get..time() method of the IIR.WaveformElement class. The returned IIR pointer 54 will point to the assignment time expression. If the pointer is not NULL, then its _publish_cc() method is called to publish the time expression. If the pointer is NULL, this means “delta”delay and the SavantGlobal.h defined “DELTA” string should be published. The IIRthdl.WaveformElement Class The IIR.WaveformElement has a predefined public method ‘ ‘ IIR* get_va1ue() ’ ’. It returns an IIR pointer pointing to the value expression being assigned to the output signal. The IIRthdLWaveformElement class is defined to overload the _publish-cc() of the IIRScram.WaveformElement class. There is simply one line in the new _publish-cc () function: get_value () ->-publish_cc O . Whole Array Assignment It is valid in VHDL to assign the value of one array to another. For example, if both a and b are two dimensional array objects, “a <= b” means to do one to one copy of the array element from b to a. In our project, array is not registered to the simulation kernel as single object but as a group of discrete elements, thus whole array assignment should be handled differently. Details on how to handle VHDL arrays will discussed in later sections. Assignment of Record Field In contrast to array, record is registered to the simulation kernel as a single object. Thus when a filed of the record object is assigned a new value, the delay should 55 be assigned to the whole record object. To get the name of the record object, the predefined _get_prefix() method of IIR_SelectedName class is called. This method will return the pointer of the record object. To publish its name, we can simply call its .publish_cc() function. 3.2.9 Variable Assignment Statement The IIR-VariableAssignmentStatement class updates the value of a variable with the value specified in an expression. It is a child class of the IIR_SequentialStatement class. Variable assignment statement may appear anywhere a sequential statement may appear. The IIR-VariableAssignmentStatement also has a predefined public target method, the ‘ ‘IIR* get_target() ’ ’. It will return an IIR pointer to the target of the assignment. It defines another public method ‘ ‘IIR* get..expression() ’ ’ to get the value of the assignment. To publish the assignment equation, the “_u get-target()->-publish_cc() is called first, then an is written out to “Classesh”, then get-expression()->_pub1ish_cc() is called. Variable Name When declaring variables, no prefix is added to their names. Now that the system-publishing prefix string is set, variable names will have the system pre- fix as well. This is not desired in this project. To overcome this prob- lem, a IIRthdl_VariableDeclaration class is added. This class overloads the .publish_cc() of IIRScram-VariableDeclaration class. Actually the new func- 56 tion is almost the same as the old one, it only comments out the line IIRScram: :_publish_cc_prefix-string(), which publish the system-publishing pre- fix. 3.2.10 Expressions In signal assignment and variable assignment statements, expressions are most commonly used as the new value to be assigned. As mentioned above, the get_value() method of the IIR-WaveformElement class and the get_expressionO of the IIR.VariableAssignmentStatement class will return an IIR pointer to the ex- pression. To publish the expression, the .publilecc () method of the IIR pointer is called. Most of the time, the IIR pointer returned will point to an IIR_DyadicOperator node or an IIR_MonadicOperator node. Dyadic operator is an operator with two operands, like ‘ ‘add’ ’. Monadic opera- ¢ tor is operator with only one operand, like ‘not ’ ’. The Dyadic Operator Classes The predefined IIR_DyadicOperator classes include logical, relational, shift, adding, multiplying and miscellaneous operators. Derivatives of this class represent both language predefined dyadic operators and subprograms defining overloading of these Operators. The parent class of IIR_DyadicOperator is IIR_Expression, which has lots of pre- defined child classes, such as the IIR_NandOperator, the IIR_EqulityOperator class, etc. Actually all operator classes with two operands are its child classes. 57 The IIR_DyadicOperator class has two useful predefined methods, the ‘ ‘IIR* get_left_operand() ’ ’ and the ‘ ‘ IIR* get_right_operand() ’ ’. The first method returns an IIR pointer to the left operand, the second method returns an IIR pointer to the right operand. By calling the _publish-cc() method, the two operands can be published easily. It is possible that either of the IIR pointers points to an IIR.DyadicOperator node itself. This is the situation where the expression contains more than one dyadic operators. The expression tree is thus more than one level. The whole expression can be published recursively. The predefined ‘ ‘ get.kind() ’ ’ method can be used to determine the name of the operator. For example, if the return value is “IIR.EQULITY-OPERATOR” , it means the current operator is an “equality” operator and we can publish the corresponding “ == ”operator in C++. Figure 3.6 is a code segment of the _publish_cc() method of the IIRthdLDyadicOperator class. Several operators, such as “and”, “or”, and “not”, can be either logical operators or bitwise operators. To publish the correct operator, their type should be determined. To solve this problem, the IIRScramDyadicOperator class defines a virtual function ‘ ‘void _publish_cc_operator.name() ’ ’. All its child classes must override this class to print out the correct operator. For example, Figure 3.7 show this function of the IIRthdLAndOperator class. If the return value of get_subtype()->-is.bit-type() is true, it means the op- eration is a bitwise operation and the bitwise operator should be published. Other- wise, the logic operator should be published. The way to publish these Operations is shown in the default section of Figure 3.6 on page 58. Please refer to [13, IIR- switchfget_kind()) case IIR_NAND_0PERATOR : _cc_out << "”("; get_left_0perand()->_publish_cc(); _cc_out << " & "; get_right_operand()->_publish_cc(); _cc_out << ")"; break; default: // for and/or/not, both logical and bitwise _cc_out << "("; get_left_operand()->-publish_cc(); _cc_out << " "; _publish_cc_operator_name(); _cc-out << " "; get_right_operand()->-publish_cc(); _cc_out << ")"; Figure 3.6: Example on How to Publish Expressions void IIRthd1_And0perator::_publish_cc_operator_name() { if(get_subtype()->-is_bit_type()){ _cc_out << "a"; } else { _cc_out << "&&"; } } Figure 3.7: The _publish_cc-operator_name() Method of IIRthdLAndOperator 59 thdl_DyadicOperator.cc] for coding detail. The Monadic Operator Classes The predefined IIR_Monadic operators include identity, negation, absolute value and not. Derivatives of this class represent both language predefined monadic operators and subprograms defining overloading of these Operators. The IIR_MonadicOperator class has a predefined function ‘ ‘ IIR* get_operand ’ ’ which returns an IIR pointer of the operand. The Operand can be either a dyadic op- erator or a monadic operator itself. To publish the operand, its ‘ ‘_publish-cc() ’ ’ method is called. The IIRScram_MonadicOperator class also defined a virtual func- ‘ ‘void _publish-cc_operator_namef) ’ ’. This function also must be over- tion loaded by its child class. Up to now, only the NOT monadic operator has been implemented. For coding details, please refer to [13, IIRthdLMonadicOperator.cc]. 3.2.11 The If Statement Like C++, VHDL has a ‘ ‘ if. .then. .else ’ ’ statement which evaluates an condtion then executes different branches accordingly. The goal here is to translate the VHDL If statement into the C++ If statement. If statement usually contains a test condition, a “then” branch, a cluster of “el- sif” branches, and a final “else” branch. AIRE defines the IIRJfStatement class and the IIR_Elsif class to implement the If statement. Correspondingly, an IIR- thlefstatement class and an IIRthdLElsif class have been implemented to per- form the translation work. 60 The IIRthlefStatement Class The AIRE predefined IIR_IfStatement class provides for the optional, selective execution of one or more sequential statement lists. It is a child class of IIR_SequentialStatement and may appear anywhere sequential statements are al- lowed. The IIRJfStatement uses a chain of IIR.Elsif tuples to contain the elsif parts of the If statement. The IIR_Elsif tuple combines a test condition and a sequence of statements, which are to be executed if the test condition is true. If the recursion does not encounter a “true”, the final else sequence of statements (the elsesequence in IIR_IfStatement) is reached. The IIR_IfStatement has the following predefined public data and method: 0 HM get_conditionO, which returns an IIR pointer to the boolean “condi- tion” which is evaluated in order to determine which sequential statements are to be executed. o IIR-SequentialStatementList then-sequence is the “then” statement branch which is to be executed when the condition is true. 0 IIR.Elsif* get_elsifO, which returns an IIR_Elsif pointer pointing to the “elsif” sequences. 0 IIR.SequentialStatementList else_sequence, which is the “else” statement branch. To publish the If statement, we only need to call the .publish_cc() method of 61 the above public data or pointers returned by the public methods. Coding is rather straightforward. For details, please refer to [13, IIRthdLIfStatementcc]. The IIRthdLElsif Class The predefined IIR_Elsif class represents one step within a recursive if-then-else state- ment. It is the “elsif” branch which may contain more than one “elsif” statement sequences. The IIR-Elsif class has the following predefined public data and methods: o 1111* get_conditionO, which returns an IIR pointer pointing to the boolean expression to be evaluated. 0 IIR.SequentialStatementList then-sequence_of_statements, which is the sequence of statement to be executed when the condition is true. 0 IIR.Elsif* get_else_c1ause(), which returns the next “elsif” sequence if it exists. This makes the “elsif” sequence a linked list. Similarly, the .publish_cc() method of the above data and returned pointers are called to publish the “elsif” statement. Details of coding please refer to [13, IIRthdLElsifcc]. 3.2.12 The Case Statement VHDL has a “Case” statement in which the behavior is to depend on the value of a single expression. Different evaluation of the expression will lead to the execution of different sequential statement sequences. This is similar to the “Switch” statement in 62 "C++. But the VHDL “Case” can not be converted to the C++ “Switch” statement directly. The reason is that in C++, the evaluation values of “Switch” can not be expressions, they can only be constants. Thus the V HDL “Case” statement is also translated into C++ “if..then..else” statement. The IIR.thdLCaseStatement Class The AIRE predefined IIR_CaseStatement provides for execution of at most one sequential statement list from a set of alternatives. It is a child class of the IIR_SequentialStatement class and may appear anywhere sequential statements are allowed. The IIR-CaseStatement class has a predefined ‘ ‘ IIR* get-expression() ’ ’ pub- lic method. The returned IIR pointer of this method points to an expression whose value is evaluated in order to select one choice and the implied sequence of statements to execute. The IIR-CaseStatement class has a predefined public data named case-statement_alternatives. It is of type IIR-CaseStatementAlternativeList. It is a list of the alternatives of the “Case” statement. The .publish_cc() function of IIRthdLCaseStatement basically does 4 things: 1. Save the returned IIR pointer of get_expressionO to -current.publish.node. The -current-publish_node is an IIR* type global variable defined in IIRScram.hh. The reason to save the pointer to this variable is to be able to publish the expression later when out of the IIR-CaseStatement node. 63 2. Publish “if(false)” as the “then” branch of the C++ If statement, so that all “Case” alternatives can be published as “elsif” branches. 3. Call the .publish-cc() method of the case_statement_alternatives to pub- lish the “Case” alternatives. 4. Restore the old _current-publish.node value. For programming details please refer to [13, IIRthdl-CaseStatement.cc]. The IIR.thdl-CaseStatementAlternativeByExpression Class The predefined IIR-CaseStatementAlternativeByExpression represents a case state- ment alternative in which the choice is a simple expression, discrete range (range type), or element simple name (the choice). It is a child class of the predefined IIR-CaseStatementAlternative class. The IIR-CaseStatementAlternativeByExpression has a predefined public method ‘ ‘ IIR* get-choice() ’ ’ which returns an IIR pointer pointing to the choice expres- sion of this alternative. The IIR_CaseStatementAlternative class has a predefined public data "IIR-SequentialStatementList sequence_of.statements” which is inherited by the IIR_CaseStatementAlternativeByExpression class. This data element is ba- sically a list of sequential statements which are to be executed when the “Case” expression is evaluated to match the choice expression of this alternative. The _publish_cc () method of IIRthdl_CaseStatementAlternativeByExpression publish the “Case” alternative as a “elsif” branch of the If statement. It does the 64 following things: 1. Publish the “else if(” string. 2. Call -current_pub1ishmode->_publish_cc() to publish the expression. In the _publish_cc () method of IIRthdLCaseStatement, the IIR pointer to the expression is stored in -current-publish_node. 3. Publish the “2:” string. 4. Call get_choic()->_publish_cc() to publish the choice expression. _ 5. Publish the “)”. 6. Call sequence-of-statements ._publish_cc() to publish the sequential state- ment of this “Case” alternative. Please refer to [13, IIRthdl-CaseStatementAlternativeByExpression.cc] for cod- ing details. The IIRthdLCaseStatementAlternativeByOthers Class The predefined IIR-CaseStatementAlternativeByOthers represents a case statement alternative in which the choice implicitly denotes other elements of the case’s com- posite subtype not previously explicit within an IIR_CaseStatementAlternativeList. It is similar to the “else” branch of the If statement or the “default” branch of the Switch statement in C++. The _publish_cc () method of IIRthdl-CaseStatementAlternativeByOthers sim- ply calls _publish_cc () of sequence_of _statements 65 to publish the code. Since IIR_CaseStatementAlternativeByOthers is a child class of IIR_CaseStatementAlternative class, it inherits this data element too. For coding details, please refer to [13, IIRthdl-CaseStatementAlternativeByOthers.cc]. 3.2.13 The For Loop Statement VHDL has a For loop statement which resembles the C++ For loop statement. The predefined IIR_ForLoopStatement executes a sequences of statements zero or more times, advancing the value of an iterator constant once before each exe- cution of the loop body. The IIR_ForLoopStatement class is the child class of IIRSequentialStatement and may appear anywhere a sequential statement is allowed. The IIR.ForLoopStatement has the following predefined public data and method: 0 IIR-ConstantDeclaration* get_iteration_scheme(), which returns an pointer pointing to the iteration scheme. The iteration scheme, a constant declaration, is the For loop iterator. The declaration’s subtype determines the iteration direction and range. 0 IIR.SequentialStatementList sequence_of-statements, which is the list of sequential statements within the For lOOp. The IIRthleorLoopStatement class is defined to overload the .publish_cc() method of the IIRScram_ForLoopStatement class. To publish the For loop, the fol- lowing functions are used: 0 get-iteration_scheme()->_is_ascending-range(), which is called to deter- mine whether the iteration scheme is ascending. If this is true, its left bound 66 is its lower bound. Otherwise, its right bound is its lower bound. The lower bound is assigned to C++ iteration variable. 0 get_iteration_scheme () ->-publish-cc_left O, which is called to publish the left bound of the iteration scheme. 0 get-iteration_scheme()->-publish_cc_right(), which is called to publish the right bound of the iteration scheme. The above functions are called to publish the head of the For loop. Inside the For loop, sequence_of_statements . _publish_cc () is called to publish the sequential statements of the For loop. In VHDL, the iteration variable is meaningful only within the For loop. Its value can’t be reference outside the For loop. In SAVANT, an iteration variable is named by its memory address. As a result, different iteration variables have different names. In the published C++ class, each iteration variable is declared within the For loop. For coding details, please refer to [13, IIRthdLForLoopStatement.cc]. 3.2.14 The While Loop VHDL also has a While Loop statement which is similar to the While Loop state- ment in C++. The predefined IIR-WhileLoopStatement executes a sequential state- ment list zero or more times. A boolean condition is. evaluated before each it- eration. If the condition evaluates true, the enclosed statement sequence is exe- cuted. Otherwise, the statement following the While loop statement is executed. 67 The IIR_WhileLoopStatement is a child class of IIR-SequentialStatement class and may appear anywhere a. sequential statement is allowed. The IIR_WhileLoopStatement has the following predefined public data and method: 0 IIR* get-whi1e-condition(), which returns an IIR pointer pointing to the loop condition. The While condition is evaluated at the beginning of each iter- ation through the loop statement’s body. When the While condition evaluates False, the loop execution terminates. o IIR_SequentialStatementList sequence-of_statements,which is the list of sequential statement that will be executed when the condition is true. C To publish the While LOOp, we simply need to call the ‘._publish_cc() ’ ’ func- tion of the above data and the IIR pointer returned by the method. Coding is straight- forward. For coding details please refer to [13, IIRthdl-WhileLoopStatement.cc]. 3.2.15 The Wait Statement VHDL has a Wait statement which does not have corresponding language construct in C++. A VHDL process (with no sensitivity list) executes from the beginning of the process to the first occurrence of a Wait statement, then suspends until the condition specified in the Wait statement is satisfied. If the process only includes a single Wait statement, the process reactivates when the condition is satisfied and continues to the “end process” statement, then begins executing again from the beginning. If there 68 wait_statement <= [labelz] wait [on signal_name {,...}] [until boolean_expression] [for time_expression] Figure 3.8: Syntax of Wait Statement are multiple Wait statements in the process, the process executes only until the next Wait statement is encountered [1, page168-169]. Syntax Wait statement is a sequential statement with syntax rule shown in Figure 3.8 on page 68. The sensitivity clause, condition clause, and timeout clause specify when the pro- cess is subsequently to resume execution. They can be combined together to use in the VHDL process. Starting with the word on, the sensitivity clause specifies a list of signals to which the process responds. If the Wait statement contains only a sensitivity list, the process will resume whenever any one of the listed signals has an event. The condition clause starts with the word until. It specify a condition that must be true for the process to resume. The timeout clause starts with the word for. It specifies a maximum interval of simulation time for which the process should be suspended [2, page114-116]. The IIR.WaitStatement Class The IIR-WaitStatement suspends execution pending a signal event, boolean condition and/or time out interval. It is a child class of the IIR_SequentialStatement class and 69 may appear almost anywhere a sequential statement may appear (some restrictions in subprograms). It has the following predefined public data and methods: 0 IIR_SignalNameList sensitivity_list, which is the sensitivity list. 0 IIR* get-condition-clause(), which returns an IIR pointer to the condition clause. If no condition clause is associated with the Wait statement, the pointer to condition clause returns NIL. o IIR* get-timeout-clause(), which returns an IIR pointer to the timeout clause. A NIL value for the clause denotes timeout at STD.STANDARD.TIME’HIGH. The IIRthdLWaitStatement class overloads the .publish_cc() method of the IIRScram.WaitStatement class. The three Wait clauses all have been implemented. The executeProcess() Function Before discussing details on how to implement the three Wait clauses, it is necessary to go back to the structure of the executeProcess () method of the simulation object class. The way the executeProcess () implements the suspension semantics of the Wait statement is simple. It uses a If statement to test the Wait conditions(an condition expression or event of sensitivity list signals). If the test returns true, then execution of the function goes to the next statement. Otherwise, the function simply returns. The semantics of Wait statement requires that VHDL process resume from the last suspended Wait statement, not the beginning of the process. In C++, each time 70 an executeProcess() function is resumed, it is always resumed from the beginning. Thus it requires a jump from the beginning of the function to the Wait statement where the function was last suspended. To solve this problem, two things have to be done. First, each Wait statement has to be labeled so that a jump can reach it directly. Second, a record has to be kept when the executeProcess() is suspended. The next time the function is resumed, the record will tell the function where to jump to. A local static integer “P” is defined to serve this purpose. Its initial value is “0”. Each time a Wait statement is reached, “P” increases by “1”. The first Wait statement is labeled “BLOCKl”, the second is labeled “BLOCK2”, and so forth. A switch statement is publish at the beginning of each executeProcess() function using the value of “P” as branching factor. Thus when a executeProcess() is suSpended, “P” keeps the sequence number of that Wait statement. Since “P” is a static variable, its value is not lost when the function returns. When the function is resumed next, the switch statement will jump to the Wait label according to the sequence number kept by “P”. This is how things work. Another issue is how each Wait statement could know its sequence number in the process. Wait statement will be published in the IIR.WaitStatement node, not the IIR-ProcessStatement node. Thus each IIR-WaitStatement node should already know its sequence number in the VHDL process when it is published. This problem is solved by SAVANT. The IIRScram_WaitStatement class has defined an public data IIR-Int32 wait_id. This integer is used to keep the Wait sequence number. Remember in the _publish_cc() method of IIRthlerocessStatement, the Wait list is built before any publishing work. It is during this building of the Wait list that 71 each IIRScramAVaitStatement node is assigned an wait_id. For details please refer to [13, IIRthdLProcessStatement.cc]. The Wait On Sensitivity List Clause The BasicObject class defines a function bool hasEvent (*) to test if a signal has an event on it. To implement the sensitivity list semantics, this function is called upon each signal in the sensitivity list of the Wait sensitivity clause. If all hasEventO function returns false, this means no event at all and the executeProcess() function should return. Otherwise, the function should start executing the following statement. The names of signals in the sensitivity list can be easily retrieved from the predefined sensitivity_list data element. The Wait Until Condition Clause The Wait condition clause is easy to handle. The get_condition_clause() will re- turn the IIR pointer to the condition clause. The condition is published as the test expression in an C++ If statement. If the condition is false, the executeProcess() function should return. Otherwise, the function should proceed from the next state- ment. The Wait For Timeout Clause As mentioned earlier, each C++ class has defined two signals exclusively to handle the Wait For clause, the in_wait-for-signal and the out_wait-for_signa1 of type SavantbitType. The first signal is registered as an input signal, the second is regis- *1 l0 P++; BLOCK3: out_wait_for_signal = ! in_wait_for_signal; assignDelay(aout_wait_for_signal,3 NS,TRANSPORT); if(lhasEvent(&1n_wait_for_signa1)) return; Figure 3.9: Example of Wait For Timeout Clause tered as an output signal. These two signals are connected directly when generating the interconnection information. The time out clause is actually handled as a signal assignment statement with transport delay. The delay time equals the timeout value. For example, if the third Wait statement in a V HDL process is “wait for 3 ns”, then the published C++ code is shown in Figure 3.9 on page 72. Thus the Wait For timeout clause is basically translated into the Wait On sensi- tivity clause. Combination of Clauses All the Wait clauses are implemented using the C++ If statement. The combination of Wait clauses is only a matter of publishing which If statement first. Since the Wait For clause is transformed into the Wait On sensitivity clause, the problem is Simplified to publishing the combination of sensitivity and condition clauses. If a Wait statement includes a sensitivity clause as well as a condition clause, the condition is only tested when an event occurs on any of the signals in the sensitivity clause [2, page 116]. This means the sensitivity clause has higher priority than the 73 condition clause. The If condtion generated by the sensitivity clause should be tested first. If there is an event. on the sensitivity list, then the If condition generated by the Wait condition clause Should be tested. For coding details, please refer to [13, IIRthdLWaitStatement.cc]. Process with Sensitivity List SAVAN T transforms process with a sensitivity list into process with a Wait statement which uses the same sensitivity list. This Wait statement is put as the last statement in the VHDL process. Thus there is no need to spend extra effort on this issue. To test this, simple type ‘ ‘scram -publish-vhd1 test.vhd’ ’ to see the VHDL code generated by SAVANT (test.vhd is the testing VHDL file containing process with sensitivity list statement). Appendix B shows the code of the IIRthdLWaitStatement.hh and appendix F shows the IIRthdLWaitStatement.cc file. 3.2.16 Constant Declaration In VHDL, constants can be declared anywhere declarations can appear. Due to limited time, the declarations of constants are restricted only to package declaration in this project. It is also possible to implement the declaration of constant in other declaration bodies. Since C++ also allows constant declarations, the translation of VHDL constant declaration into C++ constant declaration is straightforward. After being declared, constants can be used just like signals and variables. 74 VHDL Constant Declaration <= constant identifier{,...}: subtype_indication [:=expression]; C++ Constant Declaration <= const type identifier = expression; Figure 3.10: Constant Declaration Syntax The syntax of VHDL constant declaration and the C++ constant declaration syntax is shown in Figure 3.10 on page 74. The IIR_PackageDeclaration Class Package declarations are usually at the beginning of VHDL source code, thus packages will be published first by the SAVANT publisher. As a result, declarations in the package will be published at the beginning part of the “Classes.h” file. Since all C++ classes are published to “Classes.h”, these constants will become global constants. They can be accessed by any classes in the Classes.h file. The predefined IIR_PackageDeclaration class represents collections of declarations which are elaborated at most once, as a collection. This class has a predefined public data element IIR_DeclarationList package-declarative_part. It is a list of declarations appearing in the package. When processing the package declaration, the IIRScram_PackageDeclaration calls the .publish_cc() method to publish the C++ code. The -publish-cc() method in turn calls the locally defined .publish-cc.header() function. This function then calls the _publish_cc_package_declarations() method of the package_declarative-part, which is of type IIR_DeclarationList. This sequence .— ‘J C}! case IIR_CONSTANT_DECLARATION: _cc_out.set-file("Classes.h"); _cc_out << "const "; decl->_get_subtype()->_publish_cc(); _cc_out << " "; dec1->_publish_cc(); _cc_out << " = "; dec1->get_value()->_publish_cc(); _cc_out << ";\n" << endl; break; Figure 3.11: Code of Constant Declaration is correct thus there is no need to change it. There is no IIRthdl layer class, namely IIRthdl_PackageDeclaration, added to shadow the _publish_cc() method of the IIRScram_PackageDeclaration class. The IIRthdLDeclarationList Class The purpose to add the IIRthdLDeclarationList class is simply to overload the _publish_cc.package -declarat ion () function declared by the IIRScram_DeclarationList class. The new function is ba- sically a copy of the old function, only with the changes shown in Figure 3.11 on page 75. Coding is quite straightforward. For details, please refer to [13, IIR- thdLDeclarationListcc]. 3.2.17 Enumeration Types Like C++, VHDL also supports enumeration types. Thus the translation from the VHDL enumeration type declaration to C++ enumeration type is straightforward. Enumeration types can be declared anywhere, but in this project, only enumeration types declared in package are implemented. When processing a package declaration, the IIRScram_PackageDeclaration calls the .publish_cc () method to publish the C++ code. The .publish_cc() method in turn calls the locally defined _publish-cc_header() function. This function then calls the .publish-cc_package-dec1arations() method of the package-dec1arative-part, which is of type IIR_DeclarationList. A IIRthdLDeclarationList class has been added to overload the function. For enumeration declaration types, the “get_kind()” method will return “IIR.TYPE-DECLARAT ION”. The “_publish_cc_decl()” method is then called to publish the declarations (coding details please refer to [13, IIR- thdl.DeclarationList.cc]). The void .publish_cc-dec1() function is defined at IIRScram.hh as a virtual function. An IIRthdLTypeDeclaration class is defined to overload this function. There is only one line in the new function, ‘ ‘get-type()->-publish-cc_decl() ’ ’. The get_type () method is a predefined public method of the IIR-TypeDeclaration class. It returns an IIR.TypeDefinition pointer to the new type definition node. In the context of enumeration type declaration, the returning pointer will be an IIREnumerationTypeDefinition pointer. 77 An IIRthdl_EnumerationTypeDefinition class is defined to overload the _publish_cc_decl() method. In the AIRE standard, the predefined IIREnurnerationTypeDefinition represents its value domain by a set of enumeration literals. It has a predefined public data IIR_EnumerationLiteralList enumeration-literals, which is the list of enumeration literals associated with the type definition. The .publish_cc-dec1() function of IIRthdl_EnumerationTypeDefinition does the following things: 0 Set the output file name to “Classes.h”. 0 Call _publish-cc_type_name() to publish the name of the new type. 0 Use a for loop to go through enumeration_1iterals and publish each enumer- ation literal in the list. After an enumeration type has been declared, there is no difference in using a vari- able of this enumeration type and variables of other types. Thus declaration is the only thing needed to considered for enumeration types. For programming details, please re- fer to [13, IIRthdLTypeDeclaration.cc, IIRthdl_EnumerationTypeDefinition.cc]. 3.2.18 Array Types VHDL supports array types. Unlike C++, array type have to be defined first. This new type can then be used to declare array objects. This section discusses issues on how to publish VHDL array into C++ arrays. 78 The IIRthdLIndexedName Class The predefined IIR_IndexedName denotes a single element of an array. It has a predefined public method IIR* get-suffix() which returns an IIR pointer to the name’s suffix (an expression which evaluates to a single integer). The IIRthdLIndexedName Class is defined to handle array entry related prob— lems. This class has overloaded or defined the following functions: 0 void .get_signal-source_info(set *siginfo) This function is defined at IIRScram.hh as a virtual function. The purpose of this function is to put the current array entry into the output signal list siginfo. In SAVANT, the whole array will be put into the output signal list, not the single element. Thus this function is overloaded to put the array entry to the list. 0 void -get_list_of_input_signals(set* list) This function is also defined in IIRScram.hh as a virtual function. Its purpose is to put the current array entry into the input Signal list denoted by list. In SAVANT, the whole array is put into the input signal list, not the single entry. Thus this function is overloaded to put the array entry into the list. 0 void _publish_cc() This function is overloaded to publish the whole name of the array entry. It will use the two variables _proc-in-sig-list and _proc_out_sig_list defined by IIRthdl.hh to determine whether the current array entry is an output signal or an input signal, then put prefix ‘ ‘in-’ ’ or ‘ ‘ out-’ ’ accordingly. 79 o void _publish_cc_array_entry_location() This function is defined to pub- lish the suffix of the array entry using the underscore format. For example, array entry (1,2) will be published as _1_2. This function is to handle the naming of an array entry where the whole array is not in either the input or the output signal list. Thus this entry is declared as a separate signal and its name will use the underscore format. This function uses the get_suffixf) to get the IIR pointer to the suffix expression. Please refer to [13, IIRthdLIndexedNamecc] for programming details. Template Array Classes VHDL supports direct array operations. That is, array objects can be assigned, added, or multiplied as simple type objects. The result is that each array entry element will perform the operation. This feature is not supported in C++ directly. To implement this feature, VHDL array types have to be declared as C++ classes. These array classes must use operator overloading to implement the whole array operations. Template array classes have been developed to solve this problem. Right now, template array classes have been devel0ped for one, two, and three dimensional array types. The reason to use template is that all array classes are almost identical except for the data types of their entries. Thus there is no need to generate a separate class for each array type. Figure 3.12 on page 80 Show how the assignment Operator is overloaded by the one dimensional template array class. For now, the following operators have been overloaded: +,-,*,/ , ==, !=,&, l , «,~=. The “=(int)” Operation 80 // overload = thdllDArray& operator=(thdllDArray &obj) { for( int i=0; i Savantbit_vectorType; class work_Dand2_Dbehav_of_work_Dand2_classO : public BasicObject { public: // input signals SavantbitType in_work_Dand2_0a; SavantbitType in_work_Dand2_0b; // output signals SavantbitType out_work_Dand2_0y; // signals used to handle wait for statement only SavantbitType in_wait_for_signal; SavantbitType out_wait_for_signal; // local vairables - states SavantbitType gatework_Dand2_Dbehav_0n; public: work_Dand2_Dbehav_of_work_Dand2_classO() : BasicObject() 89 ‘ n. It. fl. . . .n.’ 90 // register input signals registerInSignal(&in_work_Dand2_0a,sizeof(in_work_Dand2_0a)); registerInSignal(&in_work_Dand2_Db,sizeof(in_work_Dand2_0b)); // register output signals registerDutSignal(&out_work_Dand2_0y,sizeof(out_work_Dand2_0y)); // register the wait for signals registerInSignal(&in_wait_for_signa1,sizeof(in_wait_for_signa1)); .register0utSigna1(&out_wait_for_signal,sizeof(out_wait_for-signa1)); // register states registerState(agatework_Dand2_Dbehav_0n, \ sizeof(gatework_Dand2_Dbehav_Dn)); // input signal initial values in_work_Dand2_0a = X; in_work_Dand2_0b = x; // output signal initial values out_work_Dand2_0y = Y; // wait for singal initial values in_wait_for_signal = 0; out_wait_for_signa1 = 0; // state initial values gatework_Dand2_Dbehav_Dn = 0; } // end of constructor void executeProcess() { BLDCKO: static int P=0; // resume to the last wait statement switch(P) { case 0 : goto BLDCKO; case 1 : goto BLDCK1; } // line 11 "and.tex" out_work_Dand2_0y = gatework_Dand2_Dbehav_0n; assignDelay(tout-work_Dand2_0y,DELTA,TRANSPORT); 91 // line 12 "and.tex" P++; BLOCKl: if( !hasEvent(&1n_work_Dand2_0a) && lhasEvent(ain_work_Dand2_0b) ) return; // line 13 "and.tex" gatework_Dand2_Dbehav_On = (in_work_Dand2_0a & in-work_Dand2_0b); // reset P value then return, or resume from beginning P = 0; }; #endif Appendix D SavantGlobals.h #ifndef SAVANT_GLDBALS_HH #define SAVANT_GLOBALS_HH #define X -1 #define Y -1 #define DELTA 1 #define NS *100 #define US #100000 #define MS *100000000 #define TRANSPORT 0 #define INERTIAL 1 #include "thdlArray.h" #endif Appendix E IIRthdLWaitStatement.hh #ifndef IIRPVHDL_WAITSTATEMENT_HH #define IIRPVHDL-WAITSTATEMENT_HH #include "IIRScram_HaitStatement.hh" class IIRthdl_NaitStatement : public IIRScram_UaitStatement { public: void _publish_cc(); private: void _publish_cc_wait_on(); protected: IIRthd1_WaitStatement(){}; “IIRthdl_HaitStatement(){}; }; #endif 93 Appendix F IIRthdLWaitStatement.cc #include "IIRthdl_WaitStatement.hh" #include "IIR_Designator.hh" #include "IIR_Declaration.hh" #include "IIR_DesignatorExplicit.hh" void IIRthdl-UaitStatement::_publish_cc(){ IIR_Designator *desig; IIR *cond_c1ause = get_condition_clause(); IIR *time_c1ause = get_timeout_clause(); _cc_out << "\t" << "P++;\n"; -Cc_out << "BLOCK" << wait_id +1 << ";\n"; if(time-clause != NULL){ _cc_out << "\t" << "out_wait_for_signal = ! in_wait_for_signa1;\n"; _cc_out << "\t" << "assignDelay(acut_wait_for_signal,"; time_clause->_publish_cc(); _cc_out << ",TRANSPDRT);\n" << endl; } desig = sensitivity_list.first(); if(desig != NULL) -publish_cc_wait_on(); else if(cond_clause != NULL) { _cc_out << "\t" << "if(!("; cond_c1ause->_publish_cc(); _cc_out << ")"; if(time_c1ause != NULL) { _cc_out << " && !hasEvent(ain_wait_for_signal)"; } -cc_out << ") return;\n\n"; 94 95 } else if(time_clause != NULL) { _cc_out << "\t" << "if(!hasEvent(&in_wait_for_signal)) return;\n\n"; } else { _cc_out << "\t" << "return;\n\n"; void IIRthd1_HaitStatement::_pub1ish_cc_wait_on(){ IIR_Designator *desig; IIR-Dec1aration *sens_sig; IIR *cond_c1ause = get_condition_clause(); IIR *time_clause - get_timeout_clause(); desig = sensitivity_list first(); -CC_out << "\t" << "if( u; while(desig != NULL) { ASSERdeesig->get_kind()==IIR_DESIGNATOR_EXPLICIT)3 sens_sig = (IIR-Dec1aration *) \ ((IIR_DesignatorExplicit *)desig)->get_name(); if(sens_sig->_is_array_type()){ -cc_out << "l"; sens_sig->-publish_cc(); _cc_out << ".arrayHasEvent() "; } else { -cc_out << "!hasEvent(&"; sens_sig->_publish-cc(); _cc_out << ") "; } // move to the next desig = sensitivity_list.successor(desig); if(desig !=NULL) { _cc_out << "&&" << "\n" << "\t" <( n u; } } // while if(time_clause != NULL){ _cc_out << u&&u << "\nu << "\t" << n n; _cc_out << "!hasEvent(ain_wait_for_signal)"; } 96 _cc_out << ") return;\n"; if( cond_c1ause != NULL) { _cc_out << "\t" << "else if(!("; cond_c1ause->_publish_cc(); _cc_out << ")"; if(time_clause != NULL) { _cc_out << " && !hasEvent(ain_wait_for_signal)" } _cc_out << ") return;\n"; } _cc_out << "\n"; Appendix G thdlArray.h #ifndef PVHDL_ARRAY_H #define PVHDL_ARRAY_H #include #include #include "BasicObject.h" template class thd11DArray { public: int size; Dtype *array; BasicObject *owner; // constructor thdl1DArray(){ size = 0; array = NULL; owner = NULL; } // distructor "thdlIDArray(){ if (array != NULL) delete [] array; } // allocate array void allocateArray(int s){ if(s<=0) return; size = s; array = new Dtype [s]; } 97 98 // set the owner BasicObject of this array object void setBasicDbject(BasicObject *b){ owner = b; } // register array as input signal void registerInSignalArray(){ for(int i=0;iregisterInSignal(aarrayEiJ,sizeof(array[i])); } } // register array as output signals void registerDutSignalArray(){ for(int i=0;iregister0utSignal(&array[i],sizeof(array[i])); } } // register array as states void registerStateArray(){ for(int i=0;iregisterState(tarrayfil,sizeof(array[i])); } } // test if array values have changed int arrayHasEvent(){ for(int i=0;ihasEvent(&array[i])) return 1; } return 0; } // copy array value from obj with delays void assignArray(thdllDArray aobj, int delay, int delay-type){ for(int i=0;iassignDe1ay(tarray[i],delay,delay_type); } } // overload == 99 int operator == (thdllDArray &obj) { for(int i=0;i &obj) { if (*this == obj) return 0; else return 1; } 1 1 // overload == (int) '! int operator == (int val) { for(int i=0;i& operator=(thdllDArray tobj) { for( int i=0; i& operator=(int value) { for( int i=0; i& operator+(thdl1DArray tobj) { thdlIDArray *temp = new thdllDArray; temp->allocateArray(obj.size); 100 for(int i=0; iarray[i] = array[i]+obj.array[i]; return *temp; } // overload - thdlIDArray& Operator-(thdl1DArray &obj) { thdl1DArray *temp = new thdliDArray; temp->allocateArray(obj.size); for(int i=0; iarrayfi] = arrayfi]-obj.array[i]; return *temp; } // overload * thdlIDArray& operator*(thd11DArray aobj) { thdllDArray *temp = new thdllDArray; temp->allocateArray(obj.size); for(int i=0; iarrayfi] = array[i]*obj.array[i]; return *temp; } // overload / , thdllDArray& operator/(thd11DArray aobj) { thdl1DArray *temp = new thdllDArray; temp->allocateArray(obj.size); for(int i=0; iarray[i] = arrayfi]/obj.array[i]; return *temp; } // overload & thd11DArray& operatort(thdllDArray aobj) { thdl1DArray *temp = new thdliDArray; temp->allocateArray(obj.size); for(int i=0; iarrayfi] = 1; else temp->array[i] = 0; } 101 return *temp; } // overload I thdllDArray& operatorl(thdllDArray aobj) { thdllDArray *temp = new thdllDArray; temp->allocateArray(obj.size); for(int i=0; iarrayfi] = 1; else temp->arrayfi] = 0; } return *temp; } // overload “ thdllDArray& operator“(thdlIDArray aobj) { thdlIDArray *temp = new thdllDArray; temp->allocateArray(obj.size); for(int i=0; iarray[i] = 1; else temp->arrayfi] = 0; } return *temp; } // overload " thdllDArray& operator"() { thdllDArray *temp = new thdllDArray; temp->allocateArray(size); for(int i=0; iarrayfi] = 1; else temp->array[i] = 0; } return'*temp; } }; // class thd11DArray #endif Bibliography [1] David Perllerin and Douglas Taylor, “VHDL Made Easy”, Printice Hall, Upper Saddle River, 1997. - i [2] Peter J. Ashenden, “The Designer’ Guide to VHDL”, Morgan Kaufmann, San Francisco, 1996. [3] James P. Cohoon and Jack W. Davidson, ”C++ Program Design - An Intro- duction to Programming and Object-Oriented Design”, Times Mirror Higher Education Group, 1997. [4] Moon J. Chung, Department of Computer Science, Michigan State University. Parallel VHDL Performance Simulation Cost and Schedule Report. [Online] Available http://chung-resl.cps.msu.edu/pvhdl/sep.htm, Oct. 13, 1997 [5] Dept. of ECECS, University of Cincinnati.SAVANT: An Extensible Intermediate for VHDL. [Online] Available http://www.ececs.uc.edu/ paw / savant / index.html, July 11, 1998. 102 103 [6] Department of ECECS, University of Cincinnati. TyVIS: A VHDL Simula- tion Kernel. [Online] Available http://www.ececs.uc.edu/ paw/tyvis/index.html, May 25, 1998. [7] Department of ECECS, University of Cincinnati. AIRE Home Page - Ad- vanced Intermediate Representation with Extensibility (AIRE). [Online] Avail- able http://www.ececs.uc.edu/ paw/aire/Index.html. L [8] Dept. of ECECS, University of Cincinnati. SAVANT Programmer’s Manual. [Online] Available http://www.ececs.uc.edu/ paw/savant/doc/programers.html, [ Aug. 25, 1997 [9] Khashayar Rohanimanesh, “Generating Map File by SAVANT”, Technical Doc- ument of Parallel VHDL Simulation Project, Department of Computer Science, Michigan State University, July, 1998. [10] Jinsheng Xu, Department of Computer Science, Michigan State University. An Object Oriented Model for Developing Event-Driven Systems. [Online] Available ftp: / /chung—resl.cps.msu.edu/pvhdl/paper/OOMODEL.doc, April, 1998. [11] Jinsheng Xu, Department of Computer Science, Michigan State University, Parallel VHDL Simulation Result Report. [Online] Available ftp://chung- resl.cps.msu.edu/o2k_sp1.xls, March, 1997. [12] Department of ECECS, University of Cincinnati. IIRScram Layer Source Code. [Online] Available telnet: / / chung-pvhdl.cps.msu.edu, /home/savant/Savant/src/aire/iir/IIRScram, June, 1998. 104 [13] Mai Yang, Department of Computer Science, Michignan State University. IIR- thdl Layer Source Code. [Online] Available telnet://chung-pvhdl.cps.msu.edu, /home/savant./Savant/src/aire/iir/IIRthdl, July, 1998. MICHIGAN STATE UNIV. LIBRARIES 1|11111111111111111111111111111111111111111111111111111| 31293016880522