Improved disassembly of running ISS

Dieser Commit ist enthalten in:
2018-11-24 20:29:24 +01:00
Ursprung df03e90181
Commit 769610d6fc
27 geänderte Dateien mit 5277 neuen und 5106 gelöschten Zeilen

Datei anzeigen

@ -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

Datei anzeigen

@ -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;

Datei anzeigen

@ -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;

Datei anzeigen

@ -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;

Datei anzeigen

@ -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

Datei anzeigen

@ -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);

Datei anzeigen

@ -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);

Datei anzeigen

@ -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;

Datei anzeigen

@ -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;

Datei anzeigen

@ -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];
} }

Datei anzeigen

@ -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 };

Datei anzeigen

@ -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;

Datei anzeigen

@ -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);
} }

Datei anzeigen

@ -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

Datei anzeigen

@ -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; }

Datei anzeigen

@ -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 {

Datei anzeigen

@ -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_ */

Datei anzeigen

@ -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 {

Datei anzeigen

@ -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);

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei anzeigen

@ -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;
} }

Datei anzeigen

@ -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;

Datei anzeigen

@ -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(){}