Hello,
This doubt is more C++ than Genode. The MMIO framework is brilliant for R/W access. The way it goes is that, I create structures and successively inherit Register and Bitfield structures. But would it be wrong if I create an object of the structures and call 'write' and 'read' methods?
Say, struct Register_New : Register<0x4a, 32> { };
and struct Register_New ob; write<ob>(0x5);
The above is just an example. What is normally done is write<Register_New>(0x5). The template in the Mmio class if of Register::Register_base type. But an object to this struct is also Register. So, is there any negative aspect to this?
What I am currently trying out is trying to hold an array of Registers that has such objects for some level of automation. And I don't think Register_array is what I'd look for.
Thanks for your patient replies Aditya
Hi Aditya,
Nice to hear that you like the MMIO framework :-) Personally, I can't see a benefit in constructing an object of a class that does nothing else than inheriting from an Mmio::Register. When trying to compile your example, my compiler complains that I can't use 'ob' in the constant expression 'write<...>', which sounds reasonable to me. Why do you think that 'Register_array' isn't what you're looking for? It may be helpful if you could explain your use case more precisely.
Cheers, Martin
On 08.04.2014 11:29, Aditya Kousik wrote:
Hello,
This doubt is more C++ than Genode. The MMIO framework is brilliant for R/W access. The way it goes is that, I create structures and successively inherit Register and Bitfield structures. But would it be wrong if I create an object of the structures and call 'write' and 'read' methods?
Say, struct Register_New : Register<0x4a, 32> { };
and struct Register_New ob; write<ob>(0x5);
The above is just an example. What is normally done is write<Register_New>(0x5). The template in the Mmio class if of Register::Register_base type. But an object to this struct is also Register. So, is there any negative aspect to this?
What I am currently trying out is trying to hold an array of Registers that has such objects for some level of automation. And I don't think Register_array is what I'd look for.
Thanks for your patient replies Aditya
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hello Martin,
Truth be told, I didn't want to probe the use of an object myself. But, if I want to create an array of registers that can be iteratively called, it saves a lot of effort as opposed to manually writing register by register. Since write <..> involves explicit 'register_name' here. I'm not sure (or I may not know how) if I can create an array of Mmio::Register's since declaration to Register necessitates an offset and access width.
Normally, my initial attempt was to create an array of addresses that pointed to the starting address of the registers. This gives us random access and ability to put R/W accesses in a loop. But it is very primitive and does not use the access_t concept.
But then, as you've said I looked into Register_array a bit deeper. Here is an approach I've thought of. Define all registers with offset values. Then, define a Register_array, say R_array that has an offset to the first defined register, number of items = number of registers. This works given the registers in between are all of the same size (obviously). If there are N registers defined, then write<R_array>(value, idx) should write to the ith register defined, right? Not necessarily.
Consider this.
class Foo : Mmio { struct reg1 : Register<0x0, 32> { }; struct reg2: Register<0x4, 32> { }; struct reg3: Register<0x10, 32> { }; struct reg4: Register<0x4c, 32> { }; struct reg_array : Register_array<0x0, 32,32,4> { };
public: void write_to_regs() { write<reg1>(0); write<reg4>(0xff); } };
Will I achieve random access to the registers with the use of the register array? No. Unless, I am fundamentally wrong her, in which case, I'd be glad to know where I'm going wrong.
Thanks and regards Aditya.
On Tue, Apr 8, 2014 at 4:23 PM, Martin Stein <martin.stein@...1...>wrote:
Hi Aditya,
Nice to hear that you like the MMIO framework :-) Personally, I can't see a benefit in constructing an object of a class that does nothing else than inheriting from an Mmio::Register. When trying to compile your example, my compiler complains that I can't use 'ob' in the constant expression 'write<...>', which sounds reasonable to me. Why do you think that 'Register_array' isn't what you're looking for? It may be helpful if you could explain your use case more precisely.
Cheers, Martin
On 08.04.2014 11:29, Aditya Kousik wrote:
Hello,
This doubt is more C++ than Genode. The MMIO framework is brilliant for R/W access. The way it goes is that, I create structures and successively inherit Register and Bitfield structures. But would it be wrong if I create an object of the structures and call 'write' and 'read' methods?
Say, struct Register_New : Register<0x4a, 32> { };
and struct Register_New ob; write<ob>(0x5);
The above is just an example. What is normally done is write<Register_New>(0x5). The template in the Mmio class if of Register::Register_base type. But an object to this struct is also Register. So, is there any negative aspect to this?
What I am currently trying out is trying to hold an array of Registers that has such objects for some level of automation. And I don't think Register_array is what I'd look for.
Thanks for your patient replies Aditya
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud.http://p.sf.net/sfu/13600_Cloudbees
Genode-main mailing listGenode-main@...220...://lists.sourceforge.net/lists/listinfo/genode-main
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hi Aditya,
If I understand you right, all you want is to randomly access the registers by their array index. This is exactly what 'Register_array' was created for. The driver 'base-hw/src/core/pic/imx31.h' gives a good example of how to use it for plain registers. There you have an array that starts at MMIO base + 0x20 and spans over 8 registers of 32 bit width each:
struct Nipriority : Register_array<0x20, 32, 8, 32> { enum { ALL_LOWEST = 0 }; };
Please note that the second template argument doesn't define the width of the array items (this is the forth argument) but the internal access width which affect performance only. Iterative access is done in this driver later as follows:
for (unsigned i = 0; i < Nipriority::ITEMS; i++) { write<Nipriority>(Nipriority::ALL_LOWEST, i); }
As you can see, you can use the enum 'ITEMS' which is defined by every 'Register_array' as loop parameter. You can also use bit-fields inside of register arrays instead of having plain registers only. The driver 'base-hw/src/core/pic/arm_gic.h' gives a good example for that:
struct Icfgr : Register_array<0xc00, 32, MAX_INTERRUPT_ID + 1, 2> { struct Edge_triggered : Bitfield<1, 1> { }; };
...
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) { _distr.writeDistr::Icfgr::Edge_triggered(0, i); ... }
So, here you have a register array 'Icfgr' that starts at MMIO base + 0xc00 and spans over MAX_INTERRUPT_ID + 1 registers of 2 bit width each. The least significant bit of each register is unused, but the second bit is defined to be the bit field 'Edge_triggered'. As you can see, the way of accessing 'Edge_triggered' via the register index 'i' is quite intuitive if you know how to access plain register arrays. I hope this helps you with your problem. If you have further questions, don't hesitate to ask ;-)
Cheers, Martin
On 08.04.2014 13:23, Aditya Kousik wrote:
Hello Martin,
Truth be told, I didn't want to probe the use of an object myself. But, if I want to create an array of registers that can be iteratively called, it saves a lot of effort as opposed to manually writing register by register. Since write <..> involves explicit 'register_name' here. I'm not sure (or I may not know how) if I can create an array of Mmio::Register's since declaration to Register necessitates an offset and access width.
Normally, my initial attempt was to create an array of addresses that pointed to the starting address of the registers. This gives us random access and ability to put R/W accesses in a loop. But it is very primitive and does not use the access_t concept.
But then, as you've said I looked into Register_array a bit deeper. Here is an approach I've thought of. Define all registers with offset values. Then, define a Register_array, say R_array that has an offset to the first defined register, number of items = number of registers. This works given the registers in between are all of the same size (obviously). If there are N registers defined, then write<R_array>(value, idx) should write to the ith register defined, right? Not necessarily.
Consider this.
class Foo : Mmio { struct reg1 : Register<0x0, 32> { }; struct reg2: Register<0x4, 32> { }; struct reg3: Register<0x10, 32> { }; struct reg4: Register<0x4c, 32> { }; struct reg_array : Register_array<0x0, 32,32,4> { };
public: void write_to_regs() { write<reg1>(0); write<reg4>(0xff); } };
Will I achieve random access to the registers with the use of the register array? No. Unless, I am fundamentally wrong her, in which case, I'd be glad to know where I'm going wrong.
Thanks and regards Aditya.
On Tue, Apr 8, 2014 at 4:23 PM, Martin Stein <martin.stein@...1... mailto:martin.stein@...1...> wrote:
Hi Aditya, Nice to hear that you like the MMIO framework :-) Personally, I can't see a benefit in constructing an object of a class that does nothing else than inheriting from an Mmio::Register. When trying to compile your example, my compiler complains that I can't use 'ob' in the constant expression 'write<...>', which sounds reasonable to me. Why do you think that 'Register_array' isn't what you're looking for? It may be helpful if you could explain your use case more precisely. Cheers, Martin On 08.04.2014 11:29, Aditya Kousik wrote:
Hello, This doubt is more C++ than Genode. The MMIO framework is brilliant for R/W access. The way it goes is that, I create structures and successively inherit Register and Bitfield structures. But would it be wrong if I create an object of the structures and call 'write' and 'read' methods? Say, struct Register_New : Register<0x4a, 32> { }; and struct Register_New ob; write<ob>(0x5); The above is just an example. What is normally done is write<Register_New>(0x5). The template in the Mmio class if of Register::Register_base type. But an object to this struct is also Register. So, is there any negative aspect to this? What I am currently trying out is trying to hold an array of Registers that has such objects for some level of automation. And I don't think Register_array is what I'd look for. Thanks for your patient replies Aditya ------------------------------------------------------------------------------ Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> https://lists.sourceforge.net/lists/listinfo/genode-main
------------------------------------------------------------------------------ Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net <mailto:Genode-main@lists.sourceforge.net> https://lists.sourceforge.net/lists/listinfo/genode-main
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees
Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
Hello Martin,
That's two things I've learnt. The Register_array structure really comes in handy if you have equally spaced registers. Such as interrupts that come in multitudes together, where ordering through index works fine.
The other use is with templates, with offsets. I've seen this in Genode's code itself.
My question is not this, (interestingly?).
Consider this. 5 disjoint registers defined as follows
class Reg_group : Genode::Mmio
{
struct reg1 : Register<0x0,32> { };
struct reg2 : Register<0x4c,32> { };
struct reg3 : Register<0x3a,32> { };
struct reg4 : Register<0x10a,32> { };
struct reg5 : Register<0x88, 32> { };
public: void init()
{
//init here
}
};
The above registers are just arbitrarily assigned. Is the only way of writing to these registers as follows?
write<reg1/2/3>(0x10); What I'm trying to do, is to have the above random registers as the contents of some array-like structure that can be called like so:
for(i = 0; i<5; i++)
write<array[i]>(i);
where array would be {reg1, reg2, reg3, reg4, reg5}. This is just a thought process. I'm terribly sorry if I'm being obscure.
Thanks for your patience
Aditya. Hi Aditya,
If I understand you right, all you want is to randomly access the registers by their array index. This is exactly what 'Register_array' was created for. The driver 'base-hw/src/core/pic/imx31.h' gives a good example of how to use it for plain registers. There you have an array that starts at MMIO base + 0x20 and spans over 8 registers of 32 bit width each:
struct Nipriority : Register_array<0x20, 32, 8, 32> { enum { ALL_LOWEST = 0 }; };
Please note that the second template argument doesn't define the width of the array items (this is the forth argument) but the internal access width which affect performance only. Iterative access is done in this driver later as follows:
for (unsigned i = 0; i < Nipriority::ITEMS; i++) { write<Nipriority>(Nipriority::ALL_LOWEST, i); }
As you can see, you can use the enum 'ITEMS' which is defined by every 'Register_array' as loop parameter. You can also use bit-fields inside of register arrays instead of having plain registers only. The driver 'base-hw/src/core/pic/arm_gic.h' gives a good example for that:
struct Icfgr : Register_array<0xc00, 32, MAX_INTERRUPT_ID + 1, 2> { struct Edge_triggered : Bitfield<1, 1> { }; };
...
for (unsigned i=MIN_SPI; i <= _max_interrupt; i++) { _distr.writeDistr::Icfgr::Edge_triggered(0, i); ... }
So, here you have a register array 'Icfgr' that starts at MMIO base + 0xc00 and spans over MAX_INTERRUPT_ID + 1 registers of 2 bit width each. The least significant bit of each register is unused, but the second bit is defined to be the bit field 'Edge_triggered'. As you can see, the way of accessing 'Edge_triggered' via the register index 'i' is quite intuitive if you know how to access plain register arrays. I hope this helps you with your problem. If you have further questions, don't hesitate to ask ;-)
Cheers, Martin
On 08.04.2014 13:23, Aditya Kousik wrote:
Hello Martin,
Truth be told, I didn't want to probe the use of an object myself. But, if I want to create an array of registers that can be iteratively called, it saves a lot of effort as opposed to manually writing register by register. Since write <..> involves explicit 'register_name' here. I'm not sure (or I may not know how) if I can create an array of Mmio::Register's since declaration to Register necessitates an offset and access width.
Normally, my initial attempt was to create an array of addresses that pointed to the starting address of the registers. This gives us random access and ability to put R/W accesses in a loop. But it is very primitive and does not use the access_t concept.
But then, as you've said I looked into Register_array a bit deeper. Here is an approach I've thought of. Define all registers with offset values. Then, define a Register_array, say R_array that has an offset to the first defined register, number of items = number of registers. This works given the registers in between are all of the same size (obviously). If there are N registers defined, then write<R_array>(value, idx) should write to the ith register defined, right? Not necessarily.
Consider this.
class Foo : Mmio { struct reg1 : Register<0x0, 32> { }; struct reg2: Register<0x4, 32> { }; struct reg3: Register<0x10, 32> { }; struct reg4: Register<0x4c, 32> { }; struct reg_array : Register_array<0x0, 32,32,4> { };
public: void write_to_regs() { write<reg1>(0); write<reg4>(0xff); } };
Will I achieve random access to the registers with the use of the register array? No. Unless, I am fundamentally wrong her, in which case, I'd be glad to know where I'm going wrong.
Thanks and regards Aditya.
On Tue, Apr 8, 2014 at 4:23 PM, Martin Stein <martin.stein@...1...>wrote:
Hi Aditya,
Nice to hear that you like the MMIO framework :-) Personally, I can't see a benefit in constructing an object of a class that does nothing else than inheriting from an Mmio::Register. When trying to compile your example, my compiler complains that I can't use 'ob' in the constant expression 'write<...>', which sounds reasonable to me. Why do you think that 'Register_array' isn't what you're looking for? It may be helpful if you could explain your use case more precisely.
Cheers, Martin
On 08.04.2014 11:29, Aditya Kousik wrote:
Hello,
This doubt is more C++ than Genode. The MMIO framework is brilliant for R/W access. The way it goes is that, I create structures and successively inherit Register and Bitfield structures. But would it be wrong if I create an object of the structures and call 'write' and 'read' methods?
Say, struct Register_New : Register<0x4a, 32> { };
and struct Register_New ob; write<ob>(0x5);
The above is just an example. What is normally done is write<Register_New>(0x5). The template in the Mmio class if of Register::Register_base type. But an object to this struct is also Register. So, is there any negative aspect to this?
What I am currently trying out is trying to hold an array of Registers that has such objects for some level of automation. And I don't think Register_array is what I'd look for.
Thanks for your patient replies Aditya
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud.http://p.sf.net/sfu/13600_Cloudbees
Genode-main mailing listGenode-main@...220...://lists.sourceforge.net/lists/listinfo/genode-main
Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
------------------------------------------------------------------------------ Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud.http://p.sf.net/sfu/13600_Cloudbees
_______________________________________________ Genode-main mailing listGenode-main@...220...://lists.sourceforge.net/lists/listinfo/genode-main
------------------------------------------------------------------------------ Put Bad Developers to Shame Dominate Development with Jenkins Continuous Integration Continuously Automate Build, Test & Deployment Start a new project now. Try Jenkins in the cloud. http://p.sf.net/sfu/13600_Cloudbees _______________________________________________ Genode-main mailing list Genode-main@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/genode-main
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