ตัวอย่างการออกแบบนี้แสดงขั้นตอนแบบกําหนดเอง ซึ่งคุณสามารถใช้ในไฟล์ SDC ที่ส่งคืนรายการนาฬิกาทั้งหมดที่ป้อนพิน ขั้นตอนนี้จะมีประโยชน์มากหากคุณจําเป็นต้องสร้างนาฬิกาที่สร้างขึ้นโดยที่ไม่รู้จักชื่อนาฬิกาอื่นๆ ในการออกแบบ ตัวอย่าง การออกแบบซ้ําที่ง่ายขึ้นด้วยข้อจํากัด SDC แบบไดนามิก ให้รายละเอียดเพิ่มเติมและตัวอย่างวิธีการใช้ขั้นตอนแบบกําหนดเองที่อธิบายไว้ในหน้านี้
โค้ดแบบเต็มสําหรับขั้นตอนอยู่ด้านล่างของหน้า ตามด้วยคําอธิบายโดยสมบูรณ์เกี่ยวกับวิธีการทํางานของขั้นตอน ในการใช้ขั้นตอนget_clocks_driving_pinsกําหนดเองในไฟล์ SDC ตรวจสอบให้แน่ใจว่าได้กําหนดขั้นตอนไว้แล้ว จากนั้นให้เรียกใช้งานเหมือนกับคําสั่ง SDC อื่นๆ มีสองวิธีง่ายๆ เพื่อให้แน่ใจว่ามีการกําหนดขั้นตอนไว้ก่อนใช้งาน:
- บันทึกรหัสขั้นตอนในไฟล์ SDC แยกต่างหากและรวมไฟล์ SDC ในโครงการ
- คัดลอกและวางรหัสขั้นตอนที่ด้านบนของไฟล์ SDC ใดๆ ก่อนที่จะใช้ขั้นตอนที่กําหนดเองget_clocks_driving_pins
แยกไฟล์ SDC
การบันทึกรหัสขั้นตอนในไฟล์ SDC แยกต่างหากจะแยกรหัสออกจากข้อจํากัดที่เหลือของคุณและทําให้ง่ายต่อการนําไปใช้ในโครงการอื่น ๆ หากคุณใช้ไฟล์ SDC แยกต่างหาก คุณต้องเพิ่มไฟล์ SDC พร้อมขั้นตอนไปยังรายการไฟล์ในโครงการและไฟล์ต้องปรากฏเหนือไฟล์ SDC ใดๆ ที่ใช้ขั้นตอน รายการไว้เหนือไฟล์ SDC อื่น ๆ ช่วยให้มั่นใจได้ว่าซอฟต์แวร์ Quartus® II จะกําหนดขั้นตอนก่อนที่จะใช้งานเมื่อใดก็ตามที่มีการอ่านไฟล์ SDC
คัดลอกและวาง
การคัดลอกและวางรหัสขั้นตอนในไฟล์ SDC เดียวกันกับที่ใช้ส่งผลให้ไฟล์ SDC ในโครงการมีไฟล์ SDC น้อยลง หากคุณกําลังสร้างไฟล์ SDC สําหรับโมดูลที่จะนํามาใช้ใหม่โดยนักออกแบบรายอื่น อาจเป็นเรื่องง่ายที่สุดที่จะรวมข้อจํากัดทั้งหมดและรหัสสนับสนุนไว้ในไฟล์ SDC เดียว คุณต้องรวมรหัสขั้นตอนไว้ในไฟล์ SDC ก่อนการใช้ขั้นตอนแรกเพื่อให้มีการกําหนดก่อนที่จะใช้ โดยทั่วไปคุณจะวางไฟล์ไว้ด้านบนสุดของไฟล์เพื่อตอบสนองความต้องการนี้
การทํางานของสคริปต์
การรับรายการนาฬิกาทั้งหมดในการออกแบบที่ป้อนพินใช้เวลาสามขั้นตอนหลัก:
- รับนาฬิกาทั้งหมดและสร้างการแมปจากโหนดเป้าหมายของพวกเขาไปยังนาฬิกาบนโหนดเป้าหมาย
- ดูรายชื่อโหนดที่มีนาฬิกาอยู่บนพาธพัดลมไปยังพินที่ระบุ
- จากรายการโหนดดังกล่าว ให้ค้นหาโหนดที่อยู่ใกล้กับพินที่ระบุมากที่สุด และส่งคืนนาฬิกาบนโหนดนั้น
ขั้นตอนที่ 1 รับนาฬิกาทั้งหมดและสร้างการแมป
รหัส Tcl ต่อไปนี้ได้รับนาฬิกาทั้งหมดในการออกแบบและสร้างการแมป (ด้วยอาร์เรย์ Tcl) จากโหนดไปยังนาฬิกาบนโหนด
... { array unset nodes_with_clocks } array set nodes_with_clocks [list] # ทําซ้ํานาฬิกาแต่ละนาฬิกาในforeach_in_collection clock_idการออกแบบ [all_clocks] { ตั้งค่าclock_name [get_clock_info -name $clock_id] # นาฬิกาแต่ละนาฬิกาจะถูกนําไปใช้กับโหนด รับชุดข้อมูลโหนดเป้าหมาย foreach_in_collection target_id [get_clock_info -targets $clock_id] { # เชื่อมโยงชื่อนาฬิกาด้วยชุดโหนดเป้าหมาย target_name [get_node_info -name $target_id] lappend nodes_with_clocks($target_name) $clock_name }
นาฬิกาเสมือนไม่มีเป้าหมาย ดังนั้นจะไม่มีการทําแผนที่ด้วยนาฬิกาเสมือนจริง ในรหัสขั้นตอนแบบเต็มที่ระบุไว้ด้านล่าง ข้อมูลเกี่ยวกับประเภทของโหนดเป้าหมาย (ลงทะเบียน พิน เซลล์ หรือพอร์ต) จะถูกบันทึกไว้สําหรับใช้ในภายหลัง
ขั้นตอนที่ 2 รับโหนดที่มีนาฬิกาในเส้นทาง Fanin
ขั้นตอนที่สองคือการค้นหาชุดย่อยของโหนดที่มีนาฬิกาที่อยู่บนพาธพัดลมไปยังพินที่ระบุ สําหรับแต่ละโหนดที่มีนาฬิกา (พบในขั้นตอนที่ 1) ให้หาพินที่ระบุผ่านโหนด หากมีพัดลม โหนดจะอยู่ในพาธพัดลมไปยังพิน หากไม่มีพัดลม โหนดจะไม่อยู่บนพาธพัดลมไปยังพิน
รหัส Tcl ต่อไปนี้จะวนรอบโหนดทั้งหมดด้วยนาฬิกาจากขั้นตอนที่ 1 และใช้คําสั่ง get_fanins เพื่อตรวจสอบว่าแต่ละโหนดอยู่บนพาธพัดลมของพินที่ระบุหรือไม่ หากโหนดอยู่บนพาธพัดลมของพินที่ระบุ โหนดนั้นจะถูกบันทึกไว้ในรายการ pin_drivers
ตั้งค่า pin_drivers [list] # ทําซ้ําโหนดทั้งหมดในการแมปที่สร้างขึ้นในขั้นตอนที่ 1 foreach node_with_clocks [array name nodes_with_clocks] { # รับพัดลมไปยังพินที่ระบุผ่านโหนดปัจจุบัน ตั้งค่าfanin_col [get_fanins -clock -through $node_with_clock $pin_name] # หากมีโหนด Fanin อย่างน้อยหนึ่งโหนด โหนดปัจจุบันอยู่บน พาธ fanin ไปยังพินที่ระบุ ดังนั้นโปรดบันทึกไว้ หาก { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } }
รหัสกระบวนการแบบเต็มที่แสดงด้านล่างใช้ข้อมูลเพิ่มเติมเกี่ยวกับประเภทโหนดเพื่อระบุชุดข้อมูลเฉพาะชนิดสําหรับค่า -through ในคําสั่ง get_fanins
ขั้นตอนที่ 3 ค้นหาโหนดที่อยู่ใกล้พินที่ระบุที่สุด
ตัวแปร pin_drivers มีรายชื่อโหนดทั้งหมดพร้อมนาฬิกาที่อยู่บนพาธพัดลมไปยังพินที่ระบุ ขั้นตอนนี้จะค้นหาโหนดที่อยู่ใกล้กับพินที่ระบุมากที่สุด ในขณะที่มีมากกว่าหนึ่งโหนดในรายการpin_drivers รหัสจะใช้สองโหนดแรกในรายการและตรวจสอบว่ามีโหนดหนึ่งอยู่บนพาธพัดลมไปยังอีกโหนดหนึ่งหรือไม่ หากอยู่บนพาธพัดลม โหนดแรกต้องอยู่ไกลจากพินที่มากกว่าโหนดที่สอง จึงจะสามารถลบโหนดออกจากรายการได้
ในขณะที่ { 1 < [llength $pin_drivers] } { # รับสองโหนดแรกในชุดรายการpin_drivers node_a [lindex $pin_driver 0] ตั้งค่าnode_b [lindex $pin_drivers 1] # ตรวจสอบว่าnode_bอยู่บนพาธพัดลมของnode_a ตั้งค่าfanin_col [get_fanins -clock -through $node_b $node_a] # หากมีโหนด fanin อย่างน้อยหนึ่งโหนด node_bต้อง อยู่ห่างจากพินที่ระบุมากกว่าพิน node_a # หากไม่มีโหนด Fanin node_bต้องอยู่ใกล้กับ พิน # ที่ระบุมากกว่า node_a หาก { 0 < [get_collection_size] } { # node_a อยู่ใกล้กับพินมากขึ้น # ลบnode_bออกจากชุดรายการpin_drivers pin_drivers [lreplace $pin_driver 1 1] } อื่นๆ { # node_bอยู่ใกล้กับพินมากกว่า # Remove node_a จากชุดรายการpin_drivers pin_drivers [lreplace $pin_drivers 0] } } จํานวนโหนดหนึ่งที่เหลือใน pin_drivers คือโหนดที่ขับเคลื่อน node_driving_pinชุดพินที่ระบุ [lindex $pin_driver 0] # ค้นหานาฬิกาบนโหนดในการแมปจากขั้นตอนที่ 1 และ ส่งคืน$nodes_with_clocks($node_driving_pin
รหัสกระบวนการแบบเต็มที่แสดงด้านล่างใช้ข้อมูลเพิ่มเติมเกี่ยวกับประเภทโหนดเพื่อระบุชุดข้อมูลเฉพาะชนิดสําหรับค่า -through ในคําสั่ง get_fanins
รหัสกระบวนการแบบเต็ม
รหัสสมบูรณ์สําหรับขั้นตอนget_clocks_driving_pinกําหนดเองมีการระบุไว้ด้านล่าง ซึ่งรวมถึงคุณสมบัติการตรวจสอบข้อผิดพลาดและการสนับสนุนเพิ่มเติมที่ไม่ได้อธิบายโดยละเอียดข้างต้น
proc get_clocks_feeding_pin { pin_name } { # ก่อนขั้นตอนที่ 1 ให้ทําการตรวจสอบข้อผิดพลาดเพื่อให้แน่ใจว่าpin_name # ถูกส่งผ่านไปยังกระบวนการที่ตรงกันเพียงหนึ่งพิน เท่านั้น # ส่งคืนข้อผิดพลาดหากไม่ตรงกับพินเดียวและมีเพียงพิน เดียว ตั้งค่า pin_col [get_pins -compatibility_mode $pin_name] หาก { 0 == [get_collection_size $pin_col] } { ข้อผิดพลาดในการส่งคืน -code "No pins match $pin_name" } } อื่นๆ { 1 < [get_collection_size $pin_col] } { ข้อผิดพลาดการส่งคืน -code "$pin_name matches [get_collection_size $pin_col]\ พินแต่ต้องตรงกันเพียงหนึ่งตัว" } # เริ่มต้นตัวแปรที่ใช้ในขั้นตอน { array unset nodes_with_clocks } การจํา { array unset node_types } ชุดอาร์เรย์nodes_with_clocks [list] ชุดอาร์เรย์ node_types [list] ตั้งค่าpin_drivers [list] # ขั้นตอนที่ 1 รับนาฬิกาทั้งหมดในการออกแบบและสร้างการแมปจาก # โหนดเป้าหมายไปยังนาฬิกาบนโหนดเป้าหมาย # ซ้ําต่อนาฬิกาในแต่ละนาฬิกาใน foreach_in_collection clock_idการออกแบบ [all_clocks] { ตั้งค่าclock_name [get_clock_info -name $clock_id] ตั้งค่าclock_target_col [get_clock_info -targets $clock_id] # แต่ละนาฬิกาจะถูกนําไปใช้กับโหนด รับชุดข้อมูลโหนดเป้าหมาย foreach_in_collection target_id [get_clock_info -targets $clock_id] { # เชื่อมโยงชื่อนาฬิกาด้วยชุดโหนดเป้าหมาย target_name [get_node_info -name $target_id] lappend nodes_with_clocks(($target_name) $clock_name # บันทึกประเภทของโหนดเป้าหมายสําหรับการตั้งค่า target_type [get_node_info -type $target_id] ตั้งค่าnode_types($target_name) $target_type } } ขั้นตอนที่ 2 ดูรายชื่อโหนดที่มีนาฬิกาอยู่บน พาธ # fanin ไปยังพินที่ระบุ # ทําซ้ําโหนดทั้งหมดในการแมปที่สร้างขึ้นในขั้นตอนที่ 1 foreach node_with_clocks [array name nodes_with_clocks] { # ใช้ประเภทของโหนดเป้าหมายเพื่อสร้างชุดข้อมูล # เฉพาะประเภท สําหรับค่า -through ในคําสั่ง get_fanins switch -exact -- $node_type($node_with_clocks) { "pin" { ตั้งค่าthrough_col [get_pins $node_with_clocks] } "พอร์ต" { ตั้งค่าthrough_col [get_ports $node_with_clocks] } "เซลล์" { ตั้งค่าthrough_col [get_ports $node_with_clocks] } "เซลล์" { ตั้งค่าthrough_col [get_cells $node get_ports $node_with_clocks] } "reg" { set through_col [get_registers $node_with_clocks] } ค่าเริ่มต้น { return -code error "$node_type($node_with_clocks) ไม่ได้รับการจัดการ\ เป็นประเภท fanin โดยสคริปต์" } } # รับแฟนๆ ไปยังพินที่ระบุผ่านชุดโหนดปัจจุบัน fanin_col [get_fanins -clock -through $through_col $pin_name] # หากมีอย่างน้อยหนึ่งโหนด fanin โหนดปัจจุบันอยู่บน พาธ # fanin ไปยังพินที่ระบุ ดังนั้นบันทึกไว้ หาก { 0 < [get_collection_size $fanin_col] } { lappend pin_drivers $node_with_clocks } } # ก่อนขั้นตอนที่ 3 ให้ทําการตรวจสอบข้อผิดพลาดเพื่อให้แน่ใจว่าอย่างน้อยหนึ่ง # โหนดที่มีนาฬิกาในการออกแบบอยู่บนพาธพัดลมไปยัง # พินที่ระบุ หาก { 0 == [llength $pin_drivers] } { ข้อผิดพลาด return-code "ไม่พบโหนดใดๆ ที่มีนาฬิกาที่ขับเคลื่อน $pin_name" } # ขั้นตอนที่ 3 จากรายการโหนดที่สร้างขึ้นในขั้นตอนที่ 2 ให้ค้นหาโหนด # ที่ใกล้เคียงที่สุดกับพินที่ระบุและส่งคืนนาฬิกาบนโหนด นั้น ในขณะที่ { 1 < [llength $pin_drivers] } { # รับสองโหนดแรกในชุดรายการpin_drivers node_aตั้งค่า [lindex $pin_drivers 0] node_b [lindex $pin_driver 1] # ใช้ประเภทของโหนดเป้าหมายเพื่อสร้างชุดข้อมูล # เฉพาะประเภท สําหรับค่า -through ในคําสั่ง get_fanins switch -exact -- $node_type($node_b) { "pin" { ตั้งค่าthrough_col [get_pins $node_b] } "พอร์ต" { ตั้งค่าthrough_col [get_ports $node_b] } "เซลล์" { ตั้งค่าthrough_col [get_cells $node_b] } "reg" { set through_col [get_registers $node_b] ค่าเริ่มต้น { ข้อผิดพลาดการส่งคืน -code "$node_types($node_b) ไม่ได้รับการจัดการ\ เป็นประเภท fanin โดยสคริปต์" } } # ตรวจสอบว่าnode_bอยู่บนเส้นทางพัดลมของnode_aหรือไม่ ตั้งค่าfanin_col [get_fanins -clock -through $through_col $node_a] # หากมีโหนดพัดลมอย่างน้อยหนึ่งโหนด node_bต้อง อยู่ไกลจากพินที่ระบุมากกว่า node_a # หากไม่มีโหนด Fanin node_bต้องอยู่ใกล้กับ พิน # ที่ระบุมากกว่า node_a หาก { 0 < [get_collection_size $fanin_col] } { # node_aอยู่ใกล้กับพินมากขึ้น # ลบnode_bออกจากชุดรายการpin_drivers pin_drivers [lreplace $pin_drivers 1 1] } อื่น { # node_b อยู่ใกล้กับพิน # Remove node_aจากชุดรายการpin_drivers pin_drivers [lrange" มากกว่า $pin_drivers 1 end] } # หนึ่งโหนดที่เหลือใน pin_drivers คือโหนดที่ขับเคลื่อนชุดพินที่ระบุ node_driving_pin [lindex $pin_drivers 0] # ค้นหานาฬิกาบนโหนดในการแมปจากขั้นตอนที่ 1 และส่งคืน $nodes_with_clocks($node_driving_pin) }