Daniel Carvalho has uploaded this change for review. (
https://gem5-review.googlesource.com/11100
Change subject: mem-cache: Create cache compressor
......................................................................
mem-cache: Create cache compressor
Create basic template for cache compressors. A basic compressor
must implement a compression and a decompression method.
We also implement a compressor for when compression is not used.
Change-Id: I83dc4d2b8d2bc5ed9f760c938edfa4ebdd6b8583
---
M src/mem/cache/Cache.py
A src/mem/cache/compressors/Compressors.py
A src/mem/cache/compressors/SConscript
A src/mem/cache/compressors/base.cc
A src/mem/cache/compressors/base.hh
A src/mem/cache/compressors/no_compressor.cc
A src/mem/cache/compressors/no_compressor.hh
M src/mem/cache/superblock_blk.cc
M src/mem/cache/superblock_blk.hh
M src/mem/cache/tags/Tags.py
M src/mem/cache/tags/compressed_tags.cc
M src/mem/cache/tags/compressed_tags.hh
12 files changed, 728 insertions(+), 5 deletions(-)
diff --git a/src/mem/cache/Cache.py b/src/mem/cache/Cache.py
index f23d8bc..3336c0c 100644
--- a/src/mem/cache/Cache.py
+++ b/src/mem/cache/Cache.py
@@ -41,6 +41,7 @@
from m5.params import *
from m5.proxy import *
+from Compressors import *
from MemObject import MemObject
from Prefetcher import BasePrefetcher
from ReplacementPolicies import *
@@ -85,6 +86,8 @@
replacement_policy = Param.BaseReplacementPolicy(LRURP(),
"Replacement policy")
+ compressor = Param.BaseCacheCompressor(NoCompressor(),
+ "Cache compressor.")
max_compression_ratio = Param.Int(2,
"Maximum number of compressed blocks per tag.")
diff --git a/src/mem/cache/compressors/Compressors.py
b/src/mem/cache/compressors/Compressors.py
new file mode 100644
index 0000000..b67f638
--- /dev/null
+++ b/src/mem/cache/compressors/Compressors.py
@@ -0,0 +1,44 @@
+# Copyright (c) 2018 Inria
+# All rights reserved.
+#
+# 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.
+#
+# Authors: Daniel Carvalho
+
+from m5.params import *
+from m5.proxy import *
+from ClockedObject import ClockedObject
+
+class BaseCacheCompressor(ClockedObject):
+ type = 'BaseCacheCompressor'
+ abstract = True
+ cxx_header = "mem/cache/compressors/base.hh"
+
+ line_size = Param.Int(Parent.cache_line_size,
+ "Cache line size in bytes")
+
+class NoCompressor(BaseCacheCompressor):
+ type = 'NoCompressor'
+ cxx_class = 'NoCompressor'
+ cxx_header = "mem/cache/compressors/no_compressor.hh"
diff --git a/src/mem/cache/compressors/SConscript
b/src/mem/cache/compressors/SConscript
new file mode 100644
index 0000000..3c6cfce
--- /dev/null
+++ b/src/mem/cache/compressors/SConscript
@@ -0,0 +1,36 @@
+# -*- mode:python -*-
+
+# Copyright (c) 2018 Inria
+# All rights reserved.
+#
+# 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.
+#
+# Authors: Daniel Carvalho
+
+Import('*')
+
+SimObject('Compressors.py')
+
+Source('base.cc')
+Source('no_compressor.cc')
diff --git a/src/mem/cache/compressors/base.cc
b/src/mem/cache/compressors/base.cc
new file mode 100644
index 0000000..0f60eca
--- /dev/null
+++ b/src/mem/cache/compressors/base.cc
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2018 Inria
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Authors: Daniel Carvalho
+ */
+
+/** @file
+ * Definition of a basic cache compressor.
+ */
+
+#include "mem/cache/compressors/base.hh"
+
+#include <algorithm>
+#include <cstdint>
+
+#include "params/BaseCacheCompressor.hh"
+
+CompressionData::CompressionData(std::size_t line_size,
+ const uint8_t* cache_line)
+ :
+ #ifdef DEBUG_COMPRESSION
+ _cacheLine(cache_line, cache_line + line_size),
+ #endif
+ _size(0), lineSize(line_size)
+{
+}
+
+CompressionData::~CompressionData()
+{
+}
+
+void
+CompressionData::setSize(std::size_t size)
+{
+ _size = size;
+}
+
+std::size_t
+CompressionData::getSize() const
+{
+ return _size;
+}
+
+#ifdef DEBUG_COMPRESSION
+bool
+matchLine(uint8_t* cache_line) const
+{
+ return std::memcmp(_cacheLine.data(), cache_line, lineSize) == 0;
+}
+#endif
+
+BaseCacheCompressor::BaseCacheCompressor(const Params *p)
+ : ClockedObject(p), lineSize(p->line_size)
+{
+}
+
+std::unique_ptr<CompressionData>
+BaseCacheCompressor::compress(const uint8_t* cache_line)
+{
+ Cycles lat;
+ return compress(cache_line, lat);
+}
+
+Cycles
+BaseCacheCompressor::decompress(const CompressionData* comp_data)
+{
+ uint8_t cache_line[lineSize];
+
+ // Make sure we've got something to decompress
+ assert(comp_data != nullptr);
+
+ // Apply decompression
+ Cycles lat = decompress(comp_data, cache_line);
+
+ #ifdef DEBUG_COMPRESSION
+ // Check if decompressed line matches original cache line
+ assert(comp_data->matchLine(cache_line));
+ #endif
+
+ return lat;
+}
diff --git a/src/mem/cache/compressors/base.hh
b/src/mem/cache/compressors/base.hh
new file mode 100644
index 0000000..fc36942
--- /dev/null
+++ b/src/mem/cache/compressors/base.hh
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2018 Inria
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Authors: Daniel Carvalho
+ */
+
+/** @file
+ * Definition of a basic cache compressor.
+ * A cache compressor must consist of a compression and a decompression
+ * methods. It must also be aware of the size of an uncompressed cache
+ * line.
+ */
+
+#ifndef __MEM_CACHE_COMPRESSORS_BASE_HH__
+#define __MEM_CACHE_COMPRESSORS_BASE_HH__
+
+#include <cstdint>
+
+#include "base/types.hh"
+#include "sim/clocked_object.hh"
+
+// Uncomment this line if debugging compression
+//#define DEBUG_COMPRESSION
+
+struct BaseCacheCompressorParams;
+
+class CompressionData {
+ private:
+ #ifdef DEBUG_COMPRESSION
+ /**
+ * Keep original cache line for debugging purposes.
+ */
+ const std::vector<uint8_t> _cacheLine;
+ #endif
+
+ /**
+ * Compressed cache line size (in bytes).
+ */
+ std::size_t _size;
+
+ /**
+ * Uncompressed cache line size (in bytes).
+ */
+ const std::size_t lineSize;
+
+ public:
+ /**
+ * Default constructor.
+ *
+ * @param line_size Cache line size (in bytes).
+ * @param cache_line Cache line to which compression is applied.
+ */
+ CompressionData(std::size_t line_size, const uint8_t* cache_line);
+
+ /**
+ * Virtual destructor. Without it unique_ptr will cause mem leak.
+ */
+ virtual ~CompressionData();
+
+ /**
+ * Set compression size (in bytes).
+ *
+ * @param size Compressed data size.
+ */
+ void setSize(std::size_t size);
+
+ /**
+ * Get compression size (in bytes).
+ *
+ * @return Compressed data size.
+ */
+ std::size_t getSize() const;
+
+ #ifdef DEBUG_COMPRESSION
+ /**
+ * Checks if a cache line matches the original cache line for this
+ * compression data. Useful when debugging compression/decompression.
+ *
+ * @param cache_line Line to compare against.
+ * @return True if lines match.
+ */
+ bool matchLine(uint8_t* cache_line) const;
+ #endif
+};
+
+/**
+ * Base cache compressor interface. Every cache compressor must implement a
+ * compression and a decompression method.
+ */
+class BaseCacheCompressor : public ClockedObject {
+ protected:
+ /**
+ * Uncompressed cache line size (in bytes).
+ */
+ const std::size_t lineSize;
+
+ /**
+ * Apply the compression process to the cache line.
+ * Returns the number of cycles used by the compressor, however it is
+ * usually covered by a good pipelined execution, and is currently
ignored.
+ *
+ * @param cache_line The cache line to be compressed.
+ * @param Compression latency in number of cycles.
+ * @return Cache line after compression.
+ */
+ virtual std::unique_ptr<CompressionData> compress(
+ const uint8_t* cache_line, Cycles& lat) = 0;
+
+ /**
+ * Apply the decompression process to the compressed data.
+ *
+ * @param comp_data Compressed cache line.
+ * @param cache_line The cache line to be decompressed.
+ * @return Decompression latency in number of cycles.
+ */
+ virtual Cycles decompress(const CompressionData* comp_data,
+ uint8_t* cache_line) = 0;
+
+ public:
+ /** Convenience typedef. */
+ typedef BaseCacheCompressorParams Params;
+
+ /**
+ * Default constructor.
+ */
+ BaseCacheCompressor(const Params *p);
+
+ /**
+ * Default destructor.
+ */
+ virtual ~BaseCacheCompressor() {};
+
+ /**
+ * Apply the compression process to the cache line. Ignores compression
+ * cycles.
+ *
+ * @param cache_line The cache line to be compressed.
+ * @param Compression latency in number of cycles.
+ * @return Cache line after compression.
+ */
+ std::unique_ptr<CompressionData> compress(const uint8_t* cache_line);
+
+ /**
+ * Apply the decompression process to the compressed data.
+ *
+ * @param comp_data Compressed cache line.
+ * @return Decompression latency in number of cycles.
+ */
+ Cycles decompress(const CompressionData* comp_data);
+};
+
+#endif //__MEM_CACHE_COMPRESSORS_BASE_HH__
diff --git a/src/mem/cache/compressors/no_compressor.cc
b/src/mem/cache/compressors/no_compressor.cc
new file mode 100644
index 0000000..d30ce19
--- /dev/null
+++ b/src/mem/cache/compressors/no_compressor.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2018 Inria
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Authors: Daniel Carvalho
+ */
+
+/** @file
+ * Definition of a compressor that does not compress.
+ * It should be used when compression is not used.
+ */
+
+#include "mem/cache/compressors/no_compressor.hh"
+
+#include <algorithm>
+#include <cstdint>
+
+#include "params/NoCompressor.hh"
+
+NoCompressor::NoCompressorCompData::NoCompressorCompData(std::size_t
line_size,
+ const uint8_t* cache_line)
+ : CompressionData(line_size, cache_line),
+ _cacheLine(cache_line, cache_line + line_size)
+{
+ // As there is no compression, the compressed line size is
+ // equal to the original cache line size
+ setSize(line_size);
+}
+
+NoCompressor::NoCompressorCompData::~NoCompressorCompData()
+{
+}
+
+void
+NoCompressor::NoCompressorCompData::getLine(uint8_t* cache_line) const
+{
+ std::copy(_cacheLine.begin(), _cacheLine.end(), cache_line);
+}
+
+NoCompressor::NoCompressor(const Params *p) : BaseCacheCompressor(p)
+{
+}
+
+std::unique_ptr<CompressionData>
+NoCompressor::compress(const uint8_t* cache_line, Cycles& lat)
+{
+ // The compression latency is zero, as no compression is done
+ lat = Cycles(0);
+
+ return std::unique_ptr<NoCompressorCompData>(
+ new NoCompressorCompData(lineSize, cache_line));
+}
+
+Cycles
+NoCompressor::decompress(const CompressionData* comp_data, uint8_t*
cache_line)
+{
+ static_cast<const
NoCompressorCompData*>(comp_data)->getLine(cache_line);
+
+ // The decompression latency is zero, as no decompression is done
+ return Cycles(0);
+}
+
+NoCompressor *
+NoCompressorParams::create()
+{
+ return new NoCompressor(this);
+}
diff --git a/src/mem/cache/compressors/no_compressor.hh
b/src/mem/cache/compressors/no_compressor.hh
new file mode 100644
index 0000000..7928cbc
--- /dev/null
+++ b/src/mem/cache/compressors/no_compressor.hh
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2018 Inria
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * Authors: Daniel Carvalho
+ */
+
+/** @file
+ * Definition of a compressor that does not compress.
+ * It should be used when compression is not used.
+ */
+
+#ifndef __MEM_CACHE_COMPRESSORS_NO_COMPRESSOR_HH__
+#define __MEM_CACHE_COMPRESSORS_NO_COMPRESSOR_HH__
+
+#include <cstdint>
+
+#include "base/types.hh"
+#include "mem/cache/compressors/base.hh"
+
+struct NoCompressorParams;
+
+/**
+ * Dummy compressor for when compression is not done. The compressed data
is
+ * equal to the original line, and thus the size matches the cache line
size.
+ */
+class NoCompressor : public BaseCacheCompressor {
+ private:
+ /**
+ * Compression data for when compression is not done. It contains the
+ * original cache line, and nothing else.
+ */
+ class NoCompressorCompData : public CompressionData {
+ private:
+ /**
+ * The compressed data is the original cache line.
+ */
+ const std::vector<uint8_t> _cacheLine;
+
+ public:
+ /**
+ * Default constructor.
+ *
+ * @param line_size Cache line size (in bytes).
+ * @param cache_line Cache line to which compression is applied.
+ */
+ NoCompressorCompData(std::size_t line_size,
+ const uint8_t* cache_line);
+
+ /**
+ * Default destructor.
+ */
+ ~NoCompressorCompData();
+
+ /**
+ * Get original cache line.
+ *
+ * @param cache_line Initialized container to write cache line to.
+ */
+ void getLine(uint8_t* cache_line) const;
+ };
+
+ protected:
+ /**
+ * Apply the compression process to the cache line. The compressed
line is
+ * equal to the uncompressed, and the compression latency is zero.
+ *
+ * @param cache_line The cache line to be compressed.
+ * @param Compression latency in number of cycles.
+ * @return Cache line after compression.
+ */
+ std::unique_ptr<CompressionData> compress(const uint8_t* cache_line,
+ Cycles& lat) override;
+
+ /**
+ * Decompress data, however no decompression is needed, so the latency
+ * is zero.
+ *
+ * @param comp_data Compressed cache line.
+ * @param cache_line The cache line to be decompressed.
+ * @return Decompression latency in number of cycles.
+ */
+ Cycles decompress(const CompressionData* comp_data, uint8_t*
cache_line)
+
override;
+
+ public:
+ /** Convenience typedef. */
+ typedef NoCompressorParams Params;
+
+ /**
+ * Default constructor.
+ */
+ NoCompressor(const Params *p);
+
+ /**
+ * Default destructor.
+ */
+ ~NoCompressor() {};
+};
+
+#endif //__MEM_CACHE_COMPRESSORS_NO_COMPRESSOR_HH__
diff --git a/src/mem/cache/superblock_blk.cc
b/src/mem/cache/superblock_blk.cc
index 988fa14..87fb455 100644
--- a/src/mem/cache/superblock_blk.cc
+++ b/src/mem/cache/superblock_blk.cc
@@ -42,7 +42,8 @@
#include "base/logging.hh"
CompressionBlk::CompressionBlk()
- : CacheBlk(), _superblock(nullptr), _superblockOffset(0)
+ : CacheBlk(), _superblock(nullptr), _superblockOffset(0),
+ _compressionData(nullptr)
{
}
@@ -78,8 +79,22 @@
}
void
+CompressionBlk::setCompressionData(
+ std::unique_ptr<CompressionData>& compression_data)
+{
+ _compressionData = std::move(compression_data);
+}
+
+const CompressionData*
+CompressionBlk::getCompressionData() const
+{
+ return _compressionData.get();
+}
+
+void
CompressionBlk::insert(const Addr tag, const bool is_secure,
- const int src_master_ID, const uint32_t task_ID)
+ const int src_master_ID, const uint32_t task_ID,
+ std::unique_ptr<CompressionData>& compression_data)
{
// Make sure it is not overwriting another superblock
panic_if((_superblock && _superblock->isValid()) &&
@@ -91,6 +106,9 @@
// Set superblock tag
_superblock->setTag(tag);
+
+ // Set compression data
+ setCompressionData(compression_data);
}
bool
@@ -111,6 +129,26 @@
return blk->isValid() && blk->isSecure();});
}
+int
+SuperblockBlk::countValidBlocks() const
+{
+ // Count the number of valid blocks in this superblock
+ return std::count_if(blks.begin(), blks.end(),
+ [](const CompressionBlk* blk){return
blk->isValid();});
+}
+
+std::size_t
+SuperblockBlk::getUsedSize() const
+{
+ std::size_t size = 0;
+ for (const auto& blk : blks) {
+ if (blk->isValid()) {
+ size += blk->getCompressionData()->getSize();
+ }
+ }
+ return size;
+}
+
void
SuperblockBlk::setTag(const Addr tag)
{
diff --git a/src/mem/cache/superblock_blk.hh
b/src/mem/cache/superblock_blk.hh
index 613f6cf..85160c0 100644
--- a/src/mem/cache/superblock_blk.hh
+++ b/src/mem/cache/superblock_blk.hh
@@ -40,6 +40,7 @@
#include <vector>
#include "mem/cache/blk.hh"
+#include "mem/cache/compressors/base.hh"
#include "mem/cache/replacement_policies/base.hh"
class SuperblockBlk;
@@ -61,6 +62,19 @@
*/
int _superblockOffset;
+ /**
+ * Data contained by this block in a compressed format.
+ */
+ std::unique_ptr<CompressionData> _compressionData;
+
+ /**
+ * Set data as compressed by the chosen compression method.
+ *
+ * @param compression_data The compression data.
+ */
+ void setCompressionData(
+ std::unique_ptr<CompressionData>& compression_data);
+
public:
CompressionBlk();
CompressionBlk(const CompressionBlk&) = delete;
@@ -103,6 +117,13 @@
Addr getTag() const;
/**
+ * Get compression data.
+ *
+ * @return The compression data.
+ */
+ const CompressionData* getCompressionData() const;
+
+ /**
* Set member variables when a block insertion occurs. Resets reference
* count to 1 (the insertion counts as a reference), and touch block if
* it hadn't been touched previously. Sets the insertion tick to the
@@ -112,9 +133,11 @@
* @param is_secure Whether the block is in secure space or not.
* @param src_master_ID The source requestor ID.
* @param task_ID The new task ID.
+ * @param compression_data The compression data.
*/
void insert(const Addr tag, const bool is_secure, const int
src_master_ID,
- const uint32_t task_ID);
+ const uint32_t task_ID,
+ std::unique_ptr<CompressionData>& compression_data);
};
/**
@@ -157,6 +180,20 @@
bool isSecure() const;
/**
+ * Count the number of valid blocks in this superblock.
+ *
+ * @return Number of valid blocks.
+ */
+ int countValidBlocks() const;
+
+ /**
+ * Get the occupied size (in bytes) of the blocks in this superblock.
+ *
+ * @return The occupied size.
+ */
+ std::size_t getUsedSize() const;
+
+ /**
* Set tag associated to this block.
*
* @param The tag value.
diff --git a/src/mem/cache/tags/Tags.py b/src/mem/cache/tags/Tags.py
index 46f4339..1bd70e3 100644
--- a/src/mem/cache/tags/Tags.py
+++ b/src/mem/cache/tags/Tags.py
@@ -38,6 +38,7 @@
from m5.params import *
from m5.proxy import *
from ClockedObject import ClockedObject
+from Compressors import *
class BaseTags(ClockedObject):
type = 'BaseTags'
@@ -110,6 +111,10 @@
replacement_policy = Param.BaseReplacementPolicy(
Parent.replacement_policy, "Replacement policy")
+ # Get the cache compression method
+ compressor = Param.BaseCacheCompressor(Parent.compressor,
+ "Cache compressor.")
+
# Cache compression for parallel accesses is very inefficient, as a
# decompression must be done per data block
sequential_access = True
diff --git a/src/mem/cache/tags/compressed_tags.cc
b/src/mem/cache/tags/compressed_tags.cc
index ecbf050..05db826 100644
--- a/src/mem/cache/tags/compressed_tags.cc
+++ b/src/mem/cache/tags/compressed_tags.cc
@@ -44,13 +44,14 @@
#include "base/types.hh"
#include "debug/CacheRepl.hh"
#include "mem/cache/base.hh"
+#include "mem/cache/compressors/base.hh"
#include "mem/cache/replacement_policies/base.hh"
#include "mem/request.hh"
#include "params/CompressedTags.hh"
CompressedTags::CompressedTags(const Params *p)
: BaseTags(p), assoc(p->assoc), allocAssoc(p->assoc),
- replacementPolicy(p->replacement_policy),
+ replacementPolicy(p->replacement_policy), compressor(p->compressor),
maxCR(p->max_compression_ratio),
numSuperblocks(numBlocks / maxCR), numSets(numSuperblocks /
p->assoc),
blks(numBlocks), superblockBlks(numSuperblocks), sets(numSets),
@@ -119,6 +120,17 @@
}
}
+bool
+CompressedTags::canCoAllocate(const SuperblockBlk* superblock,
+ const CompressionData* compression_data)
const
+{
+ // Simple co-allocation function: two blocks with compression ratio of
+ // up to 50% can share a superblock
+ return (superblock->countValidBlocks() < 2) &&
+ (superblock->getUsedSize() + compression_data->getSize() <=
+ blkSize) && (compression_data->getSize() <= blkSize/2);
+}
+
void
CompressedTags::invalidate(CacheBlk *blk)
{
@@ -202,11 +214,25 @@
// Cache hit
lat = accessLatency;
+ // The compressor is called to decompress data. Although the data
is
+ // stored uncompressed, even if a compressor is used, the
compression
+ // and decompression methods are called to calculate the amount of
+ // cycles used.
+ if (blk->isValid()){
+ lat += compressor->decompress(
+ compression_blk->getCompressionData());
+ }
+
// Check if the block to be accessed is available. If not,
// apply the accessLatency on top of block->whenReady.
if (blk->whenReady > curTick() &&
cache->ticksToCycles(blk->whenReady - curTick()) >
accessLatency) {
+ // TODO I think this should have been:
+ // lat = max(cache->ticksToCycles(blk->whenReady - curTick(),
+ // accessLatency) + decompressLatency;
+ // as from my understanding, the block access latency is
+ // "parallel" to the whenReady cycle
lat += cache->ticksToCycles(blk->whenReady - curTick());
}
@@ -274,11 +300,26 @@
// It would be a hit if victim was valid, and upgrades do not call
// findVictim, so it cannot happen
assert(!victim->isValid());
+
+ // The compressor is called to check if the new block can be co-
+ // allocated in the superblock. If not, we must evict the whole
+ // superblock
+ std::unique_ptr<CompressionData> compression_data =
+ compressor->compress(pkt->getConstPtr<uint8_t>());
+
+ // Check for co-allocation
+ evictSuperblock = !canCoAllocate(victim_superblock,
+ compression_data.get());
}
// The whole superblock must be evicted to make room for the new one
if (evictSuperblock) {
for (const auto& blk : victim_superblock->blks){
+ // Decompress block to calculate victim search latency
+ if (blk->isValid()) {
+ lat += compressor->decompress(blk->getCompressionData());
+ }
+
evict_blks.push_back(blk);
}
}
@@ -296,13 +337,23 @@
// Insert block
BaseTags::insertBlock(pkt, blk);
+ // The compressor is called to compress data before insertion.
+ // Although the data is stored uncompressed, even if a compressor
+ // is used, the compression/decompression methods are called to
+ // calculate the amount of cycles needed on accesses (by the
decompressor).
+ // @todo compression is being called twice for a successful insertion,
and
+ // this messes the stats. Fix it to be called just once.
+ std::unique_ptr<CompressionData> compression_data =
+ compressor->compress(pkt->getConstPtr<uint8_t>());
+
// Get block's superblock
CompressionBlk* compression_blk = static_cast<CompressionBlk*>(blk);
const SuperblockBlk* superblock = compression_blk->getSuperblock();
// Set block's metadata
compression_blk->insert(extractTag(pkt->getAddr()), pkt->isSecure(),
- pkt->req->masterId(), pkt->req->taskId());
+ pkt->req->masterId(), pkt->req->taskId(),
+ compression_data);
// When a block is inserted, the tag is only a newly used tag if the
// superblock was not previously present in the cache.
diff --git a/src/mem/cache/tags/compressed_tags.hh
b/src/mem/cache/tags/compressed_tags.hh
index 7092ff7..f3ac320 100644
--- a/src/mem/cache/tags/compressed_tags.hh
+++ b/src/mem/cache/tags/compressed_tags.hh
@@ -43,6 +43,7 @@
#include "mem/cache/tags/base.hh"
#include "mem/packet.hh"
+class BaseCacheCompressor;
class BaseReplacementPolicy;
class ReplaceableEntry;
struct CompressedTagsParams;
@@ -82,6 +83,9 @@
/** Replacement policy. */
BaseReplacementPolicy *replacementPolicy;
+ /** Compression method being used. */
+ BaseCacheCompressor* compressor;
+
/** Maximum compression ratio. */
const unsigned maxCR;
@@ -125,6 +129,16 @@
virtual ~CompressedTags() {};
/**
+ * Checks whether a superblock can co-allocate given compressed data
block.
+ *
+ * @param superblock Superblock to check.
+ * @param compression_data Compressed data of new block to co-allocate.
+ * @return True if block can be co-allocated in superblock.
+ */
+ virtual bool canCoAllocate(const SuperblockBlk* superblock,
+ const CompressionData* compression_data)
const;
+
+ /**
* This function updates the tags when a block is invalidated but does
* not invalidate the block itself. It also updates the replacement
data.
*
--
To view, visit https://gem5-review.googlesource.com/11100
To unsubscribe, or for help writing mail filters, visit
https://gem5-review.googlesource.com/settings
Gerrit-Project: public/gem5
Gerrit-Branch: master
Gerrit-Change-Id: I83dc4d2b8d2bc5ed9f760c938edfa4ebdd6b8583
Gerrit-Change-Number: 11100
Gerrit-PatchSet: 1
Gerrit-Owner: Daniel Carvalho <[email protected]>
Gerrit-MessageType: newchange
_______________________________________________
gem5-dev mailing list
[email protected]
http://m5sim.org/mailman/listinfo/gem5-dev