Fletchgen is a command-line utility that generates the upper layers of a hardware design, including simulation and platform-specific top-levels, based on Arrow Schemas and Recordbatches.
- For each Arrow Field, an ArrayReader/Writer is instantiated.
- For each Arrow Schema, a RecordBatchReader/Writer is generated and wrapper around all ArrayR/W instances.
- For all Arrow Schemas, a Kernel template is generated.
- The Kernel is wrapped in a Nucleus that hides low-level control flow to RecordBatchR/W's and instantiates the MMIO component that handles AXI4-lite memory-mapped input/output.
- All RecordBatchR/W's and the Nucleus is wrapped by a Mantle. The Mantle also instantiate the required memory bus interconnection logic.
This can also be shown schematically as follows:
Fletchgen does not generate the kernel itself.
It currently supports only two top-level platforms.
- One platform is a simulation top-level that uses a memory model that can
be filled with RecordBatches.
- To enable this top-level, use the
--sim
flag.
- To enable this top-level, use the
- The other is an AXI top-level that has an AXI4 (full) master port and
AXI4-lite slave port.
- To enable this top-level, use the
--axi
flag.
- To enable this top-level, use the
Fletchgen is under heavy development, so for now we'd recommend to make a debug build using CMake as follows:
git clone https://github.com/abs-tudelft/fletcher.git --recursive
cd fletcher/codegen/cpp/fletchgen
mkdir debug
cd debug
cmake ..
make
sudo make install
- Read the command-line options.
fletchgen -h
An example how to use Fletchgen can be found here.
A very gentle tutorial / introduction to Fletcher including how to use Fletchgen and how to generate input files for Fletchgen can be found here.
Fletchgen derives how to use an Arrow Schema from attached key-value metadata that is stored in Arrow Schemas. You can use this to, for example, prevent the generation of hardware structures for fields that you're not going to use in your kernel implementation.
Key | Possible values | Default | Description |
---|---|---|---|
fletcher_name | any string | none | The name of the schema. This is required for the schema to be identifiable after hardware generation. |
fletcher_mode | read / write | read | Determines whether a RecordBatch of this schema will be read or written by the kernel. |
fletcher_bus_spec | aw,dw,lw,bs,bm | 64,512,8,1,16 | Key to set the bus specification of the RecordBatchReader/Writer resulting from this schema. aw: address width, dw: data width, lw: burst length width, bs: minimum burst size, bm: maximum burst size. |
Key | Possible values | Default | Description |
---|---|---|---|
fletcher_ignore | true / false | false | If set to true, ignore a specific schema field, preventing generation of hardware to read/write from/to it. |
fletcher_epc | 1 / 2 / 4 / ... | 1 | Number of elements per cycle for this field. For List<X> fields where X is a fixed-width type, this applies to the values stream. |
fletcher_lepc | 1 / 2 / 4 / ... | 1 | For List<primitive> fields only. Number of elements per cycle on the length stream. |
fletcher_profile | true / false | false | If set to true, mark this field for profiling. The hardware streams resulting from this field will have a profiler attached to them. |
fletcher_tag_width | 1 / 2 / 3 / ... | 1 | Width of the tag field of commands and unlock streams of RecordBatchReaders/Writers. Can be used to identify commands. |
You can add custom MMIO registers to your kernel using --reg
.
More information can be found here.
Sometimes, your kernel requires other I/O signals than just Arrow data streams in and out, and MMIO registers. There may be some other type of data source or sink in your design, there may be some platform-specific things you want to use, or etcetera.
You can supply Fletchgen with a YAML file describing what signals you want to
draw between the kernel and the top-level. An example is shown below, where we
want to handshake completion from the platform top-level with a req
and ack
bit.
- record:
name: platform
fields:
- record:
name: complete
fields:
- field:
name: req
width: 1
- field:
name: ack
width: 1
reverse: true
This will result in the following signals appearing at the top-level:
ext_platform_complete_req : out std_logic;
ext_platform_complete_ack : in std_logic
- The signals are assumed to be driven by the kernel. To drive them from the top level, use:
reverse: true
- Fields with a width of 1 can be forced to be
std_logic_vector
instead ofstd_logic
by using:
vector: true
You can generate a simulation top level and provide a Flatbuffer file with a RecordBatch to the simulation environment. You can use this to debug your designs in simulation, independent of an FPGA platform specific simulation environment. An example is shown here..