mirror of
https://github.com/AsahiLinux/u-boot
synced 2024-11-28 07:31:15 +00:00
84ad688473
Signed-off-by: Peter Tyser <ptyser@xes-inc.com>
806 lines
23 KiB
C
806 lines
23 KiB
C
/**
|
|
* @file IxNpeDlNpeMgrUtils.c
|
|
*
|
|
* @author Intel Corporation
|
|
* @date 18 February 2002
|
|
*
|
|
* @brief This file contains the implementation of the private API for the
|
|
* IXP425 NPE Downloader NpeMgr Utils module
|
|
*
|
|
*
|
|
* @par
|
|
* IXP400 SW Release version 2.0
|
|
*
|
|
* -- Copyright Notice --
|
|
*
|
|
* @par
|
|
* Copyright 2001-2005, Intel Corporation.
|
|
* All rights reserved.
|
|
*
|
|
* @par
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. Neither the name of the Intel Corporation nor the names of its contributors
|
|
* may be used to endorse or promote products derived from this software
|
|
* without specific prior written permission.
|
|
*
|
|
* @par
|
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
|
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*
|
|
* @par
|
|
* -- End of Copyright Notice --
|
|
*/
|
|
|
|
|
|
/*
|
|
* Put the system defined include files required.
|
|
*/
|
|
#define IX_NPE_DL_MAX_NUM_OF_RETRIES 1000000 /**< Maximum number of
|
|
* retries before
|
|
* timeout
|
|
*/
|
|
|
|
/*
|
|
* Put the user defined include files required.
|
|
*/
|
|
#include "IxOsal.h"
|
|
#include "IxNpeDl.h"
|
|
#include "IxNpeDlNpeMgrUtils_p.h"
|
|
#include "IxNpeDlNpeMgrEcRegisters_p.h"
|
|
#include "IxNpeDlMacros_p.h"
|
|
|
|
/*
|
|
* #defines and macros used in this file.
|
|
*/
|
|
|
|
/* used to bit-mask a number of bytes */
|
|
#define IX_NPEDL_MASK_LOWER_BYTE_OF_WORD 0x000000FF
|
|
#define IX_NPEDL_MASK_LOWER_SHORT_OF_WORD 0x0000FFFF
|
|
#define IX_NPEDL_MASK_FULL_WORD 0xFFFFFFFF
|
|
|
|
#define IX_NPEDL_BYTES_PER_WORD 4
|
|
#define IX_NPEDL_BYTES_PER_SHORT 2
|
|
|
|
#define IX_NPEDL_REG_SIZE_BYTE 8
|
|
#define IX_NPEDL_REG_SIZE_SHORT 16
|
|
#define IX_NPEDL_REG_SIZE_WORD 32
|
|
|
|
/*
|
|
* Introduce extra read cycles after issuing read command to NPE
|
|
* so that we read the register after the NPE has updated it
|
|
* This is to overcome race condition between XScale and NPE
|
|
*/
|
|
#define IX_NPEDL_DELAY_READ_CYCLES 2
|
|
/*
|
|
* To mask top three MSBs of 32bit word to download into NPE IMEM
|
|
*/
|
|
#define IX_NPEDL_MASK_UNUSED_IMEM_BITS 0x1FFFFFFF;
|
|
|
|
|
|
/*
|
|
* typedefs
|
|
*/
|
|
typedef struct
|
|
{
|
|
UINT32 regAddress;
|
|
UINT32 regSize;
|
|
} IxNpeDlCtxtRegAccessInfo;
|
|
|
|
/* module statistics counters */
|
|
typedef struct
|
|
{
|
|
UINT32 insMemWrites;
|
|
UINT32 insMemWriteFails;
|
|
UINT32 dataMemWrites;
|
|
UINT32 dataMemWriteFails;
|
|
UINT32 ecsRegWrites;
|
|
UINT32 ecsRegReads;
|
|
UINT32 dbgInstructionExecs;
|
|
UINT32 contextRegWrites;
|
|
UINT32 physicalRegWrites;
|
|
UINT32 nextPcWrites;
|
|
} IxNpeDlNpeMgrUtilsStats;
|
|
|
|
|
|
/*
|
|
* Variable declarations global to this file only. Externs are followed by
|
|
* static variables.
|
|
*/
|
|
|
|
/*
|
|
* contains useful address and function pointers to read/write Context Regs,
|
|
* eliminating some switch or if-else statements in places
|
|
*/
|
|
static IxNpeDlCtxtRegAccessInfo ixNpeDlCtxtRegAccInfo[IX_NPEDL_CTXT_REG_MAX] =
|
|
{
|
|
{
|
|
IX_NPEDL_CTXT_REG_ADDR_STEVT,
|
|
IX_NPEDL_REG_SIZE_BYTE
|
|
},
|
|
{
|
|
IX_NPEDL_CTXT_REG_ADDR_STARTPC,
|
|
IX_NPEDL_REG_SIZE_SHORT
|
|
},
|
|
{
|
|
IX_NPEDL_CTXT_REG_ADDR_REGMAP,
|
|
IX_NPEDL_REG_SIZE_SHORT
|
|
},
|
|
{
|
|
IX_NPEDL_CTXT_REG_ADDR_CINDEX,
|
|
IX_NPEDL_REG_SIZE_BYTE
|
|
}
|
|
};
|
|
|
|
static UINT32 ixNpeDlSavedExecCount = 0;
|
|
static UINT32 ixNpeDlSavedEcsDbgCtxtReg2 = 0;
|
|
|
|
static IxNpeDlNpeMgrUtilsStats ixNpeDlNpeMgrUtilsStats;
|
|
|
|
|
|
/*
|
|
* static function prototypes.
|
|
*/
|
|
PRIVATE __inline__ void
|
|
ixNpeDlNpeMgrWriteCommandIssue (UINT32 npeBaseAddress, UINT32 cmd,
|
|
UINT32 addr, UINT32 data);
|
|
|
|
PRIVATE __inline__ UINT32
|
|
ixNpeDlNpeMgrReadCommandIssue (UINT32 npeBaseAddress, UINT32 cmd, UINT32 addr);
|
|
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrLogicalRegRead (UINT32 npeBaseAddress, UINT32 regAddr,
|
|
UINT32 regSize, UINT32 ctxtNum, UINT32 *regVal);
|
|
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrLogicalRegWrite (UINT32 npeBaseAddress, UINT32 regAddr,
|
|
UINT32 regVal, UINT32 regSize,
|
|
UINT32 ctxtNum, BOOL verify);
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrWriteCommandIssue
|
|
*/
|
|
PRIVATE __inline__ void
|
|
ixNpeDlNpeMgrWriteCommandIssue (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 cmd,
|
|
UINT32 addr,
|
|
UINT32 data)
|
|
{
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, data);
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXAD, addr);
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrReadCommandIssue
|
|
*/
|
|
PRIVATE __inline__ UINT32
|
|
ixNpeDlNpeMgrReadCommandIssue (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 cmd,
|
|
UINT32 addr)
|
|
{
|
|
UINT32 data = 0;
|
|
int i;
|
|
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXAD, addr);
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, cmd);
|
|
for (i = 0; i <= IX_NPEDL_DELAY_READ_CYCLES; i++)
|
|
{
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, &data);
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrInsMemWrite
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrInsMemWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 insMemAddress,
|
|
UINT32 insMemData,
|
|
BOOL verify)
|
|
{
|
|
UINT32 insMemDataRtn;
|
|
|
|
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_WR_INS_MEM,
|
|
insMemAddress, insMemData);
|
|
if (verify)
|
|
{
|
|
/* write invalid data to this reg, so we can see if we're reading
|
|
the EXDATA register too early */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA,
|
|
~insMemData);
|
|
|
|
/*Disabled since top 3 MSB are not used for Azusa hardware Refer WR:IXA00053900*/
|
|
insMemData&=IX_NPEDL_MASK_UNUSED_IMEM_BITS;
|
|
|
|
insMemDataRtn=ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_RD_INS_MEM,
|
|
insMemAddress);
|
|
|
|
insMemDataRtn&=IX_NPEDL_MASK_UNUSED_IMEM_BITS;
|
|
|
|
if (insMemData != insMemDataRtn)
|
|
{
|
|
ixNpeDlNpeMgrUtilsStats.insMemWriteFails++;
|
|
return IX_FAIL;
|
|
}
|
|
}
|
|
|
|
ixNpeDlNpeMgrUtilsStats.insMemWrites++;
|
|
return IX_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrDataMemWrite
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrDataMemWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 dataMemAddress,
|
|
UINT32 dataMemData,
|
|
BOOL verify)
|
|
{
|
|
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_WR_DATA_MEM,
|
|
dataMemAddress, dataMemData);
|
|
if (verify)
|
|
{
|
|
/* write invalid data to this reg, so we can see if we're reading
|
|
the EXDATA register too early */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, ~dataMemData);
|
|
|
|
if (dataMemData !=
|
|
ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_RD_DATA_MEM,
|
|
dataMemAddress))
|
|
{
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails++;
|
|
return IX_FAIL;
|
|
}
|
|
}
|
|
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWrites++;
|
|
return IX_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrExecAccRegWrite
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrExecAccRegWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regAddress,
|
|
UINT32 regData)
|
|
{
|
|
ixNpeDlNpeMgrWriteCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_WR_ECS_REG,
|
|
regAddress, regData);
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegWrites++;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrExecAccRegRead
|
|
*/
|
|
UINT32
|
|
ixNpeDlNpeMgrExecAccRegRead (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regAddress)
|
|
{
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegReads++;
|
|
return ixNpeDlNpeMgrReadCommandIssue (npeBaseAddress,
|
|
IX_NPEDL_EXCTL_CMD_RD_ECS_REG,
|
|
regAddress);
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrCommandIssue
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrCommandIssue (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 command)
|
|
{
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrCommandIssue\n");
|
|
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCTL, command);
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrCommandIssue\n");
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrDebugInstructionPreExec
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrDebugInstructionPreExec(
|
|
UINT32 npeBaseAddress)
|
|
{
|
|
/* turn off the halt bit by clearing Execution Count register. */
|
|
/* save reg contents 1st and restore later */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT,
|
|
&ixNpeDlSavedExecCount);
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT, 0);
|
|
|
|
/* ensure that IF and IE are on (temporarily), so that we don't end up
|
|
* stepping forever */
|
|
ixNpeDlSavedEcsDbgCtxtReg2 = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
|
IX_NPEDL_ECS_DBG_CTXT_REG_2);
|
|
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_2,
|
|
(ixNpeDlSavedEcsDbgCtxtReg2 |
|
|
IX_NPEDL_MASK_ECS_DBG_REG_2_IF |
|
|
IX_NPEDL_MASK_ECS_DBG_REG_2_IE));
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrDebugInstructionExec
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrDebugInstructionExec(
|
|
UINT32 npeBaseAddress,
|
|
UINT32 npeInstruction,
|
|
UINT32 ctxtNum,
|
|
UINT32 ldur)
|
|
{
|
|
UINT32 ecsDbgRegVal;
|
|
UINT32 oldWatchcount, newWatchcount;
|
|
UINT32 retriesCount = 0;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrDebugInstructionExec\n");
|
|
|
|
/* set the Active bit, and the LDUR, in the debug level */
|
|
ecsDbgRegVal = IX_NPEDL_MASK_ECS_REG_0_ACTIVE |
|
|
(ldur << IX_NPEDL_OFFSET_ECS_REG_0_LDUR);
|
|
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
|
ecsDbgRegVal);
|
|
|
|
/*
|
|
* set CCTXT at ECS DEBUG L3 to specify in which context to execute the
|
|
* instruction, and set SELCTXT at ECS DEBUG Level to specify which context
|
|
* store to access.
|
|
* Debug ECS Level Reg 1 has form 0x000n000n, where n = context number
|
|
*/
|
|
ecsDbgRegVal = (ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_CCTXT) |
|
|
(ctxtNum << IX_NPEDL_OFFSET_ECS_REG_1_SELCTXT);
|
|
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_1,
|
|
ecsDbgRegVal);
|
|
|
|
/* clear the pipeline */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
|
|
|
/* load NPE instruction into the instruction register */
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_INSTRUCT_REG,
|
|
npeInstruction);
|
|
|
|
/* we need this value later to wait for completion of NPE execution step */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC, &oldWatchcount);
|
|
|
|
/* issue a Step One command via the Execution Control register */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_STEP);
|
|
|
|
/* Watch Count register increments when NPE completes an instruction */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC,
|
|
&newWatchcount);
|
|
|
|
/*
|
|
* force the XScale to wait until the NPE has finished execution step
|
|
* NOTE that this delay will be very small, just long enough to allow a
|
|
* single NPE instruction to complete execution; if instruction execution
|
|
* is not completed before timeout retries, exit the while loop
|
|
*/
|
|
while ((IX_NPE_DL_MAX_NUM_OF_RETRIES > retriesCount)
|
|
&& (newWatchcount == oldWatchcount))
|
|
{
|
|
/* Watch Count register increments when NPE completes an instruction */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_WC,
|
|
&newWatchcount);
|
|
|
|
retriesCount++;
|
|
}
|
|
|
|
if (IX_NPE_DL_MAX_NUM_OF_RETRIES > retriesCount)
|
|
{
|
|
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs++;
|
|
}
|
|
else
|
|
{
|
|
/* Return timeout status as the instruction has not been executed
|
|
* after maximum retries */
|
|
status = IX_NPEDL_CRITICAL_NPE_ERR;
|
|
}
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrDebugInstructionExec\n");
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrDebugInstructionPostExec
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrDebugInstructionPostExec(
|
|
UINT32 npeBaseAddress)
|
|
{
|
|
/* clear active bit in debug level */
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_0,
|
|
0);
|
|
|
|
/* clear the pipeline */
|
|
ixNpeDlNpeMgrCommandIssue (npeBaseAddress, IX_NPEDL_EXCTL_CMD_NPE_CLR_PIPE);
|
|
|
|
/* restore Execution Count register contents. */
|
|
IX_NPEDL_REG_WRITE (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXCT,
|
|
ixNpeDlSavedExecCount);
|
|
|
|
/* restore IF and IE bits to original values */
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress, IX_NPEDL_ECS_DBG_CTXT_REG_2,
|
|
ixNpeDlSavedEcsDbgCtxtReg2);
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrLogicalRegRead
|
|
*/
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrLogicalRegRead (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regAddr,
|
|
UINT32 regSize,
|
|
UINT32 ctxtNum,
|
|
UINT32 *regVal)
|
|
{
|
|
IX_STATUS status = IX_SUCCESS;
|
|
UINT32 npeInstruction = 0;
|
|
UINT32 mask = 0;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrLogicalRegRead\n");
|
|
|
|
switch (regSize)
|
|
{
|
|
case IX_NPEDL_REG_SIZE_BYTE:
|
|
npeInstruction = IX_NPEDL_INSTR_RD_REG_BYTE;
|
|
mask = IX_NPEDL_MASK_LOWER_BYTE_OF_WORD; break;
|
|
case IX_NPEDL_REG_SIZE_SHORT:
|
|
npeInstruction = IX_NPEDL_INSTR_RD_REG_SHORT;
|
|
mask = IX_NPEDL_MASK_LOWER_SHORT_OF_WORD; break;
|
|
case IX_NPEDL_REG_SIZE_WORD:
|
|
npeInstruction = IX_NPEDL_INSTR_RD_REG_WORD;
|
|
mask = IX_NPEDL_MASK_FULL_WORD; break;
|
|
}
|
|
|
|
/* make regAddr be the SRC and DEST operands (e.g. movX d0, d0) */
|
|
npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_SRC) |
|
|
(regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
|
|
|
|
/* step execution of NPE intruction using Debug Executing Context stack */
|
|
status = ixNpeDlNpeMgrDebugInstructionExec (npeBaseAddress, npeInstruction,
|
|
ctxtNum, IX_NPEDL_RD_INSTR_LDUR);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* read value of register from Execution Data register */
|
|
IX_NPEDL_REG_READ (npeBaseAddress, IX_NPEDL_REG_OFFSET_EXDATA, regVal);
|
|
|
|
/* align value from left to right */
|
|
*regVal = (*regVal >> (IX_NPEDL_REG_SIZE_WORD - regSize)) & mask;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrLogicalRegRead\n");
|
|
|
|
return IX_SUCCESS;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrLogicalRegWrite
|
|
*/
|
|
PRIVATE IX_STATUS
|
|
ixNpeDlNpeMgrLogicalRegWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regAddr,
|
|
UINT32 regVal,
|
|
UINT32 regSize,
|
|
UINT32 ctxtNum,
|
|
BOOL verify)
|
|
{
|
|
UINT32 npeInstruction = 0;
|
|
UINT32 mask = 0;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
UINT32 retRegVal;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrLogicalRegWrite\n");
|
|
|
|
if (regSize == IX_NPEDL_REG_SIZE_WORD)
|
|
{
|
|
/* NPE register addressing is left-to-right: e.g. |d0|d1|d2|d3| */
|
|
/* Write upper half-word (short) to |d0|d1| */
|
|
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, regAddr,
|
|
regVal >> IX_NPEDL_REG_SIZE_SHORT,
|
|
IX_NPEDL_REG_SIZE_SHORT,
|
|
ctxtNum, verify);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
|
|
/* Write lower half-word (short) to |d2|d3| */
|
|
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress,
|
|
regAddr + IX_NPEDL_BYTES_PER_SHORT,
|
|
regVal & IX_NPEDL_MASK_LOWER_SHORT_OF_WORD,
|
|
IX_NPEDL_REG_SIZE_SHORT,
|
|
ctxtNum, verify);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (regSize)
|
|
{
|
|
case IX_NPEDL_REG_SIZE_BYTE:
|
|
npeInstruction = IX_NPEDL_INSTR_WR_REG_BYTE;
|
|
mask = IX_NPEDL_MASK_LOWER_BYTE_OF_WORD; break;
|
|
case IX_NPEDL_REG_SIZE_SHORT:
|
|
npeInstruction = IX_NPEDL_INSTR_WR_REG_SHORT;
|
|
mask = IX_NPEDL_MASK_LOWER_SHORT_OF_WORD; break;
|
|
}
|
|
/* mask out any redundant bits, so verify will work later */
|
|
regVal &= mask;
|
|
|
|
/* fill dest operand field of instruction with destination reg addr */
|
|
npeInstruction |= (regAddr << IX_NPEDL_OFFSET_INSTR_DEST);
|
|
|
|
/* fill src operand field of instruction with least-sig 5 bits of val*/
|
|
npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_SRC_DATA) <<
|
|
IX_NPEDL_OFFSET_INSTR_SRC);
|
|
|
|
/* fill coprocessor field of instruction with most-sig 11 bits of val*/
|
|
npeInstruction |= ((regVal & IX_NPEDL_MASK_IMMED_INSTR_COPROC_DATA) <<
|
|
IX_NPEDL_DISPLACE_IMMED_INSTR_COPROC_DATA);
|
|
|
|
/* step execution of NPE intruction using Debug ECS */
|
|
status = ixNpeDlNpeMgrDebugInstructionExec(npeBaseAddress, npeInstruction,
|
|
ctxtNum, IX_NPEDL_WR_INSTR_LDUR);
|
|
|
|
if (IX_SUCCESS != status)
|
|
{
|
|
return status;
|
|
}
|
|
}/* condition: if reg to be written is 8-bit or 16-bit (not 32-bit) */
|
|
|
|
if (verify)
|
|
{
|
|
status = ixNpeDlNpeMgrLogicalRegRead (npeBaseAddress, regAddr,
|
|
regSize, ctxtNum, &retRegVal);
|
|
|
|
if (IX_SUCCESS == status)
|
|
{
|
|
if (regVal != retRegVal)
|
|
{
|
|
status = IX_FAIL;
|
|
}
|
|
}
|
|
}
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrLogicalRegWrite : status = %d\n",
|
|
status);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrPhysicalRegWrite
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrPhysicalRegWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 regAddr,
|
|
UINT32 regValue,
|
|
BOOL verify)
|
|
{
|
|
IX_STATUS status;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrPhysicalRegWrite\n");
|
|
|
|
/*
|
|
* There are 32 physical registers used in an NPE. These are
|
|
* treated as 16 pairs of 32-bit registers. To write one of the pair,
|
|
* write the pair number (0-16) to the REGMAP for Context 0. Then write
|
|
* the value to register 0 or 4 in the regfile, depending on which
|
|
* register of the pair is to be written
|
|
*/
|
|
|
|
/*
|
|
* set REGMAP for context 0 to (regAddr >> 1) to choose which pair (0-16)
|
|
* of physical registers to write
|
|
*/
|
|
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress,
|
|
IX_NPEDL_CTXT_REG_ADDR_REGMAP,
|
|
(regAddr >>
|
|
IX_NPEDL_OFFSET_PHYS_REG_ADDR_REGMAP),
|
|
IX_NPEDL_REG_SIZE_SHORT, 0, verify);
|
|
if (status == IX_SUCCESS)
|
|
{
|
|
/* regAddr = 0 or 4 */
|
|
regAddr = (regAddr & IX_NPEDL_MASK_PHYS_REG_ADDR_LOGICAL_ADDR) *
|
|
IX_NPEDL_BYTES_PER_WORD;
|
|
|
|
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, regAddr, regValue,
|
|
IX_NPEDL_REG_SIZE_WORD, 0, verify);
|
|
}
|
|
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrPhysicalRegWrite: "
|
|
"error writing to physical register\n");
|
|
}
|
|
|
|
ixNpeDlNpeMgrUtilsStats.physicalRegWrites++;
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrPhysicalRegWrite : status = %d\n",
|
|
status);
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrCtxtRegWrite
|
|
*/
|
|
IX_STATUS
|
|
ixNpeDlNpeMgrCtxtRegWrite (
|
|
UINT32 npeBaseAddress,
|
|
UINT32 ctxtNum,
|
|
IxNpeDlCtxtRegNum ctxtReg,
|
|
UINT32 ctxtRegVal,
|
|
BOOL verify)
|
|
{
|
|
UINT32 tempRegVal;
|
|
UINT32 ctxtRegAddr;
|
|
UINT32 ctxtRegSize;
|
|
IX_STATUS status = IX_SUCCESS;
|
|
|
|
IX_NPEDL_TRACE0 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Entering ixNpeDlNpeMgrCtxtRegWrite\n");
|
|
|
|
/*
|
|
* Context 0 has no STARTPC. Instead, this value is used to set
|
|
* NextPC for Background ECS, to set where NPE starts executing code
|
|
*/
|
|
if ((ctxtNum == 0) && (ctxtReg == IX_NPEDL_CTXT_REG_STARTPC))
|
|
{
|
|
/* read BG_CTXT_REG_0, update NEXTPC bits, and write back to reg */
|
|
tempRegVal = ixNpeDlNpeMgrExecAccRegRead (npeBaseAddress,
|
|
IX_NPEDL_ECS_BG_CTXT_REG_0);
|
|
tempRegVal &= ~IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
|
|
tempRegVal |= (ctxtRegVal << IX_NPEDL_OFFSET_ECS_REG_0_NEXTPC) &
|
|
IX_NPEDL_MASK_ECS_REG_0_NEXTPC;
|
|
|
|
ixNpeDlNpeMgrExecAccRegWrite (npeBaseAddress,
|
|
IX_NPEDL_ECS_BG_CTXT_REG_0, tempRegVal);
|
|
|
|
ixNpeDlNpeMgrUtilsStats.nextPcWrites++;
|
|
}
|
|
else
|
|
{
|
|
ctxtRegAddr = ixNpeDlCtxtRegAccInfo[ctxtReg].regAddress;
|
|
ctxtRegSize = ixNpeDlCtxtRegAccInfo[ctxtReg].regSize;
|
|
status = ixNpeDlNpeMgrLogicalRegWrite (npeBaseAddress, ctxtRegAddr,
|
|
ctxtRegVal, ctxtRegSize,
|
|
ctxtNum, verify);
|
|
if (status != IX_SUCCESS)
|
|
{
|
|
IX_NPEDL_ERROR_REPORT ("ixNpeDlNpeMgrCtxtRegWrite: "
|
|
"error writing to context store register\n");
|
|
}
|
|
|
|
ixNpeDlNpeMgrUtilsStats.contextRegWrites++;
|
|
}
|
|
|
|
IX_NPEDL_TRACE1 (IX_NPEDL_FN_ENTRY_EXIT,
|
|
"Exiting ixNpeDlNpeMgrCtxtRegWrite : status = %d\n",
|
|
status);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrUtilsStatsShow
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrUtilsStatsShow (void)
|
|
{
|
|
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
|
IX_OSAL_LOG_DEV_STDOUT,
|
|
"\nixNpeDlNpeMgrUtilsStatsShow:\n"
|
|
"\tInstruction Memory writes: %u\n"
|
|
"\tInstruction Memory writes failed: %u\n"
|
|
"\tData Memory writes: %u\n"
|
|
"\tData Memory writes failed: %u\n",
|
|
ixNpeDlNpeMgrUtilsStats.insMemWrites,
|
|
ixNpeDlNpeMgrUtilsStats.insMemWriteFails,
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWrites,
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails,
|
|
0,0);
|
|
|
|
ixOsalLog (IX_OSAL_LOG_LVL_USER,
|
|
IX_OSAL_LOG_DEV_STDOUT,
|
|
"\tExecuting Context Stack Register writes: %u\n"
|
|
"\tExecuting Context Stack Register reads: %u\n"
|
|
"\tPhysical Register writes: %u\n"
|
|
"\tContext Store Register writes: %u\n"
|
|
"\tExecution Backgound Context NextPC writes: %u\n"
|
|
"\tDebug Instructions Executed: %u\n\n",
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegWrites,
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegReads,
|
|
ixNpeDlNpeMgrUtilsStats.physicalRegWrites,
|
|
ixNpeDlNpeMgrUtilsStats.contextRegWrites,
|
|
ixNpeDlNpeMgrUtilsStats.nextPcWrites,
|
|
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs);
|
|
}
|
|
|
|
|
|
/*
|
|
* Function definition: ixNpeDlNpeMgrUtilsStatsReset
|
|
*/
|
|
void
|
|
ixNpeDlNpeMgrUtilsStatsReset (void)
|
|
{
|
|
ixNpeDlNpeMgrUtilsStats.insMemWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.insMemWriteFails = 0;
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.dataMemWriteFails = 0;
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.ecsRegReads = 0;
|
|
ixNpeDlNpeMgrUtilsStats.physicalRegWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.contextRegWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.nextPcWrites = 0;
|
|
ixNpeDlNpeMgrUtilsStats.dbgInstructionExecs = 0;
|
|
}
|