| // 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_ |