Skip to content

How does the compiler work?

Julian Kemmerer edited this page Sep 28, 2024 · 13 revisions

/ Did you write a paper?

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...

A short list of things to get me talking...

  • 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

Tool Architecture Overview

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
Clone this wiki locally