I sketched out a few early ideas in code to get a feel on good approaches in software. As the DAG is being generated by a builder, I wanted to see if it was possible to use std::array for inputs rather than std::vector. Regardless, my first doodle was more just a simple DAG structure exploring the concepts of adding hardware dependencies: https://godbolt.org/g/5y3Gsa
This was very useful in identifying a minimal DAG node, called a Task in this example. A few points:
- Technically I don’t need to store the inputs as I’ll be processing this DAG top to bottom.
- The idea of serial and parallel operations being simple derivatives of task
- All operations on the device would be task derivatives.
- Avoid cycles during insertion (possible to static assert if DAG size is known at constrcution?)
The main() block makes a conceptual jump into a nice syntax for a builder class that builds up the DAG in a readable way, sort of like a DSL for lab protocols. The base TaskBuilder class is responsible for generating a single DAG node. The TaskBuilderContainer is responsible for a list of DAG nodes, and is derived from Task with an extra method end() to indicate the end of a scope block.
These builder classes are nicely wrapped up readable class methods like add_ingredient() or preheat(). recipe() should really be called workflow() and takes a name.