Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 49 additions & 0 deletions src/Compiler/Compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ using namespace FOEDAG;
using Time = std::chrono::high_resolution_clock;
using ms = std::chrono::milliseconds;

#define OVERRIDE_WITH_ENV_VAR 1

auto CreateDummyLog =
[](ProjectManager* projManager,
const std::string& outfileName) -> std::filesystem::path {
Expand Down Expand Up @@ -2748,12 +2750,59 @@ QProcess* Compiler::ExecuteCommand(const std::string& command) const {

std::string Compiler::ReplaceAll(std::string_view str, std::string_view from,
std::string_view to) {

#if OVERRIDE_WITH_ENV_VAR
// check if the string replacement 'from' is an env variable style definition: '${xxx}'
// if so, see if an env variable of the same name is already defined
// if so, use the value of the env variable if not empty

std::string env_var_name;
std::string env_var_value;
static const QRegularExpression env_var_pattern_re(
R"(^\$\{([A-Za-z_][A-Za-z0-9_]*)\}$)"
);
QRegularExpressionMatch env_var_pattern_match = env_var_pattern_re.match(QString::fromStdString(std::string(from)));
if(env_var_pattern_match.hasMatch()){
// 'from' has matched expected pattern of ENV variable ${}
env_var_name = QString(env_var_pattern_match.captured(1)).toStdString();
}
// if 'from' has matched ENV variable name pattern ${}
if(!env_var_name.empty()) {
const char* const env_var_value_str = std::getenv(env_var_name.c_str());
// if the ENV variable is defined
if (env_var_value_str != nullptr) {
env_var_value = std::string(env_var_value_str);
// if the value of the ENV variable is not an empty string
if(!env_var_value.empty()) {
std::cout << std::string("<info> ENV override: ") + std::string(from) + std::string(" with value from ENV!") << std::endl;
}
}
}

size_t start_pos = 0;
std::string result(str);
while ((start_pos = result.find(from, start_pos)) != std::string::npos) {
if(!env_var_value.empty()) {
result.replace(start_pos, from.length(), env_var_value);
start_pos += env_var_value.length(); // Handles case where 'env_var_value' is a substr of 'from'
}
else {
result.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substr of 'from'
}
}

#else //#if OVERRIDE_WITH_ENV_VAR

size_t start_pos = 0;
std::string result(str);
while ((start_pos = result.find(from, start_pos)) != std::string::npos) {
result.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substr of 'from'
}

#endif //#if OVERRIDE_WITH_ENV_VAR

return result;
}

Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/Compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -321,10 +321,12 @@ class Compiler {
// this will apply to all file types as of now.
bool m_copyFilesWhileAdding = false;
bool m_autoLayoutGenerationMode = false;
bool m_customLayoutGenerationMode = false;
std::string m_autoLayoutGeneratedLayoutName{};
std::filesystem::path m_autoLayoutGeneratedVPRXMLPath{};
std::filesystem::path m_autoLayoutGeneratedRRGraphBinPath{};
std::filesystem::path m_autoLayoutGeneratedRouterLookaheadBinPath{};
std::filesystem::path m_autoLayoutGeneratedSBMapsYMLPath{};

// Tasks generic options
IPGenerateOpt m_ipGenerateOpt = IPGenerateOpt::None;
Expand Down
578 changes: 455 additions & 123 deletions src/Compiler/CompilerOpenFPGA_ql.cpp

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion src/Compiler/CompilerOpenFPGA_ql.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class CompilerOpenFPGA_ql : public Compiler {
long double PowerEstimator_Leakage();
#endif // LEGACY_POWER_CALCULATOR

virtual std::string BaseVprCommandLEGACY(QLDeviceTarget device_target = QLDeviceTarget());
virtual std::tuple<std::string, std::string> BaseVprCommandLEGACY(QLDeviceTarget device_target = QLDeviceTarget());
CommandWrapperPtr BaseVprCommand(QLDeviceTarget device_target = QLDeviceTarget(), const VprStageCfg& cfg = VprStageCfg());

std::string staProfile(const QLDeviceTarget& device) const;
Expand Down Expand Up @@ -238,6 +238,8 @@ class CompilerOpenFPGA_ql : public Compiler {
std::filesystem::path m_OpenFpgaFabricKeyFile = "";
std::filesystem::path m_OpenFpgaPinMapXml = "";
std::filesystem::path m_OpenFpgaBitstreamRemappingFile = "";
std::filesystem::path m_SBMapsFile = "";
std::filesystem::path m_SBTemplatesDir = "";
std::string m_deviceSize;
std::string m_customYosysScript;
std::string m_openFPGAScript;
Expand Down
174 changes: 165 additions & 9 deletions src/Compiler/QLDeviceManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1931,6 +1931,37 @@ int QLDeviceManager::encryptDevice(std::string family, std::string foundry, std:
std::regex::icase))) {
continue;
}
// skip any 'design_variables.yml'
if (std::regex_match(dir_entry.path().filename().string(),
std::regex(".*design_variables\\.yml",
std::regex::icase))) {
continue;
}
// skip any 'vpr-template.xml'
if (std::regex_match(dir_entry.path().filename().string(),
std::regex(".*vpr-template\\.xml",
std::regex::icase))) {
continue;
}
// skip any 'openfpga-template.xml'
if (std::regex_match(dir_entry.path().filename().string(),
std::regex(".*openfpga-template\\.xml",
std::regex::icase))) {
continue;
}

// include all files in 'CSV/' files for copy, required for RRG generation
if (std::regex_match(dir_entry.path().string(),
std::regex(R"(.+[\/\\]CSV[\/\\].*)",
std::regex::icase))) {
source_device_data_file_list_to_copy.push_back(dir_entry.path().string());
}
// include SB_MAPS.yml file for copy, required for RRG generation
if (std::regex_match(dir_entry.path().filename().string(),
std::regex(".*SB_MAPS\\.yml",
std::regex::icase))) {
source_device_data_file_list_to_copy.push_back(dir_entry.path().string());
}

// include all files in 'examples/' for copy
if (std::regex_match(dir_entry.path().string(),
Expand Down Expand Up @@ -2699,10 +2730,11 @@ std::filesystem::path QLDeviceManager::deviceVPRArchitectureFile(QLDeviceTarget
std::filesystem::path empty_path;
std::filesystem::path vpr_architecture_file_path;

// if we are in auto layout generation mode, then return the generated vpr xml filepath here
// as we will not be using the (auto) device's own vpr xml.
// if we are in auto/custom layout generation mode, then return the generated vpr xml filepath here
// as we will not be using the (auto/cuustom) device's own vpr xml.

if(compiler->m_autoLayoutGenerationMode){
if(compiler->m_autoLayoutGenerationMode ||
compiler->m_customLayoutGenerationMode){
if(!FileUtils::FileExists(compiler->m_autoLayoutGeneratedVPRXMLPath)) {

compiler->ErrorMessage("Cannot find generated vpr architecture file: " + compiler->m_autoLayoutGeneratedVPRXMLPath.string());
Expand Down Expand Up @@ -3547,17 +3579,140 @@ std::filesystem::path QLDeviceManager::deviceOpenFPGAIOMapFile(QLDeviceTarget de
}


std::filesystem::path QLDeviceManager::deviceSBMAPSFile(QLDeviceTarget device_target) {

CompilerOpenFPGA_ql* compiler = static_cast<CompilerOpenFPGA_ql*>(GlobalSession->GetCompiler());

std::filesystem::path empty_path;
std::filesystem::path sb_maps_yml_file_path;

// if we are in auto/custom layout generation mode, then return the generated SB_MAPS.yml filepath here
// as we will not be using the (auto/custom) device's own SB_MAPS.yml, even if it exists.

if(compiler->m_autoLayoutGenerationMode ||
compiler->m_customLayoutGenerationMode){
if(!FileUtils::FileExists(compiler->m_autoLayoutGeneratedSBMapsYMLPath)) {

compiler->ErrorMessage("Cannot find generated SB_MAPS.yml file: " + compiler->m_autoLayoutGeneratedSBMapsYMLPath.string());
return empty_path;
}
return compiler->m_autoLayoutGeneratedSBMapsYMLPath;
}

if( !isDeviceTargetValid(device_target) ) {
device_target = this->device_target;
}

// find SB_MAPS.yml as "<device-type-dir>/filename-from-json-value" (use config.json name)

// check for config.json (it should exist at v2.9.0+)
std::filesystem::path device_target_config_json_filepath =
deviceConfigJSONPath(device_target);
if(device_target_config_json_filepath.empty()) {

compiler->ErrorMessage("no compatible 'config.json' found in device data, cannot use this device!");
return empty_path;
}


// read config JSON and get the value
std::ifstream device_target_config_json_ifstream(device_target_config_json_filepath.string());
json device_target_config_json = json::parse(device_target_config_json_ifstream);
// get json value
std::string json_value;
if( device_target_config_json.contains("SB_MAPS") ) {

json_value = device_target_config_json["SB_MAPS"].get<std::string>();
}


// check for filename as in config.json from the device
sb_maps_yml_file_path =
deviceTypeDirPath(device_target) / json_value;
if(!FileUtils::FileIsRegular(sb_maps_yml_file_path)) {
sb_maps_yml_file_path.clear();
}

if(sb_maps_yml_file_path.empty()) {
compiler->Message("Cannot find device SB_MAPS file: " + sb_maps_yml_file_path.string());
}
else {
compiler->Message("Using device SB_MAPS file: " + sb_maps_yml_file_path.string());
}

return sb_maps_yml_file_path;
}


std::filesystem::path QLDeviceManager::deviceSBTemplatesDir(QLDeviceTarget device_target) {

CompilerOpenFPGA_ql* compiler = static_cast<CompilerOpenFPGA_ql*>(GlobalSession->GetCompiler());

std::filesystem::path empty_path;
std::filesystem::path sb_templates_dir_path;

if(compiler->m_autoLayoutGenerationMode ||
compiler->m_customLayoutGenerationMode){
// no change in CSV, we can use the existing device's CSV unless something changes in the future.
}

if( !isDeviceTargetValid(device_target) ) {
device_target = this->device_target;
}

// find SB_TEMPLATES_DIR as "<devicevariant-dir>/filename-from-json-value" (use config.json name)

// check for config.json (it should exist at v2.9.0+)
std::filesystem::path device_target_config_json_filepath =
deviceConfigJSONPath(device_target);
if(device_target_config_json_filepath.empty()) {

compiler->ErrorMessage("no compatible 'config.json' found in device data, cannot use this device!");
return empty_path;
}


// read config JSON and get the value
std::ifstream device_target_config_json_ifstream(device_target_config_json_filepath.string());
json device_target_config_json = json::parse(device_target_config_json_ifstream);
// get json value
std::string json_value;
if( device_target_config_json.contains("CORNER_SB_TEMPLATE_DIR") ) {

json_value = device_target_config_json["CORNER_SB_TEMPLATE_DIR"].get<std::string>();
}


// check for filename as in config.json from the device
sb_templates_dir_path =
deviceVariantDirPath(device_target) / json_value;
if(!FileUtils::FileIsDirectory(sb_templates_dir_path)) {
sb_templates_dir_path.clear();
}

if(sb_templates_dir_path.empty()) {
compiler->Message("Cannot find device SB_TEMPLATES dir: " + sb_templates_dir_path.string());
}
else {
compiler->Message("Using device SB_TEMPLATES dir: " + sb_templates_dir_path.string());
}

return sb_templates_dir_path;
}


std::filesystem::path QLDeviceManager::deviceVPRRRGraphFile(QLDeviceTarget device_target) {

CompilerOpenFPGA_ql* compiler = static_cast<CompilerOpenFPGA_ql*>(GlobalSession->GetCompiler());

std::filesystem::path empty_path;
std::filesystem::path vpr_rr_graph_file_path;

// if we are in auto layout generation mode, then return the generated rr_graph.bin filepath here
// as we will not be using the (auto) device's own rr_graph.bin, even if it exists.
// if we are in auto/custom layout generation mode, then return the generated rr_graph.bin filepath here
// as we will not be using the (auto/custom) device's own rr_graph.bin, even if it exists.

if(compiler->m_autoLayoutGenerationMode){
if(compiler->m_autoLayoutGenerationMode ||
compiler->m_customLayoutGenerationMode){
if(!FileUtils::FileExists(compiler->m_autoLayoutGeneratedRRGraphBinPath)) {

compiler->ErrorMessage("Cannot find generated rr_graph file: " + compiler->m_autoLayoutGeneratedRRGraphBinPath.string());
Expand Down Expand Up @@ -3670,10 +3825,11 @@ std::filesystem::path QLDeviceManager::deviceVPRRouterLookaheadFile(QLDeviceTarg
std::filesystem::path vpr_router_lookahead_file_path;


// if we are in auto layout generation mode, then return the generated router_lookahead.bin filepath here
// as we will not be using the (auto) device's own router_lookahead.bin, even if it exists.
// if we are in auto/custom layout generation mode, then return the generated router_lookahead.bin filepath here
// as we will not be using the (auto/custom) device's own router_lookahead.bin, even if it exists.

if(compiler->m_autoLayoutGenerationMode){
if(compiler->m_autoLayoutGenerationMode ||
compiler->m_customLayoutGenerationMode){
if(!FileUtils::FileExists(compiler->m_autoLayoutGeneratedRouterLookaheadBinPath)) {

compiler->ErrorMessage("Cannot find generated rr_graph file: " + compiler->m_autoLayoutGeneratedRouterLookaheadBinPath.string());
Expand Down
2 changes: 2 additions & 0 deletions src/Compiler/QLDeviceManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ class QLDeviceManager : public QObject {
std::filesystem::path deviceOpenFPGAPinTableFile(QLDeviceTarget device_target = QLDeviceTarget());
std::filesystem::path deviceOpenFPGAIOMapFile(QLDeviceTarget device_target = QLDeviceTarget());

std::filesystem::path deviceSBMAPSFile(QLDeviceTarget device_target = QLDeviceTarget());
std::filesystem::path deviceSBTemplatesDir(QLDeviceTarget device_target = QLDeviceTarget());
std::filesystem::path deviceVPRRRGraphFile(QLDeviceTarget device_target = QLDeviceTarget());
std::filesystem::path deviceVPRRouterLookaheadFile(QLDeviceTarget device_target = QLDeviceTarget());

Expand Down
27 changes: 24 additions & 3 deletions src/Compiler/QLMetricsManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,30 @@ QLMetricsManager::QLMetricsManager(QObject *parent)

bool QLMetricsManager::parseJSON() {

std::string metrics_json_filename = "aurora_metrics.json";
std::filesystem::path scripts_path = GlobalSession->Context()->DataPath() / ".." / "scripts";
std::filesystem::path metrics_json_filepath = scripts_path / metrics_json_filename;
std::filesystem::path metrics_json_filepath;

// allow user to override the aurora_metrics.json path using an env variable.
// read env var
const char* const path_aurora_metrics_env_str = std::getenv("AURORA2_METRICS_JSON_PATH");

if (path_aurora_metrics_env_str != nullptr) {

// convert to std::filesystem::path and check if the path exists
metrics_json_filepath = std::string(path_aurora_metrics_env_str);

if(!FileUtils::FileExists(metrics_json_filepath)) {
// clear the variable to indicate that the env variable is either empty or incorrect.
metrics_json_filepath.clear();
}
}

// if we did not get the path from the env var
if(metrics_json_filepath.empty()) {
// use the default path from the scripts directory of the Aurora install
std::string metrics_json_filename = "aurora_metrics.json";
std::filesystem::path scripts_path = GlobalSession->Context()->DataPath() / ".." / "scripts";
metrics_json_filepath = scripts_path / metrics_json_filename;
}

if(FileUtils::FileExists(metrics_json_filepath)) {
try {
Expand Down
Loading
Loading