mem-ruby: Add a CHI-TLM transaction Generator for testing
This commit is building over the CHI-TLM wrapping introduced by the previous commit and it is adding a CHI traffic generator as a SimObject. This will get the python objects as input and it will forward them to the TlmController to convert them into ruby CHI messages Change-Id: Ia67094c9bb880e37b24184313df546ecbaa3289f Signed-off-by: Giacomo Travaglini <giacomo.travaglini@arm.com>
This commit is contained in:
committed by
Bobby R. Bruce
parent
786e539fa4
commit
706cb4195f
@@ -62,9 +62,12 @@ if env["CONF"]["BUILD_TLM"]:
|
||||
SimObject(
|
||||
"TlmController.py", sim_objects=["TlmController"], tags="arm isa"
|
||||
)
|
||||
SimObject('TlmGenerator.py', sim_objects=['TlmGenerator'], tags='arm isa')
|
||||
Source("utils.cc", tags="arm isa")
|
||||
Source("controller.cc", tags="arm isa")
|
||||
Source('tlm_chi.cc', tags='arm isa')
|
||||
Source('tlm_chi_gen.cc', tags='arm isa')
|
||||
Source('generator.cc', tags='arm isa')
|
||||
PySource('m5', 'tlm_chi.py')
|
||||
DebugFlag("TLM", tags="arm isa")
|
||||
|
||||
|
||||
69
src/mem/ruby/protocol/chi/tlm/TlmGenerator.py
Normal file
69
src/mem/ruby/protocol/chi/tlm/TlmGenerator.py
Normal file
@@ -0,0 +1,69 @@
|
||||
# -*- 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.
|
||||
|
||||
|
||||
from m5.objects.TlmController import TlmController
|
||||
from m5.params import *
|
||||
from m5.SimObject import (
|
||||
PyBindMethod,
|
||||
SimObject,
|
||||
)
|
||||
|
||||
|
||||
class TlmGenerator(SimObject):
|
||||
type = "TlmGenerator"
|
||||
cxx_header = "mem/ruby/protocol/chi/tlm/generator.hh"
|
||||
cxx_class = "gem5::tlm::chi::TlmGenerator"
|
||||
|
||||
cxx_exports = [
|
||||
PyBindMethod("scheduleTransaction"),
|
||||
]
|
||||
|
||||
_transactions = []
|
||||
|
||||
def injectAt(self, when, payload, phase):
|
||||
from m5.tlm_chi import Transaction
|
||||
|
||||
transaction = Transaction(payload, phase)
|
||||
self._transactions.append((when, transaction))
|
||||
return transaction
|
||||
|
||||
def init(self):
|
||||
for when, tr in self._transactions:
|
||||
self.getCCObject().scheduleTransaction(when, tr)
|
||||
|
||||
cpu_id = Param.Int("TlmGenerator CPU identifier")
|
||||
chi_controller = Param.TlmController("TLM-to-Ruby CacheController")
|
||||
218
src/mem/ruby/protocol/chi/tlm/generator.cc
Normal file
218
src/mem/ruby/protocol/chi/tlm/generator.cc
Normal file
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/generator.hh"
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/controller.hh"
|
||||
#include "debug/TLM.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
bool
|
||||
TlmGenerator::Transaction::Expectation::run(Transaction *tran)
|
||||
{
|
||||
auto res_print = csprintf("Checking %s...", name());
|
||||
if (cb(tran)) {
|
||||
inform("%s\n", res_print + " Success ");
|
||||
return true;
|
||||
} else {
|
||||
inform("%s\n", res_print + " Fail ");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
TlmGenerator::Transaction::Assertion::run(Transaction *tran)
|
||||
{
|
||||
if (Expectation::run(tran)) {
|
||||
return true;
|
||||
} else {
|
||||
panic("Failing assertion\n");
|
||||
}
|
||||
}
|
||||
|
||||
TlmGenerator::Transaction::Transaction(ARM::CHI::Payload *pa, ARM::CHI::Phase &ph)
|
||||
: passed(true), parent(nullptr), _payload(pa), _phase(ph)
|
||||
{
|
||||
_payload->ref();
|
||||
}
|
||||
|
||||
TlmGenerator::Transaction::~Transaction()
|
||||
{
|
||||
_payload->unref();
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::Transaction::setGenerator(TlmGenerator *gen)
|
||||
{
|
||||
parent = gen;
|
||||
}
|
||||
|
||||
std::string
|
||||
TlmGenerator::Transaction::str() const
|
||||
{
|
||||
return transactionToString(*_payload, _phase);
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::Transaction::inject()
|
||||
{
|
||||
parent->inject(this);
|
||||
}
|
||||
|
||||
bool
|
||||
TlmGenerator::Transaction::hasCallbacks() const
|
||||
{
|
||||
return !actions.empty();
|
||||
}
|
||||
|
||||
bool
|
||||
TlmGenerator::Transaction::failed() const
|
||||
{
|
||||
return !passed;
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::Transaction::addCallback(ActionPtr &&action)
|
||||
{
|
||||
actions.push_back(std::move(action));
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::Transaction::runCallbacks()
|
||||
{
|
||||
// print transaction
|
||||
auto it = actions.begin();
|
||||
while (it != actions.end()) {
|
||||
const bool is_passing = (*it)->run(this);
|
||||
if (!is_passing) {
|
||||
passed = false;
|
||||
}
|
||||
bool wait = (*it)->wait();
|
||||
|
||||
it = actions.erase(it);
|
||||
|
||||
if (wait) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::TransactionEvent::process()
|
||||
{
|
||||
transaction->inject();
|
||||
}
|
||||
|
||||
TlmGenerator::TlmGenerator(const Params &p)
|
||||
: SimObject(p), cpuId(p.cpu_id), controller(p.chi_controller)
|
||||
{
|
||||
controller->bw = [this] (ARM::CHI::Payload *payload, ARM::CHI::Phase *phase)
|
||||
{
|
||||
this->recv(payload, phase);
|
||||
};
|
||||
|
||||
registerExitCallback([this](){ passFailCheck(); });
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::scheduleTransaction(Tick when, Transaction *transaction)
|
||||
{
|
||||
transaction->setGenerator(this);
|
||||
|
||||
auto event = new TransactionEvent(transaction, when);
|
||||
|
||||
scheduledTransactions.push(event);
|
||||
|
||||
schedule(event, when);
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::inject(Transaction *transaction)
|
||||
{
|
||||
auto payload = transaction->payload();
|
||||
ARM::CHI::Phase &phase = transaction->phase();
|
||||
|
||||
if (transaction->hasCallbacks())
|
||||
pendingTransactions.insert({phase.txn_id, transaction});
|
||||
|
||||
DPRINTF(TLM, "[c%d] send %s\n", cpuId, transactionToString(*payload, phase));
|
||||
|
||||
controller->sendMsg(*payload, phase);
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::recv(ARM::CHI::Payload *payload, ARM::CHI::Phase *phase)
|
||||
{
|
||||
DPRINTF(TLM, "[c%d] rcvd %s\n", cpuId, transactionToString(*payload, *phase));
|
||||
|
||||
auto txn_id = phase->txn_id;
|
||||
if (auto it = pendingTransactions.find(txn_id);
|
||||
it != pendingTransactions.end()) {
|
||||
// Copy the new phase
|
||||
it->second->phase() = *phase;
|
||||
|
||||
// Check existing expectations
|
||||
it->second->runCallbacks();
|
||||
} else {
|
||||
warn("Transaction untested\n");
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
TlmGenerator::passFailCheck()
|
||||
{
|
||||
for (auto [txn_id, transaction] : pendingTransactions) {
|
||||
// We are failing either if a condition hasn't been met,
|
||||
// or if there are pending actions when simulation exits
|
||||
if (transaction->failed()) {
|
||||
inform(" Suite Fail: failed transaction ");
|
||||
return;
|
||||
}
|
||||
if (transaction->hasCallbacks()) {
|
||||
inform(" Suite Fail: non-empty action queue ");
|
||||
return;
|
||||
}
|
||||
}
|
||||
inform(" Suite Success ");
|
||||
}
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
304
src/mem/ruby/protocol/chi/tlm/generator.hh
Normal file
304
src/mem/ruby/protocol/chi/tlm/generator.hh
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __MEM_RUBY_PROTOCOL_CHI_TLM_GENERATOR_HH__
|
||||
#define __MEM_RUBY_PROTOCOL_CHI_TLM_GENERATOR_HH__
|
||||
|
||||
#include <queue>
|
||||
#include <unordered_map>
|
||||
|
||||
#include <ARM/TLM/arm_chi.h>
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/utils.hh"
|
||||
#include "params/TlmGenerator.hh"
|
||||
#include "sim/eventq.hh"
|
||||
#include "sim/sim_object.hh"
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace tlm::chi {
|
||||
|
||||
class CacheController;
|
||||
|
||||
/**
|
||||
* TlmGenerator: this class is basically a CHI-tlm traffic generator.
|
||||
* Its interface is mainly allowing to inject transactions at a specific
|
||||
* point in simulated time and to set expectations on what has
|
||||
* to be returned to the generator.
|
||||
* The intended use is as a testbench for the CHI implementation
|
||||
* in ruby. As such it requires to be hooked with a TlmController
|
||||
* as a bridge for converting the CHI-tlm transactions into ruby messages.
|
||||
*
|
||||
* +---------------+
|
||||
* +--------------+ +---------------+ | |
|
||||
* | | | | | |
|
||||
* | TlmGenerator |-->| TlmController |--->| Ruby |
|
||||
* | |<--| |<---| |
|
||||
* +--------------+ +---------------+ | |
|
||||
* +---------------+
|
||||
*
|
||||
* The APIs are entirely exposed to the python world for flexible
|
||||
* definition of the unit tests.
|
||||
*
|
||||
* To inject a CHI-tlm transaction at a specific tick in the
|
||||
* simulation, the following TlmGenerator method should be
|
||||
* used:
|
||||
*
|
||||
* def injectAt(self, when, payload, phase):
|
||||
*
|
||||
* This will return a Transaction object and from that point that will be the
|
||||
* handle for managing the transaction: either adding transaction expectations
|
||||
* upon response (e.g, what will be the cacheline state), or by adding action
|
||||
* callbacks (execute some logic)
|
||||
*/
|
||||
class TlmGenerator : public SimObject
|
||||
{
|
||||
public:
|
||||
PARAMS(TlmGenerator);
|
||||
TlmGenerator(const Params &p);
|
||||
|
||||
/**
|
||||
* Transaction object
|
||||
* It stores ARM::CHI::Payload and ARM::CHI::Phase objects,
|
||||
* and a list of action callables which will be executed
|
||||
* in the order they have been registered once a transaction
|
||||
* response arrives. These could be:
|
||||
* 1) Expectation callbacks (Transaction::Expectation)
|
||||
* which will check a specific condition and will warn if
|
||||
* the condition is not met
|
||||
* 2) Assertion callbacks (Transaction::Assertion)
|
||||
* Identical to expectations, they will fail simulation instead
|
||||
* of warning, which means later conditions won't be checked.
|
||||
* 3) Action callbacks (Transaction::Action)
|
||||
* Does something without condition checking
|
||||
*
|
||||
* Once the response arrives, the Transaction::runCallbacks will
|
||||
* enter the dispatching loop. Actions/callbacks will be dispatched
|
||||
* until the list is empty or until a waiting action is encountered.
|
||||
* This will break the dispatching loop.
|
||||
*/
|
||||
class Transaction
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Action:
|
||||
* Does something without condition checking. It is
|
||||
* possible to program from python whether the callback
|
||||
* is a waiting action
|
||||
*/
|
||||
class Action
|
||||
{
|
||||
public:
|
||||
using Callback = std::function<
|
||||
bool(Transaction *tran)
|
||||
>;
|
||||
|
||||
Action(Callback _cb, bool waiting)
|
||||
: cb(_cb), _wait(waiting)
|
||||
{}
|
||||
virtual ~Action() {};
|
||||
|
||||
/* A basic action always returns true */
|
||||
virtual bool
|
||||
run(Transaction *tran)
|
||||
{
|
||||
cb(tran);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the action dispatcher should break
|
||||
* the dispatching loop once the action has been executed
|
||||
*/
|
||||
bool wait() const { return _wait; }
|
||||
|
||||
protected:
|
||||
Callback cb;
|
||||
bool _wait;
|
||||
};
|
||||
|
||||
/**
|
||||
* Expectation:
|
||||
* Will check for a specific condition and will warn if
|
||||
* the condition is not met.
|
||||
* The expectation is never a waiting action
|
||||
*/
|
||||
class Expectation : public Action
|
||||
{
|
||||
public:
|
||||
Expectation(std::string exp_name, Callback _cb)
|
||||
: Action(_cb, false), _name(exp_name)
|
||||
{}
|
||||
|
||||
bool run(Transaction *tran) override;
|
||||
|
||||
std::string name() const { return _name; }
|
||||
|
||||
private:
|
||||
std::string _name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Assertion:
|
||||
* Will check for a specific condition and will fail if
|
||||
* the condition is not met.
|
||||
* The assertion is never a waiting action
|
||||
*/
|
||||
class Assertion : public Expectation
|
||||
{
|
||||
public:
|
||||
Assertion(std::string exp_name, Callback _cb)
|
||||
: Expectation(exp_name, _cb)
|
||||
{}
|
||||
|
||||
bool run(Transaction *tran) override;
|
||||
};
|
||||
|
||||
using ActionPtr = std::unique_ptr<Action>;
|
||||
using Actions = std::list<ActionPtr>;
|
||||
|
||||
Transaction(const Transaction &rhs) = delete;
|
||||
Transaction(ARM::CHI::Payload *pa, ARM::CHI::Phase &ph);
|
||||
~Transaction();
|
||||
|
||||
/**
|
||||
* Registers the TlmGenerator in the transaction. This is
|
||||
* used as a reference to the generator is required when
|
||||
* injection the transaction
|
||||
*/
|
||||
void setGenerator(TlmGenerator *gen);
|
||||
|
||||
std::string str() const;
|
||||
|
||||
void inject();
|
||||
|
||||
/**
|
||||
* Returns true if the transaction has failed, false
|
||||
* otherwise
|
||||
*/
|
||||
bool failed() const;
|
||||
|
||||
/**
|
||||
* Returns true if the transaction has some
|
||||
* registered callbacks, false otherwise
|
||||
*/
|
||||
bool hasCallbacks() const;
|
||||
|
||||
/**
|
||||
* Appends a callback to the list of actions
|
||||
*/
|
||||
void addCallback(ActionPtr &&action);
|
||||
|
||||
/**
|
||||
* Enters the dispatching loop and runs the callbacks
|
||||
* in insertion order until a waiting callback is
|
||||
* encountered (or if there is a failing assertion)
|
||||
*/
|
||||
void runCallbacks();
|
||||
|
||||
ARM::CHI::Payload* payload() const { return _payload; }
|
||||
ARM::CHI::Phase& phase() { return _phase; }
|
||||
|
||||
private:
|
||||
Actions actions;
|
||||
bool passed;
|
||||
|
||||
TlmGenerator *parent;
|
||||
ARM::CHI::Payload *_payload;
|
||||
ARM::CHI::Phase _phase;
|
||||
};
|
||||
|
||||
void scheduleTransaction(Tick when, Transaction *tr);
|
||||
|
||||
protected:
|
||||
struct TransactionEvent : public Event
|
||||
{
|
||||
public:
|
||||
struct Compare
|
||||
{
|
||||
bool
|
||||
operator()(const TransactionEvent *lhs,
|
||||
const TransactionEvent *rhs)
|
||||
{
|
||||
return lhs->when < rhs->when;
|
||||
}
|
||||
};
|
||||
|
||||
TransactionEvent(Transaction *_transaction,
|
||||
Tick _when)
|
||||
: Event(), transaction(_transaction), when(_when)
|
||||
{}
|
||||
|
||||
void process() override;
|
||||
|
||||
const char*
|
||||
description() const override
|
||||
{
|
||||
return "CHI Transaction event";
|
||||
}
|
||||
|
||||
Transaction *transaction;
|
||||
Tick when;
|
||||
};
|
||||
|
||||
void inject(Transaction *transaction);
|
||||
void recv(ARM::CHI::Payload *payload, ARM::CHI::Phase *phase);
|
||||
void passFailCheck();
|
||||
|
||||
protected:
|
||||
/** cpuId to mimic the behaviour of a CPU */
|
||||
uint8_t cpuId;
|
||||
|
||||
using SchedulingQueue = std::priority_queue<TransactionEvent*,
|
||||
std::vector<TransactionEvent*>,
|
||||
TransactionEvent::Compare>;
|
||||
|
||||
/** PQ of transactions whose injection needs to be scheduled */
|
||||
SchedulingQueue scheduledTransactions;
|
||||
|
||||
/** Map of pending (injected) transactions indexed by the txn_id */
|
||||
std::unordered_map<uint16_t, Transaction*> pendingTransactions;
|
||||
|
||||
/** Pointer to the CHI-tlm controller */
|
||||
CacheController *controller;
|
||||
};
|
||||
|
||||
} // namespace tlm::chi
|
||||
|
||||
} // namespace gem5
|
||||
|
||||
#endif // __MEM_RUBY_PROTOCOL_CHI_TLM_GENERATOR_HH__
|
||||
@@ -34,4 +34,14 @@
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import _m5.tlm_chi
|
||||
import _m5.tlm_chi_gen
|
||||
from _m5.tlm_chi import *
|
||||
from _m5.tlm_chi_gen import *
|
||||
|
||||
|
||||
def expect_equal(received, expected):
|
||||
if received != expected:
|
||||
print(f"Comparison mismatch. Received:{received}, Expected:{expected}")
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
|
||||
109
src/mem/ruby/protocol/chi/tlm/tlm_chi_gen.cc
Normal file
109
src/mem/ruby/protocol/chi/tlm/tlm_chi_gen.cc
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <ARM/TLM/arm_chi.h>
|
||||
|
||||
#include "mem/ruby/protocol/chi/tlm/generator.hh"
|
||||
// This is required by Transaction::expect
|
||||
#include "pybind11/functional.h"
|
||||
#include "python/pybind11/pybind.hh"
|
||||
#include "sim/init.hh"
|
||||
|
||||
namespace py = pybind11;
|
||||
|
||||
using namespace ARM::CHI;
|
||||
|
||||
namespace gem5 {
|
||||
|
||||
namespace {
|
||||
|
||||
void
|
||||
tlm_chi_generator_pybind(pybind11::module_ &m_tlm_chi)
|
||||
{
|
||||
auto tlm_chi_gen = m_tlm_chi.def_submodule("tlm_chi_gen");
|
||||
|
||||
using Action = tlm::chi::TlmGenerator::Transaction::Action;
|
||||
using Expectation = tlm::chi::TlmGenerator::Transaction::Expectation;
|
||||
using Assertion = tlm::chi::TlmGenerator::Transaction::Assertion;
|
||||
using Callback = Action::Callback;
|
||||
py::class_<tlm::chi::TlmGenerator::Transaction>(tlm_chi_gen, "Transaction")
|
||||
.def(py::init<Payload*, Phase&>())
|
||||
.def("EXPECT_STR",
|
||||
[] (tlm::chi::TlmGenerator::Transaction &self,
|
||||
std::string name,
|
||||
Callback cb)
|
||||
{
|
||||
self.addCallback(std::make_unique<Expectation>(name, cb));
|
||||
})
|
||||
.def("EXPECT",
|
||||
[] (tlm::chi::TlmGenerator::Transaction &self,
|
||||
py::function cb)
|
||||
{
|
||||
self.addCallback(std::make_unique<Expectation>(
|
||||
cb.attr("__name__").cast<std::string>(),
|
||||
cb.cast<Callback>()));
|
||||
})
|
||||
.def("ASSERT",
|
||||
[] (tlm::chi::TlmGenerator::Transaction &self,
|
||||
std::string name,
|
||||
Callback cb)
|
||||
{
|
||||
self.addCallback(std::make_unique<Assertion>(name, cb));
|
||||
})
|
||||
.def("DO",
|
||||
[] (tlm::chi::TlmGenerator::Transaction &self,
|
||||
Callback cb)
|
||||
{
|
||||
self.addCallback(std::make_unique<Action>(cb, false));
|
||||
})
|
||||
.def("DO_WAIT",
|
||||
[] (tlm::chi::TlmGenerator::Transaction &self,
|
||||
Callback cb)
|
||||
{
|
||||
self.addCallback(std::make_unique<Action>(cb, true));
|
||||
})
|
||||
.def("inject", &tlm::chi::TlmGenerator::Transaction::inject)
|
||||
.def_property("phase",
|
||||
&tlm::chi::TlmGenerator::Transaction::phase,
|
||||
&tlm::chi::TlmGenerator::Transaction::phase)
|
||||
;
|
||||
}
|
||||
|
||||
EmbeddedPyBind embed_("tlm_chi_gen", &tlm_chi_generator_pybind, "tlm_chi");
|
||||
|
||||
} // namespace
|
||||
} // namespace gem5
|
||||
Reference in New Issue
Block a user