• Skip to main content
  • Skip to search
  • Skip to footer
Cadence Home
  • This search text may be transcribed, used, stored, or accessed by our third-party service providers per our Cookie Policy and Privacy Policy.

  1. Community Forums
  2. Custom IC SKILL
  3. Sending SKILL commands to a running instance of ICFB

Stats

  • Locked Locked
  • Replies 18
  • Subscribers 145
  • Views 29735
  • Members are here 0
This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Sending SKILL commands to a running instance of ICFB

gsimard
gsimard over 16 years ago

Hi all !

 

 I was wondering if it would be possible to send SKILL instructions to a running instance of ICFB, just as if I was typing them in the console of the ICFB, but from an external process. The idea is to use my favorite editor (emacs) and being able to interact with the ICFB process (sending code, retrieving replies, in the best scenario).

 

Thank you for any advice !

Guillaume

  • Cancel
  • skillUser
    skillUser over 16 years ago

    Hi Guillaume,

    I don't think that you could start icfb as an interactive "slave" with your emacs session being the master, though I'm not 100% sure on that.  It is certainly possible to start an external "tool" from within DFII using interprocess communication (IPC), and I think that if you do this as an asynchronous process with an appropriate "data handler", incoming text could be executed as commands, if using ipcBeginProcess, but I think that you might want to look at the ipcBeginSkillProcess() command, for example:

    ipcSkillProcess(
      t_command 
      [ t_hostName ] 
      [ tsu_dataHandler ] 
      [ tsu_errHandler ] 
      [ tsu_postFunc ] 
      [ t_logFile ] 
      [ x_cmdDesc ] 
      [ x_resDesc ] 
    ) 
    => o_childId

    Description

    Invokes an Operating System process capable of executing SKILL functions in the parent process. Opens two additional channels to the child process that let the child send and receive the results of SKILL commands.

     

    I hope that this helps you.

    Best regards,

    Lawrence.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    Here's an approach I posted to the comp.cad.cadence news group a few years ago.

    There are three parts:

    1. Tcl script skillServer to act as a "server", listening for requests.  

      #!/usr/bin/env tclsh
      # 
      # Author     A.D.Beckett
      # Group      Custom IC, Cadence Design Systems Ltd
      # Machine    SUN
      # Date       Jun 13, 2003 
      # Modified   
      # By         
      # 
      # Simple server interface. Is started by DFII, using ipcBeginProcess(),
      # see skillServer.il.
      # 
      # Opens a server socket, and listens for incoming connections.
      # When data comes in on that incoming connection, it passes it through
      # to DFII (via this process's stdout). Then DFII sends back the result
      # to this process's stdin. The protocol is that the Tcl channel ID is
      # sent as the first word on the data sent to DFII, and also, the channel
      # ID is the first word of the result. This allows us to know where to send
      # the result back to if multiple channels are open
      #
      # the UNIX env var $SKILLSERVPORT defines the port number, and defaults
      # to 8123.
      #
      
      if [info exists env(SKILLSERVPORT)] {
        set port $env(SKILLSERVPORT)
        } else {
        set port 8123
        }
      
      proc listener {channel addr port} {
        puts "$channel abSkillServerConnection(\"$addr\" \"$port\")"
        flush stdout
        fconfigure $channel -buffering line
        fileevent $channel readable [list sendToDFII $channel]
        }
      
      proc sendToDFII {channel} {
        if {[eof $channel] || [catch {gets $channel line}]} {
          # end of file
          close $channel
          } else {
          puts "$channel $line"
          flush stdout
          }
        }
        
      proc sendBack {} {
        gets stdin line
        regsub {^(\w+) .*$} $line {\1} channel
        regsub {^\w+ (.*)$} $line {\1} result
      
        if {![eof $channel]} {
          puts $channel $result
          }
        }
      
      fconfigure stdin -buffering line
      fileevent stdin readable sendBack
      
      socket -server listener $port
      vwait forever
      
    2. SKILL code skillServer.il to launch the skillServer process, and process any output from skillServer as SKILL commands

      abSkillServerDebug=nil
      procedure(abSkillServerConnection(addr port)
          printf("Connection received from address %s, port %s\n" addr port)
          )
      
      procedure(abSkillServerListener(ipcId data)
          let((channel command result)
      	rexCompile("^\\([^ ]*\\) \\(.*\\)$")
      	channel=rexReplace(data "\\1" 1)
      	command=rexReplace(data "\\2" 1)
      	when(abSkillServerDebug
      	    printf("COMMAND: %L\n" command)
      	)
      	unless(errset(result=evalstring(command))
      	    when(abSkillServerDebug
      		printf("ERROR: %L\n" errset.errset)
      	    )
      	    ipcWriteProcess(ipcId sprintf(nil "%s ERROR %L\n" 
      		channel errset.errset))
      	) ; unless
      	when(abSkillServerDebug
      	    printf("RESULT: %L\n" result)
      	)
      	ipcWriteProcess(ipcId sprintf(nil "%s %L\n" channel result))
          )
      )
      
      abSkillServer=ipcBeginProcess("skillServer" "" 'abSkillServerListener)
      
      
    3. Tcl script skillClient to send commands to the Virtuoso session (via skillServer)

      #!/usr/bin/env tclsh
      # 
      # Author     A.D.Beckett
      # Group      Custom IC, Cadence Design Systems Ltd
      # Machine    SUN
      # Date       Jun 13, 2003 
      # Modified   
      # By         
      # 
      # simple command interface which allows me to say
      #
      # skillClient machineName 8123 "skillFunction()"
      #
      
      set hostname [lindex $argv 0]
      set port [lindex $argv 1]
      set command [lindex $argv 2]
      
      set sock [socket $hostname $port]
      puts $sock $command
      
      

    Hopefully this illustrates the idea. Search on google groups under comp.cad.cadence if you want to see some more.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • gsimard
    gsimard over 16 years ago

     Thank you both !

     

    As usual your replies are most useful. I may actually go with a slightly different solution now that your hints enlightned me.. right now both machines (the one running emacs and the one running icfb) are actually the same one, so I will use two Linux FIFOs to create a bidirectional communication channel between the pair. This will allow me to use normal file reading and writing functions for communication. Also this will solve the security issue of opening a socket to the world, it's a bit of a backdoor :) I'm not really concerned that someone would really happen to know how to hack me through this, but the FIFOs' permission will prevent this.

    To Andrew: Maybe someday I'll come up with my own emacs mode for skill, if that's so I'll release the source code ;)

     

    Guillaume

     

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    gsimard said:
    To Andrew: Maybe someday I'll come up with my own emacs mode for skill, if that's so I'll release the source code ;)

    Guillaume

     

    Excellent! I'll look forward to it! (I might even have to learn emacs; every so often I try, and then find that when I want to do something complicated, I'm too impatient to work it out, so I revert to "vi" which I know inside out, and can do anything in...)

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • gsimard
    gsimard over 16 years ago

     Same here for "vi", never went past the tutorial :)

     

    I have a seemingly obvious question related to ports in SKILL, when invoking (infile "/tmp/skill-pipe") in the icfb, one usually has to keep the return value in a variable for later usage with reading and writing functions. In the icfb, however, the result of invoking (infile ...) is something like port:"/tmp/skill-pipe". Isn't it possible to use this string as a variable in itself to access the file ? ie:

    (infile "/tmp/skill-pipe") => port:"/tmp/skill-pipe"

    (lineread port:"/tmp/skill-pipe")

    This will fail because clearly it thinks I'm trying to do a range between unbound variable "port" and string "/tmp/skill-pipe".

    In Lisp (but not SKILL it seems), port:"/tmp/skill-pipe" would be something called a READ synthax, which means you could use it as the port itself instead of using a variable holding the value of the port as in:

     p = (infile "/tmp/skill-pipe") => port:"/tmp/skill-pipe"

    (lineread p)

     

    I hope this is a bit clear to you guys,

    Guillaume

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • skillUser
    skillUser over 16 years ago

     Hi Guillaume,

     For SKILL you must store the return value of infile/outfile to be able to use the port (and later close it).  As far as I know there is no way to obtain a port object that was not stored (stdout, stdin and stderr are already stored for us).

    Hope this answers your question,

    Lawrence.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • skillUser
    skillUser over 16 years ago

     Oh and I forgot to mention, I do not know emacs/xemacs either, I'm a vi/vim person myself too :-) [in fact, I learned a fair bit from Andrew]

    Yes, you cannot type "port:"*stdout*", for example, to access the stdout port, and likewise for other port objects.

    Lawrence.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Andrew Beckett
    Andrew Beckett over 16 years ago

    Indeed, Lawrence is on the money. What you're seeing with the port:"/tmp/..." bit is merely the print representation of the object. There's no guarantee that the print representation of any object can be used as input syntax. Think of db objects, and so on. There are odd cases (for example, there's the funobj() function which can be used to retrieve a function object given its id, but even then these have to be used with caution because the id won't stay the same in different sessions.

    That said, there's nothing to stop you writing a SKILL++ package using closures which could be used for opening and closing ports - and this could store internally (in private, non-global data) the mapping between file names and ports, so you could then have a function to retrieve the port given the filename. 

    I just threw this together:

    /* abPort.ils
    
    Author     A.D.Beckett
    Group      Custom IC (UK), Cadence Design Systems Ltd.
    Language   SKILL
    Date       Jul 16, 2009 
    Modified   
    By         
    
    Package to manage ports...
    
    ***************************************************
    
    SCCS Info: @(#) abPort.ils 07/16/09.18:53:08 1.1
    
    */
    
    (importSkillVar abPort)
    (setq abPort
    (let ((portStorage (makeTable 'portStorage nil)))
      (defun infilePort (@rest args)
        (setarray portStorage (car args) (apply infile args))
        )
      (defun outfilePort (@rest args)
        (setarray portStorage (car args) (apply outfile args))
        )
      (defun closePort (port)
        (remove (get_filename port) portStorage)
        (close port)
        )
      (defun getPort (fileName)
        (arrayref portStorage fileName)
        )
      (list 
        nil 
        'infile infilePort 
        'outfile outfilePort
        'close closePort
        'get getPort
        )
      )
    )
    
    

    To use it, you'd do:

    prt=abPort->outfile("/tmp/stuff")

    If you've lost contact with your variable, you can then do:

    abPort->get("/tmp/stuff")

    and get the port back again for the given fileName.

    Regards,

    Andrew.

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • jtschaff
    jtschaff over 16 years ago

    hi guillaume - it sounds like you've settled on a solution, but you might consider using dbAccess rather than icfb. to be honest it doesn't sound like it suits your needs - there are no graphics - but i thought it was worth mentioning just in case. it provides full skill/database access and starts much quicker than icfb. (we use it primarily to get technology library data to customize physical verification decks.) as for the IPC, if you're using perl then i recommend the IPC::Run module, which works great for bidirectional communication.

    hth,

    toby

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
  • Stephane A
    Stephane A over 15 years ago

    Dear all, dear Andrew,

    Thanks to your post, I started to write Skill and Perl programs to have a Perl sript send commands to ICFB.

    I tried 3 methodologies:

    1/ icpBeginProcess with a call back that directly calls the Perl program.

    2/ ipcSkillProcess with a call back that directly call thePerl program through the "3" chanel ID.

    3/ A Linux socket through the tcl script of Andrew above (it uses ipcBeginProcess and Linux socket).

     

    All of these solution works, but all share the same issue: even though I flush the Perl script output buffer (STDOUT or "3" or socket handle) it happens almost randomly that the commands recovered by ICFB is too long and ends cutted in the middle of skill commands.

    It happens when the Perl script sends hundreds of commands at once in a loop, like:

    SKILL test.il:

     procedure(socketHandler(ipcId data)
      printf("COMMAND: %L\n" data)
      evalstring(data)
    )

    ipcBeginProcess("./test.pl" "" 'socketHandler)

    PERL test.pl (draws a red disk in the current layout windows):

     #!/usr/bin/perl

    #Flushes the perl STDOUT buffer after each print:
    $|=1;

    print "cv=deGetEditCellView() ";
    print "cw=hiGetCurrentWindow() ";
    print "geDeleteAllHilightSet(cv) ";
    print "hiZoomIn(cw list(-10:-10 10:10)) ";
    print "hlSetId = geCreateHilightSet(cv \'(\"y1\" \"drawing\")) ";
    print "hlSetId->enable = t ";

    for ($j = 1; $j <= 3.141*2000; $j++) {
      $x2=10*cos($j/1000);
      $y2=10*sin($j/1000);
      print "geAddHilightLine(hlSetId list(0:0 $x2:$y2)) ";
    }

    print "hiRedraw(cw) ";

    After running this test script, the pie drawn has missing parts (missing rays).

    Does anyone have a clue how to solve this?

    Stéphane.

     

    • Cancel
    • Vote Up 0 Vote Down
    • Cancel
>

Community Guidelines

The Cadence Design Communities support Cadence users and technologists interacting to exchange ideas, news, technical information, and best practices to solve problems and get the most from Cadence technology. The community is open to everyone, and to provide the most value, we require participants to follow our Community Guidelines that facilitate a quality exchange of ideas and information. By accessing, contributing, using or downloading any materials from the site, you agree to be bound by the full Community Guidelines.

© 2025 Cadence Design Systems, Inc. All Rights Reserved.

  • Terms of Use
  • Privacy
  • Cookie Policy
  • US Trademarks
  • Do Not Sell or Share My Personal Information