Skip to content

test_peripheral_inheritance_via_derived_from

For this feature, test cases cover scenarios where a derived peripheral inherits properties from a base peripheral, ensuring correct behavior when values are inherited.

test_alternate_peripheral

By default, each address block in the memory space of a device is assigned to a unique peripheral. If multiple peripherals share the same address block, this must be explicitly defined. A peripheral that redefines an address block must specify the name of the peripheral originally associated with that block in alternatePeripheral. This test checks whether a derived peripheral with the same address as the base peripheral is accepted by the parser without triggering an error.

Expected Outcome: The parser should process the file without raising an error, recognizing that PeripheralB shares the same base address as PeripheralA and correctly defines PeripheralA as its alternate peripheral. Both peripherals should be parsed correctly, with PeripheralA listed first and having a base address of 0x40001000. PeripheralB should also have the same base address of 0x40001000, with the alternate peripheral attribute correctly set to PeripheralA. The parser should handle this situation as expected, accepting the shared address as valid due to the explicit alternate peripheral specification.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_alternate_peripheral(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    By default, each address block in the memory space of a device is assigned to a unique peripheral. If multiple
    peripherals share the same address block, this must be explicitly defined. A peripheral that redefines an
    address block must specify the name of the peripheral originally associated with that block in
    `alternatePeripheral`. This test checks whether a derived peripheral with the same address as the base
    peripheral is accepted by the parser without triggering an error.

    **Expected Outcome:** The parser should process the file without raising an error, recognizing that `PeripheralB`
    shares the same base address as `PeripheralA` and correctly defines `PeripheralA` as its alternate peripheral.
    Both peripherals should be parsed correctly, with `PeripheralA` listed first and having a base address of
    `0x40001000`. `PeripheralB` should also have the same base address of `0x40001000`, with the alternate
    peripheral attribute correctly set to `PeripheralA`. The parser should handle this situation as expected,
    accepting the shared address as valid due to the explicit alternate peripheral specification.

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

    device = get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/alternate_peripheral.svd")

    assert len(device.peripherals) == 2
    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].base_address == 0x40001000
    assert len(device.peripherals[0].registers_clusters) == 1
    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].base_address == 0x40001000
    assert device.peripherals[1].alternate_peripheral == "PeripheralA"
    assert len(device.peripherals[1].registers_clusters) == 1
SVD file: peripheral_inheritance_via_derivedfrom/alternate_peripheral.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
<?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>alternate_peripheral</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <alternatePeripheral>PeripheralA</alternatePeripheral>
      <baseAddress>0x40001000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_alternate_peripheral_overlap

By default, each address block in the memory space of a device is assigned to a unique peripheral. If multiple peripherals share the same address block, this must be explicitly defined. A peripheral that redefines an address block must specify the name of the peripheral originally associated with that block in alternatePeripheral. This test checks whether a derived peripheral with an overlapping address block to the base peripheral is accepted by the parser without triggering an error.

Expected Outcome: The parser should process the file without raising an error, recognizing that PeripheralB shares an overlapping address block with PeripheralA and correctly defines PeripheralA as its alternate peripheral. Both peripherals should be parsed correctly, with PeripheralA listed first and having a base address of 0x40001000. PeripheralB should have the base address of 0x40001004, with the alternate peripheral attribute correctly set to PeripheralA. The parser should handle this situation as expected, accepting the shared space as valid due to the explicit alternate peripheral specification.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_alternate_peripheral_overlap(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    By default, each address block in the memory space of a device is assigned to a unique peripheral. If multiple
    peripherals share the same address block, this must be explicitly defined. A peripheral that redefines an
    address block must specify the name of the peripheral originally associated with that block in
    `alternatePeripheral`. This test checks whether a derived peripheral with an overlapping address block to the
    base peripheral is accepted by the parser without triggering an error.

    **Expected Outcome:** The parser should process the file without raising an error, recognizing that `PeripheralB`
    shares an overlapping address block with `PeripheralA` and correctly defines `PeripheralA` as its alternate
    peripheral. Both peripherals should be parsed correctly, with `PeripheralA` listed first and having a base
    address of `0x40001000`. `PeripheralB` should have the base address of `0x40001004`, with the alternate
    peripheral attribute correctly set to `PeripheralA`. The parser should handle this situation as expected,
    accepting the shared space as valid due to the explicit alternate peripheral specification.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/alternate_peripheral_overlap.svd"
    )

    assert len(device.peripherals) == 2
    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].base_address == 0x40001000
    assert len(device.peripherals[0].registers_clusters) == 1
    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].base_address == 0x40001004
    assert device.peripherals[1].alternate_peripheral == "PeripheralA"
    assert len(device.peripherals[1].registers_clusters) == 1
SVD file: peripheral_inheritance_via_derivedfrom/alternate_peripheral_overlap.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
<?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>alternate_peripheral_overlap</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <alternatePeripheral>PeripheralA</alternatePeripheral>
      <baseAddress>0x40001004</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_block_overlap

This test checks whether the parser handles cases where the address blocks of a base peripheral and a derived peripheral overlap. This test ensures that when the address ranges of two peripherals partially overlap, the parser processes the file correctly but issues a warning to the user. The behavior mirrors that of svdconv, where overlapping address blocks do not trigger an error but generate a warning to inform the user about the potential conflict.

Expected Outcome: The parser should process the file successfully but issue a warning (e.g. ProcessWarning) to inform the user that the address blocks of PeripheralA and PeripheralB overlap. PeripheralA should have a base address of 0x40001000, while PeripheralB should start at 0x40001004, leading to an overlap in their address spaces. Both peripherals should be parsed correctly, and the parser should handle the overlap as expected, warning the user without halting the process.

Processable with svdconv: yes - with warnings

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
def test_block_overlap(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test checks whether the parser handles cases where the address blocks of a base peripheral and a derived
    peripheral overlap. This test ensures that when the address ranges of two peripherals partially overlap, the
    parser processes the file correctly but issues a warning to the user. The behavior mirrors that of `svdconv`,
    where overlapping address blocks do not trigger an error but generate a warning to inform the user about the
    potential conflict.

    **Expected Outcome:** The parser should process the file successfully but issue a warning (e.g. `ProcessWarning`)
    to inform the user that the address blocks of `PeripheralA` and `PeripheralB` overlap. `PeripheralA` should
    have a base address of `0x40001000`, while `PeripheralB` should start at `0x40001004`, leading to an overlap
    in their address spaces. Both peripherals should be parsed correctly, and the parser should handle the overlap
    as expected, warning the user without halting the process.

    **Processable with svdconv:** yes - with warnings
    """

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/block_overlap.svd")

    assert len(device.peripherals) == 2
    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].base_address == 0x40001000
    assert len(device.peripherals[0].registers_clusters) == 1
    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].base_address == 0x40001004
    assert len(device.peripherals[1].registers_clusters) == 1
SVD file: peripheral_inheritance_via_derivedfrom/block_overlap.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
<?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>block_overlap</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40001004</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_circular_inheritance

This test ensures that the parser correctly identifies and handles circular inheritance, where three peripherals, PeripheralA, PeripheralB, and PeripheralC, attempt to inherit from each other, creating a loop. Circular references should be detected, and the parser should raise an appropriate error to prevent infinite recursion or incorrect parsing.

Expected Outcome: The parser should detect the circular inheritance between PeripheralA, PeripheralB, and PeripheralC, and fail with an error indicating that circular inheritance is not supported. The test should raise a ProcessException or an equivalent error, ensuring that the parser does not attempt to resolve the circular references and avoids potential infinite loops.

Processable with svdconv: no - although svdconv fails to process this test case, it is not due to the detection of circular inheritance but because svdconv does not support forward references over different peripherals.

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
@pytest.mark.xfail(strict=True, raises=ProcessException, reason="Circular inheritance is not supported")
def test_circular_inheritance(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that the parser correctly identifies and handles circular inheritance, where three
    peripherals, `PeripheralA`, `PeripheralB`, and `PeripheralC`, attempt to inherit from each other, creating a
    loop. Circular references should be detected, and the parser should raise an appropriate error to prevent
    infinite recursion or incorrect parsing.

    **Expected Outcome:** The parser should detect the circular inheritance between `PeripheralA`, `PeripheralB`, and
    `PeripheralC`, and fail with an error indicating that circular inheritance is not supported. The test should
    raise a `ProcessException` or an equivalent error, ensuring that the parser does not attempt to resolve the
    circular references and avoids potential infinite loops.

    **Processable with svdconv:** no - although `svdconv` fails to process this test case, it is not due to the
    detection of circular inheritance but because `svdconv` does not support forward references over different
    peripherals.
    """

    get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/circular_inheritance.svd")
SVD file: peripheral_inheritance_via_derivedfrom/circular_inheritance.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
<?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>circular_inheritance</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 derivedFrom="PeripheralC">
      <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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
    <peripheral derivedFrom="PeripheralB">
      <name>PeripheralC</name>
      <baseAddress>0x40003000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_derive_from_self

This test case evaluates a scenario where a peripheral attempts to derive from itself, creating an invalid configuration. In the SVD file, PeripheralA is defined with a derivedFrom attribute pointing to its own name. Such configurations should be detected as erroneous because a peripheral cannot logically inherit properties from itself. This kind of self-reference should lead to a parsing error.

Expected Outcome: The parser should detect the invalid self-referential inheritance and raise an error, indicating that a peripheral cannot derive from itself. This ensures that the system handles such configurations correctly by stopping further processing and informing the user of the issue.

Processable with svdconv: no

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
@pytest.mark.xfail(strict=True, raises=ProcessException, reason="Can't derive from self")
def test_derive_from_self(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test case evaluates a scenario where a peripheral attempts to derive from itself, creating an invalid
    configuration. In the SVD file, `PeripheralA` is defined with a `derivedFrom` attribute pointing to its own
    name. Such configurations should be detected as erroneous because a peripheral cannot logically inherit
    properties from itself. This kind of self-reference should lead to a parsing error.

    **Expected Outcome:** The parser should detect the invalid self-referential inheritance and raise an error,
    indicating that a peripheral cannot derive from itself. This ensures that the system handles such
    configurations correctly by stopping further processing and informing the user of the issue.

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

    get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/derive_from_self.svd")
SVD file: peripheral_inheritance_via_derivedfrom/derive_from_self.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
<?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>derive_from_self</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 derivedFrom="PeripheralA">
      <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>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_multiple_inheritance_backward_and_forward_reference_with_value_override

This test ensures that multiple inheritance involving both backward and forward references is handled correctly, with value overrides applied at each level. Specifically, PeripheralC is the base peripheral, PeripheralA inherits from PeripheralC, and PeripheralB inherits from PeripheralA. Additionally, the test verifies that the size value specified at the peripheral level is correctly propagated down to the registers.

Expected Outcome: The device contains three peripherals, each correctly inheriting properties from the previous peripheral and overriding specific values where necessary. The size value defined at each peripheral level is inherited by the registers within those peripherals. PeripheralA inherits from PeripheralC and overrides certain values while maintaining the inheritance structure. It has the name "PeripheralA", a prependToName of "Prepend", an appendToName of "Append2", a disableCondition of "1 == 1", a baseAddress of 0x40001000, and a size of 64 bits. It contains one address block with an offset of 0x0, a size of 0x1000, and usage for registers. PeripheralA also inherits the register RegisterA from PeripheralC, with the overridden size of 64 bits and an address offset of 0x0. PeripheralB, which inherits from PeripheralA, overrides the baseAddress, size, and the size of the inherited register. It has the name "PeripheralB", a prependToName of "Prepend", an appendToName of "Append2", a disableCondition of "1 == 1", a baseAddress of 0x40002000, and a size of 128 bits. It contains one address block with an offset of 0x0, a size of 0x1000, and usage for registers. The register RegisterA is inherited from PeripheralA, but with the size of 128 bits, correctly reflecting the peripheral-level override. PeripheralC is the base peripheral and defines the initial values. It has the name "PeripheralC", a prependToName of "Prepend", an appendToName of "Append", a disableCondition of "0 == 0", a baseAddress of 0x40003000, and a size of 16 bits. It contains one address block with an offset of 0x0, a size of 0x1000, and usage for registers. The register RegisterA is defined at this level with an address offset of 0x0 and a size of 16 bits. The test confirms that the inheritance chain works as expected, with value overrides properly applied, and that the size value specified at the peripheral level is correctly propagated to the registers within those peripherals, even though svdconv cannot handle forward references over different peripherals.

Processable with svdconv: no - svdconv can't handle forward references over different peripherals.

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_multiple_inheritance_backward_and_forward_reference_with_value_override(
    get_processed_device_from_testfile: Callable[[str], Device]
):
    """
    This test ensures that multiple inheritance involving both backward and forward references is handled
    correctly, with value overrides applied at each level. Specifically, PeripheralC is the base peripheral,
    PeripheralA inherits from PeripheralC, and PeripheralB inherits from PeripheralA. Additionally, the test
    verifies that the `size` value specified at the peripheral level is correctly propagated down to the
    registers.

    **Expected Outcome:** The device contains three peripherals, each correctly inheriting properties from the
    previous peripheral and overriding specific values where necessary. The `size` value defined at each
    peripheral level is inherited by the registers within those peripherals. PeripheralA inherits from PeripheralC
    and overrides certain values while maintaining the inheritance structure. It has the `name` "PeripheralA", a
    `prependToName` of "Prepend", an `appendToName` of "Append2", a `disableCondition` of "1 == 1", a
    `baseAddress` of `0x40001000`, and a `size` of 64 bits. It contains one address block with an offset of `0x0`,
    a size of `0x1000`, and usage for registers. PeripheralA also inherits the register `RegisterA` from
    PeripheralC, with the overridden `size` of 64 bits and an address offset of `0x0`. PeripheralB, which inherits
    from PeripheralA, overrides the `baseAddress`, `size`, and the size of the inherited register. It has the
    `name` "PeripheralB", a `prependToName` of "Prepend", an `appendToName` of "Append2", a `disableCondition` of
    "1 == 1", a `baseAddress` of `0x40002000`, and a `size` of 128 bits. It contains one address block with an
    offset of `0x0`, a size of `0x1000`, and usage for registers. The register `RegisterA` is inherited from
    PeripheralA, but with the size of 128 bits, correctly reflecting the peripheral-level override. PeripheralC is
    the base peripheral and defines the initial values. It has the `name` "PeripheralC", a `prependToName` of
    "Prepend", an `appendToName` of "Append", a `disableCondition` of "0 == 0", a `baseAddress` of `0x40003000`,
    and a `size` of 16 bits. It contains one address block with an offset of `0x0`, a size of `0x1000`, and usage
    for registers. The register `RegisterA` is defined at this level with an address offset of `0x0` and a size of
    16 bits. The test confirms that the inheritance chain works as expected, with value overrides properly
    applied, and that the `size` value specified at the peripheral level is correctly propagated to the registers
    within those peripherals, even though `svdconv` cannot handle forward references over different peripherals.

    **Processable with svdconv:** no - `svdconv` can't handle forward references over different peripherals.
    """

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/"
        "multiple_inheritance_backward_and_forward_reference_with_value_override.svd"
    )

    assert len(device.peripherals) == 3

    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].prepend_to_name == "Prepend"
    assert device.peripherals[0].append_to_name == "Append2"
    assert device.peripherals[0].disable_condition == "1 == 1"
    assert device.peripherals[0].base_address == 0x40001000
    assert device.peripherals[0].size == 64
    assert len(device.peripherals[0].address_blocks) == 1
    assert device.peripherals[0].address_blocks[0].offset == 0x0
    assert device.peripherals[0].address_blocks[0].size == 0x1000
    assert device.peripherals[0].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    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 == 64

    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].prepend_to_name == "Prepend"
    assert device.peripherals[1].append_to_name == "Append2"
    assert device.peripherals[1].disable_condition == "1 == 1"
    assert device.peripherals[1].base_address == 0x40002000
    assert device.peripherals[1].size == 128
    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x1000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert len(device.peripherals[1].registers_clusters) == 1
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 128

    assert device.peripherals[2].name == "PeripheralC"
    assert device.peripherals[2].prepend_to_name == "Prepend"
    assert device.peripherals[2].append_to_name == "Append"
    assert device.peripherals[2].disable_condition == "0 == 0"
    assert device.peripherals[2].base_address == 0x40003000
    assert device.peripherals[2].size == 16
    assert len(device.peripherals[2].address_blocks) == 1
    assert device.peripherals[2].address_blocks[0].offset == 0x0
    assert device.peripherals[2].address_blocks[0].size == 0x1000
    assert device.peripherals[2].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert len(device.peripherals[2].registers_clusters) == 1
    assert isinstance(device.peripherals[2].registers_clusters[0], Register)
    assert device.peripherals[2].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[2].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[2].registers_clusters[0].size == 16

test_multiple_inheritance_backward_reference

This test ensures that inheritance across multiple peripherals works as expected, where PeripheralB is derived first, and only afterward, PeripheralC can be derived from PeripheralB. It verifies that PeripheralC correctly inherits from PeripheralB, which in turn inherits from a base peripheral.

Expected Outcome: The device should contain three peripherals, with PeripheralB and PeripheralC correctly following the inheritance chain. PeripheralB inherits from the base peripheral and contains one register and one address block. PeripheralC inherits from PeripheralB, maintaining the inherited structure. PeripheralB has the name "PeripheralB", one register named RegisterA, and one address block with an offset of 0x0, a size of 0x1000, and usage for registers. PeripheralC, derived from PeripheralB, has the name "PeripheralC", also contains the register RegisterA, and has an identical address block with an offset of 0x0, a size of 0x1000, and usage for registers. The inheritance process between multiple peripherals is handled correctly.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_multiple_inheritance_backward_reference(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that inheritance across multiple peripherals works as expected, where PeripheralB is derived
    first, and only afterward, PeripheralC can be derived from PeripheralB. It verifies that PeripheralC correctly
    inherits from PeripheralB, which in turn inherits from a base peripheral.

    **Expected Outcome:** The device should contain three peripherals, with PeripheralB and PeripheralC correctly
    following the inheritance chain. PeripheralB inherits from the base peripheral and contains one register and
    one address block. PeripheralC inherits from PeripheralB, maintaining the inherited structure. PeripheralB has
    the name "PeripheralB", one register named `RegisterA`, and one address block with an offset of `0x0`, a size
    of `0x1000`, and usage for registers. PeripheralC, derived from PeripheralB, has the name "PeripheralC", also
    contains the register `RegisterA`, and has an identical address block with an offset of `0x0`, a size of
    `0x1000`, and usage for registers. The inheritance process between multiple peripherals is handled correctly.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/multiple_inheritance_backward_reference.svd"
    )

    assert len(device.peripherals) == 3

    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 1
    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x1000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"

    assert device.peripherals[2].name == "PeripheralC"
    assert len(device.peripherals[2].registers_clusters) == 1
    assert len(device.peripherals[2].address_blocks) == 1
    assert device.peripherals[2].address_blocks[0].offset == 0x0
    assert device.peripherals[2].address_blocks[0].size == 0x1000
    assert device.peripherals[2].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[2].registers_clusters[0], Register)
    assert device.peripherals[2].registers_clusters[0].name == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/multiple_inheritance_backward_reference.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
<?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>multiple_inheritance_backward_reference</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
    <peripheral derivedFrom="PeripheralB">
      <name>PeripheralC</name>
      <baseAddress>0x40003000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_multiple_inheritance_forward_reference

This test ensures that inheritance across multiple peripherals is correctly handled when forward references are involved, where PeripheralA inherits from PeripheralB, and PeripheralB inherits from PeripheralC.

Expected Outcome: The device should contain three peripherals. PeripheralC is the base peripheral and contains one register named RegisterA and one address block with an offset of 0x0, a size of 0x1000, and usage for registers. PeripheralB inherits from PeripheralC and should correctly include the inherited register RegisterA and the address block with the same properties. Finally, PeripheralA, which inherits from PeripheralB, also includes the inherited register RegisterA and the same address block structure. The test verifies that forward inheritance through multiple peripherals works correctly, even though svdconv is not capable of processing forward references over different peripherals.

Processable with svdconv: no - svdconv can't handle forward references over different peripherals.

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_multiple_inheritance_forward_reference(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that inheritance across multiple peripherals is correctly handled when forward references
    are involved, where PeripheralA inherits from PeripheralB, and PeripheralB inherits from PeripheralC.

    **Expected Outcome:** The device should contain three peripherals. PeripheralC is the base peripheral and contains
    one register named `RegisterA` and one address block with an offset of `0x0`, a size of `0x1000`, and usage
    for registers. PeripheralB inherits from PeripheralC and should correctly include the inherited register
    `RegisterA` and the address block with the same properties. Finally, PeripheralA, which inherits from
    PeripheralB, also includes the inherited register `RegisterA` and the same address block structure. The test
    verifies that forward inheritance through multiple peripherals works correctly, even though `svdconv` is not
    capable of processing forward references over different peripherals.

    **Processable with svdconv:** no - `svdconv` can't handle forward references over different peripherals.
    """

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/multiple_inheritance_forward_reference.svd"
    )

    assert len(device.peripherals) == 3

    assert device.peripherals[0].name == "PeripheralA"
    assert len(device.peripherals[0].registers_clusters) == 1
    assert len(device.peripherals[0].address_blocks) == 1
    assert device.peripherals[0].address_blocks[0].offset == 0x0
    assert device.peripherals[0].address_blocks[0].size == 0x1000
    assert device.peripherals[0].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[0].registers_clusters[0], Register)
    assert device.peripherals[0].registers_clusters[0].name == "RegisterA"

    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 1
    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x1000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/multiple_inheritance_forward_reference.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
<?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>multiple_inheritance_backward_reference</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 derivedFrom="PeripheralB">
      <name>PeripheralA</name>
      <baseAddress>0x40001000</baseAddress>
    </peripheral>
    <peripheral derivedFrom="PeripheralC">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
    <peripheral>
      <name>PeripheralC</name>
      <baseAddress>0x40003000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_override_behavior

This test checks whether specific values of a derived peripheral can override the inherited values from a base peripheral. It ensures that modifications to values like name, version, description, and others in the derived peripheral are applied correctly, while still inheriting the base peripheral's structure when not explicitly overridden.

Expected Outcome: The derived peripheral, PeripheralB, correctly overrides inherited values from the base peripheral. PeripheralB should have the name "PeripheralB", version "2.0", description "PeripheralB Description", an alternatePeripheral of "PeripheralD", a groupName "PeripheralsGroup2", a prependToName "Prefix2", and a appendToName "Suffix2". Additionally, the header_struct_name is correctly set to "HeaderStructName2", and the disable_condition is "1 == 1". PeripheralB should also have a base address of 0x40002000, a size of 64 bits, access type WRITE_ONCE, protection type NON_SECURE, a resetValue of 0x0F0F0F0F, and a resetMask of 0xABABABAB. PeripheralB contains one address block starting at offset 0x0, with a size of 0x2000 and usage for registers. It also contains one interrupt, named InterruptC, with a description "InterruptC Description" and a value of 2. Additionally, PeripheralB contains two registers: RegisterA with an address offset of 0x0, and RegisterB with an address offset of 0x8.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_override_behavior(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test checks whether specific values of a derived peripheral can override the inherited values from a base
    peripheral. It ensures that modifications to values like `name`, `version`, `description`, and others in the
    derived peripheral are applied correctly, while still inheriting the base peripheral's structure when not
    explicitly overridden.

    **Expected Outcome:** The derived peripheral, PeripheralB, correctly overrides inherited values from the base
    peripheral. PeripheralB should have the `name` "PeripheralB", `version` "2.0", `description` "PeripheralB
    Description", an `alternatePeripheral` of "PeripheralD", a `groupName` "PeripheralsGroup2", a `prependToName`
    "Prefix2", and a `appendToName` "Suffix2". Additionally, the `header_struct_name` is correctly set to
    "HeaderStructName2", and the `disable_condition` is `"1 == 1"`. PeripheralB should also have a base address of
    `0x40002000`, a `size` of 64 bits, `access` type `WRITE_ONCE`, `protection` type `NON_SECURE`, a `resetValue`
    of `0x0F0F0F0F`, and a `resetMask` of `0xABABABAB`. PeripheralB contains one address block starting at offset
    `0x0`, with a size of `0x2000` and usage for registers. It also contains one interrupt, named `InterruptC`,
    with a description "InterruptC Description" and a value of 2. Additionally, PeripheralB contains two
    registers: `RegisterA` with an address offset of `0x0`, and `RegisterB` with an address offset of `0x8`.

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

    device = get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/override_behavior.svd")

    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].version == "2.0"
    assert device.peripherals[1].description == "PeripheralB Description"
    assert device.peripherals[1].alternate_peripheral == "PeripheralA"
    assert device.peripherals[1].group_name == "PeripheralsGroup2"
    assert device.peripherals[1].prepend_to_name == "Prefix2"
    assert device.peripherals[1].append_to_name == "Suffix2"
    assert device.peripherals[1].header_struct_name == "HeaderStructName2"
    assert device.peripherals[1].disable_condition == "1 == 1"
    assert device.peripherals[1].base_address == 0x40002000
    assert device.peripherals[1].size == 64
    assert device.peripherals[1].access == AccessType.WRITE_ONCE
    assert device.peripherals[1].protection == ProtectionStringType.NON_SECURE
    assert device.peripherals[1].reset_value == 0x0F0F0F0F
    assert device.peripherals[1].reset_mask == 0xABABABAB

    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x2000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS

    assert len(device.peripherals[1].interrupts) == 1
    assert device.peripherals[1].interrupts[0].name == "InterruptC"
    assert device.peripherals[1].interrupts[0].description == "InterruptC Description"
    assert device.peripherals[1].interrupts[0].value == 2

    assert len(device.peripherals[1].registers_clusters) == 2
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterB"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x8
SVD file: peripheral_inheritance_via_derivedfrom/override_behavior.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
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
<?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>override_behavior</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>
      <version>1.0</version>
      <description>PeripheralA Description</description>
      <alternatePeripheral>PeripheralB</alternatePeripheral>
      <groupName>PeripheralsGroup</groupName>
      <prependToName>Prefix</prependToName>
      <appendToName>Suffix</appendToName>
      <headerStructName>HeaderStructName</headerStructName>
      <disableCondition>0 == 0</disableCondition>
      <baseAddress>0x40001000</baseAddress>
      <size>16</size>
      <access>write-only</access>
      <protection>s</protection>
      <resetValue>0xDEADBEEF</resetValue>
      <resetMask>0xDEADC0DE</resetMask>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <interrupt>
        <name>InterruptA</name>
        <description>InterruptA Description</description>
        <value>0</value>
      </interrupt>
      <interrupt>
        <name>InterruptB</name>
        <description>InterruptB Description</description>
        <value>1</value>
      </interrupt>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <version>2.0</version>
      <description>PeripheralB Description</description>
      <alternatePeripheral>PeripheralA</alternatePeripheral>
      <groupName>PeripheralsGroup2</groupName>
      <prependToName>Prefix2</prependToName>
      <appendToName>Suffix2</appendToName>
      <headerStructName>HeaderStructName2</headerStructName>
      <disableCondition>1 == 1</disableCondition>
      <baseAddress>0x40002000</baseAddress>
      <size>64</size>
      <access>writeOnce</access>
      <protection>n</protection>
      <resetValue>0x0F0F0F0F</resetValue>
      <resetMask>0xABABABAB</resetMask>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x2000</size>
        <usage>registers</usage>
      </addressBlock>
      <interrupt>
        <name>InterruptC</name>
        <description>InterruptC Description</description>
        <value>2</value>
      </interrupt>
      <registers>
        <register>
          <name>RegisterB</name>
          <addressOffset>0x8</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_alternate_group

This test checks how the parser handles peripheral inheritance when an alternate group is involved in a register. The test file includes two peripherals, PeripheralA and PeripheralB. PeripheralA contains a register, RegisterA, without an alternate group defined. PeripheralB inherits RegisterA but defines an alternate group for another register, which is also named RegisterA. Both registers have the same offset address. The test ensures that the parser can process this scenario correctly.

Expected Outcome: The parser should successfully process the SVD file, correctly handling the peripheral inheritance and alternate group settings. PeripheralB contains two instances of RegisterA, both with the same address offset of 0x0 and a size of 32 bits. The first instance of RegisterA has no alternate group defined, while the second instance correctly specifies an alternate group named RegisterX and is named RegisterA_RegisterX. The parser should correctly handle this difference between the two instances of the inherited register without raising errors.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_register_inheritance_alternate_group(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test checks how the parser handles peripheral inheritance when an alternate group is involved in a
    register. The test file includes two peripherals, `PeripheralA` and `PeripheralB`. `PeripheralA` contains a
    register, `RegisterA`, without an alternate group defined. `PeripheralB` inherits `RegisterA` but defines an
    alternate group for another register, which is also named `RegisterA`. Both registers have the same offset
    address. The test ensures that the parser can process this scenario correctly.

    **Expected Outcome:** The parser should successfully process the SVD file, correctly handling the peripheral
    inheritance and alternate group settings. `PeripheralB` contains two instances of `RegisterA`, both with the
    same address offset of `0x0` and a size of 32 bits. The first instance of `RegisterA` has no alternate group
    defined, while the second instance correctly specifies an alternate group named `RegisterX` and is named
    `RegisterA_RegisterX`. The parser should correctly handle this difference between the two instances of the
    inherited register without raising errors.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/register_inheritance_alternate_group.svd"
    )

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 2
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 32
    assert device.peripherals[1].registers_clusters[0].alternate_group is None
    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[1].size == 32
    assert device.peripherals[1].registers_clusters[1].alternate_group == "RegisterX"
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_alternate_group.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
<?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>register_inheritance_alternate_group</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <name>RegisterA</name>
          <alternateGroup>RegisterX</alternateGroup>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_alternate_register

This test evaluates the parser's ability to handle peripheral inheritance when the alternateRegister element is defined. The test file contains two peripherals, PeripheralA and PeripheralB. PeripheralA defines RegisterA, and PeripheralB inherits from PeripheralA while adding a new register, RegisterB. RegisterB shares the same address offset as RegisterA and defines RegisterA as its alternate register. This setup is used to ensure the parser correctly processes alternate register relationships between inherited registers.

Expected Outcome: The parser should successfully process the SVD file, properly handling the alternate register relationships during inheritance. PeripheralB contains two registers: RegisterA, which has an address offset of 0x0 and a size of 32 bits, with no alternate register defined, and RegisterB, which also has an address offset of 0x0 and a size of 32 bits, but specifies RegisterA as its alternate register. The parser should accurately reflect this alternate register linkage without raising any errors.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_register_inheritance_alternate_register(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test evaluates the parser's ability to handle peripheral inheritance when the `alternateRegister` element
    is defined. The test file contains two peripherals, `PeripheralA` and `PeripheralB`. `PeripheralA` defines
    `RegisterA`, and `PeripheralB` inherits from `PeripheralA` while adding a new register, `RegisterB`.
    `RegisterB` shares the same address offset as `RegisterA` and defines `RegisterA` as its alternate register.
    This setup is used to ensure the parser correctly processes alternate register relationships between inherited
    registers.

    **Expected Outcome:** The parser should successfully process the SVD file, properly handling the alternate
    register relationships during inheritance. `PeripheralB` contains two registers: `RegisterA`, which has an
    address offset of `0x0` and a size of 32 bits, with no alternate register defined, and `RegisterB`, which also
    has an address offset of `0x0` and a size of 32 bits, but specifies `RegisterA` as its alternate register. The
    parser should accurately reflect this alternate register linkage without raising any errors.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/register_inheritance_alternate_register.svd"
    )

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 2
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 32
    assert device.peripherals[1].registers_clusters[0].alternate_register is None
    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterB"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[1].size == 32
    assert device.peripherals[1].registers_clusters[1].alternate_register == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_alternate_register.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
<?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>register_inheritance_alternate_register</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <name>RegisterB</name>
          <alternateRegister>RegisterA</alternateRegister>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_overlap_address

This test ensures that the parser correctly handles cases where a register is derived from another peripheral, resulting in two registers within the same peripheral having overlapping address spaces. For backward compatibility with older svdconv versions, a warning is issued when registers overlap in address space. A parser designed to work with both new and old SVD files should allow registers with overlapping addresses but issue a warning to inform the user of the conflict.

Expected Outcome: The parser should detect the address overlap between RegisterA and RegisterB within PeripheralB. RegisterA starts at address 0x0 with a size of 32 bits, and RegisterB starts at address 0x2 with a size of 16 bits, creating the overlap. Instead of failing, the parser should successfully process the SVD file and issue a warning to inform the user of the overlap.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
def test_register_inheritance_overlap_address(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that the parser correctly handles cases where a register is derived from another peripheral,
    resulting in two registers within the same peripheral having overlapping address spaces. For backward
    compatibility with older `svdconv` versions, a warning is issued when registers overlap in address space. A
    parser designed to work with both new and old SVD files should allow registers with overlapping addresses but
    issue a warning to inform the user of the conflict.

    **Expected Outcome:** The parser should detect the address overlap between `RegisterA` and `RegisterB` within
    `PeripheralB`. `RegisterA` starts at address `0x0` with a size of 32 bits, and `RegisterB` starts at address
    `0x2` with a size of 16 bits, creating the overlap. Instead of failing, the parser should successfully process
    the SVD file and issue a warning to inform the user of the overlap.

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

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile(
            "peripheral_inheritance_via_derivedfrom/register_inheritance_overlap_address.svd"
        )

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 2
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 32
    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterB"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x2
    assert device.peripherals[1].registers_clusters[1].size == 16
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_overlap_address.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
<?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>register_inheritance_overlap_address</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>
          <size>32</size>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <name>RegisterB</name>
          <addressOffset>0x2</addressOffset>
          <size>16</size>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_oversized_field

PeripheralB inherits from PeripheralA. PeripheralA contains RegisterA, which has a default size of 32 bits. RegisterA includes a field, FieldA, with a bit width of 32 bits. When inherited by PeripheralB, the size of RegisterA is reduced to 16 bits because PeripheralB has its size set to 16. However, FieldA is inherited with its original 32-bit width, which exceeds the space available in RegisterA within PeripheralB. Despite this mismatch, svdconv neither raises a warning nor an error. A parser should be aware of this condition and warn the user when a field exceeds the size of its containing register.

Expected Outcome: The parser should process the file successfully and may issue a warning (ProcessWarning) to inform the user that FieldA exceeds the 16-bit size of RegisterA in PeripheralB. The device contains two peripherals: PeripheralA has RegisterA with a size of 32 bits and a field, FieldA, that spans from bit 0 to bit 31. PeripheralB inherits RegisterA, but with a reduced size of 16 bits, while FieldA retains its original 32-bit width. This creates a mismatch, as RegisterA in PeripheralB lacks sufficient space to accommodate the full width of FieldA. The parser should correctly handle the inheritance, but it should warn the user about the oversized field relative to the reduced register size.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
def test_register_inheritance_oversized_field(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    PeripheralB inherits from PeripheralA. PeripheralA contains `RegisterA`, which has a default size of 32 bits.
    `RegisterA` includes a field, `FieldA`, with a bit width of 32 bits. When inherited by PeripheralB, the size
    of `RegisterA` is reduced to 16 bits because PeripheralB has its size set to 16. However, `FieldA` is
    inherited with its original 32-bit width, which exceeds the space available in `RegisterA` within PeripheralB.
    Despite this mismatch, `svdconv` neither raises a warning nor an error. A parser should be aware of this
    condition and warn the user when a field exceeds the size of its containing register.

    **Expected Outcome:** The parser should process the file successfully and may issue a warning (`ProcessWarning`)
    to inform the user that `FieldA` exceeds the 16-bit size of `RegisterA` in PeripheralB. The device contains
    two peripherals: PeripheralA has `RegisterA` with a size of 32 bits and a field, `FieldA`, that spans from bit
    0 to bit 31. PeripheralB inherits `RegisterA`, but with a reduced size of 16 bits, while `FieldA` retains its
    original 32-bit width. This creates a mismatch, as `RegisterA` in PeripheralB lacks sufficient space to
    accommodate the full width of `FieldA`. The parser should correctly handle the inheritance, but it should warn
    the user about the oversized field relative to the reduced register size.

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

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile(
            "peripheral_inheritance_via_derivedfrom/register_inheritance_oversized_field.svd"
        )

    assert len(device.peripherals) == 2

    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].size == 32
    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) == 1
    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 == 31

    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].size == 16
    assert len(device.peripherals[1].registers_clusters) == 1
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 16
    assert len(device.peripherals[1].registers_clusters[0].fields) == 1
    assert device.peripherals[1].registers_clusters[0].fields[0].name == "FieldA"
    assert device.peripherals[1].registers_clusters[0].fields[0].lsb == 0
    assert device.peripherals[1].registers_clusters[0].fields[0].msb == 31
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_oversized_field.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
<?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>register_inheritance_oversized_field</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>32</bitWidth>
            </field>
          </fields>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <size>16</size>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_same_address

This test ensures that the parser correctly handles cases where a register is derived from another peripheral, so that two registers within the same peripheral are assigned the same address. Although svdconv generally raises an error when two registers share the same address, for compatibility with older svdconv versions, a warning is generated in some situations (e.g., when using dim). For a parser designed to work with both new and old SVD files, it is recommended to allow registers with the same addresses but issue a warning to the user.

Expected Outcome: The parser should detect that RegisterA and RegisterB are assigned the same address (0x00000000) within peripheral PeripheralB. Instead of failing, the parser should successfully process the SVD file but issue a warning (ProcessWarning) to inform the user about the address conflict. The device should contain two peripherals, and the second peripheral should have two registers, RegisterA and RegisterB, both with an address offset of 0x0.

Processable with svdconv: no - see subfeature test case description

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
def test_register_inheritance_same_address(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that the parser correctly handles cases where a register is derived from another peripheral,
    so that two registers within the same peripheral are assigned the same address. Although `svdconv` generally
    raises an error when two registers share the same address, for compatibility with older `svdconv` versions, a
    warning is generated in [some situations](https://github.com/Open-CMSIS-
    Pack/devtools/blob/44643999691347946562c526fc0474194f865c74/tools/svdconv/SVDModel/src/SvdPeripheral.cpp#L721)
    (e.g., when using `dim`). For a parser designed to work with both new and old SVD files, it is recommended to
    allow registers with the same addresses but issue a warning to the user.

    **Expected Outcome:** The parser should detect that `RegisterA` and `RegisterB` are assigned the same address
    (`0x00000000`) within peripheral `PeripheralB`. Instead of failing, the parser should successfully process the
    SVD file but issue a warning (`ProcessWarning`) to inform the user about the address conflict. The device
    should contain two peripherals, and the second peripheral should have two registers, `RegisterA` and
    `RegisterB`, both with an address offset of `0x0`.

    **Processable with svdconv:** no - see subfeature test case description
    """

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile(
            "peripheral_inheritance_via_derivedfrom/register_inheritance_same_address.svd"
        )

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 2
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterB"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x0
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_same_address.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
<?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>register_inheritance_same_address</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <name>RegisterB</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_same_address_dim

This test is similar to the one above, but in this case, dim is used, which causes svdconv to issue a warning instead of an error for compatibility reasons.

Expected Outcome: The parser should successfully process the SVD file without errors, even though RegisterA0 and RegisterB0 share the same address offset of 0x0, and RegisterA1 and RegisterB1 share the address offset of 0x4. Each register has a size of 32 bits, resulting in overlapping addresses. While this overlap occurs, the parser should continue processing and, as recommended, may issue a warning to inform the user about the overlapping addresses. The device should contain two peripherals, and PeripheralB should have four registers expanded using dim, with the correct address offsets and sizes maintained for each register.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
def test_register_inheritance_same_address_dim(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test is similar to the one above, but in this case, `dim` is used, which causes `svdconv` to issue a
    warning instead of an error for compatibility reasons.

    **Expected Outcome:** The parser should successfully process the SVD file without errors, even though `RegisterA0`
    and `RegisterB0` share the same address offset of `0x0`, and `RegisterA1` and `RegisterB1` share the address
    offset of `0x4`. Each register has a size of 32 bits, resulting in overlapping addresses. While this overlap
    occurs, the parser should continue processing and, as recommended, may issue a warning to inform the user
    about the overlapping addresses. The device should contain two peripherals, and `PeripheralB` should have four
    registers expanded using `dim`, with the correct address offsets and sizes maintained for each register.

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

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile(
            "peripheral_inheritance_via_derivedfrom/register_inheritance_same_address_dim.svd"
        )

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert len(device.peripherals[1].registers_clusters) == 4

    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA0"
    assert device.peripherals[1].registers_clusters[0].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[0].size == 32

    assert isinstance(device.peripherals[1].registers_clusters[1], Register)
    assert device.peripherals[1].registers_clusters[1].name == "RegisterB0"
    assert device.peripherals[1].registers_clusters[1].address_offset == 0x0
    assert device.peripherals[1].registers_clusters[1].size == 32

    assert isinstance(device.peripherals[1].registers_clusters[2], Register)
    assert device.peripherals[1].registers_clusters[2].name == "RegisterA1"
    assert device.peripherals[1].registers_clusters[2].address_offset == 0x4
    assert device.peripherals[1].registers_clusters[2].size == 32

    assert isinstance(device.peripherals[1].registers_clusters[3], Register)
    assert device.peripherals[1].registers_clusters[3].name == "RegisterB1"
    assert device.peripherals[1].registers_clusters[3].address_offset == 0x4
    assert device.peripherals[1].registers_clusters[3].size == 32
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_same_address_dim.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
<?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>register_inheritance_same_address_dim</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>
          <dim>2</dim>
          <dimIncrement>0x4</dimIncrement>
          <name>RegisterA%s</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <dim>2</dim>
          <dimIncrement>0x4</dimIncrement>
          <name>RegisterB%s</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_inheritance_same_name

This test ensures that the parser correctly handles the case where a register in a derived peripheral has the same name as an inherited register from a base peripheral. The test verifies whether the parser raises an error when a register with the same name is defined both in the base and the derived peripheral, which would create a naming conflict.

Expected Outcome: The parser should detect that RegisterA is already defined in PeripheralB and cannot be inherited from PeripheralA due to the naming conflict. The parser is expected to raise a ProcessException or an equivalent error indicating that the register inheritance cannot proceed because the register name is already in use in the derived peripheral.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
@pytest.mark.xfail(
    strict=True,
    raises=ProcessException,
    reason=(
        "RegisterA is already defined in PeripheralB and cannot be inherited from PeripheralA "
        "because it has the same name"
    ),
)
def test_register_inheritance_same_name(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that the parser correctly handles the case where a register in a derived peripheral has the
    same name as an inherited register from a base peripheral. The test verifies whether the parser raises an
    error when a register with the same name is defined both in the base and the derived peripheral, which would
    create a naming conflict.

    **Expected Outcome:** The parser should detect that `RegisterA` is already defined in `PeripheralB` and cannot be
    inherited from `PeripheralA` due to the naming conflict. The parser is expected to raise a `ProcessException`
    or an equivalent error indicating that the register inheritance cannot proceed because the register name is
    already in use in the derived peripheral.

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

    get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/register_inheritance_same_name.svd")
SVD file: peripheral_inheritance_via_derivedfrom/register_inheritance_same_name.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
<?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>register_inheritance_same_name</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_register_properties_inheritance_size_adjustment

This test evaluates how the size property is handled during inheritance. The test file contains four peripherals: PeripheralA, PeripheralB, PeripheralC, and PeripheralD. PeripheralB inherits from PeripheralA, while PeripheralD inherits from PeripheralC. PeripheralA and PeripheralC each contain a register named RegisterA. In PeripheralA, the size of RegisterA is implicitly set to 32 bits (inherited from the peripheral level), while in PeripheralC, the size is explicitly defined as 32 bits at the register level. In svdconv, sizes are handled differently depending on whether they are set implicitly (inherited from the peripheral level) or explicitly at the register level. This distinction must be considered when developing a parser.

Expected Outcome: The parser should process the file correctly, reflecting how sizes are inherited or explicitly defined. PeripheralA has a size of 32 bits, which is implicitly applied to RegisterA. PeripheralB inherits from PeripheralA but adjusts its size to 16 bits, and this change is reflected in RegisterA, which now has a size of 16 bits. In contrast, PeripheralC explicitly defines the size of RegisterA as 32 bits at the register level, and this size remains unchanged in PeripheralD, which inherits from PeripheralC. The parser should correctly handle both the implicit and explicit size settings, ensuring that the sizes are applied as expected for each peripheral and register.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_register_properties_inheritance_size_adjustment(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test evaluates how the size property is handled during inheritance. The test file contains four
    peripherals: PeripheralA, PeripheralB, PeripheralC, and PeripheralD. PeripheralB inherits from PeripheralA,
    while PeripheralD inherits from PeripheralC. PeripheralA and PeripheralC each contain a register named
    RegisterA. In PeripheralA, the size of RegisterA is implicitly set to 32 bits (inherited from the peripheral
    level), while in PeripheralC, the size is explicitly defined as 32 bits at the register level. In `svdconv`,
    sizes are handled differently depending on whether they are set implicitly (inherited from the peripheral
    level) or explicitly at the register level. This distinction must be considered when developing a parser.

    **Expected Outcome:** The parser should process the file correctly, reflecting how sizes are inherited or
    explicitly defined. PeripheralA has a size of 32 bits, which is implicitly applied to RegisterA. PeripheralB
    inherits from PeripheralA but adjusts its size to 16 bits, and this change is reflected in RegisterA, which
    now has a size of 16 bits. In contrast, PeripheralC explicitly defines the size of RegisterA as 32 bits at the
    register level, and this size remains unchanged in PeripheralD, which inherits from PeripheralC. The parser
    should correctly handle both the implicit and explicit size settings, ensuring that the sizes are applied as
    expected for each peripheral and register.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/register_properties_inheritance_size_adjustment.svd"
    )

    assert len(device.peripherals) == 4

    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].size == 32
    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].size == 32

    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].size == 16
    assert len(device.peripherals[1].registers_clusters) == 1
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[1].registers_clusters[0].size == 16

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

    assert device.peripherals[3].name == "PeripheralD"
    assert device.peripherals[3].size == 32
    assert len(device.peripherals[3].registers_clusters) == 1
    assert isinstance(device.peripherals[3].registers_clusters[0], Register)
    assert device.peripherals[3].registers_clusters[0].name == "RegisterA"
    assert device.peripherals[3].registers_clusters[0].size == 32
SVD file: peripheral_inheritance_via_derivedfrom/register_properties_inheritance_size_adjustment.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>register_properties_inheritance_size_adjustment</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>
      <size>32</size>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
      <size>16</size>
    </peripheral>
    <peripheral>
      <name>PeripheralC</name>
      <baseAddress>0x40003000</baseAddress>
      <size>32</size>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
          <size>32</size>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralC">
      <name>PeripheralD</name>
      <baseAddress>0x40004000</baseAddress>
      <size>16</size>
    </peripheral>
  </peripherals>
</device>

test_same_address

This test case examines the scenario where two peripherals, PeripheralA and PeripheralB, are set to use the same base address (0x40001000). In the SVD file, PeripheralB is derived from PeripheralA, but it explicitly specifies the same base address. Typically, svdconv would issue an error for such conflicts because peripherals should not share the same base address unless there is an alternate relationship defined. However, overlapping addresses are only treated with a warning by svdconv due to compatibility reasons with older versions. Therefore, it may be advisable to allow such configurations while issuing a warning instead of an outright error.

Expected Outcome: The parser should process the file successfully but issue a warning (e.g. ProcessWarning) to inform the user that the address blocks of PeripheralA and PeripheralB share the same address.

Processable with svdconv: no

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
def test_same_address(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test case examines the scenario where two peripherals, `PeripheralA` and `PeripheralB`, are set to use
    the same base address (`0x40001000`). In the SVD file, `PeripheralB` is derived from `PeripheralA`, but it
    explicitly specifies the same base address. Typically, `svdconv` would issue an error for such conflicts
    because peripherals should not share the same base address unless there is an alternate relationship defined.
    However, overlapping addresses are only treated with a warning by `svdconv` due to compatibility reasons with
    older versions. Therefore, it may be advisable to allow such configurations while issuing a warning instead of
    an outright error.

    **Expected Outcome:** The parser should process the file successfully but issue a warning (e.g. `ProcessWarning`)
    to inform the user that the address blocks of `PeripheralA` and `PeripheralB` share the same address.

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

    with pytest.warns(ProcessWarning):
        device = get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/same_address.svd")

    assert len(device.peripherals) == 2
    assert device.peripherals[0].name == "PeripheralA"
    assert device.peripherals[0].base_address == 0x40001000
    assert len(device.peripherals[0].registers_clusters) == 1
    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].base_address == 0x40001000
    assert len(device.peripherals[1].registers_clusters) == 1
SVD file: peripheral_inheritance_via_derivedfrom/same_address.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
<?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>same_address</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40001000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_same_name

This test checks whether a derived peripheral with the same name as its base peripheral triggers an error. The expected behavior mirrors that of svdconv, which also raises an error in this scenario. When two peripherals have the same name, it should result in a conflict, and the parser must prevent this from occurring by raising an appropriate error.

Expected Outcome: The parser should raise an error when it encounters two peripherals, a base peripheral and its derived peripheral, sharing the same name. This behavior aligns with svdconv, where the same condition also triggers an error. The parser should halt processing and notify the user of the conflict, ensuring that no two peripherals share the same name within the SVD file.

Processable with svdconv: no

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
@pytest.mark.xfail(
    strict=True,
    raises=ProcessException,
    reason="Two peripherals cannot have the same name",
)
def test_same_name(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test checks whether a derived peripheral with the same name as its base peripheral triggers an error. The
    expected behavior mirrors that of svdconv, which also raises an error in this scenario. When two peripherals
    have the same name, it should result in a conflict, and the parser must prevent this from occurring by raising
    an appropriate error.

    **Expected Outcome:** The parser should raise an error when it encounters two peripherals, a base peripheral and
    its derived peripheral, sharing the same name. This behavior aligns with `svdconv`, where the same condition
    also triggers an error. The parser should halt processing and notify the user of the conflict, ensuring that
    no two peripherals share the same name within the SVD file.

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

    get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/same_name.svd")
SVD file: peripheral_inheritance_via_derivedfrom/same_name.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
<?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>same_name</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>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralA</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_simple_inheritance_backward_reference

The derived peripheral (PeripheralB) is declared after the base peripheral (PeripheralA), representing the typical and straightforward inheritance scenario. The test ensures that peripheral PeripheralB correctly inherits register RegisterA from Peripheral PeripheralA.

Expected Outcome: The device is processed correctly, and peripheral inheritance functions as expected. PeripheralB correctly inherits the register RegisterA from PeripheralA. The device contains two peripherals, with PeripheralB having one register and one address block. The address block in PeripheralB starts at offset 0x0, has a size of 0x1000, and is used for registers. The inherited register is correctly identified as RegisterA.

Processable with svdconv: yes

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
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
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_simple_inheritance_backward_reference(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    The derived peripheral (PeripheralB) is declared **after** the base peripheral (PeripheralA), representing the
    typical and straightforward inheritance scenario. The test ensures that peripheral PeripheralB correctly
    inherits register RegisterA from Peripheral PeripheralA.

    **Expected Outcome:** The device is processed correctly, and peripheral inheritance functions as expected.
    PeripheralB correctly inherits the register `RegisterA` from PeripheralA. The device contains two peripherals,
    with PeripheralB having one register and one address block. The address block in PeripheralB starts at offset
    `0x0`, has a size of `0x1000`, and is used for registers. The inherited register is correctly identified as
    `RegisterA`.

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

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/simple_inheritance_backward_reference.svd"
    )

    assert len(device.peripherals) == 2
    assert len(device.peripherals[1].registers_clusters) == 1
    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x1000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/simple_inheritance_backward_reference.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
<?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>simple_inheritance_backward_reference</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>
      <version>1.0</version>
      <baseAddress>0x40001000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
  </peripherals>
</device>

test_simple_inheritance_forward_reference

The derived peripheral (PeripheralA) is declared before the base peripheral (PeripheralB), but PeripheralA inherits from PeripheralB. This tests the parser's ability to handle forward references, resolving references to elements defined later in the SVD file.

Expected Outcome: The parser successfully resolves the forward reference where PeripheralA inherits from PeripheralB, despite PeripheralB being declared later in the SVD file. The device contains two peripherals, with PeripheralA having one register and one address block. The address block in PeripheralA starts at offset 0x0, has a size of 0x1000, and is used for registers. The inherited register is correctly identified as RegisterA.

Processable with svdconv: no - svdconv can't handle forward references over different peripherals.

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
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
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_simple_inheritance_forward_reference(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    The derived peripheral (PeripheralA) is declared before the base peripheral (PeripheralB), but PeripheralA
    inherits from PeripheralB. This tests the parser's ability to handle forward references, resolving references
    to elements defined later in the SVD file.

    **Expected Outcome:** The parser successfully resolves the forward reference where PeripheralA inherits from
    PeripheralB, despite PeripheralB being declared later in the SVD file. The device contains two peripherals,
    with PeripheralA having one register and one address block. The address block in PeripheralA starts at offset
    `0x0`, has a size of `0x1000`, and is used for registers. The inherited register is correctly identified as
    `RegisterA`.

    **Processable with svdconv:** no - `svdconv` can't handle forward references over different peripherals.
    """

    device = get_processed_device_from_testfile(
        "peripheral_inheritance_via_derivedfrom/simple_inheritance_forward_reference.svd"
    )

    assert len(device.peripherals) == 2
    assert len(device.peripherals[0].registers_clusters) == 1
    assert len(device.peripherals[0].address_blocks) == 1
    assert device.peripherals[0].address_blocks[0].offset == 0x0
    assert device.peripherals[0].address_blocks[0].size == 0x1000
    assert device.peripherals[0].address_blocks[0].usage == EnumeratedTokenType.REGISTERS
    assert isinstance(device.peripherals[0].registers_clusters[0], Register)
    assert device.peripherals[0].registers_clusters[0].name == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/simple_inheritance_forward_reference.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
<?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>simple_inheritance_forward_reference</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 derivedFrom="PeripheralB">
      <name>PeripheralA</name>
      <baseAddress>0x40001000</baseAddress>
    </peripheral>
    <peripheral>
      <name>PeripheralB</name>
      <version>1.0</version>
      <baseAddress>0x40002000</baseAddress>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
  </peripherals>
</device>

test_value_inheritance

This test ensures that child elements from a base peripheral (PeripheralA) are correctly inherited by a derived peripheral (PeripheralB).

Expected Outcome: The derived peripheral, PeripheralB, inherits the correct values from PeripheralA. PeripheralB should have the name "PeripheralB", version "1.0", description "PeripheralA Description", an alternatePeripheral of "PeripheralC", a groupName "PeripheralsGroup", a prependToName "Prefix", and a appendToName "Suffix". The header_struct_name is not inherited, which corresponds to the behavior of svdconv, but the disable_condition is set to "0 == 0". Additionally, PeripheralB should have a base address of 0x40002000, a size of 16 bits, access type of WRITE_ONLY, protection type SECURE, a resetValue of 0xDEADBEEF, and a resetMask of 0xDEADC0DE. PeripheralB has one address block starting at offset 0x0, with a size of 0x1000 and usage for registers. PeripheralB contains no interrupts, and it correctly inherits the register RegisterA.

Processable with svdconv: no - see Github issue #1796

Source code in tests/test_process/test_peripheral_inheritance_via_derived_from.py
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
@pytest.mark.filterwarnings("error::svdsuite.process.ProcessWarning")
def test_value_inheritance(get_processed_device_from_testfile: Callable[[str], Device]):
    """
    This test ensures that child elements from a base peripheral (PeripheralA) are correctly inherited by a
    derived peripheral (PeripheralB).

    **Expected Outcome:** The derived peripheral, PeripheralB, inherits the correct values from PeripheralA.
    PeripheralB should have the `name` "PeripheralB", `version` "1.0", `description` "PeripheralA Description", an
    `alternatePeripheral` of "PeripheralC", a `groupName` "PeripheralsGroup", a `prependToName` "Prefix", and a
    `appendToName` "Suffix". The `header_struct_name` is not inherited, which corresponds to the behavior of
    svdconv, but the `disable_condition` is set to `"0 == 0"`. Additionally, PeripheralB should have a base
    address of `0x40002000`, a `size` of 16 bits, `access` type of `WRITE_ONLY`, `protection` type `SECURE`, a
    `resetValue` of `0xDEADBEEF`, and a `resetMask` of `0xDEADC0DE`. PeripheralB has one address block starting at
    offset `0x0`, with a size of `0x1000` and usage for registers. PeripheralB contains no interrupts, and it
    correctly inherits the register `RegisterA`.

    **Processable with svdconv:** no - see Github issue [#1796](https://github.com/Open-CMSIS-
    Pack/devtools/issues/1796)
    """

    device = get_processed_device_from_testfile("peripheral_inheritance_via_derivedfrom/value_inheritance.svd")

    assert len(device.peripherals) == 2
    assert device.peripherals[1].name == "PeripheralB"
    assert device.peripherals[1].version == "1.0"
    assert device.peripherals[1].description == "PeripheralA Description"
    assert device.peripherals[1].alternate_peripheral == "PeripheralB"
    assert device.peripherals[1].group_name == "PeripheralsGroup"
    assert device.peripherals[1].prepend_to_name == "Prefix"
    assert device.peripherals[1].append_to_name == "Suffix"
    assert device.peripherals[1].header_struct_name is None  # Not inherited in svdconv
    assert device.peripherals[1].disable_condition == "0 == 0"
    assert device.peripherals[1].base_address == 0x40002000
    assert device.peripherals[1].size == 16
    assert device.peripherals[1].access == AccessType.WRITE_ONLY
    assert device.peripherals[1].protection == ProtectionStringType.SECURE
    assert device.peripherals[1].reset_value == 0xDEADBEEF
    assert device.peripherals[1].reset_mask == 0xDEADC0DE

    assert len(device.peripherals[1].address_blocks) == 1
    assert device.peripherals[1].address_blocks[0].offset == 0x0
    assert device.peripherals[1].address_blocks[0].size == 0x1000
    assert device.peripherals[1].address_blocks[0].usage == EnumeratedTokenType.REGISTERS

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

    assert isinstance(device.peripherals[1].registers_clusters[0], Register)
    assert device.peripherals[1].registers_clusters[0].name == "RegisterA"
SVD file: peripheral_inheritance_via_derivedfrom/value_inheritance.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
<?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>value_inheritance</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>
      <version>1.0</version>
      <description>PeripheralA Description</description>
      <alternatePeripheral>PeripheralB</alternatePeripheral>
      <groupName>PeripheralsGroup</groupName>
      <prependToName>Prefix</prependToName>
      <appendToName>Suffix</appendToName>
      <headerStructName>HeaderStructName</headerStructName>
      <disableCondition>0 == 0</disableCondition>
      <baseAddress>0x40001000</baseAddress>
      <size>16</size>
      <access>write-only</access>
      <protection>s</protection>
      <resetValue>0xDEADBEEF</resetValue>
      <resetMask>0xDEADC0DE</resetMask>
      <addressBlock>
        <offset>0x0</offset>
        <size>0x1000</size>
        <usage>registers</usage>
      </addressBlock>
      <interrupt>
        <name>InterruptA</name>
        <description>InterruptA Description</description>
        <value>0</value>
      </interrupt>
      <interrupt>
        <name>InterruptB</name>
        <description>InterruptB Description</description>
        <value>1</value>
      </interrupt>
      <registers>
        <register>
          <name>RegisterA</name>
          <addressOffset>0x0</addressOffset>
        </register>
      </registers>
    </peripheral>
    <peripheral derivedFrom="PeripheralA">
      <name>PeripheralB</name>
      <baseAddress>0x40002000</baseAddress>
    </peripheral>
  </peripherals>
</device>