Getting Started » History » Revision 10
Revision 9 (Alexander Kamkin, 05/06/2014 10:29 AM) → Revision 10/11 (Alexander Kamkin, 05/06/2014 01:41 PM)
h1. Getting Started
This is a step-by-step instruction for getting started with developing a "VeriTrans":http://forge.ispras.ru/projects/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@).
h2. Developing a Backend
Technically, a backend is a Java object that implements the @VerilogBackend@ interface (the method @start@). Here is an example:
<pre><code class="java">
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)
{
...
}
}
</code></pre>
To ease development of a backend, one can use @VerilogTreeWalker@, a "VeriTrans":http://forge.ispras.ru/projects/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:
<pre><code class="java">
...
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();
}
</code></pre>
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><code class="java">
// 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);
</code></pre>
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.
<pre><code class="java">
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();
}
...
}
</code></pre>
h2. Registering a Backend
<pre><code class="java">
/**
* Launches the Verilog translator with the Verilog printer as a back-end.
*
* @param args the command line parameters.
*/
public static void main(String[] args)
{
VerilogTranslator translator = new VerilogTranslator();
translator.add(new VerilogPrinter());
translator.start(args);
}
</code></pre>