PyHCL/docs/GettingStarted/GettingStarted.md

6.4 KiB

sort
1

Getting Started

PyHCL is a hardware construct language written in Python, a high-level, interpreted, general-purpose programming language.

Requirements / Things to download to get started

Before you download the PyHCL tools, you need to install:

  • Python 3.7 or above
  • FIRRTL environment

Python Guide

https://www.python.org/about/gettingstarted/

FIRRTL

Firrtl is an intermediate representation (IR) for digital circuits designed as a platform for writing circuit-level transformations. In Chisel3 version, the framework tools are compiled in a chain from Scala to FIRRTL to Verilog. The introduction of FIRRTL makes the front and back end of the framework practically replaceable with other languages. The target language of PyHCL is FIRRTL and calls the FIRRTL compiler to generate Verilog code. So to use PyHCL you need to configure the FIRRTL environment.
The FIRRTL installation and configuration process is described in detail in the FIRRTL Github repo:
https://github.com/chipsalliance/firrtl#installation-instructions

You need to follow the instructions above to install verilator, yosys and sbt. Then you need to compile and install FIRRTL.

If you successfully add firrtl to the environment variables, typing firrtl --help in the terminal will display the information about the firrtl command.

Other tools

GTKwave

GTKwave is a free tool for viewing waveform files such as .vcd files generated by various simulation tools

Install on Windows / MacOS
http://gtkwave.sourceforge.net/

Install on Linux

apt-get install gtkwave

CoCotb

Cocotb is a Python-based open source verification platform, similar in design to the UVM platform built using SystemVerilog. Cocotb is a relatively large and complex platform, so only simple simulation verification processes are described here, while other advanced uses can be found in the documentation if the reader is interested.

Cocotb Site:https://cocotb.org/
Cocotb Github repo:https://github.com/cocotb/cocotb
Cocotb Documents:https://cocotb.readthedocs.io/en/latest/index.html

Installation
https://cocotb.readthedocs.io/en/latest/quickstart.html#quickstart-guide

Instructions
To use Cocotb for simulation testing, you need to provide:

  • dut's Verilog file
  • a test harness written in Python
  • a Makefile file

The following is an example of how to use Cocotb to test a full adder. If you need other more advanced methods, you can refer to the official documentation.

Treadle

Treadle is an executor for FIRRTL developed by the Chisel team to quickly perform verification testing of FIRRTL code. It has the advantage that it can run directly on FIRRTL code without the need to drop down to Verilog code for testing. However, it also has the significant disadvantage that it runs very inefficiently and is only suitable for unit testing.

Installation
https://github.com/freechipsproject/treadle

After installing and configuring Treadle, run the script treadle.sh directly from the root directory to start Treadle.
load filename is used to read the FIRRTL file and start running.
poke is used to give excitation to the specified signal.
peek is used to view the current signal value.
step is used to step the specified clock period.

Command List
https://github.com/freechipsproject/treadle/wiki/TreadleRepl-commands

Diagrammar

Diagrammer is a visualization tool for FIRRTL code developed by Chisel team, which can generate data flow vector graphics of FIRRTL code module hierarchy and module logic, and can assist in debugging tests.

Github repo:
https://github.com/freechipsproject/diagrammer

Clone the project and install the GraphViz dependency to use.
You can get the vector graphics in /project/output by running the following command in the terminal:

./diagram.sh -i ~/projects/output/circuit.fir

How to start programming with PyHCL

PyHCL is actually a library implemented in Python, so once you clone the PyHCL source code using Git, you can place it in the root of your project and simply import it into the code that uses PyHCL.

from pyhcl import *

Simple Example

Writing A Full Adder

PyHCL defines modules using only simple Python syntax that looks like this:

from pyhcl import *

class FullAdder(Module):
    io = IO(
        a=Input(Bool),
        b=Input(Bool),
        cin=Input(Bool),
        sum=Output(Bool),
        cout=Output(Bool),
    )

    # Generate the sum
    io.sum @= io.a ^ io.b ^ io.cin

    # Generate the carry
    io.cout @= io.a & io.b | io.b & io.cin | io.a & io.cin

Compiling To High FIRRTL

Compiling module by calling compile_to_highform:

Emitter.dump(Emitter.emit(FullAdder(), HighForm), "FullAdder.fir")

Will generate the following FIRRTL codes:

circuit FullAdder :
  module FullAdder :
    input clock : Clock
    input reset : UInt<1>
    output io : {flip a : UInt<1>, flip b : UInt<1>, flip cin : UInt<1>, s : UInt<1>, cout : UInt<1>}
  
    node _T = xor(io.a, io.b)
    node _T_1 = xor(_T, io.cin)
    io.s <= _T_1
    node _T_2 = and(io.a, io.b)
    node _T_3 = and(io.a, io.cin)
    node _T_4 = or(_T_2, _T_3)
    node _T_5 = and(io.b, io.cin)
    node _T_6 = or(_T_4, _T_5)
    io.cout <= _T_6

Compiling To Lowered FIRRTL

Compiling module by calling compile_to_lowform:

Emitter.dump(Emitter.emit(FullAdder(), LowForm), "FullAdder.lo.fir")

Will generate the following FIRRTL codes:

circuit FullAdder :
  module FullAdder :
    input clock : Clock
    input reset : UInt<1>
    input io_a : UInt<1>
    input io_b : UInt<1>
    input io_cin : UInt<1>
    output io_s : UInt<1>
    output io_cout : UInt<1>
  
    node _T = xor(io_a, io_b)
    node _T_1 = xor(_T, io_cin)
    io_s <= _T_1
    node _T_2 = and(io_a, io_b)
    node _T_3 = and(io_a, io_cin)
    node _T_4 = or(_T_2, _T_3)
    node _T_5 = and(io_b, io_cin)
    node _T_6 = or(_T_4, _T_5)
    io_cout <= _T_6

Compiling To Verilog

Compiling module by calling compile_to_verilog:

Emitter.dump(Emitter.emit(FullAdder(), Verilog), "FullAdder.v")

Then FullAdder.v will be generated:

module FullAdder(
  input		clock,
  input		reset,
  input		io_a,
  input		io_b,
  input		io_cin,
  output		io_s,
  output		io_cout
);

  assign io_s = io_a ^ io_b ^ io_cin;
  assign io_cout = io_a & io_b | io_a & io_cin | io_b & io_cin;
  
endmodule