Skip to content

test_enumerated_values_copy_via_derived_from

For this feature, test cases cover scenarios where a enumerated values container (enumeratedValues) is copied from a base container with derivedFrom. An enumeratedValues entry is referenced by its name. Although the CMSIS SVD standard states, that the name is resolved by uniques or further qualifiecation by specifying the associated field, register, and peripheral, svdconv can only resolve references by the same rules as the referencing derivedFrom works on peripheral, cluster, register, and field level. Since the validity of SVD files is primarily verified using svdconv, any parser implementation should ensure that its name resolution mechanism at the enumeratedValues level is consistent with that of svdconv. To maintain compatibility, the parser should adopt the same approach to name resolution, following the same rules and hierarchy used by svdconv.

test_backward_reference_different_scope

This test case verifies that an enumerated values container can be correctly copied from another field. In the SVD file, FieldA defines an enumerated values container named FieldAEnumeratedValue, while FieldB copies this container using the derivedFrom attribute. This allows FieldB to reuse the same set of enumerated values as FieldA, ensuring consistency across fields.

Expected Outcome: The parser should successfully process the SVD file, allowing FieldB to copy the enumerated values from FieldA's FieldAEnumeratedValue. The enumerated values should be identical for both FieldA and FieldB, and no conflicts or errors should arise during parsing.

Processable with svdconv: yes

Source code in tests/test_process/test_enumerated_values_copy_via_derived_from.py
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_backward_reference_different_scope(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test case verifies that an enumerated values container can be correctly copied from another field. In the
    SVD file, `FieldA` defines an enumerated values container named `FieldAEnumeratedValue`, while `FieldB` copies
    this container using the `derivedFrom` attribute. This allows `FieldB` to reuse the same set of enumerated
    values as `FieldA`, ensuring consistency across fields.

    **Expected Outcome:** The parser should successfully process the SVD file, allowing `FieldB` to copy the
    enumerated values from `FieldA`'s `FieldAEnumeratedValue`. The enumerated values should be identical for both
    `FieldA` and `FieldB`, and no conflicts or errors should arise during parsing.

    **Processable with svdconv:** yes
    """

    device = get_processed_device_from_testfile("enum_copy_via_derivedfrom/backward_reference_different_scope.svd")

    assert len(device.peripherals) == 1
    assert len(device.peripherals[0].registers_clusters) == 1

    assert isinstance(device.peripherals[0].registers_clusters[0], Register)
    assert device.peripherals[0].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[0].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[0].registers_clusters[0].size == 32
    assert len(device.peripherals[0].registers_clusters[0].fields) == 2

    assert device.peripherals[0].registers_clusters[0].fields[0].name == "FieldA"
    assert device.peripherals[0].registers_clusters[0].fields[0].lsb == 0
    assert device.peripherals[0].registers_clusters[0].fields[0].msb == 0
    assert len(device.peripherals[0].registers_clusters[0].fields[0].enumerated_value_containers) == 1
    fielda_enum_container = device.peripherals[0].registers_clusters[0].fields[0].enumerated_value_containers[0]
    assert fielda_enum_container.name == "FieldAEnumeratedValue"
    assert fielda_enum_container.usage == EnumUsageType.READ_WRITE
    assert len(fielda_enum_container.enumerated_values) == 2
    assert fielda_enum_container.enumerated_values[0].name == "0b0"
    assert fielda_enum_container.enumerated_values[0].description == "Description for 0b0"
    assert fielda_enum_container.enumerated_values[0].value == 0b0
    assert fielda_enum_container.enumerated_values[1].name == "0b1"
    assert fielda_enum_container.enumerated_values[1].description == "Description for 0b1"
    assert fielda_enum_container.enumerated_values[1].value == 0b1

    assert device.peripherals[0].registers_clusters[0].fields[1].name == "FieldB"
    assert device.peripherals[0].registers_clusters[0].fields[1].lsb == 1
    assert device.peripherals[0].registers_clusters[0].fields[1].msb == 1
    assert len(device.peripherals[0].registers_clusters[0].fields[1].enumerated_value_containers) == 1
    fieldb_enum_container = device.peripherals[0].registers_clusters[0].fields[1].enumerated_value_containers[0]
    assert fieldb_enum_container.name == "FieldAEnumeratedValue"
    assert fieldb_enum_container.usage == EnumUsageType.READ_WRITE
    assert len(fieldb_enum_container.enumerated_values) == 2
    assert fieldb_enum_container.enumerated_values[0].name == "0b0"
    assert fieldb_enum_container.enumerated_values[0].description == "Description for 0b0"
    assert fieldb_enum_container.enumerated_values[0].value == 0b0
    assert fieldb_enum_container.enumerated_values[1].name == "0b1"
    assert fieldb_enum_container.enumerated_values[1].description == "Description for 0b1"
    assert fieldb_enum_container.enumerated_values[1].value == 0b1
SVD file: enum_copy_via_derivedfrom/backward_reference_different_scope.svd
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version='1.0' encoding='utf-8'?>
<device xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" schemaVersion="1.3">
  <name>backward_reference_different_scope</name>
  <version>1.0</version>
  <description>Test_Example device</description>
  <cpu>
  <name>CM0</name>
  <revision>r0p0</revision>
  <endian>little</endian>
  <mpuPresent>false</mpuPresent>
  <fpuPresent>false</fpuPresent>
  <nvicPrioBits>4</nvicPrioBits>
  <vendorSystickConfig>false</vendorSystickConfig>
  </cpu>
  <addressUnitBits>8</addressUnitBits>
  <width>32</width>
  <peripherals>
    <peripheral>
      <name>PeripheralA</name>
      <baseAddress>0x40001000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
          <fields>
            <field>
              <name>FieldA</name>
              <bitOffset>0</bitOffset>
              <bitWidth>1</bitWidth>
              <enumeratedValues>
                <name>FieldAEnumeratedValue</name>
                <usage>read-write</usage>
                <enumeratedValue>
                  <name>0b0</name>
                  <description>Description for 0b0</description>
                  <value>0b0</value>
                </enumeratedValue>
                <enumeratedValue>
                  <name>0b1</name>
                  <description>Description for 0b1</description>
                  <value>0b1</value>
                </enumeratedValue>
              </enumeratedValues>
            </field>
            <field>
              <name>FieldB</name>
              <bitOffset>1</bitOffset>
              <bitWidth>1</bitWidth>
              <enumeratedValues derivedFrom="PeripheralA.RegisterA.FieldA.FieldAEnumeratedValue">
              </enumeratedValues>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_backward_reference_same_scope

This test case examines a scenario where the derivedFrom attribute is used within the same scope to refer directly by name to another enumeratedValues container, without providing a fully qualified path. Technically, this is allowed by the SVD standard, but it is not feasible to implement. The only situation where two enumeratedValues containers can coexist within the same field is if one has a read usage and the other has a write usage. The SVD standard specifies that no modifications are allowed when deriving from an enumeratedValues container. Therefore, it is not possible to change the usage attribute when using derivedFrom. Consequently, attempting to derive in this way results in an error, as svdconv correctly detects. A robust parser implementation should behave similarly, rejecting this configuration and raising an appropriate error to ensure compliance with the standard's technical limitations.

Expected Outcome: The parser should raise an error, indicating that two enumeratedValues containers cannot coexist within the same field unless they have distinct read and write usage types. This behavior matches that of svdconv.

Processable with svdconv: no

Source code in tests/test_process/test_enumerated_values_copy_via_derived_from.py
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@pytest.mark.xfail(strict=True, raises=ProcessException, reason="Two containers require usage types read and write")
def test_backward_reference_same_scope(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test case examines a scenario where the `derivedFrom` attribute is used within the same scope to refer
    directly by name to another `enumeratedValues` container, without providing a fully qualified path.
    Technically, this is allowed by the SVD standard, but it is not feasible to implement. The only situation
    where two `enumeratedValues` containers can coexist within the same field is if one has a `read` usage and the
    other has a `write` usage. The SVD standard specifies that no modifications are allowed when deriving from an
    `enumeratedValues` container. Therefore, it is not possible to change the `usage` attribute when using
    `derivedFrom`. Consequently, attempting to derive in this way results in an error, as `svdconv` correctly
    detects. A robust parser implementation should behave similarly, rejecting this configuration and raising an
    appropriate error to ensure compliance with the standard's technical limitations.

    **Expected Outcome:** The parser should raise an error, indicating that two `enumeratedValues` containers cannot
    coexist within the same field unless they have distinct `read` and `write` usage types. This behavior matches
    that of `svdconv`.

    **Processable with svdconv:** no
    """

    get_processed_device_from_testfile("enum_copy_via_derivedfrom/backward_reference_same_scope.svd")
SVD file: enum_copy_via_derivedfrom/backward_reference_same_scope.svd
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
<?xml version='1.0' encoding='utf-8'?>
<device xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" schemaVersion="1.3">
  <name>backward_reference_same_scope</name>
  <version>1.0</version>
  <description>Test_Example device</description>
  <cpu>
  <name>CM0</name>
  <revision>r0p0</revision>
  <endian>little</endian>
  <mpuPresent>false</mpuPresent>
  <fpuPresent>false</fpuPresent>
  <nvicPrioBits>4</nvicPrioBits>
  <vendorSystickConfig>false</vendorSystickConfig>
  </cpu>
  <addressUnitBits>8</addressUnitBits>
  <width>32</width>
  <peripherals>
    <peripheral>
      <name>PeripheralA</name>
      <baseAddress>0x40001000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
          <fields>
            <field>
              <name>FieldA</name>
              <bitOffset>0</bitOffset>
              <bitWidth>1</bitWidth>
              <enumeratedValues>
                <name>FieldAEnumeratedValue</name>
                <usage>read</usage>
                <enumeratedValue>
                  <name>0b0</name>
                  <description>Description for 0b0</description>
                  <value>0b0</value>
                </enumeratedValue>
                <enumeratedValue>
                  <name>0b1</name>
                  <description>Description for 0b1</description>
                  <value>0b1</value>
                </enumeratedValue>
              </enumeratedValues>
              <enumeratedValues derivedFrom="FieldAEnumeratedValue">
              </enumeratedValues>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_forward_reference_different_scope

This test case verifies that an enumerated values container can be correctly copied from another field, although the base container is defined lateron in the file. In the SVD file, FieldB defines an enumerated values container named FieldAEnumeratedValue, while FieldA copies this container using the derivedFrom attribute. This allows FieldA to reuse the same set of enumerated values as FieldB, ensuring consistency across fields.

Expected Outcome: The parser should successfully process the SVD file, allowing FieldA to copy the enumerated values from FieldB's FieldAEnumeratedValue. The enumerated values should be identical for both FieldA and FieldB, and no conflicts or errors should arise during parsing. svdconv can't parse the file since it does not support forward references.

Processable with svdconv: no

Source code in tests/test_process/test_enumerated_values_copy_via_derived_from.py
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_forward_reference_different_scope(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test case verifies that an enumerated values container can be correctly copied from another field,
    although the base container is defined lateron in the file. In the SVD file, `FieldB` defines an enumerated
    values container named `FieldAEnumeratedValue`, while `FieldA` copies this container using the `derivedFrom`
    attribute. This allows `FieldA` to reuse the same set of enumerated values as `FieldB`, ensuring consistency
    across fields.

    **Expected Outcome:** The parser should successfully process the SVD file, allowing `FieldA` to copy the
    enumerated values from `FieldB`'s `FieldAEnumeratedValue`. The enumerated values should be identical for both
    `FieldA` and `FieldB`, and no conflicts or errors should arise during parsing. `svdconv` can't parse the file
    since it does not support forward references.

    **Processable with svdconv:** no
    """

    device = get_processed_device_from_testfile("enum_copy_via_derivedfrom/forward_reference_different_scope.svd")

    assert len(device.peripherals) == 1
    assert len(device.peripherals[0].registers_clusters) == 1

    assert isinstance(device.peripherals[0].registers_clusters[0], Register)
    assert device.peripherals[0].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[0].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[0].registers_clusters[0].size == 32
    assert len(device.peripherals[0].registers_clusters[0].fields) == 2

    assert device.peripherals[0].registers_clusters[0].fields[0].name == "FieldA"
    assert device.peripherals[0].registers_clusters[0].fields[0].lsb == 0
    assert device.peripherals[0].registers_clusters[0].fields[0].msb == 0
    assert len(device.peripherals[0].registers_clusters[0].fields[0].enumerated_value_containers) == 1
    fielda_enum_container = device.peripherals[0].registers_clusters[0].fields[0].enumerated_value_containers[0]
    assert fielda_enum_container.name == "FieldAEnumeratedValue"
    assert fielda_enum_container.usage == EnumUsageType.READ_WRITE
    assert len(fielda_enum_container.enumerated_values) == 2
    assert fielda_enum_container.enumerated_values[0].name == "0b0"
    assert fielda_enum_container.enumerated_values[0].description == "Description for 0b0"
    assert fielda_enum_container.enumerated_values[0].value == 0b0
    assert fielda_enum_container.enumerated_values[1].name == "0b1"
    assert fielda_enum_container.enumerated_values[1].description == "Description for 0b1"
    assert fielda_enum_container.enumerated_values[1].value == 0b1

    assert device.peripherals[0].registers_clusters[0].fields[1].name == "FieldB"
    assert device.peripherals[0].registers_clusters[0].fields[1].lsb == 1
    assert device.peripherals[0].registers_clusters[0].fields[1].msb == 1
    assert len(device.peripherals[0].registers_clusters[0].fields[1].enumerated_value_containers) == 1
    fieldb_enum_container = device.peripherals[0].registers_clusters[0].fields[1].enumerated_value_containers[0]
    assert fieldb_enum_container.name == "FieldAEnumeratedValue"
    assert fieldb_enum_container.usage == EnumUsageType.READ_WRITE
    assert len(fieldb_enum_container.enumerated_values) == 2
    assert fieldb_enum_container.enumerated_values[0].name == "0b0"
    assert fieldb_enum_container.enumerated_values[0].description == "Description for 0b0"
    assert fieldb_enum_container.enumerated_values[0].value == 0b0
    assert fieldb_enum_container.enumerated_values[1].name == "0b1"
    assert fieldb_enum_container.enumerated_values[1].description == "Description for 0b1"
    assert fieldb_enum_container.enumerated_values[1].value == 0b1
SVD file: enum_copy_via_derivedfrom/forward_reference_different_scope.svd
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
<?xml version='1.0' encoding='utf-8'?>
<device xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" xs:noNamespaceSchemaLocation="CMSIS-SVD.xsd" schemaVersion="1.3">
  <name>forward_reference_different_scope</name>
  <version>1.0</version>
  <description>Test_Example device</description>
  <cpu>
  <name>CM0</name>
  <revision>r0p0</revision>
  <endian>little</endian>
  <mpuPresent>false</mpuPresent>
  <fpuPresent>false</fpuPresent>
  <nvicPrioBits>4</nvicPrioBits>
  <vendorSystickConfig>false</vendorSystickConfig>
  </cpu>
  <addressUnitBits>8</addressUnitBits>
  <width>32</width>
  <peripherals>
    <peripheral>
      <name>PeripheralA</name>
      <baseAddress>0x40001000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
          <fields>
            <field>
              <name>FieldA</name>
              <bitOffset>0</bitOffset>
              <bitWidth>1</bitWidth>
              <enumeratedValues derivedFrom="PeripheralA.RegisterA.FieldB.FieldAEnumeratedValue">
              </enumeratedValues>
            </field>
            <field>
              <name>FieldB</name>
              <bitOffset>1</bitOffset>
              <bitWidth>1</bitWidth>
              <enumeratedValues>
                <name>FieldAEnumeratedValue</name>
                <usage>read-write</usage>
                <enumeratedValue>
                  <name>0b0</name>
                  <description>Description for 0b0</description>
                  <value>0b0</value>
                </enumeratedValue>
                <enumeratedValue>
                  <name>0b1</name>
                  <description>Description for 0b1</description>
                  <value>0b1</value>
                </enumeratedValue>
              </enumeratedValues>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>