0

Objection : get the all words within the "{" "}" boundary.

input_file.txt:

set_false_path -from [get_ports {a/b[1] ab/cd_1 abcd_1_ad_}] -through [get_pins {th/th1 th2/th2[2]}]
set_derate -whatever [get_ports {xxx/xx1 xxx xxxx_1}]
set_false_path 3 -to [get_pins {aaa/d aaa/b}] -from [get_abc {abc/ac/dd nnn_2/2}]

expected output_file.txt:

a/b[1]
ab/cd_1
abcd_1_ad_
th/th1 
th2/th2[2]
aaa/d aaa/b
abc/ac/dd 
nnn_2/2

NB: there might be two or more pair of "{" "}" , and I want to grab all of those words within "{" and "}" no matter how many they are.

here is my code:

set inputfile [open "input_file.txt" r]
set outputfile [open "output_file.txt" w]


while { [gets $inputfile line] != -1 } {
 set first_word [lindex [split $line ""] 0]
  if { regexp "set_false_path" $first_word} {
    # HOW TO grab all words between "{" and "}" ; split them ; put on output_file 
  }
} else {
}

close $inputfile
close $outputfile
Andi Lee
  • 13
  • 4
  • You have `set_false_path` AND `set false_path`? Is that a typo or is that really how it is? Are there more different ways this appears? – Jerry Feb 17 '14 at 09:48
  • Hay @Jerry . It's Wrong typing, all is set_false_path. Thank you for the correction! – Andi Lee Feb 17 '14 at 09:52
  • Okay, well, my previous script [seems to be working on Tcl8.4](http://codepad.org/IoovmW7Y) (I used a list instead of a file since I can't upload the file on the test site). Here's a demo on the new data format: [link](http://codepad.org/Cr9ZDUoQ) – Jerry Feb 17 '14 at 10:00
  • Hay Jerry, I have tried my own code and try run the code on the link you gave me [link] (http://codepad.org/rLqZJrPL), However I dont know what did I missed since I didn't get any output from the link. When I run it on my machine, I got a close-expected result but I still got the unexpected space. input_file: [link] (http://imageshack.com/a/img138/4871/4fmy.png) ; output result: [link] (http://imageshack.com/a/img833/7131/iza3.png) Please check it out. – Andi Lee Feb 17 '14 at 10:39
  • I'm not sure why you're using regex to check the first word when it's really not necessary. There were some errors in your code, namely in `split`. I fixed that and used a string comparison: [link](http://codepad.org/T8477Byh) along with a `string trim` to remove extra trailing/leading spaces. – Jerry Feb 17 '14 at 10:45
  • Hay Jerry, Thank you for your reply. It has worked for me! I cant answer my own question since my reputation isn't high enough, so I have to wait 8 hours from now to post my final result. Yes, I have removed the necessary checking on my last result. Thank you, Jerry! I will post my final result in 8 hours! – Andi Lee Feb 17 '14 at 10:57

3 Answers3

0

Since you don't have the lines split on several lines, you can use a simpler script than the previous script:

set inputfile [open "input_file.txt" r]
set outputfile [open "output_file.txt" r]

while {[gets $inputfile line] != -1} {
  # If starts with set_false_path, process
  if {[lindex [split $line " "] 0] eq "set_false_path"} {

    # Grab each element with regexp into a list and print each to outputfile
    # m contains whole match, groups contains sub-matches
    foreach {m groups} [regexp -all -inline -- {\{([^\}]+)\}} $line] {

      # Trim any trailing/leading spaces
      set groups [string trim $groups]
      foreach out [split $groups] {
        puts $outputfile $out
      }
    }
  }

}

close $inputfile
close $outputfile
Community
  • 1
  • 1
Jerry
  • 70,495
  • 13
  • 100
  • 144
0

I am submitting two alternate methods just for the sake of variety.

Method 1: Using the unknown Handler

Here is a different approach: since the input file appears to be a Tcl script, as soon as we detect a line with set_false_path, we can evaluate that line in order to extract the PINs. In order for this to work, we setup a procedure called unknown to catch all unknown procedures. In this case, we are interested in get_ports, get_pins, get_abc...:

# proc unknown is invoked for all unknown procedures: those that are
# called without previously defined.
proc unknown {cmdName args} {
    global outFile

    # List of procedures with PINs as arguments
    set pinProcs {get_ports get_pins get_abc}

    # If the procedure has PINs as arguments, we extract those PINs
    # and write to a file
    if {[lsearch -exact $pinProcs $cmdName] != -1} {
        eval "set args $args"; # Remove the surrounding braces {}
        foreach arg $args { puts $outFile $arg }
    }
}

set inFile  [open "input_file.txt"]
set outFile [open "output_file.txt" "w"]
while {[gets $inFile line] != -1} {
    if {[lindex [split $line " "] 0] eq "set_false_path"} {
        eval $line; # Tells Tcl interpreter to interpret the line
    }
}
close $inFile
close $outFile

This method has a couple of advantages: it relies on Tcl to correctly parses the input lines and we don't have to deal with messy regular expressions. The disadvantages include the need to manually keeping track of which procedure we are interested in (see pinProcs, above).

Method 2: Create Our Own set_false_path Procedure

Similar to the above, this time, we setup our own set_false_path procedure to extract all the PINs that follow the following flags: -to, -from, and -through. The advantage of this approach is we don't have to manually keep a list of procedure names (see pinProcs).

# Our own proc, which returns a list of PINs
proc set_false_path {args} {
    set result {}
    for {set i 0} {$i < [llength $args]} {incr i} {
        set token [lindex $args $i]
        if {[lsearch -exact {-to -from -through} $token] != -1} {
            incr i
            set token [lindex $args $i]
            lappend result {*}[lindex $args $i]
        }        
    }
    return $result
}

# proc unknown is invoked for all unknown procedures: those that are
# called without previously defined.
proc unknown {cmdName args} {
    eval "set args $args"; # Remove the surrounding braces {}
    return $args
}

set inFile  [open "input_file.txt"]
set outFile [open "output_file.txt" "w"]
while {[gets $inFile line] != -1} {
    if {[lindex [split $line " "] 0] eq "set_false_path"} {
        foreach pin [eval $line] {
            puts $outFile $pin
        }
    }
}
close $inFile
close $outFile
Hai Vu
  • 37,849
  • 11
  • 66
  • 93
0

It's working! Thank you very much! you are awesome, dude :)

Here is my final code:

set inputfile [open "input_file.txt" r]
set outputfile [open "output_file.txt" w]

set first_word ""
while { [gets $inputfile line != -1] } {
 if { ([lindex [split $line ""] 0] eq "set_false_path") } {
  foreach {m groups} [regexp -all -inline -- {\{(.+?)\}} $line] {
   foreach out [split $groups] {
    puts $outputfile $out
   }
  }
 }
}

close $inputfile
close $outputfile

input_file.txt:

set_false_path -from [get_ports {a/b[1] ab/cd_1 abcd_1_ad_}] -through [get_pins {th/th1 th2/th2[2]}]
set_derate -whatever [get_ports {xxx/xx1 xxx xxxx_1}]
set_false_path 3 -to [get_pins {aaa/d aaa/b}] -from [get_abc {abc/ac/dd nnn_2/2}]

output_file.txt (all words within {} brackets for all lines starts with "set_false_path"):

a/b[1]
ab/cd_1
abcd_1_ad_
th/th1
th2/th2[2]
aaa/d aaa/b
abc/ac/dd 
nnn_2/2

This forum is great! Thank you Guys! :)

Best regards, Andi Lee

Andi Lee
  • 13
  • 4