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

daisytuner / sdfglib / 17368505925

01 Sep 2025 05:29AM UTC coverage: 58.982% (-0.8%) from 59.781%
17368505925

push

github

web-flow
Merge pull request #216 from daisytuner/transitions-bug

Updates API for Sequence transitions to prevent leakage of assignments

239 of 547 new or added lines in 25 files covered. (43.69%)

75 existing lines in 12 files now uncovered.

9190 of 15581 relevant lines covered (58.98%)

115.89 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

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

25
void MatMulNode::validate(const Function &) const { /* TODO */ }
×
26

27
bool MatMulNode::expand(builder::StructuredSDFGBuilder &builder, analysis::AnalysisManager &analysis_manager) {
×
28
    auto &dataflow = this->get_parent();
×
29
    auto &block = static_cast<structured_control_flow::Block &>(*dataflow.get_parent());
×
30

31
    auto &scope_analysis = analysis_manager.get<analysis::ScopeAnalysis>();
×
32
    auto &parent = static_cast<structured_control_flow::Sequence &>(*scope_analysis.parent_scope(&block));
×
NEW
33
    int index = parent.index(block);
×
NEW
34
    auto &transition = parent.at(index).second;
×
35

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

55
    std::string A_name = static_cast<const data_flow::AccessNode &>(iedge_A->src()).data();
×
56
    std::string B_name = static_cast<const data_flow::AccessNode &>(iedge_B->src()).data();
×
57
    std::string C_name = static_cast<const data_flow::AccessNode &>(oedge_C->dst()).data();
×
58

59
    // Create new sequence before
NEW
60
    auto &new_sequence = builder.add_sequence_before(parent, block, transition.assignments(), block.debug_info());
×
61
    structured_control_flow::Sequence *last_scope = &new_sequence;
×
62

63
    // Create maps over output subset dims (parallel dims)
64
    data_flow::Subset domain_begin = {
×
65
        symbolic::integer(0),
×
66
        symbolic::integer(0),
×
67
        symbolic::integer(0),
×
68
    };
69
    data_flow::Subset domain_end = {
×
70
        oedge_C->end_subset()[0],
×
71
        oedge_C->end_subset()[1],
×
72
        iedge_A->end_subset()[1],
×
73
    };
74

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

98
    // Create innermost block
99
    auto &code_block = builder.add_block(*last_scope);
×
NEW
100
    auto &tasklet =
×
NEW
101
        builder
×
NEW
102
            .add_tasklet(code_block, data_flow::TaskletCode::fma, "_out", {"_in1", "_in2", "_in3"}, block.debug_info());
×
103

104
    auto &A_in = builder.add_access(code_block, A_name, block.debug_info());
×
105
    auto &B_in = builder.add_access(code_block, B_name, block.debug_info());
×
106
    auto &C_in = builder.add_access(code_block, C_name, block.debug_info());
×
107
    auto &C_out = builder.add_access(code_block, C_name, block.debug_info());
×
108

NEW
109
    builder.add_computational_memlet(
×
NEW
110
        code_block, A_in, tasklet, "_in1", {out_syms[0], out_syms[2]}, iedge_A->base_type(), block.debug_info()
×
111
    );
NEW
112
    builder.add_computational_memlet(
×
NEW
113
        code_block, B_in, tasklet, "_in2", {out_syms[1], out_syms[2]}, iedge_B->base_type(), block.debug_info()
×
114
    );
NEW
115
    builder.add_computational_memlet(
×
NEW
116
        code_block, C_in, tasklet, "_in3", {out_syms[0], out_syms[1]}, oedge_C->base_type(), block.debug_info()
×
117
    );
NEW
118
    builder.add_computational_memlet(
×
NEW
119
        code_block, tasklet, "_out", C_out, {out_syms[0], out_syms[1]}, oedge_C->base_type(), block.debug_info()
×
120
    );
121

122
    // Cleanup old block
123
    builder.remove_memlet(block, *iedge_A);
×
124
    builder.remove_memlet(block, *iedge_B);
×
125
    builder.remove_memlet(block, *oedge_C);
×
126
    builder.remove_node(block, *this);
×
NEW
127
    builder.remove_child(parent, index + 1);
×
128

129
    return true;
×
130
}
×
131

132
std::unique_ptr<data_flow::DataFlowNode> MatMulNode::
133
    clone(size_t element_id, const graph::Vertex vertex, data_flow::DataFlowGraph &parent) const {
×
NEW
134
    return std::unique_ptr<data_flow::DataFlowNode>(new MatMulNode(element_id, this->debug_info(), vertex, parent));
×
135
}
×
136

137
nlohmann::json MatMulNodeSerializer::serialize(const data_flow::LibraryNode &library_node) {
×
138
    const MatMulNode &node = static_cast<const MatMulNode &>(library_node);
×
139
    nlohmann::json j;
×
140

141
    j["code"] = node.code().value();
×
142

143
    return j;
×
144
}
×
145

146
data_flow::LibraryNode &MatMulNodeSerializer::deserialize(
×
147
    const nlohmann::json &j, builder::StructuredSDFGBuilder &builder, structured_control_flow::Block &parent
148
) {
149
    auto code = j["code"].get<std::string>();
×
150
    if (code != LibraryNodeType_MatMul.value()) {
×
151
        throw std::runtime_error("Invalid library node code");
×
152
    }
153

154
    sdfg::serializer::JSONSerializer serializer;
×
155
    DebugInfo debug_info = serializer.json_to_debug_info(j["debug_info"]);
×
156

157
    return builder.add_library_node<MatMulNode>(parent, debug_info);
×
158
}
×
159

160
} // namespace ml
161
} // namespace math
162
} // 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