Verilog Code Generator

In a previous article, I released a VHDL code generator written in python and using python as the embedded language.  That generator worked fairly cleanly, adding constructs that mostly looked like VHDL code.  I decided to try a different approach with my Verilog code generator, which also works with VHDL.

Syntax

The new generator has a feel that is more like Verilog — concise.  There are three types of added “operators” — eval blocks, exec blocks, and hdl special blocks.  Each can be concisely written.

// eval block:
assign x = a[${my_var}];

// code generated (paraphrased)
hdl+="assign x = a[%s];"%(my_var)

The eval block is used to insert python objects into the output HDL code.  As with the previous parser, str() is called on the argument.  This means that literals, variables, functions/methods, expressions, and objects with a __str__() method will all be evaluated.

//exec example:
$[def f(x):
## this is actually a corner case
  return x+1
]

// example 2:
$[x=1
  y=2
  z=3
]

A big issue with embedding python into another language is that it makes sense to indent the python code to the level where it is used in the native language.  Python is indentation sensitive, so some method must be used to determine indentation.  My code currently just looks at the indentation of the second line in the exec block.  This itself becomes an issue if the first line is an if/for/def statement where the second line would be indented.

// example of blocks
$(x[${j}] <= $(1'b0).if(len(my_lists[j]) > 0)
     $(a[${i}]).join("||",i in my_lists[j]);
).clone(j in range(8))

The above shows all three block types.  The “if” block will generate the code “x <= 1’b0;” when “my_lists[j]” has no elements.  This is an improvement over the previous code generator — the if-gen construct can now be inlined easily.

The “join” block is the next improvement.  It allows for generation of text like “a[0] || a[2] || a[3]”.  The “||” operator is place between each element, but not after the last element.  These two constructs solve some issues with code for code that is slightly different for 0 elements, 1 element, or N elements.

The final block is “clone”, which is the normal for-gen.  This operator can now be inlined as shown above.

// another structure for clone:
$[loop initialization code]
$(
  $[loop update code]
  hdl code
).clone(generator)

The operators can also be used to generate a more common structure for loops, with exec’s used to initialize and update loop variables.  This can also be used to declare the generator and update the predicates.  This makes the $().if() statements more concise.

Pros/Cons

The generator is designed to have a minimal impact on the native language.  It imposes few restrictions on vanilla Verilog files — ones that don’t make use of the embedded python.  The restrictions are:

  1. The code can’t otherwise contain ${, $[, or $(.  These are only valid in comments anyways.
  2. The code can’t contain “”” at the moment.  Again, this would only be valid in comments.

By allowing vanilla Verilog files to pass unmodified, any Verilog file can also be used as a template.  This allows the build system to process all Verilog files with the code generator without too many issues.  Likewise, Verilog code segments that don’t use the python features can be freely copied/pasted.

The code generator doesn’t do a good job with generating human readable code — lines can be very long.  Likewise, these constructs are not highlighted in a standard HDL-highlighting text editor.  The new line breaking script might help out a lot with the former.

Finally, I’m not sure how much I like the $().action() syntax.  It places the actions at the far right, which is a bit less readable.  I’ll admit, it was a choice designed to get rid of an annoying corner case — unmatched parens within an HDL portion of the hdl-special blocks.  There are few times when these might comes up, but I just know someone’s going to be a fan of emoticons and be less than :) about what my parser does.

The code generator doesn’t have particularly elegant code — it’s simple and works and isn’t overly complicated.  Here is the python script.

This entry was posted in Verilog and tagged , . Bookmark the permalink.

Comments are closed.