Plugins of Nestor.
A plugin is a code transformation. A plugin is a piece of C++ code that gets a part of a tree (an NstTree object). This tree can be transformed, analyzed, and the result must be returned by the plugin. A plugin is dynamically linked by GTK Nestor when it is used. A plugin must always provide two functions: plugin_init and plugin_run. the first function sets the parameters of the plugin, its name, its description, etc... In the case of GTK Nestor, the arguments of the plugin automatically build a GUI when the plugin is selected. The function plugin_run is the function that is called when the plugin is applied to a piece of code.
Here is the example of a plugin that checks if the loops that are under the NstTree object passed as parameter are parallel or not. This plugin uses the class CheckParallelLoop to check if a loop is parallel. This code can be found under the directory src/plugins/test_plug. To add a new plugin, just create a new directory under the directory src/plugins, copy the Makefile from another plugin's source directory, write the code of your plugin and that's it. Just type make in the main directory of Nestor, and your plugin will be copied into bin/plugins and recognized by GTK Nestor.
#include <nst_plug.H> #define NAME "Check parallel loop" #define DESC "\ Checks if a loop nest is parallel.\n\ Adds a directive in front of the loop \n\ nest if the loop is parallel.\n" #define COPYRIGHT "no copyright" #define SUMM "Adds a directive if a loop nest is parallel" int plugin_init(struct arglist* desc) { plug_set_name(desc, NAME); plug_set_description(desc, DESC); plug_set_summary(desc, SUMM); plug_set_copyright(desc, COPYRIGHT); return(0); } int plugin_run(struct arglist * args) { NstTree* tree = plug_get_tree(args); char* report_file = plug_get_report(args); if (!tree || !report_file) return 1; ofstream plug(report_file); if (!plug) { plug_set_error(args, "Cannot open report file."); return 1; } CheckParallelLoop checker(*tree, (ofstream*)&plug); plug_set_report(args, report_file); plug_set_tree(args, tree); return 0; }Here is another example that has parameters. This example adds a data distribution for a given array declaration. This distribution is added at the end of the declaration list. If a distribution already exists, it is replaced by the new distribution. This plugin can be found under the directory src/plugins/insert_distri.
#include <nst_plug.H> #define NAME "Adds a distribution" #define DESC "\ Inserts an HPF distribution by BLOCK for an array that is already\n\ declared.\n" #define COPYRIGHT "no copyright" #define SUMM "Inserts an HPF BLOCK distribution for an array" void insert_distribution(NstDeclarationVariable* dv, int, int); void modify_distribution(NstDeclarationDistribute* dd, NstDeclarationVariable* dv, int, int); NstDeclarationDistribute* search_existing_distribution(NstDeclarationList* father, NstDeclarationVariable* dv); int plugin_init(struct arglist* desc) { plug_set_name(desc, NAME); plug_set_description(desc, DESC); plug_set_summary(desc, SUMM); plug_set_copyright(desc, COPYRIGHT); plug_set_arguments(desc); plug_add_argument(desc, "Type of distribution", P_SET, NULL); // This element has the number 2. plug_add_argument_element(desc, "Type of distribution", "BLOCK"); // This element has the number 1. plug_add_argument_element(desc, "Type of distribution", "CYCLIC"); plug_add_argument(desc, "Size of distribution", P_INT, (void*)0); return(0); } int plugin_run(struct arglist * args) { NstTree* tree = plug_get_tree(args); NstDeclarationList* father = dynamic_cast<NstDeclarationList*>(tree->in()); NstDeclarationVariable* dv = dynamic_cast<NstDeclarationVariable*>(tree); if (!dv) { plug_set_error(args, "This plugin expects a variable declaration."); return 1; } if (!father) { plug_set_error(args, "I need a declaration list to insert a distribution."); return 1; } int dtype = (int)plug_get_argument(args, "Type of distribution"); int dsize = (int)plug_get_argument(args, "Size of distribution"); if (NstDeclarationDistribute* old_dist = search_existing_distribution(father, dv)) modify_distribution(old_dist, dv, dtype, dsize); else insert_distribution(dv, dtype, dsize); plug_set_tree(args, (NstTree*)father); return 0; } NstDeclarationDistribute* search_existing_distribution(NstDeclarationList* father, NstDeclarationVariable* dv) { NstDeclarationDistribute* ret = NULL; NstDeclarationList::iterator it = father->begin(); for(; it != father->end(); it++) if (ret = dynamic_cast<NstDeclarationDistribute*>(*it)) if (ret->definition() == dv->definition()) return ret; return NULL; } NstDistformat* create_dist(int dtype, int dsize) { NstExpression* sz; if (dsize > 0) { NstInteger taille(dsize); sz = new NstExpressionConstant(taille); } else { sz = new NstExpressionDummy; } NstDistformat* df; if (dtype == 2) { df = new NstDistformatBlock(*sz); } else if (dtype == 1) { df = new NstDistformatCyclic(*sz); } assert(df); return df; } void modify_distribution(NstDeclarationDistribute* dd, NstDeclarationVariable* dv, int dtype, int dsize) { if (NstTypeArray* ta = dynamic_cast<NstTypeArray*>(dv->variable_type())) { int size = ta->shapes.size(); NstDistributionNode def_dist; NstDistformat* df = create_dist(dtype, dsize); while(size--) def_dist.mapping.push_back(*df); dd->distribution(def_dist); } } void insert_distribution(NstDeclarationVariable* dv, int dtype, int dsize) { if (NstTypeArray* ta = dynamic_cast<NstTypeArray*>(dv->variable_type())) { int size = ta->shapes.size(); NstDistributionNode def_dist; NstDistformat* df = create_dist(dtype, dsize); while(size--) def_dist.mapping.push_back(*df); NstProcessorDefault proc_def; NstDeclarationDistribute dist(*dv->definition(), def_dist, proc_def); NstDeclarationList *dl = dynamic_cast<NstDeclarationList*>(dv->in()); assert(dl); dl->push_back(dist); } }
this page has been generated automatically by doc++
(c)opyright by Malte Zöckler, Roland Wunderling
contact: doc++@zib.de