Skip to content

Commit

Permalink
完善了RV32C实现,并通过测试
Browse files Browse the repository at this point in the history
  • Loading branch information
ponyma committed Mar 30, 2023
1 parent cc14c63 commit f30e8b2
Show file tree
Hide file tree
Showing 13 changed files with 863 additions and 452 deletions.
20 changes: 20 additions & 0 deletions src/main/java/com/ponyvm/soc/board/RV32.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,26 @@ public class RV32 implements Soc {

public CPU CORE;

@Override
public String getNAME() {
return this.NAME;
}

@Override
public String getVERSION() {
return this.VERSION;
}

@Override
public SysBus getSYS_BUS() {
return this.SYS_BUS;
}

@Override
public CPU getCORE() {
return this.CORE;
}

@Override
public int launchROM(File rom) throws IOException {
ELFFile elfFile = loadELFFile(rom);
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/com/ponyvm/soc/board/Soc.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
package com.ponyvm.soc.board;

import com.ponyvm.soc.core.CPU;
import com.ponyvm.soc.internal.sysbus.SysBus;

import java.io.File;
import java.io.IOException;

public interface Soc {
String getNAME();

String getVERSION();

SysBus getSYS_BUS();

CPU getCORE();

int launchROM(File rom) throws IOException;
}
224 changes: 86 additions & 138 deletions src/main/java/com/ponyvm/soc/core/CPU.java

Large diffs are not rendered by default.

314 changes: 1 addition & 313 deletions src/main/java/com/ponyvm/soc/core/Instruction.java
Original file line number Diff line number Diff line change
@@ -1,316 +1,4 @@
package com.ponyvm.soc.core;

public class Instruction {
int instruction, opcode, rd, rs1, rs2, funct3, funct7, imm;
boolean noRd = false;
boolean sType = false;
boolean ecall = false;
boolean compress = false;

public Instruction(int instruction) {
this.instruction = instruction;
this.opcode = instruction & 0x03;

//非压缩指令
if (this.opcode == 3) {
this.opcode = instruction & 0x7F; // First 7 bits
this.rd = (instruction >> 7) & 0x1F; // bits 11 to 7
this.funct3 = (instruction >> 12) & 0x7; // bits 14 to 12
this.rs1 = (instruction >> 15) & 0x1F; // bits 19 to 15
this.rs2 = (instruction >> 20) & 0x1F; // bits 24 to 20
} else {
this.compress = true;
this.rd = (instruction >> 7) & 0x1F; // bits 11 to 7
this.funct3 = (instruction >> 12) & 0x7; // bits 14 to 12
this.rs1 = (instruction >> 15) & 0x1F; // bits 19 to 15
this.rs2 = (instruction >> 20) & 0x1F; // bits 24 to 20
}

switch (opcode) {
//16位压缩指令
case 0b00://

break;
case 0b01:

break;
case 0b10:

break;
//32位指令
case 0b1101111: // J-type
this.imm = getImmJ(instruction);
break;
case 0b1100111: // I-type
case 0b0000011:
case 0b0010011:
this.imm = (instruction >> 20); // bits 31 to 20
this.funct7 = (instruction >> 25) & 0x7F;// bits 31 to 25
break;
case 0b0110011: // R-type
this.funct7 = (instruction >> 25) & 0x7F; // bits 31 to 25
break;
case 0b0100011: // S-type
imm = (((instruction >> 20) & 0xFFFFFFE0) |
((instruction >>> 7) & 0x0000001F)); // Returns bits 31 to 25 and 11 to 7
break;
case 0b1100011: // B-type
this.imm = getImmB(instruction);
break;
case 0b0110111:// U-type
case 0b0010111:
this.imm = instruction & 0xFFFFF000;
break;
default:
// R-type 和 ECALL 没有立即数
break;
}
}


/**
* 获取 B-type 立即数
* imm[12|10:5|4:1|11]
*/
private int getImmB(int instruction) {
return ((((((instruction >>> 7) & 0x0000001F) | (instruction >> 20) & 0xFFFFFFE0)) & 0xFFFFF7FE)
| (((((instruction >> 20) & 0xFFFFFFE0) | ((instruction >>> 7) & 0x0000001F)) & 0x00000001) << 11));
}

/**
* 获取 J-type 立即数
* Decoded like this: imm[20|10:1|11|19:12]
*/
private int getImmJ(int instruction) {
int b12to19 = (instruction >> 12) & 0xFF; // Bits 12 to 19 of immediate (12 to 19 of instruction)
int b11 = (instruction >> 20) & 0x1; // Bit 11 of immediate (20th bit of instruction)
int b1to10 = (instruction >> 21) & 0x3FF; // Bit 1 to 10 of immediate (21 to 30 of instruction)
int b20 = (instruction >> 31); // Bit 20 of immediate (MSB of instruction)
return (b20 << 20 | b12to19 << 12 | b11 << 11 | b1to10 << 1);
}

public String toAssemblyString() {
String instr = "", arg1 = "", arg2 = "", arg3 = "";
switch (opcode) {
// R-type instructions
case 0b0110011: // ADD / SUB / SLL / SLT / SLTU / XOR / SRL / SRA / OR / AND
arg1 = String.format("x%d", rd);
arg2 = String.format("x%d", rs1);
arg3 = String.format("x%d", rs2);
switch (funct3) {
case 0b000: // ADD / SUB
switch (funct7) {
case 0b0000000: // ADD
instr = "add";
break;
case 0b0100000: // SUB
instr = "sub";
}
break;
case 0b001: // SLL
instr = "sll";
break;
case 0b010: // SLT
instr = "slt";
break;
case 0b011: // SLTU
instr = "sltu";
break;
case 0b100: // XOR
instr = "xor";
break;
case 0b101: // SRL / SRA
switch (funct7) {
case 0b0000000: // SRL
instr = "srl";
break;
case 0b0100000: // SRA
instr = "sra";
break;
}
break;
case 0b110: // OR
instr = "or";
break;
case 0b111: // AND
instr = "and";
}
break;
case 0b1101111: //JAL
arg1 = String.format("x%d", rd);
arg2 = String.format("%d(x%d)", imm, rs1);
instr = "jal";
break;
case 0b1100111: // JALR
arg1 = String.format("x%d", rd);
arg2 = String.format("%d(x%d)", imm, rs1);
instr = "jalr";
break;
case 0b0000011: // LB / LH / LW / LBU / LHU
arg1 = String.format("x%d", rd);
arg2 = String.format("%d(x%d)", imm, rs1);
switch (funct3) {
case 0b000: // LB
instr = "lb";
break;
case 0b001: // LH
instr = "lh";
break;
case 0b010: // LW
instr = "lw";
break;
case 0b100: // LBU
instr = "lbu";
break;
case 0b101: // LHU
instr = "lhu";
break;
}
break;
case 0b0010011: // ADDI / SLTI / SLTIU / XORI / ORI / ANDI / SLLI / SRLI / SRAI
arg1 = String.format("x%d", rd);
arg2 = String.format("x%d", rs1);
arg3 = String.format("%d", imm);
switch (funct3) {
case 0b000: // ADDI
instr = "addi";
break;
case 0b010: // SLTI
instr = "slti";
break;
case 0b011: // SLTIU
instr = "sltiu";
break;
case 0b100: // XORI
instr = "xori";
break;
case 0b110: // ORI
instr = "ori";
break;
case 0b111: // ANDI
instr = "andi";
break;
case 0b001: // SLLI
instr = "slli";
break;
case 0b101: // SRLI / SRAI
switch (funct7) {
case 0b0000000: // SRLI
instr = "srli";
break;
case 0b0100000: // SRAI
instr = "srai";
break;
}
break;
}
break;
case 0b0001111: // FENCE / FENCE.I
switch (funct3) {
case 0b000: // FENCE
instr = "fence";
break;
case 0b001: // FENCE.I
instr = "fence.i";
break;
}
break;
case 0b1110011: // ECALL / EBREAK / CSRRW / CSRRS / CSRRC / CSRRWI / CSRRSI / CSRRCI
switch (funct3) {
case 0b000: // ECALL / EBREAK
switch (imm) {
case 0b000000000000: // ECALL
instr = "ecall";
ecall = true;
break;
case 0b000000000001: // EBREAK
instr = "ebreak";
break;
}
break;
case 0b001: // CSRRW
instr = "csrrw";
break;
case 0b010: // CSRRS
instr = "csrrs";
break;
case 0b011: // CSRRC
instr = "csrrc";
break;
case 0b101: // CSRRWI
instr = "csrrwi";
break;
case 0b110: // CSRRSI
instr = "csrrsi";
break;
case 0b111: // CSRRCI
instr = "csrrci";
break;
}
noRd = true;
break;

//S-type instructions
case 0b0100011: //SB / SH / SW
arg1 = String.format("x%d", rs2);
arg2 = String.format("%d(x%d)", imm, rs1);
switch (funct3) {
case 0b000: // SB
instr = "sb";
break;
case 0b001: // SH
instr = "sh";
break;
case 0b010: // SW
instr = "sw";
break;
}
noRd = true;
sType = true;
break;

//B-type instructions
case 0b1100011: // BEQ / BNE / BLT / BGE / BLTU / BGEU
arg1 = String.format("x%d", rs1);
arg2 = String.format("x%d", rs2);
arg3 = String.format("%d", imm);
switch (funct3) {
case 0b000: // BEQ
instr = "beq";
break;
case 0b001: // BNE
instr = "bne";
break;
case 0b100: // BLT
instr = "blt";
break;
case 0b101: // BGE
instr = "bge";
break;
case 0b110: //BLTU
instr = "bltu";
break;
case 0b111: //BLGEU
instr = "blgeu";
break;
}
noRd = true;
break;

//U-type instructions
case 0b0110111: //LUI
arg1 = String.format("x%d", rd);
arg2 = String.format("%d", imm >>> 12);
instr = "lui";
break;
case 0b0010111: //AUIPC
arg1 = String.format("x%d", rd);
arg2 = String.format("%d", imm >>> 12);
instr = "auipc";
break;
default:
return String.format("Unrecognized: 0x%08x", instruction);
}
return String.format("%s %s %s %s", instr, arg1, arg2, arg3);
}
}
}
Loading

0 comments on commit f30e8b2

Please sign in to comment.