newStep.v
This commit is contained in:
223
riscv_disassembly.v
Normal file
223
riscv_disassembly.v
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* A simple disassembler for RiscV written in VERILOG.
|
||||
* See table page 104 of RiscV instruction manual.
|
||||
* Bruno Levy, August 2022
|
||||
* usage:
|
||||
* module XXX( ... );
|
||||
* ...
|
||||
* ...
|
||||
* `include "riscv_disassembly.v" // yes, *inside* module definition.
|
||||
* always @(posedge clk) begin
|
||||
* riscv_disasm(instr, PC);
|
||||
* $write("\n");
|
||||
* end
|
||||
* endmodule
|
||||
*/
|
||||
|
||||
|
||||
/* Functions to decode immediates */
|
||||
|
||||
function signed [31:0] riscv_disasm_Iimm;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Iimm = {{21{instr[31]}}, instr[30:20]};
|
||||
endfunction
|
||||
|
||||
function signed [31:0] riscv_disasm_Simm;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Simm = {{21{instr[31]}}, instr[30:25],instr[11:7]};
|
||||
endfunction
|
||||
|
||||
function [19:0] riscv_disasm_Uimm_raw;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Uimm_raw = {instr[31:12]};
|
||||
endfunction
|
||||
|
||||
function [31:0] riscv_disasm_Uimm;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Uimm = {instr[31],instr[30:12],{12{1'b0}}};
|
||||
endfunction
|
||||
|
||||
function [31:0] riscv_disasm_Bimm;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Bimm = {
|
||||
{20{instr[31]}},instr[7],instr[30:25],instr[11:8],1'b0
|
||||
};
|
||||
endfunction
|
||||
|
||||
function [31:0] riscv_disasm_Jimm;
|
||||
input [31:0] instr;
|
||||
riscv_disasm_Jimm = {
|
||||
{12{instr[31]}},instr[19:12],instr[20],instr[30:21],1'b0
|
||||
};
|
||||
endfunction
|
||||
|
||||
|
||||
/*
|
||||
* disassembler (see comment at the beginning of this file)
|
||||
*/
|
||||
task riscv_disasm;
|
||||
input [31:0] instr;
|
||||
input [31:0] PC;
|
||||
begin
|
||||
case(instr[6:0])
|
||||
7'b0110011: begin
|
||||
if(instr[31:7] == 0) begin
|
||||
$write("nop");
|
||||
end else begin
|
||||
if(instr[25]) begin // RV32M instructions
|
||||
case(instr[14:12])
|
||||
3'b000: $write("mul");
|
||||
3'b001: $write("mulh");
|
||||
3'b010: $write("mulhsu");
|
||||
3'b011: $write("mulhu");
|
||||
3'b100: $write("div");
|
||||
3'b101: $write("divu");
|
||||
3'b110: $write("rem");
|
||||
3'b111: $write("remu");
|
||||
endcase
|
||||
end else begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("%s", instr[30] ? "sub" : "add");
|
||||
3'b001: $write("sll");
|
||||
3'b010: $write("slt");
|
||||
3'b011: $write("sltu");
|
||||
3'b100: $write("xor");
|
||||
3'b101: $write("%s", instr[30] ? "sra" : "srl");
|
||||
3'b110: $write("or");
|
||||
3'b111: $write("and");
|
||||
endcase // case (instr[14:12])
|
||||
end
|
||||
$write(" x%0d,x%0d,x%0d",instr[11:7],instr[19:15],instr[24:20]);
|
||||
end
|
||||
end
|
||||
7'b0010011: begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("addi");
|
||||
3'b010: $write("slti");
|
||||
3'b011: $write("sltiu");
|
||||
3'b100: $write("xori");
|
||||
3'b110: $write("ori");
|
||||
3'b111: $write("andi");
|
||||
3'b001: $write("slli");
|
||||
3'b101: $write("%s", instr[30] ? "srai" : "srli");
|
||||
endcase
|
||||
if(instr[14:12] == 3'b001 || instr[14:12] == 3'b101) begin
|
||||
$write(" x%0d,x%0d,%0d",
|
||||
instr[11:7],instr[19:15],instr[24:20]
|
||||
);
|
||||
end else begin
|
||||
$write(" x%0d,x%0d,%0d",
|
||||
instr[11:7],instr[19:15],riscv_disasm_Iimm(instr)
|
||||
);
|
||||
end
|
||||
end
|
||||
7'b1100011: begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("beq");
|
||||
3'b001: $write("bne");
|
||||
3'b100: $write("blt");
|
||||
3'b101: $write("bge");
|
||||
3'b110: $write("bltu");
|
||||
3'b111: $write("bgeu");
|
||||
default: $write("B???");
|
||||
endcase
|
||||
$write(" x%0d,x%0d,0x%0h",
|
||||
instr[19:15],instr[24:20],PC+riscv_disasm_Bimm(instr)
|
||||
);
|
||||
end
|
||||
7'b1100111:
|
||||
$write("jalr x%0d,x%0d,%0d",
|
||||
instr[11:7],instr[19:15],riscv_disasm_Iimm(instr)
|
||||
);
|
||||
7'b1101111:
|
||||
$write("jal x%0d,0x%0h",instr[11:7],PC+riscv_disasm_Jimm(instr));
|
||||
7'b0010111:
|
||||
$write("auipc x%0d,0x%0h <0x%0h>",
|
||||
instr[11:7],
|
||||
riscv_disasm_Uimm_raw(instr),PC+riscv_disasm_Uimm(instr)
|
||||
);
|
||||
7'b0110111:
|
||||
$write("lui x%0d,0x%0h <0x%0h>",
|
||||
instr[11:7],
|
||||
riscv_disasm_Uimm_raw(instr),riscv_disasm_Uimm(instr)
|
||||
);
|
||||
7'b0000011: begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("lb");
|
||||
3'b001: $write("lh");
|
||||
3'b010: $write("lw");
|
||||
3'b100: $write("lbu");
|
||||
3'b101: $write("lhu");
|
||||
default: $write("l??");
|
||||
endcase
|
||||
$write(" x%0d,%0d(x%0d)",
|
||||
instr[11:7],riscv_disasm_Iimm(instr),instr[19:15]
|
||||
);
|
||||
end
|
||||
7'b0100011: begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("sb");
|
||||
3'b001: $write("sh");
|
||||
3'b010: $write("sw");
|
||||
default: $write("s??");
|
||||
endcase
|
||||
$write(" x%0d,%0d(x%0d)",
|
||||
instr[24:20],riscv_disasm_Simm(instr),instr[19:15]
|
||||
);
|
||||
end
|
||||
7'b1110011: begin
|
||||
case(instr[14:12])
|
||||
3'b000: $write("ebreak");
|
||||
3'b010: begin
|
||||
case({instr[27],instr[21]})
|
||||
2'b00: $write("rdcycle x%0d", instr[11:7]);
|
||||
2'b10: $write("rdcycleh x%0d", instr[11:7]);
|
||||
2'b01: $write("rdinstret x%0d", instr[11:7]);
|
||||
2'b11: $write("rdinstreth x%0d",instr[11:7]);
|
||||
endcase
|
||||
end
|
||||
default: $write("SYSTEM");
|
||||
endcase
|
||||
end
|
||||
default:
|
||||
$write("?????");
|
||||
endcase
|
||||
end
|
||||
endtask
|
||||
|
||||
|
||||
/* Instruction recognizers for the 10 RV32I instructions */
|
||||
function riscv_disasm_isALUreg; input [31:0] I; riscv_disasm_isALUreg=(I[6:0]==7'b0110011); endfunction
|
||||
function riscv_disasm_isALUimm; input [31:0] I; riscv_disasm_isALUimm=(I[6:0]==7'b0010011); endfunction
|
||||
function riscv_disasm_isBranch; input [31:0] I; riscv_disasm_isBranch=(I[6:0]==7'b1100011); endfunction
|
||||
function riscv_disasm_isJALR; input [31:0] I; riscv_disasm_isJALR =(I[6:0]==7'b1100111); endfunction
|
||||
function riscv_disasm_isJAL; input [31:0] I; riscv_disasm_isJAL =(I[6:0]==7'b1101111); endfunction
|
||||
function riscv_disasm_isAUIPC; input [31:0] I; riscv_disasm_isAUIPC =(I[6:0]==7'b0010111); endfunction
|
||||
function riscv_disasm_isLUI; input [31:0] I; riscv_disasm_isLUI =(I[6:0]==7'b0110111); endfunction
|
||||
function riscv_disasm_isLoad; input [31:0] I; riscv_disasm_isLoad =(I[6:0]==7'b0000011); endfunction
|
||||
function riscv_disasm_isStore; input [31:0] I; riscv_disasm_isStore =(I[6:0]==7'b0100011); endfunction
|
||||
function riscv_disasm_isSYSTEM; input [31:0] I; riscv_disasm_isSYSTEM=(I[6:0]==7'b1110011); endfunction
|
||||
function riscv_disasm_isRV32M; input [31:0] I; riscv_disasm_isRV32M=riscv_disasm_isALUreg(I) && I[25]; endfunction
|
||||
|
||||
/* Utility functions: register indices */
|
||||
function [4:0] riscv_disasm_rs1Id; input [31:0] I; riscv_disasm_rs1Id = I[19:15]; endfunction
|
||||
function [4:0] riscv_disasm_rs2Id; input [31:0] I; riscv_disasm_rs2Id = I[24:20]; endfunction
|
||||
function [4:0] riscv_disasm_shamt; input [31:0] I; riscv_disasm_shamt = I[24:20]; endfunction
|
||||
function [4:0] riscv_disasm_rdId; input [31:0] I; riscv_disasm_rdId = I[11:7]; endfunction
|
||||
function [1:0] riscv_disasm_csrId; input [31:0] I; riscv_disasm_csrId = {I[27],I[21]}; endfunction
|
||||
|
||||
/* Utility functions: funct3 and funct7 */
|
||||
function [2:0] riscv_disasm_funct3; input [31:0] I; riscv_disasm_funct3 = I[14:12]; endfunction
|
||||
function [6:0] riscv_disasm_funct7; input [31:0] I; riscv_disasm_funct7 = I[31:25]; endfunction
|
||||
|
||||
function riscv_disasm_readsRs1;
|
||||
input [31:0] I;
|
||||
riscv_disasm_readsRs1 = !(riscv_disasm_isJAL(I) || riscv_disasm_isAUIPC(I) || riscv_disasm_isLUI(I));
|
||||
endfunction
|
||||
|
||||
function riscv_disasm_readsRs2;
|
||||
input [31:0] I;
|
||||
riscv_disasm_readsRs2 = riscv_disasm_isALUreg(I) || riscv_disasm_isBranch(I) || riscv_disasm_isStore(I);
|
||||
endfunction
|
||||
|
||||
|
||||
Reference in New Issue
Block a user