From 7f98328914bdf6b91c6dc4fa2bc59729e6384536 Mon Sep 17 00:00:00 2001 From: coolbreeze413 Date: Fri, 22 Nov 2024 14:44:33 +0530 Subject: [PATCH 1/2] move PCF file logic into an API with QLSettingsManager --- src/Compiler/CompilerOpenFPGA_ql.cpp | 11 +++- src/Compiler/QLSettingsManager.cpp | 99 ++++++++++++++++++++++++++++ src/Compiler/QLSettingsManager.h | 3 + 3 files changed, 112 insertions(+), 1 deletion(-) diff --git a/src/Compiler/CompilerOpenFPGA_ql.cpp b/src/Compiler/CompilerOpenFPGA_ql.cpp index d15a30300..70cda916d 100644 --- a/src/Compiler/CompilerOpenFPGA_ql.cpp +++ b/src/Compiler/CompilerOpenFPGA_ql.cpp @@ -4718,7 +4718,15 @@ bool CompilerOpenFPGA_ql::GeneratePinConstraints(std::string& filepath_fpga_fix_ ///////////////////////////////////////////////////////////////// PLACE -- ///////////////////////////////////////////////////////////////// PCF ++ - std::filesystem::path filepath_pcf; + std::filesystem::path filepath_pcf = QLSettingsManager::getInstance()->parsePCFFilePath(); + + if(filepath_pcf.empty()) { + // no pcf file found, so we continue without PinConstraints defined. + // This is not an error, so we return true. + return true; + } + +#if ORIGINAL_PCF_LOGIC if( !QLSettingsManager::getStringValue("openfpga", "general", "pcf").empty() ) { filepath_pcf = QLSettingsManager::getStringValue("openfpga", "general", "pcf"); } @@ -4755,6 +4763,7 @@ bool CompilerOpenFPGA_ql::GeneratePinConstraints(std::string& filepath_fpga_fix_ // if pcf is located in current project folder, we may convert path to relative, since .openfpga also be called from that directory filepath_pcf = removePathPrefixFn(filepath_pcf, std::filesystem::path(ProjManager()->projectPath())); +#endif // #if ORIGINAL_PCF_LOGIC ///////////////////////////////////////////////////////////////// PCF -- ///////////////////////////////////////////////////////////////// NETLIST ++ diff --git a/src/Compiler/QLSettingsManager.cpp b/src/Compiler/QLSettingsManager.cpp index 6e9ef3e8a..5e328682b 100644 --- a/src/Compiler/QLSettingsManager.cpp +++ b/src/Compiler/QLSettingsManager.cpp @@ -204,6 +204,105 @@ void QLSettingsManager::parseSDCFilePath() { } +std::filesystem::path QLSettingsManager::getPCFFilePath() { + + std::filesystem::path pcf_file_path; + + if( (instance->settings_json).empty() ) { + // settings json is not parsed yet, nothing to do. + return pcf_file_path; + } + + // ---------------------------------------------------------------- sdc_file ++ + // sdc_file can come from Settings JSON -or- automatically picked up if named: .sdc + // sdc_file path can be absolute or relative + // >> note: if sdc file specified in the Settings, and not found, then we flag this as an error! + // if relative path, heuristic to find the sdc_file: + // 1. check project_path, to see if sdc_file exists, use that + // 2. check tcl_script_dir_path (if driven by TCL script), to see if sdc_file exists, use that + // 3. check current dir, to see if sdc_file exists exists, use that + + + // 1. check if an sdc file is specified in the json: (can be relative/absolute) + if( !getStringValue("openfpga", "general", "pcf").empty() ) { + + pcf_file_path = + std::filesystem::path(getStringValue("openfpga", "general", "pcf")); + } + // 2. else, check for a PCF file with the naming convention (.pcf) + // note that this will always be a 'relative_path' case + else { + + pcf_file_path = + std::filesystem::path(GlobalSession->GetCompiler()->ProjManager()->projectName() + std::string(".pcf")); + } + + // check if the path specified is absolute: + if (pcf_file_path.is_absolute()) { + // check if the file exists: + if (!FileUtils::FileExists(pcf_file_path)) { + // currently, we ignore it, if the pcf file path is not found, instead of flagging an error. + pcf_file_path.clear(); + } + } + // we have a relative path, needs further processing to determine where to pick it from: + else { + std::filesystem::path pcf_file_path_absolute; + + // 1. check project_path -> for generated PCF from pinconstraints manager + // 2. check tcl_script_dir_path (if driven by TCL script) + // 3. check current_dir_path + + // 1. project path + std::filesystem::path project_path = + std::filesystem::path(GlobalSession->GetCompiler()->ProjManager()->projectPath()); + pcf_file_path_absolute = project_path / pcf_file_path; + if(!FileUtils::FileExists(pcf_file_path_absolute)) { + pcf_file_path_absolute.clear(); + } + + // 2. check tcl_script_dir_path + if(pcf_file_path_absolute.empty()) { + std::filesystem::path tcl_script_dir_path = getTCLScriptDirPath(); + if(!tcl_script_dir_path.empty()) { + pcf_file_path_absolute = tcl_script_dir_path / pcf_file_path; + if(!FileUtils::FileExists(pcf_file_path_absolute)) { + pcf_file_path_absolute.clear(); + } + } + } + + // 3. check current working dir path + if(pcf_file_path_absolute.empty()) { + pcf_file_path_absolute = std::filesystem::current_path() / pcf_file_path; + if(!FileUtils::FileExists(pcf_file_path_absolute)) { + pcf_file_path_absolute.clear(); + } + } + + + // final: check if we have a valid sdc file path: + if(!pcf_file_path_absolute.empty()) { + // assign the absolute path to the pcf_file_path variable: + pcf_file_path = pcf_file_path_absolute; + } + else { + // currently, we ignore it, if the sdc file path is not found. + pcf_file_path.clear(); + } + } + // relative file path processing done. + + // if we have a valid pcf_file_path at this point, store that: + if(!pcf_file_path.empty()) { + // std::cout << "pcf file available: " << sdc_file_path << std::endl; + instance->pcf_file_path = pcf_file_path; + } + + return pcf_file_path; +} + + std::string QLSettingsManager::getStringValue(std::string category, std::string subcategory, std::string parameter) { std::string value; diff --git a/src/Compiler/QLSettingsManager.h b/src/Compiler/QLSettingsManager.h index 1e5d0ed7c..939517826 100644 --- a/src/Compiler/QLSettingsManager.h +++ b/src/Compiler/QLSettingsManager.h @@ -54,6 +54,7 @@ class QLSettingsManager : public QObject { void updateJSONSettingsForDeviceTarget(QLDeviceTarget device_target); void parseJSONSettings(); void parseSDCFilePath(); + std::filesystem::path getPCFFilePath(); bool areJSONSettingsChanged(); bool saveJSONSettings(); @@ -79,6 +80,8 @@ class QLSettingsManager : public QObject { std::filesystem::path sdc_file_path; bool sdc_file_path_from_json = false; + std::filesystem::path pcf_file_path; + // GUI elements and GUI related variables QWidget* settings_manager_widget = nullptr; QStackedWidget* stackedWidget; // each 'category' is a 'page'(represented by a QTabWidget) in the stackedWidget From f5e82763d56d9b3a819d75355388dc31a09055b8 Mon Sep 17 00:00:00 2001 From: coolbreeze413 Date: Fri, 22 Nov 2024 15:17:58 +0530 Subject: [PATCH 2/2] add pcf, repack constraint xml, and write constraints to repack command --- src/Compiler/CompilerOpenFPGA_ql.cpp | 61 ++++++++++++++++------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/src/Compiler/CompilerOpenFPGA_ql.cpp b/src/Compiler/CompilerOpenFPGA_ql.cpp index 70cda916d..f9f6a9d27 100644 --- a/src/Compiler/CompilerOpenFPGA_ql.cpp +++ b/src/Compiler/CompilerOpenFPGA_ql.cpp @@ -4156,34 +4156,35 @@ std::string CompilerOpenFPGA_ql::FinishOpenFPGAScript(const std::string& script) } - // [required] repack design contraint file + // [optional] repack design contraint file m_OpenFpgaRepackConstraintsFile = QLDeviceManager::getInstance()->deviceOpenFPGARepackDesignConstraintFile(); if(m_OpenFpgaRepackConstraintsFile.empty()) { - ErrorMessage("Cannot proceed without repack design contraint file."); - return std::string(""); + Message("Proceeding without user provided repack design contraint file."); } + else { - if(QLDeviceManager::getInstance()->deviceFileIsEncrypted(m_OpenFpgaRepackConstraintsFile)) { - - std::filesystem::path repack_design_contraint_xml_en_path = m_OpenFpgaRepackConstraintsFile; - m_OpenFpgaRepackConstraintsFile = GenerateTempFilePath(); + if(QLDeviceManager::getInstance()->deviceFileIsEncrypted(m_OpenFpgaRepackConstraintsFile)) { + + std::filesystem::path repack_design_contraint_xml_en_path = m_OpenFpgaRepackConstraintsFile; + m_OpenFpgaRepackConstraintsFile = GenerateTempFilePath(); - m_cryptdbPath = - CRFileCryptProc::getInstance()->getCryptDBFileName((QLDeviceManager::getInstance()->deviceTypeDirPath()).string(), - QLDeviceManager::getInstance()->convertToDeviceTypeString()); + m_cryptdbPath = + CRFileCryptProc::getInstance()->getCryptDBFileName((QLDeviceManager::getInstance()->deviceTypeDirPath()).string(), + QLDeviceManager::getInstance()->convertToDeviceTypeString()); - if (!CRFileCryptProc::getInstance()->loadCryptKeyDB(m_cryptdbPath.string())) { - Message("load cryptdb failed!"); - // empty string returned on error. - return std::string(""); - } + if (!CRFileCryptProc::getInstance()->loadCryptKeyDB(m_cryptdbPath.string())) { + Message("load cryptdb failed!"); + // empty string returned on error. + return std::string(""); + } - if (!CRFileCryptProc::getInstance()->decryptFile(repack_design_contraint_xml_en_path, m_OpenFpgaRepackConstraintsFile)) { - ErrorMessage("decryption failed!"); - // empty string returned on error. - return std::string(""); + if (!CRFileCryptProc::getInstance()->decryptFile(repack_design_contraint_xml_en_path, m_OpenFpgaRepackConstraintsFile)) { + ErrorMessage("decryption failed!"); + // empty string returned on error. + return std::string(""); + } } } @@ -4418,14 +4419,24 @@ std::string CompilerOpenFPGA_ql::FinishOpenFPGAScript(const std::string& script) result = ReplaceAll(result, "${READ_OPENFPGA_BITSTREAM_SETTING_COMMAND}", read_openfpga_bitstream_setting_command); - // optional, so only if this file is available, else use without constraints + // repack constraints + // 1. pass in the PCF file, if available with '--pcf' + // 2. pass in the user provided repack design constraint xml if available with '--design_constraints' + // 3. pass in option '--write_design_constraints' to dump constraints to verify std::string openfpga_repack_constraints_command = "repack"; + std::filesystem::path filepath_pcf = QLSettingsManager::getInstance()->getPCFFilePath(); + if(!filepath_pcf.empty()) { + openfpga_repack_constraints_command += + " --pcf " + filepath_pcf.string(); + } if(!m_OpenFpgaRepackConstraintsFile.empty()) { - // repack --design_constraints ${OPENFPGA_REPACK_CONSTRAINTS_FILE} - openfpga_repack_constraints_command = - std::string("repack --design_constraints ") + - m_OpenFpgaRepackConstraintsFile.string(); + openfpga_repack_constraints_command += + " --design_constraints " + m_OpenFpgaRepackConstraintsFile.string(); } + std::string generated_repack_design_constraint_filename = + "repack_design_constraint_generated.xml"; + openfpga_repack_constraints_command += + " --write_design_constraints " + generated_repack_design_constraint_filename; result = ReplaceAll(result, "${OPENFPGA_REPACK_CONSTRAINTS_COMMAND}", openfpga_repack_constraints_command); @@ -4718,7 +4729,7 @@ bool CompilerOpenFPGA_ql::GeneratePinConstraints(std::string& filepath_fpga_fix_ ///////////////////////////////////////////////////////////////// PLACE -- ///////////////////////////////////////////////////////////////// PCF ++ - std::filesystem::path filepath_pcf = QLSettingsManager::getInstance()->parsePCFFilePath(); + std::filesystem::path filepath_pcf = QLSettingsManager::getInstance()->getPCFFilePath(); if(filepath_pcf.empty()) { // no pcf file found, so we continue without PinConstraints defined.