This is a small post about one of the cool Yosys features: plugins. Basically, we can implement commands to be called from Yosys scripts. The plugins use the RTLIL APIs to iterate, process, modify or add elements.
Calling: yosys.ys Link to heading
Starting with the Yosys script, this is an example of the count_cells command called after proc and opt.
read_verilog example.v
hierarchy -top top
proc
opt
count_cells
Building: Makefile Link to heading
To build the command, we will use yosys-config to get the options needed to build the shared object with the plugin.
CXX = $(shell yosys-config --cxx)
CXXFLAGS = $(shell yosys-config --cxxflags)
LDFLAGS = $(shell yosys-config --ldflags)
LDLIBS = $(shell yosys-config --ldlibs)
count_cells.so: count_cells.cc
$(CXX) $(CXXFLAGS) -shared -o $@ $< $(LDFLAGS) $(LDLIBS)
clean:
rm -fr count_cells.so count_cells.d count_cells.so.dSYM
test: count_cells.so
yosys -m ./count_cells.so test.ys
Plugin: C++ Link to heading
count_cells is really simple. It just iterates over modules and counts cells. It extends the Pass class from the Yosys API. It gets the list of modules and loops over them to get the cells in each module.
#include "kernel/yosys.h"
USING_YOSYS_NAMESPACE
PRIVATE_NAMESPACE_BEGIN
struct CountCellsPass : public Pass {
CountCellsPass() : Pass("count_cells", "count cells in design") { }
void help() override
{
log("\n");
log(" count_cells [selection]\n");
log("\n");
log("This pass counts the number of cells in the current design.\n");
log("\n");
}
void execute(std::vector<std::string> args, RTLIL::Design *design) override
{
log_header(design, "Executing COUNT_CELLS pass.\n");
// Process arguments
size_t argidx;
for (argidx = 1; argidx < args.size(); argidx++) {
break;
}
extra_args(args, argidx, design);
// Iterate through all modules in the design
std::map<RTLIL::IdString, int> cell_types;
for (auto module : design->selected_modules()) {
log("Module: %s\n", log_id(module->name));
int module_cells = 0;
// Iterate through all cells in the module
for (auto cell : module->selected_cells()) {
cell_types[cell->type]++;
module_cells++;
}
log(" Cells in module: %d\n", module_cells);
}
log("\n");
log("Cell type statistics:\n");
log("---------------------\n");
for (auto &it : cell_types) {
log(" %-30s : %5d\n", log_id(it.first), it.second);
}
}
} CountCellsPass;
PRIVATE_NAMESPACE_END
And hooray!
5. Executing COUNT_CELLS pass.
Module: adder
Cells in module: 2
Module: counter
Cells in module: 2
Module: top
Cells in module: 3
Cell type statistics:
---------------------
$add : 3
$adffe : 1
$reduce_or : 1
adder : 1
counter : 1
---------------------