// ========== Copyright Header Begin ==========================================
// OpenSPARC T2 Processor File: N2_Csr.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 ============================================
/************************************************************************
** Copyright (C) 2006, Sun Microsystems, Inc.
** Sun considers its source code as an unpublished, proprietary
** trade secret and it is available only under strict license provisions.
** This copyright notice is placed here only to protect Sun in the event
** the source is deemed a published work. Disassembly, decompilation,
** or other means of reducing the object code to human readable form
** is prohibited by the license agreement under which this code is
** provided to the user or company in possession of this copy.
*************************************************************************/
const int N2_Csr::PA_BITS
= 40;
const uint64_t N2_Csr::IO_MASK
= 0x1ULL
<< (PA_BITS
- 1);
const int N2_Csr::IO_OFFSET
= 32;
const uint64_t N2_Csr::IO_RANGE
= 0xffULL
<< IO_OFFSET
;
N2_Model
* N2_Csr::model
= NULL
;
//=============================================================================
// return SS_Io::NOT_HANDLED will pass the operation to SS_Memory
//=============================================================================
int N2_Csr::access_io(void* obj
, int sid
, int access
, SS_Paddr addr
, uint32_t size
, uint64_t* data
, uint64_t bitmask
)/*{{{*/
// filter out non-io address ---> this should never happen as only I/O addr
if ((addr
& IO_MASK
) == 0x0)
return SS_Io::NOT_HANDLED
;
// CSR access should be 8-byte bound
return SS_Io::NOT_HANDLED
;
N2_Csr
*csr
= (N2_Csr
*)obj
;
csr
->set_followme(false);
int ret
= csr
->address_map(addr
, access
, sid
);
for (int i
= 0; i
< count
; i
++)
if (access
& MemoryTransaction::WRITE
)
ret
= csr
->write64((addr
+i
*8), data
[i
], access
, sid
);
ret
= csr
->read64((addr
+i
*8), &data
[i
], access
, sid
);
// make sure the entire block has the same return state
else if (prev_ret
!= ret
)
fprintf(stderr
, "ERROR: N2_Csr::access_io(): addr=%#llx, i=%d, prev_ret=%d, ret=%d\n", addr
, i
, prev_ret
, ret
);
else if (ret
== SS_Io::FOLLOWME
)
if (access
& MemoryTransaction::READ
)
// address not allowed for read
*data
= 0xDEADDEADDEADDEADLLU
;
// tell msync not to change this value
//=============================================================================
//=============================================================================
SS_Io::access_io_status
N2_Csr::address_map( SS_Paddr paddr
, int access
, int sid
)/*{{{*/
// when IO address CSRs are added, make sure there is no conflict on
// address range, when there is one, CSR has the higher priority.
bool write
= (access
& MemoryTransaction::WRITE
) ? true : false;
bool internal
= (access
& MemoryTransaction::INTERNAL
) ? true : false;
bool mem_slam
= (access
& MemoryTransaction::MEM_SLAM
) ? true : false;
uint64_t range
= (paddr
& IO_RANGE
) >> IO_OFFSET
;
// if it is an instruction fetch to I/O space other than 0xff,
// throw illegal instruction.
//TODO the current setup does not provide any information regarding whether
// the access is an instr fetch or not.
//TODO if (type == INSTR_ACCESS) && (range != 0xff) && !write && !internal
// ===> trap( illegal_instruction )
// 0x82: // RNG (Random Number Generator) IGNORE writes
if (write
&& !(internal
|| mem_slam
))
// silently drop the write
else if (((range
== 0x87) ||
((range
>= 0x8a) && (range
<= 0x8f)) ||
((range
>= 0x91) && (range
<= 0x9f) && (paddr
!= 0x9a00000000)) ||
((range
>= 0xd0) && (range
<= 0xfe))))
// 0x87: // TAP to L2 CSR (not supported) ERROR on read
// 0x91-0x9F: // Reserved ERROR on read
// xA0-0xBF: // L2 CSR (never comes to NCU) ERROR on read
// ---> 0xA0-0xBF: (Jeff) This range is read/write from a Riesling
// perspective and a "should never happen"
// from the NCU perspective.
// 0xD0-0xFE: // Reserved ERROR on read
//TODO throw data_access_error 0x32 (12.9) on read
// if (seter->getPSCCE() && cerer->getL2U_SOCU())
// ===> trap( data_access_error )
//TODO if seter & cerer are provided through ASI follow-me, then make
// sure we use those follow-me values
//=============================================================================
// return NOT_HANDLED means should re-try the operation in SS_Memory
//=============================================================================
int N2_Csr::read64( SS_Paddr paddr
, uint64_t *value
, int access
, int sid
)/*{{{*/
int range
= (int)((paddr
& IO_RANGE
) >> IO_OFFSET
);
return ncu_
.read64(paddr
, value
, access
, sid
);
return niu_
.read64(paddr
, value
, access
, sid
);
return mcu_
.read64(paddr
, value
, access
, sid
);
// TAP to L2 CSR (not supported) ERROR on read
// should be filtered out by addressMap()
return SS_Io::NOT_HANDLED
;
fprintf(stderr
, "ERROR: N2_Csr::read64( addr=%#llx ) not allowed\n", paddr
);
return piu_
.read64(paddr
, value
, access
, sid
);
return rst_
.read64(paddr
, value
, access
, sid
);
// SSI (boot ROM) IGNORE writes
return ssi_
.read64(paddr
, value
, access
, sid
);
if (range
>= RANGE_L2_LOW
&& range
<= RANGE_L2_HIGH
)
return l2_
.read64(paddr
, value
, access
, sid
);
else if (range
>= RANGE_PCIE_LOW
&& range
<= RANGE_PCIE_HIGH
)
// PCIE (64GB) / DMUPIO R/W allowed
return pcie_
.read64(paddr
, value
, access
, sid
);
return SS_Io::NOT_HANDLED
;
return SS_Io::NOT_HANDLED
;
//=============================================================================
// return NOT_HANDLED means should re-try the operation in SS_Memory
//=============================================================================
int N2_Csr::write64( SS_Paddr paddr
, uint64_t value
, int access
, int sid
)/*{{{*/
int range
= (int)((paddr
& IO_RANGE
) >> IO_OFFSET
);
return ncu_
.write64(paddr
, value
, access
, sid
);
return niu_
.write64(paddr
, value
, access
, sid
);
// RNG (Random Number Generator) IGNORE writes
// should be filtered out by addressMap()
// we can get here if msync does an memSlam write, have to take it.
if (access
& MemoryTransaction::MEM_SLAM
)
return SS_Io::NOT_HANDLED
;
return mcu_
.write64(paddr
, value
, access
, sid
);
return piu_
.write64(paddr
, value
, access
, sid
);
if (((paddr
== 0x8900000808) || (paddr
== 0x8900000810)) &&
(access
& MemoryTransaction::MEM_SLAM
))
access
|= MemoryTransaction::INTERNAL
;
int ret
= rst_
.write64(paddr
, value
, access
, sid
);
if (paddr
== 0x8900000808)
int ret2
= rst_
.read64(paddr
, &data
, (access
|MemoryTransaction::READ
|MemoryTransaction::INTERNAL
|SS_BaseCsr::NO_FOLLOW_ME
), sid
);
// if reset_gen is set to non-zero, raise reset_gen trap if in
// standalone mode, if in cosim mode, wait for testbench INTP command
//TODO if (data > 0) && !cosim ===> raise reset_gen trap
if ((data
> 0) && (sid
>= 0))
if (!(model
->strand_ptr(sid
)->sim_state
.cosim()))
fprintf(stderr
, "ERROR: N2_Csr::write64(): addr=%#llx, sid=%d, should raise a reset_gen trap\n", paddr
, sid
);
return ssi_
.write64(paddr
, value
, access
, sid
);
if (range
>= RANGE_L2_LOW
&& range
<= RANGE_L2_HIGH
)
return l2_
.write64(paddr
, value
, access
, sid
);
else if (range
>= RANGE_PCIE_LOW
&& range
<= RANGE_PCIE_HIGH
)
// PCIE (64GB) / DMUPIO R/W allowed
return pcie_
.write64(paddr
, value
, access
, sid
);
return SS_Io::NOT_HANDLED
;
return SS_Io::NOT_HANDLED
;