website: Update learning_gem5 part 2 scripts
Signed-off-by: Hoa Nguyen <hoanguyen@ucdavis.edu>
Change-Id: Id39ea9fc6601ee29c3a8763357cb1dc23ff913a3
Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5-website/+/46360
Reviewed-by: Bobby R. Bruce <bbruce@ucdavis.edu>
Maintainer: Bobby R. Bruce <bbruce@ucdavis.edu>
Tested-by: Bobby R. Bruce <bbruce@ucdavis.edu>
diff --git a/_pages/static/scripts/part2/debugging/SConscript b/_pages/static/scripts/part2/debugging/SConscript
index 287f33b..312a559 100644
--- a/_pages/static/scripts/part2/debugging/SConscript
+++ b/_pages/static/scripts/part2/debugging/SConscript
@@ -32,4 +32,4 @@
SimObject('HelloObject.py')
Source('hello_object.cc')
-DebugFlag('Hello')
+DebugFlag('HelloExample', "For Learning gem5 Part 2. Simple example debug flag")
diff --git a/_pages/static/scripts/part2/debugging/hello_object.cc b/_pages/static/scripts/part2/debugging/hello_object.cc
index 6ba4813..b6add7d 100644
--- a/_pages/static/scripts/part2/debugging/hello_object.cc
+++ b/_pages/static/scripts/part2/debugging/hello_object.cc
@@ -28,16 +28,10 @@
* Authors: Jason Lowe-Power
*/
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
#include "learning_gem5/hello_object.hh"
-HelloObject::HelloObject(HelloObjectParams *params) : SimObject(params)
+HelloObject::HelloObject(const HelloObjectParams ¶ms) : SimObject(params)
{
- DPRINTF(Hello, "Created the hello object\n");
-}
-
-HelloObject*
-HelloObjectParams::create()
-{
- return new HelloObject(this);
+ DPRINTF(HelloExample, "Created the hello object\n");
}
diff --git a/_pages/static/scripts/part2/events/hello_object.cc b/_pages/static/scripts/part2/events/hello_object.cc
index 9e622e0..41f577a 100644
--- a/_pages/static/scripts/part2/events/hello_object.cc
+++ b/_pages/static/scripts/part2/events/hello_object.cc
@@ -28,14 +28,14 @@
* Authors: Jason Lowe-Power
*/
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
#include "learning_gem5/hello_object.hh"
-HelloObject::HelloObject(HelloObjectParams *params) :
+HelloObject::HelloObject(const HelloObjectParams ¶ms) :
SimObject(params), event([this]{processEvent();}, name()),
latency(100), timesLeft(10)
{
- DPRINTF(Hello, "Created the hello object\n");
+ DPRINTF(HelloExample, "Created the hello object\n");
}
void
@@ -48,17 +48,11 @@
HelloObject::processEvent()
{
timesLeft--;
- DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
+ DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);
if (timesLeft <= 0) {
- DPRINTF(Hello, "Done firing!\n");
+ DPRINTF(HelloExample, "Done firing!\n");
} else {
schedule(event, curTick() + latency);
}
}
-
-HelloObject*
-HelloObjectParams::create()
-{
- return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/events/hello_object.hh b/_pages/static/scripts/part2/events/hello_object.hh
index 8aee5a9..022afb9 100644
--- a/_pages/static/scripts/part2/events/hello_object.hh
+++ b/_pages/static/scripts/part2/events/hello_object.hh
@@ -48,7 +48,7 @@
int timesLeft;
public:
- HelloObject(HelloObjectParams *p);
+ HelloObject(const HelloObjectParams &p);
void startup();
};
diff --git a/_pages/static/scripts/part2/helloobject/hello_object.cc b/_pages/static/scripts/part2/helloobject/hello_object.cc
index 2e151dc..c1fead7 100644
--- a/_pages/static/scripts/part2/helloobject/hello_object.cc
+++ b/_pages/static/scripts/part2/helloobject/hello_object.cc
@@ -32,13 +32,7 @@
#include <iostream>
-HelloObject::HelloObject(HelloObjectParams *params) : SimObject(params)
+HelloObject::HelloObject(const HelloObjectParams ¶ms) : SimObject(params)
{
std::cout << "Hello World! From a SimObject!" << std::endl;
}
-
-HelloObject*
-HelloObjectParams::create()
-{
- return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/helloobject/hello_object.hh b/_pages/static/scripts/part2/helloobject/hello_object.hh
index ad1b6cc..a1680aa 100644
--- a/_pages/static/scripts/part2/helloobject/hello_object.hh
+++ b/_pages/static/scripts/part2/helloobject/hello_object.hh
@@ -37,7 +37,7 @@
class HelloObject : public SimObject
{
public:
- HelloObject(HelloObjectParams *p);
+ HelloObject(const HelloObjectParams &p);
};
#endif // __LEARNING_GEM5_HELLO_OBJECT_HH__
diff --git a/_pages/static/scripts/part2/memoryobject/SConscript b/_pages/static/scripts/part2/memoryobject/SConscript
index a8c948e..bebcec3 100644
--- a/_pages/static/scripts/part2/memoryobject/SConscript
+++ b/_pages/static/scripts/part2/memoryobject/SConscript
@@ -32,4 +32,4 @@
SimObject('SimpleMemobj.py')
Source('simple_memobj.cc')
-DebugFlag('SimpleMemobj')
+DebugFlag('SimpleMemobj', "For Learning gem5 Part 2.")
diff --git a/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py b/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
index 0f0b6da..b72ebe2 100644
--- a/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
+++ b/_pages/static/scripts/part2/memoryobject/SimpleMemobj.py
@@ -24,17 +24,14 @@
# 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.
-#
-# Authors: Jason Lowe-Power
from m5.params import *
-from m5.proxy import *
-from MemObject import MemObject
+from m5.SimObject import SimObject
-class SimpleMemobj(MemObject):
+class SimpleMemobj(SimObject):
type = 'SimpleMemobj'
- cxx_header = "learning_gem5/simple_memobj/simple_memobj.hh"
+ cxx_header = "learning_gem5/part2/simple_memobj.hh"
- inst_port = SlavePort("CPU side port, receives requests")
- data_port = SlavePort("CPU side port, receives requests")
- mem_side = MasterPort("Memory side port, sends requests")
+ inst_port = ResponsePort("CPU side port, receives requests")
+ data_port = ResponsePort("CPU side port, receives requests")
+ mem_side = RequestPort("Memory side port, sends requests")
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
index 8ea00a3..f8e52b8 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.cc
@@ -30,9 +30,10 @@
#include "learning_gem5/part2/simple_memobj.hh"
+#include "base/trace.hh"
#include "debug/SimpleMemobj.hh"
-SimpleMemobj::SimpleMemobj(SimpleMemobjParams *params) :
+SimpleMemobj::SimpleMemobj(const SimpleMemobjParams ¶ms) :
SimObject(params),
instPort(params->name + ".inst_port", this),
dataPort(params->name + ".data_port", this),
@@ -41,7 +42,8 @@
{
}
-Port &SimpleMemobj::getPort(const std::string &if_name, PortID idx)
+Port &
+SimpleMemobj::getPort(const std::string &if_name, PortID idx)
{
panic_if(idx != InvalidPortID, "This object doesn't support vector ports");
@@ -228,11 +230,3 @@
instPort.sendRangeChange();
dataPort.sendRangeChange();
}
-
-
-
-SimpleMemobj*
-SimpleMemobjParams::create()
-{
- return new SimpleMemobj(this);
-}
\ No newline at end of file
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.hh b/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
index a6c9c6d..4b7719a 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.hh
@@ -50,7 +50,7 @@
* Mostly just forwards requests to the owner.
* Part of a vector of ports. One for each CPU port (e.g., data, inst)
*/
- class CPUSidePort : public SlavePort
+ class CPUSidePort : public ResponsePort
{
private:
/// The object that owns this object (SimpleMemobj)
@@ -67,7 +67,7 @@
* Constructor. Just calls the superclass constructor.
*/
CPUSidePort(const std::string& name, SimpleMemobj *owner) :
- SlavePort(name, owner), owner(owner), needRetry(false),
+ ResponsePort(name, owner), owner(owner), needRetry(false),
blockedPacket(nullptr)
{ }
@@ -81,7 +81,7 @@
/**
* Get a list of the non-overlapping address ranges the owner is
- * responsible for. All slave ports must override this function
+ * responsible for. All response ports must override this function
* and return a populated list with at least one item.
*
* @return a list of ranges responded to
@@ -96,14 +96,14 @@
protected:
/**
- * Receive an atomic request packet from the master port.
+ * Receive an atomic request packet from the request port.
* No need to implement in this simple memobj.
*/
Tick recvAtomic(PacketPtr pkt) override
{ panic("recvAtomic unimpl."); }
/**
- * Receive a functional request packet from the master port.
+ * Receive a functional request packet from the request port.
* Performs a "debug" access updating/reading the data in place.
*
* @param packet the requestor sent.
@@ -111,7 +111,7 @@
void recvFunctional(PacketPtr pkt) override;
/**
- * Receive a timing request from the master port.
+ * Receive a timing request from the request port.
*
* @param the packet that the requestor sent
* @return whether this object can consume the packet. If false, we
@@ -121,8 +121,8 @@
bool recvTimingReq(PacketPtr pkt) override;
/**
- * Called by the master port if sendTimingResp was called on this
- * slave port (causing recvTimingResp to be called on the master
+ * Called by the request port if sendTimingResp was called on this
+ * response port (causing recvTimingResp to be called on the request
* port) and was unsuccesful.
*/
void recvRespRetry() override;
@@ -132,7 +132,7 @@
* Port on the memory-side that receives responses.
* Mostly just forwards requests to the owner
*/
- class MemSidePort : public MasterPort
+ class MemSidePort : public RequestPort
{
private:
/// The object that owns this object (SimpleMemobj)
@@ -146,7 +146,7 @@
* Constructor. Just calls the superclass constructor.
*/
MemSidePort(const std::string& name, SimpleMemobj *owner) :
- MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
+ RequestPort(name, owner), owner(owner), blockedPacket(nullptr)
{ }
/**
@@ -159,19 +159,19 @@
protected:
/**
- * Receive a timing response from the slave port.
+ * Receive a timing response from the response port.
*/
bool recvTimingResp(PacketPtr pkt) override;
/**
- * Called by the slave port if sendTimingReq was called on this
- * master port (causing recvTimingReq to be called on the slave
+ * Called by the response port if sendTimingReq was called on this
+ * request port (causing recvTimingReq to be called on the response
* port) and was unsuccesful.
*/
void recvReqRetry() override;
/**
- * Called to receive an address range change from the peer slave
+ * Called to receive an address range change from the peer response
* port. The default implementation ignores the change and does
* nothing. Override this function in a derived class if the owner
* needs to be aware of the address ranges, e.g. in an
@@ -233,7 +233,7 @@
/** constructor
*/
- SimpleMemobj(SimpleMemobjParams *params);
+ SimpleMemobj(const SimpleMemobjParams ¶ms);
/**
* Get a port with a given name and index. This is used at
@@ -250,4 +250,4 @@
};
-#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
\ No newline at end of file
+#endif // __LEARNING_GEM5_PART2_SIMPLE_MEMOBJ_HH__
diff --git a/_pages/static/scripts/part2/memoryobject/simple_memobj.py b/_pages/static/scripts/part2/memoryobject/simple_memobj.py
index 8bc2baf..e13a372 100644
--- a/_pages/static/scripts/part2/memoryobject/simple_memobj.py
+++ b/_pages/static/scripts/part2/memoryobject/simple_memobj.py
@@ -24,8 +24,6 @@
# 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.
-#
-# Authors: Jason Lowe-Power
""" This file creates a barebones system and executes 'hello', a simple Hello
World application. Adds a simple memobj between the CPU and the membus.
@@ -68,32 +66,39 @@
# create the interrupt controller for the CPU and connect to the membus
system.cpu.createInterruptController()
-system.cpu.interrupts[0].pio = system.membus.master
-system.cpu.interrupts[0].int_master = system.membus.slave
-system.cpu.interrupts[0].int_slave = system.membus.master
+system.cpu.interrupts[0].pio = system.membus.mem_side_ports
+system.cpu.interrupts[0].int_master = system.membus.cpu_side_ports
+system.cpu.interrupts[0].int_slave = system.membus.mem_side_ports
# Create a DDR3 memory controller and connect it to the membus
-system.mem_ctrl = DDR3_1600_8x8()
-system.mem_ctrl.range = system.mem_ranges[0]
-system.mem_ctrl.port = system.membus.master
+system.mem_ctrl = MemCtrl()
+system.mem_ctrl.dram = DDR3_1600_8x8()
+system.mem_ctrl.dram.range = system.mem_ranges[0]
+system.mem_ctrl.port = system.membus.mem_side_ports
# Connect the system up to the membus
-system.system_port = system.membus.slave
+system.system_port = system.membus.cpu_side_ports
# Create a process for a simple "Hello World" application
process = Process()
# Set the command
+# grab the specific path to the binary
+thispath = os.path.dirname(os.path.realpath(__file__))
+binpath = os.path.join(thispath, '../../../',
+ 'tests/test-progs/hello/bin/x86/linux/hello')
# cmd is a list which begins with the executable (like argv)
-process.cmd = ['tests/test-progs/hello/bin/x86/linux/hello']
+process.cmd = [binpath]
# Set the cpu to use the process as its workload and create thread contexts
system.cpu.workload = process
system.cpu.createThreads()
+system.workload = SEWorkload.init_compatible(binpath)
+
# set up the root SimObject and start the simulation
root = Root(full_system = False, system = system)
# instantiate all of the objects we've created above
m5.instantiate()
-print('Beginning simulation!')
+print("Beginning simulation!")
exit_event = m5.simulate()
print('Exiting @ tick %i because %s' % (m5.curTick(), exit_event.getCause()))
diff --git a/_pages/static/scripts/part2/parameters/SConscript b/_pages/static/scripts/part2/parameters/SConscript
index f0949f7..660fc50 100644
--- a/_pages/static/scripts/part2/parameters/SConscript
+++ b/_pages/static/scripts/part2/parameters/SConscript
@@ -33,4 +33,4 @@
Source('hello_object.cc')
Source('goodbye_object.cc')
-DebugFlag('Hello')
+DebugFlag('HelloExample', 'For Learning gem5 Part 2. Simple example debug flag')
diff --git a/_pages/static/scripts/part2/parameters/goodbye_object.cc b/_pages/static/scripts/part2/parameters/goodbye_object.cc
index 779302c..2c6343d 100644
--- a/_pages/static/scripts/part2/parameters/goodbye_object.cc
+++ b/_pages/static/scripts/part2/parameters/goodbye_object.cc
@@ -30,15 +30,15 @@
#include "learning_gem5/goodbye_object.hh"
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
#include "sim/sim_exit.hh"
-GoodbyeObject::GoodbyeObject(GoodbyeObjectParams *params) :
+GoodbyeObject::GoodbyeObject(const GoodbyeObjectParams ¶ms) :
SimObject(params), event(*this), bandwidth(params->write_bandwidth),
bufferSize(params->buffer_size), buffer(nullptr), bufferUsed(0)
{
buffer = new char[bufferSize];
- DPRINTF(Hello, "Created the goodbye object\n");
+ DPRINTF(HelloExample, "Created the goodbye object\n");
}
GoodbyeObject::~GoodbyeObject()
@@ -49,14 +49,14 @@
void
GoodbyeObject::processEvent()
{
- DPRINTF(Hello, "Processing the event!\n");
+ DPRINTF(HelloExample, "Processing the event!\n");
fillBuffer();
}
void
GoodbyeObject::sayGoodbye(std::string other_name)
{
- DPRINTF(Hello, "Saying goodbye to %s\n", other_name);
+ DPRINTF(HelloExample, "Saying goodbye to %s\n", other_name);
message = "Goodbye " + other_name + "!! ";
@@ -80,18 +80,12 @@
if (bufferUsed < bufferSize - 1) {
// Wait for the next copy for as long as it would have taken
- DPRINTF(Hello, "Scheduling another fillBuffer in %d ticks\n",
+ DPRINTF(HelloExample, "Scheduling another fillBuffer in %d ticks\n",
bandwidth * bytes_copied);
schedule(event, curTick() + bandwidth * bytes_copied);
} else {
- DPRINTF(Hello, "Goodbye done copying!\n");
+ DPRINTF(HelloExample, "Goodbye done copying!\n");
// Be sure to take into account the time for the last bytes
exitSimLoop(buffer, 0, curTick() + bandwidth * bytes_copied);
}
}
-
-GoodbyeObject*
-GoodbyeObjectParams::create()
-{
- return new GoodbyeObject(this);
-}
diff --git a/_pages/static/scripts/part2/parameters/hello_object.cc b/_pages/static/scripts/part2/parameters/hello_object.cc
index 73ee372..173a8ce 100644
--- a/_pages/static/scripts/part2/parameters/hello_object.cc
+++ b/_pages/static/scripts/part2/parameters/hello_object.cc
@@ -28,10 +28,10 @@
* Authors: Jason Lowe-Power
*/
-#include "debug/Hello.hh"
+#include "debug/HelloExample.hh"
#include "learning_gem5/hello_object.hh"
-HelloObject::HelloObject(HelloObjectParams *params) :
+HelloObject::HelloObject(const HelloObjectParams ¶ms) :
SimObject(params),
event(*this),
goodbye(params->goodbye_object),
@@ -39,7 +39,7 @@
latency(params->time_to_wait),
timesLeft(params->number_of_fires)
{
- DPRINTF(Hello, "Created the hello object\n");
+ DPRINTF(HelloExample, "Created the hello object\n");
}
void
@@ -52,7 +52,7 @@
HelloObject::processEvent()
{
timesLeft--;
- DPRINTF(Hello, "Hello world! Processing the event! %d left\n", timesLeft);
+ DPRINTF(HelloExample, "Hello world! Processing the event! %d left\n", timesLeft);
if (timesLeft <= 0) {
DPRINTF(Hello, "Done firing!\n");
@@ -61,9 +61,3 @@
schedule(event, curTick() + latency);
}
}
-
-HelloObject*
-HelloObjectParams::create()
-{
- return new HelloObject(this);
-}
diff --git a/_pages/static/scripts/part2/parameters/hello_object.hh b/_pages/static/scripts/part2/parameters/hello_object.hh
index f70de97..8f408b3 100644
--- a/_pages/static/scripts/part2/parameters/hello_object.hh
+++ b/_pages/static/scripts/part2/parameters/hello_object.hh
@@ -57,7 +57,7 @@
int timesLeft;
public:
- HelloObject(HelloObjectParams *p);
+ HelloObject(const HelloObjectParams &p);
void startup();
};
diff --git a/_pages/static/scripts/part2/simplecache/SimpleCache.py b/_pages/static/scripts/part2/simplecache/SimpleCache.py
index ef88d5f..97b38a6 100644
--- a/_pages/static/scripts/part2/simplecache/SimpleCache.py
+++ b/_pages/static/scripts/part2/simplecache/SimpleCache.py
@@ -35,8 +35,8 @@
type = 'SimpleCache'
cxx_header = "learning_gem5/simple_cache/simple_cache.hh"
- cpu_side = VectorSlavePort("CPU side port, receives requests")
- mem_side = MasterPort("Memory side port, sends requests")
+ cpu_side = VectorResponsePort("CPU side port, receives requests")
+ mem_side = RequestPort("Memory side port, sends requests")
latency = Param.Cycles(1, "Cycles taken on a hit or to resolve a miss")
diff --git a/_pages/static/scripts/part2/simplecache/simple_cache.cc b/_pages/static/scripts/part2/simplecache/simple_cache.cc
index 1cfd0d9..788291f 100644
--- a/_pages/static/scripts/part2/simplecache/simple_cache.cc
+++ b/_pages/static/scripts/part2/simplecache/simple_cache.cc
@@ -24,45 +24,45 @@
* 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.
- *
- * Authors: Jason Lowe-Power
*/
-#include "learning_gem5/simple_cache/simple_cache.hh"
+#include "learning_gem5/part2/simple_cache.hh"
#include "base/random.hh"
#include "debug/SimpleCache.hh"
#include "sim/system.hh"
-SimpleCache::SimpleCache(SimpleCacheParams *params) :
- MemObject(params),
- latency(params->latency),
- blockSize(params->system->cacheLineSize()),
- capacity(params->size / blockSize),
- memPort(params->name + ".mem_side", this),
- blocked(false), outstandingPacket(nullptr), waitingPortId(-1)
+SimpleCache::SimpleCache(const SimpleCacheParams ¶ms) :
+ ClockedObject(params),
+ latency(params.latency),
+ blockSize(params.system->cacheLineSize()),
+ capacity(params.size / blockSize),
+ memPort(params.name + ".mem_side", this),
+ blocked(false), originalPacket(nullptr), waitingPortId(-1), stats(this)
{
// Since the CPU side ports are a vector of ports, create an instance of
// the CPUSidePort for each connection. This member of params is
// automatically created depending on the name of the vector port and
// holds the number of connections to this port name
- for (int i = 0; i < params->port_cpu_side_connection_count; ++i) {
+ for (int i = 0; i < params.port_cpu_side_connection_count; ++i) {
cpuPorts.emplace_back(name() + csprintf(".cpu_side[%d]", i), i, this);
}
}
-Port&
-SimpleCache::getPort(const std::string& if_name, PortID idx)
+Port &
+SimpleCache::getPort(const std::string &if_name, PortID idx)
{
- // This is the name from the Python SimObject declaration (SimpleMemobj.py)
- if (if_name == "cpu_side" && idx < cpuPorts.size()) {
+ // This is the name from the Python SimObject declaration in SimpleCache.py
+ if (if_name == "mem_side") {
+ panic_if(idx != InvalidPortID,
+ "Mem side of simple cache not a vector port");
+ return memPort;
+ } else if (if_name == "cpu_side" && idx < cpuPorts.size()) {
// We should have already created all of the ports in the constructor
return cpuPorts[idx];
- } else if (if_name == "mem_side") {
- return memPort;
} else {
// pass it along to our super class
- return MemObject::getPort(if_name, idx);
+ return ClockedObject::getPort(if_name, idx);
}
}
@@ -204,7 +204,9 @@
waitingPortId = port_id;
// Schedule an event after cache access latency to actually access
- schedule(new AccessEvent(this, pkt), clockEdge(latency));
+ schedule(new EventFunctionWrapper([this, pkt]{ accessTiming(pkt); },
+ name() + ".accessEvent", true),
+ clockEdge(latency));
return true;
}
@@ -219,18 +221,20 @@
// for any added latency.
insert(pkt);
- missLatency.sample(curTick() - missTime);
+ stats.missLatency.sample(curTick() - missTime);
- if (outstandingPacket != nullptr) {
+ // If we had to upgrade the request packet to a full cache line, now we
+ // can use that packet to construct the response.
+ if (originalPacket != nullptr) {
DPRINTF(SimpleCache, "Copying data from new packet to old\n");
// We had to upgrade a previous packet. We can functionally deal with
// the cache access now. It better be a hit.
- bool hit M5_VAR_USED = accessFunctional(outstandingPacket);
+ M5_VAR_USED bool hit = accessFunctional(originalPacket);
panic_if(!hit, "Should always hit after inserting");
- outstandingPacket->makeResponse();
+ originalPacket->makeResponse();
delete pkt; // We may need to delay this, I'm not sure.
- pkt = outstandingPacket;
- outstandingPacket = nullptr;
+ pkt = originalPacket;
+ originalPacket = nullptr;
} // else, pkt contains the data it needs
sendResponse(pkt);
@@ -282,12 +286,12 @@
if (hit) {
// Respond to the CPU side
- hits++; // update stats
+ stats.hits++; // update stats
DDUMP(SimpleCache, pkt->getConstPtr<uint8_t>(), pkt->getSize());
pkt->makeResponse();
sendResponse(pkt);
} else {
- misses++; // update stats
+ stats.misses++; // update stats
missTime = curTick();
// Forward to the memory side.
// We can't directly forward the packet unless it is exactly the size
@@ -322,7 +326,7 @@
assert(new_pkt->getAddr() == new_pkt->getBlockAddr(blockSize));
// Save the old packet
- outstandingPacket = pkt;
+ originalPacket = pkt;
DPRINTF(SimpleCache, "forwarding packet\n");
memPort.sendPacket(new_pkt);
@@ -374,13 +378,15 @@
// Write back the data.
// Create a new request-packet pair
- RequestPtr req(new Request(block->first, blockSize, 0, 0));
+ RequestPtr req = std::make_shared<Request>(
+ block->first, blockSize, 0, 0);
+
PacketPtr new_pkt = new Packet(req, MemCmd::WritebackDirty, blockSize);
new_pkt->dataDynamic(block->second); // This will be deleted later
DPRINTF(SimpleCache, "Writing packet back %s\n", pkt->print());
// Send the write to memory
- memPort.sendTimingReq(new_pkt);
+ memPort.sendPacket(new_pkt);
// Delete this entry
cacheStore.erase(block->first);
@@ -415,36 +421,14 @@
}
}
-void
-SimpleCache::regStats()
+SimpleCache::SimpleCacheStats::SimpleCacheStats(Stats::Group *parent)
+ : Stats::Group(parent),
+ ADD_STAT(hits, UNIT_COUNT, "Number of hits"),
+ ADD_STAT(misses, UNIT_COUNT, "Number of misses"),
+ ADD_STAT(missLatency, UNIT_TICK, "Ticks for misses to the cache"),
+ ADD_STAT(hitRatio, UNIT_RATIO,
+ "The ratio of hits to the total accesses to the cache",
+ hits / (hits + misses))
{
- // If you don't do this you get errors about uninitialized stats.
- MemObject::regStats();
-
- hits.name(name() + ".hits")
- .desc("Number of hits")
- ;
-
- misses.name(name() + ".misses")
- .desc("Number of misses")
- ;
-
- missLatency.name(name() + ".missLatency")
- .desc("Ticks for misses to the cache")
- .init(16) // number of buckets
- ;
-
- hitRatio.name(name() + ".hitRatio")
- .desc("The ratio of hits to the total accesses to the cache")
- ;
-
- hitRatio = hits / (hits + misses);
-
-}
-
-
-SimpleCache*
-SimpleCacheParams::create()
-{
- return new SimpleCache(this);
+ missLatency.init(16); // number of buckets
}
diff --git a/_pages/static/scripts/part2/simplecache/simple_cache.hh b/_pages/static/scripts/part2/simplecache/simple_cache.hh
index 725cc6c..68ab001 100644
--- a/_pages/static/scripts/part2/simplecache/simple_cache.hh
+++ b/_pages/static/scripts/part2/simplecache/simple_cache.hh
@@ -24,8 +24,6 @@
* 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.
- *
- * Authors: Jason Lowe-Power
*/
#ifndef __LEARNING_GEM5_SIMPLE_CACHE_SIMPLE_CACHE_HH__
@@ -33,8 +31,10 @@
#include <unordered_map>
-#include "mem/mem_object.hh"
+#include "base/statistics.hh"
+#include "mem/port.hh"
#include "params/SimpleCache.hh"
+#include "sim/clocked_object.hh"
/**
* A very simple cache object. Has a fully-associative data store with random
@@ -43,7 +43,7 @@
* be outstanding at a time.
* This cache is a writeback cache.
*/
-class SimpleCache : public MemObject
+class SimpleCache : public ClockedObject
{
private:
@@ -51,7 +51,7 @@
* Port on the CPU-side that receives requests.
* Mostly just forwards requests to the cache (owner)
*/
- class CPUSidePort : public SlavePort
+ class CPUSidePort : public ResponsePort
{
private:
/// Since this is a vector port, need to know what number this one is
@@ -71,7 +71,7 @@
* Constructor. Just calls the superclass constructor.
*/
CPUSidePort(const std::string& name, int id, SimpleCache *owner) :
- SlavePort(name, owner), id(id), owner(owner), needRetry(false),
+ ResponsePort(name, owner), id(id), owner(owner), needRetry(false),
blockedPacket(nullptr)
{ }
@@ -86,7 +86,7 @@
/**
* Get a list of the non-overlapping address ranges the owner is
- * responsible for. All slave ports must override this function
+ * responsible for. All response ports must override this function
* and return a populated list with at least one item.
*
* @return a list of ranges responded to
@@ -101,14 +101,14 @@
protected:
/**
- * Receive an atomic request packet from the master port.
+ * Receive an atomic request packet from the request port.
* No need to implement in this simple cache.
*/
Tick recvAtomic(PacketPtr pkt) override
{ panic("recvAtomic unimpl."); }
/**
- * Receive a functional request packet from the master port.
+ * Receive a functional request packet from the request port.
* Performs a "debug" access updating/reading the data in place.
*
* @param packet the requestor sent.
@@ -116,7 +116,7 @@
void recvFunctional(PacketPtr pkt) override;
/**
- * Receive a timing request from the master port.
+ * Receive a timing request from the request port.
*
* @param the packet that the requestor sent
* @return whether this object can consume to packet. If false, we
@@ -126,9 +126,9 @@
bool recvTimingReq(PacketPtr pkt) override;
/**
- * Called by the master port if sendTimingResp was called on this
- * slave port (causing recvTimingResp to be called on the master
- * port) and was unsuccesful.
+ * Called by the request port if sendTimingResp was called on this
+ * response port (causing recvTimingResp to be called on the request
+ * port) and was unsuccessful.
*/
void recvRespRetry() override;
};
@@ -137,7 +137,7 @@
* Port on the memory-side that receives responses.
* Mostly just forwards requests to the cache (owner)
*/
- class MemSidePort : public MasterPort
+ class MemSidePort : public RequestPort
{
private:
/// The object that owns this object (SimpleCache)
@@ -151,7 +151,7 @@
* Constructor. Just calls the superclass constructor.
*/
MemSidePort(const std::string& name, SimpleCache *owner) :
- MasterPort(name, owner), owner(owner), blockedPacket(nullptr)
+ RequestPort(name, owner), owner(owner), blockedPacket(nullptr)
{ }
/**
@@ -165,19 +165,19 @@
protected:
/**
- * Receive a timing response from the slave port.
+ * Receive a timing response from the response port.
*/
bool recvTimingResp(PacketPtr pkt) override;
/**
- * Called by the slave port if sendTimingReq was called on this
- * master port (causing recvTimingReq to be called on the slave
+ * Called by the response port if sendTimingReq was called on this
+ * request port (causing recvTimingReq to be called on the response
* port) and was unsuccesful.
*/
void recvReqRetry() override;
/**
- * Called to receive an address range change from the peer slave
+ * Called to receive an address range change from the peer response
* port. The default implementation ignores the change and does
* nothing. Override this function in a derived class if the owner
* needs to be aware of the address ranges, e.g. in an
@@ -198,7 +198,7 @@
bool handleRequest(PacketPtr pkt, int port_id);
/**
- * Handle the response from the memory side. Called from the memory port
+ * Handle the respone from the memory side. Called from the memory port
* on a timing response.
*
* @param responding packet
@@ -280,7 +280,7 @@
/// Packet that we are currently handling. Used for upgrading to larger
/// cache line sizes
- PacketPtr outstandingPacket;
+ PacketPtr originalPacket;
/// The port to send the response when we recieve it back
int waitingPortId;
@@ -291,61 +291,36 @@
/// An incredibly simple cache storage. Maps block addresses to data
std::unordered_map<Addr, uint8_t*> cacheStore;
- /**
- * Class for an event to delay handling a packet.
- * Automatically deletes itself after process is called.
- */
- class AccessEvent : public Event
- {
- private:
- /// Pointer to the cache object
- SimpleCache *cache;
-
- /// The packet we need to handle
- PacketPtr pkt;
- public:
- AccessEvent(SimpleCache *cache, PacketPtr pkt) :
- Event(Default_Pri, AutoDelete), cache(cache), pkt(pkt)
- { }
-
- /** Process the event. Just call into the cache.
- */
- void process() override {
- cache->accessTiming(pkt);
- }
- };
-
- friend class AccessEvent;
-
/// Cache statistics
- Stats::Scalar hits;
- Stats::Scalar misses;
- Stats::Histogram missLatency;
- Stats::Formula hitRatio;
+ protected:
+ struct SimpleCacheStats : public Stats::Group
+ {
+ SimpleCacheStats(Stats::Group *parent);
+ Stats::Scalar hits;
+ Stats::Scalar misses;
+ Stats::Histogram missLatency;
+ Stats::Formula hitRatio;
+ } stats;
public:
/** constructor
*/
- SimpleCache(SimpleCacheParams *params);
+ SimpleCache(const SimpleCacheParams ¶ms);
/**
* Get a port with a given name and index. This is used at
* binding time and returns a reference to a protocol-agnostic
- * base master port.
+ * port.
*
* @param if_name Port name
* @param idx Index in the case of a VectorPort
*
* @return A reference to the given port
*/
- Port& getPort(const std::string& if_name,
- PortID idx = InvalidPortID) override;
+ Port &getPort(const std::string &if_name,
+ PortID idx=InvalidPortID) override;
- /**
- * Register the stats
- */
- void regStats() override;
};