From d966c5a4b557b733450ac537055980c255f6cb03 Mon Sep 17 00:00:00 2001 From: Mykola Hohsdze Date: Fri, 19 Nov 2021 06:09:08 +0200 Subject: [PATCH] add new code layout for list_cpu_features --- CMakeLists.txt | 5 +- src/utils/bump_allocator.h | 33 ++ src/utils/list_cpu_features.c | 389 +----------------- ...list_cpu_features__base_implementation.inl | 287 +++++++++++++ ...list_cpu_features_aarch64_implementation.c | 35 ++ .../list_cpu_features_arm_implementation.c | 36 ++ .../list_cpu_features_mips_implementation.c | 31 ++ .../list_cpu_features_ppc_implementation.c | 39 ++ .../list_cpu_features_x86_implementation.c | 42 ++ src/utils/node.h | 71 ++++ 10 files changed, 580 insertions(+), 388 deletions(-) create mode 100644 src/utils/bump_allocator.h create mode 100644 src/utils/list_cpu_features__base_implementation.inl create mode 100644 src/utils/list_cpu_features_aarch64_implementation.c create mode 100644 src/utils/list_cpu_features_arm_implementation.c create mode 100644 src/utils/list_cpu_features_mips_implementation.c create mode 100644 src/utils/list_cpu_features_ppc_implementation.c create mode 100644 src/utils/list_cpu_features_x86_implementation.c create mode 100644 src/utils/node.h diff --git a/CMakeLists.txt b/CMakeLists.txt index f5d5fc7d..c9d99375 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,7 +146,10 @@ add_library(CpuFeature::cpu_features ALIAS cpu_features) # program : list_cpu_features # -add_executable(list_cpu_features ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c) +file(GLOB LIST_CPU_FEATURES_SRCS CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features_*.c") +add_executable(list_cpu_features + ${PROJECT_SOURCE_DIR}/src/utils/list_cpu_features.c + ${LIST_CPU_FEATURES_SRCS}) target_link_libraries(list_cpu_features PRIVATE cpu_features) add_executable(CpuFeature::list_cpu_features ALIAS list_cpu_features) diff --git a/src/utils/bump_allocator.h b/src/utils/bump_allocator.h new file mode 100644 index 00000000..6d2cece6 --- /dev/null +++ b/src/utils/bump_allocator.h @@ -0,0 +1,33 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_BUMP_ALLOCATOR_H_ +#define CPU_FEATURES_BUMP_ALLOCATOR_H_ + +#include + +#define ALIGN 8 + +// We use a bump allocator to allocate strings and nodes of the tree, +// Memory is not intended to be reclaimed. +typedef struct { + char* ptr; + size_t size; +} BumpAllocator; + +void assertAligned(); +void BA_Align(); +void* BA_Bump(size_t size); + +#endif // CPU_FEATURES_BUMP_ALLOCATOR_H_ diff --git a/src/utils/list_cpu_features.c b/src/utils/list_cpu_features.c index 4389f202..4e3292f7 100644 --- a/src/utils/list_cpu_features.c +++ b/src/utils/list_cpu_features.c @@ -15,300 +15,8 @@ // This program dumps current host data to the standard output. // Output can be text or json if the `--json` flag is passed. -#include -#include -#include -#include -#include -#include -#include - -#include "cpu_features_macros.h" - -#if defined(CPU_FEATURES_ARCH_X86) -#include "cpuinfo_x86.h" -#elif defined(CPU_FEATURES_ARCH_ARM) -#include "cpuinfo_arm.h" -#elif defined(CPU_FEATURES_ARCH_AARCH64) -#include "cpuinfo_aarch64.h" -#elif defined(CPU_FEATURES_ARCH_MIPS) -#include "cpuinfo_mips.h" -#elif defined(CPU_FEATURES_ARCH_PPC) -#include "cpuinfo_ppc.h" -#endif - -// Design principles -// ----------------- -// We build a tree structure containing all the data to be displayed. -// Then depending on the output type (text or json) we walk the tree and display -// the data accordingly. - -// We use a bump allocator to allocate strings and nodes of the tree, -// Memory is not intended to be reclaimed. -typedef struct { - char* ptr; - size_t size; -} BumpAllocator; - -char gGlobalBuffer[64 * 1024]; -BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer, - .size = sizeof(gGlobalBuffer)}; - -static void internal_error() { - fputs("internal error\n", stderr); - exit(EXIT_FAILURE); -} - -#define ALIGN 8 - -static void assertAligned() { - if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error(); -} - -static void BA_Align() { - while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) { - --gBumpAllocator.size; - ++gBumpAllocator.ptr; - } - assertAligned(); -} - -// Update the available memory left in the BumpAllocator. -static void* BA_Bump(size_t size) { - assertAligned(); - // Align size to next 8B boundary. - size = (size + ALIGN - 1) / ALIGN * ALIGN; - if (gBumpAllocator.size < size) internal_error(); - void* ptr = gBumpAllocator.ptr; - gBumpAllocator.size -= size; - gBumpAllocator.ptr += size; - return ptr; -} - -// The type of the nodes in the tree. -typedef enum { - NT_INVALID, - NT_INT, - NT_MAP, - NT_MAP_ENTRY, - NT_ARRAY, - NT_ARRAY_ELEMENT, - NT_STRING, -} NodeType; - -// The node in the tree. -typedef struct Node { - NodeType type; - unsigned integer; - const char* string; - struct Node* value; - struct Node* next; -} Node; - -// Creates an initialized Node. -static Node* BA_CreateNode(NodeType type) { - Node* tv = (Node*)BA_Bump(sizeof(Node)); - assert(tv); - *tv = (Node){.type = type}; - return tv; -} - -// Adds an integer node. -static Node* CreateInt(int value) { - Node* tv = BA_CreateNode(NT_INT); - tv->integer = value; - return tv; -} - -// Adds a string node. -// `value` must outlive the tree. -static Node* CreateConstantString(const char* value) { - Node* tv = BA_CreateNode(NT_STRING); - tv->string = value; - return tv; -} - -// Adds a map node. -static Node* CreateMap() { return BA_CreateNode(NT_MAP); } - -// Adds an array node. -static Node* CreateArray() { return BA_CreateNode(NT_ARRAY); } - -// Adds a formatted string node. -static Node* CreatePrintfString(const char* format, ...) { - va_list arglist; - va_start(arglist, format); - char* const ptr = gBumpAllocator.ptr; - const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist); - va_end(arglist); - if (written < 0 || written >= (int)gBumpAllocator.size) internal_error(); - return CreateConstantString((char*)BA_Bump(written)); -} - -// Adds a string node. -static Node* CreateString(const char* value) { - return CreatePrintfString("%s", value); -} - -// Adds a map entry node. -static void AddMapEntry(Node* map, const char* key, Node* value) { - assert(map && map->type == NT_MAP); - Node* current = map; - while (current->next) current = current->next; - current->next = (Node*)BA_Bump(sizeof(Node)); - *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value}; -} - -// Adds an array element node. -static void AddArrayElement(Node* array, Node* value) { - assert(array && array->type == NT_ARRAY); - Node* current = array; - while (current->next) current = current->next; - current->next = (Node*)BA_Bump(sizeof(Node)); - *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value}; -} - -static int cmp(const void* p1, const void* p2) { - return strcmp(*(const char* const*)p1, *(const char* const*)p2); -} - -#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \ - static void AddFlags(Node* map, const FeatureType* features) { \ - size_t i; \ - const char* ptrs[LastEnum] = {0}; \ - size_t count = 0; \ - for (i = 0; i < LastEnum; ++i) { \ - if (HasFeature(features, i)) { \ - ptrs[count] = FeatureName(i); \ - ++count; \ - } \ - } \ - qsort((void*)ptrs, count, sizeof(char*), cmp); \ - Node* const array = CreateArray(); \ - for (i = 0; i < count; ++i) \ - AddArrayElement(array, CreateConstantString(ptrs[i])); \ - AddMapEntry(map, "flags", array); \ - } - -#if defined(CPU_FEATURES_ARCH_X86) -DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features, - X86_LAST_) -#elif defined(CPU_FEATURES_ARCH_ARM) -DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures, - ARM_LAST_) -#elif defined(CPU_FEATURES_ARCH_AARCH64) -DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName, - Aarch64Features, AARCH64_LAST_) -#elif defined(CPU_FEATURES_ARCH_MIPS) -DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName, - MipsFeatures, MIPS_LAST_) -#elif defined(CPU_FEATURES_ARCH_PPC) -DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures, - PPC_LAST_) -#endif - -// Prints a json string with characters escaping. -static void printJsonString(const char* str) { - putchar('"'); - for (; str && *str; ++str) { - switch (*str) { - case '\"': - case '\\': - case '/': - case '\b': - case '\f': - case '\n': - case '\r': - case '\t': - putchar('\\'); - } - putchar(*str); - } - putchar('"'); -} - -// Walks a Node and print it as json. -static void printJson(const Node* current) { - assert(current); - switch (current->type) { - case NT_INVALID: - break; - case NT_INT: - printf("%d", current->integer); - break; - case NT_STRING: - printJsonString(current->string); - break; - case NT_ARRAY: - putchar('['); - if (current->next) printJson(current->next); - putchar(']'); - break; - case NT_MAP: - putchar('{'); - if (current->next) printJson(current->next); - putchar('}'); - break; - case NT_MAP_ENTRY: - printf("\"%s\":", current->string); - printJson(current->value); - if (current->next) { - putchar(','); - printJson(current->next); - } - break; - case NT_ARRAY_ELEMENT: - printJson(current->value); - if (current->next) { - putchar(','); - printJson(current->next); - } - break; - } -} - -// Walks a Node and print it as text. -static void printTextField(const Node* current) { - switch (current->type) { - case NT_INVALID: - break; - case NT_INT: - printf("%3d (0x%02X)", current->integer, current->integer); - break; - case NT_STRING: - fputs(current->string, stdout); - break; - case NT_ARRAY: - if (current->next) printTextField(current->next); - break; - case NT_MAP: - if (current->next) { - printf("{"); - printJson(current->next); - printf("}"); - } - break; - case NT_MAP_ENTRY: - printf("%-15s : ", current->string); - printTextField(current->value); - if (current->next) { - putchar('\n'); - printTextField(current->next); - } - break; - case NT_ARRAY_ELEMENT: - printTextField(current->value); - if (current->next) { - putchar(','); - printTextField(current->next); - } - break; - } -} - -static void printTextRoot(const Node* current) { - if (current->type == NT_MAP && current->next) printTextField(current->next); -} +#include "bump_allocator.h" +#include "node.h" static void showUsage(const char* name) { printf( @@ -321,99 +29,6 @@ static void showUsage(const char* name) { name); } -static Node* GetCacheTypeString(CacheType cache_type) { - switch (cache_type) { - case CPU_FEATURE_CACHE_NULL: - return CreateConstantString("null"); - case CPU_FEATURE_CACHE_DATA: - return CreateConstantString("data"); - case CPU_FEATURE_CACHE_INSTRUCTION: - return CreateConstantString("instruction"); - case CPU_FEATURE_CACHE_UNIFIED: - return CreateConstantString("unified"); - case CPU_FEATURE_CACHE_TLB: - return CreateConstantString("tlb"); - case CPU_FEATURE_CACHE_DTLB: - return CreateConstantString("dtlb"); - case CPU_FEATURE_CACHE_STLB: - return CreateConstantString("stlb"); - case CPU_FEATURE_CACHE_PREFETCH: - return CreateConstantString("prefetch"); - } - UNREACHABLE(); -} - -static void AddCacheInfo(Node* root, const CacheInfo* cache_info) { - Node* array = CreateArray(); - for (int i = 0; i < cache_info->size; ++i) { - CacheLevelInfo info = cache_info->levels[i]; - Node* map = CreateMap(); - AddMapEntry(map, "level", CreateInt(info.level)); - AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type)); - AddMapEntry(map, "cache_size", CreateInt(info.cache_size)); - AddMapEntry(map, "ways", CreateInt(info.ways)); - AddMapEntry(map, "line_size", CreateInt(info.line_size)); - AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries)); - AddMapEntry(map, "partitioning", CreateInt(info.partitioning)); - AddArrayElement(array, map); - } - AddMapEntry(root, "cache_info", array); -} - -static Node* CreateTree() { - Node* root = CreateMap(); -#if defined(CPU_FEATURES_ARCH_X86) - char brand_string[49]; - const X86Info info = GetX86Info(); - const CacheInfo cache_info = GetX86CacheInfo(); - FillX86BrandString(brand_string); - AddMapEntry(root, "arch", CreateString("x86")); - AddMapEntry(root, "brand", CreateString(brand_string)); - AddMapEntry(root, "family", CreateInt(info.family)); - AddMapEntry(root, "model", CreateInt(info.model)); - AddMapEntry(root, "stepping", CreateInt(info.stepping)); - AddMapEntry(root, "uarch", - CreateString( - GetX86MicroarchitectureName(GetX86Microarchitecture(&info)))); - AddFlags(root, &info.features); - AddCacheInfo(root, &cache_info); -#elif defined(CPU_FEATURES_ARCH_ARM) - const ArmInfo info = GetArmInfo(); - AddMapEntry(root, "arch", CreateString("ARM")); - AddMapEntry(root, "implementer", CreateInt(info.implementer)); - AddMapEntry(root, "architecture", CreateInt(info.architecture)); - AddMapEntry(root, "variant", CreateInt(info.variant)); - AddMapEntry(root, "part", CreateInt(info.part)); - AddMapEntry(root, "revision", CreateInt(info.revision)); - AddFlags(root, &info.features); -#elif defined(CPU_FEATURES_ARCH_AARCH64) - const Aarch64Info info = GetAarch64Info(); - AddMapEntry(root, "arch", CreateString("aarch64")); - AddMapEntry(root, "implementer", CreateInt(info.implementer)); - AddMapEntry(root, "variant", CreateInt(info.variant)); - AddMapEntry(root, "part", CreateInt(info.part)); - AddMapEntry(root, "revision", CreateInt(info.revision)); - AddFlags(root, &info.features); -#elif defined(CPU_FEATURES_ARCH_MIPS) - const MipsInfo info = GetMipsInfo(); - AddMapEntry(root, "arch", CreateString("mips")); - AddFlags(root, &info.features); -#elif defined(CPU_FEATURES_ARCH_PPC) - const PPCInfo info = GetPPCInfo(); - const PPCPlatformStrings strings = GetPPCPlatformStrings(); - AddMapEntry(root, "arch", CreateString("ppc")); - AddMapEntry(root, "platform", CreateString(strings.platform)); - AddMapEntry(root, "model", CreateString(strings.model)); - AddMapEntry(root, "machine", CreateString(strings.machine)); - AddMapEntry(root, "cpu", CreateString(strings.cpu)); - AddMapEntry(root, "instruction", CreateString(strings.type.platform)); - AddMapEntry(root, "microarchitecture", - CreateString(strings.type.base_platform)); - AddFlags(root, &info.features); -#endif - return root; -} - int main(int argc, char** argv) { BA_Align(); const Node* const root = CreateTree(); diff --git a/src/utils/list_cpu_features__base_implementation.inl b/src/utils/list_cpu_features__base_implementation.inl new file mode 100644 index 00000000..86a23eed --- /dev/null +++ b/src/utils/list_cpu_features__base_implementation.inl @@ -0,0 +1,287 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// Design principles +// ----------------- +// We build a tree structure containing all the data to be displayed. +// Then depending on the output type (text or json) we walk the tree and display +// the data accordingly. + +#include +#include +#include +#include +#include +#include +#include + +#include "bump_allocator.h" +#include "node.h" + +static void internal_error() { + fputs("internal error\n", stderr); + exit(EXIT_FAILURE); +} + +char gGlobalBuffer[64 * 1024]; +BumpAllocator gBumpAllocator = {.ptr = gGlobalBuffer, + .size = sizeof(gGlobalBuffer)}; + +void assertAligned() { + if ((uintptr_t)(gBumpAllocator.ptr) % ALIGN) internal_error(); +} + +void BA_Align() { + while (gBumpAllocator.size && (uintptr_t)(gBumpAllocator.ptr) % ALIGN) { + --gBumpAllocator.size; + ++gBumpAllocator.ptr; + } + assertAligned(); +} + +// Update the available memory left in the BumpAllocator. +void* BA_Bump(size_t size) { + assertAligned(); + // Align size to next 8B boundary. + size = (size + ALIGN - 1) / ALIGN * ALIGN; + if (gBumpAllocator.size < size) internal_error(); + void* ptr = gBumpAllocator.ptr; + gBumpAllocator.size -= size; + gBumpAllocator.ptr += size; + return ptr; +} + +// Creates an initialized Node. +Node* BA_CreateNode(NodeType type) { + Node* tv = (Node*)BA_Bump(sizeof(Node)); + assert(tv); + *tv = (Node){.type = type}; + return tv; +} + +// Adds an integer node. +Node* CreateInt(int value) { + Node* tv = BA_CreateNode(NT_INT); + tv->integer = value; + return tv; +} + +// Adds a string node. +// `value` must outlive the tree. +Node* CreateConstantString(const char* value) { + Node* tv = BA_CreateNode(NT_STRING); + tv->string = value; + return tv; +} + +// Adds a map node. +Node* CreateMap() { return BA_CreateNode(NT_MAP); } + +// Adds an array node. +Node* CreateArray() { return BA_CreateNode(NT_ARRAY); } + +// Adds a formatted string node. +Node* CreatePrintfString(const char* format, ...) { + va_list arglist; + va_start(arglist, format); + char* const ptr = gBumpAllocator.ptr; + const int written = vsnprintf(ptr, gBumpAllocator.size, format, arglist); + va_end(arglist); + if (written < 0 || written >= (int)gBumpAllocator.size) internal_error(); + return CreateConstantString((char*)BA_Bump(written)); +} + +// Adds a string node. +Node* CreateString(const char* value) { + return CreatePrintfString("%s", value); +} + +// Adds a map entry node. +void AddMapEntry(Node* map, const char* key, Node* value) { + assert(map && map->type == NT_MAP); + Node* current = map; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_MAP_ENTRY, .string = key, .value = value}; +} + +// Adds an array element node. +void AddArrayElement(Node* array, Node* value) { + assert(array && array->type == NT_ARRAY); + Node* current = array; + while (current->next) current = current->next; + current->next = (Node*)BA_Bump(sizeof(Node)); + *current->next = (Node){.type = NT_ARRAY_ELEMENT, .value = value}; +} + +static int cmp(const void* p1, const void* p2) { + return strcmp(*(const char* const*)p1, *(const char* const*)p2); +} + +#define DEFINE_ADD_FLAGS(HasFeature, FeatureName, FeatureType, LastEnum) \ + static void AddFlags(Node* map, const FeatureType* features) { \ + size_t i; \ + const char* ptrs[LastEnum] = {0}; \ + size_t count = 0; \ + for (i = 0; i < LastEnum; ++i) { \ + if (HasFeature(features, i)) { \ + ptrs[count] = FeatureName(i); \ + ++count; \ + } \ + } \ + qsort((void*)ptrs, count, sizeof(char*), cmp); \ + Node* const array = CreateArray(); \ + for (i = 0; i < count; ++i) \ + AddArrayElement(array, CreateConstantString(ptrs[i])); \ + AddMapEntry(map, "flags", array); \ + } + +Node* GetCacheTypeString(CacheType cache_type) { + switch (cache_type) { + case CPU_FEATURE_CACHE_NULL: + return CreateConstantString("null"); + case CPU_FEATURE_CACHE_DATA: + return CreateConstantString("data"); + case CPU_FEATURE_CACHE_INSTRUCTION: + return CreateConstantString("instruction"); + case CPU_FEATURE_CACHE_UNIFIED: + return CreateConstantString("unified"); + case CPU_FEATURE_CACHE_TLB: + return CreateConstantString("tlb"); + case CPU_FEATURE_CACHE_DTLB: + return CreateConstantString("dtlb"); + case CPU_FEATURE_CACHE_STLB: + return CreateConstantString("stlb"); + case CPU_FEATURE_CACHE_PREFETCH: + return CreateConstantString("prefetch"); + } + UNREACHABLE(); +} + +void AddCacheInfo(Node* root, const CacheInfo* cache_info) { + Node* array = CreateArray(); + for (int i = 0; i < cache_info->size; ++i) { + CacheLevelInfo info = cache_info->levels[i]; + Node* map = CreateMap(); + AddMapEntry(map, "level", CreateInt(info.level)); + AddMapEntry(map, "cache_type", GetCacheTypeString(info.cache_type)); + AddMapEntry(map, "cache_size", CreateInt(info.cache_size)); + AddMapEntry(map, "ways", CreateInt(info.ways)); + AddMapEntry(map, "line_size", CreateInt(info.line_size)); + AddMapEntry(map, "tlb_entries", CreateInt(info.tlb_entries)); + AddMapEntry(map, "partitioning", CreateInt(info.partitioning)); + AddArrayElement(array, map); + } + AddMapEntry(root, "cache_info", array); +} + +void printJsonString(const char* str) { + putchar('"'); + for (; str && *str; ++str) { + switch (*str) { + case '\"': + case '\\': + case '/': + case '\b': + case '\f': + case '\n': + case '\r': + case '\t': + putchar('\\'); + } + putchar(*str); + } + putchar('"'); +} + +void printJson(const Node* current) { + assert(current); + switch (current->type) { + case NT_INVALID: + break; + case NT_INT: + printf("%d", current->integer); + break; + case NT_STRING: + printJsonString(current->string); + break; + case NT_ARRAY: + putchar('['); + if (current->next) printJson(current->next); + putchar(']'); + break; + case NT_MAP: + putchar('{'); + if (current->next) printJson(current->next); + putchar('}'); + break; + case NT_MAP_ENTRY: + printf("\"%s\":", current->string); + printJson(current->value); + if (current->next) { + putchar(','); + printJson(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printJson(current->value); + if (current->next) { + putchar(','); + printJson(current->next); + } + break; + } +} + +void printTextField(const Node* current) { + switch (current->type) { + case NT_INVALID: + break; + case NT_INT: + printf("%3d (0x%02X)", current->integer, current->integer); + break; + case NT_STRING: + fputs(current->string, stdout); + break; + case NT_ARRAY: + if (current->next) printTextField(current->next); + break; + case NT_MAP: + if (current->next) { + printf("{"); + printJson(current->next); + printf("}"); + } + break; + case NT_MAP_ENTRY: + printf("%-15s : ", current->string); + printTextField(current->value); + if (current->next) { + putchar('\n'); + printTextField(current->next); + } + break; + case NT_ARRAY_ELEMENT: + printTextField(current->value); + if (current->next) { + putchar(','); + printTextField(current->next); + } + break; + } +} + +void printTextRoot(const Node* current) { + if (current->type == NT_MAP && current->next) printTextField(current->next); +} diff --git a/src/utils/list_cpu_features_aarch64_implementation.c b/src/utils/list_cpu_features_aarch64_implementation.c new file mode 100644 index 00000000..2c1d4e01 --- /dev/null +++ b/src/utils/list_cpu_features_aarch64_implementation.c @@ -0,0 +1,35 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_AARCH64 +#include "cpuinfo_aarch64.h" +#include "list_cpu_features__base_implementation.inl" + +DEFINE_ADD_FLAGS(GetAarch64FeaturesEnumValue, GetAarch64FeaturesEnumName, + Aarch64Features, AARCH64_LAST_) + +Node* CreateTree() { + Node* root = CreateMap(); + const Aarch64Info info = GetAarch64Info(); + AddMapEntry(root, "arch", CreateString("aarch64")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); + return root; +} +#endif // CPU_FEATURES_ARCH_AARCH64 diff --git a/src/utils/list_cpu_features_arm_implementation.c b/src/utils/list_cpu_features_arm_implementation.c new file mode 100644 index 00000000..1316308a --- /dev/null +++ b/src/utils/list_cpu_features_arm_implementation.c @@ -0,0 +1,36 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_ARM +#include "cpuinfo_arm.h" +#include "list_cpu_features__base_implementation.inl" + +DEFINE_ADD_FLAGS(GetArmFeaturesEnumValue, GetArmFeaturesEnumName, ArmFeatures, + ARM_LAST_) + +Node* CreateTree() { + Node* root = CreateMap(); + const ArmInfo info = GetArmInfo(); + AddMapEntry(root, "arch", CreateString("ARM")); + AddMapEntry(root, "implementer", CreateInt(info.implementer)); + AddMapEntry(root, "architecture", CreateInt(info.architecture)); + AddMapEntry(root, "variant", CreateInt(info.variant)); + AddMapEntry(root, "part", CreateInt(info.part)); + AddMapEntry(root, "revision", CreateInt(info.revision)); + AddFlags(root, &info.features); + return root; +} +#endif // CPU_FEATURES_ARCH_ARM diff --git a/src/utils/list_cpu_features_mips_implementation.c b/src/utils/list_cpu_features_mips_implementation.c new file mode 100644 index 00000000..61b735c0 --- /dev/null +++ b/src/utils/list_cpu_features_mips_implementation.c @@ -0,0 +1,31 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_MIPS +#include "cpuinfo_mips.h" +#include "list_cpu_features__base_implementation.inl" + +DEFINE_ADD_FLAGS(GetMipsFeaturesEnumValue, GetMipsFeaturesEnumName, + MipsFeatures, MIPS_LAST_) + +Node* CreateTree() { + Node* root = CreateMap(); + const MipsInfo info = GetMipsInfo(); + AddMapEntry(root, "arch", CreateString("mips")); + AddFlags(root, &info.features); + return root; +} +#endif // CPU_FEATURES_ARCH_MIPS diff --git a/src/utils/list_cpu_features_ppc_implementation.c b/src/utils/list_cpu_features_ppc_implementation.c new file mode 100644 index 00000000..7b69eb2a --- /dev/null +++ b/src/utils/list_cpu_features_ppc_implementation.c @@ -0,0 +1,39 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_PPC +#include "cpuinfo_ppc.h" +#include "list_cpu_features__base_implementation.inl" + +DEFINE_ADD_FLAGS(GetPPCFeaturesEnumValue, GetPPCFeaturesEnumName, PPCFeatures, + PPC_LAST_) + +Node* CreateTree() { + Node* root = CreateMap(); + const PPCInfo info = GetPPCInfo(); + const PPCPlatformStrings strings = GetPPCPlatformStrings(); + AddMapEntry(root, "arch", CreateString("ppc")); + AddMapEntry(root, "platform", CreateString(strings.platform)); + AddMapEntry(root, "model", CreateString(strings.model)); + AddMapEntry(root, "machine", CreateString(strings.machine)); + AddMapEntry(root, "cpu", CreateString(strings.cpu)); + AddMapEntry(root, "instruction", CreateString(strings.type.platform)); + AddMapEntry(root, "microarchitecture", + CreateString(strings.type.base_platform)); + AddFlags(root, &info.features); + return root; +} +#endif // CPU_FEATURES_ARCH_PPC diff --git a/src/utils/list_cpu_features_x86_implementation.c b/src/utils/list_cpu_features_x86_implementation.c new file mode 100644 index 00000000..3ee54e30 --- /dev/null +++ b/src/utils/list_cpu_features_x86_implementation.c @@ -0,0 +1,42 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "cpu_features_macros.h" + +#ifdef CPU_FEATURES_ARCH_X86 +#include "cpuinfo_x86.h" +#include "list_cpu_features__base_implementation.inl" + +DEFINE_ADD_FLAGS(GetX86FeaturesEnumValue, GetX86FeaturesEnumName, X86Features, + X86_LAST_) + +Node* CreateTree() { + Node* root = CreateMap(); + char brand_string[49]; + const X86Info info = GetX86Info(); + const CacheInfo cache_info = GetX86CacheInfo(); + FillX86BrandString(brand_string); + AddMapEntry(root, "arch", CreateString("x86")); + AddMapEntry(root, "brand", CreateString(brand_string)); + AddMapEntry(root, "family", CreateInt(info.family)); + AddMapEntry(root, "model", CreateInt(info.model)); + AddMapEntry(root, "stepping", CreateInt(info.stepping)); + AddMapEntry(root, "uarch", + CreateString( + GetX86MicroarchitectureName(GetX86Microarchitecture(&info)))); + AddFlags(root, &info.features); + AddCacheInfo(root, &cache_info); + return root; +} +#endif // CPU_FEATURES_ARCH_X86 \ No newline at end of file diff --git a/src/utils/node.h b/src/utils/node.h new file mode 100644 index 00000000..0fb3743b --- /dev/null +++ b/src/utils/node.h @@ -0,0 +1,71 @@ +// Copyright 2017 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef CPU_FEATURES_NODE_H_ +#define CPU_FEATURES_NODE_H_ + +#include +#include +#include +#include +#include +#include +#include +#include + +// The type of the nodes in the tree. +typedef enum { + NT_INVALID, + NT_INT, + NT_MAP, + NT_MAP_ENTRY, + NT_ARRAY, + NT_ARRAY_ELEMENT, + NT_STRING, +} NodeType; + +// The node in the tree. +typedef struct Node { + NodeType type; + unsigned integer; + const char* string; + struct Node* value; + struct Node* next; +} Node; + +Node* CreateTree(); +Node* CreateMap(); +Node* BA_CreateNode(NodeType type); +Node* CreateArray(); +Node* CreateInt(int value); +Node* CreatePrintfString(const char* format, ...); +Node* CreateString(const char* value); +Node* CreateConstantString(const char* value); +Node* GetCacheTypeString(CacheType cache_type); +void AddMapEntry(Node* map, const char* key, Node* value); +void AddCacheInfo(Node* root, const CacheInfo* cache_info); +void AddArrayElement(Node* array, Node* value); + +// Prints a json string with characters escaping. +void printJsonString(const char* str); + +// Walks a Node and print it as json. +void printJson(const Node* current); + +// Walks a Node and print it as text. +void printTextField(const Node* current); + +void printTextRoot(const Node* current); + +#endif // CPU_FEATURES_NODE_H_