sparta::RegisterProxy Allows interaction with a register "prototype" (name, group, index) through a proxy object which automatically chooses a sparta::Register from a variable bank in a RegisterSet based on the state of the simulation (as retrieved through a callback function in RegisterSet). A single register proxy may indirectly refer to registers of different sizes
Note that proxies only need to be defined for those "registers" which must support switching dynamically between banks, but must still have a common register name at all times for register-lookup reasons. Otherwise, differently named registers should be used for each bank. This is useful for providing a set of software visible registers without exposing the banking system.
- 1. Defining Proxies
- RegisterProxy objects are explicitly defined by creating a vector of sparta::RegisterProxy::Definition objects much like sparta::Register::Definition. This table of definitions is then given to a RegisterSet as a consruction argument along with a callback function of type RegisterSet::CurrentBankFunction, which provides the RegisterSet instance the means of querying the owning simulator about the current bank.
Instantiating a RegisterSet with a table of sparta::RegisterProxy::Definitions requires use of an extended constructor:
RegisterSet myregset(parent_node, reg_defs, proxy_defs, get_bank_fxn);
The proxy_defs table is an array of RegisterProxy::Definition objects terminated by a RegisterProxy::DEFINITION_END. The following declares a single register proxy, and requires that the reg_defs table used in the same RegisterSet have at least one 4-byte register with group_num=4, group_name="group" and group_idx=2. If such a register does not exist an exception will be thrown during RegisterSet constrution. Note that names and IDs of register proxies must be unique from all other proxy and register names.
RegisterProxy::Definition proxy_defs[] = {
{ 30001, "reg", 4, "group", 2, "example PROXY"},
};
static const Definition DEFINITION_END
Entry indicating the end of a sparta::Register::Definition array.
The get_bank_fxn argument to the RegisterSet constructor is a RegisterSet::CurrentBankFunction. It will implicitly accept static funtions having the correct signature. It accepts nullptr to indicate that Register::BANK_IDX_DEFAULT will always be used.
The arguments have the following meanings:
- group_num Group number of register requested
- group_idx Group index of register requested
- name_ptr Pointer to string interned in sparta::StringManager singleton (unless nullptr) so that pointer comparisons can be used instead of string comparisons.
It will accept correctly formed lambda functions:
const std::string*) {
return cur_bank;
};
uint32_t group_num_type
Numeric group identifier for register lookup.
TreeNode::group_idx_type group_idx_type
TreeNode group index.
uint32_t bank_idx_type
Numeric bank identifier for bank lookup.
And finally, std::bind can be used to pass a bound member function:
class BankGetter {
public:
Register::bank_idx_type getBank(Register::group_num_type,
Register::group_idx_type,
const std::string*) {
return 1;
}
};
BankGetter bg_instance;
&bg_instance,
std::placeholders::_1,
std::placeholders::_2,
std::placeholders::_3);
std::function< Register::bank_idx_type(RegisterBase::group_num_type, RegisterBase::group_idx_type, const std::string *name_ptr)> CurrentBankFunction
Function object type for holding a callback for querying the owning simulator about the current bank.
The functionality of the get_bank_fxn can be tested through RegisterSet with
myregset.getCurrentBank(<some_group>,<some_idx>,<name pointer>);
- 2. Register Name Lookup Using Proxies
- Use sparta::RegisterSet::getRegisterProxy to get a sparta::RegisterProxy when one is needed. For most purposes, this replaces RegisterSet::getRegister. RegisterSet::getRegister will NOT return any RegisterProxies, so it is insufficient for certain tasks when a RegisterSet has dynamic registers requiring RegisterProxies. Because Register names are unique, if getRegisterProxy is called with the name of a regular Register, it will return a RegisterProxy that always points to the register with the given name. In this way, RegisterSet::getRegisterProxy abstracts away the details of which registers are proxies and which are regular Registers.
The RegisterProxy references returned by this function cannot be copied. However, the reference returned refers to instances which are owned by the RegisterSet and can be referred to until that RegisterSet is destroyed.
Represents an interface to a pseudo-"Register" of a fixed size which indirectly references other regi...
The argument to getRegisterProxy can be the name of a normal Register as well, without requiring any changes in the client code. This allows registers to be turned into proxies and vise-versa transparently - requiring only a name change in the original register definition table and an entry in the register proxy table.
- 3. Accessing the Actual Register
- At any time, the RegisterProxy instance can be queried to get the real Register to which it currently points.
Register* r = rset.getRegisterProxy("reg").getCurrentRegister();
Register* r = rset.tryGetRegisterProxy("reg").getCurrentRegister();