Getting Started » History » Revision 7
Revision 6 (Alexander Kamkin, 05/06/2014 08:43 AM) → Revision 7/11 (Alexander Kamkin, 05/06/2014 09:04 AM)
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.*; ... /** * 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.*; 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@) | * Activity | *AssignBegin* |<. continuous assignment (@assign@) | * AssignBegin | *AssignStatement* |<. assignment statement (@=@, @<=@, @assign@, @deassign@, @force@ or @release@) | * AssignStatement | *Assignment* |<. assignment | * Assignment | *Attribute* |<. attribute | * Attribute | *BlockGenerate* |<. generate block | * BlockGenerate | *BlockStatement* |<. block statement (@begin@ or @fork@) | * BlockStatement | *CaseGenerate* |<. generate case selection | * CaseGenerate | *CaseGenerateItem* |<. generate case item | * CaseGenerateItem | *CaseStatement* |<. case statement (@case@, @casex@ or @casez@) | * CaseStatement | *CaseStatementItem* |<. case statement item | * CaseStatementItem | *Code* |<. source code | * Code | *Declaration* |<. declaration (@input@, @output@, @inout@, @event@, @parameter@, @specparam@, @localparam@, @defparam@, @genvar@ or variable) | * Declaration | *DelayedStatement* |<. delayed statement | * DelayedStatement | *DisableStatement* |<. disable statement | * DisableStatement | *Generate* |<. generate construct | * Generate | *IfGenerate* |<. conditional generate construct | * IfGenerate | *IfGenerateBranch* |<. if generate branch (@then@ or @else@) | * IfGenerateBranch | *IfStatement* |<. conditional statement | * IfStatement | *IfStatementBranch* |<. if statement branch (@then@ or @else@) | * IfStatementBranch | *Instantiation* |<. instantiation construct | * Instantiation | *LoopGenerate* |<. generate loop | * LoopGenerate | *LoopStatement* |<. loop statement (@forever@, @repeat@, @while@ or @for@) | * LoopStatement | *Module* |<. module declaration | * Module | *NullStatement* |<. null statement | * NullStatement | *PathDeclaration* |<. path declaration | * PathDeclaration | *Port* |<. port declaration | * Port | *PortConnection* |<. port connection | * PortConnection | *Procedure* |<. procedure declaration (@function@ or @task@) | * Procedure | *PulseStyle* |<. pulse style specification | * PulseStyle | *ShowCancelled* |<. show-cancelled construct | * ShowCancelled | *Specify* |<. specify construct | * Specify | *Table* |<. UDP (user-defined primitive) table | * Table | *TableEntry* |<. UDP table entry | * TableEntry | *TaskStatement* |<. task statement | * TaskStatement | *TriggerStatement* |<. trigger statement | * TriggerStatement | *WaitStatement* |<. wait statement | * WaitStatement 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.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