Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,12 @@ check:
@set -e; \
ninja -C build check-loom

check-one:
@rc=0; \
$(CURDIR)/tests/scripts/$(SUITE).sh --single $(CURDIR)/build/bin/loom $(CURDIR)/tests/app/$(TEST) --run || rc=$$?; \
cat $(CURDIR)/tests/app/$(TEST)/Output/$(TEST).scf.log; \
exit $$rc

clean:
@set -e; \
if [ -d build ]; then ninja -C build clean-loom; fi
Expand Down
114 changes: 114 additions & 0 deletions tests/app/breadth_first_search/breadth_first_search.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// Loom kernel implementation: breadth_first_search
#include "breadth_first_search.h"
#include "loom/loom.h"
#include <cmath>
#include <cstdlib>

// Full pipeline test from C++ source: Breadth-First Search on CSR graph
// Tests complete compilation chain with queue-based traversal and irregular memory access
// Graph (6 nodes, 11 edges):
// 0 -> 1, 3
// 1 -> 2, 4
// 2 -> 3, 5
// 3 -> 4, 5
// 4 -> 0, 2
// 5 -> 1
// BFS from node 0: distances = [0, 1, 2, 1, 2, 2]

// CPU implementation of BFS on CSR graph
// queue_size must be >= num_nodes to guarantee no overflow
// Note: programmer must guarantee arrays with __restrict__ do not overlap
void bfs_cpu(const uint32_t* __restrict__ row_ptr,
const uint32_t* __restrict__ col_idx,
int32_t* __restrict__ distance,
uint32_t* __restrict__ queue,
uint32_t* __restrict__ visited,
const uint32_t num_nodes,
const uint32_t num_edges,
const uint32_t queue_size,
const uint32_t source) {
// Initialize distances to -1 (unvisited)
for (uint32_t i = 0; i < num_nodes; i++) {
distance[i] = -1;
visited[i] = 0;
}

// Initialize BFS from source
uint32_t queue_head = 0;
uint32_t queue_tail = 0;

distance[source] = 0;
visited[source] = 1;
queue[queue_tail++] = source;

// BFS traversal (queue_tail bounded by num_nodes due to visited check)
while (queue_head < queue_tail && queue_tail <= queue_size) {
// dequeue current node
uint32_t current = queue[queue_head++];
int32_t current_dist = distance[current];

// Iterate over neighbors
uint32_t start = row_ptr[current];
uint32_t end = row_ptr[current + 1];

for (uint32_t edge = start; edge < end; edge++) {
uint32_t neighbor = col_idx[edge];

if (visited[neighbor] == 0 && queue_tail < queue_size) {
visited[neighbor] = 1;
distance[neighbor] = current_dist + 1;
queue[queue_tail++] = neighbor;
}
}
}
}

// Accelerator implementation of BFS on CSR graph
// queue_size must be >= num_nodes to guarantee no overflow
LOOM_ACCEL()
void bfs_dsa(const uint32_t* __restrict__ row_ptr,
const uint32_t* __restrict__ col_idx,
int32_t* __restrict__ distance,
uint32_t* __restrict__ queue,
uint32_t* __restrict__ visited,
const uint32_t num_nodes,
const uint32_t num_edges,
const uint32_t queue_size,
const uint32_t source) {
// Initialize distances to -1 (unvisited)
LOOM_NO_PARALLEL
LOOM_NO_UNROLL
for (uint32_t i = 0; i < num_nodes; i++) {
distance[i] = -1;
visited[i] = 0;
}

// Initialize BFS from source
uint32_t queue_head = 0;
uint32_t queue_tail = 0;

distance[source] = 0;
visited[source] = 1;
queue[queue_tail++] = source;

// BFS traversal (queue_tail bounded by num_nodes due to visited check)
while (queue_head < queue_tail && queue_tail <= queue_size) {
// dequeue current node
uint32_t current = queue[queue_head++];
int32_t current_dist = distance[current];

// Iterate over neighbors
uint32_t start = row_ptr[current];
uint32_t end = row_ptr[current + 1];

for (uint32_t edge = start; edge < end; edge++) {
uint32_t neighbor = col_idx[edge];

if (visited[neighbor] == 0 && queue_tail < queue_size) {
visited[neighbor] = 1;
distance[neighbor] = current_dist + 1;
queue[queue_tail++] = neighbor;
}
}
}
}
12 changes: 12 additions & 0 deletions tests/app/breadth_first_search/breadth_first_search.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Loom kernel: breadth_first_search
#ifndef BREADTH_FIRST_SEARCH_H
#define BREADTH_FIRST_SEARCH_H

#include <cstdint>
#include <cstddef>

void bfs_cpu(const uint32_t* __restrict__ row_ptr, const uint32_t* __restrict__ col_idx, int32_t* __restrict__ distance, uint32_t* __restrict__ queue, uint32_t* __restrict__ visited, const uint32_t num_nodes, const uint32_t num_edges, const uint32_t queue_size, const uint32_t source);

void bfs_dsa(const uint32_t* __restrict__ row_ptr, const uint32_t* __restrict__ col_idx, int32_t* __restrict__ distance, uint32_t* __restrict__ queue, uint32_t* __restrict__ visited, const uint32_t num_nodes, const uint32_t num_edges, const uint32_t queue_size, const uint32_t source);

#endif // BREADTH_FIRST_SEARCH_H
47 changes: 47 additions & 0 deletions tests/app/breadth_first_search/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#include <cstdio>

#include "breadth_first_search.h"

int main() {
// Graph setup: 6 nodes, 11 edges
// 0 -> 1, 3
// 1 -> 2, 4
// 2 -> 3, 5
// 3 -> 4, 5
// 4 -> 0, 2
// 5 -> 1
const uint32_t num_nodes = 6;
const uint32_t num_edges = 11;
const uint32_t queue_size = 6;
const uint32_t source = 0;

// CSR format: row_ptr (node offsets) and col_idx (edge destinations)
uint32_t row_ptr[7] = {0, 2, 5, 7, 9, 11, 11}; // num_nodes + 1
uint32_t col_idx[11] = {1, 3, 2, 4, 3, 5, 4, 5, 0, 2, 1};

// Output arrays
int32_t expect_distance[6];
int32_t calculated_distance[6];
uint32_t expect_queue[6];
uint32_t calculated_queue[6];
uint32_t expect_visited[6];
uint32_t calculated_visited[6];

// Compute expected result with CPU version
bfs_cpu(row_ptr, col_idx, expect_distance, expect_queue, expect_visited, num_nodes, num_edges, queue_size, source);

// Compute result with DSA version
bfs_dsa(row_ptr, col_idx, calculated_distance, calculated_queue, calculated_visited, num_nodes, num_edges, queue_size, source);

// Compare results (distances)
for (uint32_t i = 0; i < num_nodes; i++) {
if (expect_distance[i] != calculated_distance[i]) {
printf("breadth_first_search: FAILED (distance mismatch at node %u: expected %d, got %d)\n",
i, expect_distance[i], calculated_distance[i]);
return 1;
}
}

printf("breadth_first_search: PASSED\n");
return 0;
}
Loading