- 
                Notifications
    
You must be signed in to change notification settings  - Fork 56
 
How does the compiler work?
        Julian Kemmerer edited this page Sep 28, 2024 
        ·
        13 revisions
      
    You should find at least one paper in /docs.
I have a day job - message me for details please. Happy to talk your ears off. I will update this when not implementing new features, making improvements, and the like...
- Path from C syntax tree function definitions
- Tracking local variable define-use/assign chains
 - Forming directed acyclic graph from inputs to return
 - Dataflow ~netlist of assignments+operations
 - Some kind ~front end language handling layer?
 - Intermediate C-like, single assignment per variable form, highly optimized
 
 - Pipeline scheduling / ‘comb. logic tetris’
- Given delays of operations which areas of DAG need registers where
 - Seems tightly coupled with ~netlist comb. logic representation
 - Needs to know latency of modules when assembling larger modules, keeping data aligned
 
 - Rendering HDL (VHDL currently, and preferred, but SystemVerilog is fine)
- Pipelined primitives, ex. ~2 cycle latency 64b adder, as two 32b cycles w/ carry
 - ~Netlist VHDL + lots of custom arbitrary stuff
 
 - Internal C code gen for built in complex functions:
- ex. PipelineC FP operators are written in PipelineC
 
 - Support for running PNR tools, parsing timing report/measuring delays
 - How to make iterative pipelining changes if didnt meet timing
 - Running simulation tools
 - Experimental derived finite state machines
 - Generating helper C code for users
 
At a very high level the flow from C code to VHDL looks like:
C source code 
     |
 pycparser
     |
C Abstract Syntax Tree Nodes
     |
C_TO_LOGIC.PARSE_FILE
    * Does several passes over code:
      * generating headers requested from user C code
        * built in primitives, floating point ops, type to bytes packing, etc
      * updating info on global types/declarations + re parsing the AST from newly generated code
      * resolving clock domains for global MAIN function defs and global wires between them
    * Single pass over each function body/definition syntax tree
      * builds 'Logic' dataflow graphs - wires connecting other Logic objects together/submodules etc
      * constant folding,etc done as AST is walked since need to unroll loops
    * Elaborates function definitions to all instances/call locations of those functions / walking call stack in full
    |
VHDL.WRITE_LOGIC_ENTITY (and others)
    * Code for taking a single 'Logic'/function definition and writing VHDL
    * Also writes entire top level, multi clock domain etc, from other global parsed info
    |
SYN.ADD_PATH_DELAY_TO_LOOKUP
    * Render VHDL for each function definition (without pipelining)
    * Runs timing analysis on VHDL to get base combinatorial delay of each function's synthesized logic
    |
SYN.DO_THROUGHPUT_SWEEP
    * Uses information of parsed dataflow and circuit delays to decide where to add pipelining regs where possible
    * Renders pipelined VHDL
    * Iteratively makes changes if didnt meet timing