【问题标题】:Where does the Xilinx TCL shell emit the results?Xilinx TCL shell 在哪里发出结果?
【发布时间】:2016-03-23 06:17:40
【问题描述】:

我正在尝试围绕 Xilinx ISE TCL shell xtclsh.exe 开发基于 Python 的包装器。如果可行,我将添加对其他 shell 的支持,例如 PlanAhead 或 Vivado ...

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

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

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

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

在 xtclsh.exe 中手动执行search *.vhdl -type file 会导致:

% 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 命令的结果?

顺便说一句:提示符号% 对我的脚本也不可见。


重现行为的 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()

【问题讨论】:

    标签: python shell subprocess xilinx xilinx-ise


    【解决方案1】:

    我在 Linux 上尝试了几种方法,但似乎 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.
    

    【讨论】:

    • 难以置信!我刚遇到这个问题,并且正准备放弃它太深奥了:) 现在我可以将调试/构建信息打印到 Vivado 控制台!耶!
    猜你喜欢
    • 2011-07-27
    • 1970-01-01
    • 2018-02-25
    • 1970-01-01
    • 1970-01-01
    • 2015-08-12
    • 2012-01-01
    • 2011-07-02
    • 1970-01-01
    相关资源
    最近更新 更多