Commit bd463668 authored by Peter Steinbach's avatar Peter Steinbach

added new single_include header

parent 9fc4aea1
......@@ -360,6 +360,74 @@ namespace compass {
#endif
#ifndef COMPASS_RT_X86_IMPL_H_
#define COMPASS_RT_X86_IMPL_H_
#ifndef COMPASS_BIT_VIEW_H
#define COMPASS_BIT_VIEW_H
#include <climits>
#include <type_traits>
namespace compass {
namespace utility
{
template <typename T>
struct bit_view{
T& value_;
static const int width = sizeof(T)*CHAR_BIT;
static_assert(std::is_integral<T>::value, "compass bitview used with non-integral type (not supported)");
bit_view(T& _val):
value_(_val){}
bool test(int offset) const {
bool value = false;
if(offset>(width-1))
return value;
const int mask = 1 << offset;
value = value_ & mask;
return value;
}
void set(int offset) {
if(offset>(width-1))
return ;
const int mask = 1 << offset;
value_ = value_ | mask;
return;
}
T range(std::uint32_t _begin, std::uint32_t _end) const {
T value = 0;
if(_begin >= width || _end <= _begin)
return value;
const T mask = ~(~0 << (_end - _begin));
value = (value_ >> _begin) & mask;
return value;
}
};
}
}
#endif
#ifndef COMPASS_RT_X86_CPUID_H
......@@ -622,73 +690,133 @@ namespace compass {
#endif
#endif
#ifndef COMPASS_BIT_VIEW_H
#define COMPASS_BIT_VIEW_H
#ifndef COMPASS_RT_X86_META_H_
#define COMPASS_RT_X86_META_H_
#include <climits>
#include <type_traits>
#include <iostream>
#include <string>
#include <algorithm>
#include <thread>
namespace compass {
namespace utility
{
namespace runtime {
template <typename T>
struct bit_view{
namespace detail {
T& value_;
static std::string vendor(ct::x86_tag) {
static const int width = sizeof(T)*CHAR_BIT;
static_assert(std::is_integral<T>::value, "compass bitview used with non-integral type (not supported)");
bit_view(T& _val):
value_(_val){}
std::array<std::uint32_t,4> regs = rt::cpuid(0);
std::string vendor_name = "";
bool test(int offset) const {
if(!regs.empty()){
vendor_name.resize(3*4);
bool value = false;
if(offset>(width-1))
return value;
std::copy(reinterpret_cast<char*>(&regs[ct::ebx]),reinterpret_cast<char*>(&regs[ct::ebx])+4,
vendor_name.begin());
std::copy(reinterpret_cast<char*>(&regs[ct::edx]),reinterpret_cast<char*>(&regs[ct::edx])+4,
vendor_name.begin()+4);
std::copy(reinterpret_cast<char*>(&regs[ct::ecx]),reinterpret_cast<char*>(&regs[ct::ecx])+4,
vendor_name.begin()+8);
}
const int mask = 1 << offset;
value = value_ & mask;
return vendor_name;
return value;
}
void set(int offset) {
}
if(offset>(width-1))
return ;
const int mask = 1 << offset;
value_ = value_ | mask;
static std::string brand(ct::x86_tag) {
return;
}
std::string value = "";
auto regs = rt::cpuid(0x80000000);
if(regs[ct::eax] < 0x80000004)
return value;
T range(std::uint32_t _begin, std::uint32_t _end) const {
value.resize(48);
char* value_begin = &value[0];
for(std::uint32_t i = 2; i<5;++i){
auto ret = rt::cpuid(0x80000000 + i);
T value = 0;
if(_begin >= width || _end <= _begin)
return value;
for(std::uint32_t r = 0; r<4;++r){
std::uint32_t* tgt = reinterpret_cast<std::uint32_t*>(value_begin + (i-2)*16u + r*4u);
*tgt = ret[r];
}
const T mask = ~(~0 << (_end - _begin));
value = (value_ >> _begin) & mask;
return value;
}
return value;
}
static std::string device_name(ct::x86_tag) {
std::string brand_str = compass::runtime::detail::brand(ct::x86_tag());
std::string vendor = compass::runtime::detail::vendor(ct::x86_tag());
std::size_t find_pos = 0;
bool is_intel = false;
bool is_amd = false;
if((find_pos = vendor.find("Genuine"))!=std::string::npos){
vendor.erase(find_pos,7);
is_intel = true;
}
if((find_pos = vendor.find("Authentic"))!=std::string::npos){
vendor.erase(find_pos,9);
is_amd = true;
}
std::string value = "";
if((find_pos = brand_str.find(vendor)) != std::string::npos){
if(is_intel){
auto second_bracket_itr = brand_str.rfind(")");
auto last_at_itr = brand_str.rfind("@");
value = brand_str.substr(second_bracket_itr+1,last_at_itr-(second_bracket_itr+1));
if((find_pos = value.find(" CPU "))!=std::string::npos){
value.erase(find_pos,5);
}
};
if((find_pos = value.find(" CPU "))!=std::string::npos){
value.erase(find_pos,5);
}
}
value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end());
}
if(is_amd){
}
auto end_itr = brand_str.rfind("Processor");
value = brand_str.substr(find_pos+4,end_itr-4);
}
}
return value;
}
};
};
};
#endif
#ifndef COMPASS_RT_X86_SIZES_H_
#define COMPASS_RT_X86_SIZES_H_
......@@ -702,6 +830,7 @@ namespace compass {
#include <iostream>
#include <string>
#include <algorithm>
......@@ -714,6 +843,7 @@ namespace compass {
namespace detail {
using bitview = compass::utility::bit_view<std::uint32_t>;
using current_arch_t = ct::arch::type;
namespace size{
......@@ -721,31 +851,77 @@ namespace compass {
class cacheline
{
std::vector<std::uint32_t> ebx_data_;
std::vector<std::uint32_t> sizes_in_bytes_;
cacheline():
ebx_data_()
void on_intel(){
std::uint32_t maxlevel = 8;
std::uint32_t eax = 0;
sizes_in_bytes_.reserve(maxlevel);
for(std::uint32_t l = 0;l<maxlevel;++l)
{
auto regs = cpuid(0x04,0,l);
eax = regs[ct::eax];
auto bv = bitview(eax);
if(!bv.test(1))
continue;
auto truelevel = bv.range(5,8);
if(truelevel != l)
continue;
std::uint32_t value = bitview(regs[ct::ebx]).range(0,11);
sizes_in_bytes_.push_back(value+1);
}
}
void on_amd(){
ebx_data_.reserve(3);
std::uint32_t maxlevel = 8;
std::uint32_t eax = 0;
sizes_in_bytes_.reserve(3);
for(std::uint32_t l = 0;l<maxlevel;++l)
{
auto regs = cpuid(0x04,0,l);
auto regs = cpuid(0x80000005);
eax = regs[ct::eax];
auto bv = bitview(eax);
std::uint32_t ecx = regs[ct::ecx];
auto bv = bitview(ecx);
std::uint32_t linesize = bv.range(0,7);
if(!linesize)
return;
if(!bv.test(1))
continue;
sizes_in_bytes_.push_back(linesize);
auto truelevel = bv.range(5,8);
if(truelevel != l)
continue;
auto l23regs = cpuid(0x80000006);
ecx = l23regs[ct::ecx];
auto bv2 = bitview(ecx);
linesize = bv2.range(0,7);
ebx_data_.push_back(regs[ct::ebx]);
sizes_in_bytes_.push_back(linesize);
auto bv3 = bitview(l23regs[ct::edx]);
linesize = bv3.range(0,7);
sizes_in_bytes_.push_back(linesize);
}
cacheline():
sizes_in_bytes_()
{
auto brand = compass::runtime::detail::vendor( current_arch_t() );
if(brand.find("AMD") != std::string::npos){
on_amd();
}
if(brand.find("Intel") != std::string::npos){
on_intel();
}
}
......@@ -758,53 +934,102 @@ namespace compass {
}
static std::uint32_t levels_available(ct::x86_tag){
return cacheline::get().ebx_data_.size();
return cacheline::get().sizes_in_bytes_.size();
}
static std::uint32_t level(int _lvl, ct::x86_tag){
auto reg = cacheline::get().ebx_data_.at(_lvl-1);
std::uint32_t value = bitview(reg).range(0,11);
auto value = cacheline::get().sizes_in_bytes_.at(_lvl-1);
return value + 1;
return value;
}
};
class cache
{
std::vector<std::uint32_t> ebx_data_;
std::vector<std::uint32_t> ecx_data_;
std::vector<std::uint32_t> sizes_in_bytes_;
cache():
ebx_data_(),
ecx_data_()
void on_intel() {
std::uint32_t eax = 0;
std::uint32_t maxlevel = 8;
sizes_in_bytes_.reserve(8);
for(std::uint32_t l = 0;l<maxlevel;++l)
{
auto regs = cpuid(0x04,0,l);
eax = regs[ct::eax];
auto bv = bitview(eax);
if(!bv.test(1))
continue;
ebx_data_.reserve(3);
ecx_data_.reserve(3);
auto truelevel = bv.range(5,8);
if(truelevel != l)
continue;
std::uint32_t maxlevel = 8;
std::uint32_t eax = 0;
std::uint32_t ebx = regs[ct::ebx];
const bitview bv_ebx = bitview(ebx);
const std::uint32_t ecx = regs[ct::ecx];
for(std::uint32_t l = 0;l<maxlevel;++l)
{
auto regs = cpuid(0x04,0,l);
std::uint32_t ways = 1 + bv_ebx.range(22,31);
std::uint32_t partitions = 1 + bv_ebx.range(12,21);
std::uint32_t line_size = 1 + bv_ebx.range(0,11);
std::uint32_t sets = 1 + ecx;
eax = regs[ct::eax];
auto bv = bitview(eax);
std::uint32_t value = ways*partitions*line_size*sets;
if(!bv.test(1))
continue;
sizes_in_bytes_.push_back(value);
}
}
auto truelevel = bv.range(5,8);
if(truelevel != l)
continue;
void on_amd(){
ebx_data_.push_back(regs[ct::ebx]);
ecx_data_.push_back(regs[ct::ecx]);
sizes_in_bytes_.reserve(3);
auto regs = cpuid(0x80000005);
std::uint32_t ecx = regs[ct::ecx];
auto bv = bitview(ecx);
std::uint32_t test_linesize = bv.range(0,7);
if(!test_linesize)
return;
sizes_in_bytes_.push_back(bv.range(24,31)*1024);
auto l23regs = cpuid(0x80000006);
ecx = l23regs[ct::ecx];
auto bv2 = bitview(ecx);
auto l2size = bv2.range(16,31);
l2size &= 0xffff;
sizes_in_bytes_.push_back(l2size*1024);
auto bv3 = bitview(l23regs[ct::edx]);
auto l3size = bv3.range(19,31);
l3size *= 512*1024;
sizes_in_bytes_.push_back(l3size);
}
cache():
sizes_in_bytes_()
{
auto brand = compass::runtime::detail::vendor( current_arch_t() );
if(brand.find("AMD") != std::string::npos){
on_amd();
}
if(brand.find("Intel") != std::string::npos){
on_intel();
}
}
......@@ -818,38 +1043,26 @@ namespace compass {
}
static std::uint32_t levels_available(ct::x86_tag){
return cache::get().ebx_data_.size();
return cache::get().sizes_in_bytes_.size();
}
static std::uint32_t level(int _lvl, ct::x86_tag){
if(_lvl <= 0){
std::cerr << "compass::size::cache requested invalid cache level (received: "<<
_lvl << ", found on this host: [1," << cache::get().ebx_data_.size() + 1 << "]\n";
_lvl << ", found on this host: [1," << cache::get().sizes_in_bytes_.size() + 1 << "]\n";
return 0;
}
std::uint32_t index = _lvl - 1;
if(!(index < cache::get().ebx_data_.size())){
if(!(index < cache::get().sizes_in_bytes_.size())){
std::cerr << "compass::size::cache requested invalid cache level (received: "<<
_lvl << ", found on this host: [1," << cache::get().ebx_data_.size() + 1 << "]\n";
_lvl << ", found on this host: [1," << cache::get().sizes_in_bytes_.size() + 1 << "]\n";
return 0;
}
std::uint32_t ebx = cache::get().ebx_data_[index];
const bitview bv_ebx = bitview(ebx);
const std::uint32_t ecx = cache::get().ecx_data_[index];
std::uint32_t ways = 1 + bv_ebx.range(22,31);
std::uint32_t partitions = 1 + bv_ebx.range(12,21);
std::uint32_t line_size = 1 + bv_ebx.range(0,11);
std::uint32_t sets = 1 + ecx;
std::uint32_t value = ways*partitions*line_size*sets;
return value;
return cache::get().sizes_in_bytes_[index];
}
};
......@@ -887,108 +1100,6 @@ namespace compass {
}
static std::string vendor(ct::x86_tag) {
std::array<std::uint32_t,4> regs = rt::cpuid(0);
std::string vendor_name = "";
if(!regs.empty()){
vendor_name.resize(3*4);
std::copy(reinterpret_cast<char*>(&regs[ct::ebx]),reinterpret_cast<char*>(&regs[ct::ebx])+4,
vendor_name.begin());
std::copy(reinterpret_cast<char*>(&regs[ct::edx]),reinterpret_cast<char*>(&regs[ct::edx])+4,
vendor_name.begin()+4);
std::copy(reinterpret_cast<char*>(&regs[ct::ecx]),reinterpret_cast<char*>(&regs[ct::ecx])+4,
vendor_name.begin()+8);
}
return vendor_name;
}
static std::string brand(ct::x86_tag) {
std::string value = "";
auto regs = rt::cpuid(0x80000000);
if(regs[ct::eax] < 0x80000004)
return value;
value.resize(48);
char* value_begin = &value[0];
for(std::uint32_t i = 2; i<5;++i){
auto ret = rt::cpuid(0x80000000 + i);
for(std::uint32_t r = 0; r<4;++r){
std::uint32_t* tgt = reinterpret_cast<std::uint32_t*>(value_begin + (i-2)*16u + r*4u);
*tgt = ret[r];
}
}
return value;
}
static std::string device_name(ct::x86_tag) {
std::string brand_str = compass::runtime::detail::brand(ct::x86_tag());
std::string vendor = compass::runtime::detail::vendor(ct::x86_tag());
std::size_t find_pos = 0;
bool is_intel = false;
bool is_amd = false;
if((find_pos = vendor.find("Genuine"))!=std::string::npos){
vendor.erase(find_pos,7);
is_intel = true;
}
if((find_pos = vendor.find("Authentic"))!=std::string::npos){
vendor.erase(find_pos,9);
is_amd = true;
}
std::string value = "";
if((find_pos = brand_str.find(vendor)) != std::string::npos){
if(is_intel){
auto second_bracket_itr = brand_str.rfind(")");
auto last_at_itr = brand_str.rfind("@");
value = brand_str.substr(second_bracket_itr+1,last_at_itr-(second_bracket_itr+1));
if((find_pos = value.find(" CPU "))!=std::string::npos){
value.erase(find_pos,5);
}
if((find_pos = value.find(" CPU "))!=std::string::npos){
value.erase(find_pos,5);
}
value.erase(std::remove_if(value.begin(), value.end(), isspace), value.end());
}
if(is_amd){
auto end_itr = brand_str.rfind("Processor");
value = brand_str.substr(find_pos+4,end_itr-4);
}
}
return value;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment