diff --git a/include/grenade/vx/execution_instance_builder.h b/include/grenade/vx/execution_instance_builder.h index afa6c3b9c8ddc1f4a09416af4e347bc8d86ddda7..8119ff880d9270d0b9a19802527b406d92048a08 100644 --- a/include/grenade/vx/execution_instance_builder.h +++ b/include/grenade/vx/execution_instance_builder.h @@ -46,7 +46,7 @@ public: coordinate::ExecutionInstance const& execution_instance, IODataMap const& input_list, IODataMap const& data_output, - lola::vx::v2::Chip const& chip_config, + std::optional<lola::vx::v2::PPUElfFile::symbols_type> const& ppu_symbols, ExecutionInstancePlaybackHooks& playback_hooks) SYMBOL_VISIBLE; /** @@ -56,7 +56,6 @@ public: struct PlaybackPrograms { - stadls::vx::v2::PlaybackProgram static_config; std::vector<stadls::vx::v2::PlaybackProgram> realtime; bool has_hook_around_realtime; }; @@ -89,7 +88,7 @@ private: ConstantReferenceIODataMap m_local_external_data; - lola::vx::v2::Chip m_initial_config; + std::optional<lola::vx::v2::PPUElfFile::symbols_type> m_ppu_symbols; ExecutionInstancePlaybackHooks& m_playback_hooks; diff --git a/src/grenade/vx/execution_instance_builder.cpp b/src/grenade/vx/execution_instance_builder.cpp index 242b3c2f9614c98512e68bc4bce7dd68b1a343c3..63a613a8a8406a801d991f2b0410f4c9704ff030 100644 --- a/src/grenade/vx/execution_instance_builder.cpp +++ b/src/grenade/vx/execution_instance_builder.cpp @@ -46,14 +46,14 @@ ExecutionInstanceBuilder::ExecutionInstanceBuilder( coordinate::ExecutionInstance const& execution_instance, IODataMap const& input_list, IODataMap const& data_output, - lola::vx::v2::Chip const& chip_config, + std::optional<lola::vx::v2::PPUElfFile::symbols_type> const& ppu_symbols, ExecutionInstancePlaybackHooks& playback_hooks) : m_graph(graph), m_execution_instance(execution_instance), m_input_list(input_list), m_data_output(data_output), m_local_external_data(), - m_initial_config(chip_config), + m_ppu_symbols(ppu_symbols), m_playback_hooks(playback_hooks), m_post_vertices(), m_local_data(), @@ -827,37 +827,16 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate() builder.merge_back(m_playback_hooks.pre_realtime); builder.merge_back(m_playback_hooks.post_realtime); m_chunked_program = {builder.done()}; - return {{}, m_chunked_program, false}; + return {m_chunked_program, false}; } // playback builder sequence to be concatenated in the end std::vector<PlaybackProgramBuilder> builders; - // add pre static config playback hook - auto config_builder = std::move(m_playback_hooks.pre_static_config); - - // generate static configuration - auto [static_config, ppu_symbols] = - ExecutionInstanceConfigVisitor(m_graph, m_execution_instance, m_initial_config)(); - config_builder.write(ChipOnDLS(), static_config); - // wait for CapMem to settle - config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus); - config_builder.write(TimerOnDLS(), Timer()); - config_builder.block_until( - TimerOnDLS(), Timer::Value(100000 * Timer::Value::fpga_clock_cycles_per_us)); - - // bring PPUs in running state - bool const enable_ppu = static_cast<bool>(ppu_symbols); - if (enable_ppu) { - for (auto const ppu : iter_all<PPUOnDLS>()) { - PPUControlRegister ctrl; - ctrl.set_inhibit_reset(true); - config_builder.write(ppu.toPPUControlRegisterOnDLS(), ctrl); - } - } // generate playback snippet for neuron resets auto [builder_neuron_reset, _] = stadls::vx::generate(m_neuron_resets); + auto const enable_ppu = static_cast<bool>(m_ppu_symbols); bool const has_cadc_readout = std::any_of( m_ticket_requests.begin(), m_ticket_requests.end(), [](auto const v) { return v; }); assert(has_cadc_readout ? enable_ppu : true); @@ -884,14 +863,14 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate() std::optional<PPUMemoryBlockOnPPU> ppu_scheduler_event_drop_count_coord; std::vector<PPUMemoryBlockOnPPU> ppu_timer_event_drop_count_coord; if (enable_ppu) { - assert(ppu_symbols); - ppu_status_coord = ppu_symbols->at("status").coordinate.toMin(); - ppu_result_coord = ppu_symbols->at("cadc_result").coordinate; - ppu_runtime_coord = ppu_symbols->at("runtime").coordinate.toMin(); - if (ppu_symbols->contains("scheduler_event_drop_count")) { + assert(m_ppu_symbols); + ppu_status_coord = m_ppu_symbols->at("status").coordinate.toMin(); + ppu_result_coord = m_ppu_symbols->at("cadc_result").coordinate; + ppu_runtime_coord = m_ppu_symbols->at("runtime").coordinate.toMin(); + if (m_ppu_symbols->contains("scheduler_event_drop_count")) { ppu_scheduler_event_drop_count_coord.emplace( - ppu_symbols->at("scheduler_event_drop_count").coordinate); - for (auto const& [name, symbol] : *ppu_symbols) { + m_ppu_symbols->at("scheduler_event_drop_count").coordinate); + for (auto const& [name, symbol] : *m_ppu_symbols) { if (name.starts_with("timer") && name.ends_with("event_drop_count")) { ppu_timer_event_drop_count_coord.push_back(symbol.coordinate); } @@ -931,19 +910,6 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate() wait_for_ppu_command_idle.block_until( PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock()); } - // wait for PPUs to be ready - for (auto const ppu : iter_all<PPUOnDLS>()) { - PollingOmnibusBlockConfig config; - config.set_address(PPUMemoryWord::addresses<PollingOmnibusBlockConfig::Address>( - PPUMemoryWordOnDLS(ppu_status_coord, ppu)) - .at(0)); - config.set_target( - PollingOmnibusBlockConfig::Value(static_cast<uint32_t>(ppu::Status::idle))); - config.set_mask(PollingOmnibusBlockConfig::Value(0xffffffff)); - config_builder.write(PollingOmnibusBlockConfigOnFPGA(), config); - config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus); - config_builder.block_until(PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock()); - } } // get whether any of {pre,post}_realtime hooks are present @@ -1192,7 +1158,7 @@ ExecutionInstanceBuilder::PlaybackPrograms ExecutionInstanceBuilder::generate() if (!builder.empty()) { m_chunked_program.push_back(builder.done()); } - return {config_builder.done(), m_chunked_program, has_hook_around_realtime}; + return {m_chunked_program, has_hook_around_realtime}; } } // namespace grenade::vx diff --git a/src/grenade/vx/execution_instance_node.cpp b/src/grenade/vx/execution_instance_node.cpp index b20ca78bc8061d789cb4963ca71cf776c29e7417..43f969d181bade3960893c6c4b086ec67c59d340 100644 --- a/src/grenade/vx/execution_instance_node.cpp +++ b/src/grenade/vx/execution_instance_node.cpp @@ -2,6 +2,10 @@ #include "grenade/vx/backend/connection.h" #include "grenade/vx/backend/run.h" +#include "grenade/vx/execution_instance_config_visitor.h" +#include "grenade/vx/ppu/status.h" +#include "haldls/vx/v2/barrier.h" +#include "haldls/vx/v2/timer.h" #include "hate/timer.h" #include <log4cxx/logger.h> @@ -33,8 +37,16 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg) using namespace halco::common; using namespace halco::hicann_dls::vx::v2; + hate::Timer const initial_config_timer; + lola::vx::v2::Chip initial_config = chip_config; + auto const ppu_symbols = + std::get<1>(ExecutionInstanceConfigVisitor(graph, execution_instance, initial_config)()); + LOG4CXX_TRACE( + logger, + "operator(): Constructed initial configuration in " << initial_config_timer.print() << "."); + ExecutionInstanceBuilder builder( - graph, execution_instance, input_data_map, data_map, chip_config, playback_hooks); + graph, execution_instance, input_data_map, data_map, ppu_symbols, playback_hooks); hate::Timer const preprocess_timer; builder.pre_process(); @@ -43,6 +55,46 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg) // build PlaybackProgram hate::Timer const build_timer; + + // add pre static config playback hook + auto config_builder = std::move(playback_hooks.pre_static_config); + + // generate static configuration + config_builder.write(ChipOnDLS(), initial_config); + + // wait for CapMem to settle + config_builder.block_until(BarrierOnFPGA(), haldls::vx::v2::Barrier::omnibus); + config_builder.write(TimerOnDLS(), haldls::vx::v2::Timer()); + config_builder.block_until( + TimerOnDLS(), haldls::vx::v2::Timer::Value( + 100000 * haldls::vx::v2::Timer::Value::fpga_clock_cycles_per_us)); + + // bring PPUs in running state + if (ppu_symbols) { + for (auto const ppu : iter_all<PPUOnDLS>()) { + haldls::vx::v2::PPUControlRegister ctrl; + ctrl.set_inhibit_reset(true); + config_builder.write(ppu.toPPUControlRegisterOnDLS(), ctrl); + } + auto const ppu_status_coord = ppu_symbols->at("status").coordinate.toMin(); + // wait for PPUs to be ready + for (auto const ppu : iter_all<PPUOnDLS>()) { + using namespace haldls::vx::v2; + PollingOmnibusBlockConfig config; + config.set_address(PPUMemoryWord::addresses<PollingOmnibusBlockConfig::Address>( + PPUMemoryWordOnDLS(ppu_status_coord, ppu)) + .at(0)); + config.set_target( + PollingOmnibusBlockConfig::Value(static_cast<uint32_t>(ppu::Status::idle))); + config.set_mask(PollingOmnibusBlockConfig::Value(0xffffffff)); + config_builder.write(PollingOmnibusBlockConfigOnFPGA(), config); + config_builder.block_until(BarrierOnFPGA(), Barrier::omnibus); + config_builder.block_until(PollingOmnibusBlockOnFPGA(), PollingOmnibusBlock()); + } + } + auto initial_config_program = config_builder.done(); + + // build realtime programs auto program = builder.generate(); LOG4CXX_TRACE(logger, "operator(): Built PlaybackPrograms in " << build_timer.print() << "."); @@ -56,10 +108,10 @@ void ExecutionInstanceNode::operator()(tbb::flow::continue_msg) // execute hate::Timer const exec_timer; - if (!program.realtime.empty() || !program.static_config.empty()) { + if (!program.realtime.empty() || !initial_config_program.empty()) { std::lock_guard lock(continuous_chunked_program_execution_mutex); - auto static_config_reinit = connection.create_reinit_stack_entry(); - static_config_reinit.set(program.static_config, true); + auto initial_config_reinit = connection.create_reinit_stack_entry(); + initial_config_reinit.set(initial_config_program, true); for (auto& p : program.realtime) { backend::run(connection, p); }