2015-12-16 52 views
4

我正在尝试开发基于Xilinx ISE TCL外壳的基于Python的封装器xtclsh.exe。如果有效,我会添加对PlanAhead或Vivado等其他shell的支持...赛灵思TCL外壳在何处发射结果?

那么,什么是大局?我有一个VHDL源文件列表,它们构成了一个IP核。我想打开一个现有的ISE项目,搜索丢失的VHDL文件并在必要时添加它们。由于IP核具有重叠的文件依赖性,因此项目可能已经包含一些文件,所以我只查找丢失的文件。

带管道的示例用户Python 3.x和subprocess。启动xtclsh.exe并将命令逐行发送到shell。监控输出的结果。为了简化示例,我将STDERR重定向到STDOUT。虚拟输出POC_BOUNDARY被插入到命令流中,以指示完成的命令。

附加的示例代码可以通过设置示例ISE项目来测试,该项目有一些VHDL源文件。

我的问题是显示INFO,WARNING和ERROR消息,但脚本无法读取TCL命令的结果。

手动执行search *.vhdl -type file在xtclsh.exe结果:

% search *.vhdl -type file 
D:/git/PoC/src/common/config.vhdl 
D:/git/PoC/src/common/utils.vhdl 
D:/git/PoC/src/common/vectors.vhdl 

执行脚本的结果:

.... 
press ENTER for the next step 
sending 'search *.vhdl -type file' 
stdoutLine='POC_BOUNDARY 
' 
output consumed until boundary string 
.... 

问题:

  • 哪里xtclsh写?
  • 如何从TCL命令中读取结果?

BTW:提示符号%也没有给我的脚本可见。


Python代码重现行为:

import subprocess 

class XilinxTCLShellProcess(object): 
    # executable = "sortnet_BitonicSort_tb.exe" 
    executable = r"C:\Xilinx\14.7\ISE_DS\ISE\bin\nt64\xtclsh.exe" 
    boundarString = "POC_BOUNDARY" 
    boundarCommand = bytearray("puts {0}\n".format(boundarString), "ascii") 

    def create(self, arguments): 
    sysargs = [] 
    sysargs.append(self.executable) 

    self.proc = subprocess.Popen(sysargs, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
    self.sendBoundardCommand() 

    while(True): 
     stdoutLine = self.proc.stdout.readline().decode() 
     if (self.boundarString in stdoutLine): 
     break 
    print("found boundary string") 

    def terminate(self): 
    self.proc.terminate() 

    def sendBoundardCommand(self): 
    self.proc.stdin.write(self.boundarCommand) 
    self.proc.stdin.flush() 

    def sendCommand(self, line): 
    command = bytearray("{0}\n".format(line), "ascii") 
    self.proc.stdin.write(command) 
    self.sendBoundardCommand() 

    def sendLine(self, line): 
    self.sendCommand(line) 

    while(True): 
     stdoutLine = self.proc.stdout.readline().decode() 
     print("stdoutLine='{0}'".format(stdoutLine)) 
     if (stdoutLine == ""): 
     print("reached EOF in stdout") 
     break 
     elif ("vhdl" in stdoutLine): 
     print("found a file name") 
     elif (self.boundarString in stdoutLine): 
     print("output consumed until boundary string") 
     break 

def main(): 
    print("creating 'XilinxTCLShellProcess' instance") 
    xtcl = XilinxTCLShellProcess() 

    print("launching process") 
    arguments = [] 
    xtcl.create(arguments) 

    i = 1 
    while True: 
    print("press ENTER for the next step") 
    from msvcrt import getch 
    from time import sleep 
    sleep(0.1) # 0.1 seconds 

    key = ord(getch()) 
    if key == 27: # ESC 
     print("aborting") 
     print("sending 'exit'") 
     xtcl.sendLine("exit") 
     break 
    elif key == 13: # ENTER 
     if (i == 1): 
     #print("sending 'project new test.xise'") 
     #xtcl.sendLine("project new test.xise") 
     print("sending 'project open PoCTest.xise'") 
     xtcl.sendLine("project open PoCTest.xise") 
     i += 1 
     elif (i == 2): 
     print("sending 'lib_vhdl get PoC files'") 
     xtcl.sendLine("lib_vhdl get PoC files") 
     i += 1 
     elif (i == 3): 
     print("sending 'search *.vhdl -type file'") 
     xtcl.sendLine("search *.vhdl -type file") 
     i += 1 
     elif (i == 4): 
     print("sending 'xfile add ../../src/common/strings.vhdl -lib_vhdl PoC -view ALL'") 
     xtcl.sendLine("xfile add ../../src/common/strings.vhdl -lib_vhdl PoC -view ALL") 
     i += 16 
     elif (i == 20): 
     print("sending 'project close'") 
     xtcl.sendLine("project close") 
     i += 1 
     elif (i == 21): 
     print("sending 'exit'") 
     xtcl.sendCommand("exit") 
     break 

    print("exit main()") 
    xtcl.terminate() 

    print("the end!") 

# entry point 
if __name__ == "__main__": 
    main() 

回答

2

我试图在Linux上的几种方法,但它seemes该xtclsh检测标准输入是否被连接到管道或(伪)终奌站。如果它连接到管道,xtclsh会抑制通常写入标准输出(提示输出,命令结果)的任何输出。我认为,这同样适用于Windows。

即使输入连接到管道,标准错误上打印的消息(无论是信息性的,警告还是错误)仍然会到达那里。

要获得打印在标准输出上的消息,您可以使用总是在标准输出上打印的puts tcl命令。即,puts [command]采用command的标准输出,并始终将其打印到标准输出。

:假设我们有一个test.xise项目有两个文件:在test.vhd顶级实体,并在test_tb.vhd测试平台。而且,我们想用这个TCL脚本(commands.tcl)列出项目中的所有文件:

puts [project open test] 
puts "-----------------------------------------------------------------------" 
puts [search *.vhd] 
exit 

接着,电话xtclsh < commands.tcl 2> error.log打印此标准输出:

test 
----------------------------------------------------------------------- 
/home/zabel/tmp/test/test.vhd 
/home/zabel/tmp/test/test_tb.vhd 

,这是印在标准错误(存入文件error.log):

INFO:HDLCompiler:1061 - Parsing VHDL file "/home/zabel/tmp/test/test.vhd" into 
    library work 
INFO:ProjectMgmt - Parsing design hierarchy completed successfully. 
+0

令人难以置信!我刚刚遇到了这个问题,并且即将放弃它,因为它太过于深奥了:)现在,我可以将调试/编译信息打印到Vivado控制台!好极了! – GCon