comp.lang.ada
 help / color / mirror / Atom feed
* Dynamic discrimants in variant records?
@ 2003-06-19  8:44 Vinzent Hoefler
  2003-06-19 10:37 ` John McCabe
  2003-06-19 23:57 ` Jeffrey Carter
  0 siblings, 2 replies; 4+ messages in thread
From: Vinzent Hoefler @ 2003-06-19  8:44 UTC (permalink / raw)


Hi,

I got the following question for a type with discrimants. Following an
excerpt from the current source (more a case study than anything
useful yet) with a representation of a memory mapped hardware
register:

|   --  type for a programmable address region register
|   type Programmable_Address_Region (
|       Target : Window_Target := Window_Disabled;
|       Pg_Sz  : Page_Size     := Four_Ki_Byte) is
|   record
|      case Target is
|         when Window_Disabled =>
|            null;
|         when GP_Bus_IO | PCI_Bus =>
|            IO_Attr       : Chip_Select_Signal;
|            Sz_St_Addr_IO : IO_Page;
|         when GP_Bus_Memory | Boot_CS | Rom_CS_1 | Rom_CS_2 | SD_Ram =>
|            Mem_Attr : Memory_Attribute;
|
|            case Pg_Sz is
|               when Four_Ki_Byte =>
|                  Sz_St_Addr_4K  : Mem_Page_4K;
|               when Sixty_Four_Ki_Byte =>
|                  Sz_St_Addr_64K : Mem_Page_64K;
|            end case;
|      end case;
|   end record;

Well, so far so good, I can perfectly define a corresponding type
statically. Deciding which of the registers to use for what region of
memory statically is probably quite ok for most real world cases, but
I really would like to have a little bit more flexibility.

As mentioned, the actual (global) variables of this type are memory
mapped registers, so the problem occurs when I want to change a region
register dynamically (from a 4K granularity to a 64K for instance). In
Ada this would be equivalent to just change some of the discrimants
(those are really some bits in the register) and so changing the
interpretation of the record.

AFAICS this is not allowed in Ada, once a variable of a specific type
is declared I cannot change its discriminants anymore. Is there any
nice Ada-ish way around this?

Or IOW, how would someone do that what I want in the most efficient
way? Declaring an appropriate type each time and use an unchecked
conversion to apply it to the "real" memory mapped register?


Vinzent.

-- 
There are two ways of constructing a software design. One way is to make
it so simple that there are obviously no deficiencies. And the other is
to make it so complicated that there are no obvious deficiencies.
  -- T. Hoare



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Dynamic discrimants in variant records?
  2003-06-19  8:44 Dynamic discrimants in variant records? Vinzent Hoefler
@ 2003-06-19 10:37 ` John McCabe
  2003-06-19 23:57 ` Jeffrey Carter
  1 sibling, 0 replies; 4+ messages in thread
From: John McCabe @ 2003-06-19 10:37 UTC (permalink / raw)


On Thu, 19 Jun 2003 10:44:21 +0200, Vinzent Hoefler
<ada.rocks@jlfencey.com> wrote:

>Well, so far so good, I can perfectly define a corresponding type
>statically. Deciding which of the registers to use for what region of
>memory statically is probably quite ok for most real world cases, but
>I really would like to have a little bit more flexibility.
>
>As mentioned, the actual (global) variables of this type are memory
>mapped registers, so the problem occurs when I want to change a region
>register dynamically (from a 4K granularity to a 64K for instance). In
>Ada this would be equivalent to just change some of the discrimants
>(those are really some bits in the register) and so changing the
>interpretation of the record.
>
>AFAICS this is not allowed in Ada, once a variable of a specific type
>is declared I cannot change its discriminants anymore. Is there any
>nice Ada-ish way around this?

>Or IOW, how would someone do that what I want in the most efficient
>way? Declaring an appropriate type each time and use an unchecked
>conversion to apply it to the "real" memory mapped register?

It may be worth reading about mutable and immutable discrimnated
types. Whether you can change the discriminant of an object after it
is created depends on whether default values have been assigned to the
discriminants etc. I can't remember the exact details but "Ada as a
Second Language" is, I seem to remember, quite good on this.

It may also be worth reading the following message and thread.

http://groups.google.com/groups?hl=en&lr=&ie=UTF-8&oe=UTF-8&selm=mailman.10.1046461270.1343.comp.lang.ada%40ada.eu.org


Best Regards
John McCabe

To reply by email replace 'nospam' with 'assen'



^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Dynamic discrimants in variant records?
  2003-06-19  8:44 Dynamic discrimants in variant records? Vinzent Hoefler
  2003-06-19 10:37 ` John McCabe
@ 2003-06-19 23:57 ` Jeffrey Carter
  2003-06-20  7:44   ` Vinzent Hoefler
  1 sibling, 1 reply; 4+ messages in thread
From: Jeffrey Carter @ 2003-06-19 23:57 UTC (permalink / raw)


Vinzent Hoefler wrote:
> 
> |   --  type for a programmable address region register
> |   type Programmable_Address_Region (
> |       Target : Window_Target := Window_Disabled;
> |       Pg_Sz  : Page_Size     := Four_Ki_Byte) is
> |   record
> |      case Target is
> |         when Window_Disabled =>
> |            null;
> |         when GP_Bus_IO | PCI_Bus =>
> |            IO_Attr       : Chip_Select_Signal;
> |            Sz_St_Addr_IO : IO_Page;
> |         when GP_Bus_Memory | Boot_CS | Rom_CS_1 | Rom_CS_2 | SD_Ram =>
> |            Mem_Attr : Memory_Attribute;
> |
> |            case Pg_Sz is
> |               when Four_Ki_Byte =>
> |                  Sz_St_Addr_4K  : Mem_Page_4K;
> |               when Sixty_Four_Ki_Byte =>
> |                  Sz_St_Addr_64K : Mem_Page_64K;
> |            end case;
> |      end case;
> |   end record;
> 
> As mentioned, the actual (global) variables of this type are memory
> mapped registers, so the problem occurs when I want to change a region
> register dynamically (from a 4K granularity to a 64K for instance). In
> Ada this would be equivalent to just change some of the discrimants
> (those are really some bits in the register) and so changing the
> interpretation of the record.

It works sort of like this:

V : Programmable_Address_Region; -- V is unconstrained
for V'Address use ...;
...
V := (Target => GP_Bus_Memory, Pg_Size => Four_Ki_Byte,
       Mem_Attr => ..., Sz_St_Addr_4K => ...);
...
V := (Target => GP_Bus_Memory, Pg_Size => Sixty_Four_Ki_Byte,
       Mem_Attr => V.Mem_Attr, Sz_St_Addr_64K => ...);

If the object is declared without actual values for the discriminants, 
and the discriminants have default values, then the object is 
unconstrained, and the values of the discriminants can change. With many 
compilers, that results in enough space for the largest variant being 
allocated, but since you're locating the object at a specific address, 
that shouldn't be an issue.

However, the only way to change a discriminant of such an object is by 
assigning an entire new value to it. That's why there are complete 
aggregates in the assignments above. The values supplied for the 
discriminants must be static, which means you can't use "V.Target" in 
the 2nd aggregate.

If you must use a non-static value for the discriminant, there's a way 
to do that, too:

declare
    Temp : Programmable_Address_Region
           (Target => V.Target, Pg_Size => Sixty_Four_Ki_Byte);
begin
    Temp.Mem_Attr := V.Mem_Attr;
    Temp.Sz_St_Addr_64K := ...;
    V := Temp;
end;

Note that none of this code has been compiled.

-- 
Jeff Carter
"You cheesy lot of second-hand electric donkey-bottom biters."
Monty Python & the Holy Grail




^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: Dynamic discrimants in variant records?
  2003-06-19 23:57 ` Jeffrey Carter
@ 2003-06-20  7:44   ` Vinzent Hoefler
  0 siblings, 0 replies; 4+ messages in thread
From: Vinzent Hoefler @ 2003-06-20  7:44 UTC (permalink / raw)


Jeffrey Carter wrote:

>Vinzent Hoefler wrote:
>> 
[...]
>> 
>> As mentioned, the actual (global) variables of this type are memory
>> mapped registers, so the problem occurs when I want to change a region
>> register dynamically (from a 4K granularity to a 64K for instance). In
>> Ada this would be equivalent to just change some of the discrimants
>> (those are really some bits in the register) and so changing the
>> interpretation of the record.
>
>It works sort of like this:
>
>V : Programmable_Address_Region; -- V is unconstrained
>for V'Address use ...;
>...
>V := (Target => GP_Bus_Memory, Pg_Size => Four_Ki_Byte,
>       Mem_Attr => ..., Sz_St_Addr_4K => ...);
>...
>V := (Target => GP_Bus_Memory, Pg_Size => Sixty_Four_Ki_Byte,
>       Mem_Attr => V.Mem_Attr, Sz_St_Addr_64K => ...);

*aarg* Call me stupid! That's exactly how I thought, it would *not*
work. Well, I didn't actually try... sorry. I suggest, I will read the
complete ARM three times for penalty. Would this be enough? ;)

>However, the only way to change a discriminant of such an object is by 
>assigning an entire new value to it.

No problem, in this case anything else wouldn't make sense. There are
not many bits in the structure that mean the same if the discrimant
bits change.

>If you must use a non-static value for the discriminant, there's a way 
>to do that, too:
>
>declare
>    Temp : Programmable_Address_Region
>           (Target => V.Target, Pg_Size => Sixty_Four_Ki_Byte);
>begin
>    Temp.Mem_Attr := V.Mem_Attr;
>    Temp.Sz_St_Addr_64K := ...;
>    V := Temp;
>end;
>
>Note that none of this code has been compiled.

Of course, I left out too many details. But I'm quite sure it will.


Vinzent.

-- 
Parents strongly cautioned  --  this  posting  is  intended for mature
audiences  over  18.  It  may  contain some material that many parents
would not find suitable for children and may include intense violence,
sexual situations, coarse language and suggestive dialogue.



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2003-06-20  7:44 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2003-06-19  8:44 Dynamic discrimants in variant records? Vinzent Hoefler
2003-06-19 10:37 ` John McCabe
2003-06-19 23:57 ` Jeffrey Carter
2003-06-20  7:44   ` Vinzent Hoefler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox