feat: learning note for pre study phase 5: program execution and simulator.
This commit is contained in:
parent
960dced2a9
commit
1a2eea6900
3
.gitignore
vendored
3
.gitignore
vendored
@ -1,4 +1,5 @@
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
*.out
|
||||
*.out
|
||||
*.bin
|
||||
@ -100,3 +100,162 @@ while (!halt)
|
||||
inst_cycle();
|
||||
}
|
||||
```
|
||||
|
||||
### 第一版YEMU
|
||||
向YEMU_first.c中加入如下内容
|
||||
```c
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
uint32_t R[32], PC;
|
||||
uint8_t M[1024] = {
|
||||
0x13, 0x05, 0x00, 0x00, 0x93, 0x05, 0x10, 0x04, 0x73, 0x00, 0x10, 0x00, 0x13, 0x05,
|
||||
0x10, 0x00, 0x93, 0x05, 0x00, 0x00, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0x00, 0x00,
|
||||
}; //64-Byte memory
|
||||
|
||||
|
||||
bool halt = false;
|
||||
|
||||
void inst_cycle()
|
||||
{
|
||||
uint32_t inst = *(uint32_t *)&M[PC];
|
||||
if (((inst & 0x7f) == 0x13) && ((inst >> 12) & 0x7) == 0)
|
||||
{ // addi
|
||||
if (((inst >> 7) & 0x1f) != 0)
|
||||
{
|
||||
R[(inst >> 7) & 0x1f] =
|
||||
R[(inst >> 15) & 0x1f] + (((inst >> 20) & 0x7ff) - ((inst & 0x80000000) ? 4096 : 0));
|
||||
}
|
||||
}
|
||||
else if (inst == 0x00100073)
|
||||
{ // ebreak
|
||||
if (R[10] == 0)
|
||||
{
|
||||
putchar(R[11] & 0xff);
|
||||
}
|
||||
else if (R[10] == 1)
|
||||
{
|
||||
halt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupport ebreak command\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupported instruction\n");
|
||||
}
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
PC = 0;
|
||||
R[0] = 0;
|
||||
while (!halt)
|
||||
{
|
||||
inst_cycle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
在shell中执行如下命令
|
||||
```shell
|
||||
gcc ./YEMU_first.c -o a.out && ./a.out
|
||||
```
|
||||
### 第二版YEMU
|
||||
在第一版YEMU中,我们的程序时写在代码里的,为了让我们的YEMU可以执行其它程序,我们需要在YEMU中读取外部的二进制文件。
|
||||
|
||||
向YEMU_second.c中加入如下的内容:
|
||||
```c
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
uint32_t R[32], PC;
|
||||
uint8_t M[1024]; //1024-Byte memory
|
||||
|
||||
|
||||
bool halt = false;
|
||||
|
||||
void inst_cycle()
|
||||
{
|
||||
uint32_t inst = *(uint32_t *)&M[PC];
|
||||
if (((inst & 0x7f) == 0x13) && ((inst >> 12) & 0x7) == 0)
|
||||
{ // addi
|
||||
if (((inst >> 7) & 0x1f) != 0)
|
||||
{
|
||||
R[(inst >> 7) & 0x1f] =
|
||||
R[(inst >> 15) & 0x1f] + (((inst >> 20) & 0x7ff) - ((inst & 0x80000000) ? 4096 : 0));
|
||||
}
|
||||
}
|
||||
else if (inst == 0x00100073)
|
||||
{ // ebreak
|
||||
if (R[10] == 0)
|
||||
{
|
||||
putchar(R[11] & 0xff);
|
||||
}
|
||||
else if (R[10] == 1)
|
||||
{
|
||||
halt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupport ebreak command\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupported instruction\n");
|
||||
}
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
PC = 0;
|
||||
R[0] = 0;
|
||||
assert(argc >= 2);
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
assert(fp != NULL);
|
||||
int ret = fseek(fp, 0, SEEK_END);
|
||||
assert(ret != -1);
|
||||
long fsize = ftell(fp);
|
||||
assert(fsize != -1);
|
||||
rewind(fp);
|
||||
assert(fsize < 1024);
|
||||
ret = fread(M, 1, 1024, fp);
|
||||
assert(ret == fsize);
|
||||
fclose(fp);
|
||||
while (!halt)
|
||||
{
|
||||
inst_cycle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
然后将之前编译的prog.out复制到YEMU的目录下,运行下面的命令
|
||||
|
||||

|
||||
|
||||
现在让我们试试更加复杂的程序,将**_start()**换成下面的代码
|
||||
```c
|
||||
void _start() {
|
||||
putch('H'); putch('e'); putch('l'); putch('l'); putch('o'); putch(','); putch(' ');
|
||||
putch('R'); putch('I'); putch('S'); putch('C'); putch('-'); putch('V'); putch('!');
|
||||
putch('\n');
|
||||
halt(0);
|
||||
}
|
||||
```
|
||||
在shell中执行下面的命令,我们就可以使用YEMU输出"Hello, RISC-V"。
|
||||
```shell
|
||||
riscv64-unknown-elf-gcc -ffreestanding -nostdlib -static -Wl,-Ttext=0 -O2 -march=rv64g -mabi=lp64 -o prog.out ./more_complex_program.c
|
||||
riscv64-unknown-elf-objcopy -j .text -O binary prog.out prog.bin
|
||||
./a.out ./prog.bin
|
||||
```
|
||||
|
||||
|
||||
@ -0,0 +1,57 @@
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
uint32_t R[32], PC;
|
||||
uint8_t M[1024] = {
|
||||
0x13, 0x05, 0x00, 0x00, 0x93, 0x05, 0x10, 0x04, 0x73, 0x00, 0x10, 0x00, 0x13, 0x05,
|
||||
0x10, 0x00, 0x93, 0x05, 0x00, 0x00, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0x00, 0x00,
|
||||
}; //64-Byte memory
|
||||
|
||||
|
||||
bool halt = false;
|
||||
|
||||
void inst_cycle()
|
||||
{
|
||||
uint32_t inst = *(uint32_t *)&M[PC];
|
||||
if (((inst & 0x7f) == 0x13) && ((inst >> 12) & 0x7) == 0)
|
||||
{ // addi
|
||||
if (((inst >> 7) & 0x1f) != 0)
|
||||
{
|
||||
R[(inst >> 7) & 0x1f] =
|
||||
R[(inst >> 15) & 0x1f] + (((inst >> 20) & 0x7ff) - ((inst & 0x80000000) ? 4096 : 0));
|
||||
}
|
||||
}
|
||||
else if (inst == 0x00100073)
|
||||
{ // ebreak
|
||||
if (R[10] == 0)
|
||||
{
|
||||
putchar(R[11] & 0xff);
|
||||
}
|
||||
else if (R[10] == 1)
|
||||
{
|
||||
halt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupport ebreak command\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupported instruction\n");
|
||||
}
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
PC = 0;
|
||||
R[0] = 0;
|
||||
while (!halt)
|
||||
{
|
||||
inst_cycle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -0,0 +1,86 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MSIZE 1024
|
||||
|
||||
|
||||
#define Assert(cond, format, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
fprintf(stderr, format "\n", ##__VA_ARGS__); \
|
||||
assert(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define Perror(cond, format, ...) Assert(cond, format ": %s", ##__VA_ARGS__, strerror(errno))
|
||||
|
||||
|
||||
uint32_t R[32], PC;
|
||||
uint8_t M[MSIZE]; //1024-Byte memory
|
||||
|
||||
|
||||
bool halt = false;
|
||||
|
||||
void inst_cycle()
|
||||
{
|
||||
uint32_t inst = *(uint32_t *)&M[PC];
|
||||
if (((inst & 0x7f) == 0x13) && ((inst >> 12) & 0x7) == 0)
|
||||
{ // addi
|
||||
if (((inst >> 7) & 0x1f) != 0)
|
||||
{
|
||||
R[(inst >> 7) & 0x1f] =
|
||||
R[(inst >> 15) & 0x1f] + (((inst >> 20) & 0x7ff) - ((inst & 0x80000000) ? 4096 : 0));
|
||||
}
|
||||
}
|
||||
else if (inst == 0x00100073)
|
||||
{ // ebreak
|
||||
if (R[10] == 0)
|
||||
{
|
||||
putchar(R[11] & 0xff);
|
||||
}
|
||||
else if (R[10] == 1)
|
||||
{
|
||||
halt = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupport ebreak command\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("unsupported instruction\n");
|
||||
}
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PC = 0;
|
||||
R[0] = 0;
|
||||
Assert(argc >= 2, "Program is not given"); // 要求至少包含一个参数
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
Perror(fp != NULL, "Fail to open %s", argv[1]); // 要求argv[1]是一个可以成功打开的文件
|
||||
int ret = fseek(fp, 0, SEEK_END);
|
||||
Perror(ret != -1, "Fail to seek the end of the file"); // 要求fseek()成功
|
||||
long fsize = ftell(fp);
|
||||
Perror(fsize != -1, "Fail to return the file position"); // 要求ftell()成功
|
||||
rewind(fp);
|
||||
Assert(fsize < MSIZE, "Program size exceeds 1024 Bytes"); // 要求程序大小不超过1024字节
|
||||
ret = fread(M, 1, MSIZE, fp);
|
||||
Assert(ret == fsize, "Fail to load the whole program"); // 要求完全读出程序的内容
|
||||
fclose(fp);
|
||||
while (!halt)
|
||||
{
|
||||
inst_cycle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1,13 +1,28 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "yemu.h"
|
||||
|
||||
|
||||
#define Assert(cond, format, ...) \
|
||||
do \
|
||||
{ \
|
||||
if (!(cond)) \
|
||||
{ \
|
||||
fprintf(stderr, format "\n", ##__VA_ARGS__); \
|
||||
assert(cond); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
|
||||
#define Perror(cond, format, ...) Assert(cond, format ": %s", ##__VA_ARGS__, strerror(errno))
|
||||
|
||||
|
||||
uint32_t R[32], PC;
|
||||
uint8_t M[1024] = {
|
||||
0x13, 0x05, 0x00, 0x00, 0x93, 0x05, 0x10, 0x04, 0x73, 0x00, 0x10, 0x00, 0x13, 0x05,
|
||||
0x10, 0x00, 0x93, 0x05, 0x00, 0x00, 0x73, 0x00, 0x10, 0x00, 0x6f, 0x00, 0x00, 0x00,
|
||||
}; //64-Byte memory
|
||||
uint8_t M[MSIZE]; //1024-Byte memory
|
||||
|
||||
|
||||
bool halt = false;
|
||||
@ -45,13 +60,26 @@ void inst_cycle()
|
||||
PC += 4;
|
||||
}
|
||||
|
||||
int main()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
PC = 0;
|
||||
R[0] = 0;
|
||||
Assert(argc >= 2, "Program is not given"); // 要求至少包含一个参数
|
||||
FILE *fp = fopen(argv[1], "r");
|
||||
Perror(fp != NULL, "Fail to open %s", argv[1]); // 要求argv[1]是一个可以成功打开的文件
|
||||
int ret = fseek(fp, 0, SEEK_END);
|
||||
Perror(ret != -1, "Fail to seek the end of the file"); // 要求fseek()成功
|
||||
long fsize = ftell(fp);
|
||||
Perror(fsize != -1, "Fail to return the file position"); // 要求ftell()成功
|
||||
rewind(fp);
|
||||
Assert(fsize < MSIZE, "Program size exceeds 1024 Bytes"); // 要求程序大小不超过1024字节
|
||||
ret = fread(M, 1, MSIZE, fp);
|
||||
Assert(ret == fsize, "Fail to load the whole program"); // 要求完全读出程序的内容
|
||||
fclose(fp);
|
||||
while (!halt)
|
||||
{
|
||||
inst_cycle();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,27 @@
|
||||
static void ebreak(long arg0, long arg1)
|
||||
{
|
||||
asm volatile("addi a0, x0, %0;"
|
||||
"addi a1, x0, %1;"
|
||||
"ebreak"
|
||||
:
|
||||
: "i"(arg0), "i"(arg1));
|
||||
}
|
||||
|
||||
static void putch(char ch)
|
||||
{
|
||||
ebreak(0, ch);
|
||||
}
|
||||
|
||||
static void halt(int code)
|
||||
{
|
||||
ebreak(1, code);
|
||||
while (1)
|
||||
;
|
||||
}
|
||||
|
||||
void _start() {
|
||||
putch('H'); putch('e'); putch('l'); putch('l'); putch('o'); putch(','); putch(' ');
|
||||
putch('R'); putch('I'); putch('S'); putch('C'); putch('-'); putch('V'); putch('!');
|
||||
putch('\n');
|
||||
halt(0);
|
||||
}
|
||||
@ -0,0 +1 @@
|
||||
#define MSIZE 512
|
||||
Loading…
x
Reference in New Issue
Block a user