blob: 6eec9b04e8162f33abc796a3073f77f117b38edf [file] [log] [blame]
/*
* 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
*
* http://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 SIM_KELVIN_STATE_H_
#define SIM_KELVIN_STATE_H_
#include <any>
#include <array>
#include <cstdint>
#include <string>
#include <utility>
#include <vector>
#include "absl/functional/any_invocable.h"
#include "absl/strings/string_view.h"
#include "riscv/riscv_state.h"
#include "mpact/sim/generic/instruction.h"
#include "mpact/sim/util/memory/memory_interface.h"
namespace kelvin::sim {
using Instruction = ::mpact::sim::generic::Instruction;
// Kelvin HW reserves the 31st bit as the magic cache invalidation bit.
// SW can update the load/store address to include that bit to trigger immediate
// cache invalidation. The actual address should exclude that bit. In ISS the
// invalidation is no-op and the actual address should be in the lower bits.
//
// Note the core supports up to 2GB memory (4MB is actually integrated in RTL).
constexpr uint64_t kMemMask = 0x0000'0000'7fff'ffff;
// Default to 256 to match
// https://opensecura.googlesource.com/hw/kelvin/+/master/hdl/chisel/src/kelvin/Parameters.scala.
inline constexpr uint32_t kVectorLengthInBits = 256;
inline constexpr int kNumVregs = 64;
constexpr uint64_t kKelvinMaxMemoryAddress = 0x3f'ffffULL; // 4MB
template <typename T>
using AccArrayTemplate = std::array<T, kVectorLengthInBits / 32>;
using AccArrayType = AccArrayTemplate<uint32_t>;
using DwAccArray = std::array<uint32_t, 32>;
class KelvinState : public mpact::sim::riscv::RiscVState {
public:
KelvinState(absl::string_view id, mpact::sim::riscv::RiscVXlen xlen,
mpact::sim::util::MemoryInterface *memory,
mpact::sim::util::AtomicMemoryOpInterface *atomic_memory);
KelvinState(absl::string_view id, mpact::sim::riscv::RiscVXlen xlen,
mpact::sim::util::MemoryInterface *memory);
KelvinState(absl::string_view id, mpact::sim::riscv::RiscVXlen xlen);
~KelvinState() override = default;
// Deleted Constructors and operators.
KelvinState(const KelvinState &) = delete;
KelvinState(KelvinState &&) = delete;
KelvinState &operator=(const KelvinState &) = delete;
KelvinState &operator=(KelvinState &&) = delete;
void set_vector_length(uint32_t length) { vector_length_ = length; }
uint32_t vector_length() const { return vector_length_; }
AccArrayType *acc_vec(int index) { return &(acc_register_[index]); }
AccArrayTemplate<AccArrayType> acc_register() const { return acc_register_; }
uint32_t *dw_acc_vec(int i) { return &depthwise_acc_register_[i]; }
DwAccArray &dw_acc_register() { return depthwise_acc_register_; }
const DwAccArray &dw_acc_register() const { return depthwise_acc_register_; }
void SetLogArgs(std::any data) { log_args_.emplace_back(std::move(data)); }
std::string *clog_string() { return &clog_string_; }
void PrintLog(absl::string_view format_string);
// Extra Kelvin terminating state.
void MPause(const Instruction *inst);
// Add terminating state handler.
void AddMpauseHandler(absl::AnyInvocable<bool(const Instruction *)> handler) {
on_mpause_.emplace_back(std::move(handler));
}
private:
uint32_t vector_length_{kVectorLengthInBits};
// Variables to store the log arguments.
std::vector<std::any> log_args_;
std::string clog_string_;
// Extra state handlers
std::vector<absl::AnyInvocable<bool(const Instruction *)>> on_mpause_;
// Convolution accumulation register, set to be uint32[VLENW][VLENW].
AccArrayTemplate<AccArrayType> acc_register_;
// Depthwise convolution accumulation register.
DwAccArray depthwise_acc_register_;
};
} // namespace kelvin::sim
#endif // SIM_KELVIN_STATE_H_