Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / devices / n2_ncu / ncu.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: ncu.cc
// Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
// DO NOT ALTER OR REMOVE COPYRIGHT NOTICES.
//
// The above named program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License version 2 as published by the Free Software Foundation.
//
// The above named program 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
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this work; if not, write to the Free Software
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
//
// ========== Copyright Header End ============================================
#include "ncu.h"
static const char *n2ncu_help = "SAM N2 NCU module\n\
Sysconf format is :\n\
sysconf n2_ncu <instance_name> \n\
For UI help type <instance name> \n\
For module specific info type \"modinfo <instance name>\"";
static int access_ncu(uint32_t cpuid, void* obj, uint64_t paddr, mmi_bool_t wr, uint32_t size, uint64_t* buf, uint8_t bytemask){
n2Ncu * ncu = (n2Ncu*)obj;
return ncu->access_regs(cpuid,paddr,wr,size,buf,bytemask);
}
int n2ncu_ui_cmd(void * obj, int argc, char * argv[]){
n2Ncu * i = (n2Ncu *)obj;
i->handle_ui(argc, argv);
return 0;
}
const uint64_t n2Ncu::dumpRegsV1[25] = {
INT_MAN,
MONDO_INT_VEC,
SER_NUM,
EFU_STAT,
BANK_ENABLE,
BANK_ENABLE_STATUS,
L2_IDX_HASH_EN,
L2_IDX_HASH_EN_STATUS,
PCIE_A_MEM32_OFFSET_BASE,
PCIE_A_MEM32_OFFSET_MASK,
PCIE_A_MEM64_OFFSET_BASE,
PCIE_A_MEM64_OFFSET_MASK,
PCIE_A_IOCON_OFFSET_BASE,
PCIE_A_IOCON_OFFSET_MASK,
PCIE_A_FSH,
SOC_ESR,
SOC_LOG_ENABLE,
SOC_INTERRUPT_ENABLE,
SOC_ERROR_INJECTION,
SOC_FATAL_ERROR_ENABLE,
SOC_SII_ERROR_SYNDROME,
SOC_NCU_ERROR_SYNDROME,
MONDO_INT_DATA0,
MONDO_INT_DATA1,
MONDO_INT_BUSY,
};
const char * Module::get_help_string(){
return n2ncu_help;
}
Module * Module::create(const char *_modname, const char *_instance_name){
return new n2Ncu(_modname, _instance_name);
}
n2Ncu::n2Ncu(const char *_modname, const char *_instance_name)
: Module(_modname, _instance_name){
ncu_init();
mmi_register_instance_cmd(getInstance(),n2ncu_help,n2ncu_ui_cmd);
current_dump_version = strdup("v1.0");
}
void n2Ncu::ncu_init(){
uint64_t device;
int i;
//pthread_mutex_init(&ncu_lock, NULL);
/*
* setup init value (NCU spec, v0.99)
*/
for (device=0; device < NCU_DEV_MAX; device++) {
regs.int_man[device] = 0x0;
}
regs.mondo_int_vec = 0x0;
regs.ser_num = 0xdeadbeef;
regs.efu_stat = MASK64(63,0);
regs.bank_enb = 0xff;
regs.bank_enb_stat = 0x3cf;
regs.l2_idx_hash_en_stat = false;
regs.pcie_a_mem32_offset_base = 0x0;
regs.pcie_a_mem32_offset_mask = MASK64(39,36);
regs.pcie_a_mem64_offset_base = 0x0;
regs.pcie_a_mem64_offset_mask = MASK64(39,36);
regs.pcie_a_iocon_offset_base = 0x0;
regs.pcie_a_iocon_offset_mask = MASK64(39,36);
regs.pcie_a_fsh = 0x0;
regs.soc_esr = 0x0;
regs.soc_log_enb = 0x1fffffff;
regs.soc_intr_enb = 0x0;
regs.soc_err_inject = 0x0;
regs.soc_fatal_enb = 0x0;
regs.soc_sii_err_syndrome = 0x0;
regs.soc_ncu_err_syndrome = 0x0;
for (i = 0; i < NCU_TARGETS; i++) {
regs.mondo_int_data0[i] = 0x0;
regs.mondo_int_data1[i] = 0x0;
regs.mondo_int_busy[i] = 0x0; //MASK64(6,6);
}
return;
}
// support 8 byte reads/writes of registers.
int n2Ncu::access_regs(uint32_t cpuid, uint64_t paddr, mmi_bool_t wr, uint32_t size,\
uint64_t* buf, uint8_t bytemask){
if(size != 8){
debug_err("%s ERROR: %s access of size %d at addr %llx\n", \
getName(),wr?"WITE":"READ",size,paddr);
return -1;
}
if(paddr & 7){
debug_err("%s ERROR: unaligned %s access of size %d at addr %llx\n", \
getName(),wr?"WITE":"READ",size,paddr);
return -1;
}
uint64_t reg = paddr & NCU_REG_MASK;
if (reg < MONDO_INT_VEC)
reg = reg & NCU_INT_MAN_MASK;
if (reg >= MONDO_INT_DATA0) {
if (UINT64_RANGE_CHECK(MONDO_INT_DATA0, reg, MONDO_INT_DATA1))
reg = MONDO_INT_DATA0;
if (UINT64_RANGE_CHECK(MONDO_INT_DATA1, reg, MONDO_INT_ADATA0))
reg = MONDO_INT_DATA1;
if (UINT64_RANGE_CHECK(MONDO_INT_ADATA0, reg, MONDO_INT_ADATA1))
reg = MONDO_INT_ADATA0;
if (UINT64_RANGE_CHECK(MONDO_INT_ADATA1, reg, MONDO_INT_BUSY))
reg = MONDO_INT_ADATA1;
if (UINT64_RANGE_CHECK(MONDO_INT_BUSY, reg, MONDO_INT_ABUSY))
reg = MONDO_INT_BUSY;
}
//pthread_mutex_lock( &ncu_lock );
uint64_t val;
switch(wr){
case true: //8 byte write
val = *buf;
switch(reg){
case INT_MAN:
{
int idx;
idx = (paddr >> 3) & (NCU_DEV_MAX-1);
ASSIGN_NCU(regs.int_man[idx],MASK64(13,8)|MASK64(5,0),val,reg);
break;
}
case MONDO_INT_VEC:
ASSIGN_NCU(regs.mondo_int_vec, MASK64(5,0), val, reg);
break;
case SER_NUM:
case EFU_STAT:
case CORE_AVAIL:
case BANK_AVAIL:
case BANK_ENABLE_STATUS:
case L2_IDX_HASH_EN_STATUS:
case MONDO_INT_DATA0:
case MONDO_INT_DATA1:
case MONDO_INT_ADATA0:
case MONDO_INT_ADATA1:
debug_err("%s: attempted write to RO register\n \
Write 0x%llx to register %s (offset 0x%llx\n",\
getName(),val, ncu_reg_name(reg), reg);
break;
case PCIE_A_MEM32_OFFSET_BASE:
ASSIGN_NCU( regs.pcie_a_mem32_offset_base, MASK64(63,63)|MASK64(35,24), val, reg);
niagara2_pcie_mapping(PIU_REGION_MEM32);
break;
case PCIE_A_MEM32_OFFSET_MASK:
ASSIGN_NCU( regs.pcie_a_mem32_offset_mask, MASK64(39,24), val, reg);
niagara2_pcie_mapping(PIU_REGION_MEM32);
break;
case PCIE_A_MEM64_OFFSET_BASE:
ASSIGN_NCU( regs.pcie_a_mem64_offset_base, MASK64(63,63)|MASK64(35,24), val, reg);
niagara2_pcie_mapping(PIU_REGION_MEM64);
break;
case PCIE_A_MEM64_OFFSET_MASK:
ASSIGN_NCU( regs.pcie_a_mem64_offset_mask, MASK64(39,24), val, reg);
niagara2_pcie_mapping(PIU_REGION_MEM64);
break;
case PCIE_A_IOCON_OFFSET_BASE:
ASSIGN_NCU( regs.pcie_a_iocon_offset_base, MASK64(63,63)|MASK64(35,24), val, reg );
niagara2_pcie_mapping(PIU_REGION_CFGIO);
break;
case PCIE_A_IOCON_OFFSET_MASK:
ASSIGN_NCU( regs.pcie_a_iocon_offset_mask, MASK64(39,24) ,val, reg );
niagara2_pcie_mapping(PIU_REGION_CFGIO);
break;
case BANK_ENABLE:
case L2_IDX_HASH_EN:
debug_more("%s: register %s (offset 0x%llx) not implemented\n", \
getName(),ncu_reg_name(reg), reg);
break;
case PCIE_A_FSH:
ASSIGN_NCU( regs.pcie_a_fsh,~0ULL, val, reg);
break;
case SOC_ESR:
ASSIGN_NCU( regs.soc_esr, MASK64(63,63)|NCU_SOC_MASK, val, reg );
break;
case SOC_LOG_ENABLE:
ASSIGN_NCU( regs.soc_log_enb, MASK64(42,0) , val, reg );
break;
case SOC_INTERRUPT_ENABLE:
ASSIGN_NCU( regs.soc_intr_enb, MASK64(42,0), val, reg );
break;
case SOC_ERROR_INJECTION:
ASSIGN_NCU( regs.soc_err_inject, MASK64(42,0), val, reg );
break;
case SOC_FATAL_ERROR_ENABLE:
ASSIGN_NCU( regs.soc_fatal_enb, MASK64(42,0), val, reg );
break;
case SOC_PENDING_ERROR_STATUS:
/*
* same as SOC_ESR
*/
ASSIGN_NCU( regs.soc_esr, MASK64(63,63)|NCU_SOC_MASK, val, reg );
break;
case SOC_SII_ERROR_SYNDROME:
ASSIGN_NCU( regs.soc_sii_err_syndrome, MASK64(63,63)|MASK64(58,0), val, reg );
break;
case SOC_NCU_ERROR_SYNDROME:
ASSIGN_NCU( regs.soc_ncu_err_syndrome, MASK64(63,58)|MASK64(55,0), val, reg );
break;
case MONDO_INT_BUSY:
{
int target;
target = (paddr >> 3) & (NCU_TARGETS-1);
ASSIGN_NCU( regs.mondo_int_busy[target], MASK64(6,6), val, reg );
break;
}
case MONDO_INT_ABUSY:
{
int target = cpuid;
ASSIGN_NCU( regs.mondo_int_busy[target], MASK64(6,6), val, reg );
break;
}
default:
debug_err("%s: ERROR unknow register access at offset %llx\n",getName(),reg);
//pthread_mutex_unlock( &ncu_lock );
return -1;
}
//debug_more("%s: write at register %s (offset %llx)\n", getName(), ncu_reg_name(reg), val);
//pthread_mutex_unlock( &ncu_lock );
return 0;
case false: // 8 byte read
switch(reg){
case INT_MAN:
{
int idx;
idx = (paddr >> 3) & (NCU_DEV_MAX-1);
val = regs.int_man[idx];
break;
}
case MONDO_INT_VEC:
val = regs.mondo_int_vec;
break;
case SER_NUM:
// XXX this ro register becomes a big bottleneck as the cpu
// idleloop continuously reads this register. Remove the
// locks to reduce contention
val = regs.ser_num;
// val = 0xdeadbeef;
break;
case CORE_AVAIL:
// XXX need to access the ASI register to provide access.
debug_err("%s: ERROR:unimplemented reg read at %s",getName(),ncu_reg_name(reg));
break;
case EFU_STAT:
val = regs.efu_stat;
break;
case BANK_AVAIL:
case BANK_ENABLE:
val = regs.bank_enb;
break;
case BANK_ENABLE_STATUS:
val = regs.bank_enb_stat;
break;
case PCIE_A_MEM32_OFFSET_BASE:
val = regs.pcie_a_mem32_offset_base;
break;
case PCIE_A_MEM32_OFFSET_MASK:
val = regs.pcie_a_mem32_offset_mask;
break;
case PCIE_A_MEM64_OFFSET_BASE:
val = regs.pcie_a_mem64_offset_base;
break;
case PCIE_A_MEM64_OFFSET_MASK:
val = regs.pcie_a_mem64_offset_mask;
break;
case PCIE_A_IOCON_OFFSET_BASE:
val = regs.pcie_a_iocon_offset_base;
break;
case PCIE_A_IOCON_OFFSET_MASK:
val = regs.pcie_a_iocon_offset_mask;
break;
case L2_IDX_HASH_EN:
case L2_IDX_HASH_EN_STATUS:
debug_more("%s:register %s (offset 0x%llx) not implemented\n",
getName(), ncu_reg_name(reg), reg );
val = 0;
break;
case PCIE_A_FSH:
val = regs.pcie_a_fsh;
break;
case SOC_ESR:
val = regs.soc_esr;
break;
case SOC_LOG_ENABLE:
val = regs.soc_log_enb;
break;
case SOC_INTERRUPT_ENABLE:
val = regs.soc_intr_enb;
break;
case SOC_ERROR_INJECTION:
val = regs.soc_err_inject;
break;
case SOC_FATAL_ERROR_ENABLE:
val = regs.soc_fatal_enb;
break;
case SOC_PENDING_ERROR_STATUS:
/*
* same as SOC_ESR
*/
val = regs.soc_esr;
break;
case SOC_SII_ERROR_SYNDROME:
val = regs.soc_sii_err_syndrome;
break;
case SOC_NCU_ERROR_SYNDROME:
val = regs.soc_ncu_err_syndrome;
break;
case MONDO_INT_DATA0:
{
int target = (paddr >> 3) & (NCU_TARGETS-1);
val = regs.mondo_int_data0[target];
break;
}
case MONDO_INT_DATA1:
{
int target = (paddr >> 3) & (NCU_TARGETS-1);
val = regs.mondo_int_data1[target];
break;
}
case MONDO_INT_ADATA0:
{
int target = cpuid;
val = regs.mondo_int_data0[target];
break;
}
case MONDO_INT_ADATA1:
{
int target = cpuid;
val = regs.mondo_int_data1[target];
break;
}
case MONDO_INT_BUSY:
{
int target = (paddr >> 3) & (NCU_TARGETS-1);
val = regs.mondo_int_busy[target];
break;
}
case MONDO_INT_ABUSY:
{
int target = cpuid;
val = regs.mondo_int_busy[target];
break;
}
default:
*buf = 0;
debug_err("%s: ERROR unknow read register access at offset %llx\n",getName(),reg);
//pthread_mutex_unlock( &ncu_lock );
return -1;
}
*buf = val;
debug_more("%s: read register %s (value 0x%llx)\n", getName(), ncu_reg_name(reg), val);
//pthread_mutex_unlock( &ncu_lock );
return 0;
default:
*buf = 0;
//pthread_mutex_unlock( &ncu_lock );
return -1;
}
}
/*
* Create address mapping to access PCIE Cfg/IO, MEM32 and MEM64 space
*/
void n2Ncu::niagara2_pcie_mapping(piu_region_t region){
uint64_t base, mask, size;
bool enable;
const char *name[3] = {"Cfg/IO", "Mem32", "Mem64"};
switch(region){
case PIU_REGION_CFGIO:
base = regs.pcie_a_iocon_offset_base;
mask = regs.pcie_a_iocon_offset_mask;
break;
case PIU_REGION_MEM32:
base = regs.pcie_a_mem32_offset_base;
mask = regs.pcie_a_mem32_offset_mask;
break;
case PIU_REGION_MEM64:
base = regs.pcie_a_mem64_offset_base;
mask = regs.pcie_a_mem64_offset_mask;
break;
default:
assert(0);
}
enable = GETMASK64(base,63,63);
base &= PIU_REGION_OFFSET_MASK;
mask &= PIU_REGION_OFFSET_MASK;
if(enable){
size = ~(MASK64(63,36)|mask) + 1;
map[region].base = base;
map[region].mask = mask;
map[region].size = size;
map[region].enable = enable;
debug_more("%s:PCIE %s is mapped at 0x%llx - 0x%llx\n", \
getName(),name[region],base,base+size-1);
}
}
bool n2Ncu::dump_v1(FILE * fp){
const char * dump_version = "v1.0";
fwrite(dump_version,strlen(dump_version),1,fp);
fwrite("\n",strlen("\n"),1,fp);
for(int i = 0; i < (sizeof(dumpRegsV1)/sizeof(uint64_t)); i++ ){
char buf[64 * 1024], tcptr[64 * 1024];
sprintf(buf,"%-50s0x%-8llx ",ncu_reg_name(dumpRegsV1[i]),dumpRegsV1[i]);
uint64_t base = dumpRegsV1[i];
uint64_t val = 0;
switch(dumpRegsV1[i]){
case INT_MAN:
for(int j = 0; j < NCU_DEV_MAX; j++){
access_regs(0,base + j*8, mmi_false, 8, &val,0xff);
sprintf(tcptr, "0x%04x 0x%016llx,",j,val);
strcat(buf,tcptr);
}
break;
case MONDO_INT_DATA0:
case MONDO_INT_DATA1:
case MONDO_INT_BUSY:
for(int j = 0; j < NCU_TARGETS; j++){
access_regs(0,base + j*8, mmi_false, 8, &val,0xff);
sprintf(tcptr, "0x%04x 0x%016llx,",j,val);
strcat(buf,tcptr);
}
break;
default:
access_regs(0,base,mmi_false,8,&val,0xff);
sprintf(tcptr, "0x%016llx,",val);
strcat(buf,tcptr);
break;
}
fwrite(buf,strlen(buf),1,fp);
fwrite("\n",strlen("\n"),1,fp);
}
fflush(fp);
if(fp != stderr)
fclose(fp);
return true;
}
bool n2Ncu::dump(FILE * fp){
if(!strcmp(current_dump_version,"v1.0"))
return dump_v1(fp);
else {
assert(0);
}
}
bool n2Ncu::restore(FILE * fp){
const int bufsize = 64 * 1024;
char buf[bufsize];
fgets(buf,bufsize,fp);
buf[strlen(buf)-1] = 0;
if(!strcmp(buf,"v1.0")){
return restore_v1(fp);
}else{
printf("%s restore: dump version mismatch, restore failed\n",getName());
return false;
}
}
// if the CSR offsets change, this function may need change as well
bool n2Ncu::restore_v1(FILE * fp){
const int bufsize = 64 * 1024;
char buf[bufsize];
while(fgets(buf,bufsize,fp)){
strtok(buf," "); // csr name, ignore
const char * csr_offset = strtok(0," "); // csr offset
uint64_t offset = strtoull(csr_offset,0,0);
switch(offset){
case INT_MAN:
for(int j = 0; j < NCU_DEV_MAX; j++){
const char * csr_index = strtok(0," ");
uint64_t index = strtoull(csr_index,0,0);
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.int_man[index] = val;
}
break;
case MONDO_INT_DATA0:
for(int j = 0; j < NCU_TARGETS; j++){
const char * csr_index = strtok(0," ");
uint64_t index = strtoull(csr_index,0,0);
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.mondo_int_data0[index] = val;
}
break;
case MONDO_INT_DATA1:
for(int j = 0; j < NCU_TARGETS; j++){
const char * csr_index = strtok(0," ");
uint64_t index = strtoull(csr_index,0,0);
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.mondo_int_data1[index] = val;
}
break;
case MONDO_INT_BUSY:
for(int j = 0; j < NCU_TARGETS; j++){
const char * csr_index = strtok(0," ");
uint64_t index = strtoull(csr_index,0,0);
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.mondo_int_busy[index] = val;
}
break;
case MONDO_INT_VEC:
case PCIE_A_MEM32_OFFSET_BASE:
case PCIE_A_MEM32_OFFSET_MASK:
case PCIE_A_MEM64_OFFSET_BASE:
case PCIE_A_MEM64_OFFSET_MASK:
case PCIE_A_IOCON_OFFSET_BASE:
case PCIE_A_IOCON_OFFSET_MASK:
case BANK_ENABLE:
case L2_IDX_HASH_EN:
case PCIE_A_FSH:
case SOC_ESR:
case SOC_LOG_ENABLE:
case SOC_INTERRUPT_ENABLE:
case SOC_ERROR_INJECTION:
case SOC_FATAL_ERROR_ENABLE:
case SOC_SII_ERROR_SYNDROME:
case SOC_NCU_ERROR_SYNDROME:
{
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
access_regs(0,offset,mmi_true,8,&val,0xff);
}
break;
// r/o registers
case SER_NUM:
{
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.ser_num = val;
break;
}
case EFU_STAT:
{
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.efu_stat = val;
break;
}
case BANK_ENABLE_STATUS:
{
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.bank_enb_stat = val;
break;
}
case L2_IDX_HASH_EN_STATUS:
{
const char * csr_val = strtok(0,",");
uint64_t val = strtoull(csr_val,0,0);
regs.l2_idx_hash_en_stat = val;
break;
}
default:
assert(0);
}
}
return true;
}
void n2Ncu::handle_ui(int argc, char * argv[]){
if(argc == 1){
ui_cmd_usage();
return;
}else if(!strcmp(argv[1],"dump")){
FILE * fp = stderr;
if(argv[2]){
fp = fopen(argv[2],"w");
if(!fp){
printf("%s dump: error opening file <%s>\n",getName(),argv[2]);
fp = stderr;
}
}
dump(fp);
}else if(!strcmp(argv[1],"restore")){
FILE * fp;
if(argv[2]){
fp = fopen(argv[2],"r");
if(fp)
restore(fp);
else
printf("%s restore: error opening file <%s>\n",getName(),argv[2]);
}else
printf("%s restore: no restore filename specified\n",getName());
}else if(!strcmp(argv[1],"debug")){
if(argv[2]){
debug_level = atoi(argv[2]);
printf("%s: set debug level to %d\n",getName(),debug_level);
}else
printf("%s: current debug level %d\n",getName(),debug_level);
}else
debug_err("%s: unsupported UI command <%s>\n",getName(),argv[1]);
return;
}
const char *n2Ncu::ncu_reg_name(uint64_t reg){
switch (reg) {
case INT_MAN: return "int_man";
case MONDO_INT_VEC: return "mondo_int_vec";
case SER_NUM: return "ser_num";
case EFU_STAT: return "efu_stat";
case CORE_AVAIL: return "core_avail";
case BANK_AVAIL: return "bank_avail";
case BANK_ENABLE: return "bank_enable";
case BANK_ENABLE_STATUS: return "bank_enable_status";
case L2_IDX_HASH_EN: return "l2_idx_hash_en";
case L2_IDX_HASH_EN_STATUS: return "l2_idx_hash_en_status";
case PCIE_A_MEM32_OFFSET_BASE: return "pcie_a_mem32_offset_base";
case PCIE_A_MEM32_OFFSET_MASK: return "pcie_a_mem32_offset_mask";
case PCIE_A_MEM64_OFFSET_BASE: return "pcie_a_mem64_offset_base";
case PCIE_A_MEM64_OFFSET_MASK: return "pcie_a_mem64_offset_mask";
case PCIE_A_IOCON_OFFSET_BASE: return "pcie_a_iocon_offset_base";
case PCIE_A_IOCON_OFFSET_MASK: return "pcie_a_iocon_offset_mask";
case PCIE_A_FSH: return "pcie_a_fsh";
case SOC_ESR: return "soc_error_status";
case SOC_LOG_ENABLE: return "soc_error_log_enable";
case SOC_INTERRUPT_ENABLE: return "soc_error_interrupt_enable";
case SOC_FATAL_ERROR_ENABLE: return "soc_fatal_error_enable";
case SOC_PENDING_ERROR_STATUS: return "soc_pending_error_status";
case SOC_ERROR_INJECTION: return "soc_error_injection";
case SOC_SII_ERROR_SYNDROME: return "soc_sii_error_syndrome";
case SOC_NCU_ERROR_SYNDROME: return "soc_sii_error_syndrome";
case MONDO_INT_DATA0: return "mondo_int_data0";
case MONDO_INT_DATA1: return "mondo_int_data1";
case MONDO_INT_ADATA0: return "mondo_int_adata0";
case MONDO_INT_ADATA1: return "mondo_int_adata1";
case MONDO_INT_BUSY: return "mondo_int_busy";
case MONDO_INT_ABUSY: return "mondo_int_abusy";
default: return "Illegal NCU register";
}
}