Skip to content
Snippets Groups Projects
Commit 36c6e1e1 authored by Philipp Spilger's avatar Philipp Spilger
Browse files

Add perform_reinit_snapshot

* allows read-back of state to later reapply in reinit
* transform from response to request implemented for Omnibus reads

Depends-On: 16889,16891
Change-Id: I140419fd0c85668cca08261e97064080d202073b
parent cc4e3487
No related branches found
No related merge requests found
Showing
with 169 additions and 13 deletions
#pragma once
#include "hxcomm/common/quiggeldy_interface_types.h"
#include <cereal/cereal.hpp>
#include <cereal/types/optional.hpp>
namespace cereal {
template <typename Archive, typename ConnectionParameter>
void CEREAL_SERIALIZE_FUNCTION_NAME(
Archive& ar, typename hxcomm::detail::ReinitEntryType<ConnectionParameter>& reinit_entry)
{
ar(CEREAL_NVP(reinit_entry.request));
ar(CEREAL_NVP(reinit_entry.snapshot));
}
} // namespace cereal
......@@ -37,6 +37,8 @@ struct UTMessageParameter
* @tparam ReceivePhywordType Type of PHY-word of receive UTMessage set
* @tparam ReceiveDictionary Dictionary of instructions of received UTMessages
* @tparam ReceiveHaltInstructionType Instruction type of Halt message in receive dictionary
* @tparam QuiggeldyScheduleOutToInTransformType Functor to transform a schedule-out result to
* schedule-in instructions in quiggeldy
*/
template <
size_t SendHeaderAlignment,
......@@ -49,7 +51,8 @@ template <
typename ReceivePhywordType,
typename ReceiveDictionary,
typename ReceiveHaltInstructionType,
typename ReceiveTimeoutInstructionType>
typename ReceiveTimeoutInstructionType,
typename QuiggeldyScheduleOutToInTransformType>
struct ConnectionParameter
{
typedef UTMessageParameter<
......@@ -67,6 +70,7 @@ struct ConnectionParameter
Receive;
typedef ReceiveHaltInstructionType ReceiveHalt;
typedef ReceiveTimeoutInstructionType ReceiveTimeout;
typedef QuiggeldyScheduleOutToInTransformType QuiggeldyScheduleOutToInTransform;
};
} // namespace hxcomm
......@@ -4,11 +4,27 @@
#include "hxcomm/common/connection_time_info.h"
#include "hxcomm/common/execute_messages.h"
#include <optional>
#include <utility>
#include <vector>
namespace hxcomm {
namespace detail {
template <typename ConnectionParameter>
struct ReinitEntryType
{
using request_type = detail::execute_messages_argument_t<ConnectionParameter>;
request_type request;
std::optional<request_type> snapshot;
typedef typename ConnectionParameter::QuiggeldyScheduleOutToInTransform transform_type;
};
} // namespace detail
template <typename ConnectionParameter>
struct quiggeldy_interface_types
{
......@@ -16,8 +32,8 @@ struct quiggeldy_interface_types
using request_type = detail::execute_messages_argument_t<ConnectionParameter>;
using response_type = detail::execute_messages_return_t<ConnectionParameter>;
using reinit_type = std::vector<request_type>;
using reinit_entry_type = typename reinit_type::value_type;
using reinit_entry_type = detail::ReinitEntryType<ConnectionParameter>;
using reinit_type = std::vector<reinit_entry_type>;
};
// convenience partial specialization if only message types are available
......
......@@ -35,7 +35,6 @@ public:
using request_type = typename interface_types::request_type;
using response_type = typename interface_types::response_type;
// reinit is just another set of FPGA words sent to the chip prior to resuming
using reinit_type = typename interface_types::reinit_type;
// pair encoding uid and UUID of the session to differentiate them (one per QuiggeldyConnection)
......@@ -92,6 +91,13 @@ public:
*/
void perform_reinit(reinit_type const&);
/**
* This function is called whenever we have to relinquish control of our
* hardware resource and the user specified a reinit-program to be snapshotted
* after the previous work-unit was executed.
*/
void perform_reinit_snapshot(reinit_type&);
/**
* This function is run whenever the server releases control (and any
* associated slurm resources).
......
......@@ -261,7 +261,33 @@ void QuiggeldyWorker<Connection>::perform_reinit(reinit_type const& reinit)
try {
for (auto const& entry : reinit) {
execute_messages(*m_connection, entry);
execute_messages(*m_connection, entry.request);
}
} catch (const std::exception& e) {
// TODO: Implement proper exception handling
teardown();
HXCOMM_LOG_ERROR(m_logger, "Error during word execution: " << e.what());
throw;
}
}
template <typename Connection>
void QuiggeldyWorker<Connection>::perform_reinit_snapshot(reinit_type& reinit)
{
if (m_mock_mode) {
HXCOMM_LOG_DEBUG(m_logger, "Running mock-reinit-snapshot!");
return;
}
HXCOMM_LOG_TRACE(m_logger, "Performing reinit snapshot!");
try {
for (auto& entry : reinit) {
if (entry.snapshot) {
auto const [response, _] = execute_messages(*m_connection, *(entry.snapshot));
entry.request = typename std::decay_t<decltype(entry)>::transform_type{}(
response, *(entry.snapshot));
}
}
} catch (const std::exception& e) {
// TODO: Implement proper exception handling
......
......@@ -149,7 +149,9 @@ void ReinitStackEntry<QuiggeldyConnection, ConnectionVariant>::handle_unsupporte
HXCOMM_LOG_TRACE(
m_logger, "Connection does not support upload of reinit program, treating enforced "
"reinit-like regular program to execute.");
std::visit([&entry](auto& conn) { execute_messages(conn.get(), entry); }, m_connection_ref);
std::visit(
[&entry](auto& conn) { execute_messages(conn.get(), entry.request); },
m_connection_ref);
} else {
HXCOMM_LOG_TRACE(
m_logger, "Connection does not support upload of reinit program, ignoring "
......
#pragma once
#include "hxcomm/common/connection_parameter.h"
#include "hxcomm/vx/quiggeldy_schedule_out_to_in_transform.h"
#include "hxcomm/vx/utmessage.h"
namespace hxcomm::vx {
......@@ -15,7 +16,8 @@ typedef hxcomm::ConnectionParameter<
ut_message_from_fpga_phyword_type,
instruction::FromFPGADictionary,
instruction::from_fpga_system::Loopback,
instruction::from_fpga_system::TimeoutNotification>
instruction::from_fpga_system::TimeoutNotification,
detail::QuiggeldyScheduleOutToInTransform>
ConnectionParameter;
} // namespace hxcomm::vx
......@@ -60,6 +60,16 @@ struct Address
return os;
}
bool get_is_read() const
{
return m_is_read;
}
void set_is_read(bool value)
{
m_is_read = value;
}
private:
uint32_t m_address;
bool m_is_read;
......
......@@ -5,6 +5,7 @@
#include "cereal/types/vector.hpp"
#include "hate/visibility.h"
#include "hxcomm/common/cerealization_quiggeldy_interface_types.h"
#include "hxcomm/common/cerealization_utmessage.h"
#include "hxcomm/common/connection.h"
#include "hxcomm/common/connection_time_info.h"
......@@ -32,9 +33,8 @@ void serialize(Archive& ar, hxcomm::vx::quiggeldy_interface_types::request_type&
void serialize(Archive& ar, hxcomm::vx::quiggeldy_interface_types::response_type& qcr)
SYMBOL_VISIBLE;
// Note: Currently, hxcomm::vx::quiggeldy_interface_types::reinit_type is the
// same as the request_type and thus no additional declaration of serialize()
// is needed.
void serialize(Archive& ar, hxcomm::vx::quiggeldy_interface_types::reinit_entry_type& qcr)
SYMBOL_VISIBLE;
} // namespace SF
......
#pragma once
#include "hate/visibility.h"
#include "hxcomm/vx/utmessage.h"
#include <vector>
namespace hxcomm::vx::detail {
struct QuiggeldyScheduleOutToInTransform
{
using request_type = std::vector<UTMessageToFPGAVariant>;
using response_type = std::vector<UTMessageFromFPGAVariant>;
request_type operator()(response_type const& response, request_type const& snapshot)
SYMBOL_VISIBLE;
};
} // namespace hxcomm::vx::detail
......@@ -29,8 +29,9 @@ void serialize(Archive& ar, hxcomm::vx::quiggeldy_interface_types::response_type
translate_sf_cereal(ar, qcr);
}
// Note: Currently, hxcomm::vx::quiggeldy_interface_types::reinit_type is the
// same as the request_type and thus no additional declaration of serialize()
// is needed.
void serialize(Archive& ar, hxcomm::vx::quiggeldy_interface_types::reinit_entry_type& qcr)
{
translate_sf_cereal(ar, qcr);
}
} // namespace SF
#include "hxcomm/vx/quiggeldy_schedule_out_to_in_transform.h"
#include <variant>
namespace hxcomm::vx::detail {
QuiggeldyScheduleOutToInTransform::request_type QuiggeldyScheduleOutToInTransform::operator()(
response_type const& response, request_type const& snapshot)
{
// simple unchecked transform from Omnibus reads to Omnibus writes
// filter all read requests
request_type addresses;
for (auto const& ins : snapshot) {
if (!std::holds_alternative<UTMessageToFPGA<instruction::omnibus_to_fpga::Address>>(ins)) {
continue;
}
auto address = std::get<UTMessageToFPGA<instruction::omnibus_to_fpga::Address>>(ins);
auto address_payload = address.decode();
if (address_payload.get_is_read()) {
address_payload.set_is_read(false);
address.encode(address_payload);
addresses.push_back(address);
}
}
// filter all read responses
request_type data;
for (auto const& resp : response) {
if (!std::holds_alternative<UTMessageFromFPGA<instruction::omnibus_from_fpga::Data>>(
resp)) {
continue;
}
data.push_back(UTMessageToFPGA<instruction::omnibus_to_fpga::Data>(
std::get<UTMessageFromFPGA<instruction::omnibus_from_fpga::Data>>(resp)
.decode()
.value()));
}
// combine addresses and data to write accesses
if (addresses.size() != data.size()) {
throw std::runtime_error("Transform to Omnibus writes unsuccessful, mismatch in number "
"of read requests to responses.");
}
request_type ret;
for (size_t i = 0; i < addresses.size(); ++i) {
ret.push_back(addresses.at(i));
ret.push_back(data.at(i));
}
// ensure writes are successful
ret.push_back(
UTMessageToFPGA<instruction::timing::Barrier>(instruction::timing::Barrier::omnibus));
return ret;
}
} // namespace hxcomm::vx::detail
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment