|
| 1 | +Pyverilog |
| 2 | +========= |
| 3 | + |
| 4 | +Python-based Hardware Design Processing Toolkit for Verilog HDL |
| 5 | + |
| 6 | +Copyright (C) 2013, Shinya Takamaeda-Yamazaki |
| 7 | + |
| 8 | +E-mail: shinya\_at\_is.naist.jp |
| 9 | + |
| 10 | +License |
| 11 | +======= |
| 12 | + |
| 13 | +Apache License 2.0 (http://www.apache.org/licenses/LICENSE-2.0) |
| 14 | + |
| 15 | +This software package includes PLY-3.4 in "vparser/ply". The license of |
| 16 | +PLY is BSD. |
| 17 | + |
| 18 | +What's Pyverilog? |
| 19 | +================= |
| 20 | + |
| 21 | +Pyverilog is an open-source hardware design processing toolkit for |
| 22 | +Verilog HDL. All source codes are written in Python. |
| 23 | + |
| 24 | +Pyverilog includes **(1) code parser, (2) dataflow analyzer, (3) |
| 25 | +control-flow analyzer and (4) code generator**. You can create your own |
| 26 | +design analyzer, code translator and code generator of Verilog HDL based |
| 27 | +on this toolkit. |
| 28 | + |
| 29 | +Software Requirements |
| 30 | +===================== |
| 31 | + |
| 32 | +- Python (2.7, 3.3 or later) |
| 33 | +- Icarus Verilog (0.9.6 or later) |
| 34 | +- pyverilog.vparser.preprocessor.py uses 'iverilog -E' command as the |
| 35 | + preprocessor. |
| 36 | +- 'apt-get install iverilog' |
| 37 | +- Graphviz and Pygraphviz (Python3 does not support Pygraphviz) |
| 38 | +- pyverilog.dataflow.graphgen and pyverilog.controlflow.controlflow |
| 39 | + (without --nograph option) use Pygraphviz (on Python 2.7). |
| 40 | +- If you do not use graphgen and controlflow (without --nograph) |
| 41 | + option, Python 3.x is fine. |
| 42 | +- Jinja2 (2.7 or later) |
| 43 | +- ast\_code\_generator requires jinja2 module. |
| 44 | +- 'pip3 install jinja2' (for Python 3.x) or 'pip install jinja2' (for |
| 45 | + Python 2.7) |
| 46 | + |
| 47 | +Installation |
| 48 | +============ |
| 49 | + |
| 50 | +If you want to use Pyverilog as a general library, you can install on |
| 51 | +your environment by using setup.py. If Python 2.7 is used, |
| 52 | + |
| 53 | +:: |
| 54 | + |
| 55 | + python setup.py install |
| 56 | + |
| 57 | +If Python 3.x is used, |
| 58 | + |
| 59 | +:: |
| 60 | + |
| 61 | + python3 setup.py install |
| 62 | + |
| 63 | +Tools |
| 64 | +===== |
| 65 | + |
| 66 | +This software includes various tools for Verilog HDL design. |
| 67 | + |
| 68 | +- vparser: Code parser to generate AST (Abstract Syntax Tree) from |
| 69 | + source codes of Verilog HDL. |
| 70 | +- dataflow: Dataflow analyzer with an optimizer to remove redundant |
| 71 | + expressions and some dataflow handling tools. |
| 72 | +- controlflow: Control-flow analyzer with condition analyzer that |
| 73 | + identify when a signal is activated. |
| 74 | +- ast\_code\_generator: Verilog HDL code generator from AST. |
| 75 | + |
| 76 | +Getting Started |
| 77 | +=============== |
| 78 | + |
| 79 | +First, please prepare a Verilog HDL source file as below. The file name |
| 80 | +is 'test.v'. This sample design adds the input value internally whtn the |
| 81 | +enable signal is asserted. Then is outputs its partial value to the LED. |
| 82 | + |
| 83 | +.. code:: verilog |
| 84 | +
|
| 85 | + module top |
| 86 | + ( |
| 87 | + input CLK, |
| 88 | + input RST, |
| 89 | + input enable, |
| 90 | + input [31:0] value, |
| 91 | + output [7:0] led |
| 92 | + ); |
| 93 | + reg [31:0] count; |
| 94 | + reg [7:0] state; |
| 95 | + assign led = count[23:16]; |
| 96 | + always @(posedge CLK) begin |
| 97 | + if(RST) begin |
| 98 | + count <= 0; |
| 99 | + state <= 0; |
| 100 | + end else begin |
| 101 | + if(state == 0) begin |
| 102 | + if(enable) state <= 1; |
| 103 | + end else if(state == 1) begin |
| 104 | + state <= 2; |
| 105 | + end else if(state == 2) begin |
| 106 | + count <= count + value; |
| 107 | + state <= 0; |
| 108 | + end |
| 109 | + end |
| 110 | + end |
| 111 | + endmodule |
| 112 | +
|
| 113 | +Code parser |
| 114 | +----------- |
| 115 | + |
| 116 | +Let's try syntax analysis. Please type the command as below. |
| 117 | + |
| 118 | +:: |
| 119 | + |
| 120 | + python3 pyverilog/vparser/parser.py test.v |
| 121 | + |
| 122 | +Then you got the result as below. The result of syntax analysis is |
| 123 | +displayed. |
| 124 | + |
| 125 | +:: |
| 126 | + |
| 127 | + Source: |
| 128 | + Description: |
| 129 | + ModuleDef: top |
| 130 | + Paramlist: |
| 131 | + Portlist: |
| 132 | + Ioport: |
| 133 | + Input: CLK, False |
| 134 | + Width: |
| 135 | + IntConst: 0 |
| 136 | + IntConst: 0 |
| 137 | + Ioport: |
| 138 | + Input: RST, False |
| 139 | + Width: |
| 140 | + IntConst: 0 |
| 141 | + IntConst: 0 |
| 142 | + Ioport: |
| 143 | + Input: enable, False |
| 144 | + Width: |
| 145 | + IntConst: 0 |
| 146 | + IntConst: 0 |
| 147 | + Ioport: |
| 148 | + Input: value, False |
| 149 | + Width: |
| 150 | + IntConst: 31 |
| 151 | + IntConst: 0 |
| 152 | + Ioport: |
| 153 | + Output: led, False |
| 154 | + Width: |
| 155 | + IntConst: 7 |
| 156 | + IntConst: 0 |
| 157 | + Decl: |
| 158 | + Reg: count, False |
| 159 | + Width: |
| 160 | + IntConst: 31 |
| 161 | + IntConst: 0 |
| 162 | + Decl: |
| 163 | + Reg: state, False |
| 164 | + Width: |
| 165 | + IntConst: 7 |
| 166 | + IntConst: 0 |
| 167 | + Assign: |
| 168 | + Lvalue: |
| 169 | + Identifier: led |
| 170 | + Rvalue: |
| 171 | + Partselect: |
| 172 | + Identifier: count |
| 173 | + IntConst: 23 |
| 174 | + IntConst: 16 |
| 175 | + Always: |
| 176 | + SensList: |
| 177 | + Sens: posedge |
| 178 | + Identifier: CLK |
| 179 | + Block: None |
| 180 | + IfStatement: |
| 181 | + Identifier: RST |
| 182 | + Block: None |
| 183 | + NonblockingSubstitution: |
| 184 | + Lvalue: |
| 185 | + Identifier: count |
| 186 | + Rvalue: |
| 187 | + IntConst: 0 |
| 188 | + NonblockingSubstitution: |
| 189 | + Lvalue: |
| 190 | + Identifier: state |
| 191 | + Rvalue: |
| 192 | + IntConst: 0 |
| 193 | + Block: None |
| 194 | + IfStatement: |
| 195 | + Eq: |
| 196 | + Identifier: state |
| 197 | + IntConst: 0 |
| 198 | + Block: None |
| 199 | + IfStatement: |
| 200 | + Identifier: enable |
| 201 | + NonblockingSubstitution: |
| 202 | + Lvalue: |
| 203 | + Identifier: state |
| 204 | + Rvalue: |
| 205 | + IntConst: 1 |
| 206 | + IfStatement: |
| 207 | + Eq: |
| 208 | + Identifier: state |
| 209 | + IntConst: 1 |
| 210 | + Block: None |
| 211 | + NonblockingSubstitution: |
| 212 | + Lvalue: |
| 213 | + Identifier: state |
| 214 | + Rvalue: |
| 215 | + IntConst: 2 |
| 216 | + IfStatement: |
| 217 | + Eq: |
| 218 | + Identifier: state |
| 219 | + IntConst: 2 |
| 220 | + Block: None |
| 221 | + NonblockingSubstitution: |
| 222 | + Lvalue: |
| 223 | + Identifier: count |
| 224 | + Rvalue: |
| 225 | + Plus: |
| 226 | + Identifier: count |
| 227 | + Identifier: value |
| 228 | + NonblockingSubstitution: |
| 229 | + Lvalue: |
| 230 | + Identifier: state |
| 231 | + Rvalue: |
| 232 | + IntConst: 0 |
| 233 | + |
| 234 | +Dataflow analyzer |
| 235 | +----------------- |
| 236 | + |
| 237 | +Let's try dataflow analysis. Please type the command as below. |
| 238 | + |
| 239 | +:: |
| 240 | + |
| 241 | + python3 pyverilog/dataflow/dataflow_analyzer.py -t top test.v |
| 242 | + |
| 243 | +Then you got the result as below. The result of each signal definition |
| 244 | +and each signal assignment are displayed. |
| 245 | + |
| 246 | +:: |
| 247 | + |
| 248 | + Directive: |
| 249 | + Instance: |
| 250 | + (top, 'top') |
| 251 | + Term: |
| 252 | + (Term name:top.led type:{'Output'} msb:(IntConst 7) lsb:(IntConst 0)) |
| 253 | + (Term name:top.enable type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 254 | + (Term name:top.CLK type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 255 | + (Term name:top.count type:{'Reg'} msb:(IntConst 31) lsb:(IntConst 0)) |
| 256 | + (Term name:top.state type:{'Reg'} msb:(IntConst 7) lsb:(IntConst 0)) |
| 257 | + (Term name:top.RST type:{'Input'} msb:(IntConst 0) lsb:(IntConst 0)) |
| 258 | + (Term name:top.value type:{'Input'} msb:(IntConst 31) lsb:(IntConst 0)) |
| 259 | + Bind: |
| 260 | + (Bind dest:top.count tree:(Branch Cond:(Terminal top.RST) True:(IntConst 0) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 0)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 1)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 2)) True:(Operator Plus Next:(Terminal top.count),(Terminal top.value))))))) |
| 261 | + (Bind dest:top.state tree:(Branch Cond:(Terminal top.RST) True:(IntConst 0) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 0)) True:(Branch Cond:(Terminal top.enable) True:(IntConst 1)) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 1)) True:(IntConst 2) False:(Branch Cond:(Operator Eq Next:(Terminal top.state),(IntConst 2)) True:(IntConst 0)))))) |
| 262 | + (Bind dest:top.led tree:(Partselect Var:(Terminal top.count) MSB:(IntConst 23) LSB:(IntConst 16))) |
| 263 | + |
| 264 | +Let's view the result of dataflow analysis as a picture file. Now we |
| 265 | +select 'led' as the target. Please type the command as below. |
| 266 | + |
| 267 | +:: |
| 268 | + |
| 269 | + python3 pyverilog/dataflow/graphgen.py -t top -s top.led test.v |
| 270 | + |
| 271 | +Then you got a png file (out.png). The picture shows that the definition |
| 272 | +of 'led' is a part-selection of 'count' from 23-bit to 16-bit. |
| 273 | + |
| 274 | +.. figure:: http://cdn-ak.f.st-hatena.com/images/fotolife/s/sxhxtxa/20140101/20140101045641.png |
| 275 | + :alt: out.png |
| 276 | + |
| 277 | + out.png |
| 278 | +Control-flow analyzer |
| 279 | +--------------------- |
| 280 | + |
| 281 | +Let's try control-flow analysis. Please type the command as below. |
| 282 | + |
| 283 | +:: |
| 284 | + |
| 285 | + python2.7 pyverilog/controlflow/controlflow_analyzer.py -t top test.v |
| 286 | + |
| 287 | +Then you got the result as below. The result shows that the state |
| 288 | +machine structure and transition conditions to the next state in the |
| 289 | +state machine. |
| 290 | + |
| 291 | +:: |
| 292 | + |
| 293 | + FSM signal: top.count, Condition list length: 4 |
| 294 | + FSM signal: top.state, Condition list length: 5 |
| 295 | + Condition: (Ulnot, Eq), Inferring transition condition |
| 296 | + Condition: (Eq, top.enable), Inferring transition condition |
| 297 | + Condition: (Ulnot, Ulnot, Eq), Inferring transition condition |
| 298 | + # SIGNAL NAME: top.state |
| 299 | + # DELAY CNT: 0 |
| 300 | + 0 --(top_enable>'d0)--> 1 |
| 301 | + 1 --None--> 2 |
| 302 | + 2 --None--> 0 |
| 303 | + Loop |
| 304 | + (0, 1, 2) |
| 305 | + |
| 306 | +You got also a png file (top\_state.png). The picture shows that the |
| 307 | +graphical structure of the state machine. |
| 308 | + |
| 309 | +.. figure:: http://cdn-ak.f.st-hatena.com/images/fotolife/s/sxhxtxa/20140101/20140101045835.png |
| 310 | + :alt: top\_state.png |
| 311 | + |
| 312 | + top\_state.png |
| 313 | +Code generator |
| 314 | +-------------- |
| 315 | + |
| 316 | +Finally, let's try code generation. Please prepare a Python script as |
| 317 | +below. The file name is 'test.py'. A Verilog HDL code is represented by |
| 318 | +using the AST classes defined in 'vparser.ast'. |
| 319 | + |
| 320 | +.. code:: python |
| 321 | +
|
| 322 | + import pyverilog.vparser.ast as vast |
| 323 | + from pyverilog.ast_code_generator.codegen import ASTCodeGenerator |
| 324 | +
|
| 325 | + params = vast.Paramlist(()) |
| 326 | + clk = vast.Ioport( vast.Input('CLK') ) |
| 327 | + rst = vast.Ioport( vast.Input('RST') ) |
| 328 | + width = vast.Width( vast.IntConst('7'), vast.IntConst('0') ) |
| 329 | + led = vast.Ioport( vast.Output('led', width=width) ) |
| 330 | + ports = vast.Portlist( (clk, rst, led) ) |
| 331 | + items = ( vast.Assign( vast.Identifier('led'), vast.IntConst('8') ) ,) |
| 332 | + ast = vast.ModuleDef("top", params, ports, items) |
| 333 | +
|
| 334 | + codegen = ASTCodeGenerator() |
| 335 | + rslt = codegen.visit(ast) |
| 336 | + print(rslt) |
| 337 | +
|
| 338 | +Please type the command as below at the same directory with Pyverilog. |
| 339 | + |
| 340 | +:: |
| 341 | + |
| 342 | + python3 test.py |
| 343 | + |
| 344 | +Then Verilog HDL code generated from the AST instances is displayed. |
| 345 | + |
| 346 | +.. code:: verilog |
| 347 | +
|
| 348 | +
|
| 349 | + module top |
| 350 | + ( |
| 351 | + input [0:0] CLK, |
| 352 | + input [0:0] RST, |
| 353 | + output [7:0] led |
| 354 | +
|
| 355 | + ); |
| 356 | + assign led = 8; |
| 357 | + endmodule |
| 358 | +
|
| 359 | +Related Project and Site |
| 360 | +======================== |
| 361 | + |
| 362 | +`PyCoRAM <http://shtaxxx.github.io/PyCoRAM/>`__ - Python-based Portable |
| 363 | +IP-core Synthesis Framework for FPGA-based Computing |
| 364 | + |
| 365 | +`shtaxxx.hatenablog.com <http://shtaxxx.hatenablog.com/entry/2014/01/01/045856>`__ |
| 366 | +- Blog entry for introduction and examples of Pyverilog (in Japansese) |
0 commit comments