Re: [gem5-users] How to flush all dirty blk from Cache to Memory
I tried to increase the writeBuffer size??and my code works like what I want. It put all dirty cache-blk to writebuffer and will send writeBackDirty to memory controller.But it crash after perfroming several times flush all cache-blk. The error report is below. panic: panic condition (sf_item.holder req_port).none() occurred: requester 0010 is not a holder :( SF value . It seems like I flush some cache-blk that shouldn??t be flush. My code : BaseCache::recvTimingReq(pkt){//some instr will trigger this code section if(trigger){ wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts); //doWritebacks(wb_pkts, clockEdge(lat+forwardLatency)); while(!wb_pkts.empty()){ PacketPtr wbPkt = wb_pkts.front(); allocateWriteBuffer(wbPkt, clockEdge(lat + forwardLatency)); wb_pkts.pop_front(); } } bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . } BaseCache::my_memWriteback(PacketList wb_pkts) { int count = 0; tags-forEachBlk([this,count,wb_pkts](CacheBlk blk) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk blk,PacketList writebacks) { if (blk.isDirty()) { assert(blk.isValid()); /* do make request in writebackBlk() * RequestPtr request = std::make_shared( regenerateBlkAddr(blk), blkSize, 0, Request::funcMasterId); request-taskId(blk.task_id); if (blk.isSecure()) { request-setFlags(Request::SECURE); } //will not send request to memory controller when MemCmd::WriteClean PacketPtr packet = new Packet(request, MemCmd::WriteClean); packet-allocate(); std::memcpy(packet-getPtr, blk.data, blkSize); * */ PacketPtr packet = writebackBlk(blk); //invalidateBlock(blk) writebacks.push_back(packet); //blk.status = ~BlkDirty;} } And I am confuse on what is the difference among MemCmd::WritebackDirty,MemCmd::WritebackClean,and MemCmd::WriteClean.Because I run a process which execute _mm_clflush and the gem5 behavior is 4658583000: system.l2cache: sendMSHRQueuePacket: MSHR CleanInvalidReq [448760:448760] PoC 4658583000: system.l2cache: Create WriteClean [448740:44877f] PoC writable: 1, dirty: 1 4658583000: global: handleSnoop for WriteClean [448740:44877f] ES PoC 4658583001: system.l2cache: sendWriteQueuePacket: write WriteClean [448740:44877f] PoC 4658584000: system.l2cache: sendWriteQueuePacket: write WriteClean [448740:44877f] PoC 4658584000: system.mem_ctrl: recvTimingReq: request WriteClean addr 4491072 size 64 4658584000: system.mem_ctrl: Write queue limit 64, current size 3, entries needed 1 4658584000: system.mem_ctrl: Address: 4491072 Rank 0 Bank 4 Row 34 4658584000: system.mem_ctrl: Adding to write queue 4658584000: system.mem_ctrl: Responding to Address 4491072.. 4658584000: system.mem_ctrl: Done 4658591000: system.l2cache: recvTimingResp: Handling response CleanInvalidResp [448760:448760] PoC So I try to make a WriteClean for each dirty cache-blk "PacketPtr packet = new Packet(request, MemCmd::WriteClean); " But it will not send req to memory controller which make me confused. Instead WritebackDirty will send req to memory controller.___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users
Re: [gem5-users] How to flush all dirty blk from Cache to Memory
Hello, doWritebacks will only populate the write queue, which would then be emptied when possible. Since you are evicting a multitude of blocks simultaneously, the queue will become full and the assertion will trigger. You will either have to implement a specialized version of doWritebacks() for your use-case, or simply assume that these writebacks are done atomically and bypass the write queue with a call to doWritebacksAtomic(). Still, the second solution would probably not be that simple, because you will likely run into the same multi-eviction issue described in the last messages of https://gem5-review.googlesource.com/c/public/gem5/+/18209 Regards, Daniel Em quinta-feira, 16 de abril de 2020 16:43:12 GMT+2, 周泰宇 <645505...@qq.com> escreveu: Hi,DanielThanks for you reply. I’ve try to perform doWritebacks(..) before access(..). But It still can’t work for me. Cache will be blocked because writeBuffer.isFull() and finally gem5 will report that freeList has no space. Error report:gem5.opt: build/X86/mem/cache/write_queue.cc:64: WriteQueueEntry* WriteQueue::allocate(Addr, unsigned int, PacketPtr, Tick, Counter): Assertion `!freeList.empty()' failed. My new code is below BaseCache::recvTimingReq(pkt){ if(trigger){ //some instr will trigger this code section wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts);+ doWritebacks(wb_pkts, clockEdge(lat+forwardLatency)); } bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . } int BaseCache::my_memWriteback(PacketList _pkts) { int count = 0; tags->forEachBlk([this,,_pkts](CacheBlk ) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk ,PacketList ) { if (blk.isDirty()) { assert(blk.isValid()); RequestPtr request = std::make_shared( regenerateBlkAddr(), blkSize, 0, Request::funcMasterId); request->taskId(blk.task_id); if (blk.isSecure()) { request->setFlags(Request::SECURE); } - //PacketPtr packet = new Packet(request, MemCmd::WriteReq); + PacketPtr packet = new Packet(request, MemCmd::WriteReq);//should only see writes or clean evicts in allocateWriteBufferpacket->allocate(); std::memcpy(packet->getPtr, blk.data, blkSize); // packet->dataStatic(blk.data); writebacks.push_back(packet); blk.status &= ~BlkDirty; } } ___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users
Re: [gem5-users] How to flush all dirty blk from Cache to Memory
On 4/15/2020 1:13 PM, 周泰宇 wrote: I don’t know why the format so garbled. So I post my code again. |BaseCache::recvTimingReq(pkt){ wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts); bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . } int BaseCache::my_memWriteback(PacketList _pkts) { int count = 0; tags->forEachBlk([this,,_pkts](CacheBlk ) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk ,PacketList ) { if (blk.isDirty()) { assert(blk.isValid()); RequestPtr request = std::make_shared( regenerateBlkAddr(), blkSize, 0, Request::funcMasterId); request->taskId(blk.task_id); if (blk.isSecure()) { request->setFlags(Request::SECURE); } PacketPtr packet = new Packet(request, MemCmd::WriteReq); packet->allocate(); std::memcpy(packet->getPtr, blk.data, blkSize); // packet->dataStatic(blk.data); writebacks.push_back(packet); blk.status &= ~BlkDirty; } }| Silly email tool wrecked the formatting! I just wanted to say, good for you in including that last line. I implemented something like this (in an older version, etc., so I don't think it useful to share the code here) and forgot that line. It led to a nasty, rarely expressed, bug, where the line got written back to memory again later, zapping stuff that had been written by another processor. (The setup was one with intentionally non-(hardware)-coherent caches, and this broke the software managed coherence.) Best wishes - EM ___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users
Re: [gem5-users] How to flush all dirty blk from Cache to Memory
Hello, I believe what might be missing is a call to perform the writebacks (doWritebacks(wb_pkts, clockEdge(lat+forwardLatency))) before any other cache operations (e.g., access()). This will make sure that the coherence is kept, and you will not mistakenly use stale data. Regards, Daniel Em quarta-feira, 15 de abril de 2020 19:13:16 GMT+2, 周泰宇 <645505...@qq.com> escreveu: I don’t know why the format so garbled. So I post my code again. BaseCache::recvTimingReq(pkt){ wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts); bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . } int BaseCache::my_memWriteback(PacketList _pkts) { int count = 0; tags->forEachBlk([this,,_pkts](CacheBlk ) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk ,PacketList ) { if (blk.isDirty()) { assert(blk.isValid()); RequestPtr request = std::make_shared( regenerateBlkAddr(), blkSize, 0, Request::funcMasterId); request->taskId(blk.task_id); if (blk.isSecure()) { request->setFlags(Request::SECURE); } PacketPtr packet = new Packet(request, MemCmd::WriteReq); packet->allocate(); std::memcpy(packet->getPtr, blk.data, blkSize); // packet->dataStatic(blk.data); writebacks.push_back(packet); blk.status &= ~BlkDirty; } } ___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users ___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users
Re: [gem5-users] How to flush all dirty blk from Cache to Memory
I don’t know why the format so garbled. So I post my code again. BaseCache::recvTimingReq(pkt){ wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts); bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . } int BaseCache::my_memWriteback(PacketList _pkts) { int count = 0; tags->forEachBlk([this,,_pkts](CacheBlk ) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk ,PacketList ) { if (blk.isDirty()) { assert(blk.isValid()); RequestPtr request = std::make_shared( regenerateBlkAddr(), blkSize, 0, Request::funcMasterId); request->taskId(blk.task_id); if (blk.isSecure()) { request->setFlags(Request::SECURE); } PacketPtr packet = new Packet(request, MemCmd::WriteReq); packet->allocate(); std::memcpy(packet->getPtr, blk.data, blkSize); // packet->dataStatic(blk.data); writebacks.push_back(packet); blk.status &= ~BlkDirty; } } ___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users
[gem5-users] How to flush all dirty blk from Cache to Memory
Hi guys! I am trying to expand some functions to flush all dirty blk form Cache to memory.My plan is below : In BaseCache::recvTimingReq function.I use wb_pkts to store all writeback pkt.The my_memWriteback will traverse all cacheblk and return the number of dirty.For each blk it will call my_writebackVisitor to make new paket and put it into wb_pkts.But I meet bug and don't know what's going on. The bug says that "panic: Tried to read unmapped address 0x8.PC: 0x400ffa, Instr: MOV_R_M : ld rax, DS:[rax + 0x8]PacketList wb_pkts". And I run with --debug-flags=DRAM,Cache will see that cache never sends paket to memory controller. My expanding code shows below wb_pkts.clear(); dirty_blk_count = my_memWriteback(wb_pkts); bool satisfied = false; { PacketList writebacks; satisfied = access(pkt, blk, lat, writebacks); . int BaseCache::my_memWriteback(PacketList wb_pkts) { int count = 0; tags-forEachBlk([this,count,wb_pkts](CacheBlk blk) mutable{ if(blk.isDirty()){ if(blk.isValid()){ count++; } } my_writebackVisitor(blk,wb_pkts); }); //printf("NmemWriteback count:%d\n",count); return count; } BaseCache::my_writebackVisitor(CacheBlk blk,PacketList writebacks) { if (blk.isDirty()) { assert(blk.isValid()); RequestPtr request = std::make_shared___ gem5-users mailing list gem5-users@gem5.org http://m5sim.org/cgi-bin/mailman/listinfo/gem5-users