Initial commit of OpenSPARC T2 architecture model.
[OpenSPARC-T2-SAM] / sam-t2 / docs / mmi / Module.html
<html>
<head>
<title>SPARC Architectural Model: Device and Utility API</title>
</head>
<body bgcolor="#FFFFFF" LANG="en-US">
<h2>class Module</h2>
<br>common/module.cc:
<br>&nbsp;
<br>#include "module.h"
<font size=-1>
<pre>
public:
int debug_level;
void debug_err(const char *, ...);
void debug_info(const char *, ...);
void debug_more(const char *, ...);
protected:
const char *modname;
const char *instance_name;
module_t *module;
module_t *instance;
char herebuf[80];
public:
module_t *getInstance() { return instance; };
const char *getName() { return instance_name; };
const char *_here(const char *, int);
Module(const char *modname, const char *instance_name);
virtual ~Module();
public: // to be supplied by the subclass
static Module *create(const char *modname, const char *instance_name);
static const char *get_help_string();
virtual const char *get_help();
virtual bool parse_arg(const char *);
virtual bool check_args();
virtual void init_done();
virtual void module_added(module_t*, const char*);
virtual void module_deleted(module_t*, const char*);
virtual void modinfo();
virtual void *get_interface(const char*);
virtual bool_t dump(FILE *fp);
virtual bool_t restore(FILE *fp);
virtual void stop();
virtual void restart();
</pre>
</font>
<h4>Description</h4>
This is the base class for all modules. It provides the main entry point
(_init), and manages several mmi callbacks.
<p>
A subclass must define Module::create() and Module::get_help_string().
These are not defined in module.cc.
Module::create() is a factory function which creates the new subclass.
Module::get_help_string() simply provides a pointer to a one-line help string for the module.
<p>
There are stubs for each of the virtual functions defined in module.cc.
Subclasses generally provide definitions for each of the virtual functions.
<p>
A subclass may also reference an interface class.
This is called multiple inheritance, with Module and interface classes as base classes for each module.
<p>
Thus, a subclass operates by providing definitions for virtual functions in
interface classes, and by providing definitions for the virtual functions in
Module.
<p>
The sequence of calls to module functions is carefully arranged.
It is important to keep this in mind when designing the subclass.
<p>
Functions are called in this order:
<p><b>Module::get_help_string()</b> registers a string with mmi when it creates the instance.
<p><b>Module::create()</b> is the factory function that must create a new subclass of Module.
This calls the constructors for Module, any intermediate classes (for example,
PciDev), and the subclass. It is important to do as little as possible in the
constructors. Simply set class attributes to initial values.
Initial values are usually "0" for integer types, and "NULL" for pointer types.
It is best practice to *always* initialize data members to something.
It is OK to set default values for module arguments here, so long as they are
strings or integers.
But note that string arguments should be intialized with <tt>strdup("foo")</tt>, not <tt>"foo"</tt>.
<p><b>parse_arg()</b> will be called for each argument on the sysconf command line.
Module.cc parses any -d# argument (set debug level).
Any other arguments are defined by the subclass.
There are utilities in <b>common/arg.cc</b> that help with argument parsing.
(Special note about <i>argval()</i>:
make sure any string pointers are initialized to NULL or a heap item.
It will <i>free()</i> the previous string before returning the new string pointer.
It is best practice to initialize *every* member data item in the constructor.)
<p><b>check_args()</b> is an important step.
If any required arguments are missing, or have improper values, the function may return "false",
which will cause the module to immediately unload.
Note: this is not the time to look for interfaces to other modules, because other modules may not be loaded at this point.
Only the names of other modules are noted at this point.
<p><b>module_added()</b> is called for each module already loaded.
This is also called if a module is loaded later on.
This is the place to expect to find the interfaces to another module.
<p><b>init_done()</b> is called after Blaze has initialized CPU and device objects (<i>init_devices()</i>).
If the module is loaded after this time, init_done() is called immediately.
Note that "init done" does not mean "config done".
It is possible to load modules at any time.
Use the module_added hook to connect to new modules.
<p>The remaining functions may be called in any order, or not at all.
In particular:
<p><b>module_deleted()</b> is called whenever a module is unloaded.
This is when the subclass will delete any interface pointers it may have to the module.
Also, note that module_added may be called later on, and the subclass can then reconnect.
If the instance itself is being unloaded, module.cc will delete the subclass instead,
and the destructor for the subclass will be called instead.
<p><b>get_interface()</b> is called by other modules whenever it wants an interface pointer to the subclass.
The definition of an interface is very open ended.
It can be an interface class, a scalar value, or a pointer to a structure.
For interface classes, it is necessary to use casts, due to the rules of multiple inheritance.
For example,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size=-1><tt>return (PciDevIf*)this</tt></font>
<br>returns the proper interface pointer for the interface class PciDevIf.
<p><b>modinfo</b> prints information about the subclass. It does not return a value.
It is called by the <b>modinfo</b> UI command.
<p><b>dump/restore</b> support the Blaze DR facility. These are optional.
Module.cc will create the dump file whether or not it has any contents.
<p><b>stop/restart</b> support the <b>stop</b> UI command. These are optional, and rarely needed.
<p><b>debug_level</b> is set by the sysconf command line arg <i>-d#</i>. There are three levels defined:
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-d0: <i>debug_err</i>, are error messages that always print.
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-d1: <i>debug_info</i>, is for I/O traces.
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;-d2: <i>debug_more</i>, says to print errors, info, and more details.
<p><b>_here()</b> is the function called by the macro <i>HERE</i>, defined as:
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size=-1><tt>#define HERE _here(__FILE__, __LINE__)</tt></font>
<br>This macro helps to locate every message in the source code
by composing a common prefix for debug messages:
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size=-1><i>instance_name</i>:<i>__FILE__</i>(L<i>__LINE__</i>)</font>
<br>For example,
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size=-1><tt>debug_more("%s: Mips %6.2f\n", HERE, ticks / elapsed / 1e6);</tt></font>
<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<font size=-1><tt>sample25A:sample_mod.cc(L194): Mips 2.11</tt></font>
<br>Note that a static function can also use the macro:
<font size=-1><tt>sample->HERE</tt></font> is legal.
<h4>Makefile</h4>
module.cc is common code.
This means that it is compiled into each module, and preprocesser macros are expanded uniquely.
Here is the Makefile from the example PCI device <b>sample</b>:
<font size=-1>
<pre>
# Makefile for sample PCI device loadable module
# Copyright 2004 Sun Microsystems Inc
# All rights reserved
#
# @(#)Makefile 1.4 04/08/05
#
MOD = sample
CCFILES = \
pci_dev.cc \
sample_mod.cc \
module.cc \
arg.cc
CPPFLAGS += -DMODNAME=\"$(MOD)\"
# make link names unique for common classes
CPPFLAGS += -DModule=$(MOD)Module
CPPFLAGS += -DPciDev=$(MOD)PciDev
include ../Makefile.modules
</pre>
</font>
modules/Makefile always includes header files from common/include,
and allows inclusion of code from common.
pci_dev.cc, module.cc, and arg.cc are in common.
Makefile and sample_mod.cc are in sample.
<p>
Note that <i>-DModule</i> and <i>-DPciDev</i> actually rename <i>class Module</i> and <i>class PciDev</i>.
This is not strictly necessary, so as long as modules are loaded with <i>dlopen(..., RTLD_LOCAL)</i>.
Using <i>RTLD_LOCAL</i> ensures that the symbols from a module are not merged with the global symbol table.
However, <i>RTLD_GLOBAL</i> would certainly cause an ambiguity if two or more modules publish the same names.
The best reason to create unique global names is to help with debugging.
This way it is easier to distinguish 'sampleModule' from 'fooModule' in the blaze binary at runtime.
<p>
<b>arg.cc</b> could be a library (compiled once), but there is no provision for this.
</body>
</html>