Thanks for this Shehab,

Could you compare your changes to this patchset:
https://gem5-review.googlesource.com/c/public/gem5/+/22022/1

On Thu, Apr 9, 2020 at 6:22 PM Shehab Elsayed <shehaby...@gmail.com> wrote:
>
> Hello All,
>
> I was running some experiments and I ran into a problem with ruby where a 
> functional read was failing. After some investigation I found that the reason 
> was that the functional read was trying to read a line that was in a 
> MaybeStale state (no ReadOnly or ReadWrite versions).
>
> I implemented a fix which so far seems to be working fine but I am not sure 
> if there is a deeper problem that needs fixing or if my fix could present 
> future problems.
>
> I am running Full System simulations with ARM ISA and MESI_Three_Level.
>
> Here is my fix (I have marked new lines with //------NEW------//):
> Basically what this fix does is perform the functional read from the 
> controller that has the line in the MaybeStale state if no ReadOnly or 
> ReadWrite versions in any controller.
>
> bool
> RubySystem::functionalRead(PacketPtr pkt)
> {
>     Addr address(pkt->getAddr());
>     Addr line_address = makeLineAddress(address);
>
>     AccessPermission access_perm = AccessPermission_NotPresent;
>     int num_controllers = m_abs_cntrl_vec.size();
>
>     DPRINTF(RubySystem, "Functional Read request for %#x\n", address);
>
>     unsigned int num_ro = 0;
>     unsigned int num_rw = 0;
>     unsigned int num_busy = 0;
>     unsigned int num_backing_store = 0;
>     unsigned int num_invalid = 0;
>     unsigned int num_maybe_stale = 0;        //------NEW------//
>
>     // In this loop we count the number of controllers that have the given
>     // address in read only, read write and busy states.
>     for (unsigned int i = 0; i < num_controllers; ++i) {
>
>         // Ignore ATD controllers for functional reads
>         if (m_abs_cntrl_vec[i]->getType() == MachineType_ATD) {
>             continue;
>         }
>
>         access_perm = m_abs_cntrl_vec[i]-> getAccessPermission(line_address);
>         if (access_perm == AccessPermission_Read_Only)
>             num_ro++;
>         else if (access_perm == AccessPermission_Read_Write)
>             num_rw++;
>         else if (access_perm == AccessPermission_Busy)
>             num_busy++;
>         else if (access_perm == AccessPermission_Backing_Store)
>             // See RubySlicc_Exports.sm for details, but Backing_Store is 
> meant
>             // to represent blocks in memory *for Broadcast/Snooping 
> protocols*,
>             // where memory has no idea whether it has an exclusive copy of 
> data
>             // or not.
>             num_backing_store++;
>         else if (access_perm == AccessPermission_Invalid ||
>                  access_perm == AccessPermission_NotPresent)
>             num_invalid++;
>         else if (access_perm == AccessPermission_Maybe_Stale)        
> //------NEW------//
>             num_maybe_stale++;                                                
>               //------NEW------//
>     }
>
>     // This if case is meant to capture what happens in a Broadcast/Snoop
>     // protocol where the block does not exist in the cache hierarchy. You
>     // only want to read from the Backing_Store memory if there is no copy in
>     // the cache hierarchy, otherwise you want to try to read the RO or RW
>     // copies existing in the cache hierarchy (covered by the else statement).
>     // The reason is because the Backing_Store memory could easily be stale, 
> if
>     // there are copies floating around the cache hierarchy, so you want to 
> read
>     // it only if it's not in the cache hierarchy at all.
>     if (num_invalid == (num_controllers - 1) && num_backing_store == 1) {
>         DPRINTF(RubySystem, "only copy in Backing_Store memory, read from 
> it\n");
>         for (unsigned int i = 0; i < num_controllers; ++i) {
>             access_perm = 
> m_abs_cntrl_vec[i]->getAccessPermission(line_address);
>             if (access_perm == AccessPermission_Backing_Store) {
>                 m_abs_cntrl_vec[i]->functionalRead(line_address, pkt);
>                 return true;
>             }
>         }
>     } else if (num_ro > 0 || num_rw >= 1 || num_maybe_stale > 0) {            
>   //------NEW------//
>         if (num_rw > 1) {
>             // We iterate over the vector of abstract controllers, and return
>             // the first copy found. If we have more than one cache with block
>             // in writable permission, the first one found would be returned.
>             warn("More than one Abstract Controller with RW permission for "
>                  "addr: %#x on cacheline: %#x.", address, line_address);
>         }
>         // In Broadcast/Snoop protocols, this covers if you know the block
>         // exists somewhere in the caching hierarchy, then you want to read 
> any
>         // valid RO or RW block.  In directory protocols, same thing, you want
>         // to read any valid readable copy of the block.
>         DPRINTF(RubySystem, "num_busy = %d, num_ro = %d, num_rw = %d\n",
>                 num_busy, num_ro, num_rw);
>
>         // In this loop, we try to figure which controller has a read only or
>         // a read write copy of the given address. Any valid copy would 
> suffice
>         // for a functional read.
>         // Sometimes the functional read is to a line that has recently
>         // transitioned to MaybeStale state and no other controller has it in
>         // a ReadOnly or ReadWrite stat yet.
>         // For example in MESI_Three_Level a modified block in the L2 goes 
> into
>         // a MaybeStale state when requested by the L1. If the functional read
>         // occurs at that specific time when the block in L2 became MaybeStale
>         // but still hasn't made it to ReadOnly on ReadWrite state in the L1,
>         // the request should then be fulfilled from the L2 controller.
>         // (I think so)
>
>         // In case no ReadOnly or ReadWrite controller was found, this will
>         // point to the MaybeStale controller
>         AbstractController* func_read_cntrl = NULL;            
> //------NEW------//
>
>         for (unsigned int i = 0;i < num_controllers;++i) {
>
>             access_perm = m_abs_cntrl_vec[i]->
>                           getAccessPermission(line_address);
>             if (access_perm == AccessPermission_Read_Only ||
>                 access_perm == AccessPermission_Read_Write) {
>                 m_abs_cntrl_vec[i]->functionalRead(line_address, pkt);
>                 return true;
>             }
>
>             // Record the first MaybeStale controller in case no ReadOnly or
>             // ReadWrite controller was found
>             if (access_perm == AccessPermission_Maybe_Stale &&        
> //------NEW------//
>                 func_read_cntrl == NULL) {                                    
>               //------NEW------//
>                 func_read_cntrl = m_abs_cntrl_vec[i];                         
>          //------NEW------//
>             }                                                                 
>                                 //------NEW------//
>         }
>
>         // At this point no RO or RW controller was found, read from the
>         // MaybeStale one
>         if (func_read_cntrl != NULL) {                                        
>                //------NEW------//
>             func_read_cntrl->functionalRead(line_address, pkt);               
> //------NEW------//
>             return true;                                                      
>                           //------NEW------//
>         }                                                                     
>                                 //------NEW------//
>     }
>
>     return false;
> }
> _______________________________________________
> 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

Reply via email to