Improved disassembly of running ISS

This commit is contained in:
Eyck Jentzsch 2018-11-24 20:29:24 +01:00
parent df03e90181
commit 769610d6fc
27 changed files with 5277 additions and 5106 deletions

View File

@ -1,6 +1,7 @@
[requires] [requires]
gsl_microsoft/20180102@bincrafters/stable gsl_microsoft/20180102@bincrafters/stable
spdlog/0.16.3@bincrafters/stable spdlog/0.16.3@bincrafters/stable
fmt/5.2.1@bincrafters/stable
Seasocks/1.3.2@minres/stable Seasocks/1.3.2@minres/stable
SystemC/2.3.2@minres/stable SystemC/2.3.2@minres/stable
SystemCVerification/2.0.1@minres/stable SystemCVerification/2.0.1@minres/stable
@ -11,6 +12,7 @@
[options] [options]
Seasocks:shared=True Seasocks:shared=True
fmt:header_only=True
SystemC:stdcxx=14 SystemC:stdcxx=14
SystemC:shared=True SystemC:shared=True
SystemCVerification:stdcxx=14 SystemCVerification:stdcxx=14

@ -1 +1 @@
Subproject commit 0b499d216a2835015b889180ca5108b2daaed9b9 Subproject commit 83cd591e4935d5c1916e4e56d9c6147e3aab8480

View File

@ -9,7 +9,7 @@ InsructionSet RV32A extends RV32IBase{
instructions{ instructions{
LR.W { LR.W {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d"; args_disass: "{name(rd)}, {name(rs1)}";
if(rd!=0){ if(rd!=0){
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{32}, XLEN); X[rd]<= sext(MEM[offs]{32}, XLEN);
@ -18,7 +18,7 @@ InsructionSet RV32A extends RV32IBase{
} }
SC.W { SC.W {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res1[32] <= RES[offs]{32}; val res1[32] <= RES[offs]{32};
if(res1!=0) if(res1!=0)
@ -27,14 +27,14 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOSWAP.W{ AMOSWAP.W{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
if(rd!=0) X[rd]<=sext(MEM[offs]{32}); if(rd!=0) X[rd]<=sext(MEM[offs]{32});
MEM[offs]{32}<=X[rs2]; MEM[offs]{32}<=X[rs2];
} }
AMOADD.W{ AMOADD.W{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -43,7 +43,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOXOR.W{ AMOXOR.W{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -52,7 +52,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOAND.W{ AMOAND.W{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -61,7 +61,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOOR.W { AMOOR.W {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -70,7 +70,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOMIN.W{ AMOMIN.W{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -79,7 +79,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOMAX.W{ AMOMAX.W{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= sext(MEM[offs]{32}); val res1[XLEN] <= sext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -88,7 +88,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOMINU.W{ AMOMINU.W{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= zext(MEM[offs]{32}); val res1[XLEN] <= zext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;
@ -97,7 +97,7 @@ InsructionSet RV32A extends RV32IBase{
} }
AMOMAXU.W{ AMOMAXU.W{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111; encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%aq$d,rel=%rl$d)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN]<=X[rs1]; val offs[XLEN]<=X[rs1];
val res1[XLEN] <= zext(MEM[offs]{32}); val res1[XLEN] <= zext(MEM[offs]{32});
if(rd!=0) X[rd]<=res1; if(rd!=0) X[rd]<=res1;

View File

@ -14,7 +14,7 @@ InsructionSet RV32IC {
instructions{ instructions{
JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word JALR(no_cont){ // overwriting the implementation if rv32i, alignment does not need to be word
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111;
args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}";
val new_pc[XLEN] <= X[rs1]s+ imm; val new_pc[XLEN] <= X[rs1]s+ imm;
val align[XLEN] <= new_pc & 0x1; val align[XLEN] <= new_pc & 0x1;
if(align != 0){ if(align != 0){
@ -26,25 +26,25 @@ InsructionSet RV32IC {
} }
C.ADDI4SPN { //(RES, imm=0) C.ADDI4SPN { //(RES, imm=0)
encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00; encoding: b000 | imm[5:4] | imm[9:6] | imm[2:2] | imm[3:3] | rd[2:0] | b00;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(imm == 0) raise(0, 2); if(imm == 0) raise(0, 2);
X[rd+8] <= X[2] + imm; X[rd+8] <= X[2] + imm;
} }
C.LW { // (RV32) C.LW { // (RV32)
encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; encoding: b010 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
args_disass: "x(8+%rd$d), x(8+%rs1$d), 0x%uimm$05x"; args_disass: "{name(8+rd)}, {name(8+rs1)}, {uimm:#05x}";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
X[rd+8] <= MEM[offs]{32}; X[rd+8] <= MEM[offs]{32};
} }
C.SW {//(RV32) C.SW {//(RV32)
encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; encoding: b110 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
args_disass: "x(8+%rs1$d), x(8+%rs2$d), 0x%uimm$05x"; args_disass: "{name(8+rs1)}, {name(8+rs2)}, {uimm:#05x}";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{32} <= X[rs2+8]; MEM[offs]{32} <= X[rs2+8];
} }
C.ADDI {//(RV32) C.ADDI {//(RV32)
encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01; encoding:b000 | imm[5:5]s | rs1[4:0] | imm[4:0]s | b01;
args_disass: "x%rs1$d, 0x%imm$05x"; args_disass: "{name(rs1)}, {imm:#05x}";
X[rs1] <= X[rs1]'s + imm; X[rs1] <= X[rs1]'s + imm;
} }
C.NOP { C.NOP {
@ -53,118 +53,118 @@ InsructionSet RV32IC {
// C.JAL will be overwritten by C.ADDIW for RV64/128 // C.JAL will be overwritten by C.ADDIW for RV64/128
C.JAL(no_cont) {//(RV32) C.JAL(no_cont) {//(RV32)
encoding: b001 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; encoding: b001 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
X[1] <= PC+2; X[1] <= PC+2;
PC<=PC's+imm; PC<=PC's+imm;
} }
C.LI {//(RV32) C.LI {//(RV32)
encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01; encoding:b010 | imm[5:5]s | rd[4:0] | imm[4:0]s | b01;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm; X[rd] <= imm;
} }
// order matters here as C.ADDI16SP overwrites C.LUI vor rd==2 // order matters here as C.ADDI16SP overwrites C.LUI vor rd==2
C.LUI {//(RV32) C.LUI {//(RV32)
encoding:b011 | imm[17:17] | rd[4:0] | imm[16:12]s | b01; encoding:b011 | imm[17:17] | rd[4:0] | imm[16:12]s | b01;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd == 0) raise(0, 2); //TODO: should it be handled as trap? if(rd == 0) raise(0, 2); //TODO: should it be handled as trap?
if(imm == 0) raise(0, 2); //TODO: should it be handled as trap? if(imm == 0) raise(0, 2); //TODO: should it be handled as trap?
X[rd] <= imm; X[rd] <= imm;
} }
C.ADDI16SP {//(RV32) C.ADDI16SP {//(RV32)
encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01; encoding:b011 | imm[9:9]s | b00010 | imm[4:4]s | imm[6:6]s | imm[8:7]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
X[2] <= X[2]s + imm; X[2] <= X[2]s + imm;
} }
C.SRLI {//(RV32 nse) C.SRLI {//(RV32 nse)
encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01; encoding:b100 | b0 | b00 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d"; args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8; val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shrl(X[rs1_idx], shamt); X[rs1_idx] <= shrl(X[rs1_idx], shamt);
} }
C.SRAI {//(RV32) C.SRAI {//(RV32)
encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01; encoding:b100 | b0 | b01 | rs1[2:0] | shamt[4:0] | b01;
args_disass: "x(8+%rs1$d), %shamt$d"; args_disass: "{name(8+rs1)}, {shamt}";
val rs1_idx[5] <= rs1+8; val rs1_idx[5] <= rs1+8;
X[rs1_idx] <= shra(X[rs1_idx], shamt); X[rs1_idx] <= shra(X[rs1_idx], shamt);
} }
C.ANDI {//(RV32) C.ANDI {//(RV32)
encoding:b100 | imm[5:5] | b10 | rs1[2:0] | imm[4:0] | b01; encoding:b100 | imm[5:5] | b10 | rs1[2:0] | imm[4:0] | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
val rs1_idx[5] <= rs1 + 8; val rs1_idx[5] <= rs1 + 8;
X[rs1_idx] <= X[rs1_idx] & imm; X[rs1_idx] <= X[rs1_idx] & imm;
} }
C.SUB {//(RV32) C.SUB {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b00 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] - X[rs2 + 8]; X[rd_idx] <= X[rd_idx] - X[rs2 + 8];
} }
C.XOR {//(RV32) C.XOR {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b01 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8]; X[rd_idx] <= X[rd_idx] ^ X[rs2 + 8];
} }
C.OR {//(RV32) C.OR {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b10 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b10 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] | X[rs2 + 8]; X[rd_idx] <= X[rd_idx] | X[rs2 + 8];
} }
C.AND {//(RV32) C.AND {//(RV32)
encoding:b100 | b0 | b11 | rd[2:0] | b11 | rs2[2:0] | b01; encoding:b100 | b0 | b11 | rd[2:0] | b11 | rs2[2:0] | b01;
args_disass: "x(8+%rd$d), x(8+%rs2$d)"; args_disass: "{name(8+rd)}, {name(8+rs2)}";
val rd_idx[5] <= rd + 8; val rd_idx[5] <= rd + 8;
X[rd_idx] <= X[rd_idx] & X[rs2 + 8]; X[rd_idx] <= X[rd_idx] & X[rs2 + 8];
} }
C.J(no_cont) {//(RV32) C.J(no_cont) {//(RV32)
encoding:b101 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01; encoding:b101 | imm[11:11]s | imm[4:4]s | imm[9:8]s | imm[10:10]s | imm[6:6]s | imm[7:7]s | imm[3:1]s | imm[5:5]s | b01;
args_disass: "0x%imm$05x"; args_disass: "{imm:#05x}";
PC<=PC's+imm; PC<=PC's+imm;
} }
C.BEQZ(no_cont,cond) {//(RV32) C.BEQZ(no_cont,cond) {//(RV32)
encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01; encoding:b110 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s |imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
PC<=choose(X[rs1+8]==0, PC's+imm, PC+2); PC<=choose(X[rs1+8]==0, PC's+imm, PC+2);
} }
C.BNEZ(no_cont,cond) {//(RV32) C.BNEZ(no_cont,cond) {//(RV32)
encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01; encoding:b111 | imm[8:8]s | imm[4:3]s | rs1[2:0] | imm[7:6]s | imm[2:1]s | imm[5:5]s | b01;
args_disass: "x(8+%rs1$d), 0x%imm$05x"; args_disass: "{name(8+rs1)}, {imm:#05x}";
PC<=choose(X[rs1+8]!=0, PC's+imm, PC+2); PC<=choose(X[rs1+8]!=0, PC's+imm, PC+2);
} }
C.SLLI {//(RV32) C.SLLI {//(RV32)
encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10; encoding:b000 | b0 | rs1[4:0] | shamt[4:0] | b10;
args_disass: "x%rs1$d, %shamt$d"; args_disass: "{name(rs1)}, {shamt}";
if(rs1 == 0) raise(0, 2); if(rs1 == 0) raise(0, 2);
X[rs1] <= shll(X[rs1], shamt); X[rs1] <= shll(X[rs1], shamt);
} }
C.LWSP {// C.LWSP {//
encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; encoding:b010 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
args_disass: "x%rd$d, sp, 0x%uimm$05x"; args_disass: "{name(rd)}, sp, {uimm:#05x}";
val offs[XLEN] <= X[2] + uimm; val offs[XLEN] <= X[2] + uimm;
X[rd] <= MEM[offs]{32}; X[rd] <= MEM[offs]{32};
} }
// order matters as C.JR is a special case of C.MV // order matters as C.JR is a special case of C.MV
C.MV {//(RV32) C.MV {//(RV32)
encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10; encoding:b100 | b0 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs2)}";
X[rd] <= X[rs2]; X[rd] <= X[rs2];
} }
C.JR(no_cont) {//(RV32) C.JR(no_cont) {//(RV32)
encoding:b100 | b0 | rs1[4:0] | b00000 | b10; encoding:b100 | b0 | rs1[4:0] | b00000 | b10;
args_disass: "x%rs1$d"; args_disass: "{name(rs1)}";
PC <= X[rs1]; PC <= X[rs1];
} }
// order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD // order matters as C.EBREAK is a special case of C.JALR which is a special case of C.ADD
C.ADD {//(RV32) C.ADD {//(RV32)
encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10; encoding:b100 | b1 | rd[4:0] | rs2[4:0] | b10;
args_disass: "x%rd$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs2)}";
X[rd] <= X[rd] + X[rs2]; X[rd] <= X[rd] + X[rs2];
} }
C.JALR(no_cont) {//(RV32) C.JALR(no_cont) {//(RV32)
encoding:b100 | b1 | rs1[4:0] | b00000 | b10; encoding:b100 | b1 | rs1[4:0] | b00000 | b10;
args_disass: "x%rs1$d"; args_disass: "{name(rs1)}";
X[1] <= PC+2; X[1] <= PC+2;
PC<=X[rs1]; PC<=X[rs1];
} }
@ -174,7 +174,7 @@ InsructionSet RV32IC {
} }
C.SWSP {// C.SWSP {//
encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; encoding:b110 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass: "x2+0x%uimm$05x, x%rs2$d"; args_disass: "x2+{uimm:#05x}, {name(rs2)}";
val offs[XLEN] <= X[2] + uimm; val offs[XLEN] <= X[2] + uimm;
MEM[offs]{32} <= X[rs2]; MEM[offs]{32} <= X[rs2];
} }
@ -199,7 +199,7 @@ InsructionSet RV32FC extends RV32IC{
instructions{ instructions{
C.FLW { C.FLW {
encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00; encoding: b011 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rd[2:0] | b00;
args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
@ -211,13 +211,13 @@ InsructionSet RV32FC extends RV32IC{
} }
C.FSW { C.FSW {
encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00; encoding: b111 | uimm[5:3] | rs1[2:0] | uimm[2:2] | uimm[6:6] | rs2[2:0] | b00;
args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{32}<=F[rs2+8]{32}; MEM[offs]{32}<=F[rs2+8]{32};
} }
C.FLWSP { C.FLWSP {
encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10; encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:2] | uimm[7:6] | b10;
args_disass:"f%rd$d, %uimm%(x2)"; args_disass:"f{rd}, {uimm}(x2)";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
@ -229,7 +229,7 @@ InsructionSet RV32FC extends RV32IC{
} }
C.FSWSP { C.FSWSP {
encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10; encoding:b111 | uimm[5:2] | uimm[7:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), "; args_disass:"f{rs2}, {uimm}(x2), ";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
MEM[offs]{32}<=F[rs2]{32}; MEM[offs]{32}<=F[rs2]{32};
} }
@ -250,7 +250,7 @@ InsructionSet RV32DC extends RV32IC{
instructions{ instructions{
C.FLD { //(RV32/64) C.FLD { //(RV32/64)
encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00; encoding: b001 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rd[2:0] | b00;
args_disass:"f(8+%rd$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rd}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -262,13 +262,13 @@ InsructionSet RV32DC extends RV32IC{
} }
C.FSD { //(RV32/64) C.FSD { //(RV32/64)
encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00; encoding: b101 | uimm[5:3] | rs1[2:0] | uimm[7:6] | rs2[2:0] | b00;
args_disass:"f(8+%rs2$d), %uimm%(x(8+%rs1$d))"; args_disass:"f(8+{rs2}), {uimm}({name(8+rs1)})";
val offs[XLEN] <= X[rs1+8]+uimm; val offs[XLEN] <= X[rs1+8]+uimm;
MEM[offs]{64}<=F[rs2+8]{64}; MEM[offs]{64}<=F[rs2+8]{64};
} }
C.FLDSP {//(RV32/64) C.FLDSP {//(RV32/64)
encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; encoding:b001 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
args_disass:"f%rd$d, %uimm%(x2)"; args_disass:"f{rd}, {uimm}(x2)";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -280,7 +280,7 @@ InsructionSet RV32DC extends RV32IC{
} }
C.FSDSP {//(RV32/64) C.FSDSP {//(RV32/64)
encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; encoding:b101 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;
args_disass:"f%rs2$d, %uimm%(x2), "; args_disass:"f{rs2}, {uimm}(x2), ";
val offs[XLEN] <= X[2]+uimm; val offs[XLEN] <= X[2]+uimm;
MEM[offs]{64}<=F[rs2]{64}; MEM[offs]{64}<=F[rs2]{64};
} }
@ -307,11 +307,11 @@ InsructionSet RV64IC extends RV32IC {
} }
C.SUBW {//(RV64/128, RV32 res) C.SUBW {//(RV64/128, RV32 res)
encoding:b100 | b1 | b11 | rd[2:0] | b00 | rs2[2:0] | b01; encoding:b100 | b1 | b11 | rd[2:0] | b00 | rs2[2:0] | b01;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass: "{name(rd)}, sp, {imm:#05x}";
} }
C.ADDW {//(RV64/128 RV32 res) C.ADDW {//(RV64/128 RV32 res)
encoding:b100 | b1 | b11 | rd[2:0] | b01 | rs2[2:0] | b01; encoding:b100 | b1 | b11 | rd[2:0] | b01 | rs2[2:0] | b01;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass: "{name(rd)}, sp, {imm:#05x}";
} }
C.ADDIW {//(RV64/128) C.ADDIW {//(RV64/128)
encoding:b001 | imm[5:5] | rs1[4:0] | imm[4:0] | b01; encoding:b001 | imm[5:5] | rs1[4:0] | imm[4:0] | b01;
@ -327,7 +327,7 @@ InsructionSet RV64IC extends RV32IC {
} }
C.LDSP {//(RV64/128 C.LDSP {//(RV64/128
encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10; encoding:b011 | uimm[5:5] | rd[4:0] | uimm[4:3] | uimm[8:6] | b10;
args_disass: "x%rd$d, sp, 0x%imm$05x"; args_disass: "{name(rd)}, sp, {imm:#05x}";
} }
C.SDSP {//(RV64/128) C.SDSP {//(RV64/128)
encoding:b111 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10; encoding:b111 | uimm[5:3] | uimm[8:6] | rs2[4:0] | b10;

View File

@ -10,7 +10,7 @@ InsructionSet RV32D extends RV32IBase{
instructions{ instructions{
FLD { FLD {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000111;
args_disass:"f%rd$d, %imm%(x%rs1$d)"; args_disass:"f{rd}, {imm}({rs1})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
val res[64] <= MEM[offs]{64}; val res[64] <= MEM[offs]{64};
if(FLEN==64) if(FLEN==64)
@ -22,13 +22,13 @@ InsructionSet RV32D extends RV32IBase{
} }
FSD { FSD {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100111;
args_disass:"f%rs2$d, %imm%(x%rs1$d)"; args_disass:"f{rs2}, {imm}({rs1})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{64}<=F[rs2]{64}; MEM[offs]{64}<=F[rs2]{64};
} }
FMADD.D { FMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(0, 64), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -42,7 +42,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMSUB.D { FMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -56,7 +56,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FNMADD.D { FNMADD.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -70,7 +70,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FNMSUB.D { FNMSUB.D {
encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; encoding: rs3[4:0] | b01 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmadd_d(F[rs1]{64}, F[rs2]{64}, F[rs3]{64}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -84,7 +84,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FADD.D { FADD.D {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f + F[rs2]f; // F[rd]f <= F[rs1]f + F[rs2]f;
val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fadd_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -98,7 +98,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSUB.D { FSUB.D {
encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f - F[rs2]f; // F[rd]f <= F[rs1]f - F[rs2]f;
val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fsub_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -112,7 +112,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMUL.D { FMUL.D {
encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001001 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f * F[rs2]f; // F[rd]f <= F[rs1]f * F[rs2]f;
val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fmul_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -126,7 +126,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FDIV.D { FDIV.D {
encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001101 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f / F[rs2]f; // F[rd]f <= F[rs1]f / F[rs2]f;
val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fdiv_d(F[rs1]{64}, F[rs2]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -140,7 +140,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSQRT.D { FSQRT.D {
encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0101101 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
//F[rd]f<=sqrt(F[rs1]f); //F[rd]f<=sqrt(F[rs1]f);
val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8})); val res[64] <= fdispatch_fsqrt_d(F[rs1]{64}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==64) if(FLEN==64)
@ -154,7 +154,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJ.D { FSGNJ.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000); val res[64] <= (F[rs1]{64} & 0x7fffffff) | (F[rs2]{64} & 0x80000000);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
@ -165,7 +165,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJN.D { FSGNJN.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000); val res[64] <= (F[rs1]{64} & 0x7fffffff) | (~F[rs2]{64} & 0x80000000);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
@ -176,7 +176,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FSGNJX.D { FSGNJX.D {
encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b0010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000); val res[64] <= F[rs1]{64} ^ (F[rs2]{64} & 0x80000000);
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
@ -187,7 +187,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMIN.D { FMIN.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010101 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
if(FLEN==64) if(FLEN==64)
@ -201,7 +201,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FMAX.D { FMAX.D {
encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010101 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); val res[64] <= fdispatch_fsel_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
if(FLEN==64) if(FLEN==64)
@ -215,7 +215,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.S.D { FCVT.S.D {
encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d"; args_disass:"f{rd}, f{rs1}";
val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8}); val res[32] <= fdispatch_fconv_d2f(F[rs1], rm{8});
// NaN boxing // NaN boxing
val upper[FLEN] <= -1; val upper[FLEN] <= -1;
@ -223,7 +223,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.D.S { FCVT.D.S {
encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d"; args_disass:"f{rd}, f{rs1}";
val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8}); val res[64] <= fdispatch_fconv_f2d(F[rs1]{32}, rm{8});
if(FLEN==64){ if(FLEN==64){
F[rd] <= res; F[rd] <= res;
@ -234,47 +234,47 @@ InsructionSet RV32D extends RV32IBase{
} }
FEQ.D { FEQ.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32)); X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(0, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLT.D { FLT.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32)); X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(2, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLE.D { FLE.D {
encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b1010001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"{name(rd)}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32)); X[rd]<=fdispatch_fcmp_d(F[rs1]{64}, F[rs2]{64}, zext(1, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCLASS.D { FCLASS.D {
encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1110001 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<=fdispatch_fclass_d(F[rs1]{64}); X[rd]<=fdispatch_fclass_d(F[rs1]{64});
} }
FCVT.W.D { FCVT.W.D {
encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN); X[rd]<= sext(fdispatch_fcvt_d(F[rs1]{64}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCVT.WU.D { FCVT.WU.D {
encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"{name(rd)}, f{rs1}";
X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN); X[rd]<= zext(fdispatch_fcvt_d(F[rs1]{64}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCVT.D.W { FCVT.D.W {
encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101001 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, {rs1}";
val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8}); val res[64] <= fdispatch_fcvt_d(sext(X[rs1],64), zext(2, 32), rm{8});
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;
@ -285,7 +285,7 @@ InsructionSet RV32D extends RV32IBase{
} }
FCVT.D.WU { FCVT.D.WU {
encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101001 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, {rs1}";
val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8}); val res[64] <=fdispatch_fcvt_d(zext(X[rs1],64), zext(3,32), rm{8});
if(FLEN==64) if(FLEN==64)
F[rd] <= res; F[rd] <= res;

View File

@ -10,7 +10,7 @@ InsructionSet RV32F extends RV32IBase{
instructions{ instructions{
FLW { FLW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111; encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000111;
args_disass:"f%rd$d, %imm%(x%rs1$d)"; args_disass:"f{rd}, {imm}(x{rs1})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
val res[32] <= MEM[offs]{32}; val res[32] <= MEM[offs]{32};
if(FLEN==32) if(FLEN==32)
@ -22,13 +22,13 @@ InsructionSet RV32F extends RV32IBase{
} }
FSW { FSW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100111;
args_disass:"f%rs2$d, %imm%(x%rs1$d)"; args_disass:"f{rs2}, {imm}(x{rs1})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32}<=F[rs2]{32}; MEM[offs]{32}<=F[rs2]{32};
} }
FMADD.S { FMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011; encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<= F[rs1]f * F[rs2]f + F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(0, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -42,7 +42,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FMSUB.S { FMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111; encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1000111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=F[rs1]f * F[rs2]f - F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(1, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -56,7 +56,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FNMADD.S { FNMADD.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111; encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001111;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f + F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(2, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -70,7 +70,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FNMSUB.S { FNMSUB.S {
encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011; encoding: rs3[4:0] | b00 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1001011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d, f%rs3$d"; args_disass:"x{rd}, f{rs1}, f{rs2}, f{rs3}";
//F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f; //F[rd]f<=-F[rs1]f * F[rs2]f - F[rs3]f;
val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmadd_s(F[rs1]{32}, F[rs2]{32}, F[rs3]{32}, zext(3, 32), choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -84,7 +84,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FADD.S { FADD.S {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f + F[rs2]f; // F[rd]f <= F[rs1]f + F[rs2]f;
val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fadd_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -98,7 +98,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FSUB.S { FSUB.S {
encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0000100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f - F[rs2]f; // F[rd]f <= F[rs1]f - F[rs2]f;
val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fsub_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -112,7 +112,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FMUL.S { FMUL.S {
encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001000 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f * F[rs2]f; // F[rd]f <= F[rs1]f * F[rs2]f;
val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fmul_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -126,7 +126,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FDIV.S { FDIV.S {
encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0001100 | rs2[4:0] | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
// F[rd]f <= F[rs1]f / F[rs2]f; // F[rd]f <= F[rs1]f / F[rs2]f;
val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fdiv_s(F[rs1]{32}, F[rs2]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -140,7 +140,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FSQRT.S { FSQRT.S {
encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b0101100 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d"; args_disass:"f{rd}, f{rs1}";
//F[rd]f<=sqrt(F[rs1]f); //F[rd]f<=sqrt(F[rs1]f);
val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8})); val res[32] <= fdispatch_fsqrt_s(F[rs1]{32}, choose(rm<7, rm{8}, FCSR{8}));
if(FLEN==32) if(FLEN==32)
@ -154,7 +154,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FSGNJ.S { FSGNJ.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000); val res[32] <= (F[rs1]{32} & 0x7fffffff) | (F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
@ -165,7 +165,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FSGNJN.S { FSGNJN.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000); val res[32] <= (F[rs1]{32} & 0x7fffffff) | (~F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
@ -176,7 +176,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FSGNJX.S { FSGNJX.S {
encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b0010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000); val res[32] <= F[rs1]{32} ^ (F[rs2]{32} & 0x80000000);
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
@ -187,7 +187,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FMIN.S { FMIN.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b0010100 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f<F[rs2]f, F[rs1]f, F[rs2]f);
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32)); val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32));
if(FLEN==32) if(FLEN==32)
@ -201,7 +201,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FMAX.S { FMAX.S {
encoding: b0010100 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b0010100 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"f%rd$d, f%rs1$d, f%rs2$d"; args_disass:"f{rd}, f{rs1}, f{rs2}";
//F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f); //F[rd]f<= choose(F[rs1]f>F[rs2]f, F[rs1]f, F[rs2]f);
val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); val res[32] <= fdispatch_fsel_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32));
if(FLEN==32) if(FLEN==32)
@ -215,47 +215,47 @@ InsructionSet RV32F extends RV32IBase{
} }
FCVT.W.S { FCVT.W.S {
encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"x{rd}, f{rs1}";
X[rd]<= sext(fdispatch_fcvt_s(F[rs1]{32}, zext(0, 32), rm{8}), XLEN); X[rd]<= sext(fdispatch_fcvt_s(F[rs1]{32}, zext(0, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCVT.WU.S { FCVT.WU.S {
encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1100000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"x{rd}, f{rs1}";
X[rd]<= zext(fdispatch_fcvt_s(F[rs1]{32}, zext(1, 32), rm{8}), XLEN); X[rd]<= zext(fdispatch_fcvt_s(F[rs1]{32}, zext(1, 32), rm{8}), XLEN);
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FEQ.S { FEQ.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011; encoding: b1010000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"x{rd}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32)); X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(0, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLT.S { FLT.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1010000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"x{rd}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32)); X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(2, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FLE.S { FLE.S {
encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b1010000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d, f%rs2$d"; args_disass:"x{rd}, f{rs1}, f{rs2}";
X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32)); X[rd]<=fdispatch_fcmp_s(F[rs1]{32}, F[rs2]{32}, zext(1, 32));
val flags[32] <= fdispatch_fget_flags(); val flags[32] <= fdispatch_fget_flags();
FCSR <= (FCSR & ~FFLAG_MASK) + flags{5}; FCSR <= (FCSR & ~FFLAG_MASK) + flags{5};
} }
FCLASS.S { FCLASS.S {
encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011; encoding: b1110000 | b00000 | rs1[4:0] | b001 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"x{rd}, f{rs1}";
X[rd]<=fdispatch_fclass_s(F[rs1]{32}); X[rd]<=fdispatch_fclass_s(F[rs1]{32});
} }
FCVT.S.W { FCVT.S.W {
encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101000 | b00000 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, x{rs1}";
val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8}); val res[32] <= fdispatch_fcvt_s(X[rs1]{32}, zext(2, 32), rm{8});
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
@ -266,7 +266,7 @@ InsructionSet RV32F extends RV32IBase{
} }
FCVT.S.WU { FCVT.S.WU {
encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011; encoding: b1101000 | b00001 | rs1[4:0] | rm[2:0] | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, x{rs1}";
val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8}); val res[32] <=fdispatch_fcvt_s(X[rs1]{32}, zext(3,32), rm{8});
if(FLEN==32) if(FLEN==32)
F[rd] <= res; F[rd] <= res;
@ -277,12 +277,12 @@ InsructionSet RV32F extends RV32IBase{
} }
FMV.X.W { FMV.X.W {
encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b1110000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"x%rd$d, f%rs1$d"; args_disass:"x{rd}, f{rs1}";
X[rd]<=sext(F[rs1]{32}); X[rd]<=sext(F[rs1]{32});
} }
FMV.W.X { FMV.W.X {
encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011; encoding: b1111000 | b00000 | rs1[4:0] | b000 | rd[4:0] | b1010011;
args_disass:"f%rd$d, x%rs1$d"; args_disass:"f{rd}, x{rs1}";
if(FLEN==32) if(FLEN==32)
F[rd] <= X[rs1]; F[rd] <= X[rs1];
else { // NaN boxing else { // NaN boxing

View File

@ -14,29 +14,60 @@ InsructionSet RV32IBase {
registers { registers {
[31:0] X[XLEN], [31:0] X[XLEN],
PC[XLEN](is_pc), PC[XLEN](is_pc),
alias ZERO[XLEN] is X[0] alias ZERO[XLEN] is X[0],
alias RA[XLEN] is X[1],
alias SP[XLEN] is X[2],
alias GP[XLEN] is X[3],
alias TP[XLEN] is X[4],
alias T0[XLEN] is X[5],
alias T1[XLEN] is X[6],
alias T2[XLEN] is X[7],
alias S0[XLEN] is X[8],
alias S1[XLEN] is X[9],
alias A0[XLEN] is X[10],
alias A1[XLEN] is X[11],
alias A2[XLEN] is X[12],
alias A3[XLEN] is X[13],
alias A4[XLEN] is X[14],
alias A5[XLEN] is X[15],
alias A6[XLEN] is X[16],
alias A7[XLEN] is X[17],
alias S2[XLEN] is X[18],
alias S3[XLEN] is X[19],
alias S4[XLEN] is X[20],
alias S5[XLEN] is X[21],
alias S6[XLEN] is X[22],
alias S7[XLEN] is X[23],
alias S8[XLEN] is X[24],
alias S9[XLEN] is X[25],
alias S10[XLEN] is X[26],
alias S11[XLEN] is X[27],
alias T3[XLEN] is X[28],
alias T4[XLEN] is X[29],
alias T5[XLEN] is X[30],
alias T6[XLEN] is X[31]
} }
instructions { instructions {
LUI{ LUI{
encoding: imm[31:12]s | rd[4:0] | b0110111; encoding: imm[31:12]s | rd[4:0] | b0110111;
args_disass: "x%rd$d, 0x%imm$05x"; args_disass: "{name(rd)}, {imm:#05x}";
if(rd!=0) X[rd] <= imm; if(rd!=0) X[rd] <= imm;
} }
AUIPC{ AUIPC{
encoding: imm[31:12]s | rd[4:0] | b0010111; encoding: imm[31:12]s | rd[4:0] | b0010111;
args_disass: "x%rd%, 0x%imm$08x"; args_disass: "{name(rd)}, {imm:#08x}";
if(rd!=0) X[rd] <= PC's+imm; if(rd!=0) X[rd] <= PC's+imm;
} }
JAL(no_cont){ JAL(no_cont){
encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111; encoding: imm[20:20]s | imm[10:1]s | imm[11:11]s | imm[19:12]s | rd[4:0] | b1101111;
args_disass: "x%rd$d, 0x%imm$x"; args_disass: "{name(rd)}, {imm:#0x}";
if(rd!=0) X[rd] <= PC+4; if(rd!=0) X[rd] <= PC+4;
PC<=PC's+imm; PC<=PC's+imm;
} }
JALR(no_cont){ JALR(no_cont){
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b1100111;
args_disass: "x%rd$d, x%rs1$d, 0x%imm$x"; args_disass: "{name(rd)}, {name(rs1)}, {imm:#0x}";
val new_pc[XLEN] <= X[rs1]'s+ imm; val new_pc[XLEN] <= X[rs1]'s+ imm;
val align[XLEN] <= new_pc & 0x2; val align[XLEN] <= new_pc & 0x2;
if(align != 0){ if(align != 0){
@ -48,116 +79,116 @@ InsructionSet RV32IBase {
} }
BEQ(no_cont,cond){ BEQ(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]==X[rs2], PC's+imm, PC+4);
} }
BNE(no_cont,cond){ BNE(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]!=X[rs2], PC's+imm, PC+4);
} }
BLT(no_cont,cond){ BLT(no_cont,cond){
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b100 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s<X[rs2]s, PC's+imm, PC+4); PC<=choose(X[rs1]s<X[rs2]s, PC's+imm, PC+4);
} }
BGE(no_cont,cond) { BGE(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b101 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b101 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]s>=X[rs2]s, PC's+imm, PC+4); PC<=choose(X[rs1]s>=X[rs2]s, PC's+imm, PC+4);
} }
BLTU(no_cont,cond) { BLTU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b110 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]<X[rs2],PC's+imm, PC+4); PC<=choose(X[rs1]<X[rs2],PC's+imm, PC+4);
} }
BGEU(no_cont,cond) { BGEU(no_cont,cond) {
encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b111 | imm[4:1]s | imm[11:11]s | b1100011; encoding: imm[12:12]s |imm[10:5]s | rs2[4:0] | rs1[4:0] | b111 | imm[4:1]s | imm[11:11]s | b1100011;
args_disass:"x%rs1$d, x%rs2$d, 0x%imm$x"; args_disass:"{name(rs1)}, {name(rs2)}, {imm:#0x}";
PC<=choose(X[rs1]>=X[rs2], PC's+imm, PC+4); PC<=choose(X[rs1]>=X[rs2], PC's+imm, PC+4);
} }
LB { LB {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]); if(rd!=0) X[rd]<=sext(MEM[offs]);
} }
LH { LH {
encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b001 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{16}); if(rd!=0) X[rd]<=sext(MEM[offs]{16});
} }
LW { LW {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{32}); if(rd!=0) X[rd]<=sext(MEM[offs]{32});
} }
LBU { LBU {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]); if(rd!=0) X[rd]<=zext(MEM[offs]);
} }
LHU { LHU {
encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b101 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]{16}); if(rd!=0) X[rd]<=zext(MEM[offs]{16});
} }
SB { SB {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b000 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs] <= X[rs2]; MEM[offs] <= X[rs2];
} }
SH { SH {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b001 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{16} <= X[rs2]; MEM[offs]{16} <= X[rs2];
} }
SW { SW {
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b010 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{32} <= X[rs2]; MEM[offs]{32} <= X[rs2];
} }
ADDI { ADDI {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]'s + imm; if(rd != 0) X[rd] <= X[rs1]'s + imm;
} }
SLTI { SLTI {
encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b010 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]s < imm's, 1, 0);
} }
SLTIU { SLTIU {
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
val full_imm[XLEN] <= imm's; val full_imm[XLEN] <= imm's;
if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]'u < full_imm'u, 1, 0);
} }
XORI { XORI {
encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b100 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s ^ imm; if(rd != 0) X[rd] <= X[rs1]s ^ imm;
} }
ORI { ORI {
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s | imm; if(rd != 0) X[rd] <= X[rs1]s | imm;
} }
ANDI { ANDI {
encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011; encoding: imm[11:0]s | rs1[4:0] | b111 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0) X[rd] <= X[rs1]s & imm; if(rd != 0) X[rd] <= X[rs1]s & imm;
} }
SLLI { SLLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -166,7 +197,7 @@ InsructionSet RV32IBase {
} }
SRLI { SRLI {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -175,7 +206,7 @@ InsructionSet RV32IBase {
} }
SRAI { SRAI {
encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(shamt > 31){ if(shamt > 31){
raise(0,0); raise(0,0);
} else { } else {
@ -184,52 +215,52 @@ InsructionSet RV32IBase {
} }
ADD { ADD {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] + X[rs2]; if(rd != 0) X[rd] <= X[rs1] + X[rs2];
} }
SUB { SUB {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] - X[rs2]; if(rd != 0) X[rd] <= X[rs1] - X[rs2];
} }
SLL { SLL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1)); if(rd != 0) X[rd] <= shll(X[rs1], X[rs2]&(XLEN-1));
} }
SLT { SLT {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0); if (rd != 0) X[rd] <= choose(X[rs1]s < X[rs2]s, 1, 0);
} }
SLTU { SLTU {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0); if (rd != 0) X[rd] <= choose(zext(X[rs1]) < zext(X[rs2]), 1, 0);
} }
XOR { XOR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] ^ X[rs2]; if(rd != 0) X[rd] <= X[rs1] ^ X[rs2];
} }
SRL { SRL {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1)); if(rd != 0) X[rd] <= shrl(X[rs1], X[rs2]&(XLEN-1));
} }
SRA { SRA {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1)); if(rd != 0) X[rd] <= shra(X[rs1], X[rs2]&(XLEN-1));
} }
OR { OR {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] | X[rs2]; if(rd != 0) X[rd] <= X[rs1] | X[rs2];
} }
AND { AND {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0) X[rd] <= X[rs1] & X[rs2]; if(rd != 0) X[rd] <= X[rs1] & X[rs2];
} }
FENCE { FENCE {
@ -271,7 +302,7 @@ InsructionSet RV32IBase {
} }
CSRRW { CSRRW {
encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b001 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val rs_val[XLEN] <= X[rs1]; val rs_val[XLEN] <= X[rs1];
if(rd!=0){ if(rd!=0){
val csr_val[XLEN] <= CSR[csr]; val csr_val[XLEN] <= CSR[csr];
@ -284,7 +315,7 @@ InsructionSet RV32IBase {
} }
CSRRS { CSRRS {
encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b010 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr]; val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1]; val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd; if(rd!=0) X[rd] <= xrd;
@ -292,7 +323,7 @@ InsructionSet RV32IBase {
} }
CSRRC { CSRRC {
encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011; encoding: csr[11:0] | rs1[4:0] | b011 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, x%rs1$d"; args_disass:"{name(rd)}, {csr}, {name(rs1)}";
val xrd[XLEN] <= CSR[csr]; val xrd[XLEN] <= CSR[csr];
val xrs1[XLEN] <= X[rs1]; val xrs1[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= xrd; if(rd!=0) X[rd] <= xrd;
@ -300,13 +331,13 @@ InsructionSet RV32IBase {
} }
CSRRWI { CSRRWI {
encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b101 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
if(rd!=0) X[rd] <= CSR[csr]; if(rd!=0) X[rd] <= CSR[csr];
CSR[csr] <= zext(zimm); CSR[csr] <= zext(zimm);
} }
CSRRSI { CSRRSI {
encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b110 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr]; val res[XLEN] <= CSR[csr];
if(zimm!=0) CSR[csr] <= res | zext(zimm); if(zimm!=0) CSR[csr] <= res | zext(zimm);
// make sure rd is written after csr write succeeds // make sure rd is written after csr write succeeds
@ -314,7 +345,7 @@ InsructionSet RV32IBase {
} }
CSRRCI { CSRRCI {
encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011; encoding: csr[11:0] | zimm[4:0] | b111 | rd[4:0] | b1110011;
args_disass:"x%rd$d, %csr$d, 0x%zimm$x"; args_disass:"{name(rd)}, {csr}, {zimm:#0x}";
val res[XLEN] <= CSR[csr]; val res[XLEN] <= CSR[csr];
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN); if(zimm!=0) CSR[csr] <= res & ~zext(zimm, XLEN);

View File

@ -7,7 +7,7 @@ InsructionSet RV32M extends RV32IBase {
instructions{ instructions{
MUL{ MUL{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res , XLEN); X[rd]<= zext(res , XLEN);
@ -15,7 +15,7 @@ InsructionSet RV32M extends RV32IBase {
} }
MULH { MULH {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN); val res[MAXLEN] <= sext(X[rs1], MAXLEN) * sext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN); X[rd]<= zext(res >> XLEN, XLEN);
@ -23,7 +23,7 @@ InsructionSet RV32M extends RV32IBase {
} }
MULHSU { MULHSU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b010 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); val res[MAXLEN] <= sext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN); X[rd]<= zext(res >> XLEN, XLEN);
@ -31,7 +31,7 @@ InsructionSet RV32M extends RV32IBase {
} }
MULHU { MULHU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN); val res[MAXLEN] <= zext(X[rs1], MAXLEN) * zext(X[rs2], MAXLEN);
X[rd]<= zext(res >> XLEN, XLEN); X[rd]<= zext(res >> XLEN, XLEN);
@ -39,7 +39,7 @@ InsructionSet RV32M extends RV32IBase {
} }
DIV { DIV {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
if(X[rs2]!=0){ if(X[rs2]!=0){
val M1[XLEN] <= -1; val M1[XLEN] <= -1;
@ -57,7 +57,7 @@ InsructionSet RV32M extends RV32IBase {
} }
DIVU { DIVU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
if(X[rs2]!=0) if(X[rs2]!=0)
X[rd] <= zext(X[rs1], 32) / zext(X[rs2], 32); X[rd] <= zext(X[rs1], 32) / zext(X[rs2], 32);
@ -67,7 +67,7 @@ InsructionSet RV32M extends RV32IBase {
} }
REM { REM {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
if(X[rs2]!=0) { if(X[rs2]!=0) {
val M1[XLEN] <= -1; val M1[XLEN] <= -1;
@ -85,7 +85,7 @@ InsructionSet RV32M extends RV32IBase {
} }
REMU { REMU {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0110011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
if(X[rs2]!=0) if(X[rs2]!=0)
X[rd] <= zext(X[rs1], 32) % zext(X[rs2], 32); X[rd] <= zext(X[rs1], 32) % zext(X[rs2], 32);

View File

@ -10,7 +10,7 @@ InsructionSet RV64A extends RV64IBase {
instructions{ instructions{
LR.D { LR.D {
encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b00010 | aq[0:0] | rl[0:0] | b00000 | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d"; args_disass: "{name(rd)}, {name(rs1)}";
if(rd!=0){ if(rd!=0){
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
X[rd]<= sext(MEM[offs]{64}, XLEN); X[rd]<= sext(MEM[offs]{64}, XLEN);
@ -19,7 +19,7 @@ InsructionSet RV64A extends RV64IBase {
} }
SC.D { SC.D {
encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b00011 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)}";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[64] <= RES[offs]; val res[64] <= RES[offs];
if(res!=0){ if(res!=0){
@ -31,14 +31,14 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOSWAP.D{ AMOSWAP.D{
encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b00001 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
if(rd!=0) X[rd] <= sext(MEM[offs]{64}); if(rd!=0) X[rd] <= sext(MEM[offs]{64});
MEM[offs]{64} <= X[rs2]; MEM[offs]{64} <= X[rs2];
} }
AMOADD.D{ AMOADD.D{
encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b00000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd]<=res; if(rd!=0) X[rd]<=res;
@ -47,7 +47,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOXOR.D{ AMOXOR.D{
encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b00100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -56,7 +56,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOAND.D{ AMOAND.D{
encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b01100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -65,7 +65,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOOR.D { AMOOR.D {
encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b01000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -74,7 +74,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOMIN.D{ AMOMIN.D{
encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b10000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -83,7 +83,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOMAX.D{ AMOMAX.D{
encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b10100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= sext(MEM[offs]{64}); val res[XLEN] <= sext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -92,7 +92,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOMINU.D{ AMOMINU.D{
encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b11000 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= zext(MEM[offs]{64}); val res[XLEN] <= zext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;
@ -101,7 +101,7 @@ InsructionSet RV64A extends RV64IBase {
} }
AMOMAXU.D{ AMOMAXU.D{
encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111; encoding: b11100 | aq[0:0] | rl[0:0] | rs2[4:0] | rs1[4:0] | b011 | rd[4:0] | b0101111;
args_disass: "x%rd$d, x%rs1$d, x%rs2$d (aqu=%a,rel=%rl)"; args_disass: "{name(rd)}, {name(rs1)}, {name(rs2)} (aqu={aq},rel={rl})";
val offs[XLEN] <= X[rs1]; val offs[XLEN] <= X[rs1];
val res[XLEN] <= zext(MEM[offs]{64}); val res[XLEN] <= zext(MEM[offs]{64});
if(rd!=0) X[rd] <= res; if(rd!=0) X[rd] <= res;

View File

@ -4,40 +4,40 @@ InsructionSet RV64IBase extends RV32IBase {
instructions{ instructions{
LWU { // 80000104: 0000ef03 lwu t5,0(ra) LWU { // 80000104: 0000ef03 lwu t5,0(ra)
encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b110 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s+imm; val offs[XLEN] <= X[rs1]'s+imm;
if(rd!=0) X[rd]<=zext(MEM[offs]{32}); if(rd!=0) X[rd]<=zext(MEM[offs]{32});
} }
LD{ LD{
encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011; encoding: imm[11:0]s | rs1[4:0] | b011 | rd[4:0] | b0000011;
args_disass:"x%rd$d, %imm%(x%rs1$d)"; args_disass:"{name(rd)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
if(rd!=0) X[rd]<=sext(MEM[offs]{64}); if(rd!=0) X[rd]<=sext(MEM[offs]{64});
} }
SD{ SD{
encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011; encoding: imm[11:5]s | rs2[4:0] | rs1[4:0] | b011 | imm[4:0]s | b0100011;
args_disass:"x%rs2$d, %imm%(x%rs1$d)"; args_disass:"{name(rs2)}, {imm}({name(rs1)})";
val offs[XLEN] <= X[rs1]'s + imm; val offs[XLEN] <= X[rs1]'s + imm;
MEM[offs]{64} <= X[rs2]; MEM[offs]{64} <= X[rs2];
} }
SLLI { SLLI {
encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011; encoding: b000000 | shamt[5:0] | rs1[4:0] | b001 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shll(X[rs1], shamt); if(rd != 0) X[rd] <= shll(X[rs1], shamt);
} }
SRLI { SRLI {
encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b000000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shrl(X[rs1], shamt); if(rd != 0) X[rd] <= shrl(X[rs1], shamt);
} }
SRAI { SRAI {
encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011; encoding: b010000 | shamt[5:0] | rs1[4:0] | b101 | rd[4:0] | b0010011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0) X[rd] <= shra(X[rs1], shamt); if(rd != 0) X[rd] <= shra(X[rs1], shamt);
} }
ADDIW { ADDIW {
encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011; encoding: imm[11:0]s | rs1[4:0] | b000 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %imm%"; args_disass:"{name(rd)}, {name(rs1)}, {imm}";
if(rd != 0){ if(rd != 0){
val res[32] <= X[rs1]{32}'s + imm; val res[32] <= X[rs1]{32}'s + imm;
X[rd] <= sext(res); X[rd] <= sext(res);
@ -45,7 +45,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SLLIW { SLLIW {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b001 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shll(X[rs1]{32}, shamt); val sh_val[32] <= shll(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -53,7 +53,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRLIW { SRLIW {
encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; encoding: b0000000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shrl(X[rs1]{32}, shamt); val sh_val[32] <= shrl(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -61,7 +61,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRAIW { SRAIW {
encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011; encoding: b0100000 | shamt[4:0] | rs1[4:0] | b101 | rd[4:0] | b0011011;
args_disass:"x%rd$d, x%rs1$d, %shamt%"; args_disass:"{name(rd)}, {name(rs1)}, {shamt}";
if(rd != 0){ if(rd != 0){
val sh_val[32] <= shra(X[rs1]{32}, shamt); val sh_val[32] <= shra(X[rs1]{32}, shamt);
X[rd] <= sext(sh_val); X[rd] <= sext(sh_val);
@ -83,7 +83,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SLLW { SLLW {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b001 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;
@ -93,7 +93,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRLW { SRLW {
encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; encoding: b0000000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;
@ -103,7 +103,7 @@ InsructionSet RV64IBase extends RV32IBase {
} }
SRAW { SRAW {
encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; encoding: b0100000 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
val mask[32] <= 0x1f; val mask[32] <= 0x1f;
val count[32] <= X[rs2]{32} & mask; val count[32] <= X[rs2]{32} & mask;

View File

@ -4,35 +4,35 @@ InsructionSet RV64M extends RV64IBase {
instructions{ instructions{
MULW{ MULW{
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b000 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
X[rd]<= X[rs1] * X[rs2]; X[rd]<= X[rs1] * X[rs2];
} }
} }
DIVW { DIVW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0111011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b100 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
X[rd] <= X[rs1]s / X[rs2]s; X[rd] <= X[rs1]s / X[rs2]s;
} }
} }
DIVUW { DIVUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b101 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
X[rd] <= X[rs1] / X[rs2]; X[rd] <= X[rs1] / X[rs2];
} }
} }
REMW { REMW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0111011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b110 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
X[rd] <= X[rs1]s % X[rs2]s; X[rd] <= X[rs1]s % X[rs2]s;
} }
} }
REMUW { REMUW {
encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0111011; encoding: b0000001 | rs2[4:0] | rs1[4:0] | b111 | rd[4:0] | b0111011;
args_disass:"x%rd$d, x%rs1$d, x%rs2$d"; args_disass:"{name(rd)}, {name(rs1)}, {name(rs2)}";
if(rd != 0){ if(rd != 0){
X[rd] <= X[rs1] % X[rs2]; X[rd] <= X[rs1] % X[rs2];
} }

View File

@ -33,9 +33,44 @@
<% <%
import com.minres.coredsl.coreDsl.Register import com.minres.coredsl.coreDsl.Register
import com.minres.coredsl.coreDsl.RegisterFile import com.minres.coredsl.coreDsl.RegisterFile
import com.minres.coredsl.coreDsl.RegisterAlias
def getTypeSize(size){ def getTypeSize(size){
if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8 if(size > 32) 64 else if(size > 16) 32 else if(size > 8) 16 else 8
} }
def getOriginalName(reg){
if( reg.original instanceof RegisterFile) {
if( reg.index != null ) {
return reg.original.name+generator.generateHostCode(reg.index)
} else {
return reg.original.name
}
} else if(reg.original instanceof Register){
return reg.original.name
}
}
def getRegisterNames(){
def regNames = []
allRegs.each { reg ->
if( reg instanceof RegisterFile) {
(reg.range.right..reg.range.left).each{
regNames+=reg.name.toLowerCase()+it
}
} else if(reg instanceof Register){
regNames+=reg.name.toLowerCase()
}
}
return regNames
}
def getRegisterAliasNames(){
def regMap = allRegs.findAll{it instanceof RegisterAlias }.collectEntries {[getOriginalName(it), it.name]}
return allRegs.findAll{it instanceof Register || it instanceof RegisterFile}.collect{reg ->
if( reg instanceof RegisterFile) {
return (reg.range.right..reg.range.left).collect{ (regMap[reg.name]?:regMap[reg.name+it]?:reg.name.toLowerCase()+it).toLowerCase() }
} else if(reg instanceof Register){
regMap[reg.name]?:reg.name.toLowerCase()
}
}.flatten()
}
%> %>
#ifndef _${coreDef.name.toUpperCase()}_H_ #ifndef _${coreDef.name.toUpperCase()}_H_
#define _${coreDef.name.toUpperCase()}_H_ #define _${coreDef.name.toUpperCase()}_H_
@ -54,6 +89,12 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
constexpr static char const* const core_type = "${coreDef.name}"; constexpr static char const* const core_type = "${coreDef.name}";
static constexpr std::array<const char*, ${getRegisterNames().size}> reg_names{
{"${getRegisterNames().join("\", \"")}"}};
static constexpr std::array<const char*, ${getRegisterAliasNames().size}> reg_aliases{
{"${getRegisterAliasNames().join("\", \"")}"}};
enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}}; enum constants {${coreDef.constants.collect{c -> c.name+"="+c.value}.join(', ')}};
constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0}; constexpr static unsigned FP_REGS_SIZE = ${coreDef.constants.find {it.name=='FLEN'}?.value?:0};
@ -74,7 +115,12 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT<%
allRegs.each { reg ->
if(reg instanceof RegisterAlias){ def aliasname=getOriginalName(reg)%>,
${reg.name} = ${aliasname}<%
}
}%>
}; };
using reg_t = uint${regDataWidth}_t; using reg_t = uint${regDataWidth}_t;
@ -87,16 +133,12 @@ template <> struct traits<${coreDef.name.toLowerCase()}> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, ${regSizes.size}> ${coreDef.name}_reg_size{ static constexpr std::array<const uint32_t, ${regSizes.size}> reg_bit_widths{
{${regSizes.join(",")}}}; {${regSizes.join(",")}}};
static constexpr unsigned reg_bit_width(unsigned r) { return ${coreDef.name}_reg_size[r]; } static constexpr std::array<const uint32_t, ${regOffsets.size}> reg_byte_offsets{
static constexpr std::array<const uint32_t, ${regOffsets.size}> ${coreDef.name}_reg_byte_offset{
{${regOffsets.join(",")}}}; {${regOffsets.join(",")}}};
constexpr static unsigned reg_byte_offset(unsigned r) { return ${coreDef.name}_reg_byte_offset[r]; }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e { FLAGS }; enum sreg_flag_e { FLAGS };

View File

@ -49,8 +49,8 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::${coreDef.name}_reg_size; constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_sizes;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::${coreDef.name}_reg_byte_offset; constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::${coreDef.name.toLowerCase()}>::reg_byte_offset;
${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() { ${coreDef.name.toLowerCase()}::${coreDef.name.toLowerCase()}() {
reg.icount = 0; reg.icount = 0;

View File

@ -38,7 +38,7 @@
#include <iss/llvm/vm_base.h> #include <iss/llvm/vm_base.h>
#include <util/logging.h> #include <util/logging.h>
#include <boost/format.hpp> #include <fmt/format.h>
#include <array> #include <array>
#include <iss/debugger/riscv_target_adapter.h> #include <iss/debugger/riscv_target_adapter.h>
@ -54,10 +54,11 @@ namespace ${coreDef.name.toLowerCase()} {
using namespace iss::arch; using namespace iss::arch;
using namespace llvm; using namespace llvm;
using namespace iss::debugger; using namespace iss::debugger;
using namespace iss::vm::llvm;
template <typename ARCH> class vm_impl : public vm::vm_base<ARCH> { template <typename ARCH> class vm_impl : public vm_base<ARCH> {
public: public:
using super = typename vm::vm_base<ARCH>; using super = typename iss::vm::llvm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t; using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t; using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t; using code_word_t = typename super::code_word_t;
@ -71,31 +72,32 @@ public:
target_adapter_if *accquire_target_adapter(server_if *srv) override { target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true; debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr) if (vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch()); vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm::vm_base<ARCH>::tgt_adapter; return vm_base<ARCH>::tgt_adapter;
} }
protected: protected:
using vm::vm_base<ARCH>::get_reg_ptr; using vm_base<ARCH>::get_reg_ptr;
template <typename T> inline llvm::ConstantInt *size(T type) { inline const char *name(size_t index){return traits<ARCH>::reg_aliases.at(index);}
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
template <typename T> inline ConstantInt *size(T type) {
return ConstantInt::get(getContext(), APInt(32, type->getType()->getScalarSizeInBits()));
} }
void setup_module(llvm::Module *m) override { void setup_module(Module* m) override {
super::setup_module(m); super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE); iss::vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
} }
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) { inline Value *gen_choose(Value *cond, Value *trueVal, Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size)); return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
} }
std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, std::tuple<continuation_e, BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &, BasicBlock *) override;
llvm::BasicBlock *) override;
void gen_leave_behavior(llvm::BasicBlock *leave_blk) override; void gen_leave_behavior(BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause); void gen_raise_trap(uint16_t trap_id, uint16_t cause);
@ -103,17 +105,17 @@ protected:
void gen_wait(unsigned type); void gen_wait(unsigned type);
void gen_trap_behavior(llvm::BasicBlock *) override; void gen_trap_behavior(BasicBlock *) override;
void gen_trap_check(llvm::BasicBlock *bb); void gen_trap_check(BasicBlock *bb);
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) { inline Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(get_reg_ptr(i), false); return this->builder.CreateLoad(get_reg_ptr(i), false);
} }
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) { inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val), Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN)); this->get_type(traits<ARCH>::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true); this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
} }
@ -124,9 +126,9 @@ protected:
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) }; enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
using this_class = vm_impl<ARCH>; using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock *> (this_class::*)(virt_addr_t &pc, using compile_func = std::tuple<continuation_e, BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr, code_word_t instr,
llvm::BasicBlock *bb); BasicBlock *bb);
std::array<compile_func, LUT_SIZE> lut; std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10; std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
@ -192,15 +194,14 @@ private:
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %> /* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
/* instruction ${idx}: ${instr.name} */ /* instruction ${idx}: ${instr.name} */
std::tuple<vm::continuation_e, llvm::BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, llvm::BasicBlock* bb){<%instr.code.eachLine{%> std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){<%instr.code.eachLine{%>
${it}<%}%> ${it}<%}%>
} }
<%}%> <%}%>
/**************************************************************************** /****************************************************************************
* end opcode definitions * end opcode definitions
****************************************************************************/ ****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, std::tuple<continuation_e, BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr, BasicBlock *bb) {
llvm::BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size()); this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true), this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true); get_reg_ptr(traits<ARCH>::PC), true);
@ -212,7 +213,7 @@ private:
this->gen_raise_trap(0, 2); // illegal instruction trap this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size()); this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk); this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr); return std::make_tuple(BRANCH, nullptr);
} }
}; };
@ -225,7 +226,7 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH> template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id) vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm::vm_base<ARCH>(core, core_id, cluster_id) { : vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data(); qlut[0] = lut_00.data();
qlut[1] = lut_01.data(); qlut[1] = lut_01.data();
qlut[2] = lut_10.data(); qlut[2] = lut_10.data();
@ -237,8 +238,8 @@ vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
} }
template <typename ARCH> template <typename ARCH>
std::tuple<vm::continuation_e, llvm::BasicBlock *> std::tuple<continuation_e, BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) { vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2 // we fetch at max 4 byte, alignment is 2
code_word_t insn = 0; code_word_t insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK; const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
@ -270,7 +271,7 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
return (this->*f)(pc, insn, this_block); return (this->*f)(pc, insn, this_block);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk); this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false)); this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
} }
@ -278,45 +279,39 @@ template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) { template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id); auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true); this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) { template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<llvm::Value *> args{ std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, lvl)) };
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
};
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args); this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8); auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false); this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) { template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<llvm::Value *> args{ std::vector<Value *> args{ this->core_ptr, ConstantInt::get(getContext(), APInt(64, type)) };
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
};
this->builder.CreateCall(this->mod->getFunction("wait"), args); this->builder.CreateCall(this->mod->getFunction("wait"), args);
} }
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) { template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk); this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true); auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()), this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false); get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val), std::vector<Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))}; this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args); this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false); auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val); this->builder.CreateRet(trap_addr_val);
} }
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) { template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(BasicBlock *bb) {
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true); auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch(this->builder.CreateICmp( this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v, ICmpInst::ICMP_EQ, v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))), ConstantInt::get(getContext(), APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1); bb, this->trap_blk, 1);
} }

View File

@ -1,322 +0,0 @@
/*******************************************************************************
* Copyright (C) 2017, 2018 MINRES Technologies GmbH
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*******************************************************************************/
#include <iss/arch/CORE_DEF_NAME.h>
#include <iss/arch/riscv_hart_msu_vp.h>
#include <iss/debugger/gdb_session.h>
#include <iss/debugger/server.h>
#include <iss/iss.h>
#include <iss/llvm/vm_base.h>
#include <util/logging.h>
#include <boost/format.hpp>
#include <array>
#include <iss/debugger/riscv_target_adapter.h>
namespace iss {
namespace vm {
namespace fp_impl {
void add_fp_functions_2_module(llvm::Module *, unsigned);
}
}
namespace CORE_DEF_NAME {
using namespace iss::arch;
using namespace llvm;
using namespace iss::debugger;
template <typename ARCH> class vm_impl : public vm::vm_base<ARCH> {
public:
using super = typename vm::vm_base<ARCH>;
using virt_addr_t = typename super::virt_addr_t;
using phys_addr_t = typename super::phys_addr_t;
using code_word_t = typename super::code_word_t;
using addr_t = typename super::addr_t;
vm_impl();
vm_impl(ARCH &core, unsigned core_id = 0, unsigned cluster_id = 0);
void enableDebug(bool enable) { super::sync_exec = super::ALL_SYNC; }
target_adapter_if *accquire_target_adapter(server_if *srv) override {
debugger_if::dbg_enabled = true;
if (vm::vm_base<ARCH>::tgt_adapter == nullptr)
vm::vm_base<ARCH>::tgt_adapter = new riscv_target_adapter<ARCH>(srv, this->get_arch());
return vm::vm_base<ARCH>::tgt_adapter;
}
protected:
using vm::vm_base<ARCH>::get_reg_ptr;
template <typename T> inline llvm::ConstantInt *size(T type) {
return llvm::ConstantInt::get(getContext(), llvm::APInt(32, type->getType()->getScalarSizeInBits()));
}
void setup_module(llvm::Module *m) override {
super::setup_module(m);
vm::fp_impl::add_fp_functions_2_module(m, traits<ARCH>::FP_REGS_SIZE);
}
inline llvm::Value *gen_choose(llvm::Value *cond, llvm::Value *trueVal, llvm::Value *falseVal, unsigned size) {
return super::gen_cond_assign(cond, this->gen_ext(trueVal, size), this->gen_ext(falseVal, size));
}
std::tuple<vm::continuation_e, llvm::BasicBlock *> gen_single_inst_behavior(virt_addr_t &, unsigned int &,
llvm::BasicBlock *) override;
void gen_leave_behavior(llvm::BasicBlock *leave_blk) override;
void gen_raise_trap(uint16_t trap_id, uint16_t cause);
void gen_leave_trap(unsigned lvl);
void gen_wait(unsigned type);
void gen_trap_behavior(llvm::BasicBlock *) override;
void gen_trap_check(llvm::BasicBlock *bb);
inline llvm::Value *gen_reg_load(unsigned i, unsigned level = 0) {
return this->builder.CreateLoad(get_reg_ptr(i), false);
}
inline void gen_set_pc(virt_addr_t pc, unsigned reg_num) {
llvm::Value *next_pc_v = this->builder.CreateSExtOrTrunc(this->gen_const(traits<ARCH>::XLEN, pc.val),
this->get_type(traits<ARCH>::XLEN));
this->builder.CreateStore(next_pc_v, get_reg_ptr(reg_num), true);
}
// some compile time constants
// enum { MASK16 = 0b1111110001100011, MASK32 = 0b11111111111100000111000001111111 };
enum { MASK16 = 0b1111111111111111, MASK32 = 0b11111111111100000111000001111111 };
enum { EXTR_MASK16 = MASK16 >> 2, EXTR_MASK32 = MASK32 >> 2 };
enum { LUT_SIZE = 1 << util::bit_count(EXTR_MASK32), LUT_SIZE_C = 1 << util::bit_count(EXTR_MASK16) };
using this_class = vm_impl<ARCH>;
using compile_func = std::tuple<vm::continuation_e, llvm::BasicBlock *> (this_class::*)(virt_addr_t &pc,
code_word_t instr,
llvm::BasicBlock *bb);
std::array<compile_func, LUT_SIZE> lut;
std::array<compile_func, LUT_SIZE_C> lut_00, lut_01, lut_10;
std::array<compile_func, LUT_SIZE> lut_11;
std::array<compile_func *, 4> qlut;
std::array<const uint32_t, 4> lutmasks = {{EXTR_MASK16, EXTR_MASK16, EXTR_MASK16, EXTR_MASK32}};
void expand_bit_mask(int pos, uint32_t mask, uint32_t value, uint32_t valid, uint32_t idx, compile_func lut[],
compile_func f) {
if (pos < 0) {
lut[idx] = f;
} else {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, idx, lut, f);
} else {
if ((valid & bitmask) == 0) {
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1), lut, f);
expand_bit_mask(pos - 1, mask, value, valid, (idx << 1) + 1, lut, f);
} else {
auto new_val = idx << 1;
if ((value & bitmask) != 0) new_val++;
expand_bit_mask(pos - 1, mask, value, valid, new_val, lut, f);
}
}
}
}
inline uint32_t extract_fields(uint32_t val) { return extract_fields(29, val >> 2, lutmasks[val & 0x3], 0); }
uint32_t extract_fields(int pos, uint32_t val, uint32_t mask, uint32_t lut_val) {
if (pos >= 0) {
auto bitmask = 1UL << pos;
if ((mask & bitmask) == 0) {
lut_val = extract_fields(pos - 1, val, mask, lut_val);
} else {
auto new_val = lut_val << 1;
if ((val & bitmask) != 0) new_val++;
lut_val = extract_fields(pos - 1, val, mask, new_val);
}
}
return lut_val;
}
private:
/****************************************************************************
* start opcode definitions
****************************************************************************/
struct InstructionDesriptor {
size_t length;
uint32_t value;
uint32_t mask;
compile_func op;
};
/* «start generated code» */
std::array<InstructionDesriptor, 0> instr_descr = {{}};
/* «end generated code» */
/****************************************************************************
* end opcode definitions
****************************************************************************/
std::tuple<vm::continuation_e, llvm::BasicBlock *> illegal_intruction(virt_addr_t &pc, code_word_t instr,
llvm::BasicBlock *bb) {
this->gen_sync(iss::PRE_SYNC, instr_descr.size());
this->builder.CreateStore(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), true),
get_reg_ptr(traits<ARCH>::PC), true);
this->builder.CreateStore(
this->builder.CreateAdd(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::ICOUNT), true),
this->gen_const(64U, 1)),
get_reg_ptr(traits<ARCH>::ICOUNT), true);
pc = pc + ((instr & 3) == 3 ? 4 : 2);
this->gen_raise_trap(0, 2); // illegal instruction trap
this->gen_sync(iss::POST_SYNC, instr_descr.size());
this->gen_trap_check(this->leave_blk);
return std::make_tuple(iss::vm::BRANCH, nullptr);
}
};
template <typename CODE_WORD> void debug_fn(CODE_WORD insn) {
volatile CODE_WORD x = insn;
insn = 2 * x;
}
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
template <typename ARCH>
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
: vm::vm_base<ARCH>(core, core_id, cluster_id) {
qlut[0] = lut_00.data();
qlut[1] = lut_01.data();
qlut[2] = lut_10.data();
qlut[3] = lut_11.data();
for (auto instr : instr_descr) {
auto quantrant = instr.value & 0x3;
expand_bit_mask(29, lutmasks[quantrant], instr.value >> 2, instr.mask >> 2, 0, qlut[quantrant], instr.op);
}
}
template <typename ARCH>
std::tuple<vm::continuation_e, llvm::BasicBlock *>
vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, llvm::BasicBlock *this_block) {
// we fetch at max 4 byte, alignment is 2
code_word_t insn = 0;
const typename traits<ARCH>::addr_t upper_bits = ~traits<ARCH>::PGMASK;
phys_addr_t paddr(pc);
try {
auto *const data = (uint8_t *)&insn;
paddr = this->core.v2p(pc);
if ((pc.val & upper_bits) != ((pc.val + 2) & upper_bits)) { // we may cross a page boundary
auto res = this->core.read(paddr, 2, data);
if (res != iss::Ok) throw trap_access(1, pc.val);
if ((insn & 0x3) == 0x3) { // this is a 32bit instruction
res = this->core.read(this->core.v2p(pc + 2), 2, data + 2);
}
} else {
auto res = this->core.read(paddr, 4, data);
if (res != iss::Ok) throw trap_access(1, pc.val);
}
} catch (trap_access &ta) {
throw trap_access(ta.id, pc.val);
}
if (insn == 0x0000006f || (insn & 0xffff) == 0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
// curr pc on stack
++inst_cnt;
auto lut_val = extract_fields(insn);
auto f = qlut[insn & 0x3][lut_val];
if (f == nullptr) {
f = &this_class::illegal_intruction;
}
return (this->*f)(pc, insn, this_block);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_behavior(llvm::BasicBlock *leave_blk) {
this->builder.SetInsertPoint(leave_blk);
this->builder.CreateRet(this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::NEXT_PC), false));
}
template <typename ARCH> void vm_impl<ARCH>::gen_raise_trap(uint16_t trap_id, uint16_t cause) {
auto *TRAP_val = this->gen_const(32, 0x80 << 24 | (cause << 16) | trap_id);
this->builder.CreateStore(TRAP_val, get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
}
template <typename ARCH> void vm_impl<ARCH>::gen_leave_trap(unsigned lvl) {
std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, lvl)),
};
this->builder.CreateCall(this->mod->getFunction("leave_trap"), args);
auto *PC_val = this->gen_read_mem(traits<ARCH>::CSR, (lvl << 8) + 0x41, traits<ARCH>::XLEN / 8);
this->builder.CreateStore(PC_val, get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
}
template <typename ARCH> void vm_impl<ARCH>::gen_wait(unsigned type) {
std::vector<llvm::Value *> args{
this->core_ptr, llvm::ConstantInt::get(getContext(), llvm::APInt(64, type)),
};
this->builder.CreateCall(this->mod->getFunction("wait"), args);
}
template <typename ARCH> void vm_impl<ARCH>::gen_trap_behavior(llvm::BasicBlock *trap_blk) {
this->builder.SetInsertPoint(trap_blk);
auto *trap_state_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::TRAP_STATE), true);
this->builder.CreateStore(this->gen_const(32U, std::numeric_limits<uint32_t>::max()),
get_reg_ptr(traits<ARCH>::LAST_BRANCH), false);
std::vector<llvm::Value *> args{this->core_ptr, this->adj_to64(trap_state_val),
this->adj_to64(this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::PC), false))};
this->builder.CreateCall(this->mod->getFunction("enter_trap"), args);
auto *trap_addr_val = this->builder.CreateLoad(get_reg_ptr(traits<ARCH>::NEXT_PC), false);
this->builder.CreateRet(trap_addr_val);
}
template <typename ARCH> inline void vm_impl<ARCH>::gen_trap_check(llvm::BasicBlock *bb) {
auto *v = this->builder.CreateLoad(get_reg_ptr(arch::traits<ARCH>::TRAP_STATE), true);
this->gen_cond_branch(this->builder.CreateICmp(
ICmpInst::ICMP_EQ, v,
llvm::ConstantInt::get(getContext(), llvm::APInt(v->getType()->getIntegerBitWidth(), 0))),
bb, this->trap_blk, 1);
}
} // namespace CORE_DEF_NAME
template <> std::unique_ptr<vm_if> create<arch::CORE_DEF_NAME>(arch::CORE_DEF_NAME *core, unsigned short port, bool dump) {
auto ret = new CORE_DEF_NAME::vm_impl<arch::CORE_DEF_NAME>(*core, dump);
if (port != 0) debugger::server<debugger::gdb_session>::run_server(ret, port);
return std::unique_ptr<vm_if>(ret);
}
} // namespace iss

View File

@ -40,6 +40,7 @@
#include "iss/instrumentation_if.h" #include "iss/instrumentation_if.h"
#include "iss/log_categories.h" #include "iss/log_categories.h"
#include "iss/vm_if.h" #include "iss/vm_if.h"
#include <fmt/format.h>
#include <array> #include <array>
#include <elfio/elfio.hpp> #include <elfio/elfio.hpp>
#include <iomanip> #include <iomanip>
@ -478,10 +479,8 @@ public:
void wait_until(uint64_t flags) override; void wait_until(uint64_t flags) override;
void disass_output(uint64_t pc, const std::string instr) override { void disass_output(uint64_t pc, const std::string instr) override {
std::stringstream s; CLOG(INFO, disass) << fmt::format("0x{:016x} {:40} [p:{};s:0x{:x};c:{}]",
s << "[p:" << lvl[this->reg.machine_state] << ";s:0x" << std::hex << std::setfill('0') pc, instr, lvl[this->reg.machine_state], (reg_t)state.mstatus, this->reg.icount);
<< std::setw(sizeof(reg_t) * 2) << (reg_t)state.mstatus << std::dec << ";c:" << this->reg.icount << "]";
CLOG(INFO, disass) << "0x" << std::setw(16) << std::setfill('0') << std::hex << pc << "\t\t" << instr << "\t" << s.str();
}; };
iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; } iss::instrumentation_if *get_instrumentation_if() override { return &instr_if; }

View File

@ -1,53 +1,59 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
#ifndef _RV32GC_H_ #ifndef _RV32GC_H_
#define _RV32GC_H_ #define _RV32GC_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct rv32gc; struct rv32gc;
template<> template <> struct traits<rv32gc> {
struct traits<rv32gc> {
constexpr static char const* const core_type = "RV32GC"; constexpr static char const* const core_type = "RV32GC";
static constexpr std::array<const char*, 66> reg_names{
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
static constexpr std::array<const char*, 66> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc", "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", "f31", "fcsr"}};
enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff}; enum constants {XLEN=32, FLEN=64, PCLEN=32, MISA_VAL=0b1000000000101000001000100101101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 64; constexpr static unsigned FP_REGS_SIZE = 64;
@ -125,7 +131,39 @@ struct traits<rv32gc> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
@ -138,21 +176,17 @@ struct traits<rv32gc> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { static constexpr std::array<const uint32_t, 72> reg_bit_widths{
constexpr std::array<const uint32_t, 72> RV32GC_reg_size{{32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}}; {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,32,32,64}};
return RV32GC_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) { static constexpr std::array<const uint32_t, 73> reg_byte_offsets{
constexpr std::array<const uint32_t, 73> RV32GC_reg_byte_offset{{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}}; {0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,280,288,296,304,312,320,328,336,344,352,360,368,376,384,392,396,400,404,408,412,416,424}};
return RV32GC_reg_byte_offset[r];
}
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS}; enum sreg_flag_e { FLAGS };
enum mem_type_e {MEM, CSR, FENCE, RES}; enum mem_type_e { MEM, CSR, FENCE, RES };
}; };
struct rv32gc: public arch_if { struct rv32gc: public arch_if {
@ -177,14 +211,13 @@ struct rv32gc: public arch_if {
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
uint64_t get_icount() { return reg.icount;} inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; } inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv32gc>::MEM || if (addr.space != traits<rv32gc>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32gc>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32gc>::addr_mask);
} else } else
return virt2phys(addr); return virt2phys(addr);
@ -194,8 +227,7 @@ struct rv32gc: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline inline uint32_t get_last_branch() { return reg.last_branch; }
uint32_t get_last_branch(){return reg.last_branch;}
protected: protected:
struct RV32GC_regs { struct RV32GC_regs {

View File

@ -30,6 +30,7 @@
* *
*******************************************************************************/ *******************************************************************************/
#ifndef _RV32IMAC_H_ #ifndef _RV32IMAC_H_
#define _RV32IMAC_H_ #define _RV32IMAC_H_
@ -45,15 +46,15 @@ struct rv32imac;
template <> struct traits<rv32imac> { template <> struct traits<rv32imac> {
constexpr static char const *const core_type = "RV32IMAC"; constexpr static char const* const core_type = "RV32IMAC";
enum constants { static constexpr std::array<const char*, 33> reg_names{
XLEN = 32, {"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
PCLEN = 32,
MISA_VAL = 0b1000000000101000001000100000101, static constexpr std::array<const char*, 33> reg_aliases{
PGSIZE = 0x1000, {"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
PGMASK = 0xfff
}; enum constants {XLEN=32, PCLEN=32, MISA_VAL=0b1000000000101000001000100000101, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
@ -92,35 +93,61 @@ template <> struct traits<rv32imac> {
X31, X31,
PC, PC,
NUM_REGS, NUM_REGS,
NEXT_PC = NUM_REGS, NEXT_PC=NUM_REGS,
TRAP_STATE, TRAP_STATE,
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
}; };
using reg_t = uint32_t; using reg_t = uint32_t;
using addr_t = uint32_t; using addr_t = uint32_t;
using code_word_t = uint32_t; // TODO: check removal using code_word_t = uint32_t; //TODO: check removal
using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>; using virt_addr_t = iss::typed_addr_t<iss::address_type::VIRTUAL>;
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
static constexpr std::array<const uint32_t, 39> RV32IMAC_reg_size{ static constexpr std::array<const uint32_t, 39> reg_bit_widths{
{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, {32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,32,64}};
32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 64}};
constexpr static unsigned reg_bit_width(unsigned r) { return RV32IMAC_reg_size[r]; } static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
{0,4,8,12,16,20,24,28,32,36,40,44,48,52,56,60,64,68,72,76,80,84,88,92,96,100,104,108,112,116,120,124,128,132,136,140,144,148,152,160}};
static constexpr std::array<const uint32_t, 40> RV32IMAC_reg_byte_offset{
{0, 4, 8, 12, 16, 20, 24, 28, 32, 36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76,
80, 84, 88, 92, 96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144, 148, 152, 160}};
constexpr static unsigned reg_byte_offset(unsigned r) { return RV32IMAC_reg_byte_offset[r]; }
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
@ -129,41 +156,41 @@ template <> struct traits<rv32imac> {
enum mem_type_e { MEM, CSR, FENCE, RES }; enum mem_type_e { MEM, CSR, FENCE, RES };
}; };
struct rv32imac : public arch_if { struct rv32imac: public arch_if {
using virt_addr_t = typename traits<rv32imac>::virt_addr_t; using virt_addr_t = typename traits<rv32imac>::virt_addr_t;
using phys_addr_t = typename traits<rv32imac>::phys_addr_t; using phys_addr_t = typename traits<rv32imac>::phys_addr_t;
using reg_t = typename traits<rv32imac>::reg_t; using reg_t = typename traits<rv32imac>::reg_t;
using addr_t = typename traits<rv32imac>::addr_t; using addr_t = typename traits<rv32imac>::addr_t;
rv32imac(); rv32imac();
~rv32imac(); ~rv32imac();
void reset(uint64_t address = 0) override; void reset(uint64_t address=0) override;
uint8_t *get_regs_base_ptr() override; uint8_t* get_regs_base_ptr() override;
/// deprecated /// deprecated
void get_reg(short idx, std::vector<uint8_t> &value) override {} void get_reg(short idx, std::vector<uint8_t>& value) override {}
void set_reg(short idx, const std::vector<uint8_t> &value) override {} void set_reg(short idx, const std::vector<uint8_t>& value) override {}
/// deprecated /// deprecated
bool get_flag(int flag) override { return false; } bool get_flag(int flag) override {return false;}
void set_flag(int, bool value) override{}; void set_flag(int, bool value) override {};
/// deprecated /// deprecated
void update_flags(operations op, uint64_t opr1, uint64_t opr2) override{}; void update_flags(operations op, uint64_t opr1, uint64_t opr2) override {};
inline uint64_t get_icount() { return reg.icount; } inline uint64_t get_icount() { return reg.icount; }
inline bool should_stop() { return interrupt_sim; } inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t &addr) { inline phys_addr_t v2p(const iss::addr_t& addr){
if (addr.space != traits<rv32imac>::MEM || addr.type == iss::address_type::PHYSICAL || if (addr.space != traits<rv32imac>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr_mode[static_cast<uint16_t>(addr.access) & 0x3] == address_type::PHYSICAL) { addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
return phys_addr_t(addr.access, addr.space, addr.val & traits<rv32imac>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<rv32imac>::addr_mask);
} else } else
return virt2phys(addr); return virt2phys(addr);
} }
virtual phys_addr_t virt2phys(const iss::addr_t &addr); virtual phys_addr_t virt2phys(const iss::addr_t& addr);
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
@ -211,11 +238,13 @@ protected:
std::array<address_type, 4> addr_mode; std::array<address_type, 4> addr_mode;
bool interrupt_sim = false; bool interrupt_sim=false;
uint32_t get_fcsr(){return 0;}
void set_fcsr(uint32_t val){}
uint32_t get_fcsr() { return 0; }
void set_fcsr(uint32_t val) {}
}; };
} }
} }
#endif /* _RV32IMAC_H_ */ #endif /* _RV32IMAC_H_ */

View File

@ -1,53 +1,59 @@
//////////////////////////////////////////////////////////////////////////////// /*******************************************************************************
// Copyright (C) 2017, MINRES Technologies GmbH * Copyright (C) 2017, 2018 MINRES Technologies GmbH
// All rights reserved. * All rights reserved.
// *
// Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
// *
// 1. Redistributions of source code must retain the above copyright notice, * 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer. * this list of conditions and the following disclaimer.
// *
// 2. Redistributions in binary form must reproduce the above copyright notice, * 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation * this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution. * and/or other materials provided with the distribution.
// *
// 3. Neither the name of the copyright holder nor the names of its contributors * 3. Neither the name of the copyright holder nor the names of its contributors
// may be used to endorse or promote products derived from this software * may be used to endorse or promote products derived from this software
// without specific prior written permission. * without specific prior written permission.
// *
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE. * POSSIBILITY OF SUCH DAMAGE.
// *
//////////////////////////////////////////////////////////////////////////////// *******************************************************************************/
#ifndef _RV64IA_H_ #ifndef _RV64IA_H_
#define _RV64IA_H_ #define _RV64IA_H_
#include <array>
#include <iss/arch/traits.h>
#include <iss/arch_if.h> #include <iss/arch_if.h>
#include <iss/vm_if.h> #include <iss/vm_if.h>
#include <iss/arch/traits.h>
#include <array>
namespace iss { namespace iss {
namespace arch { namespace arch {
struct rv64ia; struct rv64ia;
template<> template <> struct traits<rv64ia> {
struct traits<rv64ia> {
constexpr static char const* const core_type = "RV64IA"; constexpr static char const* const core_type = "RV64IA";
static constexpr std::array<const char*, 33> reg_names{
{"x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7", "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15", "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23", "x24", "x25", "x26", "x27", "x28", "x29", "x30", "x31", "pc"}};
static constexpr std::array<const char*, 33> reg_aliases{
{"zero", "ra", "sp", "gp", "tp", "t0", "t1", "t2", "s0", "s1", "a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11", "t3", "t4", "t5", "t6", "pc"}};
enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000001, PGSIZE=0x1000, PGMASK=0xfff}; enum constants {XLEN=64, PCLEN=64, MISA_VAL=0b10000000000001000000000100000001, PGSIZE=0x1000, PGMASK=0xfff};
constexpr static unsigned FP_REGS_SIZE = 0; constexpr static unsigned FP_REGS_SIZE = 0;
@ -92,7 +98,39 @@ struct traits<rv64ia> {
PENDING_TRAP, PENDING_TRAP,
MACHINE_STATE, MACHINE_STATE,
LAST_BRANCH, LAST_BRANCH,
ICOUNT ICOUNT,
ZERO = X0,
RA = X1,
SP = X2,
GP = X3,
TP = X4,
T0 = X5,
T1 = X6,
T2 = X7,
S0 = X8,
S1 = X9,
A0 = X10,
A1 = X11,
A2 = X12,
A3 = X13,
A4 = X14,
A5 = X15,
A6 = X16,
A7 = X17,
S2 = X18,
S3 = X19,
S4 = X20,
S5 = X21,
S6 = X22,
S7 = X23,
S8 = X24,
S9 = X25,
S10 = X26,
S11 = X27,
T3 = X28,
T4 = X29,
T5 = X30,
T6 = X31
}; };
using reg_t = uint64_t; using reg_t = uint64_t;
@ -105,21 +143,17 @@ struct traits<rv64ia> {
using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>; using phys_addr_t = iss::typed_addr_t<iss::address_type::PHYSICAL>;
constexpr static unsigned reg_bit_width(unsigned r) { static constexpr std::array<const uint32_t, 39> reg_bit_widths{
constexpr std::array<const uint32_t, 39> RV64IA_reg_size{{64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}}; {64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,64,32,32,32,32,64}};
return RV64IA_reg_size[r];
}
constexpr static unsigned reg_byte_offset(unsigned r) { static constexpr std::array<const uint32_t, 40> reg_byte_offsets{
constexpr std::array<const uint32_t, 40> RV64IA_reg_byte_offset{{0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}}; {0,8,16,24,32,40,48,56,64,72,80,88,96,104,112,120,128,136,144,152,160,168,176,184,192,200,208,216,224,232,240,248,256,264,272,276,280,284,288,296}};
return RV64IA_reg_byte_offset[r];
}
static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1); static const uint64_t addr_mask = (reg_t(1) << (XLEN - 1)) | ((reg_t(1) << (XLEN - 1)) - 1);
enum sreg_flag_e {FLAGS}; enum sreg_flag_e { FLAGS };
enum mem_type_e {MEM, CSR, FENCE, RES}; enum mem_type_e { MEM, CSR, FENCE, RES };
}; };
struct rv64ia: public arch_if { struct rv64ia: public arch_if {
@ -149,9 +183,8 @@ struct rv64ia: public arch_if {
inline bool should_stop() { return interrupt_sim; } inline bool should_stop() { return interrupt_sim; }
inline phys_addr_t v2p(const iss::addr_t& addr){ inline phys_addr_t v2p(const iss::addr_t& addr){
if(addr.space != traits<rv64ia>::MEM || if (addr.space != traits<rv64ia>::MEM || addr.type == iss::address_type::PHYSICAL ||
addr.type == iss::address_type::PHYSICAL || addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL) {
addr_mode[static_cast<uint16_t>(addr.access)&0x3]==address_type::PHYSICAL){
return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64ia>::addr_mask); return phys_addr_t(addr.access, addr.space, addr.val&traits<rv64ia>::addr_mask);
} else } else
return virt2phys(addr); return virt2phys(addr);
@ -161,8 +194,7 @@ struct rv64ia: public arch_if {
virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; } virtual iss::sync_type needed_sync() const { return iss::NO_SYNC; }
inline inline uint32_t get_last_branch() { return reg.last_branch; }
uint32_t get_last_branch(){return reg.last_branch;}
protected: protected:
struct RV64IA_regs { struct RV64IA_regs {

View File

@ -40,6 +40,7 @@
#include <array> #include <array>
#include <memory> #include <memory>
#include <fmt/format.h>
#include <util/logging.h> #include <util/logging.h>
namespace iss { namespace iss {
@ -180,8 +181,8 @@ status riscv_target_adapter<ARCH>::read_registers(std::vector<uint8_t> &data, st
avail.clear(); avail.clear();
const uint8_t *reg_base = core->get_regs_base_ptr(); const uint8_t *reg_base = core->get_regs_base_ptr();
for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) { for (size_t reg_no = 0; reg_no < arch::traits<ARCH>::NUM_REGS; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
unsigned offset = traits<ARCH>::reg_byte_offset(reg_no); unsigned offset = traits<ARCH>::reg_byte_offsets[reg_no];
for (size_t j = 0; j < reg_width; ++j) { for (size_t j = 0; j < reg_width; ++j) {
data.push_back(*(reg_base + offset + j)); data.push_back(*(reg_base + offset + j));
avail.push_back(0xff); avail.push_back(0xff);
@ -215,8 +216,8 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::write_registers(cons
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto iter = data.data(); auto iter = data.data();
for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) { for (size_t reg_no = 0; reg_no < reg_count; ++reg_no) {
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(iter, iter + reg_width, reg_base); std::copy(iter, iter + reg_width, reg_base);
iter += 4; iter += 4;
reg_base += offset; reg_base += offset;
@ -231,10 +232,10 @@ status riscv_target_adapter<ARCH>::read_single_register(unsigned int reg_no, std
// auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename // auto reg_size = arch::traits<ARCH>::reg_bit_width(static_cast<typename
// arch::traits<ARCH>::reg_e>(reg_no))/8; // arch::traits<ARCH>::reg_e>(reg_no))/8;
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(reg_no) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[reg_no] / 8;
data.resize(reg_width); data.resize(reg_width);
avail.resize(reg_width); avail.resize(reg_width);
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin()); std::copy(reg_base + offset, reg_base + offset + reg_width, data.begin());
std::fill(avail.begin(), avail.end(), 0xff); std::fill(avail.begin(), avail.end(), 0xff);
} else { } else {
@ -251,8 +252,8 @@ template <typename ARCH>
status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) { status riscv_target_adapter<ARCH>::write_single_register(unsigned int reg_no, const std::vector<uint8_t> &data) {
if (reg_no < 65) { if (reg_no < 65) {
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[static_cast<typename arch::traits<ARCH>::reg_e>(reg_no)] / 8;
auto offset = traits<ARCH>::reg_byte_offset(reg_no); auto offset = traits<ARCH>::reg_byte_offsets[reg_no];
std::copy(data.begin(), data.begin() + reg_width, reg_base + offset); std::copy(data.begin(), data.begin() + reg_width, reg_base + offset);
} else { } else {
typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65); typed_addr_t<iss::address_type::PHYSICAL> a(iss::access_type::DEBUG_WRITE, traits<ARCH>::CSR, reg_no - 65);
@ -296,9 +297,7 @@ template <typename ARCH> status riscv_target_adapter<ARCH>::raw_query(std::strin
template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) { template <typename ARCH> status riscv_target_adapter<ARCH>::threadinfo_query(int first, std::string &out_buf) {
if (first) { if (first) {
std::stringstream ss; out_buf = fmt::format("m{:x}", thread_idx.val);
ss << "m" << std::hex << thread_idx.val;
out_buf = ss.str();
} else { } else {
out_buf = "l"; out_buf = "l";
} }
@ -348,8 +347,8 @@ template <typename ARCH>
status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread, status riscv_target_adapter<ARCH>::resume_from_addr(bool step, int sig, uint64_t addr, rp_thread_ref thread,
std::function<void(unsigned)> stop_callback) { std::function<void(unsigned)> stop_callback) {
auto *reg_base = core->get_regs_base_ptr(); auto *reg_base = core->get_regs_base_ptr();
auto reg_width = arch::traits<ARCH>::reg_bit_width(arch::traits<ARCH>::PC) / 8; auto reg_width = arch::traits<ARCH>::reg_bit_widths[arch::traits<ARCH>::PC] / 8;
auto offset = traits<ARCH>::reg_byte_offset(arch::traits<ARCH>::PC); auto offset = traits<ARCH>::reg_byte_offsets[arch::traits<ARCH>::PC];
const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr); const uint8_t *iter = reinterpret_cast<const uint8_t *>(&addr);
std::copy(iter, iter + reg_width, reg_base); std::copy(iter, iter + reg_width, reg_base);
return resume_from_current(step, sig, thread, stop_callback); return resume_from_current(step, sig, thread, stop_callback);

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -49,6 +49,11 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv32gc>::reg_names;
constexpr std::array<const char*, 66> iss::arch::traits<iss::arch::rv32gc>::reg_aliases;
constexpr std::array<const uint32_t, 72> iss::arch::traits<iss::arch::rv32gc>::reg_bit_widths;
constexpr std::array<const uint32_t, 73> iss::arch::traits<iss::arch::rv32gc>::reg_byte_offsets;
rv32gc::rv32gc() { rv32gc::rv32gc() {
reg.icount=0; reg.icount=0;
} }

View File

@ -49,8 +49,10 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_size; constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv32imac>::reg_names;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv32imac>::RV32IMAC_reg_byte_offset; constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv32imac>::reg_aliases;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv32imac>::reg_bit_widths;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv32imac>::reg_byte_offsets;
rv32imac::rv32imac() { rv32imac::rv32imac() {
reg.icount = 0; reg.icount = 0;

View File

@ -52,6 +52,11 @@ extern "C" {
using namespace iss::arch; using namespace iss::arch;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv64ia>::reg_names;
constexpr std::array<const char*, 33> iss::arch::traits<iss::arch::rv64ia>::reg_aliases;
constexpr std::array<const uint32_t, 39> iss::arch::traits<iss::arch::rv64ia>::reg_bit_widths;
constexpr std::array<const uint32_t, 40> iss::arch::traits<iss::arch::rv64ia>::reg_byte_offsets;
rv64ia::rv64ia() { reg.icount = 0; reg.machine_state = 0x3;} rv64ia::rv64ia() { reg.icount = 0; reg.machine_state = 0x3;}
rv64ia::~rv64ia(){} rv64ia::~rv64ia(){}

@ -1 +1 @@
Subproject commit 0f5b5f68e7d5d481b4f8da2620df633495c989d9 Subproject commit a21b2e57a2f18ff9e683d529a106ae2a8d2639c9