본문 바로가기
IT_Study/CS_Study

[Computer Architecture] (4-4) RISC-V Data Transfer Operation

by 두번째얼룩 2024. 4. 28.

 
Data Transfer Operation은 연산에 필요한 데이터를 메모리로부터 읽어오거나 연산 결과를 다시 메모리에 저장하는 동작을 말한다. 
RISC-V에서는 'ld'(Load)/'sd'(Store)를 통해서만 메모리를 접근할 수 있다. 
(나머지 Instruction은 Register를 통해서 데이터를 접근할 수 있다.)
아래와 같이 메모리에 있는 Array 'A'의 Element 간의 연산을 수행하는 코드가 있다고 하자.

// h in x21
// base address of A in x22
A[12] = h + A[8]

Array 'A'는 메모리에 저장되어 있으므로, 'ld' 명령어를 통해서 데이터를 읽어오고, 'st' 명령어를 통해서 데이터를 저장해야 한다. 기본적으로 Array 내부의 Element를 접근하는 방법은 base address + offset를 통해서 접근한다. base address는 Array의 시작 주소이며, offset은 element size*element index를 수행하여 얻을 수 있다. 

// 8 bytes per doubleword
// &A[8] = A + 64

ld  x9, 64(x22)	# x9 = M[x22+64]
add x9, x21, x9 # x9 = x21 + x9
sd  x9, 96(x22) # M[x22+96] = x9

 
아래와 같이 메모리에 Access 하는 데이터의 크기도 정할 수 있으며, 'Sign extend'와 'Zero extend'를 선택할 수도 있다.

Load/Store Unit

 
Load는 I-type, Store는 S-type을 사용한다.

Load/Store Type

 
메모리의 접근 주소는 Byte-addressable 이고, RISC-V는 Littel Endian을 사용한다. 또한 RISC-V는 Words단위 Alignment를 요구하지 않는다. 
Memory Alignment 는 아래 글에서 설명하였다.
2024.04.27 - [IT_Study/CS_Study] - [Computer Architecture] (2) Memory Alignment

[Computer Architecture] (2) Memory Alignment

Memory Alignment는 일반적으로 Memory에 저장되어 있는 데이터를 접근 하는 방식을 고려하여 데이터를 저장하는 방법을 의미한다. 데이터를 저장하는 방법에 따라 Memory를 접근하는 횟수가 달라질 수

secondspot.tistory.com

Endian 개념은 아래 글에서 설명하였다.
2024.04.27 - [IT_Study/CS_Study] - [Computer Architecture] (3) Big endian & Little endian

[Computer Architecture] (3) Big endian & Little endian

엔디언는 아래와 같이 위키백과에서 자세히 정의를 해두었다. 엔디언(Endianness)은 컴퓨터의 메모리와 같은 1차원의 공간에 여러 개의 연속된 대상을 배열하는 방법을 뜻하며, 바이트를 배열하

secondspot.tistory.com

 
아래와 같이 swap을 수행하는 함수가 어떻게 ld/st로 구현되는지 알아보자.

// 주소 xp와 주소 yp에 있는 데이터를 교환하여 변경.
void swap(long *xp, long *yp)
{
 long t0 = *xp; // 주소 xp에 있는 데이터를 t0에 로드
 long t1 = *yp; // 주소 yp에 있는 데이터를 t1에 로드
 *xp = t1;      // t1 데이터를 주소 xp에 저장.
 *yp = t0;      // t0 데이터를 주소 yp에 저장.
}

 
이를 Instruction으로 변경하면 아래와 같다.

// a0 = xp
// a1 = yp
swap:
 ld a4, 0(a0) # a4 = M[a0] // t0 = *xp
 ld a5, 0(a1) # a5 = M[a1] // t1 = *yp
 sd a5, 0(a0) # M[a0] = a5 // *xp = t1
 sd a4, 0(a1) # M[a1] = a4 // *yp = t0
 ret

 
NULL Character '\0'는 8-bit 모두 0으로 표현할 수 있고, 이는 주로 string 마지막을 표현할 때 사용한다. 
이를 활용하면 아래와 같이 String Copy를 구현할 수 있다. 

// copy y to x
void strcpy(char x[], char y[])
{
 size_t i;
 i = 0;
 while((x[i] = y[i]) != '\0') // x[y] = y[i]를 수행하고 값이 Null인지 체크.
  i += 1;
}

이를 Inst.으로 구현하면 아래와 같다.

strcpy:
	; x is in a0
    ; y is in a1
    ; i is allocated in t3
    
    add t3, zero, zero	; t3 <- 0            // i = 0
L1: add t0, t3, a1      ; t0 = i + y[] = &y[i]
    lbu t1, 0(t0)       ; t1 <- y[i]         // t1 = y[i], char -> 1B, unsigned byte load
    add t2, t3, a0      ; t2 <- x[i]         // t2 = x[i], char -> 1B, unsigned byte load
    sb t1, 0(t2)        ; x[i] <- y[i]       // x[i] = y[i]
    beq t1, zero, L2    ; if(t1==0), goto L2 // if(x[i]=='\0'), goto return
    addi t3, t3, 1      ; else t3+=1         // i+=1
    j    L1             ; goto L1
L2  ret                 ; return

 

댓글