mem-ruby: Add a CHI-TLM CacheController
This commit is extending the previously defined CHIGenericController
to implement a CacheController which acts as a bridge between the
AMBA TLM 2.0 implementation of CHI [1][2] with the gem5 (ruby) one.
In other words it translates AMBA CHI transactions into ruby
messages (which are then forwarded to the MessageQueues)
and viceversa.
ARM::CHI::Payload, CHIRequestMsg
<--> CHIDataMsg
ARM::CHI::Phase CHIResponseMsg
CHIDataMsg
[1]: https://developer.arm.com/documentation/101459/latest
[2]: https://developer.arm.com/Architectures/AMBA#Downloads
Change-Id: I6f35e7b4ade4d0de1b5e5d2dbf73ce796a9f9fb6
Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
committed by
Bobby R. Bruce
parent
76541929c9
commit
b795d28ee8
75
src/mem/ruby/protocol/chi/tlm/SConscript
Normal file
75
src/mem/ruby/protocol/chi/tlm/SConscript
Normal file
@@ -0,0 +1,75 @@
|
||||
# -*- mode:python -*-
|
||||
# Copyright (c) 2024 Arm Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# 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.
|
||||
|
||||
Import("*")
|
||||
|
||||
|
||||
def get_tlm_paths():
|
||||
tlm_dir = Dir(env["CONF"]["TLM_PATH"])
|
||||
assert tlm_dir is not None and tlm_dir != "."
|
||||
|
||||
include_dir = tlm_dir.Dir("include")
|
||||
lib_dir = tlm_dir.Dir("lib")
|
||||
|
||||
model_lib = "libarmtlmchi.so"
|
||||
if not lib_dir.File(model_lib).exists():
|
||||
print(f"Error: Can't find {model_lib} in AMBA TLM directory.")
|
||||
print(f"TLM path: {tlm_dir}")
|
||||
Exit(1)
|
||||
|
||||
return include_dir, lib_dir, "armtlmchi"
|
||||
|
||||
|
||||
if env["CONF"]["BUILD_TLM"]:
|
||||
include_path, lib_path, tlm_lib = get_tlm_paths()
|
||||
|
||||
env.Append(CPPPATH=include_path)
|
||||
env.Append(LIBPATH=lib_path)
|
||||
env.Append(LIBS=[tlm_lib])
|
||||
|
||||
SimObject(
|
||||
"TlmController.py", sim_objects=["TlmController"], tags="arm isa"
|
||||
)
|
||||
Source("utils.cc", tags="arm isa")
|
||||
Source("controller.cc", tags="arm isa")
|
||||
DebugFlag("TLM", tags="arm isa")
|
||||
|
||||
print(
|
||||
"BUILD_TLM set: "
|
||||
f"Building TLM integration with libarmtlmchi.so from '{lib_path}'\n"
|
||||
)
|
||||
elif not GetOption("silent"):
|
||||
print("BUILD_TLM not set, not building CHI-TLM integration\n")
|
||||
58
src/mem/ruby/protocol/chi/tlm/SConsopts
Normal file
58
src/mem/ruby/protocol/chi/tlm/SConsopts
Normal file
@@ -0,0 +1,58 @@
|
||||
# -*- mode:python -*-
|
||||
# Copyright (c) 2023 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# 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.
|
||||
|
||||
Import('*')
|
||||
|
||||
import os
|
||||
|
||||
tlm_vars = Variables()
|
||||
tlm_vars.AddVariables(
|
||||
PathVariable('TLM_PATH', "CHI TLM library path", '.', PathVariable.PathIsDir),
|
||||
)
|
||||
tlm_vars.Update(main)
|
||||
|
||||
main["CONF"]["BUILD_TLM"] = False
|
||||
|
||||
tlm_path_ev = os.environ.get("TLM_PATH", None)
|
||||
if tlm_path_ev is not None and tlm_path_ev != ".":
|
||||
print(f"Setting TLM_PATH from os.environ: {tlm_path_ev}")
|
||||
main["CONF"]["TLM_PATH"] = tlm_path_ev
|
||||
main["CONF"]["BUILD_TLM"] = True
|
||||
|
||||
if "TLM_PATH" in main and main["TLM_PATH"] != ".":
|
||||
print(f"Setting TLM_PATH to SCons command line: {main['TLM_PATH']}")
|
||||
main["CONF"]["TLM_PATH"] = str(main["TLM_PATH"])
|
||||
main["CONF"]["BUILD_TLM"] = True
|
||||
43
src/mem/ruby/protocol/chi/tlm/TlmController.py
Normal file
43
src/mem/ruby/protocol/chi/tlm/TlmController.py
Normal file
@@ -0,0 +1,43 @@
|
||||
# Copyright (c) 2023 ARM Limited
|
||||
# All rights reserved.
|
||||
#
|
||||
# The license below extends only to copyright in the software and shall
|
||||
# not be construed as granting a license to any other intellectual
|
||||
# property including but not limited to intellectual property relating
|
||||
# to a hardware implementation of the functionality of the software
|
||||
# licensed hereunder. You may use the software subject to the license
|
||||
# terms below provided that you ensure that this notice is replicated
|
||||
# unmodified and in its entirety in all distributions of the software,
|
||||
# modified or unmodified, in source code or in binary form.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met: redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer;
|
||||
# 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;
|
||||
# neither the name of the copyright holders nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from m5.objects.CHIGeneric import CHIGenericController
|
||||
from m5.params import *
|
||||
|
||||
|
||||
class TlmController(CHIGenericController):
|
||||
type = "TlmController"
|
||||
cxx_header = "mem/ruby/protocol/chi/tlm/controller.hh"
|
||||
cxx_class = "gem5::tlm::chi::CacheController"
|
||||
424
src/mem/ruby/protocol/chi/tlm/controller.cc
Normal file
424
src/mem/ruby/protocol/chi/tlm/controller.cc
Normal file
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/controller.hh"
|
||||
|
||||
#include "debug/TLM.hh"
|
||||
#include "mem/ruby/protocol/CHIDataMsg.hh"
|
||||
#include "mem/ruby/protocol/CHIRequestMsg.hh"
|
||||
#include "mem/ruby/protocol/CHIResponseMsg.hh"
|
||||
#include "mem/ruby/protocol/chi/tlm/utils.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
using namespace ruby;
|
||||
|
||||
CacheController::CacheController(const Params &p)
|
||||
: CHIGenericController(p)
|
||||
{
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::recvRequestMsg(const CHIRequestMsg *msg)
|
||||
{
|
||||
panic("recvRequestMsg");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::recvSnoopMsg(const CHIRequestMsg *msg)
|
||||
{
|
||||
ARM::CHI::Phase phase;
|
||||
ARM::CHI::Payload *payload = ARM::CHI::Payload::new_payload();
|
||||
|
||||
payload->address = msg->m_addr;
|
||||
payload->ns = msg->m_ns;
|
||||
phase.channel = ARM::CHI::CHANNEL_SNP;
|
||||
phase.snp_opcode = ruby_to_tlm::snpOpcode(msg->m_type);
|
||||
phase.txn_id = msg->m_txnId % 1024;
|
||||
|
||||
bw(payload, &phase);
|
||||
|
||||
// payload->unref(); ??
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::pCreditGrant(const CHIResponseMsg *msg)
|
||||
{
|
||||
ARM::CHI::Phase phase;
|
||||
ARM::CHI::Payload *payload = ARM::CHI::Payload::new_payload();
|
||||
phase.channel = ARM::CHI::CHANNEL_RSP;
|
||||
phase.rsp_opcode = ARM::CHI::RSP_OPCODE_PCRD_GRANT;
|
||||
phase.pcrd_type = 0; // TODO: set this one depending on allow retry
|
||||
|
||||
bw(payload, &phase);
|
||||
|
||||
payload->unref(); // TODO: check this
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::recvResponseMsg(const CHIResponseMsg *msg)
|
||||
{
|
||||
|
||||
if (msg->m_type == ruby::CHIResponseType_PCrdGrant) {
|
||||
// P-credit grant does not refer to a specific transaction id
|
||||
pCreditGrant(msg);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto txn_id = msg->m_txnId;
|
||||
if (auto it = pendingTransactions.find(txn_id);
|
||||
it != pendingTransactions.end()) {
|
||||
|
||||
auto& transaction = it->second;
|
||||
if (transaction->handle(msg))
|
||||
pendingTransactions.erase(it);
|
||||
} else {
|
||||
panic("recvResponseMsg");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::recvDataMsg(const CHIDataMsg *msg)
|
||||
{
|
||||
auto txn_id = msg->m_txnId;
|
||||
if (auto it = pendingTransactions.find(txn_id);
|
||||
it != pendingTransactions.end()) {
|
||||
auto& transaction = it->second;
|
||||
if (transaction->handle(msg))
|
||||
pendingTransactions.erase(it);
|
||||
} else {
|
||||
panic("Not able to find transaction");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::Transaction::handle(const CHIResponseMsg *msg)
|
||||
{
|
||||
const auto opcode = ruby_to_tlm::rspOpcode(msg->m_type);
|
||||
phase.channel = ARM::CHI::CHANNEL_RSP;
|
||||
phase.rsp_opcode = opcode;
|
||||
phase.resp = ruby_to_tlm::rspResp(msg->m_type);
|
||||
phase.txn_id = msg->m_txnId % 1024;
|
||||
|
||||
controller->bw(payload, &phase);
|
||||
return opcode != ARM::CHI::RSP_OPCODE_RETRY_ACK;
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::ReadTransaction::handle(const CHIDataMsg *msg)
|
||||
{
|
||||
dataMsgCnt++;
|
||||
|
||||
for (auto byte = 0; byte < controller->cacheLineSize; byte++) {
|
||||
if (msg->m_bitMask.test(byte))
|
||||
payload->data[byte] = msg->m_dataBlk.getByte(byte);
|
||||
}
|
||||
|
||||
// ARM::CHI::Phase phase;
|
||||
phase.channel = ARM::CHI::CHANNEL_DAT;
|
||||
phase.dat_opcode = ruby_to_tlm::datOpcode(msg->m_type);
|
||||
phase.resp = ruby_to_tlm::datResp(msg->m_type);
|
||||
phase.txn_id = msg->m_txnId % 1024;
|
||||
phase.data_id = dataId(msg->m_addr + msg->m_bitMask.firstBitSet(true));
|
||||
|
||||
// This is a hack, we should fix it on the ruby side
|
||||
if (forward(msg)) {
|
||||
controller->bw(payload, &phase);
|
||||
}
|
||||
|
||||
if (dataMsgCnt == controller->dataMsgsPerLine) {
|
||||
if (phase.exp_comp_ack == false) {
|
||||
// The client is not sending a CompAck but ruby is
|
||||
// expecting it so we send it anyway
|
||||
controller->sendCompAck(*payload, phase);
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::ReadTransaction::handle(const CHIResponseMsg *msg)
|
||||
{
|
||||
/// TODO: remove this, DBID is not sent
|
||||
phase.dbid = msg->m_dbid % 1024;
|
||||
return Transaction::handle(msg);
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::ReadTransaction::forward(const CHIDataMsg *msg)
|
||||
{
|
||||
if (payload->size == 6) {
|
||||
return true;
|
||||
} else {
|
||||
if (msg->m_bitMask.test(payload->address - msg->m_addr)) {
|
||||
return true;
|
||||
} else {
|
||||
// This is not the packet holding the original address
|
||||
// Do not forward it back (just drop it)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::DatalessTransaction::handle(const CHIResponseMsg *msg)
|
||||
{
|
||||
const auto opcode = ruby_to_tlm::rspOpcode(msg->m_type);
|
||||
assert(opcode == ARM::CHI::RSP_OPCODE_COMP ||
|
||||
opcode == ARM::CHI::RSP_OPCODE_RETRY_ACK);
|
||||
|
||||
return Transaction::handle(msg);
|
||||
}
|
||||
|
||||
bool
|
||||
CacheController::WriteTransaction::handle(const CHIResponseMsg *msg)
|
||||
{
|
||||
const auto opcode = ruby_to_tlm::rspOpcode(msg->m_type);
|
||||
if (opcode == ARM::CHI::RSP_OPCODE_COMP_DBID_RESP) {
|
||||
recvComp = true;
|
||||
recvDBID = true;
|
||||
}
|
||||
if (opcode == ARM::CHI::RSP_OPCODE_COMP) {
|
||||
recvComp = true;
|
||||
}
|
||||
if (opcode == ARM::CHI::RSP_OPCODE_DBID_RESP) {
|
||||
recvDBID = true;
|
||||
}
|
||||
|
||||
phase.dbid = msg->m_dbid % 1024;
|
||||
Transaction::handle(msg);
|
||||
|
||||
return recvComp && recvDBID;
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::sendCompAck(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase)
|
||||
{
|
||||
auto res_msg = std::make_shared<CHIResponseMsg>(
|
||||
curTick(), cacheLineSize, m_ruby_system);
|
||||
|
||||
res_msg->m_addr = ruby::makeLineAddress(payload.address, cacheLineBits);
|
||||
res_msg->m_type = CHIResponseType_CompAck;
|
||||
res_msg->m_Destination.add(mapAddressToDownstreamMachine(payload.address));
|
||||
res_msg->m_responder = getMachineID();
|
||||
|
||||
res_msg->m_txnId = phase.txn_id;
|
||||
|
||||
sendResponseMsg(res_msg);
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::sendMsg(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase)
|
||||
{
|
||||
switch (phase.channel) {
|
||||
case ARM::CHI::CHANNEL_REQ:
|
||||
sendRequestMsg(payload, phase);
|
||||
break;
|
||||
case ARM::CHI::CHANNEL_DAT:
|
||||
sendDataMsg(payload, phase);
|
||||
break;
|
||||
case ARM::CHI::CHANNEL_RSP:
|
||||
sendResponseMsg(payload, phase);
|
||||
break;
|
||||
default:
|
||||
panic("Unimplemented channel: %d", phase.channel);
|
||||
}
|
||||
}
|
||||
|
||||
Addr
|
||||
CacheController::reqAddr(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase) const
|
||||
{
|
||||
switch (phase.req_opcode) {
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_NO_SNP_PTL:
|
||||
return ruby::makeLineAddress(payload.address, cacheLineBits) +
|
||||
ctz64(payload.byte_enable);
|
||||
default:
|
||||
return payload.address;
|
||||
}
|
||||
}
|
||||
|
||||
Addr
|
||||
CacheController::reqSize(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase) const
|
||||
{
|
||||
switch (phase.req_opcode) {
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_NO_SNP_PTL:
|
||||
assert(transactionSize(payload.size) >= popCount(payload.byte_enable));
|
||||
return popCount(payload.byte_enable);
|
||||
default:
|
||||
return transactionSize(payload.size);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::sendRequestMsg(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase)
|
||||
{
|
||||
auto req_msg = std::make_shared<CHIRequestMsg>(
|
||||
curTick(), cacheLineSize, m_ruby_system);
|
||||
|
||||
req_msg->m_addr = ruby::makeLineAddress(payload.address, cacheLineBits);
|
||||
req_msg->m_accAddr = reqAddr(payload, phase);
|
||||
req_msg->m_accSize = reqSize(payload, phase);
|
||||
req_msg->m_requestor = getMachineID();
|
||||
req_msg->m_fwdRequestor = getMachineID();
|
||||
req_msg->m_dataToFwdRequestor = false;
|
||||
req_msg->m_type = tlm_to_ruby::reqOpcode(phase.req_opcode);
|
||||
req_msg->m_isSeqReqValid = false;
|
||||
req_msg->m_is_local_pf = false;
|
||||
req_msg->m_is_remote_pf = false;
|
||||
req_msg->m_allowRetry = phase.allow_retry;
|
||||
req_msg->m_Destination.add(mapAddressToDownstreamMachine(payload.address));
|
||||
|
||||
req_msg->m_txnId = phase.txn_id + (payload.lpid * 1024);
|
||||
req_msg->m_ns = payload.ns;
|
||||
|
||||
sendRequestMsg(req_msg);
|
||||
|
||||
pendingTransactions[req_msg->m_txnId] = Transaction::gen(
|
||||
this, payload, phase);
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::sendDataMsg(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase)
|
||||
{
|
||||
auto data_msg = std::make_shared<CHIDataMsg>(
|
||||
curTick(), cacheLineSize, m_ruby_system);
|
||||
|
||||
data_msg->m_addr = ruby::makeLineAddress(payload.address, cacheLineBits);
|
||||
data_msg->m_responder = getMachineID();
|
||||
data_msg->m_type = tlm_to_ruby::datOpcode(phase.dat_opcode, phase.resp);
|
||||
data_msg->m_Destination.add(
|
||||
mapAddressToDownstreamMachine(payload.address));
|
||||
data_msg->m_txnId = phase.txn_id + (payload.lpid * 1024);
|
||||
data_msg->m_dataBlk.setData(payload.data, 0, cacheLineSize);
|
||||
|
||||
std::vector<bool> byte_enabled(cacheLineSize, false);
|
||||
|
||||
const Addr data_id_offset = phase.data_id * 16;
|
||||
for (int bit = data_id_offset; bit < data_id_offset + 32; bit++) {
|
||||
if (bits(payload.byte_enable, bit)) {
|
||||
byte_enabled[bit] = true;
|
||||
}
|
||||
}
|
||||
|
||||
data_msg->m_bitMask = WriteMask(byte_enabled.size(), byte_enabled);
|
||||
|
||||
sendDataMsg(data_msg);
|
||||
}
|
||||
|
||||
void
|
||||
CacheController::sendResponseMsg(ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase)
|
||||
{
|
||||
auto res_msg = std::make_shared<CHIResponseMsg>(
|
||||
curTick(), cacheLineSize, m_ruby_system);
|
||||
|
||||
res_msg->m_addr = ruby::makeLineAddress(payload.address, cacheLineBits);
|
||||
res_msg->m_responder = getMachineID();
|
||||
res_msg->m_type = tlm_to_ruby::rspOpcode(phase.rsp_opcode, phase.resp);
|
||||
res_msg->m_Destination.add(mapAddressToDownstreamMachine(payload.address));
|
||||
res_msg->m_txnId = phase.txn_id + (payload.lpid * 1024);
|
||||
|
||||
sendResponseMsg(res_msg);
|
||||
}
|
||||
|
||||
CacheController::Transaction::Transaction(CacheController *_controller,
|
||||
ARM::CHI::Payload &_payload,
|
||||
ARM::CHI::Phase &_phase)
|
||||
: controller(_controller), payload(&_payload), phase(_phase)
|
||||
{
|
||||
payload->ref();
|
||||
}
|
||||
|
||||
CacheController::Transaction::~Transaction()
|
||||
{
|
||||
payload->unref();
|
||||
}
|
||||
|
||||
std::unique_ptr<CacheController::Transaction>
|
||||
CacheController::Transaction::gen(CacheController *controller,
|
||||
ARM::CHI::Payload &payload,
|
||||
ARM::CHI::Phase &phase)
|
||||
{
|
||||
switch (phase.req_opcode) {
|
||||
case ARM::CHI::REQ_OPCODE_READ_SHARED:
|
||||
case ARM::CHI::REQ_OPCODE_READ_CLEAN:
|
||||
case ARM::CHI::REQ_OPCODE_READ_ONCE:
|
||||
case ARM::CHI::REQ_OPCODE_READ_NO_SNP:
|
||||
case ARM::CHI::REQ_OPCODE_READ_UNIQUE:
|
||||
case ARM::CHI::REQ_OPCODE_READ_NOT_SHARED_DIRTY:
|
||||
case ARM::CHI::REQ_OPCODE_READ_PREFER_UNIQUE:
|
||||
case ARM::CHI::REQ_OPCODE_MAKE_READ_UNIQUE:
|
||||
return std::make_unique<ReadTransaction>(controller, payload, phase);
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_NO_SNP_PTL:
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_NO_SNP_FULL:
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_UNIQUE_ZERO:
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_UNIQUE_FULL:
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_BACK_FULL:
|
||||
// This is a write transaction for now. Will
|
||||
// this still be the case once WriteEvictOrEvict will also be supported
|
||||
// in ruby
|
||||
case ARM::CHI::REQ_OPCODE_WRITE_EVICT_OR_EVICT:
|
||||
return std::make_unique<WriteTransaction>(
|
||||
controller, payload, phase);
|
||||
case ARM::CHI::REQ_OPCODE_CLEAN_UNIQUE:
|
||||
case ARM::CHI::REQ_OPCODE_MAKE_UNIQUE:
|
||||
case ARM::CHI::REQ_OPCODE_EVICT:
|
||||
case ARM::CHI::REQ_OPCODE_STASH_ONCE_SEP_SHARED:
|
||||
case ARM::CHI::REQ_OPCODE_STASH_ONCE_SEP_UNIQUE:
|
||||
return std::make_unique<DatalessTransaction>(
|
||||
controller, payload, phase);
|
||||
default:
|
||||
panic("Impossible to generate transaction object");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
177
src/mem/ruby/protocol/chi/tlm/controller.hh
Normal file
177
src/mem/ruby/protocol/chi/tlm/controller.hh
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __MEM_RUBY_PROTOCOL_CHI_TLM_CONTROLLER_HH__
|
||||
#define __MEM_RUBY_PROTOCOL_CHI_TLM_CONTROLLER_HH__
|
||||
|
||||
#include <ARM/TLM/arm_chi.h>
|
||||
|
||||
#include "mem/ruby/protocol/chi/generic/CHIGenericController.hh"
|
||||
#include "mem/ruby/protocol/CHIDataType.hh"
|
||||
#include "mem/ruby/protocol/CHIRequestType.hh"
|
||||
#include "mem/ruby/protocol/CHIResponseType.hh"
|
||||
#include "mem/ruby/protocol/RequestStatus.hh"
|
||||
#include "mem/ruby/protocol/WriteMask.hh"
|
||||
#include "params/TlmController.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace ruby {
|
||||
class CHIRequestMsg;
|
||||
class CHIResponseMsg;
|
||||
class CHIDataMsg;
|
||||
}
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
/**
|
||||
* The tlm::chi::CacheController is a ruby CacheController which acts as
|
||||
* a bridge between the AMBA TLM 2.0 implementation of CHI [1][2] with
|
||||
* the gem5 (ruby) one.
|
||||
*
|
||||
* In other words it translates AMBA CHI transactions into ruby
|
||||
* messages (which are then forwarded to the MessageQueues)
|
||||
* and viceversa.
|
||||
*
|
||||
* ARM::CHI::Payload, CHIRequestMsg
|
||||
* <--> CHIDataMsg
|
||||
* ARM::CHI::Phase CHIResponseMsg
|
||||
* CHIDataMsg
|
||||
*
|
||||
* To connect the tlm::chi::CacheController in python is relatively
|
||||
* straightforward. The upstream initiator/RNF needs to have a pointer
|
||||
* to the controller, and this can be done for example with
|
||||
* SimObject params.
|
||||
* Example:
|
||||
*
|
||||
* class MyRNF():
|
||||
* chi_controller = Param.TlmController("TLM-to-Ruby CacheController")
|
||||
*
|
||||
* The RNF C++ code would then have to set the
|
||||
* tlm::chi::CacheController::bw callback to implement the backward path
|
||||
* to send data from downstream to upstream.
|
||||
*
|
||||
* [1]: https://developer.arm.com/documentation/101459/latest
|
||||
* [2]: https://developer.arm.com/Architectures/AMBA#Downloads
|
||||
*/
|
||||
class CacheController : public ruby::CHIGenericController
|
||||
{
|
||||
public:
|
||||
PARAMS(TlmController);
|
||||
CacheController(const Params &p);
|
||||
|
||||
/** Set this to send data upstream */
|
||||
std::function<void(ARM::CHI::Payload* payload, ARM::CHI::Phase* phase)> bw;
|
||||
|
||||
bool recvRequestMsg(const ruby::CHIRequestMsg *msg) override;
|
||||
bool recvSnoopMsg(const ruby::CHIRequestMsg *msg) override;
|
||||
bool recvResponseMsg(const ruby::CHIResponseMsg *msg) override;
|
||||
bool recvDataMsg(const ruby::CHIDataMsg *msg) override;
|
||||
|
||||
void sendMsg(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase);
|
||||
using CHIGenericController::sendRequestMsg;
|
||||
void sendRequestMsg(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase);
|
||||
using CHIGenericController::sendResponseMsg;
|
||||
void sendResponseMsg(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase);
|
||||
void sendCompAck(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase);
|
||||
using CHIGenericController::sendDataMsg;
|
||||
void sendDataMsg(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase);
|
||||
|
||||
Addr reqAddr(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase) const;
|
||||
Addr reqSize(ARM::CHI::Payload &payload, ARM::CHI::Phase &phase) const;
|
||||
|
||||
void pCreditGrant(const ruby::CHIResponseMsg *msg);
|
||||
|
||||
struct Transaction
|
||||
{
|
||||
enum class Type
|
||||
{
|
||||
READ,
|
||||
WRITE,
|
||||
DATALESS
|
||||
};
|
||||
|
||||
Transaction(CacheController *parent,
|
||||
ARM::CHI::Payload &_payload,
|
||||
ARM::CHI::Phase &_phase);
|
||||
~Transaction();
|
||||
|
||||
static std::unique_ptr<Transaction> gen(CacheController *parent,
|
||||
ARM::CHI::Payload &_payload,
|
||||
ARM::CHI::Phase &_phase);
|
||||
|
||||
virtual bool
|
||||
handle(const ruby::CHIDataMsg *msg)
|
||||
{
|
||||
panic("Unimplemented");
|
||||
}
|
||||
|
||||
virtual bool handle(const ruby::CHIResponseMsg *msg);
|
||||
|
||||
CacheController *controller;
|
||||
ARM::CHI::Payload *payload;
|
||||
ARM::CHI::Phase phase;
|
||||
};
|
||||
struct ReadTransaction : public Transaction
|
||||
{
|
||||
using Transaction::Transaction;
|
||||
bool handle(const ruby::CHIDataMsg *msg) override;
|
||||
bool handle(const ruby::CHIResponseMsg *msg) override;
|
||||
bool forward(const ruby::CHIDataMsg *msg);
|
||||
|
||||
uint8_t dataMsgCnt = 0;
|
||||
};
|
||||
struct DatalessTransaction : public Transaction
|
||||
{
|
||||
using Transaction::Transaction;
|
||||
bool handle(const ruby::CHIResponseMsg *msg) override;
|
||||
};
|
||||
struct WriteTransaction : public Transaction
|
||||
{
|
||||
using Transaction::Transaction;
|
||||
bool handle(const ruby::CHIResponseMsg *msg) override;
|
||||
bool recvComp = false;
|
||||
bool recvDBID = false;
|
||||
};
|
||||
std::unordered_map<uint16_t, std::unique_ptr<Transaction>> pendingTransactions;
|
||||
};
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __MEM_RUBY_PROTOCOL_CHI_TLM_CONTROLLER_HH__
|
||||
498
src/mem/ruby/protocol/chi/tlm/utils.cc
Normal file
498
src/mem/ruby/protocol/chi/tlm/utils.cc
Normal file
@@ -0,0 +1,498 @@
|
||||
/*
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/utils.hh"
|
||||
|
||||
#include "base/bitfield.hh"
|
||||
#include "base/logging.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
namespace {
|
||||
|
||||
using namespace ARM::CHI;
|
||||
|
||||
std::string
|
||||
reqOpcodeToName(ReqOpcode req_opcode)
|
||||
{
|
||||
switch (req_opcode) {
|
||||
case REQ_OPCODE_REQ_LCRD_RETURN: return "ReqLCrdReturn";
|
||||
case REQ_OPCODE_READ_SHARED: return "ReadShared";
|
||||
case REQ_OPCODE_READ_CLEAN: return "ReadClean";
|
||||
case REQ_OPCODE_READ_ONCE: return "ReadOnce";
|
||||
case REQ_OPCODE_READ_NO_SNP: return "ReadNoSnp";
|
||||
case REQ_OPCODE_PCRD_RETURN: return "PCrdReturn";
|
||||
case REQ_OPCODE_READ_UNIQUE: return "ReadUnique";
|
||||
case REQ_OPCODE_CLEAN_SHARED: return "CleanShared";
|
||||
case REQ_OPCODE_CLEAN_INVALID: return "CleanInvalid";
|
||||
case REQ_OPCODE_MAKE_INVALID: return "MakeInvalid";
|
||||
case REQ_OPCODE_CLEAN_UNIQUE: return "CleanUnique";
|
||||
case REQ_OPCODE_MAKE_UNIQUE: return "MakeUnique";
|
||||
case REQ_OPCODE_EVICT: return "Evict";
|
||||
case REQ_OPCODE_EO_BARRIER: return "EoBarrier";
|
||||
case REQ_OPCODE_EC_BARRIER: return "EcBarrier";
|
||||
case REQ_OPCODE_READ_NO_SNP_SEP: return "ReadNoSnpSep";
|
||||
case REQ_OPCODE_CLEAN_SHARED_PERSIST_SEP: return "CleanSharedPersistSep";
|
||||
case REQ_OPCODE_DVM_OP: return "DvmOp";
|
||||
case REQ_OPCODE_WRITE_EVICT_FULL: return "WriteEvictFull";
|
||||
case REQ_OPCODE_WRITE_CLEAN_PTL: return "WriteCleanPtl";
|
||||
case REQ_OPCODE_WRITE_CLEAN_FULL: return "WriteCleanFull";
|
||||
case REQ_OPCODE_WRITE_UNIQUE_PTL: return "WriteUniquePtl";
|
||||
case REQ_OPCODE_WRITE_UNIQUE_FULL: return "WriteUniqueFull";
|
||||
case REQ_OPCODE_WRITE_BACK_PTL: return "WriteBackPtl";
|
||||
case REQ_OPCODE_WRITE_BACK_FULL: return "WriteBackFull";
|
||||
case REQ_OPCODE_WRITE_NO_SNP_PTL: return "WriteNoSnpPtl";
|
||||
case REQ_OPCODE_WRITE_NO_SNP_FULL: return "WriteNoSnpFull";
|
||||
case REQ_OPCODE_WRITE_UNIQUE_FULL_STASH: return "WriteUniqueFullStash";
|
||||
case REQ_OPCODE_WRITE_UNIQUE_PTL_STASH: return "WriteUniquePtlStash";
|
||||
case REQ_OPCODE_STASH_ONCE_SHARED: return "StashOnceShared";
|
||||
case REQ_OPCODE_STASH_ONCE_UNIQUE: return "StashOnceUnique";
|
||||
case REQ_OPCODE_READ_ONCE_CLEAN_INVALID: return "ReadOnceCleanInvalid";
|
||||
case REQ_OPCODE_READ_ONCE_MAKE_INVALID: return "ReadOnceMakeInvalid";
|
||||
case REQ_OPCODE_READ_NOT_SHARED_DIRTY: return "ReadNotSharedDirty";
|
||||
case REQ_OPCODE_CLEAN_SHARED_PERSIST: return "CleanSharedPersist";
|
||||
case REQ_OPCODE_ATOMIC_STORE_ADD: return "AtomicStoreAdd";
|
||||
case REQ_OPCODE_ATOMIC_STORE_CLR: return "AtomicStoreClr";
|
||||
case REQ_OPCODE_ATOMIC_STORE_EOR: return "AtomicStoreEor";
|
||||
case REQ_OPCODE_ATOMIC_STORE_SET: return "AtomicStoreSet";
|
||||
case REQ_OPCODE_ATOMIC_STORE_SMAX: return "AtomicStoreSmax";
|
||||
case REQ_OPCODE_ATOMIC_STORE_SMIN: return "AtomicStoreSmin";
|
||||
case REQ_OPCODE_ATOMIC_STORE_UMAX: return "AtomicStoreUmax";
|
||||
case REQ_OPCODE_ATOMIC_STORE_UMIN: return "AtomicStoreUmin";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_ADD: return "AtomicLoadAdd";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_CLR: return "AtomicLoadClr";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_EOR: return "AtomicLoadEor";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_SET: return "AtomicLoadSet";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_SMAX: return "AtomicLoadSmax";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_SMIN: return "AtomicLoadSmin";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_UMAX: return "AtomicLoadUmax";
|
||||
case REQ_OPCODE_ATOMIC_LOAD_UMIN: return "AtomicLoadUmin";
|
||||
case REQ_OPCODE_ATOMIC_SWAP: return "AtomicSwap";
|
||||
case REQ_OPCODE_ATOMIC_COMPARE: return "AtomicCompare";
|
||||
case REQ_OPCODE_PREFETCH_TGT: return "PrefetchTgt";
|
||||
case REQ_OPCODE_MAKE_READ_UNIQUE: return "MakeReadUnique";
|
||||
case REQ_OPCODE_WRITE_EVICT_OR_EVICT: return "WriteEvictOrEvict";
|
||||
case REQ_OPCODE_WRITE_UNIQUE_ZERO: return "WriteUniqueZero";
|
||||
case REQ_OPCODE_WRITE_NO_SNP_ZERO: return "WriteNoSnpZero";
|
||||
case REQ_OPCODE_STASH_ONCE_SEP_SHARED: return "StashOnceSepShared";
|
||||
case REQ_OPCODE_STASH_ONCE_SEP_UNIQUE: return "StashOnceSepUnique";
|
||||
case REQ_OPCODE_READ_PREFER_UNIQUE: return "ReadPreferUnique";
|
||||
case REQ_OPCODE_WRITE_NO_SNP_FULL_CLEAN_SH: return "WriteNoSnpFullCleanSh";
|
||||
default: return std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
snpOpcodeToName(SnpOpcode snp_opcode)
|
||||
{
|
||||
switch (snp_opcode) {
|
||||
case SNP_OPCODE_SNP_LCRD_RETURN: return "SnpLcrdReturn";
|
||||
case SNP_OPCODE_SNP_SHARED: return "SnpShared";
|
||||
case SNP_OPCODE_SNP_CLEAN: return "SnpClean";
|
||||
case SNP_OPCODE_SNP_ONCE: return "SnpOnce";
|
||||
case SNP_OPCODE_SNP_NOT_SHARED_DIRTY: return "SnpNotSharedDirty";
|
||||
case SNP_OPCODE_SNP_UNIQUE_STASH: return "SnpUniqueStash";
|
||||
case SNP_OPCODE_SNP_MAKE_INVALID_STASH: return "SnpMakeInvalidStash";
|
||||
case SNP_OPCODE_SNP_UNIQUE: return "SnpUnique";
|
||||
case SNP_OPCODE_SNP_CLEAN_SHARED: return "SnpCleanShared";
|
||||
case SNP_OPCODE_SNP_CLEAN_INVALID: return "SnpCleanInvalid";
|
||||
case SNP_OPCODE_SNP_MAKE_INVALID: return "SnpMakeInvalid";
|
||||
case SNP_OPCODE_SNP_STASH_UNIQUE: return "SnpStashUnique";
|
||||
case SNP_OPCODE_SNP_STASH_SHARED: return "SnpStashShared";
|
||||
case SNP_OPCODE_SNP_DVM_OP: return "SnpDvmOp";
|
||||
case SNP_OPCODE_SNP_QUERY: return "SnpQuery";
|
||||
case SNP_OPCODE_SNP_SHARED_FWD: return "SnpSharedFwd";
|
||||
case SNP_OPCODE_SNP_CLEAN_FWD: return "SnpCleanFwd";
|
||||
case SNP_OPCODE_SNP_ONCE_FWD: return "SnpOnceFwd";
|
||||
case SNP_OPCODE_SNP_NOT_SHARED_DIRTY_FWD: return "SnpNotSharedDirtyFwd";
|
||||
case SNP_OPCODE_SNP_PREFER_UNIQUE: return "SnpPreferUnique";
|
||||
case SNP_OPCODE_SNP_PREFER_UNIQUE_FWD: return "SnpPreferUniqueFwd";
|
||||
case SNP_OPCODE_SNP_UNIQUE_FWD: return "SnpUniqueFwd";
|
||||
default: return std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
datOpcodeToName(DatOpcode dat_opcode)
|
||||
{
|
||||
switch (dat_opcode) {
|
||||
case DAT_OPCODE_DAT_LCRD_RETURN: return "DatLcrdReturn";
|
||||
case DAT_OPCODE_SNP_RESP_DATA: return "SnpRespData";
|
||||
case DAT_OPCODE_COPY_BACK_WR_DATA: return "CopyBackWrData";
|
||||
case DAT_OPCODE_NON_COPY_BACK_WR_DATA: return "NonCopyBackWrData";
|
||||
case DAT_OPCODE_COMP_DATA: return "CompData";
|
||||
case DAT_OPCODE_SNP_RESP_DATA_PTL: return "SnpRespDataPtl";
|
||||
case DAT_OPCODE_SNP_RESP_DATA_FWDED: return "SnpRespDataFwded";
|
||||
case DAT_OPCODE_WRITE_DATA_CANCEL: return "WriteDataCancel";
|
||||
case DAT_OPCODE_DATA_SEP_RESP: return "DataSepResp";
|
||||
case DAT_OPCODE_NCB_WR_DATA_COMP_ACK: return "NcbWrDataCompAck";
|
||||
default: return std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
rspOpcodeToName(RspOpcode rsp_opcode)
|
||||
{
|
||||
switch (rsp_opcode) {
|
||||
case RSP_OPCODE_RSP_LCRD_RETURN: return "RspLcrdReturn";
|
||||
case RSP_OPCODE_SNP_RESP: return "SnpResp";
|
||||
case RSP_OPCODE_COMP_ACK: return "CompAck";
|
||||
case RSP_OPCODE_RETRY_ACK: return "RetryAck";
|
||||
case RSP_OPCODE_COMP: return "OpcodeComp";
|
||||
case RSP_OPCODE_COMP_DBID_RESP: return "CompDbidResp";
|
||||
case RSP_OPCODE_DBID_RESP: return "DbidResp";
|
||||
case RSP_OPCODE_PCRD_GRANT: return "PcrdGrant";
|
||||
case RSP_OPCODE_READ_RECEIPT: return "ReadReceipt";
|
||||
case RSP_OPCODE_SNP_RESP_FWDED: return "SnpRespFwded";
|
||||
case RSP_OPCODE_TAG_MATCH: return "TagMatch";
|
||||
case RSP_OPCODE_RESP_SEP_DATA: return "RespSepData";
|
||||
case RSP_OPCODE_PERSIST: return "Persist";
|
||||
case RSP_OPCODE_COMP_PERSIST: return "CompPersist";
|
||||
case RSP_OPCODE_DBID_RESP_ORD: return "DbidRespOrd";
|
||||
case RSP_OPCODE_STASH_DONE: return "StashDone";
|
||||
case RSP_OPCODE_COMP_STASH_DONE: return "CompStashDone";
|
||||
case RSP_OPCODE_COMP_CMO: return "CompCMO";
|
||||
default: return std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
phaseToOpcodeName(const Phase &phase)
|
||||
{
|
||||
switch (phase.channel) {
|
||||
case CHANNEL_REQ:
|
||||
return reqOpcodeToName(phase.req_opcode);
|
||||
case CHANNEL_SNP:
|
||||
return snpOpcodeToName(phase.snp_opcode);
|
||||
case CHANNEL_DAT:
|
||||
return datOpcodeToName(phase.dat_opcode);
|
||||
case CHANNEL_RSP:
|
||||
return rspOpcodeToName(phase.rsp_opcode);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
std::string
|
||||
phaseToChannelName(const Phase &phase)
|
||||
{
|
||||
switch (phase.channel) {
|
||||
case CHANNEL_REQ:
|
||||
return "REQ";
|
||||
case CHANNEL_SNP:
|
||||
return "SNP";
|
||||
case CHANNEL_DAT:
|
||||
return "DAT";
|
||||
case CHANNEL_RSP:
|
||||
return "RSP";
|
||||
default:
|
||||
return std::string{};
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
std::string
|
||||
transactionToString(const Payload &payload,
|
||||
const Phase &phase)
|
||||
{
|
||||
return csprintf("%s %s addr=0x%08lx ns=%d size=%d attrs=0x%x",
|
||||
phaseToChannelName(phase),
|
||||
phaseToOpcodeName(phase).c_str(),
|
||||
payload.address, payload.ns,
|
||||
(int)payload.size, (int)payload.mem_attr);
|
||||
}
|
||||
|
||||
namespace tlm_to_ruby {
|
||||
|
||||
ruby::CHIRequestType
|
||||
reqOpcode(ReqOpcode req)
|
||||
{
|
||||
static std::unordered_map<uint8_t, ruby::CHIRequestType> translation_map = {
|
||||
{ REQ_OPCODE_READ_SHARED, ruby::CHIRequestType_ReadShared },
|
||||
{ REQ_OPCODE_READ_CLEAN, ruby::CHIRequestType_ReadOnce }, // TODO
|
||||
{ REQ_OPCODE_READ_ONCE, ruby::CHIRequestType_ReadOnce },
|
||||
{ REQ_OPCODE_READ_NO_SNP, ruby::CHIRequestType_ReadNoSnp }, // TODO
|
||||
{ REQ_OPCODE_READ_UNIQUE, ruby::CHIRequestType_ReadUnique },
|
||||
{ REQ_OPCODE_READ_NOT_SHARED_DIRTY, ruby::CHIRequestType_ReadNotSharedDirty },
|
||||
{ REQ_OPCODE_READ_PREFER_UNIQUE, ruby::CHIRequestType_ReadUnique }, // TODO
|
||||
{ REQ_OPCODE_MAKE_READ_UNIQUE, ruby::CHIRequestType_MakeReadUnique }, // TODO
|
||||
|
||||
{ REQ_OPCODE_CLEAN_UNIQUE, ruby::CHIRequestType_CleanUnique },
|
||||
{ REQ_OPCODE_MAKE_UNIQUE, ruby::CHIRequestType_CleanUnique }, // TODO
|
||||
{ REQ_OPCODE_EVICT, ruby::CHIRequestType_Evict },
|
||||
{ REQ_OPCODE_STASH_ONCE_SEP_SHARED, ruby::CHIRequestType_StashOnceShared }, // TODO
|
||||
{ REQ_OPCODE_STASH_ONCE_SEP_UNIQUE, ruby::CHIRequestType_StashOnceUnique },
|
||||
{ REQ_OPCODE_WRITE_NO_SNP_PTL, ruby::CHIRequestType_WriteUniquePtl },
|
||||
{ REQ_OPCODE_WRITE_NO_SNP_FULL, ruby::CHIRequestType_WriteUniqueFull },
|
||||
{ REQ_OPCODE_WRITE_UNIQUE_FULL, ruby::CHIRequestType_WriteUniqueFull },
|
||||
{ REQ_OPCODE_WRITE_UNIQUE_ZERO, ruby::CHIRequestType_WriteUniqueZero },
|
||||
{ REQ_OPCODE_WRITE_BACK_FULL, ruby::CHIRequestType_WriteBackFull },
|
||||
{ REQ_OPCODE_WRITE_EVICT_OR_EVICT, ruby::CHIRequestType_WriteEvictFull }, // TODO
|
||||
};
|
||||
|
||||
auto it = translation_map.find(req);
|
||||
if (it != translation_map.end()) {
|
||||
return it->second;
|
||||
} else {
|
||||
panic("Unsupported Translation: %s\n", reqOpcodeToName(req));
|
||||
}
|
||||
}
|
||||
|
||||
#define RESP_CASE(opc) \
|
||||
switch (resp) { \
|
||||
case RESP_I: return opc ## _ ## I; \
|
||||
case RESP_SC: return opc ## _ ## SC; \
|
||||
case RESP_UC: return opc ## _ ## UC; \
|
||||
case RESP_SD: return opc ## _ ## SD; \
|
||||
case RESP_I_PD: return opc ## _ ## I_PD; \
|
||||
case RESP_SC_PD: return opc ## _ ## SC_PD; \
|
||||
case RESP_UC_PD: return opc ## _ ## UC; \
|
||||
case RESP_SD_PD: return opc ## _ ## SD; \
|
||||
default: panic(""); \
|
||||
}
|
||||
|
||||
ruby::CHIDataType
|
||||
datOpcode(DatOpcode dat, Resp resp)
|
||||
{
|
||||
switch (dat) {
|
||||
case DAT_OPCODE_NON_COPY_BACK_WR_DATA:
|
||||
return ruby::CHIDataType_NCBWrData;
|
||||
case DAT_OPCODE_COPY_BACK_WR_DATA:
|
||||
switch (resp) {
|
||||
case RESP_I: return ruby::CHIDataType_CBWrData_I;
|
||||
case RESP_UC: return ruby::CHIDataType_CBWrData_UC;
|
||||
case RESP_SC: return ruby::CHIDataType_CBWrData_SC;
|
||||
case RESP_UD_PD: return ruby::CHIDataType_CBWrData_UD_PD;
|
||||
default: panic("");
|
||||
}
|
||||
case DAT_OPCODE_SNP_RESP_DATA:
|
||||
RESP_CASE(ruby::CHIDataType_SnpRespData)
|
||||
default:
|
||||
panic("Unsupported Translation: %s\n", datOpcodeToName(dat));
|
||||
}
|
||||
}
|
||||
|
||||
ruby::CHIResponseType
|
||||
rspOpcode(RspOpcode opc, Resp resp)
|
||||
{
|
||||
switch(opc) {
|
||||
case RSP_OPCODE_COMP_ACK: return ruby::CHIResponseType_CompAck;
|
||||
case RSP_OPCODE_SNP_RESP:
|
||||
switch (resp) {
|
||||
case RESP_I: return ruby::CHIResponseType_SnpResp_I;
|
||||
default: panic("Invalid resp %d for %d\n", resp, opc);
|
||||
}
|
||||
default:
|
||||
panic("Unsupported Translation: %s\n", rspOpcodeToName(opc));
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace ruby_to_tlm {
|
||||
|
||||
uint8_t
|
||||
datOpcode(ruby::CHIDataType dat)
|
||||
{
|
||||
switch (dat) {
|
||||
case ruby::CHIDataType_CompData_I:
|
||||
case ruby::CHIDataType_CompData_UC:
|
||||
case ruby::CHIDataType_CompData_SC:
|
||||
case ruby::CHIDataType_CompData_UD_PD:
|
||||
case ruby::CHIDataType_CompData_SD_PD:
|
||||
return 0x4;
|
||||
case ruby::CHIDataType_DataSepResp_UC:
|
||||
return 0xb;
|
||||
case ruby::CHIDataType_CBWrData_UC:
|
||||
case ruby::CHIDataType_CBWrData_SC:
|
||||
case ruby::CHIDataType_CBWrData_UD_PD:
|
||||
case ruby::CHIDataType_CBWrData_SD_PD:
|
||||
case ruby::CHIDataType_CBWrData_I:
|
||||
return 0x2;
|
||||
case ruby::CHIDataType_NCBWrData:
|
||||
return 0x3;
|
||||
case ruby::CHIDataType_SnpRespData_I:
|
||||
case ruby::CHIDataType_SnpRespData_I_PD:
|
||||
case ruby::CHIDataType_SnpRespData_SC:
|
||||
case ruby::CHIDataType_SnpRespData_SC_PD:
|
||||
case ruby::CHIDataType_SnpRespData_SD:
|
||||
case ruby::CHIDataType_SnpRespData_UC:
|
||||
case ruby::CHIDataType_SnpRespData_UD:
|
||||
return 0x1;
|
||||
case ruby::CHIDataType_SnpRespData_SC_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_SC_Fwded_SD_PD:
|
||||
case ruby::CHIDataType_SnpRespData_SC_PD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_SD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_I_Fwded_SD_PD:
|
||||
case ruby::CHIDataType_SnpRespData_I_PD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_I_Fwded_SC:
|
||||
return 0x6;
|
||||
default:
|
||||
panic("Unrecognised data opcode: %d\n", dat);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
rspOpcode(ruby::CHIResponseType rsp)
|
||||
{
|
||||
switch (rsp) {
|
||||
case ruby::CHIResponseType_Comp_UD_PD:
|
||||
case ruby::CHIResponseType_Comp_UC:
|
||||
case ruby::CHIResponseType_Comp_I:
|
||||
return RSP_OPCODE_COMP;
|
||||
case ruby::CHIResponseType_CompDBIDResp:
|
||||
return RSP_OPCODE_COMP_DBID_RESP;
|
||||
case ruby::CHIResponseType_RetryAck:
|
||||
return RSP_OPCODE_RETRY_ACK;
|
||||
default:
|
||||
panic("Unrecognised rsp opcode: %d\n", rsp);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t
|
||||
snpOpcode(ruby::CHIRequestType snp)
|
||||
{
|
||||
switch (snp) {
|
||||
case ruby::CHIRequestType_SnpOnceFwd:
|
||||
return SNP_OPCODE_SNP_ONCE_FWD;
|
||||
case ruby::CHIRequestType_SnpOnce:
|
||||
return SNP_OPCODE_SNP_ONCE;
|
||||
case ruby::CHIRequestType_SnpShared:
|
||||
return SNP_OPCODE_SNP_SHARED;
|
||||
case ruby::CHIRequestType_SnpCleanInvalid:
|
||||
return SNP_OPCODE_SNP_CLEAN_INVALID;
|
||||
case ruby::CHIRequestType_SnpUnique:
|
||||
return SNP_OPCODE_SNP_UNIQUE;
|
||||
default:
|
||||
panic("Unrecognised snp opcode: %d\n", snp);
|
||||
}
|
||||
}
|
||||
|
||||
Resp
|
||||
datResp(ruby::CHIDataType dat)
|
||||
{
|
||||
switch (dat) {
|
||||
case ruby::CHIDataType_SnpRespData_I:
|
||||
case ruby::CHIDataType_CompData_I:
|
||||
case ruby::CHIDataType_CBWrData_I:
|
||||
return RESP_I;
|
||||
case ruby::CHIDataType_SnpRespData_SC:
|
||||
case ruby::CHIDataType_CompData_SC:
|
||||
case ruby::CHIDataType_CBWrData_SC:
|
||||
return RESP_SC;
|
||||
case ruby::CHIDataType_SnpRespData_UC:
|
||||
case ruby::CHIDataType_CompData_UC:
|
||||
case ruby::CHIDataType_CBWrData_UC:
|
||||
case ruby::CHIDataType_DataSepResp_UC:
|
||||
return RESP_UC;
|
||||
case ruby::CHIDataType_SnpRespData_UD:
|
||||
return RESP_UD;
|
||||
case ruby::CHIDataType_SnpRespData_SD:
|
||||
return RESP_SD;
|
||||
case ruby::CHIDataType_SnpRespData_I_PD:
|
||||
return RESP_I_PD;
|
||||
case ruby::CHIDataType_SnpRespData_SC_PD:
|
||||
return RESP_SC_PD;
|
||||
case ruby::CHIDataType_CompData_UD_PD:
|
||||
case ruby::CHIDataType_CBWrData_UD_PD:
|
||||
return RESP_UD_PD;
|
||||
case ruby::CHIDataType_CompData_SD_PD:
|
||||
case ruby::CHIDataType_CBWrData_SD_PD:
|
||||
return RESP_SD_PD;
|
||||
// TODO
|
||||
case ruby::CHIDataType_SnpRespData_SC_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_SC_Fwded_SD_PD:
|
||||
case ruby::CHIDataType_SnpRespData_SC_PD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_SD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_I_Fwded_SD_PD:
|
||||
case ruby::CHIDataType_SnpRespData_I_PD_Fwded_SC:
|
||||
case ruby::CHIDataType_SnpRespData_I_Fwded_SC:
|
||||
default:
|
||||
panic("Unrecognised data opcode: %d\n", dat);
|
||||
}
|
||||
}
|
||||
|
||||
Resp
|
||||
rspResp(ruby::CHIResponseType rsp)
|
||||
{
|
||||
switch (rsp) {
|
||||
case ruby::CHIResponseType_Comp_I:
|
||||
return RESP_I;
|
||||
case ruby::CHIResponseType_Comp_UC:
|
||||
return RESP_UC;
|
||||
case ruby::CHIResponseType_Comp_UD_PD:
|
||||
return RESP_UD_PD;
|
||||
case ruby::CHIResponseType_CompDBIDResp:
|
||||
return RESP_I;
|
||||
case ruby::CHIResponseType_RetryAck:
|
||||
// Just setup to zero
|
||||
return RESP_I;
|
||||
default:
|
||||
panic("Unrecognised rsp opcode: %d\n", rsp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Addr
|
||||
transactionSize(Size sz)
|
||||
{
|
||||
return 1 << sz;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
dataId(Addr address)
|
||||
{
|
||||
uint64_t bus_width = 256;
|
||||
switch (bus_width) {
|
||||
case 128:
|
||||
return bits(address, 5, 4);
|
||||
case 256:
|
||||
return bits(address, 5, 4) & 0b10;
|
||||
case 512:
|
||||
default:
|
||||
return 0b00;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
82
src/mem/ruby/protocol/chi/tlm/utils.hh
Normal file
82
src/mem/ruby/protocol/chi/tlm/utils.hh
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2023 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* 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;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __MEM_RUBY_PROTOCOL_CHI_TLM_UTILS_HH__
|
||||
#define __MEM_RUBY_PROTOCOL_CHI_TLM_UTILS_HH__
|
||||
|
||||
#include <ARM/TLM/arm_chi.h>
|
||||
|
||||
#include "base/types.hh"
|
||||
#include "mem/ruby/protocol/CHIDataType.hh"
|
||||
#include "mem/ruby/protocol/CHIRequestType.hh"
|
||||
#include "mem/ruby/protocol/CHIResponseType.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
std::string transactionToString(const ARM::CHI::Payload &payload,
|
||||
const ARM::CHI::Phase &phase);
|
||||
|
||||
namespace tlm_to_ruby {
|
||||
|
||||
ruby::CHIRequestType reqOpcode(ARM::CHI::ReqOpcode req);
|
||||
ruby::CHIDataType datOpcode(ARM::CHI::DatOpcode dat, ARM::CHI::Resp resp);
|
||||
ruby::CHIResponseType rspOpcode(ARM::CHI::RspOpcode res, ARM::CHI::Resp resp);
|
||||
|
||||
}
|
||||
|
||||
namespace ruby_to_tlm {
|
||||
|
||||
uint8_t datOpcode(ruby::CHIDataType dat);
|
||||
uint8_t rspOpcode(ruby::CHIResponseType res);
|
||||
uint8_t snpOpcode(ruby::CHIRequestType snp);
|
||||
|
||||
ARM::CHI::Resp datResp(ruby::CHIDataType dat);
|
||||
ARM::CHI::Resp rspResp(ruby::CHIResponseType rsp);
|
||||
|
||||
}
|
||||
|
||||
Addr transactionSize(ARM::CHI::Size sz);
|
||||
|
||||
uint8_t dataId(Addr address);
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __MEM_RUBY_PROTOCOL_CHI_TLM_UTILS_HH__
|
||||
Reference in New Issue
Block a user