Chain-Load: integrate topology visualisation (DOT)
- provide as ''operator'' on the TestChainLink instance - show shortened Node-Hash as label on each Node
This commit is contained in:
parent
76f250a5cf
commit
cc56117574
6 changed files with 200 additions and 125 deletions
|
|
@ -109,6 +109,79 @@ namespace dot_gen { ///< Collection of builder DSL functions to generate Graphvi
|
|||
};
|
||||
|
||||
|
||||
|
||||
/** generate a Node name or a node_statement
|
||||
* defining attributes of that node. All variables
|
||||
* use the format `N<number>`. */
|
||||
struct Node : Code
|
||||
{
|
||||
Node (size_t id)
|
||||
: Code{"N"+toString(id)}
|
||||
{ }
|
||||
|
||||
Node&&
|
||||
addAttrib (string def)
|
||||
{
|
||||
if (back() != ']')
|
||||
append ("[");
|
||||
else
|
||||
{
|
||||
resize (length()-2);
|
||||
append (", ");
|
||||
}
|
||||
append (def+" ]");
|
||||
return move(*this);
|
||||
}
|
||||
|
||||
Node&&
|
||||
label (string text)
|
||||
{
|
||||
return addAttrib ("label=\""+text+"\"");
|
||||
}
|
||||
|
||||
Node&&
|
||||
style (Code const& code)
|
||||
{
|
||||
if (not isnil(code))
|
||||
addAttrib (code);
|
||||
return move(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** accumulator to collect nodes grouped into a scope */
|
||||
struct Scope : Code
|
||||
{
|
||||
Scope (size_t id)
|
||||
: Code{"{ /*"+toString(id)+"*/ }"}
|
||||
{ }
|
||||
|
||||
Scope&&
|
||||
add (Code const& code)
|
||||
{
|
||||
resize(length()-1);
|
||||
append (code+" }");
|
||||
return move(*this);
|
||||
}
|
||||
|
||||
Scope&&
|
||||
rank (string rankSetting)
|
||||
{
|
||||
return add(Code{"rank="+rankSetting});
|
||||
}
|
||||
};
|
||||
|
||||
inline Node node (size_t id) { return Node(id); }
|
||||
inline Scope scope (size_t id) { return Scope(id); }
|
||||
|
||||
/** generate a directed node connectivity clause */
|
||||
inline Code
|
||||
connect (size_t src, size_t dest)
|
||||
{
|
||||
return Code{Node(src) +" -> "+ Node(dest)};
|
||||
}
|
||||
|
||||
|
||||
/** Helper to collect DOT-Graphviz code for output */
|
||||
class DotOut
|
||||
{
|
||||
|
|
@ -154,76 +227,6 @@ namespace dot_gen { ///< Collection of builder DSL functions to generate Graphvi
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/** generate a Node name or a node_statement
|
||||
* defining attributes of that node. All variables
|
||||
* use the format `N<number>`. */
|
||||
struct Node : Code
|
||||
{
|
||||
Node (size_t id)
|
||||
: Code{"N"+toString(id)}
|
||||
{ }
|
||||
|
||||
Node&&
|
||||
addAttrib (string def)
|
||||
{
|
||||
if (back() != ']')
|
||||
append ("[");
|
||||
else
|
||||
{
|
||||
resize (length()-2);
|
||||
append (", ");
|
||||
}
|
||||
append (def+" ]");
|
||||
return move(*this);
|
||||
}
|
||||
|
||||
Node&&
|
||||
label (size_t i)
|
||||
{
|
||||
return addAttrib ("label="+toString(i));
|
||||
}
|
||||
|
||||
Node&&
|
||||
style (Code const& code)
|
||||
{
|
||||
if (not isnil(code))
|
||||
addAttrib (code);
|
||||
return move(*this);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** accumulator to collect nodes grouped into a scope */
|
||||
struct Scope : Code
|
||||
{
|
||||
Scope (size_t id)
|
||||
: Code{"{ /*"+toString(id)+"*/ }"}
|
||||
{ }
|
||||
|
||||
Scope&&
|
||||
add (Code const& code)
|
||||
{
|
||||
resize(length()-1);
|
||||
append (code+" }");
|
||||
return move(*this);
|
||||
}
|
||||
|
||||
Scope&&
|
||||
rank (string rankSetting)
|
||||
{
|
||||
return add(Code{"rank="+rankSetting});
|
||||
}
|
||||
};
|
||||
|
||||
/** generate a directed node connectivity clause */
|
||||
inline Code
|
||||
connect (size_t src, size_t dest)
|
||||
{
|
||||
return Code{Node(src) +" -> "+ Node(dest)};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Entrance-point: generate a graph spec in DOT-Language.
|
||||
* @param parts a sequence of Section or Code objects to be combined and rendered
|
||||
|
|
|
|||
|
|
@ -325,6 +325,7 @@ namespace util {
|
|||
using std::setw;
|
||||
using std::right;
|
||||
using std::setfill;
|
||||
using std::uppercase;
|
||||
using std::noshowbase;
|
||||
using std::ostringstream;
|
||||
using std::ostream;
|
||||
|
|
@ -399,5 +400,24 @@ namespace util {
|
|||
{ return FAILURE_INDICATOR; }
|
||||
|
||||
|
||||
string
|
||||
showHash (size_t hash, uint showBytes) noexcept
|
||||
try {
|
||||
showBytes = util::limited (1u, showBytes, 8u);
|
||||
size_t suffix_modulus = size_t(1) << showBytes * 8;
|
||||
ostringstream buffer;
|
||||
buffer << hex
|
||||
<< uppercase
|
||||
<< noshowbase
|
||||
<< setw (showBytes * 2) // need 2 hex digits per byte
|
||||
<< setfill('0')
|
||||
<< right
|
||||
<< (showBytes==8? hash : hash % suffix_modulus);
|
||||
return buffer.str();
|
||||
}
|
||||
catch(...)
|
||||
{ return FAILURE_INDICATOR; }
|
||||
|
||||
|
||||
|
||||
} // namespace util
|
||||
|
|
|
|||
|
|
@ -91,6 +91,16 @@ namespace util {
|
|||
/** preconfigured format for pretty-printing of addresses */
|
||||
std::ostream& showAddr (std::ostream&, void const* addr);
|
||||
|
||||
/** renders the size_t in hex, optionally only trailing bytes */
|
||||
std::string showHash (size_t hash, uint showBytes=8) noexcept;
|
||||
|
||||
inline std::string
|
||||
showHashLSB (size_t hash) noexcept
|
||||
{
|
||||
return showHash(hash,1);
|
||||
}
|
||||
|
||||
|
||||
|
||||
namespace {
|
||||
/** toggle to prefer specialisation with direct lexical conversion */
|
||||
|
|
|
|||
|
|
@ -170,50 +170,12 @@ namespace test {
|
|||
verify_Topology()
|
||||
{
|
||||
auto graph = TestChainLoad<32>{}
|
||||
.buildToplolgy();
|
||||
.buildToplolgy()
|
||||
.printTopologyDOT();
|
||||
|
||||
CHECK (31 == graph.topLevel());
|
||||
CHECK (0 == graph.getSeed());
|
||||
CHECK (0 == graph.getHash());
|
||||
|
||||
///////////////////////////////////////////////////////////////////////TODO : what follows is WIP to test the DOT graph generator....
|
||||
using N = const TestChainLoad<32>::Node;
|
||||
|
||||
using namespace dot;
|
||||
Section nodes("Nodes");
|
||||
Section layers("Layers");
|
||||
Section topology("Topology");
|
||||
|
||||
Code BOTTOM{"shape=doublecircle"};
|
||||
Code SEED {"shape=circle"};
|
||||
Code TOP {"shape=box, style=rounded"};
|
||||
Code DEFAULT{};
|
||||
|
||||
N& n0n = *graph.allNodes();
|
||||
auto nNr = [&](N& nn){ return size_t(&nn - &n0n); };
|
||||
size_t level(0);
|
||||
Scope timeLevel{level};
|
||||
layers += timeLevel.rank("min ");
|
||||
for (N& nn : graph.allNodes())
|
||||
{
|
||||
size_t i = nNr(nn);
|
||||
nodes += Node(i).label(i+1).style(i==0 ? BOTTOM
|
||||
:isnil(nn.pred)? SEED
|
||||
:isnil(nn.succ)? TOP
|
||||
: DEFAULT);
|
||||
for (N* suc : nn.succ)
|
||||
topology += connect(i, nNr(*suc));
|
||||
|
||||
if (level != nn.level)
|
||||
{
|
||||
++level;
|
||||
ENSURE (level == nn.level);
|
||||
timeLevel = Scope(level).rank("same");
|
||||
layers += timeLevel;
|
||||
}
|
||||
timeLevel.add(Node(i));
|
||||
}
|
||||
cout << digraph(nodes,layers,topology) <<endl;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -86,6 +86,7 @@
|
|||
//#include "lib/meta/function.hpp"
|
||||
//#include "lib/wrapper.hpp"
|
||||
#include "lib/iter-explorer.hpp"
|
||||
#include "lib/format-cout.hpp"
|
||||
#include "lib/dot-gen.hpp"
|
||||
|
||||
#include <boost/functional/hash.hpp>
|
||||
|
|
@ -111,6 +112,8 @@ namespace test {
|
|||
// using lib::meta::RebindVariadic;
|
||||
using util::max;
|
||||
using util::unConst;
|
||||
using util::toString;
|
||||
using util::showHashLSB;
|
||||
// using std::forward;
|
||||
// using std::string;
|
||||
using std::swap;
|
||||
|
|
@ -256,7 +259,7 @@ namespace test {
|
|||
/**
|
||||
* Use current configuration and seed to (re)build Node connectivity.
|
||||
*/
|
||||
TestChainLoad
|
||||
TestChainLoad&&
|
||||
buildToplolgy()
|
||||
{
|
||||
NodeTab a,b, // working data for generation
|
||||
|
|
@ -331,6 +334,66 @@ namespace test {
|
|||
return move(*this);
|
||||
}
|
||||
|
||||
|
||||
/* ===== Operators ===== */
|
||||
|
||||
std::string
|
||||
generateTopologyDOT()
|
||||
{
|
||||
using namespace dot;
|
||||
|
||||
Section nodes("Nodes");
|
||||
Section layers("Layers");
|
||||
Section topology("Topology");
|
||||
|
||||
// Styles to distinguish the computation nodes
|
||||
Code BOTTOM{"shape=doublecircle"};
|
||||
Code SEED {"shape=circle"};
|
||||
Code TOP {"shape=box, style=rounded"};
|
||||
Code DEFAULT{};
|
||||
|
||||
auto nodeID = [&](Node& nn){ return size_t(&nn - &nodes_->front()); };
|
||||
|
||||
// prepare time-level zero
|
||||
size_t level(0);
|
||||
auto timeLevel = scope(level);
|
||||
layers += timeLevel.rank("min ");
|
||||
|
||||
for (Node& n : allNodes())
|
||||
{
|
||||
size_t i = nodeID(n);
|
||||
nodes += node(i).label(toString(i)+": "+showHashLSB(n.hash))
|
||||
.style(i==0 ? BOTTOM
|
||||
:isnil(n.pred)? SEED
|
||||
:isnil(n.succ)? TOP
|
||||
: DEFAULT);
|
||||
for (Node* suc : n.succ)
|
||||
topology += connect (i, nodeID(*suc));
|
||||
|
||||
if (level != n.level)
|
||||
{// switch to next time-level
|
||||
++level;
|
||||
ENSURE (level == n.level);
|
||||
timeLevel = scope(level).rank("same");
|
||||
layers += timeLevel;
|
||||
}
|
||||
timeLevel.add (node(i));
|
||||
}
|
||||
|
||||
// combine and render collected definitions as DOT-code
|
||||
return digraph (nodes, layers, topology);
|
||||
}
|
||||
|
||||
TestChainLoad&&
|
||||
printTopologyDOT()
|
||||
{
|
||||
cout << "───═══───═══───═══───═══───═══───═══───═══───═══───═══───═══───\n"
|
||||
<< generateTopologyDOT()
|
||||
<< "───═══───═══───═══───═══───═══───═══───═══───═══───═══───═══───"
|
||||
<< endl;
|
||||
return move(*this);
|
||||
}
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -95851,9 +95851,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
<node CREATED="1700100288256" ID="ID_844700164" MODIFIED="1700100289765" TEXT="control_Topology">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700100290904" ID="ID_1991398605" MODIFIED="1700100351351" TEXT="brauche Hilfsmittel zur Visualisierung">
|
||||
<node COLOR="#338800" CREATED="1700100290904" ID="ID_1991398605" MODIFIED="1700156439824" TEXT="brauche Hilfsmittel zur Visualisierung">
|
||||
<arrowlink COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" STARTARROW="None" STARTINCLINATION="787;55;"/>
|
||||
<icon BUILTIN="pencil"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700100356900" FOLDED="true" HGAP="45" ID="ID_216360062" LINK="#ID_764096140" MODIFIED="1700105412090" TEXT="erst mal einfaches Referenz-Skript (re)-generieren" VSHIFT="-5">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node CREATED="1700100394556" ID="ID_587545230" MODIFIED="1700100416123" TEXT="die entsprechende Node-Struktur fest verdrahtet aufbauen"/>
|
||||
|
|
@ -96011,11 +96011,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699971822836" ID="ID_1118263931" MODIFIED="1699971831481" TEXT="Diagnostik">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1699972014017" ID="ID_1464042796" MODIFIED="1700100343215" TEXT="Topologie sichtbar machen">
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699971822836" ID="ID_1118263931" MODIFIED="1700156360589" TEXT="Diagnostik">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1699972014017" FOLDED="true" ID="ID_1464042796" MODIFIED="1700156443450" TEXT="Topologie sichtbar machen">
|
||||
<linktarget COLOR="#62819c" DESTINATION="ID_1464042796" ENDARROW="Default" ENDINCLINATION="21;-256;" ID="Arrow_ID_596151514" SOURCE="ID_1991398605" STARTARROW="None" STARTINCLINATION="787;55;"/>
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1699972026007" ID="ID_551004748" MODIFIED="1700105381375" TEXT="Idee: DOT generieren (Graphviz)">
|
||||
<arrowlink COLOR="#435fb4" DESTINATION="ID_1402372766" ENDARROW="Default" ENDINCLINATION="-1358;124;" ID="Arrow_ID_1189460163" STARTARROW="None" STARTINCLINATION="-1697;146;"/>
|
||||
<icon BUILTIN="idea"/>
|
||||
|
|
@ -96162,8 +96162,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
</node>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699983287679" ID="ID_1236079516" MODIFIED="1700105397578" TEXT="Ausgabestruktur erzeugen">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1699983287679" ID="ID_1236079516" MODIFIED="1700156324205" TEXT="Ausgabestruktur erzeugen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#435e98" CREATED="1699983387905" FOLDED="true" ID="ID_1906181979" MODIFIED="1700105376397" TEXT="muß Klammern und Gruppen erzeugen">
|
||||
<icon BUILTIN="messagebox_warning"/>
|
||||
<icon BUILTIN="hourglass"/>
|
||||
|
|
@ -96415,23 +96415,36 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="yes"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1699983654942" ID="ID_1968810638" MODIFIED="1700105304336" TEXT="lokale Spezialisierung hiervon im Arbeits-Scope">
|
||||
<icon BUILTIN="pencil"/>
|
||||
<node COLOR="#338800" CREATED="1699983654942" ID="ID_1968810638" MODIFIED="1700156322919" TEXT="DSL verwenden zur Visualisierung">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700105305528" ID="ID_1899482943" MODIFIED="1700105320553" TEXT="testweise direkt im verify_Topology() aufgebaut">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#435e98" CREATED="1700105322133" ID="ID_1080416201" MODIFIED="1700105347114" TEXT="einfache For-Schleife mit »schleppendem« time-Level">
|
||||
<icon BUILTIN="idea"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700156293989" ID="ID_1727407041" MODIFIED="1700156304913" TEXT="Node-ID direkt aus Speicher-Offset ableiten">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700156308658" ID="ID_646954295" MODIFIED="1700156321018" TEXT="Hash gekürzt darstellen (1byte)">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700156287032" ID="ID_1166019368" MODIFIED="1700156292918" TEXT="Formate vorbelegen">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eef0c5" COLOR="#990000" CREATED="1700147510434" ID="ID_1659345454" MODIFIED="1700151160461" TEXT="Extrahieren und reorganisieren">
|
||||
<icon BUILTIN="pencil"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700147510434" ID="ID_1659345454" MODIFIED="1700156327130" TEXT="Extrahieren und reorganisieren">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
<node COLOR="#338800" CREATED="1700147703792" ID="ID_1662535458" MODIFIED="1700151155878" TEXT="separater Header: lib/dot-gen.hpp">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700151162860" ID="ID_479859970" MODIFIED="1700151187644" TEXT="Graph-generierungs-Code in eigenen Operator extrahieren">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
<node COLOR="#338800" CREATED="1700151162860" ID="ID_479859970" MODIFIED="1700156416376" TEXT="Graph-generierungs-Code in eigenen Operator extrahieren">
|
||||
<arrowlink COLOR="#42b360" DESTINATION="ID_1175949615" ENDARROW="Default" ENDINCLINATION="334;0;" ID="Arrow_ID_357935660" STARTARROW="None" STARTINCLINATION="-103;5;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700156329113" ID="ID_1238209773" MODIFIED="1700156340930" TEXT="alternativ direkt nach SDOUT schreiben">
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
</node>
|
||||
|
|
@ -96448,6 +96461,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200<br/>
|
|||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
</node>
|
||||
<node COLOR="#338800" CREATED="1700156375137" ID="ID_1175949615" MODIFIED="1700156408543" TEXT="Topologie-Visualisierung">
|
||||
<linktarget COLOR="#42b360" DESTINATION="ID_1175949615" ENDARROW="Default" ENDINCLINATION="334;0;" ID="Arrow_ID_357935660" SOURCE="ID_479859970" STARTARROW="None" STARTINCLINATION="-103;5;"/>
|
||||
<icon BUILTIN="button_ok"/>
|
||||
</node>
|
||||
<node BACKGROUND_COLOR="#eee5c3" COLOR="#990000" CREATED="1700105549294" ID="ID_1778641158" MODIFIED="1700105554766" TEXT="Neuberechnung">
|
||||
<icon BUILTIN="flag-yellow"/>
|
||||
</node>
|
||||
|
|
|
|||
Loading…
Reference in a new issue