많은 응용 프로그램에서 명령 실행에 예상되는 입력 자극과 알려진 타이밍 관계가있는 CPU는 관계를 알 수없는 경우 훨씬 더 빠른 CPU가 필요한 작업을 처리 할 수 있습니다. 예를 들어, PSOC를 사용하여 비디오를 생성 한 프로젝트에서 코드를 사용하여 16 개의 CPU 클럭마다 1 바이트의 비디오 데이터를 출력했습니다. IIRC가 13 클럭을 취하지 않을 경우 SPI 디바이스가 준비되고 분기되는지 테스트하고 출력 데이터를로드 및 저장하는 데 11이 걸리기 때문에 바이트 사이의 준비 상태에 대해 디바이스를 테스트 할 방법이 없었습니다. 대신, 프로세서가 첫 번째 바이트 후 각 바이트에 대해 정확히 16 사이클의 코드를 실행하도록 준비했습니다 (실제 인덱스로드, 더미 인덱스로드 및 저장소를 사용했다고 생각합니다). 각 라인의 첫 번째 SPI 쓰기는 비디오 시작 전에 발생했습니다. 모든 후속 쓰기에 대해 버퍼 오버런 또는 언더런없이 쓰기가 발생할 수있는 16 사이클 창이있었습니다. 분기 루프는 13 사이클의 불확실성을 생성했지만 예측 가능한 16 사이클 실행은 모든 후속 바이트에 대한 불확실성이 동일한 13 사이클 창에 해당한다는 것을 의미했습니다. 나오다).
구형 CPU의 경우 명령 타이밍 정보가 명확하고 사용 가능하며 명확합니다. 최신 ARM의 경우 타이밍 정보가 훨씬 모호해 보입니다. 코드가 플래시에서 실행될 때 캐싱 동작으로 인해 예측하기가 더 어려워 질 수 있으므로 모든 사이클 계산 코드는 RAM에서 실행되어야합니다. 그러나 RAM에서 코드를 실행할 때에도 사양이 약간 모호해 보입니다. 사이클 카운트 코드를 사용하는 것이 여전히 좋은 생각입니까? 그렇다면 안정적으로 작동시키는 가장 좋은 기술은 무엇입니까? 칩 벤더가 특정 경우에 특정 명령의 실행을 단축시키는 "개선 된"칩에 조용히 들어 가지 않을 것이라고 어느 정도까지 안전하게 추정 할 수 있습니까?
다음 루프가 단어 경계에서 시작한다고 가정하면 사양에 따라 얼마나 오래 걸 렸는지 정확하게 판단 할 수 있습니다 (제로 대기 상태 메모리가있는 Cortex-M3을 가정합니다.이 예에서는 시스템에 관한 다른 사항은 없습니다).
myloop : mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 mov r0, r0; 더 많은 명령어를 프리 페치 할 수있는 간단한 간단한 명령어 r2, r1, # 0x12000000 추가; 2 워드 명령 ; 다른 피연산자와 함께 다음을 반복하십시오. ; 캐리가 발생할 때까지 값을 계속 추가합니다 itcc addscc r2, r2, # 0x12000000; itcc를위한 2 워드 명령어 및 추가 "워드" itcc addscc r2, r2, # 0x12000000; itcc를위한 2 워드 명령어 및 추가 "워드" itcc addscc r2, r2, # 0x12000000; itcc를위한 2 워드 명령어 및 추가 "워드" itcc addscc r2, r2, # 0x12000000; itcc를위한 2 워드 명령어 및 추가 "워드" ; ... etc,보다 조건부 두 단어 명령어 하위 r8, r8, # 1 BPL 마이 루프
처음 6 개의 명령어를 실행하는 동안 코어는 6 개의 단어를 가져올 시간이 있으며 그 중 3 개는 실행되므로 최대 3 개의 프리 페치가 가능합니다. 다음 명령어는 각각 세 단어 모두이므로 코어가 명령을 실행하는 속도만큼 빨리 가져올 수 없습니다. "일부"명령어 중 일부는주기가 걸릴 것으로 예상하지만 어느 명령어를 예측하는지는 알 수 없습니다.
ARM이 "it"명령어 타이밍이 결정적인 특정 조건을 지정할 수 있다면 (예를 들어 대기 상태 나 코드 버스 경합이없고 앞의 두 명령어가 16 비트 레지스터 명령어 등인 경우) 좋을 것입니다. 그러나 나는 그런 사양을 보지 못했습니다.
샘플 애플리케이션
Atari 2600이 480P에서 컴포넌트 비디오 출력을 생성하기위한 도터 보드를 설계하려고한다고 가정 해 봅시다. 2600에는 3.579MHz 픽셀 클럭과 1.19MHz CPU 클럭 (도트 클럭 / 3)이 있습니다. 480P 컴포넌트 비디오의 경우 각 라인은 두 번 출력되어야하며 7.158MHz 도트 클럭 출력을 의미합니다. Atari의 비디오 칩 (TIA)은 3 비트 루마 신호와 약 18ns 해상도의 위상 신호를 사용하여 128 색 중 하나를 출력하기 때문에 출력을 보면 색을 정확하게 결정하기가 어렵습니다. 더 나은 방법은 컬러 레지스터에 대한 쓰기를 차단하고, 기록 된 값을 관찰하고, 레지스터 번호에 해당하는 TIA 휘도 값으로 각 레지스터를 공급하는 것입니다.
이 모든 것은 FPGA로 수행 할 수 있지만, 필요한 버퍼링을 처리하기에 충분한 RAM을 가진 FPGA보다 훨씬 빠른 ARM 디바이스가 훨씬 저렴할 수 있습니다 (예, 볼륨의 경우 비용이 많이들 수 있음을 알고 있습니다) t 진짜 요인). 그러나 ARM이 들어오는 클럭 신호를 보도록 요구하면 필요한 CPU 속도가 크게 증가합니다. 예측 가능한 사이클 수는 물건을 더 깨끗하게 만들 수 있습니다.
비교적 간단한 설계 방식은 CPLD가 CPU와 TIA를 감시하고 13 비트 RGB + 동기화 신호를 생성 한 다음 ARM DMA가 한 포트에서 16 비트 값을 가져 와서 적절한 타이밍으로 다른 포트에 쓰는 것입니다. 그러나 저렴한 ARM이 모든 것을 할 수 있는지 확인하는 것은 흥미로운 디자인 과제입니다. DMA는 CPU주기 카운트에 대한 영향을 예측할 수있는 경우 (특히 메모리 버스가 유휴 상태 일 때주기에서 DMA주기가 발생할 수있는 경우) 올인원 방식의 유용한 측면 일 수 있지만 프로세스의 어느 시점에서 ARM은 테이블 조회 및 버스 감시 기능을 수행해야합니다. 블랭킹 간격 동안 컬러 레지스터가 기록되는 많은 비디오 아키텍처와 달리 Atari 2600은 프레임의 표시된 부분 동안 컬러 레지스터에 자주 기록합니다.
아마도 가장 좋은 방법은 몇 개의 개별 논리 칩을 사용하여 컬러 쓰기를 식별하고 하위 비트의 컬러 레지스터를 적절한 값으로 강제 한 다음 2 개의 DMA 채널을 사용하여 들어오는 CPU 버스 및 TIA 출력 데이터를 샘플링하는 것입니다. 출력 데이터를 생성하기위한 제 3 DMA 채널. 그러면 CPU는 각 스캔 라인에 대해 두 소스의 모든 데이터를 자유롭게 처리하고 필요한 변환을 수행하며 출력을 위해 버퍼링합니다. "실시간"으로 발생해야하는 어댑터 업무의 유일한 측면은 COLUxx에 기록 된 데이터를 대체하는 것이며 두 개의 공통 논리 칩을 사용하여 처리 할 수 있습니다.