• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

daisytuner / sdfglib / 17106423092

20 Aug 2025 06:00PM UTC coverage: 63.01%. First build
17106423092

Pull #206

github

web-flow
Merge e8a06b113 into 7eb275e0e
Pull Request #206: Add MatMul node and ml:: prefixes to LibraryNodes

2 of 92 new or added lines in 2 files covered. (2.17%)

9243 of 14669 relevant lines covered (63.01%)

122.88 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/data_flow/library_nodes/math/ml/matmul.cpp
1
#include "sdfg/data_flow/library_nodes/math/ml/matmul.h"
2

3
#include "sdfg/analysis/analysis.h"
4
#include "sdfg/analysis/scope_analysis.h"
5
#include "sdfg/builder/structured_sdfg_builder.h"
6

7
namespace sdfg {
8
namespace math {
9
namespace ml {
10

NEW
11
MatMulNode::MatMulNode(
×
12
    size_t element_id,
13
    const DebugInfo &debug_info,
14
    const graph::Vertex vertex,
15
    data_flow::DataFlowGraph &parent
16
)
NEW
17
    : MathNode(
×
NEW
18
          element_id, debug_info, vertex, parent, LibraryNodeType_MatMul, {"C"}, {"A", "B"}, data_flow::ImplementationType_NONE
×
NEW
19
      ) {}
×
20

NEW
21
void MatMulNode::validate(const Function &) const { /* TODO */ }
×
22

NEW
23
bool MatMulNode::expand(builder::StructuredSDFGBuilder &builder, analysis::AnalysisManager &analysis_manager) {
×
NEW
24
    auto &dataflow = this->get_parent();
×
NEW
25
    auto &block = static_cast<structured_control_flow::Block &>(*dataflow.get_parent());
×
26

NEW
27
    auto &scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
NEW
28
    auto &parent = static_cast<structured_control_flow::Sequence &>(*scope_analysis.parent_scope(&block));
×
29

30
    // Locate edges
NEW
31
    const data_flow::Memlet *iedge_A = nullptr;
×
NEW
32
    const data_flow::Memlet *iedge_B = nullptr;
×
NEW
33
    const data_flow::Memlet *oedge_C = nullptr;
×
NEW
34
    for (const auto &edge : dataflow.in_edges(*this)) {
×
NEW
35
        if (edge.dst_conn() == "A") {
×
NEW
36
            iedge_A = &edge;
×
NEW
37
        }
×
NEW
38
        if (edge.dst_conn() == "B") {
×
NEW
39
            iedge_B = &edge;
×
NEW
40
        }
×
41
    }
NEW
42
    for (const auto &edge : dataflow.out_edges(*this)) {
×
NEW
43
        if (edge.src_conn() == "C") {
×
NEW
44
            oedge_C = &edge;
×
NEW
45
        }
×
46
    }
NEW
47
    if (!iedge_A || !iedge_B || !oedge_C) return false;
×
48

NEW
49
    std::string A_name = static_cast<const data_flow::AccessNode &>(iedge_A->src()).data();
×
NEW
50
    std::string B_name = static_cast<const data_flow::AccessNode &>(iedge_B->src()).data();
×
NEW
51
    std::string C_name = static_cast<const data_flow::AccessNode &>(oedge_C->dst()).data();
×
52

53
    // Create new sequence before
NEW
54
    auto &new_sequence = builder.add_sequence_before(parent, block, block.debug_info()).first;
×
NEW
55
    structured_control_flow::Sequence *last_scope = &new_sequence;
×
56

57
    // Create maps over output subset dims (parallel dims)
NEW
58
    data_flow::Subset domain_begin = {
×
NEW
59
        symbolic::integer(0),
×
NEW
60
        symbolic::integer(0),
×
NEW
61
        symbolic::integer(0),
×
62
    };
NEW
63
    data_flow::Subset domain_end = {
×
NEW
64
        oedge_C->end_subset()[0],
×
NEW
65
        oedge_C->end_subset()[1],
×
NEW
66
        iedge_A->end_subset()[1],
×
67
    };
68

NEW
69
    std::vector<symbolic::Expression> out_syms;
×
NEW
70
    structured_control_flow::Map *last_map = nullptr;
×
NEW
71
    for (size_t d = 0; d < domain_begin.size(); ++d) {
×
NEW
72
        std::string indvar_str = builder.find_new_name("_i");
×
NEW
73
        builder.add_container(indvar_str, types::Scalar(types::PrimitiveType::UInt64));
×
NEW
74
        auto indvar = symbolic::symbol(indvar_str);
×
NEW
75
        auto init = domain_begin[d];
×
NEW
76
        auto update = symbolic::add(indvar, symbolic::one());
×
NEW
77
        auto cond = symbolic::Lt(indvar, symbolic::add(domain_end[d], symbolic::one()));
×
NEW
78
        last_map = &builder.add_map(
×
NEW
79
            *last_scope,
×
80
            indvar,
81
            cond,
82
            init,
83
            update,
84
            structured_control_flow::ScheduleType_Sequential,
NEW
85
            {},
×
NEW
86
            block.debug_info()
×
87
        );
NEW
88
        last_scope = &last_map->root();
×
NEW
89
        out_syms.push_back(indvar);
×
NEW
90
    }
×
91

92
    // Create innermost block
NEW
93
    auto &code_block = builder.add_block(*last_scope);
×
NEW
94
    auto &tasklet = builder.add_tasklet(code_block, data_flow::TaskletCode::fma, "_out", {"_in1", "_in2", "_in3"}, block.debug_info());
×
95

NEW
96
    auto &A_in = builder.add_access(code_block, A_name, block.debug_info());
×
NEW
97
    auto &B_in = builder.add_access(code_block, B_name, block.debug_info());
×
NEW
98
    auto &C_in = builder.add_access(code_block, C_name, block.debug_info());
×
NEW
99
    auto &C_out = builder.add_access(code_block, C_name, block.debug_info());
×
100

NEW
101
    builder.add_computational_memlet(code_block, A_in, tasklet, "_in1", {out_syms[0], out_syms[2]}, iedge_A->base_type(), block.debug_info());
×
NEW
102
    builder.add_computational_memlet(code_block, B_in, tasklet, "_in2", {out_syms[1], out_syms[2]}, iedge_B->base_type(), block.debug_info());
×
NEW
103
    builder.add_computational_memlet(code_block, C_in, tasklet, "_in3", {out_syms[0], out_syms[1]}, oedge_C->base_type(), block.debug_info());
×
NEW
104
    builder.add_computational_memlet(code_block, tasklet, "_out", C_out, {out_syms[0], out_syms[1]}, oedge_C->base_type(), block.debug_info());
×
105

106
    // Cleanup old block
NEW
107
    builder.remove_memlet(block, *iedge_A);
×
NEW
108
    builder.remove_memlet(block, *iedge_B);
×
NEW
109
    builder.remove_memlet(block, *oedge_C);
×
NEW
110
    builder.remove_node(block, *this);
×
NEW
111
    builder.remove_child(parent, block);
×
112

NEW
113
    return true;
×
NEW
114
}
×
115

116
std::unique_ptr<data_flow::DataFlowNode> MatMulNode::
NEW
117
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph &parent) const {
×
NEW
118
    return std::unique_ptr<data_flow::DataFlowNode>(new MatMulNode(
×
NEW
119
        element_id, this->debug_info(), vertex, parent
×
120
    ));
NEW
121
}
×
122

NEW
123
nlohmann::json MatMulNodeSerializer::serialize(const data_flow::LibraryNode &library_node) {
×
NEW
124
    const MatMulNode &node = static_cast<const MatMulNode &>(library_node);
×
NEW
125
    nlohmann::json j;
×
126

NEW
127
    j["code"] = node.code().value();
×
128

NEW
129
    return j;
×
NEW
130
}
×
131

NEW
132
data_flow::LibraryNode &MatMulNodeSerializer::deserialize(
×
133
    const nlohmann::json &j, builder::StructuredSDFGBuilder &builder, structured_control_flow::Block &parent
134
) {
NEW
135
    auto code = j["code"].get<std::string>();
×
NEW
136
    if (code != LibraryNodeType_MatMul.value()) {
×
NEW
137
        throw std::runtime_error("Invalid library node code");
×
138
    }
139

NEW
140
    sdfg::serializer::JSONSerializer serializer;
×
NEW
141
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
142

NEW
143
    return builder.add_library_node<MatMulNode>(parent, debug_info);
×
NEW
144
}
×
145

146
} // namespace ml
147
} // namespace math
148
} // namespace sdfg
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc