Viewing enum names in vcs ucli - enums

I am working in VCS UCLI (ie, the command line interface) and am having trouble getting VCS to display various state variables, of a typedef'd enum type, value as the name rather than the number. For example, I have some SystemVerilog like this:
typedef enum logic [1:0] {A, B, C} state_t;
state_t s;
...
Now in ucli, I want to see the value of s (say its in state A) so I type something like:
ucli% get s
0
ucli% get s -radix symbolic
0
ucli% show s -value
s 0
ucli% show s -value -radix symbolic
s 0
ucli% show s -value -type
s 0 { ENUM state_t { {A 0} {B 1} {C 2} } }
(Or something like that). I have read the ucli user guide, and it seems like symbolic radix, the only one I know of that might possibly be close, just uses the raw value from the enum, not the enum name. I have tried calling the .name() method for variable s using the call command in ucli (ucli% call {$display("%s", s.name())}), but it doesnt seem to be supported. I know VCS has the capacity to print the enum name, it certainly can in DVE, but I am having trouble coming up with ways to get to show me in the ucli.
Does anyone know how to get the ucli to print the enum name instead of the number when queried? Is enum-type radix somehow (user-defined like in DVE?), use some SystemVerilog system call to get the name, anything like that?
(Note, I understand I could just use the DVE, but I am trying to use the ucli to simply the interface for potential users, this is for educational purposes and I want to mask alot of the ucli interface (and VCS interface in general) to not overwhelm students and get some variables easily; Im turning the vcs ucli into a simple processor simulator)
++++++++++++ UPDATE ++++++++++++
I came up with a very hacky solution but I would really like a better approach. I quickly wrote my own wrapper for show (called eshow) whish ill replace any -value with the enum name if -radix enum is set:
#
# An extension of show to include "-radix enum"
#
# Borrowed from http://wiki.tcl.tk/17342
# Credit to Richard Suchenwirth (12-8-2006)
proc getopt {_argv name {_var ""} {default ""}} {
upvar 1 $_argv argv $_var var
set pos [lsearch -regexp $argv ^$name]
if {$pos>=0} {
set to $pos
if {$_var ne ""} {
set var [lindex $argv [incr to]]
}
set argv [lreplace $argv $pos $to]
return 1
} else {
if {[llength [info level 0]] == 5} {set var $default}
return 0
}
}
proc eshow {args} {
set argv $args
# If radix is not specified or value is not specified, then dont bother doing anything but regular show
if { 0 == [getopt argv -radix radix] } {
return [eval show $args]
}
if { 0 == [getopt argv -value] } {
return [eval show $args]
}
# If radix isnt enum, just pass off to regular show
if { 0 == [string equal -nocase $radix "enum"] } {
return [eval show $args]
}
# Now get the signal, its value and its type
set var [lindex [eval show $argv] 0]
set val [lindex [show $var -value] 1]
set typ [lindex [show $var -type] 1]
# If the type isnt an enum, error
if { 0 == [string equal -nocase [lindex $typ 0] "ENUM"] } {
return "The type of variable $var is not an enumerated type"
}
# Process the enumerations
set enuml [lindex $typ 2]
# Find the value name
foreach v $enuml {
if { $val == [lindex $v 1] } {
set enumname [lindex $v 0]
break
}
}
# If could not be found....
if { 0 == [info exists enumname] } {
return "The variabel $var has a value which does not map"
}
# Get rid of radix from args
getopt args -radix trashcan
# Replace all values with the name
set retval [eval show $args]
set retshow $retval
foreach v [lsearch -all $retval $val] {
set retshow [lreplace $retshow $v $v $enumname]
}
return $retshow
}
Thus, if I type any other non-radix enum eshow commands, it will pass to show, but otherwise, it will replace all values with thier names and return the same thing show would with the replacement. As I said, I REALLY want a better solution, but in case anyone wants to use my function, here it is.

Related

How to implement queue and priority queue in Tcl?

I have to implement either queue or priority queue in Tcl without use of any library.
I have tried to write below code. Kindly help me to implement queue in better way in Tcl/Tk.
create node
// crearting node element of queue
proc createNode {name cost} {
namespace eval $name [subst {
variable cost $cost
variable this $name
}]
functions
proc ${name}::getCost {} {
variable cost
return $cost
}
return $name
}
delete queue
proc deQueue name {
#upvar 1 $name queue
set queue $name
set res [lindex $queue 0]
set queue [lrange $queue 1 end]; # remove the first element
set res; # return the value
}
queue insertion
proc enQueue {newNode name} {
#upvar 1 $name queue
set queue $name
set queue [concat $newNode $queue]
}
create queue
proc makeQueue {n g } {
set queue [list [createNode $n $g ]]
return $queue
}
A simple queue implementation:
proc enqueue {name item} {
upvar 1 $name queue
lappend queue $item
}
proc dequeue name {
upvar 1 $name queue
set queue [lassign $queue item]
return $item
}
% enqueue a foo
% set item [dequeue a]
A simple priority queue:
proc enpqueue {name prio item} {
upvar 1 $name queue
lappend queue [list $prio $item]
set queue [lsort -decreasing -integer -index 0 $queue]
}
proc depqueue name {
upvar 1 $name queue
set queue [lassign $queue prioitem]
return [lindex $prioitem 1]
}
% enpqueue a 10 foo
% enpqueue a 40 bar
% set item [depqueue a]
bar
The only thing you need for a queue or priority queue is a list and an add/remove interface.
If you want to store structured data in the queue, make the item either a tuple of data:
set item [list "Smith, John" 42 1500]
or a dictionary:
set item [list name "Smith, John" age 42 foo 1500]
Documentation:
lappend,
lassign,
lindex,
list,
lsort,
proc,
return,
set,
upvar
Queues are abstract data structures with two (key) operations: add and get (and an empty test is pretty common too). They're sufficiently complex internally that it's probably best to think in terms of using a TclOO object as their implementation:
oo::class create Queue {
variable q
constructor {} {
set q {}
}
method add {item} {
lappend q $item
return
}
method empty {} {
expr {[llength $q] == 0}
}
method get {} {
if {[my empty]} {
return -code error "queue is empty"
}
set q [lassign $q item]
return $item
}
}
Priority queues are like queues, except that they have a priority as well and sort by that priority. The trick to implementing them efficiently is not to sort on each add or get, but rather to only sort when necessary. (Or you can use an appropriate balanced tree, but they're quite complicated.)
oo::class create PriorityQueue {
variable q sorted
constructor {} {
set q {}
set sorted 1
}
method add {item priority} {
lappend q $item $priority
set sorted 0
return
}
method empty {} {
expr {[llength $q] == 0}
}
method get {} {
if {[my empty]} {
return -code error "queue is empty"
}
if {!$sorted} {
# You might want other options here, depending on what "priority" means
set q [lsort -stride 2 -index 1 -integer $q]
set sorted 1
}
set q [lassign $q item priority]
return $item
}
}
Using these data structures is fairly simple:
# Instantiate
set myq [PriorityQueue new]
# Add some values
$myq add "The quick brown fox" 12
$myq add "The lazy dog" 34
# Drain the queue
while {![$myq empty]} {
puts [$myq get]
}
# Get rid of it now we're done
$myq destroy

how to change Tcl default font size

I am not very good at Tcl but I am using this code to visualize some systems. Can anyone help me with changing the default font of the produce of this code below?
I tried to put this to the top of the code but it didn't work:
font create myDefaultFont -family Helvetica -size 20
option add *font myDefaultFont
Here is the code:
proc DisplayModel2D { {ShapeType nill} {dAmp 5} {xLoc 10} {yLoc 10} {xPixels 512} {yPixels 384} {nEigen 1} } {
global TunitTXT
global ScreenResolutionX ScreenResolutionY
if { [info exists TunitTXT] != 1} {set TunitTXT ""}
if { [info exists ScreenResolutionX] != 1} {set ScreenResolutionX 1024}
if { [info exists ScreenResolutionY] != 1} {set ScreenResolutionY 768}
if {$xPixels == 0} {
set xPixels [expr int($ScreenResolutionX/2)];
set yPixels [expr int($ScreenResolutionY/2)];
set xLoc 10
set yLoc 10
}
if {$ShapeType == "nill"} {
puts ""; puts ""; puts "------------------"
puts "View the Model? (N)odes, (D)eformedShape, anyMode(1),(2),(#). Press enter for NO."
gets stdin answer
if {[llength $answer]>0 } {
if {$answer != "N" & $answer != "n"} {
puts "Modify View Scaling Factor=$dAmp? Type factor, or press enter for NO."
gets stdin answerdAmp
if {[llength $answerdAmp]>0 } {
set dAmp $answerdAmp
}
}
if {[string index $answer 0] == "N" || [string index $answer 0] == "n"} {
set ShapeType NodeNumbers
} elseif {[string index $answer 0] == "D" ||[string index $answer 0] == "d" } {
set ShapeType DeformedShape
} else {
set ShapeType ModeShape
set nEigen $answer
}
} else {
return
}
}
if {$ShapeType == "ModeShape" } {
set lambdaN [eigen $nEigen]; # perform eigenvalue analysis for ModeShape
set lambda [lindex $lambdaN [expr $nEigen-1]];
set omega [expr pow($lambda,0.5)]
set PI [expr 2*asin(1.0)]; # define constant
set Tperiod [expr 2*$PI/$omega]; # period (sec.)
set fmt1 "Mode Shape, Mode=%.1i Period=%.3f %s "
set windowTitle [format $fmt1 $nEigen $Tperiod $TunitTXT]
} elseif {$ShapeType == "NodeNumbers" } {
set windowTitle "Node Numbers"
} elseif {$ShapeType == "DeformedShape" } {
set windowTitle "Deformed Shape"
}
set viewPlane XY
recorder display $windowTitle $xLoc $yLoc $xPixels $yPixels -wipe ; # display recorder
DisplayPlane $ShapeType $dAmp $viewPlane $nEigen 0
}
font create myDefaultFont -family Helvetica -size 20
option add *font myDefaultFont
will indeed set the default font for all text added to widgets that have a -font option. It will not change the font of text printed on the console with puts. It's not clear from the code you've posted how your text is being displayed, but if you e.g. set the text of a label to the value of one of your variables it should be displayed with the font you've selected.

Expand passed arguments before printing with puts to virtual server

I am having trouble with an expect script not evaluating arguments. Everything in the puts ${file_id} block (simplified obviously) gets placed onto a virtual machine and is later used to for configuration. The block you see puts the same code into a local directory for me to see if things are working properly.
global env
set env(os1) [lindex $argv 0]
set env(scratch_repo) /tmp/yum.repo_[pid]
set file_id [ open ${env(scratch_repo)} "w"]
puts ${file_id} {
root_image=node-${env(os1)}
if {[string first r ${env(os1)}] == 0} {
create_node_byid 1 [string range ${env(os1)} 0 4]-64
} else {
create_node_byid 1 [string range ${env(os1)} 0 5]-64
}
}
Unfortunately, the log file looks exactly as above. The arguments are not being substituted properly and I can't figure out why. I've tried using regular variables, different syntax for referencing local and global variables but have had no luck getting this to work. Any thoughts?
As Etan Reisner pointed use double quotes in the puts command instead of braces, so that it will get replaced.
puts ${file_id} "
root_image=node-${env(os1)}
if {[string first r ${env(os1)}] == 0} {
create_node_byid 1 [string range ${env(os1)} 0 4]-64
} else {
create_node_byid 1 [string range ${env(os1)} 0 5]-64
}
"
Assuming env(os1) as Ubuntu, will produce the following content in the file
root_image=node-Ubuntu
if {-1 == 0} {
create_node_byid 1 Ubunt-64
} else {
create_node_byid 1 Ubuntu-64
}
Note : This will only do variable substitutions not evaluation of code as such. i.e. if-else commands won't be evaluated.

Counting commands inside the proc in tcl?

Is there any way to count the commands before execution (may be callstack number including tclcmds) from specified proc name? I think it is needed to assume that the source is available (not for precomiled).
Thanking you.
Dynamic Analysis
You can use traces to find how many commands are executed during the execution of a particular procedure. Under the assumption that the command is not re-entered (i.e., isn't recursive) you do:
proc theProcedureOfInterest {} {
# Whatever in here...
for {set i 0} {$i < 5} {incr i} {
puts i=$i
}
}
trace add execution theProcedureOfInterest {enter leave enterstep} countCalls
proc countCalls {cmd args} {
global counter
switch [lindex $args end] {
enter {
set counter 0
}
enterstep {
incr counter
puts >>>$cmd
}
leave {
puts "$counter calls in $cmd"
}
}
}
theProcedureOfInterest
If you execute the above code, you get this output:
>>>for {set i 0} {$i < 5} {incr i} {
puts i=$i
}
>>>set i 0
>>>puts i=0
i=0
>>>incr i
>>>puts i=1
i=1
>>>incr i
>>>puts i=2
i=2
>>>incr i
>>>puts i=3
i=3
>>>incr i
>>>puts i=4
i=4
>>>incr i
12 calls in theProcedureOfInterest
That code has 12 command calls inside it, and you can count them yourself too.
This will also trace into procedures called from that procedure (and making it handle recursive calls is possible, but rather more involved). Be aware that changing the definition of the procedure will remove the trace (just reapply it if desired) and also note that this sort of tracing has a substantial performance impact (it greatly inhibits possible optimizations in Tcl's bytecode compiler).
Static Analysis
To get a static analysis of the code, you need the dkf-improved-disassembler branch (I've not merged it yet). Then, you can do:
set disassembled [::tcl::unsupported::getbytecode script {
# Whatever in here...
for {set i 0} {$i < 5} {incr i} {
puts i=$i
}
}]
set commandCount [llength [dict get $disassembled commands]]
You can also look at the commands element to see the identified commands (dict get [lindex [dict get $disassembled commands] $n] source). It will inspect into commands like for, but not into custom commands with bodies (since it doesn't understand that they're part of the code as opposed to just a funny string). It also has no idea how often they're executed; it's static analysis after all.

Difficulties understanding the mechanism of retrieving parameter values passed to a script in a function

The script passes two parameter values to another instance of the script. So the built-in parameter variable, 0, contains the number of passed parameters. 1 is in the below example "C:/Windows" and 2 is "/switchtest"
It is possible to assign the parameter values to strParam1 and strParam2 with the traditional method outside the function (with the single equal sign). However, inside a function, the assignments fail.
If they are assigned in a loop with the := sign, it seems to work.
Why is it? Can anybody explain this behavior?
strParam1 = %1%
strParam2 = %2%
msgbox, 64, Outside the Function, number of parameters:%0%`npath: %strParam1%`nswitch: %strParam2%
test_params()
strPath := "C:/Windows"
strSwitch := "/switchtest"
RunWait "%A_AhkPath%" "%A_ScriptFullPath%" "%strPath%" "%strSwitch%"
test_params() {
global 0
; this works
; loop %0%
; strParam%A_Index% := %A_Index%
; this causes an error: "This dynamic variable is blank. If this variable was not intended to be dynamic, remove the % symbols from it."
; strParam1 := %1%
; strParam2 := %2%
; this passes empty values; however, this method works outside the function.
strParam1 = %1%
strParam2 = %2%
msgbox, 64, Inside the Function, number of parameters:%0%`npath: %strParam1%`nswitch: %strParam2%
if strParam2
exitapp
}
You had the right idea with global 0; that allows %0% to carry into the function from toplevel. You just need to declare global 1, 2 as well.
Even if you do this, you can't use := to assign them to variables, because := deals with expressions and there is no syntax to use them in expressions (normally a variable is referred to in an expression with the variable name alone, without %%; obviously 1 and 2 are interpreted as actual numbers instead of variables).
#echristopherson answered the question, but I'd like to propose a workaround. This assumes you're using AutoHotkey_L.
If you run the test script with the args "a b c", it gives you this.
3
1, a
2, b
3, c
The test:
argv := args()
test := argv.MaxIndex() "`n"
for index,param in argv
test .= index ", " param "`n"
MsgBox % test
And the function:
args() {
global
local _tmp, _out
_out := []
Loop %0% {
_tmp := %A_Index%
if _tmp
_out.Insert(_tmp)
}
return _out
}

Resources