On Mon, Apr 16, 2012 at 2:02 AM, Julius Baxter <[email protected]> wrote:
> On Mon, Apr 16, 2012 at 1:54 AM, Julius Baxter <[email protected]> wrote:
>> The following is the second version of a patch implementing correct DSX bit
>> behaviour in the supervisor register and software tests in ORPSoC. There
>> have been some fixes to the first software test, and a new software test has
>> been added ensuring the DSX bit is correctly set on ITLB misses which occur
>> on instructions in the delay slot of a jump/branch instruction.\
>
> Argh, sorry about the formatting on this. I copy and paste patches
> from SVN into Gmail in Chrome and I'd read that switching to "rich
> formatting" in the browser stopped the line breaks being inserted, but
> apparently it doesn't and it makes the formatting even worse!
>
> Anyway, I hope you get the point.
>
> Julius

Can I get an ACK on this? Trailing is the final patch I propose to add
(basically also adding the tests to the default test list.)

This implements the feature as indicated lacking by bug 85:
http://bugzilla.opencores.org/bugzilla4/show_bug.cgi?id=85

I can confirm the basic regression suite still passes with this.


Index: rtl/verilog/or1200/or1200_sprs.v
===================================================================
--- rtl/verilog/or1200/or1200_sprs.v    (revision 798)
+++ rtl/verilog/or1200/or1200_sprs.v    (working copy)
@@ -57,7 +57,7 @@

                   // Internal CPU interface
                   flagforw, flag_we, flag, cyforw, cy_we, carry,
-                  ovforw, ov_we,
+                  ovforw, ov_we, dsx,
                   addrbase, addrofs, dat_i, branch_op, ex_spr_read,
                   ex_spr_write,
                   epcr, eear, esr, except_started,
@@ -99,6 +99,7 @@
    output                              carry;          // SR[CY]
    input                               ovforw;         // From ALU
    input                               ov_we;          // From ALU
+   input                                dsx;            // From except
    input [width-1:0]                   addrbase;       // SPR base address
    input [15:0]                        addrofs;        // SPR offset
    input [width-1:0]                   dat_i;          // SPR write data
@@ -289,7 +290,7 @@
    // What to write into SR
    //
    assign to_sr[`OR1200_SR_FO:`OR1200_SR_OVE]
-           = (except_started) ? {sr[`OR1200_SR_FO:`OR1200_SR_DSX],1'b0} :
+           = (except_started) ? {sr[`OR1200_SR_FO:`OR1200_SR_EPH],dsx,1'b0} :
              (branch_op == `OR1200_BRANCHOP_RFE) ?
              esr[`OR1200_SR_FO:`OR1200_SR_OVE] : (spr_we && sr_sel) ?
              {1'b1, spr_dat_o[`OR1200_SR_FO-1:`OR1200_SR_OVE]} :
Index: rtl/verilog/or1200/or1200_cpu.v
===================================================================
--- rtl/verilog/or1200/or1200_cpu.v     (revision 798)
+++ rtl/verilog/or1200/or1200_cpu.v     (working copy)
@@ -289,6 +289,7 @@
 wire                           sr_we;
 wire   [`OR1200_SR_WIDTH-1:0]  to_sr;
 wire   [`OR1200_SR_WIDTH-1:0]  sr;
+wire                           dsx;
 wire                           except_flushpipe;
 wire                           except_start;
 wire                           except_started;
@@ -723,7 +724,8 @@
        .sr_we(sr_we),
        .to_sr(to_sr),
        .sr(sr),
-       .branch_op(branch_op)
+       .branch_op(branch_op),
+       .dsx(dsx)
 );

 //
@@ -877,7 +879,8 @@
        .sr_we(sr_we),
        .to_sr(to_sr),
        .sr(sr),
-       .abort_ex(abort_ex)
+       .abort_ex(abort_ex),
+       .dsx(dsx)
 );

 //
Index: rtl/verilog/or1200/or1200_except.v
===================================================================
--- rtl/verilog/or1200/or1200_except.v  (revision 798)
+++ rtl/verilog/or1200/or1200_except.v  (working copy)
@@ -78,7 +78,8 @@
    except_stop, except_trig, ex_void, abort_mvspr, branch_op, spr_dat_ppc,
    spr_dat_npc, datain, du_dsr, epcr_we, eear_we, esr_we, pc_we, epcr, eear,
    du_dmr1, du_hwbkpt, du_hwbkpt_ls_r, esr, sr_we, to_sr, sr, lsu_addr,
-   abort_ex, icpu_ack_i, icpu_err_i, dcpu_ack_i, dcpu_err_i, sig_fp, fpcsr_fpee
+   abort_ex, icpu_ack_i, icpu_err_i, dcpu_ack_i, dcpu_err_i, sig_fp,
fpcsr_fpee,
+   dsx

 );

@@ -147,7 +148,8 @@
 input                          icpu_err_i;
 input                          dcpu_ack_i;
 input                          dcpu_err_i;
-
+output                                 dsx;
+
 //
 // Internal regs and wires
 //
@@ -177,6 +179,7 @@
 wire                           tick_pending;
 wire                           fp_pending;
 wire                           range_pending;
+reg                            dsx;
                        
 reg trace_trap      ;
 reg ex_freeze_prev;
@@ -462,6 +465,7 @@
         eear <=  32'b0;
         esr <=  {2'h1, {`OR1200_SR_WIDTH-3{1'b0}}, 1'b1};
         extend_flush_last <=  1'b0;
+        dsx <= 1'b0;
       end
       else begin
 `ifdef OR1200_CASE_DEFAULT
@@ -482,6 +486,7 @@
                               ex_pc : ex_pc;
                       epcr <=  ex_dslot ?
                               wb_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_IPF
@@ -495,6 +500,7 @@
                               wb_pc : delayed1_ex_dslot ?
                               id_pc : delayed2_ex_dslot ?
                               id_pc : id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_BUSERR
@@ -504,6 +510,7 @@
                               wb_pc : ex_pc;
                       epcr <=  ex_dslot ?
                               wb_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_ILLEGAL
@@ -512,6 +519,7 @@
                       eear <=  ex_pc;
                       epcr <=  ex_dslot ?
                               wb_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_ALIGN
@@ -520,6 +528,7 @@
                       eear <=  lsu_addr;
                       epcr <=  ex_dslot ?
                               wb_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_DTLBMISS
@@ -529,6 +538,7 @@
                       epcr <=  ex_dslot ?
                               wb_pc : delayed1_ex_dslot ?
                               dl_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_TRAP                      
@@ -537,6 +547,7 @@
                       epcr <=  ex_dslot ?
                               wb_pc : delayed1_ex_dslot ?
                               id_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_SYSCALL
@@ -546,6 +557,7 @@
                               wb_pc : delayed1_ex_dslot ?
                               id_pc : delayed2_ex_dslot ?
                               id_pc : id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_DPF
@@ -555,6 +567,7 @@
                       epcr <=  ex_dslot ?
                               wb_pc : delayed1_ex_dslot ?
                               dl_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_BUSERR
@@ -564,6 +577,7 @@
                       epcr <=  ex_dslot ?
                               wb_pc : delayed1_ex_dslot ?
                               dl_pc : ex_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_RANGE
@@ -573,24 +587,28 @@
                               wb_pc : delayed1_ex_dslot ?
                               id_pc : delayed2_ex_dslot ?
                               id_pc : id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_FLOAT
                    14'b00_0000_0000_01??: begin
                       except_type <=  `OR1200_EXCEPT_FLOAT;
                       epcr <=  id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_INT
                    14'b00_0000_0000_001?: begin
                       except_type <=  `OR1200_EXCEPT_INT;
                       epcr <=  id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
 `ifdef OR1200_EXCEPT_TICK
                    14'b00_0000_0000_0001: begin
                       except_type <=  `OR1200_EXCEPT_TICK;
                       epcr <=  id_pc;
+                      dsx <= ex_dslot;
                    end
 `endif
                    default:
Index: sim/bin/Makefile
===================================================================
--- sim/bin/Makefile    (revision 798)
+++ sim/bin/Makefile    (working copy)
@@ -68,6 +68,8 @@
        or1200-ov       \
        or1200-sf       \
        or1200-ffl1 \
+       or1200-dsx \
+       or1200-dsxinsn \
        or1200-linkregtest \
        or1200-tick \
        or1200-ticksyscall \
Index: sw/tests/or1200/sim/or1200-dsx.S
===================================================================
--- sw/tests/or1200/sim/or1200-dsx.S    (revision 0)
+++ sw/tests/or1200/sim/or1200-dsx.S    (revision 0)
@@ -0,0 +1,531 @@
+/*
+       Delay-slot exception bit (DSX) test.
+
+       Generate some exceptions in delay slots and not in delay slots
+       and confirm the SR[DSX] bit gets set.
+
+       Just synchronous exceptions for now (a bit trickier to test
+       asynchronous ones like timer and interrupts.)
+
+       Set r10 to hold whether we are expecting SR[DSX] to be set or
+       not. Exceptions will advance the PC by 0x8 to step over both
+       the jump/branch and instruction causing an exception.
+
+       Julius Baxter <[email protected]>
+       
+*/
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// Copyright (C) 2012 Authors and OPENCORES.ORG                 ////
+////                                                              ////
+//// This source file may be used and distributed without         ////
+//// restriction provided that this copyright statement is not    ////
+//// removed from the file and that any derivative work contains  ////
+//// the original copyright notice and the associated disclaimer. ////
+////                                                              ////
+//// This source file is free software; you can redistribute it   ////
+//// and/or modify it under the terms of the GNU Lesser General   ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any   ////
+//// later version.                                               ////
+////                                                              ////
+//// This source is distributed in the hope that it will be       ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
+//// PURPOSE.  See the GNU Lesser General Public License for more ////
+//// details.                                                     ////
+////                                                              ////
+//// You should have received a copy of the GNU Lesser General    ////
+//// Public License along with this source; if not, download it   ////
+//// from http://www.opencores.org/lgpl.shtml                     ////
+////                                                              ////
+//////////////////////////////////////////////////////////////////////
+
+#include "spr-defs.h"
+#include "board.h"
+
+#define TEST_DSX_AND_RETURN                                                    
; \
+       l.mfspr r3,r0,SPR_EPCR_BASE     /* Get EPC */                           
; \
+       l.nop   2                       /* Report PC for diagnostic purpose */  
; \
+       /* Check SR[DSX] was as expected */                                     
; \
+       l.mfspr r8,r0,SPR_SR            /* Get SR */                            
; \
+       l.andi  r8,r8,SPR_SR_DSX        /* Clear all bits except DSX */         
; \
+       l.xor   r8,r8,r10               /* r8 will be >0 if error */            
; \
+       l.sfne  r8,r0                                                           
; \
+       l.bf    test_fail                                                       
; \
+       l.nop                                                                   
; \
+       /* Check if we were in delay slot, if so just advance by 8, else 4 */   
; \
+       l.addi  r3,r3,4                 /* Step two instructions past where     
; \
+                                       exception       occurred */             
; \
+       l.srli  r8,r10,11               /* If we were in delay slot, add extra  
; \
+                                       4 to PC (0x2000>>11=4)*/                
; \
+       l.add   r3,r3,r8                                                        
; \
+       l.mtspr r0,r3,SPR_EPCR_BASE                                             
; \
+       l.rfe
+       
+       
+/* =================================================== [ exceptions ] === */
+       .section .vectors, "ax"
+
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+        .org 0x100     
+       l.movhi r0, 0
+       /* Clear status register */
+       l.ori   r1, r0, SPR_SR_SM
+       l.mtspr r0, r1, SPR_SR
+       /* Clear timer  */
+       l.mtspr r0, r0, SPR_TTMR
+       /* Init the stack */
+       .global stack
+       l.movhi r1, hi(stack)
+       l.ori   r1, r1, lo(stack)
+       l.addi  r2, r0, -3
+       l.and   r1, r1, r2
+       /* Jump to program initialisation code */
+       .global _start
+       l.movhi r4, hi(_start)
+       l.ori   r4, r4, lo(_start)
+       l.jr    r4
+       l.nop
+
+
+/* ---[ 0x200: BUS error ]------------------------------------------------ */
+       .org 0x200
+       .global _bus_handler
+_bus_handler:
+       TEST_DSX_AND_RETURN
+       
+
+/* ---[ 0x600: ALIGN error ]------------------------------------------------ */
+       .org 0x600
+       .global _align_handler
+_align_handler:
+       TEST_DSX_AND_RETURN
+
+
+/* ---[ 0x700: ILLEGAL INSN exception ]------------------------------------- */
+       .org 0x700
+       .global _illinsn_handler
+_illinsn_handler:
+       TEST_DSX_AND_RETURN
+
+/* ---[ 0x900: DTLB exception ]--------------------------------------------- */
+       .org 0x900
+       .global _dtlb_handler
+       TEST_DSX_AND_RETURN
+
+/* ---[ 0xe00: TRAP error ]------------------------------------------------ */
+       .org 0xe00
+       .global _trap_handler
+_trap_handler:
+       TEST_DSX_AND_RETURN
+
+       
+/* =================================================== [ text section ] === */
+       .section  .text
+
+/* =================================================== [ start ] === */        
+
+       .global _start
+_start:
+       /* r2 is test counter - put in r3 and will be printed out for each
+       successful call to test_func */
+       l.movhi r2,0
+
+       l.movhi r9,hi(test_fail)
+       l.ori   r9,r9,lo(test_fail)
+
+       /* Alignment exception tests */
+       
+       /* This test should _NOT_ set DSX, so clear r10 */
+       l.movhi r10,0
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfeq  r0,r0
+       l.bf    test_func
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfne  r0,r0
+       l.bnf   test_func
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.j     test_func
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.jal   test_func
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jr    r5
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jalr  r5
+       /* Should cause an alignment error */
+       l.lwz   r1,1(r0)
+
+       /* Make some calls to the functions which will trigger exceptions
+          to check that the DSX bit is not set */
+       l.ori   r10,r0,0
+       l.jal   align_func
+       l.nop
+
+       
+       /* Illegal instruction exception tests */
+
+       /* This test should _NOT_ set DSX, so clear r10 */
+       l.movhi r10,0
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfeq  r0,r0
+       l.bf    test_func
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfne  r0,r0
+       l.bnf   test_func
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.j     test_func
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.jal   test_func
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jr    r5
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jalr  r5
+       /* Should cause an illegal insn error */
+       .word 0xef000000
+
+       /* Make some calls to the functions which will trigger exceptions
+          to check that the DSX bit is not set */
+       l.ori   r10,r0,0
+       l.jal   illegal_insn_func
+       l.nop
+
+       /* Bus error exceptions */
+
+       /* This test should _NOT_ set DSX, so clear r10 */
+       l.movhi r10,0
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfeq  r0,r0
+       l.bf    test_func
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfne  r0,r0
+       l.bnf   test_func
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.j     test_func
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.jal   test_func
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jr    r5
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jalr  r5
+       /* This should cause a bus error */
+       l.lwz   r1,-4(r0)
+
+       /* Make some calls to the functions which will trigger exceptions
+          to check that the DSX bit is not set */
+       l.ori   r10,r0,0
+       l.jal   bus_err_func
+       l.nop
+
+       /* Trap instruction exception tests */
+
+       /* This test should _NOT_ set DSX, so clear r10 */
+       l.movhi r10,0
+       /* Should cause an trap error */
+       l.trap 0
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfeq  r0,r0
+       l.bf    test_func
+       /* Should cause an trap error */
+       l.trap 0
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfne  r0,r0
+       l.bnf   test_func
+       /* Should cause an trap error */
+       l.trap 0
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.j     test_func
+       /* Should cause an trap error */
+       l.trap 0
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.jal   test_func
+       /* Should cause an trap error */
+       l.trap 0
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jr    r5
+       /* Should cause an trap error */
+       l.trap 0
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jalr  r5
+       /* Should cause an trap error */
+       l.trap 0
+
+       /* Make some calls to the functions which will trigger exceptions
+          to check that the DSX bit is not set */
+       l.ori   r10,r0,0
+       l.jal   trap_func
+       l.nop
+
+       /* DMMU miss test */
+
+       /* Check if we have a DMMU */
+       l.mfspr r3,r0,SPR_UPR
+       l.andi  r3,r3,SPR_UPR_DMP
+       l.sfeq  r3,r0
+       /* Flag set if no DMMU */
+       l.bf    dmmu_test_done
+       l.nop
+       
+       /* Just enabling the DMMU with no valid match match registers should
+       be enough to determine number of DMMU entries - hold this value in r3 */
+       l.mfspr r3,r0,SPR_DMMUCFGR
+       l.andi  r4,r3,SPR_DMMUCFGR_NTS
+       l.srli  r4,r4,SPR_DMMUCFGR_NTS_OFF
+       l.ori   r6,r0,1
+       l.sll   r3,r6,r4
+       
+       /* Setup the Data MMU's TLBS - invalidate them */
+       l.movhi r4, hi(SPR_DTLBMR_BASE(0))
+       l.ori r4, r4, lo(SPR_DTLBMR_BASE(0))
+
+       /* DTLB invalidate loop */
+1:
+       l.mtspr r4, r0, 0x0
+       l.addi r4, r4, 0x1
+       l.sfeq r3, r0
+       l.bnf 1b
+       l.addi r3, r3, -1
+
+       .extern lo_dmmu_en
+       /* Now enable the DMMU */
+       l.movhi r4, hi(lo_dmmu_en)
+       l.ori r4, r4, lo(lo_dmmu_en)
+       l.jalr r4
+       l.nop
+
+       /* Now any data access should cause a miss */
+
+       /* This test should _NOT_ set DSX, so clear r10 */
+       l.movhi r10,0
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfeq  r0,r0
+       l.bf    test_func
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.sfne  r0,r0
+       l.bnf   test_func
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.j     test_func
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.jal   test_func
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jr    r5
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+       
+       /* This test should_ set DSX, so put SPR_SR_DSX in r10 */
+       l.ori   r10,r0,SPR_SR_DSX
+       l.movhi r5,hi(test_func)
+       l.ori   r5,r5,lo(test_func)
+       l.jalr  r5
+       /* This should cause a DLTB miss */
+       l.lwz   r1,0(r0)
+
+       /* Make some calls to the functions which will trigger exceptions
+          to check that the DSX bit is not set */
+       l.ori   r10,r0,0
+       l.jal   dtlb_func
+       l.nop
+
+       /* Now disable DMMU */
+        l.mfspr r3,r0,SPR_SR
+        l.xori  r3,r3,SPR_SR_DME
+        l.mtspr r0,r3,SPR_ESR_BASE
+       l.movhi r9,hi(dmmu_test_done)
+       l.ori   r9,r9,lo(dmmu_test_done)
+        l.mtspr r0,r9,SPR_EPCR_BASE
+        l.rfe
+       
+dmmu_test_done:        
+
+       /* Check if we have an instruction cache */
+       l.mfspr r3,r0,SPR_UPR
+       l.andi  r3,r3,SPR_UPR_ICP
+       l.sfeq  r3,r0
+       /* Flag set if no icache */
+       l.bf    test_ok
+       l.nop
+
+       /* Now repeat the tests with caches enabled if they weren't */
+       l.mfspr r1,r0,SPR_SR
+       l.andi  r1,r1,SPR_SR_ICE
+       l.sfeq  r0,r1  /* Set flag if caches not enabled */
+       l.bf    restart_with_caches_enabled
+       l.nop
+       
+test_ok:
+       l.movhi r3,0x8000
+       l.ori   r3,r3,0x000d
+       l.nop   2
+       l.or    r3,r0,r0
+       l.nop   1
+
+test_func:
+       /* A test function to call, just return */
+       l.jr    r9
+       l.nop   2       /* print out whatever is in r3 */
+
+test_fail:
+       l.movhi r3,0xbaaa
+       l.ori   r3,r3,0xaaad
+       l.nop   2
+       l.ori   r3,r0,1
+       l.nop   1
+
+align_func:
+       /* DSX should _not_ be set on exception here */
+       l.lwz   r1,1(r0)
+       l.jr    r9
+       l.nop
+
+illegal_insn_func:
+       /* DSX should _not_ be set on exception here */ 
+       .word 0xef000000
+       l.jr    r9
+       l.nop
+
+bus_err_func:
+       /* DSX should _not_ be set on exception here */ 
+       l.lwz   r1,-4(r0)
+       l.jr    r9
+       l.nop
+
+trap_func:
+       /* DSX should _not_ be set on exception here */ 
+       l.trap  0
+       l.jr    r9
+       l.nop
+
+dtlb_func:
+       /* DSX should _not_ be set on exception here */ 
+       l.lwz   r1,0(r0)
+       l.jr    r9
+       l.nop
+
+restart_with_caches_enabled:
+       l.jal   _cache_init
+       l.nop
+       l.j     _start
+       l.nop
Index: sw/tests/or1200/sim/or1200-dsxinsn.S
===================================================================
--- sw/tests/or1200/sim/or1200-dsxinsn.S        (revision 0)
+++ sw/tests/or1200/sim/or1200-dsxinsn.S        (revision 0)
@@ -0,0 +1,289 @@
+/*
+       Test correct delay-slot exception bit (DSX) behavior on
+       instruction-fetch related exceptions.
+
+       The only case where DSX is set on instruction-fetch related
+       exception is when instructions in delay slots occur in a new
+       page which needs to be mapped.
+
+       In this test we will trigger an instruction MMU miss for an
+       instruction in a delay slot. To do this, we need to have a
+       branch instruction as the very last instruction of a page,
+       with the delay slot instruction being on a new unmapped page.
+       
+       Set r10 to hold whether we are expecting SR[DSX] to be set or
+       not. Exceptions will advance the PC by 0x8 to step over both
+       the jump/branch and instruction causing an exception.
+
+       Julius Baxter <[email protected]>
+       
+*/
+//////////////////////////////////////////////////////////////////////
+////                                                              ////
+//// Copyright (C) 2012 Authors and OPENCORES.ORG                 ////
+////                                                              ////
+//// This source file may be used and distributed without         ////
+//// restriction provided that this copyright statement is not    ////
+//// removed from the file and that any derivative work contains  ////
+//// the original copyright notice and the associated disclaimer. ////
+////                                                              ////
+//// This source file is free software; you can redistribute it   ////
+//// and/or modify it under the terms of the GNU Lesser General   ////
+//// Public License as published by the Free Software Foundation; ////
+//// either version 2.1 of the License, or (at your option) any   ////
+//// later version.                                               ////
+////                                                              ////
+//// This source is distributed in the hope that it will be       ////
+//// useful, but WITHOUT ANY WARRANTY; without even the implied   ////
+//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      ////
+//// PURPOSE.  See the GNU Lesser General Public License for more ////
+//// details.                                                     ////
+////                                                              ////
+//// You should have received a copy of the GNU Lesser General    ////
+//// Public License along with this source; if not, download it   ////
+//// from http://www.opencores.org/lgpl.shtml                     ////
+////                                                              ////
+//////////////////////////////////////////////////////////////////////
+
+#include "spr-defs.h"
+#include "board.h"
+       
+/* =================================================== [ exceptions ] === */
+       .section .vectors, "ax"
+
+
+/* ---[ 0x100: RESET exception ]----------------------------------------- */
+        .org 0x100     
+       l.movhi r0, 0
+       /* Clear status register */
+       l.ori   r1, r0, SPR_SR_SM
+       l.mtspr r0, r1, SPR_SR
+       /* Clear timer  */
+       l.mtspr r0, r0, SPR_TTMR
+       /* Init the stack */
+       .global stack
+       l.movhi r1, hi(stack)
+       l.ori   r1, r1, lo(stack)
+       l.addi  r2, r0, -3
+       l.and   r1, r1, r2
+       /* Jump to program initialisation code */
+       .global _start
+       l.movhi r4, hi(_start)
+       l.ori   r4, r4, lo(_start)
+       l.jr    r4
+       l.nop
+
+/* ---[ 0x200: BUS error ]------------------------------------------------ */
+       .org 0x200
+       l.j     test_fail
+       l.nop
+       
+/* ---[ 0x600: ALIGN error ]------------------------------------------------ */
+       .org 0x600
+       l.j     test_fail
+       l.nop
+       
+/* ---[ 0x700: ILLEGAL INSN exception ]------------------------------------- */
+       .org 0x700
+       l.j     test_fail
+       l.nop
+
+/* ---[ 0x900: DTLB exception ]--------------------------------------------- */
+       .org 0x900
+       l.j     test_fail
+       l.nop
+
+/* ---[ 0xa00: itlb miss ]---------------------------------------------- */
+        .org 0xa00
+
+       /* First check if we're expecting a miss in a delay slot - check r10 */
+       l.mfspr r3,r0,SPR_EEAR_BASE     /* Get EPC */                           
+       l.nop   2                       /* Report PC for diagnostic purpose */  
+       /* Check SR[DSX] was as expected */                                     
+       l.mfspr r8,r0,SPR_SR            /* Get SR */                            
+       l.andi  r8,r8,SPR_SR_DSX        /* Clear all bits except DSX */         
+       l.xor   r8,r8,r10               /* r8 will be >0 if error */            
+       l.sfne  r8,r0                                                           
+       l.bf    test_fail                                                       
+       l.nop                                                                   
+       
+       /* Simple itlb miss handler - install 1-1 mappings on misses */
+       l.mfspr r12,r0,SPR_EEAR_BASE /* Get the PC of the exception */
+       l.srli  r13,r12,13 /* Get the page number, divide by 8K, store in r13 */
+       /* Set up the match registers */
+       l.movhi r14,hi(SPR_ITLBMR_VPN)
+       l.ori   r14,r14,lo(SPR_ITLBMR_VPN)
+       l.and   r14,r12,r14 /* Mask in the VPN */
+       l.ori   r15,r14,SPR_ITLBMR_V /* Set this match as valid */
+       /* Write it into the appropriate match register, way 0 only */
+       l.mtspr r13,r15,SPR_ITLBMR_BASE(0)
+       /* Set up the translate register - no restrictions */
+       l.ori   r15,r14,ITLB_PR_NOLIMIT
+       /* Write it into the appropriate translate register  */
+       l.mtspr r13,r15,SPR_ITLBTR_BASE(0)
+       /* MMU setup should now be complete, let's go back */
+       l.rfe   
+       
+/* ---[ 0xe00: TRAP error ]------------------------------------------------ */
+       .org 0xe00
+       l.j     test_fail
+       l.nop
+       
+/* =================================================== [ text section ] === */
+       .section  .text
+
+/* =================================================== [ start ] === */        
+
+       .global _start
+_start:
+       /* First initialise the instruction MMU */
+       
+       l.mfspr r3,r0,SPR_IMMUCFGR
+       l.andi  r4,r3,SPR_IMMUCFGR_NTS
+       l.srli  r4,r4,SPR_IMMUCFGR_NTS_OFF
+       l.ori   r6,r0,1
+       l.sll   r3,r6,r4
+       
+       /* Setup the IMMU's TLBs - invalidate them */
+       l.movhi r4, hi(SPR_ITLBMR_BASE(0))
+       l.ori r4, r4, lo(SPR_ITLBMR_BASE(0))
+
+       /* ITLB invalidate loop */
+1:
+       l.mtspr r4, r0, 0x0
+       l.addi r4, r4, 0x1
+       l.sfeq r3, r0
+       l.bnf 1b
+       l.addi r3, r3, -1
+
+       /* Enable MMU - we should get a miss for this page */
+       l.movhi r10,0 /* Clear r10 - not expecting to be in a delay slot
+                       when this TLB miss occurs */
+       
+       .extern lo_immu_en
+       /* Now enable the IMMU */
+       l.movhi r4, hi(lo_immu_en)
+       l.ori r4, r4, lo(lo_immu_en)
+       l.jalr r4
+       l.nop
+
+       /* Copy the 2 instructions from the ljr9_function function to
+       places which should cause TLB misses in the delay slot */
+       l.movhi r6,hi(ljr9_function)
+       l.ori   r6,r6,lo(ljr9_function)
+
+       /* r13 should have the page number we're in from the TLB miss we caused
+       when enabling the immu. Take that and add 16 to determine the page
+       boundary we'll play with */
+       l.addi  r4,r13,16
+
+       /* Calculate the physical address for this page */
+       l.slli  r8,r4,13
+
+       /* Copy our function to the last 2 instructions of the page before */
+       l.lwz   r1,0(r6)
+       l.sw    -8(r8),r1
+       l.lwz   r1,4(r6)
+       l.sw    -4(r8),r1
+
+       /* Call it - we should _not_ have DSX set on the itbl miss */
+       l.movhi r10,0
+       l.addi  r1,r8,-8
+
+       /* Report value */
+       l.or    r3,r1,r1
+       l.nop   2
+
+       l.jalr  r1
+       l.nop
+       
+       /* Tests finish */
+
+       /* Now do what we've done for the miss but put delay slot instruction
+       in the new page */
+
+       /* Calculate the physical address for this page */
+       l.slli  r8,r4,13
+
+       /* Copy our function to the last 2 instructions of the page before */
+       l.lwz   r1,0(r6)
+       l.sw    -4(r8),r1
+       l.lwz   r1,4(r6)
+       l.sw    0(r8),r1
+
+       /* Clear insn cache for this area (need to if it's enabled so we
+       don't get the cached instructions from the previous test) */
+       l.mtspr r0,r8,SPR_ICBIR
+       l.addi  r1,r8,-4
+       l.mtspr r0,r1,SPR_ICBIR
+
+       /* Jump to (r8-0x4) - we _should_ have DSX set on the itbl miss as
+       the jump instruction will be on the last instruction of the previous
+       page (already mapped in ITLB) and the delay slot will be the first
+       instruction on the next page, which is unmapped at this stage and
+       should cause an ITLB miss*/
+       l.ori   r10,r0,SPR_SR_DSX
+       l.addi  r1,r8,-4
+
+       /* Report value */
+       l.or    r3,r1,r1
+       l.nop   2
+
+       l.jalr  r1
+       l.nop
+       
+
+       /* TODO - track and check the number of TLB misses we should
+       have incurred */
+       
+       /* Now repeat the tests with caches enabled if they weren't */
+       l.mfspr r1,r0,SPR_SR
+       l.andi  r1,r1,SPR_SR_ICE
+       l.sfeq  r0,r1  /* Set flag if caches not enabled */
+       l.bf    restart_with_caches_enabled
+       l.nop
+       
+test_ok:
+       l.movhi r3,0x8000
+       l.ori   r3,r3,0x000d
+       l.nop   2
+       l.or    r3,r0,r0
+       l.nop   1
+
+test_fail:
+       l.movhi r3,0xbaaa
+       l.ori   r3,r3,0xaaad
+       l.nop   2
+       l.ori   r3,r0,1
+       l.nop   1
+
+restart_with_caches_enabled:
+       
+       /* Disable IMMU before restart*/
+        l.mfspr r3,r0,SPR_SR
+        l.xori  r3,r3,SPR_SR_IME
+        l.mtspr r0,r3,SPR_ESR_BASE
+       l.movhi r9,hi(.L1)
+       l.ori   r9,r9,lo(.L1)
+        l.mtspr r0,r9,SPR_EPCR_BASE
+        l.rfe
+.L1:   
+       l.jal   _cache_init
+       l.nop
+
+       /* Actually we won't want dcache enabled as we'll be reading
+       and writing instructions around the shop so will not want them
+       being cached */
+        l.mfspr r3,r0,SPR_SR
+        l.xori  r3,r3,SPR_SR_DCE
+        l.mtspr r0,r3,SPR_SR
+       
+       l.j     _start
+       l.nop
+
+       /* A simple function, which we will copy the instructions of
+       to different parts of memory */
+ljr9_function:
+       l.jr    r9
+       l.nop
+
_______________________________________________
OpenRISC mailing list
[email protected]
http://lists.openrisc.net/listinfo/openrisc

Reply via email to