| // 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_SIMPLE_RESOURCE_H_ |
| #define MPACT_SIM_GENERIC_SIMPLE_RESOURCE_H_ |
| |
| #include <list> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/container/flat_hash_map.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "mpact/sim/generic/resource_bitset.h" |
| |
| namespace mpact { |
| namespace sim { |
| namespace generic { |
| |
| // A simple resource belongs to a SimpleResourcePool. It can be in two |
| // states: reserved or free, indicated by a single bit (1 - reserved, 0 - free) |
| // in a bit vector. While the exact semantics of reserved and free depends on |
| // the underlying use of the classes, the initial intended use is to have |
| // reserved mean that a write is pending to a register or an empty fifo to |
| // indicate when to stall (or hold) issue of an instruction due to RAW (or WAW) |
| // dependencies. A SimpleResource instance can be attached to a the object it |
| // represents so that the object can mark the resource free (or reserved) based |
| // on the state of the object. For instance, for a register/fifo, the instance |
| // may Release() the resource when the write lands. |
| |
| // A SimpleResource is part of a SimpleResourcePool that represents the set of |
| // resources as a bit vector. This makes it easy to specify a set of required |
| // resources as a SimpleResourceSet and test for availability with bitwise AND. |
| |
| // A SimpleResourceSet can be associated with an instruction to indicate the set |
| // of resources that must be available prior to issue. The issue logic then |
| // tests against the resource pool to see if any of the required resources are |
| // reserved or not. |
| |
| class SimpleResourcePool; |
| |
| // The SimpleResource class models a single simulated resource that can have |
| // two states: free or reserved. It is "simple" because it cannot be reserved |
| // for cycles in the future. Any reserve/free action takes effect immediately. |
| class SimpleResource { |
| friend class SimpleResourcePool; |
| |
| private: |
| // The constructor is private. It is called from a SimpleResourcePool |
| // instance in which the resource belongs. |
| SimpleResource(absl::string_view name, int index, SimpleResourcePool *pool); |
| SimpleResource() = delete; |
| virtual ~SimpleResource() = default; |
| |
| public: |
| // Mark the resource reserved in the associated resource pool. |
| void Acquire(); |
| // Mark the resource free in the associated resource pool. |
| void Release(); |
| // Return true if the resource is not marked reserved in the associated |
| // resource pool. |
| bool IsFree() const; |
| |
| // Returns the "one hot" bitvector for the resource. |
| const ResourceBitSet &resource_bit() const { return resource_bit_; } |
| |
| // The bit index of the resource in the bitvector. |
| int index() const { return index_; } |
| |
| // Other accessors. |
| const std::string &name() const { return name_; } |
| const SimpleResourcePool *pool() const { return pool_; } |
| |
| private: |
| ResourceBitSet resource_bit_; |
| std::string name_; |
| int index_; |
| SimpleResourcePool *pool_; |
| }; |
| |
| // The SimpleResourceSet models a set of individual SimpleResources that are |
| // reserved/released/checked (CanReserve()) at the same time. |
| class SimpleResourceSet { |
| friend class SimpleResourcePool; |
| |
| private: |
| explicit SimpleResourceSet(SimpleResourcePool *); |
| SimpleResourceSet() = delete; |
| virtual ~SimpleResourceSet() = default; |
| |
| public: |
| // Adds the resource to the resource set. Return error if the resource |
| // belongs to a different pool. |
| absl::Status AddResource(SimpleResource *resource); |
| absl::Status AddResource(absl::string_view name); |
| |
| // Mark the resources in the set reserved in the associated resource pool. |
| void Acquire(); |
| |
| // Mark the resources free in the associated resource pool. |
| void Release(); |
| |
| // Return true if the resource set is not marked reserved in the associated |
| // resource pool. |
| bool IsFree() const; |
| |
| std::string AsString() const; |
| |
| // Return the bit vector for the resources in this set. |
| const ResourceBitSet &resource_vector() const { return resource_vector_; } |
| |
| private: |
| ResourceBitSet resource_vector_; |
| SimpleResourcePool *pool_; |
| }; |
| |
| // The SimpleResourcePool is a class for managing a group of SimpleResource |
| // instances. The resource pool is meant to group together resources that |
| // typically would be checked/reserved/freed at the same. |
| class SimpleResourcePool { |
| public: |
| // Create a named resource pool with the given maximum size. |
| SimpleResourcePool(absl::string_view name, int width); |
| SimpleResourcePool() = delete; |
| virtual ~SimpleResourcePool(); |
| |
| // Add a named resource to the resource pool. This will assign the resource |
| // an index in the set of named resources in the pool. |
| absl::Status AddResource(absl::string_view name); |
| |
| // Return the SimpleResource pointer of the named resource, or nullptr if it |
| // hasn't been added. |
| SimpleResource *GetResource(absl::string_view name) const; |
| // Return the SimpleResource pointer of resource with bit index 'index', or |
| // nullptr if it hasn't been added. |
| SimpleResource *GetResource(unsigned index) const; |
| // If the resource does not exisit, add it. Return a pointer to the named |
| // resource. |
| SimpleResource *GetOrAddResource(absl::string_view name); |
| // Create an resource set for the current resource pool. |
| SimpleResourceSet *CreateResourceSet(); |
| |
| // Return true if the resources in the resource/resource set are not reserved |
| // in the resource pool. |
| bool IsFree(const SimpleResourceSet *resource_set) const; |
| bool IsFree(const SimpleResource *resource) const; |
| |
| // Mark the resource/resource set reserved in the resource pool. |
| void Acquire(const SimpleResourceSet *resource_set); |
| void Acquire(const SimpleResource *resource); |
| |
| // Mark the resource/resource set unreserved in the resource pool. |
| void Release(const SimpleResourceSet *resource_set); |
| void Release(const SimpleResource *resource); |
| |
| // List reserved resources as string. |
| std::string ReservedAsString() const; |
| |
| // Accessors. |
| const std::string &name() const { return name_; } |
| const ResourceBitSet &resource_vector() const { return resource_vector_; } |
| |
| // The width is the max number of resources (i.e., bitwidth of the resource |
| // vector). |
| unsigned width() const { return width_; } |
| |
| private: |
| absl::StatusOr<SimpleResource *> AddResourceInternal(absl::string_view name); |
| absl::flat_hash_map<std::string, SimpleResource *> resource_name_map_; |
| std::vector<SimpleResource *> resources_; |
| std::list<SimpleResourceSet *> resource_sets_; |
| ResourceBitSet resource_vector_; |
| std::string name_; |
| unsigned width_; |
| }; |
| |
| } // namespace generic |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_SIM_GENERIC_SIMPLE_RESOURCE_H_ |