diff --git a/src/Compiler/Compiler.cpp b/src/Compiler/Compiler.cpp index b5a3ed82f..29edd497e 100644 --- a/src/Compiler/Compiler.cpp +++ b/src/Compiler/Compiler.cpp @@ -671,11 +671,11 @@ bool Compiler::RegisterCommands(TclInterpreter* interp, bool batchMode) { compiler->Message(std::string("Reading ") + actualType + " " + expandedFile + std::string("\n")); std::ostringstream out; - bool isFileCopy = true; - bool localToProject = true; - if(compiler->copyFilesOnAdd() == false) { - isFileCopy = false; - localToProject = false; + bool isFileCopy = false; + bool localToProject = false; + if(compiler->copyFilesOnAdd() == true) { + isFileCopy = true; + localToProject = true; } bool ok = compiler->m_tclCmdIntegration->TclAddDesignFiles( {}, {}, origPathFileList.c_str(), language, isFileCopy, localToProject, out); @@ -2737,6 +2737,9 @@ int Compiler::add_files(Compiler* compiler, Tcl_Interp* interp, int argc, } else if (type == "-CPP") { language = Design::Language::CPP; actualType = "C++"; + } else if (type == "-OTHER") { + language = Design::Language::OTHER; + actualType = "OTHER"; } else if (type.find("-D") != std::string::npos) { fileList += type + " "; } else { @@ -2795,11 +2798,11 @@ int Compiler::add_files(Compiler* compiler, Tcl_Interp* interp, int argc, bool ok{true}; // check additionally, if user *does not* want to copy files from TCL script path to project dir? // user can set this using: `copy_files_on_add off` in the TCL script - bool isFileCopy = true; - bool localToProject = true; - if(compiler->copyFilesOnAdd() == false) { - isFileCopy = false; - localToProject = false; + bool isFileCopy = false; + bool localToProject = false; + if(compiler->copyFilesOnAdd() == true) { + isFileCopy = true; + localToProject = true; } if (filesType == Design) { ok = compiler->m_tclCmdIntegration->TclAddDesignFiles( diff --git a/src/Compiler/Compiler.h b/src/Compiler/Compiler.h index 073beb4c9..c9e0df45d 100644 --- a/src/Compiler/Compiler.h +++ b/src/Compiler/Compiler.h @@ -304,9 +304,10 @@ class Compiler { std::string m_output; bool m_useVerific = false; // on calling 'add_file' from TCL, should we copy them into the project dir? - // default is set to true, so they will be copied unless user does not want this. - // call set - bool m_copyFilesWhileAdding = true; + // default is set to false, so they will be copied only when user want to do this. + // call 'copy_files_on_add on' to enable this feature. + // this will apply to all file types as of now. + bool m_copyFilesWhileAdding = false; // Tasks generic options IPGenerateOpt m_ipGenerateOpt = IPGenerateOpt::None; diff --git a/src/Compiler/CompilerDefines.cpp b/src/Compiler/CompilerDefines.cpp index df5248b85..e1ed6cf5d 100644 --- a/src/Compiler/CompilerDefines.cpp +++ b/src/Compiler/CompilerDefines.cpp @@ -162,8 +162,9 @@ FOEDAG::Design::Language FOEDAG::FromFileType(const QString &type, if (QtUtils::IsEqual(type, "c") || QtUtils::IsEqual(type, "cc")) return Design::Language::C; if (QtUtils::IsEqual(type, "cpp")) return Design::Language::CPP; + if (QtUtils::IsEqual(type, "txt")) return Design::Language::OTHER; return postSynth ? Design::Language::VERILOG_NETLIST - : Design::Language::VERILOG_2001; + : Design::Language::OTHER; } int FOEDAG::read_sdc(const QString &file) { diff --git a/src/Compiler/CompilerDefines.h b/src/Compiler/CompilerDefines.h index 3c3e45a8a..ea9f063bb 100644 --- a/src/Compiler/CompilerDefines.h +++ b/src/Compiler/CompilerDefines.h @@ -48,7 +48,8 @@ enum Language { C, CPP, VHDL_2019, - EDIF + EDIF, + OTHER }; } // namespace Design diff --git a/src/Compiler/CompilerOpenFPGA_ql.cpp b/src/Compiler/CompilerOpenFPGA_ql.cpp index 91d0e9a4c..b5de004f4 100644 --- a/src/Compiler/CompilerOpenFPGA_ql.cpp +++ b/src/Compiler/CompilerOpenFPGA_ql.cpp @@ -117,6 +117,9 @@ void CompilerOpenFPGA_ql::Help(std::ostream* out) { (*out) << " --verific : Uses Verific parser" << std::endl; (*out) << "Tcl commands:" << std::endl; (*out) << " help : This help" << std::endl; + (*out) << " copy_files_on_add : sets whether to copy all the " + "design files into the generated project directory" + << std::endl; (*out) << " create_design ?-type ? : Creates a design " "with name" << std::endl; @@ -1646,34 +1649,22 @@ bool CompilerOpenFPGA_ql::RegisterCommands(TclInterpreter* interp, auto list_devices = [](void* clientData, Tcl_Interp* interp, int argc, const char* argv[]) -> int { -#if 0 - CompilerOpenFPGA_ql* compiler = (CompilerOpenFPGA_ql*)clientData; - - - std::vector device_list = compiler->ListDevices(); - - // save std::ios settings. - std::ios ios_default_state(nullptr); - ios_default_state.copyfmt(std::cout); - - std::cout << std::endl; - std::cout << "devices available:" << std::endl; - std::cout << ",,,[voltage_threshold],[p_v_t_corner]" << std::endl; - int index = 1; - for (auto device_variant: device_list) { - std::cout << std::setw(4) - << std::setfill(' ') - << index; - // restore cout state - std::cout.copyfmt(ios_default_state); - std::cout << ". " - << device_variant - << std::endl; - index++; - } - std::cout << std::endl; -#endif - return TCL_OK; + std::vector device_list = QLDeviceManager::getInstance(true)->device_list; + + for (QLDeviceType device: device_list) { + for (QLDeviceVariant device_variant: device.device_variants) { + for (QLDeviceVariantLayout device_variant_layout: device_variant.device_variant_layouts) { + std::cout << device_variant.family << "," + << device_variant.foundry << "," + << device_variant.node << "," + << device_variant.voltage_threshold << "," + << device_variant.p_v_t_corner << "," + << device_variant_layout.name << std::endl; + } + } + } + + return TCL_OK; }; interp->registerCmd("list_devices", list_devices, this, 0); @@ -2190,6 +2181,9 @@ std::string CompilerOpenFPGA_ql::InitAnalyzeScript() { lang = "BLIF"; ErrorMessage("Unsupported file format:" + lang); return ""; + case Design::Language::OTHER: + // don't include it in the compilation process + continue; } if (filesIndex < commandsLibs.size()) { const auto& filesCommandsLibs = commandsLibs[filesIndex]; @@ -2569,6 +2563,9 @@ bool CompilerOpenFPGA_ql::Synthesize() { lang = "BLIF"; ErrorMessage("Unsupported file format:" + lang); return false; + case Design::Language::OTHER: + // don't include it in the compilation process + continue; } if (filesIndex < commandsLibs.size()) { const auto& filesCommandsLibs = commandsLibs[filesIndex]; @@ -2656,8 +2653,11 @@ bool CompilerOpenFPGA_ql::Synthesize() { case Design::Language::EBLIF: ErrorMessage("Unsupported language (Yosys default parser)"); break; + case Design::Language::OTHER: + // don't include it in the compilation process + continue; } - std::string options = lang; + std::string options = lang; options += " -nolatches"; filesScript = ReplaceAll(filesScript, "${READ_VERILOG_OPTIONS}", options); filesScript = ReplaceAll(filesScript, "${INCLUDE_PATHS}", includes); diff --git a/src/Compiler/QLDeviceManager.cpp b/src/Compiler/QLDeviceManager.cpp index a609f2e37..d2f56633d 100644 --- a/src/Compiler/QLDeviceManager.cpp +++ b/src/Compiler/QLDeviceManager.cpp @@ -236,13 +236,18 @@ QWidget* QLDeviceManager::createDeviceSelectionWidget(bool newProjectMode) { m_combobox_layout->setSizeAdjustPolicy(QComboBox::AdjustToContents); families.clear(); + singularity.clear(); m_combobox_family->clear(); for (QLDeviceType device: this->device_list) { - families.push_back(device.family); + // ensure that the item being added has not been added before using std::set + // for performance reasons, keeping a vector as final container for future need of sorting. + if(singularity.insert(device.family).second == true) { + families.push_back(device.family); + } } for (std::string family: families) { - m_combobox_family->addItem(QString::fromStdString(family)); + m_combobox_family->addItem(QString::fromStdString(family)); } // connect( m_combobox_family, SIGNAL(currentTextChanged(const QString&)), this, SLOT(familyChanged(const QString&)) ); @@ -396,6 +401,7 @@ void QLDeviceManager::familyChanged(const QString& family_qstring) // std::cout << "familychanged: " << family_qstring.toStdString() << std::endl; foundrynodes.clear(); + singularity.clear(); m_combobox_foundry_node->blockSignals(true); m_combobox_foundry_node->clear(); @@ -405,7 +411,11 @@ void QLDeviceManager::familyChanged(const QString& family_qstring) if(device.family == family) { std::string _foundrynode = convertToFoundryNode(device.foundry, device.node); - foundrynodes.push_back(_foundrynode); + // ensure that the item being added has not been added before using std::set + // for performance reasons, keeping a vector as final container for future need of sorting. + if(singularity.insert(_foundrynode).second == true) { + foundrynodes.push_back(_foundrynode); + } } } @@ -444,6 +454,7 @@ void QLDeviceManager::foundrynodeChanged(const QString& foundrynode_qstring) foundry = foundrynode_vector[0]; node = foundrynode_vector[1]; voltage_thresholds.clear(); + singularity.clear(); m_combobox_voltage_threshold->blockSignals(true); m_combobox_voltage_threshold->clear(); @@ -452,7 +463,11 @@ void QLDeviceManager::foundrynodeChanged(const QString& foundrynode_qstring) std::string _foundrynode = convertToFoundryNode(device.foundry, device.node); if (_foundrynode == foundrynode) { for (QLDeviceVariant variant : device.device_variants) { + // ensure that the item being added has not been added before using std::set + // for performance reasons, keeping a vector as final container for future need of sorting. + if(singularity.insert(variant.voltage_threshold).second == true) { voltage_thresholds.push_back(variant.voltage_threshold); + } } } } @@ -485,6 +500,7 @@ void QLDeviceManager::voltage_thresholdChanged(const QString& voltage_threshold_ voltage_threshold = voltage_threshold_qstring.toStdString(); p_v_t_corners.clear(); + singularity.clear(); m_combobox_p_v_t_corner->blockSignals(true); m_combobox_p_v_t_corner->clear(); @@ -494,7 +510,11 @@ void QLDeviceManager::voltage_thresholdChanged(const QString& voltage_threshold_ if (_foundrynode == foundrynode) { for (QLDeviceVariant variant : device.device_variants) { if (variant.voltage_threshold == voltage_threshold) { - p_v_t_corners.push_back(variant.p_v_t_corner); + // ensure that the item being added has not been added before using std::set + // for performance reasons, keeping a vector as final container for future need of sorting. + if(singularity.insert(variant.p_v_t_corner).second == true) { + p_v_t_corners.push_back(variant.p_v_t_corner); + } } } } @@ -528,6 +548,7 @@ void QLDeviceManager::p_v_t_cornerChanged(const QString& p_v_t_corner_qstring) p_v_t_corner = p_v_t_corner_qstring.toStdString(); layouts.clear(); + singularity.clear(); m_combobox_layout->blockSignals(true); m_combobox_layout->clear(); @@ -539,7 +560,11 @@ void QLDeviceManager::p_v_t_cornerChanged(const QString& p_v_t_corner_qstring) if (variant.voltage_threshold == voltage_threshold) { if(variant.p_v_t_corner == p_v_t_corner) { for(QLDeviceVariantLayout _layout : variant.device_variant_layouts) { - layouts.push_back(_layout.name); + // ensure that the item being added has not been added before using std::set + // for performance reasons, keeping a vector as final container for future need of sorting. + if(singularity.insert(_layout.name).second == true) { + layouts.push_back(_layout.name); + } } } } diff --git a/src/Compiler/QLDeviceManager.h b/src/Compiler/QLDeviceManager.h index 3903d1d7c..8746d67c7 100644 --- a/src/Compiler/QLDeviceManager.h +++ b/src/Compiler/QLDeviceManager.h @@ -180,6 +180,7 @@ class QLDeviceManager : public QObject { std::string p_v_t_corner; std::vector layouts; std::string layout; + std::set singularity; QComboBox* m_combobox_family; QComboBox* m_combobox_foundry_node; diff --git a/src/Compiler/QLSettingsManager.cpp b/src/Compiler/QLSettingsManager.cpp index f3828c145..cf6f51e37 100644 --- a/src/Compiler/QLSettingsManager.cpp +++ b/src/Compiler/QLSettingsManager.cpp @@ -177,6 +177,8 @@ void QLSettingsManager::parseSDCFilePath() { } } + + // final: check if we have a valid sdc file path: if(!sdc_file_path_absolute.empty()) { // assign the absolute path to the sdc_file_path variable: @@ -371,6 +373,28 @@ std::filesystem::path QLSettingsManager::getTCLScriptDirPath() { } +std::filesystem::path QLSettingsManager::getCurrentDirPath() { + + std::filesystem::path current_dir_path_c; + + std::error_code ec; + + current_dir_path_c = std::filesystem::canonical(".", ec); + + if(!ec) { + // path exists, and can be used + } + else { + // no tcl script was used. + current_dir_path_c.clear(); + } + + // std::cout << "current_dir_path_c() : " << current_dir_path_c.string() << std::endl; + + return current_dir_path_c; +} + + QWidget* QLSettingsManager::createSettingsWidget(bool newProjectMode) { // whenever a new GUI Widget is created, we mark the mode of operation of this widget: @@ -1279,6 +1303,13 @@ void QLSettingsManager::parseJSONSettings() { } } + // 4. convert to canonical path: + // if(!settings_json_filepath.empty()) { + // std::error_code ec; + // settings_json_filepath = std::filesystem::canonical(settings_json_filepath, ec); + // if(!ec) settings_json_filepath.clear(); + // } + // final: check we have a valid settings json: if(!settings_json_filepath.empty()) { try { @@ -1329,6 +1360,13 @@ void QLSettingsManager::parseJSONSettings() { } } + // 4. convert to canonical path: + // if(!power_estimation_json_filepath.empty()) { + // std::error_code ec; + // power_estimation_json_filepath = std::filesystem::canonical(power_estimation_json_filepath, ec); + // if(!ec) power_estimation_json_filepath.clear(); + // } + // final: check we have a valid settings json: if(!power_estimation_json_filepath.empty()) { try { diff --git a/src/Compiler/QLSettingsManager.h b/src/Compiler/QLSettingsManager.h index 5e913fc21..dd21a7687 100644 --- a/src/Compiler/QLSettingsManager.h +++ b/src/Compiler/QLSettingsManager.h @@ -42,6 +42,7 @@ class QLSettingsManager : public QObject { static const json* getJson(std::string category); static std::filesystem::path getSDCFilePath(); static std::filesystem::path getTCLScriptDirPath(); + static std::filesystem::path getCurrentDirPath(); ~QLSettingsManager(); diff --git a/src/NewProject/ProjectManager/project_manager.cpp b/src/NewProject/ProjectManager/project_manager.cpp index 4c519cfab..dfd50553c 100644 --- a/src/NewProject/ProjectManager/project_manager.cpp +++ b/src/NewProject/ProjectManager/project_manager.cpp @@ -270,25 +270,66 @@ int ProjectManager::CreateProject(const QString& strName, if(qlSettingsManagerInstance) { // check whether we were launched via TCL script, or in 'project' mode: + bool create_project_from_tcl_script = false; + // get the TCL script path (which should be valid, if we are being executed from the TCL script) std::filesystem::path tcl_script_dir_path = QLSettingsManager::getTCLScriptDirPath(); + std::filesystem::path current_dir_path = QLSettingsManager::getCurrentDirPath(); + std::error_code ec; if(!tcl_script_dir_path.empty()) { - // we are in TCL script mode, which means we are executed from the TCL script to: create_design - // so, we need to copy the settings/power json files from the TCL script directory into the generated project directory - // unless the user has set the option *not* to copy via: `copy_files_on_add off` in the TCL script + // we were launched in TCL script mode, which means we are executed from the TCL script to: create_design + + // additional consideration: we may have started in TCL script mode (GUI), but when we get here, it may be + // that the user is now trying to create a new project from the current project GUI window itself. + // In that case, the TCL script dir path is still set, from before, however we are actually here on GUI > create project + // flow and not from TCL 'create_design' command flow!! + // So, we need to branch off into the GUI flow here in that case. + // how do we check this condition? + // when we create project from TCL script by specifying 'create_design ' + // and run the TCL script from the commandline: + // then the project being created will have the path: / *always* + // if this is the case, then we are here creating a project from the TCL script flow. + // if this is *NOT* the case, then although Aurora was *initially* started via TCL script, + // we are actually creating a new project from the GUI flow! + // So, we enhance using this condition: + // if == / -->> create_project from TCL script flow + // else -->> create_project from GUI Create Project flow! + + if( std::filesystem::equivalent(strPath.toStdString(), + (current_dir_path/strName.toStdString()), + ec) ) { + create_project_from_tcl_script = true; + } + else { + create_project_from_tcl_script = false; + } + } + else { + // we are in 'project'/GUI mode + create_project_from_tcl_script = false; + } + + // std::cout << "create_project_from_tcl_script: " << create_project_from_tcl_script << std::endl; + + if(create_project_from_tcl_script) { + // TCL script has 'create_design' command, which caused us to reach this point + + // by default, we use the JSON files from the TCL script directory + // if the user chooses to 'copy' the files using 'copy_files_on_add on' in the TCL script, + // we need to copy the settings/power json files from the TCL script directory into the generated project directory if(GlobalSession->GetCompiler()->copyFilesOnAdd()) { // get the settings/power JSON filepaths (always expected in the TCL script directory) std::filesystem::path source_settings_json_path = tcl_script_dir_path / (strName.toStdString() + ".json"); - + std::filesystem::path source_power_estimation_json_path = tcl_script_dir_path / (strName.toStdString() + "_power" + ".json"); // settings json should exist, and should be copied into the generated project directory if(FileUtils::FileExists(source_settings_json_path)) { std::filesystem::path target_settings_json_path = std::filesystem::path(strPath.toStdString()) / (strName.toStdString() + ".json"); - std::error_code ec; + std::filesystem::copy_file(source_settings_json_path, target_settings_json_path, std::filesystem::copy_options::overwrite_existing, @@ -322,6 +363,8 @@ int ProjectManager::CreateProject(const QString& strName, } } else { + // GUI was invoked and Create New Project flow was used, to reach this point + // we are in 'project'/GUI mode, which means that the settings/power estimation JSON must be created using the 'Project Settings' // selections that user has done: qlSettingsManagerInstance->newProjectMode = true; diff --git a/src/NewProject/add_constraints_form.cpp b/src/NewProject/add_constraints_form.cpp index 9ab436fc7..9cd581a5b 100644 --- a/src/NewProject/add_constraints_form.cpp +++ b/src/NewProject/add_constraints_form.cpp @@ -28,7 +28,7 @@ addConstraintsForm::addConstraintsForm(QWidget *parent) ui->m_frame->setLayout(box); ui->m_ckkBoxCopy->setText(tr("Copy sources into project.")); - ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Checked); + ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Unchecked); Compiler *compiler = GlobalSession->GetCompiler(); if (compiler->PinAssignOpts() == Compiler::PinAssignOpt::Random) diff --git a/src/NewProject/add_sim_form.cpp b/src/NewProject/add_sim_form.cpp index 5eebe7039..a90215ffd 100644 --- a/src/NewProject/add_sim_form.cpp +++ b/src/NewProject/add_sim_form.cpp @@ -40,7 +40,7 @@ addSimForm::addSimForm(QWidget *parent) ui->m_frame->setLayout(box); ui->m_ckkBoxCopy->setText(tr("Copy sources into project. ")); - ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Checked); + ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Unchecked); } addSimForm::~addSimForm() { delete ui; } diff --git a/src/NewProject/add_source_form.cpp b/src/NewProject/add_source_form.cpp index 87316a5e8..01d5f15f3 100644 --- a/src/NewProject/add_source_form.cpp +++ b/src/NewProject/add_source_form.cpp @@ -33,7 +33,7 @@ addSourceForm::addSourceForm(GridType gt, QWidget *parent) ui->m_frame->setLayout(box); ui->m_ckkBoxCopy->setText(tr("Copy sources into project. ")); - ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Checked); + ui->m_ckkBoxCopy->setCheckState(Qt::CheckState::Unchecked); connect(ui->toolButtonIncludePath, &QToolButton::clicked, this, &addSourceForm::includePathClicked); diff --git a/src/NewProject/create_file_dialog.cpp b/src/NewProject/create_file_dialog.cpp index 20c839ecb..28894e2ef 100644 --- a/src/NewProject/create_file_dialog.cpp +++ b/src/NewProject/create_file_dialog.cpp @@ -56,6 +56,7 @@ void createFileDialog::initialDialog(int type) { ui->m_comboxFileType->addItem(tr("Verilog")); ui->m_comboxFileType->addItem(tr("SystemVerilog")); if (GT_SIM != m_type) ui->m_comboxFileType->addItem(tr("VHDL")); + ui->m_comboxFileType->addItem(tr("Other")); } else if (GT_CONSTRAINTS == m_type) { setWindowTitle(tr("Create Constraints File")); ui->m_labelDetailed->setText( diff --git a/src/NewProject/source_grid.cpp b/src/NewProject/source_grid.cpp index 00fe45bba..e737694dd 100644 --- a/src/NewProject/source_grid.cpp +++ b/src/NewProject/source_grid.cpp @@ -40,7 +40,8 @@ static const auto DESIGN_SOURCES_FILTER = QObject::tr( "SystemVerilog Header Files (*.svh *.svhp);;" "NETLIST files (*.eblif *.blif *.v *.sv *.svp);;" "HDL Files (*.vhd *.vhdl *.vhf *.vhdp *.v *.verilog" - "*.vh *.h *.svh *.vhp *.svhp *.sv )"); + "*.vh *.h *.svh *.vhp *.svhp *.sv);;" + "ALL Files(*.*)"); static const auto SIM_SOURCES_FILTER = QObject::tr( "Simulation Source Files (*.c *.cc *.cpp *.v *.sv *.vhd *.vhdl)"); @@ -485,6 +486,7 @@ QComboBox *sourceGrid::CreateLanguageCombo(int projectType, GridType gType) { combo->addItem("SV 2009", Design::Language::SYSTEMVERILOG_2009); combo->addItem("SV 2012", Design::Language::SYSTEMVERILOG_2012); combo->addItem("SV 2017", Design::Language::SYSTEMVERILOG_2017); + combo->addItem("OTHER", Design::Language::OTHER); break; } return combo;