Skip to content
29 changes: 21 additions & 8 deletions src/hotspot/cpu/riscv/vm_version_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,28 @@

uint32_t VM_Version::_initial_vector_length = 0;

#define DEF_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \
VM_Version::NAME##RVFeatureValue VM_Version::NAME(PRETTY, BIT, FSTRING);
RV_FEATURE_FLAGS(DEF_RV_FEATURE)

#define ADD_RV_FEATURE_IN_LIST(NAME, PRETTY, BIT, FSTRING, FLAGF) \
&VM_Version::NAME,
VM_Version::RVFeatureValue* VM_Version::_feature_list[] = {
RV_FEATURE_FLAGS(ADD_RV_FEATURE_IN_LIST)
#define DEF_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::NAME##RVExtFeatureValue VM_Version::NAME;
RV_EXT_FEATURE_FLAGS(DEF_RV_EXT_FEATURE)
#undef DEF_RV_EXT_FEATURE

#define DEF_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
VM_Version::NAME##RVNonExtFeatureValue VM_Version::NAME;
RV_NON_EXT_FEATURE_FLAGS(DEF_RV_NON_EXT_FEATURE)
#undef DEF_RV_NON_EXT_FEATURE

#define ADD_RV_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::NAME,
#define ADD_RV_NON_EXT_FEATURE_IN_LIST(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
&VM_Version::NAME,
VM_Version::RVFeatureValue* VM_Version::_feature_list[] = {
RV_EXT_FEATURE_FLAGS(ADD_RV_EXT_FEATURE_IN_LIST)
RV_NON_EXT_FEATURE_FLAGS(ADD_RV_NON_EXT_FEATURE_IN_LIST)
nullptr};
#undef ADD_RV_NON_EXT_FEATURE_IN_LIST
#undef ADD_RV_EXT_FEATURE_IN_LIST

VM_Version::RVExtFeatures* VM_Version::_rv_ext_features = new VM_Version::RVExtFeatures();

void VM_Version::useRVA20U64Profile() {
RV_USE_RVA20U64;
Expand Down
247 changes: 184 additions & 63 deletions src/hotspot/cpu/riscv/vm_version_riscv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,30 +46,29 @@ class VM_Version : public Abstract_VM_Version {
RIVOS = 0x6cf, // JEDEC: 0x4f, Bank: 14
};

class RVExtFeatures;

class RVFeatureValue {
const char* const _pretty;
const bool _feature_string;
const uint64_t _feature_bit;
bool _enabled;
const uint64_t _linux_feature_bit;
int64_t _value;
public:
RVFeatureValue(const char* pretty, int bit_num, bool fstring) :
_pretty(pretty), _feature_string(fstring), _feature_bit(nth_bit(bit_num)),
_enabled(false), _value(-1) {
RVFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
_pretty(pretty), _feature_string(fstring), _linux_feature_bit(nth_bit(linux_bit_num)),
_value(-1) {
}
void enable_feature(int64_t value = 0) {
_enabled = true;
virtual void enable_feature(int64_t value = 0) {
_value = value;
}
void disable_feature() {
_enabled = false;
virtual void disable_feature() {
_value = -1;
}
const char* pretty() { return _pretty; }
uint64_t feature_bit() { return _feature_bit; }
uint64_t feature_bit() { return _linux_feature_bit; }
bool feature_string() { return _feature_string; }
bool enabled() { return _enabled; }
int64_t value() { return _value; }
virtual bool enabled() = 0;
virtual void update_flag() = 0;
};

Expand Down Expand Up @@ -111,6 +110,45 @@ class VM_Version : public Abstract_VM_Version {
#define NO_UPDATE_DEFAULT \
void update_flag() {} \


class RVExtFeatureValue : public RVFeatureValue {
const uint32_t _cpu_feature_index;
public:
RVExtFeatureValue(const char* pretty, int linux_bit_num, uint32_t cpu_feature_index, bool fstring) :
RVFeatureValue(pretty, linux_bit_num, fstring),
_cpu_feature_index(cpu_feature_index) {
}
bool enabled() {
return RVExtFeatures::current()->support_feature(_cpu_feature_index);
}
void enable_feature(int64_t value = 0) {
RVFeatureValue::enable_feature(value);
RVExtFeatures::current()->set_feature(_cpu_feature_index);
}
void disable_feature() {
RVFeatureValue::disable_feature();
RVExtFeatures::current()->clear_feature(_cpu_feature_index);
}
};

class RVNonExtFeatureValue : public RVFeatureValue {
bool _enabled;
public:
RVNonExtFeatureValue(const char* pretty, int linux_bit_num, bool fstring) :
RVFeatureValue(pretty, linux_bit_num, fstring),
_enabled(false) {
}
bool enabled() { return _enabled; }
void enable_feature(int64_t value = 0) {
RVFeatureValue::enable_feature(value);
_enabled = true;
}
void disable_feature() {
RVFeatureValue::disable_feature();
_enabled = false;
}
};

// Frozen standard extensions
// I RV64I
// M Integer Multiplication and Division
Expand Down Expand Up @@ -161,58 +199,140 @@ class VM_Version : public Abstract_VM_Version {
#define RV_NO_FLAG_BIT (BitsPerWord+1) // nth_bit will return 0 on values larger than BitsPerWord

// Note: the order matters, depender should be after their dependee. E.g. ext_V before ext_Zvbb.
// declaration name , extension name, bit pos ,in str, mapped flag)
#define RV_FEATURE_FLAGS(decl) \
decl(ext_I , "i" , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_M , "m" , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_A , "a" , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_F , "f" , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_D , "d" , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_C , "c" , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
decl(ext_Q , "q" , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_H , "h" , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_V , "v" , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
decl(ext_Zicbom , "Zicbom" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
decl(ext_Zicboz , "Zicboz" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
decl(ext_Zicbop , "Zicbop" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
decl(ext_Zba , "Zba" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
decl(ext_Zbb , "Zbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , "Zbc" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , "Zbs" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
decl(ext_Zbkb , "Zbkb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
decl(ext_Zcb , "Zcb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
decl(ext_Zfa , "Zfa" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
decl(ext_Zfh , "Zfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zfhmin , "Zfhmin" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
decl(ext_Zicsr , "Zicsr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zicntr , "Zicntr" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , "Zifencei" , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , "Zic64b" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
decl(ext_Ztso , "Ztso" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
decl(ext_Zihintpause , "Zihintpause" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
decl(ext_Zacas , "Zacas" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
decl(ext_Zvbb , "Zvbb" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \
decl(ext_Zvbc , "Zvbc" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \
decl(ext_Zvfh , "Zvfh" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \
decl(ext_Zvkn , "Zvkn" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \
decl(ext_Zicond , "Zicond" , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \
decl(mvendorid , "VendorId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(marchid , "ArchId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mimpid , "ImpId" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(unaligned_access , "Unaligned" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(satp_mode , "SATP" , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(zicboz_block_size, "ZicbozBlockSize", RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \

#define DECLARE_RV_FEATURE(NAME, PRETTY, BIT, FSTRING, FLAGF) \
struct NAME##RVFeatureValue : public RVFeatureValue { \
NAME##RVFeatureValue(const char* pretty, int bit, bool fstring) : \
RVFeatureValue(pretty, bit, fstring) {} \
FLAGF; \
}; \
static NAME##RVFeatureValue NAME; \

RV_FEATURE_FLAGS(DECLARE_RV_FEATURE)
#undef DECLARE_RV_FEATURE
//
// Fields description in `decl`:
// declaration name, extension name, bit value from linux, feature string?, mapped flag)
#define RV_EXT_FEATURE_FLAGS(decl) \
decl(ext_I , i , ('I' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_M , m , ('M' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_A , a , ('A' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_F , f , ('F' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_D , d , ('D' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_C , c , ('C' - 'A'), true , UPDATE_DEFAULT(UseRVC)) \
decl(ext_Q , q , ('Q' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_H , h , ('H' - 'A'), true , NO_UPDATE_DEFAULT) \
decl(ext_V , v , ('V' - 'A'), true , UPDATE_DEFAULT(UseRVV)) \
decl(ext_Zicbom , Zicbom , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbom)) \
decl(ext_Zicboz , Zicboz , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicboz)) \
decl(ext_Zicbop , Zicbop , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicbop)) \
decl(ext_Zba , Zba , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZba)) \
decl(ext_Zbb , Zbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbb)) \
decl(ext_Zbc , Zbc , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zbs , Zbs , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbs)) \
decl(ext_Zbkb , Zbkb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZbkb)) \
decl(ext_Zcb , Zcb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZcb)) \
decl(ext_Zfa , Zfa , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfa)) \
decl(ext_Zfh , Zfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfh)) \
decl(ext_Zfhmin , Zfhmin , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZfhmin)) \
decl(ext_Zicsr , Zicsr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zicntr , Zicntr , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zifencei , Zifencei , RV_NO_FLAG_BIT, true , NO_UPDATE_DEFAULT) \
decl(ext_Zic64b , Zic64b , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZic64b)) \
decl(ext_Ztso , Ztso , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZtso)) \
decl(ext_Zihintpause , Zihintpause , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZihintpause)) \
decl(ext_Zacas , Zacas , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZacas)) \
decl(ext_Zvbb , Zvbb , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbb, ext_V)) \
decl(ext_Zvbc , Zvbc , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvbc, ext_V)) \
decl(ext_Zvfh , Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, ext_V)) \
decl(ext_Zvkn , Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, ext_V)) \
decl(ext_Zicond , Zicond , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT(UseZicond)) \

#define DECLARE_RV_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct NAME##RVExtFeatureValue : public RVExtFeatureValue { \
NAME##RVExtFeatureValue() : \
RVExtFeatureValue(#PRETTY, LINUX_BIT, RVExtFeatures::CPU_##NAME, FSTRING) {} \
FLAGF; \
}; \
static NAME##RVExtFeatureValue NAME; \

RV_EXT_FEATURE_FLAGS(DECLARE_RV_EXT_FEATURE)
#undef DECLARE_RV_EXT_FEATURE

// Non-extension features
//
#define RV_NON_EXT_FEATURE_FLAGS(decl) \
decl(unaligned_access , Unaligned , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mvendorid , VendorId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(marchid , ArchId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(mimpid , ImpId , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(satp_mode , SATP , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \
decl(zicboz_block_size, ZicbozBlockSize , RV_NO_FLAG_BIT, false, NO_UPDATE_DEFAULT) \

#define DECLARE_RV_NON_EXT_FEATURE(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) \
struct NAME##RVNonExtFeatureValue : public RVNonExtFeatureValue { \
NAME##RVNonExtFeatureValue() : \
RVNonExtFeatureValue(#PRETTY, LINUX_BIT, FSTRING) {} \
FLAGF; \
}; \
static NAME##RVNonExtFeatureValue NAME; \

RV_NON_EXT_FEATURE_FLAGS(DECLARE_RV_NON_EXT_FEATURE)
#undef DECLARE_RV_NON_EXT_FEATURE

private:
// Utility for AOT CPU feature store/check.
class RVExtFeatures : public CHeapObj<mtCode> {
public:
enum RVFeatureIndex {
#define DECLARE_RV_FEATURE_ENUM(NAME, PRETTY, LINUX_BIT, FSTRING, FLAGF) CPU_##NAME,

RV_EXT_FEATURE_FLAGS(DECLARE_RV_FEATURE_ENUM)
MAX_CPU_FEATURE_INDEX
#undef DECLARE_RV_FEATURE_ENUM
};
private:
uint64_t _features_bitmap[(MAX_CPU_FEATURE_INDEX / BitsPerLong) + 1];
STATIC_ASSERT(sizeof(_features_bitmap) * BitsPerByte >= MAX_CPU_FEATURE_INDEX);

// Number of 8-byte elements in _features_bitmap.
constexpr static int element_count() {
return sizeof(_features_bitmap) / sizeof(uint64_t);
}

static int element_index(RVFeatureIndex feature) {
int idx = feature / BitsPerLong;
assert(idx < element_count(), "Features array index out of bounds");
return idx;
}

static uint64_t feature_bit(RVFeatureIndex feature) {
return (1ULL << (feature % BitsPerLong));
}

static RVFeatureIndex convert(uint32_t index) {
assert(index < MAX_CPU_FEATURE_INDEX, "must");
return (RVFeatureIndex)index;
}

public:
static RVExtFeatures* current() {
return _rv_ext_features;
}

RVExtFeatures() {
for (int i = 0; i < element_count(); i++) {
_features_bitmap[i] = 0;
}
}

void set_feature(uint32_t feature) {
RVFeatureIndex f = convert(feature);
int idx = element_index(f);
_features_bitmap[idx] |= feature_bit(f);
}

void clear_feature(uint32_t feature) {
RVFeatureIndex f = convert(feature);
int idx = element_index(f);
_features_bitmap[idx] &= ~feature_bit(f);
}

bool support_feature(uint32_t feature) {
RVFeatureIndex f = convert(feature);
int idx = element_index(f);
return (_features_bitmap[idx] & feature_bit(f)) != 0;
}
};

// enable extensions based on profile, current supported profiles:
// RVA20U64
Expand Down Expand Up @@ -286,6 +406,7 @@ class VM_Version : public Abstract_VM_Version {

// Null terminated list
static RVFeatureValue* _feature_list[];
static RVExtFeatures* _rv_ext_features;

// Enables features in _feature_list
static void setup_cpu_available_features();
Expand Down