Commit 4c8d5dc3 authored by Andrey Filippov's avatar Andrey Filippov

Working on command sequencing

parent 8c4668b9
...@@ -103,6 +103,7 @@ public class VDT { ...@@ -103,6 +103,7 @@ public class VDT {
public static final String ATTR_TOOL_INFO = ID_VDT + ".ATTR_TOOL_INFO"; public static final String ATTR_TOOL_INFO = ID_VDT + ".ATTR_TOOL_INFO";
public static final String ATTR_LOG_BUILD_STAMP = ID_VDT + ".ATTR_LOG_BUILD_STAMP"; public static final String ATTR_LOG_BUILD_STAMP = ID_VDT + ".ATTR_LOG_BUILD_STAMP";
public static final String ATTR_TOOL_STATE_FILE = ID_VDT + ".TOOL_STATE_FILE"; // name of state (snapshot) file to restore passed at tool launch
/** /**
...@@ -153,4 +154,9 @@ public class VDT { ...@@ -153,4 +154,9 @@ public class VDT {
public static final String GENERATOR_ID_USERNAME = "UserName"; public static final String GENERATOR_ID_USERNAME = "UserName";
public static final String GENERATOR_ID_BLANK = "Blank"; public static final String GENERATOR_ID_BLANK = "Blank";
public static final String GENERATOR_ID_NEWLINE = "NewLine"; public static final String GENERATOR_ID_NEWLINE = "NewLine";
public static final String GENERATOR_ID_STATE_DIR = "StateDir";
public static final String GENERATOR_ID_STATE_FILE = "StateFile";
} // class VDT } // class VDT
...@@ -115,8 +115,10 @@ public class LaunchCore { ...@@ -115,8 +115,10 @@ public class LaunchCore {
, String logBuildStamp ) throws CoreException { , String logBuildStamp ) throws CoreException {
workingCopy.setAttribute(VDT.ATTR_LOG_BUILD_STAMP, logBuildStamp); workingCopy.setAttribute(VDT.ATTR_LOG_BUILD_STAMP, logBuildStamp);
} }
public static void setToolStateFile( ILaunchConfigurationWorkingCopy workingCopy
, String stateFile ) throws CoreException {
workingCopy.setAttribute(VDT.ATTR_TOOL_STATE_FILE, stateFile);
}
public static void updateLaunchConfiguration( ILaunchConfigurationWorkingCopy workingCopy public static void updateLaunchConfiguration( ILaunchConfigurationWorkingCopy workingCopy
...@@ -217,12 +219,7 @@ public class LaunchCore { ...@@ -217,12 +219,7 @@ public class LaunchCore {
return launchConfig; return launchConfig;
} // createLaunchConfiguration() } // createLaunchConfiguration()
/*
public static void launch(Tool tool, IProject project) throws CoreException {
launch(tool, project, VDT.VARIABLE_RESOURCE_NAME);
}
*/
public static void launch( public static void launch(
......
...@@ -290,7 +290,7 @@ public class RunningBuilds { ...@@ -290,7 +290,7 @@ public class RunningBuilds {
if (toolName.equals(runConfig.getToolName())){ if (toolName.equals(runConfig.getToolName())){
Tool tool=ToolsCore.getTool(runConfig.getToolName()); Tool tool=ToolsCore.getTool(runConfig.getToolName());
tool.setRunning(false); tool.setRunning(false);
tool.updateViewStateIcon(); tool.toolFinished();
if (tool.getState()==TOOL_STATE.KEPT_OPEN) { if (tool.getState()==TOOL_STATE.KEPT_OPEN) {
MessageUI.error("Termninal that starts by this tool ("+toolName+") is already open in console \""+consoleName+"\""); MessageUI.error("Termninal that starts by this tool ("+toolName+") is already open in console \""+consoleName+"\"");
return true; return true;
......
...@@ -97,6 +97,14 @@ public class ToolLogFile { ...@@ -97,6 +97,14 @@ public class ToolLogFile {
return null; return null;
} }
public static String insertTimeStamp(String filename, String timestamp){
int index=filename.lastIndexOf(".");
if (index>=0){
return filename.substring(0, index)+BUILD_STAMP_SEPARATOR+timestamp+filename.substring(index);
} else {
return filename+BUILD_STAMP_SEPARATOR+timestamp;
}
}
/** /**
* @param logDir Directory path of the log files root directory (or null) * @param logDir Directory path of the log files root directory (or null)
......
...@@ -330,7 +330,11 @@ public class VDTLaunchUtil { ...@@ -330,7 +330,11 @@ public class VDTLaunchUtil {
public static String getLogBuildStamp(ILaunchConfiguration configuration) throws CoreException{ public static String getLogBuildStamp(ILaunchConfiguration configuration) throws CoreException{
return configuration.getAttribute(VDT.ATTR_LOG_BUILD_STAMP, (String) null); return configuration.getAttribute(VDT.ATTR_LOG_BUILD_STAMP, (String) null);
} }
public static String getToolStateFile(ILaunchConfiguration configuration) throws CoreException{
return configuration.getAttribute(VDT.ATTR_TOOL_STATE_FILE, (String) null);
}
/** /**
* Throws a core exception with an error status object built from * Throws a core exception with an error status object built from
* the given message, lower level exception, and error code. * the given message, lower level exception, and error code.
......
...@@ -95,8 +95,8 @@ public class VDTRunner { ...@@ -95,8 +95,8 @@ public class VDTRunner {
tool.setDirty(false); tool.setDirty(false);
tool.setState(TOOL_STATE.FAILURE); tool.setState(TOOL_STATE.FAILURE);
tool.setRunning(false); tool.setRunning(false);
tool.setFinishTimeStamp(); tool.setTimeStamp();
tool.updateViewStateIcon(); tool.toolFinished();
//removeConfiguration //removeConfiguration
runningBuilds.removeConfiguration(runConfig.getOriginalConsoleName()); runningBuilds.removeConfiguration(runConfig.getOriginalConsoleName());
} }
...@@ -265,13 +265,13 @@ public class VDTRunner { ...@@ -265,13 +265,13 @@ public class VDTRunner {
monitor.done(); monitor.done();
Tool tool=ToolsCore.getTool(runConfig.getToolName()); Tool tool=ToolsCore.getTool(runConfig.getToolName());
tool.setRunning(false); tool.setRunning(false);
tool.setFinishTimeStamp(); tool.setTimeStamp();
if ((tool.getState()==TOOL_STATE.SUCCESS) && runConfig.isKeptOpen()) { if ((tool.getState()==TOOL_STATE.SUCCESS) && runConfig.isKeptOpen()) {
tool.setState(TOOL_STATE.KEPT_OPEN); tool.setState(TOOL_STATE.KEPT_OPEN);
} else { // failure on not } else { // failure on not
runningBuilds.removeConfiguration(consoleName); runningBuilds.removeConfiguration(consoleName);
} }
tool.updateViewStateIcon(); tool.toolFinished();
} }
public void logPlaybackLaunch(String consoleName) throws CoreException { public void logPlaybackLaunch(String consoleName) throws CoreException {
...@@ -332,7 +332,7 @@ public class VDTRunner { ...@@ -332,7 +332,7 @@ public class VDTRunner {
System.out.println("All playbacks finished"); System.out.println("All playbacks finished");
monitor.done(); monitor.done();
ToolsCore.getTool(runConfig.getToolName()).setRunning(false); ToolsCore.getTool(runConfig.getToolName()).setRunning(false);
ToolsCore.getTool(runConfig.getToolName()).updateViewStateIcon(); ToolsCore.getTool(runConfig.getToolName()).toolFinished();
} }
......
...@@ -39,7 +39,7 @@ public abstract class Option { ...@@ -39,7 +39,7 @@ public abstract class Option {
} }
/** /**
* Return core option (optiuon without UI elements) * Return core option (option without UI elements)
*/ */
public Option getOption() { public Option getOption() {
return this; return this;
......
...@@ -75,7 +75,7 @@ public class ParamBasedListOption extends ParamBasedOption { ...@@ -75,7 +75,7 @@ public class ParamBasedListOption extends ParamBasedOption {
/** /**
* Load the default option value from persistent storage * Load the default option value from persistent storage
* *
* @return the sequnce of the list items separated by SEPARATOR. * @return the sequence of the list items separated by SEPARATOR.
*/ */
public String doLoadDefault() { public String doLoadDefault() {
List<String> list = doLoadDefaultList(); List<String> list = doLoadDefaultList();
...@@ -91,7 +91,7 @@ public class ParamBasedListOption extends ParamBasedOption { ...@@ -91,7 +91,7 @@ public class ParamBasedListOption extends ParamBasedOption {
/** /**
* Save value to persistent storage * Save value to persistent storage
* *
* @param value the sequnce of the list items separated by SEPARATOR. * @param value the sequence of the list items separated by SEPARATOR.
*/ */
public boolean doStore(String value) { public boolean doStore(String value) {
List<String> list = OptionsUtils.convertStringToList(value); List<String> list = OptionsUtils.convertStringToList(value);
......
...@@ -21,6 +21,9 @@ import java.io.File; ...@@ -21,6 +21,9 @@ import java.io.File;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import org.eclipse.ui.IMemento;
//import com.elphel.vdt.VDTPlugin; //import com.elphel.vdt.VDTPlugin;
import com.elphel.vdt.veditor.VerilogPlugin; import com.elphel.vdt.veditor.VerilogPlugin;
import com.elphel.vdt.core.options.OptionsCore; import com.elphel.vdt.core.options.OptionsCore;
...@@ -35,7 +38,7 @@ import com.elphel.vdt.core.tools.params.Tool; ...@@ -35,7 +38,7 @@ import com.elphel.vdt.core.tools.params.Tool;
import com.elphel.vdt.ui.MessageUI; import com.elphel.vdt.ui.MessageUI;
/** /**
* Manager of tools configuartion * Manager of tools configuration
* *
* Created: 14.01.2006 * Created: 14.01.2006
* @author Lvov Konstantin * @author Lvov Konstantin
...@@ -73,6 +76,17 @@ public class ToolsCore { ...@@ -73,6 +76,17 @@ public class ToolsCore {
return null; return null;
} }
public static void saveToolsState(IMemento memento){
for (Tool tool : getConfig().getContextManager().getToolList())
tool.saveState(memento);
}
public static void restoreToolsState(IMemento memento){
for (Tool tool : getConfig().getContextManager().getToolList())
tool.restoreState(memento);
}
public static Tool getToolWorkingCopy(String toolID) { public static Tool getToolWorkingCopy(String toolID) {
Tool tool = getTool(toolID); Tool tool = getTool(toolID);
......
...@@ -126,6 +126,12 @@ public class XMLConfig extends Config { ...@@ -126,6 +126,12 @@ public class XMLConfig extends Config {
static final String CONTEXT_TOOL_SYNTAX_INFO = "info"; static final String CONTEXT_TOOL_SYNTAX_INFO = "info";
static final String CONTEXT_TOOL_IGNORE_FILTER = "ignore"; // file path regular expression to remove libraries from source list static final String CONTEXT_TOOL_IGNORE_FILTER = "ignore"; // file path regular expression to remove libraries from source list
static final String CONTEXT_TOOL_LOG_DIRECTORY = "log-dir"; // folder to store the tool log files static final String CONTEXT_TOOL_LOG_DIRECTORY = "log-dir"; // folder to store the tool log files
static final String CONTEXT_TOOL_STATE_DIRECTORY = "state-dir"; // folder to store the tool state (snapshot) files
static final String CONTEXT_TOOL_DISABLED = "disabled"; // Parameter name that disables the tool if true
static final String CONTEXT_TOOL_RESULT = "result"; // Parameter name keeps the filename representing result (snapshot)
static final String CONTEXT_TOOL_RESTORE = "restore"; // tool name that restores the state form result
static final String CONTEXT_LINEBLOCK_TAG = "line"; static final String CONTEXT_LINEBLOCK_TAG = "line";
static final String CONTEXT_LINEBLOCK_NAME_ATTR = "name"; static final String CONTEXT_LINEBLOCK_NAME_ATTR = "name";
...@@ -162,6 +168,7 @@ public class XMLConfig extends Config { ...@@ -162,6 +168,7 @@ public class XMLConfig extends Config {
static final String MENUITEM_TAG = "menuitem"; static final String MENUITEM_TAG = "menuitem";
static final String MENUITEM_CALL_ATTR = "call"; static final String MENUITEM_CALL_ATTR = "call";
static final String MENUITEM_INSTANCE_ATTR = "tool-instance";
static final String MENUITEM_NAME_ATTR = MENU_NAME_ATTR; static final String MENUITEM_NAME_ATTR = MENU_NAME_ATTR;
static final String MENUITEM_LABEL_ATTR = MENU_LABEL_ATTR; static final String MENUITEM_LABEL_ATTR = MENU_LABEL_ATTR;
static final String MENUITEM_ICON_ATTR = MENU_ICON_ATTR; static final String MENUITEM_ICON_ATTR = MENU_ICON_ATTR;
...@@ -623,6 +630,11 @@ public class XMLConfig extends Config { ...@@ -623,6 +630,11 @@ public class XMLConfig extends Config {
String toolInfo = getAttributeValue(contextNode, CONTEXT_TOOL_SYNTAX_INFO); String toolInfo = getAttributeValue(contextNode, CONTEXT_TOOL_SYNTAX_INFO);
String ignoreFilter = getAttributeValue(contextNode, CONTEXT_TOOL_IGNORE_FILTER); String ignoreFilter = getAttributeValue(contextNode, CONTEXT_TOOL_IGNORE_FILTER);
String logDir = getAttributeValue(contextNode, CONTEXT_TOOL_LOG_DIRECTORY); String logDir = getAttributeValue(contextNode, CONTEXT_TOOL_LOG_DIRECTORY);
String stateDir = getAttributeValue(contextNode, CONTEXT_TOOL_STATE_DIRECTORY);
String disabled = getAttributeValue(contextNode, CONTEXT_TOOL_DISABLED);
String result = getAttributeValue(contextNode, CONTEXT_TOOL_RESULT);
String restore = getAttributeValue(contextNode, CONTEXT_TOOL_RESTORE);
boolean isShell=false; boolean isShell=false;
if (toolShell != null){ if (toolShell != null){
...@@ -666,10 +678,13 @@ public class XMLConfig extends Config { ...@@ -666,10 +678,13 @@ public class XMLConfig extends Config {
ignoreFilter, ignoreFilter,
toolDepends, toolDepends,
logDir, logDir,
stateDir,
disabled,
result,
restore,
null, null,
null, null,
null); null);
break; break;
default: default:
...@@ -1189,6 +1204,8 @@ public class XMLConfig extends Config { ...@@ -1189,6 +1204,8 @@ public class XMLConfig extends Config {
String itemLabel = getAttributeValue(menuItemNode, MENUITEM_LABEL_ATTR); String itemLabel = getAttributeValue(menuItemNode, MENUITEM_LABEL_ATTR);
String itemIcon = getAttributeValue(menuItemNode, MENUITEM_ICON_ATTR); String itemIcon = getAttributeValue(menuItemNode, MENUITEM_ICON_ATTR);
String itemCall = getAttributeValue(menuItemNode, MENUITEM_CALL_ATTR); String itemCall = getAttributeValue(menuItemNode, MENUITEM_CALL_ATTR);
String itemInstance = getAttributeValue(menuItemNode, MENUITEM_INSTANCE_ATTR);
String itemVisible = getAttributeValue(menuItemNode, MENUITEM_VISIBLE_ATTR); String itemVisible = getAttributeValue(menuItemNode, MENUITEM_VISIBLE_ATTR);
String itemAfter = getAttributeValue(menuItemNode, MENUITEM_AFTER_ATTR); String itemAfter = getAttributeValue(menuItemNode, MENUITEM_AFTER_ATTR);
...@@ -1206,7 +1223,8 @@ public class XMLConfig extends Config { ...@@ -1206,7 +1223,8 @@ public class XMLConfig extends Config {
itemLabel, itemLabel,
itemIcon, itemIcon,
isVisible, isVisible,
itemCall); itemCall,
itemInstance);
} }
private List<CommandLinesBlock> readCommandLinesBlocks(Node node, Context context) private List<CommandLinesBlock> readCommandLinesBlocks(Node node, Context context)
......
...@@ -204,6 +204,22 @@ public abstract class Context { ...@@ -204,6 +204,22 @@ public abstract class Context {
// all other needed params are built into command line array // all other needed params are built into command line array
// that array is then returned // that array is then returned
// public String[] buildParams() throws ToolException { // public String[] buildParams() throws ToolException {
public List<String> getSessionConsoles(){
List<String> consoleList=new ArrayList<String>();
Iterator<CommandLinesBlock> commandLinesBlockIter = commandLinesBlocks.iterator();
while(commandLinesBlockIter.hasNext()) {
CommandLinesBlock commandLinesBlock = (CommandLinesBlock)commandLinesBlockIter.next();
if (commandLinesBlock.isConsoleKind()){
Parameter parName = findParam(commandLinesBlock.getDestination()); // command file or console name
String consoleName = (parName != null)? parName.getValue().get(0).trim() : null;
if (consoleName!=null) consoleList.add(consoleName);
}
}
return consoleList;
}
public BuildParamsItem[] buildParams() throws ToolException { public BuildParamsItem[] buildParams() throws ToolException {
List<BuildParamsItem> buildParamItems = new ArrayList<BuildParamsItem>(); List<BuildParamsItem> buildParamItems = new ArrayList<BuildParamsItem>();
......
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
package com.elphel.vdt.core.tools.generators; package com.elphel.vdt.core.tools.generators;
import com.elphel.vdt.core.Utils; import com.elphel.vdt.core.Utils;
import com.elphel.vdt.core.tools.params.Tool;
import com.elphel.vdt.ui.MessageUI; import com.elphel.vdt.ui.MessageUI;
/** /**
...@@ -32,6 +33,7 @@ public abstract class AbstractGenerator { ...@@ -32,6 +33,7 @@ public abstract class AbstractGenerator {
protected String separator; protected String separator;
private final boolean forcedMultiline; private final boolean forcedMultiline;
private boolean menuMode=false; // managing menu items, not running tool. Ignore Generator errors private boolean menuMode=false; // managing menu items, not running tool. Ignore Generator errors
protected Tool tool0; // "tool" was already used in ToolParamRecognizer / Andrey
public AbstractGenerator() { public AbstractGenerator() {
this(false); this(false);
...@@ -68,6 +70,9 @@ public abstract class AbstractGenerator { ...@@ -68,6 +70,9 @@ public abstract class AbstractGenerator {
public boolean getMenuMode(){ public boolean getMenuMode(){
return menuMode; return menuMode;
} }
public void setTool(Tool tool){
this.tool0=tool;
}
public abstract String getName(); public abstract String getName();
......
/*******************************************************************************
* Copyright (c) 2014 Elphel, Inc.
* This file is a part of Eclipse/VDT plug-in.
* Eclipse/VDT plug-in is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Eclipse/VDT plug-in is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.elphel.vdt.core.tools.generators;
import com.elphel.vdt.VDT;
import com.elphel.vdt.ui.variables.SelectedResourceManager;
public class StateDirGenerator extends AbstractGenerator {
public static final String NAME = VDT.GENERATOR_ID_STATE_DIR;
public String getName() {
return NAME;
}
protected String[] getStringValues() {
String stateDir=(tool0==null)?null:tool0.getStateDir();
if (stateDir==null) stateDir="";
return new String[] {stateDir};
}
}
/*******************************************************************************
* Copyright (c) 2014 Elphel, Inc.
* This file is a part of Eclipse/VDT plug-in.
* Eclipse/VDT plug-in is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Eclipse/VDT plug-in is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.elphel.vdt.core.tools.generators;
import com.elphel.vdt.VDT;
import com.elphel.vdt.ui.variables.SelectedResourceManager;
public class StateFileGenerator extends AbstractGenerator {
public static final String NAME = VDT.GENERATOR_ID_STATE_FILE;
public String getName() {
return NAME;
}
protected String[] getStringValues() {
String stateFile=(tool0==null)? null: tool0.getStateFile(); // calculated from result name and timestamp, or explicitly specified
if (stateFile==null) stateFile="";
return new String[] {stateFile};
}
}
...@@ -24,6 +24,7 @@ import com.elphel.vdt.core.tools.params.Tool; ...@@ -24,6 +24,7 @@ import com.elphel.vdt.core.tools.params.Tool;
public class DesignMenuToolItem extends DesignMenuItem { public class DesignMenuToolItem extends DesignMenuItem {
private String tcall; private String tcall;
private String toolInstance;
public DesignMenuToolItem(Config config, public DesignMenuToolItem(Config config,
DesignMenu parentMenu, DesignMenu parentMenu,
...@@ -32,7 +33,8 @@ public class DesignMenuToolItem extends DesignMenuItem { ...@@ -32,7 +33,8 @@ public class DesignMenuToolItem extends DesignMenuItem {
String label, String label,
String icon, String icon,
Boolean visible, Boolean visible,
String tcall) String tcall,
String toolInstance)
{ {
super(config, super(config,
parentMenu, parentMenu,
...@@ -43,6 +45,7 @@ public class DesignMenuToolItem extends DesignMenuItem { ...@@ -43,6 +45,7 @@ public class DesignMenuToolItem extends DesignMenuItem {
visible); visible);
this.tcall = tcall; this.tcall = tcall;
this.toolInstance = toolInstance;
} }
public void init() throws ConfigException { public void init() throws ConfigException {
...@@ -74,7 +77,8 @@ public class DesignMenuToolItem extends DesignMenuItem { ...@@ -74,7 +77,8 @@ public class DesignMenuToolItem extends DesignMenuItem {
label, label,
icon, icon,
visible, visible,
tcall); tcall,
toolInstance);
} }
......
...@@ -79,7 +79,7 @@ public class FormatProcessor { ...@@ -79,7 +79,7 @@ public class FormatProcessor {
while(pos < template.length()) { while(pos < template.length()) {
if(template.startsWith(CONTROL_SEQ, pos)) { if(template.startsWith(CONTROL_SEQ, pos)) {
pos += CONTROL_SEQ_LEN; pos += CONTROL_SEQ_LEN;
// got different instance of ToolParamRecognizer with tool==null
RecognizerResult result = recognize(template, pos); // Already skipped blank lines (and spaces in each line, added separators - no, on deifferent level RecognizerResult result = recognize(template, pos); // Already skipped blank lines (and spaces in each line, added separators - no, on deifferent level
if(result != null && result.getGenerator() != null) { if(result != null && result.getGenerator() != null) {
......
...@@ -118,7 +118,10 @@ public class Parameter implements Cloneable, Updateable { ...@@ -118,7 +118,10 @@ public class Parameter implements Cloneable, Updateable {
public Object clone() { // did not clone context (intentionally) public Object clone() { // did not clone context (intentionally)
return new Parameter(this); return new Parameter(this);
} }
public String getSourceXML(){
return sourceXML;
}
public boolean getIsChild(){ public boolean getIsChild(){
return isChild; return isChild;
} }
...@@ -386,7 +389,7 @@ public class Parameter implements Cloneable, Updateable { ...@@ -386,7 +389,7 @@ public class Parameter implements Cloneable, Updateable {
if (firstLine.substring(0,2).equals("\\@")){ if (firstLine.substring(0,2).equals("\\@")){
firstLine=firstLine.substring(1); firstLine=firstLine.substring(1);
} }
if (firstLine.substring(1,3).equals("\\@")){ if ((firstLine.length()>2) && (firstLine.substring(1,3).equals("\\@"))){
firstLine=firstLine.substring(0,1)+firstLine.substring(2); firstLine=firstLine.substring(0,1)+firstLine.substring(2);
} }
processedDefaultValue.remove(0); processedDefaultValue.remove(0);
......
/*******************************************************************************
* Copyright (c) 2014 Elphel, Inc.
* This file is a part of Eclipse/VDT plug-in.
* Eclipse/VDT plug-in is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Eclipse/VDT plug-in is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*******************************************************************************/
package com.elphel.vdt.core.tools.params;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.swt.widgets.Display;
import com.elphel.vdt.core.launching.ToolLogFile;
import com.elphel.vdt.core.tools.ToolsCore;
import com.elphel.vdt.core.tools.params.Tool.TOOL_STATE;
import com.elphel.vdt.ui.MessageUI;
import com.elphel.vdt.ui.options.FilteredFileSelector;
import com.elphel.vdt.ui.variables.SelectedResourceManager;
import com.elphel.vdt.ui.views.DesignFlowView;
import com.elphel.vdt.veditor.VerilogPlugin;
import com.elphel.vdt.veditor.preference.PreferenceStrings;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ToolSequence {
private DesignFlowView designFlowView;
public ToolSequence(DesignFlowView designFlowView){
this.designFlowView=designFlowView;
}
public void toolFinished(Tool tool){
if (tool.isRunning()) {
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE))
System.out.println("\nTool "+tool.getName()+" is still running");
return;
}
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE))
System.out.println("\nTool "+tool.getName()+" FINISHED - add more stuff here");
if (tool.getState()==TOOL_STATE.SUCCESS){
updateLinkLatest(tool);
} else if (tool.getState()==TOOL_STATE.KEPT_OPEN){
} else {
}
if (designFlowView!=null){
Display.getDefault().syncExec(new Runnable() {
public void run() {
designFlowView.updateLaunchAction(); // Run from Display thread to prevent "invalid thread access" when called from Runner
}
});
}
}
// Result file may be skipped, in that case link should not be updated, but the console state should be
private void updateLinkLatest(Tool tool){
String stateDirString=tool.getStateDir();
String linkString=tool.getResultName();
String targetString=tool.getStateFile(); // With timestamp or specifically set through selection
IProject project = SelectedResourceManager.getDefault().getSelectedProject(); // should not be null when we got here
IFolder stateDir= project.getFolder((stateDirString==null)?"":stateDirString);
// Create file for target and see if it actually exists
IFile target= stateDir.getFile(targetString);
// Eclipse does not know IFile exists until it refreshes. It is also possible to test File existence, not the IFile
try {
target.refreshLocal(0, null); // long-running
} catch (CoreException e1) {
System.out.println("Failed to refreshLocal "+target.getLocation().toOSString()+" e="+e1.toString());
}
File file=new File (target.getLocation().toOSString());
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE)) {
System.out.println("File "+file.getAbsolutePath()+" exists="+file.exists());
System.out.println("IFile "+target.getLocation().toOSString()+" exists="+target.exists());
}
// if (!file.exists()){
if (!target.exists()){
System.out.println("Will not link "+linkString+" to nonexistent resource:"+targetString+" in "+stateDirString+": "+target.getLocation());
return; // No link created as there was no snapshot, but the console state is valid.
}
IFile link= stateDir.getFile(linkString);
try {
link.createLink(
target.getLocation(),
IResource.ALLOW_MISSING_LOCAL | IResource.REPLACE,
null);
} catch (CoreException e) {
MessageUI.error("Failed to create link "+link.toString()+" to the target "+
target.toString()+" e="+e.toString());
return;
}
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE)) {
System.out.println("Created link "+link.toString()+" to the target "+
target.toString());
System.out.println("link.getRawLocation()= "+link.getRawLocation().toString());
System.out.println("link.getModificationStamp()= "+link.getModificationStamp());
System.out.println("target.getModificationStamp()= "+target.getModificationStamp());
}
}
private boolean updateSessionTools(Tool tool){
String targetString=tool.getStateFile();
// after restore this may be a non-timestamp file - use current timestamp instead of the restored?
if (targetString==null){
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE))
System.out.println("No result state specified for tool "+tool.getName()+
", no session will be updated");
return false;
}
List<Tool> sessionList=new ArrayList<Tool>();
List<String> consoleNames=tool.getSessionConsoles();
if (consoleNames!=null){
for(Iterator<String> iter = consoleNames.iterator(); iter.hasNext();) {
String consoleName=iter.next();
if (consoleName!=null) {
Tool consoleTool=ToolsCore.getContextManager().findTool(consoleName);
if (tool!=null) sessionList.add(consoleTool);
}
}
}
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE))
System.out.println("Found "+sessionList.size()+" console sessions for this tool "+tool.getName());
if (sessionList.size()>0){
for(Iterator<Tool> iter = sessionList.iterator(); iter.hasNext();) {
Tool consoleTool=iter.next();
consoleTool.setOpenState(targetString);
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_TOOL_SEQUENCE))
System.out.println("Set openState of "+consoleTool.getName()+" to "+targetString);
}
}
/*
public String getOpenState() { return openState; }
public void setOpenState(String stateName) { openState=stateName;}
*/
return true;
}
public String getSelectedStateFile(Tool tool, boolean select){
String [] filter=splitResultName(tool);
String linkString=tool.getResultName();
if (filter==null) return null;
String stateDirString=tool.getStateDir();
IProject project = SelectedResourceManager.getDefault().getSelectedProject(); // should not be null when we got here
IFolder stateDir= project.getFolder((stateDirString==null)?"":stateDirString);
if (!select){
if (linkString==null) {
MessageUI.error("Saved data for tool "+tool.getName()+" is not specified");
return null;
}
IFile link= stateDir.getFile(linkString);
if (!link.exists()) {
MessageUI.error("Saved data for tool "+tool.getName()+": "+ link.getLocation().toOSString()+" does not exist.");
return null;
}
String targetString=link.getRawLocation().makeRelativeTo(stateDir.getRawLocation()).toString();
IFile target=stateDir.getFile(targetString);
if (!target.exists()){
MessageUI.error("Saved data for tool "+tool.getName()+": "+targetString+", pointed by link "+
link.getLocation().toOSString()+" does not exist.");
return null;
}
return targetString;
}
FilteredFileSelector selector= new FilteredFileSelector(
stateDir.getLocation().toFile() , //File dir,
"Select snapshot file for "+tool.getName(), //String title,
null, // Component parent, or convert from SHell VerilogPlugin.getActiveWorkbenchShell()
"Select", //String approveText,
"Select snapshot file to restore", //String approveToolTip,
filter[0]+ToolLogFile.BUILD_STAMP_SEPARATOR,
filter[1],
false, // allow empty middle
"Matchig log files for "+tool.getName(), //String filterDescription,
false //boolean allowDirs
);
File result=selector.openDialog();
if (result == null) {
if (VerilogPlugin.getPreferenceBoolean(PreferenceStrings.DEBUG_OTHER))
System.out.println("Selection canceled");
return null;
}
return result.getName();
}
public static String[] splitResultName(Tool tool){
String linkString=tool.getResultName();
if (linkString==null) return null;
int index=linkString.lastIndexOf(".");
String [] result={
((index>=0)?linkString.substring(0,index):linkString),
((index>=0)?linkString.substring(index):"")
};
return result;
}
}
...@@ -19,6 +19,7 @@ package com.elphel.vdt.core.tools.params.recognizers; ...@@ -19,6 +19,7 @@ package com.elphel.vdt.core.tools.params.recognizers;
import com.elphel.vdt.core.Utils; import com.elphel.vdt.core.Utils;
import com.elphel.vdt.core.tools.generators.*; import com.elphel.vdt.core.tools.generators.*;
import com.elphel.vdt.core.tools.params.Tool;
public class SimpleGeneratorRecognizer implements Recognizer { public class SimpleGeneratorRecognizer implements Recognizer {
...@@ -35,7 +36,9 @@ public class SimpleGeneratorRecognizer implements Recognizer { ...@@ -35,7 +36,9 @@ public class SimpleGeneratorRecognizer implements Recognizer {
new CurrentFileBaseGenerator(), new CurrentFileBaseGenerator(),
new ChosenActionGenerator(), new ChosenActionGenerator(),
new BuildStampGenerator(), new BuildStampGenerator(),
new UserNameGenerator() new UserNameGenerator(),
new StateDirGenerator(),
new StateFileGenerator()
}; };
public SimpleGeneratorRecognizer(){ public SimpleGeneratorRecognizer(){
...@@ -46,6 +49,19 @@ public class SimpleGeneratorRecognizer implements Recognizer { ...@@ -46,6 +49,19 @@ public class SimpleGeneratorRecognizer implements Recognizer {
for (int i=0;i<generators.length;i++){ for (int i=0;i<generators.length;i++){
generators[i].setMenuMode(menuMode); generators[i].setMenuMode(menuMode);
} }
}
public SimpleGeneratorRecognizer(boolean menuMode, Tool tool){
super();
for (int i=0;i<generators.length;i++){
generators[i].setMenuMode(menuMode);
generators[i].setTool(tool);
}
}
public SimpleGeneratorRecognizer(Tool tool){
super();
for (int i=0;i<generators.length;i++){
generators[i].setTool(tool);
}
} }
public RecognizerResult recognize(String template, int startPos) { public RecognizerResult recognize(String template, int startPos) {
RecognizerResult result = new RecognizerResult(); RecognizerResult result = new RecognizerResult();
......
...@@ -37,9 +37,10 @@ public class ToolParamRecognizer extends ParamRecognizer { ...@@ -37,9 +37,10 @@ public class ToolParamRecognizer extends ParamRecognizer {
protected AbstractGenerator getGenerator(final Parameter param) throws ToolException { protected AbstractGenerator getGenerator(final Parameter param) throws ToolException {
return new StringsGenerator(param.getCommandLine()) { return new StringsGenerator(param.getCommandLine()) {
String toolName=(tool==null)?"<null>":tool.getName();
public String getName() { public String getName() {
return "Param '" + param + return "Param '" + param +
"' of tool '" + tool.getName() + "' of tool '" + toolName +
"' command line"; "' command line";
} }
}; };
......
...@@ -75,6 +75,12 @@ public class VDTPluginImages { ...@@ -75,6 +75,12 @@ public class VDTPluginImages {
public static final ImageDescriptor DESC_PROJECT_PROPERTIES = create(ICONS_PATH, "obj16"+File.separator+"project_prop.gif", null); public static final ImageDescriptor DESC_PROJECT_PROPERTIES = create(ICONS_PATH, "obj16"+File.separator+"project_prop.gif", null);
public static final ImageDescriptor DESC_DESIGM_MENU = create(ICONS_PATH, "obj16"+File.separator+"design_menu.gif", null); public static final ImageDescriptor DESC_DESIGM_MENU = create(ICONS_PATH, "obj16"+File.separator+"design_menu.gif", null);
public static final ImageDescriptor DESC_TOOLS_LINKED = create(ICONS_PATH, "obj16"+File.separator+"link.png", null);
public static final ImageDescriptor DESC_TOOLS_UNLINKED = create(ICONS_PATH, "obj16"+File.separator+"broken_link.png", null);
public static final ImageDescriptor DESC_TOOLS_PIN = create(ICONS_PATH, "obj16"+File.separator+"pin.png", null);
public static final ImageDescriptor DESC_TOOLS_RESTORE = create(ICONS_PATH, "obj16"+File.separator+"restore.png", null);
public static final ImageDescriptor DESC_TOOLS_RESTORE_SELECT = create(ICONS_PATH, "obj16"+File.separator+"restore_select.png", null);
public static final String ICON_TOOLSTATE_NEW = "obj16"+File.separator+"white.png"; public static final String ICON_TOOLSTATE_NEW = "obj16"+File.separator+"white.png";
public static final String ICON_TOOLSTATE_BAD = "obj16"+File.separator+"cross.png"; public static final String ICON_TOOLSTATE_BAD = "obj16"+File.separator+"cross.png";
...@@ -86,6 +92,7 @@ public class VDTPluginImages { ...@@ -86,6 +92,7 @@ public class VDTPluginImages {
public static final String ICON_TOOLSTATE_RUNNING = "obj16"+File.separator+"spinning.gif"; public static final String ICON_TOOLSTATE_RUNNING = "obj16"+File.separator+"spinning.gif";
// public static final String ICON_TOOLSTATE_KEPT_OPEN= "obj16"+File.separator+"heart.gif"; // public static final String ICON_TOOLSTATE_KEPT_OPEN= "obj16"+File.separator+"heart.gif";
public static final String ICON_TOOLSTATE_KEPT_OPEN= "obj16"+File.separator+"beat.gif"; public static final String ICON_TOOLSTATE_KEPT_OPEN= "obj16"+File.separator+"beat.gif";
public static final String ICON_TOOLSTATE_PINNED = "obj16"+File.separator+"pinned_good.png";
public static final String KEY_TOOLSTATE_NEW = "TOOLSTATE_NEW"; public static final String KEY_TOOLSTATE_NEW = "TOOLSTATE_NEW";
public static final String KEY_TOOLSTATE_BAD = "TOOLSTATE_BAD"; public static final String KEY_TOOLSTATE_BAD = "TOOLSTATE_BAD";
...@@ -96,6 +103,7 @@ public class VDTPluginImages { ...@@ -96,6 +103,7 @@ public class VDTPluginImages {
public static final String KEY_TOOLSTATE_WTF_OLD = "TOOLSTATE_WTF_OLD"; public static final String KEY_TOOLSTATE_WTF_OLD = "TOOLSTATE_WTF_OLD";
public static final String KEY_TOOLSTATE_RUNNING = "TOOLSTATE_RUNNING"; public static final String KEY_TOOLSTATE_RUNNING = "TOOLSTATE_RUNNING";
public static final String KEY_TOOLSTATE_KEPT_OPEN ="TOOLSTATE_KEPT_OPEN"; public static final String KEY_TOOLSTATE_KEPT_OPEN ="TOOLSTATE_KEPT_OPEN";
public static final String KEY_TOOLSTATE_PINNED = "TOOLSTATE_PINNED";
public static final String CHECKBOX_ON = "CHECKBOX_ON"; public static final String CHECKBOX_ON = "CHECKBOX_ON";
......
...@@ -50,6 +50,28 @@ public class FilteredFileSelector{ ...@@ -50,6 +50,28 @@ public class FilteredFileSelector{
if (approveToolTip!=null) fileChooser.setApproveButtonToolTipText(approveToolTip); if (approveToolTip!=null) fileChooser.setApproveButtonToolTipText(approveToolTip);
fileChooser.setApproveButtonText(this.approveText); fileChooser.setApproveButtonText(this.approveText);
} }
public FilteredFileSelector(
File dir,
String title,
Component parent,
String approveText,
String approveToolTip,
String prefix,
String suffix,
boolean allowEmptyMiddle,
String filterDescription,
boolean allowDirs
){
this.parent=parent;
fileChooser = new JFileChooser(dir);
FileFilter filter1 = new PrefixSuffixFileFilter(prefix,suffix, allowEmptyMiddle,filterDescription,allowDirs);
fileChooser.setFileFilter(filter1);
if (title!=null) fileChooser.setDialogTitle(title);
this.approveText=approveText;
if (this.approveText==null) this.approveText="Select";
if (approveToolTip!=null) fileChooser.setApproveButtonToolTipText(approveToolTip);
fileChooser.setApproveButtonText(this.approveText);
}
public File openDialog() { public File openDialog() {
if (fileChooser.showDialog(parent, approveText) == JFileChooser.APPROVE_OPTION) { if (fileChooser.showDialog(parent, approveText) == JFileChooser.APPROVE_OPTION) {
...@@ -89,5 +111,42 @@ public class FilteredFileSelector{ ...@@ -89,5 +111,42 @@ public class FilteredFileSelector{
return description; return description;
} }
} }
private class PrefixSuffixFileFilter extends FileFilter {
private String prefix;
private String suffix;
private boolean allowEmptyMiddle;
private String description;
private boolean allowDirs;
public PrefixSuffixFileFilter(
String prefix,
String suffix,
boolean allowEmptyMiddle,
String description,
boolean allowDirs){
this.prefix=prefix;
this.suffix=suffix;
this.allowEmptyMiddle=allowEmptyMiddle;
this.description=description;
this.allowDirs=allowDirs;
this.allowEmptyMiddle=allowEmptyMiddle;
}
@Override
public boolean accept(File file) {
if (file.isDirectory()) {
return allowDirs;
} else {
String name = file.getName();
// System.out.println("filename="+name+", matches()="+pattern.matcher(name).matches());
if (!name.startsWith(prefix)) return false;
if (!name.endsWith(suffix)) return false;
if (allowEmptyMiddle || (name.length()> (prefix.length()+suffix.length()))) return true;
return false;
}
}
@Override
public String getDescription() {
return description;
}
}
} }
...@@ -23,6 +23,8 @@ import java.util.Stack; ...@@ -23,6 +23,8 @@ import java.util.Stack;
import com.elphel.vdt.VerilogUtils; import com.elphel.vdt.VerilogUtils;
import com.elphel.vdt.core.tools.params.Tool; import com.elphel.vdt.core.tools.params.Tool;
import com.elphel.vdt.veditor.VerilogPlugin;
import com.elphel.vdt.veditor.preference.PreferenceStrings;
import org.eclipse.core.resources.IContainer; import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IFile;
...@@ -73,6 +75,8 @@ public class SelectedResourceManager implements IWindowListener, ISelectionListe ...@@ -73,6 +75,8 @@ public class SelectedResourceManager implements IWindowListener, ISelectionListe
// private long timestamp=0; // private long timestamp=0;
private String timestamp; private String timestamp;
private String ignoreFilter=null; private String ignoreFilter=null;
private boolean toolsLinked=true;
// private Tool selectedTool=null; // last selected tool // private Tool selectedTool=null; // last selected tool
// //
private SelectedResourceManager() { private SelectedResourceManager() {
...@@ -106,6 +110,13 @@ public class SelectedResourceManager implements IWindowListener, ISelectionListe ...@@ -106,6 +110,13 @@ public class SelectedResourceManager implements IWindowListener, ISelectionListe
} }
} }
public void setToolsLinked(boolean linked){
this.toolsLinked=linked;
}
public boolean isToolsLinked(){
return toolsLinked;
}
/** /**
* @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow) * @see org.eclipse.ui.IWindowListener#windowActivated(org.eclipse.ui.IWorkbenchWindow)
*/ */
......
...@@ -49,6 +49,7 @@ import com.elphel.vdt.core.tools.menu.DesignMenuItem; ...@@ -49,6 +49,7 @@ import com.elphel.vdt.core.tools.menu.DesignMenuItem;
import com.elphel.vdt.core.tools.menu.DesignMenuToolItem; import com.elphel.vdt.core.tools.menu.DesignMenuToolItem;
import com.elphel.vdt.core.tools.params.Tool; import com.elphel.vdt.core.tools.params.Tool;
import com.elphel.vdt.ui.VDTPluginImages; import com.elphel.vdt.ui.VDTPluginImages;
import com.elphel.vdt.ui.variables.SelectedResourceManager;
/** /**
* Adapter of core design menu for user interface level. * Adapter of core design menu for user interface level.
...@@ -302,6 +303,7 @@ public class DesignMenuModel { ...@@ -302,6 +303,7 @@ public class DesignMenuModel {
public void measureItem (Event event){ public void measureItem (Event event){
super.measureItem (event); super.measureItem (event);
boolean dirty=tool.isDirty(); boolean dirty=tool.isDirty();
boolean pinned=tool.isPinned() || !SelectedResourceManager.getDefault().isToolsLinked();
String iconName,key; String iconName,key;
if (tool.isRunning()){ if (tool.isRunning()){
iconName=VDTPluginImages.ICON_TOOLSTATE_RUNNING; iconName=VDTPluginImages.ICON_TOOLSTATE_RUNNING;
...@@ -323,12 +325,17 @@ public class DesignMenuModel { ...@@ -323,12 +325,17 @@ public class DesignMenuModel {
} }
break; break;
case SUCCESS: case SUCCESS:
if (dirty){ if (pinned){
iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD_OLD; iconName=VDTPluginImages.ICON_TOOLSTATE_PINNED;
key= VDTPluginImages.KEY_TOOLSTATE_GOOD_OLD; key= VDTPluginImages.KEY_TOOLSTATE_PINNED;
} else { } else {
iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD; if (dirty){
key= VDTPluginImages.KEY_TOOLSTATE_GOOD; iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD_OLD;
key= VDTPluginImages.KEY_TOOLSTATE_GOOD_OLD;
} else {
iconName=VDTPluginImages.ICON_TOOLSTATE_GOOD;
key= VDTPluginImages.KEY_TOOLSTATE_GOOD;
}
} }
break; break;
case KEPT_OPEN: case KEPT_OPEN:
......
...@@ -70,6 +70,17 @@ ...@@ -70,6 +70,17 @@
label="Testing some VDT features" label="Testing some VDT features"
icon="sample.gif" icon="sample.gif"
call="VDTTest"/> call="VDTTest"/>
<!--
<menuitem name="Test VDT-A"
label="Testing some VDT features"
icon="sample.gif"
tool-instance="VDTTest_inst2"
call="VDTTest"/>
-->
<menuitem name="Test VDT1"
label="Testing some VDT features - variant 1"
icon="sample.gif"
call="VDTTest1"/>
</menu> </menu>
......
...@@ -110,6 +110,9 @@ ...@@ -110,6 +110,9 @@
<parameter id="VivadoLocalDir" label="Local Xilinx directory" tooltip="Local project subdirectroy for Xilinx Vivado generated files" <parameter id="VivadoLocalDir" label="Local Xilinx directory" tooltip="Local project subdirectroy for Xilinx Vivado generated files"
type="Pathname" default="vivado" format="CopyValue" readonly="false" /> type="Pathname" default="vivado" format="CopyValue" readonly="false" />
<parameter id="VivadoLogDir" label="Local Vivado tool logsx directory" tooltip="Local project subdirectroy for Xilinx Vivado tools log files"
type="Pathname" default="vivado_logs" format="CopyValue" readonly="false" />
<parameter id="VivadoIgnoreSource" label="Ignore source files" tooltip="Pattern to ignore source files that match this regular expression" <parameter id="VivadoIgnoreSource" label="Ignore source files" tooltip="Pattern to ignore source files that match this regular expression"
type="String" default=".*unisims.*" format="CopyValue" readonly="false" /> type="String" default=".*unisims.*" format="CopyValue" readonly="false" />
<!-- Calculated --> <!-- Calculated -->
...@@ -119,22 +122,40 @@ ...@@ -119,22 +122,40 @@
<parameter id="SnapshotSynth" <parameter id="SnapshotSynth"
label="Synthesis snapshot" tooltip="Name of Vivado snapshot archive after synthesis" label="Synthesis snapshot" tooltip="Name of Vivado snapshot archive after synthesis"
default="%%ProjectName-synth.dcp" default="%%ProjectName-synth.dcp"
type="String" format="CopyValue" /> type="Filename" format="CopyValue" />
<parameter id="SnapshotOptPlace" <parameter id="SnapshotOptPlace"
label="Placement snapshot" tooltip="Name of Vivado snapshot archive after optimization/placement" label="Placement snapshot" tooltip="Name of Vivado snapshot archive after optimization/placement"
default="%%ProjectName-opt-pace.dcp" default="%%ProjectName-opt-place.dcp"
type="String" format="CopyValue" /> type="Filename" format="CopyValue" />
<parameter id="SnapshotRoute" <parameter id="SnapshotRoute"
label="Routing snapshot" tooltip="Name of Vivado snapshot archive after routing" label="Routing snapshot" tooltip="Name of Vivado snapshot archive after routing"
default="%%ProjectName-route.dcp" default="%%ProjectName-route.dcp"
type="String" format="CopyValue" /> type="Filename" format="CopyValue" />
"" <!-- same as in project --> <parameter id="DisableVivadoSynth"
label="Disable Vivado synthesis" tooltip="Disable tool Vivado Synthesis"
default="false"
type="Boolean" format="None" />
<parameter id="DisableVivadoOptPlace"
label="Disable Vivado opt/place" tooltip="Disable tool Vivado Optimize and Place"
default="false"
type="Boolean" format="None" />
<parameter id="DisableVivadoRoute"
label="Disable Vivado route" tooltip="Disable tool Vivado route"
default="false"
type="Boolean" format="None" />
<parameter id="DisableVivadoBitsteam"
label="Disable Vivado bitstream" tooltip="Disable tool Vivado bitstream generator"
default="false"
type="Boolean" format="None" />
"" <!-- same as in project -->
<!-- Invisible (calculated) project-wide parameters --> <!-- Invisible (calculated) project-wide parameters -->
<parameter id="SimulDirSlash" type="Pathname" visible="false" <parameter id="SimulDirSlash" type="Pathname" visible="false"
...@@ -155,9 +176,16 @@ ...@@ -155,9 +176,16 @@
"part" "part"
"VivadoProjectRoot" "VivadoProjectRoot"
"VivadoLocalDir" "VivadoLocalDir"
"VivadoLogDir"
"VivadoIgnoreSource" "VivadoIgnoreSource"
"SedPaths" "SedPaths"
</group> </group>
<group name="VivadoDisable" label="Selectively disable Vivado tools">
"DisableVivadoSynth"
"DisableVivadoOptPlace"
"DisableVivadoRoute"
"DisableVivadoBitsteam"
</group>
<!-- TODO: make time-stamped and "latest" for snapshots --> <!-- TODO: make time-stamped and "latest" for snapshots -->
<group name="VivadoSnapshots" label="Vivado snapshot archive names"> <group name="VivadoSnapshots" label="Vivado snapshot archive names">
"SnapshotSynth" "SnapshotSynth"
......
...@@ -10,12 +10,13 @@ ...@@ -10,12 +10,13 @@
package="FPGA_package" package="FPGA_package"
shell="/bin/bash" shell="/bin/bash"
description="Generate bitstream" description="Generate bitstream"
log-dir="vivado_logs"> log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
disable="DisableVivadoBitsteam"
>
<action-menu> <action-menu>
<action label="Generate bitstream" resource="" icon="bitstream.png" /> <action label="Generate bitstream" resource="" icon="bitstream.png" />
</action-menu> </action-menu>
<parameter id="FromMemory" label="Run from memory" tooltip="Do not load snapshot created after routing"
default="false" type= "Boolean" format="None"/>
<parameter id="SkipPreBitstream" label="Skip pre-bitstream" tooltip="Do not run pre bitstream TCL commands" <parameter id="SkipPreBitstream" label="Skip pre-bitstream" tooltip="Do not run pre bitstream TCL commands"
default="false" type= "Boolean" format="None"/> default="false" type= "Boolean" format="None"/>
<!-- left from synthesis, may need update--> <!-- left from synthesis, may need update-->
...@@ -111,7 +112,6 @@ ...@@ -111,7 +112,6 @@
<input> <input>
<group name="General"> <group name="General">
"FromMemory"
"SkipPreBitstream" "SkipPreBitstream"
"ShowWarnings" "ShowWarnings"
"ShowInfo" "ShowInfo"
...@@ -156,36 +156,17 @@ ...@@ -156,36 +156,17 @@
<output> <output>
<!-- mkdir -p vdt/npmtest--> <!-- mkdir -p vdt/npmtest-->
<!-- Now skipping completely pre_opt copying - maybe some will still be needed (custom tcl scripts), then move conditional inside block --> <!-- Now skipping completely pre_opt copying - maybe some will still be needed (custom tcl scripts), then move conditional inside block -->
<if FromMemory = "false"> <if-not reference_bitfile="">
<line name="vivado_copy_pre_opt"> <line name="vivado_copy_pre_opt">
"-c" "-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after opt/place from local to remote -->
"rsync -avrR -e ssh" "rsync -avrR -e ssh"
<!-- from: --> <!-- from: (trying full name) -->
"%VivadoLocalDir/%SnapshotOptPlace" "%reference_bitfile"
<!-- to: --> <!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot" "%RemoteUser@%RemoteHost:%VivadoProjectRoot/build"
";" ";"
<!-- Copy bitstream reference file (full name) reference_bitfile -->
<if-not reference_bitfile="">
"rsync -avrR -e ssh"
<!-- from: (trying full name) -->
<!-- "%VivadoLocalDir/%SnapshotOptPlace" -->
"%reference_bitfile"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot/build"
";"
</if-not>
</line> </line>
</if> </if-not>
<!-- Set sep="", so all new lines should be specified as \n --> <!-- Set sep="", so all new lines should be specified as \n -->
<line name="vivado_run_bitstream" <line name="vivado_run_bitstream"
dest="VivadoConsole" dest="VivadoConsole"
...@@ -198,10 +179,6 @@ ...@@ -198,10 +179,6 @@
"cd ~/%VivadoProjectRoot\n" "cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n" "set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n" "file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
<if FromMemory = "false">
"open_checkpoint %SnapshotRoute\n"
</if>
<!-- Run pre-bitstream TCL commands (if specified) --> <!-- Run pre-bitstream TCL commands (if specified) -->
<if SkipPreBitstream="false"> <if SkipPreBitstream="false">
<if-not PreBitstreamTCL=""> <if-not PreBitstreamTCL="">
......
...@@ -54,12 +54,15 @@ ...@@ -54,12 +54,15 @@
package="FPGA_package" package="FPGA_package"
shell="/bin/bash" shell="/bin/bash"
description="Vivado optimize, power optimize, place and physical optimize design" description="Vivado optimize, power optimize, place and physical optimize design"
log-dir="vivado_logs"> result="SnapshotOptPlace"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
restore="RestoreVivadoOptPlace"
disable="DisableVivadoOptPlace"
>
<action-menu> <action-menu>
<action label="Optimize and Place" resource="" icon="mondrian2x2.png" /> <action label="Optimize and Place" resource="" icon="mondrian2x2.png" />
</action-menu> </action-menu>
<parameter id="FromMemory" label="Run from memory" tooltip="Do not load snapshot created after synthesis"
default="false" type= "Boolean" format="None"/>
<parameter id="SkipPreOptimization" label="Skip pre-optimization" tooltip="Do not run pre optimization TCL commands" <parameter id="SkipPreOptimization" label="Skip pre-optimization" tooltip="Do not run pre optimization TCL commands"
default="false" type= "Boolean" format="None"/> default="false" type= "Boolean" format="None"/>
<parameter id="SkipOptimization" label="Skip optimize" tooltip="Do not run opt_design" <parameter id="SkipOptimization" label="Skip optimize" tooltip="Do not run opt_design"
...@@ -211,7 +214,6 @@ ...@@ -211,7 +214,6 @@
<input> <input>
<group name="General"> <group name="General">
"FromMemory"
"SkipPreOptimization" "SkipPreOptimization"
"SkipOptimization" "SkipOptimization"
"SkipPowerOptimization" "SkipPowerOptimization"
...@@ -294,28 +296,6 @@ ...@@ -294,28 +296,6 @@
</input> </input>
<output> <output>
<!-- mkdir -p vdt/npmtest-->
<!-- Now skipping completely pre_opt copying - maybe some will still be needed (custom tcl scripts), then move conditional inside block -->
<if FromMemory = "false">
<line name="vivado_copy_pre_opt">
"-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after synthesis from local to remote -->
"rsync -avrR -e ssh"
<!-- from: -->
"%VivadoLocalDir/%SnapshotSynth"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot"
";"
</line>
</if>
<!-- Combining optimization and placement TCL commands in a single command block <!-- Combining optimization and placement TCL commands in a single command block
May need to split if they will need different error parsers (external and/or Eclipse patterns) --> May need to split if they will need different error parsers (external and/or Eclipse patterns) -->
<!-- Set sep="", so all new lines should be specified as \n --> <!-- Set sep="", so all new lines should be specified as \n -->
...@@ -330,10 +310,6 @@ ...@@ -330,10 +310,6 @@
"cd ~/%VivadoProjectRoot\n" "cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n" "set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n" "file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
<if FromMemory = "false">
"open_checkpoint %SnapshotSynth\n"
</if>
<!-- Run pre-optimization TCL commands (if specified) --> <!-- Run pre-optimization TCL commands (if specified) -->
<if SkipPreOptimization="false"> <if SkipPreOptimization="false">
<if-not PreOptTCL=""> <if-not PreOptTCL="">
...@@ -398,7 +374,7 @@ ...@@ -398,7 +374,7 @@
"\n" "\n"
</if> </if>
<if SkipSnapshotPlace="false"> <if SkipSnapshotPlace="false">
"write_checkpoint -force %SnapshotOptPlace\n" "write_checkpoint -force %%StateFile\n"
</if> </if>
"puts \"@@FINISH@@\"\n" "puts \"@@FINISH@@\"\n"
</line> </line>
...@@ -409,8 +385,8 @@ ...@@ -409,8 +385,8 @@
"-c" "-c"
"mkdir -p %VivadoLocalDir ;" "mkdir -p %VivadoLocalDir ;"
"rsync -avr -e ssh" "rsync -avr -e ssh"
"%RemoteUser@%RemoteHost:%VivadoProjectRoot/%SnapshotOptPlace" "%RemoteUser@%RemoteHost:%VivadoProjectRoot/%%StateFile"
"%VivadoLocalDir/" "%%StateDir/"
</line> </line>
</if-and> </if-and>
<line name="parser_VivadoOpt" <line name="parser_VivadoOpt"
...@@ -439,5 +415,53 @@ ...@@ -439,5 +415,53 @@
</line> </line>
</output> </output>
</tool> </tool>
<tool name="RestoreVivadoOptPlace" label="Restore state after Vivado OptPlace"
project="FPGA_project"
interface="VivadoOptPlaceInterface"
package="FPGA_package"
shell="/bin/bash"
ignore="%VivadoIgnoreSource"
description="Restore Vivado OptPlace"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
>
<output>
<line name="vivado_pre_restore_opt_place">
"-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after opt/place from local to remote -->
"rsync -avrR -e ssh"
<!-- from: -->
"%VivadoLocalDir/%%StateFile"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot"
";"
</line>
<!-- success="phys_opt_design completed successfully" -->
<line name="vivado_restore_synthesis"
dest="VivadoConsole"
mark="``"
sep=""
failure="ERROR"
prompt="@@FINISH@@"
log="">
"cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
"open_checkpoint %%StateFile\n"
"puts \"@@FINISH@@\"\n"
</line>
</output>
</tool>
</vdt-project> </vdt-project>
...@@ -22,12 +22,15 @@ ...@@ -22,12 +22,15 @@
package="FPGA_package" package="FPGA_package"
shell="/bin/bash" shell="/bin/bash"
description="Route design with Vivado" description="Route design with Vivado"
log-dir="vivado_logs"> result="SnapshotRoute"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
restore="RestoreVivadoRoute"
disable="DisableVivadoRoute"
>
<action-menu> <action-menu>
<action label="Route" resource="" icon="route66.png" /> <action label="Route" resource="" icon="route66.png" />
</action-menu> </action-menu>
<parameter id="FromMemory" label="Run from memory" tooltip="Do not load snapshot created after placement"
default="false" type= "Boolean" format="None"/>
<parameter id="SkipPreRoute" label="Skip pre-route" tooltip="Do not run pre route TCL commands" <parameter id="SkipPreRoute" label="Skip pre-route" tooltip="Do not run pre route TCL commands"
default="false" type= "Boolean" format="None"/> default="false" type= "Boolean" format="None"/>
<parameter id="SkipSnapshotRoute" label="Skip snapshot save" tooltip="Do not create snapshot after route" <parameter id="SkipSnapshotRoute" label="Skip snapshot save" tooltip="Do not create snapshot after route"
...@@ -136,7 +139,6 @@ ...@@ -136,7 +139,6 @@
<input> <input>
<group name="General"> <group name="General">
"FromMemory"
"SkipPreRoute" "SkipPreRoute"
"SkipSnapshotRoute" "SkipSnapshotRoute"
"SnapshotRoute" <!-- same as in project --> "SnapshotRoute" <!-- same as in project -->
...@@ -187,28 +189,6 @@ ...@@ -187,28 +189,6 @@
</input> </input>
<output> <output>
<!-- mkdir -p vdt/npmtest-->
<!-- Now skipping completely pre_opt copying - maybe some will still be needed (custom tcl scripts), then move conditional inside block -->
<if FromMemory = "false">
<line name="vivado_copy_pre_opt">
"-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after opt/place from local to remote -->
"rsync -avrR -e ssh"
<!-- from: -->
"%VivadoLocalDir/%SnapshotOptPlace"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot"
";"
</line>
</if>
<!-- Set sep="", so all new lines should be specified as \n --> <!-- Set sep="", so all new lines should be specified as \n -->
<line name="vivado_run_route" <line name="vivado_run_route"
dest="VivadoConsole" dest="VivadoConsole"
...@@ -221,10 +201,6 @@ ...@@ -221,10 +201,6 @@
"cd ~/%VivadoProjectRoot\n" "cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n" "set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n" "file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
<if FromMemory = "false">
"open_checkpoint %SnapshotOptPlace\n"
</if>
<!-- Run pre-route TCL commands (if specified) --> <!-- Run pre-route TCL commands (if specified) -->
<if SkipPreRoute="false"> <if SkipPreRoute="false">
<if-not PreRouteTCL=""> <if-not PreRouteTCL="">
...@@ -295,4 +271,50 @@ ...@@ -295,4 +271,50 @@
</line> </line>
</output> </output>
</tool> </tool>
<tool name="RestoreVivadoRoute" label="Restore state after Vivado Route"
project="FPGA_project"
interface="VivadoRouteInterface"
package="FPGA_package"
shell="/bin/bash"
ignore="%VivadoIgnoreSource"
description="Restore Vivado Routing"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
>
<output>
<line name="vivado_pre_restore_route">
"-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after route from local to remote -->
"rsync -avrR -e ssh"
<!-- from: -->
"%VivadoLocalDir/%%StateFile"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot"
";"
</line>
<!-- success="phys_opt_design completed successfully" -->
<line name="vivado_restore_route"
dest="VivadoConsole"
mark="``"
sep=""
failure="ERROR"
prompt="@@FINISH@@"
log="">
"cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
"open_checkpoint %%StateFile\n"
"puts \"@@FINISH@@\"\n"
</line>
</output>
</tool>
</vdt-project> </vdt-project>
...@@ -56,7 +56,12 @@ ...@@ -56,7 +56,12 @@
shell="/bin/bash" shell="/bin/bash"
ignore="%VivadoIgnoreSource" ignore="%VivadoIgnoreSource"
description="Vivado Synthesis" description="Vivado Synthesis"
log-dir="vivado_logs"> result="SnapshotSynth"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
restore="RestoreVivadoSynthesis"
disable="DisableVivadoSynth"
>
<extensions-list> <extensions-list>
<extension mask="v" /> <extension mask="v" />
...@@ -305,7 +310,8 @@ ...@@ -305,7 +310,8 @@
"\n" "\n"
<if-and SkipSnapshotSynth="false" <if-and SkipSnapshotSynth="false"
VivadoSynthActionIndex="0"> VivadoSynthActionIndex="0">
"write_checkpoint -force %SnapshotSynth\n" <!-- "write_checkpoint -force %SnapshotSynth\n" -->
"write_checkpoint -force %%StateFile\n"
</if-and> </if-and>
"puts \"@@FINISH@@\"\n" "puts \"@@FINISH@@\"\n"
</line> </line>
...@@ -316,8 +322,10 @@ ...@@ -316,8 +322,10 @@
"-c" "-c"
"mkdir -p %VivadoLocalDir ;" "mkdir -p %VivadoLocalDir ;"
"rsync -avr -e ssh" "rsync -avr -e ssh"
"%RemoteUser@%RemoteHost:%VivadoProjectRoot/%SnapshotSynth" <!-- "%RemoteUser@%RemoteHost:%VivadoProjectRoot/%SnapshotSynth"
"%VivadoLocalDir/" "%VivadoLocalDir/" -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot/%%StateFile"
"%%StateDir/"
</line> </line>
</if-and> </if-and>
<!-- errors=".*[ERROR|CRITICAL WARNING]: (\[.*\].*)\[(.*):([0-9]+)\]" <!-- errors=".*[ERROR|CRITICAL WARNING]: (\[.*\].*)\[(.*):([0-9]+)\]"
...@@ -347,8 +355,50 @@ ...@@ -347,8 +355,50 @@
</line> </line>
</output> </output>
</tool> </tool>
<!-- sed 's@^[^\[]*\[[^\[]*$@&\[Synthesis:0000\]@' <tool name="RestoreVivadoSynthesis" label="Restore state after Vivado Synthesis"
sed -u 's@^[^\[]*\[[^\[]*$@&amp;\[Synthesis:0000\]@' project="FPGA_project"
interface="VivadoSynthesisInterface"
--> package="FPGA_package"
shell="/bin/bash"
ignore="%VivadoIgnoreSource"
description="Restore Vivado Synthesis"
log-dir="VivadoLogDir"
state-dir="VivadoLocalDir"
>
<output>
<line name="vivado_pre_restore_synthesis">
"-c"
<!-- Create project directory on remote server if it did not exist -->
"ssh"
"-oBatchMode=yes"
"-l %RemoteUser %RemoteHost"
"'"
"mkdir -p"
"%VivadoProjectRoot"
"' ;"
<!-- Copy snapshot generated after synthesis from local to remote -->
"rsync -avrR -e ssh"
<!-- from: -->
"%VivadoLocalDir/%%StateFile"
<!-- to: -->
"%RemoteUser@%RemoteHost:%VivadoProjectRoot"
";"
</line>
<!-- success="phys_opt_design completed successfully" -->
<line name="vivado_restore_synthesis"
dest="VivadoConsole"
mark="``"
sep=""
failure="ERROR"
prompt="@@FINISH@@"
log="">
"cd ~/%VivadoProjectRoot\n"
"set outputDir ~/%VivadoProjectRoot/build\n"
"file mkdir $outputDir\n"
<!-- Start fresh from the loaded checkpoint -->
"open_checkpoint %%StateFile\n"
"puts \"@@FINISH@@\"\n"
</line>
</output>
</tool>
</vdt-project> </vdt-project>
...@@ -32,10 +32,9 @@ ...@@ -32,10 +32,9 @@
<parameter id="command1Contents" label="Command1 contents" default="@@%command1" <parameter id="command1Contents" label="Command1 contents" default="@@%command1"
type="Stringlist" format="ProgramSyntax" visible="true" readonly="false" /> type="Stringlist" format="ProgramSyntax" visible="true" readonly="false" />
<parameter id="command2Contents" label="Command2 contents" default="@@%command2" <parameter id="command2Contents" label="Command2 contents" default="@@%command2"
type="String" format="CopyValue" visible="true" readonly="false" /> type="String" format="CopyValue" visible="true" readonly="false" />
<input> <input>
<group name="General"> <group name="General">
"file1" "file1"
...@@ -52,6 +51,7 @@ ...@@ -52,6 +51,7 @@
<output> <output>
<line name="test"> <line name="test">
"-c" "-c"
"echo \"ProjectName=%%ProjectName\";"
"echo \"file1=%file1\";" "echo \"file1=%file1\";"
"echo \"file2=%file2\";" "echo \"file2=%file2\";"
"echo \"command1=%command1\";" "echo \"command1=%command1\";"
...@@ -63,4 +63,31 @@ ...@@ -63,4 +63,31 @@
</line> </line>
</output> </output>
</tool> </tool>
<tool name="VDTTest1"
inherits="VDTTest"
shell="/bin/bash"
label="VDT Test1"
interface="VDTTestInterface"
description="Testing VDT features - variant 1">
<action-menu>
<action label="Test VDT - variant 1" resource="" icon="route66.png" />
</action-menu>
<!-- all calculated parameters that depend on this tool parameters should also be here, not in the base tool-->
<parameter id="command1" label="Command1 (for list)" default=""
type="String" format="CopyValue" visible="true" readonly="false" />
<parameter id="command2" label="Command2 (for single)" default=""
type="String" format="CopyValue" visible="true" readonly="false" />
<parameter id="file1Contents" label="File1 contents" default="@%file1"
type="Stringlist" format="ProgramSyntax" visible="true" readonly="false" />
<parameter id="file2Contents" label="File2 contents" default="@%file2"
type="String" format="CopyValue" visible="true" readonly="false" />
<parameter id="command1Contents" label="Command1 contents" default="@@%command1"
type="Stringlist" format="ProgramSyntax" visible="true" readonly="false" />
<parameter id="command2Contents" label="Command2 contents" default="@@%command2"
type="String" format="CopyValue" visible="true" readonly="false" />
</tool>
</vdt-project> </vdt-project>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment