Skip to content

A C++ to Verilog translation tool with some basic guarantees that your code will work.

License

Notifications You must be signed in to change notification settings

aappleby/metron

Repository files navigation

Metron C++ to Verilog Translator

Metron is a tool for translating a very limited subset of C++ into a very limited subset of SystemVerilog.

Metron accepts plain, unannotated C++ header files as inputs and produces synthesizable SystemVerilog files that are compatible with Icarus, Verilator, Yosys, and most commercial tools.

Metron is not a "High-Level Synthesis" tool. Metron does some basic analysis to determine if your code is semantically compatible with Verilog and then produces a line-by-line translation with only the minimal set of changes needed to make the code compatible with Verilog tooling.

Because it targets hardware implementation, Metron can't handle a lot of C++ language features - no pointers, no virtual functions, no pass-by-reference, limited data structures - but it's still sufficient to build CPUs and peripherals that will run on a FPGA.

TL;DR:

Metron v0.0.1 Release Notes

First public release!

  • Stuff that works
    • Testbench has tests for Verilator, Icarus, and Yosys parsing Metron output.
    • Testbench has pretty good coverage of Metron via kcov.
    • Testbench has test suites for two RISC-V RV32I cores.
    • Testbench has some lock-step tests that check that Metron and Verilator outputs are bit-identical.
    • Tutorial and demo work and have nice responsive live code windows.
  • Stuff that doesn't work, but should eventually
    • Struct support. It was kinda working in some tools and not in others and I need to revisit it.
    • Visual Studio support has bit-rotted somewhat.
  • Stuff that I'll be doing next
    • Better error reporting. The error checking is good, but the information printed out is pretty useless unless you're in a debugger. I should at least be printing filename + source line for all errors.
    • More complicated examples ported from Verilog to Metron. I have a full-featured UART from OpenCores and the Ibex RISC-V CPU that I've started looking at but they're not functional yet.
    • More chunks of GateBoy/LogicBoy made compatible with Metron.

FAQ

  • I'm already using Verilator to convert my Verilog to C for testing, why would I want to use Metron?
    • Metron can help you prototype new RTL faster than writing it in Verilog.
    • Metron doesn't require a conversion step to integrate with an existing Verilator C++ testbench.
    • Metron modules usually simulate 2x - 5x faster than Verilated modules.
  • Wait, what? How fast do Metron models simulate?
    • A trivial LFSR module simulates at 600+ Mhz on my 5900x
    • A 640x480 "Pong" VGA video generator runs at 260+ Mhz with simulated video out via SDL2, or over 10x realtime.
    • A simple RISC-V RV32I core simulates at 360 mhz, though with the caveat that it's a single-cycle core and probably wouldn't synthesize.
    • The UART example in the test bench runs a loopback transmission + checksum at ~400 mhz (the Verilated version is ~130 mhz).
  • Have you heard of TLA+?
    • Yes, and I'm aware that I'm also using the phrase "temporal logic", which might confuse some readers. I couldn't think of a better term for the "How Metron Works" page though, alas. Apolgies in advance to Leslie Lamport.
    • It would be interesting to see how Metron programs could use (or be translated into?) TLA+ proofs, but it's out of scope for now.
  • Why C++ instead of {language}?
    • When I started the project I wasn't sure if I'd end up needing to do a bunch of brute-force "trace every possible path" stuff, and C++ is my most fluent language so I stuck with it. Now that Metron's working.... yeah, it would probably be simpler if written in Python, and Rust would probably make a better source language for conversion. Might be a future project.

Building the Metron binary from source:

Note: Metron doesn't use Git submodules anymore, instead it expects its dependencies to be checked out in folders alongside itself.

sudo apt install git build-essential ninja-build python3 libicu-dev libsdl2-dev
git clone https://github.com/CLIUtils/CLI11
git clone https://github.com/aappleby/metron
cd metron
./build.py
ninja build/metron

Building everything in the repo:

The full test suite requires quite a bit of stuff. The versions of Verilator and Yosys available via apt are slightly too old and have some bugs, so build them from source - instructions tested on a clean install of Ubuntu 22.04:

#sudo apt install verilator    // too old, get verilated_heavy.h error
#sudo apt install yosys        // too old, doesn't like "module uart_hello #(parameter int repeat_msg = 0)"
sudo apt install iverilog      // strongly recommended to build from source
sudo apt install fpga-icestorm // strongly recommended to build from source
sudo apt install nextpnr-ice40 // strongly recommended to build from source
sudo apt install libsdl2-dev
sudo apt install gcc-riscv64-unknown-elf
sudo apt install srecord

Installing Emscripten:

cd ~
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh

Building Yosys from source:

cd ~
sudo apt-get install build-essential clang bison flex libreadline-dev gawk tcl-dev libffi-dev git graphviz xdot pkg-config python3 libboost-system-dev libboost-python-dev libboost-filesystem-dev zlib1g-dev
git clone https://github.com/YosysHQ/yosys
cd yosys
make config-gcc
make -j$(nproc)
sudo make install

Building Verilator from source:

cd ~
sudo apt-get install git perl python3 make autoconf g++ flex bison ccache libgoogle-perftools-dev numactl perl-doc libfl2 libfl-dev zlib1g zlib1g-dev help2man
git clone https://github.com/verilator/verilator
cd verilator
autoconf
./configure
make -j$(nproc)
sudo make install

Building Icarus from source:

cd ~
sudo apt install build-essential bison flex gperf libreadline-dev autoconf
git clone https://github.com/steveicarus/iverilog
cd iverilog
sh autoconf.sh
./configure
make -j$(nproc)
sudo make install

Building Icestorm from source:

cd ~
git clone https://github.com/YosysHQ/icestorm
cd icestorm
sudo apt install build-essential libftdi-dev
make
sudo make install

Building Nextpnr-iCE40 from source (note - requires Icestorm to be installed first):

cd ~
git clone https://github.com/YosysHQ/nextpnr
cd nextpnr
sudo apt install python3 python3-dev cmake libboost-dev libboost-filesystem-dev libboost-thread-dev libboost-program-options-dev libboost-iostreams-dev libboost-dev libeigen3-dev
cmake . -DARCH=ice40
make -j$(nproc)
sudo make install

Running the Metron test suite:

./build.py
ninja
./run_tests.py

Running test coverage:

./build.py
ninja
./run_tests.py --coverage

About

A C++ to Verilog translation tool with some basic guarantees that your code will work.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published