blob: cba72345b4f06b63723d28213bd93a88efe29b80 [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.
#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_