OpenCores
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
// ========================================================

powered by: WebSVN 2.1.0

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