Skip to content

Commit 396200e

Browse files
committed
sw: add idma library functions
1 parent 02c84a6 commit 396200e

File tree

3 files changed

+143
-0
lines changed

3 files changed

+143
-0
lines changed

sw/config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define UART_BASE_ADDR 0x03002000
1313
#define GPIO_BASE_ADDR 0x03005000
1414
#define OBI_TIMER_BASE_ADDR 0x0300A000
15+
#define IDMA_BASE_ADDR 0x0300B000
1516
#define CLINT_BASE_ADDR 0x02040000
1617

1718
// Frequencies
@@ -31,3 +32,4 @@
3132
#define IRQ_OBI_TIMER 16
3233
#define IRQ_UART 17
3334
#define IRQ_GPIO 18
35+
#define IRQ_IDMA 19

sw/lib/inc/idma.h

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// Copyright 2026 ETH Zurich and University of Bologna.
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Thomas Benz <tbenz@iis.ee.ethz.ch>
6+
// Philippe Sauter <phsauter@iis.ee.ethz.ch>
7+
8+
#pragma once
9+
10+
#include <stdint.h>
11+
12+
// Register offsets (from croc_idma.sv)
13+
#define IDMA_CONF_OFFSET 0x00
14+
#define IDMA_NEXT_ID_OFFSET 0x44
15+
#define IDMA_DONE_ID_OFFSET 0x84
16+
#define IDMA_DST_ADDR_OFFSET 0xd0
17+
#define IDMA_SRC_ADDR_OFFSET 0xd8
18+
#define IDMA_LENGTH_OFFSET 0xe0
19+
#define IDMA_DST_STRIDE_2_OFFSET 0xe8
20+
#define IDMA_SRC_STRIDE_2_OFFSET 0xf0
21+
#define IDMA_REPS_2_OFFSET 0xf8
22+
23+
// Config register bits
24+
#define IDMA_CONF_ND_ENA_BIT 11
25+
26+
// Configure a simple 1D DMA transfer
27+
void idma_set_src_addr(uint32_t addr);
28+
void idma_set_dst_addr(uint32_t addr);
29+
void idma_set_length(uint32_t length);
30+
31+
// Configure 2D (ND) transfers
32+
void idma_set_nd_enable(int enable);
33+
void idma_set_src_stride(uint32_t stride);
34+
void idma_set_dst_stride(uint32_t stride);
35+
void idma_set_reps(uint32_t reps);
36+
37+
// Launch a transfer and return the job ID.
38+
// Reading NEXT_ID submits the job configured in the registers.
39+
uint32_t idma_launch(void);
40+
41+
// Return the ID of the last completed transfer
42+
uint32_t idma_done_id(void);
43+
44+
// Check if a transfer with the given job ID has completed
45+
uint32_t idma_is_done(uint32_t job_id);
46+
47+
// Launch a blocking 1D memory copy and return the job ID
48+
uint32_t idma_memcpy(uint32_t dst, uint32_t src, uint32_t length);
49+
50+
// Launch a blocking 2D transfer and return the job ID
51+
uint32_t idma_memcpy_2d(uint32_t dst, uint32_t src, uint32_t length,
52+
uint32_t dst_stride, uint32_t src_stride,
53+
uint32_t reps);

sw/lib/src/idma.c

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
// Copyright 2026 ETH Zurich and University of Bologna.
2+
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
3+
// SPDX-License-Identifier: Apache-2.0
4+
//
5+
// Thomas Benz <tbenz@iis.ee.ethz.ch>
6+
// Philippe Sauter <phsauter@iis.ee.ethz.ch>
7+
8+
#include "idma.h"
9+
#include "util.h"
10+
#include "config.h"
11+
12+
////////////////////////
13+
// Register access //
14+
////////////////////////
15+
16+
void idma_set_src_addr(uint32_t addr) {
17+
*reg32(IDMA_BASE_ADDR, IDMA_SRC_ADDR_OFFSET) = addr;
18+
}
19+
20+
void idma_set_dst_addr(uint32_t addr) {
21+
*reg32(IDMA_BASE_ADDR, IDMA_DST_ADDR_OFFSET) = addr;
22+
}
23+
24+
void idma_set_length(uint32_t length) {
25+
*reg32(IDMA_BASE_ADDR, IDMA_LENGTH_OFFSET) = length;
26+
}
27+
28+
void idma_set_nd_enable(int enable) {
29+
uint32_t conf = *reg32(IDMA_BASE_ADDR, IDMA_CONF_OFFSET);
30+
if (enable)
31+
conf |= (1u << IDMA_CONF_ND_ENA_BIT);
32+
else
33+
conf &= ~(1u << IDMA_CONF_ND_ENA_BIT);
34+
*reg32(IDMA_BASE_ADDR, IDMA_CONF_OFFSET) = conf;
35+
}
36+
37+
void idma_set_src_stride(uint32_t stride) {
38+
*reg32(IDMA_BASE_ADDR, IDMA_SRC_STRIDE_2_OFFSET) = stride;
39+
}
40+
41+
void idma_set_dst_stride(uint32_t stride) {
42+
*reg32(IDMA_BASE_ADDR, IDMA_DST_STRIDE_2_OFFSET) = stride;
43+
}
44+
45+
void idma_set_reps(uint32_t reps) {
46+
*reg32(IDMA_BASE_ADDR, IDMA_REPS_2_OFFSET) = reps;
47+
}
48+
49+
uint32_t idma_launch(void) {
50+
return *reg32(IDMA_BASE_ADDR, IDMA_NEXT_ID_OFFSET);
51+
}
52+
53+
uint32_t idma_done_id(void) {
54+
return *reg32(IDMA_BASE_ADDR, IDMA_DONE_ID_OFFSET);
55+
}
56+
57+
uint32_t idma_is_done(uint32_t job_id) {
58+
return idma_done_id() >= job_id;
59+
}
60+
61+
////////////////////////
62+
// Convenience API //
63+
////////////////////////
64+
65+
uint32_t idma_memcpy(uint32_t dst, uint32_t src, uint32_t length) {
66+
idma_set_nd_enable(0);
67+
idma_set_src_addr(src);
68+
idma_set_dst_addr(dst);
69+
idma_set_length(length);
70+
uint32_t id = idma_launch();
71+
while (!idma_is_done(id));
72+
return id;
73+
}
74+
75+
uint32_t idma_memcpy_2d(uint32_t dst, uint32_t src, uint32_t length,
76+
uint32_t dst_stride, uint32_t src_stride,
77+
uint32_t reps) {
78+
idma_set_nd_enable(1);
79+
idma_set_src_addr(src);
80+
idma_set_dst_addr(dst);
81+
idma_set_length(length);
82+
idma_set_dst_stride(dst_stride);
83+
idma_set_src_stride(src_stride);
84+
idma_set_reps(reps);
85+
uint32_t id = idma_launch();
86+
while (!idma_is_done(id));
87+
return id;
88+
}

0 commit comments

Comments
 (0)