XHWIF Porting Guide


The Xilinx Hardware Interface, or XHWIF is designed to provide a standard interface to FPGA-based hardware. XHWIF was designed for one reason: software portability. Software written for FPGA-based hardware, which uses the XHWIF, interface will run on any system, which implements this interface. Currently approximately a half dozen vendors support entire families of boards using XHWIF. This permits design tools such as JBits and debug tools such as BoardScope to run unmodified on new systems with a minimum of effort. Moving these tools or other similar applications to new hardware is also simplified. This interface is designed with portability in mind, but every effort has been made to provide a flexible and powerful abstraction to the underlying hardware.

Additionally, part of XHWIF is a remote access capability. Once a port is done to a particular hardware platform, the XHWIF Server is available with no additional porting effort required. This remote access capability permits hardware to be accessed using the XHWIF interface via any TCP/IP network. This permits all applications, which use the XHWIF standard to be run remotely across any TCP/IP network. Tools such as BoardScope can be run from any machine and access hardware on any other machine, which runs the XHWIF Server. Not only does this facilitate the sharing of hardware among multiple users, but it also permits embedded FPGAs to be remotely reconfigured under software control.

Finally, the XHWIF interface provides support for dynamic access of hardware interfaces. This means that new hardware can be supported by adding an XHWIF interface for that hardware, and existing applications will be able to use the new hardware without modification or recompilation. As an example, the BoardScope debug tool uses this capability to detect hardware platforms from command line flags. If a XHWIF interface called "MyBoard" is supplied, BoardScope will respond to a command line invocation of "BoardScope -MyBoard" and correctly find and connect to the new MyBoard hardware. This capability provides a unique support for future systems, not just existing ones.

Porting to XHWIF

Perhaps the most challenging aspect of porting to new hardware in the XHWIF environment is the use of the Java programming language. Java was designed to be a portable, secure, hardware-independent programming language. Unfortunately, this means that there is little support in the language for interfacing to other languages or to the underlying hardware. The current method used by Java to provide support for non-Java implementations is called the Native method.

The Java Native Method is simply a function defined in a Java program, which is tagged with the reserved keyword native. This means that no Java code will be supplied for this function. Instead, Java will search some user-supplied library for the code, which implements this "native" function. This approach is the technique used by Java to interface to other languages such as C, which in turn is used to interface to device drivers, custom hardware or other non-Java software.

This document is intended as a porting guide for the Xilinx XHWIF interface, and as such will not delve into the details of Java and native methods. If more information is desired on native methods, any Java language reference will provide you with a good starting point. In addition, the implementation of Java Native Methods has been somewhat varied and controversial. For a look at the various standards and a technique for supporting several of these standards simultaneously, have a look at Portable Native Methods in Java. This paper was originally published in Embedded Systems (Europe) in the May 1998 issue and provides a method for simultaneously supporting the different native method interface standards.

This porting guide will provide a short, example-driven walk through the process of supplying an XHWIF interface for some new piece of FPGA-based hardware. Only Sun's Java Native Interface (JNI) standard of interfacing XHWIF with the hardware is discussed here. Supplied with this documentation is a directory of files used to implement an XHWIF interface for a fictitious piece of hardware called "custom". But during porting the user can give any suitable name for their hardware. The files provided can be easily customized to define your hardware and can be easily modified. But its strongly suggested the porting process be completely understood before actually modifying the provided code for your hardware.

Also note that all examples in this document are implemented on a PC platform running Microsoft Windows NT. The software development tools used are from Sun Microsystem's Java Development Kit (JDK). This is available for download on the WWW at Sun web site. Finally, Microsoft's Visual C++ compiler was used to build the library for the native method, which in this case is a Dynamically Linked Library or DLL. Similar tools and techniques are used for other platforms.

Porting XHWIF involves the following steps:

  1. Creating a subclass of the com.xilinx.XHWIF package. This is a subclass describes the details of the new hardware platform. In the examples below, this class will be called "custom".
  2. Compile this interface, called custom.java into a custom.class file and place this class file in the "XHWIF/Boards/" directory.
  3. Produce the Java Native Method interface for the custom class by running Sun's javah
  4. Implement the Java Native Method interfaces in "C" and compile into a library / libraries.
  5. Place these libraries in an appropriate directory (typically one in the search path).

If all of these steps are done correctly, XHWIF applications such as BoardScope should run on your hardware.

The sections below will provide a step by step guide for producing the libraries necessary to get your hardware to support XHWIF. While there are many steps to the process, each step is fairly simple. In general, expect to spend approximately one day on an XHWIF port, providing that stable libraries and drivers to the hardware exist. In no case should porting to XHWIF take more than a few days. An engineer familiar and comfortable with native methods could conceivably provide an XHWIF port in just a few hours.

It is recommended that you read through this guide completely and be sure you have all the necessary hardware and software before you begin. If all else fails, limited support is available through the email address JBits@xilinx.com.

You may wish to read the sections below before you continue. If you are familiar with this process, feel free to go to the source code examples and which will illustrate the implementation details. The example code is heavily commented and easy to understand. It should be possible for a programmer experienced in implementing Java Native Methods to quickly modify them and produce a working interface.

Quickstart: All files necessary to build your custom XHWIF interface are found in the src/com/xilinx/XHWIF/Boards directory. The only files you must modify are custom.java and custom.c. Follow the comments in these files and you have everything necessary to produce the XHWIF interface and the supporting libraries for your hardware.

The Java XHWIF Interface

The XHWIF interface consists of two distinct pieces which require customization. The first is the board description code, which tells XHWIF which FPGA devices and packages are used by the hardware. The second piece is the native methods section. These are the functions which must be supplied by an external library. The bulk of this document, and most of the work in porting to XHWIF involves building libraries to implement and interface to these native methods. As stated before, only Sun's Java Native Interface standard of native method are discussed in this documentation. But techniques to easily support different standards of native methods have been followed, thus if needed, different standrads like Microsoft's RNI(Raw Native Interface), Sun JDK 1.0's Stubs interface can also be easily supported. For supporting these different standrad's follow the techniques suggested in the article Portable Native Methods in Java.

Detailed documentation of the base XHWIF class can be found in the on-line XHWIF documentation at com.xilinx.XHWIF.XHWIF. While this information is likely to more useful to programmers using XHWIF to write applications, it is recommended that engineers doing porting to XHWIF also study the details of this interface. Note that much of the interface is implemented and should not be modified. This is discussed in more detail in the sections below.

Board Description in XHWIF

XHWIF is a simple interface, and as such is interested only in basic information about the hardware. In general, the only information of interest is the type and number of FPGA devices on the board and their package types. Note that there is an implicitly assumed ordering here. The devices on the board are referenced internally by XHWIF in numerical order, starting with device 0. This numerical tag for each device is used throughout the interface to determine which device is being accessed.

The file custom.java should be used as the starting point for customizing XHWIF. You should copy and rename this file into something more descriptive of your system, being sure to keep the class and file name entirely in lower case letters. At the top of this file are few constants that you should edit and change to describe your hardware.

Once these constants are defined, you may compile this file to produce a java class file. Note that your compiler may require that other XHWIF classes be visible. See your compiler documentation if it complains about missing classes. Once you have produced this class file, it should be moved to the XHWIF/Boards directory.

The Native Methods in XHWIF

Once the board has been described and the XHWIF interface compiled into a class file, the Java Native Methods must be implemented. These native methods are the low-level and system dependent functions which provide access to the hardware. The following native methods must be implemented to provide full XHWIF support:

public native int customConnect();
public native int customDisconnect();
public native int customGetSystemInfo(int data[], int length);
public native int customReset();
public native int customSetClockFrequency(float frequency);
public native int customClockOn();
public native int customClockOff();
public native int customClockStep(int count);
public native int customGetConfiguration(int device, byte data[], int length);
public native int customSetConfiguration(int device, byte data[], int length);
public native int customGetRAM(int address, byte data[], int length);
public native int customSetRAM(int address, byte data[], int length);

Note that all of these functions must be implemented. They may, however, not actually do anything useful. Hardware without on-board memory, for instance, will have to supply a customGetRAM() and a customSetRAM() function, but these functions should simply return an error code. Most of the functions are fairly self-explanatory, but see the source code examples or the XHWIF on-line documentation for more details on the definition of these functions.

Building the "C" Libraries

Once the Java code in custom.java has been customized and compiled, the implementation of the Java Native Methods must be done. This means writing some "C" code to supply access to the hardware, either directly or through some device driver or API library. In most cases, the hardware will already have some high-level support for the functions required by the XHWIF Java Native Methods. All that is required is to make the appropriate calls from the hardware support libraries in the correct places. The details of supplying this code and building the libraries are discussed in the sections below.

The Java Software Development Kits

In order to implement native methods, software development kits from your Java vendor must be used. These software development kits contain tools to help produce "C" functions, which can be directly called by Java. In this example, we will implement ONLY one library for the Java Native Method interface format, the Sun Java 1.1 Java Native Interface (JNI).

If you aren't familiar with implementing Java Native Methods, now is probably a good time to look at either a book or some on-line documentation which discusses the subject. You may also want to look at the paper Portable Native Methods in Java. This paper was originally published in Embedded Systems (Europe) in the May 1998 issue and give a detailed run through of supporting the different native method interface standards.

Additionally, if you want to support this interface you will need the latest development kit from Sun. The software development kit used in the examples in this document are from Sun Java Development Kit (JDK) 1.2.

Producing "C" Function Prototypes

The software development kits are used to produce "C" header files, which describe the "C" functions, which are called by the Java Native Methods. Once these header files are produced, you must supply "C" code to implement these functions. The actual code to implement the hardware functionality will be placed in a single "C" file, which will have "generic" functions which will be referenced by the JNI. By this way, different formats of native method integration can be supported, if needed.

These files should now be copied into a project directory where they can be compiled to produce the libraries required by the Java Native Methods. You will notice that all of the functions produced by these tools and included in the Source directory have very long names and somewhat obscure parameters. The long names are a result of the package name used by Xilinx. The parameters are a result of the way Java interfaces to "C". Part of the design of XHWIF involved the specification of simple function interfaces with simple parameter lists. This eases the porting task. More complex interfacing is possible, but will not be discussed here. See any of the various Java documentation which discusses Native Methods for more information on the definitions of these interfaces.

Producing the Sun JNI Library

The Sun Java Native Interface (JNI) is an improvement over the original Sun JDK1.0's native method interface, and is used by nearly all Sun interpreters, as well as several non-Sun systems. Now that the custom.c interface has been built, it is a simple matter to produce the Sun JNI library. The following files are required by the Sun JNI build. They should all already exist in the src/com/xilinx/XHWIF/Boards/Boards directory. If you are using the name "custom" as your interface, all that has to be done is to compile and link these files.

custom.c: This file contains all of the functions which must be implemented to produce the "C" library. The file supplied in the src/com/xilinx/XHWIF/Boards/Boards directory contains an example with all of the functions more or less empty. It is recommended that you edit a copy of this file to produce your library. This file contains comments and pieces of code which should help you.

custom.h: The custom.h file is simply a small file containing the function prototypes for the custom.c file. This file mostly helps compilers find problems. While you could probably compile without it, it is highly recommended that you keep this file in your build.

customJNI.h: This is the header file automatically generated by javah utility from the Sun JDK. This file should also never be modified.

customJNI.c: This provides the bridge between the automatically generated interface and the more generic functions in custom.c This file can easily be produced by taking the function prototypes for customJNI.h. Note that there are some differences in the way parameters, particularly arrays are handled by JNI. These will have to be edited by hand.

Finishing Up and Testing

At this point, the library containing the native method has been built. In this example, the library is a Dynamically Linked Library (DLLs) for Microsoft Windows 95 and Windows NT. This file is named customJNI.dll. A compiled version of this library is shipped with the distribution, but they contain NO hardware dependent code. This permits applications like the BoardScope debug tool to come up completely, but run-time errors will quickly be noticed once operations such as configuration readback are attempted. This will, however, verify that the libraries are being loaded and all interfaces are working correctly.

The XHWIF class contains a main() routine which is used to provide basic verification of the XHWIF interface. Running XHWIF as an application exercises the interface with the board. XHWIF can be invoked from the command line as follows:

java com.xilinx.XHWIF.XHWIF -<board> <bitfile>

Here, <board> is the name of the Java class which provides the interface to the hardware. Note that this is a compiled Java class file, which must reside in the XHWIF/Boards/ directory. The <bitfile> is some bitstream file which can be downloaded to and readback from the hardware. And of course, the "java" in the command line is the Sun Java interpreter.

If applications cannot find, load or interface to the library you have built, the Java interpreter should produce error messages describing the problem. The most common problem is that the libraries are not someplace where they will be found by the interpreter, such as in the system "PATH".

2100 Logic Drive
San Jose, CA 95124-3450
Last updated: 8 Sep 2000