01signal.com

Tcl 명령을 사용하여 logic elements선택

이 페이지는 timing에 대한 일련의 페이지 에 속합니다. 이전 페이지에서는 timing 계산에 대한 이론을 설명하고, clock period constraint에 대해 논의하고, timing closure의 원리를 보여주고, Tcl 환경을 살펴보기 시작했습니다. 이 페이지에서는 timing constraints를 특정화할 수 있는 명령을 설명합니다.

개요

timing constraints 의 목적은 design 에 있는 모든 paths 의 timing 요구 사항이 충족되도록 하는 것입니다. 다른 paths 에는 다른 요구 사항이 있을 수 있으므로 각 timing constraint는 관련 paths그룹으로 지정되어야 하며 다른 항목은 포함하지 않아야 합니다.

paths를 정의하는 유일한 방법은 이러한 paths와 관련된 logic elements를 참조하는 것입니다. 따라서 올바른 logic elements그룹을 선택하는 정확한 표현을 작성할 수 있는 능력이 중요합니다. 즉, get_clocks, get_ports 및 get_cells와 같은 명령을 올바르게 사용하여 필요한 결과를 얻을 수 있도록 해야 합니다.

이 페이지에서는 logic elements그룹을 설명하는 기본 기술을 안내합니다. 여기에 있는 거의 모든 것이 SDC 구문에만 해당됩니다. 또한 Tcl command-line 인터페이스를 사용할 수 있다고 가정합니다. 이는 Vivado 및 Quartus뿐만 아니라 최근 대부분의 FPGA 도구에도 해당됩니다.

일부 FPGA 공급업체는 Synopsys의 소프트웨어가 자사 도구에 통합되어 있다고 공개적으로 선언하므로 당연히 이러한 도구는 동일한 Tcl 명령을 사용합니다. 반면 Vivado는 Synopsys에서 파생된 것으로 간주되지 않습니다. 그럼에도 불구하고 특히 Tcl 인터페이스와 관련하여 둘 사이에는 몇 가지 놀라운 유사점이 있습니다. Quartus는 독립적으로 개발된 것으로 보이며 따라서 Tcl 인터페이스는 약간 다릅니다.

언뜻 보기에 이 페이지가 Tcl scripting의 세부 사항에 너무 많이 들어가는 것처럼 보일 수 있습니다. 사실은 그 반대입니다. 정확성은 매우 중요하며 이는 명령이 해석되는 방식을 정확히 이해해야만 달성할 수 있습니다. 사실 이 페이지는 기본 원리만 설명합니다. 문서를 읽는 것을 대신할 수 있는 것은 없습니다.

FPGA 도구에서 안내 받기

처리해야 할 세부 사항이 너무 많기 때문에 timing constraints작성을 시작하기가 어려운 경우가 많습니다. FPGA 도구가 도움이 될 수 있습니다.

"help" 명령은 Tcl 명령에 대한 문서를 보기 위해 Tcl console 에서 사용할 수 있습니다. 이것은 종종 공식 문서(예: pdf 형식)와 정확히 동일한 정보입니다.

대부분의 FPGA 도구에는 timing constraints를 자동으로 생성하기 위한 GUI 인터페이스가 있습니다. 작업 방법은 일반적으로 필요한 timing constraints 의 유형을 선택하는 데 사용됩니다. 다음 단계는 목록에서 관련 logic elements를 선택하는 것입니다. 결과는 SDC 파일에 추가되는 하나 이상의 timing constraints 입니다.

이러한 종류의 wizard를 사용하면 Tcl 구문에 대한 힌트를 얻을 수 있습니다. 경우에 따라 자동으로 생성된 constraints를 그대로 사용할 수도 있습니다. 그러나 대부분의 경우 wizard의 출력을 사용하려는 유혹을 뿌리치고 대신 timing constraint 의 목적을 가장 잘 달성하는 방법을 신중하게 생각해 볼 가치가 있습니다. 프로젝트가 어떻게 발전할 것으로 예상되는지 고려하고 시간이 지나도 timing constraints가 올바른 상태를 유지하는지 확인하는 것도 중요합니다. GUI wizard 와의 빠른 세션으로는 이를 달성할 수 없습니다.

일부 FPGA 도구에는 design에서 logic elements를 찾기 위한 GUI 인터페이스도 있습니다. 이 인터페이스를 사용하면 요청한 검색에 해당하는 Tcl 명령이 자주 표시됩니다. 이것은 특정 logic elements를 찾기 위한 Tcl 표현식을 얻는 편리한 방법입니다. 다시 한 번, 이러한 표현은 추가 작업을 위한 출발점으로 취급되어야 합니다.

대부분의 FPGA 도구의 세 번째 기능은 명령을 입력하고(또는 Copy-Paste사용) 화면에서 결과를 볼 수 있는 Tcl command-line console 입니다. 이를 통해 명령과 해당 search patterns를 테스트하고 어떤 objects가 발견되었는지 확인할 수 있습니다. 이는 search pattern이 올바른지 확인하는 데 도움이 될 수 있습니다.

결론적으로 FPGA 도구는 Tcl 명령을 만드는 데 도움이 될 수 있습니다. 그러나 이미 말했듯이 도구에 의해 생성된 Tcl 명령은 시간이 지남에 따라 올바르게 작동하도록 보장되는 정확한 search patterns를 작성하기 위한 기초에 지나지 않아야 합니다.

이제 timing constraints를 만드는 게으른 방법을 알았으니 이제 이를 제대로 수행하는 방법을 배울 차례입니다.

netlist: 짧은 알림

Tcl 환경에 대해 더 구체적으로 알아보기 전에 netlists에 대해 간략하게 상기시켜 드리고자 합니다.

netlists 의 가장 일반적인 파일 형식은 EDIF가 지만 많은 FPGA 도구에도 고유한 형식이 있습니다. 일반적으로 synthesizer는 netlist를 생성하지만 이후 단계에서도 도구가 netlist를 변경할 수 있습니다. 이 파일은 기본 구성 요소와 이러한 구성 요소 간의 연결 측면에서 logic design을 설명합니다. 배선도와 같지만 그래픽 이미지가 아닌 텍스트로 표현됩니다.

netlist 의 구성 요소를 "cells"라고 합니다. 대부분의 cells는 LUT, combinatorial logic 또는 flip-flop의 또 다른 작은 요소입니다. 또한 Verilog 코드(예: IP cores)에서 black boxes 의 instantiations는 netlist에서 cell 로 표시됩니다. 다른 cells는 PLLs, block RAMs및 대형 logic elements ("hard IPs")입니다. PCIe blocks, MGT transceivers, processors 등

각 cell 에는 여러 개의 pins 가 있습니다. 이 pins는 물리적 전자 부품의 외부 연결 지점과 같습니다. 그러나 이것을 FPGA의 외부 I/O와 혼동하지 마십시오. cells 와 pins는 모두 FPGA내부에 있습니다.

netlist 의 상호 연결은 nets로 구성됩니다. 이들은 물리적 전선과 같습니다. 예를 들어, signal이 Verilog에서 "wire"로 정의되면 net이 됩니다. net은 2개 이상의 pins를 연결하며, 그렇게 함으로써 이러한 pins가 항상 동일한 logic level을 갖도록 보장합니다.

logic elements를 objects로 표현

FPGA 도구가 프로젝트의 implementation을 통해 실행될 때 실제로 발생하는 것은 Tcl scripts가 실행되는 것입니다. 이는 Vivado , Quartus 및 기타 여러 FPGA 도구에 해당됩니다. 다르게 작동하는 소프트웨어를 사용하더라도 다음과 같이 가정하는 것이 여전히 옳습니다. 모든 것이 하나의 큰 Tcl script 라는 환상은 constraints 및 기타 script 파일에 대한 API 에 의해 생성됩니다.

이 Tcl script 의 환경(가상이든 아니든)에서 모든 logic elements는 다른 classes에서 생성된 objects 로 표시됩니다. 이러한 objects는 SDC 파일(또는 Xilinx의 XDC 파일)에서 timing constraints 에 의해 액세스될 수 있습니다. 마찬가지로 Tcl command-line console 및 Tcl scripts 의 Tcl 명령은 이러한 objects에 액세스할 수 있습니다.

다음은 SDC 구문과 함께 작동하는 모든 FPGA 도구에서 지원하는 5개의 Tcl 명령입니다. 이 명령은 다른 유형(예: 다른 classes)의 objects를 찾는 데 사용됩니다. timing constraints의 이전 예제에서 이미 사용했습니다. 실제로 이러한 명령 없이 의미 있는 timing constraints를 작성하는 것은 거의 불가능합니다.

arguments가 없으면 이 명령은 해당 유형의 모든 objects를 찾습니다. 나중에 검색을 세분화하는 방법을 살펴보겠습니다.

이 다섯 가지 명령을 제외하고 각 FPGA 도구에는 자체 추가 명령과 추가 objects가 있습니다. 예를 들어, Vivado 에는 all_ffs, all_registers, all_inputs, all_outputs, all_rams 및 이와 유사한 여러 명령과 같은 추가 명령이 있습니다. Quartus는 이들 중 일부를 지원하며 get_registers, get_keepers, get_nodes, get_fanins 및 get_fanouts 등도 있습니다.

이러한 objects 의 중요성은 FPGA design에서 logic elements를 참조하기 위해 timing constraints 에서 사용된다는 것입니다. 예를 들어 clock의 주파수와 같은 정보를 얻기 위해 Tcl scripts 에서 사용할 수도 있습니다. 각 FPGA 도구에는 Tcl scripts에서 이러한 objects 에 액세스하기 위한 자체 API가 있습니다. 예를 들어, 이 Tcl 명령은 Vivado 에서 clock period를 얻기 위해 사용될 수 있습니다.

> get_property PERIOD [get_clocks clk]
4.000

Quartus에서도 마찬가지입니다.

> get_clock_info -period [get_clocks clk]
4.000

이러한 차이점에도 불구하고 대부분의 FPGA 도구는 SDC 형식의 timing constraints 구문과 의미에 동의합니다. 각 도구가 지원하는 API 에 대한 정보는 일반적으로 Tcl scripting 또는 Timing Closure와 관련된 제목이 있는 user guides 에서 찾을 수 있습니다.

달리 명시되지 않는 한 이 페이지의 예제는 Vivado를 기반으로 합니다.

Tcl에 대한 몇 가지 참고 사항

Tcl은 고대 언어이지만 logic design분야에서 이미 자리를 잡고 있기 때문에 이 언어가 곧 사라지지는 않을 것으로 예상됩니다. 운 좋게도 Tcl을 잘 알지 못하더라도 유용한 작업을 수행할 수 있습니다.

먼저 간단히 언급한 것은 square brackets ("[" 및 "]")입니다. Tcl에서 이는 square brackets에서 명령을 실행하고 결과를 해당 위치에 넣는 것을 의미합니다. shell scripting 나 Perl에 익숙한 분들에게는 backticks와 동일합니다. 예를 들어, 이 명령에서 get_port는 이름이 "clk"인 port object 로 대체됩니다.

create_clock -period 4.000 -name clk [get_ports clk]

마찬가지로 이것은 다음과 같이 작성할 수 있습니다.

set the_clk_port [get_ports clk]
create_clock -period 4.000 -name clk $the_clk_port

이 두 번째 예에서 볼 수 있듯이 "set" 명령을 사용하여 변수를 정의하고 값을 할당합니다. 변수 값에 액세스하기 위해 dollar sign ($)가 사용됩니다. 다시 한 번 shell script 및 Perl와 유사합니다.

curly braces ("{" 및 "}")에 대해서는 이야기가 다릅니다. 다른 여러 언어와 마찬가지로 그 의미는 문맥에 따라 많이 달라집니다. Tcl에서 curly braces 의 덜 기대되는 의미 중 하나는 동봉된 string이 그대로 유지되어야 한다는 것입니다. 즉, 대체가 없어야 하며 whitespaces는 모든 character와 같은 것으로 간주되어야 합니다. 예를 들어 동일한 timing constraint를 다음과 같이 작성할 수 있습니다.

create_clock -period {4.000} -name {clk} [get_ports {clk}]

이 예에서 curly braces는 완전히 불필요하며 이 명령은 이전과 완전히 동일합니다. 불필요한 curly braces는 불행하게도 일반적이며 종종 이 예에서와 같이 아무 의미가 없습니다.

Tcl console사용 팁

발견된 objects 의 수가 많아 검색 명령의 출력을 읽기 어려운 경우가 종종 있습니다. 이는 간단한 Tcl 명령으로 해결할 수 있습니다. 이 작업을 정확히 수행하는 방법은 사용하는 도구에 따라 다릅니다. Vivado에서 이 명령은 design의 모든 cells를 인쇄합니다. 각 cell은 별도의 줄에 인쇄되므로 cells가 많더라도 출력을 읽을 수 있습니다.

> join [get_cells -hierarchical] \n
GND
VCC
bar__0_i_1
bar_reg_OBUF_inst
bar_reg__0
[ ... ]

"join" 명령은 get_cell이 생성하는 array 의 각 요소 사이에 newline을 넣습니다.

Quartus를 사용하면 다음과 같은 결과를 얻을 수 있습니다.

join [query_collection -all [get_cells -hierarchical] ] \n

또는 query_collection을 보다 현명하게 사용하여:

query_collection -all -report_format [get_cells -hierarchical]

특정 요소 찾기

긴 소개가 끝나고 마침내 정말 흥미로운 것에 대해 이야기할 시간입니다. 아래 예제를 위해 나중에 사용 되는 다음 Verilog 코드를 참조하십시오.

module top(
    input clk,
    input foo,
    output reg bar_reg,
    output reg baz
);
    reg foo_reg;
    reg bar;
    reg baz_metaguard;
    wire pll_clk_8, pll_clk_6;

   clk_wiz_1 pll_i
   (.clk_in1(clk),
    .clk_out1(pll_clk_8),
    .clk_out2(pll_clk_6));

always @(posedge pll_clk_8)
  foo_reg <= foo;

always @(posedge pll_clk_6)
  begin
    bar <= !foo_reg;
    bar_reg <= bar;
  end

always @(posedge clk)
  begin
    baz_metaguard <= bar;
    baz <= baz_metaguard;
  end

이 페이지 상단에서 언급한 바와 같이 timing constraints 의 정확도는 올바른 logic elements그룹을 선택하는 데 달려 있습니다. 따라서 위에서 언급한 5개의 get_* 명령에서 검색 결과를 좁히는 것이 가능하고 필요합니다. 여러 가지 방법이 있지만 가장 일반적인 방법은 object의 이름을 기반으로 합니다. 가장 간단한 pattern은 우리가 찾고 있는 정확한 이름을 가진 단일 object를 찾는 것입니다. 예를 들어, Vivado의 Tcl console에서:

> get_ports clk
clk

마찬가지로 특정 pattern와 일치하는 이름을 가진 모든 objects를 찾을 수 있습니다.

> get_pins pll_i/*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2

이 두 예의 출력은 objects입니다. Vivado의 Tcl console에서는 이러한 objects 의 이름이 편의상 인쇄되어 있습니다.

더 중요한 것은 각 FPGA 도구가 이러한 search patterns와 관련하여 약간 다르게 작동한다는 점입니다. 여기 예제에서는 Vivado가 사용됩니다. 다른 도구에도 동일한 원칙이 적용됩니다.

별표("*")는 wildcard character가 며 임의 개수의 characters를 대체합니다. 물음표("?")는 하나의 character를 대체합니다. 이것은 파일 이름이 있는 wildcards 와 동일하게 작동합니다.

파일 이름과 마찬가지로 wildcards는 hierarchy separator 와 일치하지 않습니다(예: "/"는 Vivado 및 "|"는 Quartus).

hierarchical path 와 파일 디렉토리 사이에도 유사점이 있습니다. 검색은 file system의 root directory 와 유사한 top-level hierarchy와 관련하여 이루어집니다. 예를 들면 다음과 같습니다.

> get_pins */clk_*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
> get_pins pll_i/clk_out?
pll_i/clk_out1 pll_i/clk_out2

hierarchy 에서 각 logic element 의 정확한 위치를 구체적으로 지정해야 하는 필요성은 종종 중요한 결점입니다. 우리가 찾고자 하는 logic elements는 종종 다른 위치에 있습니다. 이것은 "-hierarchical"로 해결됩니다. 이 flag이 있으면 hierarchy의 모든 위치에서 pattern을 검색합니다.

일반적으로 wildcards를 사용하여 logic elements를 찾는 것은 권장되지 않습니다. 유일한 예외는 search pattern이 매우 단순하거나 다른 선택이 없는 경우입니다. wildcards 와 "-hierarchical"를 사용하는 방법을 설명하고 이 방법의 한계를 보여주는 별도의 페이지 가 있습니다.

-filter사용

wildcards를 기반으로 하는 search patterns를 사용하면 몇 가지 단점이 있습니다. 가장 중요한 단점은 hierarchy를 정확하게 정의하거나 전혀 정의하지 않아야 한다는 것입니다. 한 가지 문제는 검색을 sub-hierarchy에 속한 objects 로 제한하는 것이 종종 바람직하다는 것입니다. 그러나 이것은 wildcards에서는 불가능하며 "-hierarchical" 옵션은 이 문제를 해결하지 못합니다.

이러한 이유 때문에 search patterns를 정의하는 기본 방법은 -filter 옵션을 사용하는 것입니다. 이 옵션은 boolean expression와 함께 제공됩니다. 이 옵션을 사용하면 이 expression이 true 인 검색 결과만 남습니다.

예를 들어,

> get_pins */clk_*
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2
> get_pins */clk_* -filter {name =~ *2*}
pll_i/clk_out2

이 예에서는 "name"라는 property가 wildcard덕분에 발견된 각 objects 에서 검사되었습니다. object는 이 property가 "*2*"와 일치하는 경우에만 검색 결과에 남아 있습니다. 즉, object 의 이름에 "2"가 포함된 경우에만 해당됩니다.

이 예는 실용적인 관점에서 흥미롭지 않습니다. "-hierarchical"를 사용하면 훨씬 더 흥미로워집니다. search pattern이 없으면 모든 objects가 검색됩니다. 즉, 이 명령은 모든 hierarchies에서 모든 pins를 찾습니다.

get_pins -hierarchical

이 시점에서 -filter로 검색 결과를 좁힐 수 있습니다.

> get_pins -hierarchical -filter {name =~ pll_i/*/*out1 }
pll_i/inst/clk_out1
> get_pins -hierarchical -filter {name =~ pll_i/*out1 }
pll_i/clk_out1 pll_i/inst/clk_out1
> get_pins -hierarchical -filter {name =~ *out1 }
pll_i/clk_out1 pll_i/inst/clk_out1

curly braces ("{" 및 "}")의 의미는 단지 그 안에 있는 부분을 Tcl interpreter로 수정해서는 안된다는 것입니다.

또한 search pattern은 -filter 옵션에 속하며 다르게 작동합니다. "name"를 object의 property 로 취급합니다. 따라서 모든 characters는 동일하게 취급됩니다. "/"는 특별한 의미가 없습니다. "/"가 hierarchy separator라는 것은 중요하지 않습니다. "/"를 포함한 모든 문자는 wildcard ("*")와 일치할 수 있습니다. 마찬가지로 "/"를 포함한 모든 문자를 search pattern에서 사용할 수 있습니다. 이것은 물론 -filter없이는 사실이 아닙니다.

모든 character가 "*"와 일치할 수 있다는 사실은 -filter를 더 강력한 도구로 만들지만 이 장점은 실수할 가능성도 있습니다. 위의 예에서 볼 수 있듯이 순진한 "*"가 실수로 "pll_i/clk_" 및 "pll_i/inst/clk_" 모두와 일치할 수 있다는 사실을 잊기 쉽습니다.

이 기능의 올바른 사용은 hierarchy에서 알려진 이름을 가진 logic element를 찾는 것입니다.

> get_pins -hierarchical -filter {name =~ */clkout2_buf/O }
pll_i/inst/clkout2_buf/O

design 에 이름이 "clkout2_buf"인 cell이 하나만 있다고 확신하는 경우 이는 정확합니다. 이 명령을 사용하면 이 logic element를 포함하는 module이 project의 hierarchy에서 이동하더라도 이 cell 의 output pin이 항상 발견됩니다. 실제 시나리오에서는 "clkout2_buf"보다 고유한 이름을 선택하는 것이 좋습니다.

동일한 방법이 get_cells 및 get_nets에서 작동합니다. 예를 들면 다음과 같습니다.

> get_cells -hierarchical -filter {name =~ */clk*_buf}
pll_i/inst/clkf_buf pll_i/inst/clkout1_buf pll_i/inst/clkout2_buf

그러나 -filter는 이름뿐만 아니라 모든 properties에서 작동합니다. 따라서 이 명령은 이름 안에 "bar"가 있는 모든 registers를 찾습니다.

get_cells -hier -filter {primitive_type =~ register.*.* && name =~ *bar*}

logical AND를 의미하는 "&&" 연산자에 유의하십시오( Verilog 및 C와 동일).

이 명령에서 "primitive_type" 및 "name"는 properties의 이름일 뿐입니다. "=~" 연산자는 비교를 수행하고 wildcards를 허용합니다.

object 의 속성은 "report_property" 명령( Vivado에서)으로 나열할 수 있음을 기억하십시오.

따라서 -filter는 유연하게 작업할 수 있습니다. 불행히도 모든 FPGA 도구에서 사용할 수는 없습니다.

Vivado 에는 filter라는 명령이 있으며 이는 -filter와 동일한 작업을 수행합니다. 따라서 다음 두 명령은 동일합니다.

set result [get_cells -hierarchical -filter {name =~ *_reg}]
set result [filter [get_cells -hierarchical] {name =~ *_reg}]

두 번째 형식은 objects 목록이 변수에 저장될 때 유용합니다. 따라서 위의 두 명령은 다음과 동일합니다.

set all_cells [get_cells -hierarchical]
set result [filter $all_cells {name =~ *_reg}]

-regex사용

regular expressions 에 익숙한 사용자는 이 옵션을 사용할 수 있습니다. 다른 사람들이 timing constraints를 이해하기 더 어렵게 만들기 때문에 일반적으로 이렇게 하는 것은 좋은 생각이 아닙니다. regular expressions를 지원하는 FPGA 도구는 일반적으로 -filter 옵션도 지원하므로 거의 항상 -filter를 사용하는 것이 좋습니다.

일반적인 search pattern 의 주요 문제는 hierarchy separator가 wildcard와 일치하지 않는다는 것입니다.

따라서 -regexp은 다음 몇 가지 예와 같이 이 문제를 해결할 수 있습니다.

> get_pins -hierarchical -regexp {.+/clk_out[123]}
pll_i/clk_out1 pll_i/clk_out2 pll_i/inst/clk_out1 pll_i/inst/clk_out2
> get_pins {pll_i/[^/]+/clk[^/]+} -hierarchical -regexp
pll_i/inst/clk_in1 pll_i/inst/clk_out1 pll_i/inst/clk_out2

첫 번째 명령은 "." 모든 character와 일치합니다. 여기에는 "/"( hierarchy separator)가 포함됩니다.

두 번째 명령은 "[^/]+"를 사용하여 hierarchy separator를 제외한 모든 것과 일치시키는 방법을 보여줍니다. 따라서 검색 결과의 hierarchy 에 대한 정확한 깊이를 제어할 수 있습니다. 이 명령은 또한 search pattern이 -regexp의 argument가 아니라 -regexp이 search pattern의 구문을 변경한다는 것을 보여줍니다.

regular expression은 object의 전체 이름과 일치해야 합니다. 즉, 도구는 암시적으로 regular expression의 시작 부분에 "^"를 추가하고 끝에 "$"를 추가합니다.

그러나 동일한 결과를 얻을 수 있는 다른 방법이 있다면 -regex를 사용하지 마십시오. 대부분의 다른 FPGA designers는 search pattern을 이해할 수 없습니다.

-of_object사용

이름에 따라 objects를 찾는 대신 -of_object는 다른 objects와의 관계에 따라 objects를 찾을 수 있습니다. 대부분의 경우 "-of_objects"는 대략 "~에 연결됨"을 의미합니다.

예를 들어, net에 연결된 모든 pins를 찾으려면:

> get_pins -of_objects [get_nets bar]
bar_reg_reg/D baz_metaguard_reg/D bar_reg__0/Q

또는 cell의 모든 pins :

> get_pins -of_objects [get_cells bar_reg_reg]
bar_reg_reg/Q bar_reg_reg/C bar_reg_reg/CE bar_reg_reg/D bar_reg_reg/R

또는 clock의 기원인 pin :

> get_pins -of_objects [get_clocks clk_out1_clk_wiz_1]
pll_i/inst/mmcme3_adv_inst/CLKOUT0

동일한 방법으로 nets를 찾을 수 있습니다. 예를 들어 어떤 nets가 특정 pin에 연결되어 있습니까?

> get_nets -of_objects [get_pins bar_reg_reg/C]
pll_clk_6

또는 관련 cell에 연결된 nets는 무엇입니까?

> get_nets -of_objects [get_cells bar_reg_reg]
bar_reg_OBUF pll_clk_6 <const1> bar <const0>

마찬가지로 이 방법으로 cells를 검색할 수 있습니다. 예를 들어 어떤 cells가 @pll_clk_6에 연결되어 있습니까?

> get_cells -of_objects [get_nets pll_clk_6]
bar_reg__0 bar_reg_reg pll_i

"pll_i"는 Clock Wizard의 IP의 instantiation name 입니다. 원하는 검색 결과가 아닐 수 있습니다. 그렇다면 검색 결과를 flip-flops로 좁힐 수 있을까요?

> get_cells -of_objects [get_nets pll_clk_6] -filter {primitive_type =~ register.*.*}
bar_reg__0 bar_reg_reg

지금까지 -of_objects를 사용한 위의 예는 pins, nets 및 cells가 서로를 참조할 수 있는 방법을 보여주었습니다. 하지만 다음 옵션을 사용하여 clock objects를 찾을 수도 있습니다.

> get_clocks -of_objects [get_nets pll_clk_6]
clk_out2_clk_wiz_1
> get_clocks -of_objects [get_cells bar_reg_reg]
clk_out2_clk_wiz_1
> get_clocks -of_objects [get_pins bar_reg_reg/C]
clk_out2_clk_wiz_1

이 세 가지 명령은 연결된 logic element 에 따라 clock을 찾는 방법을 보여줍니다. 이 logic element가 cell인 경우 둘 이상의 결과가 있을 수 있습니다. 예를 들어:

> get_clocks -of_objects [get_cells pll_i]
clk clk_out1_clk_wiz_1 clk_out2_clk_wiz_1

"pll_i"는 IP가 므로 pins는 이 module의 ports 입니다.

> get_pins -of_objects [get_cells pll_i]
pll_i/clk_in1 pll_i/clk_out1 pll_i/clk_out2

따라서 특정 clock을 찾으려면 get_pins가 더 안전합니다.

> get_clocks -of_objects [get_pins pll_i/clk_out2]
clk_out2_clk_wiz_1

물론 외부 I/O port 의 clock object는 다음과 함께 가장 잘 찾을 수 있습니다.

> get_clocks -of_objects [get_ports clk]
clk

또는 더 짧은 명령을 사용하면 다음과 같습니다.

> get_clocks [get_ports clk]
clk

get_ports라고 하면 -of_objects에서도 작동합니다. get_ports에 특정한 가능성에 관한 문서를 참조하십시오. 다른 명령과 유사한 가능성은 매우 무의미합니다. 예를 들면 다음과 같습니다.

> get_ports -of_objects [get_nets clk]
clk

요약하면 -of_objects는 특정 logic elements를 선택하는 탁월한 방법입니다. 이것은 아래의 다음 주제인 object의 이름에 따른 검색의 어려움 때문에 특히 그렇습니다.

불행히도 많은 FPGA 도구는 -of_objects를 지원하지 않으므로 덜 안정적인 방법에 의존할 수밖에 없습니다.

이름으로 검색할 때의 문제

위에서 이미 논의한 바와 같이 timing constraints 의 정확도는 logic elements를 찾는 정확도에 달려 있습니다. 이러한 검색 결과 중 적어도 일부는 object의 이름에 따라 다릅니다. 이것이 어떻게 문제를 일으킬 수 있는지 봅시다.

예를 들어 "get_ports clk"는 clock object 와 특정 I/O pin에 있는 signal을 연결하는 데 사용됩니다. 이 I/O pin은 이름이 "clk"인 port object 로 표시됩니다.

create_clock -period 4.000 -name clk [get_ports clk]

그런데 왜 이 port object 에 "clk"라는 이름이 붙었을까요? 대답은 synthesizer가 netlist를 만든 방법과 관련이 있습니다. Verilog 코드에서 top-level port 의 이름은 netlist의 top-level port 이름으로도 선택되었습니다. 이것은 분명한 선택이므로 적절한 synthesizer 라면 모두 동일하게 작동합니다.

그러나 cells의 이름은 어떻습니까? 위의 Verilog 코드에서 "foo_reg"라는 이름의 register를 살펴보겠습니다. 이 register의 flip-flop을 대표하는 cell object 의 이름은? Vivado의 synthesizer는 이 object에 "foo_reg_reg"라는 이름을 선택했습니다. 따라서 이 synthesizer는 Verilog 코드의 이름에 "_reg" 접미사를 추가하는 경향이 있음이 분명합니다. 그것은 신뢰할 수있는 규칙처럼 들립니다. 그러나 또 다른 synthesizer는 아마도 뭔가 다른 일을 할 것입니다.

그러나 이름이 "bar"인 register는 어떻습니까? 관련 cell object 의 이름은 "bar_reg"였어야 하지만 synthesizer는 다른 선택을 했습니다. "bar_reg__0". Verilog 코드에 "bar_reg"라는 register가 있기 때문이다. 따라서 이름 충돌을 피하기 위해 synthesizer는 약간 다른 이름을 선택했습니다. "_reg" 대신 "_reg__0"를 추가했습니다. 이 간단한 예는 objects라는 이름에 의존하는 문제를 보여줍니다.

설상가상으로, "bar_reg"라는 이름의 register가 Verilog 코드에 추가되기 전에 timing constraint가 작성되었다고 가정합니다. 이 경우 @bar 와 관련된 cell object는 평소와 같이 "bar_reg"라는 이름을 갖게 됩니다. 따라서 timing constraint는 object에 이 이름을 사용합니다. 이후 단계에서 "bar_reg"라는 이름의 register가 design에 추가됩니다. 결과적으로 요청된 cell object 의 이름이 "bar_reg"에서 "bar_reg__0"로 변경됩니다. "bar_reg"라는 이름에 의존하는 timing constraint는 갑자기 올바르지 않습니다. 운이 좋으면 도구에서 이에 대해 warning을 발행할 것입니다.

objects 라는 이름을 잘못 사용할 수 있는 다른 이유가 있습니다. 예를 들어 fan-out가 한도를 초과하면 도구가 register를 자동으로 복제할 수 있습니다. 이 경우 새 register의 이름이 search pattern와 일치하지 않기 때문에 추가 register가 timing constraint에 포함되지 않을 수 있습니다.

더 심각한 문제는 우연히 logic elements가 timing constraints 에 포함된 경우입니다. 예를 들어 IP blocks에 속하는 logic elements 에서 이런 일이 발생할 수 있습니다. 이러한 logic elements의 이름을 제어할 수 없기 때문에 이러한 이름이 실수로 timing constraint의 pattern 와 일치할 가능성이 있습니다.

실수로 timing constraints 에 logic elements를 포함하는 것도 게으름의 결과일 수 있습니다. timing constraints는 일반적으로 logic design에 새로운 기능을 추가하면서 작성됩니다. search pattern이 시행착오를 거쳐 작성된 경우 향후 logic elements 의 이름이 고려되지 않을 수 있습니다. 따라서 새로운 logic이 추가되면 일부 logic elements 의 이름이 의도하지 않게 기존 timing constraints와 일치할 수 있습니다.

timing constraints로 실수를 피하는 방법

첫 번째이자 가장 중요한 규칙은 어떤 logic elements가 timing constraint의 search pattern 와 일치하는지 테스트하는 것만으로는 충분하지 않다는 것입니다. 이러한 logic elements 의 전체 목록을 만들고 이 목록을 주의 깊게 검토하더라도 나중에 추가될 logic 와 관련하여 어떤 것도 보장하지 않습니다. 그러한 검토는 objects 의 이름이 synthesizer 에 의해 변경되거나 implementation의 다른 단계에서 변경되는 경우에도 timing constraints가 예상대로 계속 작동할 것이라고 보장하지 않습니다.

따라서 search patterns를 수학적 표현처럼 취급하는 것이 중요합니다. 이러한 search patterns가 현재 예상대로 작동하는 것만으로는 충분하지 않습니다. 그리고 예상대로 작동하지 않는 경우 작동하도록 약간 수정하는 것만으로는 충분하지 않습니다. 오히려 search pattern이 올바른 이유와 시간이 지나도 계속 올바른 상태로 유지될 가능성이 높은 이유에 대한 논리적 설명이 있어야 합니다.

search patterns가 변경 가능성이 없는 것에 의존하는 것도 중요합니다. 예를 들어 도구는 Verilog 코드에서 instantiations 의 이름을 변경하지 않습니다. 이것은 modules, IPs 및 primitives의 instantiations 에 해당됩니다. 따라서 Verilog 코드로 작성된 instantiations 의 이름으로만 구성된 hierarchical path 에 의존하는 것이 안전합니다. IP block내부에서 생성된 이름을 사용하는 것은 안전하지 않습니다. 이를 설명하기 위해 다음 명령을 살펴보겠습니다.

get_clocks -of_object [get_pins pll_i/inst/clkout1_buf/O]

clock을 배포하는 global clock buffer 의 output pin을 참고하여 clock object를 구하는 방법입니다. 문제는 이것이 장기적으로 작동할 것이라고 확신할 수 있는지 여부입니다.

이 방법의 문제점은 "inst" 및 "clkout1_buf"가 Clocking Wizard IP내부에서 만들어진 instantiations 의 이름이라는 것입니다. 이러한 이름은 변경되지 않을 것 같지만 변경되지 않는다는 보장은 없습니다.

한 가지 가능한 해결책은 IP를 구현하는 Verilog 코드를 찾아 이 Verilog을 프로젝트에 직접 포함시키는 것입니다. 이렇게 하면 미래에 아무 것도 변경되지 않습니다.

대안은 Verilog에서 IP 의 instantiation을 보는 것입니다. 다음을 기억하십시오.

clk_wiz_1 pll_i
   (.clk_in1(clk),
    .clk_out1(pll_clk_8),
    .clk_out2(pll_clk_6));

이것은 black box의 instantiation이 기 때문에 각 ports 에는 netlist에 pin이 있습니다. IP 의 ports가 식별되는 방식이기 때문에 이름은 변경할 수 없습니다. 따라서 이름이 "pll_i/clk_out1"인 pin이 @pll_clk_8와 연결된다는 것이 보장됩니다. 따라서 이것은 clock object를 확보하는 안전한 방법입니다.

get_clocks -of_object [get_pins pll_i/clk_out1]

clk_wiz_1이 프로젝트의 또 다른 Verilog module 인 경우에는 작동하지 않을 수 있습니다. 이 경우 module의 instantiation을 대신하여 pins가 생성되지 않습니다( synthesizer는 일반적으로 nets를 병합하여 ports 의 연결을 구현하기 때문입니다). 가능한 해결책은 hierarchy의 하위 레벨에 나타나는 이름을 사용하는 것일 수 있습니다.

따라서 신뢰할 수 있는 몇 가지 이름이 있습니다.

크게 실패하는 것이 낫다

최악의 상황은 timing constraint가 거의 정확할 때입니다. 포함되지 않은 paths가 몇 개만 있는 경우. 또는 실수로 timing constraint 에 포함된 paths가 몇 개만 있는 경우. 이러한 종류의 오류는 찾기가 가장 어렵습니다.

이것이 짧고 간결하며 수학적 스타일을 가진 timing constraints가 더 나은 주된 이유입니다. logic elements의 작은 그룹마다 timing constraint가 있는 경우 이 긴 규칙 목록에 실수가 끼어들기 쉽습니다.

이 아이디어를 시연하기 위해 clock object를 찾기 위해 위에 표시된 예제로 돌아가 보겠습니다.

get_clocks -of_object [get_pins pll_i/inst/clkout1_buf/O]

위에서 언급했듯이 이 표현의 문제점은 pll_i 의 instantiation이 hierarchy의 다른 위치로 이동하면 clock object를 찾을 수 없다는 것입니다. 얼마나 나쁠까요?

이 clock object가 다음과 같이 Tcl 변수에 저장되어 있다고 가정합니다.

set my_clock [get_clocks -of_object [get_pins pll_i/inst/clkout1_buf/O]]

그리고 $my_clock은 많은 timing constraints에서 사용되므로 많은 paths가 관련됩니다. 이 경우 버그로 인해 $my_clock 에 갑자기 clock object가 포함되지 않더라도 실제로 큰 문제는 아닙니다. 많은 일이 잘못될 것이기 때문에 이 실수를 곧 알아차릴 가능성이 높습니다.

그러나 $my_clock이 하나의 timing constraint에만 사용되고 이 constraint가 거의 효과가 없는 작은 문제를 해결하기 위한 것이라면 이는 나쁜 상황입니다. 이 실수는 눈에 띄지 않을 것입니다.

결론적으로: 잘 작성된 timing constraint는 완벽하게 작동하거나 전혀 작동하지 않습니다.


이 페이지는 logic elements를 정확하게 선택하는 방법을 보여줍니다. 다음 페이지 에서 이 지식은 선택적 timing constraints를 정의하는 데 사용됩니다.

이 페이지는 영어에서 자동으로 번역됩니다. 불분명한 사항이 있으면 원본 페이지를 참조하십시오.
Copyright © 2021-2024. All rights reserved. (6f913017)