UVM环境介绍
HEAD commitID: 1f968ef
//
// //
// Author: Francesco Minervini - [email protected] //
// //
// Additional contributions by: Davide Schiavone - [email protected] //
// Design Name: Interrupt generator //
// Project Name: RI5CY, Zeroriscy //
// Language: SystemVerilog //
// //
// Description: Send interrupt request to core choosing one option between: //
// - Random; //
// - Standard; //
// - PC value-triggering //
// //
//
//import riscv_defines::*;
import perturbation_defines::*;
module riscv_random_interrupt_generator
`ifndef VERILATOR
import uvm_pkg::*;
`include "uvm_macros.svh"
`endif
(
input logic rst_ni,
input logic clk_i,
input logic irq_i,
input logic [4:0] irq_id_i,
input logic irq_ack_i,
output logic irq_o,
output logic [4:0] irq_id_o,
output logic irq_ack_o,
input logic [31:0] irq_mode_i,
input logic [31:0] irq_min_cycles_i,
input logic [31:0] irq_max_cycles_i,
input logic [31:0] irq_min_id_i,
input logic [31:0] irq_max_id_i,
output logic [31:0] irq_act_id_o,
output logic irq_id_we_o,
input logic [31:0] irq_pc_id_i,
input logic [31:0] irq_pc_trig_i
);
`ifndef VERILATOR
class rand_irq_cycles;
rand int n;
endclass : rand_irq_cycles
class rand_irq_id;
rand int n;
endclass : rand_irq_id
logic [31:0] irq_mode_q;
logic irq_random;
logic [4:0] irq_id_random;
logic irq_ack_random;
logic irq_monitor;
logic [4:0] irq_id_monitor;
logic irq_ack_monitor;
assign irq_ack_o = irq_ack_i;
always_ff @(posedge clk_i or negedge rst_ni)
begin
if(~rst_ni) begin
irq_mode_q <= 0;
end else begin
irq_mode_q <= irq_mode_i;
end
end
always_comb
begin
unique case (irq_mode_q)
RANDOM:
begin
irq_o = irq_random;
irq_id_o = irq_id_random;
end
PC_TRIG:
begin
irq_o = irq_monitor;
irq_id_o = irq_id_monitor;
end
default:
begin
irq_o = irq_i;
irq_id_o = irq_id_i;
end
endcase
end
//Random Process
initial
begin
automatic rand_irq_cycles wait_cycles = new();
automatic rand_irq_id value = new();
int rs,i, min_irq_cycles, max_irq_cycles, min_irq_id, max_irq_id;
irq_random = 1'b0;
irq_id_random = '0;
while(1) begin
irq_random = 1'b0;
irq_id_random = '0;
@(posedge clk_i);
wait(irq_mode_q == RANDOM);
min_irq_id = irq_min_id_i;
max_irq_id = irq_max_id_i;
min_irq_cycles = irq_min_cycles_i;
max_irq_cycles = irq_max_cycles_i;
rs = 0; // "randomize success"
rs = value.randomize() with{
n >= min_irq_id;
n <= max_irq_id;
};
if (!rs) `uvm_error("RISCV_RANDOM_INTERRUPT_GENERATOR", "Randomization failure on value.randomize()")
rs = wait_cycles.randomize() with{
n >= min_irq_cycles;
n <= max_irq_cycles;
};
if (!rs) `uvm_error("RISCV_RANDOM_INTERRUPT_GENERATOR", "Randomization failure on wait_cycles.randomize()")
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
end
irq_id_random = value.n;
irq_random = 1'b1;
irq_act_id_o = value.n;
@(posedge clk_i);
//we don't care about the ack in this mode
for(i=0; i<max_irq_cycles; i++) begin
@(posedge clk_i);
end
end // while(1)
end
//Monitor Process
initial
begin
irq_monitor = 1'b0;
irq_id_monitor = '0;
wait(irq_mode_q == PC_TRIG);
wait(irq_pc_id_i == irq_pc_trig_i);
irq_monitor = 1'b1;
irq_id_monitor = irq_min_id_i;
while(irq_ack_i != 1'b1) begin
@(posedge clk_i); //Keep the request high until the acknowledge is received
end
@(posedge clk_i);
irq_monitor = 1'b0;
irq_id_monitor = '0;
end
initial
begin
while(1) begin
irq_id_we_o = 1'b0;
wait(irq_ack_i == 1'b1);
irq_id_we_o = 1'b1; //Give the write enable to store the core response
@(posedge clk_i);
end
end
`endif //VERILATOR
endmodule
riscv_random_interrupt_generator.sv
是一个 SystemVerilog 文件,用于实现一个随机中断生成器模块,该模块可根据不同的模式向核心发送中断请求。
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
此部分声明了文件的版权归属以及使用该文件需遵循的 Solderpad Hardware License 0.51。
//
// //
// Author: Francesco Minervini - [email protected] //
// //
// Additional contributions by: Davide Schiavone - [email protected] //
// Design Name: Interrupt generator //
// Project Name: RI5CY, Zeroriscy //
// Language: SystemVerilog //
// //
// Description: Send interrupt request to core choosing one option between: //
// - Random; //
// - Standard; //
// - PC value-triggering //
// //
//
这部分注释提供了模块的基本信息,包括作者、设计名称、项目名称、使用的语言以及模块的功能描述,即可以在随机、标准和 PC 值触发三种模式下向核心发送中断请求。
import perturbation_defines::*;
导入 perturbation_defines
包,该包可能定义了一些与扰动相关的常量、类型等。
module riscv_random_interrupt_generator
`ifndef VERILATOR
import uvm_pkg::*;
`include "uvm_macros.svh"
`endif
(
input logic rst_ni,
input logic clk_i,
input logic irq_i,
input logic [4:0] irq_id_i,
input logic irq_ack_i,
output logic irq_o,
output logic [4:0] irq_id_o,
output logic irq_ack_o,
input logic [31:0] irq_mode_i,
input logic [31:0] irq_min_cycles_i,
input logic [31:0] irq_max_cycles_i,
input logic [31:0] irq_min_id_i,
input logic [31:0] irq_max_id_i,
output logic [31:0] irq_act_id_o,
output logic irq_id_we_o,
input logic [31:0] irq_pc_id_i,
input logic [31:0] irq_pc_trig_i
);
riscv_random_interrupt_generator
。ifndef VERILATOR
条件编译块用于在非 Verilator 仿真环境下导入 UVM 包和相关宏文件。rst_ni
(异步低电平复位)、clk_i
(时钟信号)。irq_i
(外部中断请求)、irq_id_i
(外部中断 ID)、irq_ack_i
(中断确认信号)。irq_o
(输出中断请求)、irq_id_o
(输出中断 ID)、irq_ack_o
(输出中断确认)。irq_mode_i
(中断模式)、irq_min_cycles_i
(最小中断周期)、irq_max_cycles_i
(最大中断周期)、irq_min_id_i
(最小中断 ID)、irq_max_id_i
(最大中断 ID)。irq_act_id_o
(实际中断 ID)、irq_id_we_o
(中断 ID 写使能)、irq_pc_id_i
(PC 值)、irq_pc_trig_i
(PC 触发值)。`ifndef VERILATOR
class rand_irq_cycles;
rand int n;
endclass : rand_irq_cycles
class rand_irq_id;
rand int n;
endclass : rand_irq_id
定义了两个随机类 rand_irq_cycles
和 rand_irq_id
,分别用于生成随机的中断周期和中断 ID。
logic [31:0] irq_mode_q;
logic irq_random;
logic [4:0] irq_id_random;
logic irq_ack_random;
logic irq_monitor;
logic [4:0] irq_id_monitor;
logic irq_ack_monitor;
定义了一些内部信号,用于存储中断模式、随机中断信息和监控中断信息。
assign irq_ack_o = irq_ack_i;
将输入的中断确认信号 irq_ack_i
直接赋值给输出的中断确认信号 irq_ack_o
。
always_ff @(posedge clk_i or negedge rst_ni)
begin
if(~rst_ni) begin
irq_mode_q <= 0;
end else begin
irq_mode_q <= irq_mode_i;
end
end
使用一个同步寄存器 irq_mode_q
来存储中断模式 irq_mode_i
,在复位时将其清零。
always_comb
begin
unique case (irq_mode_q)
RANDOM:
begin
irq_o = irq_random;
irq_id_o = irq_id_random;
end
PC_TRIG:
begin
irq_o = irq_monitor;
irq_id_o = irq_id_monitor;
end
default:
begin
irq_o = irq_i;
irq_id_o = irq_id_i;
end
endcase
end
根据 irq_mode_q
的值选择不同的中断输出:
irq_mode_q
为 RANDOM
时,输出随机中断信息。irq_mode_q
为 PC_TRIG
时,输出 PC 触发的中断信息。initial
begin
automatic rand_irq_cycles wait_cycles = new();
automatic rand_irq_id value = new();
int rs,i, min_irq_cycles, max_irq_cycles, min_irq_id, max_irq_id;
irq_random = 1'b0;
irq_id_random = '0;
while(1) begin
irq_random = 1'b0;
irq_id_random = '0;
@(posedge clk_i);
wait(irq_mode_q == RANDOM);
min_irq_id = irq_min_id_i;
max_irq_id = irq_max_id_i;
min_irq_cycles = irq_min_cycles_i;
max_irq_cycles = irq_max_cycles_i;
rs = 0; // "randomize success"
rs = value.randomize() with{
n >= min_irq_id;
n <= max_irq_id;
};
if (!rs) `uvm_error("RISCV_RANDOM_INTERRUPT_GENERATOR", "Randomization failure on value.randomize()")
rs = wait_cycles.randomize() with{
n >= min_irq_cycles;
n <= max_irq_cycles;
};
if (!rs) `uvm_error("RISCV_RANDOM_INTERRUPT_GENERATOR", "Randomization failure on wait_cycles.randomize()")
while(wait_cycles.n != 0) begin
@(posedge clk_i);
wait_cycles.n--;
end
irq_id_random = value.n;
irq_random = 1'b1;
irq_act_id_o = value.n;
@(posedge clk_i);
//we don't care about the ack in this mode
for(i=0; i
irq_mode_q
为 RANDOM
时生成随机中断。rand_irq_cycles
和 rand_irq_id
类生成随机的中断周期和中断 ID。initial
begin
irq_monitor = 1'b0;
irq_id_monitor = '0;
wait(irq_mode_q == PC_TRIG);
wait(irq_pc_id_i == irq_pc_trig_i);
irq_monitor = 1'b1;
irq_id_monitor = irq_min_id_i;
while(irq_ack_i != 1'b1) begin
@(posedge clk_i); //Keep the request high until the acknowledge is received
end
@(posedge clk_i);
irq_monitor = 1'b0;
irq_id_monitor = '0;
end
irq_mode_q
为 PC_TRIG
时工作。irq_pc_id_i
等于 irq_pc_trig_i
时,发出中断请求,并将中断 ID 设置为 irq_min_id_i
。initial
begin
while(1) begin
irq_id_we_o = 1'b0;
wait(irq_ack_i == 1'b1);
irq_id_we_o = 1'b1; //Give the write enable to store the core response
@(posedge clk_i);
end
end
irq_ack_i
时,将中断 ID 写使能信号 irq_id_we_o
置为高电平,用于存储核心的响应。`endif //VERILATOR
endmodule
结束模块定义,endif
对应前面的 ifndef VERILATOR
。
该模块实现了一个可配置的随机中断生成器,支持随机、标准和 PC 值触发三种中断模式。通过不同的过程根据配置生成相应的中断请求,并处理中断确认信号。在随机模式下,使用随机类生成随机的中断周期和中断 ID;在 PC 触发模式下,根据 PC 值触发中断。同时,提供了中断 ID 写使能信号用于存储核心的响应。
//
// //
// Author: Andreas Traber - [email protected] //
// //
// Additional contributions by: Francesco Minervini - [email protected] //
// Davide Schiavone - [email protected] //
// Design Name: Perturbation Unit //
// Project Name: RI5CY, Zeroriscy //
// Language: SystemVerilog //
// //
// Description: Introduce stalls on core standard execution for both data and instructions //
// //
//
//import riscv_defines::*;
import perturbation_defines::*;
module riscv_random_stall
#(
parameter MAX_STALL_N = 1,
RAM_ADDR_WIDTH = 32,
DATA_WIDTH = 32
)
(
input logic clk_i,
input logic rst_ni,
//grant from memory
input logic grant_mem_i,
input logic rvalid_mem_i,
input logic [DATA_WIDTH-1:0] rdata_mem_i,
output logic grant_core_o,
output logic rvalid_core_o,
output logic [DATA_WIDTH-1:0] rdata_core_o,
input logic req_core_i,
output logic req_mem_o,
input logic [RAM_ADDR_WIDTH-1:0] addr_core_i,
output logic [RAM_ADDR_WIDTH-1:0] addr_mem_o,
input logic [DATA_WIDTH-1:0] wdata_core_i,
output logic [DATA_WIDTH-1:0] wdata_mem_o,
input logic we_core_i,
output logic we_mem_o,
input logic [3:0] be_core_i,
output logic [3:0] be_mem_o,
input logic [31:0] stall_mode_i,
input logic [31:0] max_stall_i,
input logic [31:0] gnt_stall_i,
input logic [31:0] valid_stall_i
);
`ifndef VERILATOR
logic req_per_q, grant_per_q, rvalid_per_q;
typedef struct {
logic [31:0] addr;
logic we;
logic [ 3:0] be;
logic [DATA_WIDTH