Adding Compressed Instruction support in tracer

Added compressed instruction decoder in the tracer to correctly
trace compressed instructions with their mnemonics. Fixes #197
This commit is contained in:
Rahul Behl 2019-08-25 16:52:33 +05:30 committed by Philipp Wagner
parent 1162b995fa
commit 60de915d6b
5 changed files with 215 additions and 11 deletions

View file

@ -56,15 +56,15 @@ lint_off -msg UNUSED -file "*/rtl/ibex_pmp.sv" -lines 16
// Signal is not used: csr_pmp_addr
// Signal not connected when PMP is not configured
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 186
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 185
// Signal is not used: csr_pmp_cfg
// Signal not connected when PMP is not configured
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 187
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 186
// Signal is not used: priv_mode
// Signal not connected when PMP is not configured
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 199
lint_off -msg UNUSED -file "*/rtl/ibex_core.sv" -lines 198
// Signal unoptimizable: Feedback to clock or circular logic:
// ibex_core.id_stage_i.controller_i.ctrl_fsm_cs

View file

@ -66,7 +66,6 @@ module ibex_core #(
output logic rvfi_valid,
output logic [63:0] rvfi_order,
output logic [31:0] rvfi_insn,
output logic [31:0] rvfi_insn_uncompressed,
output logic rvfi_trap,
output logic rvfi_halt,
output logic rvfi_intr,
@ -671,7 +670,6 @@ module ibex_core #(
rvfi_intr <= '0;
rvfi_order <= '0;
rvfi_insn <= '0;
rvfi_insn_uncompressed <= '0;
rvfi_mode <= '0;
rvfi_rs1_addr <= '0;
rvfi_rs2_addr <= '0;
@ -693,7 +691,6 @@ module ibex_core #(
rvfi_intr <= rvfi_intr_d;
rvfi_order <= rvfi_order + rvfi_valid;
rvfi_insn <= rvfi_insn_id;
rvfi_insn_uncompressed <= instr_rdata_id;
rvfi_mode <= PRIV_LVL_M; // TODO: Update for user mode support
rvfi_rs1_addr <= rvfi_rs1_addr_id;
rvfi_rs2_addr <= rvfi_rs2_addr_id;

View file

@ -68,7 +68,6 @@ module ibex_core_tracing #(
logic rvfi_valid;
logic [63:0] rvfi_order;
logic [31:0] rvfi_insn;
logic [31:0] rvfi_insn_uncompressed;
logic rvfi_trap;
logic rvfi_halt;
logic rvfi_intr;
@ -131,7 +130,6 @@ module ibex_core_tracing #(
.rvfi_valid,
.rvfi_order,
.rvfi_insn,
.rvfi_insn_uncompressed,
.rvfi_trap,
.rvfi_halt,
.rvfi_intr,
@ -165,7 +163,7 @@ module ibex_core_tracing #(
.valid_i ( rvfi_valid ),
.pc_i ( rvfi_pc_rdata ),
.instr_i ( rvfi_insn_uncompressed ),
.instr_i ( rvfi_insn ),
.rs1_value_i ( rvfi_rs1_rdata ),
.rs2_value_i ( rvfi_rs2_rdata ),
.ex_reg_addr_i ( rvfi_rd_addr ),

View file

@ -191,6 +191,131 @@ module ibex_tracer #(
end
endfunction // printCSRInstr
function void printCRInstr(input string mnemonic);
logic [4:0] rs1;
logic [4:0] rs2;
begin
rs1 = instr_i[11:7];
rs2 = instr_i[6:2];
if (rs2 == 5'b0) begin
regs_read.push_back('{rs1, rs1_value_i});
str = $sformatf("%-16s x%0d", mnemonic, rs1);
end else begin
regs_write.push_back('{rs1, 'x});
regs_read.push_back('{rs2, rs2_value_i});
str = $sformatf("%-16s x%0d, x%0d", mnemonic, rs1, rs2);
end
end
endfunction // printCRInstr
function void printCIInstr(input string mnemonic);
begin
regs_write.push_back('{rd, 'x});
str = $sformatf("%-16s x%0d, 0x%h", mnemonic, rd, {instr_i[12], instr_i[4:0]});
end
endfunction // printCIInstr
function void printCIWInstr(input string mnemonic);
logic [4:0] rd;
begin
rd = {2'b01, instr_i[4:2]};
regs_write.push_back('{rd, 'x});
str = $sformatf("%-16s x%0d, 0x%h", mnemonic, rd, {instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6]});
end
endfunction // printCIWInstr
function void printCBInstr(input string mnemonic);
logic [4:0] rs1;
logic [8:1] imm;
begin
rs1 = {2'b01, instr_i[9:7]};
if ((instr_i[15:13] == 3'b110) || (instr_i[15:13] == 3'b111)) begin
imm = {instr_i[12], instr_i[6:5], instr_i[2], instr_i[11:10], instr_i[4:3]};
regs_read.push_back('{rs1, rs1_value_i});
end else begin
imm = {instr_i[12], instr_i[6:2], 2'b00};
regs_write.push_back('{rs1, 'x});
end
str = $sformatf("%-16s x%0d, 0x%h", mnemonic, rs1, imm);
end
endfunction // printCBInstr
function void printCSInstr(input string mnemonic);
logic [4:0] rd;
logic [4:0] rs2;
begin
rd = {2'b01, instr_i[9:7]};
rs2 = {2'b01, instr_i[4:2]};
regs_write.push_back('{rd, 'x});
regs_read.push_back('{rs2, rs2_value_i});
str = $sformatf("%-16s x%0d, x%0d", mnemonic, rd, rs2);
end
endfunction // printCSInstr
function void printCJInstr(input string mnemonic);
logic [11:1] imm;
imm = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6],
instr_i[7], instr[2], instr[11], instr_i[5:3]};
begin
str = $sformatf("%-16s 0x%h", mnemonic, imm);
end
endfunction // printCJInstr
function void printCompressedLoadInstr(input string mnemonic);
logic [4:0] rd;
logic [4:0] rs1;
logic [7:0] imm;
mem_acc_t mem_acc;
begin
// Detect C.LW intruction
if (instr_i[1:0] == OPCODE_C0) begin
rd = {2'b01, instr_i[4:2]};
rs1 = {2'b01, instr_i[9:7]};
imm = {1'b0, instr[5], instr[12:10], instr[6], 2'b00};
end else begin
// LWSP instruction
rd = instr_i[11:7];
rs1 = 5'h2;
imm = {instr[3:2], instr[12], instr[6:4], 2'b00};
end
regs_write.push_back('{rd, 'x});
regs_read.push_back('{rs1, rs1_value_i});
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rd, rs1, imm);
mem_acc.addr = ex_data_addr_i;
mem_acc.rdata = ex_data_rdata_i;
mem_access.push_back(mem_acc);
end
endfunction // printCompressedLoadInstr()
function void printCompressedStoreInstr(input string mnemonic);
logic [4:0] rs1;
logic [4:0] rs2;
logic [7:0] imm;
mem_acc_t mem_acc;
begin
// Detect C.SW instruction
if (instr_i[1:0] == OPCODE_C0) begin
rs1 = {2'b01, instr_i[9:7]};
rs2 = {2'b01, instr_i[4:2]};
imm = {1'b0, instr[5], instr[12:10], instr[6], 2'b0};
end else begin
// SWSP instruction
rs1 = 5'h2;
rs2 = instr_i[11:7];
imm = {instr[8:7], instr[12:9], 2'b00};
end
str = $sformatf("%-16s x%0d, %0d(x%0d)", mnemonic, rs2, rs1, imm);
regs_read.push_back('{rs1, rs1_value_i});
regs_read.push_back('{rs2, rs2_value_i});
mem_acc.addr = ex_data_addr_i;
mem_acc.we = 1'b1;
mem_acc.wdata = ex_data_wdata_i;
mem_access.push_back(mem_acc);
end
endfunction // printCompressedStoreInstr
function void printLoadInstr();
string mnemonic;
logic [2:0] size;
@ -317,8 +442,56 @@ module ibex_tracer #(
trace.pc = pc_i;
trace.instr = instr_i;
// separate case for 'nop' instruction to avoid overlapping with 'addi'
if (instr_i == 32'h00_00_00_13) begin
// Check for compressed instructions
if (instr_i[1:0] != 2'b11) begin
// Separate case to avoid overlapping decoding
if ((instr_i[15:13] == 3'b100) && (instr_i[1:0] == 2'b10)) begin
if (instr_i[12]) begin
if (instr_i[11:2] == 10'h0) begin
trace.printMnemonic("c.ebreak");
end else if (instr_i[6:2] == 5'b0) begin
trace.printCRInstr("c.jalr");
end else begin
trace.printCRInstr("c.add");
end
end else begin
if (instr_i[6:2] == 5'h0) begin
trace.printCRInstr("c.jr");
end else begin
trace.printCRInstr("c.mv");
end
end
end else begin
// use casex instead of case inside due to ModelSim bug
unique casex (instr_i)
// C0 Opcodes
INSTR_CADDI4SPN: trace.printCIWInstr("c.addi4spn");
INSTR_CLW: trace.printCompressedLoadInstr("c.lw");
INSTR_CSW: trace.printCompressedStoreInstr("c.sw");
// C1 Opcodes
INSTR_CADDI: trace.printCIInstr("c.addi");
INSTR_CJAL: trace.printCJInstr("c.jal");
INSTR_CJ: trace.printCJInstr("c.j");
INSTR_CLI: trace.printCIInstr("c.li");
INSTR_CLUI: trace.printCIInstr("c.lui");
INSTR_CSRLI: trace.printCBInstr("c.srli");
INSTR_CSRAI: trace.printCBInstr("c.srai");
INSTR_CANDI: trace.printCBInstr("c.andi");
INSTR_CSUB: trace.printCSInstr("c.sub");
INSTR_CXOR: trace.printCSInstr("c.xor");
INSTR_COR: trace.printCSInstr("c.or");
INSTR_CAND: trace.printCSInstr("c.and");
INSTR_CBEQZ: trace.printCBInstr("c.beqz");
INSTR_CBNEZ: trace.printCBInstr("c.bnez");
// C2 Opcodes
INSTR_CSLLI: trace.printCIInstr("c.slli");
INSTR_CLWSP: trace.printCompressedLoadInstr("c.lwsp");
INSTR_SWSP: trace.printCompressedStoreInstr("c.swsp");
default: trace.printMnemonic("INVALID");
endcase // unique casex (instr_i)
end
end else if (instr_i == 32'h00_00_00_13) begin
// separate case for 'nop' instruction to avoid overlapping with 'addi'
trace.printMnemonic("nop");
end else begin
// use casex instead of case inside due to ModelSim bug

View file

@ -6,6 +6,10 @@
package ibex_tracer_pkg;
import ibex_pkg::*;
parameter logic [1:0] OPCODE_C0 = 2'b00;
parameter logic [1:0] OPCODE_C1 = 2'b01;
parameter logic [1:0] OPCODE_C2 = 2'b10;
// instruction masks (for tracer)
parameter logic [31:0] INSTR_LUI = { 25'b?, {OPCODE_LUI } };
parameter logic [31:0] INSTR_AUIPC = { 25'b?, {OPCODE_AUIPC} };
@ -71,4 +75,36 @@ parameter logic [31:0] INSTR_STORE = {25'b?, {OPCOD
// MISC-MEM
parameter logic [31:0] INSTR_FENCE = { 17'b?, 3'b000, 5'b?, {OPCODE_MISC_MEM} };
// Compressed Instructions
// C0
parameter logic [15:0] INSTR_CADDI4SPN = { 3'b000, 11'b?, {OPCODE_C0} };
parameter logic [15:0] INSTR_CLW = { 3'b010, 11'b?, {OPCODE_C0} };
parameter logic [15:0] INSTR_CSW = { 3'b110, 11'b?, {OPCODE_C0} };
// C1
parameter logic [15:0] INSTR_CADDI = { 3'b000, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CJAL = { 3'b001, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CJ = { 3'b101, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CLI = { 3'b010, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CLUI = { 3'b011, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CBEQZ = { 3'b110, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CBNEZ = { 3'b111, 11'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CSRLI = { 3'b100, 1'b?, 2'b00, 8'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CSRAI = { 3'b100, 1'b?, 2'b01, 8'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CANDI = { 3'b100, 1'b?, 2'b10, 8'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CSUB = { 3'b100, 1'b0, 2'b11, 3'b?, 2'b00, 3'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CXOR = { 3'b100, 1'b0, 2'b11, 3'b?, 2'b01, 3'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_COR = { 3'b100, 1'b0, 2'b11, 3'b?, 2'b10, 3'b?, {OPCODE_C1} };
parameter logic [15:0] INSTR_CAND = { 3'b100, 1'b0, 2'b11, 3'b?, 2'b11, 3'b?, {OPCODE_C1} };
// C2
parameter logic [15:0] INSTR_CSLLI = { 3'b000, 11'b?, {OPCODE_C2} };
parameter logic [15:0] INSTR_CLWSP = { 3'b010, 11'b?, {OPCODE_C2} };
parameter logic [15:0] INSTR_SWSP = { 3'b110, 11'b?, {OPCODE_C2} };
parameter logic [15:0] INSTR_CMV = { 3'b100, 1'b0, 10'b?, {OPCODE_C2} };
parameter logic [15:0] INSTR_CADD = { 3'b100, 1'b1, 10'b?, {OPCODE_C2} };
parameter logic [15:0] INSTR_CEBREAK = { 3'b100, 1'b1, 5'b0, 5'b0, {OPCODE_C2} };
parameter logic [15:0] INSTR_CJR = { 3'b100, 1'b0, 5'b?, 5'b0, {OPCODE_C2} };
parameter logic [15:0] INSTR_CJALR = { 3'b100, 1'b1, 5'b?, 5'b0, {OPCODE_C2} };
endpackage