blob: f5fb4749ebebb406ec7765c5cd9bf85173f6de3a [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.
#include "mpact/sim/generic/complex_resource_operand.h"
#include "absl/status/status.h"
namespace mpact {
namespace sim {
namespace generic {
// Sets the bits in the bit_array_ array for the cycles, starting at begin and
// ending at end. Bits are counted from lsb to msb [(63..0), (127..64), (191,
// 128),..] etc.
absl::Status ComplexResourceOperand::SetCycleMask(size_t begin, size_t end) {
// If the resource is null return an error.
if (resource_ == nullptr) {
return absl::InternalError("Resource is null in ComplexResourceOperand");
}
// If the start cycle is after the end cycle, return an error.
if (begin > end) {
return absl::InvalidArgumentError(absl::StrCat(
"Begin cycle (", begin, ") is greater than end cycle (", end, ")"));
}
// If the end cycle is beyond the cycle depth of the resource, return an
// error.
if (end >= resource_->cycle_depth()) {
return absl::InvalidArgumentError(absl::StrCat(
"ComplexResourceOperand for resource '", resource_->name(), "': end(",
end, ") is greater than cycle depth (", resource_->cycle_depth()));
}
// Compute the size of the array needed.
span_size_ = (end + 63) / 64;
// Delete any previous allocation.
delete[] bit_array_;
// Allocate the array and clear the bytes.
bit_array_ = new uint64_t[span_size_];
memset(bit_array_, 0, span_size_ * 8);
// Set the bits in [begin, end].
for (size_t i = begin; i <= end; i++) {
int word_index = i >> 6;
int bit_index = i & 0x3f;
bit_array_[word_index] |= 1ULL << bit_index;
}
return absl::OkStatus();
}
absl::Status ComplexResourceOperand::SetCycleMask(
absl::Span<const uint64_t> span) {
// If the resource is null, return an error.
if (resource_ == nullptr) {
return absl::InternalError("Resource is null in ComplexResourceOperand");
}
// If the span is too long, return an error.
if (resource_->bit_array().size() < span.size()) {
return absl::InvalidArgumentError("Span too long for cycle mask");
}
span_size_ = span.size();
// See if there are any bits set beyond the cycle depth of the resource.
size_t mod = resource_->cycle_depth() & 0x3f;
if (span[span_size_ - 1] >> mod) {
return absl::InvalidArgumentError(
absl::StrCat("Bits set beyond the cycle depth of resource '",
resource_->name(), "'"));
}
// Make sure that there are some bits set in the span.
uint64_t or_value = 0;
for (uint64_t value : span) {
or_value |= value;
}
if (or_value == 0) {
return absl::InvalidArgumentError("No bits set in input span");
}
// Delete any previous allocation.
delete[] bit_array_;
// Allocate the array and copy the span.
bit_array_ = new uint64_t[span_size_];
for (int i = 0; i < span_size_; i++) {
bit_array_[i] = span[i];
}
return absl::OkStatus();
}
} // namespace generic
} // namespace sim
} // namespace mpact