Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

generate_svd: generalize DTS parser #18

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,22 @@
# cmsis-svd-generator
Generates CMSIS-SVD xml files from DTS info and Register templates in the regmaps directory.

# Generating a compatible DTS file

Many DTS files are multi-level, and have both C and DSTI includes.

To flatten the DTS file, one can run the C preprocessor and device tree compiler:

```bash
# run CPP to handle any C-style includes

cpp -nostdinc -I include -I arch -undef -x assembler-with-cpp /path/to/input.dts > processed.dts

# run DTC to handle any DTSI includes

dtc -I dts -O dts -o output.dts processed.dts

# finally, run generate-svd.py

./generate-svd.py -o output.svd -d output.dts
```
46 changes: 43 additions & 3 deletions generate_svd.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,33 @@ def generate_peripherals(dts):
idx[compatible] = 0

for peripheral in soc.child_nodes():
if peripheral.get_field("compatible") is not None and \
peripheral.get_field("reg-names") is not None:
if peripheral.get_field("compatible") is not None:
if peripheral.get_fields("reg") is not None and len(peripheral.get_fields("reg").values) % (peripheral.address_cells() + peripheral.size_cells()) != 0:
continue

compatibles = peripheral.get_fields("compatible")
reg_names = peripheral.get_fields("reg-names")

reg_names = {}
if peripheral.get_field("reg-names") is not None:
reg_names = peripheral.get_fields("reg-names")
else:
reg_names = {"reg"}

for comp in compatibles:
for reg in reg_names:
regmap_root = os.path.abspath(os.path.dirname(sys.argv[0]))
regmap_name = get_name_as_id(comp) + "_" + reg + ".svd"
regmap_path = os.path.join(regmap_root, "regmaps", regmap_name)
script_name = get_name_as_id(comp) + "_" + reg + ".py"
script_path = os.path.join(regmap_root, "scripts", script_name)

if "clint0" in comp and not os.path.exists(script_path):
script_path = os.path.join(regmap_root, "scripts", "riscv_clint0_control.py")
elif "plic0" in comp and not os.path.exists(script_path):
script_path = os.path.join(regmap_root, "scripts", "riscv_plic0_control.py")
elif "clic0" in comp and not os.path.exists(script_path):
script_path = os.path.join(regmap_root, "scripts", "sifive_clic0_control.py")

if os.path.exists(regmap_path):
ext = str(idx[comp])
txt += generate_peripheral(dts, peripheral, comp, ext, reg, regmap_path)
Expand All @@ -82,14 +98,34 @@ def generate_peripherals(dts):
ext = str(idx[comp])
txt += generate_peripheral(dts, peripheral, comp, ext, reg, script_path)
idx[comp] += 1
else:
ext = str(idx[comp])
txt += generate_peripheral(dts, peripheral, comp, ext, reg, "")
idx[comp] += 1

return txt

#pylint: disable=too-many-arguments
def generate_peripheral(dts, peripheral, comp, ext, reg, regmap_path):
"""Generate xml string for peripheral"""
reg_dict = peripheral.get_reg()

if reg_dict is None:
return ""

reg_pair = reg_dict.get_by_name(reg)

addr_cells = peripheral.address_cells()
size_cells = peripheral.size_cells()
group_size = addr_cells + size_cells

if reg_pair is None and len(reg_dict.values) == group_size:
# no reg-names field was present, so parse according to the spec
reg_pair = [reg_dict.values[addr_cells - 1], reg_dict.values[group_size - 1]]
elif reg_pair is None:
# malformed DTS, give up
return ""

reg_desc = comp + """,""" + reg
print("Emitting registers for '" + peripheral.name + "' soc peripheral node")

Expand All @@ -108,6 +144,10 @@ def generate_peripheral(dts, peripheral, comp, ext, reg, regmap_path):
"""

def generate_registers(dts, peripheral, regmap_path):
if regmap_path == "":
# FIXME: instead of just giving up here, attempt to parse register data from the DTS
return ""

"""Generate xml string for registers from regmap file or generator code"""
if regmap_path.endswith("riscv_clint0_control.py"):
return generate_registers_riscv_clint0(dts)
Expand Down