it seems like a good approach to me. I can't comment on the completeness. There may be other steps involved...you may have to stall all the Simics processors, etc.
--Mike
On Jan 10, 2008 12:53 PM, Mladen Nikitovic <
mladen@xxxxxx> wrote:
Mike Marty wrote: >> 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? >> >> > > Yes, this is the code I'm talking about.
OK, now that I have identified the right code sequence I'm not really
sure what modifications/augmentations I need to do.
> Since the line you are > invalidating is already present, your addition to > mandatory_request_type_to_event will work fine. My apologies.
> > > >
OK, so I assume my addition (as suggested below) to the mandatory_request_type_to_event function is correct.
>> 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. >> >> > > What I had in mind is that the Sequencer would walk the cache by directly
> accessing the CacheMemory objects. It would then issue an INVALIDATE for > each block address that is valid. > > > >
Yes, you are right, I forgot that I should just "blindly" send
INVALIDATE requests for all the blocks.
>> 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. >> >> > > I think the approach is sound and that Invalidate is not such a bad label. > >
I agree also now that I remember the original purpose.
> >> 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. >> >> > > You can add to CacheRequestType in RubySlicc_Exports.sm in the protocols/
> directory. > >
OK, so to recap the whole thing. There are three steps:
1) Define an INVALIDATE CacheRequestType in RubySlicc_Exports.sm. When I compile ruby, the definition will be added to the related files in the
/generated catalog, which enables me to do the next step.
// CacheRequestType enumeration(CacheRequestType, desc="...", default="CacheRequestType_NULL") { LD, desc="Load";
ST, desc="Store"; ATOMIC, desc="Atomic Load/Store"; IFETCH, desc="Instruction fetch"; IO, desc="I/O"; REPLACEMENT, desc="Replacement";
COMMIT, desc="Commit version"; LD_XACT, desc="Transactional Load"; LDX_XACT, desc="Transactional Load-Intend-To-Modify"; ST_XACT, desc="Transactional Store";
BEGIN_XACT, desc="Begin Transaction"; COMMIT_XACT, desc="Commit Transaction"; ABORT_XACT, desc="Abort Transaction"; NULL, desc="Invalid request type";
INVALIDATE, desc="test"; }
2) Upon a flush, go through the cache-blocks in Sequencer.C and send a message (CacheMsg with the field request-type set to INVALIDATE) via the mandatory queue to the L1 cache controller as suggested as earlier.
m_chip_ptr->m_L1Cache_mandatoryQueue_vec[m_version]->enqueue(msg, latency);
3) Add the INVALIDATE clause to the mandatory_request_type_to_event function in the MOESI_CMP_directory-
L1cache.sm 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"); } }
Are these three steps enough?
One thought though - wouldn't the automatic translation from INVALIDATE
request to a L1_Replacement event cause replacements in cases where no writeback is needed?
The one thing that might be missing is the possible addition (which I don't know how it should be done right now) to this code.
// *** 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));
I wasn't sure from your latest answer whether I should do something with this code or not.
Thanks for the super-fast answers and the patience!
/M
|