Level Defines - Technical Documentation¶
Contents¶
- Overview
- Feature Flags
- Multiplier Implementations
- Trace and Log Controls
- Simulation Controls
- Makefile Integration
- Usage Examples
Overview¶
Purpose¶
The level_defines.svh file provides compile-time configuration for the Level RISC-V core. This header provides central definitions for feature flags, multiplier selection, and trace controls.
File Location¶
Include Method¶
Feature Flags¶
Multiplier Selection¶
Only one multiplier implementation may be active at a time:
//------------------------------------------------------------------------------
// MULTIPLIER IMPLEMENTATION SELECTION
// Enable only ONE of the following multiplier implementations
//------------------------------------------------------------------------------
// Single-cycle Wallace tree multiplier (default - best performance)
`define FEAT_WALLACE_SINGLE
// Multi-cycle Wallace tree multiplier (area optimized)
//`define FEAT_WALLACE_MULTI
// DSP block multiplier (FPGA optimized)
//`define FEAT_DSP_MUL
Multiplier Comparison¶
| Implementation | Latency | Throughput | Area | Use case |
|---|---|---|---|---|
| WALLACE_SINGLE | 1 cycle | 1/cycle | High | Performance |
| WALLACE_MULTI | N cycle | 1/N cycle | Low | Area opt. |
| DSP_MUL | 1-3 cycle | 1/cycle | DSP | FPGA |
Multiplier Implementations¶
Wallace Single (Default)¶
`define FEAT_WALLACE_SINGLE
// Usage
`ifdef FEAT_WALLACE_SINGLE
// Single-cycle 32x32 Wallace tree
wallace_mul_single u_mul (
.i_a (operand_a),
.i_b (operand_b),
.o_prod (product)
);
`endif
Features: - 32x32 multiply in one cycle - 64-bit result - High area usage - Long critical path
Wallace Multi¶
//`define FEAT_WALLACE_MULTI
// Usage
`ifdef FEAT_WALLACE_MULTI
// Multi-cycle radix-4 Booth multiplier
wallace_mul_multi u_mul (
.clk_i (clk),
.rst_ni (rst_n),
.i_start (mul_start),
.i_a (operand_a),
.i_b (operand_b),
.o_prod (product),
.o_done (mul_done)
);
`endif
Features: - Multi-cycle multiply (4-16 cycles) - Low area usage - Requires pipeline stalls
DSP Multiplier¶
//`define FEAT_DSP_MUL
// Usage
`ifdef FEAT_DSP_MUL
// FPGA DSP48 block multiplier
dsp_mul u_mul (
.clk_i (clk),
.i_a (operand_a),
.i_b (operand_b),
.o_prod (product)
);
`endif
Features: - Uses FPGA DSP block - 1-3 cycle latency (pipeline) - Low logic usage - Vendor-specific
Trace and Log Controls¶
Trace Flags¶
These flags are normally commented out and enabled via the makefile:
//------------------------------------------------------------------------------
// TRACE AND LOGGING CONTROLS
// These are typically enabled via makefile +define+ flags
//------------------------------------------------------------------------------
// `define COMMIT_TRACER // Carry trace info in pipeline registers
// `define KONATA_TRACER // Konata pipeline visualizer support
// `define LOG_COMMIT // Spike-compatible commit trace
// `define LOG_RAM // RAM initialization messages
// `define LOG_UART // UART TX file logging
// `define LOG_BP // Branch predictor statistics
// `define LOG_BP_VERBOSE // Per-branch verbose logging
Flag Descriptions¶
| Flag | Description | Output |
|---|---|---|
COMMIT_TRACER |
Carries trace info in pipeline registers | - |
KONATA_TRACER |
Konata pipeline visualizer support | pipeline.log |
LOG_COMMIT |
Spike-comparable commit trace | commit.log |
LOG_RAM |
RAM load messages | Console |
LOG_UART |
UART TX output logged to file | uart.log |
LOG_BP |
Branch predictor statistics | Console |
LOG_BP_VERBOSE |
Verbose log per branch | Console |
Simulation Controls¶
Simulation Flags¶
//------------------------------------------------------------------------------
// SIMULATION CONTROLS
// Enabled via makefile for simulation modes
//------------------------------------------------------------------------------
// `define SIM_FAST // Disable all logging for speed
// `define SIM_UART_MONITOR // UART monitoring + auto-stop
// `define SIM_COVERAGE // Enable coverage collection
SIM_FAST Mode¶
`ifdef SIM_FAST
// All logs disabled
// Maximum simulation speed
`else
// Normal debug modunda
`ifdef LOG_COMMIT
// Commit trace aktif
`endif
`endif
SIM_UART_MONITOR¶
`ifdef SIM_UART_MONITOR
// Monitor UART output
// Stop simulation when PASS or FAIL is seen
// Detect benchmark results
`endif
Makefile Integration¶
Passing Verilator Defines¶
# Trace kontrolleri
LOG_COMMIT ?= 0
LOG_PIPELINE ?= 0
LOG_RAM ?= 0
LOG_UART ?= 0
LOG_BP ?= 0
LOG_BP_VERBOSE ?= 0
KONATA_TRACER ?= 0
# Pass defines to Verilator
VFLAGS_DEFINES :=
ifeq ($(LOG_COMMIT),1)
VFLAGS_DEFINES += +define+LOG_COMMIT
endif
ifeq ($(KONATA_TRACER),1)
VFLAGS_DEFINES += +define+KONATA_TRACER +define+COMMIT_TRACER
endif
# ... other flags
Usage Examples¶
# Sadece commit trace
make run T=rv32ui-p-add LOG_COMMIT=1
# Pipeline visualizer
make run T=rv32ui-p-add KONATA_TRACER=1 LOG_PIPELINE=1
# Branch predictor stats
make run_coremark LOG_BP=1 SIM_UART_MONITOR=1
# Fast simulation
make run T=coremark SIM_FAST=1
# All logs
make run T=test LOG_COMMIT=1 LOG_RAM=1 LOG_UART=1 LOG_BP=1
Usage Examples¶
Conditional Compilation¶
module example
import level_param::*;
(
input logic clk_i,
// ...
);
`ifdef FEAT_WALLACE_SINGLE
// Single-cycle multiplier
assign mul_done = 1'b1; // Always ready
`elsif FEAT_WALLACE_MULTI
// Multi-cycle multiplier
logic mul_busy;
// ...
`endif
`ifdef LOG_COMMIT
always_ff @(posedge clk_i) begin
if (commit_valid) begin
$display("core 0: 0x%08x (0x%08x) x%0d 0x%08x",
commit_pc, commit_instr, commit_rd, commit_data);
end
end
`endif
endmodule
Guard Pattern¶
Cross-Module Dependency¶
// KONATA_TRACER aktifse, COMMIT_TRACER da gerekli
`ifdef KONATA_TRACER
`ifndef COMMIT_TRACER
`define COMMIT_TRACER
`endif
`endif
Flag Dependencies¶
Relationship Diagram¶
┌─────────────────────────────────────────────────────────────────────────────────┐
│ FLAG DEPENDENCIES │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ KONATA_TRACER ──────────────────────► COMMIT_TRACER │
│ │ │ │
│ │ ▼ │
│ │ Pipeline registers │
│ │ carry trace info │
│ │ │
│ ▼ │
│ LOG_PIPELINE ─────────────────────► pipeline.log output │
│ │
│ │
│ LOG_COMMIT ───────────────────────► commit.log output │
│ │ │ │
│ │ ▼ │
│ │ Spike comparison │
│ │ │
│ │
│ SIM_FAST ─────────────────────────► Disables all LOG_* │
│ │
│ │
│ LOG_BP_VERBOSE ───────────────────► LOG_BP │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Implicit Dependencies¶
| Flag | Requires |
|---|---|
KONATA_TRACER |
COMMIT_TRACER (auto-enabled) |
LOG_BP_VERBOSE |
LOG_BP (implied) |
SIM_FAST |
Disables all LOG_* flags |
Best Practices¶
1. Multiplier Selection¶
// Only one multiplier implementation should be active
`define FEAT_WALLACE_SINGLE
//`define FEAT_WALLACE_MULTI // Comment out
//`define FEAT_DSP_MUL // Comment out
2. Trace Logs¶
// Normalde comment halinde
// Enable via Makefile
//`define LOG_COMMIT
// Makefile:
// make run T=test LOG_COMMIT=1
3. Debug vs Release¶
# Debug build (default)
make run T=test MODE=debug
# Release build (minimal logging)
make run T=coremark MODE=release SIM_FAST=1
# Test mode (assertions enabled)
make isa MODE=test
Summary¶
The level_defines.svh file:
- Feature Selection: Multiplier implementasyonu
- Trace Control: Commit, pipeline, UART logging
- Simulation Modes: Fast, coverage, UART monitor
- Makefile Integration: Runtime define passing
- Conditional Compilation:
ifdef/endifpattern
This header file supports different configurations of the Level RISC-V core.
Exception Priority - Technical Documentation¶
Contents¶
- Overview
- RISC-V Exception Model
- Priority Configuration
- Exception Types
- Trap Handling
- Pipeline Integration
- Usage Examples
Overview¶
Purpose¶
The exception_priority.svh file defines the priority order of RISC-V exceptions and selects which exception is handled when multiple exceptions occur in the same cycle.
File Location¶
Basic Concept¶
Multiple exceptions can occur at the same time:
- Instruction page fault (fetch)
- Illegal instruction (decode)
- Load/Store fault (memory)
The exception with the lowest priority number is taken first.
RISC-V Exception Model¶
Exception vs Interrupt¶
| Type | Property | Example |
|---|---|---|
| Exception | Synchronous, instruction-related | Illegal instruction |
| Interrupt | Asynchronous, external | Timer interrupt |
Exception Classes¶
┌─────────────────────────────────────────────────────────────────────────────────┐
│ EXCEPTION CLASSIFICATION │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ INSTRUCTION EXCEPTIONS │ │
│ │ │ │
│ │ • Instruction Address Misaligned │ │
│ │ • Instruction Access Fault │ │
│ │ • Illegal Instruction │ │
│ │ • Breakpoint │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ LOAD EXCEPTIONS │ │
│ │ │ │
│ │ • Load Address Misaligned │ │
│ │ • Load Access Fault │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ STORE EXCEPTIONS │ │
│ │ │ │
│ │ • Store/AMO Address Misaligned │ │
│ │ • Store/AMO Access Fault │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
│ ┌─────────────────────────────────────────────────────────────────────────┐ │
│ │ ENVIRONMENT CALLS │ │
│ │ │ │
│ │ • Environment Call from U-mode │ │
│ │ • Environment Call from S-mode │ │
│ │ • Environment Call from M-mode │ │
│ │ │ │
│ └─────────────────────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Priority Configuration¶
RISC-V Standard Priority¶
The RISC-V specification defines exception priorities:
// exception_priority.svh
`ifndef EXCEPTION_PRIORITY_SVH
`define EXCEPTION_PRIORITY_SVH
//------------------------------------------------------------------------------
// EXCEPTION PRIORITY CONFIGURATION
// Lower number = Higher priority
// Based on RISC-V Privileged Specification
//------------------------------------------------------------------------------
// Instruction Exceptions (highest priority for same instruction)
localparam int PRIORITY_INSTR_ADDR_MISALIGNED = 0;
localparam int PRIORITY_INSTR_ACCESS_FAULT = 1;
localparam int PRIORITY_ILLEGAL_INSTR = 2;
localparam int PRIORITY_BREAKPOINT = 3;
// Load Exceptions
localparam int PRIORITY_LOAD_ADDR_MISALIGNED = 4;
localparam int PRIORITY_LOAD_ACCESS_FAULT = 5;
// Store Exceptions
localparam int PRIORITY_STORE_ADDR_MISALIGNED = 6;
localparam int PRIORITY_STORE_ACCESS_FAULT = 7;
// Environment Calls (lowest priority)
localparam int PRIORITY_ECALL_U = 8;
localparam int PRIORITY_ECALL_S = 9;
localparam int PRIORITY_ECALL_M = 10;
`endif // EXCEPTION_PRIORITY_SVH
Priority Table¶
| Priority | Exception | Code | Description |
|---|---|---|---|
| 0 | Instruction Address Misaligned | 0 | Highest priority |
| 1 | Instruction Access Fault | 1 | I-Cache/Bus fault |
| 2 | Illegal Instruction | 2 | Invalid opcode |
| 3 | Breakpoint | 3 | EBREAK instruction |
| 4 | Load Address Misaligned | 4 | Unaligned load |
| 5 | Load Access Fault | 5 | D-Cache/Bus fault |
| 6 | Store Address Misaligned | 6 | Unaligned store |
| 7 | Store Access Fault | 7 | D-Cache/Bus fault |
| 8 | Environment Call U-mode | 8 | ECALL from User |
| 9 | Environment Call S-mode | 9 | ECALL from Supervisor |
| 10 | Environment Call M-mode | 11 | ECALL from Machine |
Exception Types¶
Instruction Address Misaligned¶
// Fetch stage'de kontrol
// Compressed (RV32C) may be 2-byte aligned
// Standard instructions must be 4-byte aligned
logic instr_addr_misaligned;
`ifdef RV32C_ENABLED
assign instr_addr_misaligned = pc[0]; // Bit 0 must be 0
`else
assign instr_addr_misaligned = |pc[1:0]; // Bits 1:0 must be 0
`endif
Instruction Access Fault¶
// I-Cache miss + bus error
// PMA non-executable region
// PMP execute violation
logic instr_access_fault;
assign instr_access_fault = icache_error ||
pma_exec_fault ||
pmp_exec_fault;
Illegal Instruction¶
// Decode stage'de kontrol
// - Invalid opcode
// - Invalid funct3/funct7
// - CSR access violation
logic illegal_instr;
assign illegal_instr = !valid_opcode ||
invalid_funct ||
csr_access_fault;
Load/Store Misaligned¶
// Memory stage'de kontrol
// LW/SW: 4-byte aligned
// LH/SH: 2-byte aligned
// LB/SB: no alignment requirement
logic addr_misaligned;
always_comb begin
case (mem_size)
MEM_SIZE_WORD: addr_misaligned = |addr[1:0];
MEM_SIZE_HALF: addr_misaligned = addr[0];
MEM_SIZE_BYTE: addr_misaligned = 1'b0;
default: addr_misaligned = 1'b1;
endcase
end
Load/Store Access Fault¶
// D-Cache miss + bus error
// PMA read/write violation
// PMP read/write violation
logic load_access_fault;
logic store_access_fault;
assign load_access_fault = dcache_error && is_load;
assign store_access_fault = dcache_error && is_store;
Trap Handling¶
Exception Priority Resolver¶
// If multiple exceptions occur in the same cycle
// Select the highest-priority one
function automatic logic [3:0] resolve_exception_priority(
input logic instr_addr_mis,
input logic instr_access,
input logic illegal,
input logic breakpoint,
input logic load_mis,
input logic load_access,
input logic store_mis,
input logic store_access,
input logic ecall
);
// Priority order (low number = high priority)
if (instr_addr_mis) return 4'd0; // Instruction address misaligned
if (instr_access) return 4'd1; // Instruction access fault
if (illegal) return 4'd2; // Illegal instruction
if (breakpoint) return 4'd3; // Breakpoint
if (load_mis) return 4'd4; // Load address misaligned
if (load_access) return 4'd5; // Load access fault
if (store_mis) return 4'd6; // Store address misaligned
if (store_access) return 4'd7; // Store access fault
if (ecall) return 4'd11; // Environment call M-mode
return 4'd15; // No exception
endfunction
Trap Entry¶
// When an exception occurs
always_ff @(posedge clk_i or negedge rst_ni) begin
if (!rst_ni) begin
mepc <= '0;
mcause <= '0;
mtval <= '0;
end else if (exception_valid) begin
// Save PC
mepc <= exception_pc;
// Save cause (exception code)
mcause <= {1'b0, 27'b0, exception_code};
// Save trap value
case (exception_code)
EXC_INSTR_ADDR_MIS: mtval <= exception_pc;
EXC_INSTR_ACC_FAULT: mtval <= exception_pc;
EXC_ILLEGAL_INSTR: mtval <= exception_instr;
EXC_LOAD_ADDR_MIS: mtval <= exception_addr;
EXC_LOAD_ACC_FAULT: mtval <= exception_addr;
EXC_STORE_ADDR_MIS: mtval <= exception_addr;
EXC_STORE_ACC_FAULT: mtval <= exception_addr;
default: mtval <= '0;
endcase
end
end
Pipeline Integration¶
Exception Propagation¶
┌─────────────────────────────────────────────────────────────────────────────────┐
│ EXCEPTION FLOW IN PIPELINE │
├─────────────────────────────────────────────────────────────────────────────────┤
│ │
│ FETCH ─────► DECODE ─────► EXECUTE ─────► MEMORY ─────► WRITEBACK │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ ▼ ▼ ▼ ▼ ▼ │
│ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐ │
│ │Instr │ │Illegal│ │ (none│ │Load/ │ │ │ │
│ │Addr │ │Instr │ │ usually) │Store │ │Commit│ │
│ │Fault │ │Break │ │ │ │Fault │ │ │ │
│ └──────┘ └──────┘ └──────┘ └──────┘ └──────┘ │
│ │ │ │ │ │ │
│ │ │ │ │ │ │
│ └────────────┴──────────────┴─────────────┴──────────────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ EXCEPTION │ │
│ │ RESOLVER │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ TRAP ENTRY │ │
│ │ (CSR write) │ │
│ └──────┬──────┘ │
│ │ │
│ ▼ │
│ ┌─────────────┐ │
│ │ FLUSH PIPE │ │
│ │ Jump mtvec │ │
│ └─────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────────────────────┘
Exception Register¶
Exception information is carried between pipeline stages:
typedef struct packed {
logic valid; // Exception aktif
logic [3:0] cause; // Exception code
logic [31:0] pc; // Exception PC
logic [31:0] tval; // Trap value
} exception_t;
// Pipeline register
exception_t ex_exception_q, mem_exception_q;
Precise Exception¶
RISC-V requires precise exceptions:
// All instructions before the faulting instruction
// must have committed
// Sonrakiler flush edilmeli
always_comb begin
if (exception_valid) begin
// Flush younger instructions
flush_if = 1'b1;
flush_id = 1'b1;
flush_ex = 1'b1;
// Exception instruction commit edilmez
mem_commit = 1'b0;
end
end
Usage Examples¶
Exception Handler¶
module exception_handler
import level_param::*;
(
input logic clk_i,
input logic rst_ni,
// Exception inputs from pipeline
input logic i_fetch_fault,
input logic i_illegal_instr,
input logic i_load_fault,
input logic i_store_fault,
input logic [31:0] i_pc,
input logic [31:0] i_addr,
input logic [31:0] i_instr,
// Exception output
output logic o_exception,
output logic [3:0] o_cause,
output logic [31:0] o_tval
);
`include "exception_priority.svh"
// Priority-based exception selection
always_comb begin
o_exception = 1'b0;
o_cause = '0;
o_tval = '0;
if (i_fetch_fault) begin
o_exception = 1'b1;
o_cause = PRIORITY_INSTR_ACCESS_FAULT[3:0];
o_tval = i_pc;
end else if (i_illegal_instr) begin
o_exception = 1'b1;
o_cause = PRIORITY_ILLEGAL_INSTR[3:0];
o_tval = i_instr;
end else if (i_load_fault) begin
o_exception = 1'b1;
o_cause = PRIORITY_LOAD_ACCESS_FAULT[3:0];
o_tval = i_addr;
end else if (i_store_fault) begin
o_exception = 1'b1;
o_cause = PRIORITY_STORE_ACCESS_FAULT[3:0];
o_tval = i_addr;
end
end
endmodule
Test Code¶
// Exception test (C code)
void test_illegal_instruction() {
// Illegal instruction - should trap
asm volatile(".word 0x00000000");
}
void test_load_misaligned() {
volatile int* ptr = (int*)0x80000001; // Misaligned
int val = *ptr; // Should trap
}
void test_store_access_fault() {
volatile int* ptr = (int*)0x00000000; // Invalid region
*ptr = 0xDEADBEEF; // Should trap
}
Summary¶
The exception_priority.svh file:
- Priority Definition: RISC-V exception priorities
- Exception Types: 11 distinct exception types
- Trap Handling: CSR registers (mepc, mcause, mtval)
- Precise exception: Pipeline flush and recovery
- Configurable: Customizable via parameters
This file forms the basis of the Level RISC-V core exception-handling mechanism.
Fetch Log - Technical Documentation¶
Contents¶
Overview¶
Purpose¶
The fetch_log.svh file defines log formats for fetch stage debug and trace output. I-cache accesses, branch prediction results, and pipeline stalls can be observed.
File Location¶
Activation¶
Log Format¶
Basic Log Structure¶
`ifdef LOG_FETCH
// Fetch trace output
always_ff @(posedge clk_i) begin
if (fetch_valid && !stall) begin
$display("[FETCH] PC=%08x INSTR=%08x %s @ %0t",
pc,
instruction,
is_compressed ? "C" : "I",
$time);
end
end
`endif
Sample Output¶
[FETCH] PC=80000000 INSTR=00000297 I @ 1000
[FETCH] PC=80000004 INSTR=02028293 I @ 1010
[FETCH] PC=80000008 INSTR=00010137 I @ 1020
[FETCH] PC=8000000c INSTR=f1402573 I @ 1030
[FETCH] PC=80000010 INSTR=30200073 I @ 1040
Signals¶
Monitored Signals¶
// Fetch stage signals
logic [31:0] pc; // Current program counter
logic [31:0] instruction; // Fetched instruction
logic fetch_valid; // Fetch successful
logic is_compressed; // Compressed instruction
logic stall; // Pipeline stall
logic flush; // Pipeline flush
// I-Cache signals
logic icache_hit; // Cache hit
logic icache_miss; // Cache miss
logic icache_busy; // Cache busy
// Branch prediction
logic bp_taken; // Predicted taken
logic [31:0] bp_target; // Predicted target
Log Levels¶
// Basic fetch log
`ifdef LOG_FETCH
// PC, instruction logging
`endif
// Verbose fetch log
`ifdef LOG_FETCH_VERBOSE
// Cache hit/miss
// Branch prediction details
// Stall reasons
`endif
Usage¶
Simple Fetch Log¶
`include "fetch_log.svh"
module fetch_stage
import level_param::*;
(
input logic clk_i,
// ...
);
`ifdef LOG_FETCH
always_ff @(posedge clk_i) begin
if (o_valid) begin
$display("[FETCH] PC=%08x INSTR=%08x @ %0t",
o_pc, o_instr, $time);
end
end
`endif
endmodule
Detailed Fetch Log¶
`ifdef LOG_FETCH_VERBOSE
always_ff @(posedge clk_i) begin
// Cache durumu
if (icache_req) begin
if (icache_hit) begin
$display("[FETCH] ICACHE HIT PC=%08x @ %0t", pc, $time);
end else begin
$display("[FETCH] ICACHE MISS PC=%08x @ %0t", pc, $time);
end
end
// Branch prediction
if (bp_valid) begin
$display("[FETCH] BP %s target=%08x @ %0t",
bp_taken ? "TAKEN" : "NOT_TAKEN",
bp_target, $time);
end
// Stall nedeni
if (stall) begin
$display("[FETCH] STALL reason=%s @ %0t",
stall_reason.name(), $time);
end
// Flush
if (flush) begin
$display("[FETCH] FLUSH redirect=%08x @ %0t",
redirect_pc, $time);
end
end
`endif
Debug Scenarios¶
1. I-Cache Miss Analizi¶
// Track cache miss count
`ifdef LOG_FETCH
int icache_miss_count = 0;
int icache_hit_count = 0;
always_ff @(posedge clk_i) begin
if (icache_req) begin
if (icache_hit) begin
icache_hit_count <= icache_hit_count + 1;
end else begin
icache_miss_count <= icache_miss_count + 1;
$display("[FETCH] MISS #%0d PC=%08x @ %0t",
icache_miss_count, pc, $time);
end
end
end
final begin
$display("[FETCH] Total: Hits=%0d Misses=%0d Rate=%.2f%%",
icache_hit_count, icache_miss_count,
100.0 * icache_hit_count / (icache_hit_count + icache_miss_count));
end
`endif
2. Branch Misprediction¶
`ifdef LOG_FETCH
always_ff @(posedge clk_i) begin
if (branch_resolve) begin
if (bp_mispredicted) begin
$display("[FETCH] MISPREDICT PC=%08x pred=%08x actual=%08x @ %0t",
branch_pc, bp_target, actual_target, $time);
end
end
end
`endif
3. Pipeline Stall Monitoring¶
`ifdef LOG_FETCH
int stall_cycles = 0;
always_ff @(posedge clk_i) begin
if (stall) begin
stall_cycles <= stall_cycles + 1;
if (stall_cycles > 100) begin
$warning("[FETCH] Long stall: %0d cycles @ %0t",
stall_cycles, $time);
end
end else begin
if (stall_cycles > 0) begin
$display("[FETCH] Stall ended after %0d cycles @ %0t",
stall_cycles, $time);
end
stall_cycles <= 0;
end
end
`endif
Related Files¶
| File | Description |
|---|---|
rtl/core/stage01_fetch/ |
Fetch stage modules |
rtl/core/mmu/cache.sv |
I-cache implementation |
writeback_log.svh |
Commit trace (for comparison) |
Summary¶
The fetch_log.svh file:
- PC/Instruction Log: Basic fetch monitoring
- Cache Analysis: Hit/miss statistics
- Branch Debug: Misprediction monitoring
- Stall Analysis: Pipeline stall reasons
- Conditional Compilation: Control via
ifdef
This file is used for fetch-stage debug and performance analysis.
Writeback Log - Technical Documentation¶
Contents¶
- Overview
- Spike-Compatible Commit Trace
- Log Formats
- PASS/FAIL Detection
- Konata Pipeline Trace
- CSR Trace
- Usage and Integration
Overview¶
Purpose¶
The writeback_log.svh file defines comprehensive trace and logging for the writeback stage. In particular, it provides a commit trace format comparable to the Spike simulator.
File Location¶
Key Features¶
| Feature | Description |
|---|---|
| Spike Format | core 0: PC (INSTR) rd DATA |
| PASS/FAIL | Automatic test result detection |
| Konata | Pipeline visualizer support |
| CSR Trace | CSR register changes |
Spike-Compatible Commit Trace¶
Format Definition¶
Spike commit trace format:
core 0: 0x80000000 (0x00000297) x5 0x80000000
core 0: 0x80000004 (0x02028293) x5 0x80000028
core 0: 0x80000008 (0x30529073)
Format: core <hart_id>: 0x<PC> (0x<INSTR>) [x<rd> 0x<DATA>]
Implementation¶
`ifdef LOG_COMMIT
// Spike-compatible commit trace
always_ff @(posedge clk_i) begin
if (commit_valid && !flush) begin
if (rd_we && rd_addr != 5'd0) begin
// Register write - show rd and value
$display("core 0: 0x%08x (0x%08x) x%-2d 0x%08x",
commit_pc,
commit_instr,
rd_addr,
rd_data);
end else begin
// No register write (stores, branches, etc.)
$display("core 0: 0x%08x (0x%08x)",
commit_pc,
commit_instr);
end
end
end
`endif
Spike Comparison¶
# RTL simulation
make run T=rv32ui-p-add LOG_COMMIT=1 > rtl_trace.log
# Spike simulation
spike --log-commits rv32ui-p-add > spike_trace.log
# Comparison
diff rtl_trace.log spike_trace.log
Log Formats¶
Basic Commit Log¶
`ifdef LOG_COMMIT
always_ff @(posedge clk_i) begin
if (commit_valid) begin
// Standard format
$display("core 0: 0x%08x (0x%08x) x%-2d 0x%08x",
pc, instr, rd, data);
end
end
`endif
Extended Log¶
`ifdef LOG_COMMIT_VERBOSE
always_ff @(posedge clk_i) begin
if (commit_valid) begin
// Instruction disassembly
$display("[WB] PC=%08x %s rd=x%0d val=%08x",
pc,
disasm(instr), // Disassembly function
rd,
data);
// Memory operations
if (is_load) begin
$display("[WB] LOAD addr=%08x data=%08x",
mem_addr, load_data);
end
if (is_store) begin
$display("[WB] STORE addr=%08x data=%08x",
mem_addr, store_data);
end
end
end
`endif
Memory Trace¶
`ifdef LOG_MEM
always_ff @(posedge clk_i) begin
// Load commit
if (load_commit) begin
$display("MEM: LOAD addr=%08x data=%08x size=%0d",
mem_addr, load_data, mem_size);
end
// Store commit
if (store_commit) begin
$display("MEM: STORE addr=%08x data=%08x size=%0d",
mem_addr, store_data, mem_size);
end
end
`endif
PASS/FAIL Detection¶
RISC-V Test Signature¶
RISC-V tests report results by writing to tohost:
// Test result detection
localparam TOHOST_ADDR = 32'h8000_1000; // Configurable
`ifdef LOG_COMMIT
always_ff @(posedge clk_i) begin
// tohost write detection
if (store_commit && mem_addr == TOHOST_ADDR) begin
if (store_data == 32'h0000_0001) begin
$display("*** PASS ***");
$display("Test completed successfully @ %0t", $time);
$finish(0);
end else if (store_data != 32'h0) begin
$display("*** FAIL ***");
$display("Test failed with code: %0d @ %0t",
store_data >> 1, $time);
$finish(1);
end
end
end
`endif
Benchmark Result Detection¶
`ifdef SIM_UART_MONITOR
// UART output monitoring
string uart_buffer;
always_ff @(posedge clk_i) begin
if (uart_tx_valid) begin
uart_buffer = {uart_buffer, string'(uart_tx_data)};
// Check for PASS/FAIL patterns
if (uart_buffer.find("PASS") != -1) begin
$display("*** PASS detected in UART output ***");
$finish(0);
end
if (uart_buffer.find("FAIL") != -1) begin
$display("*** FAIL detected in UART output ***");
$finish(1);
end
// CoreMark result pattern
if (uart_buffer.find("CoreMark 1.0 :") != -1) begin
$display("*** CoreMark completed ***");
end
end
end
`endif
Write to TOHOST Detection¶
// Detailed tohost analysis
always_ff @(posedge clk_i) begin
if (store_commit && mem_addr == TOHOST_ADDR) begin
case (store_data)
32'h0000_0001: begin
$display("[TEST] PASS @ cycle %0d", cycle_count);
end
32'h0000_0000: begin
// Ignore zero write
end
default: begin
// Fail with test number
$display("[TEST] FAIL test_num=%0d @ cycle %0d",
store_data >> 1, cycle_count);
end
endcase
end
end
Konata Pipeline Trace¶
Konata Format¶
Special trace format for the Konata pipeline visualizer:
`ifdef KONATA_TRACER
integer konata_file;
initial begin
konata_file = $fopen("pipeline.log", "w");
$fwrite(konata_file, "Kanata\t0004\n");
end
always_ff @(posedge clk_i) begin
// Instruction fetch
if (if_valid) begin
$fwrite(konata_file, "I\t%0d\t%0d\t0\n",
instr_id, cycle_count);
end
// Stage transitions
if (id_valid) begin
$fwrite(konata_file, "S\t%0d\t%0d\t%s\n",
instr_id, cycle_count, "D");
end
if (ex_valid) begin
$fwrite(konata_file, "S\t%0d\t%0d\t%s\n",
instr_id, cycle_count, "E");
end
if (mem_valid) begin
$fwrite(konata_file, "S\t%0d\t%0d\t%s\n",
instr_id, cycle_count, "M");
end
// Instruction commit
if (commit_valid) begin
$fwrite(konata_file, "R\t%0d\t%0d\t0\n",
instr_id, cycle_count);
end
// Instruction flush
if (flush_valid) begin
$fwrite(konata_file, "R\t%0d\t%0d\t1\n",
instr_id, cycle_count);
end
end
final begin
$fclose(konata_file);
end
`endif
Konata Commands¶
| Command | Format | Description |
|---|---|---|
| I | I id cycle 0 |
Instruction issue |
| S | S id cycle stage |
Stage transition |
| R | R id cycle flush |
Retire (0=commit, 1=flush) |
| L | L id cycle text |
Label (optional) |
CSR Trace¶
CSR Write Logging¶
`ifdef LOG_CSR
always_ff @(posedge clk_i) begin
if (csr_we) begin
$display("[CSR] WRITE %s (0x%03x) = 0x%08x @ PC=%08x",
csr_name(csr_addr),
csr_addr,
csr_wdata,
commit_pc);
end
end
function automatic string csr_name(input logic [11:0] addr);
case (addr)
12'h300: return "mstatus";
12'h301: return "misa";
12'h304: return "mie";
12'h305: return "mtvec";
12'h340: return "mscratch";
12'h341: return "mepc";
12'h342: return "mcause";
12'h343: return "mtval";
12'h344: return "mip";
12'hF11: return "mvendorid";
12'hF12: return "marchid";
12'hF13: return "mimpid";
12'hF14: return "mhartid";
12'hB00: return "mcycle";
12'hB02: return "minstret";
default: return $sformatf("csr_%03x", addr);
endcase
endfunction
`endif
Exception/Interrupt Logging¶
`ifdef LOG_EXCEPTION
always_ff @(posedge clk_i) begin
if (exception_valid) begin
$display("[TRAP] EXCEPTION cause=%s (%0d) PC=%08x tval=%08x",
exception_name(mcause),
mcause,
mepc,
mtval);
end
if (interrupt_valid) begin
$display("[TRAP] INTERRUPT cause=%0d PC=%08x",
mcause[30:0],
mepc);
end
if (mret_valid) begin
$display("[TRAP] MRET return to PC=%08x",
mepc);
end
end
`endif
Usage and Integration¶
Makefile Integration¶
# Log kontrolleri
LOG_COMMIT ?= 0
LOG_CSR ?= 0
LOG_MEM ?= 0
KONATA_TRACER ?= 0
# Verilator defines
ifeq ($(LOG_COMMIT),1)
VFLAGS += +define+LOG_COMMIT
endif
ifeq ($(KONATA_TRACER),1)
VFLAGS += +define+KONATA_TRACER +define+COMMIT_TRACER
endif
Usage Examples¶
# ISA test with commit trace
make run T=rv32ui-p-add LOG_COMMIT=1
# Pipeline visualization
make run T=rv32ui-p-add KONATA_TRACER=1
# Full debug mode
make run T=test LOG_COMMIT=1 LOG_CSR=1 LOG_MEM=1
# Benchmark with UART monitoring
make run_coremark SIM_UART_MONITOR=1 LOG_COMMIT=1
Log Files¶
| Log | File | Content |
|---|---|---|
| Commit | stdout/commit.log | Spike-compatible trace |
| Pipeline | pipeline.log | Konata format |
| UART | uart.log | UART output |
Performance Impact¶
Log Overhead¶
| Mode | Overhead | Use |
|---|---|---|
| No logging | 0% | Production |
| LOG_COMMIT | ~5% | Debug |
| KONATA_TRACER | ~10% | Pipeline analysis |
| All logs | ~20% | Full debug |
SIM_FAST Mode¶
`ifdef SIM_FAST
// All logs disabled
// Maximum simulation speed
`else
// Normal log modes enabled
`endif
Summary¶
The writeback_log.svh file:
- Spike Format:
core 0: PC (INSTR) rd DATA - PASS/FAIL: tohost and UART monitoring
- Konata: Pipeline visualizer support
- CSR Trace: Register changes
- Configurable: Controlled via Makefile
This file forms the basis of the Level RISC-V core verification and debug infrastructure.