#pragma once #include "concept.h" #include "module.h" #include "wire.h" #include #include #include #include extern unsigned int global_clock; namespace dark { class CPU { private: std::vector> mod_owned; std::vector modules; bool reset_signal = false; public: unsigned long long cycles = 0; dark::Wire<9> halt_signal; private: void sync_all() { for (auto &module: modules) module->sync(); } public: /// @attention the pointer will be moved. you SHOULD NOT use it after calling this function. template requires std::derived_from<_Tp, ModuleBase> void add_module(std::unique_ptr<_Tp> &module) { modules.push_back(module.get()); mod_owned.emplace_back(std::move(module)); } void add_module(std::unique_ptr module) { modules.push_back(module.get()); mod_owned.emplace_back(std::move(module)); } void add_module(ModuleBase *module) { modules.push_back(module); } void run_once() { ++cycles; for (auto &module: modules) module->work(); sync_all(); } void run_once_shuffle() { static std::default_random_engine engine; std::vector shuffled = modules; std::shuffle(shuffled.begin(), shuffled.end(), engine); ++cycles; for (auto &module: shuffled) module->work(); sync_all(); } bool GetResetSignal(){ return reset_signal; } uint8_t run(unsigned long long max_cycles = 0, bool shuffle = false) { auto func = shuffle ? &CPU::run_once_shuffle : &CPU::run_once; reset_signal=true; while (max_cycles == 0 || cycles < max_cycles) { std::cerr<<"\nclock: "<*func)(); reset_signal=false; halt_signal.sync(); uint32_t halt_signal_value = static_cast(halt_signal); std::cerr<<"simulator received halt_signal_value="<