14#include "llvm/Support/ErrorOr.h"
15#include "llvm/Support/FileSystem.h"
16#include "llvm/Support/MemoryBuffer.h"
17#include "llvm/Support/Path.h"
18#include "llvm/Support/Program.h"
19#include "llvm/Support/raw_ostream.h"
29 if (field.name == fieldName) {
37std::optional<std::string> findRegDBFile(llvm::StringRef fileName) {
38 auto checkDirectory = [&](llvm::StringRef dir) -> std::optional<std::string> {
41 llvm::SmallString<256> candidate(dir);
42 llvm::sys::path::append(candidate, fileName);
43 if (llvm::sys::fs::exists(candidate))
44 return std::string(candidate.str());
48 if (
const char *installDir = std::getenv(
"MLIR_AIE_INSTALL_DIR")) {
49 llvm::SmallString<256> dir(installDir);
50 llvm::sys::path::append(dir,
"lib",
"regdb");
51 if (
auto path = checkDirectory(dir))
55 std::string mainExecutable = llvm::sys::fs::getMainExecutable(
56 nullptr,
reinterpret_cast<void *
>(&findRegDBFile));
57 if (!mainExecutable.empty()) {
58 llvm::SmallString<256> dir(mainExecutable);
59 llvm::sys::path::remove_filename(dir);
60 llvm::sys::path::append(dir,
"..",
"lib",
"regdb");
61 llvm::sys::path::remove_dots(dir,
true);
62 if (
auto path = checkDirectory(dir))
71 auto registerPath = findRegDBFile(
"aie_registers_aie2.json");
72 auto eventPath = findRegDBFile(
"events_database.json");
74 if (!registerPath || !eventPath) {
75 llvm::errs() <<
"Failed to locate AIE register database resources. "
76 <<
"Set MLIR_AIE_INSTALL_DIR to the "
77 <<
"MLIR-AIE installation path.\n";
82 if (!db->loadFromJSON(*registerPath, *eventPath))
88bool RegisterDatabase::loadFromJSON(StringRef registerPath,
89 StringRef eventPath) {
91 auto registerBuf = MemoryBuffer::getFile(registerPath);
93 llvm::errs() <<
"Failed to load register database: " << registerPath
98 auto registerJSON = json::parse(registerBuf.get()->getBuffer());
100 llvm::errs() <<
"Failed to parse register JSON\n";
105 auto *root = registerJSON->getAsObject();
109 auto *modules = root->getObject(
"modules");
114 for (
const auto &modulePair : *modules) {
115 StringRef moduleName = modulePair.first;
116 auto *moduleObj = modulePair.second.getAsObject();
120 auto *registers = moduleObj->getArray(
"registers");
125 for (
const auto ®Val : *registers) {
126 auto *regObj = regVal.getAsObject();
131 regInfo.module = moduleName.str();
134 if (
auto name = regObj->getString(
"name"))
135 regInfo.
name = name->str();
136 if (
auto offset = regObj->getString(
"offset")) {
138 StringRef offsetStr = *offset;
140 if (offsetStr.starts_with(
"0x") || offsetStr.starts_with(
"0X"))
141 offsetStr = offsetStr.drop_front(2);
144 if (offsetStr.getAsInteger(16, offsetVal)) {
145 llvm::errs() <<
"Warning: Failed to parse offset '" << *offset
146 <<
"' for register " << regInfo.
name <<
"\n";
148 regInfo.
offset =
static_cast<uint32_t
>(offsetVal);
151 if (
auto width = regObj->getInteger(
"width"))
152 regInfo.
width =
static_cast<uint32_t
>(*width);
153 if (
auto type = regObj->getString(
"type"))
154 regInfo.
type = type->str();
155 if (
auto reset = regObj->getString(
"reset"))
156 regInfo.
reset = reset->str();
157 if (
auto desc = regObj->getString(
"description"))
161 if (
auto *fields = regObj->getArray(
"bit_fields")) {
162 for (
const auto &fieldVal : *fields) {
163 auto *fieldObj = fieldVal.getAsObject();
168 if (
auto name = fieldObj->getString(
"name"))
169 fieldInfo.
name = name->str();
170 if (
auto *bitRange = fieldObj->getArray(
"bit_range")) {
171 if (bitRange->size() == 2) {
172 if (
auto start = (*bitRange)[0].getAsInteger())
173 fieldInfo.
bit_start =
static_cast<uint32_t
>(*start);
174 if (
auto end = (*bitRange)[1].getAsInteger())
175 fieldInfo.
bit_end =
static_cast<uint32_t
>(*end);
178 if (
auto type = fieldObj->getString(
"type"))
179 fieldInfo.
type = type->str();
180 if (
auto reset = fieldObj->getString(
"reset"))
181 fieldInfo.
reset = reset->str();
182 if (
auto desc = fieldObj->getString(
"description"))
191 std::string key = moduleName.lower() +
"::" + regInfo.
name;
192 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
193 registers_[key] = regInfo;
198 auto eventBuf = MemoryBuffer::getFile(eventPath);
200 llvm::errs() <<
"Failed to load event database: " << eventPath <<
"\n";
204 auto eventJSON = json::parse(eventBuf.get()->getBuffer());
206 llvm::errs() <<
"Failed to parse event JSON\n";
211 auto *eventRoot = eventJSON->getAsObject();
215 auto *aie2 = eventRoot->getObject(
"aie2");
217 llvm::errs() <<
"Failed to find 'aie2' architecture in event database\n";
221 auto *eventModules = aie2->getObject(
"modules");
226 for (
const auto &modulePair : *eventModules) {
227 StringRef moduleName = modulePair.first;
228 auto *events = modulePair.second.getAsArray();
233 for (
const auto &eventVal : *events) {
234 auto *eventObj = eventVal.getAsObject();
239 eventInfo.module = moduleName.str();
241 if (
auto name = eventObj->getString(
"name"))
242 eventInfo.
name = name->str();
243 if (
auto number = eventObj->getInteger(
"number"))
244 eventInfo.
number =
static_cast<uint32_t
>(*number);
247 std::string key = moduleName.str() +
"::" + eventInfo.
name;
248 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
249 events_[key] = eventInfo;
257 StringRef module)
const {
258 std::string key =
module.str() + "::" + name.str();
259 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
260 auto it = registers_.find(key);
261 return it != registers_.end() ? &it->second :
nullptr;
265 StringRef module)
const {
266 std::string key =
module.str() + "::" + name.str();
267 std::transform(key.begin(), key.end(), key.begin(), ::tolower);
268 auto it = events_.find(key);
269 if (it != events_.end()) {
270 return it->second.number;
276 uint32_t value)
const {
282 uint64_t maxValue = width >= 32 ? std::numeric_limits<uint32_t>::max()
283 : ((1ULL << width) - 1ULL);
285 if (value > maxValue) {
286 llvm::errs() <<
"Warning: value " << value <<
" exceeds field width "
288 value =
static_cast<uint32_t
>(value & maxValue);
289 }
else if (width < 32) {
290 value &=
static_cast<uint32_t
>(maxValue);
294 uint64_t encoded = (
static_cast<uint64_t
>(value) << field.
bit_start);
295 return static_cast<uint32_t
>(encoded);
Register and event database for a specific architecture.
uint32_t encodeFieldValue(const BitFieldInfo &field, uint32_t value) const
Encode a value for a specific bitfield.
static std::unique_ptr< RegisterDatabase > loadAIE2()
Load database for AIE2 architecture.
const RegisterInfo * lookupRegister(llvm::StringRef name, llvm::StringRef module) const
Lookup register by name and module.
std::optional< uint32_t > lookupEvent(llvm::StringRef name, llvm::StringRef module) const
Lookup event by name and module.
Include the generated interface declarations.
Bit field information for a register.
uint32_t getWidth() const
const BitFieldInfo * getField(llvm::StringRef fieldName) const
std::vector< BitFieldInfo > bit_fields
std::string uint32_t width