No public description PiperOrigin-RevId: 869737255 Change-Id: I936f44db323f8d67ed19f993aca414f8712c9aff
diff --git a/mpact/sim/decoder/BUILD b/mpact/sim/decoder/BUILD index 00eaa42..f214fa9 100644 --- a/mpact/sim/decoder/BUILD +++ b/mpact/sim/decoder/BUILD
@@ -128,6 +128,7 @@ "@com_google_absl//absl/status", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings", + "@com_google_absl//absl/strings:str_format", "@com_googlesource_code_re2//:re2", ], )
diff --git a/mpact/sim/decoder/slot.cc b/mpact/sim/decoder/slot.cc index d967ec5..0c786ef 100644 --- a/mpact/sim/decoder/slot.cc +++ b/mpact/sim/decoder/slot.cc
@@ -34,6 +34,7 @@ #include "absl/status/statusor.h" #include "absl/strings/numbers.h" #include "absl/strings/str_cat.h" +#include "absl/strings/str_format.h" #include "absl/strings/string_view.h" #include "mpact/sim/decoder/format_name.h" #include "mpact/sim/decoder/instruction.h" @@ -1101,6 +1102,10 @@ return output; } +std::string Slot::GetInstructionArrayName() const { + return absl::StrCat("k", pascal_name(), "SlotInstructionArray"); +} + // Generates a string that is a unique identifier from the operands to // determine which instructions can share operand getter functions. std::string Slot::CreateOperandLookupKey(const Opcode* opcode) const { @@ -1251,25 +1256,22 @@ return output; } -std::string Slot::ListFuncGetterInitializations( - absl::string_view encoding_type) { - std::string output; - if (instruction_map_.empty()) return output; - std::string class_name = pascal_name() + "Slot"; - // For each instruction create two lambda functions. One that is used to - // obtain the semantic function object for the instruction, the other a - // lambda that sets the predicate, source and target operands. Both lambdas - // use calls to virtual functions declared in the current class or a base - // class thereof. - std::string signature = - absl::StrCat("(Instruction *inst, ", encoding_type, - " *enc, OpcodeEnum opcode, SlotEnum slot, int entry)"); +std::string Slot::CreateFuncGetterGlobalArray(absl::string_view encoding_type) { + const std::string class_name = pascal_name() + "Slot"; + std::string output = absl::StrFormat( + "const std::array<std::pair<OpcodeEnum, InstructionInfo>, %d>\n" + "%s {\n", + instruction_map_.size() + 1, GetInstructionArrayName()); + absl::StrAppend(&setter_functions_, GenerateOperandSetterFcn( absl::StrCat(pascal_name(), "SlotSetOperandsNull"), encoding_type, default_instruction_->opcode())); + absl::StrAppend( - &output, " {static_cast<int>(OpcodeEnum::kNone), {OperandSetter{", + &output, + " std::make_pair(OpcodeEnum::kNone, " + "InstructionInfo{OperandSetter{", pascal_name(), "SlotSetOperandsNull},\n" " ", @@ -1277,7 +1279,7 @@ GenerateResourceSetter(default_instruction_, encoding_type), ",\n", " ", GenerateAttributeSetter(default_instruction_), ",\n", " SemFuncSetter{", default_instruction_->semfunc_code_string(), "}, ", - default_instruction_->opcode()->instruction_size(), "}},\n"); + default_instruction_->opcode()->instruction_size(), "}),\n"); for (auto const& [unused, inst_ptr] : instruction_map_) { auto* instruction = inst_ptr; std::string opcode_name = instruction->opcode()->pascal_name(); @@ -1316,14 +1318,16 @@ } sep = ", "; } - absl::StrAppend(&output, " {static_cast<int>(OpcodeEnum::k", opcode_name, - "), {OperandSetter{", operands_str, "},\n", " ", - GenerateDisassemblySetter(instruction), ",\n", " ", - GenerateResourceSetter(instruction, encoding_type), ",\n", - " ", GenerateAttributeSetter(instruction), ",\n", + absl::StrAppend(&output, " std::make_pair(OpcodeEnum::k", opcode_name, + ", InstructionInfo{OperandSetter{", operands_str, "},\n", + " ", GenerateDisassemblySetter(instruction), ",\n", + " ", GenerateResourceSetter(instruction, encoding_type), + ",\n", " ", GenerateAttributeSetter(instruction), ",\n", " SemFuncSetter{", code_str, "}, ", - instruction->opcode()->instruction_size(), "}},\n"); + instruction->opcode()->instruction_size(), "}),\n"); } + absl::StrAppend(&output, "};\n\n"); + return output; } @@ -1346,10 +1350,8 @@ "* isa_encoding, SlotEnum, int entry);\n", "\n" " private:\n" - " ArchState *arch_state_;\n" + " ArchState *arch_state_;\n", " absl::flat_hash_map<int, InstructionInfo> instruction_info_;\n", - //" std::array<InstructionInfo, ", - // instruction_map_.size() + 1, "> instruction_info_", ";\n", " static constexpr SlotEnum slot_ = SlotEnum::k", pascal_name(), ";\n" "};\n" @@ -1367,9 +1369,14 @@ absl::StrAppend( &output, class_name, "::", class_name, "(ArchState *arch_state) :\n" - " arch_state_(arch_state),\n", - " instruction_info_{{\n", ListFuncGetterInitializations(encoding_type), - "}} {}\n", + " arch_state_(arch_state) {\n" + " for (const auto& inst_info : ", + GetInstructionArrayName(), + ") {\n" + " instruction_info_[static_cast<int>(inst_info.first)] =\n" + " inst_info.second;\n" + " }\n" + "}\n" "\n" "Instruction *", class_name, "::Decode(uint64_t address, ", encoding_type, @@ -1398,9 +1405,12 @@ " inst_info.attribute_setter(inst);\n" " return inst;\n" "}\n"); - // Prepend the setter functions. - std::string combined_output = absl::StrCat( - "namespace {\n\n", setter_functions_, "} // namespace\n\n", output); + // Prepend the setter functions and global instruction map. + const std::string instruction_map_string = + CreateFuncGetterGlobalArray(encoding_type); + std::string combined_output = + absl::StrCat("namespace {\n\n", setter_functions_, instruction_map_string, + "} // namespace\n\n", output); return combined_output; }
diff --git a/mpact/sim/decoder/slot.h b/mpact/sim/decoder/slot.h index fbdae67..640ff0c 100644 --- a/mpact/sim/decoder/slot.h +++ b/mpact/sim/decoder/slot.h
@@ -168,6 +168,11 @@ } 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; @@ -194,13 +199,10 @@ std::string GenerateAttributeSetterFcn(absl::string_view name, const Instruction* inst) const; std::string CreateAttributeLookupKey(const Instruction* inst) const; - // Generates a string that is a unique key for the operands to determine which - // instructions can share operand getter functions. - // Build up a string containing the function getter initializers that are - // stored in two flat hash maps with the opcode as the key. These functions - // are lambda's that call the getters for the semantic functions as well as - // operand getters for each instruction opcode. - std::string ListFuncGetterInitializations(absl::string_view encoding_type); + // 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 @@ -242,6 +244,10 @@ 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_;