From 090c867eb81c00e5fd039bca3e5e0d24f922ef1b Mon Sep 17 00:00:00 2001 From: lukas-valenta-tul Date: Wed, 15 Oct 2025 18:59:22 +0200 Subject: [PATCH 1/5] Alternative dot print which helps understand the DAG using any dot graph creator --- include/expression_dag.hh | 53 +++++++++++++++++++++++++++++++++++++++ include/parser.hh | 1 + 2 files changed, 54 insertions(+) diff --git a/include/expression_dag.hh b/include/expression_dag.hh index da08bb5..2b44a47 100644 --- a/include/expression_dag.hh +++ b/include/expression_dag.hh @@ -102,6 +102,7 @@ public: /** * Print ScalarExpression graph in the dot format. + * Useful for debugging */ void print_in_dot() { std::map i_node; @@ -131,6 +132,58 @@ public: std::cout << "Node: " << node->op_name_ << "_" << node->result_idx_ << " " << node->result_storage << std::endl; } + /** + * Print ScalarExpression graph in the common dot format. + * Useful for understanding the DAG + */ + void print_in_dot2() { + sort_nodes(); + + std::cout << "\n" << "----- begin cut here -----" << "\n"; + std::cout << "digraph Expr {" << "\n"; + + std::cout << "/* definitions */" << "\n"; + std::cout << "edge [dir=back]" << "\n"; + for (uint i = 0; i < sorted.size(); ++i) { + _print_dot_node_definition(sorted[i]); + } + std::cout << "/* end of definitions */" << "\n"; + + for (uint i = 0; i < sorted.size(); ++i) { + for (uint in = 0; in < sorted[i]->n_inputs_; ++in) { + std::cout << " "; + _print_dot_node(sorted[i]); + std::cout << "\n -> "; + _print_dot_node(sorted[i]->inputs_[in]); + std::cout << "\n\n"; + } + } + std::cout << "}" << "\n"; + std::cout << "----- end cut here -----" << "\n"; + std::cout.flush(); + } + void _print_dot_node(ScalarNodePtr node) { + std::cout << node->op_name_ << "_" << (int)node.get() << "__" << node->result_storage;// << std::endl; + } + + void _print_dot_node_definition(ScalarNodePtr node) { + _print_dot_node(node); + std::cout << ' '; + + if (node->result_storage == ResultStorage::constant) { + std::cout << "[shape=circle,label=\"const " << *node->values_ << "\"]" << std::endl; + } + else if (node->result_storage == ResultStorage::constant_bool) { + std::cout << "[shape=circle,label=\"const " << *node->values_ << "\"]" << std::endl; + } + else if (node->result_storage == ResultStorage::expr_result) { + std::cout << "[shape=box,label=\"" << node->op_name_ << " " << node->result_idx_ << "\"]" << std::endl; + } + else { + std::cout << "[label=\"" << node->op_name_ << "\"]" << std::endl; + } + } + private: void _print_i_node(uint i) { diff --git a/include/parser.hh b/include/parser.hh index ca8bde1..ade2953 100644 --- a/include/parser.hh +++ b/include/parser.hh @@ -190,6 +190,7 @@ public: details::ExpressionDAG se(result_array_.elements()); //se.print_in_dot(); + //se.print_in_dot2(); processor = ProcessorBase::create_processor(se, max_vec_size, simd_size, arena); } From cb9414e2a97cdce2772d349c661d44a661c3e6e9 Mon Sep 17 00:00:00 2001 From: lukas-valenta-tul Date: Sun, 19 Oct 2025 16:58:29 +0200 Subject: [PATCH 2/5] Better cast --- include/expression_dag.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/expression_dag.hh b/include/expression_dag.hh index 2b44a47..64f95e3 100644 --- a/include/expression_dag.hh +++ b/include/expression_dag.hh @@ -163,7 +163,7 @@ public: std::cout.flush(); } void _print_dot_node(ScalarNodePtr node) { - std::cout << node->op_name_ << "_" << (int)node.get() << "__" << node->result_storage;// << std::endl; + std::cout << node->op_name_ << "_" << (uintptr_t)node.get() << "__" << node->result_storage;// << std::endl; } void _print_dot_node_definition(ScalarNodePtr node) { From 95d91c38f64a1659c60b1ad6162c432d9a410c90 Mon Sep 17 00:00:00 2001 From: lukas-valenta-tul Date: Mon, 20 Oct 2025 19:03:11 +0200 Subject: [PATCH 3/5] Improved print_in_dot2. If the symbols_ map is supplied, it will also print the variable and constant names in dot --- include/expression_dag.hh | 130 +++++++++++++++++++++++++++++++++----- include/parser.hh | 1 + 2 files changed, 115 insertions(+), 16 deletions(-) diff --git a/include/expression_dag.hh b/include/expression_dag.hh index 64f95e3..b57cfc5 100644 --- a/include/expression_dag.hh +++ b/include/expression_dag.hh @@ -15,6 +15,7 @@ #include "config.hh" #include "scalar_node.hh" #include "assert.hh" +#include "array.hh" namespace bparser { @@ -40,6 +41,8 @@ private: /// Result nodes, given as input. NodeVec results; + typedef std::pair InvDotNameAndScalar; + typedef std::map InvDotMap; /** * Used in the setup_result_storage to note number of unclosed nodes @@ -134,27 +137,45 @@ public: /** * Print ScalarExpression graph in the common dot format. - * Useful for understanding the DAG + * Useful for understanding the DAG. */ void print_in_dot2() { + print_in_dot2(InvDotMap()); + } + + /** + * Print ScalarExpression graph in the common dot format. + * Useful for understanding the DAG. Using the parser's map of var. Name -> Array find the inverse ScalarNodePtr -> var. Name + */ + void print_in_dot2(const std::map& symbols) { + print_in_dot2(create_inverse_map(symbols)); + } + + /** + * Print ScalarExpression graph in the common dot format. + * Useful for understanding the DAG. Using the map of ScalarNodePtr -> variableName + */ + void print_in_dot2(const InvDotMap& names) { + sort_nodes(); std::cout << "\n" << "----- begin cut here -----" << "\n"; std::cout << "digraph Expr {" << "\n"; std::cout << "/* definitions */" << "\n"; + std::cout << "edge [dir=back]" << "\n"; for (uint i = 0; i < sorted.size(); ++i) { - _print_dot_node_definition(sorted[i]); + _print_dot_node_definition(sorted[i],names); } std::cout << "/* end of definitions */" << "\n"; for (uint i = 0; i < sorted.size(); ++i) { for (uint in = 0; in < sorted[i]->n_inputs_; ++in) { std::cout << " "; - _print_dot_node(sorted[i]); + _print_dot_node_id(sorted[i]); std::cout << "\n -> "; - _print_dot_node(sorted[i]->inputs_[in]); + _print_dot_node_id(sorted[i]->inputs_[in]); std::cout << "\n\n"; } } @@ -162,30 +183,107 @@ public: std::cout << "----- end cut here -----" << "\n"; std::cout.flush(); } - void _print_dot_node(ScalarNodePtr node) { + + //Create a map of ScalarNodePtr -> (variable name, is_scalar) + InvDotMap create_inverse_map(const std::map& symbols) const { + InvDotMap inv_map; + if (symbols.empty()) return inv_map; + for (const auto& s : symbols) + { + for (const auto& n : s.second.elements()) { + inv_map[n] = std::pair(s.first, s.second.shape().empty()); + } + } + return inv_map; + } + + +private: + //Print the vertice identifier for dot + void _print_dot_node_id(const ScalarNodePtr& node) const { std::cout << node->op_name_ << "_" << (uintptr_t)node.get() << "__" << node->result_storage;// << std::endl; } - void _print_dot_node_definition(ScalarNodePtr node) { - _print_dot_node(node); + //Print how the vertice should look in dot + void _print_dot_node_definition(const ScalarNodePtr& node, const InvDotMap& invmap) const { + _print_dot_node_id(node); std::cout << ' '; - if (node->result_storage == ResultStorage::constant) { - std::cout << "[shape=circle,label=\"const " << *node->values_ << "\"]" << std::endl; + if (node->result_storage == ResultStorage::constant) { // Constant + std::cout << "[shape=circle,"; + + try { //If the constant has a name + std::string name(invmap.at(node).first); + std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; + } + catch (std::out_of_range) { //No name + std::cout << "label=\"" << "const " << *node->values_ << '"'; + } + std::cout << "]" << std::endl; + } + + else if (node->result_storage == ResultStorage::constant_bool) { //Constant bool + std::cout << "[shape=circle,"; + + try { //If the constant has a name + std::string name(invmap.at(node).first); + std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; + } + catch (std::out_of_range) { //No name + std::cout << "label=\"" << "const " << *node->values_ << '"'; + } + std::cout << "]" << std::endl; } - else if (node->result_storage == ResultStorage::constant_bool) { - std::cout << "[shape=circle,label=\"const " << *node->values_ << "\"]" << std::endl; + + else if (node->result_storage == ResultStorage::expr_result) { //Result + std::cout << "[shape=box,label=\"" << node->op_name_ << " [" << node->result_idx_ << "]" << "\"]" << std::endl; } - else if (node->result_storage == ResultStorage::expr_result) { - std::cout << "[shape=box,label=\"" << node->op_name_ << " " << node->result_idx_ << "\"]" << std::endl; + + else if (node->result_storage == ResultStorage::value) { // Value + + std::cout << "[shape=circle,"; + try { + std::string name(invmap.at(node).first); + bool scalar(invmap.at(node).second); + if (scalar) { + std::cout << "label=\"" << name << '"'; + } + else { + std::cout << "label=<" << name << "i" << '>'; + } + std::cout << ",group=\"" << name << '"'; + } + catch (std::out_of_range) { + std::cout << "label=<var>"; + } + + std::cout << "]" << std::endl; + } + + else if (node->result_storage == ResultStorage::value_copy) { //Value copy + std::cout << "[shape=circle,"; + try { + std::string name(invmap.at(node).first); + bool scalar(invmap.at(node).second); + if (scalar) { + std::cout << "label=\"" << name << '"'; + } + else { + std::cout << "label=<" << name << "i" << '>'; + } + std::cout << ",group=\"" << name << '"'; + } + catch (std::out_of_range) { + std::cout << "label=<var_cp>"; + } + std::cout << "]" << std::endl; } - else { + + else {//Temporary & other //Temporary & other std::cout << "[label=\"" << node->op_name_ << "\"]" << std::endl; } } - -private: void _print_i_node(uint i) { std::cout << sorted[i]->op_name_ << "_" << i << "_"<< sorted[i]->result_idx_; } diff --git a/include/parser.hh b/include/parser.hh index ade2953..781dbc8 100644 --- a/include/parser.hh +++ b/include/parser.hh @@ -191,6 +191,7 @@ public: //se.print_in_dot(); //se.print_in_dot2(); + //se.print_in_dot2(symbols_); processor = ProcessorBase::create_processor(se, max_vec_size, simd_size, arena); } From 12b37e909f8d269efbbdb8630c3715eab8b2774e Mon Sep 17 00:00:00 2001 From: lukas-valenta-tul Date: Mon, 20 Oct 2025 19:08:09 +0200 Subject: [PATCH 4/5] More appropriate catch blocks --- include/expression_dag.hh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/expression_dag.hh b/include/expression_dag.hh index b57cfc5..ab32ccb 100644 --- a/include/expression_dag.hh +++ b/include/expression_dag.hh @@ -216,7 +216,7 @@ private: std::string name(invmap.at(node).first); std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; } - catch (std::out_of_range) { //No name + catch (const std::out_of_range&) { //No name std::cout << "label=\"" << "const " << *node->values_ << '"'; } std::cout << "]" << std::endl; @@ -229,7 +229,7 @@ private: std::string name(invmap.at(node).first); std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; } - catch (std::out_of_range) { //No name + catch (const std::out_of_range&) { //No name std::cout << "label=\"" << "const " << *node->values_ << '"'; } std::cout << "]" << std::endl; @@ -253,7 +253,7 @@ private: } std::cout << ",group=\"" << name << '"'; } - catch (std::out_of_range) { + catch (const std::out_of_range&) { std::cout << "label=<var>"; } @@ -273,7 +273,7 @@ private: } std::cout << ",group=\"" << name << '"'; } - catch (std::out_of_range) { + catch (const std::out_of_range&) { std::cout << "label=<var_cp>"; } std::cout << "]" << std::endl; From 5bb3f9ac2146beabed02ed407985677471cd6394 Mon Sep 17 00:00:00 2001 From: lukas-valenta-tul Date: Sun, 9 Nov 2025 17:37:58 +0100 Subject: [PATCH 5/5] InverseMap now holds the indices of the node which is then printed to dot --- include/expression_dag.hh | 190 +++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 64 deletions(-) diff --git a/include/expression_dag.hh b/include/expression_dag.hh index ab32ccb..43a194f 100644 --- a/include/expression_dag.hh +++ b/include/expression_dag.hh @@ -41,8 +41,8 @@ private: /// Result nodes, given as input. NodeVec results; - typedef std::pair InvDotNameAndScalar; - typedef std::map InvDotMap; + typedef std::pair InvDotNameAndIndices; + typedef std::map InvDotMap; /** * Used in the setup_result_storage to note number of unclosed nodes @@ -190,9 +190,12 @@ public: if (symbols.empty()) return inv_map; for (const auto& s : symbols) { - for (const auto& n : s.second.elements()) { - inv_map[n] = std::pair(s.first, s.second.shape().empty()); + for (MultiIdx idx(s.second.range()); idx.valid();idx.inc_src()) { + inv_map[s.second[idx]] = InvDotNameAndIndices(s.first, idx.indices()); } + /*for (const auto& n : s.second.elements()) { + inv_map[n] = InvDotNameAndIndices(s.first, s.second.shape().empty()); + }*/ } return inv_map; } @@ -209,79 +212,138 @@ private: _print_dot_node_id(node); std::cout << ' '; - if (node->result_storage == ResultStorage::constant) { // Constant - std::cout << "[shape=circle,"; - - try { //If the constant has a name - std::string name(invmap.at(node).first); - std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; - } - catch (const std::out_of_range&) { //No name - std::cout << "label=\"" << "const " << *node->values_ << '"'; + switch (node->result_storage) { + case ResultStorage::constant: { // Constant + std::cout << "[shape=circle,"; + + try { //If the constant has a name + std::string name(invmap.at(node).first); + const MultiIdx::VecUint indices(invmap.at(node).second); + bool scalar(indices.empty()); + if (scalar) { + std::cout << "label=\"" << name << '=' << *node->values_ << '\"'; + } + else { + MultiIdx::VecUint::size_type size(indices.size()); + std::cout << "label=\"" << name << "["; + for (MultiIdx::VecUint::size_type i = 0; i < size; i++) { + std::cout << indices.at(i); + if (i != size - 1) { + std::cout << ','; + } + } + std::cout << "]"; + std::cout << '=' << *node->values_ << '\"'; + } + std::cout << ", group = \"" << name << '\"'; + } + catch (const std::out_of_range&) { //No name + std::cout << "label=\"" << "const " << *node->values_ << '"'; + } + std::cout << "]" << std::endl; + break; } - std::cout << "]" << std::endl; - } - else if (node->result_storage == ResultStorage::constant_bool) { //Constant bool - std::cout << "[shape=circle,"; - - try { //If the constant has a name - std::string name(invmap.at(node).first); - std::cout << "label=\"" << name << ": " << *node->values_ << "\",group=\"" << name << '"'; - } - catch (const std::out_of_range&) { //No name - std::cout << "label=\"" << "const " << *node->values_ << '"'; + case ResultStorage::constant_bool: { //Constant bool + std::cout << "[shape=circle,"; + + try { //If the constant has a name + std::string name(invmap.at(node).first); + const MultiIdx::VecUint indices(invmap.at(node).second); + bool scalar(indices.empty()); + if (scalar) { + std::cout << "label=\"" << name << '=' << *node->values_ << '\"'; + } + else { + MultiIdx::VecUint::size_type size(indices.size()); + std::cout << "label=\"" << name << "["; + for (MultiIdx::VecUint::size_type i = 0; i < size; i++) { + std::cout << indices.at(i); + if (i != size - 1) { + std::cout << ','; + } + } + std::cout << "]"; + std::cout << '=' << *node->values_ << '\"'; + } + std::cout << ", group = \"" << name << '\"'; + } + catch (const std::out_of_range&) { //No name + std::cout << "label=\"" << "const " << *node->values_ << '"'; + } + std::cout << "]" << std::endl; + break; } - std::cout << "]" << std::endl; - } - else if (node->result_storage == ResultStorage::expr_result) { //Result - std::cout << "[shape=box,label=\"" << node->op_name_ << " [" << node->result_idx_ << "]" << "\"]" << std::endl; - } - - else if (node->result_storage == ResultStorage::value) { // Value + case ResultStorage::expr_result: { //Result + std::cout << "[shape=box,label=\"" << node->op_name_ << " [" << node->result_idx_ << "]" << "\"]" << std::endl; + break; + } - std::cout << "[shape=circle,"; - try { - std::string name(invmap.at(node).first); - bool scalar(invmap.at(node).second); - if (scalar) { - std::cout << "label=\"" << name << '"'; + case ResultStorage::value: { // Value + std::cout << "[shape=circle,"; + try { + std::string name(invmap.at(node).first); + const MultiIdx::VecUint indices(invmap.at(node).second); + bool scalar(indices.empty()); + if (scalar) { + std::cout << "label=\"" << name << '"'; + } + else { + MultiIdx::VecUint::size_type size(indices.size()); + std::cout << "label=\"" << name << "["; + for (MultiIdx::VecUint::size_type i = 0; i < size; i++) { + std::cout << indices.at(i); + if (i != size - 1) { + std::cout << ','; + } + } + std::cout << "]\""; + } + std::cout << ",group=\"" << name << '"'; } - else { - std::cout << "label=<" << name << "i" << '>'; + catch (const std::out_of_range&) { + std::cout << "label=<var>"; } - std::cout << ",group=\"" << name << '"'; - } - catch (const std::out_of_range&) { - std::cout << "label=<var>"; + + std::cout << "]" << std::endl; + break; } - - std::cout << "]" << std::endl; - } - else if (node->result_storage == ResultStorage::value_copy) { //Value copy - std::cout << "[shape=circle,"; - try { - std::string name(invmap.at(node).first); - bool scalar(invmap.at(node).second); - if (scalar) { - std::cout << "label=\"" << name << '"'; + case ResultStorage::value_copy: { //Value copy + std::cout << "[shape=circle,"; + try { + std::string name(invmap.at(node).first); + MultiIdx::VecUint indices(invmap.at(node).second); + bool scalar(indices.empty()); + if (scalar) { + std::cout << "label=\"" << name << '"'; + } + else { + MultiIdx::VecUint::size_type size(indices.size()); + std::cout << "label=\"" << name << "["; + for (MultiIdx::VecUint::size_type i = 0; i < size; i++) { + std::cout << indices.at(i); + if (i != size - 1) { + std::cout << ','; + } + } + std::cout << "]\""; + } + std::cout << ",group=\"" << name << '"'; } - else { - std::cout << "label=<" << name << "i" << '>'; + catch (const std::out_of_range&) { + std::cout << "label=<var_cp>"; } - std::cout << ",group=\"" << name << '"'; - } - catch (const std::out_of_range&) { - std::cout << "label=<var_cp>"; + std::cout << "]" << std::endl; + break; } - std::cout << "]" << std::endl; - } - else {//Temporary & other //Temporary & other - std::cout << "[label=\"" << node->op_name_ << "\"]" << std::endl; - } + default: { //Temporary & other + std::cout << "[label=\"" << node->op_name_ << "\"]" << std::endl; + break; + } + } //switch } void _print_i_node(uint i) {