| #ifndef MPACT_SIM_DECODER_FORMAT_H_ |
| #define MPACT_SIM_DECODER_FORMAT_H_ |
| |
| // 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. |
| |
| #include <map> |
| #include <string> |
| #include <vector> |
| |
| #include "absl/container/btree_map.h" |
| #include "absl/status/status.h" |
| #include "absl/status/statusor.h" |
| #include "antlr4-runtime/antlr4-runtime.h" |
| |
| // This file declares the classes necessary to manage instruction formats, |
| // defined as a sequence of fields (or sub-formats) as well as a set of |
| // overlays. The format provides a way of defining an interface for accessing |
| // the different parts of an instruction encoding. |
| |
| namespace mpact { |
| namespace sim { |
| namespace decoder { |
| namespace bin_format { |
| |
| class BinEncodingInfo; |
| class Overlay; |
| class Format; |
| |
| // Helper struct to store the information about an individual field. |
| struct Field { |
| std::string name; |
| bool is_signed; |
| int high; |
| int low; |
| int width; |
| Format *format = nullptr; |
| Field(std::string name_, bool is_signed_, int width_, Format *format_) |
| : name(name_), |
| is_signed(is_signed_), |
| high(-1), |
| low(-1), |
| width(width_), |
| format(format_) {} |
| }; |
| |
| class Format; |
| |
| // Captures a reference to a format by name and how many instances. |
| struct FormatReference { |
| std::string name; |
| int size; |
| explicit FormatReference(std::string name_) : FormatReference(name_, 1) {} |
| FormatReference(std::string name_, int size_) : name(name_), size(size_) {} |
| }; |
| |
| // Wrapper class to store information about each component of the format. |
| |
| class FieldOrFormat { |
| public: |
| explicit FieldOrFormat(Field *field) : is_field_(true), field_(field) {} |
| FieldOrFormat(std::string fmt_name, int size, antlr4::Token *ctx) |
| : is_field_(false), format_name_(fmt_name), size_(size), ctx_(ctx) {} |
| |
| bool is_field() const { return is_field_; } |
| Field *field() const { return field_; } |
| int high() const { return high_; } |
| void set_high(int value) { high_ = value; } |
| const std::string &format_name() const { return format_name_; } |
| antlr4::Token *ctx() const { return ctx_; } |
| Format *format() const { return format_; } |
| int size() const { return size_; } |
| void set_format(Format *fmt) { format_ = fmt; } |
| |
| bool operator==(const FieldOrFormat &rhs) const; |
| bool operator!=(const FieldOrFormat &rhs) const; |
| |
| private: |
| bool is_field_; |
| Field *field_ = nullptr; |
| std::string format_name_; |
| int high_ = 0; |
| int size_ = 0; |
| antlr4::Token *ctx_ = nullptr; |
| Format *format_ = nullptr; |
| }; |
| |
| class Format { |
| public: |
| Format() = delete; |
| Format(std::string name, int width, BinEncodingInfo *encoding_info); |
| Format(std::string name, int width, std::string base_format_name, |
| BinEncodingInfo *encoding_info); |
| ~Format(); |
| |
| // Adds a field (signed or unsigned) of the given width to the format. |
| absl::Status AddField(std::string name, bool is_signed, int width); |
| // Adds a format reference to the current format. It will be resolved to |
| // another format later, or generate an error at that time. |
| void AddFormatReferenceField(std::string name, int size, antlr4::Token *ctx); |
| // Adds an overlay to the format. An overlay is an alias to a set of bits |
| // in the instruction format. |
| absl::StatusOr<Overlay *> AddFieldOverlay(std::string name, bool is_signed, |
| int width); |
| |
| // Returns the named field if it exists in the format. Otherwise it returns |
| // nullptr. |
| Field *GetField(absl::string_view field_name) const; |
| // Returns the named overlay if it exists in the format. Otherwise it returns |
| // nullptr. |
| Overlay *GetOverlay(absl::string_view overlay_name) const; |
| |
| // Performs a consistency check on the format. |
| absl::Status ComputeAndCheckFormatWidth(); |
| // Propagate extractors to the top level in the format inheritance |
| // hierarchy. |
| void PropagateExtractorsUp(); |
| void PropagateExtractorsDown(); |
| // Generates definitions the field and overlay extractors in the format. |
| std::string GenerateExtractors(); |
| |
| // True if the current format is a descendent of format. |
| bool IsDerivedFrom(const Format *format); |
| |
| // Accessors. |
| const std::string &name() const { return name_; } |
| // The unsigned integer type name larger or equal to the format width. |
| // E.g. uint32_t etc. |
| const std::string &uint_type_name() const { return uint_type_name_; } |
| int declared_width() const { return declared_width_; } |
| int computed_width() const { return computed_width_; } |
| Format *base_format() const { return base_format_; } |
| // Return pointer to the parent encoding info class. |
| BinEncodingInfo *encoding_info() const { return encoding_info_; } |
| |
| private: |
| bool HasExtract(const std::string &name) const; |
| bool HasOverlayExtract(const std::string &name) const; |
| |
| std::string GenerateFieldExtractor(Field *field); |
| std::string GenerateFormatExtractor(Format *format, int high, int size); |
| std::string GenerateOverlayExtractor(Overlay *overlay); |
| // Return string representation of the int type that contains bitwidth bits. |
| std::string GetIntType(int bitwidth); |
| int GetIntTypeBitWidth(int bitwidth); |
| |
| std::string name_; |
| std::string base_format_name_; |
| std::string uint_type_name_; |
| std::string int_type_name_; |
| int declared_width_; |
| int computed_width_ = 0; |
| Format *base_format_ = nullptr; |
| std::vector<Format *> derived_formats_; |
| BinEncodingInfo *encoding_info_; |
| |
| absl::btree_map<std::string, Overlay *> overlay_map_; |
| absl::btree_map<std::string, Field *> field_map_; |
| std::vector<FieldOrFormat *> field_vec_; |
| // Using std::map because of sorted traversal and better iterator stability |
| // when elements are erased. |
| std::map<std::string, FieldOrFormat *> extractors_; |
| std::map<std::string, Overlay *> overlay_extractors_; |
| }; |
| |
| } // namespace bin_format |
| } // namespace decoder |
| } // namespace sim |
| } // namespace mpact |
| |
| #endif // MPACT_SIM_DECODER_FORMAT_H_ |