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 25. 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.