From ae783b3c6b96366e3b3c02460c523aa5a09db9d6 Mon Sep 17 00:00:00 2001 From: Andrei Solodovnikov Date: Tue, 21 Nov 2023 09:52:01 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9B=D0=A010.=20=D0=9F=D0=B5=D1=80=D0=B5?= =?UTF-8?q?=D0=B4=D0=B5=D0=BB=D0=B0=D0=BD=20=D1=82=D0=B1=20=D0=BA=20csr-?= =?UTF-8?q?=D0=BA=D0=BE=D0=BD=D1=82=D1=80=D0=BE=D0=BB=D0=BB=D0=B5=D1=80?= =?UTF-8?q?=D1=83?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Labs/10. Interrupt subsystem/tb_csr.sv | 217 +++++++++++++++++-------- 1 file changed, 153 insertions(+), 64 deletions(-) diff --git a/Labs/10. Interrupt subsystem/tb_csr.sv b/Labs/10. Interrupt subsystem/tb_csr.sv index 5a91e580..ac518da7 100644 --- a/Labs/10. Interrupt subsystem/tb_csr.sv +++ b/Labs/10. Interrupt subsystem/tb_csr.sv @@ -9,21 +9,20 @@ // ////////////////////////////////////////////////////////////////////////////////// - module tb_csr(); logic clk_i; logic rst_i; logic trap_i; - + logic [ 2:0] opcode_i; - - logic [11:0] addr_i; + + logic [11:0] addr_i; logic [31:0] pc_i; logic [31:0] mcause_i; logic [31:0] rs1_data_i; logic [31:0] imm_data_i; logic write_enable_i; - + logic [31:0] read_data_o; logic [31:0] mie_o; logic [31:0] mepc_o; @@ -36,12 +35,11 @@ csr_controller dut(.*); always #5 clk_i <= ~clk_i; int err_count; -bit not_stopped; + initial begin $display("\n\n===========================\n\nPress button 'Run All' (F3)\n\n===========================\n\n"); $stop(); err_count = 0; - not_stopped = 1; clk_i <= 0; rst_i <= 1'b1; repeat(2)@(posedge clk_i); @@ -66,8 +64,22 @@ initial begin csrr(); csrw(); trap(); - $display("Simulation finished. Number of errors: %d", err_count); - $finish(); + + $display("Simulation finished. Number of errors: %d", err_count); + if( !err_count ) $display("\n csr_controller SUCCESS!!!\n"); + $finish; +end + +initial begin + int not_stopped = 1; + forever begin + @(posedge clk_i); + if((err_count >= 10) && not_stopped) begin + $display("Simulation stopped after ten errors."); + $stop(); + not_stopped = 0; + end + end end logic [31:0] data_ref; @@ -81,7 +93,9 @@ MCAUSE_ADDR}; assign pc_ref = write_enable_i ? pc_i : pc_ref; assign mcause_ref = write_enable_i ? mcause_i : mcause_ref; + always_comb begin + if (rst_i) data_ref <= 0; if (write_enable_i) case(opcode_i) CSR_RW: data_ref <= #1 rs1_data_i; @@ -95,34 +109,33 @@ always_comb begin end task clear(); -opcode_i <= CSR_RW; -rs1_data_i <= 0; -imm_data_i <= 0; -write_enable_i <= 1; -@(posedge clk_i); -write_enable_i <= 0; -@(posedge clk_i); + rst_i <= 1'b1; + repeat(2)@(posedge clk_i); + rst_i <= 1'b0; endtask //csrrw task csrrw(); -trap_i <= 0; -opcode_i <= CSR_RW; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin + opcode_i <= CSR_RW; addr_i <= addr[i]; rs1_data_i <= $random; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end clear(); + @(posedge clk_i); end endtask //csrrs task csrrs(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin opcode_i <= CSR_RS; @@ -131,98 +144,117 @@ for (int i = 0; i<5; i = i+1) begin imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); end clear(); + @(posedge clk_i); end endtask //csrrc task csrrc(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; - opcode_i <= CSR_RC; + opcode_i <= CSR_RC; rs1_data_i <= $random; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end clear(); + @(posedge clk_i); end endtask //csrrwi task csrrwi(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; - opcode_i <= CSR_RWI; + opcode_i <= CSR_RWI; rs1_data_i <= $random; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end clear(); + @(posedge clk_i); end endtask //csrrsi task csrrsi(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; - opcode_i <= CSR_RSI; + opcode_i <= CSR_RSI; rs1_data_i <= $random; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end clear(); + @(posedge clk_i); end endtask //csrrci task csrrci(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; - opcode_i <= CSR_RCI; + opcode_i <= CSR_RCI; rs1_data_i <= $random; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end clear(); + @(posedge clk_i); end endtask //csrr task csrr(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; - opcode_i <= CSR_RS; + opcode_i <= CSR_RS; rs1_data_i <= 0; imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end + clear(); + @(posedge clk_i); end endtask //csrw task csrw(); -trap_i <= 0; + trap_i <= 0; for (int i = 0; i<5; i = i+1) begin repeat(20) begin addr_i <= addr[i]; @@ -231,8 +263,12 @@ for (int i = 0; i<5; i = i+1) begin imm_data_i <= $random; write_enable_i <= 1; @(posedge clk_i); + write_enable_i <= 0; + @(posedge clk_i); check_reg(); -end + end + clear(); + @(posedge clk_i); end endtask @@ -253,72 +289,125 @@ end endtask task check_reg(); - trap_i <= 0; + trap_i <= 0; + opcode_i <= 0; + rs1_data_i <= 0; + imm_data_i <= 0; + write_enable_i <= 0; for (int i = 0; i<5; i = i+1) begin addr_i <= addr[i]; - opcode_i <= CSR_RS; - rs1_data_i <= 0; - imm_data_i <= $random; - write_enable_i <= 1; @(posedge clk_i); end endtask trap_a: assert property ( @(posedge clk_i) disable iff ( rst_i ) - (trap_i && (addr_i == MCAUSE_ADDR)) |-> ##1 (mepc_o === pc_i) && (read_data_o === mcause_i) -)else begin + ($rose(trap_i) && (addr_i == MCAUSE_ADDR)) |-> ##1 (mepc_o === pc_i) && (read_data_o === mcause_i) +)else begin err_count++; - $error("\error write/read trap\n"); + if (mepc_o != pc_i) + if (read_data_o != mcause_i) + $error("Incorrect mepc and mcause on trap_i == 1: Time = %t. mepc_o(%h) != pc_i(%h), read_data_o(%h) != mcause_i(%h).\n", $time, mepc_o, pc_i, read_data_o, mcause_i); + else + $error("Incorrect mepc on trap_i == 1: Time = %t. mepc_o(%h) != pc_i(%h).\n", $time, mepc_o, pc_i); + else + $error("Incorrect mcause on trap_i == 1: Time = %t. read_data_o(%h) != mcause_i(%h).\n", $time, read_data_o, mcause_i); end csrrw_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ( (opcode_i === CSR_RW) && write_enable_i) |=> (read_data_o === data_ref) and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ( (opcode_i === CSR_RW) && $rose(write_enable_i)) |=> (read_data_o === data_ref) +)else begin err_count++; - $error("\error write/read csrrw\n"); + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrw: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrw: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrw: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrw: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrw: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); end - + csrrs_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((opcode_i === CSR_RS) && write_enable_i) |=> read_data_o === data_ref and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ((opcode_i === CSR_RS) && $rose(write_enable_i)) |=> read_data_o === data_ref +)else begin err_count++; - $error("\error write/read csrrs\n"); + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrs: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrs: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrs: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrs: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrs: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); end csrrc_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((opcode_i === CSR_RC) && write_enable_i) |=> read_data_o === data_ref and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ((opcode_i === CSR_RC) && $rose(write_enable_i)) |=> read_data_o === data_ref +)else begin err_count++; - $error("\error write/read csrrc\n"); + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrc: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrc: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrc: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrc: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrc: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); end csrrwi_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((opcode_i === CSR_RWI) && write_enable_i) |=> read_data_o === data_ref and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ((opcode_i === CSR_RWI) && $rose(write_enable_i)) |=> read_data_o === data_ref +)else begin err_count++; - $error("\error write/read csrwi\n"); + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrwi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrwi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrwi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrwi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrwi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); end csrrci_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((opcode_i === CSR_RCI) && write_enable_i ) |=> read_data_o === data_ref and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ((opcode_i === CSR_RCI) && $rose(write_enable_i) ) |=> read_data_o === data_ref //and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) +)else begin err_count++; - $error("\error write/read csrrci\n"); + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrci: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrci: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrci: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrci: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrci: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); end csrrsi_a: assert property ( @(posedge clk_i) disable iff ( rst_i || trap_i ) - ((opcode_i === CSR_RSI) && write_enable_i) |=> read_data_o === data_ref and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) -)else begin + ((opcode_i === CSR_RSI) && $rose(write_enable_i)) |=> read_data_o === data_ref //and (addr_i === MIE_ADDR) |-> (mie_o === data_ref) and (addr_i === MEPC_ADDR) |-> (mepc_o === data_ref) and (addr_i === MTVEC_ADDR) |-> (mtvec_o === data_ref) +)else begin + err_count++; + if (addr_i === MIE_ADDR) $error("Incorrect value in register mie by csrrsi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MEPC_ADDR) $error("Incorrect value in register mepc by csrrsi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MTVEC_ADDR) $error("Incorrect value in register mtvec by csrrsi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MCAUSE_ADDR) $error("Incorrect value in register mcause by csrrsi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + if (addr_i === MSCRATCH_ADDR) $error("Incorrect value in register mscratch by csrrsi: Time = %t. read_data_o(%h) != data_ref(%h).\n", $time, read_data_o, data_ref); + end + +mie_a: assert property ( + @(posedge clk_i) disable iff ( rst_i || trap_i ) + ((addr_i === MIE_ADDR) && $rose(write_enable_i)) |=> (mie_o === data_ref) +)else begin err_count++; - $error("\error write/read csrrsi\n"); + $error("Incorrect signal mie_o: Time = %t. mie_o(%h) != data_ref(%h).\n", $time, mie_o, data_ref); + end + +mepc_a: assert property ( + @(posedge clk_i) disable iff ( rst_i || trap_i ) + ((addr_i === MEPC_ADDR) && $rose(write_enable_i)) |=> (mepc_o === data_ref) +)else begin + err_count++; + $error("Incorrect signal mepc_o: Time = %t. mepc_o(%h) != data_ref(%h).\n", $time, mepc_o, data_ref); end +mtvec_a: assert property ( + @(posedge clk_i) disable iff ( rst_i || trap_i ) + ((addr_i === MTVEC_ADDR) && $rose(write_enable_i)) |=> (mtvec_o === data_ref) +)else begin + err_count++; + $error("Incorrect signal mtvec_o: Time = %t. mtvec_o(%h) != data_ref(%h).\n", $time, mtvec_o, data_ref); + end endmodule