Parse our memory location bases and name them well-ish.

This commit is contained in:
Bob McWhirter 2021-07-29 15:44:44 -04:00
parent 2d38aad861
commit 2e7af6b842

172
parse.py
View File

@ -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