forked from olofk/ipyxact
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathgen_c_header.py
115 lines (100 loc) · 4.07 KB
/
gen_c_header.py
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
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
#ipyxact example. Parses an IP-XACT XML file called generic_example.xml
#and prints out a C header of the register maps found
import argparse
import sys
import time
from ipyxact.ipyxact import Component
def parse_args():
parser = argparse.ArgumentParser(
description='Generate a C header from an IP-XACT file')
parser.add_argument('ipxact_file', help='IP-XACT file to parse')
parser.add_argument('-o', dest='output_file', help='Write output to file')
parser.add_argument('-g', '--header-guard', dest='header_guard',
help='Header guard. If not specified it will be derived from the '
'output file name else there will be no guard.')
return parser.parse_args();
def open_output(output):
return open(output, 'w') if output else sys.stdout
def get_header_guard(args):
if args.header_guard:
return args.header_guard
elif args.output_file:
return args.output_file.upper().replace('.', '_').replace('/', '_');
else:
return None
def write_prologue(of, args):
guard = get_header_guard(args);
of.write('/* Header generated by ipyxact ({}) */\n'
.format(time.strftime("%Y-%m-%d %H:%M:%S")));
if guard:
of.write('#ifndef {}\n'.format(guard))
of.write('#define {}\n\n'.format(guard))
of.write('#include <stdint.h>\n\n')
for bit in [8, 16, 32, 64]:
of.write('#define IPYXACT_REG_{}(addr) (*(volatile uint{}_t*)(addr))\n'
.format(bit, bit));
of.write('#define IPYXACT_RO_REG_{}(addr) '
'(*(const volatile uint{}_t*)(addr))\n'
.format(bit, bit));
of.write('\n')
def write_epilogue(of, args):
guard = get_header_guard(args);
if guard:
of.write('#endif /* {} */\n'.format(guard))
def gen_mask(offset, width):
mask = 0
for i in range(offset, offset+width):
mask += 1<<i
return mask
def write_enum(field):
of.write("typedef enum {\n")
for es in field.enumeratedValues:
for e in sorted(es.enumeratedValue, key=lambda x: x.value):
of.write(" {}_{} = {},\n".format(
field.name.lower(), e.name, e.value<<field.bitOffset))
of.write("} {}_t;\n\n".format(field.name.lower()))
def write_reg_fields(reg, reg_name):
for f in sorted(reg.field, key=lambda x: x.bitOffset):
of.write("#define {}_{}_MASK 0x{:08X}\n".format(
reg_name, f.name.upper().replace('-','_'),
gen_mask(f.bitOffset, f.bitWidth)))
if f.enumeratedValues:
of.write('\n')
write_enum(field)
of.write('\n')
def write_memory_maps(of, memory_maps, offset=0, name=None):
for m in memory_maps.memoryMap:
if name:
mname=name.upper()
else:
mname = m.name.upper()
multiblock = len(m.addressBlock) > 1
for block in m.addressBlock:
if multiblock:
bname = mname + '_' + block.name.upper()
else:
bname = mname
for reg in sorted(block.register, key=lambda a: a.addressOffset):
reg_name = '{}_{}'.format(
bname, reg.name.upper().replace('-', '_'))
reg_addr = '0x{:08X}'.format(
offset + block.baseAddress + reg.addressOffset)
if reg.size in [8, 16, 32, 64]:
reg_access = 'RO_' if reg.access == 'read-only' else ''
of.write('#define {} IPYXACT_{}REG_{}({})\n'.format(
reg_name, reg_access, reg.size, reg_addr))
else:
of.write("#define {} {}\n".format(reg_name, reg_addr))
if reg.field:
write_reg_fields(reg, reg_name)
if __name__ == '__main__':
args = parse_args()
with open(args.ipxact_file) as f:
name = None
offset = 0
component = Component()
component.load(f)
with open_output(args.output_file) as of:
write_prologue(of, args);
write_memory_maps(of, component.memoryMaps, offset, name)
write_epilogue(of, args);