[Harman 세미콘 아카데미] Day_51(System Verilog)
RV32I Core_SingleCycle에 대해 발표를 진행하였습니다. 발표자료나 코드는 아래의 링크에 있습니다!
https://uiop1716.tistory.com/37
그리고 오늘부터는 MultiCycle에 대한 학습을 위한 C언어를 어셈블리어로 해석하는 법을 배웠습니다.
아래는 C언어를 어셈블리어로 변환하는 사이트 입니다.
https://godbolt.org/
Compiler Explorer
godbolt.org
아래의 사이트는 RISC-V 어셈블러에 관한 사이트입니다.
https://riscvasm.lucasteske.dev/
RISC-V Online Assembler
RISC-V Online Assembler. This is a very crude online assembler for RISC-V assembly (all variants that gas supports)
riscvasm.lucasteske.dev
아래의 사이트는 RISC-V 어셈블리어를 분석해 주는 사이트입니다.
https://luplab.gitlab.io/rvcodecjs/
rvcodec.js · RISC-V Instruction Encoder/Decoder
luplab.gitlab.io
메모리에 대한 구조입니다.
아래의 부분에서 Free Memory 공간의 RAM 최상위 주소부터 활용하여 Stack 할당 부분의 공간을 활용합니다. Stack Pointer의 위치를 변경해가며, main이나 함수등을 실행하고 Pointer의 위치변경으로 왔다갔다 하며 전체적인 코드를 수행합니다.
Stack Pointer : 스택의 주소를 가리킴, 전원/reset이 인가되면 처음 SP할당 명령 수행
- 제일 먼저, RAM의 최상위 주소, 가변적으로 변하는 RAM의 Stack부분에서 SP도 같이 변화함 //ROM[0]에 들어가게 됨.
- Stack이 늘어나면 점점 RAM의 아래로 내려가므로 SP의 값은 ( - )가 되게 됨. (최상위 시작, 아래로 내려감)
- 변수가 많아질수록 SP의 값은 점점 내려감
간단한 예제로 Memory활용에 대해 알아보겠습니다.
a+b에 대한 간단한 C언어 코드이지만, 이를 어셈블리 언어로 변경하면 살짝 복잡해집니다. Stack Pointer를 변경하며, 변수나 값들에 대해 RAM Memory에 할당하고 불러오고를 반복하며 adder에 대한 연산을 수행하게 됩니다.
아래의 그림과 같이, RAM의 영역에서 Stack의 최상위 위치를 0x2000이라고 가정했을 때, 변수에 대한 값들이 저장되는 것을 확인할 수 있습니다.
아래는 포인터에 대한 예제와 메모리 그림입니다. 저장 주소를 가리키는 포인터를 어렵게 생각하지 않고, a와b 같은 그냥 변수1,2로 생각하여, 값들의 주소를 포함하고 있다고 생각하면 이해하기에 도움이 많이 되었습니다.
Godbolt 사이트에서 저희가 그동안 설계한 MCU를 테스트하기 위해 c언어로 정렬함수를 구현했습니다.
Bubble 정렬을 사용하여, 배열에 있는 값의 주소를 통해 값들에 접근하여 비교하고 위치를 바꿔 오름차순 정렬을 진행합니다.
위의 c언어 코드를 RISC-V어셈블러로 변환하면 아래와 같이 나오게 됩니다.
저희가 MCU를 설계하며 구현하였던 명령어들이 함수에 맞게 나오는것을 확인할 수 있고, c언어의 코드의 글자 하나하나에 대해 풀어서 작성이 되어있다고 생각하시면 됩니다.
사용할 값들이나 주소들은 memory의 특정 위치에 저장되고, 이를 불러다가 사용하며 c언어를 구현하게 됩니다.
Main, Sort, Swap 등의 함수가 call에 의해 실행될 때는, Stack pointer가 변화하며 함수 동작을 수행합니다. 함수 호출 call은 …………이 있어, 함수의 동작이 종료되면 웡래 있었던 곳으로 돌아오고, pc+4가 되어 다음 명령어를 수행합니다.
아래는 어셈블러언어에 대한 저의 해석본입니다.
메모리에 대한 활용과 포인터에 대한 이해를 위해 막 작성하였습니다. 두개의 for문을 돌며 저장되어있던 memory의 main에 저장되어 있는 배열의 값들을 포인터와 주소에 대한 값으로 불러와 필요시 swap동작을하며 값을 변경해 주었습니다.
이를 저희가 만든 MCU에 적용합니다.
아래와 같은 RISC-V 어셈블러를 통해 얻은 HEX Dump를 memory file로 만들어 ROM에서 실행하도록 합니다. 그러면 자동적으로, 이 명령들을 MCU가 수행하게되고 저희가 구현한 C code 동작을 수행합니다.
결과:
53124에 대한 값들이 12345로 정렬됨을 확인 + MCU에 적용된 명령어가 잘 동작함을 확인할 수 있음
Code_Verilog_SystemVerilog/workspace/250416_MCU_C/250416_MCU_C.srcs at main · Heeju99/Code_Verilog_SystemVerilog
Contribute to Heeju99/Code_Verilog_SystemVerilog development by creating an account on GitHub.
github.com
포인터에 대한 이해, 그리고 함수 종료 시 실행되는 다음 명령어의 위치나 명령어 동작에 대한 이해를 하는데 어려움이 있었지만, 메모리 그림을 그리고 순차적으로 어셈블러 언어를 따라가며 이해를 도울 수 있었습니다. 꼭 메모리 그림을 그리시길..!