// Copyright (c) The M1CPU Authors
// SPDX-License-Identifier: MPL-2.0

//go:build darwin && arm64 && cgo

package m1cpu

// #cgo LDFLAGS: -framework CoreFoundation -framework IOKit
// #include <AvailabilityMacros.h>
// #include <CoreFoundation/CoreFoundation.h>
// #include <IOKit/IOKitLib.h>
// #include <sys/sysctl.h>
//
// #if !defined(MAC_OS_VERSION_12_0) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_VERSION_12_0
// #define kIOMainPortDefault kIOMasterPortDefault
// #endif
//
// #define BUFSIZE 512
//
// UInt64 global_pCoreClock;
// UInt64 global_eCoreClock;
// int global_pCoreCount;
// int global_eCoreCount;
// int global_pCoreL1InstCacheSize;
// int global_eCoreL1InstCacheSize;
// int global_pCoreL1DataCacheSize;
// int global_eCoreL1DataCacheSize;
// int global_pCoreL2CacheSize;
// int global_eCoreL2CacheSize;
// char global_brand[32];
//
// UInt64 getFrequency(CFTypeRef typeRef) {
//  if (typeRef == NULL) {
//    return 0;
//  }
//  CFDataRef cfData = typeRef;
//
//  CFIndex size = CFDataGetLength(cfData);
//  UInt8 buf[size];
//  CFDataGetBytes(cfData, CFRangeMake(0, size), buf);
//
//  UInt8 b1 = buf[size-5];
//  UInt8 b2 = buf[size-6];
//  UInt8 b3 = buf[size-7];
//  UInt8 b4 = buf[size-8];
//
//  UInt64 pCoreHz = 0x00000000FFFFFFFF & ((b1<<24) | (b2 << 16) | (b3 << 8) | (b4));
//  return pCoreHz;
// }
//
// int sysctl_int(const char * name) {
//  int value = -1;
//  size_t size = 8;
//  sysctlbyname(name, &value, &size, NULL, 0);
//  return value;
// }
//
// void sysctl_string(const char * name, char * dest) {
//   size_t size = 32;
//   sysctlbyname(name, dest, &size, NULL, 0);
// }
//
// void initialize() {
//   global_pCoreCount = sysctl_int("hw.perflevel0.physicalcpu");
//   global_eCoreCount = sysctl_int("hw.perflevel1.physicalcpu");
//   global_pCoreL1InstCacheSize = sysctl_int("hw.perflevel0.l1icachesize");
//   global_eCoreL1InstCacheSize = sysctl_int("hw.perflevel1.l1icachesize");
//   global_pCoreL1DataCacheSize = sysctl_int("hw.perflevel0.l1dcachesize");
//   global_eCoreL1DataCacheSize = sysctl_int("hw.perflevel1.l1dcachesize");
//   global_pCoreL2CacheSize = sysctl_int("hw.perflevel0.l2cachesize");
//   global_eCoreL2CacheSize = sysctl_int("hw.perflevel1.l2cachesize");
//   sysctl_string("machdep.cpu.brand_string", global_brand);
//
//   CFMutableDictionaryRef matching = IOServiceMatching("AppleARMIODevice");
//   io_iterator_t  iter;
//   IOServiceGetMatchingServices(kIOMainPortDefault, matching, &iter);
//
//   io_object_t obj;
//   while ((obj = IOIteratorNext(iter))) {
//     char class[BUFSIZE];
//     IOObjectGetClass(obj, class);
//     char name[BUFSIZE];
//     IORegistryEntryGetName(obj, name);
//
//     if (strncmp(name, "pmgr", BUFSIZE) == 0) {
//       CFTypeRef pCoreRef = NULL, eCoreRef = NULL;
//       pCoreRef = IORegistryEntryCreateCFProperty(obj, CFSTR("voltage-states5-sram"), kCFAllocatorDefault, 0);
//       eCoreRef = IORegistryEntryCreateCFProperty(obj, CFSTR("voltage-states1-sram"), kCFAllocatorDefault, 0);
//
//       long long pCoreClock = getFrequency(pCoreRef);
//       long long eCoreClock = getFrequency(eCoreRef);
//
//       global_pCoreClock = pCoreClock;
//       global_eCoreClock = eCoreClock;
//  	 CFRelease(pCoreRef);
//  	 CFRelease(eCoreRef);
//		 break;
//     }
//   }
//   IOObjectRelease(iter);
// }
//
// UInt64 eCoreClock() {
//   return global_eCoreClock;
// }
//
// UInt64 pCoreClock() {
//   return global_pCoreClock;
// }
//
// int pCoreCount() {
//   return global_pCoreCount;
// }
//
// int eCoreCount() {
//   return global_eCoreCount;
// }
//
// int pCoreL1InstCacheSize() {
//   return global_pCoreL1InstCacheSize;
// }
//
// int pCoreL1DataCacheSize() {
//   return global_pCoreL1DataCacheSize;
// }
//
// int pCoreL2CacheSize() {
//   return global_pCoreL2CacheSize;
// }
//
// int eCoreL1InstCacheSize() {
//   return global_eCoreL1InstCacheSize;
// }
//
// int eCoreL1DataCacheSize() {
//   return global_eCoreL1DataCacheSize;
// }
//
// int eCoreL2CacheSize() {
//   return global_eCoreL2CacheSize;
// }
//
// char * modelName() {
//   return global_brand;
// }
import "C"
import "fmt"

func init() {
	C.initialize()
}

// IsAppleSilicon returns true on this platform.
func IsAppleSilicon() bool {
	return true
}

// PCoreHZ returns the max frequency in Hertz of the P-Core of an Apple Silicon CPU.
func PCoreHz() uint64 {
	return toHz(uint64(C.pCoreClock()))
}

// ECoreHZ returns the max frequency in Hertz of the E-Core of an Apple Silicon CPU.
func ECoreHz() uint64 {
	return toHz(uint64(C.eCoreClock()))
}

// PCoreGHz returns the max frequency in Gigahertz of the P-Core of an Apple Silicon CPU.
func PCoreGHz() float64 {
	return toGhz(uint64(C.pCoreClock()))
}

// ECoreGHz returns the max frequency in Gigahertz of the E-Core of an Apple Silicon CPU.
func ECoreGHz() float64 {
	return toGhz(uint64(C.eCoreClock()))
}

// PCoreCount returns the number of physical P (performance) cores.
func PCoreCount() int {
	return int(C.pCoreCount())
}

// ECoreCount returns the number of physical E (efficiency) cores.
func ECoreCount() int {
	return int(C.eCoreCount())
}

// PCoreCacheSize returns the sizes of the P (performance) core cache sizes
// in the order of
//
// - L1 instruction cache
// - L1 data cache
// - L2 cache
func PCoreCache() (int, int, int) {
	return int(C.pCoreL1InstCacheSize()),
		int(C.pCoreL1DataCacheSize()),
		int(C.pCoreL2CacheSize())
}

// ECoreCacheSize returns the sizes of the E (efficiency) core cache sizes
// in the order of
//
// - L1 instruction cache
// - L1 data cache
// - L2 cache
func ECoreCache() (int, int, int) {
	return int(C.eCoreL1InstCacheSize()),
		int(C.eCoreL1DataCacheSize()),
		int(C.eCoreL2CacheSize())
}

// ModelName returns the model name of the CPU.
func ModelName() string {
	return C.GoString(C.modelName())
}

func toHz(hz uint64) uint64 {
	var gen int
	// If this errors, fallback to default int value
	fmt.Sscanf(ModelName(), "Apple M%", &gen)

	// Starting with M4, Apple appears to report clock speed in Khz
	// See https://github.com/exelban/stats/commit/3e056562b360c937b883725f14f3427d5401b6fe
	if gen >= 4 {
		return hz * 1000
	}
	return hz
}

func toGhz(hz uint64) float64 {
	return float64(toHz(hz) / 1000000000)
}
