next up previous contents
Next: 4.0.2 Frozen memory Up: 4.0.1 Memory banks Previous: 4.0.1 Memory banks

  
4.0.1.1 Memory navigation

The memory bank navigator gives uniform access to memory banks. We implement a generic navigator for resource ``banks'' because all of them are similar.

<Off banks navigator. >= (U->)
// A B bank (containing Ts) navigator
//
template <class B, class T>
class off_BankNav : public off_Navigator {
private:
  B &n_bank;
  <Other private members of off_BankNav. >
public:
  // Creates a bank navigator. 
  off_BankNav(B &bank) : 
    n_bank(bank),
    <Initialize other aggregate members of off_BankNav. >
  {  assert(bank.valid()); }

  // Returns a reference to the resource being navigated
  virtual off_Resource *get_current(void) {return &n_bank;}
  
  // Advances the iteration and returns the next element.
  virtual off_Resource *get_next(void);
  // Resets the iteration so that get_next will return the 1st element.
  virtual void reset(void);
  
  // Selects a component by name.
  virtual off_Resource *operator[](const char *name);
  virtual off_Resource *operator[](const off_id_t &id);

};

Defines off_BankNav (links are to index).

<Off banks navigator dependencies. >= (U->)
#include <assert.h>             // for assert
#include <klib/ids.h>           // for off_id_t et al.
#include <klib/nav.h>           // for off_Navigator.

Memory bank navigators are created dynamically. Now we can implement this method:

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Returns a navigator for memory banks. 
off_Navigator *get_navigator(void);  

<off_MBank::get_navigator implementation. >= (U->)
// Returns a navigator for memory banks. 
off_Navigator *off_MBank::get_navigator(void) 
{
  return new off_BankNav<off_MBank,off_PFrame>(*this);
}

<Off memory bank navigator dependencies. >= (U->)
#include <hw/MBank.h>           // for off_MBank
#include <hw/PFrame.h>          // for off_PFrame
#include <hw/bnav.h>            // for off_BankNav et al.

<Off memory bank dependencies. >+= (U->) [<-D->]
#include <klib/nav.h>           // for off_Navigator

The key methods are reset and get_next. They use some members to keep the iteration state.

<Other private members of off_BankNav. >= (<-U)
natural_t n_pos;                // Resource unit the navigator is pointing to.

<Initialize other aggregate members of off_BankNav. >= (<-U)
  n_pos(n_bank.get_first())

The initial state is recovered by reset.

<off_BankNav::reset implementation. >= (U->)
// Resets the iteration so that get_next will return the 1st element.
template <class B, class T>
void off_BankNav<B,T>::reset(void)
{
  n_pos=n_bank.get_first();
}

Iteration is advanced by get_next.

<off_BankNav::get_next implementation. >= (U->)
// Advances the iteration and returns the next element.
template <class B, class T>
off_Resource *off_BankNav<B,T>::get_next(void)
{
  T *pf=NULL;
  if (n_pos<n_bank.get_last())
    pf=n_bank+n_pos++;
  return pf;
  
}

The last couple of iteration methods are implemented with those shown above.

<off_BankNav::operator[]  implementation. >= (U->) [D->]
// Selects a component by name.
template <class B, class T>
off_Resource *off_BankNav<B,T>::operator[](const char *name)
{
  (void)name;
  return NULL;                  // Bank's resource units have no name.
}

<off_BankNav::operator[]  implementation. >+= (U->) [<-D]
// Selects a component by name.
template <class B, class T>
off_Resource *off_BankNav<B,T>::operator[](const off_id_t &id)
{
  if (id.i_node==n_bank.get_id().i_node &&
      id.i_seq==n_bank.get_id().i_seq &&
      id >= n_bank.get_first() && id < n_bank.get_last()){
    return n_bank+id;
  }
  else
    return NULL;

}

\subsubsection{Memory bank inspection}

The memory bank inspector's attribute array looks like this:

<Off mbank inspector attribute array initializer. >= (U->)
{{ OFF_STR_ATTR , "name",     &off_MBank::nameof },
 { OFF_STR_ATTR,  "class",    &off_MBank::kindof },
 { OFF_ID_ATTR,   "dom",      &off_MBank::get_domain },
 { OFF_ID_ATTR,   "id",       &off_MBank::get_id },
 { OFF_STR_ATTR,  "url",      &off_MBank::get_url },
 { OFF_STR_ATTR,  "provides", &off_MBank::nameof },
 { OFF_STR_ATTR,  NULL,       NULL    },    // no requeriments. 
 // Memory bank specific attributes.
 { OFF_BOOL_ATTR, "doesdma",     &off_MBank::is_dmable },
 { OFF_BOOL_ATTR, "doesiomap",   &off_MBank::is_iomapable },
 { OFF_BOOL_ATTR, "doespersist", &off_MBank::is_persistent},
 { OFF_NAT_ATTR,  "npgs",        &off_MBank::get_npgs},

// If this is not commented out I get a g++ internal compiler error 40.
//     In function `(static initializers for ../Src/mmnav.C)' :-( Sic!
// { OFF_NAT_ATTR,  "first",       &off_MBank::get_first},
// { OFF_NAT_ATTR,  "last",       &off_MBank::get_last},
// { OFF_NAT_ATTR,  "mat",        &off_MBank::get_mat},
// { OFF_NAT_ATTR,  "pgsize",     &off_MBank::get_pgsize},

 { OFF_NULL_ATTR, NULL,       NULL } } // End of attribute list. 

<Off mbank inspector attribute array length. >= (U->)
const int OFF_MINSP_NATTR=11;   // not counting final NULL attr.

Given this attribute list, the memory bank inspector is defined as follows

<Off memory bank inspector. >= (U->)
// A memory bank inspector.
//
class off_MBankInsp : public off_Inspector {
private:
  static off_attr_t m_attrs[OFF_MINSP_NATTR+1]; // for final NULL attr.
public:
  off_MBankInsp(off_MBank *mbank) : 
     off_Inspector(mbank,(const off_attr_t *)m_attrs, OFF_MINSP_NATTR)
  {assert(mbank && mbank->valid());}
};

Defines off_MBankInsp (links are to index).

Where the attribute array is shared.

<Off mbank inspector static members. >= (U->)
// inspector attributes for mbanks.
off_attr_t off_MBankInsp::m_attrs[OFF_MINSP_NATTR+1] =
               <Off mbank inspector attribute array initializer. > 
;

Every time get_inspector is called, a new inspector is created. The user should delete it whenever it is no longer needed.

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Returns an inspector for memory banks
off_Inspector *get_inspector(void); 

<off_MBank::get_inspector implementation. >= (U->)
// Returns an inspector for memory banks
off_Inspector *off_MBank::get_inspector(void)
 { 
  assert(valid());
  return new off_MBankInsp(this);
}

<Off memory bank implementation dependencies. >+= (U->) [<-D->]
#include <hw/mmnav.h>           // for off_MBankInsp et al

We have implemented neither get_url nor nameof yet.

<Other public methods of off_MBank. >+= (<-U) [<-D->]
// Get the memory bank URL.
const char *get_url(void);
// Returns the memory bank name. 
const char *nameof(void);

The URL for a memory bank is that of its node with mm.html appended. We use a new member, a character array initialized the very first time it is needed.

<Other private members of off_MBank. >+= (<-U) [<-D->]
static char *m_url;             // URL for this memory bank.

Initially it is empty.

<Off memory bank static members. >+= (U->) [<-D]
char *off_MBank::m_url=NULL;    // URL for memory banks.

<off_MBank::get_url implementation. >= (U->)
// Get the memory bank URL.
const char *off_MBank::get_url(void)
{
  assert(valid());
  if (!m_url){
    m_url=new char[strlen(nd.get_url())+strlen(OFF_MBANK_URL)+1]; // +1 for \0
    if (m_url)
      sprintf(m_url,"%s%s",nd.get_url(),OFF_MBANK_URL);
  }
  return m_url;
}

Where he have to define the relative URL for memory banks.

<Off source code urls. >= [D->]
const char OFF_MBANK_URL[]="/mm.html";

<Off memory bank dependencies. >+= (U->) [<-D->]
#include <klib/url.h>           // for OFF_MBANK_URL

<Off memory bank implementation dependencies. >+= (U->) [<-D->]
#include <stdio.h>              // for sprintf et al
#include <node/Node.h>          // for nd

The name for a memory bank is that of its node complemented with a little suffix. The implementation is almost the same of get_url, however, the name is not shared among memory banks in the same node (i.e. it is not static).

<off_MBank::nameof implementation. >= (U->)
// Returns the memory bank name. 
const char *off_MBank::nameof(void)
{
  assert(valid());
  if (!m_name){
    m_name = new char[strlen(nd.nameof())+strlen("/mbank")+10]; // for N...N\0
    if (m_name)
      sprintf(m_name,"%s/mbank%08x",nd.nameof(),get_first());
  }
  return m_name;
}

<Other private members of off_MBank. >+= (<-U) [<-D->]
char *m_name;                   // name for this memory bank.

<Initialize other aggregate members of off_MBank. >+= (<-U) [<-D]
m_name(NULL)

\subsubsection{Page frame inspection}

Page frames can be inspected too. The attribute array of their inspectors is as follows.

<Off pframe inspector attribute array initializer. >= (U->)
{{ OFF_STR_ATTR , "name",     &off_PFrame::nameof },
 { OFF_STR_ATTR,  "class",    &off_PFrame::kindof },
 { OFF_ID_ATTR,   "dom",      &off_PFrame::get_domain },
 { OFF_ID_ATTR,   "id",       &off_PFrame::get_id },
 { OFF_STR_ATTR,  "url",      &off_PFrame::get_url },
 { OFF_STR_ATTR,  "provides", &off_PFrame::nameof },
 { OFF_STR_ATTR,  NULL,       NULL    },    // no requeriments. 
 // Page frame specific attributes.
 { OFF_ID_ATTR,   "container",   &off_PFrame::get_container },
 { OFF_NAT_ATTR,  "bits",        &off_PFrame::get_bits },
 { OFF_NULL_ATTR, NULL,       NULL } } // End of attribute list. 

<Off page frame inspector attribute array length. >= (U->)
const int OFF_PFINSP_NATTR=9;   // not counting final NULL attr.

We need get_rurl and get_url_holder for page frames to support ResUnit::get_url.

<Other protected methods of off_PFrame. >= (<-U) [D->]
// Get the page URL.
virtual const char *get_rurl(void) const { return OFF_PFRAME_URL; }
// Returns the page name. 
virtual char *&get_url_holder(void);

Where he have to define the relative URL for page frames.

<Off source code urls. >+= [<-D]
const char OFF_PFRAME_URL[]="#PFrame";
Defines OFF_PFRAME_URL (links are to index).

<Off page frame dependencies. >+= (U->) [<-D->]
#include <klib/url.h>           // for OFF_PFRAME_URL

<Off page frame implementation dependencies. >= (U->) [D->]
#include <stdio.h>              // for sprintf et al

URLs are the same for all page frames.

<Other private members of off_PFrame. >= (<-U)
static char *p_url;             // URL for this page frame.

<off_PFrame::get_url_holder implementation. >= (U->)
char *&off_PFrame::get_url_holder(void) {  return p_url; }

Initially it is empty.

<Off page frame static members. >= (U->)
char *off_PFrame::p_url=NULL;   // URL for page frames.

Given the attribute list shown above, a page frame inspector is defined as follows.

<Off page frame inspector. >= (U->)
// A page frame inspector.
//
class off_PFrameInsp : public off_Inspector {
private:
  static off_attr_t p_attrs[OFF_PFINSP_NATTR+1]; // for final NULL attr.
public:
  off_PFrameInsp(off_PFrame *pf) : 
     off_Inspector(pf, p_attrs, OFF_PFINSP_NATTR)
  {assert(pf && pf->valid());}
};

Defines off_PFrameInsp (links are to index).

Where the attribute array is shared.

<Off page frame inspector static members. >= (U->)
// inspector attributes for page frames.
off_attr_t off_PFrameInsp::p_attrs[OFF_PFINSP_NATTR+1] =
               <Off pframe inspector attribute array initializer. > 
;

Every time get_inspector is called, a new inspector is created. The user should delete it whenever it is no longer needed.

<Other public methods of off_PFrame. >+= (<-U) [<-D->]
// Returns an inspector for page frames.
off_Inspector *get_inspector(void);

<off_PFrame::get_inspector implementation. >= (U->)
// Returns an inspector for page frames.
off_Inspector *off_PFrame::get_inspector(void)
{ 
  assert(valid());
  return new off_PFrameInsp(this);
}

<Off page frame implementation dependencies. >+= (U->) [<-D->]
#include <hw/mmnav.h>           // for off_PFrameInsp et al

\subsubsection{Memory bank navigation and inspection \cpp{} source files}

The navigation and inspection code for memory banks is kept in hw/mmnav.h. Generic bank navigation code is kept in hw/bnav.h.

<bnav.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_BANK_NAV_H
#define __OFF_BANK_NAV_H 1

<Off banks navigator dependencies. >

<Off banks navigator. >

#endif // __OFF_BANK_NAV_H

#ifndef __OFF_BANK_NAV_C
#define __OFF_BANK_NAV_C 1

<off_BankNav::reset implementation. >
<off_BankNav::get_next implementation. >
<off_BankNav::operator[]  implementation. >

#endif // __OFF_BANK_NAV_C

<mmnav.h*>=
<Read the literate code instead warning. >
#ifndef __OFF_MBANK_NAV_H
#define __OFF_MBANK_NAV_H 1

<Off memory bank navigator dependencies. >

<Off mbank inspector attribute array length. >
<Off page frame inspector attribute array length. >

#ifdef __KERNEL__
<Off memory bank inspector. >
<Off page frame inspector. >
#endif // __KERNEL__

#endif // __OFF_MBANK_NAV_H

<mmnav.C*>=
<Read the literate code instead warning. >

#include <hw/mmnav.h>           // Exported interface.

<Off mbank inspector static members. >
<Off page frame inspector static members. >


next up previous contents
Next: 4.0.2 Frozen memory Up: 4.0.1 Memory banks Previous: 4.0.1 Memory banks
Francisco J. Ballesteros
1998-05-25