Tcl code to fetch pin details and compare with another file pins

Viewed 45

I have two files and I am comparing specific lines between two files using the def function. python and I am trying to write same code on tcl

The file data is given below

PIN i_hbmc_ieee1500_sel_wir
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER K3 ;
RECT 2090.163000 3265.856000 2090.476000 3265.920000 ;
END
END i_hbmc_ieee1500_sel_wir
PIN i_hbmc_ieee1500_cap_wr
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER K3 ;
RECT 2090.163000 3265.984000 2090.476000 3266.048000 ;
END
END i_hbmc_ieee1500_cap_wr
PIN i_hbmc_ieee1500_shft_wr
DIRECTION INPUT ;
USE SIGNAL ;
PORT
LAYER K3 ;
RECT 2090.163000 3265.728000 2090.476000 3265.792000 ;
END
END i_hbmc_ieee1500_shft_wr

The python code to fetch pin details of both files and compare between files

   def readPinFile(filename):
   result = None
   with open(filename, "r") as file:    

    result = {}
    lastPin = None        
    for line in file:
        lines = line.strip()
        
        if lines[:3] == "PIN": 
            lastPin = lines.split(" ")[1]               
            result[lastPin] = {"LAYER": None, "RECT": None}
        
        if lines[:5] == "LAYER":
            result[lastPin]["LAYER"] = lines.split(" ")[1]
           
        if lines[:4] == "RECT":
            result[lastPin]["RECT"] = lines.split(" ")

return result

pin_of_file1 = readPinFile("osi_hbmp_top_briscm_1.lef") #lef file1
pin_of_file2 = readPinFile("osi_hbmp_top_briscm_2.lef")#lef file2



with open("file04.txt", "r+") as output_file4:  #compare same pins with layer and location
 for pin, pin_data in pin_of_file1.items():
      if pin in pin_of_file2:
         if pin_of_file2[pin]["LAYER"] == pin_data["LAYER"] and pin_of_file2[pin]["RECT"] == pin_data["RECT"]:
             output_file4.write(pin + "\n\n")

The TCL code I tried to get the same output

proc fileinput {filename} {
set filedata [open filename r]
set file1 [ read $filedata ]
foreach line [split $file1 \n] {
      set pindata { PIN { LAYER {} RECT {} }}
      if {[string match *PIN* $line]} {
          dict lappend pindata PIN $line         
         }
      if {[string match *LAYER* $line]} {
           dict lappend pindata PIN {LAYER{$line}} 
         } 
      if {[string match *RECT* $line]} {
           dict lappend pindata PIN {RECT{$line}}
          } 
      }
  return $pindata
}
set fileinput1 [fileinput osi_hbmp_top_briscm_1.txt]
set fileinput2 [fileinput osi_hbmp_top_briscm_2.txt]

In tcl I am trying to write comparing between the pins section (last 4-5 lines on python code), but I am stuck in the middle. I am fully confused to continue this code. can anyone help me to complete this code(mainly last 2 lines of python code)

  foreach $pin, $pin_data [gets $fileinput1]
    if{[string match $pin $fileinput2]} 

This is the code I tried

2 Answers

Your code is using a proc called fileinput but you didn't include the proc definition. It actually looks like you are including the body of the proc, you didn't include the proc command at the beginning.

I will assume you want to do this (I also changed how the pindata dictionary is set)

proc fileinput {filename} {
    set filedata [open $filename r]
    set file1 [ read $filedata ]
    close $filedata
    set pindata [dict create]
    foreach line [split $file1 \n] {
        if {[string match "PIN*" $line]} {
            set pin [lindex $line 1]
        }
        if {[string match "LAYER*" $line]} {
            set layer [lindex $line 1]
            dict lappend pindata $pin layer $layer
        } 
        if {[string match "RECT*" $line]} {
            set rect [lrange $line 1 4]
            dict lappend pindata $pin rect $rect
        } 
    }
    return $pindata
}

Now the proc returns a dictionary with a top key set to the pin name and nested keys called "layer" and "rect".

To compare the pin layer of two different files:

# Parse each file and return a dict
set pin_data1 [fileinput osi_hbmp_top_briscm_1.txt]
set pin_data2 [fileinput osi_hbmp_top_briscm_2.txt]

# Iterate over the keys and compare layers:
foreach pin_name [dict keys $pin_data1] {
    set layer1 [dict get $pin_data1 $pin_name layer]

    # Check that the pin_name is in the second file
    if {![dict exists $pin_data2 $pin_name]} {
        puts "$pin_name exists in pin_data1 but not pin_data2"
        continue
    }

    # If we get this far, then $pin_name appears in both files.
    set layer2 [dict get $pin_data2 $pin_name layer]
    if {$layer1 ne $layer2} {
        puts "Layer mismatch for $pin_name:"
        puts "     1:  $layer1"
        puts "     2:  $layer2"
    }
}

By the way, your example input file is incomplete. There is an END for a pin name that was never declared earlier.

@ChrisHeithoff it's throwing an error when the file consists of extra pin details

pin matching i_hbmc_ieee1500_sel_wir
pin matching o_hbmc_ieee1500_sel_wso[5]
pin matching o_hbmc_ieee1500_sel_wso[4]
key "o_hbmc_ieee1500_sel_wso[3]" not known in dictionary
      while executing
"dict get $pin_data2 $pin_name layer"
      ("foreach" body line 3)
      invoked from within
"foreach pin_name [dict keys $pin_data1] {
       set layer1 [dict get $pin_data1 $pin_name layer]
       set layer2 [dict get $pin_data2 $pin_name lay..."
       (file "aa.tcl" line 26)
Related