From 4c016b5c4989a433adb96151c8918f21c028d4ac Mon Sep 17 00:00:00 2001 From: greenfool Date: Fri, 30 Jan 2026 09:34:03 +0000 Subject: [PATCH 1/3] add restore memtrace --- configs/common/Options.py | 2 + configs/common/Simulation.py | 3 +- configs/common/xiangshan.py | 5 + configs/example/kmhv3.py | 1 + src/mem/cache/cache_blk.hh | 10 + src/mem/cache/replacement_policies/base.hh | 2 + src/mem/cache/replacement_policies/bip_rp.hh | 3 + .../cache/replacement_policies/brrip_rp.hh | 4 +- .../cache/replacement_policies/dueling_rp.hh | 3 + src/mem/cache/replacement_policies/fifo_rp.hh | 4 +- src/mem/cache/replacement_policies/lfu_rp.hh | 4 +- src/mem/cache/replacement_policies/lru_rp.cc | 9 + src/mem/cache/replacement_policies/lru_rp.hh | 2 + src/mem/cache/replacement_policies/mru_rp.hh | 4 +- .../cache/replacement_policies/random_rp.hh | 4 +- .../replacement_policies/second_chance_rp.hh | 4 +- src/mem/cache/replacement_policies/ship_rp.hh | 4 +- .../replacement_policies/tree_plru_rp.hh | 4 +- .../cache/replacement_policies/xs_drrip_rp.hh | 4 +- src/mem/cache/tags/base.cc | 194 ++++++++++++++++++ src/mem/cache/tags/base.hh | 11 + src/mem/cache/tags/base_set_assoc.hh | 9 + src/mem/cache/tags/fa_lru.hh | 17 ++ src/mem/cache/tags/indexing_policies/base.cc | 7 + src/mem/cache/tags/indexing_policies/base.hh | 12 ++ .../indexing_policies/skewed_associative.cc | 1 + src/mem/cache/tags/sector_tags.cc | 8 + src/mem/cache/tags/sector_tags.hh | 3 + src/mem/physical.cc | 6 + src/mem/physical.hh | 4 + src/mem/snoop_filter.cc | 22 +- src/python/m5/SimObject.py | 6 + src/python/m5/simulate.py | 6 +- src/sim/System.py | 2 + src/sim/eventq.hh | 1 - src/sim/globals.cc | 5 + src/sim/globals.hh | 1 + src/sim/root.cc | 9 + src/sim/root.hh | 12 ++ src/sim/sim_object.hh | 11 + src/sim/simulate.cc | 5 - src/sim/system.cc | 4 +- src/sim/system.hh | 4 + 43 files changed, 414 insertions(+), 22 deletions(-) diff --git a/configs/common/Options.py b/configs/common/Options.py index 952360fc03..972c30f794 100644 --- a/configs/common/Options.py +++ b/configs/common/Options.py @@ -147,6 +147,8 @@ def addNoISAOptions(parser, configure_xiangshan=False): parser.add_argument("--l1-to-l2-pf-hint", action="store_true") parser.add_argument("--l2-to-l3-pf-hint", action="store_true") + parser.add_argument("--memtrace_path", type=str, default=None) # Memtrace file path for restoring the microarchitectural state in L3 Cache + parser.add_argument("--num-dirs", type=int, default=1) parser.add_argument("--num-l2caches", type=int, default=1) parser.add_argument("--num-l3caches", type=int, default=1) diff --git a/configs/common/Simulation.py b/configs/common/Simulation.py index 5f7741dff6..b791eb2f83 100644 --- a/configs/common/Simulation.py +++ b/configs/common/Simulation.py @@ -821,7 +821,8 @@ def run_vanilla(options, root, testsys, cpu_class): checkpoint_dir = None root.apply_config(options.param) - m5.instantiate(checkpoint_dir) + # add path for generic_rv_cpt and memtrace_path + m5.instantiate(pmem_file_path=options.generic_rv_cpt,mem_trace_file=options.memtrace_path,ckpt_dir=checkpoint_dir) # Handle the max tick settings now that tick frequency was resolved # during system instantiation diff --git a/configs/common/xiangshan.py b/configs/common/xiangshan.py index 1190d5486d..6e633bf1dc 100644 --- a/configs/common/xiangshan.py +++ b/configs/common/xiangshan.py @@ -227,9 +227,13 @@ def config_xiangshan_inputs(args: argparse.Namespace, sys): sys.workload.raw_bootloader = True else: sys.gcpt_restorer_file = gcpt_restorer + if args.memtrace_path is not None: + sys.restore_from_memtrace = True + sys.memtrace_file = args.memtrace_path # enable h checkpoint if args.enable_h_gcpt: sys.enable_h_gcpt = True + # configure DRAMSim input if args.mem_type == 'DRAMsim3' and args.dramsim3_ini is None: # use relative path to find the dramsim3 ini file, from configs/common/ to root @@ -274,6 +278,7 @@ def build_xiangshan_system(args): ruby = True # Create system using FS mode with trace-specific memory configuration + # memtrace test_sys = makeBareMetalXiangshanSystem('timing', SysConfig(mem=args.mem_size), None, np=np, ruby=ruby) # CRITICAL FIX: Configure trace-specific memory ranges and functional TLB for trace mode diff --git a/configs/example/kmhv3.py b/configs/example/kmhv3.py index 71844d9478..01bca59b1b 100644 --- a/configs/example/kmhv3.py +++ b/configs/example/kmhv3.py @@ -162,6 +162,7 @@ def setKmhV3Params(args, system): system.l3.prefetch_can_offload = False system.l3.num_slices = 4 + if __name__ == '__m5_main__': FutureClass = None diff --git a/src/mem/cache/cache_blk.hh b/src/mem/cache/cache_blk.hh index b2235e8bb3..626fff32d5 100644 --- a/src/mem/cache/cache_blk.hh +++ b/src/mem/cache/cache_blk.hh @@ -498,6 +498,16 @@ class CacheBlk : public TaggedEntry } } + // Public versions of some protected setters for use in restore L3 microarchitectural state + /** Set the task id value. */ + void setTaskId_pub(const uint32_t task_id) { _taskId = task_id; } + + /** Set the source requestor id. */ + void setSrcRequestorId_pub(const uint32_t id) { _srcRequestorId = id; } + + /** Set the current tick as this block's insertion tick. */ + void setTickInserted_pub() { _tickInserted = curTick(); } + /** Set the XS metadata. */ void setXsMetadata(const Request::XsMetadata &xs_meta) { diff --git a/src/mem/cache/replacement_policies/base.hh b/src/mem/cache/replacement_policies/base.hh index fc92ecb6ae..c1c310f6fb 100644 --- a/src/mem/cache/replacement_policies/base.hh +++ b/src/mem/cache/replacement_policies/base.hh @@ -95,6 +95,8 @@ class Base : public SimObject virtual void reset(const std::shared_ptr& replacement_data) const = 0; + virtual void reset4memtrace(const std::shared_ptr& + replacement_data,int priority) const = 0; /** * Find replacement victim among candidates. * diff --git a/src/mem/cache/replacement_policies/bip_rp.hh b/src/mem/cache/replacement_policies/bip_rp.hh index 486f4597dd..e2373c94d5 100644 --- a/src/mem/cache/replacement_policies/bip_rp.hh +++ b/src/mem/cache/replacement_policies/bip_rp.hh @@ -76,6 +76,9 @@ class BIP : public LRU */ void reset(const std::shared_ptr& replacement_data) const override; + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } }; } // namespace replacement_policy diff --git a/src/mem/cache/replacement_policies/brrip_rp.hh b/src/mem/cache/replacement_policies/brrip_rp.hh index f4f815e056..57b60d4956 100644 --- a/src/mem/cache/replacement_policies/brrip_rp.hh +++ b/src/mem/cache/replacement_policies/brrip_rp.hh @@ -142,7 +142,9 @@ class BRRIP : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using rrpv. * diff --git a/src/mem/cache/replacement_policies/dueling_rp.hh b/src/mem/cache/replacement_policies/dueling_rp.hh index 0180908ed2..d59344b3e4 100644 --- a/src/mem/cache/replacement_policies/dueling_rp.hh +++ b/src/mem/cache/replacement_policies/dueling_rp.hh @@ -115,6 +115,9 @@ class Dueling : public Base const PacketPtr pkt) override; void reset(const std::shared_ptr& replacement_data) const override; + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } ReplaceableEntry* getVictim(const ReplacementCandidates& candidates) const override; std::shared_ptr instantiateEntry() override; diff --git a/src/mem/cache/replacement_policies/fifo_rp.hh b/src/mem/cache/replacement_policies/fifo_rp.hh index f4703d1299..6d246a9f9d 100644 --- a/src/mem/cache/replacement_policies/fifo_rp.hh +++ b/src/mem/cache/replacement_policies/fifo_rp.hh @@ -94,7 +94,9 @@ class FIFO : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using insertion timestamps. * diff --git a/src/mem/cache/replacement_policies/lfu_rp.hh b/src/mem/cache/replacement_policies/lfu_rp.hh index aa058c46bd..f4157db642 100644 --- a/src/mem/cache/replacement_policies/lfu_rp.hh +++ b/src/mem/cache/replacement_policies/lfu_rp.hh @@ -94,7 +94,9 @@ class LFU : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using reference frequency. * diff --git a/src/mem/cache/replacement_policies/lru_rp.cc b/src/mem/cache/replacement_policies/lru_rp.cc index c22f3fe2ba..84d766a1b3 100644 --- a/src/mem/cache/replacement_policies/lru_rp.cc +++ b/src/mem/cache/replacement_policies/lru_rp.cc @@ -70,6 +70,15 @@ LRU::reset(const std::shared_ptr& replacement_data) const replacement_data)->lastTouchTick = curTick(); } +void +LRU::reset4memtrace(const std::shared_ptr& replacement_data,int priority) const +{ + // Set last touch timestamp + // Here we use priority to set lastTouchTick, the lower the priority, the older the lastTouchTick + std::static_pointer_cast( + replacement_data)->lastTouchTick = curTick() - priority; +} + ReplaceableEntry* LRU::getVictim(const ReplacementCandidates& candidates) const { diff --git a/src/mem/cache/replacement_policies/lru_rp.hh b/src/mem/cache/replacement_policies/lru_rp.hh index 620117dca5..2ed0402242 100644 --- a/src/mem/cache/replacement_policies/lru_rp.hh +++ b/src/mem/cache/replacement_policies/lru_rp.hh @@ -93,6 +93,8 @@ class LRU : public Base void reset(const std::shared_ptr& replacement_data) const override; + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override; + /** * Find replacement victim using LRU timestamps. * diff --git a/src/mem/cache/replacement_policies/mru_rp.hh b/src/mem/cache/replacement_policies/mru_rp.hh index 1657ace3d5..e2d5acc35f 100644 --- a/src/mem/cache/replacement_policies/mru_rp.hh +++ b/src/mem/cache/replacement_policies/mru_rp.hh @@ -94,7 +94,9 @@ class MRU : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using access timestamps. * diff --git a/src/mem/cache/replacement_policies/random_rp.hh b/src/mem/cache/replacement_policies/random_rp.hh index 9c383d5418..2b14643947 100644 --- a/src/mem/cache/replacement_policies/random_rp.hh +++ b/src/mem/cache/replacement_policies/random_rp.hh @@ -95,7 +95,9 @@ class Random : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim at random. * diff --git a/src/mem/cache/replacement_policies/second_chance_rp.hh b/src/mem/cache/replacement_policies/second_chance_rp.hh index 4d0a36cdeb..458de803b2 100644 --- a/src/mem/cache/replacement_policies/second_chance_rp.hh +++ b/src/mem/cache/replacement_policies/second_chance_rp.hh @@ -109,7 +109,9 @@ class SecondChance : public FIFO */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using insertion timestamps and second chance * bit. diff --git a/src/mem/cache/replacement_policies/ship_rp.hh b/src/mem/cache/replacement_policies/ship_rp.hh index fa27540adb..b4ecaffd2c 100644 --- a/src/mem/cache/replacement_policies/ship_rp.hh +++ b/src/mem/cache/replacement_policies/ship_rp.hh @@ -152,7 +152,9 @@ class SHiP : public BRRIP const PacketPtr pkt) override; void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Instantiate a replacement data entry. * diff --git a/src/mem/cache/replacement_policies/tree_plru_rp.hh b/src/mem/cache/replacement_policies/tree_plru_rp.hh index 335670457c..167eff6b01 100644 --- a/src/mem/cache/replacement_policies/tree_plru_rp.hh +++ b/src/mem/cache/replacement_policies/tree_plru_rp.hh @@ -186,7 +186,9 @@ class TreePLRU : public Base */ void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find replacement victim using TreePLRU bits. It is assumed that all * candidates share the same replacement data tree. diff --git a/src/mem/cache/replacement_policies/xs_drrip_rp.hh b/src/mem/cache/replacement_policies/xs_drrip_rp.hh index b1a4d6e3fd..8bf119b4ba 100644 --- a/src/mem/cache/replacement_policies/xs_drrip_rp.hh +++ b/src/mem/cache/replacement_policies/xs_drrip_rp.hh @@ -203,7 +203,9 @@ class XSDRRIP : public Base void reset(const std::shared_ptr& replacement_data) const override; - + void reset4memtrace(const std::shared_ptr& replacement_data,int priority) const override + { + } /** * Find victim for replacement */ diff --git a/src/mem/cache/tags/base.cc b/src/mem/cache/tags/base.cc index 20c6ac20b6..1801e18450 100644 --- a/src/mem/cache/tags/base.cc +++ b/src/mem/cache/tags/base.cc @@ -55,6 +55,17 @@ #include "sim/sim_exit.hh" #include "sim/system.hh" +// memtrace includes +#include +#include +#include +#include +#include +#include +#include +#include +#include "sim/root.hh" + namespace gem5 { @@ -311,4 +322,187 @@ BaseTags::BaseTagStats::preDumpStats() tags.computeStats(); } + +// restore L3 cache microarchitecture states based on memtrace +void +BaseTags::warmupState(const std::string &pmem_file,const std::string &memtrace_file) +{ + std::ifstream file(memtrace_file); // the file contains the microarchitecture states from memtrace + if(!file.is_open()) + { + std::cout << "无法打开文件:" << memtrace_file << std::endl; + }; + std::string line; + std::string taskid; + std::string requestorid; + std::string rank; + int line_max = this->size / this->blkSize; //compute the number of cache lines + volatile int offset_num=0; + int num = this->blkMask; + while(num) //compute tag+set bits + { + offset_num += num & 1; + num >>= 1; + } + + int total_num =64; //compute set bits + + int assoc = this->indexingPolicy->getAssoc(); + + num = size/assoc; + num = num/blkSize; + volatile int set_num=0; + while(num) + { + num >>= 1; + set_num++; + } + set_num--; + volatile int tag_num= total_num-set_num-offset_num; + + std::vector decompressed_data = decompress_gz_to_memory(pmem_file); + for(int line_num=0;line_num setbin(myset); + std::string myset_str = setbin.to_string(); + + myset_str=myset_str.substr(myset_str.size()-set_num,set_num); + std::string myaddr = mytag+myset_str; + myaddr.append(offset_num,'0');//paddr + + const Addr p_addr = std::stoull(myaddr, nullptr, 2); + const Addr h_addr = p_addr - 0x100000000 + 0x80000000;// host + Addr tag = std::stoull(mytag, nullptr, 2); + uint32_t set = indexingPolicy->myextractSet(p_addr); + const bool is_secure = false; + + std::size_t blk_size_bits = blkSize*8; + + + // Find replacement victim + std::vector evict_blks; + CacheBlk *victim = this->findVictim(p_addr, is_secure, blk_size_bits, + evict_blks); + this->updateRp(victim,memtrace_priority);//replacement policy state update + victim->insert(tag, is_secure); + victim->setSrcRequestorId_pub(static_cast(std::stoul(requestorid))); + victim->setTaskId_pub(static_cast(std::stoul(taskid))); + victim->setTickInserted_pub(); + victim->setCoherenceBits(CacheBlk::WritableBit); + victim->setCoherenceBits(CacheBlk::ReadableBit); + + Addr offset = p_addr & Addr (blkSize - 1); + unsigned size = this->blkSize; + char result_buffer[size + 1]; + size_t bytes_read = query_in_memory(decompressed_data, h_addr, result_buffer, size); + std::memcpy(victim->data + offset, result_buffer, size); + victim->setWhenReady(curTick()); + } + else if(myvalid != '1') + { + break; + } + } + file.close(); +} + + +std::vector +BaseTags::decompress_gz_to_memory(const std::string& gz_path) { + std::vector decompressed_data; + const size_t CHUNK_SIZE = 32 * 1024; + std::vector in_buffer(CHUNK_SIZE); + std::vector out_buffer(CHUNK_SIZE * 2); + std::ifstream gz_file(gz_path, std::ios_base::binary); + if (!gz_file.is_open()) { + throw std::runtime_error("无法打开文件: " + gz_path); + } + z_stream strm; + strm.zalloc = Z_NULL; + strm.zfree = Z_NULL; + strm.opaque = Z_NULL; + int ret = inflateInit2(&strm, MAX_WBITS | 16); + if (ret != Z_OK) { + throw std::runtime_error("inflateInit2 失败: " + std::to_string(ret)); + } + + while (true) { + gz_file.read(in_buffer.data(), in_buffer.size()); + std::streamsize bytes_read = gz_file.gcount(); + + strm.avail_in = static_cast(bytes_read); + strm.next_in = reinterpret_cast(in_buffer.data()); + + if (strm.avail_in == 0 && strm.avail_out == 0) { + break; + } + + do { + strm.avail_out = static_cast(out_buffer.size()); + strm.next_out = reinterpret_cast(out_buffer.data()); + + ret = inflate(&strm, Z_NO_FLUSH); + + if (ret == Z_STREAM_ERROR) { + inflateEnd(&strm); + gz_file.close(); + throw std::runtime_error("inflate 失败: " + std::to_string(ret)); + } + + size_t bytes_decompressed = out_buffer.size() - strm.avail_out; + if (bytes_decompressed > 0) { + decompressed_data.insert(decompressed_data.end(), + out_buffer.begin(), + out_buffer.begin() + bytes_decompressed); + } + + } while (strm.avail_out == 0); + + if (bytes_read == 0) { + break; + } + } + + if (ret != Z_STREAM_END) { + inflateEnd(&strm); + gz_file.close(); + throw std::runtime_error("解压未正常结束,可能是文件损坏。zlib 返回码: " + std::to_string(ret)); + } + + inflateEnd(&strm); + gz_file.close(); + std::cout << "解压完成!" << std::endl; + return decompressed_data; +} +size_t +BaseTags::query_in_memory(const std::vector& data, + uint64_t target_address, + char* result, + size_t max_result_length) { + if (max_result_length == 0 || result == nullptr) { + return 0; + } + + if (target_address >= data.size()) { + throw std::out_of_range("目标地址 0x" + std::to_string(target_address) + " 超出解压后数据范围。"); + } + + size_t bytes_to_copy = std::min(max_result_length, data.size() - static_cast(target_address)); + + std::memcpy(result, data.data() + target_address, bytes_to_copy); + + return bytes_to_copy; +} + } // namespace gem5 diff --git a/src/mem/cache/tags/base.hh b/src/mem/cache/tags/base.hh index 4e411f7206..bae59cbd45 100644 --- a/src/mem/cache/tags/base.hh +++ b/src/mem/cache/tags/base.hh @@ -207,6 +207,17 @@ class BaseTags : public ClockedObject */ virtual ReplaceableEntry* findBlockBySetAndWay(int set, int way) const; + + // memtrace + void warmupState(const std::string &pmem_file,const std::string &trace_file); + std::vector decompress_gz_to_memory(const std::string &gz_path); + size_t query_in_memory(const std::vector& data, + uint64_t target_address, + char* result, + size_t max_result_length) ; + virtual void updateRp(CacheBlk* blk,int rank) = 0; + + /** * Align an address to the block size. * @param addr the address to align. diff --git a/src/mem/cache/tags/base_set_assoc.hh b/src/mem/cache/tags/base_set_assoc.hh index 44061eca3d..bd89ec84c9 100644 --- a/src/mem/cache/tags/base_set_assoc.hh +++ b/src/mem/cache/tags/base_set_assoc.hh @@ -187,6 +187,15 @@ class BaseSetAssoc : public BaseTags return victim; } + + +// for replacement data + void updateRp(CacheBlk* blk,int priority) override + { + replacementPolicy->reset4memtrace(blk->replacementData,priority); + } + + /** * Insert the new block into the cache and update replacement data. * diff --git a/src/mem/cache/tags/fa_lru.hh b/src/mem/cache/tags/fa_lru.hh index 0f0c717f33..d00973000a 100644 --- a/src/mem/cache/tags/fa_lru.hh +++ b/src/mem/cache/tags/fa_lru.hh @@ -230,6 +230,23 @@ class FALRU : public BaseTags */ void insertBlock(const PacketPtr pkt, CacheBlk *blk) override; + // for replacement data + void updateRp(CacheBlk* blk,int priority) override + { + FALRUBlk* falruBlk = static_cast(blk); + + // Make sure block is not present in the cache + assert(falruBlk->inCachesMask == 0); + + // New block is the MRU + moveToHead(falruBlk); + + // Insert new block in the hash table + tagHash[std::make_pair(blk->getTag(), blk->isSecure())] = falruBlk; + + } + + void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override; /** diff --git a/src/mem/cache/tags/indexing_policies/base.cc b/src/mem/cache/tags/indexing_policies/base.cc index 8e30ace3b7..e9af7595e3 100644 --- a/src/mem/cache/tags/indexing_policies/base.cc +++ b/src/mem/cache/tags/indexing_policies/base.cc @@ -104,4 +104,11 @@ BaseIndexingPolicy::extractTag(const Addr addr) const return (addr >> tagShift); } + +uint32_t +BaseIndexingPolicy::myextractSet(const Addr addr) const +{ + return (addr >> setShift) & setMask; +} + } // namespace gem5 diff --git a/src/mem/cache/tags/indexing_policies/base.hh b/src/mem/cache/tags/indexing_policies/base.hh index 16eecc4a80..508b94a71f 100644 --- a/src/mem/cache/tags/indexing_policies/base.hh +++ b/src/mem/cache/tags/indexing_policies/base.hh @@ -125,6 +125,18 @@ class BaseIndexingPolicy : public SimObject */ void setEntry(ReplaceableEntry* entry, const uint64_t index); + // memtrace + virtual uint32_t myextractSet(const Addr addr) const; + int getAssoc(){ return assoc; } + uint32_t getnumSets() + { + return numSets; + } + std::vector> getsets() + { + return sets; + } + /** * Get an entry based on its set and way. All entries must have been set * already before calling this function. diff --git a/src/mem/cache/tags/indexing_policies/skewed_associative.cc b/src/mem/cache/tags/indexing_policies/skewed_associative.cc index 00af3cda5d..8c37835e7c 100644 --- a/src/mem/cache/tags/indexing_policies/skewed_associative.cc +++ b/src/mem/cache/tags/indexing_policies/skewed_associative.cc @@ -210,6 +210,7 @@ SkewedAssociative::regenerateAddr(const Addr tag, std::vector SkewedAssociative::getPossibleEntries(const Addr addr) const { + //std::cout << "lixu :getPossibleEntries skewed_assoc"< entries; // Parse all ways diff --git a/src/mem/cache/tags/sector_tags.cc b/src/mem/cache/tags/sector_tags.cc index cb121ebd9a..b5cc005601 100644 --- a/src/mem/cache/tags/sector_tags.cc +++ b/src/mem/cache/tags/sector_tags.cc @@ -200,6 +200,14 @@ SectorTags::insertBlock(const PacketPtr pkt, CacheBlk *blk) BaseTags::insertBlock(pkt, blk); } + +void +SectorTags::updateRp(CacheBlk *blk,int priority) +{ + replacementPolicy->reset4memtrace(blk->replacementData,priority); +} + + void SectorTags::moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) { diff --git a/src/mem/cache/tags/sector_tags.hh b/src/mem/cache/tags/sector_tags.hh index c64621213d..468ff8de51 100644 --- a/src/mem/cache/tags/sector_tags.hh +++ b/src/mem/cache/tags/sector_tags.hh @@ -153,6 +153,9 @@ class SectorTags : public BaseTags */ void insertBlock(const PacketPtr pkt, CacheBlk *blk) override; + // memtrace + void updateRp(CacheBlk *blk,int priority) override; + void moveBlock(CacheBlk *src_blk, CacheBlk *dest_blk) override; /** diff --git a/src/mem/physical.cc b/src/mem/physical.cc index 94a93ba4cd..20df6d6c12 100644 --- a/src/mem/physical.cc +++ b/src/mem/physical.cc @@ -89,6 +89,8 @@ PhysicalMemory::PhysicalMemory(const std::string& _name, const std::string& shared_backstore, bool enable_h_gcpt, bool restore_from_gcpt, + bool restore_from_memtrace, + const std::string& memtrace_file, const std::string& gcpt_restorer_path, const std::string& gcpt_path, bool map_to_raw_cpt, @@ -101,6 +103,8 @@ PhysicalMemory::PhysicalMemory(const std::string& _name, pageSize(sysconf(_SC_PAGE_SIZE)), enableHGcpt(enable_h_gcpt), restoreFromXiangshanCpt(restore_from_gcpt), + restoreFromMemtrace(restore_from_memtrace), + memtraceFile(memtrace_file), gCptRestorerPath(gcpt_restorer_path), xsCptPath(gcpt_path), mapToRawCpt(map_to_raw_cpt), gcptRestorerSizeLimit(gcpt_restorer_size_limit), enableDedup(enable_mem_dedup), @@ -702,7 +706,9 @@ PhysicalMemory::overrideGCptRestorer(unsigned store_id) { uint8_t* pmem = backingStore[store_id].pmem; if (enableHGcpt) + { return; + } if (restoreFromXiangshanCpt && !gCptRestorerPath.empty()) { if (gCptRestorerPath == "None") { warn("gcpt restore is None\n"); diff --git a/src/mem/physical.hh b/src/mem/physical.hh index ea87d37599..404db29536 100644 --- a/src/mem/physical.hh +++ b/src/mem/physical.hh @@ -177,6 +177,8 @@ class PhysicalMemory : public Serializable bool enableHGcpt; // Restore from Xiangshan checkpoint image bool restoreFromXiangshanCpt; + bool restoreFromMemtrace; + std::string memtraceFile; std::string gCptRestorerPath; @@ -221,6 +223,8 @@ class PhysicalMemory : public Serializable const std::string& shared_backstore, bool enable_h_gcpt, bool restore_from_gcpt, + bool restore_from_memtrace, + const std::string& memtrace_file, const std::string& gcpt_restorer_path, const std::string&gcpt_path, bool map_to_raw_cpt, diff --git a/src/mem/snoop_filter.cc b/src/mem/snoop_filter.cc index fc4648cb4f..d1fa146dda 100644 --- a/src/mem/snoop_filter.cc +++ b/src/mem/snoop_filter.cc @@ -132,6 +132,12 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const ResponsePort& // to the CPU, already -> the response will not be seen by this // filter -> we do not need to keep the in-flight request, but make // sure that we know that that cluster has a copy + SimObject * temp_simobject =find("system"); + System * temp_system = dynamic_cast (temp_simobject); + if(temp_system->restore_from_memtrace_enabled() == true) + { + sf_item.holder |= req_port; + } panic_if((sf_item.holder & req_port).none(), "Need to hold the value!"); DPRINTF(SnoopFilter, @@ -141,9 +147,19 @@ SnoopFilter::lookupRequest(const Packet* cpkt, const ResponsePort& } else { // if (!cpkt->needsResponse()) assert(cpkt->isEviction()); // make sure that the sender actually had the line - panic_if((sf_item.holder & req_port).none(), "requestor %x is not a " \ - "holder :( SF value %x.%x\n", req_port, - sf_item.requested, sf_item.holder); + SimObject * temp_simobject =find("system"); + System * temp_system = dynamic_cast (temp_simobject); + if(temp_system->restore_from_memtrace_enabled() == true) + { + panic_if(!sf_item.holder.none() && (sf_item.holder & req_port).none(), "requestor %x is not a " \ + "holder :( SF value %x.%x\n", req_port, + sf_item.requested, sf_item.holder); + } + else{ + panic_if((sf_item.holder & req_port).none(), "requestor %x is not a " \ + "holder :( SF value %x.%x\n", req_port, + sf_item.requested, sf_item.holder); + } // CleanEvicts and Writebacks -> the sender and all caches above // it may not have the line anymore. if (!cpkt->isBlockCached()) { diff --git a/src/python/m5/SimObject.py b/src/python/m5/SimObject.py index d855775272..9b7f741fd8 100644 --- a/src/python/m5/SimObject.py +++ b/src/python/m5/SimObject.py @@ -607,6 +607,12 @@ def loadState(self, cp): """Load SimObject state from a checkpoint""" pass + # memtrace + @cxxMethod + def warmupState(self, cache_restore_dir,cpt_dir): + """restore L3 microarchitecture state from a memtrace""" + pass + # Returns a dict of all the option strings that can be # generated as command line options for this simobject instance # by tracing all reachable params in the top level instance and diff --git a/src/python/m5/simulate.py b/src/python/m5/simulate.py index 3194218095..b536158762 100644 --- a/src/python/m5/simulate.py +++ b/src/python/m5/simulate.py @@ -66,7 +66,7 @@ # The final call to instantiate the SimObject graph and initialize the # system. -def instantiate(ckpt_dir=None): +def instantiate(pmem_file_path,mem_trace_file,ckpt_dir=None): global _instantiated from m5 import options @@ -89,7 +89,6 @@ def instantiate(ckpt_dir=None): # Unproxy in sorted order for determinism for obj in root.descendants(): obj.unproxyParams() - if options.dump_config: ini_file = open(os.path.join(options.outdir, options.dump_config), 'w') # Print ini sections in sorted order for easier diffing @@ -148,6 +147,9 @@ def instantiate(ckpt_dir=None): for obj in root.descendants(): obj.loadState(ckpt) else: for obj in root.descendants(): obj.initState() + for obj in root.descendants(): + if str(obj) == "system.l3.tags" and pmem_file_path is not None and mem_trace_file is not None: + obj.warmupState(pmem_file_path,mem_trace_file) # Check to see if any of the stat events are in the past after resuming from # a checkpoint, If so, this call will shift them to be at a valid time. diff --git a/src/sim/System.py b/src/sim/System.py index 6c11bd195d..ee38918687 100644 --- a/src/sim/System.py +++ b/src/sim/System.py @@ -132,6 +132,8 @@ class System(SimObject): # Checkpoint image file for Xiangshan enable_h_gcpt = Param.Bool(False, "Restoring set for Xiangshan h-gcpt") restore_from_gcpt = Param.Bool(False, "Restoring from Xiangshan gcpt") + restore_from_memtrace = Param.Bool(False, "Restoring cache from memtrace") + memtrace_file = Param.String("", "Memtrace file") gcpt_file = Param.String("", "Xiangshan checkpoint image file") map_to_raw_cpt = Param.Bool(False, "Map physical memory to raw cpt with mmap") gcpt_restorer_file = Param.String("", "GCPT restorer image file") diff --git a/src/sim/eventq.hh b/src/sim/eventq.hh index a7226ffead..28e35696d1 100644 --- a/src/sim/eventq.hh +++ b/src/sim/eventq.hh @@ -766,7 +766,6 @@ class EventQueue assert(when >= getCurTick()); assert(!event->scheduled()); assert(event->initialized()); - event->setWhen(when, this); // The check below is to make sure of two things diff --git a/src/sim/globals.cc b/src/sim/globals.cc index f2962d96c8..c346809fdc 100644 --- a/src/sim/globals.cc +++ b/src/sim/globals.cc @@ -123,4 +123,9 @@ Globals::unserialize(CheckpointIn &cp) } } +void +Globals::memtrace_init() +{ + unserializedCurTick = 100; +} } // namespace gem5 diff --git a/src/sim/globals.hh b/src/sim/globals.hh index 30b0b5f9ef..8f7798bdae 100644 --- a/src/sim/globals.hh +++ b/src/sim/globals.hh @@ -59,6 +59,7 @@ class Globals : public Serializable void serialize(CheckpointOut &cp) const override; void unserialize(CheckpointIn &cp) override; + void memtrace_init(); Tick unserializedCurTick; }; diff --git a/src/sim/root.cc b/src/sim/root.cc index e53f09d883..68cebb146a 100644 --- a/src/sim/root.cc +++ b/src/sim/root.cc @@ -217,6 +217,15 @@ Root::unserialize(CheckpointIn &cp) mainEventQueue[i]->setCurTick(globals.unserializedCurTick); } +void +Root::memtrace_init() +{ + globals.memtrace_init(); + + for (uint32_t i = 0; i < numMainEventQueues; ++i) + mainEventQueue[i]->setCurTick(globals.unserializedCurTick); +} + bool FullSystem; unsigned int FullSystemInt; diff --git a/src/sim/root.hh b/src/sim/root.hh index ce2245f875..58c8f132a9 100644 --- a/src/sim/root.hh +++ b/src/sim/root.hh @@ -59,6 +59,8 @@ #include "sim/globals.hh" #include "sim/sim_object.hh" + +#include "sim/system.hh" namespace gem5 { @@ -81,6 +83,16 @@ class Root : public SimObject EventFunctionWrapper syncEvent; public: + void initState() override + { + SimObject * temp_simobject =find("system"); + System * temp_system = dynamic_cast (temp_simobject); + if(temp_system->restore_from_memtrace_enabled() == true) + { + memtrace_init(); + } + } + void memtrace_init(); /** * Use this function to get a pointer to the single Root object in the * simulation. This function asserts that such an object has actual been diff --git a/src/sim/sim_object.hh b/src/sim/sim_object.hh index c2c5d4d29b..20ed3db5b1 100644 --- a/src/sim/sim_object.hh +++ b/src/sim/sim_object.hh @@ -217,6 +217,17 @@ class SimObject : public EventManager, public Serializable, public Drainable, */ virtual void initState(); + + virtual void warmupState(const std::string &pmem_file,const std::string &trace_file){} + virtual int getcachesize() + { + return 0; + } + virtual int getcacheassoc() + { + return 0; + } + /** * Register probe points for this object. * diff --git a/src/sim/simulate.cc b/src/sim/simulate.cc index c5d07942ef..5708cb8775 100644 --- a/src/sim/simulate.cc +++ b/src/sim/simulate.cc @@ -192,7 +192,6 @@ simulate(Tick num_cycles) curTick() + num_cycles : MaxTick; inform("Entering event queue @ %d. Starting simulation...\n", curTick()); - if (!simulatorThreads) simulatorThreads.reset(new SimulatorThreads(numMainEventQueues)); @@ -202,22 +201,18 @@ simulate(Tick num_cycles) "simulate() limit reached", 0); } simulate_limit_event->reschedule(exit_tick); - if (numMainEventQueues > 1) { fatal_if(simQuantum == 0, "Quantum for multi-eventq simulation not specified"); - quantum_event.reset( new GlobalSyncEvent(curTick() + simQuantum, simQuantum, EventBase::Progress_Event_Pri, 0)); inParallelMode = true; } - simulatorThreads->runUntilLocalExit(); Event *local_event = doSimLoop(mainEventQueue[0]); assert(local_event); - inParallelMode = false; // locate the global exit event and return it to Python diff --git a/src/sim/system.cc b/src/sim/system.cc index 7bc4ec37ce..b6cea54da5 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -186,9 +186,10 @@ System::System(const Params &p) enableDifftest(p.enable_difftest), enableMemDedup(p.enable_mem_dedup), physmem(name() + ".physmem", p.memories, p.mmap_using_noreserve, - p.shared_backstore, p.enable_h_gcpt, p.restore_from_gcpt, p.gcpt_restorer_file, + p.shared_backstore, p.enable_h_gcpt, p.restore_from_gcpt, p.restore_from_memtrace, p.memtrace_file, p.gcpt_restorer_file, p.gcpt_file, p.map_to_raw_cpt, p.auto_unlink_shared_backstore, p.gcpt_restorer_size_limit, &dedupMemManager, p.enable_mem_dedup), + restore_from_memtrace(p.restore_from_memtrace), ShadowRomRanges(p.shadow_rom_ranges.begin(), p.shadow_rom_ranges.end()), memoryMode(p.mem_mode), @@ -201,6 +202,7 @@ System::System(const Params &p) redirectPaths(p.redirect_paths), xiangshanSystem(p.xiangshan_system) { + std::cout << "lixu System "<< p.restore_from_memtrace <setSystem(this); diff --git a/src/sim/system.hh b/src/sim/system.hh index db49b66926..0dfa04bbdf 100644 --- a/src/sim/system.hh +++ b/src/sim/system.hh @@ -430,6 +430,8 @@ class System : public SimObject, public PCEventScope memory::PhysicalMemory physmem; + bool restore_from_memtrace; + AddrRangeList ShadowRomRanges; enums::MemoryMode memoryMode; @@ -457,6 +459,8 @@ class System : public SimObject, public PCEventScope public: + + bool restore_from_memtrace_enabled() const { return restore_from_memtrace; } /** * Request an id used to create a request object in the system. All objects * that intend to issues requests into the memory system must request an id From ba4100769eb1e34e7118ef58583e0304223ed9e3 Mon Sep 17 00:00:00 2001 From: greenfool Date: Thu, 5 Feb 2026 14:50:44 +0800 Subject: [PATCH 2/3] style: delete debug info --- src/mem/cache/tags/indexing_policies/skewed_associative.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mem/cache/tags/indexing_policies/skewed_associative.cc b/src/mem/cache/tags/indexing_policies/skewed_associative.cc index 8c37835e7c..00af3cda5d 100644 --- a/src/mem/cache/tags/indexing_policies/skewed_associative.cc +++ b/src/mem/cache/tags/indexing_policies/skewed_associative.cc @@ -210,7 +210,6 @@ SkewedAssociative::regenerateAddr(const Addr tag, std::vector SkewedAssociative::getPossibleEntries(const Addr addr) const { - //std::cout << "lixu :getPossibleEntries skewed_assoc"< entries; // Parse all ways From c81f6ec5f1f90b9db45af21fc0ade8f8ea9bd240 Mon Sep 17 00:00:00 2001 From: greenfool Date: Thu, 5 Feb 2026 14:53:43 +0800 Subject: [PATCH 3/3] style: Remove debug output from system constructor Remove debug output for lixu System initialization --- src/sim/system.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/src/sim/system.cc b/src/sim/system.cc index b6cea54da5..8f6f6a36f7 100644 --- a/src/sim/system.cc +++ b/src/sim/system.cc @@ -202,7 +202,6 @@ System::System(const Params &p) redirectPaths(p.redirect_paths), xiangshanSystem(p.xiangshan_system) { - std::cout << "lixu System "<< p.restore_from_memtrace <setSystem(this);