I'm working on modelling some hardware in SystemC (although that's not relevant to the question). The goal is to be able to declare a bunch of registers in a block (class) which are used directly in the class implementation. The external software/firmware will access the registers through a register map to decode based on address. So the HW block as part of its constructor will initialize the register map (not shown below). The issue arises from the fact that some registers need to trigger an action. To do this is seems appropriate to have method in the HW class that is called if the register is written.
The simplified class hierarchy is as follows
class regBase {
public:
regBase(uint64_t _address, std::string _name) :
m_address(_address),
m_name(_name) { }
regBase() {};
void setAddress(uint64_t _address) { m_address = _address;}
virtual void write(uint32_t newval) = 0; //virtual methods to be overridden in template
virtual uint32_t read(void) = 0;
virtual int size(void) = 0;
private:
uint64_t m_address;
std::string m_name;
};
template <class REG>
class hwRegister : public regBase
{
public:
uint32_t read(void) override
{
return m_val.value();
}
void write(uint32_t newval) override
{
m_val.setValue(newval);
}
int size(void) override
{
return (m_val.size());
}
private:
REG m_val;
};
typedef std::function<void(uint64_t, uint32_t)> writeCallback_t;
struct reg_entry {
reg_entry(int _size, regBase *_reg) :
m_reg(_reg), m_size(_size) {}
reg_entry() {}
regBase *m_reg;
int m_size;
writeCallback_t m_callback;
};
typedef boost::ptr_map<int, std::shared_ptr<reg_entry> > reg_map_t;
class RegMap {
public:
void write(uint64_t address, uint32_t val) {
auto it = m_register_map.find(address);
if (it==m_register_map.end())
{
BOOST_ASSERT_MSG(false, "Invalid address");
}
auto entry = *it->second;
entry->m_reg->write(val);
if (entry->m_callback)
entry->m_callback(address, val);
};
void setCallback(uint64_t address, writeCallback_t newcallback)
{
auto it = m_register_map.find(address);
if (it==m_register_map.end())
{
BOOST_ASSERT_MSG(false, "Invalid address");
}
(*it->second)->m_callback = newcallback;
};
void addReg(uint64_t address, regBase *reg) {
auto entry = std::make_shared<reg_entry>(reg->size(), reg);
entry->m_callback = nullptr;
entry->m_reg = reg;
m_register_map[address] = entry;
}
private:
reg_map_t m_register_map;
};
I want to in the implementation of HW block, add myReg to myMap and be able to add a callback if necessary for a given register. The issue is around the callback. Does the declaration of the callback look right? Do I need to use std::bind and placeholders? Ok, updated with compiling code.