OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /openrisc/trunk/orpsocv2
    from Rev 805 to Rev 807
    Reverse comparison

Rev 805 → Rev 807

/rtl/verilog/or1200/or1200_sprs.v
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]} :
/rtl/verilog/or1200/or1200_cpu.v
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)
);
 
//
/rtl/verilog/or1200/or1200_except.v
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,6 → 587,7
wb_pc : delayed1_ex_dslot ?
dl_pc : delayed2_ex_dslot ?
id_pc : ex_pc;
dsx <= ex_dslot;
end
`endif
`ifdef OR1200_EXCEPT_FLOAT
579,6 → 594,7
14'b00_0000_0000_01??: begin
except_type <= `OR1200_EXCEPT_FLOAT;
epcr <= id_pc;
dsx <= ex_dslot;
end
`endif
`ifdef OR1200_EXCEPT_INT
585,6 → 601,7
14'b00_0000_0000_001?: begin
except_type <= `OR1200_EXCEPT_INT;
epcr <= id_pc;
dsx <= ex_dslot;
end
`endif
`ifdef OR1200_EXCEPT_TICK
591,6 → 608,7
14'b00_0000_0000_0001: begin
except_type <= `OR1200_EXCEPT_TICK;
epcr <= id_pc;
dsx <= ex_dslot;
end
`endif
default:
/sim/bin/Makefile
67,6 → 67,8
or1200-cy \
or1200-ov \
or1200-sf \
or1200-dsx \
or1200-dsxinsn \
or1200-ffl1 \
or1200-linkregtest \
or1200-tick \
/sw/tests/or1200/sim/or1200-dsx.S
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 <juliusbaxter@gmail.com>
*/
//////////////////////////////////////////////////////////////////////
//// ////
//// 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
/sw/tests/or1200/sim/or1200-dsxinsn.S
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 <juliusbaxter@gmail.com>
*/
//////////////////////////////////////////////////////////////////////
//// ////
//// 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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.