Skip to content

Commit

Permalink
snRuntime: Add check on DMA transfer size
Browse files Browse the repository at this point in the history
  • Loading branch information
colluca committed Oct 24, 2023
1 parent e5b0161 commit 8a020de
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 97 deletions.
204 changes: 108 additions & 96 deletions sw/snRuntime/src/dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,49 @@ typedef uint32_t snrt_dma_txid_t;
/// Initiate an asynchronous 1D DMA transfer with wide 64-bit pointers.
inline snrt_dma_txid_t snrt_dma_start_1d_wideptr(uint64_t dst, uint64_t src,
size_t size) {
register uint32_t reg_dst_low asm("a0") = dst >> 0; // 10
register uint32_t reg_dst_high asm("a1") = dst >> 32; // 11
register uint32_t reg_src_low asm("a2") = src >> 0; // 12
register uint32_t reg_src_high asm("a3") = src >> 32; // 13
register uint32_t reg_size asm("a4") = size; // 14

// dmsrc a2, a3
asm volatile(
".word (0b0000000 << 25) | \
( (13) << 20) | \
( (12) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_src_high),
"r"(reg_src_low));

// dmdst a0, a1
asm volatile(
".word (0b0000001 << 25) | \
( (11) << 20) | \
( (10) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_dst_high),
"r"(reg_dst_low));

// dmcpyi a0, a4, 0b00
register uint32_t reg_txid asm("a0"); // 10
asm volatile(
".word (0b0000010 << 25) | \
( 0b00000 << 20) | \
( (14) << 15) | \
( 0b000 << 12) | \
( (10) << 7) | \
(0b0101011 << 0) \n"
: "=r"(reg_txid)
: "r"(reg_size));

return reg_txid;
// Current DMA does not allow transfers with size == 0 (blocks)
// TODO(colluca) remove this check once new DMA is integrated
if (size > 0) {
register uint32_t reg_dst_low asm("a0") = dst >> 0; // 10
register uint32_t reg_dst_high asm("a1") = dst >> 32; // 11
register uint32_t reg_src_low asm("a2") = src >> 0; // 12
register uint32_t reg_src_high asm("a3") = src >> 32; // 13
register uint32_t reg_size asm("a4") = size; // 14

// dmsrc a2, a3
asm volatile(
".word (0b0000000 << 25) | \
( (13) << 20) | \
( (12) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_src_high),
"r"(reg_src_low));

// dmdst a0, a1
asm volatile(
".word (0b0000001 << 25) | \
( (11) << 20) | \
( (10) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_dst_high),
"r"(reg_dst_low));

// dmcpyi a0, a4, 0b00
register uint32_t reg_txid asm("a0"); // 10
asm volatile(
".word (0b0000010 << 25) | \
( 0b00000 << 20) | \
( (14) << 15) | \
( 0b000 << 12) | \
( (10) << 7) | \
(0b0101011 << 0) \n"
: "=r"(reg_txid)
: "r"(reg_size));

return reg_txid;
} else {
return -1;
}
}

/// Initiate an asynchronous 1D DMA transfer.
Expand All @@ -58,65 +64,71 @@ inline snrt_dma_txid_t snrt_dma_start_2d_wideptr(uint64_t dst, uint64_t src,
size_t size, size_t dst_stride,
size_t src_stride,
size_t repeat) {
register uint32_t reg_dst_low asm("a0") = dst >> 0; // 10
register uint32_t reg_dst_high asm("a1") = dst >> 32; // 11
register uint32_t reg_src_low asm("a2") = src >> 0; // 12
register uint32_t reg_src_high asm("a3") = src >> 32; // 13
register uint32_t reg_size asm("a4") = size; // 14
register uint32_t reg_dst_stride asm("a5") = dst_stride; // 15
register uint32_t reg_src_stride asm("a6") = src_stride; // 16
register uint32_t reg_repeat asm("a7") = repeat; // 17

// dmsrc a0, a1
asm volatile(
".word (0b0000000 << 25) | \
( (13) << 20) | \
( (12) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_src_high),
"r"(reg_src_low));

// dmdst a0, a1
asm volatile(
".word (0b0000001 << 25) | \
( (11) << 20) | \
( (10) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_dst_high),
"r"(reg_dst_low));

// dmstr a5, a6
asm volatile(
".word (0b0000110 << 25) | \
( (15) << 20) | \
( (16) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n"
:
: "r"(reg_dst_stride), "r"(reg_src_stride));

// dmrep a7
asm volatile(
".word (0b0000111 << 25) | \
( (17) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n"
:
: "r"(reg_repeat));

// dmcpyi a0, a4, 0b10
register uint32_t reg_txid asm("a0"); // 10
asm volatile(
".word (0b0000010 << 25) | \
( 0b00010 << 20) | \
( (14) << 15) | \
( 0b000 << 12) | \
( (10) << 7) | \
(0b0101011 << 0) \n"
: "=r"(reg_txid)
: "r"(reg_size));

return reg_txid;
// Current DMA does not allow transfers with size == 0 (blocks)
// TODO(colluca) remove this check once new DMA is integrated
if (size > 0) {
register uint32_t reg_dst_low asm("a0") = dst >> 0; // 10
register uint32_t reg_dst_high asm("a1") = dst >> 32; // 11
register uint32_t reg_src_low asm("a2") = src >> 0; // 12
register uint32_t reg_src_high asm("a3") = src >> 32; // 13
register uint32_t reg_size asm("a4") = size; // 14
register uint32_t reg_dst_stride asm("a5") = dst_stride; // 15
register uint32_t reg_src_stride asm("a6") = src_stride; // 16
register uint32_t reg_repeat asm("a7") = repeat; // 17

// dmsrc a0, a1
asm volatile(
".word (0b0000000 << 25) | \
( (13) << 20) | \
( (12) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_src_high),
"r"(reg_src_low));

// dmdst a0, a1
asm volatile(
".word (0b0000001 << 25) | \
( (11) << 20) | \
( (10) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n" ::"r"(reg_dst_high),
"r"(reg_dst_low));

// dmstr a5, a6
asm volatile(
".word (0b0000110 << 25) | \
( (15) << 20) | \
( (16) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n"
:
: "r"(reg_dst_stride), "r"(reg_src_stride));

// dmrep a7
asm volatile(
".word (0b0000111 << 25) | \
( (17) << 15) | \
( 0b000 << 12) | \
(0b0101011 << 0) \n"
:
: "r"(reg_repeat));

// dmcpyi a0, a4, 0b10
register uint32_t reg_txid asm("a0"); // 10
asm volatile(
".word (0b0000010 << 25) | \
( 0b00010 << 20) | \
( (14) << 15) | \
( 0b000 << 12) | \
( (10) << 7) | \
(0b0101011 << 0) \n"
: "=r"(reg_txid)
: "r"(reg_size));

return reg_txid;
} else {
return -1;
}
}

/// Initiate an asynchronous 2D DMA transfer.
Expand Down
2 changes: 1 addition & 1 deletion sw/snRuntime/src/start.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ static inline void snrt_init_cls() {

// Copy cdata section to base of the TCDM
size = (size_t)(&__cdata_end) - (size_t)(&__cdata_start);
if (size > 0) snrt_dma_start_1d(ptr, (void*)(&__cdata_start), size);
snrt_dma_start_1d(ptr, (void*)(&__cdata_start), size);

// Clear cbss section
ptr = (void*)((uint32_t)ptr + size);
Expand Down

0 comments on commit 8a020de

Please sign in to comment.