Home > Community > Forums > Digital Implementation > Multi point CTS implementation

Email

* Required Fields

Recipients email * (separate multiple addresses with commas)

Your name *

Your email *

Message *

Contact Us

* Required Fields
First Name *

Last Name *

Email *

Company / Institution *

Comments: *

 Multi point CTS implementation 

Last post Wed, Dec 4 2013 5:31 AM by fitz. 5 replies.
Started by vamsi611 28 Nov 2013 11:17 PM. Topic has 5 replies and 5128 views
Page 1 of 1 (6 items)
Sort Posts:
  • Thu, Nov 28 2013 11:17 PM

    • vamsi611
    • Not Ranked
    • Joined on Fri, Apr 26 2013
    • Ahmedabad, Gujarat
    • Posts 4
    • Points 80
    Multi point CTS implementation Reply

    I have a netlist and def with single clock port clk.

    I want to implement multi point cts with 4 clocks(clk1,clk2,clk3,clk4).They are equilent to clock port clk.

    What are the flow steps in encounter to  implement this multipoint CTS.

    (How can create 4 new clock ports and remove old clock port clk, how to take care of clock connectivity in the design and implementation of multi point CTS)

    • Post Points: 20
  • Mon, Dec 2 2013 9:01 AM

    • fitz
    • Top 150 Contributor
    • Joined on Wed, Aug 4 2010
    • Kanata, Ontario
    • Posts 56
    • Points 745
    Re: Multi point CTS implementation Reply

    Been there done that , but I would not do it the same way again.
    We used multiple  discrete  DLL drops points for a main clock in a physically large block.
    Basically we would run a regular placeDesign and then disconnect all of the clock leafs and reconnect them to the closest DLL with a tcl script.
    All fun and games until you get to timeDesign and realize you are now essentially randomly crossing clock domains.
    Even more fun when you add clock gating and  DFT scan reorder mode to the mix.

    Next time I would restrict the multiple clock domains to follow the logical hierarchy and the placement floorplan fences.
    i.e. moduleA has a placement fenceA and uses clkA , moduleB has a placement fenceB and uses clkB etc. etc.
    That way the manual clock edits to the verilog are simple you can predict / anticipate potential domain crossings timing issues.

    The KISS principle rules ( Keep It Simple Stupid ) especially where clock is concerned.

    First try a single central clock drop point, if your block is not too convoluted clockDesign with tuning can do a very good job.
    If you are trying to reduce total insertion delay,  manually route the top level clock tree root net to a central location in each of your hierarchical blocks.
    You will have to run some spice simulations to determine the optimal root routing style, start with, top two metals, double wide, quad via, double spaced.

    Shawn


     

    • Post Points: 20
  • Mon, Dec 2 2013 9:09 PM

    • vamsi611
    • Not Ranked
    • Joined on Fri, Apr 26 2013
    • Ahmedabad, Gujarat
    • Posts 4
    • Points 80
    Re: Multi point CTS implementation Reply

     Hi Shawn,

    Thanks for the reply.

    Here your are disconecting clock leaf  and reconnecting to nearest clock port.

    Can you please share the script which is doing this job.

     

    Thanks and Regards,

    Vamsi.

    • Post Points: 20
  • Tue, Dec 3 2013 5:06 AM

    • fitz
    • Top 150 Contributor
    • Joined on Wed, Aug 4 2010
    • Kanata, Ontario
    • Posts 56
    • Points 745
    Re: Multi point CTS implementation Reply

    Vamsi:
    You were not listening!
    "Next time I would restrict the multiple clock domains to follow the logical hierarchy and the placement floorplan fences."
    KISS, you have not figured out all of the complex ramifications yet.
    But if you insist, the script that our local Ottawa Cadence AE Stefano wrote for us follows....it's slick coding.

    Shawn

    ############################################################################################################
    # connectRegsToClosestDP.tcl
    # V. 1.2b, Apr 18 2011
    # Stefano Somenzi, CADENCE
    #
    # This procedure connects each flop to the closest drop point.
    # Gating cells are cloned if needed.
    # User has to supply 4 parameters in the following order :
    # 1. name of the top level clock port that drives the design flops
    # 2. a pattern matching the hierarchical name of all the drop point pins
    # 3. the name of the eco file where the commands to manipulate the
    # netlist will be written out.
    # 4. (OPTIONAL) the name of a file where the list of hierarchical instances
    # to be treated as black boxes is provided. Such hinstances will be reattached
    # "as is" to the drop point specified by the user.
    # FILE SYNTAX EXAMPLE
    # dp1/Z bist
    # where :
    # 1st field : drop point to which the pins of the hierarchical instance specified later
    # will be re-attached
    # 2nd field : hinst name whose pins connected to the top level clock port will
    # be reattached to the specified dp
    #
    # KNOWN LIMITATIONS :
    # - one single level of gating logic is supported
    # - only gating cells supported are icg, buf, inv
    # - square brackets in net/instance names not supported
    #
    # IMPORTANT NOTE :
    # TIMING LIBRARIES MUST BE LOADED FOR THE CODE TO WORK PROPERLY
    #
    # Usage :
    #   connectRegsToClosestDP < clock port name> <pattern to match drop point pins> <ecofile name> {<bboxList>}
    #
    ############################################################################################################

    set connectRegsToClosestDPVerbose 0

    proc isPinPlaced { pin } {
      set instName [get_property [get_cells -of_objects [get_pin $pin]] hierarchical_name]
      return [dbIsInstPlaced [dbGetInstByName $instName]]
    }

    logCommand connectRegsToClosestDP

    proc connectRegsToClosestDP { args } {
    global dbgTopCellName connectRegsToClosestDPVerbose

      if {[llength $args] < 3} {
        Puts "Err : usage connectRegsToClosestDP <clockPort> <dropPointKey> <ecoFile> {<bboxList>}"
        return -2
      }

      set clkPortName [lindex $args 0]
      set DPkey [lindex $args 1]
      set ecoFile [lindex $args 2]

      if {[llength $args] > 3} {
        set bboxList [lindex $args 3]
        Puts "Info : running connectRegsToClosestDP $clkPortName $DPkey $ecoFile $bboxList"
      } else {
        Puts "Info : running connectRegsToClosestDP $clkPortName $DPkey $ecoFile"
      }

      if {![isDesignInMemory]} {
        Puts "Err : design is not in memory"
        return -1
      }

      set clockPort [get_ports -quiet $clkPortName]

      if {[sizeof_collection $clockPort] == 0} {
        Puts "Err : no clock ports with the name $clkPortName"
        return -1
      }

      if {[sizeof_collection $clockPort] > 1} {
        Puts "Err : more than one clock port matching name $clkPortName"
        return -1
      }

      if {[catch {open $ecoFile "w"} fptr] != 0} {
        Puts "Err : failed to open net eco file $ecoFile"
        return -1
      }

      if {[llength $args] > 3 && [catch {open $bboxList "r"} fptr1] != 0} {
        Puts "Err : failed to open bbox list file file $bboxList"
        return -1
      }

      set dropPoints [get_pins -quiet $DPkey]

      if {[sizeof_collection $dropPoints] == 0} {
        Puts "Err : no drop points with the give key $DPkey"
        return -1
      }

      set err 0

      foreach_in_collection dropPoint $dropPoints {
        if {![isPinPlaced $dropPoint]} {
          Puts "Err : drop point $dpName is unplaced"
          set err 1
        }
        set dpName [get_property $dropPoint hierarchical_name]
        set addedRegPinNum($dpName) 0
        set addedGatNum($dpName) 0
        set addedBboxNum($dpName) 0
        set addedBboxPinNum($dpName) 0
      }

      set bbList {}

      if {[llength $args] > 3} {
        Puts "Info : parsing bbox list file $bboxList"
        set ln 0
        dbForEachFileLine $bboxList line {
          incr ln
          regsub -all { +} $line { } line
          regsub {^ } $line {} line
          regsub { $} $line {} line

          if {[string range $line 0 0] == "#"} { continue }
          if {[llength $line] == 0} { continue }
          if {[llength $line] < 2} {
            Puts "Err : less than 2 fields at line $ln"
            set err 1
            continue
          }

          set dropPointName [lindex $line 0]
          set dropPoint [get_pins -quiet $dropPointName]
          if {[sizeof_collection $dropPoint] == 0} {
            Puts "Err : drop point $dropPointName at line $ln does not exist"
            set err 1
          }

          set hinstName [lindex $line 1]
          set hinst [get_cells -quiet $hinstName]
          if {[sizeof_collection $hinst] == 0} {
            Puts "Err : hierarchical instance $hinstName at line $ln does not exist"
            set err 1
          }

          lappend bbList $hinstName
          set hinstDpName($hinstName) $dropPointName
        }
      }

      if {$err} { return -1 }

      set bbList [lsort -unique $bbList]

      set removedRegPinNum 0
      set removedGatNum 0
      set removedBboxNum 0
      set removedBboxPinNum 0

      # writes eco file header
      set line "# Eco file to reconnect each register of design $dbgTopCellName to the closest drop point"
      puts $fptr [string repeat # [string length $line]]
      puts $fptr $line
      puts $fptr "# Clock port name is : $clkPortName"
      puts $fptr "# Drop point keyword is : $DPkey"
      puts $fptr "# Created on [clock format [clock seconds]] by connectRegsToClosestDP v. 1.2b"
      puts $fptr [string repeat # [string length $line]]

      # finds output net for each drop point; net is created if does not exist
      set missingDpNet 0
      foreach_in_collection dropPoint $dropPoints {
        if {[get_property $dropPoint net_name] == "NA"} { set missingDpNet 1 }
      }
      if {$missingDpNet} {
        puts $fptr "\n# creating output nets for drop points that don't have one"
      }
      foreach_in_collection dropPoint $dropPoints {
        set dropPointName [get_property $dropPoint hierarchical_name]
        set dropPointOutNetName [get_property $dropPoint net_name]
     
        if {$dropPointOutNetName == "NA"} {
          set lastSlashIndex [string last / $dropPointName]
          set dropPointTermName [string range $dropPointName [expr $lastSlashIndex +1] end]
          set dropPointInstName [string range $dropPointName 0 [expr $lastSlashIndex -1]]
          set dropPointOutNetName ${dropPointInstName}_${dropPointTermName}_DPCLKOUTNET
          puts $fptr "addNet $dropPointOutNetName"
          puts $fptr "attachTerm $dropPointInstName $dropPointTermName $dropPointOutNetName"
        }
     
        set netAttached($dropPointName) $dropPointOutNetName
      }

      # attaching black box hinstance clock pins to user specified drop point
      if {[llength $bbList] > 0} {
        puts $fptr "\n# moving black box hinstance clock pins to user defined drop point"
        foreach hinstName $bbList {
          set hinst [get_cells -quiet $hinstName]
          set pins [get_pins -quiet -of_objects $hinst -filter "net_name==$clkPortName"]
          if {[sizeof_collection $pins] == 0} {
            Puts "Warn : bbox hinstance $hinstName ignored as it does not have any pin connected to $clkPortName"
            continue
          }
          if {$connectRegsToClosestDPVerbose} {
            Puts "Info : moving black box hinstance $hinstName clock pins to user defined drop point $hinstDpName($hinstName)"
          }
          foreach_in_collection pin $pins {
            set termName [get_property $pin name]
            puts $fptr "attachModulePort $hinstName $termName $netAttached($hinstDpName($hinstName))"
          }
          incr addedBboxNum($hinstDpName($hinstName))
         
          # finds bbox pin fanout ( inside of the bbox only )
          incr removedBboxNum
          set bboxPinNum [expr [sizeof_collection $pins] * -1]
          foreach_in_collection pin [filter_collection [all_fanout -from $pins] {direction==in}] {
            if {[string match $hinstName/* [get_property $pin hierarchical_name]]} { incr bboxPinNum }
          }
          set removedBboxPinNum [expr $removedBboxPinNum + $bboxPinNum]
          set addedBboxPinNum($hinstDpName($hinstName)) [expr $addedBboxPinNum($hinstDpName($hinstName)) + $bboxPinNum]
        }
      }

      set gatNameList {}

      set regClkPins [filter_collection [all_registers -clock_pins] "is_clock_gating_clock != true"]

      # parsing the collection of register clock pins in the design
      foreach_in_collection regClkPin $regClkPins {
        set regClkPinName [get_property $regClkPin hierarchical_name]

        # register inside bboxes are ignored
        set isRegInBB 0
        foreach hinstName $bbList {
          if {[string match "$hinstName/*" $regClkPinName]} { set isRegInBB 1 }
        }
        if {$isRegInBB} { continue }

        set levelNum [sizeof_collection [all_fanin -to $regClkPin]]

        if {$levelNum == 1} {
          Puts "Warn : register clock pin $regClkPinName ignored as dangling"
          continue
        }

        # registers not connected to clock port are ignored
        set rootPorts [index_collection [all_fanin -startpoints_only -to $regClkPin] 0]
        set clockPortFl 0
        foreach_in_collection rootPort $rootPorts {
          if {[get_property $rootPort hierarchical_name] == $clkPortName} {
            set clockPortFl 1
            break
          }
        }
        if {!$clockPortFl} { continue }

        # checking for clock feedthrough across bbox hinstances
        if {$levelNum > 3} {
          set bboxDrivingReg ""
          set instsOutOfBbox 0
          foreach_in_collection pin [filter_collection [all_fanin -to $regClkPin] {direction==in && is_pin==true}] {
            set pinName [get_property $pin hierarchical_name]
            if {$pinName == $regClkPinName} { continue }
            foreach hinstName $bbList {
              if {$bboxDrivingReg == "" && [string match "$hinstName/*" $pinName]} {
                set bboxDrivingReg $hinstName
              }
              if {![string match "$hinstName/*" $pinName]} { set instsOutOfBbox 1 }
            }
          }
          if {$bboxDrivingReg != ""} {
            incr addedRegPinNum($hinstDpName($bboxDrivingReg))
            Puts "Warn : register clock pin $regClkPinName ignored as bbox hinst $bboxDrivingReg is in its fanin cone"
            if {$instsOutOfBbox} {
              Puts "Warn : fanin cone for register clock pin $regClkPinName includes also instances not from any bbox hinst"
              Puts "       This might lead to a final incorrect removedRegPinNum count"
            } else {
              incr removedRegPinNum
            }
            continue
          }
        }

        # registers with more than 2 levels of logic from the clock port or driven by multiplexing
        # logic are ignored
        if {$levelNum > 4} {
          Puts "Warn :  register clock pin $regClkPinName ignored as far more than 2 levels from root $clkPortName"
          Puts "        or driven by multiplexing logic"
          continue
        }

        # unplaced registers are ignored
        if {![isPinPlaced $regClkPin]} {
          Puts "Warn : register clock pin $regClkPinName ignored as unplaced"
          continue
        }

        set lastSlashIndex [string last / $regClkPinName]
        set regInstName [string range $regClkPinName 0 [expr $lastSlashIndex -1]]
        set regClkTermName [string range $regClkPinName [expr $lastSlashIndex +1] end]

        # finds drop point closest to register
        set minDist 100000000.0
        foreach_in_collection dropPoint $dropPoints {
          set distX [expr abs([get_property $dropPoint x_coordinate] - [get_property $regClkPin x_coordinate])]
          set distY [expr abs([get_property $dropPoint y_coordinate] - [get_property $regClkPin y_coordinate])]
          if {$minDist > [expr $distX + $distY]} {
            set minDist [expr $distX + $distY]
            set closestDropPoint $dropPoint
          }
        }

        set closestDropPointName [get_property $closestDropPoint hierarchical_name]
        set lastSlashIndex [string last / $closestDropPointName]
        set closestDropPointTermName [string range $closestDropPointName [expr $lastSlashIndex +1] end]
        set closestDropPointInstName [string range $closestDropPointName 0 [expr $lastSlashIndex -1]]
        set closestDropPointNetName $netAttached($closestDropPointName)

        incr addedRegPinNum($closestDropPointName)
        incr removedRegPinNum

        if {$levelNum == 2} {
        # register clock pin attached directly to clock port
          if {$connectRegsToClosestDPVerbose} {
            Puts "Info : moving register pin $regClkPinName to drop point $closestDropPointName"
          }
          puts $fptr "\n# moving register pin $regClkPinName to drop point $closestDropPointName"
          puts $fptr "attachTerm $regInstName $regClkTermName $closestDropPointNetName"

        } else {
        # levelNum==4 means there is a gate between clock port and reg

          set regGat [index_collection [all_fanin -only_cells -levels 1 -to $regClkPin] 1]
          set regGatName [get_property $regGat hierarchical_name]

          regsub -all "/" $closestDropPointInstName "_" cdpInstName
          set cloneGatClkOutNetName ${regGatName}_${cdpInstName}_CLONECLKOUTNET

          if {![info exists fanoutNr($regGatName)]} {
            set endPoints [all_fanout -from [get_pins -of_objects $regGat -filter "@direction == out"] -endpoints_only]
            set fanoutNr($regGatName) [sizeof_collection $endPoints]
            lappend gatNameList $regGatName
          }
          set fanoutNr($regGatName) [expr $fanoutNr($regGatName) - 1]

          if {![info exists isCloneGat($closestDropPointName.$regGatName)]} {
          # first time that a clone gat is made for that drop point

            set isCloneGat($closestDropPointName.$regGatName) 1
            incr addedGatNum($closestDropPointName)

            # creates the clone instance
            set cloneGatInstName ${regGatName}_${cdpInstName}_CLONEINST
            puts $fptr "\n# creating clone gating instance $cloneGatInstName"
            puts $fptr "addInst -cell [get_property $regGat ref_lib_cell_name] -inst $cloneGatInstName"

            # creates the clone clock out net
             puts $fptr "addNet $cloneGatClkOutNetName"
             puts $fptr "specifyNetWeight $cloneGatClkOutNetName 10"

            foreach_in_collection pin [get_pins -of_objects $regGat] {
            # connecting clone gat pins

              set cloneGatNetName [get_property $pin net_name]
              if {$cloneGatNetName == "NA"} { continue }

              # will connect cloneGatClkOutNetName to gate out pin
              if {$cloneGatNetName == [get_property $regClkPin net_name]} {
                set cloneGatNetName $cloneGatClkOutNetName
              }

              # will connect clone gat input clock pin to closest drop point
              if {$cloneGatNetName == [get_property [get_ports $clkPortName] net_name]} {
                set cloneGatNetName $closestDropPointNetName
              }

              set gatPinName [get_property $pin hierarchical_name]
              set lastSlashIndex [string last / $gatPinName]
              set gatTermName [string range $gatPinName [expr $lastSlashIndex +1] end]
     
              puts $fptr "attachTerm $cloneGatInstName $gatTermName $cloneGatNetName"
            }
          }

          # connects reg clk pin to clone gate ouput pin
          if {$connectRegsToClosestDPVerbose} {
            Puts "Info : moving register pin $regClkPinName to drop point $closestDropPointName"
          }
          puts $fptr "\n# moving register pin $regClkPinName to drop point $closestDropPointName"
          puts $fptr "attachTerm $regInstName $regClkTermName $cloneGatClkOutNetName"
        }
      }

      # removing gating instances with dangling clkOut pin
      puts $fptr "\n# removing gating instances with dangling clkOut pin"
      foreach gatName $gatNameList {
        if {$fanoutNr($gatName) == 0} {
          puts $fptr "deleteInst $gatName"
          incr removedGatNum
        } else {
          Puts "Warn : gating inst $gatName cannot be removed as still driving some registers"
          puts $fptr "# gating inst $gatName cannot be removed as still driving some registers"
        }
      }

      # removing clock port if dangling
      set fanoutFromClockPort [filter_collection [all_fanout -from $clockPort] {direction==in && is_pin==true}]
      set clockTreePinNum [sizeof_collection $fanoutFromClockPort]
      if {$clockTreePinNum == [expr $removedGatNum + $removedRegPinNum + $removedBboxPinNum]} {
        puts $fptr "\n# removing dangling clock port $clkPortName"
        puts $fptr "deleteModulePort - $clkPortName"
      } else {
        Puts "Warn : clockPort $clkPortName cannot be removed as still driving some logic"
      }

      puts $fptr "\necoPlace"

      # writing final summary
      Puts \n[string repeat = 80]
      Puts "                  SUMMARY"
      Puts [string repeat = 80]
      Puts "dropPoint\taddedRegPinNum\taddedGatNum\taddedBboxPinNum\taddedBboxNum"

      foreach_in_collection dropPoint $dropPoints {
        set dpName [get_property $dropPoint hierarchical_name]
        set dpNameStr $dpName
        if {[string length $dpName] < 16} { set dpNameStr "$dpNameStr\t" }
        if {[string length $dpName] < 8} { set dpNameStr "$dpNameStr\t" }

        set line "$dpNameStr$addedRegPinNum($dpName)\t\t$addedGatNum($dpName)"
        set line "$line\t\t$addedBboxPinNum($dpName)\t\t$addedBboxNum($dpName)"

        Puts $line
      }
      Puts "\noriginal clock tree input pin number : $clockTreePinNum"
      Puts "number of register clock pins detached from original clock tree : $removedRegPinNum"
      Puts "number of gating instances detached from original clock tree : $removedGatNum"
      Puts "number of bbox hinstance pins detached from original clock tree : $removedBboxPinNum"
      Puts "number of bbox hinstances detached from original clock tree : $removedBboxNum"

      Puts "\nInfo : connectRegsToClosestDP completed successfully; eco file is $ecoFile"
      close $fptr
      return 0
    }

    • Post Points: 20
  • Wed, Dec 4 2013 2:11 AM

    • vamsi611
    • Not Ranked
    • Joined on Fri, Apr 26 2013
    • Ahmedabad, Gujarat
    • Posts 4
    • Points 80
    Re: Multi point CTS implementation Reply

     Hi Shawn,

    Thanks for sending me the script.

    I understand that you want to restrict the multiple clock domains to follow the logical hierarchy and the placement floorplan fence to avoid

    domain crossing issues.

    Thanks alot

    Regards,

    vamsi.

    • Post Points: 20
  • Wed, Dec 4 2013 5:31 AM

    • fitz
    • Top 150 Contributor
    • Joined on Wed, Aug 4 2010
    • Kanata, Ontario
    • Posts 56
    • Points 745
    Re: Multi point CTS implementation Reply

    Vamsi ... you have almost got it!

    I still suggest starting with the simplest  clock possible and see if clockDesign can meet your requirements.
    Start with one drop, If not, try two, then three, then four........ no sense in making your life more complicated than it already is.  

    The only reason we required multiple clock drops was to reduce clock insertion latency on the high speed interface module to full custom ADC.
    The ADC was 16mm tall and the interface module was pitch matched at 2mm x 16mm,  we could not meet the maximum latency specification across the full 16mm distance.
    We ended up requiring  four clock drops, if I were to do this again I would request to have interface RTL coded into four separate self contained channels from the get go.
    The layout would then be one module replicated four times , too easy.

    Rant #1
    One thing the RTL designers don't seem to comprehend is the importance of logical hierarchy.
    An optimal logical hierarchy allows us to  decide  the optimal layout strategy in ... hmm ... layout.
    Layout can choose to use or ignore logical hierarchy ( partition, region, guide, modulePadding  etc etc etc )
    Flatland RTL coding offers the layout team no options but to take one possibly very difficult route.
    Sorry for the rant, I have to try and convince an RTL designers boss, that 1 man week re-coding / re-verifying will save me 4 weeks in layout.

    Shawn

    • Post Points: 5
Page 1 of 1 (6 items)
Sort Posts:
Started by vamsi611 at 28 Nov 2013 11:17 PM. Topic has 5 replies.