renode-esp32s3/svd-to-renode.py
Sean Cross 1166c4ce41 initial commit
Signed-off-by: Sean Cross <sean@xobs.io>
2023-07-24 12:00:46 +08:00

172 lines
6.9 KiB
Python

#!/usr/bin/env python3
import xml.etree.ElementTree as ET
class SVDExtractor:
def __init__(self, filename):
self.tree = ET.parse(filename)
self.root = self.tree.getroot()
self.peripherals = self.root.find("peripherals")
def extract(
self,
peripheral_to_print,
namespace,
generated_peripheral_name,
imports=None,
extra_subclasses=None,
):
for peripheral in self.peripherals.iter("peripheral"):
peripheral_name = peripheral.find("name").text
if peripheral_name != peripheral_to_print:
continue
register_list = dict()
peripheral_size = int(peripheral.find("addressBlock").find("size").text, 0)
registers = peripheral.find("registers")
if imports is not None:
for i in imports:
print(f"using {i};")
print()
print(f"namespace {namespace}")
print("{")
print(f" public class {generated_peripheral_name} : ", end="")
if extra_subclasses is not None:
for esc in extra_subclasses:
print(f"{esc}, ", end="")
print(
"IDoubleWordPeripheral, IProvidesRegisterCollection<DoubleWordRegisterCollection>, IKnownSize"
)
print(" {")
print(" public GPIO IRQ { get; private set; }")
print(
" public DoubleWordRegisterCollection RegistersCollection { get; }"
)
print(f" public long Size => 0x1000; // {hex(peripheral_size)}")
print(" private readonly Machine machine;")
print()
print(
f" public {generated_peripheral_name}(Machine machine) : base(machine)"
)
print(" {")
print(" this.machine = machine;")
print()
print(" IRQ = new GPIO();")
print()
print(
" RegistersCollection = new DoubleWordRegisterCollection(this);"
)
print(" DefineRegisters();")
print(" Reset();")
print(" }")
print()
print(" private void DefineRegisters()")
print(" {")
for register in registers.iter("register"):
register_name = register.find("name").text
register_description = register.find("description").text
register_offset = int(register.find("addressOffset").text, 0)
register_default = 0
register_reset_value_field = register.find("resetValue")
if register_reset_value_field is not None:
register_default = int(register_reset_value_field.text, 0)
register_list[register_offset] = register_name
if "\n" in register_description:
raise Exception("Register description contains a newline")
print(f" // {register_description}")
print(f" Registers.{register_name}.Define(this, {hex(register_default)})")
for field in register.find("fields").iter("field"):
field_offset = int(field.find("bitOffset").text, 0)
field_width = int(field.find("bitWidth").text, 0)
field_name = field.find("name").text
field_description = field.find("description").text
field_access = field.find("access").text
field_access_mask = ""
if field_access == "read-write":
field_access_mask = "FieldMode.Read | FieldMode.Write, "
elif field_access == "read-only":
field_access_mask = "FieldMode.Read, "
elif field_access == "write-only":
field_access_mask = "FieldMode.Write, "
else:
raise Exception(
f"Unrecognized field access type: {field_access}"
)
if "\n" in field_description:
raise Exception("Field description contains a newline")
if field_width == 1:
print(
f' .WithFlag({field_offset}, {field_access_mask}name: "{field_name}") // {field_description}'
)
else:
print(
f' .WithValueField({field_offset}, {field_width}, {field_access_mask}name: "{field_name}") // {field_description}'
)
print(" ;")
print()
print(" }")
print()
print(" public override void Reset()")
print(" {")
print(" RegistersCollection.Reset();")
print(" UpdateInterrupts();")
print(" }")
print()
print(" public uint ReadDoubleWord(long offset)")
print(" {")
print(" return RegistersCollection.Read(offset);")
print(" }")
print()
print(" public void WriteDoubleWord(long offset, uint value)")
print(" {")
print(" RegistersCollection.Write(offset, value);")
print(" }")
print(" private void UpdateInterrupts()")
print(" {")
print(" var status = false;")
print(" this.Log(LogLevel.Noisy, \"Setting IRQ to {0}\", status);")
print(" IRQ.Set(status);")
print(" }")
print()
print(" private enum Registers")
print(" {")
for offset, name in register_list.items():
print(f" {name} = {hex(offset)},")
print(" }")
print(" }")
print("}")
if __name__ == "__main__":
extractor = SVDExtractor("esp32s3.svd")
extractor.extract(
"SPI1",
"Antmicro.Renode.Peripherals.SPI",
"ESP32_SPIController",
imports=[
"System.Linq",
"System.Collections.Generic",
"Antmicro.Renode.Core",
"Antmicro.Renode.Core.Structure",
"Antmicro.Renode.Core.Structure.Registers",
"Antmicro.Renode.Logging",
"Antmicro.Renode.Peripherals.Bus",
"Antmicro.Renode.Peripherals.Memory",
"Antmicro.Renode.Peripherals.MTD",
],
extra_subclasses=["NullRegistrationPointPeripheralContainer<ISPIPeripheral>"],
)