Parse our memory location bases and name them well-ish.
This commit is contained in:
parent
2d38aad861
commit
2e7af6b842
172
parse.py
172
parse.py
@ -3,6 +3,7 @@
|
|||||||
import sys
|
import sys
|
||||||
import xmltodict
|
import xmltodict
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from yaml import CSafeLoader as SafeLoader
|
from yaml import CSafeLoader as SafeLoader
|
||||||
except ImportError:
|
except ImportError:
|
||||||
@ -14,6 +15,24 @@ import os
|
|||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
from glob import glob
|
from glob import glob
|
||||||
|
|
||||||
|
class DecimalInt:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def represent_decimal_int(dumper, data):
|
||||||
|
return dumper.represent_int(data.val)
|
||||||
|
|
||||||
|
yaml.add_representer(DecimalInt, represent_decimal_int)
|
||||||
|
|
||||||
|
class HexInt:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def represent_hex_int(dumper, data):
|
||||||
|
return dumper.represent_int(hex(data.val))
|
||||||
|
|
||||||
|
yaml.add_representer(HexInt, represent_hex_int)
|
||||||
|
|
||||||
|
|
||||||
def removeprefix(value: str, prefix: str, /) -> str:
|
def removeprefix(value: str, prefix: str, /) -> str:
|
||||||
if value.startswith(prefix):
|
if value.startswith(prefix):
|
||||||
@ -52,6 +71,7 @@ def represent_ordereddict(dumper, data):
|
|||||||
yaml.add_representer(OrderedDict, represent_ordereddict)
|
yaml.add_representer(OrderedDict, represent_ordereddict)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def hexint_presenter(dumper, data):
|
def hexint_presenter(dumper, data):
|
||||||
if data > 0x10000:
|
if data > 0x10000:
|
||||||
return dumper.represent_int(hex(data))
|
return dumper.represent_int(hex(data))
|
||||||
@ -112,6 +132,7 @@ def paren_ok(val):
|
|||||||
return False
|
return False
|
||||||
return n == 0
|
return n == 0
|
||||||
|
|
||||||
|
|
||||||
# warning: horrible abomination ahead
|
# warning: horrible abomination ahead
|
||||||
|
|
||||||
|
|
||||||
@ -167,21 +188,21 @@ def parse_header(f):
|
|||||||
cur_core = "cm" + str(m.group(1))
|
cur_core = "cm" + str(m.group(1))
|
||||||
if m.group(2) != None:
|
if m.group(2) != None:
|
||||||
cur_core += "p"
|
cur_core += "p"
|
||||||
#print("Cur core is ", cur_core, "matched", l)
|
# print("Cur core is ", cur_core, "matched", l)
|
||||||
found = False
|
found = False
|
||||||
for core in cores:
|
for core in cores:
|
||||||
if core == cur_core:
|
if core == cur_core:
|
||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
cores.append(cur_core)
|
cores.append(cur_core)
|
||||||
#print("Switching to core", cur_core, "for", f)
|
# print("Switching to core", cur_core, "for", f)
|
||||||
elif m := re.match('.*else.*', l):
|
elif m := re.match('.*else.*', l):
|
||||||
cur_core = "all"
|
cur_core = "all"
|
||||||
if m := re.match('.*else.*CORE_CM(\\d+)(PLUS)?.*', l):
|
if m := re.match('.*else.*CORE_CM(\\d+)(PLUS)?.*', l):
|
||||||
cur_core = "cm" + str(m.group(1))
|
cur_core = "cm" + str(m.group(1))
|
||||||
if m.group(2) != None:
|
if m.group(2) != None:
|
||||||
cur_core += "p"
|
cur_core += "p"
|
||||||
#print("Cur core is ", cur_core, "matched", l)
|
# print("Cur core is ", cur_core, "matched", l)
|
||||||
elif len(cores) > 1:
|
elif len(cores) > 1:
|
||||||
# Pick the second core assuming we've already parsed one
|
# Pick the second core assuming we've already parsed one
|
||||||
cur_core = cores[1]
|
cur_core = cores[1]
|
||||||
@ -192,19 +213,19 @@ def parse_header(f):
|
|||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
cores.append(cur_core)
|
cores.append(cur_core)
|
||||||
#print("Switching to core", cur_core, "for", f)
|
# print("Switching to core", cur_core, "for", f)
|
||||||
elif m := re.match('.*endif.*', l):
|
elif m := re.match('.*endif.*', l):
|
||||||
#print("Switching to common core for", f)
|
# print("Switching to common core for", f)
|
||||||
cur_core = "all"
|
cur_core = "all"
|
||||||
|
|
||||||
if cur_core not in irqs:
|
if cur_core not in irqs:
|
||||||
#print("Registering new core", cur_core)
|
# print("Registering new core", cur_core)
|
||||||
irqs[cur_core] = {}
|
irqs[cur_core] = {}
|
||||||
if cur_core not in defines:
|
if cur_core not in defines:
|
||||||
defines[cur_core] = {}
|
defines[cur_core] = {}
|
||||||
|
|
||||||
if m := re.match('([a-zA-Z0-9_]+)_IRQn += (\\d+),? +/\\*!< (.*) \\*/', l):
|
if m := re.match('([a-zA-Z0-9_]+)_IRQn += (\\d+),? +/\\*!< (.*) \\*/', l):
|
||||||
#print("Found irq for", cur_core)
|
# print("Found irq for", cur_core)
|
||||||
irqs[cur_core][m.group(1)] = int(m.group(2))
|
irqs[cur_core][m.group(1)] = int(m.group(2))
|
||||||
|
|
||||||
if m := re.match('#define +([0-9A-Za-z_]+)\\(', l):
|
if m := re.match('#define +([0-9A-Za-z_]+)\\(', l):
|
||||||
@ -217,11 +238,11 @@ def parse_header(f):
|
|||||||
continue
|
continue
|
||||||
val = val.split('/*')[0].strip()
|
val = val.split('/*')[0].strip()
|
||||||
val = parse_value(val, defines[cur_core])
|
val = parse_value(val, defines[cur_core])
|
||||||
#print("Found define for", cur_core)
|
# print("Found define for", cur_core)
|
||||||
defines[cur_core][name] = val
|
defines[cur_core][name] = val
|
||||||
|
|
||||||
#print("Found", len(cores), "cores for", f)
|
# print("Found", len(cores), "cores for", f)
|
||||||
#print("Found", len(irqs['all']), "shared interrupts for", f)
|
# print("Found", len(irqs['all']), "shared interrupts for", f)
|
||||||
|
|
||||||
if len(cores) == 0:
|
if len(cores) == 0:
|
||||||
cores.append("all")
|
cores.append("all")
|
||||||
@ -369,7 +390,7 @@ perimap = [
|
|||||||
|
|
||||||
def match_peri(peri):
|
def match_peri(peri):
|
||||||
for r, block in perimap:
|
for r, block in perimap:
|
||||||
if re.match('^'+r+'$', peri):
|
if re.match('^' + r + '$', peri):
|
||||||
if block == '':
|
if block == '':
|
||||||
return None
|
return None
|
||||||
return block
|
return block
|
||||||
@ -462,11 +483,28 @@ def chip_name_from_package_name(x):
|
|||||||
]
|
]
|
||||||
|
|
||||||
for a, b in name_map:
|
for a, b in name_map:
|
||||||
r, n = re.subn('^'+a+'$', b, x)
|
r, n = re.subn('^' + a + '$', b, x)
|
||||||
if n != 0:
|
if n != 0:
|
||||||
return r
|
return r
|
||||||
raise Exception("bad name: {}".format(x))
|
raise Exception("bad name: {}".format(x))
|
||||||
|
|
||||||
|
memories_map = {
|
||||||
|
'flash': [
|
||||||
|
'FLASH', 'FLASH_BANK1', 'FLASH_BANK2',
|
||||||
|
'D1_AXIFLASH', 'D1_AXIICP',
|
||||||
|
],
|
||||||
|
'ram': [
|
||||||
|
'SRAM', 'SRAM1', 'SRAM2',
|
||||||
|
'D1_AXISRAM',
|
||||||
|
'D1_ITCMRAM',
|
||||||
|
'D1_DTCMRAM',
|
||||||
|
'D1_AHBSRAM',
|
||||||
|
'D2_AXISRAM',
|
||||||
|
'D3_BKPSRAM',
|
||||||
|
'D3_SRAM'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def parse_chips():
|
def parse_chips():
|
||||||
os.makedirs('data/chips', exist_ok=True)
|
os.makedirs('data/chips', exist_ok=True)
|
||||||
@ -488,19 +526,19 @@ def parse_chips():
|
|||||||
package_flashs = r['Flash']
|
package_flashs = r['Flash']
|
||||||
die = r['Die']
|
die = r['Die']
|
||||||
if type(package_rams) != list:
|
if type(package_rams) != list:
|
||||||
package_rams = [package_rams]*len(package_names)
|
package_rams = [package_rams] * len(package_names)
|
||||||
if type(package_flashs) != list:
|
if type(package_flashs) != list:
|
||||||
package_flashs = [package_flashs]*len(package_names)
|
package_flashs = [package_flashs] * len(package_names)
|
||||||
for package_i, package_name in enumerate(package_names):
|
for package_i, package_name in enumerate(package_names):
|
||||||
chip_name = chip_name_from_package_name(package_name)
|
chip_name = chip_name_from_package_name(package_name)
|
||||||
flash = OrderedDict( {
|
flash = OrderedDict({
|
||||||
'size': int(package_flashs[package_i]),
|
'bytes': DecimalInt(int(package_flashs[package_i]) * 1024),
|
||||||
'base': None,
|
'regions': []
|
||||||
} )
|
})
|
||||||
ram = OrderedDict( {
|
ram = OrderedDict({
|
||||||
'size': int(package_rams[package_i]),
|
'bytes': DecimalInt(int(package_rams[package_i]) * 1024),
|
||||||
'base': None,
|
'regions': [],
|
||||||
} )
|
})
|
||||||
gpio_af = next(filter(lambda x: x['@Name'] == 'GPIO', r['IP']))['@Version']
|
gpio_af = next(filter(lambda x: x['@Name'] == 'GPIO', r['IP']))['@Version']
|
||||||
gpio_af = removesuffix(gpio_af, '_gpio_v1_0')
|
gpio_af = removesuffix(gpio_af, '_gpio_v1_0')
|
||||||
|
|
||||||
@ -586,7 +624,7 @@ def parse_chips():
|
|||||||
|
|
||||||
for ip in r['IP']:
|
for ip in r['IP']:
|
||||||
pname = ip['@InstanceName']
|
pname = ip['@InstanceName']
|
||||||
pkind = ip['@Name']+':'+ip['@Version']
|
pkind = ip['@Name'] + ':' + ip['@Version']
|
||||||
pkind = removesuffix(pkind, '_Cube')
|
pkind = removesuffix(pkind, '_Cube')
|
||||||
|
|
||||||
if pname == 'SYS':
|
if pname == 'SYS':
|
||||||
@ -595,7 +633,7 @@ def parse_chips():
|
|||||||
continue
|
continue
|
||||||
if pname.startswith('ADC'):
|
if pname.startswith('ADC'):
|
||||||
if not 'ADC_COMMON' in peris:
|
if not 'ADC_COMMON' in peris:
|
||||||
peris['ADC_COMMON'] = 'ADC_COMMON:'+removesuffix(ip['@Version'], '_Cube')
|
peris['ADC_COMMON'] = 'ADC_COMMON:' + removesuffix(ip['@Version'], '_Cube')
|
||||||
peris[pname] = pkind
|
peris[pname] = pkind
|
||||||
pins[pname] = []
|
pins[pname] = []
|
||||||
|
|
||||||
@ -653,14 +691,57 @@ def parse_chips():
|
|||||||
raise Exception("missing header for {}".format(chip_name))
|
raise Exception("missing header for {}".format(chip_name))
|
||||||
h = headers_parsed[h]
|
h = headers_parsed[h]
|
||||||
|
|
||||||
chip['flash']['base'] = h['defines']['all']['FLASH_BASE']
|
found = []
|
||||||
|
|
||||||
|
for each in memories_map['flash']:
|
||||||
|
if each + '_BASE' in h['defines']['all']:
|
||||||
|
if each == 'FLASH':
|
||||||
|
key = 'BANK_1'
|
||||||
|
elif each == 'FLASH_BANK1':
|
||||||
|
key = 'BANK_1'
|
||||||
|
elif each == 'FLASH_BANK2':
|
||||||
|
key = 'BANK_2'
|
||||||
|
else:
|
||||||
|
key = each
|
||||||
|
|
||||||
|
if key in found:
|
||||||
|
continue
|
||||||
|
|
||||||
|
found.append(key)
|
||||||
|
|
||||||
|
chip['flash']['regions'].append(
|
||||||
|
OrderedDict({
|
||||||
|
key: {
|
||||||
|
'base': HexInt(h['defines']['all'][each + '_BASE']),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
found = []
|
||||||
|
|
||||||
|
for each in memories_map['ram']:
|
||||||
|
if each + '_BASE' in h['defines']['all']:
|
||||||
|
if each == 'D1_AXISRAM':
|
||||||
|
key = 'SRAM'
|
||||||
|
elif each == 'SRAM1':
|
||||||
|
key = 'SRAM'
|
||||||
|
else:
|
||||||
|
key = each
|
||||||
|
|
||||||
|
if key in found:
|
||||||
|
continue
|
||||||
|
|
||||||
|
found.append(key)
|
||||||
|
|
||||||
|
chip['ram']['regions'].append(
|
||||||
|
OrderedDict({
|
||||||
|
key: {
|
||||||
|
'base': HexInt(h['defines']['all'][each + '_BASE'])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
if 'SRAM_BASE' in h['defines']['all']:
|
|
||||||
chip['ram']['base'] = h['defines']['all']['SRAM_BASE']
|
|
||||||
elif 'SRAM1_BASE' in h['defines']['all']:
|
|
||||||
chip['ram']['base'] = h['defines']['all']['SRAM1_BASE']
|
|
||||||
elif 'D1_AXISRAM_BASE' in h['defines']['all']:
|
|
||||||
chip['ram']['base'] = h['defines']['all']['D1_AXISRAM_BASE']
|
|
||||||
|
|
||||||
# print("Got", len(chip['cores']), "cores")
|
# print("Got", len(chip['cores']), "cores")
|
||||||
for core in chip['cores']:
|
for core in chip['cores']:
|
||||||
@ -672,7 +753,7 @@ def parse_chips():
|
|||||||
|
|
||||||
if not core_name in h['interrupts'] or not core_name in h['defines']:
|
if not core_name in h['interrupts'] or not core_name in h['defines']:
|
||||||
core_name = 'all'
|
core_name = 'all'
|
||||||
#print("Defining for core", core_name)
|
# print("Defining for core", core_name)
|
||||||
|
|
||||||
# Gather all interrupts and defines for this core
|
# Gather all interrupts and defines for this core
|
||||||
|
|
||||||
@ -702,7 +783,7 @@ def parse_chips():
|
|||||||
if pname in clocks[rcc]:
|
if pname in clocks[rcc]:
|
||||||
p['clock'] = clocks[rcc][pname]
|
p['clock'] = clocks[rcc][pname]
|
||||||
|
|
||||||
if block := match_peri(chip_name+':'+pname+':'+pkind):
|
if block := match_peri(chip_name + ':' + pname + ':' + pkind):
|
||||||
p['block'] = block
|
p['block'] = block
|
||||||
|
|
||||||
if pname in chip['pins']:
|
if pname in chip['pins']:
|
||||||
@ -725,7 +806,7 @@ def parse_chips():
|
|||||||
|
|
||||||
# Handle GPIO specially.
|
# Handle GPIO specially.
|
||||||
for p in range(20):
|
for p in range(20):
|
||||||
port = 'GPIO' + chr(ord('A')+p)
|
port = 'GPIO' + chr(ord('A') + p)
|
||||||
if addr := defines.get(port + '_BASE'):
|
if addr := defines.get(port + '_BASE'):
|
||||||
block = 'gpio_v2/GPIO'
|
block = 'gpio_v2/GPIO'
|
||||||
if chip['family'] == 'STM32F1':
|
if chip['family'] == 'STM32F1':
|
||||||
@ -743,7 +824,7 @@ def parse_chips():
|
|||||||
p = OrderedDict({
|
p = OrderedDict({
|
||||||
'address': addr,
|
'address': addr,
|
||||||
})
|
})
|
||||||
if block := match_peri(chip_name+':'+dma+':DMA'):
|
if block := match_peri(chip_name + ':' + dma + ':DMA'):
|
||||||
p['block'] = block
|
p['block'] = block
|
||||||
|
|
||||||
if chip_nvic in chip_interrupts:
|
if chip_nvic in chip_interrupts:
|
||||||
@ -755,13 +836,13 @@ def parse_chips():
|
|||||||
|
|
||||||
# DMAMUX is not in the cubedb XMLs
|
# DMAMUX is not in the cubedb XMLs
|
||||||
for dma in ('DMAMUX', 'DMAMUX1', "DMAMUX2"):
|
for dma in ('DMAMUX', 'DMAMUX1', "DMAMUX2"):
|
||||||
if addr := defines.get(dma+'_BASE'):
|
if addr := defines.get(dma + '_BASE'):
|
||||||
kind = 'DMAMUX:v1'
|
kind = 'DMAMUX:v1'
|
||||||
dbg_peri = OrderedDict({
|
dbg_peri = OrderedDict({
|
||||||
'address': addr,
|
'address': addr,
|
||||||
'kind': kind,
|
'kind': kind,
|
||||||
})
|
})
|
||||||
if block := match_peri(chip_name+':'+dma+':'+kind):
|
if block := match_peri(chip_name + ':' + dma + ':' + kind):
|
||||||
dbg_peri['block'] = block
|
dbg_peri['block'] = block
|
||||||
peris[dma] = dbg_peri
|
peris[dma] = dbg_peri
|
||||||
|
|
||||||
@ -852,7 +933,6 @@ def parse_chips():
|
|||||||
# Process peripheral - DMA channel associations
|
# Process peripheral - DMA channel associations
|
||||||
for pname, p in peris.items():
|
for pname, p in peris.items():
|
||||||
if (peri_chs := dma_channels[chip_dma]['peripherals'].get(pname)) is not None:
|
if (peri_chs := dma_channels[chip_dma]['peripherals'].get(pname)) is not None:
|
||||||
|
|
||||||
p['dma_channels'] = {
|
p['dma_channels'] = {
|
||||||
req: [
|
req: [
|
||||||
ch
|
ch
|
||||||
@ -866,7 +946,7 @@ def parse_chips():
|
|||||||
del chip['pins']
|
del chip['pins']
|
||||||
del chip['peripherals']
|
del chip['peripherals']
|
||||||
|
|
||||||
with open('data/chips/'+chip_name+'.yaml', 'w') as f:
|
with open('data/chips/' + chip_name + '.yaml', 'w') as f:
|
||||||
f.write(yaml.dump(chip, width=500))
|
f.write(yaml.dump(chip, width=500))
|
||||||
|
|
||||||
|
|
||||||
@ -874,7 +954,7 @@ af = {}
|
|||||||
|
|
||||||
|
|
||||||
def parse_gpio_af():
|
def parse_gpio_af():
|
||||||
#os.makedirs('data/gpio_af', exist_ok=True)
|
# os.makedirs('data/gpio_af', exist_ok=True)
|
||||||
for f in glob('sources/cubedb/mcu/IP/GPIO-*_gpio_v1_0_Modes.xml'):
|
for f in glob('sources/cubedb/mcu/IP/GPIO-*_gpio_v1_0_Modes.xml'):
|
||||||
if 'STM32F1' in f:
|
if 'STM32F1' in f:
|
||||||
continue
|
continue
|
||||||
@ -912,7 +992,7 @@ def parse_gpio_af():
|
|||||||
pins[pin_name] = afs
|
pins[pin_name] = afs
|
||||||
|
|
||||||
# with open('data/gpio_af/'+ff+'.yaml', 'w') as f:
|
# with open('data/gpio_af/'+ff+'.yaml', 'w') as f:
|
||||||
# f.write(yaml.dump(pins))
|
# f.write(yaml.dump(pins))
|
||||||
|
|
||||||
af[ff] = pins
|
af[ff] = pins
|
||||||
|
|
||||||
@ -932,7 +1012,7 @@ def parse_dma():
|
|||||||
ff = removeprefix(ff, 'BDMA-')
|
ff = removeprefix(ff, 'BDMA-')
|
||||||
ff = removesuffix(ff, '_Modes.xml')
|
ff = removesuffix(ff, '_Modes.xml')
|
||||||
|
|
||||||
r = xmltodict.parse(open(f, 'rb'), force_list={'Mode', 'RefMode'})
|
r = xmltodict.parse(open(f, 'rb'), force_list={'Mode', 'RefMode'})
|
||||||
|
|
||||||
chip_dma = {
|
chip_dma = {
|
||||||
'channels': {},
|
'channels': {},
|
||||||
@ -956,7 +1036,7 @@ def parse_dma():
|
|||||||
with open(mf, 'r') as yaml_file:
|
with open(mf, 'r') as yaml_file:
|
||||||
y = yaml.load(yaml_file, Loader=SafeLoader)
|
y = yaml.load(yaml_file, Loader=SafeLoader)
|
||||||
mf = removesuffix(mf, '.yaml')
|
mf = removesuffix(mf, '.yaml')
|
||||||
dmamux = mf[mf.index('_')+1:] # DMAMUX1 or DMAMUX2
|
dmamux = mf[mf.index('_') + 1:] # DMAMUX1 or DMAMUX2
|
||||||
|
|
||||||
for (request_name, request_num) in y.items():
|
for (request_name, request_num) in y.items():
|
||||||
parts = request_name.split('_')
|
parts = request_name.split('_')
|
||||||
@ -990,8 +1070,8 @@ def parse_dma():
|
|||||||
if low == 1:
|
if low == 1:
|
||||||
low -= 1
|
low -= 1
|
||||||
high -= 1
|
high -= 1
|
||||||
for i in range(low, high+1):
|
for i in range(low, high + 1):
|
||||||
chip_dma['channels'][n+'_CH'+str(i)] = OrderedDict({
|
chip_dma['channels'][n + '_CH' + str(i)] = OrderedDict({
|
||||||
'dma': n,
|
'dma': n,
|
||||||
'channel': i,
|
'channel': i,
|
||||||
'dmamux': dmamux,
|
'dmamux': dmamux,
|
||||||
@ -1114,7 +1194,7 @@ def match_peri_clock(rcc_block, peri_name):
|
|||||||
family_clocks = peripheral_to_clock[rcc_block]
|
family_clocks = peripheral_to_clock[rcc_block]
|
||||||
if peri_name in family_clocks:
|
if peri_name in family_clocks:
|
||||||
return family_clocks[peri_name]
|
return family_clocks[peri_name]
|
||||||
#print("found no clock for ", peri_name)
|
# print("found no clock for ", peri_name)
|
||||||
if peri_name.endswith("1"):
|
if peri_name.endswith("1"):
|
||||||
return match_peri_clock(rcc_block, removesuffix(peri_name, "1"))
|
return match_peri_clock(rcc_block, removesuffix(peri_name, "1"))
|
||||||
return None
|
return None
|
||||||
|
Loading…
x
Reference in New Issue
Block a user