| // 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/fifo.h" |
| |
| #include <string> |
| #include <vector> |
| |
| #include "absl/strings/string_view.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace generic { |
| |
| FifoBase::FifoBase(class ArchState *arch_state, absl::string_view name, |
| const std::vector<int> &shape, int element_size, |
| int default_capacity) |
| : StateItemBase(arch_state, name, shape, element_size), |
| Component(std::string(name), arch_state), |
| depth_("depth", default_capacity), |
| overflow_program_error_(nullptr), |
| underflow_program_error_(nullptr), |
| name_(name), |
| capacity_(default_capacity), |
| reserved_(0) { |
| // empty |
| } |
| |
| FifoBase::~FifoBase() { |
| for (auto ptr : fifo_) { |
| ptr->DecRef(); |
| } |
| fifo_.clear(); |
| } |
| |
| bool FifoBase::IsFull() const { return fifo_.size() + reserved_ >= capacity_; } |
| |
| bool FifoBase::IsEmpty() const { return fifo_.empty() && (reserved_ == 0); } |
| |
| bool FifoBase::IsOverSubscribed() const { |
| return fifo_.size() + reserved_ > capacity_; |
| } |
| |
| void FifoBase::Reserve(int count) { reserved_ += count; } |
| |
| bool FifoBase::Push(DataBuffer *db) { |
| // If any slots are reserved, decrement first before checking for full. |
| if (reserved_ > 0) { |
| reserved_--; |
| } |
| if (IsFull()) { |
| if (nullptr != overflow_program_error_) { |
| overflow_program_error_->Raise("Overflow in fifo " + name_); |
| } |
| return false; |
| } else { |
| db->IncRef(); |
| fifo_.push_back(db); |
| return true; |
| } |
| } |
| |
| void FifoBase::Pop() { |
| if (fifo_.empty()) { |
| if (nullptr != underflow_program_error_) { |
| underflow_program_error_->Raise("Underflow in fifo " + name_); |
| } |
| return; |
| } |
| fifo_.front()->DecRef(); |
| fifo_.pop_front(); |
| } |
| |
| DataBuffer *FifoBase::Front() const { |
| if (fifo_.empty()) { |
| if (nullptr != underflow_program_error_) { |
| underflow_program_error_->Raise("Underflow in fifo " + name_); |
| } |
| return nullptr; |
| } else { |
| return fifo_.front(); |
| } |
| } |
| |
| unsigned FifoBase::Available() const { return fifo_.size(); } |
| |
| void FifoBase::SetDataBuffer(DataBuffer *db) { Push(db); } |
| |
| absl::Status FifoBase::ImportSelf( |
| const mpact::sim::proto::ComponentData &component_data) { |
| auto status = Component::ImportSelf(component_data); |
| if (!status.ok()) return status; |
| capacity_ = depth_.GetValue(); |
| return absl::OkStatus(); |
| } |
| |
| } // namespace generic |
| } // namespace sim |
| } // namespace mpact |