Yet Another Hardware Description Language.
To provide a familiar and productive language for makers and hobbyists to develop applications on FPGAs.
These principals are used to guide design and development of the language, tools, and ecosystem.
- Make it easy to use and understand.
- Make it easy to write reusable libraries. Make it easy to use reusable libraries.
- Provide a clear path from "easy but unoptimized" to "optimized but difficult".
- Prefer the most widely recognizable syntax, structure, and patterns over cutting-edge or exotic alternatives.
- Prefer low-level library functions over built-in language features.
- Avoid high-level synthesis.
The core language borrows heavily from both Verilog and C++. Most Verilog concepts translate directly into yahdl concepts but with a syntax that looks more like C++. Verilog modules, parameters, ports, nets, always blocks, and assign statements all have direct representations in yahdl. New concepts of synthesizable threads, function calls, and classes are added. Threads and sequential functions are transformed into control and datapath logic.
Tokenize and parse the design files into concrete syntax trees.
Convert the concrete syntax trees into abstract syntax trees. An AST (abstract syntax tree) is more suitable for further processing.
The symbol table for each scope is generated. The complete symbol table is actually a tree of tables where each node represents a scope.
Every reference to a symbol is resolved to the definition of that symbol.
Starting at the top module going down the hierarchy, modules are copied to each location they are instantiated.
Starting at the top module going down the hierarchy, parameter and constant expressions are evaluated and propagated.
Expressions are simplified.
The control flow for each method and thread is extracted. Assignments and expressions are included in
The data flow from each control graph is extracted with signals connecting the control graph to the data graph control points. Temporary storage and muxes are added as necessary.
Dead code is pruned from the control graph and data graph based on expressions known at compile-time.
Combine independent and trivially dependent statement nodes into a single node. Trivially dependent statements are dependent assignment expressions comprised of a small number of logical functions, unlimited constant bitslicing, unlimited constant shifts, and variable references.
Beginning from each always block and thread, a directed graph is generated that describes every location that every function is called from.
Trival getter and setter functions are inlined.
Arbiters are inserted for functions that are called from more than one thread and for module fields that are updated from more than one always block or thread.
When implementing the design, there are many implementation decisions to be made along the way. Simple decisions like whether a function should be inlined or not can make a big difference in performance and resource utilization.
Optimization stages must implement three features:
- Identify locations to perform the optimization.
- Heuristics to get cheap decisions on whether the optimization should be performed when it is obvious what to do.
- Perform the optimization.
Possible implementation optimizations:
- Loop Unrolling
- Function Inline
- Complex State Fusion
Output the design in human-readable and synthesizable verilog.