blob: 0e805819cab9ca54b9d5159dbe9ff6b5f78b7814 [file]
// Copyright 2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_
#define LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_
#include <memory>
#include <string>
#include <vector>
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/string_view.h"
// This file provides classes to facilitate modeling program errors/exceptions
// and store appropriate error messages in a "controller". The controller allows
// program errors to be masked or unmasked by name. There is also an internal
// simulation program error name where any detected simulator errors (as opposed
// to simulated architecture errors) can be raised.
//
// The idea is that code that is responsible for instruction issue and control
// uses this code to detect when a program error/exception has been raised and
// based on the type/masking status of the error acts accordingly.
//
// Different simulator constructs use ProgramError instances to signal error
// occurrences to the ProgramErrorController.
//
// Note: The term exception is used to describe the hardware exception or
// program error that may be raised on a simulated target architecture. It does
// not refer to C++ exceptions.
namespace mpact {
namespace sim {
namespace generic {
class ProgramError;
// The ProgramErrorController keeps track of errors that have been raised
// during the simulation, or by the simulator itself (for internal errors).
// It supports masked and unmasked errors. It does not by itself perform any
// actions in response to a reported error.
class ProgramErrorController {
public:
// Name for internal simulator errors.
static constexpr char kInternalErrorName[] = "internal_simulator_error";
explicit ProgramErrorController(absl::string_view name);
// Clears the named program error (masked or unmasked).
void Clear(absl::string_view program_error_name);
// Clears all errors (masked or unmasked).
void ClearAll();
// Masks the named program error.
void Mask(absl::string_view program_error_name);
// Unmasks the named program error.
void Unmask(absl::string_view program_error_name);
// Returns true if the named program error is masked.
bool IsMasked(absl::string_view program_error_name);
// Returns true if any program errors have been set.
bool HasError() const;
// Returns true if a masked program error has been set.
bool HasMaskedError() const;
// Returns true if an unmasked program error has been set.
bool HasUnmaskedError() const;
// Returns a vector of active masked program error names. Active in this
// context means that they have not been cleared since they were raised.
std::vector<std::string> GetMaskedErrorNames() const;
// Returns a vector of active, unmasked program error names.
std::vector<std::string> GetUnmaskedErrorNames() const;
// Returns a reference to the vector of error messages associated with the
// named program error. If there is no such program_error_name the internal
// error is raised (see kInternalErrorName), and the error messages for that
// are returned.
const std::vector<std::string> &GetErrorMessages(
absl::string_view program_error_name);
// Raises the named program error and adds the error message to its message
// queue. This method is intended to be called from a ProgramError instance.
void Raise(absl::string_view program_error_name,
absl::string_view error_message);
// Add a program error name to the controller, return true if it was added
// successfully. Return false if it already exists.
bool AddProgramErrorName(absl::string_view program_error_name);
// Returns true if the program error name has already been added to the
// controller.
bool HasProgramErrorName(absl::string_view program_error_name);
// Return a unique_ptr to a ProgramError instance tied to a program error that
// already exists in the controller. Returns a nullptr if the program error
// doesn't exist.
std::unique_ptr<ProgramError> GetProgramError(
absl::string_view program_error_name);
// Accessors.
absl::string_view name() const { return name_; }
private:
// Internal method used to insert a program error into the map and vector.
void Insert(absl::string_view name);
std::string name_;
struct ProgramErrorInfo {
std::string name;
bool is_masked;
std::vector<std::string> error_messages;
explicit ProgramErrorInfo(absl::string_view error_name)
: name(error_name), is_masked(false) {}
};
absl::flat_hash_map<std::string, int> program_error_map_;
absl::flat_hash_set<int> unmasked_program_errors_;
absl::flat_hash_set<int> masked_program_errors_;
std::vector<ProgramErrorInfo> program_error_info_;
};
// The ProgramError class is used as a handle to report a particular program
// error or exception. Each ProgramError instance is tied to a particular
// error or exception type.
class ProgramError {
friend class ProgramErrorController;
private:
// The constructor is private, as the handle is obtained from a
// ProgramErrorController instance.
ProgramError(absl::string_view name, ProgramErrorController *controller);
public:
// Raise the error to the ProgramErrorController with the given additional
// error message.
void Raise(absl::string_view error_message);
// Accessor.
absl::string_view name() const { return name_; }
private:
std::string name_;
ProgramErrorController *controller_;
};
} // namespace generic
} // namespace sim
} // namespace mpact
#endif // LEARNING_BRAIN_RESEARCH_MPACT_SIM_GENERIC_PROGRAM_ERROR_H_