mirror of
https://git.wownero.com/wownero/RandomWOW.git
synced 2024-12-22 15:58:53 +00:00
Configurable parameters separated into configuration.h
This commit is contained in:
parent
096a7c0d7b
commit
e65d9da66c
@ -47,7 +47,7 @@ namespace RandomX {
|
||||
|
||||
void AssemblyGeneratorX86::generateProgram(Program& prog) {
|
||||
asmCode.str(std::string()); //clear
|
||||
for (unsigned i = 0; i < ProgramLength; ++i) {
|
||||
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
Instruction& instr = prog(i);
|
||||
instr.src %= RegistersCount;
|
||||
instr.dst %= RegistersCount;
|
||||
@ -491,7 +491,6 @@ namespace RandomX {
|
||||
INST_HANDLE(ISMULH_R)
|
||||
INST_HANDLE(ISMULH_M)
|
||||
INST_HANDLE(IMUL_RCP)
|
||||
INST_HANDLE(ISDIV_C)
|
||||
INST_HANDLE(INEG_R)
|
||||
INST_HANDLE(IXOR_R)
|
||||
INST_HANDLE(IXOR_M)
|
||||
@ -511,8 +510,6 @@ namespace RandomX {
|
||||
|
||||
//Floating point group E
|
||||
INST_HANDLE(FMUL_R)
|
||||
INST_HANDLE(FMUL_M)
|
||||
INST_HANDLE(FDIV_R)
|
||||
INST_HANDLE(FDIV_M)
|
||||
INST_HANDLE(FSQRT_R)
|
||||
|
||||
@ -520,9 +517,7 @@ namespace RandomX {
|
||||
INST_HANDLE(COND_R)
|
||||
INST_HANDLE(COND_M)
|
||||
INST_HANDLE(CFROUND)
|
||||
|
||||
INST_HANDLE(ISTORE)
|
||||
INST_HANDLE(FSTORE)
|
||||
|
||||
INST_HANDLE(NOP)
|
||||
};
|
||||
|
@ -24,7 +24,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace RandomX {
|
||||
|
||||
static_assert(ArgonMemorySize % (ArgonLanes * ARGON2_SYNC_POINTS) == 0, "ArgonMemorySize - invalid value");
|
||||
static_assert(RANDOMX_ARGON_MEMORY % (RANDOMX_ARGON_LANES * ARGON2_SYNC_POINTS) == 0, "RANDOMX_ARGON_MEMORY - invalid value");
|
||||
|
||||
void Cache::argonFill(const void* seed, size_t seedSize) {
|
||||
uint32_t memory_blocks, segment_length;
|
||||
@ -35,15 +35,15 @@ namespace RandomX {
|
||||
context.outlen = 0;
|
||||
context.pwd = CONST_CAST(uint8_t *)seed;
|
||||
context.pwdlen = (uint32_t)seedSize;
|
||||
context.salt = CONST_CAST(uint8_t *)ArgonSalt;
|
||||
context.salt = CONST_CAST(uint8_t *)RANDOMX_ARGON_SALT;
|
||||
context.saltlen = (uint32_t)ArgonSaltSize;
|
||||
context.secret = NULL;
|
||||
context.secretlen = 0;
|
||||
context.ad = NULL;
|
||||
context.adlen = 0;
|
||||
context.t_cost = ArgonIterations;
|
||||
context.m_cost = ArgonMemorySize;
|
||||
context.lanes = ArgonLanes;
|
||||
context.t_cost = RANDOMX_ARGON_ITERATIONS;
|
||||
context.m_cost = RANDOMX_ARGON_MEMORY;
|
||||
context.lanes = RANDOMX_ARGON_LANES;
|
||||
context.threads = 1;
|
||||
context.allocate_cbk = NULL;
|
||||
context.free_cbk = NULL;
|
||||
|
@ -23,6 +23,9 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace RandomX {
|
||||
|
||||
static_assert(sizeof(MemoryRegisters) == 2 * sizeof(addr_t) + sizeof(uintptr_t), "Invalid alignment of struct RandomX::MemoryRegisters");
|
||||
static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct RandomX::RegisterFile");
|
||||
|
||||
CompiledVirtualMachine::CompiledVirtualMachine() {
|
||||
totalSize = 0;
|
||||
}
|
||||
@ -39,7 +42,7 @@ namespace RandomX {
|
||||
void CompiledVirtualMachine::execute() {
|
||||
//executeProgram(reg, mem, scratchpad, InstructionCount);
|
||||
//totalSize += compiler.getCodeSize();
|
||||
compiler.getProgramFunc()(reg, mem, scratchpad, InstructionCount);
|
||||
compiler.getProgramFunc()(reg, mem, scratchpad, RANDOMX_PROGRAM_ITERATIONS);
|
||||
#ifdef TRACEVM
|
||||
for (int32_t i = InstructionCount - 1; i >= 0; --i) {
|
||||
std::cout << std::hex << tracepad[i].u64 << std::endl;
|
||||
|
@ -26,6 +26,10 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace RandomX {
|
||||
|
||||
extern "C" {
|
||||
void executeProgram(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t);
|
||||
}
|
||||
|
||||
class CompiledVirtualMachine : public VirtualMachine {
|
||||
public:
|
||||
void* operator new(size_t size) {
|
||||
|
@ -346,12 +346,10 @@ namespace RandomX {
|
||||
INST_NAME(ISMULH_R)
|
||||
INST_NAME(ISMULH_M)
|
||||
INST_NAME(IMUL_RCP)
|
||||
INST_NAME(ISDIV_C)
|
||||
INST_NAME(INEG_R)
|
||||
INST_NAME(IXOR_R)
|
||||
INST_NAME(IXOR_M)
|
||||
INST_NAME(IROR_R)
|
||||
INST_NAME(IROL_R)
|
||||
INST_NAME(ISWAP_R)
|
||||
|
||||
//Common floating point
|
||||
@ -366,8 +364,6 @@ namespace RandomX {
|
||||
|
||||
//Floating point group E
|
||||
INST_NAME(FMUL_R)
|
||||
INST_NAME(FMUL_M)
|
||||
INST_NAME(FDIV_R)
|
||||
INST_NAME(FDIV_M)
|
||||
INST_NAME(FSQRT_R)
|
||||
|
||||
@ -377,7 +373,6 @@ namespace RandomX {
|
||||
INST_NAME(CFROUND)
|
||||
|
||||
INST_NAME(ISTORE)
|
||||
INST_NAME(FSTORE)
|
||||
|
||||
INST_NAME(NOP)
|
||||
};
|
||||
@ -397,7 +392,6 @@ namespace RandomX {
|
||||
INST_HANDLE(ISMULH_R)
|
||||
INST_HANDLE(ISMULH_M)
|
||||
INST_HANDLE(IMUL_RCP)
|
||||
INST_HANDLE(ISDIV_C)
|
||||
INST_HANDLE(INEG_R)
|
||||
INST_HANDLE(IXOR_R)
|
||||
INST_HANDLE(IXOR_M)
|
||||
@ -417,8 +411,6 @@ namespace RandomX {
|
||||
|
||||
//Floating point group E
|
||||
INST_HANDLE(FMUL_R)
|
||||
INST_HANDLE(FMUL_M)
|
||||
INST_HANDLE(FDIV_R)
|
||||
INST_HANDLE(FDIV_M)
|
||||
INST_HANDLE(FSQRT_R)
|
||||
|
||||
@ -428,7 +420,6 @@ namespace RandomX {
|
||||
INST_HANDLE(CFROUND)
|
||||
|
||||
INST_HANDLE(ISTORE)
|
||||
INST_HANDLE(FSTORE)
|
||||
|
||||
INST_HANDLE(NOP)
|
||||
};
|
||||
|
@ -68,7 +68,7 @@ namespace RandomX {
|
||||
|
||||
void InterpretedVirtualMachine::initialize() {
|
||||
VirtualMachine::initialize();
|
||||
for (unsigned i = 0; i < ProgramLength; ++i) {
|
||||
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
program(i).src %= RegistersCount;
|
||||
program(i).dst %= RegistersCount;
|
||||
}
|
||||
@ -81,7 +81,7 @@ namespace RandomX {
|
||||
}
|
||||
|
||||
template<>
|
||||
void InterpretedVirtualMachine::executeBytecode<ProgramLength>(int_reg_t(&r)[8], __m128d (&f)[4], __m128d (&e)[4], __m128d (&a)[4]) {
|
||||
void InterpretedVirtualMachine::executeBytecode<RANDOMX_PROGRAM_SIZE>(int_reg_t(&r)[8], __m128d (&f)[4], __m128d (&e)[4], __m128d (&a)[4]) {
|
||||
}
|
||||
|
||||
static void print(int_reg_t r) {
|
||||
@ -299,7 +299,7 @@ namespace RandomX {
|
||||
printState(r, f, e, a);
|
||||
}
|
||||
|
||||
for(unsigned iter = 0; iter < InstructionCount; ++iter) {
|
||||
for(unsigned ic = 0; ic < RANDOMX_PROGRAM_ITERATIONS; ++ic) {
|
||||
//std::cout << "Iteration " << iter << std::endl;
|
||||
uint64_t spMix = r[readReg0] ^ r[readReg1];
|
||||
spAddr0 ^= spMix;
|
||||
@ -326,7 +326,7 @@ namespace RandomX {
|
||||
e[3] = ieee_set_exponent<-240>(load_cvt_i32x2(scratchpad + spAddr1 + 56));
|
||||
|
||||
if (trace) {
|
||||
std::cout << "iteration " << std::dec << iter << std::endl;
|
||||
std::cout << "iteration " << std::dec << ic << std::endl;
|
||||
std::cout << "spAddr " << std::hex << std::setw(8) << std::setfill('0') << spAddr1 << " / " << std::setw(8) << std::setfill('0') << spAddr0 << std::endl;
|
||||
std::cout << "ma/mx " << std::hex << std::setw(8) << std::setfill('0') << mem.ma << std::setw(8) << std::setfill('0') << mem.mx << std::endl;
|
||||
printState(r, f, e, a);
|
||||
@ -357,7 +357,7 @@ namespace RandomX {
|
||||
}
|
||||
|
||||
if (trace) {
|
||||
std::cout << "iteration " << std::dec << iter << std::endl;
|
||||
std::cout << "iteration " << std::dec << ic << std::endl;
|
||||
std::cout << "spAddr " << std::hex << std::setw(8) << std::setfill('0') << spAddr1 << " / " << std::setw(8) << std::setfill('0') << spAddr0 << std::endl;
|
||||
std::cout << "ma/mx " << std::hex << std::setw(8) << std::setfill('0') << mem.ma << std::setw(8) << std::setfill('0') << mem.mx << std::endl;
|
||||
printState(r, f, e, a);
|
||||
@ -421,7 +421,7 @@ namespace RandomX {
|
||||
#include "instructionWeights.hpp"
|
||||
|
||||
void InterpretedVirtualMachine::precompileProgram(int_reg_t(&r)[8], __m128d (&f)[4], __m128d (&e)[4], __m128d (&a)[4]) {
|
||||
for (unsigned i = 0; i < ProgramLength; ++i) {
|
||||
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
auto& instr = program(i);
|
||||
auto& ibc = byteCode[i];
|
||||
switch (instr.opcode) {
|
||||
@ -593,10 +593,6 @@ namespace RandomX {
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE_REP(ISDIV_C) {
|
||||
ibc.type = InstructionType::NOP;
|
||||
} break;
|
||||
|
||||
CASE_REP(INEG_R) {
|
||||
auto dst = instr.dst % RegistersCount;
|
||||
ibc.type = InstructionType::INEG_R;
|
||||
@ -731,12 +727,6 @@ namespace RandomX {
|
||||
ibc.fsrc = &a[src];
|
||||
} break;
|
||||
|
||||
CASE_REP(FMUL_M) {
|
||||
} break;
|
||||
|
||||
CASE_REP(FDIV_R) {
|
||||
} break;
|
||||
|
||||
CASE_REP(FDIV_M) {
|
||||
auto dst = instr.dst % 4;
|
||||
auto src = instr.src % 8;
|
||||
@ -789,9 +779,6 @@ namespace RandomX {
|
||||
ibc.memMask = ((instr.mod % 4) ? ScratchpadL1Mask : ScratchpadL2Mask);
|
||||
} break;
|
||||
|
||||
CASE_REP(FSTORE) {
|
||||
} break;
|
||||
|
||||
CASE_REP(NOP) {
|
||||
ibc.type = InstructionType::NOP;
|
||||
} break;
|
||||
|
@ -79,7 +79,7 @@ namespace RandomX {
|
||||
static InstructionHandler engine[256];
|
||||
DatasetReadFunc readDataset;
|
||||
bool softAes, asyncWorker;
|
||||
InstructionByteCode byteCode[ProgramLength];
|
||||
InstructionByteCode byteCode[RANDOMX_PROGRAM_SIZE];
|
||||
|
||||
#ifdef STATS
|
||||
int count_ADD_64 = 0;
|
||||
|
@ -195,7 +195,7 @@ namespace RandomX {
|
||||
emitByte(0xc0 + readReg1);
|
||||
memcpy(code + codePos, codeLoopLoad, loopLoadSize);
|
||||
codePos += loopLoadSize;
|
||||
for (unsigned i = 0; i < ProgramLength; ++i) {
|
||||
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
Instruction& instr = prog(i);
|
||||
instr.src %= RegistersCount;
|
||||
instr.dst %= RegistersCount;
|
||||
@ -658,7 +658,6 @@ namespace RandomX {
|
||||
INST_HANDLE(ISMULH_R)
|
||||
INST_HANDLE(ISMULH_M)
|
||||
INST_HANDLE(IMUL_RCP)
|
||||
INST_HANDLE(ISDIV_C)
|
||||
INST_HANDLE(INEG_R)
|
||||
INST_HANDLE(IXOR_R)
|
||||
INST_HANDLE(IXOR_M)
|
||||
@ -672,15 +671,12 @@ namespace RandomX {
|
||||
INST_HANDLE(FSUB_M)
|
||||
INST_HANDLE(FSCAL_R)
|
||||
INST_HANDLE(FMUL_R)
|
||||
INST_HANDLE(FMUL_M)
|
||||
INST_HANDLE(FDIV_R)
|
||||
INST_HANDLE(FDIV_M)
|
||||
INST_HANDLE(FSQRT_R)
|
||||
INST_HANDLE(COND_R)
|
||||
INST_HANDLE(COND_M)
|
||||
INST_HANDLE(CFROUND)
|
||||
INST_HANDLE(ISTORE)
|
||||
INST_HANDLE(FSTORE)
|
||||
INST_HANDLE(NOP)
|
||||
};
|
||||
|
||||
|
@ -22,7 +22,7 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
|
||||
namespace RandomX {
|
||||
void Program::print(std::ostream& os) const {
|
||||
for (int i = 0; i < RandomX::ProgramLength; ++i) {
|
||||
for (int i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
auto instr = programBuffer[i];
|
||||
os << instr;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ namespace RandomX {
|
||||
private:
|
||||
void print(std::ostream&) const;
|
||||
uint64_t entropyBuffer[16];
|
||||
Instruction programBuffer[ProgramLength];
|
||||
Instruction programBuffer[RANDOMX_PROGRAM_SIZE];
|
||||
};
|
||||
|
||||
static_assert(sizeof(Program) % 64 == 0, "Invalid size of class Program");
|
||||
|
@ -22,30 +22,43 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include "blake2/endian.h"
|
||||
#include "configuration.h"
|
||||
|
||||
namespace RandomX {
|
||||
|
||||
static_assert((RANDOMX_ARGON_MEMORY & (RANDOMX_ARGON_MEMORY - 1)) == 0, "RANDOMX_ARGON_MEMORY must be a power of 2.");
|
||||
static_assert((RANDOMX_DATASET_SIZE & (RANDOMX_DATASET_SIZE - 1)) == 0, "RANDOMX_DATASET_SIZE must be a power of 2.");
|
||||
static_assert(RANDOMX_DATASET_SIZE <= 4294967296ULL, "RANDOMX_DATASET_SIZE must not exceed 4294967296.");
|
||||
static_assert(RANDOMX_DS_GROWTH_RATE % 64 == 0, "RANDOMX_DS_GROWTH_RATE must be divisible by 64.");
|
||||
static_assert(RANDOMX_PROGRAM_SIZE > 0, "RANDOMX_PROGRAM_SIZE must be greater than 0");
|
||||
static_assert(RANDOMX_PROGRAM_ITERATIONS > 0, "RANDOMX_PROGRAM_ITERATIONS must be greater than 0");
|
||||
static_assert(RANDOMX_PROGRAM_COUNT > 0, "RANDOMX_PROGRAM_COUNT must be greater than 0");
|
||||
static_assert((RANDOMX_SCRATCHPAD_L3 & (RANDOMX_SCRATCHPAD_L3 - 1)) == 0, "RANDOMX_SCRATCHPAD_L3 must be a power of 2.");
|
||||
static_assert(RANDOMX_SCRATCHPAD_L3 >= RANDOMX_SCRATCHPAD_L2, "RANDOMX_SCRATCHPAD_L3 must be greater than or equal to RANDOMX_SCRATCHPAD_L2.");
|
||||
static_assert((RANDOMX_SCRATCHPAD_L2 & (RANDOMX_SCRATCHPAD_L2 - 1)) == 0, "RANDOMX_SCRATCHPAD_L2 must be a power of 2.");
|
||||
static_assert(RANDOMX_SCRATCHPAD_L2 >= RANDOMX_SCRATCHPAD_L1, "RANDOMX_SCRATCHPAD_L2 must be greater than or equal to RANDOMX_SCRATCHPAD_L1.");
|
||||
static_assert((RANDOMX_SCRATCHPAD_L1 & (RANDOMX_SCRATCHPAD_L1 - 1)) == 0, "RANDOMX_SCRATCHPAD_L1 must be a power of 2.");
|
||||
static_assert(RANDOMX_CACHE_ACCESSES > 1, "RANDOMX_CACHE_ACCESSES must be greater than 1");
|
||||
|
||||
constexpr int wtSum = RANDOMX_FREQ_IADD_R + RANDOMX_FREQ_IADD_M + RANDOMX_FREQ_IADD_RC + RANDOMX_FREQ_ISUB_R + \
|
||||
RANDOMX_FREQ_ISUB_M + RANDOMX_FREQ_IMUL_9C + RANDOMX_FREQ_IMUL_R + RANDOMX_FREQ_IMUL_M + RANDOMX_FREQ_IMULH_R + \
|
||||
RANDOMX_FREQ_IMULH_M + RANDOMX_FREQ_ISMULH_R + RANDOMX_FREQ_ISMULH_M + RANDOMX_FREQ_IMUL_RCP + \
|
||||
RANDOMX_FREQ_INEG_R + RANDOMX_FREQ_IXOR_R + RANDOMX_FREQ_IXOR_M + RANDOMX_FREQ_IROR_R + RANDOMX_FREQ_ISWAP_R + \
|
||||
RANDOMX_FREQ_FSWAP_R + RANDOMX_FREQ_FADD_R + RANDOMX_FREQ_FADD_M + RANDOMX_FREQ_FSUB_R + RANDOMX_FREQ_FSUB_M + \
|
||||
RANDOMX_FREQ_FSCAL_R + RANDOMX_FREQ_FMUL_R + RANDOMX_FREQ_FDIV_M + RANDOMX_FREQ_FSQRT_R + RANDOMX_FREQ_COND_R + \
|
||||
RANDOMX_FREQ_COND_M + RANDOMX_FREQ_CFROUND + RANDOMX_FREQ_ISTORE + RANDOMX_FREQ_NOP;
|
||||
|
||||
static_assert(wtSum == 256, "Sum of instruction frequencies must be 256.");
|
||||
|
||||
using addr_t = uint32_t;
|
||||
|
||||
constexpr int SeedSize = 32;
|
||||
constexpr int ResultSize = 64;
|
||||
|
||||
constexpr int ArgonIterations = 3;
|
||||
constexpr uint32_t ArgonMemorySize = 262144; //KiB
|
||||
constexpr int ArgonLanes = 1;
|
||||
const char ArgonSalt[] = "Monero\x1A$";
|
||||
constexpr int ArgonSaltSize = sizeof(ArgonSalt) - 1;
|
||||
|
||||
constexpr int ArgonSaltSize = sizeof(RANDOMX_ARGON_SALT) - 1;
|
||||
constexpr int CacheLineSize = 64;
|
||||
|
||||
constexpr uint64_t DatasetSize = 4ULL * 1024 * 1024 * 1024; //4 GiB
|
||||
constexpr uint32_t CacheLineAlignMask = (DatasetSize - 1) & ~(CacheLineSize - 1);
|
||||
constexpr uint32_t CacheSize = ArgonMemorySize * 1024;
|
||||
constexpr uint32_t CacheLineAlignMask = (RANDOMX_DATASET_SIZE - 1) & ~(CacheLineSize - 1);
|
||||
constexpr uint32_t CacheSize = RANDOMX_ARGON_MEMORY * 1024;
|
||||
constexpr int CacheBlockCount = CacheSize / CacheLineSize;
|
||||
constexpr int DatasetExpansionRatio = DatasetSize / CacheSize;
|
||||
constexpr int DatasetBlockCount = DatasetExpansionRatio * CacheBlockCount;
|
||||
constexpr int DatasetIterations = DatasetExpansionRatio;
|
||||
|
||||
|
||||
#ifdef TRACE
|
||||
constexpr bool trace = true;
|
||||
@ -70,29 +83,19 @@ namespace RandomX {
|
||||
double hi;
|
||||
};
|
||||
|
||||
constexpr int ProgramLength = 256;
|
||||
constexpr uint32_t InstructionCount = 2048;
|
||||
constexpr int ChainLength = 8;
|
||||
constexpr uint32_t ScratchpadSize = 2 * 1024 * 1024;
|
||||
constexpr uint32_t ScratchpadLength = ScratchpadSize / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL1 = ScratchpadSize / 128 / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL2 = ScratchpadSize / 8 / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL3 = ScratchpadSize / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL1 = RANDOMX_SCRATCHPAD_L1 / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL2 = RANDOMX_SCRATCHPAD_L2 / sizeof(int_reg_t);
|
||||
constexpr uint32_t ScratchpadL3 = RANDOMX_SCRATCHPAD_L3 / sizeof(int_reg_t);
|
||||
constexpr int ScratchpadL1Mask = (ScratchpadL1 - 1) * 8;
|
||||
constexpr int ScratchpadL2Mask = (ScratchpadL2 - 1) * 8;
|
||||
constexpr int ScratchpadL1Mask16 = (ScratchpadL1 / 2 - 1) * 16;
|
||||
constexpr int ScratchpadL2Mask16 = (ScratchpadL2 / 2 - 1) * 16;
|
||||
constexpr int ScratchpadL3Mask = (ScratchpadLength - 1) * 8;
|
||||
constexpr int ScratchpadL3Mask64 = (ScratchpadLength / 8 - 1) * 64;
|
||||
constexpr uint32_t TransformationCount = 90;
|
||||
constexpr int ScratchpadL3Mask = (ScratchpadL3 - 1) * 8;
|
||||
constexpr int ScratchpadL3Mask64 = (ScratchpadL3 / 8 - 1) * 64;
|
||||
constexpr int RegistersCount = 8;
|
||||
|
||||
class Cache;
|
||||
|
||||
inline int wrapInstr(int i) {
|
||||
return i % RandomX::ProgramLength;
|
||||
}
|
||||
|
||||
class ILightClientAsyncWorker {
|
||||
public:
|
||||
virtual ~ILightClientAsyncWorker() {}
|
||||
@ -120,8 +123,6 @@ namespace RandomX {
|
||||
dataset_t ds;
|
||||
};
|
||||
|
||||
static_assert(sizeof(MemoryRegisters) == 2 * sizeof(addr_t) + sizeof(uintptr_t), "Invalid alignment of struct RandomX::MemoryRegisters");
|
||||
|
||||
struct RegisterFile {
|
||||
int_reg_t r[RegistersCount];
|
||||
fpu_reg_t f[RegistersCount / 2];
|
||||
@ -129,15 +130,9 @@ namespace RandomX {
|
||||
fpu_reg_t a[RegistersCount / 2];
|
||||
};
|
||||
|
||||
static_assert(sizeof(RegisterFile) == 256, "Invalid alignment of struct RandomX::RegisterFile");
|
||||
|
||||
typedef void(*DatasetReadFunc)(addr_t, MemoryRegisters&, int_reg_t(®)[RegistersCount]);
|
||||
|
||||
typedef void(*ProgramFunc)(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t);
|
||||
|
||||
extern "C" {
|
||||
void executeProgram(RegisterFile&, MemoryRegisters&, uint8_t* /* scratchpad */, uint64_t);
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const RandomX::RegisterFile& rf);
|
||||
|
101
src/configuration.h
Normal file
101
src/configuration.h
Normal file
@ -0,0 +1,101 @@
|
||||
/*
|
||||
Copyright (c) 2019 tevador
|
||||
|
||||
This file is part of RandomX.
|
||||
|
||||
RandomX is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
RandomX is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
//Cache size in KiB. Must be a power of 2.
|
||||
#define RANDOMX_ARGON_MEMORY (256 * 1024)
|
||||
|
||||
//Number of Argon2d iterations for Cache initialization
|
||||
#define RANDOMX_ARGON_ITERATIONS 3
|
||||
|
||||
//Number of parallel lanes for Cache initialization
|
||||
#define RANDOMX_ARGON_LANES 1
|
||||
|
||||
//Argon2d salt
|
||||
#define RANDOMX_ARGON_SALT "RandomX\x03"
|
||||
|
||||
//Number of random Cache accesses per Dataset block. Minimum is 2.
|
||||
#define RANDOMX_CACHE_ACCESSES 16
|
||||
|
||||
//Dataset size in bytes. Must be a power of 2.
|
||||
#define RANDOMX_DATASET_SIZE (4ULL * 1024 * 1024 * 1024)
|
||||
|
||||
//Dataset growth per epoch in bytes. Must be divisible by 64.
|
||||
#define RANDOMX_DS_GROWTH_RATE (2 * 1024 * 1024)
|
||||
|
||||
//Number of instructions in a RandomX program
|
||||
#define RANDOMX_PROGRAM_SIZE 256
|
||||
|
||||
//Number of iterations during VM execution
|
||||
#define RANDOMX_PROGRAM_ITERATIONS 2048
|
||||
|
||||
//Number of chained VM executions per hash
|
||||
#define RANDOMX_PROGRAM_COUNT 8
|
||||
|
||||
//Scratchpad L3 size in bytes. Must be a power of 2.
|
||||
#define RANDOMX_SCRATCHPAD_L3 (2 * 1024 * 1024)
|
||||
|
||||
//Scratchpad L2 size in bytes. Must be a power of two and less than or equal to RANDOMX_SCRATCHPAD_L3.
|
||||
#define RANDOMX_SCRATCHPAD_L2 (256 * 1024)
|
||||
|
||||
//Scratchpad L1 size in bytes. Must be a power of two and less than or equal to RANDOMX_SCRATCHPAD_L2.
|
||||
#define RANDOMX_SCRATCHPAD_L1 (16 * 1024)
|
||||
|
||||
/*
|
||||
Instruction frequencies (per 256 opcodes)
|
||||
Total sum of frequencies must be 256
|
||||
*/
|
||||
|
||||
#define RANDOMX_FREQ_IADD_R 12
|
||||
#define RANDOMX_FREQ_IADD_M 7
|
||||
#define RANDOMX_FREQ_IADD_RC 16
|
||||
#define RANDOMX_FREQ_ISUB_R 12
|
||||
#define RANDOMX_FREQ_ISUB_M 7
|
||||
#define RANDOMX_FREQ_IMUL_9C 9
|
||||
#define RANDOMX_FREQ_IMUL_R 16
|
||||
#define RANDOMX_FREQ_IMUL_M 4
|
||||
#define RANDOMX_FREQ_IMULH_R 4
|
||||
#define RANDOMX_FREQ_IMULH_M 1
|
||||
#define RANDOMX_FREQ_ISMULH_R 4
|
||||
#define RANDOMX_FREQ_ISMULH_M 1
|
||||
#define RANDOMX_FREQ_IMUL_RCP 8
|
||||
#define RANDOMX_FREQ_INEG_R 2
|
||||
#define RANDOMX_FREQ_IXOR_R 16
|
||||
#define RANDOMX_FREQ_IXOR_M 4
|
||||
#define RANDOMX_FREQ_IROR_R 10
|
||||
#define RANDOMX_FREQ_IROL_R 0
|
||||
#define RANDOMX_FREQ_ISWAP_R 4
|
||||
|
||||
#define RANDOMX_FREQ_FSWAP_R 8
|
||||
#define RANDOMX_FREQ_FADD_R 20
|
||||
#define RANDOMX_FREQ_FADD_M 5
|
||||
#define RANDOMX_FREQ_FSUB_R 20
|
||||
#define RANDOMX_FREQ_FSUB_M 5
|
||||
#define RANDOMX_FREQ_FSCAL_R 6
|
||||
#define RANDOMX_FREQ_FMUL_R 20
|
||||
#define RANDOMX_FREQ_FDIV_M 4
|
||||
#define RANDOMX_FREQ_FSQRT_R 6
|
||||
|
||||
#define RANDOMX_FREQ_COND_R 7
|
||||
#define RANDOMX_FREQ_COND_M 1
|
||||
#define RANDOMX_FREQ_CFROUND 1
|
||||
#define RANDOMX_FREQ_ISTORE 16
|
||||
|
||||
#define RANDOMX_FREQ_NOP 0
|
@ -47,7 +47,7 @@ namespace RandomX {
|
||||
|
||||
constexpr uint32_t mask = (CacheSize - 1) & CacheLineAlignMask;
|
||||
|
||||
for (auto i = 0; i < DatasetIterations; ++i) {
|
||||
for (auto i = 0; i < RANDOMX_CACHE_ACCESSES; ++i) {
|
||||
const uint8_t* mixBlock = cache + (c0 & mask);
|
||||
PREFETCHNTA(mixBlock);
|
||||
c0 = squareHash(c0);
|
||||
@ -103,14 +103,14 @@ namespace RandomX {
|
||||
aw->prepareBlock(memory.ma);
|
||||
}
|
||||
|
||||
void datasetAlloc(dataset_t& ds, bool largePages) {
|
||||
void datasetAlloc(dataset_t& ds, uint64_t size, bool largePages) {
|
||||
if (sizeof(size_t) <= 4)
|
||||
throw std::runtime_error("Platform doesn't support enough memory for the dataset");
|
||||
if (largePages) {
|
||||
ds.dataset = (uint8_t*)allocLargePagesMemory(DatasetSize);
|
||||
ds.dataset = (uint8_t*)allocLargePagesMemory(size);
|
||||
}
|
||||
else {
|
||||
ds.dataset = (uint8_t*)_mm_malloc(DatasetSize, 64);
|
||||
ds.dataset = (uint8_t*)_mm_malloc(size, 64);
|
||||
if (ds.dataset == nullptr) {
|
||||
throw std::runtime_error("Dataset memory allocation failed. >4 GiB of free virtual memory is needed.");
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ namespace RandomX {
|
||||
|
||||
void initBlock(const uint8_t* cache, uint8_t* block, uint32_t blockNumber);
|
||||
|
||||
void datasetAlloc(dataset_t& ds, bool largePages);
|
||||
void datasetAlloc(dataset_t& ds, uint64_t size, bool largePages);
|
||||
|
||||
void datasetInit(Cache* cache, dataset_t ds, uint32_t startBlock, uint32_t blockCount);
|
||||
|
||||
|
@ -19,67 +19,6 @@ along with RandomX. If not, see<http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
//Integer
|
||||
#define WT_IADD_R 12
|
||||
#define WT_IADD_M 7
|
||||
#define WT_IADD_RC 16
|
||||
#define WT_ISUB_R 12
|
||||
#define WT_ISUB_M 7
|
||||
#define WT_IMUL_9C 9
|
||||
#define WT_IMUL_R 16
|
||||
#define WT_IMUL_M 4
|
||||
#define WT_IMULH_R 4
|
||||
#define WT_IMULH_M 1
|
||||
#define WT_ISMULH_R 4
|
||||
#define WT_ISMULH_M 1
|
||||
#define WT_IMUL_RCP 8
|
||||
#define WT_ISDIV_C 0
|
||||
#define WT_INEG_R 2
|
||||
#define WT_IXOR_R 16
|
||||
#define WT_IXOR_M 4
|
||||
#define WT_IROR_R 10
|
||||
#define WT_IROL_R 0
|
||||
#define WT_ISWAP_R 4
|
||||
|
||||
//Common floating point
|
||||
#define WT_FSWAP_R 8
|
||||
|
||||
//Floating point group F
|
||||
#define WT_FADD_R 20
|
||||
#define WT_FADD_M 5
|
||||
#define WT_FSUB_R 20
|
||||
#define WT_FSUB_M 5
|
||||
#define WT_FSCAL_R 6
|
||||
|
||||
//Floating point group E
|
||||
#define WT_FMUL_R 20
|
||||
#define WT_FMUL_M 0
|
||||
#define WT_FDIV_R 0
|
||||
#define WT_FDIV_M 4
|
||||
#define WT_FSQRT_R 6
|
||||
|
||||
//Control
|
||||
#define WT_COND_R 7
|
||||
#define WT_COND_M 1
|
||||
#define WT_CFROUND 1
|
||||
|
||||
//Store
|
||||
#define WT_ISTORE 16
|
||||
#define WT_FSTORE 0
|
||||
|
||||
#define WT_NOP 0
|
||||
|
||||
constexpr int wtSum = WT_IADD_R + WT_IADD_M + WT_IADD_RC + WT_ISUB_R + \
|
||||
WT_ISUB_M + WT_IMUL_9C + WT_IMUL_R + WT_IMUL_M + WT_IMULH_R + \
|
||||
WT_IMULH_M + WT_ISMULH_R + WT_ISMULH_M + WT_IMUL_RCP + WT_ISDIV_C + \
|
||||
WT_INEG_R + WT_IXOR_R + WT_IXOR_M + WT_IROR_R + WT_IROL_R + \
|
||||
WT_ISWAP_R + WT_FSWAP_R + WT_FADD_R + WT_FADD_M + WT_FSUB_R + WT_FSUB_M + \
|
||||
WT_FSCAL_R + WT_FMUL_R + WT_FMUL_M + WT_FDIV_R + WT_FDIV_M + \
|
||||
WT_FSQRT_R + WT_COND_R + WT_COND_M + WT_CFROUND + WT_ISTORE + WT_FSTORE + WT_NOP;
|
||||
|
||||
static_assert(wtSum == 256,
|
||||
"Sum of instruction weights must be 256");
|
||||
|
||||
#define REP0(x)
|
||||
#define REP1(x) x,
|
||||
#define REP2(x) REP1(x) x,
|
||||
@ -121,7 +60,7 @@ static_assert(wtSum == 256,
|
||||
#define REPNX(x,N) REP##N(x)
|
||||
#define REPN(x,N) REPNX(x,N)
|
||||
#define NUM(x) x
|
||||
#define WT(x) NUM(WT_##x)
|
||||
#define WT(x) NUM(RANDOMX_FREQ_##x)
|
||||
|
||||
#define REPCASE0(x)
|
||||
#define REPCASE1(x) case __COUNTER__:
|
||||
|
35
src/main.cpp
35
src/main.cpp
@ -132,8 +132,8 @@ void generateAsm(uint32_t nonce) {
|
||||
memcpy(blockTemplate, blockTemplate__, sizeof(blockTemplate));
|
||||
store32(blockTemplate + 39, nonce);
|
||||
blake2b(hash, sizeof(hash), blockTemplate, sizeof(blockTemplate), nullptr, 0);
|
||||
uint8_t scratchpad[RandomX::ScratchpadSize];
|
||||
fillAes1Rx4<softAes>((void*)hash, RandomX::ScratchpadSize, scratchpad);
|
||||
uint8_t scratchpad[RANDOMX_SCRATCHPAD_L3];
|
||||
fillAes1Rx4<softAes>((void*)hash, RANDOMX_SCRATCHPAD_L3, scratchpad);
|
||||
RandomX::AssemblyGeneratorX86 asmX86;
|
||||
RandomX::Program p;
|
||||
fillAes1Rx4<softAes>(hash, sizeof(p), &p);
|
||||
@ -148,11 +148,11 @@ void generateNative(uint32_t nonce) {
|
||||
memcpy(blockTemplate, blockTemplate__, sizeof(blockTemplate));
|
||||
store32(blockTemplate + 39, nonce);
|
||||
blake2b(hash, sizeof(hash), blockTemplate, sizeof(blockTemplate), nullptr, 0);
|
||||
uint8_t scratchpad[RandomX::ScratchpadSize];
|
||||
fillAes1Rx4<softAes>((void*)hash, RandomX::ScratchpadSize, scratchpad);
|
||||
uint8_t scratchpad[RANDOMX_SCRATCHPAD_L3];
|
||||
fillAes1Rx4<softAes>((void*)hash, RANDOMX_SCRATCHPAD_L3, scratchpad);
|
||||
alignas(16) RandomX::Program prog;
|
||||
fillAes1Rx4<softAes>((void*)hash, sizeof(prog), &prog);
|
||||
for (int i = 0; i < RandomX::ProgramLength; ++i) {
|
||||
for (int i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
prog(i).dst %= 8;
|
||||
prog(i).src %= 8;
|
||||
}
|
||||
@ -171,11 +171,11 @@ void mine(RandomX::VirtualMachine* vm, std::atomic<uint32_t>& atomicNonce, Atomi
|
||||
//std::cout << "Thread " << thread << " nonce " << nonce << std::endl;
|
||||
store32(noncePtr, nonce);
|
||||
blake2b(hash, sizeof(hash), blockTemplate, sizeof(blockTemplate), nullptr, 0);
|
||||
fillAes1Rx4<softAes>((void*)hash, RandomX::ScratchpadSize, scratchpad);
|
||||
fillAes1Rx4<softAes>((void*)hash, RANDOMX_SCRATCHPAD_L3, scratchpad);
|
||||
vm->resetRoundingMode();
|
||||
vm->setScratchpad(scratchpad);
|
||||
//dump((char*)scratchpad, RandomX::ScratchpadSize, "spad-before.txt");
|
||||
for (int chain = 0; chain < RandomX::ChainLength - 1; ++chain) {
|
||||
for (int chain = 0; chain < RANDOMX_PROGRAM_COUNT - 1; ++chain) {
|
||||
fillAes1Rx4<softAes>((void*)hash, sizeof(RandomX::Program), vm->getProgramBuffer());
|
||||
vm->initialize();
|
||||
vm->execute();
|
||||
@ -190,7 +190,7 @@ void mine(RandomX::VirtualMachine* vm, std::atomic<uint32_t>& atomicNonce, Atomi
|
||||
std::cout << std::hex << std::setw(16) << std::setfill('0') << res << std::endl;
|
||||
}
|
||||
}*/
|
||||
vm->getResult<softAes>(scratchpad, RandomX::ScratchpadSize, hash);
|
||||
vm->getResult<softAes>(scratchpad, RANDOMX_SCRATCHPAD_L3, hash);
|
||||
result.xorWith(hash);
|
||||
if (RandomX::trace) {
|
||||
std::cout << "Nonce: " << nonce << " ";
|
||||
@ -267,10 +267,11 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
else {
|
||||
RandomX::Cache* cache = dataset.cache;
|
||||
RandomX::datasetAlloc(dataset, largePages);
|
||||
RandomX::datasetAlloc(dataset, RANDOMX_DATASET_SIZE, largePages);
|
||||
const uint64_t datasetBlockCount = RANDOMX_DATASET_SIZE / RandomX::CacheLineSize;
|
||||
if (initThreadCount > 1) {
|
||||
auto perThread = RandomX::DatasetBlockCount / initThreadCount;
|
||||
auto remainder = RandomX::DatasetBlockCount % initThreadCount;
|
||||
auto perThread = datasetBlockCount / initThreadCount;
|
||||
auto remainder = datasetBlockCount % initThreadCount;
|
||||
for (int i = 0; i < initThreadCount; ++i) {
|
||||
auto count = perThread + (i == initThreadCount - 1 ? remainder : 0);
|
||||
threads.push_back(std::thread(&RandomX::datasetInit, cache, dataset, i * perThread, count));
|
||||
@ -280,7 +281,7 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
}
|
||||
else {
|
||||
RandomX::datasetInit(cache, dataset, 0, RandomX::DatasetBlockCount);
|
||||
RandomX::datasetInit(cache, dataset, 0, datasetBlockCount);
|
||||
}
|
||||
RandomX::Cache::dealloc(cache, largePages);
|
||||
threads.clear();
|
||||
@ -300,19 +301,19 @@ int main(int argc, char** argv) {
|
||||
}
|
||||
uint8_t* scratchpadMem;
|
||||
if (largePages) {
|
||||
scratchpadMem = (uint8_t*)allocLargePagesMemory(threadCount * RandomX::ScratchpadSize);
|
||||
scratchpadMem = (uint8_t*)allocLargePagesMemory(threadCount * RANDOMX_SCRATCHPAD_L3);
|
||||
}
|
||||
else {
|
||||
scratchpadMem = (uint8_t*)_mm_malloc(threadCount * RandomX::ScratchpadSize, RandomX::CacheLineSize);
|
||||
scratchpadMem = (uint8_t*)_mm_malloc(threadCount * RANDOMX_SCRATCHPAD_L3, RandomX::CacheLineSize);
|
||||
}
|
||||
std::cout << "Running benchmark (" << programCount << " nonces) ..." << std::endl;
|
||||
sw.restart();
|
||||
if (threadCount > 1) {
|
||||
for (unsigned i = 0; i < vms.size(); ++i) {
|
||||
if (softAes)
|
||||
threads.push_back(std::thread(&mine<true>, vms[i], std::ref(atomicNonce), std::ref(result), programCount, i, scratchpadMem + RandomX::ScratchpadSize * i));
|
||||
threads.push_back(std::thread(&mine<true>, vms[i], std::ref(atomicNonce), std::ref(result), programCount, i, scratchpadMem + RANDOMX_SCRATCHPAD_L3 * i));
|
||||
else
|
||||
threads.push_back(std::thread(&mine<false>, vms[i], std::ref(atomicNonce), std::ref(result), programCount, i, scratchpadMem + RandomX::ScratchpadSize * i));
|
||||
threads.push_back(std::thread(&mine<false>, vms[i], std::ref(atomicNonce), std::ref(result), programCount, i, scratchpadMem + RANDOMX_SCRATCHPAD_L3 * i));
|
||||
}
|
||||
for (unsigned i = 0; i < threads.size(); ++i) {
|
||||
threads[i].join();
|
||||
@ -330,7 +331,7 @@ int main(int argc, char** argv) {
|
||||
std::cout << "Calculated result: ";
|
||||
result.print(std::cout);
|
||||
if(programCount == 1000)
|
||||
std::cout << "Reference result: e1b4144293ff9ab5aa4c98f2389bb18950d8c3fd874891ac64628e028a286006" << std::endl;
|
||||
std::cout << "Reference result: 128599cc10f9f6251e7917fa1d09ab2116ab4081bf1357149bd4054275dd8ee9" << std::endl;
|
||||
if (!miningMode) {
|
||||
std::cout << "Performance: " << 1000 * elapsed / programCount << " ms per hash" << std::endl;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user