The Sparta Modeling Framework
Loading...
Searching...
No Matches
RegisterDefnsJSON.hpp
1#pragma once
2
3#include <rapidjson/document.h>
4#include <rapidjson/filereadstream.h>
5#include <rapidjson/writer.h>
6#include <rapidjson/stringbuffer.h>
7
8namespace sparta
9{
10
12{
13public:
14 RegisterDefnsFromJSON(const std::vector<std::string>& register_defns_json_filenames)
15 {
16 for (const auto& filename : register_defns_json_filenames) {
17 parse_(filename);
18 }
19
20 // Add a definition that indicates the end of the array
21 register_defns_.push_back(RegisterBase::DEFINITION_END);
22 }
23
24 RegisterDefnsFromJSON(const std::string& register_defns_json_filename)
25 {
26 parse_(register_defns_json_filename);
27
28 // Add a definition that indicates the end of the array
29 register_defns_.push_back(RegisterBase::DEFINITION_END);
30 }
31
32 RegisterBase::Definition* getAllDefns() {
33 return register_defns_.data();
34 }
35
36private:
37 void parse_(const std::string& register_defns_json_filename)
38 {
39 // Read the file into a string
40 std::ifstream ifs(register_defns_json_filename);
41 std::stringstream ss;
42 ss << ifs.rdbuf();
43 std::string json_str = ss.str();
44
45 // Parse the JSON string
46 rapidjson::Document document;
47 document.Parse(json_str.c_str());
48
49 for (auto& item : document.GetArray()) {
50 if (item.HasMember("enabled") && !item["enabled"].GetBool()) {
51 continue;
52 }
53
54 const RegisterBase::ident_type id = item["num"].GetInt();
55
56 cached_strings_.emplace_back(item["name"].GetString());
57 const char *name = cached_strings_.back().raw();
58
59 const RegisterBase::group_num_type group_num = item["group_num"].GetInt();
60 auto iter = group_idx_map_.find(group_num);
61 if (iter == group_idx_map_.end()) {
62 group_idx_map_[group_num] = 0;
63 }
64
65 RegisterBase::group_idx_type group_idx = group_idx_map_[group_num]++;
66 cached_strings_.emplace_back(item["group_name"].GetString());
67 const char* group = cached_strings_.back().raw();
68
69 if (std::string(group).empty()) {
71 }
72
73 cached_strings_.emplace_back(item["desc"].GetString());
74 const char* desc = cached_strings_.back().raw();
75
76 const RegisterBase::size_type bytes = item["size"].GetInt();
77
78 std::vector<RegisterBase::Field::Definition> field_defns;
79 if (item.HasMember("fields")) {
80 for (auto it = item["fields"].MemberBegin(); it != item["fields"].MemberEnd(); ++it) {
81 const char* field_name = it->name.GetString();
82 const rapidjson::Value& field_info = it->value;
83 cached_field_defns_.emplace_back(field_name, field_info);
84 field_defns.push_back(cached_field_defns_.back().getDefn());
85 }
86 }
87
88 static const std::vector<RegisterBase::bank_idx_type> bank_membership;
89
90 std::vector<std::string> alias_strings;
91 for (auto& alias : item["aliases"].GetArray()) {
92 alias_strings.push_back(alias.GetString());
93 }
94 cached_aliases_.emplace_back(alias_strings);
95 const char** aliases = cached_aliases_.back().raw();
96
98 constexpr RegisterBase::size_type subset_offset = 0;
99
100 const unsigned char *initial_value = nullptr;
101 if (item.HasMember("initial_value")) {
102 cached_initial_values_.emplace_back(item["initial_value"].GetString());
103 initial_value = cached_initial_values_.back().raw();
104 }
105
106 constexpr RegisterBase::Definition::HintsT hints = 0;
107 constexpr RegisterBase::Definition::RegDomainT regdomain = 0;
108
110 id,
111 name,
112 group_num,
113 group,
114 group_idx,
115 desc,
116 bytes,
117 field_defns,
118 bank_membership,
119 aliases,
120 subset_of,
121 subset_offset,
122 initial_value,
123 hints,
124 regdomain
125 };
126
127 register_defns_.push_back(defn);
128 }
129 }
130
131 // Converts a string to a const char* pointer
132 class StringRef
133 {
134 public:
135 StringRef(const std::string& str) : storage_(str) {}
136 const char* raw() const { return storage_.c_str(); }
137 private:
138 std::string storage_;
139 };
140
141 // Converts a vector of strings to an array of const char* pointers
142 class AliasRef
143 {
144 public:
145 AliasRef(const std::vector<std::string>& aliases)
146 : storage_(aliases)
147 {
148 for (const auto& str : storage_) {
149 pointers_.push_back(str.c_str());
150 }
151 }
152
153 const char** raw() {
154 return pointers_.data();
155 }
156
157 private:
158 std::vector<std::string> storage_;
159 std::vector<const char*> pointers_;
160 };
161
162 // Converts any hex ("0xdeafbeef") to a const unsigned char* pointer
163 class InitialValueRef
164 {
165 public:
166 InitialValueRef(const std::string& hex_str)
167 {
168 // Remove the "0x" prefix if present
169 std::string hex = hex_str;
170 if (hex.substr(0, 2) == "0x") {
171 hex = hex.substr(2);
172 }
173
174 // Ensure the hex string has an even length
175 sparta_assert(hex.length() % 2 == 0, "Hex string must have an even length");
176
177 // Create a vector to hold the bytes
178 hex_bytes_.resize(hex.length() / 2);
179
180 // Convert hex string to bytes
181 for (size_t i = 0; i < hex.length(); i += 2) {
182 const auto byte_string = hex.substr(i, 2);
183 std::istringstream iss(byte_string);
184 int byte;
185 iss >> std::hex >> byte;
186 hex_bytes_[i / 2] = static_cast<char>(byte);
187 }
188 }
189
190 const unsigned char* raw() const {
191 return hex_bytes_.data();
192 }
193
194 private:
195 std::vector<unsigned char> hex_bytes_;
196 };
197
198 // Converts a rapidjson::Value that represents a field to a Field::Definition
199 class FieldDefnConverter
200 {
201 public:
202 FieldDefnConverter(const std::string& field_name, const rapidjson::Value& field_info)
203 : field_name_(field_name)
204 , desc_(field_info["desc"].GetString())
205 , field_defn_(field_name_.c_str(),
206 desc_.c_str(),
207 field_info["low_bit"].GetInt(),
208 field_info["high_bit"].GetInt(),
209 field_info["readonly"].GetBool())
210 {
211 }
212
213 const RegisterBase::Field::Definition& getDefn() const
214 {
215 return field_defn_;
216 }
217
218 private:
219 std::string field_name_;
220 std::string desc_;
222 };
223
224 std::deque<StringRef> cached_strings_;
225 std::deque<AliasRef> cached_aliases_;
226 std::deque<InitialValueRef> cached_initial_values_;
227 std::deque<FieldDefnConverter> cached_field_defns_;
228 std::vector<RegisterBase::Definition> register_defns_;
229
230 // TODO: Find the official way to handle group_idx. For now we will just use
231 // a map of auto-incrementing group_idx values for each group_num
232 std::map<RegisterBase::group_num_type, RegisterBase::group_idx_type> group_idx_map_;
233};
234
235} // namespace sparta
#define sparta_assert(...)
Simple variadic assertion that will throw a sparta_exception if the condition fails.
DataView::ident_type ident_type
Identifier to distinguish from other registers in the same RegisterSet.
Definition Register.hpp:72
static constexpr ident_type INVALID_ID
Represents an invalid Register ID.
Definition Register.hpp:681
TreeNode::group_idx_type group_idx_type
TreeNode group index.
Definition Register.hpp:92
DataView::offset_type size_type
Size of register and bit or byte offset within register data.
Definition Register.hpp:82
uint32_t group_num_type
Numeric group identifier for register lookup.
Definition Register.hpp:87
static const Definition DEFINITION_END
Entry indicating the end of a sparta::Register::Definition array.
Definition Register.hpp:687
static const group_idx_type GROUP_IDX_NONE
GroupIndex indicating that a node has no group index because it belongs to no group.
Definition TreeNode.hpp:303
Macros for handling exponential backoff.
Describes an architected Register.
Definition Register.hpp:548
uint16_t HintsT
Register hint flags. The flags are not part of sparta but should be defined by the model.
Definition Register.hpp:669
uint16_t RegDomainT
Register Domain. The flags are not part of sparta but should be defined by the model.
Definition Register.hpp:676
Field Definition structure.
Definition Register.hpp:168