Hello Aditya,
it looks like you would need to keep an array of 'Genode::Mmio' objects. Here is a rough sketch of the idea:
struct Device { Genode::addr_t const base; /* base of the entire device */
struct Block : Genode::Mmio { struct Reg1 : Register<0x0,32> { }; struct Reg2 : Register<0x4,32> { };
/** * Constructor * * \param base base address of the block */ Block(Genode::addr_t base) : Genode::Mmio(base) { }
/** * Init single block */ void init() { write<Reg1>(1); write<Reg2>(2); } };
Block blocks[3] = { { base + 0 }, { base + 0x4c }, { base + 0x3a } };
unsigned num_blocks() const { return sizeof(blocks)/sizeof(blocks[0]); }
Device(Genode::addr_t base) : base(base) { }
void init() { for (unsigned i = 0; i < num_blocks(); i++) blocks[i].init(); } };
With 'Block' I denote the part of the device that occurs repeatedly. The code above models each block as a separate 'Genode::Mmio' instance. Hence, it can be individually positioned. Of course, the 'Device' may also be an 'Genode::Mmio' instance. So registers that occur only once would be placed directly in the 'Device' scope.
Best regards Norman