blob: 6e6e3fb7527e4766b5768cc27c8edb67fae732e2 [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 MPACT_SIM_GENERIC_CONTROL_REGISTER_H_
#define MPACT_SIM_GENERIC_CONTROL_REGISTER_H_
// Defines a new register base class that registers a callback function that
// is called when the register receives a new value update in the form of a
// data buffer. The callback can be used in several ways according to need. One
// intended use case is to generate a side-effect or action in the simulated
// system. Another may be to constrain the written value to a legal subset or
// bit range, for instance when using a 32 bit element type to store an 18
// bit value. This function is in addition to the "next_update_callback" of
// RegisterBase, in that it is persistent, and allows for changes to the
// stored value before the "next_update_callback" is called.
//
// While the additional functionality of this class over the regular Register
// class is minor, it is done in a separate class to avoid adding any more
// overhead to the most common usecase of normal register writes.
//
// It's worth noting that the value_update_notification that is available for
// the RegisterBase class will only be called if the RegisterBase::SetDataBuffer
// method is called from the update callback function, as that is the only way
// the register object's data pointer is updated.
#include <cstdint>
#include <functional>
#include <map>
#include <string>
#include <vector>
#include "absl/strings/string_view.h"
#include "mpact/sim/generic/data_buffer.h"
#include "mpact/sim/generic/register.h"
#include "mpact/sim/generic/state_item.h"
#include "mpact/sim/generic/state_item_base.h"
namespace mpact {
namespace sim {
namespace generic {
class ArchState;
// Base class for control registers types with the DataBufferDestination
// interface. There is no default constructor, should only be
// constructed/destructed from derived classes.
class ControlRegisterBase : public RegisterBase {
public:
// Type alias for the update callback function type (set in the constructor).
using UpdateCallbackFunction =
std::function<void(ControlRegisterBase *, DataBuffer *)>;
ControlRegisterBase() = delete;
ControlRegisterBase(const ControlRegisterBase &) = delete;
~ControlRegisterBase() override = default;
// Calls the update callback function.
void SetDataBuffer(DataBuffer *db) override;
protected:
ControlRegisterBase(ArchState *arch_state, absl::string_view name,
const std::vector<int> &shape, int element_size,
UpdateCallbackFunction on_update_callback);
private:
UpdateCallbackFunction on_update_callback_;
};
// Scalar control register type with value type ElementType.
template <typename ElementType>
using ControlRegister = StateItem<ControlRegisterBase, ElementType,
RegisterSourceOperand<ElementType>,
RegisterDestinationOperand<ElementType>>;
// Holding off defining any vector valued or matrix valued control registers
// for now until the need arises. Most control registers are scalar.
} // namespace generic
} // namespace sim
} // namespace mpact
#endif // MPACT_SIM_GENERIC_CONTROL_REGISTER_H_