diff options
Diffstat (limited to 'src/mem/ruby/interfaces')
-rw-r--r-- | src/mem/ruby/interfaces/OpalInterface.cc | 446 | ||||
-rw-r--r-- | src/mem/ruby/interfaces/OpalInterface.hh | 214 | ||||
-rw-r--r-- | src/mem/ruby/interfaces/mf_api.hh | 165 |
3 files changed, 825 insertions, 0 deletions
diff --git a/src/mem/ruby/interfaces/OpalInterface.cc b/src/mem/ruby/interfaces/OpalInterface.cc new file mode 100644 index 000000000..362c7bcb6 --- /dev/null +++ b/src/mem/ruby/interfaces/OpalInterface.cc @@ -0,0 +1,446 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + */ + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +#include "OpalInterface.hh" +#include "interface.hh" +#include "System.hh" +#include "SubBlock.hh" +#include "mf_api.hh" +#include "Chip.hh" +#include "RubyConfig.hh" +//#include "XactIsolationChecker.hh" //gem5:Arka for decomissioning ruby/log_tm +// #include "TransactionInterfaceManager.hh" +//#include "TransactionVersionManager.hh" //gem5:Arka for decomissioning ruby/log_tm +#include "Sequencer.hh" + +/*------------------------------------------------------------------------*/ +/* Forward declarations */ +/*------------------------------------------------------------------------*/ + +static CacheRequestType get_request_type( OpalMemop_t opaltype ); +static OpalMemop_t get_opal_request_type( CacheRequestType type ); + +/// The static opalinterface instance +OpalInterface *OpalInterface::inst = NULL; + +/*------------------------------------------------------------------------*/ +/* Constructor(s) / destructor */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +OpalInterface::OpalInterface(System* sys_ptr) { + clearStats(); + ASSERT( inst == NULL ); + inst = this; + m_opal_intf = NULL; +} + +/*------------------------------------------------------------------------*/ +/* Public methods */ +/*------------------------------------------------------------------------*/ + +//************************************************************************** +void OpalInterface::printConfig(ostream& out) const { + out << "Opal_ruby_multiplier: " << OPAL_RUBY_MULTIPLIER << endl; + out << endl; +} + +void OpalInterface::printStats(ostream& out) const { + out << endl; + out << "Opal Interface Stats" << endl; + out << "----------------------" << endl; + out << endl; +} + +//************************************************************************** +void OpalInterface::clearStats() { +} + +//************************************************************************** +integer_t OpalInterface::getInstructionCount(int procID) const { + return ((*m_opal_intf->getInstructionCount)(procID)); +} + +//************************************************************************* +uint64 OpalInterface::getOpalTime(int procID) const { + return ((*m_opal_intf->getOpalTime)(procID)); +} + +/************ For WATTCH power stats ************************************/ +//************************************************************************* +void OpalInterface::incrementL2Access(int procID) const{ + ((*m_opal_intf->incrementL2Access)(procID)); +} + +//************************************************************************* +void OpalInterface::incrementPrefetcherAccess(int procID, int num_prefetches, int isinstr) const{ + ((*m_opal_intf->incrementPrefetcherAccess)(procID, num_prefetches, isinstr)); +} +/******************** END WATTCH power stats ****************************/ + +// Notifies Opal of an L2 miss +//************************************************************************* +void OpalInterface::notifyL2Miss(int procID, physical_address_t physicalAddr, OpalMemop_t type, int tagexists) const{ + ((*m_opal_intf->notifyL2Miss)(procID, physicalAddr, type, tagexists)); +} + +/****************************************************************** + * void hitCallback(int cpuNumber) + * Called by Sequencer. Calls opal. + ******************************************************************/ + +//************************************************************************** +void OpalInterface::hitCallback(NodeID proc, SubBlock& data, CacheRequestType type, int thread) { + // notify opal that the transaction has completed + (*m_opal_intf->hitCallback)( proc, data.getAddress().getAddress(), get_opal_request_type(type), thread ); +} + +//************************************************************************** +// Useful functions if Ruby needs to read/write physical memory when running with Opal +integer_t OpalInterface::readPhysicalMemory(int procID, + physical_address_t address, + int len ){ + return SIMICS_read_physical_memory(procID, address, len); +} + +//************************************************************************** +void OpalInterface::writePhysicalMemory( int procID, + physical_address_t address, + integer_t value, + int len ){ + SIMICS_write_physical_memory(procID, address, value, len); +} + +//*************************************************************** +// notifies Opal to print debug info +void OpalInterface::printDebug(){ + (*m_opal_intf->printDebug)(); +} + +//*************************************************************** + +/****************************************************************** + * Called by opal's memory operations (memop.C) + * May call Sequencer. + ******************************************************************/ + +//**************************************************************************** +int OpalInterface::getNumberOutstanding( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstanding(); +} + +//**************************************************************************** +int OpalInterface::getNumberOutstandingDemand( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstandingDemand(); +} + +//**************************************************************************** +int OpalInterface::getNumberOutstandingPrefetch( int cpuNumber ){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + return targetSequencer_ptr->getNumberOutstandingPrefetch(); +} + +//************************************************************************** +int OpalInterface::isReady( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ) { + // Send request to sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + // FIXME - some of these fields have bogus values sinced isReady() + // doesn't need them. However, it would be cleaner if all of these + // fields were exact. + + return (targetSequencer_ptr->isReady(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(0), + AccessModeType_UserMode, // User/supervisor mode + 0, // Size in bytes of request + PrefetchBit_No, // Not a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + )); +} + +// FIXME: duplicated code should be avoided +//************************************************************************** +void OpalInterface::makeRequest(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread) { + // Issue the request to the sequencer. + // set access type (user/supervisor) + AccessModeType access_mode; + if (isPriv) { + access_mode = AccessModeType_SupervisorMode; + } else { + access_mode = AccessModeType_UserMode; + } + + // Send request to sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + + targetSequencer_ptr->makeRequest(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(virtualPC), + access_mode, // User/supervisor mode + requestSize, // Size in bytes of request + PrefetchBit_No, // Not a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + ); +} + + +//************************************************************************** +void OpalInterface::makePrefetch(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread) { + DEBUG_MSG(SEQUENCER_COMP,MedPrio,"Making prefetch request"); + + // Issue the request to the sequencer. + // set access type (user/supervisor) + AccessModeType access_mode; + if (isPriv) { + access_mode = AccessModeType_SupervisorMode; + } else { + access_mode = AccessModeType_UserMode; + } + + // make the prefetch + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + targetSequencer_ptr->makeRequest(CacheMsg(Address( physicalAddr ), + Address( physicalAddr ), + get_request_type(typeOfRequest), + Address(virtualPC), + access_mode, + requestSize, + PrefetchBit_Yes, // True means this is a prefetch + 0, // Version number + Address(logicalAddr), // Virtual Address + thread, // SMT thread + 0, // TM specific - timestamp of memory request + false // TM specific - whether request is part of escape action + ) + ); + return; +} + +//************************************************************************** +int OpalInterface::staleDataRequest( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ) { + // Find sequencer + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + assert(targetSequencer_ptr != NULL); + + // query the cache for stale data values (if any) + bool hit = false; + //hit = targetSequencer_ptr->staleDataAccess( Address(physicalAddr), + // requestSize, buffer ); + + return hit; +} + +//************************************************************************** +void OpalInterface::notify( int status ) { + if (OpalInterface::inst == NULL) { + if (status == 1) { + // notify system that opal is now loaded + g_system_ptr->opalLoadNotify(); + } else { + return; + } + } + + // opal interface must be allocated now + ASSERT( OpalInterface::inst != NULL ); + if ( status == 0 ) { + + } else if ( status == 1 ) { + // install notification: query opal for its interface + OpalInterface::inst->queryOpalInterface(); + if ( OpalInterface::inst->m_opal_intf != NULL ) { + cout << "OpalInterface: installation successful." << endl; + // test: (*(OpalInterface::inst->m_opal_intf->hitCallback))( 0, 0xFFULL ); + } + } else if ( status == 2 ) { + // unload notification + // NOTE: this is not tested, as we can't unload ruby or opal right now. + OpalInterface::inst->removeOpalInterface(); + } +} + +// advance ruby time +//************************************************************************** +int OpalInterface::s_advance_counter = 0; + +void OpalInterface::advanceTime( void ) { + s_advance_counter++; + if (s_advance_counter == OPAL_RUBY_MULTIPLIER) { + Time time = g_eventQueue_ptr->getTime() + 1; + DEBUG_EXPR(NODE_COMP, HighPrio, time); + g_eventQueue_ptr->triggerEvents(time); + s_advance_counter = 0; + } +} + +// return ruby's time +//************************************************************************** +unsigned long long OpalInterface::getTime( void ) { + return (g_eventQueue_ptr->getTime()); +} + +// print's Ruby outstanding request table +void OpalInterface::printProgress(int cpuNumber){ + Sequencer* targetSequencer_ptr = g_system_ptr->getChip(cpuNumber/RubyConfig::numberOfProcsPerChip())->getSequencer(cpuNumber%RubyConfig::numberOfProcsPerChip()); + assert(targetSequencer_ptr != NULL); + + targetSequencer_ptr->printProgress(cout); +} + +// Non-method helper function +//************************************************************************** +static CacheRequestType get_request_type( OpalMemop_t opaltype ) { + CacheRequestType type; + + if (opaltype == OPAL_LOAD) { + type = CacheRequestType_LD; + } else if (opaltype == OPAL_STORE){ + type = CacheRequestType_ST; + } else if (opaltype == OPAL_IFETCH){ + type = CacheRequestType_IFETCH; + } else if (opaltype == OPAL_ATOMIC){ + type = CacheRequestType_ATOMIC; + } else { + ERROR_MSG("Error: Strange memory transaction type: not a LD or a ST"); + } + return type; +} + +//************************************************************************** +static OpalMemop_t get_opal_request_type( CacheRequestType type ) { + OpalMemop_t opal_type; + + if(type == CacheRequestType_LD){ + opal_type = OPAL_LOAD; + } + else if( type == CacheRequestType_ST){ + opal_type = OPAL_STORE; + } + else if( type == CacheRequestType_IFETCH){ + opal_type = OPAL_IFETCH; + } + else if( type == CacheRequestType_ATOMIC){ + opal_type = OPAL_ATOMIC; + } + else{ + ERROR_MSG("Error: Strange memory transaction type: not a LD or a ST"); + } + + //cout << "get_opal_request_type() CacheRequestType[ " << type << " ] opal_type[ " << opal_type << " ] " << endl; + return opal_type; +} + +//************************************************************************** +void OpalInterface::removeOpalInterface( void ) { + cout << "ruby: opal uninstalled. reinstalling timing model." << endl; + SIMICS_install_timing_model(); +} + +//************************************************************************** +bool OpalInterface::isOpalLoaded( void ) { + if (!g_SIMICS) { + return false; + } else { + mf_opal_api_t *opal_interface = SIMICS_get_opal_interface(); + if ( opal_interface == NULL ) { + return false; + } else { + return true; + } + } +} + +//************************************************************************** +void OpalInterface::queryOpalInterface( void ) { + m_opal_intf = SIMICS_get_opal_interface(); + if ( m_opal_intf == NULL ) { + WARN_MSG("error: OpalInterface: opal does not implement mf-opal-api interface.\n"); + } else { + // opal is loaded -- remove the timing_model interface + cout << "Ruby: ruby-opal link established. removing timing_model." << endl; + SIMICS_remove_timing_model(); + + if (m_opal_intf->notifyCallback != NULL) { + cout << "opalinterface: doing notify callback\n"; + (*m_opal_intf->notifyCallback)( 1 ); + } else { + // 2/27/2005, removed spurious error message (MRM) + // cout << "error: opalinterface: mf-opal-api has NULL notify callback.\n"; + } + } +} + +// install the opal interface to simics +//************************************************************************** +void OpalInterface::installInterface( mf_ruby_api_t *api ) { + // install ruby interface + api->isReady = &OpalInterface::isReady; + api->makeRequest = &OpalInterface::makeRequest; + api->makePrefetch = &OpalInterface::makePrefetch; + api->advanceTime = &OpalInterface::advanceTime; + api->getTime = &OpalInterface::getTime; + api->staleDataRequest = &OpalInterface::staleDataRequest; + api->notifyCallback = &OpalInterface::notify; + api->getNumberOutstanding = &OpalInterface::getNumberOutstanding; + api->getNumberOutstandingDemand = &OpalInterface::getNumberOutstandingDemand; + api->getNumberOutstandingPrefetch = &OpalInterface::getNumberOutstandingPrefetch; + api->printProgress = &OpalInterface::printProgress; +} diff --git a/src/mem/ruby/interfaces/OpalInterface.hh b/src/mem/ruby/interfaces/OpalInterface.hh new file mode 100644 index 000000000..4bc63d15a --- /dev/null +++ b/src/mem/ruby/interfaces/OpalInterface.hh @@ -0,0 +1,214 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * $Id$ + * + * Description: + * + */ + +#ifndef OpalInterface_H +#define OpalInterface_H + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +#include "Global.hh" +#include "Driver.hh" +#include "mf_api.hh" +#include "CacheRequestType.hh" + +/*------------------------------------------------------------------------*/ +/* Class declaration(s) */ +/*------------------------------------------------------------------------*/ + +class System; +class TransactionInterfaceManager; +class Sequencer; + +/** + * the processor model (opal) calls these OpalInterface APIs to access + * the memory hierarchy (ruby). + * @see pseq_t + * @author cmauer + * @version $Id$ + */ +class OpalInterface : public Driver { +public: + // Constructors + OpalInterface(System* sys_ptr); + + // Destructor + // ~OpalInterface(); + + integer_t getInstructionCount(int procID) const; + void hitCallback( NodeID proc, SubBlock& data, CacheRequestType type, int thread ); + void printStats(ostream& out) const; + void clearStats(); + void printConfig(ostream& out) const; + void print(ostream& out) const; + + integer_t readPhysicalMemory(int procID, physical_address_t address, + int len ); + + void writePhysicalMemory( int procID, physical_address_t address, + integer_t value, int len ); + uint64 getOpalTime(int procID) const; + + // for WATTCH power + void incrementL2Access(int procID) const; + void incrementPrefetcherAccess(int procID, int num_prefetches, int isinstr) const; + + // notifies Opal of an L2 miss + void notifyL2Miss(int procID, physical_address_t physicalAddr, OpalMemop_t type, int tagexists) const; + + void printDebug(); + + /// The static opalinterface instance + static OpalInterface *inst; + + /// static methods + static int getNumberOutstanding(int cpuNumber); + static int getNumberOutstandingDemand(int cpuNumber); + static int getNumberOutstandingPrefetch( int cpuNumber ); + + /* returns true if the sequencer is able to handle more requests. + This implements "back-pressure" by which the processor knows + not to issue more requests if the network or cache's limits are reached. + */ + static int isReady( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ); + + /* + makeRequest performs the coherence transactions necessary to get the + physical address in the cache with the correct permissions. More than + one request can be outstanding to ruby, but only one per block address. + The size of the cache line is defined to Intf_CacheLineSize. + When a request is finished (e.g. the cache contains physical address), + ruby calls completedRequest(). No request can be bigger than + Opal_CacheLineSize. It is illegal to request non-aligned memory + locations. A request of size 2 must be at an even byte, a size 4 must + be at a byte address half-word aligned, etc. Requests also can't cross a + cache-line boundaries. + */ + static void makeRequest(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /* prefetch a given block... + */ + static void makePrefetch(int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /* + * request data from the cache, even if it's state is "Invalid". + */ + static int staleDataRequest( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ); + + /* notify ruby of opal's status + */ + static void notify( int status ); + + /* + * advance ruby one cycle + */ + static void advanceTime( void ); + + /* + * return ruby's cycle count. + */ + static unsigned long long getTime( void ); + + /* prints Ruby's outstanding request table */ + static void printProgress(int cpuNumber); + + /* + * initialize / install the inter-module interface + */ + static void installInterface( mf_ruby_api_t *api ); + + /* + * Test if opal is loaded or not + */ + static bool isOpalLoaded( void ); + + /* + * query opal for its api + */ + void queryOpalInterface( void ); + + /* + * remove the opal interface (opal is unloaded). + */ + void removeOpalInterface( void ); + + /* + * set the opal interface (used if stand-alone testing) + */ + void setOpalInterface( mf_opal_api_t *opal_intf ) { + m_opal_intf = opal_intf; + } + + /** + * Signal an abort + */ + //void abortCallback(NodeID proc); + +private: + // Private Methods + + // Private copy constructor and assignment operator + OpalInterface(const OpalInterface& obj); + OpalInterface& operator=(const OpalInterface& obj); + + // Data Members (m_ prefix) + mf_opal_api_t *m_opal_intf; + Time m_simicsStartTime; + + static int s_advance_counter; +}; + +// Output operator declaration +ostream& operator<<(ostream& out, const OpalInterface& obj); + +// ******************* Definitions ******************* + +// Output operator definition +extern inline +ostream& operator<<(ostream& out, const OpalInterface& obj) +{ +// obj.print(out); + out << flush; + return out; +} + +#endif // OpalInterface_H diff --git a/src/mem/ruby/interfaces/mf_api.hh b/src/mem/ruby/interfaces/mf_api.hh new file mode 100644 index 000000000..c04a39308 --- /dev/null +++ b/src/mem/ruby/interfaces/mf_api.hh @@ -0,0 +1,165 @@ + +/* + * Copyright (c) 1999-2008 Mark D. Hill and David A. Wood + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer; + * redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution; + * neither the name of the copyright holders nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/*------------------------------------------------------------------------*/ +/* Includes */ +/*------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------*/ +/* Macro declarations */ +/*------------------------------------------------------------------------*/ + +#ifndef _MF_MEMORY_API_H_ +#define _MF_MEMORY_API_H_ + +#ifdef SIMICS30 +#ifndef pa_t +typedef physical_address_t pa_t; +typedef physical_address_t la_t; +#endif +#endif + +/** + * Defines types of memory requests + */ +typedef enum OpalMemop { + OPAL_LOAD, + OPAL_STORE, + OPAL_IFETCH, + OPAL_ATOMIC, +} OpalMemop_t; + +/*------------------------------------------------------------------------*/ +/* Class declaration(s) */ +/*------------------------------------------------------------------------*/ + +/** +* structure which provides an interface between ruby and opal. +*/ +typedef struct mf_opal_api { + /** + * @name Methods + */ + //@{ + /** + * notify processor model that data from address address is available at proc + */ + void (*hitCallback)( int cpuNumber, pa_t phys_address, OpalMemop_t type, int thread ); + + /** + * notify opal that ruby is loaded, or removed + */ + void (*notifyCallback)( int status ); + + /** + * query for the number of instructions executed on a given processor. + */ + integer_t (*getInstructionCount)( int cpuNumber ); + + // for printing out debug info on crash + void (*printDebug)(); + + /** query Opal for the current time */ + uint64 (*getOpalTime)(int cpuNumber); + + /** For WATTCH power stats */ + // Called whenever L2 is accessed + void (*incrementL2Access)(int cpuNumber); + // Called whenever prefetcher is accessed + void (*incrementPrefetcherAccess)(int cpuNumber, int num_prefetches, int isinstr); + + /* Called whenever there's an L2 miss */ + void (*notifyL2Miss)(int cpuNumber, physical_address_t physicalAddr, OpalMemop_t type, int tagexists); + + //@} +} mf_opal_api_t; + +typedef struct mf_ruby_api { + /** + * @name Methods + */ + //@{ + /** + * Check to see if the system is ready for more requests + */ + int (*isReady)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, OpalMemop_t typeOfRequest, int thread ); + + /** + * Make a 'mandatory' request to the memory hierarchy + */ + void (*makeRequest)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /** + * Make a prefetch request to the memory hierarchy + */ + void (*makePrefetch)( int cpuNumber, la_t logicalAddr, pa_t physicalAddr, + int requestSize, OpalMemop_t typeOfRequest, + la_t virtualPC, int isPriv, int thread); + + /** + * Ask the memory hierarchy for 'stale' data that can be used for speculation + * Returns true (1) if the tag matches, false (0) if not. + */ + int (*staleDataRequest)( int cpuNumber, pa_t physicalAddr, + int requestSize, int8 *buffer ); + + /** + * Advance ruby's cycle time one step + */ + void (*advanceTime)( void ); + + /** + * Get ruby's cycle time count. + */ + uint64 (*getTime)( void ); + + /** prints Ruby's outstanding request table */ + void (*printProgress)(int cpuNumber); + + /** + * notify ruby that opal is loaded, or removed + */ + void (*notifyCallback)( int status ); + + // Returns the number of outstanding request + int (*getNumberOutstanding)(int cpuNumber); + + // Returns the number of outstanding demand requests + int (*getNumberOutstandingDemand)(int cpuNumber ); + + // Returns the number of outstanding prefetch request + int (*getNumberOutstandingPrefetch)(int cpuNumber ); + + + //@} +} mf_ruby_api_t; + +#endif //_MF_MEMORY_API_H_ |