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);
};
Definesoff_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());}
};
Definesoff_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.
<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";
DefinesOFF_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; }
<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());}
};
Definesoff_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::resetimplementation. > <off_BankNav::get_nextimplementation. > <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. >