Responsibilities of a CAD Engineer: Development of a flow, deployment/integration and support. Developing a flow involves working on different nanometer technology nodes and flow tools.Work with vendors (CDNS/SNPS/MENTOR) who provide the access to designated tools and develop the flow structure as per the nm specs. Deployment is integrating your flow in a structural environment that acts as a user interface. Once the flow is released to the user, a CAD Engineer should be able to support the designer to resolve the flow issues, if any. What to learn : Automation is the easy way of exploring a design using a tool. It is a mere saving of time to do any repetitive work. This requires knowledge on design concepts, tools and finally scripting. Tools and scripting are interlinked. Languages like tcl, perl, python provide a Graphical user Interface(GUI) for a designer to explore the design. They come in handy while automating the tasks as well. For example, Tempus/Innovus command interface (shell), speaks, listens and understands tcl Tutorials: Tcl : https://www.tutorialspoint.com/tcl-tk/index.htm Regexp : https://www.tutorialspoint.com/tcl-tk/tcl_regular_expressions.html Execute Tcl online platform: https://www.tutorialspoint.com/execute_tcl_online.php Example scripts 1. Script to report the endpoints, startpoints and slack of top 1000 failing paths set rpt [report_timing -max_paths 1000 -max_slack 0 -collection] foreach_in_collection r $rpt { puts "Endpoint: [get_property [get_property $r capturing_point] hierarchical_name] \t Startpoint: [get_property [get_property $rlaunching_point] hierarchical_name] \t Slack: [get_property $r slack]" } Output: Endpoint: tdigit[7] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_7/CK Slack: -0.727 Endpoint: tdigit_flag Startpoint: DTMF_INST/DIGIT_REG_INST/flag_out_reg/CK Slack: -0.495 Endpoint: tdigit[6] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_6/CK Slack: -0.488 Endpoint: tdigit[5] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_5/CK Slack: -0.409 Endpoint: tdigit[4] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_4/CK Slack: -0.353 Endpoint: tdigit[0] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_0/CK Slack: -0.266 Endpoint: tdigit[3] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_3/CK Slack: -0.218 Endpoint: tdigit[1] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_1/CK Slack: -0.189 Endpoint: tdigit[2] Startpoint: DTMF_INST/DIGIT_REG_INST/digit_out_reg_2/CK Slack: -0.184 2. To return all the instance pins that are used in the path set paths [report_timing -collection] foreach_in_collection path $paths { Puts “set timingPoints [get_property $path timing_points]” foreach_in_collection point $timingPoints { set pinPtr [get_property $point pin] set pin [get_object_name $pinPtr] Puts $pin } } Output: TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/Q TDSP_CORE_INST/EXECUTE_INST/FE_PSC541_sel_op_a_2_/A TDSP_CORE_INST/EXECUTE_INST/FE_PSC541_sel_op_a_2_/Z TDSP_CORE_INST/TDSP_CORE_GLUE_INST/Fn0090D/A TDSP_CORE_INST/TDSP_CORE_GLUE_INST/Fn0090D/ZN TDSP_CORE_INST/TDSP_CORE_GLUE_INST/FE_RC_1304_0/A3 TDSP_CORE_INST/TDSP_CORE_GLUE_INST/FE_RC_1304_0/ZN TDSP_CORE_INST/TDSP_CORE_GLUE_INST/FE_OCPC334_n_2/A TDSP_CORE_INST/TDSP_CORE_GLUE_INST/FE_OCPC334_n_2/Z TDSP_CORE_INST/EXECUTE_INST/FE_PSC520_n_650/A TDSP_CORE_INST/EXECUTE_INST/FE_PSC520_n_650/Z TDSP_CORE_INST/EXECUTE_INST/n0439D/A TDSP_CORE_INST/EXECUTE_INST/n0439D/ZN TDSP_CORE_INST/EXECUTE_INST/p_reg[27]/D 3. To get a list of the register sinks for a clock redirect clock_sink.rpt { foreach_in_collection ck [all_clocks] { puts "Clock_Name No_of_register_sinks Sink_list" puts "#####################################"] puts "[get_object_name $ck] [sizeof_collection [all_registers -clock $ck]] [get_object_name [all_registers -clock $ck]]\n" } } Output: Clock_Name No_of_register_sinks Sink_list ##################################### m_spi_clk 23 SPI_INST/spare_200 SPI_INST/spare_201 SPI_INST/spare_205............. SPI_INST/spare_202 SPI_INST/spare_203 SPI_INST/spare_204 4. Script to report slack and difference between clock arrival time at launch and capture clocks set a [report_timing -max_paths 4 -collection] puts "" puts " Reporting Slack and Skew between paths" puts "" puts "\t StartPoint? \t\t\t EndPoint? \t\t\t Slack \t\t\t Skew" puts "" foreach_in_collection i $a { set StartPoint? [get_object_name [get_property $i launching_point]] set EndPoint? [get_object_name [get_property $i capturing_point]] set l1 [get_property $i launching_clock_latency] set l2 [get_property $i launching_clock_open_edge_time] set launchClockTime [expr $l1 + $l2] set c1 [get_property $i capturing_clock_latency] set c2 [get_property $i capturing_clock_close_edge_time] set captureClockTime [expr $c1 + $c2] set Slack [get_property $i slack] set Skew [expr $captureClockTime - $launchClockTime] puts "$StartPoint \t $EndPoint \t $Slack \t $Skew" } Output: TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[27]/D -843.802 -0.015 TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[30]/D -762.004 -0.015 TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[24]/D -684.326 -0.015 TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[26]/D -680.548 -0.015 5. Script to report logics between reg-to-reg. This script can be modified for different path groups group_path -from [all_registers] -to [all_registers] -name GRP set a [report_timing -path_group GRP -max_paths 100 -collection] foreach_in_collection i $a { set StartPoint? [get_object_name [get_property $i launching_point]] set EndPoint? [get_object_name [get_property $i capturing_point]] set points [get_property $i timing_points] puts "" puts "Timing points between $StartPoint and $EndPoint" puts "" foreach_in_collection j $points { set p [get_object_name [get_property $j pin]] puts $p } } Output: Timing points between TDSP_CORE_INST/EXECUTE_INST/arp_reg/CP and RAM256x16_TEST_INST/RAM_256x16_INST/A[6]TDSP_CORE_INST/EXECUTE_INST/arp_reg/CP TDSP_CORE_INST/EXECUTE_INST/arp_reg/Q TDSP_CORE_INST/TDSP_CORE_GLUE_INST/p1929A/S TDSP_CORE_INST/TDSP_CORE_GLUE_INST/p1929A/Z TDSP_CORE_INST/TDSP_CORE_GLUE_INST/p1927A/A1 TDSP_CORE_INST/TDSP_CORE_GLUE_INST/p1927A/ZN DATA_SAMPLE_MUX_INST/p1989A/I1 DATA_SAMPLE_MUX_INST/p1989A/Z RAM_256x16_TEST_INST/RAM_256x16_INST/A[6] 6. Script to find the number of logic levels (combinational) in a timing path or group of timing paths proc num_of_logicLevel {max_paths} { set a [report_timing -max_paths $max_paths -collection] puts "Start Point \t\t\t End Point \t\t\t Instance Count" foreach_in_collection i $a { set StartPoint? [get_object_name [get_property $i launching_point]] set EndPoint? [get_object_name [get_property $i capturing_point]] set Size [sizeof_collection [get_property $i timing_points]] set InstCount? [expr $Size/2] puts "$StartPoint \t $EndPoint \t $InstCount" } } Output: num_of_logicLevel 3 Start Point End Point Instance Count TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[27]/D 58 TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[30]/D 58 TDSP_CORE_INST/EXECUTE_INST/sel_op_a_reg[2]/CK TDSP_CORE_INST/EXECUTE_INST/p_reg[24]/D 54 7. Script to check if macros(SRAM) are outside block boundary proc check_macro_position { } { set a [list] set i 0 set a [get_attribute [get_cells -physical_context -filter "is_hard_macro == true"] full_name] foreach cell_name $a { set c_llx [lindex [lindex [get_attribute [get_cells $cell_name] boundary_bbox] 0] 0] set c_lly [lindex [lindex [get_attribute [get_cells $cell_name] boundary_bbox] 0] 1] set c_urx [lindex [lindex [get_attribute [get_cells $cell_name] boundary_bbox] 1] 0] set c_ury [lindex [lindex [get_attribute [get_cells $cell_name] boundary_bbox] 1] 1] set d_llx [lindex [lindex [get_attribute [current_design] boundary_bbox] 0] 0] set d_lly [lindex [lindex [get_attribute [current_design] boundary_bbox] 0] 1] set d_urx [lindex [lindex [get_attribute [current_design] boundary_bbox] 1] 0] set d_ury [lindex [lindex [get_attribute [current_design] boundary_bbox] 1] 1] set llx [expr $c_llx - $d_llx] set lly [expr $c_lly - $d_lly] set urx [expr $d_urx - $c_urx] set ury [expr $d_ury - $c_ury] if {$llx < 0 || $lly < 0 || $urx < 0 || $ury < 0} { puts "ERROR: $cell_name is outside the block boundary\n" incr i } } if {$i == 0} { puts "\nCHECK PASS: ALL SRAMS INSIDE BLOCK BOUNDARY!!\n" } } define_proc_attributes check_macro_position -info "checks whether sram/macros are inside the block boundary." -define_args { } Output: 8. Script to report pin info of cells queried/selected proc get_pin_info {a} { if {$a == "get_selection"} { set b [list] set b [get_attribute [get_selection] full_name] } else { set b [list] set b [get_attribute [get_cells -physical_context $a] full_name] } foreach cell_name $b { set p [list] set p [get_object_name [get_pins -of_objects [get_flat_cells $cell_name]]] set sig_p [sizeof_collection [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == signal"]] set sig_p_name [get_attribute [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == signal"] name] set power_p [sizeof_collection [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == power"]] set power_p_name [get_attribute [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == power"] name] set ground_p [sizeof_collection [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == ground"]] set ground_p_name [get_attribute [get_pins -of_objects [get_flat_cells $cell_name] -filter "port_type == ground"] name] set pg [expr {$power_p + $ground_p}] puts "\nCELL_NAME: $cell_name \nSIGNAL_PINS == $sig_p \n PG_PINS == $pg \nSIGNAL_PIN_NAMES == $sig_p_name\nPOWER_PIN_NAME ==$power_p_name\nGND_PIN_NAME == $ground_p_name" } } define_proc_attributes get_pin_info -info "Gives pin names and pin type of selected or queried cell names. User can either give cells list or \[get_selection\]" -define_args {{a "cell_name" a list required}} 9. Script to automate application of routing blockages over srams/macros until their highest pin layers proc create_rb_over_sram {} { remove_routing_blockages *SRAM_RB* set a [list] set a [get_attribute [get_cells -physical_context -filter "is_hard_macro == true"] full_name] foreach cell_name $a { set rb_layer [lsort -unique [join [get_attribute [get_pins -of_objects [get_flat_cells $cell_name]] layer_name]]] set bb [get_attribute [get_flat_cells $cell_name] boundary_bbox] create_routing_blockage -boundary "{$bb}" -layers "$rb_layer" -name_prefix SRAM_RB } set c [sizeof_collection [get_routing_blockages *SRAM_RB*]] puts "INFO: $c ROUTING BLOCKAGES OVER MACROS CREATED SUCCESSFULLY!" } define_proc_attributes create_rb_over_sram -info "creates routing blockages over sram according to its pin layers" -define_args { }