Ibex Documentation: Release 0.1.dev50+g36ce999.d20191026
Ibex Documentation: Release 0.1.dev50+g36ce999.d20191026
Release 0.1.dev50+g36ce999.d20191026
lowRISC
1 Introduction 1
1.1 Standards Compliance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 ASIC Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 FPGA Synthesis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4 Contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5 History . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.6 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
3 Core Integration 7
3.1 Instantiation Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3.2 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
3.3 Interfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
4 Pipeline Details 11
4.1 Multi- and Single-Cycle Instructions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
5 Instruction Fetch 13
5.1 Instruction-Side Memory Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
5.2 Misaligned Accesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
5.3 Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
7 Load-Store Unit 19
7.1 Data-Side Memory Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.2 Misaligned Accesses . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
7.3 Protocol . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
i
8 Register File 23
8.1 Flip-Flop-Based Register File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
8.2 Latch-Based Register File . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 23
10 Performance Counters 31
10.1 Event Selector . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
10.2 Controlling the counters from software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
10.3 Parametrization at synthesis time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
13 Debug Support 37
13.1 Interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
13.2 Parameters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
14 Tracer 39
14.1 Output file . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
14.2 Trace output format . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
16 Verification 43
16.1 Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
16.2 Testbench Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
16.3 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
17 Examples 47
17.1 FPGA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
18 Licensing 49
ii
CHAPTER
ONE
INTRODUCTION
Ibex is a 2-stage in-order 32b RISC-V processor core. Ibex has been designed to be small and efficient. Via two
parameters, the core is configurable to support four ISA configurations. Figure 1.1 shows a block diagram of the core.
Most content of the RISC-V privileged specification is optional. Ibex currently supports the following features accord-
ing to the RISC-V Privileged Specification, version 1.11.
• M-Mode and U-Mode
• All CSRs listed in Control and Status Registers
• Performance counters as described in Performance Counters
1
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
ASIC synthesis is supported for Ibex. The whole design is completely synchronous and uses positive-edge triggered
flip-flops, except for the register file, which can be implemented either with latches or with flip-flops. See Register
File for more details. The core occupies an area of roughly 18.9 kGE when using the latch-based register file and
implementing the RV32IMC ISA, or 11.6 kGE when implementing the RV32EC ISA.
FPGA synthesis is supported for Ibex when the flip-flop based register file is used. Since latches are not well supported
on FPGAs, it is crucial to select the flip-flop based register file.
1.4 Contents
• Getting Started with Ibex discusses the requirements and initial steps to start using Ibex.
• Core Integration provides the instantiation template and gives descriptions of the design parameters as well as
the input and output ports.
• Ibex Pipeline described the overal pipeline structure.
• Instruction Decode and Execute describes how the Instruction Decode and Execute stage works.
• The instruction and data interfaces of Ibex are explained in Instruction Fetch and Load-Store Unit, respectively.
• The two register-file flavors are described in Register File.
• The control and status registers are explained in Control and Status Registers.
• Performance Counters gives an overview of the performance monitors and event counters available in Ibex.
• Exceptions and Interrupts deals with the infrastructure for handling exceptions and interrupts,
• Physical Memory Protection (PMP) gives a brief overview of PMP support.
• Debug Support gives a brief overview on the debug infrastructure.
• Tracer gives a brief overview of the tracer module.
• For information regarding formal verification support, check out RISC-V Formal Interface.
• Examples gives an overview of how Ibex can be used.
1.5 History
Ibex development started in 2015 under the name “Zero-riscy” as part of the PULP platform for energy-efficient
computing. Much of the code was developed by simplifying the RV32 CPU core “RI5CY” to demonstrate how small
a RISC-V CPU core could actually be [1]. To make it even smaller, support for the “E” extension was added under
the code name “Micro-riscy”. In the PULP ecosystem, the core is used as the control core for PULP, PULPino and
PULPissimo.
In December 2018 lowRISC took over the development of Zero-riscy and renamed it to Ibex.
2 Chapter 1. Introduction
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
1.6 References
1. Schiavone, Pasquale Davide, et al. “Slow and steady wins the race? A comparison of ultra-low-power RISC-
V cores for Internet-of-Things applications.” 27th International Symposium on Power and Timing Modeling,
Optimization and Simulation (PATMOS 2017)
1.6. References 3
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
4 Chapter 1. Introduction
CHAPTER
TWO
This page discusses initial steps and requirements to start using Ibex in your design.
Ibex comes with two different register file implementations. Depending on the target technology, either the implemen-
tation in ibex_register_file_ff.sv or the one in ibex_register_file_latch.sv should be selected.
For more information about the two register file implementations and their trade-offs, check out Register File.
Ibex requires clock gating cells. This cells are usually specific to the selected target technology and thus not provided as
part of the RTL design. It is assumed that the clock gating cell is wrapped in a module called prim_clock_gating
that has the following ports:
• clk_i: Clock Input
• en_i: Clock Enable Input
• test_en_i: Test Enable Input (activates the clock even though en_i is not set)
• clk_o: Gated Clock Output
Inside Ibex, clock gating cells are used both in ibex_core.sv and ibex_register_file_latch.sv. For
more information on the expected behavior of the clock gating cell when using the latch-based register file check out
Register File.
5
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
THREE
CORE INTEGRATION
The main module is named ibex_core and can be found in ibex_core.sv. Below, the instantiation template is
given and the parameters and interfaces are described.
ibex_core #(
.PMPEnable ( 0 ),
.PMPGranularity ( 0 ),
.PMPNumRegions ( 4 ),
.MHPMCounterNum ( 0 ),
.MHPMCounterWidth ( 40 ),
.RV32E ( 0 ),
.RV32M ( 1 ),
.MultiplierImplementation ( "fast" ),
.DmHaltAddr ( 32'h1A110800 ),
.DmExceptionAddr ( 32'h1A110808 )
) u_core (
// Clock and reset
.clk_i (),
.rst_ni (),
.test_en_i (),
// Configuration
.hart_id_i (),
.boot_addr_i (),
7
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
// Interrupt inputs
.irq_software_i (),
.irq_timer_i (),
.irq_external_i (),
.irq_fast_i (),
.irq_nm_i (),
// Debug interface
.debug_req_i (),
3.2 Parameters
3.3 Interfaces
3.3. Interfaces 9
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
FOUR
PIPELINE DETAILS
In the table below when an instruction stalls for X cycles X + 1 cycles pass before a new instruction enters the ID/EX
stage. Some instructions stall for a variable time, this is indicated as a range e.g. 1 - N means the instruction stalls a
minimum of 1 cycle with an indeterminate maximum cycles. Read the description for more information.
11
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
FIVE
INSTRUCTION FETCH
rtl/ibex_if_stage.sv.
The Instruction Fetch (IF) stage of the core is able to supply one instruction to the Instruction-Decode (ID) stage per
cycle if the instruction cache or the instruction memory is able to serve one instruction per cycle.
Instructions are fetched into a prefetch buffer (rtl/ibex_prefetch_buffer.sv) for optimal performance and
timing closure reasons. This buffer simply fetches instructions linearly until it is full. The instructions themselves are
stored along with the Program Counter (PC) they came from in the fetch FIFO (rtl/ibex_fetch_fifo.sv). The
fetch FIFO has a feedthrough path so when empty a new instruction entering the FIFO is immediately made available
on the FIFO output. A localparam DEPTH gives a configurable depth which is set to 3 by default.
The top-level of the instruction fetch controls the prefetch buffer (in particular flushing it on branches/jumps/exception
and beginning prefetching from the appropriate new PC) and supplies new instructions to the ID/EX stage along with
their PC. Compressed instructions are expanded by the IF stage so the decoder can always deal with uncompressed
instructions (the ID stage still receives the compressed instruction for placing into mtval on an illegal instruction
exception).
The following table describes the signals that are used to fetch instructions. This interface is a simplified version of
the interface used on the data interface as described in Load-Store Unit. The main difference is that the instruction
interface does not allow for write transactions and thus needs less signals.
13
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
Externally, the IF interface performs word-aligned instruction fetches only. Misaligned instruction fetches are handled
by performing two separate word-aligned instruction fetches. Internally, the core can deal with both word- and half-
word-aligned instruction addresses to support compressed instructions. The LSB of the instruction address is ignored
internally.
5.3 Protocol
The protocol used to communicate with the instruction cache or the instruction memory is very similar to the protocol
used by the LSU on the data interface of Ibex. See the description of the LSU in LSU Protocol for details about this
protocol.
SIX
The Instruction Decode and Execute stage takes instruction data from the instruction fetch stage (which has been
converted to the uncompressed representation in the compressed instruction case). The instructions are decoded and
executed all within one cycle including the register read and write. The stage is made up of multiple sub-blocks which
are described below.
6.2 Controller
6.3 Decoder
15
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
Divider Both the fast and slow blocks use the same long division algorithm, it takes 37 cycles to compute (though
only requires 2 cycles when there is a divide by 0) and proceeds as follows:
• Cycle 0: Check for divide by 0
• Cycle 1: Compute absolute value of operand A (or return result on divide by 0)
• Cycle 2: Compute absolute value of operand B
• Cycles 4 - 36: Perform long division as described here: https://en.wikipedia.org/wiki/Division_algorithm#
Integer_division_(unsigned)_with_remainder.
SEVEN
LOAD-STORE UNIT
rtl/ibex_load_store_unit.sv
The Load-Store Unit (LSU) of the core takes care of accessing the data memory. Loads and stores of words (32 bit),
half words (16 bit) and bytes (8 bit) are supported.
Any load or store will stall the ID/EX stage for at least a cycle to await the response (whether that is awaiting load data
or a response indicating whether an error has been seen for a store).
The LSU is able to handle misaligned memory accesses, meaning accesses that are not aligned on natural word
boundaries. However, it does so by performing two separate word-aligned accesses. This means that at least two
cycles are needed for misaligned loads and stores.
19
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
If an error response is received for the first transaction, the second transaction will still be issued. The second trans-
action will then follow the normal bus protocol, but its response/data will be ignored. If a new load/store request is
received while waiting for an abandoned second part to complete, it will not be serviced until the state machine returns
to IDLE.
7.3 Protocol
The protocol that is used by the LSU to communicate with a memory works as follows:
1. The LSU provides a valid address in data_addr_o and sets data_req_o high. In the case of a store,
the LSU also sets data_we_o high and configures data_be_o and data_wdata_o. The memory then
answers with a data_gnt_i set high as soon as it is ready to serve the request. This may happen in the same
cycle as the request was sent or any number of cycles later.
2. After receiving a grant, the address may be changed in the next cycle by the LSU. In addition, the
data_wdata_o, data_we_o and data_be_o signals may be changed as it is assumed that the memory
has already processed and stored that information.
3. The memory answers with a data_rvalid_i set high for exactly one cycle to signal the response from the
bus or the memory using data_err_i and data_rdata_i (during the very same cycle). This may happen
one or more cycles after the grant has been received. If data_err_i is low, the request could successfully be
handled at the destination and in the case of a load, data_rdata_i contains valid data. If data_err_i is
high, an error occurred in the memory system and the core will raise an exception.
4. When multiple granted requests are outstanding, it is assumed that the memory requests will be kept in-order
and one data_rvalid_i will be signalled for each of them, in the order they were issued.
Figure 7.1, Figure 7.2 and Figure 7.3 show example-timing diagrams of the protocol.
clk
data_req_o
data_addr_o Address
data_we_o WE
data_be_o BE
data_wdata_o WData
data_gnt_i
data_rvalid_i
data_err_i Err
data_rdata_i RData
clk
data_req_o
data_gnt_i
data_rvalid_i
clk
data_req_o
data_addr_o Address
data_we_o WE
data_be_o BE
data_wdata_o WData
data_gnt_i
data_rvalid_i
data_err_i Err
data_rdata_i RData
7.3. Protocol 21
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
EIGHT
REGISTER FILE
The flip-flop-based register file uses regular, positive-edge-triggered flip-flops to implement the registers.
This makes it the first choice for FPGA synthesis or when simulating the design using Verilator.
To select the flip-flop-based register file, make sure to use the source file ibex_register_file_ff.sv in your
project.
The latch-based register file uses level-sensitive latches to implement the registers.
This allows for significant area savings compared to an implementation using regular flip-flops and thus makes the
latch-based register file the first choice for ASIC implementations. Simulation of the latch-based register file is
possible using commercial tools.
The latch-based register file can also be used for FPGA synthesis, but this is not recommended as FPGAs usually do
not well support latches.
To select the latch-based register file, make sure to use the source file ibex_register_file_latch.sv in your
project. In addition, a technology-specific clock gating cell must be provided to keep the clock inactive when the
latches are not written. This cell must be wrapped in a module called prim_clock_gating. For more information
regarding the clock gating cell, checkout Getting Started with Ibex.
Note: The latch-based register file requires the gated clock to be enabled in the cycle after the write enable we_a_i
signal was set high. This can be achieved by latching we_a_i in the clock gating cell during the low phase of clk_i.
23
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
The resulting behavior of the latch-based register file is visualized in Figure 8.1. The input data wdata_a_i is
sampled into a flip-flop-based register wdata_a_q using clk_int. The actual latch-based registers mem[1] and
mem[2] are transparent during high phases of mem_clk[1] and mem_clk[2], respectively. Their content is
sampled from wdata_a_q on falling edges of these clocks.
clk_i
we_a_i
waddr_a_i 1 2
clk_int
mem_clk[1]
mem[1] Data1
mem_clk[2]
mem[2] Data2
NINE
Ibex implements all the Control and Status Registers (CSRs) listed in the following table according to the RISC-V
Privileged Specification, version 1.11.
25
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
See the Performance Counters documentation for a description of the counter registers.
When an exception is encountered, mstatus.MPIE will be set to mstatus.MIE, and mstatus.MPP will be set
to the current privilege mode. When the MRET instruction is executed, the value of MPIE will be stored back to
mstatus.MIE, and the privilege mode will be restored from mstatus.MPP.
If you want to enable interrupt handling in your exception handler, set mstatus.MIE to 1’b1 inside your handler
code.
Only Machine Mode and User Mode are supported. Any write to mstatus.MPP of an unsupported value will be
interpreted as Machine Mode.
Bit# Interrupt
30:16 Machine Fast Interrupt Enables: Set bit x+16 to enable fast interrupt irq_fast_i[x].
11 Machine External Interrupt Enable (MEIE): If set, irq_external_i is enabled.
7 Machine Timer Interrupt Enable (MTIE): If set, irq_timer_i is enabled.
3 Machine Software Interrupt Enable (MSIE): if set, irq_software_i is enabled.
Bit# Interrupt
31:2 BASE: The trap-vector base address, always aligned to 256 bytes, i.e., mtvec[7:2] is always set to 6’b0.
1:0 MODE: Always set to 2’b01 to indicate vectored interrupt handling (read-only).
When an exception is encountered, the corresponding exception code is stored in this register.
Bit# Interrupt
30:16 Machine Fast Interrupts Pending: If bit x+16 is set, fast interrupt irq_fast_i[x] is pending.
11 Machine External Interrupt Pending (MEIP): If set, irq_external_i is pending.
7 Machine Timer Interrupt Pending (MTIP): If set, irq_timer_i is pending.
3 Machine Software Interrupt Pending (MSIP): if set, irq_software_i is pending.
Bit# Definition
7 Lock
6:5 Reserved (Read as zero)
4:3 Mode
2 Execute permission
1 Write permission
0 Read permission
Details of these configuration bits can be found in the RISC-V Privileged Specification, version 1.11 (see Physical
Memory Protection CSRs, Section 3.6.1).
Note that the combination of Write permission = 1, Read permission = 0 is reserved, and will be treated by the core as
Read/Write permission = 0.
31:0
address[33:2]
TEN
PERFORMANCE COUNTERS
Ibex implements performance counters according to the RISC-V Privileged Specification, version 1.11 (see Hardware
Performance Monitor, Section 3.1.11). The performance counters are placed inside the Control and Status Registers
(CSRs) and can be accessed with the CSRRW(I) and CSRRS/C(I) instructions.
Ibex implements the clock cycle counter mcycle(h), the retired instruction counter minstret(h), as well as
the 29 event counters mhpmcounter3(h) - mhpmcounter31(h) and the corresponding event selector CSRs
mhpmevent3 - mhpmevent31, and the mcountinhibit CSR to individually enable/disable the counters.
mcycle(h) and minstret(h) are always available and 64 bit wide. The mhpmcounter performance coun-
ters are optional (unavailable by default) and parametrizable in width.
The following events can be monitored using the performance counters of Ibex.
The event selector CSRs mhpmevent3 - mhpmevent31 define which of these events are counted by the event
counters mhpmcounter3(h) - mhpmcounter31(h). If a specific bit in an event selector CSR is set to 1, this
means that events with this ID are being counted by the counter associated with that selector CSR. If an event selector
CSR is 0, this means that the corresponding counter is not counting any event.
By default, all available counters are enabled after reset. They can be individually enabled/disabled by overwriting the
corresponding bit in the mcountinhibit CSR at address 0x320 as described in the RISC-V Privileged Specifica-
31
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
tion, version 1.11 (see Machine Counter-Inhibit CSR, Section 3.1.13). In particular, to enable/disable mcycle(h),
bit 0 must be written. For minstret(h), it is bit 2. For event counter mhpmcounterX(h), it is bit X.
The lower 32 bits of all counters can be accessed through the base register, whereas the upper 32 bits are accessed
through the h-register. Reads to all these registers are non-destructive.
The mcycle(h) and minstret(h) counters are always available and 64 bit wide.
The event counters mhpmcounter3(h) - mhpmcounter31(h) are parametrizable. Their width can be
parametrized between 1 and 64 bit through the WidthMHPMCounters parameter, which defaults to 40 bit wide
counters.
The number of available event counters mhpmcounterX(h) can be controlled via the NumMHPMCounters pa-
rameter. By default (NumMHPMCounters set to 0), no counters are available to software. Set NumMHPMCounters
to a value between 1 and 8 to make the counters mhpmcounter3(h) - mhpmcounter10(h) available as listed
below. Setting NumMHPMCounters to values larger than 8 does not result in any more performance counters.
Unavailable counters always read 0.
The association of events with the mphmcounter registers is hardwired as listed in the following table.
Similarly, the event selector CSRs are hardwired as follows. The remaining event selector CSRs are tied to 0, i.e., no
events are counted by the corresponding counters.
ELEVEN
Ibex implements trap handling for interrupts and exceptions according to the RISC-V Privileged Specification, version
1.11.
All exceptions cause the core to jump to the base address of the vector table in the mtvec CSR. Interrupts are handled
in vectored mode, i.e., the core jumps to the base address plus four times the interrupt ID.
The base address of the vector table is initialized to the boot address (must be aligned to 256 bytes, i.e., its least
significant byte must be 0x00) when the core is booting. The base address can be changed after bootup by writing to
the mtvec CSR. For more information, see the Control and Status Registers documentation.
The core starts fetching at the address made by concatenating the most significant 3 bytes of the boot address and the
reset value (0x80) as the least significant byte. It is assumed that the boot address is supplied via a register to avoid
long paths to the instruction fetch unit.
Ibex supports operation in Machine Mode (M-Mode) and User Mode (U-Mode). The core resets into M-Mode and
will jump to M-Mode on any interrupt or exception. On execution of an MRET instruction, the core will return to the
Privilege Mode stored in mstatus.MPP.
11.2 Interrupts
All interrupts except for the non-maskable interrupt (NMI) are controlled via the mstatus, mie and mip CSRs.
After reset, all interrupts are disabled. To enable interrupts, both the global interrupt enable (MIE) bit in the mstatus
CSR and the corresponding individual interrupt enable bit in the mie CSR need to be set. For more information, see
the Control and Status Registers documentation.
If multiple interrupts are pending, the highest priority is given to the interrupt with the highest ID.
33
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
The NMI is enabled independent of the values in the mstatus and mie CSRs, and it is not visible through the mip
CSR. It has interrupt ID 31, i.e., it has the highest priority of all interrupts and the core jumps to the trap-handler base
address (in mtvec) plus 0x7C to handle the NMI.
All interrupt lines are level-sensitive. It is assumed that the interrupt handler signals completion of the handling routine
to the interrupt source, e.g., through a memory-mapped register, which then deasserts the corresponding interrupt line.
In debug mode, all interrupts including the NMI are ignored independent of mstatus.MIE and the content of the
mie CSR.
To support recovering from an NMI happening during a trap handling routine, Ibex features additional CSRs for back-
ing up mstatus.MPP, mstatus.MPIE, mepc and mcause. These CSRs are not accessible by software running on
the core.
These CSRs are nonstandard. For more information, see the corresponding proposal.
11.4 Exceptions
The illegal instruction exception, instruction access fault, LSU error exceptions and ECALL instruction exceptions
cannot be disabled and are always active.
11.5 Handling
Ibex does support nested interrupt/exception handling. Exceptions inside interrupt/exception handlers cause another
exception. However, exceptions during the critical part of your exception handlers, i.e. before having saved the
mepc and mstatus, will cause those CSRs to be overwritten. Interrupts during interrupt/exception handlers are thus
disabled by default, but can be explicitly enabled if desired.
When entering an interrupt/exception handler, the core sets mepc to the current program counter and saves
mstatus.MIE to mstatus.MPIE. Upon executing an MRET instruction, the core jumps to the program counter
saved in the mepc CSR and restores mstatus.MPIE to mstatus.MIE.
TWELVE
The Physical Memory Protection (PMP) unit implements region-based memory access checking in-accordance with
the RISC-V Privileged Specification, version 1.11. The following configuration parameters are available to control
PMP checking:
When PMPEnable is zero, the PMP module is not instantiated and all PMP registers read as zero (regardless of the
value of PMPNumRegions)
Addresses from the instruction fetch unit and load-store unit are passed to the PMP module for checking, and the output
of the PMP check is used to gate the external request. To maintain consistency with external errors, the instruction
fetch unit and load-store unit progress with their request as if it was granted externally. The PMP error is registered
and consumed by the core when the data would have been consumed.
The PMP granularity parameter is used to reduce the size of the address matching comparators by increasing the
minimum region size. When the granularity is greater than zero, NA4 mode is not available and will be treated as OFF
mode.
35
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
THIRTEEN
DEBUG SUPPORT
Ibex offers support for execution-based debug according to the RISC-V Debug Specification, version 0.13.
13.1 Interface
debug_req_i is the “debug interrupt”, issued by the debug module when the core should enter debug mode.
13.2 Parameters
Parameter Description
DmHaltAddr Address to jump to when entering debug mode
DmExceptionAddr Address to jump to when an exception occurs while in debug mode
37
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
FOURTEEN
TRACER
The module ibex_tracer can be used to create a log of the executed instructions. It is used by
ibex_core_tracing which forwards the RVFI signals to the tracer (see also RISC-V Formal Interface).
All traced instructions are written to a log file. By default, the log file is named trace_core_<HARTID>.log,
with <HARTID> being the 8 digit hart ID of the core being traced.
The file name base, defaulting to trace_core can be set using the ibex_tracer_file_base plusarg passed
to the simulation. For example, +ibex_tracer_file_base=ibex_my_trace will produce log files named
ibex_my_trace_<HARTID>.log. The exact syntax of passing plusargs to a simulation depends on the simulator.
39
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
FIFTEEN
Ibex supports the RISC-V Formal Interface (RVFI). This interface basically decodes the current instruction and pro-
vides additional insight into the core state thereby enabling formal verification. Examples of such information include
opcode, source and destination registers, program counter, as well as address and data for memory operations.
The signals provided by RVFI can be used to formally verify compliance of Ibex with the RISC-V specification.
Currently, the implementation is restricted to support the “I” and “C” extensions, and Ibex is not yet formally verified.
It predecessor “Zero-riscy” had been tested, but this required changes to the core as well as to the tool used in the
process (yosys). The formal verification of the Ibex core is work in progress.
41
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
SIXTEEN
VERIFICATION
16.1 Overview
This is a SV/UVM testbench for verification of the Ibex core. At a high level, this testbench uses the open source
RISCV-DV random instruction generator to generate compiled instruction binaries, loads them into a simple memory
model, stimulates the Ibex core to run this program in memory, and then compares the core trace log against a golden
model ISS trace log to check for correctness of execution.
As previously mentioned, this testbench has been constructed based on its usage of the RISCV-DV random instruction
generator developed by Google. A block diagram of the testbench is below.
The code can be found in the dv/uvm/common/ibex_mem_intf_agent directory. Two of these agents are instantiated
within the testbench, one for the instruction fetch interface, and the second for the LSU interface. These agents run
slave sequences that wait for memory requests from the core, and then grant the requests for instructions or for data.
The code can be found in the dv/uvm/common/irq_agent directory. This agent is used to drive stimulus onto the Ibex
core’s interrupt pins randomly during test execution.
The code can be found in the dv/uvm/common/mem_model directory. The testbench instantiates a single instance of
this memory model that it loads the compiled assembly test program into at the beginning of each test. This acts as a
unified instruction/data memory that serves all requests from both of the memory interface agents.
43
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
The code can be found in the dv/uvm/tests directory. The tests here are the main sources of external stimulus generation
and checking for this testbench, as the memory interface slave sequences simply serve the core’s memory requests.
The tests here are all extended from core_ibex_base_test, and coordinate the entire flow for a single test, from
loading the compiled assembly binary program into the testbench memory model, to checking the Ibex core status
during the test and dealing with test timeouts. The sequences here are used to drive interrupt and debug stimulus into
the core.
16.2.5 Testplan
The goal of this bench is to fully verify the Ibex core with 100% coverage. This includes testing all RV32IMC
instructions, privileged spec compliance, exception and interrupt testing, debug mode operation etc. The complete test
list can be found in the file dv/uvm/riscv_dv_extension/testlist.yaml.
Please note that verification is still a work in progress.
Correctness checking is performed by the last stage in this flow, where the Ibex core’s trace log is compared against a
golden model ISS trace log and checked for any inconsistent instruction executions.
The flow is controlled by the Makefile found at dv/uvm/Makefile, here is the list of frequently used commands:
# Verbose logging
make ... VERBOSE=1
SEVENTEEN
EXAMPLES
17.1 FPGA
A minimal example for the Arty A7 FPGA Development board is provided. In this example Ibex is directly linked
to a SRAM memory instance. Four LEDs from the board are connected to the data bus and are updated each time
when a word is written. The memory is separated into a instruction and data section. The instructions memory is
initialized at synthesis time by reading the output from the software build. The software writes to the data section the
complementary lower for bits of a word every second resulting in blinking LEDs.
Find the description of how to build and program the Arty board in examples/fpga/artya7-100/README.md.
47
Ibex Documentation, Release 0.1.dev50+g36ce999.d20191026
EIGHTEEN
LICENSING
49