diff --git a/src/lib/dot-gen.hpp b/src/lib/dot-gen.hpp index e3f940d34..146adb6e9 100644 --- a/src/lib/dot-gen.hpp +++ b/src/lib/dot-gen.hpp @@ -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`. */ + 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`. */ - 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 diff --git a/src/lib/format-obj.cpp b/src/lib/format-obj.cpp index 7c8d79a8a..a08a66e73 100644 --- a/src/lib/format-obj.cpp +++ b/src/lib/format-obj.cpp @@ -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 diff --git a/src/lib/format-obj.hpp b/src/lib/format-obj.hpp index 8bf9bb778..79a6970ab 100644 --- a/src/lib/format-obj.hpp +++ b/src/lib/format-obj.hpp @@ -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 */ diff --git a/tests/vault/gear/test-chain-load-test.cpp b/tests/vault/gear/test-chain-load-test.cpp index 3c4a011cc..05dcdca36 100644 --- a/tests/vault/gear/test-chain-load-test.cpp +++ b/tests/vault/gear/test-chain-load-test.cpp @@ -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) < @@ -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: }; diff --git a/wiki/thinkPad.ichthyo.mm b/wiki/thinkPad.ichthyo.mm index 214f77ddb..5823ccd83 100644 --- a/wiki/thinkPad.ichthyo.mm +++ b/wiki/thinkPad.ichthyo.mm @@ -95851,9 +95851,9 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- + - + @@ -96011,11 +96011,11 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - - + + + - + @@ -96162,8 +96162,8 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + @@ -96415,23 +96415,36 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
- - + + + + + + + + + + - - + + + - - + + + + + + @@ -96448,6 +96461,10 @@ Date:   Thu Apr 20 18:53:17 2023 +0200
+ + + +