Re: [Gems-users] invalidating a cache block


Date: Thu, 10 Jan 2008 18:21:28 +0100
From: Mladen Nikitovic <mladen@xxxxxx>
Subject: Re: [Gems-users] invalidating a cache block
Mike Marty wrote:
On Jan 10, 2008 2:06 AM, Mladen Nikitovic <mladen@xxxxxx> wrote:

Mike Marty wrote:
On Jan 9, 2008 3:43 AM, Mladen Nikitovic <mladen@xxxxxx> wrote:


I have found a possible solution:

I noticed that there is a section in the generated file
L1Cache_Transitions.C that handles L1Cache_Event_L1_Replacement and
L1Cache_Event_L1_Writeback events with the following actions:

i_allocateTBE(addr);
d_issuePUTX(addr);
x_copyDataFromL1CacheToTBE(addr);
ff_deallocateL1CacheBlock(addr);
return TransitionResult_Valid;

I have seen that these functions/methods (i_allocTBE etc) are
implemented in the L1Cache_Controller.C file, which means that I should
be able to call them via a L1cache_controller object, right?


I don't recommend this approach.  The protocol needs to go through its
state-machine actions for handling replacements.  The Ruby Sequencer
currently issues either a "Load", "Store", or "Ifetch" request to L1
controllers via the mandatory queue.  I think adding a fourth
"Invalidate"
request is a better approach. The in_port processing logic would then
just
trigger an L1_Replacement event and the protocol will take care of the
rest.




 Ok, I just want to confirm that I have understood what needs to be
done here.

First, in order to send a request to the L1 controller via the mandatory
queue I can do something like this, right?

m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg,
latency);


Yes, something like that.


 OK, at least I got one thing right :)

Then, to support the Invalidate request I intend to add a
CacheRequestType_Invalidate definition to the file CacheRequestType.h
file, add a case for this in the string_to_CacheRequestType and
CacheRequestType_to_string functions in the CacheRequestType.C

Finally, when the definitions and string conversions are in place I can
add an if-case that catches the Invalidate message in file
MOESI_CMP_directory-L1Cache.sm protocol file

 Event mandatory_request_type_to_event(CacheRequestType type) {
   if (type == CacheRequestType:LD) {
     return Event:Load;
   } else if (type == CacheRequestType:IFETCH) {
     return Event:Ifetch;
   } else if ((type == CacheRequestType:ST) || (type ==
CacheRequestType:ATOMIC)) {
     return Event:Store;
   } else if(type == CacheRequestType:INVALIDATE) {
     return Event:L1_Replacement;
   } else {
     error("Invalid CacheRequestType");
   }
 }

Will this be enough to do the trick?


Close, but you might want to check the CacheRequestType in the in_port
itself instead of using the above wrapper function.  The reason is that for
an INVALIDATE request, you do *not* want to make room for the block by
kicking something else out.  See how the in_port logic triggers a
replacement for a victim on a Load, Store, or Ifetch

I'm really sorry, but I can't find the place in the protocol where the in_port triggers replacement for a load, store or Ifetch. There are definitions of "Events" in the protocol for LD, ST, IFETCH and L1_Replacement, but I guess that is not the place to add a invalidate definition.

The only place that sounds similar to what you are describing is the code starting at line 402 in the protocol file:

         // *** DATA ACCESS ***

         // Check to see if it is in the OTHER L1
         if (L1IcacheMemory.isTagPresent(in_msg.Address)) {
// The block is in the wrong L1, put the request on the queue to the shared L2
           trigger(Event:L1_Replacement, in_msg.Address);
         }
         if (L1DcacheMemory.isTagPresent(in_msg.Address)) {
           // The tag matches for the L1, so the L1 ask the L2 for it
trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
         } else {
           if (L1DcacheMemory.cacheAvail(in_msg.Address)) {
// L1 does't have the line, but we have space for it in the L1 let's see if the L2 has it trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.Address);
           } else {
             // No room in the L1, so we need to make room in the L1
trigger(Event:L1_Replacement, L1DcacheMemory.cacheProbe(in_msg.Address));



This code triggers replacement but I don't see that it is caused by load, store, or Ifetch. Is this the code you are talking about?

Regarding the label INVALIDATE - although it is called like that I want to actually cause a writeback in cases where I discover modified or owned cache blocks when traversing the cache inside the sequencer. In all other cases I want to simply make an invalidation, which now I'm unsure whether I have to do through the protocol or if I can do by simply modifying the state variable without sending a message to the controller.

Even though i have created an event called INVALIDATE, my main goal was to cause a writeback of dirty data by triggering the replacement event in the protocol which I believe would give me the result I want (dirty data being pushed to L2 with possibly replacing the entry with some dummy data). So the label is wrong, but is the approach also wrong? Do I need to create a new separate code for this? My hope was to avoid that.

Another thing, since the files in the generated directory are off-limits due to re-generation upon compilation, I guess the modification to CacheRequestType is also invalid, right? So, any changes I make should only be done to the sequencer and the protocol file is my conclusion.

I really apologize for the confusion, I'm not familiar with the protocol and how it works. Hope you have the patience to help me understand this.

/M

I have another question related to this. I found another file (in the
generated catalog) called L1Cache_mandatory_request_type_to_event.C that
looks like this:

#include "Types.h"
#include "Chip.h"
#include "L1Cache_Controller.h"

L1Cache_Event

L1Cache_Controller::L1Cache_mandatory_request_type_to_event(CacheRequestType
param_type)
{
 if ((param_type == CacheRequestType_LD)) {
   return L1Cache_Event_Load;
 } else {
   if ((param_type == CacheRequestType_IFETCH)) {
     return L1Cache_Event_Ifetch;
   } else {
     if (((param_type == CacheRequestType_ST) || (param_type ==
CacheRequestType_ATOMIC))) {
       return L1Cache_Event_Store;
     } else {
               cerr << "Runtime Error at
../protocols/MSI_MOSI_CMP_directory-L1cache.sm:252, Ruby Time: " <<
g_eventQueue_ptr->getTime() << ": " << ("Invalid CacheRequestType") <<
", PID: " << getpid() << endl;
char c; cerr << "press return to continue." << endl; cin.get(c); abort();

;
     }
   }
 }
}

It is very similar to the if-else switch statements in the protocol. I
could add another clause here also but then I noticed that there is
already a L1Cache_Event_INV event defined in L1Cache_Event.h. The
problem I find here is that I could choose to translate the
CacheRequestType_INVALIDATE into either  a L1Cache_Event_INV or
L1Cache_Event_L1_Replacement. Should I choose the latter to be
consistent with the changes in the protocol? What happens if I choose
the former option? do I need to make any changes at all to this file?


This is the corresponding generated C-file.  I do not recommend modifying
the generated files because when SLICC regenerates the file, your
modifications are gone

--Mike

------------------------------------------------------------------------

_______________________________________________
Gems-users mailing list
Gems-users@xxxxxxxxxxx
https://lists.cs.wisc.edu/mailman/listinfo/gems-users
Use Google to search the GEMS Users mailing list by adding "site:https://lists.cs.wisc.edu/archive/gems-users/"; to your search.


[← Prev in Thread] Current Thread [Next in Thread→]