-
Notifications
You must be signed in to change notification settings - Fork 0
Loader Plug‐in
File Loader plug-ins read a circuit description from a file and initialize the internal graph representation. Each input file format can be supported by a different plug-in. For example, the existing BLIF loader plug-in allows reading circuits from BLIF files.
Default loader plug-ins are BlifLoader and GEXFLoader.
The only method that must be overridden to wrote a file loader plug-in is
Elve::SharedGraph load(const QString &filepath) override;
whose prototype is self-explanatory: a path is passed to the method and the latter should return a valid Elve::SharedGraph.
If new plugin folder and files were created using the corresponding template (see Writing Plug‐ins) method implementation should look like this:
SharedGraph LoaderName::load(const QString &filepath) {
GraphData::Builder b;
//YOUR CODE HERE
//See GEFXLoader for a concrete example, avoid peeking in Blifloader as it is legacy code of pretty much bad quality
SharedData sdata = b.build(filepath); //Build the graph data
return make_shared<Graph>(sdata);
}
Existing code is most certainly to be kept, a builder is provided to create graph data without worrying about definition order or node existence. For standard file parsing, the builder will assign unique ids to nodes by itself. Providing the various properties of the nodes is sufficient, calling them by their name.
For example, creating an empty Node:
b.setType("myNodeName",NodeType::NODE);
Of course, this line is often just unnecessary as the default node type is NODE. So if any other property of the node is set, it gets created and assigned default values for the other properties.
Most used properties are the following:
- type, if the node is an input/output/cluster or combination of these.
- IOIndex, if the node is an input/output, it gives inputs/output an order.
- dependencies, that's the way nodes are connected, adding a node A to dependencies of a node B will make an edge from A to B, dependencies are, for short, the fan-in of a node. Adding dependencies with choose of the input and output the edge comes from/goes to is a bit more involved. See overloadings of the setDependencies method in the documentation.
- properties, this seems redundant but these are arbitrary properties that can be attached to the node, some of them are taken into account by other plugin's if provided. For example: 'level'.
- [input/output]Names allow setting the name of inputs and output of the node.
The following sample code gives examples for the above properties:
auto name = "sampleOutputNode";
b.setType(name,NodeType::OUTPUT); //Node is an output
b.setIoIndex(name,2); //Node is third output
b.setDependencies(name,Names{"ancestor1","ancestor2"}); //Setup ancestors of the node
b.addProperty(name,"color","0xF00"); //Set the color property of the node to red
b.setNodeInputNames(name,{"fromAncestor1", "fromAncestor2"}); //Setting the inputs names, order is preserved, this modify the inputCount accordingly.
For concrete examples, see GEXFLoader or BLIFLoader
To directly load a graph with ungroupable-groups, the whole graph must first be built flat (without any groups). Then either the Graph::group or Graph::fastGroup methods should be used to group the nodes. This will create a new SharedGraph with the groups set up. To make multiple depths of groups, nodes must be grouped in the right order, but it may appear that, for the moment, this could be done only with calls to Graph::group. So it is better to stick with Graph::group while doing multiple levels of groups, although it will be much slower than fastGroup. In the future, builder for layered groups should be provided for easier use.
Calls to Graph::group allows to create groups of nodes. But if some part of the graph are to be hidden, or some edges must be routed differently, Aliases and Exclusion must be used.
By using an overloaded constructor for the Graph. Additional information can be provided and the Graph will be created with holes and redirections. This is how groups are done under-the-hood. Aliases and Excluded type are pretty easy to construct by looking at the Graph documentation.
It is good to keep in mind that Aliases are separated for inputs and outputs and that they are evaluated recursively. Meaning that if A is aliased to B and B aliased to C. And edge from D to A will be changed to be an edge from D to C.
To use file loader plug-ins their shared libraries (.so,.dll,.dynlib...) must be placed in:
<elve_root>/plugins/loaders
they are then available trough the File->Import menu and trough the CLI by issuing commands of this form:
load_<plugin_cli_name> <filepath>
Using CLI or GUI is fully equivalent, as the GUI button will construct the commands and issue them.
ELVE is developed and maintained by the Processor Architecture Lab, EPFL.
You can contact us at elve@groupes.epfl.ch.