blob: 732bd786d9908cee67b28f2fd0c2e8705e63042e [file]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
// Helper code for the UVM testbench. The corresponding SV declarations are in
// otbn_env_pkg.sv.
#include <cassert>
#include <cstring>
#include <dirent.h>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <sys/types.h>
namespace {
struct DirDeleter {
void operator()(DIR *dir) const {
// Ignore the return value from closedir: the only way it can fail is if
// dir was an invalid descriptor, which it isn't.
(void)closedir(dir);
}
};
typedef std::unique_ptr<DIR, DirDeleter> dir_ptr;
// Return true if this name looks like it might be an ELF file (must be
// <FOO>.elf for some non-empty <FOO>).
static bool IsElfFileName(const char *name) {
size_t len = strlen(name);
return (len >= 5) && (memcmp(name + len - 4, ".elf", 4) == 0);
}
class OtbnTestHelper {
public:
std::string dir_path_;
std::string file_path_;
OtbnTestHelper(const std::string dir_path) : dir_path_(dir_path) {}
int CountFilesInDir() const {
dir_ptr dir(opendir(dir_path_.c_str()));
if (!dir)
return 0;
int count = 0;
for (;;) {
struct dirent *entry = readdir(dir.get());
if (!entry)
break;
if (entry->d_type != DT_REG)
continue;
// Only look at files ending in .elf
if (!IsElfFileName(entry->d_name)) {
continue;
}
++count;
}
return count;
}
void SetFile(unsigned idx) {
file_path_ = "";
dir_ptr dir(opendir(dir_path_.c_str()));
if (!dir) {
return;
}
unsigned count = 0;
for (;;) {
struct dirent *entry = readdir(dir.get());
if (!entry)
break;
if (entry->d_type != DT_REG)
continue;
if (!IsElfFileName(entry->d_name))
continue;
if (count == idx) {
std::ostringstream oss;
oss << dir_path_ << "/" << entry->d_name;
file_path_ = oss.str();
return;
}
++count;
}
// We ran out of entries before we got to index.
}
};
} // namespace
// Make an OTBN test helper
extern "C" OtbnTestHelper *OtbnTestHelperMake(const char *path) {
assert(path != nullptr);
return new OtbnTestHelper(path);
}
// Free an OTBN test helper
extern "C" void OtbnTestHelperFree(OtbnTestHelper *helper) {
assert(helper != nullptr);
delete helper;
}
// Count the number of regular files in the directory at path. If path does not
// name a directory (or names a directory that cannot be opened for some
// reason), return zero.
extern "C" int OtbnTestHelperCountFilesInDir(OtbnTestHelper *helper) {
assert(helper != nullptr);
return helper->CountFilesInDir();
}
// Get a file in the given directory. The file is that at position index when
// stepping through the directory with readdir(). On success, returns the path.
// On failure, returns an empty string.
extern "C" const char *OtbnTestHelperGetFilePath(OtbnTestHelper *helper,
int index) {
assert(helper != nullptr);
assert(index >= 0);
helper->SetFile(index);
return helper->file_path_.c_str();
}