blob: 174fd2bfcbc2a486e4333c7b8ab7985d21b29bb1 [file] [log] [blame]
#pragma once
#include <hei_signature.hpp>
#include <util/hei_bit_string.hpp>
#include <algorithm>
#include <map>
#include <memory>
#include <vector>
namespace libhei
{
/**
* @brief The main isolate() API is given a list of chips to analyze. This class
* will contain a list of all active hardware errors found on those
* chips, the contents of any registers associated with the active
* errors, and any other data that can be useful for debug.
*/
class IsolationData
{
public: // Constructors, destructor, assignment, etc.
/** @brief Default constructor. */
IsolationData() = default;
/** @brief Destructor. */
~IsolationData() = default;
/** @brief Copy constructor. */
IsolationData(const IsolationData&) = default;
/** @brief Assignment operator. */
IsolationData& operator=(const IsolationData&) = default;
public:
/** The data stored in each entry of the register dump. */
struct RegDumpEntry
{
RegDumpEntry(RegisterId_t i_regId, Instance_t i_regInst,
std::shared_ptr<BitStringBuffer> i_data) :
regId(i_regId),
regInst(i_regInst), data(i_data)
{}
RegisterId_t regId; ///< 3-byte register ID
Instance_t regInst; ///< 1-byte register instance
std::shared_ptr<BitStringBuffer> data; ///< register data
bool operator==(const RegDumpEntry& r) const
{
return regId == r.regId && regInst == r.regInst && *data == *r.data;
}
};
private: // Instance variables
/** A list of all signatures found during isolation. */
std::vector<Signature> iv_sigLists;
/**
* This intended to be a snapshot of the register values read from hardware
* as the isolator iterates the isolation tree. Therefore, it cannot share
* the values stored in the hardware register cache. Instead, it must be a
* copy of the data.
*/
std::map<Chip, std::vector<RegDumpEntry>> iv_regDump;
public: // Member functions
/**
* @brief Adds a signature to the signature list.
* @param i_signature The target signature.
*/
void addSignature(const Signature& i_signature)
{
iv_sigLists.push_back(i_signature);
}
/**
* @brief Adds the contents of a register to the register dump.
* @param i_chip The chip associated with this register.
* @param i_regId The register ID.
* @param i_regInst The register instance.
* @param i_data A BitString containing the contents of the register.
* Note that this function will make a copy of the data,
* which will be stored separately from the hardware
* register cache.
*/
void addRegister(const Chip& i_chip, RegisterId_t i_regId,
Instance_t i_regInst, const BitString* i_data)
{
if (!i_data->isZero()) // Only add non-zero values to save space.
{
// Make a copy of the register value.
auto data = std::make_shared<BitStringBuffer>(*i_data);
// We'll want to avoid adding duplicate data if possible.
if (iv_regDump.end() == iv_regDump.find(i_chip))
{
// The chip doesn't exist in the map. Therefore, the data
// doesn't currently exist. So, add it.
iv_regDump[i_chip].emplace_back(i_regId, i_regInst, data);
}
else
{
// Search this chip for the data.
RegDumpEntry entry{i_regId, i_regInst, data};
auto itr = std::find(iv_regDump[i_chip].begin(),
iv_regDump[i_chip].end(), entry);
if (iv_regDump[i_chip].end() == itr)
{
// The data doesn't currently exist. So, add it.
iv_regDump[i_chip].push_back(entry);
}
}
}
}
/** @brief Allows access to the signature list. */
const std::vector<Signature>& getSignatureList() const
{
return iv_sigLists;
}
/** @brief Allows access to the register dump. */
const std::map<Chip, std::vector<RegDumpEntry>>& getRegisterDump() const
{
return iv_regDump;
}
/** @brief Flushes the data to ensure a clean slate for isolation. */
void flush()
{
iv_sigLists.clear();
iv_regDump.clear();
}
}; // end class IsolationData
} // end namespace libhei