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>
491 ArchData::DEFAULT_INITIAL_FILL_SIZE,
493 , cur_bank_fxn_(cbfxn)
502 const auto *rdef = defs;
503 if (rdef !=
nullptr) {
504 while (rdef->name !=
nullptr) {
505 addRegister_<RegisterT>(rdef);
511 const auto *pdef = proxy_defs;
512 if (pdef !=
nullptr) {
513 while (pdef->name !=
nullptr) {
530 template <
typename RegisterT>
539 template <
typename RegisterT = Register>
540 static std::unique_ptr<RegisterSet>
546 return std::unique_ptr<RegisterSet>(
new RegisterSet(
547 parent, defs, proxy_defs, cbfxn, RegisterTypeTag<RegisterT>()));
550 template <
typename RegisterT = Register>
551 static std::unique_ptr<RegisterSet>
552 create(
TreeNode *parent,
const RegisterBase::Definition *defs)
554 return std::unique_ptr<RegisterSet>(
new RegisterSet(
555 parent, defs, RegisterTypeTag<RegisterT>()));
565 for (
auto r : owned_regs_) {
574 for (uint32_t i=0; i<regs_.size(); i++) {
630 virtual std::string
stringize(
bool pretty=
false)
const override {
632 std::stringstream ss;
633 ss <<
'<' <<
getLocation() <<
' ' << regs_.size() <<
" regs>";
655 return getChildAs<RegisterBase>(name);
673 auto rpi = reg_proxies_.find(name);
674 if(rpi != reg_proxies_.end()){
675 return *(rpi->second.get());
677 auto r = getChildAs<RegisterBase>(name,
false);
680 <<
" named \"" << name <<
"\" because there was no existing proxy and no "
681 "register with this name.";
684 typename RegisterProxyMap::mapped_type(
new RegisterProxy(*r));
685 return *reg_proxies_[name];
716 return banks_.canLookupRegister(group_num, group_idx, bank_idx);
753 const auto idx_count = rm.count(group_idx);
757 return (idx_count==1 ? rm.at(group_idx) :
nullptr);
770 const auto &rm = banks_[bank_idx][group_num];
771 const auto idx_count = rm.count(group_idx);
775 return (idx_count==1 ? rm.at(group_idx) :
nullptr);
806 return banks_.
getRegister(group_num, group_idx, bank_idx);
851 const std::string *name_ptr)
const
853 if (cur_bank_fxn_ ==
nullptr) {
856 return cur_bank_fxn_(group_num, group_idx, name_ptr);
868 virtual void onAddingChild_(
TreeNode *child)
override
871 if (
nullptr == reg) {
873 << child <<
" which is not a Register to RegisterSet "
878 regs_.push_back(reg);
894 template <
typename RegisterT>
895 void addRegister_(
const RegisterBase::Definition *rdef)
899 auto r =
new RegisterT(
nullptr, *rdef, &adata_);
906 owned_regs_.push_back(r);
918 void addProxy_(
const RegisterProxyBase::Definition *pdef)
921 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
922 <<
" with a null proxy definition");
926 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
927 <<
" with a null proxy name");
929 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
930 <<
" named \"" << pdef->name <<
"\" with a null proxy description");
932 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
933 <<
" named \"" << pdef->name <<
"\" with a group number of "
934 "GROUP_NUM_NONE. RegisterProxy definitions must have a valid group number");
936 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
937 <<
" named \"" << pdef->name <<
"\" with a group number of "
938 "GROUP_NUM_NONE. RegisterProxy definitions must have a valid group number");
941 for(
auto& reg : regs_){
943 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
944 <<
" named \"" << pdef->name <<
"\" with an ID of " << pdef->id
945 <<
" which is already usd by Register " << reg);
949 auto reg_samename = getChildAs<RegisterBase>(pdef->name,
false);
951 "Attempted to add a RegisterProxy to RegisterSet " <<
getLocation()
952 <<
" named \"" << pdef->name <<
"\" but there is already a normal "
953 "Register with the same name: " << reg_samename->getLocation());
956 auto rpi = reg_proxies_.find(pdef->name);
957 if(rpi != reg_proxies_.end()){
958 throw SpartaException(
"A RegisterProxy in ") <<
getLocation()
959 <<
" named \"" << pdef->name <<
"\" already exists";
966 uint32_t matches = 0;
967 for(uint32_t b = 0; b < banks_.
getNumBanks(); b++){
968 if(banks_.canLookupRegister(pdef->group_num, pdef->group_idx, b)){
969 auto r = banks_.lookupRegister(pdef->group_num, pdef->group_idx, b);
978 "Attempted to add a RegisterProxy to RegisterSet "
979 <<
getLocation() <<
" named \"" << pdef->name <<
"\" which matched "
980 "the group number and group index with " << *r <<
" but the "
981 "proxy had an incorrect group name \"" << pdef->group <<
"\"");
989 "Attempted to add a RegisterProxy to RegisterSet "
990 <<
getLocation() <<
" named \"" << pdef->name <<
"\" with group num "
991 << pdef->group_num <<
" and group idx " << pdef->group_idx <<
" which did "
992 "not match any known registers");
995 auto rp =
new RegisterProxy(*
this,
999 reg_proxies_[pdef->name] =
typename RegisterProxyMap::mapped_type(rp);
1023 RegisterBankTable<RegisterBase> banks_;
1042 std::stringstream ss;
1043 ss <<
"<RegisterProxy to ";
1047 ss <<
"name: \"" << reg_name_ <<
"\" group: " << group_num_
1048 <<
" idx: " << group_idx_;
1056 if (reg_inv_ !=
nullptr) {
1060 auto bank_idx = rs_.
getCurrentBank(group_num_, group_idx_, reg_name_);
1061 return rs_.
getRegister(group_num_, group_idx_, bank_idx);
1066 if (reg_inv_ !=
nullptr) {
1070 auto bank_idx = rs_.
getCurrentBank(group_num_, group_idx_, reg_name_);
1094 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.
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.
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.
RegisterSet(TreeNode *parent, const RegisterBase::Definition *defs, RegisterTypeTag< RegisterT > tag)
Constructor with no current-bank query function.
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.
RegisterSet(TreeNode *parent, const RegisterBase::Definition *defs, const RegisterProxyBase::Definition *proxy_defs, CurrentBankFunction cbfxn, RegisterTypeTag< RegisterT > tag)
Constructor.
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...