diff --git a/Labs/10. Interrupt subsystem/tb_irq.sv b/Labs/10. Interrupt subsystem/tb_irq.sv index e3ef01c3..8c768026 100644 --- a/Labs/10. Interrupt subsystem/tb_irq.sv +++ b/Labs/10. Interrupt subsystem/tb_irq.sv @@ -9,7 +9,6 @@ // ////////////////////////////////////////////////////////////////////////////////// - module tb_irq(); logic clk_i; logic rst_i; @@ -22,14 +21,17 @@ module tb_irq(); logic [31:0] irq_cause_o; logic irq_o; + string str; + interrupt_controller dut(.*); +int err_count; always #5 clk_i <= ~clk_i; initial begin - $display("\n\n===========================\n\nPress button 'Run All' (F3)\n\n===========================\n\n"); + $display("\n\n===========================\n\nPress button 'Run All' (F3)\n\n===========================\n\n", $time); $stop(); - clk_i <= 0; + clk_i = '0; exception_i = '0; mret_i = '0; irq_req_i = '0; @@ -47,6 +49,9 @@ initial begin t10(); t11(); t12(); + t13(); + t14(); + $display("Simulation finished. Number of errors: %d", err_count); $finish; end @@ -62,7 +67,8 @@ mie_i = 0; endtask logic [1:0] k; -task t1(); +task t1(); + $display("TEST 01. Granted request."); reset(); @(posedge clk_i); mret_i = 0; @@ -70,342 +76,317 @@ task t1(); irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=1) $display("Error: irq_o != 1"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(1,0); @(posedge clk_i); endtask task t2(); + $display("TEST 02. Forbidden request."); reset(); @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 0; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); + eror_info(0,0); + @(posedge clk_i); endtask task t3(); + $display("TEST 03. Another request while handling previous."); reset(); @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 0; irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(0,0); @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); + eror_info(0,0); + @(posedge clk_i); endtask task t4(); + $display("TEST 04. Request while unhandled exception."); reset(); @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 1; irq_req_i = 0; mie_i = 1; @(posedge clk_i); - mret_i = 0; + mret_i = 0; exception_i = 0; - irq_req_i = 1; + irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); + eror_info(0,0); + @(posedge clk_i); + mret_i = 0; + exception_i = 1; + irq_req_i = 0; + mie_i = 1; + #1 + eror_info(0,0); + @(posedge clk_i); endtask task t5(); + $display("TEST 05. MRET while handling interrupt only."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=1) $display("Error: irq_ret_o != 1"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); + eror_info(0,1); + @(posedge clk_i); endtask task t6(); + $display("TEST 06. MRET while handling exception only."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 1; irq_req_i = 0; mie_i = 1; -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); + eror_info(0,0); + @(posedge clk_i); endtask task t7(); + $display("TEST 07. MRET while handling interrupt and exception."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 1; - irq_req_i = 1; - mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); -@(posedge clk_i); - mret_i = 1; - exception_i = 0; irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + eror_info(0,0); + @(posedge clk_i) + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(0,0); @(posedge clk_i); endtask task t8(); + $display("TEST 08. Two MRETs while handling interrupt and exception."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 1; - irq_req_i = 1; + irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); - @(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=1) $display("Error: irq_ret_o != 1"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(0,1); @(posedge clk_i); - endtask task t9(); + $display("TEST 09. MRET while unhandled interrupt and subsequent request."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=1) $display("Error: irq_ret_o != 1"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=1) $display("Error: irq_o != 1"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(1,0); + @(posedge clk_i); endtask task t10(); + $display("TEST 10. MRET while unhandled exception and subsequent request."); reset(); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 1; irq_req_i = 0; mie_i = 1; -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=1) $display("Error: irq_o != 1"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(1,0); + @(posedge clk_i); endtask task t11(); + $display("TEST 11. MRET while unhandled interrupt and exception and subsequent request."); reset(); -@(posedge clk_i); - mret_i = 0; - exception_i = 0; - irq_req_i = 1; - mie_i = 1; -@(posedge clk_i); - mret_i = 0; - exception_i = 1; - irq_req_i = 1; - mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); -@(posedge clk_i); - mret_i = 1; - exception_i = 0; - irq_req_i = 0; - mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; - exception_i = 0; - irq_req_i = 0; - mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); @(posedge clk_i); - mret_i = 0; + mret_i <= 0; + exception_i <= 0; + irq_req_i <= 1; + mie_i <= 1; + @(posedge clk_i); + mret_i <= 0; + exception_i <= 1; + irq_req_i <= 0; + mie_i <= 1; + @(posedge clk_i); + mret_i <= 1; + exception_i <= 0; + irq_req_i <= 0; + mie_i <= 1; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(0,0); + @(posedge clk_i); + endtask task t12(); - reset(); -@(posedge clk_i); - mret_i = 0; + $display("TEST 12. Two MRETs while unhandled interrupt and exception and susbsequent request."); + reset(); + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 1; - irq_req_i = 1; + irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); -@(posedge clk_i); - mret_i = 1; + @(posedge clk_i); + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 0; mie_i = 1; - #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); @(posedge clk_i); - mret_i = 1; + mret_i = 1; exception_i = 0; irq_req_i = 0; mie_i = 1; + @(posedge clk_i); + mret_i = 0; + exception_i = 0; + irq_req_i = 1; + mie_i = 1; #1 - if (irq_o!=0) $display("Error: irq_o != 0"); - if (irq_ret_o!=1) $display("Error: irq_ret_o != 1"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); -@(posedge clk_i); - mret_i = 0; + str = "request interrupt after 2 mret for interrupt and exception"; + eror_info(1,0); + @(posedge clk_i); +endtask + +task t13(); + $display("TEST 13. Request next cycle after excetion."); + reset(); + @(posedge clk_i); + mret_i = 0; + exception_i = 1; + irq_req_i = 0; + mie_i = 1; + @(posedge clk_i); + mret_i = 0; exception_i = 0; irq_req_i = 1; mie_i = 1; #1 - if (irq_o!=1) $display("Error: irq_o != 1"); - if (irq_ret_o!=0) $display("Error: irq_ret_o != 0"); - if (irq_cause_o!=32'h1000_0010) $display("Error: irq_o != 32'h1000_0010"); + eror_info(0,0); + @(posedge clk_i); +endtask + +task t14(); + $display("TEST 14. Request same cycle with the exception."); + reset(); + @(posedge clk_i); + mret_i = 0; + exception_i = 1; + irq_req_i = 1; + mie_i = 1; + #1 + eror_info(0,0); + @(posedge clk_i); +endtask + +//logic irq, irq_ret; + +task eror_info(irq, irq_ret); + if (irq_o!=irq) begin $error("invalid irq_o = %b, expected value %b." , irq_o, irq ); err_count++; end + if (irq_ret_o!=irq_ret) begin $error("invalid irq_ret_o = %b, expected value %b." , irq_ret_o, irq_ret); err_count++; end + if (irq_cause_o!=32'h1000_0010) begin $error("invalid irq_cause_o = %h, expected value 32'h1000_0010.", irq_cause_o ); err_count++; end endtask endmodule