Open macd opened 3 years ago
Did you find how to capture the output of yosys commands? I am struggling with this same issue.
Well after much trial and tribulation, I made an incredibly ugly hack to get this functionality.
Basically, It redirects stdout to a temporary file, reads that file, and returns the value. It also restores stdout before returning.
I'm at a loss why I had to make this hack, it seems like basic functionality that should be builtin to yosys. What's the point of TCL scripting if the script can't react to what yosys returns?
Anway, here's the ugly code. I do depend on tclx for access to the "dup" command (for stdout preservation). There is a way to do it without dup (read here: https://stackoverflow.com/a/8532484/600853), but ugly as it is, if we don't preserve stdout, it will mess up logging.
#for some reason yosys doesn't initialize basic functionality like the ability to load packages. Do it manually here.
set tcl_library "/usr/share/tcl8.6"
source /usr/share/tcl8.6/init.tcl
#require tclx for dup command
package require Tclx
#import the yosys commands
yosys -import
proc capture_stdout {args} {
#open a tmpfile.
set temp [exec mktemp]
set newstdout [open $temp w]
#Save the old stdout to restore later
set old_stdout [dup stdout]
#close old stdout
close stdout
#make the new file act as stdout
dup $newstdout stdout
#Run the yosys command
{*}$args
#close the tempfile (acting as stdout)
close stdout
#restore stdout fd
dup $old_stdout stdout
#read the temp file
set response [open $temp r]
set retval [read $response]
close $response
#Cleanup
file delete $temp
#return what we read
return $retval
}
#it works with any command. For example:
puts "before"
set capture [capture_stdout "puts" "hello world"]
puts "after"
puts $capture
I am emphatically not a TCL expert, there may be some glaring issues in this code. But it works well enough for me...
It's not implemented because the TCL interface is a straight import of the Yosys CLI commands, and the Yosys CLI doesn't have conditionals. We usually make a ScriptPass if we need to decide something on contents of the design.
BTW, could you avoid the need for the package if you use the yosys tee
command to write the output to the temp file instead?
That's a good idea, using the tee command. Here's a revised version of my function. It is so much simpler:
#import the yosys commands
yosys -import
proc capture_stdout {args} {
#open a tmpfile.
set temp [exec mktemp]
#Run the yosys command
tee -o $temp {*}$args
#read the temp file
set response [open $temp r]
set retval [read $response]
close $response
#Cleanup
file delete $temp
#return what we read
return $retval
}
Thanks for bringing tee to my attention!
Side note, the documentation does not make it clear that yosys does not return values to the TCL prompt. I think it should be updated to make this clearer and the solution we came to here (tee) be mentioned.
I've made a pull request to this effect in yosys-web.
The documentation is actually autogenerated from the help messages included in the source code, so the right place to edit this would be here: https://github.com/YosysHQ/yosys/blob/197c9e04e8778f99f82b1b6bddc9eba3fbf85104/kernel/yosys.cc#L759-L777
With #3572 you can now skip the file on disk and return the output via the scratchpad (still using tee
, in the future we plan to make commands return values directly where it makes sense).
The result of a tcl command such as
set xxx [cmd]
should set the variable xxx to the result of command cmd. This works for normal tcl commands but not for Yosys commands. Here is a simple example. Say we have test.tcl with the following:This results in