* riscv_disassembly.v: added utility functions in riscv_disasm (RV32I instruction recognizers and field extraction)
* pipelineX_generic.v: improved debugger
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
PROJECTNAME=SOC
|
||||
BOARD=ulx3s
|
||||
BOARD_FREQ=25
|
||||
CPU_FREQ=110
|
||||
CPU_FREQ=100
|
||||
FPGA_VARIANT=85k
|
||||
FPGA_PACKAGE=CABGA381
|
||||
VERILOGS=$1
|
||||
|
||||
@@ -1,15 +1,21 @@
|
||||
/**
|
||||
* pipelineX_generic.v
|
||||
* Configurable PC prediction
|
||||
* Configurable 5-stages pipelined RV32I
|
||||
*/
|
||||
|
||||
`define CONFIG_PC_PREDICT // enables D -> F path (needed by options above)
|
||||
`define CONFIG_RAS // return address stack
|
||||
`define CONFIG_GSHARE // gshare branch prediction (or BTFNT if not set)
|
||||
//`define CONFIG_REGISTERED_D_PREDICT_BRANCH // registers branch prediction signal
|
||||
`define CONFIG_REGISTERED_D_PREDICT_BRANCH // registers branch predict signal
|
||||
// (may gain a bit of fmax, but not
|
||||
// always...)
|
||||
|
||||
|
||||
`define CONFIG_DEBUG // debug mode, copies instr in all stages
|
||||
`define CONFIG_DEBUG_STEP_BY_STEP // press key for next instr (verilator only)
|
||||
|
||||
//`define CONFIG_INITIALIZE // initialize register file and BHT table
|
||||
// (required by Icarus/iverilog and by some synth tools)
|
||||
|
||||
`default_nettype none
|
||||
`include "clockworks.v"
|
||||
`include "emitter_uart.v"
|
||||
@@ -25,6 +31,10 @@ module Processor (
|
||||
output IO_mem_wr // IO write flag
|
||||
);
|
||||
|
||||
`ifdef CONFIG_DEBUG
|
||||
`include "riscv_disassembly.v"
|
||||
`endif
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
/*
|
||||
@@ -44,6 +54,11 @@ module Processor (
|
||||
|
||||
/******************************************************************************/
|
||||
|
||||
`ifdef CONFIG_INITIALIZE
|
||||
// Iteration variable for the "initial" blocks
|
||||
integer i;
|
||||
`endif
|
||||
|
||||
// CSRs (cycle and retired instructions counters)
|
||||
reg [63:0] cycle;
|
||||
reg [63:0] instret;
|
||||
@@ -172,6 +187,15 @@ module Processor (
|
||||
// branch history table (2 bits per entry)
|
||||
reg [1:0] BHT[BHT_SIZE-1:0];
|
||||
|
||||
`ifdef CONFIG_INITIALIZE
|
||||
initial begin
|
||||
branch_history = 0;
|
||||
for(i=0; i<BHT_SIZE; i++) begin
|
||||
BHT[i] = 2'b01; // all entries of BHT initialized as "weakly taken"
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
// gets the index in the branch prediction table
|
||||
// from the PC
|
||||
function [BHT_INDEX_BITS-1:0] BHT_index;
|
||||
@@ -231,6 +255,15 @@ module Processor (
|
||||
`endif // `CONFIG_PC_PREDICT
|
||||
|
||||
reg [31:0] RegisterBank [0:31];
|
||||
|
||||
`ifdef CONFIG_INITIALIZE
|
||||
initial begin
|
||||
for(i=0; i<32; i++) begin
|
||||
RegisterBank[i] = 0;
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
||||
DE_rdId <= D_rdId;
|
||||
@@ -494,7 +527,7 @@ module Processor (
|
||||
{dir, prev} == 3'b101 ? 2'b10 :
|
||||
{dir, prev} == 3'b110 ? 2'b11 :
|
||||
2'b11 ;
|
||||
endfunction;
|
||||
endfunction
|
||||
`endif
|
||||
`endif
|
||||
|
||||
@@ -700,6 +733,97 @@ module Processor (
|
||||
always @(posedge clk) begin
|
||||
if(halt) $finish();
|
||||
end
|
||||
|
||||
`ifdef CONFIG_DEBUG
|
||||
reg [31:0] DE_instr; reg [31:0] DE_PC;
|
||||
reg [31:0] EM_instr; reg [31:0] EM_PC;
|
||||
reg [31:0] MW_instr; reg [31:0] MW_PC;
|
||||
|
||||
localparam NOP = 32'b0000000_00000_00000_000_00000_0110011;
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(!D_stall) begin
|
||||
DE_instr <= FD_nop ? NOP : FD_instr;
|
||||
DE_PC <= FD_PC;
|
||||
end
|
||||
if(E_flush) begin
|
||||
DE_instr <= NOP;
|
||||
end
|
||||
EM_instr <= DE_instr;
|
||||
EM_PC <= DE_PC;
|
||||
MW_instr <= EM_instr;
|
||||
MW_PC <= EM_PC;
|
||||
end
|
||||
|
||||
|
||||
always @(posedge clk) begin
|
||||
if(resetn & !halt) begin
|
||||
|
||||
$write(" ");
|
||||
$write("[W] PC=%h ", MW_PC);
|
||||
$write(" ");
|
||||
riscv_disasm(MW_instr,MW_PC);
|
||||
if(wbEnable) $write(" x%0d <- 0x%0h",riscv_disasm_rdId(MW_instr),wbData);
|
||||
$write("\n");
|
||||
|
||||
$write(" ");
|
||||
$write("[M] PC=%h ", EM_PC);
|
||||
$write(" ");
|
||||
riscv_disasm(EM_instr,EM_PC);
|
||||
$write("\n");
|
||||
|
||||
$write("( %c) ",E_flush ? "f":" ");
|
||||
$write("[E] PC=%h ", DE_PC);
|
||||
$write(" ");
|
||||
riscv_disasm(DE_instr,DE_PC);
|
||||
if(DE_instr != NOP) begin
|
||||
$write(" rs1=0x%h rs2=0x%h ",E_rs1, E_rs2);
|
||||
`ifdef CONFIG_PC_PREDICT
|
||||
if(riscv_disasm_isBranch(DE_instr)) begin
|
||||
$write(" taken:%0d %s",
|
||||
E_takeBranch,
|
||||
(E_takeBranch == DE_predictBranch) ? "predict hit" : "predict miss"
|
||||
);
|
||||
end
|
||||
`endif
|
||||
end
|
||||
$write("\n");
|
||||
|
||||
$write("(%c%c) ",D_stall ? "s":" ",D_flush ? "f":" ");
|
||||
$write("[D] PC=%h ", FD_PC);
|
||||
$write("[%s%s] ",
|
||||
dataHazard && rs1Hazard?"*":" ",
|
||||
dataHazard && rs2Hazard?"*":" ");
|
||||
riscv_disasm(FD_nop ? NOP : FD_instr,FD_PC);
|
||||
`ifdef CONFIG_PC_PREDICT
|
||||
if(riscv_disasm_isBranch(FD_instr)) begin
|
||||
$write(" predict taken:%0d",D_predictBranch);
|
||||
end
|
||||
`endif
|
||||
$write("\n");
|
||||
|
||||
$write("(%c ) ",F_stall ? "s":" ");
|
||||
$write("[F] PC=%h ", F_PC);
|
||||
`ifdef CONFIG_PC_PREDICT
|
||||
if(D_predictPC) $write(" PC <- [D] 0x%0h (prediction)",D_PCprediction);
|
||||
`endif
|
||||
if(EM_correctPC) $write(" PC <- [E] 0x%0h (correction)",EM_PCcorrection);
|
||||
$write("\n");
|
||||
|
||||
$display("");
|
||||
end
|
||||
end
|
||||
|
||||
`ifdef CONFIG_DEBUG_STEP_BY_STEP
|
||||
reg [31:0] z;
|
||||
always @(posedge clk) begin
|
||||
if(resetn & !halt) begin
|
||||
z <= $c32("getchar()");
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
`endif
|
||||
`endif
|
||||
|
||||
/******************************************************************************/
|
||||
@@ -767,8 +891,12 @@ module SOC (
|
||||
`ifdef BENCH
|
||||
always @(posedge clk) begin
|
||||
if(uart_valid) begin
|
||||
`ifdef CONFIG_DEBUG
|
||||
$display("UART: %c", IO_mem_wdata[7:0]);
|
||||
`else
|
||||
$write("%c", IO_mem_wdata[7:0] );
|
||||
$fflush(32'h8000_0001);
|
||||
`endif
|
||||
end
|
||||
end
|
||||
`endif
|
||||
|
||||
@@ -2,8 +2,21 @@
|
||||
* 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]};
|
||||
@@ -38,6 +51,10 @@ function [31:0] riscv_disasm_Jimm;
|
||||
};
|
||||
endfunction
|
||||
|
||||
|
||||
/*
|
||||
* disassembler (see comment at the beginning of this file)
|
||||
*/
|
||||
task riscv_disasm;
|
||||
input [31:0] instr;
|
||||
input [31:0] PC;
|
||||
@@ -155,3 +172,27 @@ task riscv_disasm;
|
||||
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
|
||||
|
||||
/* 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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user