| // 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. |
| |
| #include "riscv/riscv_register.h" |
| |
| #include <any> |
| #include <cstdint> |
| #include <limits> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/types/span.h" |
| #include "mpact/sim/generic/data_buffer.h" |
| #include "mpact/sim/generic/register.h" |
| #include "riscv/riscv_state.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace riscv { |
| |
| using DataBuffer = generic::DataBuffer; |
| |
| RV32VectorSourceOperand::RV32VectorSourceOperand( |
| absl::Span<generic::RegisterBase*> reg_span, std::string op_name) |
| : op_name_(op_name) { |
| if (reg_span.empty()) return; |
| if (reg_span[0] == nullptr) return; |
| |
| vector_size_ = reg_span[0]->shape()[0]; |
| vector_byte_size_ = vector_size_ * reg_span[0]->element_size(); |
| group_size_ = reg_span.size(); |
| for (int i = 0; i < group_size_; i++) { |
| // If there is a nullptr, break off the loop and truncate the potential |
| // vector group. |
| if (reg_span[i] == nullptr) { |
| group_size_ = i; |
| break; |
| } |
| // Verify that the vector registers in the group all have the same length. |
| if (reg_span[i]->shape()[0] != vector_size_) { |
| registers_[i] = nullptr; |
| group_size_ = i; |
| break; |
| } |
| registers_.push_back(reg_span[i]); |
| } |
| } |
| |
| RV32VectorSourceOperand::RV32VectorSourceOperand( |
| absl::Span<generic::RegisterBase*> reg_span) |
| : RV32VectorSourceOperand(reg_span, reg_span[0]->name()) {} |
| |
| RV32VectorSourceOperand::RV32VectorSourceOperand(generic::RegisterBase* reg, |
| std::string op_name) |
| : op_name_(op_name) { |
| if (reg == nullptr) return; |
| |
| vector_size_ = 1; |
| vector_byte_size_ = vector_size_ * reg->element_size(); |
| group_size_ = 1; |
| registers_.push_back(reg); |
| } |
| |
| RV32VectorSourceOperand::RV32VectorSourceOperand(generic::RegisterBase* reg) |
| : RV32VectorSourceOperand(reg, reg->name()) {} |
| |
| bool RV32VectorSourceOperand::AsBool(int i) { |
| int offset = i % vector_byte_size_; |
| int group = i / vector_byte_size_; |
| return static_cast<bool>( |
| registers_[group]->data_buffer()->Get<uint8_t>(offset)); |
| } |
| |
| int8_t RV32VectorSourceOperand::AsInt8(int i) { |
| int offset = i % vector_byte_size_; |
| int group = i / vector_byte_size_; |
| return registers_[group]->data_buffer()->Get<int8_t>(offset); |
| } |
| |
| uint8_t RV32VectorSourceOperand::AsUint8(int i) { |
| int offset = i % vector_byte_size_; |
| int group = i / vector_byte_size_; |
| return registers_[group]->data_buffer()->Get<uint8_t>(offset); |
| } |
| |
| int16_t RV32VectorSourceOperand::AsInt16(int i) { |
| int offset = i % (vector_byte_size_ >> 1); |
| int group = i / (vector_byte_size_ >> 1); |
| return registers_[group]->data_buffer()->Get<int16_t>(offset); |
| } |
| |
| uint16_t RV32VectorSourceOperand::AsUint16(int i) { |
| int offset = i % (vector_byte_size_ >> 1); |
| int group = i / (vector_byte_size_ >> 1); |
| return registers_[group]->data_buffer()->Get<uint16_t>(offset); |
| } |
| |
| int32_t RV32VectorSourceOperand::AsInt32(int i) { |
| int offset = i % (vector_byte_size_ >> 2); |
| int group = i / (vector_byte_size_ >> 2); |
| return registers_[group]->data_buffer()->Get<int32_t>(offset); |
| } |
| |
| uint32_t RV32VectorSourceOperand::AsUint32(int i) { |
| int offset = i % (vector_byte_size_ >> 2); |
| int group = i / (vector_byte_size_ >> 2); |
| return registers_[group]->data_buffer()->Get<uint32_t>(offset); |
| } |
| |
| int64_t RV32VectorSourceOperand::AsInt64(int i) { |
| int offset = i % (vector_byte_size_ >> 3); |
| int group = i / (vector_byte_size_ >> 3); |
| return registers_[group]->data_buffer()->Get<int64_t>(offset); |
| } |
| |
| uint64_t RV32VectorSourceOperand::AsUint64(int i) { |
| int offset = i % (vector_byte_size_ >> 3); |
| int group = i / (vector_byte_size_ >> 3); |
| return registers_[group]->data_buffer()->Get<uint64_t>(offset); |
| } |
| |
| RV32VectorTrueOperand::RV32VectorTrueOperand(RiscVState* state) |
| : RV32VectorSourceOperand( |
| state->GetRegister<RVVectorRegister>(kName).first) { |
| // Ensure the value is all ones. |
| auto* reg = state->GetRegister<RVVectorRegister>(kName).first; |
| auto data = reg->data_buffer()->Get<uint64_t>(); |
| for (int i = 0; i < data.size(); i++) { |
| data[i] = std::numeric_limits<uint64_t>::max(); |
| } |
| } |
| |
| RV32VectorDestinationOperand::RV32VectorDestinationOperand( |
| absl::Span<generic::RegisterBase*> reg_span, int latency, |
| std::string op_name) |
| : db_factory_(reg_span[0]->arch_state()->db_factory()), |
| delay_line_(reg_span[0]->arch_state()->data_buffer_delay_line()), |
| latency_(latency), |
| op_name_(op_name) { |
| if (reg_span.empty()) return; |
| if (reg_span[0] == nullptr) return; |
| |
| vector_size_ = reg_span[0]->shape()[0]; |
| vector_byte_size_ = vector_size_ * reg_span[0]->element_size(); |
| group_size_ = reg_span.size(); |
| for (int i = 0; i < group_size_; i++) { |
| // If there is a nullptr, break off the loop and truncate the potential |
| // vector group. |
| if (reg_span[i] == nullptr) { |
| group_size_ = i; |
| break; |
| } |
| // Verify that the vector registers in the group all have the same length. |
| if (reg_span[i]->shape()[0] != vector_size_) { |
| registers_[i] = nullptr; |
| group_size_ = i; |
| break; |
| } |
| registers_.push_back(reg_span[i]); |
| } |
| } |
| |
| RV32VectorDestinationOperand::RV32VectorDestinationOperand( |
| absl::Span<generic::RegisterBase*> reg_span, int latency) |
| : RV32VectorDestinationOperand(reg_span, latency, reg_span[0]->name()) {} |
| |
| RV32VectorDestinationOperand::RV32VectorDestinationOperand( |
| generic::RegisterBase* reg, int latency, std::string op_name) |
| : op_name_(op_name) { |
| if (reg == nullptr) return; |
| |
| vector_size_ = 1; |
| vector_byte_size_ = vector_size_ * reg->element_size(); |
| group_size_ = 1; |
| registers_.push_back(reg); |
| } |
| |
| RV32VectorDestinationOperand::RV32VectorDestinationOperand( |
| generic::RegisterBase* reg, int latency) |
| : RV32VectorDestinationOperand(reg, latency, reg->name()) {} |
| |
| DataBuffer* RV32VectorDestinationOperand::AllocateDataBuffer() { |
| return AllocateDataBuffer(0); |
| } |
| |
| void RV32VectorDestinationOperand::InitializeDataBuffer(DataBuffer* db) { |
| InitializeDataBuffer(0, db); |
| } |
| |
| DataBuffer* RV32VectorDestinationOperand::CopyDataBuffer() { |
| return CopyDataBuffer(0); |
| } |
| |
| int RV32VectorDestinationOperand::latency() const { return latency_; } |
| |
| std::any RV32VectorDestinationOperand::GetObject() const { |
| return GetObject(0); |
| } |
| |
| std::vector<int> RV32VectorDestinationOperand::shape() const { |
| return registers_[0]->shape(); |
| } |
| |
| std::string RV32VectorDestinationOperand::AsString() const { return op_name_; } |
| |
| DataBuffer* RV32VectorDestinationOperand::AllocateDataBuffer(int i) { |
| DataBuffer* db = db_factory_->Allocate(registers_[i]->size()); |
| InitializeDataBuffer(i, db); |
| return db; |
| } |
| |
| void RV32VectorDestinationOperand::InitializeDataBuffer(int i, DataBuffer* db) { |
| db->set_destination(registers_[i]); |
| db->set_latency(latency_); |
| db->set_delay_line(delay_line_); |
| } |
| |
| DataBuffer* RV32VectorDestinationOperand::CopyDataBuffer(int i) { |
| DataBuffer* db = db_factory_->MakeCopyOf(registers_[i]->data_buffer()); |
| InitializeDataBuffer(i, db); |
| return db; |
| } |
| |
| std::any RV32VectorDestinationOperand::GetObject(int i) const { |
| return std::any(registers_[i]); |
| } |
| |
| } // namespace riscv |
| } // namespace sim |
| } // namespace mpact |