mirror of
https://git.wownero.com/wownero/RandomWOW.git
synced 2024-12-21 23:38:54 +00:00
Added performance simulation
This commit is contained in:
parent
8a5ead5ce3
commit
378d5def38
11
randomx.sln
11
randomx.sln
@ -25,6 +25,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "scratchpad-entropy", "vcxpr
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "jit-performance", "vcxproj\jit-performance.vcxproj", "{535F2111-FA81-4C76-A354-EDD2F9AA00E3}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "perf-simulation", "vcxproj\perf-simulation.vcxproj", "{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -113,6 +115,14 @@ Global
|
||||
{535F2111-FA81-4C76-A354-EDD2F9AA00E3}.Release|x64.Build.0 = Release|x64
|
||||
{535F2111-FA81-4C76-A354-EDD2F9AA00E3}.Release|x86.ActiveCfg = Release|Win32
|
||||
{535F2111-FA81-4C76-A354-EDD2F9AA00E3}.Release|x86.Build.0 = Release|Win32
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Debug|x64.Build.0 = Debug|x64
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Debug|x86.Build.0 = Debug|Win32
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Release|x64.ActiveCfg = Release|x64
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Release|x64.Build.0 = Release|x64
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Release|x86.ActiveCfg = Release|Win32
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -127,6 +137,7 @@ Global
|
||||
{3E490DEC-1874-43AA-92DA-1AC57C217EAC} = {4A4A689F-86AF-41C0-A974-1080506D0923}
|
||||
{FF8BD408-AFD8-43C6-BE98-4D03B37E840B} = {4A4A689F-86AF-41C0-A974-1080506D0923}
|
||||
{535F2111-FA81-4C76-A354-EDD2F9AA00E3} = {4A4A689F-86AF-41C0-A974-1080506D0923}
|
||||
{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2} = {4A4A689F-86AF-41C0-A974-1080506D0923}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4EBC03DB-AE37-4141-8147-692F16E0ED02}
|
||||
|
645
src/tests/perf-simulation.cpp
Normal file
645
src/tests/perf-simulation.cpp
Normal file
@ -0,0 +1,645 @@
|
||||
/*
|
||||
Copyright (c) 2018-2019, tevador <tevador@gmail.com>
|
||||
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
* Neither the name of the copyright holder nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "utility.hpp"
|
||||
#include "../common.hpp"
|
||||
#include "../aes_hash.hpp"
|
||||
#include "../program.hpp"
|
||||
#include "../blake2/blake2.h"
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
int analyze(randomx::Program& p);
|
||||
int executeInOrder(randomx::Program& p, randomx::Program& original, bool print, int executionPorts, int memoryPorts, bool speculate, int pipeline);
|
||||
int executeOutOfOrder(randomx::Program& p, randomx::Program& original, bool print, int executionPorts, int memoryPorts, bool speculate, int pipeline);
|
||||
|
||||
constexpr uint32_t DST_NOP = 0;
|
||||
constexpr uint32_t DST_INT = 1;
|
||||
constexpr uint32_t DST_FLT = 2;
|
||||
constexpr uint32_t DST_MEM = 3;
|
||||
constexpr uint32_t MASK_DST = 3;
|
||||
|
||||
constexpr uint32_t SRC_NOP = 0;
|
||||
constexpr uint32_t SRC_INT = 4;
|
||||
constexpr uint32_t SRC_FLT = 8;
|
||||
constexpr uint32_t SRC_MEM = 12;
|
||||
constexpr uint32_t MASK_SRC = 12;
|
||||
|
||||
constexpr uint32_t OP_CFROUND = 16;
|
||||
constexpr uint32_t OP_SWAP = 32;
|
||||
constexpr uint32_t OP_BRANCH = 48;
|
||||
constexpr uint32_t MASK_EXT = 48;
|
||||
|
||||
constexpr uint32_t OP_FLOAT = 64;
|
||||
constexpr uint32_t BRANCH_TARGET = 128;
|
||||
|
||||
//template<bool softAes>
|
||||
void generate(randomx::Program& p, uint32_t nonce) {
|
||||
alignas(16) uint64_t hash[8];
|
||||
blake2b(hash, sizeof(hash), &nonce, sizeof(nonce), nullptr, 0);
|
||||
fillAes1Rx4<false>((void*)hash, sizeof(p), &p);
|
||||
}
|
||||
|
||||
bool has(randomx::Instruction& instr, uint32_t mask, uint32_t prop) {
|
||||
return (instr.opcode & mask) == prop;
|
||||
}
|
||||
|
||||
bool has(randomx::Instruction& instr, uint32_t prop) {
|
||||
return (instr.opcode & prop) != 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
int nonces, seed, executionPorts, memoryPorts, pipeline;
|
||||
bool print, reorder, speculate;
|
||||
readOption("--print", argc, argv, print);
|
||||
readOption("--reorder", argc, argv, reorder);
|
||||
readOption("--speculate", argc, argv, speculate);
|
||||
readIntOption("--nonces", argc, argv, nonces, 1);
|
||||
readIntOption("--seed", argc, argv, seed, 0);
|
||||
readIntOption("--executionPorts", argc, argv, executionPorts, 4);
|
||||
readIntOption("--memoryPorts", argc, argv, memoryPorts, 2);
|
||||
readIntOption("--pipeline", argc, argv, pipeline, 3 + speculate);
|
||||
randomx::Program p, original;
|
||||
double totalCycles = 0.0;
|
||||
double jumpCount = 0;
|
||||
for (int i = 0; i < nonces; ++i) {
|
||||
generate(original, i ^ seed);
|
||||
memcpy(&p, &original, sizeof(p));
|
||||
jumpCount += analyze(p);
|
||||
totalCycles +=
|
||||
reorder
|
||||
?
|
||||
executeOutOfOrder(p, original, print, executionPorts, memoryPorts, speculate, pipeline)
|
||||
:
|
||||
executeInOrder(p, original, print, executionPorts, memoryPorts, speculate, pipeline);
|
||||
}
|
||||
totalCycles /= nonces;
|
||||
jumpCount /= nonces;
|
||||
std::cout << "Execution took " << totalCycles << " cycles per program" << std::endl;
|
||||
//std::cout << "Jump count: " << jumpCount << std::endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int executeInOrder(randomx::Program& p, randomx::Program& original, bool print, int executionPorts, int memoryPorts, bool speculate, int pipeline) {
|
||||
int cycle = pipeline - 1;
|
||||
int index = 0;
|
||||
int branchCount = 0;
|
||||
int int_reg_ready[randomx::RegistersCount] = { 0 };
|
||||
int flt_reg_ready[randomx::RegistersCount] = { 0 };
|
||||
//each workgroup takes 1 or 2 cycles (2 cycles if any instruction has a memory operand)
|
||||
while (index < RANDOMX_PROGRAM_SIZE) {
|
||||
int memoryReads = 0;
|
||||
int memoryAccesses = 0;
|
||||
bool hasRound = false;
|
||||
int workers = 0;
|
||||
//std::cout << "-----------" << std::endl;
|
||||
for (; workers < executionPorts && memoryAccesses < memoryPorts && index < RANDOMX_PROGRAM_SIZE; ++workers) {
|
||||
auto& instr = p(index);
|
||||
auto& origi = original(index);
|
||||
origi.dst %= randomx::RegistersCount;
|
||||
origi.src %= randomx::RegistersCount;
|
||||
|
||||
//check dependencies
|
||||
if (has(instr, MASK_SRC, SRC_INT) && int_reg_ready[instr.src] > cycle)
|
||||
break;
|
||||
|
||||
if (has(instr, MASK_SRC, SRC_MEM) && int_reg_ready[instr.src] > cycle)
|
||||
break;
|
||||
|
||||
if (has(instr, MASK_DST, DST_FLT) && flt_reg_ready[instr.dst] > cycle)
|
||||
break;
|
||||
|
||||
if (has(instr, MASK_DST, DST_INT) && int_reg_ready[instr.dst] > cycle)
|
||||
break;
|
||||
|
||||
if (hasRound && has(instr, OP_FLOAT))
|
||||
break;
|
||||
|
||||
//execute
|
||||
index++;
|
||||
|
||||
if (has(instr, MASK_EXT, OP_BRANCH)) {
|
||||
branchCount++;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_FLT))
|
||||
flt_reg_ready[instr.dst] = cycle + 1;
|
||||
|
||||
if (has(instr, MASK_DST, DST_INT))
|
||||
int_reg_ready[instr.dst] = cycle + 1;
|
||||
|
||||
if (has(instr, MASK_EXT, OP_SWAP)) {
|
||||
int_reg_ready[instr.src] = cycle + 1;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_EXT, OP_CFROUND))
|
||||
hasRound = true;
|
||||
|
||||
if (has(instr, MASK_SRC, SRC_MEM)) {
|
||||
memoryReads++;
|
||||
memoryAccesses++;
|
||||
if (print)
|
||||
std::cout << std::setw(2) << (cycle + 2) << ": " << origi;
|
||||
}
|
||||
else {
|
||||
if (print)
|
||||
std::cout << std::setw(2) << (cycle + 1) << ": " << origi;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_MEM)) {
|
||||
memoryAccesses++;
|
||||
}
|
||||
|
||||
//non-speculative execution must stall after branch
|
||||
if (!speculate && has(instr, MASK_EXT, OP_BRANCH)) {
|
||||
cycle += pipeline - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//std::cout << " workers: " << workers << std::endl;
|
||||
cycle++;
|
||||
if (memoryReads)
|
||||
cycle++;
|
||||
}
|
||||
if (speculate) {
|
||||
//account for mispredicted branches
|
||||
int i = 0;
|
||||
while (branchCount--) {
|
||||
auto entropy = p.getEntropy(i / 8);
|
||||
entropy >> (i % 8) * 8;
|
||||
if ((entropy & 0xff) == 0) // 1/256 chance to flush the pipeline
|
||||
cycle += pipeline - 1;
|
||||
}
|
||||
}
|
||||
return cycle;
|
||||
}
|
||||
|
||||
int executeOutOfOrder(randomx::Program& p, randomx::Program& original, bool print, int executionPorts, int memoryPorts, bool speculate, int pipeline) {
|
||||
int index = 0;
|
||||
int busyExecutionPorts[RANDOMX_PROGRAM_SIZE] = { 0 };
|
||||
int busyMemoryPorts[RANDOMX_PROGRAM_SIZE] = { 0 };
|
||||
int int_reg_ready[randomx::RegistersCount] = { 0 };
|
||||
int flt_reg_ready[randomx::RegistersCount] = { 0 };
|
||||
int fprcReady = 0;
|
||||
int lastBranch = 0;
|
||||
int branchCount = 0;
|
||||
for (; index < RANDOMX_PROGRAM_SIZE; ++index) {
|
||||
auto& instr = p(index);
|
||||
int retireCycle = pipeline - 1;
|
||||
|
||||
//non-speculative execution cannot reorder across branches
|
||||
if (!speculate && !has(instr, MASK_EXT, OP_BRANCH))
|
||||
retireCycle = std::max(lastBranch + pipeline - 1, retireCycle);
|
||||
|
||||
//check dependencies
|
||||
if (has(instr, MASK_SRC, SRC_INT)) {
|
||||
retireCycle = std::max(retireCycle, int_reg_ready[instr.src]);
|
||||
}
|
||||
|
||||
if (has(instr, MASK_SRC, SRC_MEM)) {
|
||||
retireCycle = std::max(retireCycle, int_reg_ready[instr.src]);
|
||||
//find free memory port
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyMemoryPorts[retireCycle - 1] >= memoryPorts);
|
||||
busyMemoryPorts[retireCycle - 1]++;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_FLT)) {
|
||||
retireCycle = std::max(retireCycle, flt_reg_ready[instr.dst]);
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_INT)) {
|
||||
retireCycle = std::max(retireCycle, int_reg_ready[instr.dst]);
|
||||
}
|
||||
|
||||
//floating point operations depend on the fprc register
|
||||
if (has(instr, OP_FLOAT))
|
||||
retireCycle = std::max(retireCycle, fprcReady);
|
||||
|
||||
//execute
|
||||
if (has(instr, MASK_DST, DST_MEM)) {
|
||||
//find free memory port
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyMemoryPorts[retireCycle - 1] >= memoryPorts);
|
||||
busyMemoryPorts[retireCycle - 1]++;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_FLT)) {
|
||||
//find free execution port
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyExecutionPorts[retireCycle - 1] >= executionPorts);
|
||||
busyExecutionPorts[retireCycle - 1]++;
|
||||
flt_reg_ready[instr.dst] = retireCycle;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_DST, DST_INT)) {
|
||||
//find free execution port
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyExecutionPorts[retireCycle - 1] >= executionPorts);
|
||||
busyExecutionPorts[retireCycle - 1]++;
|
||||
int_reg_ready[instr.dst] = retireCycle;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_EXT, OP_SWAP)) {
|
||||
int_reg_ready[instr.src] = retireCycle;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_EXT, OP_CFROUND)) {
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyExecutionPorts[retireCycle - 1] >= executionPorts);
|
||||
busyExecutionPorts[retireCycle - 1]++;
|
||||
fprcReady = retireCycle;
|
||||
}
|
||||
|
||||
if (has(instr, MASK_EXT, OP_BRANCH)) {
|
||||
/*if (!speculate && instr.mod == 1) { //simulated predication
|
||||
do {
|
||||
retireCycle++;
|
||||
} while (busyExecutionPorts[retireCycle - 1] >= executionPorts);
|
||||
busyExecutionPorts[retireCycle - 1]++;
|
||||
int_reg_ready[instr.dst] = retireCycle;
|
||||
}*/
|
||||
//else {
|
||||
lastBranch = std::max(lastBranch, retireCycle);
|
||||
branchCount++;
|
||||
//}
|
||||
}
|
||||
|
||||
//print
|
||||
auto& origi = original(index);
|
||||
origi.dst %= randomx::RegistersCount;
|
||||
origi.src %= randomx::RegistersCount;
|
||||
if (print) {
|
||||
std::cout << std::setw(2) << retireCycle << ": " << origi;
|
||||
if (has(instr, MASK_EXT, OP_BRANCH)) {
|
||||
std::cout << " jump: " << (int)instr.mod << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
int cycle = 0;
|
||||
for (int i = 0; i < randomx::RegistersCount; ++i) {
|
||||
cycle = std::max(cycle, int_reg_ready[i]);
|
||||
}
|
||||
for (int i = 0; i < randomx::RegistersCount; ++i) {
|
||||
cycle = std::max(cycle, flt_reg_ready[i]);
|
||||
}
|
||||
if (speculate) {
|
||||
//account for mispredicted branches
|
||||
int i = 0;
|
||||
while (branchCount--) {
|
||||
auto entropy = p.getEntropy(i / 8);
|
||||
entropy >> (i % 8) * 8;
|
||||
if ((entropy & 0xff) == 0) // 1/256 chance to flush the pipeline
|
||||
cycle += pipeline - 1;
|
||||
}
|
||||
}
|
||||
return cycle;
|
||||
}
|
||||
|
||||
#include "../instruction_weights.hpp"
|
||||
|
||||
//old register selection
|
||||
struct RegisterUsage {
|
||||
int32_t lastUsed;
|
||||
int32_t count;
|
||||
};
|
||||
|
||||
inline int getConditionRegister(RegisterUsage(®isterUsage)[randomx::RegistersCount]) {
|
||||
int min = INT_MAX;
|
||||
int minCount = 0;
|
||||
int minIndex;
|
||||
//prefer registers that have been used as a condition register fewer times
|
||||
for (unsigned i = 0; i < randomx::RegistersCount; ++i) {
|
||||
if (registerUsage[i].lastUsed < min || (registerUsage[i].lastUsed == min && registerUsage[i].count < minCount)) {
|
||||
min = registerUsage[i].lastUsed;
|
||||
minCount = registerUsage[i].count;
|
||||
minIndex = i;
|
||||
}
|
||||
}
|
||||
return minIndex;
|
||||
}
|
||||
|
||||
int analyze(randomx::Program& p) {
|
||||
int jumpCount = 0;
|
||||
RegisterUsage registerUsage[randomx::RegistersCount];
|
||||
for (unsigned i = 0; i < randomx::RegistersCount; ++i) {
|
||||
registerUsage[i].lastUsed = -1;
|
||||
registerUsage[i].count = 0;
|
||||
}
|
||||
for (unsigned i = 0; i < RANDOMX_PROGRAM_SIZE; ++i) {
|
||||
auto& instr = p(i);
|
||||
int opcode = instr.opcode;
|
||||
instr.opcode = 0;
|
||||
switch (opcode) {
|
||||
CASE_REP(IADD_RS) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_INT;
|
||||
instr.opcode |= DST_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IADD_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISUB_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISUB_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IMUL_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IMUL_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IMULH_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IMULH_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISMULH_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISMULH_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IMUL_RCP) {
|
||||
uint64_t divisor = instr.getImm32();
|
||||
if (!randomx::isPowerOf2(divisor)) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE_REP(INEG_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IXOR_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IXOR_M) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= DST_INT;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
}
|
||||
else {
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
}
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IROR_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(IROL_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISWAP_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
if (instr.src != instr.dst) {
|
||||
instr.opcode |= DST_INT;
|
||||
instr.opcode |= SRC_INT;
|
||||
instr.opcode |= OP_SWAP;
|
||||
registerUsage[instr.dst].lastUsed = i;
|
||||
registerUsage[instr.src].lastUsed = i;
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE_REP(FSWAP_R) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.opcode |= DST_FLT;
|
||||
} break;
|
||||
|
||||
CASE_REP(FADD_R) {
|
||||
instr.dst = instr.dst % randomx::RegisterCountFlt;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
} break;
|
||||
|
||||
CASE_REP(FADD_M) {
|
||||
instr.dst = instr.dst % randomx::RegisterCountFlt;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
} break;
|
||||
|
||||
CASE_REP(FSUB_R) {
|
||||
instr.dst = instr.dst % randomx::RegisterCountFlt;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
} break;
|
||||
|
||||
CASE_REP(FSUB_M) {
|
||||
instr.dst = instr.dst % randomx::RegisterCountFlt;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
} break;
|
||||
|
||||
CASE_REP(FSCAL_R) {
|
||||
instr.dst = instr.dst % randomx::RegisterCountFlt;
|
||||
instr.opcode |= DST_FLT;
|
||||
} break;
|
||||
|
||||
CASE_REP(FMUL_R) {
|
||||
instr.dst = 4 + instr.dst % randomx::RegisterCountFlt;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
} break;
|
||||
|
||||
CASE_REP(FDIV_M) {
|
||||
instr.dst = 4 + instr.dst % randomx::RegisterCountFlt;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= SRC_MEM;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
} break;
|
||||
|
||||
CASE_REP(FSQRT_R) {
|
||||
instr.dst = 4 + instr.dst % randomx::RegisterCountFlt;
|
||||
instr.opcode |= DST_FLT;
|
||||
instr.opcode |= OP_FLOAT;
|
||||
} break;
|
||||
|
||||
CASE_REP(CBRANCH) {
|
||||
instr.opcode |= OP_BRANCH;
|
||||
instr.opcode |= DST_INT;
|
||||
//jump condition
|
||||
//int reg = getConditionRegister(registerUsage);
|
||||
int reg = instr.dst % randomx::RegistersCount;
|
||||
int target = registerUsage[reg].lastUsed;
|
||||
int offset = (i - target);
|
||||
instr.mod = offset;
|
||||
jumpCount += offset;
|
||||
p(target + 1).opcode |= BRANCH_TARGET;
|
||||
registerUsage[reg].count++;
|
||||
instr.dst = reg;
|
||||
//mark all registers as used
|
||||
for (unsigned j = 0; j < randomx::RegistersCount; ++j) {
|
||||
registerUsage[j].lastUsed = i;
|
||||
}
|
||||
} break;
|
||||
|
||||
CASE_REP(CFROUND) {
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_INT;
|
||||
instr.opcode |= OP_CFROUND;
|
||||
} break;
|
||||
|
||||
CASE_REP(ISTORE) {
|
||||
instr.dst = instr.dst % randomx::RegistersCount;
|
||||
instr.src = instr.src % randomx::RegistersCount;
|
||||
instr.opcode |= SRC_INT;
|
||||
instr.opcode |= DST_MEM;
|
||||
if (instr.getModCond() < randomx::StoreL3Condition)
|
||||
instr.imm32 = (instr.getModMem() ? randomx::ScratchpadL1Mask : randomx::ScratchpadL2Mask);
|
||||
else
|
||||
instr.imm32 &= randomx::ScratchpadL3Mask;
|
||||
} break;
|
||||
|
||||
CASE_REP(NOP) {
|
||||
|
||||
} break;
|
||||
|
||||
default:
|
||||
UNREACHABLE;
|
||||
}
|
||||
}
|
||||
return jumpCount;
|
||||
}
|
128
vcxproj/perf-simulation.vcxproj
Normal file
128
vcxproj/perf-simulation.vcxproj
Normal file
@ -0,0 +1,128 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{F1FC7AC0-2773-4A57-AFA7-56BB07216AA2}</ProjectGuid>
|
||||
<RootNamespace>perfsimulation</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\tests\perf-simulation.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="randomx.vcxproj">
|
||||
<Project>{3346a4ad-c438-4324-8b77-47a16452954b}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
22
vcxproj/perf-simulation.vcxproj.filters
Normal file
22
vcxproj/perf-simulation.vcxproj.filters
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="..\src\tests\perf-simulation.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
Loading…
Reference in New Issue
Block a user