blob: 640ff0c0c4078381b60c3d34b7966c0893d6ceb0 [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_DECODER_SLOT_H_
#define MPACT_SIM_DECODER_SLOT_H_
#include <limits>
#include <string>
#include <tuple>
#include <vector>
#include "absl/base/no_destructor.h"
#include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_map.h"
#include "absl/container/flat_hash_set.h"
#include "absl/status/status.h"
#include "absl/strings/string_view.h"
#include "mpact/sim/decoder/InstructionSetParser.h"
#include "mpact/sim/decoder/base_class.h"
#include "mpact/sim/decoder/instruction_set_contexts.h"
#include "mpact/sim/decoder/opcode.h"
#include "mpact/sim/decoder/template_expression.h"
namespace mpact {
namespace sim {
namespace machine_description {
namespace instruction_set {
class Instruction;
class InstructionSet;
class Resource;
// A structure that holds the resources specified by a named resource specifier.
struct ResourceSpec {
std::string name;
std::vector<ResourceReference*> use_vec;
std::vector<ResourceReference*> acquire_vec;
};
// A slot class instance represents one or more identical instruction slots
// in an instruction word where a defined set of opcodes may be executed. A
// slot may inherit from a base slot to facilitate the factoring of common
// subsets of instruction opcodes into "base slots". These "base slots" need
// not be directly used in a bundle, in which case, they are not part of the
// instruction word encoding per se.
class Slot {
public:
using BaseSlot = BaseClass<Slot>;
using ResourceDetailsCtx = ::sim::machine_description::instruction_set::
generated::InstructionSetParser::Resource_detailsContext;
// Constructor and destructor.
Slot(absl::string_view name, InstructionSet* instruction_set,
bool is_templated, SlotDeclCtx* ctx, unsigned generator_version);
Slot(absl::string_view name, InstructionSet* instruction_set,
bool is_templated, SlotDeclCtx* ctx)
: Slot(name, instruction_set, is_templated, ctx, 1) {}
~Slot();
// Add declared opcode to the current slot.
absl::Status AppendInstruction(Instruction* inst);
// Add an opcode inherited from a base slot to the current slot.
absl::Status AppendInheritedInstruction(Instruction* inst,
TemplateInstantiationArgs* args);
// Add default instruction attribute.
void AddInstructionAttribute(const std::string& name,
TemplateExpression* expr);
bool HasInstruction(const std::string& opcode_name) const;
// Return string for the header file declarations for this class.
std::string GenerateClassDeclaration(absl::string_view encoding_type) const;
// Return string for the .cc file definitions for this class.
std::string GenerateClassDefinition(absl::string_view encoding_type);
// Add a non-templated slot as a base.
absl::Status AddBase(const Slot* base);
// Add a templated slot as a base with the vector of expressions as the
// template parameter values.
absl::Status AddBase(const Slot* base, TemplateInstantiationArgs* arguments);
// Add a declared constant (scoped to the slot).
absl::Status AddConstant(const std::string& ident, const std::string& type,
TemplateExpression* expression);
TemplateExpression* GetConstExpression(const std::string& ident) const;
// When the current slot is templated, adds an identifier as a template
// formal parameter.
absl::Status AddTemplateFormal(const std::string& name);
TemplateFormal* GetTemplateFormal(const std::string& name) const;
// Generate the calls to encode the given operand.
std::string GenerateOperandEncoder(int position, absl::string_view op_name,
const OperandLocator& locator,
const Opcode* opcode) const;
// Generate regex for a given instruction.
std::tuple<std::string, std::vector<OperandLocator>> GenerateRegEx(
const Instruction* inst, std::vector<std::string>& formats) const;
// Generate regexes to match the assembly string for the instructions.
std::tuple<std::string, std::string> GenerateAsmRegexMatcher() const;
// Generate assembler function for the given instruction.
std::string GenerateAssemblerFcn(const Instruction* inst,
absl::string_view encoder_type) const;
// Resources
Resource* GetOrInsertResource(const std::string& name);
// Attributes
void AddAttributeName(const std::string& name);
// Getters and setters.
InstructionSet* instruction_set() const { return instruction_set_; }
const SlotDeclCtx* ctx() const { return ctx_; }
int default_instruction_size() const { return default_instruction_size_; }
void set_default_instruction_size(int val) {
default_instruction_size_ = val;
}
TemplateExpression* default_latency() const { return default_latency_; }
void set_default_latency(TemplateExpression* latency_expr) {
if (default_latency_ != nullptr) delete default_latency_;
default_latency_ = latency_expr;
}
Instruction* default_instruction() const { return default_instruction_; }
void set_default_instruction(Instruction* inst) {
default_instruction_ = inst;
}
int size() const { return size_; }
void set_size(int size) { size_ = size; }
int min_instruction_size() const { return min_instruction_size_; }
void set_min_instruction_size(int size) { min_instruction_size_ = size; }
bool is_templated() const { return is_templated_; }
bool is_marked() const { return is_marked_; }
void set_is_marked(bool value) { is_marked_ = value; }
void set_is_referenced(bool value) { is_referenced_ = value; }
bool is_referenced() const { return is_referenced_; }
const std::string& name() const { return name_; }
const std::string& pascal_name() const { return pascal_name_; }
const std::vector<BaseSlot>& base_slots() const { return base_slots_; }
const absl::btree_map<std::string, Instruction*>& instruction_map() const {
return instruction_map_;
}
const std::vector<TemplateFormal*>& template_parameters() const {
return template_parameters_;
}
const absl::flat_hash_map<std::string, int>& template_parameter_map() const {
return template_parameter_map_;
}
absl::btree_map<std::string, ResourceDetailsCtx*>& resource_spec_map() {
return resource_spec_map_;
}
absl::btree_map<std::string, IdentListCtx*>& resource_array_ref_map() {
return resource_array_ref_map_;
}
const absl::btree_map<std::string, TemplateExpression*>& attribute_map() {
return attribute_map_;
}
const absl::btree_set<std::string>& attribute_names() const {
return attribute_names_;
}
private:
// Returns the name of the instruction array used for this slot. The
// instruction array is a constexpr global array of instruction information,
// keyed by the opcode.
std::string GetInstructionArrayName() const;
// These functions generate the functions that are called by the decoder to
// set the instruction operands.
std::string CreateOperandLookupKey(const Opcode* opcode) const;
std::string GenerateOperandSetterFcn(absl::string_view getter_name,
absl::string_view encoding_type,
const Opcode* opcode) const;
// These functions generate the functions that are called by the decoder to
// set the instruction resources.
std::string CreateResourceKey(
const std::vector<const ResourceReference*>& refs) const;
std::string GenerateResourceSetter(const Instruction* inst,
absl::string_view encoding_type);
std::string GenerateResourceSetterFcn(absl::string_view name,
const Instruction* inst,
absl::string_view encoding_type) const;
// These functions generate the functions that are called by the decoder to
// set the instruction disassembly string.
std::string GenerateDisassemblySetter(const Instruction* inst);
std::string GenerateDisasmSetterFcn(absl::string_view name,
const Instruction* inst) const;
// These functions generate the functions that are called by the decoder to
// set the instruction attributes.
std::string GenerateAttributeSetter(const Instruction* inst);
std::string GenerateAttributeSetterFcn(absl::string_view name,
const Instruction* inst) const;
std::string CreateAttributeLookupKey(const Instruction* inst) const;
// Generates a string that defines a global constexpr array of instruction
// opcodes and instruction info structs. Also populates the setter function
// string 'setter_functions_' with the setters.
std::string CreateFuncGetterGlobalArray(absl::string_view encoding_type);
// Transitively check if base slot is in the predecessor set of the current
// slot or any of its inheritance predecessors. Returns AlreadyExistsError
// if the current slot or its predecessors already inherit from base or its
// predecessors.
absl::Status CheckPredecessors(const Slot* base) const;
// Parent instruction_set class.
InstructionSet* instruction_set_;
// Parser context.
SlotDeclCtx* ctx_ = nullptr;
// The default and minimum opcode size specified for the slot.
int default_instruction_size_ = 1;
int min_instruction_size_ = std::numeric_limits<int>::max();
// Default latency for destination operands.
TemplateExpression* default_latency_ = nullptr;
// Fallback opcode for failed decodes.
Instruction* default_instruction_ = nullptr;
// Number of instances of this slot in the instruction_set instruction word.
int size_ = 1;
unsigned generator_version_;
// True if the slot is a templated slot.
bool is_templated_;
bool is_marked_ = false;
// True if this slot is referenced in a bundle.
bool is_referenced_ = false;
// Name of slot.
std::string name_;
// Name of slot in PascalCase.
std::string pascal_name_;
// Pointer to slot it inherits from.
std::vector<BaseSlot> base_slots_;
absl::flat_hash_set<const Slot*> predecessor_set_;
// Map from operand getter key to operand getter function name. These are
// static so that they can be shared across different slots.
static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
operand_setter_name_map_;
static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
disasm_setter_name_map_;
static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
resource_setter_name_map_;
static absl::NoDestructor<absl::flat_hash_map<std::string, std::string>>
attribute_setter_name_map_;
// Stores a string representation of the instruction array for this slot. This
// is an array that is used to initialize the map within the decoder.
std::string instruction_array_str_;
std::string setter_functions_;
// Used to list the unique getters for the operands.
absl::flat_hash_set<std::string> pred_operand_getters_;
absl::flat_hash_set<std::string> src_operand_getters_;
absl::flat_hash_set<std::string> dst_operand_getters_;
// Map of instructions defined in this slot or inherited.
absl::btree_map<std::string, Instruction*> instruction_map_;
absl::flat_hash_set<std::string> operand_setters_;
// Template parameter names.
std::vector<TemplateFormal*> template_parameters_;
absl::flat_hash_map<std::string, int> template_parameter_map_;
absl::flat_hash_map<std::string, TemplateExpression*> constant_map_;
// Named resource specifiers.
absl::btree_map<std::string, ResourceDetailsCtx*> resource_spec_map_;
absl::btree_map<std::string, IdentListCtx*> resource_array_ref_map_;
// Default instruction attributes.
absl::btree_map<std::string, TemplateExpression*> attribute_map_;
absl::btree_set<std::string> attribute_names_;
};
} // namespace instruction_set
} // namespace machine_description
} // namespace sim
} // namespace mpact
#endif // MPACT_SIM_DECODER_SLOT_H_