blob: d86bb7f8c1c86496059a437510d9a8a4f3586fb0 [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_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_