From: Tiago Mück Date: Wed, 15 Apr 2020 23:40:02 +0000 (-0500) Subject: mem-ruby: Deallocating unused entries in MOESI_CMP dir X-Git-Tag: v20.1.0.0~663 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=852198cd7b3be2598ba0f31a6ca1cfa424b11a10;p=gem5.git mem-ruby: Deallocating unused entries in MOESI_CMP dir Invalid entries are never removed from the directory the Directory controller. This patch fixes this by deallocating the entries when they become invalid. Change-Id: I616686a78c5eddb7748192bf94bb691a4f158cbc Signed-off-by: Tiago Mück Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/27847 Maintainer: Jason Lowe-Power Tested-by: kokoro Reviewed-by: Pouya Fotouhi --- diff --git a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm index 7faa8e035..e8d086335 100644 --- a/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm +++ b/src/mem/ruby/protocol/MOESI_CMP_directory-dir.sm @@ -138,70 +138,97 @@ machine(MachineType:Directory, "Directory protocol") Entry getDirectoryEntry(Addr addr), return_by_pointer="yes" { Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); + assert(is_valid(dir_entry)); + return dir_entry; + } - if (is_valid(dir_entry)) { - return dir_entry; - } - - dir_entry := static_cast(Entry, "pointer", + Entry allocateDirectoryEntry(Addr addr), return_by_pointer="yes" { + Entry dir_entry := static_cast(Entry, "pointer", directory.allocate(addr, new Entry)); return dir_entry; } + void deallocateDirectoryEntry(Addr addr) { + // Always going to transition from a valid state to I when deallocating + // Owners and shares must be clear + assert(getDirectoryEntry(addr).DirectoryState != State:I); + assert(getDirectoryEntry(addr).Owner.count() == 0); + assert(getDirectoryEntry(addr).Sharers.count() == 0); + + directory.deallocate(addr); + + // disable coherence checker + // sequencer.checkCoherence(addr); + } + State getState(TBE tbe, Addr addr) { - return getDirectoryEntry(addr).DirectoryState; + Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); + if (is_valid(dir_entry)) { + return dir_entry.DirectoryState; + } + else { + return State:I; + } } void setState(TBE tbe, Addr addr, State state) { if (directory.isPresent(addr)) { - if (state == State:I) { - assert(getDirectoryEntry(addr).Owner.count() == 0); - assert(getDirectoryEntry(addr).Sharers.count() == 0); - } + Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); - if (state == State:S) { - assert(getDirectoryEntry(addr).Owner.count() == 0); - } + if (is_valid(dir_entry)) { - if (state == State:O) { - assert(getDirectoryEntry(addr).Owner.count() == 1); - assert(getDirectoryEntry(addr).Sharers.isSuperset(getDirectoryEntry(addr).Owner) == false); - } + assert(state != State:I); - if (state == State:M) { - assert(getDirectoryEntry(addr).Owner.count() == 1); - assert(getDirectoryEntry(addr).Sharers.count() == 0); - } + if (state == State:S) { + assert(dir_entry.Owner.count() == 0); + } - if ((state != State:SS) && (state != State:OO)) { - assert(getDirectoryEntry(addr).WaitingUnblocks == 0); - } + if (state == State:O) { + assert(dir_entry.Owner.count() == 1); + assert(dir_entry.Sharers.isSuperset(dir_entry.Owner) == false); + } - if ( (getDirectoryEntry(addr).DirectoryState != State:I) && (state == State:I) ) { - getDirectoryEntry(addr).DirectoryState := state; - // disable coherence checker - // sequencer.checkCoherence(addr); - } - else { - getDirectoryEntry(addr).DirectoryState := state; + if (state == State:M) { + assert(dir_entry.Owner.count() == 1); + assert(dir_entry.Sharers.count() == 0); + } + + if ((state != State:SS) && (state != State:OO)) { + assert(dir_entry.WaitingUnblocks == 0); + } + + dir_entry.DirectoryState := state; + + } else { + assert(state == State:I); } } } AccessPermission getAccessPermission(Addr addr) { if (directory.isPresent(addr)) { - DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState)); - return Directory_State_to_permission(getDirectoryEntry(addr).DirectoryState); + Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); + if (is_valid(dir_entry)) { + DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(dir_entry.DirectoryState)); + return Directory_State_to_permission(dir_entry.DirectoryState); + } else { + DPRINTF(RubySlicc, "%s\n", Directory_State_to_permission(State:I)); + return Directory_State_to_permission(State:I); + } } - DPRINTF(RubySlicc, "AccessPermission_NotPresent\n"); return AccessPermission:NotPresent; } void setAccessPermission(Addr addr, State state) { if (directory.isPresent(addr)) { - getDirectoryEntry(addr).changePermission(Directory_State_to_permission(state)); + Entry dir_entry := static_cast(Entry, "pointer", directory[addr]); + if (is_valid(dir_entry)) { + dir_entry.changePermission(Directory_State_to_permission(state)); + } else { + assert(state == State:I); + } } } @@ -319,6 +346,14 @@ machine(MachineType:Directory, "Directory protocol") // Actions + action(allocDirEntry, "alloc", desc="Allocate directory entry") { + allocateDirectoryEntry(address); + } + + action(deallocDirEntry, "dealloc", desc="Deallocate directory entry") { + deallocateDirectoryEntry(address); + } + action(a_sendWriteBackAck, "a", desc="Send writeback ack to requestor") { peek(requestQueue_in, RequestMsg) { enqueue(responseNetwork_out, ResponseMsg, directory_latency) { @@ -600,16 +635,19 @@ machine(MachineType:Directory, "Directory protocol") // TRANSITIONS transition(I, GETX, MM) { + allocDirEntry; qf_queueMemoryFetchRequest; i_popIncomingRequestQueue; } transition(I, DMA_READ, XI_M) { + allocDirEntry; qf_queueMemoryFetchRequest; i_popIncomingRequestQueue; } transition(I, DMA_WRITE, XI_U) { + allocDirEntry; qw_queueMemoryWBFromDMARequest; a_sendDMAAck; // ack count may be zero i_popIncomingRequestQueue; @@ -617,12 +655,14 @@ machine(MachineType:Directory, "Directory protocol") transition(XI_M, Memory_Data, I) { d_sendDataMsg; // ack count may be zero + deallocDirEntry; q_popMemQueue; } transition(XI_U, Exclusive_Unblock, I) { cc_clearSharers; c_clearOwner; + deallocDirEntry; j_popIncomingUnblockQueue; } @@ -647,6 +687,7 @@ machine(MachineType:Directory, "Directory protocol") } transition(I, GETS, IS) { + allocDirEntry; qf_queueMemoryFetchRequest; i_popIncomingRequestQueue; } @@ -812,6 +853,7 @@ machine(MachineType:Directory, "Directory protocol") c_clearOwner; cc_clearSharers; qw_queueMemoryWBFromCacheRequest; + deallocDirEntry; i_popIncomingRequestQueue; } @@ -846,6 +888,7 @@ machine(MachineType:Directory, "Directory protocol") transition(MI, Clean_Writeback, I) { c_clearOwner; cc_clearSharers; + deallocDirEntry; i_popIncomingRequestQueue; }