8#include <unordered_map>
15#include "sparta/functional/Register.hpp"
16#include "sparta/functional/RegisterBankTable.hpp"
21#include "sparta/functional/ArchData.hpp"
22#include "sparta/utils/StringManager.hpp"
107 if (!utils::strcmp_with_null(a.
name, b.
name)) {
113 if (!utils::strcmp_with_null(a.
group, b.
group)) {
119 if (!utils::strcmp_with_null(a.
desc, b.
desc)) {
126inline bool operator!=(
const RegisterProxyBase::Definition &a,
127 const RegisterProxyBase::Definition &b)
174 , group_num_(
Register::GROUP_NUM_NONE)
175 , group_idx_(
Register::GROUP_IDX_NONE)
176 , reg_name_(reg.getNamePtr())
180 "reg argument of RegisterProxy constructor must not be nullptr")
198 const std::string *managed_name)
201 , group_num_(group_num)
202 , group_idx_(group_idx)
203 , reg_name_(managed_name)
206 "group_num argument of RegisterProxy constructor must not "
207 "be GROUP_NUM_NONE");
209 "group_idx argument of RegisterProxy constructor must not "
210 "be GROUP_IDX_NONE");
211 sparta_assert(reg_name_ !=
nullptr,
"managed_name argument of "
212 "RegisterProxy constructor must not "
215 "managed_name argument of RegisterProxy constructor must "
216 "be a string managed by the StringManager singleton");
277 const std::string *reg_name_;
438 using GroupVector =
typename RegisterBankTable<RegisterBase>::RegisterVector;
449 typedef std::function<
452 const std::string *name_ptr)>
458 template <
typename RegisterT>
478 template <
typename RegisterT>
484 const std::string& name =
"regs")
492 ArchData::DEFAULT_INITIAL_FILL_SIZE,
494 , cur_bank_fxn_(cbfxn)
503 const auto *rdef = defs;
504 if (rdef !=
nullptr) {
505 while (rdef->name !=
nullptr) {
506 addRegister_<RegisterT>(rdef);
512 const auto *pdef = proxy_defs;
513 if (pdef !=
nullptr) {
514 while (pdef->name !=
nullptr) {
531 template <
typename RegisterT>
535 const std::string& name =
"regs")
536 :
RegisterSet(parent, defs, nullptr, nullptr, tag, name)
541 template <
typename RegisterT = Register>
542 static std::unique_ptr<RegisterSet>
547 const std::string& name =
"regs")
549 return std::unique_ptr<RegisterSet>(
new RegisterSet(
550 parent, defs, proxy_defs, cbfxn, RegisterTypeTag<RegisterT>(), name));
553 template <
typename RegisterT = Register>
554 static std::unique_ptr<RegisterSet>
555 create(
TreeNode *parent,
const RegisterBase::Definition *defs,
const std::string& name =
"regs")
557 return std::unique_ptr<RegisterSet>(
new RegisterSet(
558 parent, defs, RegisterTypeTag<RegisterT>(), name));
568 for (
auto r : owned_regs_) {
577 for (uint32_t i=0; i<regs_.size(); i++) {
633 virtual std::string
stringize(
bool pretty=
false)
const override {
635 std::stringstream ss;
636 ss <<
'<' <<
getLocation() <<
' ' << regs_.size() <<
" regs>";
658 return getChildAs<RegisterBase>(name);
676 auto rpi = reg_proxies_.find(name);
677 if(rpi != reg_proxies_.end()){
678 return *(rpi->second.get());
680 auto r = getChildAs<RegisterBase>(name,
false);
683 <<
" named \"" << name <<
"\" because there was no existing proxy and no "
684 "register with this name.";
687 typename RegisterProxyMap::mapped_type(
new RegisterProxy(*r));
688 return *reg_proxies_[name];
719 return banks_.canLookupRegister(group_num, group_idx, bank_idx);
756 const auto idx_count = rm.count(group_idx);
760 return (idx_count==1 ? rm.at(group_idx) :
nullptr);
773 const auto &rm = banks_[bank_idx][group_num];
774 const auto idx_count = rm.count(group_idx);
778 return (idx_count==1 ? rm.at(group_idx) :
nullptr);
809 return banks_.
getRegister(group_num, group_idx, bank_idx);
854 const std::string *name_ptr)
const
856 if (cur_bank_fxn_ ==
nullptr) {
859 return cur_bank_fxn_(group_num, group_idx, name_ptr);
871 virtual void onAddingChild_(
TreeNode *child)
override
874 if (
nullptr == reg) {
876 << child <<
" which is not a Register to RegisterSet "
881 regs_.push_back(reg);
897 template <
typename RegisterT>
898 void addRegister_(
const RegisterBase::Definition *rdef)
902 auto r =
new RegisterT(
nullptr, *rdef, &adata_);
909 owned_regs_.push_back(r);
921 void addProxy_(
const RegisterProxyBase::Definition *pdef)
924 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
925 <<
" with a null proxy definition");
929 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
930 <<
" with a null proxy name");
932 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
933 <<
" named \"" << pdef->name <<
"\" with a null proxy description");
935 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
936 <<
" named \"" << pdef->name <<
"\" with a group number of "
937 "GROUP_NUM_NONE. RegisterProxy definitions must have a valid group number");
939 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
940 <<
" named \"" << pdef->name <<
"\" with a group number of "
941 "GROUP_NUM_NONE. RegisterProxy definitions must have a valid group number");
944 for(
auto& reg : regs_){
946 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
947 <<
" named \"" << pdef->name <<
"\" with an ID of " << pdef->id
948 <<
" which is already usd by Register " << reg);
952 auto reg_samename = getChildAs<RegisterBase>(pdef->name,
false);
954 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
955 <<
" named \"" << pdef->name <<
"\" but there is already a normal "
956 "Register with the same name: " << reg_samename->getLocation());
959 auto rpi = reg_proxies_.find(pdef->name);
960 if(rpi != reg_proxies_.end()){
961 throw SpartaException(
"A RegisterProxy in ") <<
getLocation()
962 <<
" named \"" << pdef->name <<
"\" already exists";
969 uint32_t matches = 0;
970 for(uint32_t b = 0; b < banks_.
getNumBanks(); b++){
971 if(banks_.canLookupRegister(pdef->group_num, pdef->group_idx, b)){
972 auto r = banks_.lookupRegister(pdef->group_num, pdef->group_idx, b);
981 "Attempted to add a RegisterProxy to RegisterSet "
982 <<
getLocation() <<
" named \"" << pdef->name <<
"\" which matched "
983 "the group number and group index with " << *r <<
" but the "
984 "proxy had an incorrect group name \"" << pdef->group <<
"\"");
992 "Attempted to add a RegisterProxy to RegisterSet "
993 <<
getLocation() <<
" named \"" << pdef->name <<
"\" with group num "
994 << pdef->group_num <<
" and group idx " << pdef->group_idx <<
" which did "
995 "not match any known registers");
998 auto rp =
new RegisterProxy(*
this,
1002 reg_proxies_[pdef->name] =
typename RegisterProxyMap::mapped_type(rp);
1026 RegisterBankTable<RegisterBase> banks_;
1045 std::stringstream ss;
1046 ss <<
"<RegisterProxy to ";
1050 ss <<
"name: \"" << reg_name_ <<
"\" group: " << group_num_
1051 <<
" idx: " << group_idx_;
1059 if (reg_inv_ !=
nullptr) {
1063 auto bank_idx = rs_.
getCurrentBank(group_num_, group_idx_, reg_name_);
1064 return rs_.
getRegister(group_num_, group_idx_, bank_idx);
1069 if (reg_inv_ !=
nullptr) {
1073 auto bank_idx = rs_.
getCurrentBank(group_num_, group_idx_, reg_name_);
1097 if (
nullptr == rp) {
Set of macros for Sparta assertions. Caught by the framework.
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
Exception class for all of Sparta.
Basic Node framework in sparta device tree composite pattern.
Contains a set of contiguous line of architectural data which can be referred to by any architected o...
bool isLaidOut() const
Has this ArchData been laid out yet.
void layout()
Organizes the Segments into overlapping regions as needed, eventually calling ArchDataSegment::place ...
void addRegister(RegisterT *r)
Adds a register to this table unless it is not a member of a group (See Register::getGroupNum.
void dump(std::ostream &out, bool detailed=false) const
Dump this register bank table to an out stream. Banks will be columns and group num/id will be rows.
void setMinimumBankIndex(Register::bank_idx_type min_idx)
Sets the minimum bank index for this register set, overriding the default of BANK_IDX_DEFAULT.
RegisterT::group_idx_type getNumGroups() const
Gets the number of register groups added to this table regardless of banks.
uint32_t getGroupSize(typename RegisterT::group_num_type group_num, typename RegisterT::bank_idx_type bank_num)
Gets the number of registers in a group by its group num and bank.
RegisterT * getRegister(typename RegisterT::group_num_type group_num, typename RegisterT::group_idx_type group_idx, typename RegisterT::bank_idx_type bank_idx)
Gets a Register by group number and group index and throws an exception if it cannot be found.
RegisterT::bank_idx_type getNumBanks() const
Gets the total number of banks instantiated (even if they contain have no actual registers accessible...
Base class to represents an architected register of any size that is a power of 2 and greater than 0 ...
DataView::ident_type ident_type
Identifier to distinguish from other registers in the same RegisterSet.
uint32_t bank_idx_type
Numeric bank identifier for bank lookup.
static constexpr bank_idx_type BANK_IDX_DEFAULT
Default index for bank when no bank is specified. A bank having this index will always exist.
TreeNode::group_idx_type group_idx_type
TreeNode group index.
uint32_t group_num_type
Numeric group identifier for register lookup.
static constexpr group_num_type GROUP_NUM_NONE
Represents no group much like sparta::TreeNode::GROUP_NAME_NONE.
static const Definition DEFINITION_END
Entry indicating the end of a sparta::Register::Definition array.
Represents an interface to a pseudo-"Register" of a fixed size which indirectly references other regi...
RegisterProxy(RegisterBase ®)
Concrete Register Constructor. The "current register" of this proxy never changes.
RegisterProxy & operator=(const RegisterProxy &)=delete
Assignment Operator deleted to assure persistence of any proxy's group information and RegisterSet.
RegisterBase * tryGetCurrentRegister() const
Attempt to get the current register being pointed to by this proxy based on simulation state.
std::string stringize() const
Form a string representing this proxy.
RegisterProxy(const RegisterProxy &)=delete
Not Copy Constructable.
RegisterBase * getCurrentRegister() const
Gets the current register being pointed to by this proxy based on simulation state.
RegisterSet & getContainingRegisterSet() const
Gets the RegisterSet which this proxy accesses.
RegisterProxy(RegisterSet &rs, Register::group_num_type group_num, Register::group_idx_type group_idx, const std::string *managed_name)
Actual Proxy Contruction. Proxies all registers having a specific group_num and group_idx in a single...
RegisterProxy(RegisterProxy &&)=delete
Move construction not allowed.
RegisterProxy()=delete
RegisterProxy disabled.
~RegisterProxy()
Destructor.
Holds and can create a set of Register objects having various names and groups.
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.
RegisterBase * getRegister(const std::string &name)
Retrieves a concrete register child that is a Register with the given dotted path.
static const ArchData::offset_type ARCH_DATA_LINE_SIZE
Size of an ArchData line for Registers (bytes) Must be large enough to fit the largest register in a ...
void dumpBanks(std::ostream &out) const
Dumps the table of banks and registers.
RegisterSet(TreeNode *parent, const RegisterBase::Definition *defs, RegisterTypeTag< RegisterT > tag, const std::string &name="regs")
Constructor with no current-bank query function.
RegisterBase::bank_idx_type getCurrentBank(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx, const std::string *name_ptr) const
Determine the current bank for this register set based on the context of time simulator.
RegisterProxy & getRegisterProxy(const std::string &name)
Retrieves a register proxy based on the given name. RegisterProxies are an indirection layer that dir...
RegisterBase * getRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx)
Gets a Register by group number and group index and throws an exception if it cannot be found.
const RegisterVector & getRegisters() const
Gets the vector of Registers contained by this set.
RegisterSet(TreeNode *parent, const RegisterBase::Definition *defs, const RegisterProxyBase::Definition *proxy_defs, CurrentBankFunction cbfxn, RegisterTypeTag< RegisterT > tag, const std::string &name="regs")
Constructor.
bool canLookupRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx, RegisterBase::bank_idx_type bank_idx) const noexcept
Alternate canLookupRegister with additional bank field.
std::unordered_map< std::string, std::unique_ptr< RegisterProxy > > RegisterProxyMap
Map of strings to self-deleting RegisterProxy instances.
bool canLookupRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx) const noexcept
Determines if a register exists with the given group number and index.
RegisterBase::bank_idx_type getNumBanks() const
Returns the number of banks created (empty banks are automatically created between sprarse bank indic...
uint32_t getGroupSize(RegisterBase::group_num_type group_num, RegisterBase::bank_idx_type bank_num)
Alternate getGroupSize with additional bank field.
RegisterBase * getRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx, RegisterBase::bank_idx_type bank_idx)
Alternate getRegister with additional bank field.
typename RegisterBankTable< RegisterBase >::RegisterVector GroupVector
Vector of RegisterVectors used for lookup by numeric group number of type Register::Definition::group...
uint32_t getNumRegisters() const
Gets the number of counters in this Set.
void reset()
Reset all registers in this set to default values.
void setMinimumBankIndex(RegisterBase::bank_idx_type min_idx)
Sets the minimum bank index for this register set, overriding the default of Register::BANK_IDX_DEFAU...
RegisterBase * lookupRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx, RegisterBase::bank_idx_type bank_idx)
Alternate lookupRegister with additional bank field.
RegisterBase * lookupRegister(RegisterBase::group_num_type group_num, RegisterBase::group_idx_type group_idx)
Quickly looks up a register by its number and index with bounds checking.
RegisterBase::group_idx_type getNumGroups() const
Returns the number of groups in this register set.
typename RegisterBankTable< RegisterBase >::RegisterVector RegisterVector
Type for holding registers.
virtual std::string stringize(bool pretty=false) const override
Create a string representation of this node.
~RegisterSet()
Destructor.
uint32_t getGroupSize(RegisterBase::group_num_type group_num) noexcept
Gets the number of Registers in a group by its group num.
An implementation of a RegisterBase.
Used to construct and throw a standard C++ exception. Inherits from std::exception.
static StringManager & getStringManager()
Returns the StringManager singleton.
std::string * internString(const std::string &s)
Stores a string in shared space within this manager unless it is already stored.
Node in a composite tree representing a sparta Tree item.
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
std::string getLocation() const override final
static constexpr char GROUP_NAME_BUILTIN[]
Reserved name for built-in nodes.
TreeNode()=delete
Not default-constructable.
void addChild(TreeNode *child, bool inherit_phase=true)
Adds a TreeNode to this node as a child.
void setExpectedParent_(const TreeNode *parent)
Tracks a node as an expected parent without actually adding this node as a child. This is used almost...
Macros for handling exponential backoff.
std::ostream & operator<<(std::ostream &o, const SimulationInfo &info)
ostream insertion operator for SimulationInfo
Describes an architected Register.
Describes a register Proxy.
const Register::group_idx_type group_idx
Group index by which the a Register will be looked up when this RegisterProxy is accessed.
const Register::group_num_type group_num
Group number by which the a Register will be looked up when this RegisterProxy is accessed.
const char * desc
Description of this proxy as if it were a Register. Must NOT be NULL.
const Register::ident_type id
ID. Must be unique within all registers and register proxies within a register set.
const char * group
String name of group in which this register resides (e.g. gpr). Must NOT be NULL. This is the same as...
const char * name
String identifier for this register proxy. This name must be unique from all other RegisterProxies in...