|   JHDL Home Page   |   Configurable Computing Lab   |   User's Manual (TOC)   | Search

XMAC

Table of Contents

Introduction
Mini XML Tutorial
Using XMAC

XMAC as a template generator
Extending XMAC

Introduction

So, just what is XMAC? Simply put, XMAC is a flexible system for creating Java code from an XML template file. It was designed as an aid to make the creation of JHDL library primitives as simple as possible. As such, this document will focus mainly on library primitives and how they are created using the XMAC system. It is worth noting that XMAC was designed to be flexible and open, so its use is not stricly limited to library primitives. There will be a brief discussion of these other uses later in the document.

Essentially the XMAC "language" consists of a bunch of xml tags that define the java code to be created. The XMAC system is also flexible enough to be extended to parse user defined tags if the need should arise.

XMAC also uses a very powerful feature of XML parsers, that is the ability to validate xml against a rigid set of rules. These rules are contained in a schema file called xmac.xsd.

Another program associated with the XMAC package is boolgen. Boolgen will be mentioned briefly later on because it exists, but it's not something that most people need ever worry about.

This document is intended as an introduction to XMAC and how it applies to the JHDL primitives. A prior knowledge of basic xml is helpful, though not completely necessary. Those familiar with html will find xml very intuitive (though xml is much better!).

Tutorial

Mini XML Tutorial First off, just enough XML to get started. XML stands for eXtensible Markup Language. It is very flexible and used often to describe data, which is why it was chosen for this project. XML, unlike HTML is very structured and must conform to certain standards. Unlike HTML, XML must have a closing tag for every opening tag. Also, XML requires that tags be nested neatly. No overlapping tags are allowed. For example:

<tag1>
<tag2>
</tag2>
</tag1>

Is legal XML code, while

<tag1>
<tag2>
</tag1>
</tag2>

is not. XML Must be nested or the XML parser will generate an error. An XML document is said to be well formed if each opening tag has a closing tag and if all the tags are nested properly. XML is valid if it conforms to specific requirements based on the application.

Some tags will have attributes associated with them and are of the form: <tag1 attribute="something">

Another nice feature of XML is the ability to create self closing tags. If for example a tag has no data associated with it, but must be in place, you can use either one of two forms: <tag1 attribute="something"></tag1> or <tag1 attribute="something"/> Either is valid, the last one is of course easier to use.

Each and every single XML document must have a line at the top that declares what type of document this is and the encoding. There are many variations but the most simple is:

<?xml version="1.0"?>

Don't forget the include that as the first line in every single XML document.

Another thing to keep in mind is that the input xmac file will be completely parsed by the XML parser. This means that any special characters will be interpreted by the parser. Some of these characters are: &, <, >, and depending on context the " char. These characters are used by the parser and so special care must be taken to ensure you get the desired results. For example, the < char opens a new tag. If you wrote some java code that did a comparison such as if (a < b).... The xml parser would die because it couldn't figure out what you were doing. To get around this rewrite it as if (a &lt; b).... The xml parser will turn the &lt; into a < symbol for you. Here are the most common codes (note the trailing semicolon is important):

That should be enough XML to make the rest of this document easier....now on with the show....

Using XMAC

System Requirements
So far XMAC has been tested on the Linux platform, though any machine that has Java 2 should run XMAC just fine.

At the core of XMAC is the Xerces XML parsing engine. Xerces is distributed by the Apache Software Foundation and can be obtained from their web site. PLEASE NOTE XMAC uses a Schema to validate the input files. As of this writing the only version of Xerces to support schema's is 1.4.3. You must use Xerces 1.4.3 for XMAC to work. After downloading Xerces place it in your classpath and XMAC will find what it needs.

Invoking XMAC

All of the XMAC files are located in the package byucc.jhdl.util.xmac. The system is however designed to be run using a wrapper class located in the byucc/jhdl/helpers directory. Note that this class does not have a package associated with it, so during a normal compilation the class files will fall out to the head of the jhdl tree. If you are running XMAC from a jhdl jar file then as long as the jar is in your classpath all that is needed to run XMAC is:

java xmac basedir [options]

Where the basedir is the base directory to store the resulting java files in. The final directory the files are placed in is a function of the package tag, which will be discussed later. If you are creating files for the jhdl tree then this needs to be the base (or head if you prefer) of the tree.

Options

-s directoryname        The directory to start scanning for .xmac files. The default is the current directory.

-q                                               Quiet mode.  This suppresses all output messages.
 

A Simple Example

The following is a simple example illustrating a buffer cell.

<?xml version="1.0"?>
<xmac>
  <package>byucc.jhdl.Xilinx.XC4000</package>
  <package>byucc.jhdl.Xilinx.Virtex</package>
  <package>byucc.jhdl.Xilinx.Virtex2</package>

  <javadoc>
    This class implements a basic buffer.
  </javadoc>

  <class name="buf" extends="XilinxCL" implements="UnmappableCell, Buf">
    <interface>
      <in name="i" width="1"/>
      <out name="o" width="1"/>
    </interface>

    <sharecell/>

    <propagate>
      <put refid="o"><get refid="i"/></put>
    </propagate>

    <constructor/>

    <schematic>BUF</schematic>

    <test>
      0, 0
      0, 0
      1, 1
      1, 1
    </test>
  </class>
</xmac>

Each of the tags will be discussed in detail below, but briefly here's what is going on. The first thing to note is the line <?xml version="1.0"?>. This is required in every xml document and MUST be the very first thing in the document. If there is even so much as a space before this line the xml parser will complain and die.

The next requirement is that the document root tag must be <xmac> or an error will be generated.

Under the <xmac> tag is where everything else belongs. Note there are three <package> tags. These instruct XMAC to create three files, place them in the correct package directory, and give each one an appropriate header - usually a bunch of import statements. The header is configured in the config.xml document. The format is pretty straight forward and is well documented in that file. For example the Virtex header is:

package byucc.jhdl.Xilinx.Virtex;
import byucc.jhdl.base.*;
import byucc.jhdl.Xilinx.*;
import byucc.jhdl.Logic.Logic;
import byucc.jhdl.Logic.LogicGates;
import byucc.jhdl.Logic.LibrarySelfTester;
import byucc.jhdl.Logic.TestException;
import byucc.jhdl.Logic.WideBooleanFunction;
import byucc.jhdl.Xilinx.Virtex.*;
import byucc.jhdl.apps.Viewers.Schematic.PreDefinedSchematic;

The <javadoc> tag will neatly format its contents and place it in the output file as javadoc style comments.

The <class> tag is one of the most important tags in the whole xmac document. If this is not present then XMAC will die. The output file gets its name from this tag. Also, it's easy to see where the class declaration comes from by looking at the attributes in the tag.

The rest of the tags define the ports this cell will have, and the behavior of the cell. This simple example will take the input and pass it to the output - thus this models a buffer.

XMAC Syntax and Tags

XMAC is a system for creating Java files from xml. As such, XMAC defines a basic set of xml tags that create certain resulting output and behaviors of the parser. The following is a list of all tags and the scope for which they are valid. Some of these tags have attributes which will be enumerated later.

TAG Required Scope Description
<xmac> Yes Root Tag XML requires that there be one and only one root tag. This seemed like a logical choice. :)
<package> No <xmac> This defines the package that the resulting java file will be created for. Example: <package>byucc.jhdl.Xilinx.Virtex</package> Note that more than one package tag may be present in any given xmac file.
<javadoc> No <xmac> Text blocks within this tag will be formatted and output to the file in javadoc format.
<class> Yes <xmac> This tag sets several things: First it outlines the body of the class, second it sets a class name with a name attribute, third it sets other important parameters with other attributes.
<interface> No* <class> Defines the wires and port info needed by this cell. This is primarily useful for JHDL, but may prove useful for other applications.
<sharecell> No <class> Results in cellInterfaceDeterminesUniqueNetlistStructure() method.
<clock> No <class> Model synchronous behavior.
<propagate> No <class> The asynchronous behavior model.
<reset> No <class> The behavior at reset time.
<constructor> No <class> Build the default constructor set.
<wire> No any Create a new wire object.
<schematic> No <class> Defines which schematic symbol to use.
<test> No <class> Defines a series of test vectors for the cell.
<code> No any Allows java code to be inserted directly into the xmac file.
<put> No any Put a value on a wire or port.
<get> No any Retrieve a value from a wire or port.
<not> No any Usually used in conjunction with a get, this inverts the signal.
* Functionality may be reduced as other tags get a lot of information from this tag
Tag Descriptions
<xmac>
Attributes: Description:
This tag must be the root tag of the xmac document. All other tags go under this one.

<package>
Attributes

Scope
Under xmac tag only.

Description
The package this file will be created for. Note, more than one package tag may exist. If more than one exists then a copy of the file will be created for each package and tossed to the appropriate directory. If no package tag is present then the file will be placed in the current directory.

Example
<package>byucc.jhdl.Xilinx.Virtex</package>

When XMAC is invoked it requires a head directory to place the output files. In the example the output file would be placed in the directory byucc/jhdl/Xilinx/Virtex relative to this head directory.
 

<javadoc>
Attributes

Scope
Under xmac tag only.

Description
The text under this tag will be neatly formatted and output to the resulting java file in javadoc format.

Example
<javadoc>
  The buf cell performs simple buffering.
</javadoc>

Will result in:
/**
 * The buf cell performs simple buffering.
 */

Which is neatly formatted for javadoc.

<class>
Attributes

Scope
Under xmac tag only.

Description
The contents between the opening and closing class tags constitute the bulk of the xmac file. This is where most other tags live and the real work is done.

Example
<class name="buf" extends="Logic" implements="UnmappableCell" returncellname="buffer">
...
</class>
Most of the info will be obvious to Java programmers, the one attribute above that is worth mentioning is the returncellname attribute. Normally this cell would return the name "buf" to the netlister. However, this attribute will override that default and return "buffer" instead. If its not desireable to have a name returned at all, then the attribute suppresscellname can be set to true.

<interface>
Attributes

Scope
Within class tag only.

Description
This tag describes the interface block for the cell. There are several subtags associated with this tag: in, out, inout, clk, sout, saout, sin, sain, ain, aout, implicit, and generic.  All tags except generic have the same attributes: name and width.  The generic tag has: name and value.  Note that for the width either a number or the word GENERIC is acceptable.

Example 1
<interface>
  <in name="i" width="1"/>
  <out name="o" width="1"/>
</interface>

Example 2
<interface>
  <implicit name="clk" width="1"/>
  <ain name="i" width="GENERIC"/>
  <out name="o" width="GENERIC"/>
  <generic name="INIT" value="1234"/>
</interface>
 

<sharecell>
Attributes

Scope
Within class tag only.

Description
This tag results in the code cellInterfaceDeterminesUniqueNetlistStructure(). There is no other data associated with this tag.

Example
<sharecell/>
 

<clock>

Attributes

Scope
Within class tag only.

Description
The body of this tag defines the synchronous behavior of the cell.
 

<propagate>

Attributes

Scope
Within class tag only.

Description
The body of this tag defines the asynchronous behavior of the cell.

Example
A simple buffer can be defined as:
<put refid="o"><get refid="i"/></put>
 

<reset>
Attributes

Scope
Within class tag only.

Description
The body of this method defines the reset behavior.

Example
<put refid="o">0</put> - Set the port "o" to zero on reset.
 

<constructor>
Attributes

Scope
Within class tag only.

Description
This tag does two things: first it creates a default set of constructors, and second it makes each of those constructors run any code that you place within the constructor tags.

The default constructors include wires only, wires with an instance name, wire pairs, etc. The can all be defined in the configuration document. Also, multiple constructor sets can be defined, if the need should arise. See the documentation on the configuration for more information.

Any code placed between the tags will in turn be placed in the init() method of the output.

Example
<constructor/> -  Produces the default set of constructors.

<constructor>
  (code)
</constructor>

Will creates the default constructor set and dumps the code into the init method which is called by each constructor.

<constructor name="set2"/> - Create the constructor set called set2 as defined in the configuration.

<wire>
Attributes

Scope
Anywhere

Description
Create a new wire object in the cell. There is one main advantage of using the tag, rather than just straight java code - the XML parser will know about this tag while it would not otherwise. This is useful info for many of the tags, particularly the get and put tags. They use this to figure out how wide a wire is and adjust themselves accordingly.

Example
<wire name="w" width="4"/>

<schematic>
Attributes

Scope
Within class tag only.

Description
Define the schematic symbol to use in the simulator. For a list of currently supported schematic types see the documentation on byucc.jhdl.apps.Viewers.Schematic.PreDefinedSchematic.

Example
<schematic>BUF</schematic>

<test>
Attributes

Scope
Within class tag only.

Description
Define a set of test vectors. Note that any implicit ports are not included in this list.

Example
Suppose the cell in question is a generic width buffer with one input and one output. The test vectors could be:

<test width="1">
  0, 0
  0, 0
  1, 1
  1, 1
</test>
<test width="16">
  0x0000, 0x0000
  0x0000, 0x0000
  0xabcd, 0xabcd
  0xabcd, 0xabcd
  0x1234, 0x1234
  0x1234, 0x1234
</test>
<test width="64">
  0x0123456789abcdefL, 0x0123456789abcdefL
  ...
</test>
<test width="128">
  0.0.0.0, 0.0.0.0
  0.0.0.0, 0.0.0.0
  0xdeadbeef.0xdeadbeef.0x12345678.0xabcdef00, 0xdeadbeef.0xdeadbeef.0x12345678.0xabcdef00
  ...
</test>

Notice how the 128-bit wide vector is broken up. Also, note that 64-bit wide vectors have the trailing "l" to make them longs.

<code>
Attributes

Scope
Any

Description
No "floating text" is allowed in the document. What this means is that everything must be enclosed in tags. If tags alone are not sufficient to meet the needs of the cell, then java code may be placed directly in the xmac file. The code must be placed between the <code>...</code> tags. Also note that any tags present within this tag will still be parsed, and example will follow.

Example
<code>
  if (<get refid="i"/> == 0) {
    <put refid="o">1</put>
  }
  else {
    <put refid="o"><get refid="i"/></put>
  }
</code>
 

<put>
Attributes

Scope
Any

Description
This tag will put a value on a wire or port. In JHDL there are three main put methods: put, putL, and putA. Which one to use depends on the width of the wire. If the put tag knows about a wire either through the port interface or a wire tag then it will automagically configure the resulting put in the java output to the right method. If the wire is a generic width then put will also build an if...else... clause and let the cell figure out how wide it is.

Example
<put refid="o">0</put>

<get>
Attributes

Scope
Any

Description
This tag will get a value from a wire or port. Often this is used in conjunction with a put tag, but may be used alone.

Example
<put refid="o"><get refid="i"/></put>

See the code tag documentation for another example.

<not>
Attributes

Scope
Surrounding a get tag.

Description
This will invert a wire. This is usually used to surround a get tag.

Example
<put refid="o"><not><get refid="i"/></not></put>

XMAC as a template generator

As mentioned XMAC has many potential uses. One such use is to generate "templates.". Suppose there is a need to create a bunch of JHDL circuits, all with the same port interface. This is easily handled by creating a simple .xmac file and letting XMAC do the rest.
For example:

<xmac>
  <class name="file1,file2,file3" extends="Logic">
    <interface>
      <in name="i" width="1"/>
      <out name="o" width="1"/>
    </interface>
  </class>
</xmac>

That file would then create three files: file1.java, file2.java, and file3.java - each with the port interface already set up. If default empty constructors need to be created add the <constructor/> tag.

Extending XMAC

Programming for XMAC
The XMAC programming API is designed to be fairly easy to use. This allows new tags to be added with relative ease. This document will attempt to describe briefly how to add new features or tags to XMAC. Specific API functions will be discussed as needed, however, the JHDL API documentation for XMAC should be consulted for all the methods and call available.

For the most part the XMAC classes are separated by functionality. The naming convention is TagnameParser. For example, the <test> tag is parsed by TestParser, the <class> tag is parsed by ClassParser, etc. The most important classes are: XMAC, XMACParser, ClassParser, and DocInfo. Becuase all of the classes need certain information the class DocInfo contains all the important information about the current job. This object is passed back and forth between the parser classes so they know what they are doing. The top level class is XMAC. XMAC is normally called by the wrapper class xmac which is in the byucc/jhdl/helpers directory. This class contains the outer loop and takes care of creating the DOM document and the DocInfo object. From there control is passed to XMACParser which will process the tags under the <xmac> tag. Control is passed in turn to the classes that parse each of the tags.

Each of the Parser classes extend the TagParser class, which provides some common functionality between all the parsers.

It's probably best to illustrate with an example....

Adding Tags to XMAC

In theory adding a new tag to XMAC is very easy. Most of the classes are already set up to use new parser object that a user programs. The way it does this is to stuff a hashtable with tagnames and the objects that parse them. So, all you need to do is extend TagParser, override the parse() method, stuff the HashTable with your new object, modify the schema file and go.

Most of the tag parsers conform to this and will work just fine. Some parsers however need to call a tag by name. Where this happens they usually also handle tags that it doesn't explicitly know the name. A good example is in order here. Let's say we want to add a <foobar> tag. This is the code that would add that tag:

package byucc.jhdl.util.xmac;

// Exception handling
import java.io.IOException;

// DOM Interface
import org.w3c.dom.Node;
import org.w3c.dom.Element;

/**
 * Process the foobar tag
 */
public class FoobarParser extends TagParser {
  private Node docRoot; // The "root" of this part of the DOM tree
  private Element docElm; // The Element version of the same root
  private WireInfo wireInfo;

  /**
   * The default constructor for this class.
   * @param docInfo   The <code>DocInfo</code> object that contains the
   * current settings and parameters.
   */
  public FoobarParser(DocInfo docInfo) throws Exception {
    super (docInfo);
    wireInfo = new WireInfo(docInfo.getDOMDoc().getElementsByTagName("xmac").item(0));
  }

  /**
   * This is the actual method that does the parsing of the tag.
   * @param docRoot   The <code>Node</code> of the foobar tag.
   */
  public void parse(Node docRoot) throws Exception {
    this.docRoot = docRoot;
    docElm = (Element) docRoot;

    // Did they for some reason pass us a node with the wrong name?
    if (!docElm.getTagName().equals("foobar"))
      throw new Exception("FoobarParser was passed a wrong node!\n");

    // Check out parent and make sure we have the right heritage.
    if (!checkParent(docRoot, "xmac"))
      throw new Exception("<foobar> must be a child of <xmac>!");

    StringBuffer str = new StringBuffer();

    str.append(indentLine("for (int i = 0; i < 10; i++) {\n"));
    increaseIndent();
    str.append(indentLine("System.out.println(\"Hello World!\");\n"));
    decreaseIndent();
    str.append(indentLine("}\n"));

    // Dump this to the output file
    writeOutput(str.toString());
  }
}

That would create an output file with the following contents:

for (int i = 0; i < 10; i++) {
  System.out.println("Hello World!");
}

A few methods to make note of: writeOutput(), indentLine(), increaseIndent(), decreaseIndent(), and checkParent(). These are some of the methods inherited from the TagParser class. See the API documentation for the complete list of methods. Briefly though the methods are as follows:

writeOutput() takes a String and dumps it to the output file stream.
indentLine() takes a String, and then returns a String which has spaces at the beginning of the line, thus indenting the line. The number of spaces on the front is dependent on two variables. One is set in the config file, which is how many spaces per indent level, and the other is the current indent level.
increaseIndent() increases the current indent level. See the code above for a good example on where to use this method. decreaseIndent() decreases the current indent level. See above code for example. Note: always remember to match an increaseIndent() and decreaseIndent() or subsequent .xmac files will be really messed up!!!!!!

To be continued...Obviously there is a ton more to cover, which I will add as time permits...
 

Modifying the Schema

First, what is a schema? Essentially it is a set of gramatical rules that the xml parser uses while it is parsing. In the XMAC schema each tag is declared and its data structure is set. Anything not conforming to this defined structure will generate an exception. It might be argued that this takes some of the flexibility out of XMAC because now a strict set of rules must be adhered to. To a degree this is true, however, try contrasting BASIC and Java code. One is a mess and has no structure, the other is very structured and easy to read. XMAC with a schema is much the same way - it must conform to certain rules or it dies.

Let's illustrate with an example. Below is the code in the schema which defines the class tag.
<xsd:element name="class">
  <xsd:complexType>
    <xsd:sequence>
      <xsd:element ref="code" minOccurs="0" maxOccurs="1"/>
      <xsd:element ref="interface" minOccurs="0" maxOccurs="1"/>
      <xsd:sequence minOccurs="0" maxOccurs="unbounded">
        <xsd:choice minOccurs="0" maxOccurs="1">
          <xsd:element ref="constructor" maxOccurs="1"/>
          <xsd:element ref="code" maxOccurs="unbounded"/>
          <xsd:element ref="clock" maxOccurs="1"/>
          <xsd:element ref="propagate" maxOccurs="1"/>
          <xsd:element ref="reset" maxOccurs="1"/>
          <xsd:element ref="schematic" maxOccurs="1"/>
          <xsd:element ref="test" maxOccurs="unbounded"/>
          <xsd:element ref="sharecell" maxOccurs="1"/>
        </xsd:choice>
      </xsd:sequence>
    </xsd:sequence>
    <xsd:attribute name="name" use="required" type="xsd:string"/>
    <xsd:attribute name="extends" use="optional" type="xsd:string"/>
    <xsd:attribute name="implements" use="optional" type="xsd:string"/>
    <xsd:attribute name="returncellname" use="optional" type="xsd:string"/>
    <xsd:attribute name="suppresscellname" use="optional" type="xsd:string"/>
  </xsd:complexType>
</xsd:element>

In the example on extending XMAC we added a foobar tag. Suppose we want to use this tag under the class tag now. In the class tag declaration we'd add:

<xsd:element ref="foobar" maxOccurs="1"/>

Note that the above is only a reference to the tag foobar. Now we need to define the actual declaration. In this case it's simple:

<xsd:element name="foobar" type="xsd:string"/>

That should be good enough to get you started. The schema file xmac.xsd is documented well and should be easy to follow.

|   JHDL Home Page   |   Configurable Computing Lab   |   Prev (Behavioral Models)   |   Next (General Issues)   |


JHDL 0.3.45