| // 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_PROTO_ENCODING_GROUP_H_ |
| #define MPACT_SIM_DECODER_PROTO_ENCODING_GROUP_H_ |
| |
| #include <cstdint> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/container/btree_map.h" |
| #include "absl/container/flat_hash_set.h" |
| #include "absl/strings/string_view.h" |
| #include "src/google/protobuf/descriptor.h" |
| |
| // This file defines the ProtoEncodingGroup class, which is used in a hierarchy |
| // to divide instruction encodings into groups that can be differentiated based |
| // on a single field value (or has_*() reference). Based on how complex the |
| // instruction encoding is, this can create a hierarchy that are several levels |
| // deep. |
| |
| namespace mpact { |
| namespace sim { |
| namespace decoder { |
| |
| class DecoderErrorListener; |
| |
| namespace proto_fmt { |
| |
| // Forward declarations. |
| class ProtoConstraintValueSet; |
| class ProtoInstructionEncoding; |
| class ProtoInstructionGroup; |
| struct FieldInfo; |
| |
| class ProtoEncodingGroup { |
| public: |
| // Constructor for a top level encoding group with no field differentiator. |
| ProtoEncodingGroup(ProtoInstructionGroup* inst_group, int level, |
| DecoderErrorListener* error_listener); |
| // Constructor for a child encoding group. |
| ProtoEncodingGroup(ProtoEncodingGroup* parent, |
| ProtoInstructionGroup* inst_group, int level, |
| DecoderErrorListener* error_listener); |
| // Deleted constructors. |
| ProtoEncodingGroup() = delete; |
| ProtoEncodingGroup(const ProtoEncodingGroup&) = delete; |
| ProtoEncodingGroup& operator=(const ProtoEncodingGroup&) = delete; |
| // Destructor. |
| ~ProtoEncodingGroup(); |
| |
| // Add encoding to the current group. |
| void AddEncoding(ProtoInstructionEncoding* encoding); |
| // Process the encodings in this group and divide them into subgroups based |
| // on their constraint value for the differentiating field. |
| void AddSubGroups(); |
| // Top level function called for creating C++ code for the decoder. |
| std::string EmitDecoders(absl::string_view fcn_name, |
| absl::string_view opcode_enum, |
| absl::string_view message_type_name); |
| |
| // Getters/Setters. |
| DecoderErrorListener* error_listener() const { return error_listener_; } |
| int64_t value() const { return value_; } |
| void set_value(int64_t value) { value_ = value; } |
| int level() const { return level_; } |
| |
| private: |
| // Check the encodings after the subgroups have been created and make sure |
| // there are no encoding ambiguities, such as multiple opcodes with the same |
| // encoding, etc. |
| void CheckEncodings(); |
| bool DoConstraintsOverlap(const std::vector<ProtoConstraintValueSet*>& lhs, |
| const std::vector<ProtoConstraintValueSet*>& rhs); |
| // Create C++ code for leaf (encoding group) instruction decoder. |
| std::string EmitLeafDecoder(absl::string_view fcn_name, |
| absl::string_view opcode_enum, |
| absl::string_view message_type_name, |
| int indent_width) const; |
| // Create C++ code for intermediary instruction decoder. |
| std::string EmitComplexDecoder(absl::string_view fcn_name, |
| absl::string_view opcode_enum, |
| absl::string_view message_type_name); |
| |
| ProtoInstructionGroup* inst_group_ = nullptr; |
| [[maybe_unused]] ProtoEncodingGroup* parent_ = nullptr; |
| DecoderErrorListener* error_listener_ = nullptr; |
| FieldInfo* differentiator_ = nullptr; |
| int64_t value_; |
| int level_; |
| std::vector<ProtoInstructionEncoding*> encoding_vec_; |
| std::vector<ProtoEncodingGroup*> encoding_group_vec_; |
| absl::btree_map<std::string, FieldInfo*> field_map_; |
| absl::flat_hash_set<const google::protobuf::FieldDescriptor*> |
| other_field_set_; |
| absl::flat_hash_set<const google::protobuf::OneofDescriptor*> |
| other_oneof_set_; |
| }; |
| |
| } // namespace proto_fmt |
| } // namespace decoder |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_SIM_DECODER_PROTO_ENCODING_GROUP_H_ |