Skip to content

Plugin Development for Kactus2

hagantsa edited this page Feb 29, 2024 · 1 revision

Installing the plugin templates

You need Kactus2 source code to develop plugins. There are separate instructions on how to build Kactus2 from source code in the Kactus2 repository

Download and unzip the plugin templates, and place them to directory /Plugins.

Place the test suite template to directory /tests/Plugins.

Non-Visual Studio installation

Each plugin comes with a pro and pri files usable for installation. Open file Kactus2_Solution.pro and add the relative paths of the new pro files to list SUBDIRS.

On Linux installation, you have to configure, make, and install again at this point. This procedure is explained in the readme of the Kactus2 repo.

When you need to add new files to the plugin, you have to add their relative paths to the pri file, unless you generate a new pri file from Visual Studio.

When you need to rename your plugin, you may also need to modify some definitions in the pro file: DEFINES, TARGET, and include. Notice, that the pro file includes the pri file, so if you rename the pri file as well, you have to change the include. You may also need to rename preprocessor macros in file sample_global.h.

Visual Studio installation

Add the plugin projects to Kactus2 solution. This can be done by navigating to File -> Add... -> Existing project. Notice that with Visual Studio 2022, you cannot add new projects to the solution if debugger is running, so make sure that you have closed Kactus2. Build the plugins. The plugin files should appear to directory /executable/Plugins.

In case you wish to change names of plugins, notice that renaming files and variables may not be enough: You may need to also change some preprocessor macros in file sample_global.h as well as the Visual Studio preprocessor definitions setting, as illustrated in the image below.

Plugin renaming

If you wish to keep the Linux installation files of a plugin up to date, you may export pri files from Visual Studio: Right click the plugin project for context menu, choose Qt and select Export Project to .pri File... You need to do this if you add, remove or rename files within the project.

Installing sample library

This tutorial uses the sample plugins in conjunction with sample IP-XACT components and designs, also available in GitHub: https://github.com/kactus2/ipxactexamplelib

After you have downloaded and unzipped the library, configure Kactus2 to use it. The documents used with each sample plugin are catalogued in library tut.fi:examples.

Sample Generator

Sample Generator works in conjunction with generation_sample, as is illustrated in the image below: Open the HW design of generation_sample, unlock, and press Sample Generator button found behind the generation button. If you do not see the Sample generator option, something probably went wrong with the build. Re-check the instructions on installing the plugin templates. Moreover, the Sample generator option will not appear on a component tab, as it is designed to work with a design. This sample generator creates a text file containing the file sets of the component instances of the generation_sample design.

Sample generator

The following output should be seen after generation is complete:
sample_generator_output

The generation should result in a new file within a new file set, which are added to the top component:
Fileset generated by sample generator

Now, if you open the source file SampleParser.cpp, you will notice there function parse. It finds all component instances in the design, gets their associated components, and looks for file sets with at least one file. Since there are 3 instances of component SampleIP, which does have a file set with a file, three file sets are found.

As illustrated in the image below, function parse is called from function runGenerator within file SampleGeneratorPlugin.cpp. Function runGenerator is called by Kactus2 core when generator is ran. After the parsing the result is passed to function write in file SampleWriter.cpp, which creates the file and the file set as needed, and then generates content to them.

Generator architecture

This sort of architecture has been proven to be a good practice for generator plugin development, especially if you plan to implement unit testing for the plugin: It is easier to verify the parsed objects rather than the raw output. On the other hand, the output may have its own test suite, which uses mock-up of parsed data rather than IP-XACT models.

Moreover, generator plugins may display dialogs to the user, so the writer does not need to directly write a file to the file system, but instead create the content for preview. Naturally, this would adjust the architecture somewhat, since the main plugin class would have to create and execute a dialog, and thus the model class of the dialog would have to handle the generation pipeline. Examples of this sort of generators are the Verilog and VHDL generators of Kactus2.

Sample Plugin Test Suite

For unit testing the sample plugins, use directory /tests/Plugins/SamplePluginTestSuite as the location for the files of the sample test suite. The relative path to file tst_SampleGenerator.pro can be inserted as a subdirectory in file /tests/Plugins/plugins.pro to be able to run all plugin tests easily. If using Visual Studio, the VS project files need to be created from the .pro file using the Qt VS Tools addon (Extensions -> Qt VS Tools -> Open Qt Project File (.pro)...). This will generate the .vcxproj files that can be opened in Visual Studio.

The sample test suite works in conjunction with the sample generator, so it shall assume that the files of the sample generator are placed in directory /Plugins/SampleGenerator. The tests are contained in file tst_SampleGenerator.cpp with three test cases: Two for the pre-parsing and one for actual generator output. The cases use some convenience functions for repeated operations, such as creating mock components and designs for the test cases and for verifying the output.

When the number of test cases grows large, it is good practice split them to multiple test suites. For instance, splitting verification of pre-parsing and generation may be good idea, since they mostly use separate convenience functions.

Sample Importer

The Sample Importer reads a .c file and highlights the first return statement it encounters and the main function. It also creates a wire port for the component to simulate what an import plugin could do. Sample Importer uses the component SampleIP as an example, as illustrated in the image below: Open the component, unlock, and press the import button at the top ribbon. Then select Next. From the import source file page, select file main.c as the top-level file to import. The import wizard should consequently show two highlighted text sections. The last page of the wizard should show that one port was created. After the import is done, the new port should appear in the ports of the component.

Sample import dialog Sample import generated port

The implementation of the Sample Importer is within file SampleImportPlugin.cpp. Function getSupportedFileTypes returns which file types are supported by this importer. Function import contains the actual functionality: It highlights main based on exact match, and the return statement based on a regular expression. In addition, the import function contains the code which adds port Sample.

The Sample Importer also showcases plugin settings: As illustrated in the image below they are accessible via Kactus2 settings at the Plugins page. The widgets within group Settings are customizable for the plugin. In case of the Sample Importer, you may switch off highlighting the main and add a suffix to the imported port.

Sample import settings

The settings data is stored within class SampleImportSettingsModel. Function loadSettings is called when Kactus2 is launched and the plugin is loaded. Function saveSettings is called when settings are applied: The pending settings become the current settings and they are saved to the settings file. See more details at https://doc.qt.io/qt-6.2/qsettings.html. Function validateSettings is called for validation of the settings: It enforces the rule that suffix must be less than 10 characters.

The Sample Importer initializes the model in its constructor. Widget SampleImportSettingsWidget is created when requested by Kactus2 core and the model is given to its constructor as a parameter. The widget passes the user input to the model as pending changes and catches the error messages from the model and displays them.

Sample Source Analyzer

Sample Source Analyzer uses SW component LoremIpsum as an example, as illustrated in the image below: Open the component, unlock, select File sets. Here you can see that the file dependencies of the files in the fileset should be illustrated. If no dependencies are shown, press the "rescan" button denoted by the green arrow to scan for dependencies.

Sample source analyzer

The implementation of the Sample Source Analyzer is in file SampleSourceAnalyzer.cpp. Its core functionality is within function getFileDependencies, which goes through a single file given to it as a parameter. From each line it searches for statement "needs " and interpretes the rest of the line as the name of a needed file, creates a dependency struct, and appends it to the list. After all lines are parsed, the list is returned. The arrows denoting the dependencies are drawn based on the list.

Moreover, file SampleSourceAnalyzer.cpp contains function calculateHash, which is used to generate a hash based on the file content. Based on the hash, Kactus2 detects changes on the files. For instance, you could add line "needs LoremIpsum.txt" to file Bot.txt, rescan, and then the dependency visualizer should illustrate the changes.

In this case, all of a file is used to calculate a hash, meaning that any change in the content means a changed file. It is recommended that whitespaces and comments are removed from the feed before a calculation as those do not generally affect the dependencies or the functionality of a file.