mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
riscv: Implement CPU feature detection.
This commit is contained in:
parent
dfbe10eb08
commit
82f0502b4e
3 changed files with 117 additions and 47 deletions
|
@ -97,6 +97,14 @@ struct CPUInfo {
|
|||
bool bXBurst1;
|
||||
bool bXBurst2;
|
||||
|
||||
// RiscV specific extension flags.
|
||||
bool RiscV_M;
|
||||
bool RiscV_A;
|
||||
bool RiscV_F;
|
||||
bool RiscV_D;
|
||||
bool RiscV_C;
|
||||
bool RiscV_V;
|
||||
|
||||
// Quirks
|
||||
struct {
|
||||
// Samsung Galaxy S7 devices (Exynos 8890) have a big.LITTLE configuration where the cacheline size differs between big and LITTLE.
|
||||
|
|
|
@ -18,13 +18,16 @@
|
|||
#include "ppsspp_config.h"
|
||||
#if PPSSPP_ARCH(RISCV64)
|
||||
|
||||
#include <cstring>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
#include <sys/auxv.h>
|
||||
#include <vector>
|
||||
#include "Common/Common.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Common/File/FileUtil.h"
|
||||
#include "Common/Data/Encoding/Utf8.h"
|
||||
#include <cstring>
|
||||
#include <sstream>
|
||||
|
||||
// Only Linux platforms have /proc/cpuinfo
|
||||
#if defined(__linux__)
|
||||
|
@ -32,30 +35,59 @@ const char procfile[] = "/proc/cpuinfo";
|
|||
// https://www.kernel.org/doc/Documentation/ABI/testing/sysfs-devices-system-cpu
|
||||
const char syscpupresentfile[] = "/sys/devices/system/cpu/present";
|
||||
|
||||
std::string GetCPUString() {
|
||||
//TODO
|
||||
std::string cpu_string;
|
||||
cpu_string = "Unknown";
|
||||
return cpu_string;
|
||||
class RiscVCPUInfoParser {
|
||||
public:
|
||||
RiscVCPUInfoParser();
|
||||
|
||||
int ProcessorCount();
|
||||
int TotalLogicalCount();
|
||||
|
||||
std::string ISAString();
|
||||
|
||||
private:
|
||||
std::vector<std::vector<std::string>> cores_;
|
||||
};
|
||||
|
||||
RiscVCPUInfoParser::RiscVCPUInfoParser() {
|
||||
std::string procdata, line;
|
||||
if (!File::ReadFileToString(true, Path(procfile), procdata))
|
||||
return;
|
||||
|
||||
std::istringstream file(procdata);
|
||||
int index = -1;
|
||||
while (std::getline(file, line)) {
|
||||
if (line.length() == 0) {
|
||||
index = -1;
|
||||
} else {
|
||||
if (index == -1) {
|
||||
index = (int)cores_.size();
|
||||
cores_.push_back(std::vector<std::string>());
|
||||
}
|
||||
cores_[index].push_back(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string GetCPUBrandString() {
|
||||
//TODO
|
||||
std::string brand_string;
|
||||
brand_string = "Unknown";
|
||||
return brand_string;
|
||||
int RiscVCPUInfoParser::ProcessorCount() {
|
||||
// Not using present as that counts the logical CPUs (aka harts.)
|
||||
static const char *marker = "processor\t: ";
|
||||
std::set<std::string> processors;
|
||||
for (auto core : cores_) {
|
||||
for (auto line : core) {
|
||||
if (line.find(marker) != line.npos)
|
||||
processors.insert(line);
|
||||
}
|
||||
}
|
||||
|
||||
return (int)processors.size();
|
||||
}
|
||||
|
||||
int GetCoreCount()
|
||||
{
|
||||
std::string line, marker = "processor\t: ";
|
||||
int cores = 1;
|
||||
|
||||
std::string presentData;
|
||||
int RiscVCPUInfoParser::TotalLogicalCount() {
|
||||
std::string presentData, line;
|
||||
bool presentSuccess = File::ReadFileToString(true, Path(syscpupresentfile), presentData);
|
||||
std::istringstream presentFile(presentData);
|
||||
|
||||
if (presentSuccess) {
|
||||
std::istringstream presentFile(presentData);
|
||||
|
||||
int low, high, found;
|
||||
std::getline(presentFile, line);
|
||||
found = sscanf(line.c_str(), "%d-%d", &low, &high);
|
||||
|
@ -65,21 +97,36 @@ int GetCoreCount()
|
|||
return high - low + 1;
|
||||
}
|
||||
|
||||
std::string procdata;
|
||||
if (!File::ReadFileToString(true, Path(procfile), procdata))
|
||||
return 1;
|
||||
std::istringstream file(procdata);
|
||||
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line.find(marker) != std::string::npos)
|
||||
++cores;
|
||||
static const char *marker = "hart\t\t: ";
|
||||
std::set<std::string> harts;
|
||||
for (auto core : cores_) {
|
||||
for (auto line : core) {
|
||||
if (line.find(marker) != line.npos)
|
||||
harts.insert(line);
|
||||
}
|
||||
}
|
||||
|
||||
return cores;
|
||||
|
||||
return (int)harts.size();
|
||||
}
|
||||
|
||||
std::string RiscVCPUInfoParser::ISAString() {
|
||||
static const char *marker = "isa\t\t: ";
|
||||
for (auto core : cores_) {
|
||||
for (auto line : core) {
|
||||
if (line.find(marker) != line.npos)
|
||||
return line.substr(strlen(marker));
|
||||
}
|
||||
}
|
||||
|
||||
return "Unknown";
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool ExtensionSupported(unsigned long v, char c) {
|
||||
unsigned long bit = (v >> (c - 'A')) & 1;
|
||||
return bit == 1;
|
||||
}
|
||||
|
||||
CPUInfo cpu_info;
|
||||
|
||||
CPUInfo::CPUInfo() {
|
||||
|
@ -101,16 +148,31 @@ void CPUInfo::Detect()
|
|||
Mode64bit = false;
|
||||
#endif
|
||||
vendor = VENDOR_OTHER;
|
||||
logical_cpu_count = 1;
|
||||
|
||||
// Not sure how to get anything great here.
|
||||
truncate_cpy(brand_string, "Unknown");
|
||||
|
||||
// Get the information about the CPU
|
||||
#if !defined(__linux__)
|
||||
num_cores = 1;
|
||||
logical_cpu_count = 1;
|
||||
truncate_cpy(cpu_string, "Unknown");
|
||||
#else // __linux__
|
||||
truncate_cpy(cpu_string, GetCPUString().c_str());
|
||||
truncate_cpy(brand_string, GetCPUBrandString().c_str());
|
||||
num_cores = GetCoreCount();
|
||||
RiscVCPUInfoParser parser;
|
||||
num_cores = parser.ProcessorCount();
|
||||
logical_cpu_count = parser.TotalLogicalCount() / num_cores;
|
||||
if (logical_cpu_count <= 0)
|
||||
logical_cpu_count = 1;
|
||||
|
||||
truncate_cpy(cpu_string, parser.ISAString().c_str());
|
||||
#endif
|
||||
|
||||
unsigned long hwcap = getauxval(AT_HWCAP);
|
||||
RiscV_M = ExtensionSupported(hwcap, 'M');
|
||||
RiscV_A = ExtensionSupported(hwcap, 'A');
|
||||
RiscV_F = ExtensionSupported(hwcap, 'F');
|
||||
RiscV_D = ExtensionSupported(hwcap, 'D');
|
||||
RiscV_C = ExtensionSupported(hwcap, 'C');
|
||||
RiscV_V = ExtensionSupported(hwcap, 'V');
|
||||
}
|
||||
|
||||
// Turn the cpu info into a string we can show
|
||||
|
|
|
@ -19,38 +19,38 @@
|
|||
#include <algorithm>
|
||||
#include <cstring>
|
||||
#include "Common/BitScan.h"
|
||||
#include "Common/CPUDetect.h"
|
||||
#include "Common/RiscVEmitter.h"
|
||||
|
||||
namespace RiscVGen {
|
||||
|
||||
static inline bool SupportsCompressed() {
|
||||
// TODO
|
||||
return true;
|
||||
return cpu_info.RiscV_C;
|
||||
}
|
||||
|
||||
static inline uint8_t BitsSupported() {
|
||||
// TODO
|
||||
return 64;
|
||||
return cpu_info.OS64bit ? 64 : 32;
|
||||
}
|
||||
|
||||
static inline uint8_t FloatBitsSupported() {
|
||||
// TODO: 0 if not.
|
||||
return 64;
|
||||
if (cpu_info.RiscV_D)
|
||||
return 64;
|
||||
if (cpu_info.RiscV_F)
|
||||
return 32;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline bool SupportsMulDiv() {
|
||||
// TODO
|
||||
return true;
|
||||
return cpu_info.RiscV_M;
|
||||
}
|
||||
|
||||
static inline bool SupportsAtomic() {
|
||||
// TODO
|
||||
return true;
|
||||
return cpu_info.RiscV_A;
|
||||
}
|
||||
|
||||
static inline bool SupportsZicsr() {
|
||||
// TODO
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
enum class Opcode32 {
|
||||
|
|
Loading…
Add table
Reference in a new issue