modm_data.svd
1# Copyright 2022, Niklas Hauser 2# SPDX-License-Identifier: MPL-2.0 3 4from . import stmicro 5from .model import Device, PeripheralType, Peripheral, Register, BitField, compare_device_trees 6from .write import format_svd, write_svd 7from .read import read_svd 8 9__all__ = [ 10 "stmicro", 11 "Device", 12 "PeripheralType", 13 "Peripheral", 14 "Register", 15 "BitField", 16 "compare_device_trees", 17 "format_svd", 18 "write_svd", 19 "read_svd", 20]
8class Device(Node): 9 def __init__(self, name, **kw): 10 if "compatible" not in kw: 11 kw["compatible"] = [name] 12 super().__init__(name, **kw) 13 14 def __hash__(self) -> int: 15 value = 0 16 for peripheral in self.children: 17 value += hash(peripheral) 18 for register in peripheral.children: 19 value += hash(register) 20 for bitfield in register.children: 21 value += hash(bitfield) 22 return value 23 24 def __eq__(self, other) -> bool: 25 if isinstance(other, self.__class__): 26 return compare_device_trees(self, other) 27 else: 28 return NotImplemented
A simple tree node with a name
and any kwargs
.
Args: name: A name or any other object this node can reference to as identifier.
Keyword Args: parent: Reference to parent node. children: Iterable with child nodes. *: Any other given attribute is just stored as object attribute.
Other than :any:AnyNode
this class has at least the name
attribute,
to distinguish between different instances.
The parent
attribute refers the parent node:
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
The same tree can be constructed by using the children
attribute:
>>> root = Node("root", children=[
... Node("sub0", children=[
... Node("sub0B", bar=109, foo=4),
... Node("sub0A", children=None),
... ]),
... Node("sub1", children=[
... Node("sub1A"),
... Node("sub1B", bar=8, children=[]),
... Node("sub1C", children=[
... Node("sub1Ca"),
... ]),
... ]),
... ])
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
Inherited Members
- anytree.node.node.Node
- name
- parent
- anytree.node.nodemixin.NodeMixin
- separator
- children
- path
- iter_path_reverse
- ancestors
- anchestors
- descendants
- root
- siblings
- leaves
- is_leaf
- is_root
- height
- depth
- size
31class PeripheralType(Node): 32 def __init__(self, name, **kw): 33 super().__init__(name, **kw) 34 35 def __hash__(self) -> int: 36 value = hash(self.name) 37 if hasattr(self, "filters") and self.filters: 38 value += hash(str(self.filters)) 39 return value 40 41 def __eq__(self, other) -> bool: 42 if isinstance(other, self.__class__): 43 return self.name == other.name and self.filters == other.filters 44 else: 45 return NotImplemented
A simple tree node with a name
and any kwargs
.
Args: name: A name or any other object this node can reference to as identifier.
Keyword Args: parent: Reference to parent node. children: Iterable with child nodes. *: Any other given attribute is just stored as object attribute.
Other than :any:AnyNode
this class has at least the name
attribute,
to distinguish between different instances.
The parent
attribute refers the parent node:
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
The same tree can be constructed by using the children
attribute:
>>> root = Node("root", children=[
... Node("sub0", children=[
... Node("sub0B", bar=109, foo=4),
... Node("sub0A", children=None),
... ]),
... Node("sub1", children=[
... Node("sub1A"),
... Node("sub1B", bar=8, children=[]),
... Node("sub1C", children=[
... Node("sub1Ca"),
... ]),
... ]),
... ])
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
Inherited Members
- anytree.node.node.Node
- name
- parent
- anytree.node.nodemixin.NodeMixin
- separator
- children
- path
- iter_path_reverse
- ancestors
- anchestors
- descendants
- root
- siblings
- leaves
- is_leaf
- is_root
- height
- depth
- size
48class Peripheral(Node): 49 def __init__(self, name, type, address, **kw): 50 super().__init__(name, type=type, address=address, **kw) 51 52 def __hash__(self) -> int: 53 value = hash(f"{self.name} {self.address} {self.type}") 54 if hasattr(self, "filters") and self.filters: 55 value += hash(str(self.filters)) 56 return value 57 58 def __eq__(self, other) -> bool: 59 if isinstance(other, self.__class__): 60 return self.name == other.name and self.address == other.address 61 else: 62 return NotImplemented
A simple tree node with a name
and any kwargs
.
Args: name: A name or any other object this node can reference to as identifier.
Keyword Args: parent: Reference to parent node. children: Iterable with child nodes. *: Any other given attribute is just stored as object attribute.
Other than :any:AnyNode
this class has at least the name
attribute,
to distinguish between different instances.
The parent
attribute refers the parent node:
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
The same tree can be constructed by using the children
attribute:
>>> root = Node("root", children=[
... Node("sub0", children=[
... Node("sub0B", bar=109, foo=4),
... Node("sub0A", children=None),
... ]),
... Node("sub1", children=[
... Node("sub1A"),
... Node("sub1B", bar=8, children=[]),
... Node("sub1C", children=[
... Node("sub1Ca"),
... ]),
... ]),
... ])
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
Inherited Members
- anytree.node.node.Node
- name
- parent
- anytree.node.nodemixin.NodeMixin
- separator
- children
- path
- iter_path_reverse
- ancestors
- anchestors
- descendants
- root
- siblings
- leaves
- is_leaf
- is_root
- height
- depth
- size
65class Register(Node): 66 def __init__(self, name, offset, width=None, **kw): 67 super().__init__(name, offset=offset, width=width or 4, **kw) 68 69 @property 70 def address(self) -> int: 71 return self.parent.address + self.offset 72 73 @property 74 def addresses(self) -> int: 75 for ii in range(self.width): 76 yield self.parent.address + self.offset + ii 77 78 def __hash__(self) -> int: 79 value = hash(f"{self.name} {self.offset} {self.width}") 80 if hasattr(self, "filters") and self.filters: 81 value += hash(str(self.filters)) 82 return value 83 84 def __eq__(self, other) -> bool: 85 if isinstance(other, self.__class__): 86 return self.name == other.name and self.offset == other.offset 87 else: 88 return NotImplemented
A simple tree node with a name
and any kwargs
.
Args: name: A name or any other object this node can reference to as identifier.
Keyword Args: parent: Reference to parent node. children: Iterable with child nodes. *: Any other given attribute is just stored as object attribute.
Other than :any:AnyNode
this class has at least the name
attribute,
to distinguish between different instances.
The parent
attribute refers the parent node:
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
The same tree can be constructed by using the children
attribute:
>>> root = Node("root", children=[
... Node("sub0", children=[
... Node("sub0B", bar=109, foo=4),
... Node("sub0A", children=None),
... ]),
... Node("sub1", children=[
... Node("sub1A"),
... Node("sub1B", bar=8, children=[]),
... Node("sub1C", children=[
... Node("sub1Ca"),
... ]),
... ]),
... ])
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
Inherited Members
- anytree.node.node.Node
- name
- parent
- anytree.node.nodemixin.NodeMixin
- separator
- children
- path
- iter_path_reverse
- ancestors
- anchestors
- descendants
- root
- siblings
- leaves
- is_leaf
- is_root
- height
- depth
- size
91class BitField(Node): 92 def __init__(self, name, position, width=None, **kw): 93 super().__init__(name, position=position, width=width or 1, **kw) 94 95 @property 96 def bit_address(self) -> int: 97 return self.parent.address * 8 + self.position 98 99 @property 100 def bit_addresses(self) -> int: 101 for ii in range(self.width): 102 yield self.parent.address * 8 + self.position + ii 103 104 def __hash__(self) -> int: 105 return hash(f"{self.name} {self.position} {self.width}") 106 107 def __eq__(self, other) -> bool: 108 if isinstance(other, self.__class__): 109 return self.name == other.name and self.position == other.position 110 else: 111 return NotImplemented
A simple tree node with a name
and any kwargs
.
Args: name: A name or any other object this node can reference to as identifier.
Keyword Args: parent: Reference to parent node. children: Iterable with child nodes. *: Any other given attribute is just stored as object attribute.
Other than :any:AnyNode
this class has at least the name
attribute,
to distinguish between different instances.
The parent
attribute refers the parent node:
>>> from anytree import Node, RenderTree
>>> root = Node("root")
>>> s0 = Node("sub0", parent=root)
>>> s0b = Node("sub0B", parent=s0, foo=4, bar=109)
>>> s0a = Node("sub0A", parent=s0)
>>> s1 = Node("sub1", parent=root)
>>> s1a = Node("sub1A", parent=s1)
>>> s1b = Node("sub1B", parent=s1, bar=8)
>>> s1c = Node("sub1C", parent=s1)
>>> s1ca = Node("sub1Ca", parent=s1c)
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
The same tree can be constructed by using the children
attribute:
>>> root = Node("root", children=[
... Node("sub0", children=[
... Node("sub0B", bar=109, foo=4),
... Node("sub0A", children=None),
... ]),
... Node("sub1", children=[
... Node("sub1A"),
... Node("sub1B", bar=8, children=[]),
... Node("sub1C", children=[
... Node("sub1Ca"),
... ]),
... ]),
... ])
>>> print(RenderTree(root))
Node('/root')
├── Node('/root/sub0')
│ ├── Node('/root/sub0/sub0B', bar=109, foo=4)
│ └── Node('/root/sub0/sub0A')
└── Node('/root/sub1')
├── Node('/root/sub1/sub1A')
├── Node('/root/sub1/sub1B', bar=8)
└── Node('/root/sub1/sub1C')
└── Node('/root/sub1/sub1C/sub1Ca')
Inherited Members
- anytree.node.node.Node
- name
- parent
- anytree.node.nodemixin.NodeMixin
- separator
- children
- path
- iter_path_reverse
- ancestors
- anchestors
- descendants
- root
- siblings
- leaves
- is_leaf
- is_root
- height
- depth
- size
129def compare_device_trees(left, right): 130 assert isinstance(left, Device) and isinstance(right, Device) 131 if len(left.children) != len(right.children): 132 return False 133 if not left.children: 134 return True 135 return all(_compare_trees(left, right) for left, right in zip(left.children, right.children))
80def format_svd(register_tree): 81 device = etree.Element("device") 82 device.set("schemaVersion", "1.1") 83 # device.set("xmlns:xs", "http://www.w3.org/2001/XMLSchema-instance") 84 # device.set("xs:noNamespaceSchemaLocation", "CMSIS-SVD_Schema_1_1.xsd") 85 86 _format_svd(device, register_tree) 87 88 svd = etree.ElementTree(device) 89 return svd
8def read_svd(path) -> Device: 9 from cmsis_svd.parser import SVDParser 10 11 parser = SVDParser.for_xml_file(path) 12 pdev = parser.get_device() 13 device = Device(pdev.name, compatible=pdev.description.split(",")) 14 15 for peripheral in pdev.peripherals: 16 ptype = peripheral.get_derived_from() 17 if ptype is not None: 18 ptype = ptype.name 19 nper = Peripheral(peripheral.name, ptype, peripheral.base_address, parent=device) 20 for register in peripheral.registers: 21 nreg = Register(register.name, register.address_offset, register.size // 8, parent=nper) 22 for field in register.fields: 23 BitField(field.name, field.bit_offset, field.bit_width, parent=nreg) 24 25 return device