ranan-usp | e6a8abc | 2022-05-23 07:01:33 +0900 | [diff] [blame] | 1 | # Copyright 2021 The University of Michigan |
| 2 | # Copyright 2022 Efabless Corporation |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | |
| 16 | proc insert_buffer {pin_name pin_type master_name net_name inst_name} { |
| 17 | set db [ord::get_db] |
| 18 | set block [ord::get_db_block] |
| 19 | |
| 20 | # Create buffer instance |
| 21 | set master [$db findMaster $master_name] |
| 22 | if { $master == "NULL" } { |
| 23 | puts "Buffer cell '$master' not found." |
| 24 | exit -1 |
| 25 | } |
| 26 | |
| 27 | set inst [odb::dbInst_create $block $master $inst_name] |
| 28 | |
| 29 | # Figure out the inputs & outputs of the master |
| 30 | foreach mterm [$master getMTerms] { |
| 31 | if {[$mterm getSigType] == "POWER"} { |
| 32 | continue |
| 33 | } |
| 34 | if {[$mterm getSigType] == "GROUND"} { |
| 35 | continue |
| 36 | } |
| 37 | if {[$mterm getIoType] == "INPUT"} { |
| 38 | set input $mterm |
| 39 | } |
| 40 | if {[$mterm getIoType] == "OUTPUT"} { |
| 41 | set output $mterm |
| 42 | } |
| 43 | } |
| 44 | |
| 45 | # New net to connect to |
| 46 | set new_net [odb::dbNet_create $block $net_name] |
| 47 | |
| 48 | if {$pin_type=="ITerm"} { |
| 49 | # Finding the block with pin name |
| 50 | set iterm [$block findITerm $pin_name] |
| 51 | if { $iterm == "NULL" } { |
| 52 | puts "Instance terminal '$pin_name' not found." |
| 53 | exit -1 |
| 54 | } |
| 55 | set old_net [$iterm getNet] |
| 56 | |
| 57 | # Original disconnect command |
| 58 | odb::dbITerm_disconnect $iterm |
| 59 | |
| 60 | # Original connect command |
| 61 | odb::dbITerm_connect $iterm $new_net |
| 62 | |
| 63 | # Set I/O of iterm (Buffer) |
| 64 | set in_iterm [$inst getITerm $input] |
| 65 | set out_iterm [$inst getITerm $output] |
| 66 | |
| 67 | if { ![info exists ::env(INSERT_BUFFER_NO_PLACE)] } { |
| 68 | # define the instance to which the buffer inserted will connected to |
| 69 | set master_inst [$iterm getInst] |
| 70 | # get the geometry of the instance, geometry means its shape, the coordinate of its vertex... |
| 71 | set box [$master_inst getBBox] |
| 72 | |
| 73 | # get the position of the lower left point of this instance |
| 74 | set x_min [$box xMin] |
| 75 | set y_min [$box yMin] |
| 76 | |
| 77 | # $inst is the buffer we want to insert, now insert it in the position of the instance it is connected to, |
| 78 | # using setLocation, and detail_place will help us separate them |
| 79 | [$inst setLocation $x_min $y_min] |
| 80 | [$inst setPlacementStatus PLACED] |
| 81 | } |
| 82 | |
| 83 | odb::dbITerm_connect $in_iterm $new_net |
| 84 | odb::dbITerm_connect $out_iterm $old_net |
| 85 | |
| 86 | } else { |
| 87 | # Finding the block with pin name |
| 88 | set bterm [$block findBTerm $pin_name] |
| 89 | set old_net [$bterm getNet] |
| 90 | set net_out_iterm [odb::dbNet_get1stITerm $old_net] |
| 91 | set old_net_inst [$net_out_iterm getInst] |
| 92 | set net_mterm [$net_out_iterm getMTerm] |
| 93 | set old_net_input $net_mterm |
| 94 | odb::dbITerm_disconnect $net_out_iterm |
| 95 | |
| 96 | if { ![info exists ::env(INSERT_BUFFER_NO_PLACE)] } { |
| 97 | set box [$bterm getBBox] |
| 98 | |
| 99 | # get the position of the lower left point of this instance |
| 100 | set x_min [$box xMin] |
| 101 | set y_min [$box yMin] |
| 102 | |
| 103 | # $inst is the buffer we want to insert, now insert it in the position of the instance it is connected to, |
| 104 | # using setLocation, and detail_place will help us separate them |
| 105 | [$inst setLocation $x_min $y_min] |
| 106 | [$inst setPlacementStatus PLACED] |
| 107 | } |
| 108 | |
| 109 | # Find output/input of buffer iterm |
| 110 | set in_iterm [$inst getITerm $input] |
| 111 | set out_iterm [$inst getITerm $output] |
| 112 | |
| 113 | odb::dbITerm_connect $out_iterm $new_net |
| 114 | odb::dbITerm_connect $net_out_iterm $new_net |
| 115 | odb::dbITerm_connect $in_iterm $old_net |
| 116 | } |
| 117 | } |
| 118 | |
| 119 | if { [info exists ::env(INSERT_BUFFER_COMMAND) ]} { |
| 120 | if {[catch {read_lef $::env(MERGED_LEF)} errmsg]} { |
| 121 | puts stderr $errmsg |
| 122 | exit 1 |
| 123 | } |
| 124 | |
| 125 | if {[catch {read_def $::env(CURRENT_DEF)} errmsg]} { |
| 126 | puts stderr $errmsg |
| 127 | exit 1 |
| 128 | } |
| 129 | |
| 130 | set arg_list [split $::env(INSERT_BUFFER_COMMAND) " "] |
| 131 | insert_buffer {*}$arg_list |
| 132 | |
| 133 | write_def $::env(SAVE_DEF) |
| 134 | } |