2017-06-21 22:55:25 +00:00
|
|
|
#pragma once
|
|
|
|
|
2017-09-03 11:11:14 +00:00
|
|
|
#include <cstdint>
|
2017-06-21 22:55:25 +00:00
|
|
|
#include <chrono>
|
2017-07-04 12:00:23 +00:00
|
|
|
#include <iostream>
|
2017-06-21 22:55:25 +00:00
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
#include "EightBitCompilerDefinitions.h"
|
|
|
|
|
2017-09-03 20:30:46 +00:00
|
|
|
#ifdef _MSC_VER
|
2017-09-03 11:11:14 +00:00
|
|
|
#include <intrin.h>
|
2017-11-04 23:15:55 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef __GNUG__
|
2017-09-03 20:30:46 +00:00
|
|
|
#include <x86intrin.h>
|
2017-09-03 11:11:14 +00:00
|
|
|
#endif
|
|
|
|
|
2017-06-21 22:55:25 +00:00
|
|
|
namespace EightBit {
|
2021-07-18 13:28:40 +00:00
|
|
|
template<class ConfigurationT, class BoardT> class TestHarness final {
|
2017-06-21 22:55:25 +00:00
|
|
|
public:
|
2022-01-17 19:10:15 +00:00
|
|
|
TestHarness(const ConfigurationT& configuration) noexcept
|
|
|
|
: m_board(configuration) {}
|
2017-06-21 22:55:25 +00:00
|
|
|
|
|
|
|
~TestHarness() {
|
2017-07-05 16:40:16 +00:00
|
|
|
std::cout << std::dec << std::endl;
|
2017-06-22 09:16:02 +00:00
|
|
|
std::cout.imbue(std::locale(""));
|
|
|
|
|
2017-06-25 22:48:15 +00:00
|
|
|
std::cout << "Guest cycles = " << m_totalCycles << std::endl;
|
2017-06-22 09:16:02 +00:00
|
|
|
std::cout << "Seconds = " << getElapsedSeconds() << std::endl;
|
2017-06-21 22:55:25 +00:00
|
|
|
|
2017-07-05 18:15:58 +00:00
|
|
|
std::cout << getCyclesPerSecond() << " MHz" << std::endl;
|
2017-07-06 20:32:52 +00:00
|
|
|
std::cout << getInstructionsPerSecond() << " instructions per second" << std::endl;
|
2017-06-25 22:48:15 +00:00
|
|
|
|
|
|
|
auto elapsedHostCycles = m_finishHostCycles - m_startHostCycles;
|
|
|
|
std::cout << "Host cycles = " << elapsedHostCycles << std::endl;
|
|
|
|
|
|
|
|
auto efficiency = elapsedHostCycles / m_totalCycles;
|
|
|
|
std::cout << "Efficiency = " << efficiency << std::endl;
|
2017-06-21 22:55:25 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 00:09:40 +00:00
|
|
|
[[nodiscard]] std::chrono::steady_clock::duration getElapsedTime() const {
|
2017-06-22 09:16:02 +00:00
|
|
|
return m_finishTime - m_startTime;
|
|
|
|
}
|
2017-06-21 22:55:25 +00:00
|
|
|
|
2018-11-29 00:09:40 +00:00
|
|
|
[[nodiscard]] auto getElapsedSeconds() const {
|
2017-07-05 18:15:58 +00:00
|
|
|
return std::chrono::duration_cast<std::chrono::duration<double>>(getElapsedTime()).count();
|
2017-06-21 22:55:25 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 00:09:40 +00:00
|
|
|
[[nodiscard]] auto getCyclesPerSecond() const {
|
2017-07-05 18:15:58 +00:00
|
|
|
return (m_totalCycles / 1000000 ) / getElapsedSeconds();
|
2017-06-21 22:55:25 +00:00
|
|
|
}
|
|
|
|
|
2018-11-29 00:09:40 +00:00
|
|
|
[[nodiscard]] auto getInstructionsPerSecond() {
|
2017-07-06 20:32:52 +00:00
|
|
|
auto floating = m_instructions / getElapsedSeconds();
|
|
|
|
return (long long)floating;
|
|
|
|
}
|
|
|
|
|
2022-01-17 19:10:15 +00:00
|
|
|
void run() noexcept {
|
2017-06-22 09:16:02 +00:00
|
|
|
m_startTime = now();
|
2017-07-06 20:32:52 +00:00
|
|
|
m_totalCycles = m_instructions = 0L;
|
2017-06-25 22:48:15 +00:00
|
|
|
m_startHostCycles = currentHostCycles();
|
2017-06-21 22:55:25 +00:00
|
|
|
|
2019-01-14 02:10:17 +00:00
|
|
|
m_board.initialise();
|
|
|
|
m_board.raisePOWER();
|
2018-11-11 16:48:44 +00:00
|
|
|
|
2017-07-05 16:40:16 +00:00
|
|
|
auto& cpu = m_board.CPU();
|
2017-08-31 11:13:00 +00:00
|
|
|
|
2017-12-10 21:41:48 +00:00
|
|
|
while (LIKELY(cpu.powered())) {
|
2017-06-21 22:55:25 +00:00
|
|
|
m_totalCycles += cpu.step();
|
2017-07-06 20:32:52 +00:00
|
|
|
++m_instructions;
|
2017-06-21 22:55:25 +00:00
|
|
|
}
|
|
|
|
|
2017-06-25 22:48:15 +00:00
|
|
|
m_finishHostCycles = currentHostCycles();
|
2017-06-22 09:16:02 +00:00
|
|
|
m_finishTime = now();
|
2017-06-21 22:55:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
BoardT m_board;
|
2018-04-14 08:39:06 +00:00
|
|
|
long long m_totalCycles = 0;
|
|
|
|
long long m_instructions = 0;
|
2017-06-22 09:16:02 +00:00
|
|
|
std::chrono::steady_clock::time_point m_startTime;
|
|
|
|
std::chrono::steady_clock::time_point m_finishTime;
|
2018-04-14 08:39:06 +00:00
|
|
|
uint64_t m_startHostCycles = 0;
|
|
|
|
uint64_t m_finishHostCycles = 0;
|
2017-06-22 09:16:02 +00:00
|
|
|
|
2018-12-01 16:41:39 +00:00
|
|
|
[[nodiscard]] static auto now() {
|
2017-06-22 09:16:02 +00:00
|
|
|
return std::chrono::steady_clock::now();
|
|
|
|
}
|
2017-06-25 22:48:15 +00:00
|
|
|
|
2018-12-01 16:41:39 +00:00
|
|
|
[[nodiscard]] static uint64_t currentHostCycles() {
|
2017-06-25 22:48:15 +00:00
|
|
|
return __rdtsc();
|
|
|
|
}
|
2017-06-21 22:55:25 +00:00
|
|
|
};
|
2017-11-30 23:19:17 +00:00
|
|
|
}
|