ISA opcode ---- 어디에서 왔습니까?


13

엔지니어가 명령어 세트 아키텍처를 설계 할 때 특정 바이너리 코드를 명령어로 지정할 때 따라야 할 절차 나 프로토콜 (있는 경우)에 따라 수행합니다. 예를 들어, 10110이로드 명령이라고하는 ISA가있는 경우이 이진수는 어디에서 왔습니까? 로드 조작을 나타내는 유한 상태 머신의 상태 테이블에서 모델링 되었습니까?

편집 : 더 많은 연구를 한 후에 다양한 CPU 명령에 대한 opcode가 할당되는 방법에 대해 묻고 싶습니다. ADD는 10011의 opcode로 지정 될 수 있습니다. 로드 명령어는 10110으로 지정 될 수 있습니다. 명령어 세트에이 바이너리 opcode를 할당하기 위해 어떤 사고 프로세스가 진행됩니까?


8
Monte Dalrymple의 "Verilog HDL을 사용한 마이크로 프로세서 설계"는 Z80 CPU에 대한 매우 상세한 설계 접근 방식을 제공하며, 그로부터 귀하의 질문에 대해 많이 배울 것이라고 생각합니다. 그러나 다른 명령어 세트, 컴파일러 출력 등의 통계 분석을 포함하여 특정 선택에 고려해야 할 많은 사항이 있습니다.하지만이 책부터 시작하는 것이 좋습니다. 그것은 알려진 디자인으로 시작하지만, 그는 그것에 대해 친밀한 세부 사항으로 들어가고 나는 당신이 몇 가지를 선택할 것이라고 생각합니다. 좋은 책.
jonk

또는 실행 엔진 설계에 대해 질문하고 명령의 비트가 어떻게 작동하는지 궁금하십니까? 당신의 말에서 확실하지 않습니다.
jonk

2
다른 사람이이 질문을합니다. 화요일이어야합니다.
Ignacio Vazquez-Abrams

5
@ 스티븐 생각 해봐. 경우 당신이 가 ISA를 설계했다, 어떤 것이 당신 에 대해 생각? 당신의 지침은 같은 길이의 모든 아니었다면, 어떻게 것입니다 당신이 지침은 짧거나 긴 명령어 단어를 선택? 당신이 설계 한 경우 디코드 단계 , 당신은 어떤 것이 소원 처럼 보이도록하여 ISA에 대한? 나는 그 질문이 불필요하게 광범위하기 때문에 (완전히 대답하기가 거의 불가능하다고 생각한다), 당신은 그것에 대한 좀 더 자신의 생각을 넣고 우리가 대답 할 책을 쓸 필요가없는 정확한 질문을 함으로써 그것을 많이 향상시킬 수있다 그것.
Marcus Müller

4
RISC-V 사양 들이 기계 명령어의 인코딩에 대한 공정한 비트를 포함하여, 모든 수준에서 만든 디자인 결정에 대해 이야기. (이것은 프로세서 매뉴얼에서는 드문 일입니다. RISC-V는 가장 먼저 학문적 운동이고 CPU 아키텍처는 두 번째입니다.)
zwol

답변:


6

ISA가 시간이 지남에 따라 성장함에 따라 많은 경우에있어 선택은 꽤 임의적이거나 "가장 적합한 곳"을 기준으로합니다. 그러나 MOS 6502는 제한된 트랜지스터에서 최대한 많이 짜내려고함으로써 ISA 디자인이 큰 영향을받는 칩의 훌륭한 예입니다.

6502의 리버스 엔지니어링 방식 , 특히 34:20 이후의 방법을 설명하는이 비디오를 확인하십시오 .

6502는 1975 년에 도입 된 8 비트 마이크로 프로세서입니다. Z80보다 게이트가 60 % 더 적었지만 두 배 빠르며 (레지스터 등의 관점에서) 더 제한적이지만 우아한 지시 세트.

여기에는 3510 개의 트랜지스터가 포함되어 있는데, 이들은 작은 플라스틱 팀을 통해 광학적으로 축소 된 6502의 다양한 층을 형성하는 작은 플라스틱 팀을 통해 수작업 으로 작성되었습니다 .

아래에서 볼 수 있듯이 6502는 명령 opcode 및 타이밍 데이터를 디코드 ROM으로 전달한 다음 특정 복잡한 상황에서 ROM의 출력을 우선시하는 "랜덤 제어 논리"구성 요소로 전달합니다.

6502 블록 다이어그램

비디오에서 37:00에 주어진 제어 출력에 대해 "1"을 얻기 위해 입력이 어떤 조건을 만족시켜야하는지 보여주는 디코드 ROM 테이블을 볼 수 있습니다. 이 페이지 에서도 찾을 수 있습니다 .

이 표에서 대부분의 것들이 다양한 위치에 X가 있음을 알 수 있습니다. 예를 들어 봅시다

011XXXXX 2 X RORRORA

이는 opcode의 처음 3 비트는 011이어야하고 G는 2 여야합니다. 아무것도 중요하지 않습니다. 그렇다면 RORRORA라는 출력이 적용됩니다. 모든 ROR opcode는 011로 시작합니다. 그러나 011로 시작하는 다른 지침도 있습니다. 이것들은 아마도 "무작위 제어 로직"유닛에 의해 걸러 져야 할 것입니다.

따라서 기본적으로 opcode가 선택되어 서로 동일한 작업을 수행해야하는 명령어가 비트 패턴에서 공통적 인 사항을 갖도록했습니다. opcode 테이블 을 보면이를 알 수 있습니다 . 모든 OR 명령어는 000으로 시작하고 모든 Store 명령어는 010으로 시작하며 0 페이지 주소 지정을 사용하는 모든 명령어는 xxxx01xx 형식입니다. 물론 일부 명령어는 "적합한"것처럼 보이지 않습니다. 왜냐하면 목표는 완전히 규칙적인 opcode 형식이 아니라 강력한 명령어 세트를 제공하기 때문입니다. 이것이 바로 "무작위 제어 논리"가 필요한 이유입니다.

위에서 언급 한 페이지에 따르면 ROM의 일부 출력 라인이 두 번 나타납니다. "우리는 원하는 라인의 출력을 라우팅 할 방법이 없어서 동일한 라인을 다른 라인에 넣었다고 가정합니다. 다시 위치합니다. " 엔지니어가 게이트를 하나씩 직접 그리면서 갑자기 설계의 결함을 깨닫고 전체 프로세스를 다시 시작하지 않는 방법을 생각해내는 것을 상상할 수 있습니다.


22

ISA의 나이에 달려 있습니다.

수작업 설계 초기에 CPU가 개별 논리로 조립 될 때 논리 설계가 먼저 시작되고 광범위하게 최소화 된 후 ISA 비트 패턴은 최소값을 만들기 위해 필요한 값이되었을 것입니다. 논리 작업.

따라서 일부 멀티플렉서가 ALU 출력을 GP 레지스터 파일의 입력에 연결할 수 있도록하는 특정 제어 신호 패턴이있을 수 있습니다. 레지스터 비트의 주소 비트. 이 세 가지 신호 그룹은 명령어 내에 필드를 형성합니다. 각 그룹은 함께 유지되며 자세한 의미는 해당 장치 (ALU 등)의 설계에서 발생하지만 명령 디코더를 설계 할 때까지 그룹은 순서에 관계없이있을 수 있습니다. (x86은 올바른 위치를 보면이 중 일부를 감지 할 수있을 정도로 오래되었습니다. 완전히 새로운 디자인은 아니지만 이전 8080에서 가져 왔습니다.)

나중에 ISA를 "정리"하고보다 규칙적이고 사용하기 쉽게 만들 수 있으며, 하드웨어와 실제 하드웨어 수준의 제어 신호 사이를 "마이크로 코드"를 통해 변환 할 수 있습니다. 이를 "CISC"또는 "Complex Instruction Set Coding"이라고합니다. x86 "Rep"명령어 접두사는 이에 대한 간단한 예입니다. FOR 루프를 작성하지 않아도되므로 다음 명령어가 여러 번 반복됩니다.

나중에 (1980 년대) ARM 프로세서에서 볼 수있는 더 간단한 스타일의 직접 인코딩 (RISC-Reduced Instruction Set Coding)으로 되돌아갔습니다. 이것은 당시 작은 크기의 ASIC과 32 비트 CPU를 사용하고자했기 때문에 복잡한 명령어 세트 디코더를위한 여분의 용량이 없었기 때문에 전체 CPU를 약 20,000 게이트까지 줄일 수있었습니다. 사람들이 CISC 디코더를 빠르게 만드는 기술을 아직 개발하지 않았기 때문에 일시적인 성능 향상도있었습니다. 1995 년 Pentium Pro와 함께 제공되었습니다.

그리고 요즘은 중요하지 않습니다 .CPU는 한 번에 여러 명령을 읽고 수백만 개의 트랜지스터를 디코딩하여 순서를 바꾸고 한 번에 가능한 한 많이 실행하여 가장 오래된 것으로 작성된 프로그램의 속도를 높입니다. ISA의 스타일.


2
CISC를 "사용하기 더 쉽다"고 정말로 확신하지는 않습니다. 그것은 원래 의도 였을지 모르지만, 30 년 후 그들은 "사용하기 쉽다"(적어도 RISC ISA와 비교)라는 반론 일뿐입니다.
tonysdg

2
컴파일러가 비교적 사소한 프로그램이었을 때 규칙 성 (직교성이 큰 주제)으로 돌아가거나 더 높은 수준의 연산을 직접 지원하여 컴파일러에서 적은 번역을 요구하는 점에서 사용하기가 더 쉽다는 점이 있습니다. 그러나 그것은 오래 전에 이루어졌으며 살아남은 CISC는 원래 명령 세트 위에 너무 많은 수정 레이어가 있습니다. 컴파일러는 모든 인식에서 벗어났습니다. gcc가 수행 한 수천 가지의 최적화 패스는 당시에는 생각할 수 없었을 것입니다. 그래서 "쉬운"것과 지금은 거의 관계가 없습니다.
Brian Drummond

4
이 차이는 사라졌고 ( "RISC"는 명령어를 추가로 설정) VLIW와 같은 훨씬 더 복잡한 새 아키텍처로 대체되었습니다. 실제로 유일한 합의는 x86 (16 및 32 비트)을 사용하기 어렵다는 것입니다.
pjc50

1
@tonysdg : RISC를 사용하기 어렵고 CISC를 사용하기가 어렵습니다. "프로그래머 친 화성"에 대한 좋은 비교는 68k와 ARM을 비교하는 것입니다. ARM은 컴파일러 용으로 설계되었으므로 RAM에서 데이터를 가져오고 RAM에 다시 쓰려면 많은 수동 작업을 수행해야했습니다. 68k는 어셈블리 프로그래머를 위해 설계되었으며 RAM의 데이터를 직접 조작 할 수 있습니다. 68k ISA를 보면 한 가지 예외를 제외하고는 현대 RISC ISA와 매우 비슷하다는 것을 알 수 있습니다. RAM에서는 직접 작동 할 수 있지만 RISC는 레지스터에서만 작동 할 수 있습니다.
slebetman

1
마이크로 코드는 주로 CISC 속성입니다. 그러나 마이크로 코드없이 CISC를 구현할 수 있습니다. 명령어 디코더가 더 복잡합니다. 또한 Pentium-Pro의 일부 CISC는 내부적으로 RISC로 설명되어 있습니다. 하나 개 이상의 내부 RISC 본부에 각각 CISC 인스트럭션 번역 : 마이크로 다른 이름을 (구별은 수퍼 스칼라 실행 유닛 흐리게받을지라도)
브라이언 Drummond는

9

유사한 지침을 함께 그룹화하면 패턴이 나타납니다. 이것은 ARM에서 매우 분명합니다. ISA 매뉴얼은 실제로 어떤 비트의 명령어가 함수, 레지스터 선택 등에 해당 하는지를 보여줍니다. 그러나 X86 에서도 추론 될 수 있습니다 .

궁극적으로 opcode의 "기능"부분은 파이프 라인 된 작업의 특정 기능이나 시퀀스를 실제로 활성화하는 2 진 대 1 핫 디코더로 들어갑니다. 상태 머신이 디코딩해야하는 가변 길이 명령어를 고려하지 않는 한 일반적으로 상태 머신의 내용과 관련이 없습니다.


당신은 기본적으로 칩에서 가능한 가장 낮은 트랜지스터 수를 위해 움직입니다. 나는 OP의 질문과 관련하여 더 깔끔한 명령 세트를 위해 수백 개의 추가 트랜지스터를 감당할 수 없다는 것에 완전히 동의합니다. 백만 트랜지스터 CPU는 관심을 가질만한 이유가 거의 없지만 물론 이전 버전과의 호환성을 위해 많은 CPU를 유지합니다.
하퍼-복원 모니카

@Harper 트랜지스터가 작아졌지만 여전히 크기가 있고 그 동안 클럭 속도가 크게 증가했기 때문에 여전히 이유가 있습니다. 따라서 너무 큰 명령어 디코더는 여전히 성능에 병목 현상이 될 수 있습니다 (많은 CPU가 사전에 명령어 를 미리 디코딩 하도록 선택한 이유 중 하나 ). 트랜지스터 수에 관한 것이 아니라 다이 영역과 결합한 클록 속도에 관한 것입니다. 정보를 전파하는 데 여전히 시간이 걸리고, 최신 CPU는 빠른 속도로 실행되지 않지만, 상당한 개선을 기대하기에는 속도 제한에서 멀지 않습니다.
Luaan

@Luaan : 실제로 "이러한 트랜지스터로 무엇을해야합니까?"는 요즘 실제 질문입니다. 요즘 던져지는 모든 L2 / L3 캐시를보십시오. 그것은 우리가 수백만 개의 트랜지스터 모두에 대해 더 잘 사용하지 않는 조용한 입장입니다. 최신 Xeon 은 캐시에 20 억 개 이상의 트랜지스터를 사용합니다!
MSalters

6

어느 시점에서 누군가 앉아서 앉았다.

좋은 ISA는 디코더를 가능한 한 단순하게 만듭니다.

예를 들어 ALU 명령어를 사용하면 일부 opcode 비트를 ALU의 제어 라인으로 직접 보낼 수 있습니다.


훌륭한 답변에 감사드립니다. 당신은 내가 이것을 훨씬 더 잘 이해하도록 도와주었습니다.
Steven

4
실제로 디코더 단순성 외에 고려해야 할 몇 가지 요소가 있습니다. 상황 및 의도 된 용도에 따라, 다른 것 (예를 들어, 코드 밀도)이 디코더 단순성보다 더 중요 할 수있다. 최신 프로세서에서 코드 밀도는 대부분의 경우 디코더 단순성보다 중요 합니다.
Jerry Coffin

5

일반적으로 ISA를 기능 그룹으로 분할합니다. 무료 쌍이 단일 비트 변경 (로드 대 저장)에 의해 구별되고 디코드 결정 트리에 영향을주는 비트 계층이 있다는 것이 의미가 있습니다 (논리 최적화 또는 깔끔함).

하루가 끝나면 함수 블록에 임의의 비트 할당 (명령에 '데이터'필드를 배치하는 것과 달리 전체 설계 효율성에 미치는 영향은 적지 만 방법에 대한 선택은 많이 있습니다. 느끼는 것이 중요한 매개 변수에 따라 ISA 인코딩을 '최적화'하십시오.


1

명령어 인코딩은 그 사이의 추악한 절충안입니다.

디코드를 간단하게하기 위해, 각각의 필드가 별도로 디코딩되어 실행 엔진의 별도 부분으로 라우팅 될 수있는 간단한 필드 세트를 원합니다.

가능한 한 많은 기능을 제한된 크기의 명령어로 포장합니다. 이것은 다양한 공통 숫자를 인코딩 할 수있는 특수 상수 형식과 같은 것들로 이어집니다.

정방향 및 역방향 호환성. 가능한 모든 opcode에 기능을 할당하면 나중에 아키텍처를 확장 할 여지가 없습니다. 기존 아키텍처에 추가하는 경우 새 명령을 예비 opcode에 슬롯해야합니다.


1

랜디 하이드 (Randy Hyde)의 우수함 (일부 날짜가있는 경우) The Art of Assembly3.3.4 장에 나오는 제어 유닛 및 명령 세트 및 세부 사항에 자세히 설명되어있는 x86 명령 세트에 들어갑니다 .

초기 (Von Neumann 이전) 컴퓨터 시스템의 프로그램은 종종 회로에 "하드 와이어"되었습니다. 즉, 컴퓨터의 배선으로 인해 컴퓨터가 어떤 문제를 해결할지 결정했습니다. 프로그램을 바꾸기 위해 회로를 다시 배선해야했습니다. 매우 어려운 작업입니다. 컴퓨터 설계의 다음 발전은 프로그램 가능한 컴퓨터 시스템으로, 컴퓨터 프로그래머가 일련의 소켓 및 플러그 와이어를 사용하여 컴퓨터 시스템을 쉽게 "재배 선"할 수있게하였습니다. 컴퓨터 프로그램은 일련의 구멍 (소켓)으로 구성되어 있으며 각 행은 프로그램 실행 중 하나의 작업을 나타냅니다. 프로그래머는 원하는 명령어를 위해 특정 소켓에 와이어를 꽂아 여러 명령어 중 하나를 선택할 수 있습니다.

그런 다음 첫 번째 플러그 쌍이 명령을 나타내는 방법에 대해 매우 흥미롭고 긴 길이를 보여주고 다음 플러그는 소스와 대상을 인코딩합니다. 물론 오늘날에는 더 이상 "플러그"하는 사람이 없지만, 아주 오래된 ISA의 경우 opcode의 비트는 기본적으로 이전의 플러그와 동일한 작업을 수행합니다.

다음과 같이 끝납니다.

여기에 이미지 설명을 입력하십시오


Hyde의 링크에 감사드립니다! 그것은 매우 유익하고 그는 훌륭한 교수 스타일을 가지고있는 것 같습니다.
Steven
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.