Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / sam / cpus / vonk / ss / api / memsync / src / LoadStoreCmd.cc
// ========== Copyright Header Begin ==========================================
//
// OpenSPARC T2 Processor File: LoadStoreCmd.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 "LoadStoreCmd.h"
#include <sstream>
#include "assert.h"
using namespace std;
////////////////////////////////////////////////
LoadStoreCmd::LoadStoreCmd() :
cmd_(MAX_MEM_CMDS), itype_(ITYPE_NONE), id_(0), cid_(0), tid_(0), srcTid_(0),
srcBank_(0), inv_(0), set_(0), way_(0), addr_(0), data_(0), vbyte_(0), size_(0),
dsrc_(DSRC_NONE), cacheL1_(false), rmoStore_(false), l2hit_(false), switchData_(true),
ioaddr_(false), tsize(0),
cycle_(0)
{
}
LoadStoreCmd::LoadStoreCmd(enum MEM_CMD cmd, enum INSTR_TYPE itype, uint32_t cid, uint32_t tid,
uint32_t srcTid, uint32_t srcBank, uint32_t inv, uint32_t set,
uint32_t way, uint64_t id, uint64_t addr, uint64_t data,
uint8_t size_vector,
uint8_t size, enum DATA_SRC dsrc, bool cacheL1, bool rmoStore,
bool l2hit, bool switchData, bool ioaddr, uint64_t cycle) :
cmd_(cmd), itype_(itype), id_(id), cid_(cid), tid_(tid), srcTid_(srcTid), srcBank_(srcBank),
inv_(inv), set_(set), way_(way), addr_(addr), data_(data), vbyte_(size_vector), size_(size),
dsrc_(dsrc), cacheL1_(cacheL1), rmoStore_(rmoStore), l2hit_(l2hit), switchData_(switchData),
ioaddr_(ioaddr), tsize(0),
cycle_(cycle)
{
}
////////////////////////////////////////////////
LoadStoreCmd::LoadStoreCmd( const LoadStoreCmd & orig )
{
// Replace the following line with your function body.
// RIESLING_THROW_DOMAIN_ERROR( "Unimplemented function." );
}
////////////////////////////////////////////////
LoadStoreCmd::~LoadStoreCmd()
{
}
////////////////////////////////////////////////
// const LoadStoreCmd &
// LoadStoreCmd::operator=( const LoadStoreCmd & rhs )
// {
// // Replace the following line with your function body.
// // RIESLING_THROW_DOMAIN_ERROR( "Unimplemented function." );
// return *this;
// }
// ////////////////////////////////////////////////
// bool
// LoadStoreCmd::operator==( const LoadStoreCmd & rhs ) const
// {
// // Replace the following line with your function body.
// // RIESLING_THROW_DOMAIN_ERROR( "Unimplemented function." );
// return false;
// }
////////////////////////////////////////////////
string
LoadStoreCmd::toString() const
{
ostringstream os;
os << "LSCMD ";
os << "(";
os << "id=" << id_;
os << " cmd=" << mmcmd[cmd_];
os << " i=" << mmitype[itype_];
os << " dsrc=" << mmdsrc[dsrc_];
os << " $L1=" << (int) cacheL1_;
os << " io=" << (int) ioaddr_;
os << " rmo=" << (int) rmoStore_;
os << " l2hit=" << (int) l2hit_;
os << " cid=" << dec << cid_;
os << " tid=" << tid_;
os << " stid=" << srcTid_;
os << " bank=" << srcBank_;
os << " inv=0x" << hex << inv_;
os << " s=" << dec << set_;
os << " w=" << way_;
os << " a=0x" << hex << addr_;
os << " d=0x" << data_;
os << " vb=0x" << (int) vbyte_;
os << " sz=" << dec << (int) size_;
os << " cas=" << dec << (int) switchData_;
os << " cycle=" << cycle_;
os << ")" << endl;
return os.str();
}
void
LoadStoreCmd::auxInit () {
ioaddr_ = ((addr_ & IO_ADDR_BIT_MASK) != 0);
if (!rmoStore_) { // some command does not send rmoStore, use itype
rmoStore_ = (itype_ == ITYPE_BLOCK_STORE || itype_ == ITYPE_STORE_INIT) ? true : false;
}
MemorySyncMessage::rtlCycle = cycle_;
MSYNC_DEBUG(1, "%s", toString().c_str());
}
/* implement big endian */
uint8_t
LoadStoreCmd::sz2szv (uint8_t size, uint32_t aoffset)
{
uint8_t size_vector;
MSYNC_DEBUG(4, "sz2szv->addr_offset=0x%x size=%d", aoffset, (int) size);
assert (size <= 8);
switch (size) {
case 8:
assert((aoffset & 0x7) == 0);
size_vector = 0xff;
break;
case 4:
assert((aoffset & 0x3) == 0);
size_vector = 0xf0 >> (aoffset & 0x7);
break;
case 2:
assert((aoffset & 0x1) == 0);
size_vector = 0xc0 >> (aoffset & 0x7);
break;
case 1:
size_vector = 0x80 >> (aoffset & 0x7);
break;
case 0:
size_vector = 0;
break;
default:
size_vector = 0xff;
assert(0);
break;
}
return (size_vector);
}
/* size = number of 1s for normal store, = 8 for partial store */
uint8_t
LoadStoreCmd::szv2sz (uint8_t size_vector)
{
int i;
bool patn1 = false;
bool patn10 = false;
uint8_t size = 0;
/* size = number of 1s for normal store, = 8 for partial store */
for (i = 0; i < 8; i++) {
if ((size_vector >> i) & 1 == 1)
{
size++;
patn1 = true;
if (patn10) { // partial store
size = 8;
break;
}
} else { // bit = 0
if (patn1) {
patn10 = true;
}
}
}
if ((size != 8) && (size != 4) && (size != 2) && (size != 1) && (size != 0)) {
size = 8;
}
return (size);
}
uint8_t
LoadStoreCmd::sz2szlog (uint8_t size)
{
uint8_t i;
assert(size > 0);
/* convert to log 2 */
i = size;
size = 0;
while ((i & 1) != 1) {
i = i >> 1;
size++;
}
return (size);
}
/******************************************************************************
* The data format MemorySync model expects on STOREs is as follows: (Big Edian)
*
* bit 63 0
* +--------+--------+------------+--------+
* data | byte 0 | byte 1 | --- | byte 7 |
* (64 bits) +--------+--------+------------+--------+
*
* size_vector: bit 7 bit 6 bit 0
* (8 bits)
******************************************************************************/
/******************************************************************************
* A StoreIssueCmd is issued when a store is inserted into STB after address
* translation
*
******************************************************************************/
StoreIssueCmd::StoreIssueCmd(enum INSTR_TYPE itype,
uint32_t tid,
uint64_t id,
uint64_t addr,
uint64_t data,
uint8_t size_vector,
uint64_t cycle)
{
uint8_t size = szv2sz(size_vector);
setCmd(MEM_STORE_ISSUE);
setItype(itype);
setThrdId(tid);
setId(id);
setAddr(addr);
setData(data);
setSizeV(size_vector);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
setSize(size);
auxInit();
}
/******************************************************************************
* A StoreCommitCmd is issued when a store whose data is observed by other
* thread/cpu
******************************************************************************/
StoreCommitCmd::StoreCommitCmd(uint32_t tid,
uint32_t inv,
uint64_t id,
uint64_t addr,
uint8_t size_vector,
bool l2hit,
bool switchData,
uint64_t cycle)
{
uint8_t size = szv2sz(size_vector);
setCmd(MEM_STORE_COMMIT);
setThrdId(tid);
setInv(inv);
setId(id);
setAddr(addr);
setSizeV(size_vector);
setL2hit(l2hit);
setSwitchData(switchData);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
setSize(size);
setSrcBank((addr & L2_BANK_ADDR_BITS) >> L2_BANK_ADDR_SFT);
auxInit();
}
/******************************************************************************
* A StoreInv is issued when an invalidation is performed on its L1 cache
******************************************************************************/
StoreInvCmd::StoreInvCmd(uint32_t cid,
uint32_t srcTid,
uint64_t addr,
uint64_t cycle)
{
setCmd(MEM_STORE_INV);
setCoreId(cid);
setSrcTid(srcTid);
setAddr(addr);
setCycle(cycle);
setThrdId(cid*NSTRANDS_PER_CORE);
auxInit();
}
/******************************************************************************
* A StoreUpdate is issued when a update is performed on its L1 cache
******************************************************************************/
StoreUpdateCmd::StoreUpdateCmd(uint32_t tid,
uint64_t addr,
uint64_t cycle)
{
setCmd(MEM_STORE_UPDATE);
setThrdId(tid);
setAddr(addr);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
/* srcTid is set to tid, which allows the handle routine to share
MemoryAccssBuffer::findStoreInvSrc() to find the corresponding
STORE_COMMIT entry */
setSrcTid(tid);
auxInit();
}
/******************************************************************************
* A StoreAck is issued when a thread receives the Ack indicating to
* remove the store from the Store Buffer.
******************************************************************************/
StoreAckCmd::StoreAckCmd(uint32_t tid,
uint64_t addr,
bool rmoStore,
uint64_t cycle)
{
setCmd(MEM_STORE_ACK);
setThrdId(tid);
setAddr(addr);
setRMOStore(rmoStore);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
/* srcTid is set to tid, which allows the handle routine to share
MemoryAccssBuffer::findStoreInvSrc() to find the corresponding
STORE_COMMIT entry */
setSrcTid(tid);
auxInit();
}
/******************************************************************************
* A LoadIssue is issued when in RTL a load is issued from an in-order domain
* to an out-of-order domain
******************************************************************************/
LoadIssueCmd::LoadIssueCmd(enum INSTR_TYPE itype,
uint32_t tid,
uint64_t id,
uint64_t addr,
uint8_t size,
bool cacheL1,
uint64_t cycle)
{
if (size > 8)
{
MS_ERROR("LoadIssueCmd data size should be no greater than 8 bytes. tid=%d PA=%llx", tid, addr);
return;
}
setCmd(MEM_LOAD_ISSUE);
setItype(itype);
setThrdId(tid);
setId(id);
setAddr(addr);
setSize(size);
setCacheL1(cacheL1);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
uint8_t szv = sz2szv(size, addr & (~ADDR_MASK));
setSizeV(szv);
auxInit();
}
/******************************************************************************
* A LoadData is issued when a load gets its data
******************************************************************************/
LoadDataCmd::LoadDataCmd(uint32_t tid,
uint64_t id,
uint64_t addr,
uint8_t size,
enum DATA_SRC dsrc,
bool cacheL1,
uint64_t cycle)
{
if (size > 8)
{
MS_ERROR("LoadDataCmd data size should be no greater than 8 bytes. tid=%d PA=%llx", tid, addr);
return;
}
setCmd(MEM_LOAD_DATA);
setThrdId(tid);
setId(id);
setAddr(addr);
setSize(size);
setDsrc(dsrc);
setCacheL1(cacheL1);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
uint8_t szv = sz2szv(size, addr & (~ADDR_MASK));
setSizeV(szv);
setSrcBank((addr & L2_BANK_ADDR_BITS) >> L2_BANK_ADDR_SFT);
auxInit();
}
/******************************************************************************
* A LoadFill is issued when a line is filled into L1 and the new data can be
* seen by next access from the same core
******************************************************************************/
LoadFillCmd::LoadFillCmd(uint32_t tid,
uint64_t id,
uint64_t addr,
uint64_t cycle)
{
setCmd(MEM_LOAD_FILL);
setThrdId(tid);
setId(id);
setAddr(addr);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
auxInit();
}
/******************************************************************************
* An Evict is issued When a line is evicted from L2 which'll in turn
* invalid line in L1
******************************************************************************/
EvictCmd::EvictCmd(uint32_t inv,
uint32_t set,
uint32_t way,
uint64_t addr,
uint64_t cycle)
{
setCmd(MEM_EVICT);
setInv(inv);
setSet(set);
setWay(way);
setAddr(addr);
setCycle(cycle);
setSrcBank((addr & L2_BANK_ADDR_BITS) >> L2_BANK_ADDR_SFT);
auxInit();
}
/******************************************************************************
* A EvictInv is issued when an invalidation is performed on its L1 cache
******************************************************************************/
EvictInvCmd::EvictInvCmd(uint32_t cid,
uint32_t srcBank,
uint32_t set,
uint32_t way,
uint64_t cycle)
{
setCmd(MEM_EVICT_INV);
setCoreId(cid);
setSrcBank(srcBank);
setSet(set);
setWay(way);
setCycle(cycle);
setThrdId(cid*NSTRANDS_PER_CORE);
auxInit();
}
/******************************************************************************
* A FetchIssue is issued when an instruction fetch is issued, every instruction
* should have one FetchIssue
******************************************************************************/
FetchIssueCmd::FetchIssueCmd(enum INSTR_TYPE itype,
uint32_t tid,
uint64_t id,
uint64_t addr,
uint8_t size,
bool cacheL1,
uint64_t cycle)
{
if (size > 8)
{
MS_ERROR("FetchIssueCmd data size should be no greater than 8 bytes. tid=%d PA=%llx", tid, addr);
return;
}
setCmd(MEM_FETCH_ISSUE);
setItype(itype);
setThrdId(tid);
setId(id);
setAddr(addr);
setSize(size);
setCacheL1(cacheL1);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
uint8_t szv = sz2szv(size, addr & (~ADDR_MASK));
setSizeV(szv);
auxInit();
}
/******************************************************************************
* A FetchData is issued when a fetch gets its data
******************************************************************************/
FetchDataCmd::FetchDataCmd(uint32_t tid,
uint64_t id,
uint64_t addr,
uint8_t size,
enum DATA_SRC dsrc,
bool cacheL1,
uint64_t cycle)
{
if (size > 8)
{
MS_ERROR("FetchDataCmd data size should be no greater than 8 bytes. tid=%d PA=%llx", tid, addr);
return;
}
setCmd(MEM_FETCH_DATA);
setThrdId(tid);
setId(id);
setAddr(addr);
setSize(size);
setDsrc(dsrc);
setCacheL1(cacheL1);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
uint8_t szv = sz2szv(size, addr & (~ADDR_MASK));
setSizeV(szv);
setSrcBank((addr & L2_BANK_ADDR_BITS) >> L2_BANK_ADDR_SFT);
auxInit();
}
/******************************************************************************
* A FetchFill is issued when a fetched line is filled into L1 I$ and the
* new instruction can be seen by next access from the same core
******************************************************************************/
FetchFillCmd::FetchFillCmd(uint32_t tid,
uint64_t id,
uint64_t addr,
uint64_t cycle)
{
setCmd(MEM_FETCH_FILL);
setThrdId(tid);
setId(id);
setAddr(addr);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
auxInit();
}
/******************************************************************************
* A DmaStoreCmd is issued when a dma_store command is issued, it is treated
* almost like a mem_slam, but with inv_vec to handle L1 conflict.
******************************************************************************/
DmaStoreCmd::DmaStoreCmd(uint32_t tid,
uint64_t id,
uint64_t addr,
uint64_t data,
uint8_t size_vector,
uint32_t inv,
int _tsize,
uint64_t cycle)
{
uint8_t size = szv2sz(size_vector);
setCmd(MEM_DMA_STORE);
setThrdId(tid);
setId(id);
setAddr(addr);
setData(data);
setSizeV(size_vector);
setInv(inv);
setCycle(cycle);
setCoreId(tid/NSTRANDS_PER_CORE);
setSize(size);
setTsize(_tsize);
setSrcBank((addr & L2_BANK_ADDR_BITS) >> L2_BANK_ADDR_SFT);
auxInit();
}