-
Notifications
You must be signed in to change notification settings - Fork 49
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