Skip to main content

Attribute: pack_mode

The pragma defines how a data structure is packed during the allocation. The attribute has to be inserted above the data structure and affects the packing of the entire structure.

Syntax:

{attribute 'pack_mode' := ' <pack mode value> '}

Insert location: Above the declaration of the data structure

Table 27. Possible values for <pack mode value>

<pack mode value>

Associated packing method

Description

0

Aligned

All variables are allocated to byte addresses. There are no memory gaps.

1

1-byte-aligned

2

2-byte-aligned

. There are
  • 1-byte variables at byte addresses

  • 2-byte variables at addresses divisible by 2. A maximum gap of 1 byte results.

  • 4-byte variables at addresses divisible by 2. A maximum gap of 1 byte results.

  • 8-byte variables at addresses divisible by 2. A maximum gap of 1 byte results.

  • Strings always at byte addresses. No gaps result.

4

4-byte-aligned

. There are
  • 1-byte variables at byte addresses

  • 2-byte variables at addresses divisible by 2. A maximum gap of 1 byte results.

  • 4 byte variables at addresses divisible by 4. A maximum gap of 3 byte results.

  • 8-byte variables at addresses divisible by 4. A maximum gap of 3 byte results.

  • Strings always at byte addresses. No gaps result.

8

8-byte-aligned

. There are
  • 1-byte variables at byte addresses

  • 2-byte variables at addresses divisible by 2. A maximum gap of 1 byte results.

  • 4 byte variables at addresses divisible by 4. A maximum gap of 3 byte results.

  • 8 byte variables at addresses divisible by 8. A maximum gap of 7 byte results.

  • Strings always at byte addresses. No gaps result.



Tip

Depending on the structure, there may be no difference in the memory mapping of the individual modes. For example, the memory distribution of a structure with the {attribute 'pack mode' := '4'} pragma can correspond to that of {attribute 'pack mode' := '8'}.

Tip

Arrays of structures

If the structures are combined in arrays, then bytes are added at the end of the structure so that the next structure is aligned.

Important

If the Compatibility layout option is selected in the symbol configuration and at the same time the attribute 'pack_mode' is used in the code, then problems can occur due to unintentional memory misalignment.

Example 1

{attribute 'pack_mode' := '1'}

TYPE myStruct:
STRUCT
  Enable: BOOL;
  Counter: INT;
  MaxSize: BOOL;
  MaxSizeReached: BOOL;
  END_STRUCT
END_TYPE

The memory range for a variable of the data type myStruct is allocated "aligned". If the storage address of its component Enable is 0x0100, for example, then the component Counter follows at the address 0x0101, MaxSize at address 0x0103 and MaxSizeReached at address 0x0104. In the case of 'pack_mode':=2, Counter would be at 0x0102, MaxSize at 0x0104 and MaxSizeReached at 0x0105.

Example 2

STRUCT
  Var1 : BOOL  := 16#01;
  Var2 : BYTE  := 16#11;
  Var3 : WORD  := 16#22;
  Var4 : BYTE  := 16#44;
  Var5 : DWORD := 16#88776655;
  Var6 : BYTE  := 16#99;
  Var7 : BYTE  := 16#AA;
  Var8 : DWORD := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

Variable

Value

Variable

Value

Variable

Value

Variable

Value

Variable

Value

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

Var2

11

Var2

11

Var2

11

2

Var3

22

Var3

22

Var3

22

Var3

22

Var3

22

3

…

00

…

00

…

00

…

00

…

00

4

Var4

44

Var4

44

Var4

44

Var4

44

Var4

44

5

Var5

55

Var5

55

6

…

66

…

66

Var5

55

7

…

77

…

77

…

66

8

Var5

55

…

88

…

88

…

77

Var5

55

9

…

66

Var6

99

Var6

99

…

88

…

66

10

…

77

Var7

AA

Var7

AA

Var6

99

…

77

11

…

88

Var8

AA

Var8

AA

Var7

AA

…

88

12

Var6

99

…

00

…

00

Var8

AA

Var6

99

13

Var7

AA

…

00

…

00

…

00

Var7

AA

14

…

00

…

00

…

00

15

…

00

16

Var8

AA

Var8

AA

17

…

00

…

00

18

…

00

…

00

19

…

00

…

00

20

21

22

23

24

25

26

27

28

29

30

31

Example 3

STRUCT
    Var1 : BYTE  := 16#01;
    Var2 : LWORD := 16#11;
    Var3 : BYTE  := 16#22;
    Var4 : BYTE  := 16#44;
    Var5 : DWORD := 16#88776655;
    Var6 : BYTE  := 16#99;
    Var7 : BYTE  := 16#AA;
    Var8 : WORD  := 16#AA;
END_TYPE

pack_mode = 8

pack_mode = 0

pack_mode = 1

pack_mode = 2

pack_mode = 4

Variable

Value

Variable

Value

Variable

Value

Variable

Value

Variable

Value

0

Var1

01

Var1

01

Var1

01

Var1

01

Var1

01

1

Var2

11

Var2

11

2

…

00

…

00

Var2

11

3

…

00

…

00

…

00

4

…

00

…

00

…

00

Var2

11

5

…

00

…

00

…

00

…

00

6

…

00

…

00

…

00

…

00

7

…

00

…

00

…

00

…

00

8

Var2

11

…

00

…

00

…

00

…

00

9

…

00

Var3

22

Var3

22

…

00

…

00

10

…

00

Var4

44

Var4

44

Var3

22

…

00

11

…

00

Var5

55

Var5

55

Var4

44

…

00

12

…

00

…

66

…

66

Var5

55

Var3

22

13

…

00

…

77

…

77

…

66

Var4

44

14

…

00

…

88

…

88

…

77

15

…

00

Var6

99

Var6

99

…

88

16

Var3

22

Var7

AA

Var7

AA

Var6

99

Var5

55

17

Var4

44

Var8

AA

Var8

AA

Var7

AA

…

66

18

…

00

…

00

Var8

AA

…

77

19

…

00

…

88

20

Var5

55

Var6

99

21

…

66

Var7

AA

22

…

77

Var8

AA

23

…

88

…

00

24

Var6

99

25

Var7

AA

26

Var8

AA

27

…

00

28

29

30

31

Behavior without 'pack-mode'

If 'pack-mode’ is not used, then the compiler typically uses pack mode 4 or 8, depending on the device description. In each case, a pack mode which is particularly beneficial for the processor is used so that memory access can be performed. This is also called natural alignment or a natural alignment of data.

Negative effects when using 'pack-mode'

Unaligned memory access can be the result of using the attribute 'pack_mode'. This means, for example, that a data type with a size of 4 bytes is then located at an address which is not divisible by 4. Normally, on a 32-bit system a 32-bit data type can be read and written with a single memory access. On some platforms, for example on ARM platforms, this is possible only when this value is aligned in the memory. On other platforms, it can be that the access is possible but it is performed much more slowly.

{attribute 'pack_mode':=1}

TYPE DUT
STRUCT
    by1 : BYTE;
    dw1 : DWORD;
END_STRUCT
END_TYPE

On an ARM platform, the value dw1 cannot be read with a single access. When an attempt is made to access this element directly, the ARM processor will throw an exception.

Assumption: The following read access is performed: dwTest := dut1.dw1;

For this access to the DWORD dw1, four memory accesses are required because each byte is read, shifted, and disjuncted individually. The flow is somewhat the same as in the following example in which a DWORD is generated from an array of four bytes:

dwHelp := bytes[0];
dwResult := dwHelp;
dwHelp := bytes[1];
dwHelp := SHL(dwHelp, 8);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[2];
dwHelp := SHL(dwHelp, 16);
dwResult := dwResult OR dwHelp;
dwHelp := bytes[3];
dwHelp := SHL(dwHelp, 24);
dwResult := dwResult OR dwHelp;

Obviously, this kind of access is much slower than access to a DWORD, which is aligned appropriately in the memory.

pdw := ADR(dut1.dw1);
dwTest := pdw^;

However, the compiler will not generate the access of the example when this kind of member is accessed by means of a pointer. This means that the following code results in an exception on an ARM platform.

pdw := ADR(dut1.dw1);
dwTest := pdw^;

For performance reasons, you should therefore avoid working with structures which are not naturally aligned.

A packed structure must not contain an unpacked structure.