URL
https://opencores.org/ocsvn/amber/amber/trunk
Subversion Repositories amber
Compare Revisions
- This comparison shows the changes necessary to convert path
/amber
- from Rev 59 to Rev 60
- ↔ Reverse comparison
Rev 59 → Rev 60
/trunk/hw/tests/irq_disable.S
0,0 → 1,249
/***************************************************************** |
// // |
// Amber 2 Core Interrupt Test // |
// // |
// This file is part of the Amber project // |
// http://www.opencores.org/project,amber // |
// // |
// Description // |
// Tests running a simple algorithm to add a bunch of numbers // |
// and check that the result is correct. This algorithm runs // |
// 80 times. During this, a whole bunch of IRQ interrupts are // |
// triggered using the random timer. // |
// // |
// The test passes if the add algorithm runs successfully // |
// each time. // |
// // |
// Author(s): // |
// - Conor Santifort, csantifort.amber@gmail.com // |
// // |
////////////////////////////////////////////////////////////////// |
// // |
// Copyright (C) 2010 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 "amber_registers.h" |
|
.section .text |
.globl main |
main: |
|
/* 0x00 Reset Interrupt vector address */ |
b start |
|
/* 0x04 Undefined Instruction Interrupt vector address */ |
b testfail |
|
/* 0x08 SWI Interrupt vector address */ |
b testfail |
|
/* 0x0c Prefetch abort Interrupt vector address */ |
b testfail |
|
/* 0x10 Data abort Interrupt vector address */ |
b testfail |
b testfail |
|
/* 0x18 IRQ vector address */ |
b service_irq |
|
/* 0x1c FIRQ vector address */ |
b testfail |
|
/* This doesn't actually disabe the irq because |
you can't disable it uin user mode */ |
disable_irq: |
orr lr, lr, #0x08000000 |
mov pc, lr |
|
start: |
/* Set Supervisor Mode stack pointer */ |
ldr sp, AdrSVCStack |
|
/* Test that lr is immediately accessible after a mode switch */ |
mov lr, #0x8000 |
mov r0, #0x08000002 |
teqp pc, r0 @ move to irq mode |
nop |
nop |
|
@ Switch back to supervisor mode |
mov r0, #0x08000003 |
teqp pc, r0 |
sub lr, lr, #4 @ access lr immediately after mode switch |
|
mov r0, #0x8000 |
sub r0, r0, #4 |
cmp lr, r0 |
movne r10, #200 |
bne testfail |
|
/* Switch to IRQ Mode */ |
mov r0, #0x00000002 |
teqp pc, r0 |
/* Set IRQ Mode stack pointer */ |
ldr sp, AdrIRQStack |
|
/* Switch to User Mode */ |
/* and unset interrupt mask bits */ |
mov r0, #0x00000000 |
teqp pc, r0 |
|
bl disable_irq |
|
/* Set User Mode stack pointer */ |
ldr sp, AdrUSRStack |
|
ldr r4, AdrRanNum |
ldr r5, [r4] |
and r5, r5, #0x1c |
add r5, r5, #5 |
ldr r6, AdrIRQTimer |
str r5, [r6] |
|
mov r2, #0 |
|
loop: |
@ set some condition bits |
@ to test that these get preserved |
@ correctly through interrupts |
mov r3, #4 |
subs r3, r3, #4 |
|
mov r1, #1 |
add r1, r1, #2 |
add r1, r1, #3 |
add r1, r1, #4 |
addeq r1, r1, #5 |
add r1, r1, #6 |
add r1, r1, #7 |
addeq r1, r1, #8 |
add r1, r1, #9 |
add r1, r1, #10 |
add r1, r1, #11 |
add r1, r1, #12 |
|
mov r7, #13 |
mov r8, #14 |
mov r9, #15 |
|
stmfd sp!, {r7, r8, r9} |
mov r7, #0 |
mov r8, #0 |
mov r9, #0 |
ldmfd sp!, {r7, r8, r9} |
|
add r1, r1, r7 |
add r1, r1, r8 |
add r1, r1, r9 |
|
add r1, r1, #16 |
add r1, r1, #17 |
add r1, r1, #18 |
add r1, r1, #19 |
add r1, r1, #20 |
add r1, r1, #21 |
add r1, r1, #22 |
add r1, r1, #23 |
add r1, r1, #24 |
add r1, r1, #25 |
add r1, r1, #26 |
add r1, r1, #27 |
add r1, r1, #28 |
add r1, r1, #29 |
add r1, r1, #30 |
add r1, r1, #47 @ adds up to exactly 512 |
|
cmp r1, #512 |
movne r10, r2 |
bne testfail |
|
cmp r2, #80 |
beq testpass |
|
add r2, r2, #1 |
b loop |
|
@ just put these here in case |
@ the cpu incorrectly executes some instructions |
b testfail |
b testfail |
b testfail |
|
|
service_irq: |
@ Save lr to the stack |
stmfd sp!, {lr} |
|
@ Set the IRQ Timer to a random number |
ldr r5, [r4] |
and r5, r5, #0x7f |
|
@ Ensure that never set the IRQ timer to zero |
add r5, r5, #30 |
str r5, [r6] |
|
@ Restore lr from the stack |
ldmfd sp!, {lr} |
|
@ Jump straight back to normal execution |
subs pc, lr, #4 |
|
@ ------------------------------------------ |
@ ------------------------------------------ |
|
testfail: |
ldr r11, AdrTestStatus |
str r10, [r11] |
b testfail |
|
testpass: |
ldr r11, AdrTestStatus |
mov r10, #17 |
str r10, [r11] |
b testpass |
|
|
|
|
/* Write 17 to this address to generate a Test Passed message */ |
AdrTestStatus: .word ADR_AMBER_TEST_STATUS |
AdrRanNum: .word ADR_AMBER_TEST_RANDOM_NUM |
AdrIRQTimer: .word ADR_AMBER_TEST_IRQ_TIMER |
|
AdrText1: .word Text1 |
|
AdrSVCStack: .word 0x0800 |
AdrUSRStack: .word 0x1000 |
AdrIRQStack: .word 0x1800 |
|
|
.align 2 |
Text1: .ascii "Interrupt!\n\000" |
|
/* ========================================================================= */ |
/* ========================================================================= */ |
|
|
/trunk/hw/vlog/amber25/a25_dcache.v
474,13 → 474,14
data_wdata_r[127: 96] ; |
|
|
assign con_write_data_word = i_byte_enable == 4'b0001 ? { con_read_data_word[31: 8], i_write_data[ 7: 0] } : |
i_byte_enable == 4'b0010 ? { con_read_data_word[31:16], i_write_data[15: 8], con_read_data_word[ 7:0]} : |
i_byte_enable == 4'b0100 ? { con_read_data_word[31:24], i_write_data[23:16], con_read_data_word[15:0]} : |
i_byte_enable == 4'b1000 ? { i_write_data[31:24], con_read_data_word[23:0]} : |
i_byte_enable == 4'b0011 ? { con_read_data_word[31:16], i_write_data[15: 0] } : |
i_byte_enable == 4'b1100 ? { i_write_data[31:16], con_read_data_word[15:0]} : |
i_write_data ; |
assign con_write_data_word = |
i_byte_enable == 4'b0001 ? { con_read_data_word[31: 8], i_write_data[ 7: 0] } : |
i_byte_enable == 4'b0010 ? { con_read_data_word[31:16], i_write_data[15: 8], con_read_data_word[ 7:0]} : |
i_byte_enable == 4'b0100 ? { con_read_data_word[31:24], i_write_data[23:16], con_read_data_word[15:0]} : |
i_byte_enable == 4'b1000 ? { i_write_data[31:24], con_read_data_word[23:0]} : |
i_byte_enable == 4'b0011 ? { con_read_data_word[31:16], i_write_data[15: 0] } : |
i_byte_enable == 4'b1100 ? { i_write_data[31:16], con_read_data_word[15:0]} : |
i_write_data ; |
|
|
|
/trunk/hw/vlog/amber25/a25_mem.v
114,8 → 114,8
assign address_cachable = in_cachable_mem( i_daddress ) && i_cacheable_area[i_daddress[25:21]]; |
assign sel_cache_p = daddress_valid_p && address_cachable && i_cache_enable && !i_exclusive; |
assign sel_cache = i_daddress_valid && address_cachable && i_cache_enable && !i_exclusive; |
assign uncached_data_access = i_daddress_valid && !sel_cache && !(cache_stall); |
assign uncached_data_access_p = daddress_valid_p && !sel_cache && !(cache_stall); |
assign uncached_data_access = i_daddress_valid && !sel_cache && !cache_stall; |
assign uncached_data_access_p = daddress_valid_p && !sel_cache; |
|
assign use_mem_reg = wb_stop && !mem_stall_r; |
assign o_mem_read_data = use_mem_reg ? mem_read_data_r : mem_read_data_c; |
170,7 → 170,7
|
always @( posedge i_clk ) |
begin |
uncached_wb_stop_r <= (uncached_wb_stop_r || uncached_data_access_p) && (i_fetch_stall || o_mem_stall); |
uncached_wb_stop_r <= (uncached_wb_stop_r || (uncached_data_access_p&&!cache_stall)) && (i_fetch_stall || o_mem_stall); |
cached_wb_stop_r <= (cached_wb_stop_r || cached_wb_req) && (i_fetch_stall || o_mem_stall); |
daddress_valid_stop_r <= (daddress_valid_stop_r || daddress_valid_p) && (i_fetch_stall || o_mem_stall); |
// hold this until the mem access completes |
/trunk/hw/vlog/amber25/a25_decode.v
288,6 → 288,7
wire use_hold_instruction; |
wire use_pre_fetch_instruction; |
wire interrupt; |
wire interrupt_or_conflict; |
wire [1:0] interrupt_mode; |
wire [2:0] next_interrupt; |
reg irq = 'd0; |
457,7 → 458,12
(type == MULT && |
(control_state == MULT_PROC1 || |
control_state == MULT_PROC2 || |
instruction_valid && !interrupt )) ; |
// instruction_valid && !interrupt )) ; |
// remove the '!conflict' term from the interrupt logic used here |
// to break a combinational loop |
(instruction_valid && !interrupt_or_conflict))) ; |
|
|
assign branch = type == BRANCH; |
assign opcode_compare = opcode == CMP || opcode == CMN || opcode == TEQ || opcode == TST ; |
assign mem_op = type == TRANS; |
687,9 → 693,10
swi_request ? 3'd7 : // SWI |
3'd0 ; // none |
|
// SWI and undefined instructions do not cause an interrupt in the decode |
// stage. They only trigger interrupts if they arfe executed, so the |
// interrupt is triggered if the execute condition is met in the execute stage |
|
// SWI and undefined instructions do not cause an interrupt in the decode |
// stage. They only trigger interrupts if they arfe executed, so the |
// interrupt is triggered if the execute condition is met in the execute stage |
assign interrupt = next_interrupt != 3'd0 && |
next_interrupt != 3'd7 && // SWI |
next_interrupt != 3'd6 && // undefined interrupt |
696,6 → 703,14
!conflict ; // Wait for conflicts to resolve before |
// triggering int |
|
|
// Added to use in rds_use_rs logic to break a combinational loop invloving |
// the conflict signal |
assign interrupt_or_conflict |
= next_interrupt != 3'd0 && |
next_interrupt != 3'd7 && // SWI |
next_interrupt != 3'd6 ; // undefined interrupt |
|
assign interrupt_mode = next_interrupt == 3'd2 ? FIRQ : |
next_interrupt == 3'd3 ? IRQ : |
next_interrupt == 3'd4 ? SVC : |
706,8 → 721,6
USR ; |
|
|
|
|
// ======================================================== |
// Generate control signals |
// ======================================================== |