-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #451 from 4ms/load-balance-with-cables
Load balancing of modules and internal cables
- Loading branch information
Showing
9 changed files
with
377 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
#pragma once | ||
#include "core_a7/smp_api.hh" | ||
#include "drivers/interrupt.hh" | ||
#include "drivers/smp.hh" | ||
#include "gui/ui.hh" | ||
#include "patch_play/patch_player.hh" | ||
#include "util/fixed_vector.hh" | ||
|
||
namespace MetaModule | ||
{ | ||
|
||
struct AuxPlayer { | ||
PatchPlayer &patch_player; | ||
Ui &ui; | ||
|
||
FixedVector<unsigned, 64> module_ids; | ||
|
||
AuxPlayer(PatchPlayer &patch_player, Ui &ui) | ||
: patch_player{patch_player} | ||
, ui{ui} { | ||
using namespace mdrivlib; | ||
|
||
constexpr auto NewModuleListIRQn = SMPControl::IRQn(SMPCommand::NewModuleList); | ||
InterruptManager::register_and_start_isr(NewModuleListIRQn, 0, 0, [this]() { assign_module_list(); }); | ||
|
||
constexpr auto PlayModuleListIRQn = SMPControl::IRQn(SMPCommand::PlayModuleList); | ||
InterruptManager::register_and_start_isr(PlayModuleListIRQn, 1, 0, [this]() { play_modules(); }); | ||
|
||
constexpr auto ReadPatchLightsIRQn = SMPControl::IRQn(SMPCommand::ReadPatchLights); | ||
InterruptManager::register_and_start_isr(ReadPatchLightsIRQn, 2, 0, [this]() { read_patch_gui_elements(); }); | ||
} | ||
|
||
void play_modules() { | ||
|
||
for (auto module_i : module_ids) { | ||
patch_player.process_module_outputs(module_i); | ||
} | ||
|
||
for (auto module_i : module_ids) { | ||
patch_player.step_module(module_i); | ||
} | ||
|
||
mdrivlib::SMPThread::signal_done(); | ||
} | ||
|
||
void assign_module_list() { | ||
using namespace mdrivlib; | ||
|
||
module_ids.clear(); | ||
|
||
auto num_modules = SMPControl::read<SMPRegister::NumModulesInPatch>(); | ||
|
||
if (num_modules < module_ids.max_size()) { | ||
for (auto i = 0u; i < num_modules; i++) { | ||
auto id = SMPControl::read(i + 2); | ||
module_ids.push_back(id); | ||
} | ||
|
||
} else | ||
pr_err("Error: %u modules requested to run on core 2, max is %z\n", num_modules, module_ids.size()); | ||
|
||
SMPThread::signal_done(); | ||
} | ||
|
||
void read_patch_gui_elements() { | ||
if (ui.new_patch_data == false) { | ||
|
||
for (auto &w : ui.lights().watch_lights) { | ||
if (w.is_active()) { | ||
auto val = patch_player.get_module_light(w.module_id, w.light_id); | ||
w.value = val; | ||
} | ||
} | ||
|
||
for (auto &d : ui.displays().watch_displays) { | ||
if (d.is_active()) { | ||
auto text = std::span<char>(d.text._data, d.text.capacity); | ||
auto sz = patch_player.get_display_text(d.module_id, d.light_id, text); | ||
d.text._data[sz] = '\0'; | ||
} | ||
} | ||
|
||
for (auto &p : ui.watched_params().active_watched_params()) { | ||
if (p.is_active()) { | ||
p.value = patch_player.get_param(p.module_id, p.param_id); | ||
} | ||
} | ||
|
||
ui.new_patch_data = true; | ||
} | ||
|
||
SMPThread::signal_done(); | ||
} | ||
}; | ||
|
||
} // namespace MetaModule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
#pragma once | ||
#include "CoreModules/CoreProcessor.hh" | ||
#include "drivers/cycle_counter.hh" | ||
#include "patch/module_type_slug.hh" | ||
#include "util/partition.hh" | ||
#include <memory> | ||
#include <vector> | ||
|
||
#include "console/pr_dbg.hh" | ||
|
||
namespace MetaModule | ||
{ | ||
|
||
template<size_t NumCores, size_t MaxModules> | ||
struct Balancer { | ||
Partition<NumCores, MaxModules> cores; | ||
|
||
std::vector<unsigned> | ||
measure_modules(std::span<std::unique_ptr<CoreProcessor>> modules, unsigned num_modules, auto run) { | ||
|
||
mdrivlib::CycleCounter counter; | ||
|
||
constexpr size_t NumIterations = 512; | ||
constexpr size_t DropFirst = 32; | ||
|
||
std::vector<unsigned> times(num_modules - 1, 0); | ||
|
||
for (auto iter_i = 0u; iter_i < NumIterations + DropFirst; iter_i++) { | ||
|
||
for (size_t module_i = 1; module_i < num_modules; module_i++) { | ||
|
||
counter.start_measurement(); | ||
run(module_i); | ||
counter.end_measurement(); | ||
|
||
if (iter_i >= DropFirst) | ||
times[module_i - 1] += counter.get_last_measurement_raw(); | ||
} | ||
} | ||
|
||
return times; | ||
} | ||
|
||
void balance_loads(std::span<unsigned> times) { | ||
if (NumCores == 2) { | ||
// Core 2 needs extra time to respond to its interrupt | ||
// units is 1/24MHz | ||
auto bias = std::array<unsigned, 2>{0, 1000}; | ||
cores.calc_partitions(times, bias); | ||
} else | ||
cores.calc_partitions(times); | ||
|
||
// Adjust indices since we skip module 0 | ||
for (auto &part : cores.parts) { | ||
for (auto &idx : part) | ||
idx++; | ||
} | ||
} | ||
|
||
void print_times(std::span<unsigned> times, std::span<BrandModuleSlug> slugs) { | ||
// Debug output: | ||
for (auto core = 0u; core < NumCores; core++) { | ||
unsigned sum = 0; | ||
for (auto idx : cores.parts[core]) { | ||
pr_dbg("Core %d: Module %u (%s): %u\n", core, idx, slugs[idx].c_str(), times[idx - 1]); | ||
sum += times[idx - 1]; | ||
} | ||
pr_dbg("Core %d Total: %u\n", core, sum); | ||
} | ||
} | ||
}; | ||
|
||
} // namespace MetaModule |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
#pragma once | ||
#include "conf/patch_conf.hh" | ||
#include "patch/patch_data.hh" | ||
#include <span> | ||
|
||
namespace MetaModule | ||
{ | ||
|
||
struct CableCache { | ||
CableCache() = default; | ||
|
||
struct CableOut { | ||
float val; | ||
uint16_t jack_id; | ||
}; | ||
|
||
struct CableIn { | ||
uint16_t jack_id; | ||
uint16_t out_module_id; | ||
uint16_t out_cache_idx; | ||
//todo: profile using this instead: | ||
// CableOut *out; | ||
}; | ||
|
||
void clear() { | ||
for (auto &out : outs) | ||
out.clear(); | ||
for (auto &in : ins) | ||
in.clear(); | ||
} | ||
|
||
void build(std::span<const InternalCable> cables) { | ||
clear(); | ||
|
||
for (auto &cable : cables) { | ||
if (cable.out.module_id >= outs.size()) | ||
continue; | ||
|
||
auto &out = outs[cable.out.module_id]; | ||
auto out_idx = out.size(); | ||
out.emplace_back(0.f, cable.out.jack_id); | ||
|
||
for (auto &in : cable.ins) { | ||
if (in.module_id < ins.size()) { | ||
ins[in.module_id].emplace_back(in.jack_id, cable.out.module_id, out_idx); | ||
} | ||
} | ||
} | ||
} | ||
|
||
void add(Jack injack, Jack outjack) { | ||
if (injack.module_id < ins.size() && outjack.module_id < outs.size()) { | ||
auto &out = outs[outjack.module_id]; | ||
auto out_idx = out.size(); | ||
out.emplace_back(0.f, outjack.jack_id); | ||
ins[injack.module_id].emplace_back(injack.jack_id, outjack.module_id, out_idx); | ||
} | ||
} | ||
|
||
// outs[N] and ins[N] are the cables connected to module id N | ||
std::array<std::vector<CableOut>, MAX_MODULES_IN_PATCH> outs; | ||
std::array<std::vector<CableIn>, MAX_MODULES_IN_PATCH> ins; | ||
}; | ||
} // namespace MetaModule |
Oops, something went wrong.