Skip to content
This repository has been archived by the owner on Jul 19, 2022. It is now read-only.

Files

Latest commit

defba76 · Jul 18, 2022

History

History

blocklib

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Apr 11, 2022
Mar 28, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 18, 2022
Jul 6, 2022
Jun 7, 2022

Blocklib

This folder holds the in-tree blocks, which depend on the runtime library. Each module of blocks is within its own folder.

How to add/port a block

The create_block.py script is a stripped down modtool surrogate that drops a block directory into the desired location

Create the block directory

cd blocklib/[MODULE]
python3 utils/modtool/create_block.py --intree [BLOCKNAME] --author "[AUTHOR NAME]"

If this block is going to be templated (such as the add or vector_source blocks), then add the --templated flag

This creates a directory with the following files:

.
├── .gitignore
├── [BLOCKNAME]_cpu.cc
├── [BLOCKNAME]_cpu.h
└── [BLOCKNAME].yml

Editing the YML file

The .yml file is the landing point for all the interfaces to the block

Edit it according to the desired parameters, ports, callbacks, etc.

More detail to come about the yml spec

Add Private Variables

Open [BLOCKNAME]_cpu.h which maps roughly to the _impl.h file from GR3

Add any private variables that will

The constructor and make

The make function is no longer needed as this is automatically generated

The constructor code looks like GR3 except

  1. No io_signature - this is handled in the auto-generated code from the yml
  2. No msg ports - also handled from the auto-generated code

The constructor has the form:

[BLOCKNAME]_cpu::[BLOCKNAME]_cpu(block_args args) : INHERITED_CONSTRUCTORS {}

The INHERITED_CONSTRUCTORS macro covers the initialization of the base classes since the block class is virtual, this would require initializing the same thing multiple times. In the case of a templated block class, INHERITED_CONSTRUCTORS takes the template parameter, e.g. INHERITED_CONSTRUCTORS(T).

Each of the parameters that are defined in the .yml are available as a member of the args struct. So what previously would have been a parameter to the constructor is now lumped into this struct so the constructor signature does not change.

Work Function

Work functions are conceptually the same as GR3, but syntactically slightly different to keep the block API separated from the scheduler API.

    work_return_code_t work(work_io&)
                                     override;

First, the work function takes in a vector of pointers to input objects, and a vector of pointers to output objects.

To get the noutput_items would be

auto noutput_items = work_output[0].n_items;

block_work_input_sptr contains a pointer to the underlying buffer object - it is not just raw pointers. But it is easy to get the underlying pointer

    auto in = wio.inputs()[0].items<T>();
    auto out = wio.outputs()[0].items<T>();

Where T is whatever specific type for a non-templated block

The return value of the work function is a return code instead of the number of output items produce. Therefore, produce and consume must be called from within the work function. This keeps some consistency between sync and general blocks.

wio.produce_each(noutput_items);

or

wio.outputs()[0].n_produced = noutput_items;

and then

return work_return_code_t::WORK_OK;

Message Handlers

When a message port is added in the yml, an automatically named handler is instatiated at the top level block class (autogenerated)

For example, for an input message port with id: in

ports:
-   domain: message
    id: in
    direction: input
    optional: true

a virtual method is expected to be implemented in the underlying block class named

void handle_msg_in(pmtf::pmt msg) override

Callbacks

Publicly accessible methods (not necessary for parameter handlers, e.g. k() and set_k()) - but generic methods must be defined in the yaml, and then implemented in the _cpu.cc

More definition is needed into how these fields map, but the basic idea is this

callbacks:
-   id: last_endpoint
    return: std::string
    const: true

gets autogenerated into the blockname.h as

virtual std::string last_endpoint() const = 0;

then must be implemented

There is some big TODOs here to make this more robust and prevent creating a new mini-language to generate some basic c++