This fixes handling of instruction attributes. Attributes are now per slot. PiperOrigin-RevId: 864978959 Change-Id: I3e3e22ba6eb6bf0b7239ea6899b8ab79addd07ac
diff --git a/mpact/sim/decoder/instruction_set.cc b/mpact/sim/decoder/instruction_set.cc index 710326d..796cc74 100644 --- a/mpact/sim/decoder/instruction_set.cc +++ b/mpact/sim/decoder/instruction_set.cc
@@ -38,8 +38,6 @@ namespace machine_description { namespace instruction_set { -absl::btree_set<std::string>* InstructionSet::attribute_names_ = nullptr; - static void EmitEnumNames(const absl::btree_set<std::string>& names, absl::string_view namespace_name, absl::string_view op_name, std::string& h_output, @@ -159,16 +157,6 @@ slot_order_.push_back(slot); } -void InstructionSet::AddAttributeName(const std::string& name) { - if (attribute_names_ == nullptr) { - attribute_names_ = new absl::btree_set<std::string>(); - } - auto iter = attribute_names_->find(name); - if (iter == attribute_names_->end()) { - attribute_names_->insert(name); - } -} - // Return a string containing class header file, for all bundles and slots. // As an example the following shows an abbreviated example of code that is // generated. @@ -751,16 +739,22 @@ EmitEnumNames(name_set, "list_complex_resource_names", "ListComplexResource", h_output, cc_output); // Emit instruction attribute types. - absl::StrAppend(&h_output, " enum class AttributeEnum {\n"); - int attribute_count = 0; - if (InstructionSet::attribute_names_ != nullptr) { - for (auto const& name : *InstructionSet::attribute_names_) { - absl::StrAppend(&h_output, " k", ToPascalCase(name), " = ", - attribute_count++, ",\n"); + + for (auto const& [name, slot_ptr] : slots_by_name) { + if (slot_ptr->attribute_names().empty()) continue; + absl::StrAppend(&h_output, "namespace ", ToSnakeCase(name), " {\n\n"); + absl::StrAppend(&h_output, " enum class AttributeEnum {\n"); + int attribute_count = 0; + if (!slot_ptr->attribute_names().empty()) { + for (auto const& attribute_name : slot_ptr->attribute_names()) { + absl::StrAppend(&h_output, " k", ToPascalCase(attribute_name), " = ", + attribute_count++, ",\n"); + } } + absl::StrAppend(&h_output, " kPastMaxValue = ", attribute_count, + "\n };\n\n"); + absl::StrAppend(&h_output, "} // namespace ", name, "\n\n"); } - absl::StrAppend(&h_output, " kPastMaxValue = ", attribute_count, - "\n };\n\n"); return {h_output, cc_output}; }
diff --git a/mpact/sim/decoder/instruction_set.h b/mpact/sim/decoder/instruction_set.h index a1a2efc..825eeba 100644 --- a/mpact/sim/decoder/instruction_set.h +++ b/mpact/sim/decoder/instruction_set.h
@@ -80,8 +80,6 @@ // defined. StringPair GenerateEnums(absl::string_view file_name); - static void AddAttributeName(const std::string& name); - void AddInstruction(Instruction* inst) { if (instruction_map_.contains(inst->opcode()->name())) return; instruction_map_.emplace(inst->opcode()->name(), inst); @@ -95,10 +93,7 @@ Bundle* bundle() { return bundle_; } OpcodeFactory* opcode_factory() const { return opcode_factory_.get(); } ResourceFactory* resource_factory() const { return resource_factory_.get(); } - // Attribute names are shared across the isa's. - static const absl::btree_set<std::string>* attribute_names() { - return attribute_names_; - } + absl::flat_hash_map<std::string, Bundle*>& bundle_map() { return bundle_map_; } @@ -141,8 +136,6 @@ // Maps from names to bundle/slot pointers. absl::flat_hash_map<std::string, Bundle*> bundle_map_; absl::flat_hash_map<std::string, Slot*> slot_map_; - // Attribute name list - shared across all the isas. - static absl::btree_set<std::string>* attribute_names_; // Maps from operand names to enum values. absl::flat_hash_map<std::string, int> pred_op_map_; absl::flat_hash_map<std::string, int> source_op_map_;
diff --git a/mpact/sim/decoder/instruction_set_visitor.cc b/mpact/sim/decoder/instruction_set_visitor.cc index 00172e4..0c9bf89 100644 --- a/mpact/sim/decoder/instruction_set_visitor.cc +++ b/mpact/sim/decoder/instruction_set_visitor.cc
@@ -1314,7 +1314,7 @@ absl::StrCat("Duplicate attribute name '", name, "' in list")); continue; } - InstructionSet::AddAttributeName(name); + slot->AddAttributeName(name); if (attribute->expression() != nullptr) { context_file_map_.insert( {attribute->expression(), context_file_map_.at(slot->ctx())}); @@ -1322,7 +1322,7 @@ attributes.emplace(name, expr); continue; } - attributes.emplace(name, new TemplateConstant(1)); + attributes.emplace(name, new TemplateConstant(0)); } // Are we parsing attributes for an instruction? if (inst != nullptr) {
diff --git a/mpact/sim/decoder/slot.cc b/mpact/sim/decoder/slot.cc index e7cf436..d967ec5 100644 --- a/mpact/sim/decoder/slot.cc +++ b/mpact/sim/decoder/slot.cc
@@ -252,33 +252,35 @@ const Instruction* inst) const { std::string output; absl::StrAppend(&output, "void ", name, "(Instruction *inst) {\n"); - if (!attribute_map_.empty()) { + int size = attribute_names_.size(); + if (size > 0) { // Allocate the array and initialize to zero. - absl::StrAppend(&output, " int *attrs = new int[", attribute_map_.size(), + absl::StrAppend(&output, " int *attrs = new int[", size, "];\n" - " attrs = {"); - std::string sep = ""; - for (auto const& [name, expr] : inst->attribute_map()) { - auto result = expr->GetValue(); + " *attrs = {"); + for (auto const& attribute_name : attribute_names_) { + auto it = inst->attribute_map().find(attribute_name); + if (it == inst->attribute_map().end()) { + absl::StrAppend(&output, "0, "); + continue; + } + auto result = it->second->GetValue(); if (!result.ok()) { - absl::StrAppend(&output, " #error Expression for '", name, - "' has no constant value\n"); + absl::StrAppend(&output, "0, "); continue; } int* value = std::get_if<int>(&result.value()); if (value == nullptr) { - absl::StrAppend(&output, " #error Expression for '", name, - "' does not have type int\n"); + absl::StrAppend(&output, "0, "); continue; } - absl::StrAppend(&output, sep, "*value"); - sep = ", "; + absl::StrAppend(&output, *value, ", "); } absl::StrAppend(&output, "};\n"); - absl::StrAppend(&output, - " inst->SetAttributes(absl::Span<int>(attrs, size));\n"); + absl::StrAppend(&output, " inst->SetAttributes(absl::Span<int>(attrs,", + size, "));\n"); } - absl::StrAppend(&output, "}\n"); + absl::StrAppend(&output, "}\n\n"); return output; } @@ -1490,6 +1492,12 @@ attribute_map_.emplace(name, expr); } +void Slot::AddAttributeName(const std::string& name) { + if (!attribute_names_.contains(name)) { + attribute_names_.insert(name); + } +} + } // namespace instruction_set } // namespace machine_description } // namespace sim
diff --git a/mpact/sim/decoder/slot.h b/mpact/sim/decoder/slot.h index 9065874..fbdae67 100644 --- a/mpact/sim/decoder/slot.h +++ b/mpact/sim/decoder/slot.h
@@ -22,6 +22,7 @@ #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" @@ -112,6 +113,9 @@ // 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_; } @@ -159,6 +163,10 @@ return attribute_map_; } + const absl::btree_set<std::string>& attribute_names() const { + return attribute_names_; + } + private: // These functions generate the functions that are called by the decoder to // set the instruction operands. @@ -251,6 +259,7 @@ 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
diff --git a/mpact/sim/generic/instruction.h b/mpact/sim/generic/instruction.h index b8606dc..12b66b6 100644 --- a/mpact/sim/generic/instruction.h +++ b/mpact/sim/generic/instruction.h
@@ -219,7 +219,7 @@ absl::MakeConstSpan(static_cast<int*>(nullptr), 0); // Architecture state object. ArchState* state_; - // Instruction execution context (this is usuall nullptr). + // Instruction execution context (this is usually nullptr). ReferenceCount* context_; // Semantic function that implements the instruction semantics. SemanticFunction semantic_fcn_;