This is the mail archive of the sid@sources.redhat.com mailing list for the SID project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH][RFC][RFA]Bus Arbitration Modelling Using Blockable Components


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

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<blocking_cache_component *>(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/<s>kb/<l>
hw-blocking-cache-<a>/<s>kb/<l>

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<blocking_cpu *>(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.


// 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 <sidconfig.h>
#include <sidattrutil.h>

#include <iostream>
#include <pthread.h>

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
? 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<typename DataType>
+ 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<typename DataType>
+ 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<blocking_cache_component *>(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<string> 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<string> 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<string> 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 "<x>kb", where <x> 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 "<x>kb", where <x> 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 <typename DataType> bus::status 
    write_any (host_int_4 addr, DataType data);
    
*************** protected:
*** 127,168 ****
    void emit_report (host_int_4 ignore);
  
    callback_pin<cache_component> flush_all_pin;
!   void flush_all_lines (host_int_4 ignore);
  
    callback_pin<cache_component> flush_pin;
!   void flush_line (host_int_4 addr);
  
    callback_pin<cache_component> flush_set_pin;
!   void flush_set (host_int_4 set);
  
    callback_pin<cache_component> flush_and_invalidate_set_pin;
!   void flush_and_invalidate_set (host_int_4 set);
  
    callback_pin<cache_component> invalidate_all_pin;
!   void invalidate_all_lines (host_int_4 ignore);
  
    callback_pin<cache_component> invalidate_pin;
!   void invalidate_line (host_int_4 addr);
  
    callback_pin<cache_component> flush_and_invalidate_pin;
!   void flush_and_invalidate_line (host_int_4 addr);
  
    callback_pin<cache_component> invalidate_set_pin;
!   void invalidate_set (host_int_4 set);
  
    callback_pin<cache_component> prefetch_pin;
!   void prefetch_line (host_int_4 addr);
  
    callback_pin<cache_component> lock_pin;
!   void lock_line (host_int_4 addr);
  
    callback_pin<cache_component> 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<cache_component> flush_all_pin;
!   virtual void flush_all_lines (host_int_4 ignore);
  
    callback_pin<cache_component> flush_pin;
!   virtual void flush_line (host_int_4 addr);
  
    callback_pin<cache_component> flush_set_pin;
!   virtual void flush_set (host_int_4 set);
  
    callback_pin<cache_component> flush_and_invalidate_set_pin;
!   virtual void flush_and_invalidate_set (host_int_4 set);
  
    callback_pin<cache_component> invalidate_all_pin;
!   virtual void invalidate_all_lines (host_int_4 ignore);
  
    callback_pin<cache_component> invalidate_pin;
!   virtual void invalidate_line (host_int_4 addr);
  
    callback_pin<cache_component> flush_and_invalidate_pin;
!   virtual void flush_and_invalidate_line (host_int_4 addr);
  
    callback_pin<cache_component> invalidate_set_pin;
!   virtual void invalidate_set (host_int_4 set);
  
    callback_pin<cache_component> prefetch_pin;
!   virtual void prefetch_line (host_int_4 addr);
  
    callback_pin<cache_component> lock_pin;
!   virtual void lock_line (host_int_4 addr);
  
    callback_pin<cache_component> 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<typename DataType> bus::status read_downstream (host_int_4 address, DataType &data);
+   template<typename DataType> 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 <typename DataType>
  bus::status
  cache_bus::write_any (host_int_4 addr, DataType data)
  {
!   return cache.write_any (addr, data);
  }
    
  template <typename DataType>
  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 <typename DataType>
  bus::status
  cache_bus::write_any (host_int_4 addr, DataType data)
  {
!   return cache.write (addr, data);
  }
    
  template <typename DataType>
  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 ****
      <defpin name="report!" direction="in" behaviors="statistics reporting" />
      <defpin name="flush" direction="in" legalvalues="32-bit address" behaviors="flushing" />
      <defpin name="flush-all" direction="in" legalvalues="any" behaviors="flushing" />
!     <defpin name="flush-set" direction="in" legalvalues="set index" behaviors="flushing" />
      <defpin name="invalidate" direction="in" legalvalues="32-bit address" behaviors="invalidating" />
      <defpin name="invalidate-all" direction="in" legalvalues="any" behaviors="invalidating" />
!     <defpin name="invalidate-set" direction="in" legalvalues="set index" behaviors="invalidating" />
      <defpin name="flush-and-invalidate" direction="in" legalvalues="32-bit address" behaviors="flushing, invalidating" />
!     <defpin name="flush-and-invalidate-set" direction="in" legalvalues="set index" behaviors="flushing, invalidating" />
      <defpin name="prefetch" direction="in" legalvalues="32-bit address" behaviors="prefetching" />
      <defpin name="lock" direction="in" legalvalues="32-bit address" behaviors="line locking" />
      <defpin name="unlock" direction="in" legalvalues="32-bit address" behaviors="line locking" />
--- 14,25 ----
      <defpin name="report!" direction="in" behaviors="statistics reporting" />
      <defpin name="flush" direction="in" legalvalues="32-bit address" behaviors="flushing" />
      <defpin name="flush-all" direction="in" legalvalues="any" behaviors="flushing" />
!     <defpin name="flush-set" direction="in" legalvalues="any" behaviors="flushing" />
      <defpin name="invalidate" direction="in" legalvalues="32-bit address" behaviors="invalidating" />
      <defpin name="invalidate-all" direction="in" legalvalues="any" behaviors="invalidating" />
!     <defpin name="invalidate-set" direction="in" legalvalues="any" behaviors="invalidating" />
      <defpin name="flush-and-invalidate" direction="in" legalvalues="32-bit address" behaviors="flushing, invalidating" />
!     <defpin name="flush-and-invalidate-set" direction="in" legalvalues="any" behaviors="flushing, invalidating" />
      <defpin name="prefetch" direction="in" legalvalues="32-bit address" behaviors="prefetching" />
      <defpin name="lock" direction="in" legalvalues="32-bit address" behaviors="line locking" />
      <defpin name="unlock" direction="in" legalvalues="32-bit address" behaviors="line locking" />
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<SF>(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<USI>(value));
      }
  
    inline DF
!   GETMEMDF(PCADDR pc, IADDR addr) const
      {
        return reinterpret_cast<DF>(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<UDI>(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<SF>(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<USI>(value));
      }
  
    inline DF
!   GETMEMDF(PCADDR pc, IADDR addr)
      {
        return reinterpret_cast<DF>(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<UDI>(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_int<IntTy
*** 1022,1056 ****
    : public virtual fixed_attribute_map_component,
      public virtual fixed_pin_map_component
    {
- #define SID_LOG_PERSISTENT_BUFFER (HAVE_VSNPRINTF || ! HAVE_VASPRINTF)
- #define SID_LOG_TRANSIENT_MALLOC_BUFFER (! SID_LOG_PERSISTENT_BUFFER)
    protected:
      fixed_attribute_map_with_logging_component () :
        ulog_level (0),
        ulog_mode ("less"),
        ulog_out_pin (),
!       buffer_output (true),
!       buffer_size (4096), // big enough for now
!       saved_messages (),
!       saved_levels ()
        {
  	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);
- #if SID_LOG_PERSISTENT_BUFFER
- 	buffer = new char[buffer_size];
- #endif
        }
      ~fixed_attribute_map_with_logging_component () throw()
        {
  	// Output any saved messages.
  	// output_saved_messages ();
  	ulog_logger->output_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_int<IntTy
*** 1063,1100 ****
  	va_end (ap);
        }
  
! private:
!     bool check_level (sid::host_int_4 level)
!       {
! 	ulog_logger->check_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<std::string> saved_messages;
-     std::vector<sid::host_int_4> 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 <sidconfig.h>
  #include <sidtypes.h>
+ #include <sidcomputil.h>
+ #include <sidschedutil.h>
+ #include <sidpinutil.h>
+ #include <sidblockingutil.h>
  
  #include <string>
  #include <map>
*************** 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<std::string,sid::bus*> 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<class DataType>
+     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<class DataType>
+     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<class DataType>
+     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<class DataType>
+     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<class DataType>
+     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<class DataType>
+     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<bus_arbitrator> sched;
+     // This class must be a friend of scheduler_event_subscription<T>.
+     friend class scheduler_event_subscription<bus_arbitrator>;
+ 
+     // 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 <typename BigOrLittleInt>
!     BigOrLittleInt read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const;
      template <typename BigOrLittleInt>
!     BigOrLittleInt write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const;
      template <typename BigOrLittleInt>
!     BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt) const;
      template <typename BigOrLittleInt>
!     BigOrLittleInt write_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value) const;
  
      // ------------------------------------------------------------------------
      
--- 530,552 ----
  
    protected:
      template <typename BigOrLittleInt>
!     BigOrLittleInt read_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt);
      template <typename BigOrLittleInt>
!     BigOrLittleInt write_insn_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt value);
      template <typename BigOrLittleInt>
!     BigOrLittleInt read_data_memory (sid::host_int_4 pc, sid::host_int_4 address, BigOrLittleInt);
      template <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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 <typename BigOrLittleInt>
!     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

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]