Skip to content

Commit

Permalink
Add linked-list kernel. Auto-flush L1D$ when finish executing.
Browse files Browse the repository at this point in the history
  • Loading branch information
DiyouS committed Jan 9, 2025
1 parent 161c862 commit bd80b30
Show file tree
Hide file tree
Showing 9 changed files with 638 additions and 0 deletions.
1 change: 1 addition & 0 deletions sw/snRuntime/src/platforms/standalone/start_snitch.S
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ _snrt_exit:
ori t0, t0, 1
la t1, tohost
sw t0, 0(t1)
call l1d_flush
1: ret

# HTIF sections
Expand Down
5 changes: 5 additions & 0 deletions sw/spatzBenchmarks/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ add_library(dp-fconv2d dp-fconv2d/kernel/fconv2d.c)
add_library(dp-fft dp-fft/kernel/fft.c)
add_library(sp-fft sp-fft/kernel/fft.c)

add_library(linked-list linked-list/kernel/llist.c)

# Tests
enable_testing()
set(SNITCH_TEST_PREFIX spatzBenchmarks-)
Expand Down Expand Up @@ -155,6 +157,8 @@ add_spatz_test_twoParam(sp-fft sp-fft/main.c 512 2)

add_spatz_test_threeParam(dp-mxfmatmul dp-mxfmatmul/main.c 64 64 64)

add_spatz_test_oneParam(linked-list linked-list/main.c 64)

# Tests for DATE
# Vanilla fmatmul
add_spatz_test_threeParam(dp-fmatmul-8x2vl dp-fmatmul-8x2vl/main.c 64 64 64)
Expand Down Expand Up @@ -187,3 +191,4 @@ add_spatz_test_threeParam(dp-mxfmatmul-m4n4k8-b2 dp-mxfmatmul-m4n4k8-b2/main.c 1
add_spatz_test_threeParam(dp-db-fmatmul-4x4vl dp-db-fmatmul-4x4vl/main.c 128 128 128)
add_spatz_test_threeParam(dp-db-fmatmul-4x4vl dp-db-fmatmul-4x4vl/main.c 64 64 64)
add_spatz_test_threeParam(dp-db-fmatmul-4x4vl dp-db-fmatmul-4x4vl/main.c 32 32 32)
add_spatz_test_threeParam(dp-db-fmatmul-4x4vl dp-db-fmatmul-4x4vl/main.c 16 32 32)
77 changes: 77 additions & 0 deletions sw/spatzBenchmarks/linked-list/data/data_64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2025 ETH Zurich and University of Bologna.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

// This file was generated automatically.

#include "layer.h"

int N = 64;

node_t nodes[64] __attribute__((section(".data"))) = {
{.payload = {.id = 23, .data = (double)71.063544}, .next = NULL},
{.payload = {.id = 25, .data = (double)73.296733}, .next = NULL},
{.payload = {.id = 7, .data = (double)-23.974755}, .next = NULL},
{.payload = {.id = 22, .data = (double)-9.31794}, .next = NULL},
{.payload = {.id = 45, .data = (double)66.822085}, .next = NULL},
{.payload = {.id = 33, .data = (double)-67.469181}, .next = NULL},
{.payload = {.id = 19, .data = (double)-28.94586}, .next = NULL},
{.payload = {.id = 59, .data = (double)34.035035}, .next = NULL},
{.payload = {.id = 46, .data = (double)40.364063}, .next = NULL},
{.payload = {.id = 9, .data = (double)36.709533}, .next = NULL},
{.payload = {.id = 40, .data = (double)-85.719498}, .next = NULL},
{.payload = {.id = 18, .data = (double)26.995658}, .next = NULL},
{.payload = {.id = 42, .data = (double)6.827975}, .next = NULL},
{.payload = {.id = 31, .data = (double)-51.037815}, .next = NULL},
{.payload = {.id = 16, .data = (double)-7.547958}, .next = NULL},
{.payload = {.id = 21, .data = (double)-46.010435}, .next = NULL},
{.payload = {.id = 36, .data = (double)85.078236}, .next = NULL},
{.payload = {.id = 41, .data = (double)37.632392}, .next = NULL},
{.payload = {.id = 29, .data = (double)-56.076965}, .next = NULL},
{.payload = {.id = 20, .data = (double)-35.143453}, .next = NULL},
{.payload = {.id = 11, .data = (double)53.662716}, .next = NULL},
{.payload = {.id = 50, .data = (double)-88.81241}, .next = NULL},
{.payload = {.id = 39, .data = (double)64.360519}, .next = NULL},
{.payload = {.id = 48, .data = (double)61.00916}, .next = NULL},
{.payload = {.id = 3, .data = (double)-19.767043}, .next = NULL},
{.payload = {.id = 30, .data = (double)-86.762279}, .next = NULL},
{.payload = {.id = 24, .data = (double)82.627225}, .next = NULL},
{.payload = {.id = 55, .data = (double)13.43601}, .next = NULL},
{.payload = {.id = 4, .data = (double)43.582854}, .next = NULL},
{.payload = {.id = 57, .data = (double)-57.474691}, .next = NULL},
{.payload = {.id = 54, .data = (double)-0.153748}, .next = NULL},
{.payload = {.id = 49, .data = (double)76.936631}, .next = NULL},
{.payload = {.id = 10, .data = (double)28.570374}, .next = NULL},
{.payload = {.id = 0, .data = (double)-71.425682}, .next = NULL},
{.payload = {.id = 60, .data = (double)-72.073936}, .next = NULL},
{.payload = {.id = 28, .data = (double)48.997796}, .next = NULL},
{.payload = {.id = 44, .data = (double)7.795458}, .next = NULL},
{.payload = {.id = 26, .data = (double)49.402762}, .next = NULL},
{.payload = {.id = 52, .data = (double)-14.313235}, .next = NULL},
{.payload = {.id = 12, .data = (double)16.706585}, .next = NULL},
{.payload = {.id = 35, .data = (double)-27.600711}, .next = NULL},
{.payload = {.id = 53, .data = (double)99.465156}, .next = NULL},
{.payload = {.id = 38, .data = (double)-72.333651}, .next = NULL},
{.payload = {.id = 32, .data = (double)-1.296833}, .next = NULL},
{.payload = {.id = 58, .data = (double)51.156432}, .next = NULL},
{.payload = {.id = 13, .data = (double)72.220582}, .next = NULL},
{.payload = {.id = 51, .data = (double)-69.431736}, .next = NULL},
{.payload = {.id = 62, .data = (double)-68.0036}, .next = NULL},
{.payload = {.id = 2, .data = (double)36.096243}, .next = NULL},
{.payload = {.id = 27, .data = (double)19.281806}, .next = NULL},
{.payload = {.id = 37, .data = (double)-23.046538}, .next = NULL},
{.payload = {.id = 5, .data = (double)19.177686}, .next = NULL},
{.payload = {.id = 34, .data = (double)-6.390022}, .next = NULL},
{.payload = {.id = 56, .data = (double)-49.717176}, .next = NULL},
{.payload = {.id = 43, .data = (double)10.645179}, .next = NULL},
{.payload = {.id = 6, .data = (double)88.486172}, .next = NULL},
{.payload = {.id = 61, .data = (double)36.056682}, .next = NULL},
{.payload = {.id = 8, .data = (double)-77.089651}, .next = NULL},
{.payload = {.id = 63, .data = (double)76.95769}, .next = NULL},
{.payload = {.id = 15, .data = (double)50.17556}, .next = NULL},
{.payload = {.id = 17, .data = (double)53.719747}, .next = NULL},
{.payload = {.id = 47, .data = (double)-31.964905}, .next = NULL},
{.payload = {.id = 1, .data = (double)-41.299974}, .next = NULL},
{.payload = {.id = 14, .data = (double)-68.368449}, .next = NULL},
};

160 changes: 160 additions & 0 deletions sw/spatzBenchmarks/linked-list/data/layer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
// Copyright 2020 ETH Zurich and University of Bologna.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#pragma once

#include <stdint.h>

typedef enum { FP64 = 8, FP32 = 4, FP16 = 2, FP8 = 1 } precision_t;

/**
* @struct gemm_layer_struct
* @brief This structure contains all parameters necessary for GEMM.
* @var gemm_layer_struct::M
* Dimension of matrix product MxK * KxN
* @var gemm_layer_struct::M_p
* M divided by number of compute cores
* @var gemm_layer_struct::N
* Dimension of matrix product MxK * KxN
* @var gemm_layer_struct::K
* Dimension of matrix product MxK * KxN
* @var gemm_layer_struct::TA
* Transpose matrix A
* @var gemm_layer_struct::TB
* Transpose matrix B
* @var gemm_layer_struct::TILE_M
* Tile factor across M dimension
* @var gemm_layer_struct::TILE_N
* Tile factor across N dimension
* @var gemm_layer_struct::TILE_K
* Tile factor across K dimension
* @var gemm_layer_struct::A
* Pointer to matrix A
* @var gemm_layer_struct::B
* Pointer to matrix B
* @var gemm_layer_struct::C
* Pointer to matrix C
* @var gemm_layer_struct::ALPHA
* constant factor: A * B + ALPHA * C
* @var gemm_layer_struct::dtype
* Precision of GEMM
* @var gemm_layer_struct::expand
* Use expanding DOTP instructions
*/
typedef struct gemm_layer_struct {
uint32_t M;
uint32_t M_p;
uint32_t N;
uint32_t K;

uint32_t TA;
uint32_t TB;

uint32_t TILE_M;
uint32_t TILE_N;
uint32_t TILE_K;

double *A;
double *B;
double *C;

uint32_t ALPHA;

precision_t dtype;
uint32_t expand;
} gemm_layer;

/**
* @struct conv_layer_struct
* @brief This structure contains all parameters necessary for Convolutional
* layers
* @var conv_layer_struct::CO
* Number of output channels
* @var conv_layer_struct::CI
* Number of input channels
* @var conv_layer_struct::IH
* Height of input feature map
* @var conv_layer_struct::IW
* Width of input feature map
* @var conv_layer_struct::OH
* Height of output feature map
* @var conv_layer_struct::OW
* Width of output feature map
* @var conv_layer_struct::FH
* Height of filter
* @var conv_layer_struct::FW
* Width of filter
* @var conv_layer_struct::pad
* Padding on all sides
* @var conv_layer_struct::ifmap
* Pointer to input feature map
* @var conv_layer_struct::weights
* Pointer to weights
* @var conv_layer_struct::ofmap
* Pointer to output feature map
* @var conv_layer_struct::TILE_CI
* Tiling factor of input channel
* @var conv_layer_struct::cluster2cluster
* Flag for enabling cluster 2 cluster communication
* @var conv_layer_struct::im2col
* Flag for enabling im2col + GEMM
* @var conv_layer_struct::gamma
* Pointer to gamma for BatchNorm
* @var conv_layer_struct::beta
* Pointer to beta for BatchNorm
* @var gemm_layer_struct::dtype
* Precision of Convolution layer
*/
typedef struct conv_layer_struct {
// CONV2D
uint32_t CO;
uint32_t CI;
uint32_t IH;
uint32_t IW;
uint32_t OH;
uint32_t OW;
uint32_t FH;
uint32_t FW;
uint32_t pad;

double *ifmap;
double *weights;
double *ofmap;

uint32_t TILE_CI;
uint32_t cluster2cluster;
uint32_t im2col;

// BATCHNORM
double *gamma;
double *beta;

precision_t dtype;
} conv_layer;

/**
* @struct dotp_layer_struct
* @brief This structure contains all parameters necessary for DOTP
* layers
* @var dotp_layer_struct::M
* Length of the vectors
* @var gemm_layer_struct::dtype
* Precision of Convolution layer
*/
typedef struct dotp_layer_struct {
// DOTP
uint32_t M;

precision_t dtype;
} dotp_layer;

typedef struct payload_t {
int id;
double data;
} payload_t;

typedef struct node_t {
payload_t payload;
struct node_t *next;
} node_t;
125 changes: 125 additions & 0 deletions sw/spatzBenchmarks/linked-list/kernel/llist.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
// Copyright 2025 ETH Zurich and University of Bologna.
//
// SPDX-License-Identifier: Apache-2.0
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Author: Diyou Shen <[email protected]>

#include "llist.h"


node_t* createNode (int id, const double data) {
node_t* newnode = (node_t* ) snrt_l3alloc(sizeof(node_t));
newnode->payload.id = id;
newnode->payload.data = data;
newnode->next = NULL;

return newnode;
}


int insertNode (node_t** head, node_t* newNode) {
if (newNode == NULL) {
// Cannot insert a NULL node.
return 1;
}

// If the list is empty, the new node becomes the head
if (*head == NULL) {
*head = newNode;
return 0;
}

// Traverse to the end of the list and append the new node
node_t* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
newNode->next = NULL; // Ensure the new node is the last node

return 0;
}

int deleteNode (node_t** head, int id) {
if (*head == NULL) {
// empty linked list
return 1;
}

node_t* tempnode = *head;
node_t* prevnode = NULL;

if (tempnode->payload.id == id) {
*head = tempnode->next;
// In theory we should free this node, but currently we don't have this function support
return 0;
}


while (tempnode != NULL && tempnode->payload.id != id) {
prevnode = tempnode;
tempnode = tempnode->next;
}

if (tempnode == NULL) {
// ID is not found in the linked-list
return 2;
}

// Remove the node
prevnode->next = tempnode->next;
// In theory we should free this node, but currently we don't have this function support
return 0;
}

void sortList(node_t** head) {
if (*head == NULL || (*head)->next == NULL) {
// List is empty or has only one node, no sorting needed
return;
}

// Bubble sort logic for simplicity (can be optimized if needed)
int swapped;
node_t *ptr1, *lptr = NULL;

do {
swapped = 0;
ptr1 = *head;

while (ptr1->next != lptr) {
if (ptr1->payload.id > ptr1->next->payload.id) {
// Swap the payloads
payload_t temp = ptr1->payload;
ptr1->payload = ptr1->next->payload;
ptr1->next->payload = temp;
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1; // Move the lptr marker to the last sorted node
} while (swapped);
}

int traverseList (node_t* head) {
if (head == NULL) {
// List is empty
return 1;
}

volatile node_t* tempnode = head;
while (tempnode != NULL) {
tempnode = tempnode->next;
}
}
Loading

0 comments on commit bd80b30

Please sign in to comment.