bool TryLocateFieldForSubregisterMacroName(ParsedStructure str, string[] nameComponents, int skippedComponents, out MatchedStructureField[] result) { //Pass 1. Try locating a structure field with the exact name of the macro (e.g. MODER for GPIO_MODER_xxx). //We also iterate multi-component names for rare special cases (e.g. UCPD_TX_ORDSET_TXORDSET would split into UCPD->TX_ORDSET, not UCPD->TX) if (RunSingleSubregisterLocatingPass(str, nameComponents, skippedComponents, SubregisterMatchingFlags.None, out result)) { return(true); } //Pass 2. Try discarding instance numbers from the field name. if (RunSingleSubregisterLocatingPass(str, nameComponents, skippedComponents, SubregisterMatchingFlags.StripIndicies | SubregisterMatchingFlags.ExpandIndicies, out result)) { return(true); } //Pass 3. Try discarding 'x' and 'Sx' strings. E.g. 'DMA_SxCR_MBURST' becomes 'DMA_CR_MBURST' and will get matched to DMA->CR. if (RunSingleSubregisterLocatingPass(str, nameComponents, skippedComponents, SubregisterMatchingFlags.ReplaceXes, out result)) { return(true); } //Pass 4. Apply hardcoded name transformations that cannot be realistically guessed (e.g. OSPEEDR -> OSPEEDER). We should keep the amount of them to a minimum. if (RunSingleSubregisterLocatingPass(str, nameComponents, skippedComponents, SubregisterMatchingFlags.InvokeCustomRules, out result)) { return(true); } //Pass 5. Fix registers that don't have an underscore in the field names. APBx_FZ => APBxFZ if (RunSingleSubregisterLocatingPass(str, nameComponents, skippedComponents, SubregisterMatchingFlags.MergeAdjacentNameComponents, out result)) { return(true); } return(false); }
bool RunSingleSubregisterLocatingPass(ParsedStructure str, string[] nameComponents, int skippedComponents, SubregisterMatchingFlags flags, out MatchedStructureField[] result) { for (int i = 1; i < (nameComponents.Length - skippedComponents); i++) { string[] nameForMatching = nameComponents.Skip(skippedComponents).Take(i).ToArray(); if (flags.HasFlag(SubregisterMatchingFlags.ReplaceXes)) { nameForMatching = nameForMatching.Select(s => s.Replace("Sx", "").Replace("Lx", "").Replace("x", "")).ToArray(); } int?discardedIndex = null; if (flags.HasFlag(SubregisterMatchingFlags.StripIndicies)) { string lastComponent = nameForMatching.Last(); if (lastComponent.EndsWith("L") || lastComponent.EndsWith("H")) //E.g. GPIO->AFRH/AFRL { discardedIndex = lastComponent.EndsWith("L") ? 0 : 1; lastComponent = lastComponent.Substring(0, lastComponent.Length - 1); } else { int j = lastComponent.Length; while (j > 0 && char.IsNumber(lastComponent[j - 1])) { j--; } if (j > 0 && j < lastComponent.Length) { discardedIndex = int.Parse(lastComponent.Substring(j)) - 1; lastComponent = lastComponent.Substring(0, j); } } nameForMatching[nameForMatching.Length - 1] = lastComponent; } if (flags.HasFlag(SubregisterMatchingFlags.InvokeCustomRules)) { ManualPeripheralRegisterRules.ApplyKnownNameTransformations(ref nameForMatching); } if (flags.HasFlag(SubregisterMatchingFlags.MergeAdjacentNameComponents)) { nameForMatching = new[] { string.Join("", nameForMatching) } } ; if (str.EntriesByName.TryGetValue(string.Join("_", nameForMatching), out var entry)) { result = new MatchedStructureField[] { new MatchedStructureField { SubregisterName = string.Join("_", nameComponents.Skip(skippedComponents + 1)), Entry = entry, StrippedIndex = discardedIndex, } }; return(true); } if (flags.HasFlag(SubregisterMatchingFlags.ExpandIndicies) && str.EntriesByNameWithoutTrailingIndex.TryGetValue(string.Join("_", nameForMatching), out var entries)) { result = entries.Select(f => new MatchedStructureField { SubregisterName = string.Join("_", nameComponents.Skip(skippedComponents + 1)), Entry = f, StrippedIndex = discardedIndex, } ).ToArray(); return(true); } } result = null; return(false); }
private static DiscoveredPeripheral.Register[] TranslateStructureFieldsToRegisters(ParsedStructure obj, ParsedHeaderFile parsedFile) { ConstructedRegisterList lst = new ConstructedRegisterList(); RegisterTranslationContext ctx = new RegisterTranslationContext(); lst.TranslateStructureFieldsToRegistersRecursively(obj, parsedFile, ref ctx, ""); return(lst.Complete()); }
public void TranslateStructureFieldsToRegistersRecursively(ParsedStructure obj, ParsedHeaderFile parsedFile, ref RegisterTranslationContext ctx, string prefix) { foreach (var field in obj.Entries) { var type = field.Type .Where(t => t.Type == CppTokenizer.TokenType.Identifier) .Select(t => t.Value) .Where(t => t != "__IO" && t != "__I" && t != "__IM" && t != "__O" && t != "const") .ToArray(); bool isReadOnly = field.Type.Count(t => t.Value == "__I" || t.Value == "const") > 0; if (type.Length > 1) { throw new Exception("Could not reduce register type to a single token: " + string.Join("", type)); } int size; switch (type[0]) { case "int32_t": case "uint32_t": size = 4; break; case "int16_t": case "uint16_t": size = 2; break; case "int8_t": case "uint8_t": size = 1; break; case "RSSLIB_S_CloseExitHDP_TypeDef": //Actually a function pointer size = 4; break; default: for (int i = 0; i < field.ArraySize; i++) { string extraPrefix; if (field.ArraySize == 1) { extraPrefix = $"{field.Name}."; } else { extraPrefix = $"{field.Name}[{i}]."; } TranslateStructureFieldsToRegistersRecursively(parsedFile.Structures[type[0]], parsedFile, ref ctx, prefix + extraPrefix); } continue; } if ((ctx.CurrentOffset % size) != 0) { ctx.CurrentOffset += (size - (ctx.CurrentOffset % size)); } for (int i = 0; i < field.ArraySize; i++) { string nameSuffix = ""; if (field.ArraySize > 1) { nameSuffix = $"[{i}]"; } if (!field.Name.StartsWith("RESERVED", StringComparison.InvariantCultureIgnoreCase)) { _Registers.Add(new DiscoveredPeripheral.Register { Offset = (uint)ctx.CurrentOffset, Name = prefix + field.Name + nameSuffix, SizeInBytes = size, IsReadOnly = isReadOnly, OriginalField = field, ZeroBasedIndex = i, }); } ctx.CurrentOffset += size; } } }