Getting Started » History » Version 11
Alexander Kamkin, 05/06/2014 02:04 PM
1 | 1 | Alexander Kamkin | h1. Getting Started |
---|---|---|---|
2 | |||
3 | 4 | Alexander Kamkin | 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@). |
4 | 3 | Alexander Kamkin | |
5 | 1 | Alexander Kamkin | h2. Developing a Backend |
6 | |||
7 | 3 | Alexander Kamkin | Technically, a backend is a Java object that implements the @VerilogBackend@ interface (the method @start@). Here is an example: |
8 | 1 | Alexander Kamkin | |
9 | 3 | Alexander Kamkin | <pre><code class="java"> |
10 | 5 | Alexander Kamkin | package ru.ispras.verilog.parser.sample; |
11 | |||
12 | 1 | Alexander Kamkin | import ru.ispras.verilog.parser.VerilogBackend; |
13 | 8 | Alexander Kamkin | |
14 | 9 | Alexander Kamkin | import ru.ispras.verilog.parser.model.*; // AST nodes (Module, Activity, etc.) |
15 | import ru.ispras.verilog.parser.model.basis.*; // Objects used in AST nodes (Expression, Range, etc.) |
||
16 | 3 | Alexander Kamkin | ... |
17 | 1 | Alexander Kamkin | |
18 | /** |
||
19 | 3 | Alexander Kamkin | * This class illustrates development of a Verilog backend. |
20 | 1 | Alexander Kamkin | */ |
21 | public final class VerilogPrinter extends VerilogBackend |
||
22 | { |
||
23 | /** |
||
24 | 3 | Alexander Kamkin | * Processes the abstract syntax tree (AST). |
25 | * |
||
26 | * @param root the AST''s root. |
||
27 | 1 | Alexander Kamkin | */ |
28 | public void start(final VerilogNode root) |
||
29 | { |
||
30 | 3 | Alexander Kamkin | ... |
31 | 1 | Alexander Kamkin | } |
32 | 3 | Alexander Kamkin | } |
33 | </code></pre> |
||
34 | |||
35 | 4 | Alexander Kamkin | 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: |
36 | 3 | Alexander Kamkin | |
37 | 1 | Alexander Kamkin | <pre><code class="java"> |
38 | ... |
||
39 | 9 | Alexander Kamkin | import ru.ispras.verilog.parser.walker.*; // Walker and visitor (VerilogTreeWalker and VerilogNodeVisitor) |
40 | 3 | Alexander Kamkin | |
41 | 1 | Alexander Kamkin | public void start(final VerilogNode root) |
42 | 3 | Alexander Kamkin | { |
43 | 4 | Alexander Kamkin | // Create the AST traverser. |
44 | 3 | Alexander Kamkin | VerilogTreeWalker walker = new VerilogTreeWalker(root, new VerilogNodePrinter()); |
45 | walker.start(); |
||
46 | 1 | Alexander Kamkin | } |
47 | </code></pre> |
||
48 | 4 | Alexander Kamkin | |
49 | 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: |
||
50 | |||
51 | <pre><code class="java"> |
||
52 | // Pre-visitor: it is invoked before the child nodes are visited. |
||
53 | public void on<NodeType>Begin (final <NodeType> node); |
||
54 | |||
55 | // Post-visitor: it is invoked after the child nodes are visited. |
||
56 | public void on<NodeType>End (final <NodeType> node); |
||
57 | </code></pre> |
||
58 | |||
59 | 6 | Alexander Kamkin | Supported node types include (see the package @ru.ispras.verilog.parser.model@): |
60 | 4 | Alexander Kamkin | |
61 | 7 | Alexander Kamkin | | *Activity* |<. process (@always@ or @initial@) | |
62 | | *AssignBegin* |<. continuous assignment (@assign@) | |
||
63 | | *AssignStatement* |<. assignment statement (@=@, @<=@, @assign@, @deassign@, @force@ or @release@) | |
||
64 | | *Assignment* |<. assignment | |
||
65 | | *Attribute* |<. attribute | |
||
66 | | *BlockGenerate* |<. generate block | |
||
67 | | *BlockStatement* |<. block statement (@begin@ or @fork@) | |
||
68 | | *CaseGenerate* |<. generate case selection | |
||
69 | | *CaseGenerateItem* |<. generate case item | |
||
70 | | *CaseStatement* |<. case statement (@case@, @casex@ or @casez@) | |
||
71 | | *CaseStatementItem* |<. case statement item | |
||
72 | | *Code* |<. source code | |
||
73 | | *Declaration* |<. declaration (@input@, @output@, @inout@, @event@, @parameter@, @specparam@, @localparam@, @defparam@, @genvar@ or variable) | |
||
74 | | *DelayedStatement* |<. delayed statement | |
||
75 | | *DisableStatement* |<. disable statement | |
||
76 | | *Generate* |<. generate construct | |
||
77 | | *IfGenerate* |<. conditional generate construct | |
||
78 | | *IfGenerateBranch* |<. if generate branch (@then@ or @else@) | |
||
79 | | *IfStatement* |<. conditional statement | |
||
80 | | *IfStatementBranch* |<. if statement branch (@then@ or @else@) | |
||
81 | | *Instantiation* |<. instantiation construct | |
||
82 | | *LoopGenerate* |<. generate loop | |
||
83 | | *LoopStatement* |<. loop statement (@forever@, @repeat@, @while@ or @for@) | |
||
84 | | *Module* |<. module declaration | |
||
85 | | *NullStatement* |<. null statement | |
||
86 | | *PathDeclaration* |<. path declaration | |
||
87 | | *Port* |<. port declaration | |
||
88 | | *PortConnection* |<. port connection | |
||
89 | | *Procedure* |<. procedure declaration (@function@ or @task@) | |
||
90 | | *PulseStyle* |<. pulse style specification | |
||
91 | | *ShowCancelled* |<. show-cancelled construct | |
||
92 | | *Specify* |<. specify construct | |
||
93 | | *Table* |<. UDP (user-defined primitive) table | |
||
94 | | *TableEntry* |<. UDP table entry | |
||
95 | | *TaskStatement* |<. task statement | |
||
96 | | *TriggerStatement* |<. trigger statement | |
||
97 | | *WaitStatement* |<. wait statement | |
||
98 | 5 | Alexander Kamkin | |
99 | A visitor example is given below. |
||
100 | |||
101 | <pre><code class="java"> |
||
102 | package ru.ispras.verilog.parser.sample; |
||
103 | 1 | Alexander Kamkin | |
104 | 5 | Alexander Kamkin | import ru.ispras.verilog.parser.model.*; |
105 | 8 | Alexander Kamkin | import ru.ispras.verilog.parser.model.basis.*; |
106 | 5 | Alexander Kamkin | import ru.ispras.verilog.parser.walker.*; |
107 | ... |
||
108 | |||
109 | /** |
||
110 | * This class illustrates development of a Verilog node visitor. |
||
111 | */ |
||
112 | public final class VerilogNodePrinter extends VerilogNodeVisitor |
||
113 | { |
||
114 | @Override |
||
115 | public void onActivityBegin(final Activity node) |
||
116 | { |
||
117 | indent(); |
||
118 | |||
119 | switch(node.getType()) |
||
120 | { |
||
121 | case INITIAL: |
||
122 | text("initial"); |
||
123 | break; |
||
124 | case ALWAYS: |
||
125 | text("always"); |
||
126 | break; |
||
127 | } |
||
128 | |||
129 | endl(); |
||
130 | begin(); |
||
131 | } |
||
132 | |||
133 | @Override |
||
134 | public void onActivityEnd(final Activity node) |
||
135 | { |
||
136 | end(); |
||
137 | } |
||
138 | ... |
||
139 | } |
||
140 | </code></pre> |
||
141 | 2 | Alexander Kamkin | |
142 | h2. Registering a Backend |
||
143 | 10 | Alexander Kamkin | |
144 | 11 | Alexander Kamkin | A backend is registered by calling the @add@ method of the @VerilogTranslator@ object. An example is given below: |
145 | 10 | Alexander Kamkin | |
146 | <pre><code class="java"> |
||
147 | 1 | Alexander Kamkin | /** |
148 | 11 | Alexander Kamkin | * Launches the Verilog translator with the Verilog printer as a backend. |
149 | 10 | Alexander Kamkin | * |
150 | * @param args the command line parameters. |
||
151 | */ |
||
152 | public static void main(String[] args) |
||
153 | { |
||
154 | VerilogTranslator translator = new VerilogTranslator(); |
||
155 | translator.add(new VerilogPrinter()); |
||
156 | translator.start(args); |
||
157 | } |
||
158 | </code></pre> |