1

Problem : Expressing the regexp for grabbing words between two boundaries. Below code is not working

regexp -- {/b/{(.+)/}}/b} $outputline8 - filtered

Objective :

  1. Grabbing all pin name xxx/xxx[x] which is located after the set_false_path and between { and }.
  2. There might be another option such as "-through" in the set_false_path and I still want to grab those pins after those options and put those pins into the output file just as described below.

Here is my input file : input_file.txt

set_false_path -from [get_ports {AAAcc/BBB/CCC[1] \
BBB_1/CCC[1] CCC/DDD[1] \
DDD/EEE EEE/FFF[1] \
FFF/GGG[1]}] -through\
[get_pins {GGG/HHH[1] HHH/III[1] \
XXX/YYY[1] YYY/XXX[1] \
AAA/ZZZ[1]}]
set_timing_derate -cell_sdada [get_cells \
{NONO[1]}
set_false_path -from [get_ports {AAA/DDD[2]}]

Here is the output file (The format I expected): output_file.txt

AAAcc/BBB/CCC[1]
BBB_1/CCC[1]
CCC/DDD[1]
DDD/EEE
EEE/FFF[1]
FFF/GGG[1]
GGG/HHH[1]
HHH/III[1]
XXX/YYY[1]
YYY/XXX[1]
AAA/ZZZ[1]
AAA/DDD[2]

Generally speaking, those pins don't have any general pattern. So the only way is to grab all pins between { and }.

From above input file, we can see that those set_ commands (from the input.txt) is not connected in a single sentence. So I made a code that will only grab the content within set_false path and join those lines, below is my code:

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

set first_word ""
set outputline1 ""
set filtered ""

while { [gets $inputfile line] != 1} {
 set first_word [lindex [split $line ""] 0]
 set re2 {^set_+?}
 #match any "set_ " command
 if { [regexp $re2 $first_word matched] } {
  #if the "set_ " command is found and the outputline1 is not empty, then it's 
  # the end of the last set_ command
  if {$outputline1 != ""} {
   #do the splitting here and put into the outputfile later on
   regexp -- {/b/{(.+)/}}/b} $outputline8 - filtered
   puts "$filtered:$filtered"
   set outputline1 ""
  }

  # grab content if part of set_false_path
  if{ [regexp "set_false_path" $first_word] } {
   # if it's the expected command set, put "command_set" flag on which will be used on 
   # the next elseif
   set command_set 1
   lappend outputline1 $line
   regsub -all {\\\[} $outputline1 "\[" outputline2
   regsub -all {\\\]} $outputline2 "\]" outputline3
   regsub -all {\\\{} $outputline3 "\{" outputline4
   regsub -all {\\\}} $outputline4 "\}" outputline5
   regsub -all {\\\\} $outputline5 "\\" outputline6
   regsub -all {\\ +} $outputline6 " " outputline7
   regsub -all {\s+} $outputline7 " " outputline8
  } else {
   set command_set 0
   # if the line isn't started with set_false_path but it's part of set_false_path command
  } elseif {$command_set} {
   lappend outputline1 $line
   regsub -all {\\\[} $outputline1 "\[" outputline2
   regsub -all {\\\]} $outputline2 "\]" outputline3
   regsub -all {\\\{} $outputline3 "\{" outputline4
   regsub -all {\\\}} $outputline4 "\}" outputline5
   regsub -all {\\\\} $outputline5 "\\" outputline6
   regsub -all {\\ +} $outputline6 " " outputline7
   regsub -all {\s+} $outputline7 " " outputline8
  } else {
  }
 }
}

puts "outputline:outputline8"
#do the splitting here and put into the file later on for the last grabbed line!

close $inputfile
close $outputfile

Code in-depth discussion:

  • I notice that after I lapped the line to outputline1, I will get unexpected output with multiple spaces and forward slash: set_false_path\ -from\ \[get_ports\ \{AAA/BBB\[1\] \ ... etc..

    This output contains of backspaces (\) for every special character such as { , [ , space, etc. So that I put many regsub to remove all of these unnecessary addition. And the final joined result is located in $outputline8

    The result of $outputline8 :

    set_false_path -from [get_ports {AAAcc/BBB/CCC[1] BBB_1/CCC[1] CCC/DDD[1] DDD/EEE EEE/FFF[1] FFF/GGG[1]}] -through [get_pins {GGG/HHH[1] HHH/III[1] XXX/YYY[1] YYY/XXX[1] AAA/ZZZ[1]}]
    set_false_path -from [get_ports {AAA/DDD[2]}]
    
  • I am planning to grab and split the pin within the outputline8 within { and }

Reference: process multiple lines text file to print in single line

  • HERE IS THE LAST UPDATE START:

    If the input file :

    set_false_path -from [get_ports {AAAcc/BBB/CCC[1] BBB_1/CCC[1] DDD/EEE}] -through [get_pins {XXX_1[1]}]
    

    I want the output file:

    AAAcc/BBB/CCC[1]
    BBB_1/CCC[1]
    DDD/EEE
    XXX_1[1]
    

Thank you! HERE IS THE LAST UPDATE END:

NB: I am new to TCL and this forum and any advice is really appreciated!

Community
  • 1
  • 1
Andi Lee
  • 13
  • 4
  • Shouldn't you have backslashes instead of forward slashes in `{/b/{(.+)/}}/b}`? `{\b\{(.+)\}}\b}` – devnull Feb 17 '14 at 03:52
  • Yes, devnull .. I am stupid :( I have tried {/b/{(.+)/}}/b} but it doesn't work neither – Andi Lee Feb 17 '14 at 04:07
  • I have tried to use `regexp -- {\{(.+)\}} $outputline8 - filtered` But I get: `AAAcc/BBB[1] BBB_1/CCC[1] CCC/DDD[1] DDD/EEE EEE/FFF[1] FFF/GGG[1]}] -through [get_pins {GGG/HHH[1] HHH/III[1] XXX/YYY[1] YYY/XXX[1] AAA/ZZZ[1]` Seems like it will get the first "{" to the last "}" But I want: `AAAcc/BBB[1] BBB_1/CCC[1] CCC/DDD[1] DDD/EEE EEE/FFF[1] FFF/GGG[1] GGG/HHH[1] HHH/III[1] XXX/YYY[1] YYY/XXX[1] AAA/ZZZ[1]` Thank you! – Andi Lee Feb 17 '14 at 04:50
  • @AndiLee Is your file big? – Jerry Feb 17 '14 at 07:11
  • Yes, it's a big file @Jerry , Thank you for your reply – Andi Lee Feb 17 '14 at 07:53
  • Hay Guys, let me update my last question : If the input file : `set_false_path -from [get_ports {AAAcc/BBB/CCC[1] BBB_1/CCC[1] DDD/EEE}] -through [get_pins {XXX_1[1]}]` I want the output file: AAAcc/BBB/CCC[1]BBB_1/CCC[1] DDD/EEE}] -through [get_pins {XXX_1[1]}] – Andi Lee Feb 17 '14 at 08:27

1 Answers1

0

Try the following script. I have added explanations in the code comments:

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

# This is a temp variable to store the partial lines
set buffer ""

while { [gets $inputfile line] != -1} {
  # Take previous line and add to current line
  set buffer "$buffer[regsub -- {\\[[:blank:]]*$} $line ""]"

  # If there is no ending \ then stop adding and process the elements to extract
  if {![regexp -- {\\[[:blank:]]*$} $line]} {
    # Skip line if not "set_false_path"
    if {[lindex [split $buffer " "] 0] ne "set_false_path"} {
      set buffer ""
      continue
    }

    # 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 -- {\{([^\}]+)\}} $buffer] {
      foreach out [split $groups] {
        puts $outputfile $out
      }
    }

    # Clear the temp variable
    set buffer ""
  }
}

close $inputfile
close $outputfile
Jerry
  • 70,495
  • 13
  • 100
  • 144
  • Hay Jerry, I got Error message of: extra characters after close-quote. btw, I think I am opening the new topic since there's a new modification on the input file. Please help me on the new topic! – Andi Lee Feb 17 '14 at 09:17
  • @AndiLee Oh? What Tcl version are you using? I think the part that causes the error is `"$buffer[regsub -- {\\[[:blank:]]*$} $line ""]"`. Could you try `$buffer[regsub -- {\\[[:blank:]]*$} $line ""]`? I check the new question in the meantime. – Jerry Feb 17 '14 at 09:19
  • @AndiLee Also, I don't think there's a need to put another question, unless the input file is drastically different. But then, what would happen to this question? – Jerry Feb 17 '14 at 09:20
  • The input file is much simpler, without those newline and \. Please check it out. I need some advice there. [link] (http://stackoverflow.com/questions/21825462/tcl-grabbing-words-within-special-boundaries) – Andi Lee Feb 17 '14 at 09:40