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);
        }
Esempio n. 3
0
        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());
        }
Esempio n. 4
0
            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;
                    }
                }
            }