From d493ea4bcae5bcd11a9b517d4d168a99372ecd80 Mon Sep 17 00:00:00 2001 From: Thomas Harte Date: Sun, 28 Jan 2018 22:22:21 -0500 Subject: [PATCH] Introduces a multimachine to handle multi-target static analyser outputs. Non-functional as of yet. --- Analyser/Dynamic/ConfidenceCounter.cpp | 2 +- Analyser/Dynamic/ConfidenceCounter.hpp | 4 +- Analyser/Dynamic/ConfidenceSource.hpp | 4 +- Analyser/Dynamic/ConfidenceSummary.cpp | 2 +- Analyser/Dynamic/ConfidenceSummary.hpp | 4 +- .../Dynamic/MultiMachine/MultiMachine.cpp | 38 ++++++++++++++ .../Dynamic/MultiMachine/MultiMachine.hpp | 50 ++++++++++++++++++ Machines/MSX/ROMSlotHandler.hpp | 2 +- Machines/Utility/MachineForTarget.cpp | 52 ++++++++++++++----- Machines/Utility/MachineForTarget.hpp | 3 +- .../Clock Signal.xcodeproj/project.pbxproj | 14 +++++ 11 files changed, 154 insertions(+), 21 deletions(-) create mode 100644 Analyser/Dynamic/MultiMachine/MultiMachine.cpp create mode 100644 Analyser/Dynamic/MultiMachine/MultiMachine.hpp diff --git a/Analyser/Dynamic/ConfidenceCounter.cpp b/Analyser/Dynamic/ConfidenceCounter.cpp index 8a39a474c..c2ce5bbc4 100644 --- a/Analyser/Dynamic/ConfidenceCounter.cpp +++ b/Analyser/Dynamic/ConfidenceCounter.cpp @@ -8,7 +8,7 @@ #include "ConfidenceCounter.hpp" -using namespace DynamicAnalyser; +using namespace Analyser::Dynamic; float ConfidenceCounter::get_confidence() { return static_cast(hits_) / static_cast(hits_ + misses_); diff --git a/Analyser/Dynamic/ConfidenceCounter.hpp b/Analyser/Dynamic/ConfidenceCounter.hpp index ed1be56d4..9d424c0c5 100644 --- a/Analyser/Dynamic/ConfidenceCounter.hpp +++ b/Analyser/Dynamic/ConfidenceCounter.hpp @@ -11,7 +11,8 @@ #include "ConfidenceSource.hpp" -namespace DynamicAnalyser { +namespace Analyser { +namespace Dynamic { /*! Provides a confidence source that calculates its probability by virtual of a history of events. @@ -40,6 +41,7 @@ class ConfidenceCounter: public ConfidenceSource { int misses_ = 1; }; +} } #endif /* ConfidenceCounter_hpp */ diff --git a/Analyser/Dynamic/ConfidenceSource.hpp b/Analyser/Dynamic/ConfidenceSource.hpp index 2754a8fdb..b0e57648c 100644 --- a/Analyser/Dynamic/ConfidenceSource.hpp +++ b/Analyser/Dynamic/ConfidenceSource.hpp @@ -9,7 +9,8 @@ #ifndef ConfidenceSource_hpp #define ConfidenceSource_hpp -namespace DynamicAnalyser { +namespace Analyser { +namespace Dynamic { /*! Provides an abstract interface through which objects can declare the probability @@ -21,6 +22,7 @@ struct ConfidenceSource { virtual float get_confidence() = 0; }; +} } #endif /* ConfidenceSource_hpp */ diff --git a/Analyser/Dynamic/ConfidenceSummary.cpp b/Analyser/Dynamic/ConfidenceSummary.cpp index 4306fba13..d18328f2c 100644 --- a/Analyser/Dynamic/ConfidenceSummary.cpp +++ b/Analyser/Dynamic/ConfidenceSummary.cpp @@ -11,7 +11,7 @@ #include #include -using namespace DynamicAnalyser; +using namespace Analyser::Dynamic; ConfidenceSummary::ConfidenceSummary(const std::vector &sources, const std::vector &weights) : sources_(sources), weights_(weights) { diff --git a/Analyser/Dynamic/ConfidenceSummary.hpp b/Analyser/Dynamic/ConfidenceSummary.hpp index cb8cdac55..5952e00a9 100644 --- a/Analyser/Dynamic/ConfidenceSummary.hpp +++ b/Analyser/Dynamic/ConfidenceSummary.hpp @@ -13,7 +13,8 @@ #include -namespace DynamicAnalyser { +namespace Analyser { +namespace Dynamic { /*! Summaries a collection of confidence sources by calculating their weighted sum. @@ -39,6 +40,7 @@ class ConfidenceSummary: public ConfidenceSource { float weight_sum_; }; +} } #endif /* ConfidenceSummary_hpp */ diff --git a/Analyser/Dynamic/MultiMachine/MultiMachine.cpp b/Analyser/Dynamic/MultiMachine/MultiMachine.cpp new file mode 100644 index 000000000..71649c016 --- /dev/null +++ b/Analyser/Dynamic/MultiMachine/MultiMachine.cpp @@ -0,0 +1,38 @@ +// +// MultiMachine.cpp +// Clock Signal +// +// Created by Thomas Harte on 28/01/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#include "MultiMachine.hpp" + +using namespace Analyser::Dynamic; + +MultiMachine::MultiMachine(std::vector> &&machines) : + machines_(std::move(machines)) {} + +ConfigurationTarget::Machine *MultiMachine::configuration_target() { + return nullptr; +} + +CRTMachine::Machine *MultiMachine::crt_machine() { + return nullptr; +} + +JoystickMachine::Machine *MultiMachine::joystick_machine() { + return nullptr; +} + +KeyboardMachine::Machine *MultiMachine::keyboard_machine() { + return nullptr; +} + +Configurable::Device *MultiMachine::configurable_device() { + return nullptr; +} + +Utility::TypeRecipient *MultiMachine::type_recipient() { + return nullptr; +} diff --git a/Analyser/Dynamic/MultiMachine/MultiMachine.hpp b/Analyser/Dynamic/MultiMachine/MultiMachine.hpp new file mode 100644 index 000000000..e1f86760c --- /dev/null +++ b/Analyser/Dynamic/MultiMachine/MultiMachine.hpp @@ -0,0 +1,50 @@ +// +// MultiMachine.hpp +// Clock Signal +// +// Created by Thomas Harte on 28/01/2018. +// Copyright © 2018 Thomas Harte. All rights reserved. +// + +#ifndef MultiMachine_hpp +#define MultiMachine_hpp + +#include "../../../Machines/Utility/MachineForTarget.hpp" + +#include +#include + +namespace Analyser { +namespace Dynamic { + +/*! + Provides the same interface as to a single machine, while multiplexing all + underlying calls to an array of real dynamic machines. + + Calls to crt_machine->get_crt will return that for the first machine. + + Following each crt_machine->run_for, reorders the supplied machines by + confidence. + + If confidence for any machine becomes disproportionately low compared to + the others in the set, that machine is removed from the array. +*/ +class MultiMachine: public ::Machine::DynamicMachine { + public: + MultiMachine(std::vector> &&machines); + + ConfigurationTarget::Machine *configuration_target() override; + CRTMachine::Machine *crt_machine() override; + JoystickMachine::Machine *joystick_machine() override; + KeyboardMachine::Machine *keyboard_machine() override; + Configurable::Device *configurable_device() override; + Utility::TypeRecipient *type_recipient() override; + + private: + std::vector> machines_; +}; + +} +} + +#endif /* MultiMachine_hpp */ diff --git a/Machines/MSX/ROMSlotHandler.hpp b/Machines/MSX/ROMSlotHandler.hpp index 5c8f8a533..cf742daa8 100644 --- a/Machines/MSX/ROMSlotHandler.hpp +++ b/Machines/MSX/ROMSlotHandler.hpp @@ -70,7 +70,7 @@ class ROMSlotHandler { } protected: - DynamicAnalyser::ConfidenceCounter confidence_counter_; + Analyser::Dynamic::ConfidenceCounter confidence_counter_; }; } diff --git a/Machines/Utility/MachineForTarget.cpp b/Machines/Utility/MachineForTarget.cpp index c71e33303..c523032ed 100644 --- a/Machines/Utility/MachineForTarget.cpp +++ b/Machines/Utility/MachineForTarget.cpp @@ -16,24 +16,25 @@ #include "../Oric/Oric.hpp" #include "../ZX8081/ZX8081.hpp" +#include "../../Analyser/Dynamic/MultiMachine/MultiMachine.hpp" #include "TypedDynamicMachine.hpp" -::Machine::DynamicMachine *::Machine::MachineForTargets(const std::vector> &targets, const ROMMachine::ROMFetcher &rom_fetcher, Error &error) { - // TODO: deal with target lists containing more than one machine. +namespace { - error = Error::None; +::Machine::DynamicMachine *MachineForTarget(const Analyser::Static::Target &target, const ROMMachine::ROMFetcher &rom_fetcher, Machine::Error &error) { + error = Machine::Error::None; ::Machine::DynamicMachine *machine = nullptr; - switch(targets.front()->machine) { - case Analyser::Machine::AmstradCPC: machine = new TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); break; - case Analyser::Machine::Atari2600: machine = new TypedDynamicMachine(Atari2600::Machine::Atari2600()); break; - case Analyser::Machine::Electron: machine = new TypedDynamicMachine(Electron::Machine::Electron()); break; - case Analyser::Machine::MSX: machine = new TypedDynamicMachine(MSX::Machine::MSX()); break; - case Analyser::Machine::Oric: machine = new TypedDynamicMachine(Oric::Machine::Oric()); break; - case Analyser::Machine::Vic20: machine = new TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); break; - case Analyser::Machine::ZX8081: machine = new TypedDynamicMachine(ZX8081::Machine::ZX8081(*targets.front())); break; + switch(target.machine) { + case Analyser::Machine::AmstradCPC: machine = new Machine::TypedDynamicMachine(AmstradCPC::Machine::AmstradCPC()); break; + case Analyser::Machine::Atari2600: machine = new Machine::TypedDynamicMachine(Atari2600::Machine::Atari2600()); break; + case Analyser::Machine::Electron: machine = new Machine::TypedDynamicMachine(Electron::Machine::Electron()); break; + case Analyser::Machine::MSX: machine = new Machine::TypedDynamicMachine(MSX::Machine::MSX()); break; + case Analyser::Machine::Oric: machine = new Machine::TypedDynamicMachine(Oric::Machine::Oric()); break; + case Analyser::Machine::Vic20: machine = new Machine::TypedDynamicMachine(Commodore::Vic20::Machine::Vic20()); break; + case Analyser::Machine::ZX8081: machine = new Machine::TypedDynamicMachine(ZX8081::Machine::ZX8081(target)); break; default: - error = Error::UnknownMachine; + error = Machine::Error::UnknownMachine; return nullptr; } @@ -42,19 +43,42 @@ if(crt_machine) { if(!machine->crt_machine()->set_rom_fetcher(rom_fetcher)) { delete machine; - error = Error::MissingROM; + error = Machine::Error::MissingROM; return nullptr; } } ConfigurationTarget::Machine *configuration_target = machine->configuration_target(); if(configuration_target) { - machine->configuration_target()->configure_as_target(*targets.front()); + machine->configuration_target()->configure_as_target(target); } return machine; } +} + +::Machine::DynamicMachine *::Machine::MachineForTargets(const std::vector> &targets, const ROMMachine::ROMFetcher &rom_fetcher, Error &error) { + // Zero targets implies no machine. + if(targets.empty()) { + error = Error::NoTargets; + return nullptr; + } + + // If there's more than one target, get all the machines and combine them into a multimachine. + if(targets.size() > 1) { + std::vector> machines; + for(const auto &target: targets) { + machines.emplace_back(MachineForTarget(*target, rom_fetcher, error)); + } + + return new Analyser::Dynamic::MultiMachine(std::move(machines)); + } + + // There's definitely exactly one target. + return MachineForTarget(*targets.front(), rom_fetcher, error); +} + std::string Machine::ShortNameForTargetMachine(const Analyser::Machine machine) { switch(machine) { case Analyser::Machine::AmstradCPC: return "AmstradCPC"; diff --git a/Machines/Utility/MachineForTarget.hpp b/Machines/Utility/MachineForTarget.hpp index b54fbc120..490f8ac59 100644 --- a/Machines/Utility/MachineForTarget.hpp +++ b/Machines/Utility/MachineForTarget.hpp @@ -41,7 +41,8 @@ struct DynamicMachine { enum class Error { None, UnknownMachine, - MissingROM + MissingROM, + NoTargets }; /*! diff --git a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj index 11f66c982..707dad95f 100644 --- a/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj +++ b/OSBindings/Mac/Clock Signal.xcodeproj/project.pbxproj @@ -161,6 +161,7 @@ 4B3BA0D01D318B44005DD7A7 /* MOS6532Bridge.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CB1D318B44005DD7A7 /* MOS6532Bridge.mm */; }; 4B3BA0D11D318B44005DD7A7 /* TestMachine6502.mm in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BA0CD1D318B44005DD7A7 /* TestMachine6502.mm */; }; 4B3BF5B01F146265005B6C36 /* CSW.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3BF5AE1F146264005B6C36 /* CSW.cpp */; }; + 4B3FCC40201EC24200960631 /* MultiMachine.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FCC3F201EC24200960631 /* MultiMachine.cpp */; }; 4B3FE75E1F3CF68B00448EE4 /* CPM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */; }; 4B448E811F1C45A00009ABD6 /* TZX.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */; }; 4B448E841F1C4C480009ABD6 /* PulseQueuedTape.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4B448E821F1C4C480009ABD6 /* PulseQueuedTape.cpp */; }; @@ -749,6 +750,8 @@ 4B3BA0CD1D318B44005DD7A7 /* TestMachine6502.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = TestMachine6502.mm; sourceTree = ""; }; 4B3BF5AE1F146264005B6C36 /* CSW.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSW.cpp; sourceTree = ""; }; 4B3BF5AF1F146264005B6C36 /* CSW.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = CSW.hpp; sourceTree = ""; }; + 4B3FCC3E201EC24200960631 /* MultiMachine.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; path = MultiMachine.hpp; sourceTree = ""; }; + 4B3FCC3F201EC24200960631 /* MultiMachine.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = MultiMachine.cpp; sourceTree = ""; }; 4B3FE75C1F3CF68B00448EE4 /* CPM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CPM.cpp; path = Parsers/CPM.cpp; sourceTree = ""; }; 4B3FE75D1F3CF68B00448EE4 /* CPM.hpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.h; name = CPM.hpp; path = Parsers/CPM.hpp; sourceTree = ""; }; 4B448E7F1F1C45A00009ABD6 /* TZX.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = TZX.cpp; sourceTree = ""; }; @@ -1687,6 +1690,15 @@ path = Bridges; sourceTree = ""; }; + 4B3FCC3D201EC24200960631 /* MultiMachine */ = { + isa = PBXGroup; + children = ( + 4B3FCC3E201EC24200960631 /* MultiMachine.hpp */, + 4B3FCC3F201EC24200960631 /* MultiMachine.cpp */, + ); + path = MultiMachine; + sourceTree = ""; + }; 4B3FE75F1F3CF6BA00448EE4 /* Parsers */ = { isa = PBXGroup; children = ( @@ -2066,6 +2078,7 @@ 4B8944E7201967B4007DE474 /* ConfidenceCounter.hpp */, 4B8944E5201967B4007DE474 /* ConfidenceSource.hpp */, 4B8944E4201967B4007DE474 /* ConfidenceSummary.hpp */, + 4B3FCC3D201EC24200960631 /* MultiMachine */, ); path = Dynamic; sourceTree = ""; @@ -3564,6 +3577,7 @@ 4B98A05E1FFAD3F600ADF63B /* CSROMFetcher.mm in Sources */, 4B8FE2201DA19D7C0090D3CE /* Atari2600OptionsPanel.swift in Sources */, 4B8805F41DCFD22A003085B1 /* Commodore.cpp in Sources */, + 4B3FCC40201EC24200960631 /* MultiMachine.cpp in Sources */, 4B2E2D9A1C3A06EC00138695 /* Atari2600.cpp in Sources */, 4B9CCDA11DA279CA0098B625 /* Vic20OptionsPanel.swift in Sources */, 4B8805F01DCFC99C003085B1 /* Acorn.cpp in Sources */,