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

Reply via email to