From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 10575 invoked by alias); 4 May 2005 14:47:59 -0000 Mailing-List: contact sid-help@sources.redhat.com; run by ezmlm Precedence: bulk List-Subscribe: List-Archive: List-Post: List-Help: , Sender: sid-owner@sources.redhat.com Received: (qmail 4496 invoked from network); 4 May 2005 14:45:10 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 4 May 2005 14:45:10 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.11) with ESMTP id j44EjAL1006657 for ; Wed, 4 May 2005 10:45:10 -0400 Received: from pobox.toronto.redhat.com (pobox.toronto.redhat.com [172.16.14.4]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id j44Ej8O14208; Wed, 4 May 2005 10:45:08 -0400 Received: from [172.16.14.227] (IDENT:L5VrfYatNVM4ouy5zWGGJZvbnUPyyI6b@topaz.toronto.redhat.com [172.16.14.227]) by pobox.toronto.redhat.com (8.12.8/8.12.8) with ESMTP id j44Ej8xY011114; Wed, 4 May 2005 10:45:08 -0400 Message-ID: <4278DFF4.8060707@redhat.com> Date: Wed, 04 May 2005 14:47:00 -0000 From: Dave Brolley User-Agent: Mozilla Thunderbird 1.0.2 (X11/20050317) MIME-Version: 1.0 To: sid@sources.redhat.com CC: moris dong Subject: [PATCH][RFC][RFA]Bus Arbitration Modelling Using Blockable Components Content-Type: multipart/mixed; boundary="------------080706090704020105020008" X-SW-Source: 2005-q2/txt/msg00010.txt.bz2 This is a multi-part message in MIME format. --------------080706090704020105020008 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Content-length: 1081 Hello, About a month ago, Morris Dong asked about modelling bus contention and stalls. At that time, I promised that I would submit some work that I have done in that area. Apologies for taking so long, but here it is. Attached to this message you will find: o A description of the notion of a blockable component in SID o An overview of the implementation of the sidutil::blocking_component mix-in class o A description of a blocking cache component implementation o A description and skeletal example of a blocking cpu implementation o A description of a new virtual base class: sidutil::bus_arbitrator for implementing bus arbitrator components o A patch which implements all of the above and fixes some bugs I noticed while completing the work This patch has been tested using an internal port which, unfortunately can not be submitted at this time. However, it would appear that this infrastructure is of interest and possible use to folks like Morris. As always, comments, suggestions and questions are welcome. I am seeking approval to commit this work. Dave --------------080706090704020105020008 Content-Type: text/plain; name="sid-blocking-components.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-blocking-components.txt" Content-length: 25107 Blocking Components In SID ========================== This document outlines the design, implementation and use of blocking components in SID. Introduction ============ SID is a serial simulator. Components in the simulation are notified, one by one, by a scheduling component that it is their turn to perform an activity. Each component completes its activity and returns control to the scheduler which then notifies the next component in turn. One might consider one complete round of scheduling to represent one "cycle" of execution for the simulated system. There is no need for arbitration of resources, since only one component has control at any one time. For most systems, simulating concurrency is not a problem, since the timing of accesses to a resource by more than one component is often unimportant. One exception is when the purpose of the simulation is to model the arbitration of access to a resource by more than one component. It may be useful to simulate different arbitration schemes in order to determine which one will be best for the system being designed. In this case, we need some way of blocking access to a resource and a way to arbitrate among requests which arrive in the same "cycle". In order to achieve this, the accessing component requires some way to be informed that a request has been denied as well as some way of being informed that access is later granted. This can be accomplished by the introduction of a new bus status, sid::bus::busy, and by the addition of a new mix-in class for components -- blocking_component -- which provides components with the ability to save state so that access to a resource can be retried when the component is next activated by the scheduler. Components may be arbitrarily complex and the point at which access is denied, or blocked may be arbitrarily deep within the logic of the implementation. One way of saving state in a general way under these conditions is by using a separate thread to perform the work of the component (child thread). When the component is activated by the scheduler, it activates its child thread to perform the task. If the task bcomes blocked for any reason, the child thread is suspended at the point at which it became blocked, the parent thread regains control and, in turn, returns control to the scheduler. During the next "cycle" when the component is activated again, the child thread is awakened and it retries the activity which was blocked. This pattern repeats until the "cycle" at which the component is no longer blocked. In this case, the child thread is still suspended, however, the point of suspension is at the beginning of its task. Note that the execution is still synchronous and deterministic, since only one thread executes at any one time, having been given control in order to perform its task and suspending when the task becomes blocked or is completed. Similarly, when a child thread is activated, the activating thread (parent thread) suspends until the child thread becomes blocked or completes its task. The following patch contains the implementation of the blocking_component class, the implementation of a new blocking_cache_component and some changes needed in order to support the implementation of a blocking cpu component (I have an implementation of a blocking cpu which, unfortunately, can not be contributed at this time, however I have provided a skeletal sample implementation below). The patch also contains the implementation of a virtual base class, bus_arbitrator, which can be extended to provide the implementation of a bus arbitrator component. The Patch ========= This section will describe the changes and additions introduced by the patch which follows. sid/include/sidblockingutil.h: ------------------------------ This new header contains the definition of the sidutil::blocking_component class which is designed for virtual inheritence similar to the existing component "mix-in" classes like fixed_attribute_map_component. This class is used to implement the threaded state saving alorithm described above and may be virtually inherited by any component. The threads are implemented using POSIX pthreads. The constructor is declared as follows blocking_component::blocking_component (void *child_self, void *(*f)(void *)); The 'child_self' argument is the 'this' pointer of the class which inherits from blocking_component and is used to give the child thread access to the class. The 'f' argument is the entry point to the child thread. child_self will be passed to this function when the child thread is created. Note that blocking_component inherits from fixed_attribute_map_with_logging_component. This is because component logging was used to help debug the implementation and remains for use in debugging possible future problems. A boolean attribute, "blockable?" is provided to allow the blocking behaviour to be enabled and disabled. The remaining methods are as follows: protected: // Called by the parent thread to ensure that a child thread exists // void need_child_thread (); // Called by the parent thread to signal the child thread to resume // int continue_child_thread_and_wait (); public: // Called by the child thread once when it is created. // void child_init (); // Called by the child thread to signal normal completion of the child task // void child_completed (); // Called by the child thread to signal that it is blocked // void child_blocked (); private: // Called by need_child_thread // void parent_init (); // Called by continue_child_thread_and_wait // int wait_for_child_thread (); // Called by child_completed and child_blocked // void child_wait_for_resume (); The typical logic for the parent thread of the component is: 1) Component is activated (pin driven or bus receives request) 2) call need_child_thread () 3) setup any state needed by the child 4) call continue_child_thread_and_wait () - the parent thread suspends here until the child gives up control 5) return control to the activating component For the logic of the child thread, we will use the child thread of the blocking_cache_component, which is very typical: extern "C" void * blocking_cache_child_thread_root (void *comp) { // Set up this thread to receive and handle signals from the parent thread. // This need only be done once. // blocking_cache_component *cache = static_cast(comp); cache->child_init (); for (;;) { // Signal completion and wait for the signal to resume cache->child_completed (); // Now perform the transaction cache->perform_transaction (); } // We should never reach here. return NULL; } This function is called when the child thread is created (when the parent thread calls need_child_thread). Its logic is as follows: 1) calls child_init once () and then signals completion right away. The parent thread will awaken it almost immediately (see parent logic above). 2) when awakened, it performs its activity and either a) signals completion if control returns to the main loop or b) signals that it is blocked if that condition arises during perform_transaction (). In either case, the child thread will wait for the parent thread to reawaken it. Note that the child thread is never created if the component is never activated and that a single child thread is used during the duration of the simulation for this component. Configury Changes ----------------- Solaris requires the definition of some macros when using pthreads in order to enable thread safety. The changes to sid/component/configure.in ensure that these macro definitions are available for the components which need this. The Makefile.in changes are as a result of running autoconf. cache_component Changes: sid/component/cache/cache.{cxx,h} ---------------------------------------------------------- These are changes to the existing cache_component class which were necessary to support the implementation of the new blocking_cache_component and its application in bus arbitration modelling. Changes include: o A new operation-status pin which reports the status of the last operation - This is needed to return status for operations which are initiated by driving a pin and which could become blocked, such as flush-and-invalidate . o Logic and a pin (data-width) for accessing the downstream components in units of 4 or 8 bytes. - This was needed for the implementation of an internal bus model which operated in units of 4 or 8 bytes. o Logic and a pin (total-latency) for accumulating the total latency of a cache line flush or fill. - This is needed for determining the actual latency of a flush or refill burst in the presence of bus arbitration downstream o Logic and virtual methods for handing unsuccessful reads/writes. - These are used as a hook by blocking_cache_component for handling accesses which are blocked downstream. o Virtual methods (lock_downstream, unlock_downstream) required for modelling exclusive access to a downstream bus interface during a read/write burst. o Virtual read/write methods - Used by blocking_cache_component to implement blockable reads/writes o Virtual pin handlers - Used by blocking_cache_component to implement blockable operations o New methods (read_downstream, write_downstream) simply encapsulate some logic which would have otherwise been coded identically in several places. o Fixed a bug in flush_set, invalidate_set, flush_and_invalidate_set. The pins were driven with address which these methods were treating as a cache set index. Introduced cache::addr_to_index method to convert the address to a set index before use. blocking_cache_component: sid/component/cache/cache.{cxx,h} ----------------------------------------------------------- This class inherits from cache_component and uses the new virtual interfaces to implement blocking behaviour when a downstream component returns sid::bus:busy. o handle_{read,write}_error: These virtual methods are called when a request downstream returns something other than sid::bus::ok. If the status is not sid::bus:busy, then the status is passed upstream as usual. Otherwise, child_blocked (child thread) is called which will suspend the thread and return control to the parent. The child thread will remain suspended until it is awoken again by the parent. o The remaining methods are blockable versions of the handers for each type of cache request (bus reads/writes and transactions initiated by driving input pins). In each case the blockable implementation checks the "blockable?" attribute and calls the normal handler if it is false. Otherwise it o calls need_child_thread to ensure that the child thread has been created o sets up the transaction details for the child thread o calls continue_child_thread_and_wait to execute the transaction o returns or reports the transaction status when control is returned New cache component types ------------------------- Using the implementation above, several new cache component types are now available: hw-blocking-cache-basic hw-blocking-cache-buffer-8 hw-blocking-cache-direct/kb/ hw-blocking-cache-/kb/ Each of these corresponds to an existing non-blocking cache type. BlockingCacheCfg: sid/main/dynamic/commonCfg.{cxx,h} ---------------------------------------------------- The configuration class has been added to suppor the creation of the new cache types above. Changes to enable blocking cpu implementation used to model bus arbitration =========================================================================== These changes make the implementation of a blocking cpu component possible. I have such a cpu implemented, however I am unable to contribute it at this time. sid/component/cgen-cpu/cgen-cpu.h --------------------------------- o GETMEM*, SETMEM*, GETIMEM*, SETIMEM* are no longer 'const' methods, since blocking during these operations may require some internal state to be changed. sid/include/sidbusutil.h ------------------------- o The readAny and writeAny methods of word_bus now track the maximum latency of the reads and writes performed during the transaction and return that as the overall latency of the transaction. sid/include/sidcomp.h --------------------- o A new enumerator has ben added --- sid::bus::busy. sid/include/sidcpuutil.h ------------------------ o basic_cpu now inherits virtually from its base classes in order to avoid unexpected complications when mixing in blocking_component lower in the heirarchy. o {read,write}_{insn,data}_memory* are no longer 'const' since the implementation of blocking on reads/writes may require state changes. o New virtual methods handle_{insn,data}_memory_{read,write}_error may be used as hooks for implementing blocking on reads/writes. The default methods return false to indicate that the error was not handled. o New virtual methods record_{insn,data}_{read,write}_latency may be used to record the latency caused by blocked reads/writes. The default methods add the given latency to total_latency. o {read,write}_{insn,data}_memory now call the new methods documented above. Misellaneous Changes ==================== sid/include/sidattrutil.h ------------------------- o Some methods and members which had previously been moved to the logger class in sidmiscutil.h was still also in sid_attribute_map_with_logging_component and was unused. These have been removed. o the check_level method is declared to return bool, but was not returning anything. o The members and methods of sid_attribute_map_with_logging_component are now protected (some were private) to allow access from inheriting classes. Sample implementation of a blocking cpu component ================================================= The sample below is a skeletal implementation of a blocking cpu component which blocks on reads/writes from/to data/insn memory when sid::bus::busy is returned. In order to model latency in the presence of other components, notice that it notes the latency returned with the status of all read/writes (blocked and unblocked), schedules itself such that it won't be called to step again until that latency has expired and then blocks itself for the same duration (see record_latency). ------------------------------------------------------ extern "C" void *blocking_cpu_child_thread_root (void *comp); // Abstract class! class blocking_cpu: public cgen_bi_endian_cpu, public blocking_component { public: blocking_cpu (); ~blocking_cpu () throw() { }; // blockable thread support // public: virtual void step_pin_handler (sid::host_int_4); void parent_step_pin_handler (sid::host_int_4 v) { blocked_latency = 0; cgen_bi_endian_cpu::step_pin_handler (v); } protected: virtual bool handle_insn_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return handle_bus_error (s); } virtual bool handle_insn_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return handle_bus_error (s); } virtual bool handle_data_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return handle_bus_error (s); } virtual bool handle_data_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return handle_bus_error (s); } // Handles errors for all of the above. bool handle_bus_error (sid::bus::status s); virtual void record_insn_memory_read_latency (sid::bus::status s) { record_latency (s); } virtual void record_data_memory_read_latency (sid::bus::status s) { record_latency (s); } void record_latency (sid::bus::status s) { if (s.latency == 0) return; total_latency += s.latency; if (blockable) { blocked_latency += s.latency; cgen_bi_endian_cpu::stepped (s.latency); child_blocked (); } } virtual void stepped (sid::host_int_4 n) { cgen_bi_endian_cpu::stepped (n - blocked_latency); } sid::host_int_4 blocked_latency; }; // Constructor blocking_cpu::blocking_cpu () : blocking_component (this, blocking_cpu_child_thread_root)\ { } // Virtual override of step_pin_handler // void blocking_cpu::step_pin_handler (sid::host_int_4 v) { if (blockable) { // Signal the child thread to resume need_child_thread (); continue_child_thread_and_wait (); return; } cgen_bi_endian_cpu::step_pin_handler (v); } // Handles bus errors from reads and writes from/to insn and data memory. // Specifically, bus::busy is handled in blockable mode. // bool blocking_cpu::handle_bus_error (sid::bus::status s) { if (s != sid::bus::busy) return false; // not handled // Reschedule for after the length of time the bus will be busy. // This will also block this child thread so that we continue // from here when scheduled again. record_latency (s); return true; } // This function is the root of the blockable child thread. It gets passed // to pthread_create. // extern "C" void * blocking_cpu_child_thread_root (void *comp) { // Set up this thread to receive and handle signals from the parent thread. // this need only be done once. // blocking_cpu *cpu = static_cast(comp); cpu->child_init (); for (;;) { // Signal completion and wait for the signal to resume cpu->child_completed (); // Call the parent class' step_pin_handler cpu->parent_step_pin_handler (1); } // We should never reach here. return NULL; } New virtual base class: sidutil::bus_arbitrator =============================================== This class is designed to be the base class for a customized bus arbitrator component. The component is designed to accept read/write requests from multiple upstream busses and to map them to multiple downstream accessors while prioritizing the requests using an implementation defined strategy. Upstream and downstream interfaces are identified using integral indices the assignment of which is implementation defined. Features include: o read/write methods which identify the upstream interface, the address and the size of the request. Mapping of upstream requests to downstream interfaces is implementation defined. o helper classes, input_interface and bus_request, help automate the delivery of upstream requests to the arbitration logic. o virtual methods for customizing the behaviour of the arbitrator. In many cases, the default implementations are sufficient. o passthough capability which bypasses the arbitration logic when the system is initializing or is idle (e.g. stopped by GDB). o scheduling and methods to manage the passing of time (cycles) provide the capability to compute accurate latencies for requests. Adding upstream interfaces -------------------------- The input_interface class inherits from sid::bus, so upstream interfaces are added in the usual way using add_accessor. Each input_interface is assigned a unique integer index when constructed, so that the arbitration logic knows which interface is making each request. Virtual methods --------------- These methods may be specialized in order to implement abritrary arbitration strategies: virtual bool prioritize_request (bus_request &r); This method examines the given request. It returns true if it should be serviced right away and returns false otherwise. The default method simply returns true (i.e. there is no arbitration). virtual void lock_downstream (int upstream, int downstream); If the model requires locking an interface for the duration of several accesses then this method should lock the given downstream interface if the given upstream interface is locked and unlock it otherwise. The mechanism for locking an interface (e.g. pin, attribute, etc.) is implementation defined. The default method simply returns without providing any locking. virtual sid::bus::status set_route_busy (bus_request &r, sid::bus::status s); This method should set state indicating that the route represented by the request r is busy for the number of cycles indicated by the latency contained within the status s. How this is done is implementation defined. The default method simply returns s without setting any busy state. virtual bool check_route_busy (int upstream, int downstream); This method is called after prioritize_request has indicated that a request should be processed. It returns true if the route through the arbitrator from the upstream interface to the downstream interface is busy. This can happen, for example, if a previous request used one of the interfaces and the latency of that request has not yet elapsed. The default implementation simply returns false (i.e. not busy). virtual sid::bus::status busy_status (); This method is called after prioritize_request has determined that a request can not be handled right away or after check_route_busy has returned true. It should return sid::bus:busy with the latency set to the minimum number of "cycles" which the requesting component should wait before trying again. The default implementation sets the latency to 1. virtual void step_cycle (); Handles the step-event pin which is normally driven by the target scheduler. The default implementation simply calls another virtual method, update_busy_routes. virtual void update_busy_routes (); This method should update any state associated with interfaces being busy and should be called once per simulated "cycle". By default, it is called once by the step_cycle method each time the step-event pin is driven. The default implementation does nothing. virtual void reschedule (sid::host_int_2 latency); This method reschedules the arbitrator using the step-control pin. It should be called by the implementation whenever internal state which must be updated as time passes has been set. This is implementation defined, however this generally occurs when: o a request has been accepted and set_route_busy has saved state associated with the busy route o the step-event pin has been driven and update_busy_routes has updated the state of busy routes If the internal state is changed such that no updates are required with the passage of time, then reschedule need not be called. The default implementation ignores the given latency and reschedules for 1 tick later. virtual int downstream_for_address (sid::host_int_4 address) = 0; Returns the index of the downstream accessor associated with the given address. Indices are assigned by the implementation. virtual sid::bus *downstream_bus (int downstream) = 0; This method should return a pointer to the downstream accessor identified by the given index. The index will have been obtained from the downstream_for_address method. virtual const char *up2str (int upstream) = 0; This method maps an upstream interface index to a name. It is used in logging messages. Arbitration ----------- Each read or write request on an upstream interface will trigger a call to arbitrate_read or arbitrate_write respectively. These methods will check whether the request should be passed through. If so the request is passed immediately to the proper downstream accessor. Otherwise they will: o create a bus_request representing the read/write request o pass the bus_request to prioritize_request. If true is returned then the request is handled immediately using perform_read or perform_write. Otherwise sid::bus::busy is returned with the latency computed by busy_status. Scheduling ---------- The bus_arbitrator component has a step-event pin and a step-control pin which are intended to be connected in the usual way with the target scheduler component. The implementation should cause the arbitrator to be scheduled in such a way that the passage of time in "cycles" can be managed, if necessary. For example, if a request is granted and has a latency of n "cycles", then the arbitrator should schedule itself such that the passage of those n cycles can be detected. Passthrough ----------- The abritration logic will only be executed if the "passthrough" pin is inactive and the "running" and "active" pins are both active. Thus, if the "running", "active" and "passthrough" pins are connected as follows, requests to the arbitrator will automatically be passed through (bypassing the arbitration logic) during loading of the executable and when GDB has stopped the simulation, : o the "running" pin should be connected to an init-seq output which is driven after the one connected to the loader's "load!" pin. o the "active" pin should be connected to the sim-sched's "active" pin. o the "passthrough" pin may be connected to the output pin of any component which has a need to set the arbitrator into passthrough mode. For example, a cpu component should drive this pin with a non-zero value before executing a syscall via the gloss component and drive it again with a value of zero after the syscall finishes. --------------080706090704020105020008 Content-Type: text/x-c-header; name="sidblockingutil.h" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sidblockingutil.h" Content-length: 5678 // sidblockingutil.h - Elements used for blockable components. -*- C++ -*- // Copyright (C) 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. #ifndef SIDBLOCKINGUTIL_H #define SIDBLOCKINGUTIL_H #include #include #include #include using std::cerr; using std::endl; namespace sidutil { // A mix-in for classes with blocking class blocking_component : public virtual fixed_attribute_map_with_logging_component { protected: blocking_component (void *child_self, void *(*f)(void *)) : name ("unknown"), self (child_self), child_created (false), child_thread_function (f), blockable (false) { add_attribute ("name", &name); add_attribute ("blockable?", & blockable, "setting"); } ~blocking_component () throw() { } protected: // Called by the parent thread to ensure that a child thread exists // void need_child_thread () { if (child_created) return; log (10, "%s: need_child_thread\n", name.c_str ()); parent_init (); // Create the child thread which will attempt to perform it's given // task. log (11, "%s: creating child thread\n", name.c_str ()); child_created = true; int rc = pthread_create (& child_thread, NULL, child_thread_function, self); if (rc == EAGAIN) { cerr << name << ": Could not create thread for a blockable component" << endl; child_created = false; } else log (11, "%s: child thread created\n", name.c_str ()); // Now wait for the child thread to signal that it is ready int status = wait_for_child_thread (); assert (status == ctl_child_complete); } // Called by the parent thread to signal the child thread to resume // int continue_child_thread_and_wait () { log (10, "%s: continue_child_thread\n", name.c_str ()); if (! child_created) return ctl_child_complete; log (11, "%s: signalling child to resume\n", name.c_str ()); return wait_for_child_thread (); } private: // Called once by the parent thread just before the child thread is // created. void parent_init () { log (10, "%s: parent_init\n", name.c_str ()); // Create mutexes for synchronizing the parent and child threads pthread_mutex_init (& child_resume_mutex, NULL); pthread_cond_init (& child_resume_condition, NULL); pthread_mutex_init (& child_stopped_mutex, NULL); pthread_cond_init (& child_stopped_condition, NULL); // Lock both mutexes pthread_mutex_lock (& child_resume_mutex); pthread_mutex_lock (& child_stopped_mutex); control_status = ctl_parent; } // Called by the parent to wait for the child thread to give up control // int wait_for_child_thread () { log (10, "%s: wait_for_child_thread\n", name.c_str ()); // Signal the child to resume assert (control_status == ctl_parent); control_status = ctl_child_start; pthread_cond_signal (& child_resume_condition); // Unlock the mutex so that the child can gain control pthread_mutex_unlock (& child_resume_mutex); // Wait for the return signal from the child pthread_cond_wait (& child_stopped_condition, & child_stopped_mutex); // Reacquire the mutex so that the child can gain control pthread_mutex_lock (& child_resume_mutex); // Check the value of control_status int s = control_status; assert (s != ctl_child_start); control_status = ctl_parent; return s; } public: // Called by the child thread once when it is created. // void child_init () { log (10, "%s: child_init\n", name.c_str ()); assert (child_created); // Lock both mutexes pthread_mutex_lock (& child_resume_mutex); pthread_mutex_lock (& child_stopped_mutex); } // Called by the child thread to signal normal completion of the child task // void child_completed () { log (10, "%s: child_completed\n", name.c_str ()); log (11, "%s: child sending completion signal\n", name.c_str ()); control_status = ctl_child_complete; child_wait_for_resume (); } // Called by the child thread to signal that it is blocked // void child_blocked () { log (10, "%s: child_blocked\n", name.c_str ()); log (11, "%s: child sending blocked signal\n", name.c_str ()); control_status = ctl_child_blocked; child_wait_for_resume (); } private: // Called by the child thread to wait for a signal from the parent thread // to resume void child_wait_for_resume () { log (10, "%s: child_wait_for_resume\n", name.c_str ()); // Signal the parent that we're stopped log (11, "%s: child signalling the parent thread\n", name.c_str ()); pthread_cond_signal (& child_stopped_condition); // Unlock the mutex so that the parent can gain control pthread_mutex_unlock (& child_stopped_mutex); // Wait for a signal to resume log (11, "%s: child waiting for parent thread\n", name.c_str ()); pthread_cond_wait (& child_resume_condition, & child_resume_mutex); // Reacquire the stopped mutex pthread_mutex_lock (& child_stopped_mutex); assert (control_status == ctl_child_start); } protected: string name; bool blockable; void *self; bool child_created; pthread_t child_thread; void *(*child_thread_function)(void *); pthread_mutex_t child_resume_mutex; pthread_cond_t child_resume_condition; pthread_mutex_t child_stopped_mutex; pthread_cond_t child_stopped_condition; enum { ctl_parent, ctl_child_start, ctl_child_blocked, ctl_child_complete } control_status; }; } #endif // SIDBLOCKINGUTIL_H --------------080706090704020105020008 Content-Type: text/plain; name="sid-blocking.patch.txt" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="sid-blocking.patch.txt" Content-length: 113339 ? sid/include/sidblockingutil.h Index: sid/component/Makefile.am =================================================================== RCS file: /cvs/src/src/sid/component/Makefile.am,v retrieving revision 1.3 diff -c -p -r1.3 Makefile.am *** sid/component/Makefile.am 17 Jul 2001 01:42:34 -0000 1.3 --- sid/component/Makefile.am 3 May 2005 20:42:14 -0000 *************** SUBDIRS = @subdirs@ @make_subdirs@ *** 7,12 **** --- 7,17 ---- bin_SCRIPTS=siddoc + CXXFLAGS= + TOP_CXXFLAGS=$(CXXFLAGS) @comp_defs@ + AM_CXXFLAGS=$(TOP_CXXFLAGS) + AM_MAKEFLAGS= "TOP_CXXFLAGS=$(TOP_CXXFLAGS)" + all-local: chmod a+x siddoc Index: sid/component/configure.in =================================================================== RCS file: /cvs/src/src/sid/component/configure.in,v retrieving revision 1.12 diff -c -p -r1.12 configure.in *** sid/component/configure.in 24 Oct 2003 19:03:01 -0000 1.12 --- sid/component/configure.in 3 May 2005 20:42:14 -0000 *************** if test x$ac_cv_decl_socklen_t = xyes; t *** 89,94 **** --- 89,107 ---- AC_DEFINE(HAVE_SOCKLEN_T, 1, [Define if socklen_t is declared via sys/socket.h]) fi + dnl Need extra defines for Solaris threads + case "$host" in + sparc-sun-solaris*) + # Note: If _REENTRANT isn't defined, then Solaris + # won't define thread-safe library routines. + comp_defs="-D_REENTRANT -D_POSIX_PTHREAD_SEMANTICS" + ;; + *) + comp_defs= + ;; + esac + AC_SUBST(comp_defs) + AC_SUBST(CYGWIN) dnl building docs Index: sid/component/cache/Makefile.am =================================================================== RCS file: /cvs/src/src/sid/component/cache/Makefile.am,v retrieving revision 1.4 diff -c -p -r1.4 Makefile.am *** sid/component/cache/Makefile.am 17 May 2002 21:28:14 -0000 1.4 --- sid/component/cache/Makefile.am 3 May 2005 20:42:14 -0000 *************** AUTOMAKE_OPTIONS = foreign *** 4,11 **** pkglib_LTLIBRARIES = libcache.la INCLUDES = -I. -I../../include -I$(srcdir)/../../include ! libcache_la_SOURCES = cache.cxx cache.h cacheutil.cxx cacheutil.h log2.h libcache_la_LDFLAGS = -module -no-undefined pkgdata_DATA = hw-cache.txt --- 4,17 ---- pkglib_LTLIBRARIES = libcache.la + AM_CXXFLAGS=$(TOP_CXXFLAGS) + AM_MAKEFLAGS= "TOP_CXXFLAGS=$(TOP_CXXFLAGS)" + INCLUDES = -I. -I../../include -I$(srcdir)/../../include ! EXTRA_SOURCES= ! libcache_la_SOURCES = cache.cxx cache.h \ ! $(EXTRA_SOURCES) \ ! cacheutil.cxx cacheutil.h log2.h libcache_la_LDFLAGS = -module -no-undefined pkgdata_DATA = hw-cache.txt Index: sid/component/cache/cache.cxx =================================================================== RCS file: /cvs/src/src/sid/component/cache/cache.cxx,v retrieving revision 1.19 diff -c -p -r1.19 cache.cxx *** sid/component/cache/cache.cxx 20 Jul 2004 17:10:48 -0000 1.19 --- sid/component/cache/cache.cxx 3 May 2005 20:42:14 -0000 *************** *** 1,6 **** // cache.cxx -- A universal memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // cache.cxx -- A universal memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004, 2005 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** cache_component::cache_component (unsign *** 73,82 **** line_size (line_sz), cache_size (cache_sz), assoc (assocy), hit_latency (0), miss_latency (0), refill_latency (0), ! refill_latency_specified (false) { acache.init (); memset (&stats, 0, sizeof (stats)); --- 73,84 ---- line_size (line_sz), cache_size (cache_sz), assoc (assocy), + data_width (4), hit_latency (0), miss_latency (0), refill_latency (0), ! refill_latency_specified (false), ! total_latency_p (false) { acache.init (); memset (&stats, 0, sizeof (stats)); *************** cache_component::cache_component (unsign *** 96,101 **** --- 98,104 ---- add_pin ("prefetch", &prefetch_pin); add_pin ("lock", &lock_pin); add_pin ("unlock", &unlock_pin); + add_pin ("operation-status", &operation_status_pin); add_attribute_ro ("cache-size", &cache_size, "setting"); add_attribute_ro ("line-size", &line_size, "setting"); *************** cache_component::cache_component (unsign *** 103,108 **** --- 106,112 ---- &cache_component::associativity, &cache_component::set_nothing, "setting"); + add_attribute ("data-width", &data_width, "setting"); add_attribute ("write-through?", &write_through_p, "setting"); add_attribute ("write-allocate?", &write_allocate_p, "setting"); *************** cache_component::cache_component (unsign *** 144,149 **** --- 148,154 ---- add_attribute ("hit-latency", &hit_latency, "setting"); add_attribute ("miss-latency", &miss_latency, "setting"); + add_attribute ("total-latency?", &total_latency_p, "setting"); add_attribute_virtual ("refill-latency", this, &cache_component::get_refill_latency, *************** cache_component::write_any (host_int_4 a *** 199,205 **** line->insert (line_offset (*line, addr), data); if (write_through_p) { ! if ((st = downstream->write (addr, data)) != bus::ok) return st; } } --- 204,217 ---- line->insert (line_offset (*line, addr), data); if (write_through_p) { ! do ! { ! st = downstream->write (addr, data); ! if (st == bus::ok) ! break; ! } ! while (handle_write_error (st, addr)); ! if (st != bus::ok) return st; } } *************** cache_component::write_any (host_int_4 a *** 224,230 **** } else { ! if ((st = downstream->write (addr, data)) != bus::ok) return st; } --- 236,249 ---- } else { ! do ! { ! st = downstream->write (addr, data); ! if (st == bus::ok) ! break; ! } ! while (handle_write_error (st, addr)); ! if (st != bus::ok) return st; } *************** cache_component::write_any (host_int_4 a *** 237,243 **** else { // write through to memory to preserve the write ! if ((st = downstream->write (addr, data)) != bus::ok) return st; } } --- 256,269 ---- else { // write through to memory to preserve the write ! do ! { ! st = downstream->write (addr, data); ! if (st == bus::ok) ! break; ! } ! while (handle_write_error (st, addr)); ! if (st != bus::ok) return st; } } *************** cache_component::read_any (host_int_4 ad *** 304,310 **** } else { ! st = downstream->read (addr, data); st.latency += miss_latency; return st; } --- 330,342 ---- } else { ! do ! { ! st = downstream->read (addr, data); ! if (st == bus::ok) ! break; ! } ! while (handle_read_error (st, addr)); st.latency += miss_latency; return st; } *************** bus::status *** 322,348 **** cache_component::read_line (cache_line& line) { bus::status st; - int overall_latency = 0; host_int_4 base = acache.tag_to_addr (line.tag ()); ! for (host_int_4 offset = 0; offset < line_size; offset += 4) ! { ! sid::big_int_4 data; ! st = downstream->read (base + offset, data); ! // Record the latency of the first read. ! if (offset == 0) ! overall_latency = st.latency; if (st != bus::ok) ! return st; ! line.insert (offset, data); } line.unlock (); line.clean (); line.validate (); ! if (refill_latency_specified) st.latency = refill_latency; else ! st.latency = overall_latency; return st; } --- 354,400 ---- cache_component::read_line (cache_line& line) { bus::status st; host_int_4 base = acache.tag_to_addr (line.tag ()); ! lock_downstream (); ! host_int_2 actual_fill_latency = 0; ! for (host_int_4 offset = 0; offset < line_size; offset += data_width) ! { ! // Unlock the downstream interface for the last read ! if (offset + data_width >= line_size) ! unlock_downstream (); ! ! sid::big_int_8 data8; ! sid::big_int_4 data4; ! host_int_4 address = base + offset; ! if (data_width == 8) ! st = read_downstream (address, data8); ! else ! st = read_downstream (address, data4); ! if (st != bus::ok) ! { ! unlock_downstream (); ! return st; ! } ! ! if (total_latency_p) ! actual_fill_latency += st.latency; ! else if (st.latency > actual_fill_latency) ! actual_fill_latency = st.latency; ! ! if (data_width == 8) ! line.insert (offset, data8); ! else ! line.insert (offset, data4); } line.unlock (); line.clean (); line.validate (); ! if (refill_latency_specified && ! total_latency_p) st.latency = refill_latency; else ! st.latency = actual_fill_latency; return st; } *************** cache_component::write_line (cache_line& *** 352,427 **** { bus::status st; host_int_4 base = acache.tag_to_addr (line.tag ()); ! for (host_int_4 offset = 0; offset < line_size; offset += 4) ! { ! sid::big_int_4 data; ! line.extract (offset, data); ! st = downstream->write (base + offset, data); if (st != bus::ok) ! return st; } line.clean (); if (LIKELY (collect_p)) stats.flushes++; return st; } void cache_component::flush_all_lines (host_int_4) { while (true) { cache_line* line = acache.find_any_dirty (); if (line == 0) break; ! (void) write_line (*line); } } void cache_component::flush_line (host_int_4 addr) { cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line && line->dirty_p ()) ! (void) write_line (*line); } void ! cache_component::flush_set (host_int_4 index) { ! if (index >= acache.num_sets ()) ! return; // bad value cache_set& set = acache [index]; for (unsigned i = 0; i < set.num_lines(); i++) { cache_line& line = set [i]; if (line.valid_p () && line.dirty_p ()) ! (void) write_line (line); } } void ! cache_component::flush_and_invalidate_set (host_int_4 index) { ! if (index >= acache.num_sets ()) ! return; // bad value cache_set& set = acache [index]; for (unsigned i = 0; i < set.num_lines(); i++) { cache_line& line = set [i]; if (line.valid_p () && line.dirty_p ()) { ! (void) write_line (line); line.invalidate (); } } } void cache_component::invalidate_all_lines (host_int_4 ignore) { acache.invalidate (); } void --- 404,561 ---- { bus::status st; host_int_4 base = acache.tag_to_addr (line.tag ()); ! lock_downstream (); ! host_int_2 actual_latency = 0; ! for (host_int_4 offset = 0; offset < line_size; offset += data_width) ! { ! // Unlock the downstream interface for the last write ! if (offset + data_width >= line_size) ! unlock_downstream (); ! ! sid::big_int_4 data4; ! sid::big_int_8 data8; ! host_int_4 address = base + offset; ! if (data_width == 8) ! { ! line.extract (offset, data8); ! st = write_downstream (address, data8); ! } ! else ! { ! line.extract (offset, data4); ! st = write_downstream (address, data4); ! } ! if (st != bus::ok) ! { ! unlock_downstream (); ! return st; ! } ! ! if (total_latency_p) ! actual_latency += st.latency; ! else if (st.latency > actual_latency) ! actual_latency = st.latency; } line.clean (); if (LIKELY (collect_p)) stats.flushes++; + st.latency = actual_latency; + return st; + } + + template + bus::status + cache_component::read_downstream (host_int_4 address, DataType &data) + { + bus::status st; + do + { + st = downstream->read (address, data); + if (st == bus::ok) + break; + } + while (handle_read_error (st, address)); + return st; + } + + template + bus::status + cache_component::write_downstream (host_int_4 address, DataType data) + { + bus::status st; + do + { + st = downstream->write (address, data); + if (st == bus::ok) + break; + } + while (handle_write_error (st, address)); return st; } void cache_component::flush_all_lines (host_int_4) { + host_int_2 total_latency = 0; + bus::status st; while (true) { cache_line* line = acache.find_any_dirty (); if (line == 0) break; ! st = write_line (*line); ! if (st != bus::ok) ! break; ! total_latency += st.latency; } + st.latency = total_latency; + report_status (st); } void cache_component::flush_line (host_int_4 addr) { + bus::status st; cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line && line->dirty_p ()) ! st = write_line (*line); ! report_status (st); } void ! cache_component::flush_set (host_int_4 addr) { ! host_int_4 index = acache.addr_to_index (addr); ! assert (index < acache.num_sets ()); + host_int_2 total_latency = 0; + bus::status st; cache_set& set = acache [index]; for (unsigned i = 0; i < set.num_lines(); i++) { cache_line& line = set [i]; if (line.valid_p () && line.dirty_p ()) ! { ! st = write_line (line); ! if (st != bus::ok) ! break; ! total_latency += st.latency; ! } } + st.latency = total_latency; + report_status (st); } void ! cache_component::flush_and_invalidate_set (host_int_4 addr) { ! host_int_4 index = acache.addr_to_index (addr); ! assert (index < acache.num_sets ()); + host_int_2 total_latency = 0; + bus::status st; cache_set& set = acache [index]; for (unsigned i = 0; i < set.num_lines(); i++) { cache_line& line = set [i]; if (line.valid_p () && line.dirty_p ()) { ! st = write_line (line); ! if (st != bus::ok) ! break; ! total_latency += st.latency; line.invalidate (); } } + st.latency = total_latency; + report_status (st); } void cache_component::invalidate_all_lines (host_int_4 ignore) { acache.invalidate (); + report_status (bus::ok); } void *************** cache_component::invalidate_line (host_i *** 430,435 **** --- 564,570 ---- cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line) line->invalidate (); + report_status (bus::ok); } void *************** cache_component::flush_and_invalidate_li *** 438,459 **** cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line && line->dirty_p ()) { ! (void) write_line (*line); line->invalidate (); } } void ! cache_component::invalidate_set (host_int_4 set) { acache.invalidate (set); } void cache_component::prefetch_line (host_int_4 addr) { sid::big_int_1 dummy; ! (void) read_any (addr, dummy); } void --- 573,600 ---- cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line && line->dirty_p ()) { ! bus::status st = write_line (*line); line->invalidate (); + report_status (st); + return; } + report_status (bus::ok); } void ! cache_component::invalidate_set (host_int_4 addr) { + host_int_4 set = acache.addr_to_index (addr); acache.invalidate (set); + report_status (bus::ok); } void cache_component::prefetch_line (host_int_4 addr) { sid::big_int_1 dummy; ! bus::status st = read_any (addr, dummy); ! report_status (st); } void *************** cache_component::lock_line (host_int_4 a *** 462,467 **** --- 603,609 ---- cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line) line->lock (); + report_status (bus::ok); } void *************** cache_component::unlock_line (host_int_4 *** 470,475 **** --- 612,618 ---- cache_line* line = acache.find (acache.addr_to_tag (addr)); if (line) line->unlock (); + report_status (bus::ok); } void *************** cache_component::write_hit_rate () *** 586,591 **** --- 729,931 ---- } } + // ------------------------------------------------------------------------ + // The blocking cache component. + + // This function is the root of the blockable child thread. It gets passed + // to pthread_create. + // + extern "C" void * + blocking_cache_child_thread_root (void *comp) + { + // Set up this thread to receive and handle signals from the parent thread. + // this need only be done once. + // + blocking_cache_component *cache = static_cast(comp); + cache->child_init (); + + for (;;) + { + // Signal completion and wait for the signal to resume + cache->child_completed (); + + // Now perform the transaction + cache->perform_transaction (); + } + + // We should never reach here. + return NULL; + } + + blocking_cache_component::blocking_cache_component (unsigned assocy, + unsigned cache_sz, + unsigned line_sz, + cache_replacement_algorithm& replacer, + cache_line_factory& factory) + :cache_component (assocy, cache_sz, line_sz, replacer, factory), + blocking_component (this, blocking_cache_child_thread_root) + { + add_pin ("downstream-lock", & downstream_lock_pin); + downstream_lock_pin.set_active_high (); + } + + blocking_cache_component::blocking_cache_component (void *child_self, + unsigned assocy, + unsigned cache_sz, + unsigned line_sz, + cache_replacement_algorithm& replacer, + cache_line_factory& factory) + :cache_component (assocy, cache_sz, line_sz, replacer, factory), + blocking_component (child_self, blocking_cache_child_thread_root) + { + add_pin ("downstream-lock", & downstream_lock_pin); + downstream_lock_pin.set_active_high (); + } + + // Handles bus errors from reads and writes from/to insn and data memory. + // Specifically, bus::busy is handled in blockable mode. + // + bool + blocking_cache_component::handle_bus_error (bus::status s) + { + if (s != bus::busy) + return false; // not handled + + // Signal that we're blocked and wait for the signal to try again + transaction_status = s; + child_blocked (); + return true; + } + + #define DEFN_METHOD(DataType) \ + bus::status \ + blocking_cache_component::write(host_int_4 addr, DataType data) \ + { \ + if (blockable) \ + { \ + /* Signal the child thread to resume */ \ + need_child_thread (); \ + setup_write_transaction (addr, data); \ + continue_child_thread_and_wait (); \ + \ + return transaction_status; \ + } \ + return this->write_any(addr, data); \ + } \ + bus::status \ + blocking_cache_component::read(host_int_4 addr, DataType& data) \ + { \ + if (blockable) \ + { \ + /* Signal the child thread to resume */ \ + need_child_thread (); \ + setup_read_transaction (addr, data); \ + continue_child_thread_and_wait (); \ + \ + get_transaction_data (data); \ + return transaction_status; \ + } \ + return this->read_any(addr, data); \ + } + DEFN_METHOD (big_int_1) + DEFN_METHOD (big_int_2) + DEFN_METHOD (big_int_4) + DEFN_METHOD (big_int_8) + DEFN_METHOD (little_int_1) + DEFN_METHOD (little_int_2) + DEFN_METHOD (little_int_4) + DEFN_METHOD (little_int_8) + #undef DEFN_METHOD + + void + blocking_cache_component::flush_all_lines (host_int_4 v) + { + if (blockable) + { + // Signal the child thread to resume + need_child_thread (); + setup_flush_all_transaction (); + int signal = continue_child_thread_and_wait (); + if (signal == ctl_child_blocked) + report_status (transaction_status); + return; + } + cache_component::flush_all_lines (v); + } + + void + blocking_cache_component::flush_line (host_int_4 addr) + { + if (blockable) + { + // Signal the child thread to resume + need_child_thread (); + setup_flush_line_transaction (addr); + int signal = continue_child_thread_and_wait (); + if (signal == ctl_child_blocked) + report_status (transaction_status); + return; + } + cache_component::flush_line (addr); + } + + void + blocking_cache_component::flush_set (host_int_4 addr) + { + if (blockable) + { + // Signal the child thread to resume + need_child_thread (); + setup_flush_set_transaction (addr); + int signal = continue_child_thread_and_wait (); + if (signal == ctl_child_blocked) + report_status (transaction_status); + return; + } + cache_component::flush_set (addr); + } + + void + blocking_cache_component::flush_and_invalidate_set (host_int_4 addr) + { + if (blockable) + { + // Signal the child thread to resume + need_child_thread (); + setup_flush_and_invalidate_set_transaction (addr); + int signal = continue_child_thread_and_wait (); + if (signal == ctl_child_blocked) + report_status (transaction_status); + return; + } + cache_component::flush_and_invalidate_set (addr); + } + + void + blocking_cache_component::flush_and_invalidate_line (host_int_4 addr) + { + if (blockable) + { + // Signal the child thread to resume + need_child_thread (); + setup_flush_and_invalidate_line_transaction (addr); + int signal = continue_child_thread_and_wait (); + if (signal == ctl_child_blocked) + report_status (transaction_status); + return; + } + cache_component::flush_and_invalidate_line (addr); + } + + void + blocking_cache_component::prefetch_line (host_int_4 addr) + { + sid::big_int_1 dummy; + bus::status st = read (addr, dummy); + report_status (st); + } + + cache_line * cache_replacement_fifo::expell (cache_set& cset) { *************** CacheListTypes () *** 715,721 **** --- 1055,1063 ---- vector types; types.push_back ("hw-cache-basic"); + types.push_back ("hw-blocking-cache-basic"); types.push_back ("hw-cache-buffer-8"); + types.push_back ("hw-blocking-cache-buffer-8"); for (unsigned i = 0; i < (sizeof (assocs) / sizeof (string)); i++) for (unsigned j = 0; j < (sizeof (cache_sizes) / sizeof (string)); j++) *************** CacheListTypes () *** 723,743 **** { if (assocs[i] == "direct") { ! type = string ("hw-cache-direct/"); ! type += cache_sizes[j] + "kb/"; type += line_sizes[k]; ! types.push_back (type); } else for (unsigned m = 0; m < (sizeof (replacement_algorithms) / sizeof (string)); m++) { ! type = string ("hw-cache-"); ! type += assocs[i] + "/"; type += cache_sizes[j] + "kb/"; type += line_sizes[k] + "/"; type += replacement_algorithms[m]; ! types.push_back (type); } } return types; --- 1065,1085 ---- { if (assocs[i] == "direct") { ! type = cache_sizes[j] + "kb/"; type += line_sizes[k]; ! types.push_back ("hw-cache-direct/" + type); ! types.push_back ("hw-blocking-cache-direct/" + type); } else for (unsigned m = 0; m < (sizeof (replacement_algorithms) / sizeof (string)); m++) { ! type = assocs[i] + "/"; type += cache_sizes[j] + "kb/"; type += line_sizes[k] + "/"; type += replacement_algorithms[m]; ! types.push_back ("hw-cache-" + type); ! types.push_back ("hw-blocking-cache-" + type); } } return types; *************** CacheCreate (const string& typeName) *** 752,766 **** if (typeName == "hw-cache-basic") return new cache_component (1, 16384, 32, null_replacement, internal_line_factory); if (typeName == "hw-cache-buffer-8") return new cache_component (0, 8, 8, null_replacement, internal_line_factory); vector parts = sidutil::tokenize (typeName, "-/"); ! if (parts.size () < 5 || parts[0] != "hw" || parts[1] != "cache") return 0; ! string assoc_string = parts[2]; for (match = false, i = 0; i < sizeof (assocs) / sizeof (string); i++) if (assoc_string == assocs[i]) match = true; --- 1094,1119 ---- if (typeName == "hw-cache-basic") return new cache_component (1, 16384, 32, null_replacement, internal_line_factory); + if (typeName == "hw-blocking-cache-basic") + return new blocking_cache_component (1, 16384, 32, null_replacement, internal_line_factory); + if (typeName == "hw-cache-buffer-8") return new cache_component (0, 8, 8, null_replacement, internal_line_factory); + if (typeName == "hw-blocking-cache-buffer-8") + return new blocking_cache_component (0, 8, 8, null_replacement, internal_line_factory); + vector parts = sidutil::tokenize (typeName, "-/"); ! unsigned extra_ix; ! if (parts.size () >= 5 && parts[0] == "hw" && parts[1] == "cache") ! extra_ix = 0; ! else if (parts.size () >= 6 && parts[0] == "hw" && parts[1] == "blocking" && parts[2] == "cache") ! extra_ix = 1; ! else return 0; ! string assoc_string = parts[2 + extra_ix]; for (match = false, i = 0; i < sizeof (assocs) / sizeof (string); i++) if (assoc_string == assocs[i]) match = true; *************** CacheCreate (const string& typeName) *** 770,776 **** // Parse "kb", where is a positive integer. int cache_sz; ! string cache_size_string = parts[3].substr (0, parts[3].length() - 2); for (match = false, i = 0; i < sizeof (cache_sizes) / sizeof (string); i++) if (cache_size_string == cache_sizes[i]) { --- 1123,1129 ---- // Parse "kb", where is a positive integer. int cache_sz; ! string cache_size_string = parts[3 + extra_ix].substr (0, parts[3 + extra_ix].length() - 2); for (match = false, i = 0; i < sizeof (cache_sizes) / sizeof (string); i++) if (cache_size_string == cache_sizes[i]) { *************** CacheCreate (const string& typeName) *** 782,788 **** return 0; int line_sz; ! string line_size_string = parts[4]; for (match = false, i = 0; i < sizeof (line_sizes) / sizeof (string); i++) if (line_size_string == line_sizes[i]) { --- 1135,1141 ---- return 0; int line_sz; ! string line_size_string = parts[4 + extra_ix]; for (match = false, i = 0; i < sizeof (line_sizes) / sizeof (string); i++) if (line_size_string == line_sizes[i]) { *************** CacheCreate (const string& typeName) *** 795,805 **** string replace_alg_string; if (assoc_string != "direct") ! if (parts.size () < 6) return 0; else { ! replace_alg_string = parts[5]; for (match = false, i = 0; i < sizeof (replacement_algorithms) / sizeof (string); i++) if (replace_alg_string == replacement_algorithms[i]) match = true; --- 1148,1158 ---- string replace_alg_string; if (assoc_string != "direct") ! if (parts.size () + extra_ix < 6) return 0; else { ! replace_alg_string = parts[5 + extra_ix]; for (match = false, i = 0; i < sizeof (replacement_algorithms) / sizeof (string); i++) if (replace_alg_string == replacement_algorithms[i]) match = true; *************** CacheCreate (const string& typeName) *** 823,837 **** return 0; } ! if (assoc == 1) ! return new cache_component (assoc, cache_sz, line_sz, null_replacement, internal_line_factory); ! if (replace_alg_string == "lru") ! return new cache_component (assoc, cache_sz, line_sz, lru_replacement, internal_line_factory); ! else if (replace_alg_string == "fifo") ! return new cache_component (assoc, cache_sz, line_sz, fifo_replacement, internal_line_factory); ! else if (replace_alg_string == "random") ! return new cache_component (assoc, cache_sz, line_sz, random_replacement, internal_line_factory); return 0; } --- 1176,1205 ---- return 0; } ! if (extra_ix == 0) ! { ! if (assoc == 1) ! return new cache_component (assoc, cache_sz, line_sz, null_replacement, internal_line_factory); ! ! if (replace_alg_string == "lru") ! return new cache_component (assoc, cache_sz, line_sz, lru_replacement, internal_line_factory); ! else if (replace_alg_string == "fifo") ! return new cache_component (assoc, cache_sz, line_sz, fifo_replacement, internal_line_factory); ! else if (replace_alg_string == "random") ! return new cache_component (assoc, cache_sz, line_sz, random_replacement, internal_line_factory); ! } ! else ! { ! if (assoc == 1) ! return new blocking_cache_component (assoc, cache_sz, line_sz, null_replacement, internal_line_factory); ! if (replace_alg_string == "lru") ! return new blocking_cache_component (assoc, cache_sz, line_sz, lru_replacement, internal_line_factory); ! else if (replace_alg_string == "fifo") ! return new blocking_cache_component (assoc, cache_sz, line_sz, fifo_replacement, internal_line_factory); ! else if (replace_alg_string == "random") ! return new blocking_cache_component (assoc, cache_sz, line_sz, random_replacement, internal_line_factory); ! } return 0; } Index: sid/component/cache/cache.h =================================================================== RCS file: /cvs/src/src/sid/component/cache/cache.h,v retrieving revision 1.10 diff -c -p -r1.10 cache.h *** sid/component/cache/cache.h 29 Apr 2004 20:26:08 -0000 1.10 --- sid/component/cache/cache.h 3 May 2005 20:42:14 -0000 *************** *** 7,30 **** #ifndef CACHE_H #define CACHE_H #include "cacheutil.h" using std::string; using std::vector; ! using sid::bus; ! using sid::component; ! using sid::host_int_2; ! using sid::host_int_4; using sidutil::fixed_attribute_map_component; using sidutil::fixed_bus_map_component; using sidutil::fixed_pin_map_component; using sidutil::fixed_accessor_map_component; using sidutil::no_relation_component; using sidutil::callback_pin; using sidutil::make_attribute; using sidutil::parse_attribute; class cache_component; class cache_bus: public bus --- 7,31 ---- #ifndef CACHE_H #define CACHE_H + #include "sidblockingutil.h" #include "cacheutil.h" using std::string; using std::vector; ! using namespace sid; using sidutil::fixed_attribute_map_component; using sidutil::fixed_bus_map_component; using sidutil::fixed_pin_map_component; using sidutil::fixed_accessor_map_component; using sidutil::no_relation_component; + using sidutil::blocking_component; using sidutil::callback_pin; using sidutil::make_attribute; using sidutil::parse_attribute; + using sidutil::binary_output_pin; + using sidutil::output_pin; class cache_component; class cache_bus: public bus *************** private: *** 46,59 **** bus::status write(host_int_4 addr, DataType data) throw (); \ bus::status read(host_int_4 addr, DataType& data) throw (); ! DEFN_METHOD (sid::big_int_1) ! DEFN_METHOD (sid::big_int_2) ! DEFN_METHOD (sid::big_int_4) ! DEFN_METHOD (sid::big_int_8) ! DEFN_METHOD (sid::little_int_1) ! DEFN_METHOD (sid::little_int_2) ! DEFN_METHOD (sid::little_int_4) ! DEFN_METHOD (sid::little_int_8) #undef DEFN_METHOD }; --- 47,60 ---- bus::status write(host_int_4 addr, DataType data) throw (); \ bus::status read(host_int_4 addr, DataType& data) throw (); ! DEFN_METHOD (big_int_1) ! DEFN_METHOD (big_int_2) ! DEFN_METHOD (big_int_4) ! DEFN_METHOD (big_int_8) ! DEFN_METHOD (little_int_1) ! DEFN_METHOD (little_int_2) ! DEFN_METHOD (little_int_4) ! DEFN_METHOD (little_int_8) #undef DEFN_METHOD }; *************** public: *** 98,106 **** class cache_component: public virtual component, ! protected fixed_attribute_map_component, protected fixed_bus_map_component, ! protected fixed_pin_map_component, protected fixed_accessor_map_component, protected no_relation_component { --- 99,107 ---- class cache_component: public virtual component, ! protected virtual fixed_attribute_map_component, protected fixed_bus_map_component, ! protected virtual fixed_pin_map_component, protected fixed_accessor_map_component, protected no_relation_component { *************** public: *** 111,116 **** --- 112,131 ---- virtual ~cache_component () throw(); + #define DEFN_METHOD(DataType) \ + virtual bus::status write(host_int_4 addr, DataType data) { return this->write_any(addr, data); } \ + virtual bus::status read(host_int_4 addr, DataType& data) { return this->read_any(addr, data); } + DEFN_METHOD (big_int_1) + DEFN_METHOD (big_int_2) + DEFN_METHOD (big_int_4) + DEFN_METHOD (big_int_8) + DEFN_METHOD (little_int_1) + DEFN_METHOD (little_int_2) + DEFN_METHOD (little_int_4) + DEFN_METHOD (little_int_8) + #undef DEFN_METHOD + + protected: template bus::status write_any (host_int_4 addr, DataType data); *************** protected: *** 127,168 **** void emit_report (host_int_4 ignore); callback_pin flush_all_pin; ! void flush_all_lines (host_int_4 ignore); callback_pin flush_pin; ! void flush_line (host_int_4 addr); callback_pin flush_set_pin; ! void flush_set (host_int_4 set); callback_pin flush_and_invalidate_set_pin; ! void flush_and_invalidate_set (host_int_4 set); callback_pin invalidate_all_pin; ! void invalidate_all_lines (host_int_4 ignore); callback_pin invalidate_pin; ! void invalidate_line (host_int_4 addr); callback_pin flush_and_invalidate_pin; ! void flush_and_invalidate_line (host_int_4 addr); callback_pin invalidate_set_pin; ! void invalidate_set (host_int_4 set); callback_pin prefetch_pin; ! void prefetch_line (host_int_4 addr); callback_pin lock_pin; ! void lock_line (host_int_4 addr); callback_pin unlock_pin; ! void unlock_line (host_int_4 addr); string read_hit_rate (); string write_hit_rate (); string get_nothing () { return ""; } ! status set_nothing (const string& ignore) { return sid::component::ok; } string associativity (); status dump (const string& ignore); string get_hash_mask (); --- 142,191 ---- void emit_report (host_int_4 ignore); callback_pin flush_all_pin; ! virtual void flush_all_lines (host_int_4 ignore); callback_pin flush_pin; ! virtual void flush_line (host_int_4 addr); callback_pin flush_set_pin; ! virtual void flush_set (host_int_4 set); callback_pin flush_and_invalidate_set_pin; ! virtual void flush_and_invalidate_set (host_int_4 set); callback_pin invalidate_all_pin; ! virtual void invalidate_all_lines (host_int_4 ignore); callback_pin invalidate_pin; ! virtual void invalidate_line (host_int_4 addr); callback_pin flush_and_invalidate_pin; ! virtual void flush_and_invalidate_line (host_int_4 addr); callback_pin invalidate_set_pin; ! virtual void invalidate_set (host_int_4 set); callback_pin prefetch_pin; ! virtual void prefetch_line (host_int_4 addr); callback_pin lock_pin; ! virtual void lock_line (host_int_4 addr); callback_pin unlock_pin; ! virtual void unlock_line (host_int_4 addr); ! ! // Completion status for the above operations ! output_pin operation_status_pin; ! void report_status (bus::status st) ! { ! host_int_4 v = (st.latency << 16) | st.code; ! operation_status_pin.drive (v); ! } string read_hit_rate (); string write_hit_rate (); string get_nothing () { return ""; } ! status set_nothing (const string& ignore) { return component::ok; } string associativity (); status dump (const string& ignore); string get_hash_mask (); *************** protected: *** 177,182 **** --- 200,215 ---- bus::status read_line (cache_line& line); bus::status write_line (cache_line& line); + template bus::status read_downstream (host_int_4 address, DataType &data); + template bus::status write_downstream (host_int_4 address, DataType data); + + // Handle read/write errors. The default is not to handle them. + virtual bool handle_read_error (bus::status s, host_int_4 &addr) { return false; } + virtual bool handle_write_error (bus::status s, host_int_4 &addr) { return false; } + + virtual void lock_downstream () { } + virtual void unlock_downstream () { } + bool write_allocate_p; bool write_through_p; bool collect_p; *************** protected: *** 198,236 **** unsigned line_size; unsigned cache_size; unsigned assoc; host_int_2 hit_latency; host_int_2 miss_latency; host_int_2 refill_latency; bool refill_latency_specified; }; template bus::status cache_bus::write_any (host_int_4 addr, DataType data) { ! return cache.write_any (addr, data); } template bus::status cache_bus::read_any (host_int_4 addr, DataType& data) { ! return cache.read_any (addr, data); } #define DEFN_METHOD(DataType) \ inline bus::status cache_bus::write(host_int_4 addr, DataType data) throw () { return this->write_any(addr, data); } \ inline bus::status cache_bus::read(host_int_4 addr, DataType& data) throw () { return this->read_any(addr, data); } ! DEFN_METHOD (sid::big_int_1) ! DEFN_METHOD (sid::big_int_2) ! DEFN_METHOD (sid::big_int_4) ! DEFN_METHOD (sid::big_int_8) ! DEFN_METHOD (sid::little_int_1) ! DEFN_METHOD (sid::little_int_2) ! DEFN_METHOD (sid::little_int_4) ! DEFN_METHOD (sid::little_int_8) #undef DEFN_METHOD #endif // CACHE_H --- 231,407 ---- unsigned line_size; unsigned cache_size; unsigned assoc; + unsigned data_width; host_int_2 hit_latency; host_int_2 miss_latency; host_int_2 refill_latency; bool refill_latency_specified; + bool total_latency_p; }; template bus::status cache_bus::write_any (host_int_4 addr, DataType data) { ! return cache.write (addr, data); } template bus::status cache_bus::read_any (host_int_4 addr, DataType& data) { ! return cache.read (addr, data); } #define DEFN_METHOD(DataType) \ inline bus::status cache_bus::write(host_int_4 addr, DataType data) throw () { return this->write_any(addr, data); } \ inline bus::status cache_bus::read(host_int_4 addr, DataType& data) throw () { return this->read_any(addr, data); } ! DEFN_METHOD (big_int_1) ! DEFN_METHOD (big_int_2) ! DEFN_METHOD (big_int_4) ! DEFN_METHOD (big_int_8) ! DEFN_METHOD (little_int_1) ! DEFN_METHOD (little_int_2) ! DEFN_METHOD (little_int_4) ! DEFN_METHOD (little_int_8) ! #undef DEFN_METHOD ! ! // This cache component handles bus::busy from downstream by blocking on ! // and waiting to retry. ! // ! class blocking_cache_component : ! public cache_component, public blocking_component ! { ! public: ! // For use when constructing directly ! blocking_cache_component (unsigned asoctvty, unsigned cache_sz, ! unsigned line_sz, ! cache_replacement_algorithm& replacer, ! cache_line_factory &line_factory); ! // For use by constructor of derived class ! blocking_cache_component (void *child_self, ! unsigned asoctvty, unsigned cache_sz, ! unsigned line_sz, ! cache_replacement_algorithm& replacer, ! cache_line_factory &line_factory); ! ! virtual ~blocking_cache_component () throw() {} ! ! #define DEFN_METHOD(DataType) \ ! virtual bus::status write(host_int_4 addr, DataType data); \ ! virtual bus::status read(host_int_4 addr, DataType& data); ! DEFN_METHOD (big_int_1) ! DEFN_METHOD (big_int_2) ! DEFN_METHOD (big_int_4) ! DEFN_METHOD (big_int_8) ! DEFN_METHOD (little_int_1) ! DEFN_METHOD (little_int_2) ! DEFN_METHOD (little_int_4) ! DEFN_METHOD (little_int_8) ! #undef DEFN_METHOD ! ! protected: ! // Virtual overrides ! virtual void flush_all_lines (host_int_4 ignore); ! virtual void flush_line (host_int_4 addr); ! virtual void flush_set (host_int_4 set); ! virtual void flush_and_invalidate_set (host_int_4 set); ! virtual void flush_and_invalidate_line (host_int_4 addr); ! virtual void prefetch_line (host_int_4 addr); ! ! protected: ! // Handle read/write errors. ! virtual bool handle_read_error (bus::status s, host_int_4 &addr) ! { return handle_bus_error (s); } ! virtual bool handle_write_error (bus::status s, host_int_4 &addr) ! { return handle_bus_error (s); } ! ! // Common function handles both read and write errors ! bool handle_bus_error (bus::status s); ! ! // Performing transactions on the child thread ! public: ! void perform_transaction () { (this->*transaction_func) (); } ! protected: ! host_int_4 transaction_addr; ! bus::status transaction_status; ! void (blocking_cache_component::*transaction_func)(); ! ! #define DEFN_METHOD(DataType) \ ! DataType transaction_data##DataType; \ ! void setup_read_transaction (host_int_4 addr, const DataType &data) \ ! { transaction_addr = addr; \ ! transaction_func = & blocking_cache_component::perform_read_transaction##DataType; \ ! } \ ! void setup_write_transaction (host_int_4 addr, const DataType &data) \ ! { transaction_addr = addr; \ ! transaction_data##DataType = data; \ ! transaction_func = & blocking_cache_component::perform_write_transaction##DataType; \ ! } \ ! void perform_read_transaction##DataType () \ ! { transaction_status = cache_component::read (transaction_addr, transaction_data##DataType); } \ ! void perform_write_transaction##DataType () \ ! { transaction_status = cache_component::write (transaction_addr, transaction_data##DataType); } \ ! void get_transaction_data (DataType &data) { data = transaction_data##DataType; } ! ! DEFN_METHOD (big_int_1) ! DEFN_METHOD (big_int_2) ! DEFN_METHOD (big_int_4) ! DEFN_METHOD (big_int_8) ! DEFN_METHOD (little_int_1) ! DEFN_METHOD (little_int_2) ! DEFN_METHOD (little_int_4) ! DEFN_METHOD (little_int_8) #undef DEFN_METHOD + protected: + // Setup methods for blockable transactions + // + void setup_flush_all_transaction () + { + transaction_func = & blocking_cache_component::perform_flush_all_transaction; + } + void setup_flush_line_transaction (host_int_4 addr) + { + transaction_addr = addr; + transaction_func = & blocking_cache_component::perform_flush_line_transaction; + } + void setup_flush_set_transaction (host_int_4 index) + { + transaction_addr = index; + transaction_func = & blocking_cache_component::perform_flush_set_transaction; + } + void setup_flush_and_invalidate_set_transaction (host_int_4 index) + { + transaction_addr = index; + transaction_func = & blocking_cache_component::perform_flush_and_invalidate_set_transaction; + } + void setup_flush_and_invalidate_line_transaction (host_int_4 addr) + { + transaction_addr = addr; + transaction_func = & blocking_cache_component::perform_flush_and_invalidate_line_transaction; + } + + protected: + // Work methods for blockable transactions + // + void perform_flush_all_transaction () + { cache_component::flush_all_lines (transaction_addr); } + void perform_flush_line_transaction () + { cache_component::flush_line (transaction_addr); } + void perform_flush_set_transaction () + { cache_component::flush_set (transaction_addr); } + void perform_flush_and_invalidate_set_transaction () + { cache_component::flush_and_invalidate_set (transaction_addr); } + void perform_flush_and_invalidate_line_transaction () + { cache_component::flush_and_invalidate_line (transaction_addr); } + + protected: + binary_output_pin downstream_lock_pin; + virtual void lock_downstream () { downstream_lock_pin.on (); } + virtual void unlock_downstream () { downstream_lock_pin.off (); } + }; + #endif // CACHE_H Index: sid/component/cache/cacheutil.cxx =================================================================== RCS file: /cvs/src/src/sid/component/cache/cacheutil.cxx,v retrieving revision 1.10 diff -c -p -r1.10 cacheutil.cxx *** sid/component/cache/cacheutil.cxx 20 Jul 2004 17:10:48 -0000 1.10 --- sid/component/cache/cacheutil.cxx 3 May 2005 20:42:14 -0000 *************** *** 1,6 **** // cacheutil.cxx -- Helper classes for a generic memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // cacheutil.cxx -- Helper classes for a generic memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004, 2005 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** cache::addr_to_tag (const sid::host_int_ *** 289,294 **** --- 289,300 ---- return addr >> num_non_tag_bits; } + unsigned + cache::addr_to_index (const sid::host_int_4& addr) const + { + return hash_fn (addr_to_tag (addr)); + } + sid::host_int_4 cache::tag_to_addr (const cache_tag& tag) const { Index: sid/component/cache/cacheutil.h =================================================================== RCS file: /cvs/src/src/sid/component/cache/cacheutil.h,v retrieving revision 1.7 diff -c -p -r1.7 cacheutil.h *** sid/component/cache/cacheutil.h 29 Apr 2004 20:26:08 -0000 1.7 --- sid/component/cache/cacheutil.h 3 May 2005 20:42:15 -0000 *************** *** 1,6 **** // cacheutil.h -- Helper classes for a generic memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // cacheutil.h -- Helper classes for a generic memory cache. -*- C++ -*- ! // Copyright (C) 2001, 2002, 2004, 2005 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** public: *** 270,275 **** --- 270,278 ---- // Calculate a tag. cache_tag addr_to_tag (const sid::host_int_4& addr) const; + // Calculate a set index. + unsigned addr_to_index (const sid::host_int_4& addr) const; + // Perform the inverse operation. sid::host_int_4 tag_to_addr (const cache_tag& tag) const; Index: sid/component/cache/hw-cache.xml =================================================================== RCS file: /cvs/src/src/sid/component/cache/hw-cache.xml,v retrieving revision 1.9 diff -c -p -r1.9 hw-cache.xml *** sid/component/cache/hw-cache.xml 16 Jul 2002 19:25:45 -0000 1.9 --- sid/component/cache/hw-cache.xml 3 May 2005 20:42:15 -0000 *************** *** 14,25 **** ! ! ! --- 14,25 ---- ! ! ! Index: sid/component/cgen-cpu/cgen-cpu.h =================================================================== RCS file: /cvs/src/src/sid/component/cgen-cpu/cgen-cpu.h,v retrieving revision 1.11 diff -c -p -r1.11 cgen-cpu.h *** sid/component/cgen-cpu/cgen-cpu.h 12 Feb 2005 16:25:45 -0000 1.11 --- sid/component/cgen-cpu/cgen-cpu.h 3 May 2005 20:42:15 -0000 *************** *** 25,30 **** --- 25,31 ---- #include "bfd.h" #include "dis-asm.h" + #include "opcode/cgen-bitset.h" // ansidecl.h interferes with this perfectly ordinary word #undef AND *************** public: *** 68,74 **** // Disassembly tracing support void disassemble (PCADDR pc, disassembler_ftype printfn, enum bfd_flavour flavour, enum bfd_architecture arch, ! enum bfd_endian endian, const char *name, unsigned long isa_mask = 0, int machine = 0); struct disassemble_info info; protected: static int cgen_read_memory (bfd_vma memaddr, bfd_byte *myaddr, --- 69,75 ---- // Disassembly tracing support void disassemble (PCADDR pc, disassembler_ftype printfn, enum bfd_flavour flavour, enum bfd_architecture arch, ! enum bfd_endian endian, const char *name, CGEN_BITSET *isas = NULL, int machine = 0); struct disassemble_info info; protected: static int cgen_read_memory (bfd_vma memaddr, bfd_byte *myaddr, *************** public: *** 88,192 **** public: // rtl memory access methods inline QI ! GETMEMQI(PCADDR pc, ADDR addr) const { return this->read_data_memory_1 (pc, addr); } inline UQI ! GETMEMUQI(PCADDR pc, ADDR addr) const { return this->read_data_memory_1 (pc, addr); } inline void ! SETMEMBI(PCADDR pc, ADDR addr, BI value) const { return this->write_insn_memory_1 (pc, addr, value); } inline void ! SETMEMQI(PCADDR pc, ADDR addr, QI value) const { return this->write_data_memory_1 (pc, addr, value); } inline void ! SETMEMUQI(PCADDR pc, ADDR addr, UQI value) const { return this->write_data_memory_1 (pc, addr, value); } inline HI ! GETMEMHI(PCADDR pc, ADDR addr) const { return this->read_data_memory_2 (pc, addr); } inline UHI ! GETMEMUHI(PCADDR pc, ADDR addr) const { return this->read_data_memory_2 (pc, addr); } inline void ! SETMEMHI(PCADDR pc, ADDR addr, HI value) const { return this->write_data_memory_2 (pc, addr, value); } inline void ! SETMEMUHI(PCADDR pc, ADDR addr, UHI value) const { return this->write_data_memory_2 (pc, addr, value); } inline SI ! GETMEMSI(PCADDR pc, ADDR addr) const { return this->read_data_memory_4 (pc, addr); } inline void ! SETMEMSI(PCADDR pc, ADDR addr, SI value) const { return this->write_data_memory_4 (pc, addr, value); } inline USI ! GETMEMUSI(PCADDR pc, ADDR addr) const { return this->read_data_memory_4 (pc, addr); } inline void ! SETMEMUSI(PCADDR pc, ADDR addr, USI value) const { return this->write_data_memory_4 (pc, addr, value); } inline DI ! GETMEMDI(PCADDR pc, ADDR addr) const { return this->read_data_memory_8 (pc, addr); } inline void ! SETMEMDI(PCADDR pc, ADDR addr, DI value) const { return this->write_data_memory_8 (pc, addr, value); } inline void ! SETMEMUDI(PCADDR pc, ADDR addr, UDI value) const { return this->write_data_memory_8 (pc, addr, value); } // floats (can you think of a better way to do this?) inline SF ! GETMEMSF(PCADDR pc, IADDR addr) const { return reinterpret_cast(this->read_insn_memory_4 (pc, addr)); } inline void ! SETMEMSF(PCADDR pc, ADDR addr, SF value) const { return this->write_insn_memory_4 (pc, addr, reinterpret_cast(value)); } inline DF ! GETMEMDF(PCADDR pc, IADDR addr) const { return reinterpret_cast(this->read_insn_memory_8 (pc, addr)); } inline void ! SETMEMDF(PCADDR pc, ADDR addr, DF value) const { return this->write_insn_memory_8 (pc, addr, reinterpret_cast(value)); } --- 89,193 ---- public: // rtl memory access methods inline QI ! GETMEMQI(PCADDR pc, ADDR addr) { return this->read_data_memory_1 (pc, addr); } inline UQI ! GETMEMUQI(PCADDR pc, ADDR addr) { return this->read_data_memory_1 (pc, addr); } inline void ! SETMEMBI(PCADDR pc, ADDR addr, BI value) { return this->write_insn_memory_1 (pc, addr, value); } inline void ! SETMEMQI(PCADDR pc, ADDR addr, QI value) { return this->write_data_memory_1 (pc, addr, value); } inline void ! SETMEMUQI(PCADDR pc, ADDR addr, UQI value) { return this->write_data_memory_1 (pc, addr, value); } inline HI ! GETMEMHI(PCADDR pc, ADDR addr) { return this->read_data_memory_2 (pc, addr); } inline UHI ! GETMEMUHI(PCADDR pc, ADDR addr) { return this->read_data_memory_2 (pc, addr); } inline void ! SETMEMHI(PCADDR pc, ADDR addr, HI value) { return this->write_data_memory_2 (pc, addr, value); } inline void ! SETMEMUHI(PCADDR pc, ADDR addr, UHI value) { return this->write_data_memory_2 (pc, addr, value); } inline SI ! GETMEMSI(PCADDR pc, ADDR addr) { return this->read_data_memory_4 (pc, addr); } inline void ! SETMEMSI(PCADDR pc, ADDR addr, SI value) { return this->write_data_memory_4 (pc, addr, value); } inline USI ! GETMEMUSI(PCADDR pc, ADDR addr) { return this->read_data_memory_4 (pc, addr); } inline void ! SETMEMUSI(PCADDR pc, ADDR addr, USI value) { return this->write_data_memory_4 (pc, addr, value); } inline DI ! GETMEMDI(PCADDR pc, ADDR addr) { return this->read_data_memory_8 (pc, addr); } inline void ! SETMEMDI(PCADDR pc, ADDR addr, DI value) { return this->write_data_memory_8 (pc, addr, value); } inline void ! SETMEMUDI(PCADDR pc, ADDR addr, UDI value) { return this->write_data_memory_8 (pc, addr, value); } // floats (can you think of a better way to do this?) inline SF ! GETMEMSF(PCADDR pc, IADDR addr) { return reinterpret_cast(this->read_insn_memory_4 (pc, addr)); } inline void ! SETMEMSF(PCADDR pc, ADDR addr, SF value) { return this->write_insn_memory_4 (pc, addr, reinterpret_cast(value)); } inline DF ! GETMEMDF(PCADDR pc, IADDR addr) { return reinterpret_cast(this->read_insn_memory_8 (pc, addr)); } inline void ! SETMEMDF(PCADDR pc, ADDR addr, DF value) { return this->write_insn_memory_8 (pc, addr, reinterpret_cast(value)); } *************** public: *** 194,275 **** // IMEM: instruction memory calls inline QI ! GETIMEMQI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_1 (pc, addr); } inline void ! SETIMEMQI(PCADDR pc, ADDR addr, QI value) const { return this->write_insn_memory_1 (pc, addr, value); } inline UQI ! GETIMEMUQI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_1 (pc, addr); } inline void ! SETIMEMUQI(PCADDR pc, ADDR addr, UQI value) const { return this->write_insn_memory_1 (pc, addr, value); } inline HI ! GETIMEMHI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_2 (pc, addr); } inline void ! SETIMEMHI(PCADDR pc, ADDR addr, HI value) const { return this->write_insn_memory_2 (pc, addr, value); } inline UHI ! GETIMEMUHI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_2 (pc, addr); } inline void ! SETIMEMUHI(PCADDR pc, ADDR addr, UHI value) const { return this->write_insn_memory_2 (pc, addr, value); } inline SI ! GETIMEMSI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_4 (pc, addr); } inline void ! SETIMEMSI(PCADDR pc, ADDR addr, SI value) const { return this->write_insn_memory_4 (pc, addr, value); } inline USI ! GETIMEMUSI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_4 (pc, addr); } inline void ! SETIMEMUSI(PCADDR pc, ADDR addr, USI value) const { return this->write_insn_memory_4 (pc, addr, value); } inline DI ! GETIMEMDI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_8 (pc, addr); } inline void ! SETIMEMDI(PCADDR pc, ADDR addr, DI value) const { return this->write_insn_memory_8 (pc, addr, value); } inline UDI ! GETIMEMUDI(PCADDR pc, IADDR addr) const { return this->read_insn_memory_8 (pc, addr); } inline void ! SETIMEMUDI(PCADDR pc, ADDR addr, UDI value) const { return this->write_insn_memory_8 (pc, addr, value); } --- 195,276 ---- // IMEM: instruction memory calls inline QI ! GETIMEMQI(PCADDR pc, IADDR addr) { return this->read_insn_memory_1 (pc, addr); } inline void ! SETIMEMQI(PCADDR pc, ADDR addr, QI value) { return this->write_insn_memory_1 (pc, addr, value); } inline UQI ! GETIMEMUQI(PCADDR pc, IADDR addr) { return this->read_insn_memory_1 (pc, addr); } inline void ! SETIMEMUQI(PCADDR pc, ADDR addr, UQI value) { return this->write_insn_memory_1 (pc, addr, value); } inline HI ! GETIMEMHI(PCADDR pc, IADDR addr) { return this->read_insn_memory_2 (pc, addr); } inline void ! SETIMEMHI(PCADDR pc, ADDR addr, HI value) { return this->write_insn_memory_2 (pc, addr, value); } inline UHI ! GETIMEMUHI(PCADDR pc, IADDR addr) { return this->read_insn_memory_2 (pc, addr); } inline void ! SETIMEMUHI(PCADDR pc, ADDR addr, UHI value) { return this->write_insn_memory_2 (pc, addr, value); } inline SI ! GETIMEMSI(PCADDR pc, IADDR addr) { return this->read_insn_memory_4 (pc, addr); } inline void ! SETIMEMSI(PCADDR pc, ADDR addr, SI value) { return this->write_insn_memory_4 (pc, addr, value); } inline USI ! GETIMEMUSI(PCADDR pc, IADDR addr) { return this->read_insn_memory_4 (pc, addr); } inline void ! SETIMEMUSI(PCADDR pc, ADDR addr, USI value) { return this->write_insn_memory_4 (pc, addr, value); } inline DI ! GETIMEMDI(PCADDR pc, IADDR addr) { return this->read_insn_memory_8 (pc, addr); } inline void ! SETIMEMDI(PCADDR pc, ADDR addr, DI value) { return this->write_insn_memory_8 (pc, addr, value); } inline UDI ! GETIMEMUDI(PCADDR pc, IADDR addr) { return this->read_insn_memory_8 (pc, addr); } inline void ! SETIMEMUDI(PCADDR pc, ADDR addr, UDI value) { return this->write_insn_memory_8 (pc, addr, value); } Index: sid/include/sidattrutil.h =================================================================== RCS file: /cvs/src/src/sid/include/sidattrutil.h,v retrieving revision 1.6 diff -c -p -r1.6 sidattrutil.h *** sid/include/sidattrutil.h 21 Oct 2003 21:38:24 -0000 1.6 --- sid/include/sidattrutil.h 3 May 2005 20:42:16 -0000 *************** make_attribute (const sid::any_intoutput_saved_messages (); - #if SID_LOG_PERSISTENT_BUFFER - delete [] buffer; - #endif } void log (sid::host_int_4 level, const char *fmt, ...) --- 1022,1045 ---- : public virtual fixed_attribute_map_component, public virtual fixed_pin_map_component { protected: fixed_attribute_map_with_logging_component () : ulog_level (0), ulog_mode ("less"), ulog_out_pin (), ! buffer_output (true) { add_attribute ("buffer-output", &buffer_output, "setting"); add_attribute ("ulog-level", &ulog_level, "setting"); add_attribute ("ulog-mode", &ulog_mode, "setting"); add_pin ("ulog-out", & ulog_out_pin); ulog_logger = new logger (& ulog_out_pin, buffer_output, ulog_level, ulog_mode); } ~fixed_attribute_map_with_logging_component () throw() { // Output any saved messages. // output_saved_messages (); ulog_logger->output_saved_messages (); } void log (sid::host_int_4 level, const char *fmt, ...) *************** make_attribute (const sid::any_intcheck_level (level); ! } ! ! void output_saved_messages () { ! while (saved_messages.size () > 0) ! { ! if (check_level (saved_levels[0])) ! { ! std::string s = saved_messages[0]; ! for (int i = 0; i < s.size (); ++i) ! ulog_out_pin.drive (s[i]); ! } ! saved_messages.erase (saved_messages.begin ()); ! saved_levels.erase (saved_levels.begin ()); ! } } - sid::host_int_4 ulog_level; std::string ulog_mode; sidutil::output_pin ulog_out_pin; bool buffer_output; sidutil::logger *ulog_logger; - char *buffer; - long buffer_size; - std::vector saved_messages; - std::vector saved_levels; - #undef SID_LOG_PERSISTENT_BUFFER - #undef SID_LOG_TRANSIENT_MALLOC_BUFFER }; } --- 1052,1067 ---- va_end (ap); } ! protected: ! bool check_level (sid::host_int_4 level) const { ! return ulog_logger->check_level (level); } sid::host_int_4 ulog_level; std::string ulog_mode; sidutil::output_pin ulog_out_pin; bool buffer_output; sidutil::logger *ulog_logger; }; } Index: sid/include/sidbusutil.h =================================================================== RCS file: /cvs/src/src/sid/include/sidbusutil.h,v retrieving revision 1.14 diff -c -p -r1.14 sidbusutil.h *** sid/include/sidbusutil.h 21 Oct 2003 21:38:24 -0000 1.14 --- sid/include/sidbusutil.h 3 May 2005 20:42:16 -0000 *************** *** 1,6 **** // sidbusutil.h -*- C++ -*- Different types and sizes of buses. ! // Copyright (C) 1999, 2000, 2001, 2002 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,6 ---- // sidbusutil.h -*- C++ -*- Different types and sizes of buses. ! // Copyright (C) 1999, 2000, 2001, 2002, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** *** 9,14 **** --- 9,18 ---- #include #include + #include + #include + #include + #include #include #include *************** namespace sidutil *** 52,59 **** --- 56,65 ---- sid::host_int_4 a = address; unsigned bytesWritten = 0; + sid::host_int_2 max_latency = 0; DataType d = 0; DataType mask = 0; + sid::bus::status s; while(bytesWritten < accWidth) { sid::host_int_1 byte = data.read_byte(bytesWritten); *************** namespace sidutil *** 63,69 **** if(((bytesWritten + a) % busWidth == (busWidth - 1)) || // last byte in target (bytesWritten == (accWidth - 1))) // last byte in source { - sid::bus::status s; s = this->word_write(sid::host_int_4(a / busWidth), mask, d); if (s != sid::bus::ok) --- 69,74 ---- *************** namespace sidutil *** 71,76 **** --- 76,83 ---- this->post_access_hook(); return s; } + if (s.latency > max_latency) + max_latency = s.latency; a = a + busWidth; // advance address // Clear data. *************** namespace sidutil *** 82,88 **** } this->post_access_hook(); ! return sid::bus::ok; } --- 89,96 ---- } this->post_access_hook(); ! s.latency = max_latency; ! return s; } *************** namespace sidutil *** 101,107 **** --- 109,117 ---- unsigned bytesRead = 0; unsigned bytesAddressed = 0; + sid::host_int_2 max_latency = 0; DataType mask = 0; + sid::bus::status s; while(bytesAddressed < accWidth) { mask.write_byte((bytesAddressed + a) % busWidth, 0xff); *************** namespace sidutil *** 109,116 **** if(((bytesAddressed + a) % busWidth == (busWidth - 1)) || // last byte in target (bytesAddressed == (accWidth - 1))) // last byte in source { - sid::bus::status s; - DataType d = 0; s = this->word_read(sid::host_int_4(a / busWidth), mask, d); if (s != sid::bus::ok) --- 119,124 ---- *************** namespace sidutil *** 118,123 **** --- 126,133 ---- this->post_access_hook(); return s; } + if (s.latency > max_latency) + max_latency = s.latency; // Copy over newly read bytes while (bytesRead <= bytesAddressed) *************** namespace sidutil *** 138,144 **** assert (bytesAddressed == bytesRead); this->post_access_hook(); ! return sid::bus::ok; } --- 148,155 ---- assert (bytesAddressed == bytesRead); this->post_access_hook(); ! s.latency = max_latency; ! return s; } *************** namespace sidutil *** 1180,1185 **** --- 1191,1464 ---- typedef std::map bus_map_t; mutable bus_map_t bus_map; }; + + // Following class is a virtual base class used for implementing bus + // arbitrators. + class bus_arbitrator: public virtual sid::component, + protected fixed_bus_map_component, + protected virtual fixed_pin_map_component, + protected fixed_accessor_map_component, + protected no_relation_component, + public fixed_attribute_map_with_logging_component + { + public: + bus_arbitrator () : + sched ("step", this, & bus_arbitrator::step_cycle) + { + // Attributes + add_attribute ("name", &name); + // Control pins + // + add_pin ("running", & running_pin); + running_pin.set_active_high (); + add_pin ("active", & active_pin); + active_pin.set_active_high (); + add_pin ("passthrough", & passthrough_pin); + passthrough_pin.set_active_high (); + } + ~bus_arbitrator () throw () { } + + protected: + // A bus for requests from the input interfaces. + // + class input_interface : public sid::bus + { + public: + input_interface (bus_arbitrator *h, int us) : host (h), upstream (us) { } + + #define SID_GB_WRITE(dtype) \ + sid::bus::status write(sid::host_int_4 addr, dtype data) throw ()\ + { return host->write(upstream, addr, data); } + + #define SID_GB_READ(dtype) \ + sid::bus::status read(sid::host_int_4 addr, dtype& data) throw ()\ + { return host->read(upstream, addr, data); } + + SID_GB_WRITE(sid::little_int_1) + SID_GB_WRITE(sid::big_int_1) + SID_GB_WRITE(sid::little_int_2) + SID_GB_WRITE(sid::big_int_2) + SID_GB_WRITE(sid::little_int_4) + SID_GB_WRITE(sid::big_int_4) + SID_GB_WRITE(sid::little_int_8) + SID_GB_WRITE(sid::big_int_8) + + SID_GB_READ(sid::little_int_1) + SID_GB_READ(sid::big_int_1) + SID_GB_READ(sid::little_int_2) + SID_GB_READ(sid::big_int_2) + SID_GB_READ(sid::little_int_4) + SID_GB_READ(sid::big_int_4) + SID_GB_READ(sid::little_int_8) + SID_GB_READ(sid::big_int_8) + + #undef SID_GB_WRITE + #undef SID_GB_READ + private: + bus_arbitrator *host; + int upstream; + }; + friend class input_interface; + + // A struct representing a bus request + struct bus_request + { + bus_request () {} + bus_request (bool r, int us, int ds, sid::host_int_4 a, unsigned s) + : is_read(r), upstream(us), downstream(ds), addr(a), size(s) + { } + bool operator== (const bus_request &r) + { + return is_read == r.is_read + && upstream == r.upstream + && downstream == r.downstream + && addr == r.addr + && size == r.size; + } + bool is_read; + int upstream; + int downstream; + sid::host_int_4 addr; + unsigned size; + }; + + protected: + // Handlers for input interfaces + // + template + sid::bus::status + write(int upstream, sid::host_int_4 addr, DataType data) + { + if (ulog_level >= 8 || ! check_passthrough ()) + log (5, "%s: received write request from %s interface at 0x%x\n", + name.c_str (), up2str(upstream), addr); + return arbitrate_write (upstream, downstream_for_address (addr), addr, data); + } + + template + sid::bus::status + read(int upstream, sid::host_int_4 addr, DataType& data) + { + if (ulog_level >= 8 || ! check_passthrough ()) + log (5, "%s: received read request from %s interface at 0x%x\n", + name.c_str (), up2str(upstream), addr); + return arbitrate_read (upstream, downstream_for_address (addr), addr, data); + } + + virtual const char *up2str (int upstream) = 0; + virtual int downstream_for_address (sid::host_int_4 address) = 0; + + protected: + // Advance time + // + virtual void step_cycle () + { + log (5, "%s: Stepping\n", name.c_str()); + update_busy_routes (); + } + + virtual void reschedule (sid::host_int_2 latency) + { + if (latency) + { + log (5, "%s: rescheduling (%d)\n", name.c_str (), latency); + sched.schedule_irregular (1); + } + } + + // Methods for arbitration + // + template + sid::bus::status arbitrate_read (int upstream, + int downstream, + sid::host_int_4 addr, + DataType& data) + { + // Check for direct passthrough + if (check_passthrough ()) + return downstream_bus (downstream)->read (addr, data); + + // Prioritize the request + // Execute it if it's ready + bus_request r (true, upstream, downstream, addr, sizeof (data)); + if (prioritize_request (r)) + return perform_read (r, data); + + return busy_status (); + } + + template + sid::bus::status arbitrate_write (int upstream, + int downstream, + sid::host_int_4 addr, + DataType data) + { + // Check for direct passthrough + if (check_passthrough ()) + return downstream_bus (downstream)->write(addr, data); + + // Prioritize the request + // Execute it if it's ready + bus_request r (false, upstream, downstream, addr, sizeof (data)); + if (prioritize_request (r)) + return perform_write (r, data); + + return busy_status (); + } + + // Provide a default implementation which does no prioritization and + // handles the requests right away as they arrive. + virtual bool prioritize_request (bus_request &r) { return true; } + + // Methods for downstream accessors + // + template + sid::bus::status perform_read (bus_request &r, DataType &data) + { + // See if the route is available + if (check_route_busy (r.upstream, r.downstream)) + return busy_status (); + + // Propagate any locked pin from upstream + lock_downstream (r.upstream, r.downstream); + + // Perform the read + sid::bus::status s = downstream_bus (r.downstream)->read (r.addr, data); + + // Update status + if (s == sid::bus::ok) + s = set_route_busy (r, s); + return s; + } + + template + sid::bus::status perform_write (bus_request &r, DataType data) + { + // See if the route is available + if (check_route_busy (r.upstream, r.downstream)) + return busy_status (); + + // Propogate any locked pin from upstream + lock_downstream (r.upstream, r.downstream); + + // Perform the write + sid::bus::status s = downstream_bus (r.downstream)->write (r.addr, data); + + // Update status + if (s == sid::bus::ok) + s = set_route_busy (r, s); + return s; + } + + bool check_passthrough () + { + if (passthrough_pin.state () == binary_pin_active) + { + log (8, "%s: passthrough enabled\n", name.c_str ()); + return true; + } + + if (running_pin.state () != binary_pin_active + || active_pin.state () != binary_pin_active) + { + log (8, "%s: system is idle -- passthrough\n", name.c_str ()); + return true; + } + return false; + } + + protected: + // Route locking + // + virtual void lock_downstream (int upstream, int downstream) { } + + virtual bool check_route_busy (int upstream, int downstream) { return false; } + + virtual sid::bus::status set_route_busy (bus_request &r, sid::bus::status s) { return s; } + virtual void update_busy_routes () {} + virtual sid::bus::status busy_status () + { + // Default - busy for 1 cycle + sid::bus::status s (sid::bus::busy, 1); + return s; + } + + virtual sid::bus *downstream_bus (int downstream) = 0; + + protected: + scheduler_event_subscription sched; + // This class must be a friend of scheduler_event_subscription. + friend class scheduler_event_subscription; + + // Attributes + string name; + + // Control pins + // + binary_input_pin running_pin; + binary_input_pin active_pin; + binary_input_pin passthrough_pin; + }; } Index: sid/include/sidcomp.h =================================================================== RCS file: /cvs/src/src/sid/include/sidcomp.h,v retrieving revision 1.5 diff -c -p -r1.5 sidcomp.h *** sid/include/sidcomp.h 25 Jun 2001 01:45:28 -0000 1.5 --- sid/include/sidcomp.h 3 May 2005 20:42:16 -0000 *************** *** 1,7 **** // sidcomp.h - Define the external interface of a SID component, that // is, the SID component API expressed in -*- C++ -*-. ! // Copyright (C) 1999, 2000, 2001 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. --- 1,7 ---- // sidcomp.h - Define the external interface of a SID component, that // is, the SID component API expressed in -*- C++ -*-. ! // Copyright (C) 1999, 2000, 2001, 2004 Red Hat. // This file is part of SID and is licensed under the GPL. // See the file COPYING.SID for conditions for redistribution. *************** namespace sid *** 45,50 **** --- 45,51 ---- misaligned = 0x01, // address misaligned unmapped = 0x02, // address not in mapped range unpermitted = 0x04, // may not read or may not write at address + busy = 0x05 // target component is busy }; struct status Index: sid/include/sidcpuutil.h =================================================================== RCS file: /cvs/src/src/sid/include/sidcpuutil.h,v retrieving revision 1.29 diff -c -p -r1.29 sidcpuutil.h *** sid/include/sidcpuutil.h 29 Jun 2004 19:10:41 -0000 1.29 --- sid/include/sidcpuutil.h 3 May 2005 20:42:17 -0000 *************** namespace sidutil *** 101,111 **** class basic_cpu: public virtual sid::component, ! protected fixed_pin_map_component, ! protected fixed_accessor_map_component, ! protected fixed_attribute_map_component, ! protected fixed_relation_map_component, ! protected fixed_bus_map_component { // custom memory allocators for poisioning freshly-allocated memory public: --- 101,111 ---- class basic_cpu: public virtual sid::component, ! protected virtual fixed_pin_map_component, ! protected virtual fixed_accessor_map_component, ! protected virtual fixed_attribute_map_component, ! protected virtual fixed_relation_map_component, ! protected virtual fixed_bus_map_component { // custom memory allocators for poisioning freshly-allocated memory public: *************** namespace sidutil *** 260,266 **** bool enable_step_trap_p; cpu_trace_stream trace_stream; ! void step_pin_handler (sid::host_int_4) { recursion_record limit (& this->step_limit); if (UNLIKELY(! limit.ok())) return; --- 260,266 ---- bool enable_step_trap_p; cpu_trace_stream trace_stream; ! virtual void step_pin_handler (sid::host_int_4) { recursion_record limit (& this->step_limit); if (UNLIKELY(! limit.ok())) return; *************** namespace sidutil *** 530,542 **** protected: template ! BigOrLittleInt read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const; template ! BigOrLittleInt write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const; template ! BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const; template ! BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const; // ------------------------------------------------------------------------ --- 530,552 ---- protected: template ! BigOrLittleInt read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt); template ! BigOrLittleInt write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value); template ! BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt); template ! BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value); ! ! virtual bool handle_insn_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return false; } ! virtual bool handle_insn_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return false; } ! virtual bool handle_data_memory_read_error (sid::bus::status s, sid::host_int_4 & address) { return false; } ! virtual bool handle_data_memory_write_error (sid::bus::status s, sid::host_int_4 & address) { return false; } ! ! virtual void record_insn_memory_read_latency (sid::bus::status s) { total_latency += s.latency; } ! virtual void record_insn_memory_write_latency (sid::bus::status s) { total_latency += s.latency; } ! virtual void record_data_memory_read_latency (sid::bus::status s) { total_latency += s.latency; } ! virtual void record_data_memory_write_latency (sid::bus::status s) { total_latency += s.latency; } // ------------------------------------------------------------------------ *************** public: *** 642,704 **** } template ! BigOrLittleInt basic_cpu::read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const { - BigOrLittleInt value; sid::bus::status s; ! if (LIKELY(this->insn_bus)) ! s = this->insn_bus->read (address, value); ! else ! s = sid::bus::unmapped; ! total_latency += s.latency; ! if (LIKELY(s == sid::bus::ok)) ! return value; throw cpu_memory_fault (pc, address, s, "insn read"); } template ! BigOrLittleInt basic_cpu::write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const { sid::bus::status s; ! if (LIKELY(this->insn_bus)) ! s = this->insn_bus->write (address, value); ! else ! s = sid::bus::unmapped; ! total_latency += s.latency; ! if (LIKELY(s == sid::bus::ok)) ! return value; throw cpu_memory_fault (pc, address, s, "insn write"); } template ! BigOrLittleInt basic_cpu::read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const { - BigOrLittleInt value; sid::bus::status s; ! if (LIKELY(this->data_bus)) ! s = this->data_bus->read (address, value); ! else ! s = sid::bus::unmapped; ! total_latency += s.latency; ! if (LIKELY(s == sid::bus::ok)) ! return value; throw cpu_memory_fault (pc, address, s, "data read"); } template ! BigOrLittleInt basic_cpu::write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const { sid::bus::status s; ! if (LIKELY(this->data_bus)) ! s = this->data_bus->write (address, value); ! else ! s = sid::bus::unmapped; ! total_latency += s.latency; ! if (LIKELY(s == sid::bus::ok)) ! return value; throw cpu_memory_fault (pc, address, s, "data write"); } --- 652,750 ---- } template ! BigOrLittleInt basic_cpu::read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) { sid::bus::status s; ! do ! { ! BigOrLittleInt value; ! if (LIKELY(this->insn_bus)) ! { ! s = this->insn_bus->read (address, value); ! if (LIKELY(s == sid::bus::ok)) ! { ! if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency)) ! record_insn_memory_read_latency (s); ! return value; ! } ! } ! else ! s = sid::bus::unmapped; ! } ! while (UNLIKELY (handle_insn_memory_read_error (s, address))); throw cpu_memory_fault (pc, address, s, "insn read"); } template ! BigOrLittleInt basic_cpu::write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) { sid::bus::status s; ! do ! { ! if (LIKELY(this->insn_bus)) ! { ! s = this->insn_bus->write (address, value); ! if (LIKELY(s == sid::bus::ok)) ! { ! if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency)) ! record_insn_memory_write_latency (s); ! return value; ! } ! } ! else ! s = sid::bus::unmapped; ! } ! while (UNLIKELY (handle_insn_memory_read_error (s, address))); throw cpu_memory_fault (pc, address, s, "insn write"); } template ! BigOrLittleInt basic_cpu::read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) { sid::bus::status s; ! do ! { ! BigOrLittleInt value; ! if (LIKELY(this->data_bus)) ! { ! s = this->data_bus->read (address, value); ! if (LIKELY(s == sid::bus::ok)) ! { ! if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency)) ! record_data_memory_read_latency (s); ! return value; ! } ! } ! else ! s = sid::bus::unmapped; ! } ! while (UNLIKELY (handle_insn_memory_read_error (s, address))); throw cpu_memory_fault (pc, address, s, "data read"); } template ! BigOrLittleInt basic_cpu::write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) { sid::bus::status s; ! do ! { ! if (LIKELY(this->data_bus)) ! { ! s = this->data_bus->write (address, value); ! if (LIKELY(s == sid::bus::ok)) ! { ! if (UNLIKELY ((trace_counter_p || final_insn_count_p) && s.latency)) ! record_data_memory_write_latency (s); ! return value; ! } ! } ! else ! s = sid::bus::unmapped; ! } ! while (UNLIKELY (handle_insn_memory_read_error (s, address))); throw cpu_memory_fault (pc, address, s, "data write"); } *************** public: *** 721,802 **** } ~basic_big_endian_cpu () throw() {} ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::big_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { this->write_insn_memory (pc, address, sid::big_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { this->write_insn_memory (pc, address, sid::big_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { this->write_insn_memory (pc, address, sid::big_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { this->write_insn_memory (pc, address, sid::big_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::big_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { this->write_data_memory (pc, address, sid::big_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { this->write_data_memory (pc, address, sid::big_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { this->write_data_memory (pc, address, sid::big_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { this->write_data_memory (pc, address, sid::big_int_8(value)); } --- 767,848 ---- } ~basic_big_endian_cpu () throw() {} ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::big_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { this->write_insn_memory (pc, address, sid::big_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { this->write_insn_memory (pc, address, sid::big_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { this->write_insn_memory (pc, address, sid::big_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { this->write_insn_memory (pc, address, sid::big_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::big_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { this->write_data_memory (pc, address, sid::big_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { this->write_data_memory (pc, address, sid::big_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { this->write_data_memory (pc, address, sid::big_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { this->write_data_memory (pc, address, sid::big_int_8(value)); } *************** public: *** 817,898 **** } ~basic_little_endian_cpu () throw() {} ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::little_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::little_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::little_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_insn_memory (pc, address, sid::little_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { this->write_insn_memory (pc, address, sid::little_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { this->write_insn_memory (pc, address, sid::little_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { this->write_insn_memory (pc, address, sid::little_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { this->write_insn_memory (pc, address, sid::little_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::little_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::little_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::little_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { return this->read_data_memory (pc, address, sid::little_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { this->write_data_memory (pc, address, sid::little_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { this->write_data_memory (pc, address, sid::little_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { this->write_data_memory (pc, address, sid::little_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { this->write_data_memory (pc, address, sid::little_int_8(value)); } --- 863,944 ---- } ~basic_little_endian_cpu () throw() {} ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::little_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::little_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::little_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_insn_memory (pc, address, sid::little_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { this->write_insn_memory (pc, address, sid::little_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { this->write_insn_memory (pc, address, sid::little_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { this->write_insn_memory (pc, address, sid::little_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { this->write_insn_memory (pc, address, sid::little_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::little_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::little_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::little_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { return this->read_data_memory (pc, address, sid::little_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { this->write_data_memory (pc, address, sid::little_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { this->write_data_memory (pc, address, sid::little_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { this->write_data_memory (pc, address, sid::little_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { this->write_data_memory (pc, address, sid::little_int_8(value)); } *************** public: *** 945,951 **** } ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_1()); --- 991,997 ---- } ! sid::host_int_1 read_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_1()); *************** public: *** 953,959 **** return this->read_insn_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_2()); --- 999,1005 ---- return this->read_insn_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_2()); *************** public: *** 961,967 **** return this->read_insn_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_4()); --- 1007,1013 ---- return this->read_insn_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_4()); *************** public: *** 969,975 **** return this->read_insn_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_8()); --- 1015,1021 ---- return this->read_insn_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_insn_memory (pc, address, sid::little_int_8()); *************** public: *** 977,983 **** return this->read_insn_memory (pc, address, sid::big_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_1(value)); --- 1023,1029 ---- return this->read_insn_memory (pc, address, sid::big_int_8()); } ! void write_insn_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_1(value)); *************** public: *** 985,991 **** this->write_insn_memory (pc, address, sid::big_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_2(value)); --- 1031,1037 ---- this->write_insn_memory (pc, address, sid::big_int_1(value)); } ! void write_insn_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_2(value)); *************** public: *** 993,999 **** this->write_insn_memory (pc, address, sid::big_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_4(value)); --- 1039,1045 ---- this->write_insn_memory (pc, address, sid::big_int_2(value)); } ! void write_insn_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_4(value)); *************** public: *** 1001,1007 **** this->write_insn_memory (pc, address, sid::big_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_8(value)); --- 1047,1053 ---- this->write_insn_memory (pc, address, sid::big_int_4(value)); } ! void write_insn_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { if (this->_current_endianness == endian_little) this->write_insn_memory (pc, address, sid::little_int_8(value)); *************** public: *** 1009,1015 **** this->write_insn_memory (pc, address, sid::big_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_1()); --- 1055,1061 ---- this->write_insn_memory (pc, address, sid::big_int_8(value)); } ! sid::host_int_1 read_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_1()); *************** public: *** 1017,1023 **** return this->read_data_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_2()); --- 1063,1069 ---- return this->read_data_memory (pc, address, sid::big_int_1()); } ! sid::host_int_2 read_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_2()); *************** public: *** 1025,1031 **** return this->read_data_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_4()); --- 1071,1077 ---- return this->read_data_memory (pc, address, sid::big_int_2()); } ! sid::host_int_4 read_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_4()); *************** public: *** 1033,1039 **** return this->read_data_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) const { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_8()); --- 1079,1085 ---- return this->read_data_memory (pc, address, sid::big_int_4()); } ! sid::host_int_8 read_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address) { if (this->_current_endianness == endian_little) return this->read_data_memory (pc, address, sid::little_int_8()); *************** public: *** 1041,1047 **** return this->read_data_memory (pc, address, sid::big_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) const { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_1(value)); --- 1087,1093 ---- return this->read_data_memory (pc, address, sid::big_int_8()); } ! void write_data_memory_1 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_1 value) { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_1(value)); *************** public: *** 1049,1055 **** this->write_data_memory (pc, address, sid::big_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) const { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_2(value)); --- 1095,1101 ---- this->write_data_memory (pc, address, sid::big_int_1(value)); } ! void write_data_memory_2 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_2 value) { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_2(value)); *************** public: *** 1057,1063 **** this->write_data_memory (pc, address, sid::big_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) const { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_4(value)); --- 1103,1109 ---- this->write_data_memory (pc, address, sid::big_int_2(value)); } ! void write_data_memory_4 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_4 value) { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_4(value)); *************** public: *** 1065,1071 **** this->write_data_memory (pc, address, sid::big_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) const { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_8(value)); --- 1111,1117 ---- this->write_data_memory (pc, address, sid::big_int_4(value)); } ! void write_data_memory_8 (sid::host_int_4 pc, sid::host_int_4 address, sid::host_int_8 value) { if (this->_current_endianness == endian_little) this->write_data_memory (pc, address, sid::little_int_8(value)); Index: sid/main/dynamic/commonCfg.cxx =================================================================== RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.cxx,v retrieving revision 1.8 diff -c -p -r1.8 commonCfg.cxx *** sid/main/dynamic/commonCfg.cxx 29 Jun 2004 19:10:41 -0000 1.8 --- sid/main/dynamic/commonCfg.cxx 3 May 2005 20:42:17 -0000 *************** void CacheCfg::set_refill_latency (sid:: *** 254,259 **** --- 254,301 ---- set (this, "refill-latency", sidutil::make_attribute (i)); } + // BlockingCacheCfg + BlockingCacheCfg::~BlockingCacheCfg () {} + BlockingCacheCfg::BlockingCacheCfg (const string name) : + CacheCfg (name), + ComponentCfg (name), + AtomicCfg (name, + "libcache.la", + "cache_component_library", + "hw-blocking-cache-buffer-8") + {} + + // direct caches + BlockingCacheCfg::BlockingCacheCfg (const string name, + const sid::host_int_4 size, + const sid::host_int_4 linesize) : + CacheCfg (name, size, linesize), + ComponentCfg (name), + AtomicCfg (name, + "libcache.la", + "cache_component_library", + "hw-blocking-cache-direct/" + + sidutil::make_attribute(size) + "kb/" + + sidutil::make_attribute(linesize)) + {} + + // complex associative caches + BlockingCacheCfg::BlockingCacheCfg (const string name, + const string assoc, + const sid::host_int_4 size, + const sid::host_int_4 linesize, + const string replace) : + CacheCfg (name, assoc, size, linesize, replace), + ComponentCfg (name), + AtomicCfg (name, + "libcache.la", + "cache_component_library", + "hw-blocking-cache-" + assoc + "/" + + sidutil::make_attribute(size) + "kb/" + + sidutil::make_attribute(linesize) + "/" + + replace) + {} + // CpuCfg Index: sid/main/dynamic/commonCfg.h =================================================================== RCS file: /cvs/src/src/sid/main/dynamic/commonCfg.h,v retrieving revision 1.6 diff -c -p -r1.6 commonCfg.h *** sid/main/dynamic/commonCfg.h 29 Apr 2004 20:28:01 -0000 1.6 --- sid/main/dynamic/commonCfg.h 3 May 2005 20:42:17 -0000 *************** public: *** 70,75 **** --- 70,94 ---- string my_replace; }; + class BlockingCacheCfg : + public CacheCfg + { + public: + // 8-byte buffers + BlockingCacheCfg (const string name); + // direct caches + BlockingCacheCfg (const string name, + const sid::host_int_4 size, + const sid::host_int_4 linesize); + // complex associative caches + BlockingCacheCfg (const string name, + const string assoc, + const sid::host_int_4 size, + const sid::host_int_4 linesize, + const string replace); + virtual ~BlockingCacheCfg(); + }; + class SchedCfg : virtual public AtomicCfg --------------080706090704020105020008--