11#include "llvm/ADT/STLExtras.h"
12#include "llvm/Support/ErrorOr.h"
13#include "llvm/Support/FileSystem.h"
14#include "llvm/Support/MemoryBuffer.h"
15#include "llvm/Support/Path.h"
16#include "llvm/Support/Program.h"
17#include "llvm/Support/raw_ostream.h"
27 if (field.name == fieldName) {
35std::optional<std::string> findRegDBFile(llvm::StringRef fileName) {
36 auto checkDirectory = [&](llvm::StringRef dir) -> std::optional<std::string> {
39 llvm::SmallString<256> candidate(dir);
40 llvm::sys::path::append(candidate, fileName);
41 if (llvm::sys::fs::exists(candidate))
42 return std::string(candidate.str());
46 if (
const char *installDir = std::getenv(
"MLIR_AIE_INSTALL_DIR")) {
47 llvm::SmallString<256> dir(installDir);
48 llvm::sys::path::append(dir,
"lib",
"regdb");
49 if (
auto path = checkDirectory(dir))
53 std::string mainExecutable = llvm::sys::fs::getMainExecutable(
54 nullptr,
reinterpret_cast<void *
>(&findRegDBFile));
55 if (!mainExecutable.empty()) {
56 llvm::SmallString<256> dir(mainExecutable);
57 llvm::sys::path::remove_filename(dir);
58 llvm::sys::path::append(dir,
"..",
"lib",
"regdb");
59 llvm::sys::path::remove_dots(dir,
true);
60 if (
auto path = checkDirectory(dir))
69 auto registerPath = findRegDBFile(
"aie_registers_aie2.json");
70 auto eventPath = findRegDBFile(
"events_database.json");
72 if (!registerPath || !eventPath) {
73 llvm::errs() <<
"Failed to locate AIE register database resources. "
74 <<
"Set MLIR_AIE_INSTALL_DIR to the "
75 <<
"MLIR-AIE installation path.\n";
79 auto db = std::unique_ptr<RegisterDatabase>(
new RegisterDatabase());
80 if (!db->loadFromJSON(*registerPath, *eventPath))
82 db->buildOffsetIndex();
87bool RegisterDatabase::loadFromJSON(StringRef registerPath,
88 StringRef eventPath) {
90 auto registerBuf = MemoryBuffer::getFile(registerPath);
92 llvm::errs() <<
"Failed to load register database: " << registerPath
97 auto registerJSON = json::parse(registerBuf.get()->getBuffer());
99 llvm::errs() <<
"Failed to parse register JSON\n";
104 auto *root = registerJSON->getAsObject();
108 auto *modules = root->getObject(
"modules");
113 for (
const auto &modulePair : *modules) {
114 StringRef moduleName = modulePair.first;
115 auto *moduleObj = modulePair.second.getAsObject();
119 auto *registers = moduleObj->getArray(
"registers");
124 for (
const auto ®Val : *registers) {
125 auto *regObj = regVal.getAsObject();
130 regInfo.
module = moduleName.str();
133 if (
auto name = regObj->getString(
"name"))
134 regInfo.
name = name->str();
135 if (
auto offset = regObj->getString(
"offset")) {
137 StringRef offsetStr = *offset;
139 if (offsetStr.starts_with(
"0x") || offsetStr.starts_with(
"0X"))
140 offsetStr = offsetStr.drop_front(2);
143 if (offsetStr.getAsInteger(16, offsetVal)) {
144 llvm::errs() <<
"Warning: Failed to parse offset '" << *offset
145 <<
"' for register " << regInfo.
name <<
"\n";
147 regInfo.
offset =
static_cast<uint32_t
>(offsetVal);
150 if (
auto width = regObj->getInteger(
"width"))
151 regInfo.
width =
static_cast<uint32_t
>(*width);
152 if (
auto type = regObj->getString(
"type"))
153 regInfo.
type = type->str();
154 if (
auto reset = regObj->getString(
"reset"))
155 regInfo.
reset = reset->str();
156 if (
auto desc = regObj->getString(
"description"))
160 if (
auto *fields = regObj->getArray(
"bit_fields")) {
161 for (
const auto &fieldVal : *fields) {
162 auto *fieldObj = fieldVal.getAsObject();
166 BitFieldInfo fieldInfo;
167 if (
auto name = fieldObj->getString(
"name"))
168 fieldInfo.
name = name->str();
169 if (
auto *bitRange = fieldObj->getArray(
"bit_range")) {
170 if (bitRange->size() == 2) {
171 if (
auto start = (*bitRange)[0].getAsInteger())
172 fieldInfo.
bit_start =
static_cast<uint32_t
>(*start);
173 if (
auto end = (*bitRange)[1].getAsInteger())
174 fieldInfo.
bit_end =
static_cast<uint32_t
>(*end);
177 if (
auto type = fieldObj->getString(
"type"))
178 fieldInfo.
type = type->str();
179 if (
auto reset = fieldObj->getString(
"reset"))
180 fieldInfo.
reset = reset->str();
181 if (
auto desc = fieldObj->getString(
"description"))
190 std::string key = moduleName.lower() +
"::" + regInfo.
name;
191 llvm::transform(key, key.begin(), ::tolower);
192 registers_[key] = regInfo;
197 auto eventBuf = MemoryBuffer::getFile(eventPath);
199 llvm::errs() <<
"Failed to load event database: " << eventPath <<
"\n";
203 auto eventJSON = json::parse(eventBuf.get()->getBuffer());
205 llvm::errs() <<
"Failed to parse event JSON\n";
210 auto *eventRoot = eventJSON->getAsObject();
214 auto *aie2 = eventRoot->getObject(
"aie2");
216 llvm::errs() <<
"Failed to find 'aie2' architecture in event database\n";
220 auto *eventModules = aie2->getObject(
"modules");
225 for (
const auto &modulePair : *eventModules) {
226 StringRef moduleName = modulePair.first;
227 auto *events = modulePair.second.getAsArray();
232 for (
const auto &eventVal : *events) {
233 auto *eventObj = eventVal.getAsObject();
238 eventInfo.
module = moduleName.str();
240 if (
auto name = eventObj->getString(
"name"))
241 eventInfo.
name = name->str();
242 if (
auto number = eventObj->getInteger(
"number"))
243 eventInfo.
number =
static_cast<uint32_t
>(*number);
246 std::string key = moduleName.str() +
"::" + eventInfo.
name;
247 llvm::transform(key, key.begin(), ::tolower);
248 events_[key] = eventInfo;
256 StringRef module)
const {
257 std::string key =
module.str() + "::" + name.str();
258 llvm::transform(key, key.begin(), ::tolower);
259 auto it = registers_.find(key);
260 return it != registers_.end() ? &it->second :
nullptr;
263void RegisterDatabase::buildOffsetIndex() {
264 registersByOffset_.clear();
265 for (
const auto &entry : registers_) {
267 std::string moduleKey = info.
module;
268 llvm::transform(moduleKey, moduleKey.begin(), ::tolower);
269 registersByOffset_[moduleKey][info.
offset] = &info;
275 StringRef module)
const {
276 std::string moduleKey =
module.lower();
277 auto modIt = registersByOffset_.find(moduleKey);
278 if (modIt == registersByOffset_.end())
280 auto offIt = modIt->second.find(offset);
281 if (offIt == modIt->second.end())
283 return offIt->second;
287 StringRef module)
const {
288 std::string key =
module.str() + "::" + name.str();
289 llvm::transform(key, key.begin(), ::tolower);
290 auto it = events_.find(key);
291 if (it != events_.end()) {
292 return it->second.number;
297std::optional<uint32_t>
299 uint32_t value)
const {
305 uint64_t maxValue = width >= 32 ? std::numeric_limits<uint32_t>::max()
306 : ((1ULL << width) - 1ULL);
308 if (value > maxValue)
311 value &=
static_cast<uint32_t
>(maxValue);
314 uint64_t encoded = (
static_cast<uint64_t
>(value) << field.
bit_start);
315 return static_cast<uint32_t
>(encoded);
std::optional< 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.
const RegisterInfo * lookupRegisterByOffset(uint32_t offset, llvm::StringRef module) const
Lookup register by tile-relative offset and module name.
Bit field information for a register.
uint32_t getWidth() const
const BitFieldInfo * getField(llvm::StringRef fieldName) const
std::vector< BitFieldInfo > bit_fields