Project

General

Profile

Actions

Getting Started

This is a step-by-step instruction for getting started with developing a VeriTrans backend and using it within the Verilog translator environment. The term backend refers to a component that traverses an abstract syntax tree (AST) of the Verilog description and processes it in some way (e.g., constructs the internal representation and/or converts the description into some other language). The document is illustrated by the example of VerilogPrinter (see the package ru.ispras.verilog.parser.sample).

Developing a Backend

Technically, a backend is a Java object that implements the VerilogBackend interface (the method start). Here is an example:

package ru.ispras.verilog.parser.sample;

import ru.ispras.verilog.parser.VerilogBackend;

import ru.ispras.verilog.parser.model.*;       // AST nodes (Module, Activity, etc.)
import ru.ispras.verilog.parser.model.basis.*; // Objects used in AST nodes (Expression, Range, etc.)
...

/**
 * This class illustrates development of a Verilog backend.
 */
public final class VerilogPrinter extends VerilogBackend
{
    /**
     * Processes the abstract syntax tree (AST).
     *
     * @param root the AST's root.
     */
    public void start(final VerilogNode root)
    {
        ...
    }
}

To ease development of a backend, one can use VerilogTreeWalker, a VeriTrans class that implements AST traversal. The VerilogTreeWalker's constructor takes two parameters: (1) a reference to the tree's root and (2) a visitor to be applied to the tree nodes:

...
import ru.ispras.verilog.parser.walker.*; // Walker and visitor (VerilogTreeWalker and VerilogNodeVisitor)

public void start(final VerilogNode root)
{
    // Create the AST traverser.
    VerilogTreeWalker walker = new VerilogTreeWalker(root, new VerilogNodePrinter());
    walker.start();
}

The most substantial part of backend development concerns creation of the AST nodes’ visitor, a subclass of the abstract class VerilogNodeVisitor. The visitor should implement two methods for each of the node types:

// Pre-visitor: it is invoked before the child nodes are visited.
public void on<NodeType>Begin (final <NodeType> node);

// Post-visitor: it is invoked after the child nodes are visited.
public void on<NodeType>End   (final <NodeType> node);

Supported node types include (see the package ru.ispras.verilog.parser.model):

Activity process (always or initial)
AssignBegin continuous assignment (assign)
AssignStatement assignment statement (=, <=, assign, deassign, force or release)
Assignment assignment
Attribute attribute
BlockGenerate generate block
BlockStatement block statement (begin or fork)
CaseGenerate generate case selection
CaseGenerateItem generate case item
CaseStatement case statement (case, casex or casez)
CaseStatementItem case statement item
Code source code
Declaration declaration (input, output, inout, event, parameter, specparam, localparam, defparam, genvar or variable)
DelayedStatement delayed statement
DisableStatement disable statement
Generate generate construct
IfGenerate conditional generate construct
IfGenerateBranch if generate branch (then or else)
IfStatement conditional statement
IfStatementBranch if statement branch (then or else)
Instantiation instantiation construct
LoopGenerate generate loop
LoopStatement loop statement (forever, repeat, while or for)
Module module declaration
NullStatement null statement
PathDeclaration path declaration
Port port declaration
PortConnection port connection
Procedure procedure declaration (function or task)
PulseStyle pulse style specification
ShowCancelled show-cancelled construct
Specify specify construct
Table UDP (user-defined primitive) table
TableEntry UDP table entry
TaskStatement task statement
TriggerStatement trigger statement
WaitStatement wait statement

A visitor example is given below.

package ru.ispras.verilog.parser.sample;

import ru.ispras.verilog.parser.model.*;
import ru.ispras.verilog.parser.model.basis.*;
import ru.ispras.verilog.parser.walker.*;
...

/**
 * This class illustrates development of a Verilog node visitor.
 */
public final class VerilogNodePrinter extends VerilogNodeVisitor
{
    @Override
    public void onActivityBegin(final Activity node)
    {
        indent();

        switch(node.getType())
        {
        case INITIAL:
            text("initial");
            break;
        case ALWAYS:
            text("always");
            break;
        }

        endl();
        begin();
    }

    @Override
    public void onActivityEnd(final Activity node)
    {
        end();
    }
    ...
}

Registering a Backend

A backend is registered by calling the add method of the VerilogTranslator object. An example is given below:

/**
 * Launches the Verilog translator with the Verilog printer as a backend.
 *
 * @param args the command line parameters.
 */
public static void main(String[] args)
{
    VerilogTranslator translator = new VerilogTranslator();
    translator.add(new VerilogPrinter());
    translator.start(args);
}

Updated by Alexander Kamkin over 6 years ago · 11 revisions