Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / memsync / src / RieslingInterface.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: RieslingInterface.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) 2002, 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."
**
*************************************************************************/
#include <sstream>
#include "RieslingInterface.h"
using namespace std;
/* this will be removed once pli-socket files are in place */
int RieslingInterface::max_strands=256;
int RieslingInterface::strands_per_core=8;
int RieslingInterface::cores_per_cpu=8;
uint64_t RieslingInterface::readMemory(uint32_t cid, uint32_t tid, uint64_t addr, uint_t size, int convert)
{
uint64_t data;
if (convert)
addr = convertPA(cid, tid, addr);
assert(size <= 8);
if(size == 1)
data = io->peek8u(tid,addr);
else if(size == 2)
data = io->peek16u(tid,addr);
else if(size == 4)
data = io->peek32u(tid,addr);
else if(size == 8)
data = io->peek64(tid,addr);
MSYNC_DEBUG (1, "ReadMemory tid=%d pa=%#llx data=%#llx size=%d", tid, addr, data, size);
return data;
}
void RieslingInterface::writeMemory(uint32_t cid, uint32_t tid, uint64_t addr, uint64_t data, uint_t size, int convert)
{
if (convert)
addr = convertPA(cid, tid, addr);
switch (size)
{
case 1: io->poke8( tid,addr,data); break;
case 2: io->poke16(tid,addr,data); break;
case 4: io->poke32(tid,addr,data); break;
case 8: io->poke64(tid,addr,data); break;
default: assert(0);
}
MSYNC_DEBUG (1, "WriteMemory tid=%d pa=%#llx data=%#llx size=%d", tid, addr, data, size);
}
void RieslingInterface::slamMemory(uint32_t cid, uint32_t tid, uint64_t addr, uint64_t data, uint_t size, int convert )
{
if (convert)
addr = convertPA(cid, tid, addr);
switch (size)
{
case 1: io->poke8( tid,addr,data); break;
case 2: io->poke16(tid,addr,data); break;
case 4: io->poke32(tid,addr,data); break;
case 8: io->poke64(tid,addr,data); break;
default: assert(0);
}
MSYNC_DEBUG (1, "WriteMemory tid=%d pa=%#llx data=%#llx size=%d", tid, addr, data, size);
}
//=============================================================================
// 16.3.2.4 PCI Express addressing & 24.3
//
// #define MEM32_OFFSET_BASE_REG_ADDR 0x80-0000-2000
// #define MEM32_OFFSET_MASK_REG_ADDR 0x80-0000-2008
// #define MEM64_OFFSET_BASE_REG_ADDR 0x80-0000-2010
// #define MEM64_OFFSET_MASK_REG_ADDR 0x80-0000-2018
// #define MEM64_PCIE_OFFSET_REG_ADDR 0x88-0063-4018
//
// match = false;
// if (PA[39:36] == 0xc) {
// if ((BASE64[63] == 1) &&
// ((PA[35:24] & MASK64[35:24]) == BASE64[35:24])) {
// // 64bit address
// match = true;
// newPA = OFFSET64[63:36] |
// (OFFSET[35:24] | (PA[35:24] & ~MASK64[35:24])) |
// PA[23:0];
// }
// if ((match == false) &&
// (BASE32[63] == 1) &&
// ((PA[35:24] & MASK32[35:24]) == BASE32[35:24])) {
// // 32bit address
// newPA = PA[31:0] & ~MASK32[35:24];
// }
// }
//
// maybe we should move this function to N2_System.cc ?
//---> no, we need it here so that we can match msync address.
//
//=============================================================================
uint64_t
RieslingInterface::convertPA(int cid, int tid, uint64_t pa)
{
if ((getBits(pa, 39, 36) & 0xf) == 0xc) {
//cerr << "DBX: enter convertPA(), pa=0x" << hex << pa << endl;//DBX
// looking for 32bit/64bit PCIE PIO address mapping, check 64bit first
bool match = false;
uint64_t newPa = pa;
uint64_t mem64_offset_base = readMemory(cid, tid, 0x8000002010, 8, 0);
//cerr << "DBX: RieslingInterface::convertPA: offset64=0x" << hex << mem64_offset_base << endl;//DBX
if (getBits(mem64_offset_base, 63, 63) == 0x1) {
// 64bit enabled
uint64_t mem64_offset_mask = readMemory(cid, tid, 0x8000002018, 8, 0);
//cerr << "DBX: RieslingInterface::convertPA: mask64=0x" << hex << mem64_offset_mask << endl;//DBX
if ((getBits(pa, 35, 24) & getBits(mem64_offset_mask, 35, 24)) == getBits(mem64_offset_base, 35, 24)) {
// match 64bit base
match = true;
uint64_t pcie_offset = readMemory(cid, tid, 0x8800634018, 8, 0);
//cerr << "DBX: RieslingInterface::convertPA: pcie_offset=0x" << hex << pcie_offset << endl;//DBX
newPa = getBits(pcie_offset, 63, 36, true) |
(getBits(pcie_offset, 35, 24, true) | (getBits(pa, 35, 24, true) & ~(getBits(mem64_offset_mask, 35, 24, true)))) |
getBits(pa, 23, 0, true);
}
}
// 64bit has higher priority, check 32bit only if not matching 64bit
//TODO 32bit checking is disable for now, 1/6/06
if (0 && (match == false)) {
uint64_t mem32_offset_base = readMemory(cid, tid, 0x8000002000, 8, 0);
//cerr << "DBX: RieslingInterface::convertPA: offset32=0x" << hex << mem32_offset_base << endl;//DBX
if (getBits(mem32_offset_base, 63, 63) == 0x1) {
// 32bit enabled
uint64_t mem32_offset_mask = readMemory(cid, tid, 0x8000002008, 8, 0);
//cerr << "DBX: RieslingInterface::convertPA: mask32=0x" << hex << mem32_offset_mask << endl;//DBX
if ((getBits(pa, 35, 24) & getBits(mem32_offset_mask, 35, 24)) == getBits(mem32_offset_base, 35, 24)) {
// match 32bit base
newPa = getBits(pa, 31, 0, true) & ~(getBits(mem32_offset_mask, 35, 24, true));
}
}
}
//cerr << "DBX: RieslingInterface::convertPA: pa=0x" << hex << pa << " newPa=0x" << newPa << endl;//DBX
return newPa;
}
else {
return pa;
}
}