2011-09-20 5 views
15

TTL 직렬 컴퓨터를 설계하고 있으며 LLVM 컴파일러 백엔드에 더 적합한 아키텍처 선택에 어려움을 겪고 있습니다. (저는 C++ 소프트웨어를 실행할 수 있기를 원합니다). MMU, 곱셈/나눗셈, 하드웨어 스택 없음, 인터럽트 없음.LLVM/CLANG에 대한 CPU 아키텍처 선택

나는 두 가지 주요 옵션이 있습니다

1) 8 비트 메모리, 8 비트 ALU, 8 비트 레지스터 (~ 12-16). 메모리 주소 너비는 24 비트입니다. 그래서 나는 3 개의 레지스터를 IP로, 3 개의 레지스터를 메모리 위치에 사용해야 할 것입니다.

모든 주소 계산은 컴파일러에서 구현하기에 순수한 고통이라고 말할 수 있습니다.

2) 24 비트 메모리, 24 비트 ALU, 24 비트 레지스터 (~ 6-8). 편평한 기억, 좋은. 단점은 디자인의 일련의 특성으로 인해 각 연산은 심지어 일부 불리언 (boolean)으로 작동하는 경우에도 3 배 더 많은 시간이 소요된다는 것입니다. 24 비트 메모리 데이터 폭은 비쌉니다. 그리고 하드웨어 전반에 구현하기가 더 어렵습니다.


질문은 :이 8 비트의 모든 C++ 기능을 구현하는 생각합니까, 스택리스 기반의 하드웨어는 가능하다, 아니면 합리적인 품질 & 속도의 생성 된 코드를 가지고 더 복잡한 하드웨어가 필요?

+0

이것은 간단한 질문 일 수도 있지만, 왜 C++의 모든 기능을 구현해야합니까? 당신은 단지 새로운 LLVM 타겟 아키텍처를 쓸 수 없으며, Clang은 문제없이 C++를 컴파일 할 것인가? –

+0

@Dan Cecile 바로 내가 할 일입니다. 그러나 24 비트 메모리 공간을 갖춘 8 비트 CPU 용 LLVM 백엔드 작성은 다소 단순 할 수 있습니다. – BarsMonster

+0

그래서 네 부분으로되어 있습니다. [LLVM 어셈블리 언어] (http://llvm.org/docs/LangRef.html)를 구현하는 방법을 알아 내고 하드웨어와 함께 작동하며 [기존 LLVM 대상] (https://github.com/earl)을 복사 및 적용합니다./llvm-mirror/tree/master/lib/Target) 하드웨어를 사용하여 Clang이 [8 비트 LLVM 바이트 코드를 생성하는 방법] (http://clang.llvm.org/doxygen/classclang_1_1TargetInfo.html)을 구하십시오.) ([포인터 크기는 구성 가능합니다.] (http://clang-developers.42468.n3.nabble.com/Re-targeting-clang-to-a-new-architecture-tp761920p762813.html)) 하드웨어를 다음과 같이 변경하십시오. 더 적합하다. –

답변

18

초부터 LCC를 사용하는 것이 좋습니다. 이 homebrew 16-bit RISC 프로젝트에서 사용했습니다 : http://fpgacpu.org/xsoc/cc.html.

8 비트 변형을 구현하고 3 개의 add-with-carry를 사용하여 IP를 늘리거나 24 비트 변형을하고 하드웨어에서 전체 작업을 수행해야할지 여부는별로 다르지 않다고 생각합니다. 어셈블러의 차이를 숨길 수 있습니다.

위의 기사 나 여기의 더 간단한 CPU를 보면 : http://fpgacpu.org/papers/soc-gr0040-paper.pdf 정수 C 반복문을 다루는 데 필요한 많은 연산자/명령어가 필요하지 않습니다. 실제로 주어진 기계에 대해 min 연산자 세트를 인쇄하는 lcc 유틸리티 (ops)가 있습니다. 자세한 내용은

여기에 새 시스템으로 LCC를 포팅에 내 문서를 참조하십시오 http://www.fpgacpu.org/usenet/lcc.html 내가 LCC를 이식 한 후

, 나는 어셈블러를 작성하고, 기본적인 것들과 지침의 큰 repetoire을 합성.예를 들어, 내 컴퓨터는로드 바이트 부호하지만 부하 바이트 서명했다, 그래서 나는이 순서 방출 :

registers 
    load register with constant 
    load rd = *rs 
    store *rs1 = rs2 
    + - (w/ w/o carry) // actually can to + with - and^
    >> 1     // << 1 is just + 
    &^     // (synthesize ~ from ^, | from & and ^) 
    jump-and-link rd,rs // rd = pc, pc = rs 
    skip-z/nz/n/nn rs  // skip next insn on rs==0, !=0, <0, >=0 
:

lbs rd,imm(rs) -> 
    lbu rd,imm(rs) 
    lea r1,0x80 
    xor rd,r1 
    sub rd,r1 

그래서 난 당신이 작업이 분 커버에 의해 얻을 수 있다고 생각을

심지어 레지스터가 없으면 (또는 메모리가있는 레지스터를 흐릿하게 만드는 경우 - 모든 레지스터에 메모리 주소가 있음) 훨씬 간단합니다.

SP에 대한 레지스터를 별도로 설정하고 컴파일러에 prolog/epilog 처리기 함수를 쓰면 스택 지침에 대해 걱정할 필요가 없습니다. 각 피 호출자 저장 레지스터를 저장하고 프레임 크기에 따라 SP를 조정하는 등의 코드가 있습니다.

인터럽트 (및 인터럽트로부터의 복귀)는 간단합니다. 명령 레지스터에 점프 앤 링크 명령을 강제로 수행하면됩니다. 0과 같은 비트 패턴을 선택하고 올바른 주소를 소스 레지스터 rs (특히 r0 인 경우)에 넣으면 플립 플롭 재설정 입력 또는 추가 강제 설정 값을 사용하여 수행 할 수 있습니다. 0과 게이트. 위의 두 번째 논문에서 비슷한 트릭을 사용합니다.

흥미로운 프로젝트입니다. TTL/7400 컨테스트가 진행 중이고 컴퓨터가 얼마나 단순해질 수 있는지 생각하고 있었고 코드와 데이터를 저장하기 위해 32KB 또는 128KB 비동기 SRAM을 컴퓨터에 추가하는 것이 바람 피 웠을 것입니다.

어쨌든, 해피 해킹!

p.s.

1) 각 정수 유형의 크기를 결정해야합니다. 원하는 경우 최소 문자 표현 범위에서 호환되지는 않지만 char, short, int, long, long long 등과 같은 크기, 한 개의 24b 단어를 만들 수 있습니다.

2) 그리고 여기서 lcc에 초점을 맞추었지만 C++에 대해 묻고있었습니다. 나는 C를 우선 권고한다. 소프트웨어에서 *, /, % 연산자를 포함한 C에 대한 정보를 얻은 후에는 LLVM 또는 GCC에 상관없이 완전한 C++로 이동하는 것이 더 쉽습니다. C와 C++의 차이점은 가상 함수 호출, 멤버 역 참조 (dereference), 동적 캐스트, 정적 생성자, 예외에 대한 포인터를 처리하는 데 필요한 여분의 vtable 및 RTTI 테이블과 코드 시퀀스 (전체적으로 기본 C 정수 연산자 repetoire로 구성되어 있음) 처리 등.

+2

p.s. 나는 생각하고 있었다. 8b 변형보다 24b 변형을 빌드해야합니다. 명령과 데이터를위한 선형 24b 주소 공간의 개념이 필요하기 때문에 넓은 데이터 작업마다 각각 여러 개의 명령이 필요하기 때문이 아닙니다. 3 개의 8b로드 중 24b로드를 합성 할 수 있지만 하드웨어에서 명령어 가져 오기, 프로그램 카운터 및 PC 증가를 처리하려면 24b 주소 (24b 주소 증가)가 필요합니다. 주소가 8b 인 경우 256 개 이상의 명령어를 처리하는 방법이 명확하지 않습니다. –

1

제 생각에 스택리스 하드웨어는 이미 C 및 C++ 코드에 적합하지 않습니다. 중첩 된 함수 호출이 있으면 어쨌든 소프트웨어 스택을 에뮬레이션해야합니다. 물론 속도는 훨씬 느립니다.

스택리스 경로를 사용하면 대부분의 변수를 '정적'으로 할당하고 재진입 기능이 없을 것입니다. 이 경우 6502 스타일 어드레싱 모드가 효과적 일 수 있습니다. 메모리에 즉시 24 비트 주소 : 오피

  • 즉시 주소 (24 비트) 플러스 인덱스 레지스터 (8 비트)
  • 간접 접근의 일환으로

    1. 즉시 주소 (24 비트) : 당신은 예를 들어 다음 주소 모드를 가질 수있다 실제 주소가 포함 된 주소
    2. 간접 액세스 : 메모리에 24 비트 주소, 메모리에서 값에 8 비트 인덱스 레지스터가 추가되었습니다.

    위에서 설명한 주소 모드를 사용하면 고정 주소 (정적 할당)에 할당 된 배열, 구조 및 개체에 효율적으로 액세스 할 수 있습니다. 동적 및 스택 할당 객체에 대해서는 효율성이 떨어지지만 여전히 유용합니다.

    또한 직렬 디자인에서 약간의 혜택을 얻을 것

    은 : 일반적으로 24 비트 + 8 비트뿐만 아니라 24주기를 고려하지 않습니다,하지만 당신은 단락 캐리가 0

    대신 매핑 추가 대신 할 수 IP를 레지스터로 직접 사용하는 경우 위와 동일한 주소 모드를 사용하여 goto/branch 명령을 통해서만 IP를 변경할 수 있습니다. 동적으로 계산 된 주소로의 점프는 매우 드물기 때문에 전체 24 비트 주소를 opcode에 직접 제공하는 것이 좋습니다.

    CPU를 신중하게 설계하면 많은 C++ 기능을 매우 효율적으로 사용할 수 있다고 생각합니다. 그러나 임의의 C++ 코드가 제한된 CPU에서 빠르게 실행될 것으로 예상하지 마십시오.

  • +0

    그래, 스택없는 코드는 쓸모가 없다. 나는 여전히 기존 코드를 크로스 컴파일 할 수 있기를 원한다. 그래서 에뮬레이트 스택을 사용해야 할 것입니다. – BarsMonster

    +1

    하드웨어 스택을 구현할 수 있습니다. 단지 두 가지 더 많은 명령어가 필요하며 직렬 아키텍처에서 증가/감소가 매우 빠르고 쉽습니다. – jpa

    1

    구현은 가능하지만 C++ 코드에서는 사용할 수 있을지는 의문입니다.이미 언급했듯이, 첫 번째 문제는 스택 부족입니다. 다음으로 C++은 동적 메모리 할당에 크게 의존하며 C++의 "내부"구조도 상당히 큰 편입니다.

    1. 를 사용하여 24 비트를 요구 ++ C를 제거 (또는 적어도 일부 부분 집합에 자신을 제한)하기,하지 : 그것은 나에게 보인다는 경우

      그래서, 그것은 더 좋을 것이다 (레지스터뿐만 아니라) 모든 8 비트

    2. 추가 하드웨어 스택
    +0

    음, 하위 집합을 구현하는 것이 전체 C++보다 어렵습니다. 후자의 경우 clang/llvm 백엔드 만 써야합니다. 왜 하드웨어가 없다면 그런 심각한 문제가 쌓일까요? 소프트웨어가 동일한 작업을 수행 할 수 있습니까? – BarsMonster

    +0

    성능에 신경 쓰지 않는다면 괜찮습니다. 예 : –

    3

    IMHO, 그것은 C 컴파일러 가능하다. 그래도 C++에 대한 확신이 없습니다.

    LLVM/연타는

    대신, 첫째, 등/다음 두 번째 LLVM, HTH를 lcc 시도, 8 비트 컴퓨터의 하드 선택이 될 수 있습니다.

    빌 Buzbee 그의 매직-1 (homebrewcpu라고도 함)에 대한 LCC 컴파일러의 대상을하는 성공.

    일반적으로 Magic-1의 하드웨어 설계 및 구성에 가장 많은 관심을 기울이지 만 프로젝트의 가장 큰 부분 (지금까지)은 소프트웨어를 개발/이식하고 있습니다. 이를 위해 어셈블러와 링커를 처음부터 작성하고, C 컴파일러의 타겟을 다시 지정하고, 표준 C 라이브러리를 작성하고 포팅하고, 단순화 된 운영 체제를 작성한 다음보다 정교한 코드를 포팅해야했습니다. 도전 이었지만 재미있었습니다. 다소 엉망이긴하지만 어려운 문제를 디버깅하는 것을 즐긴다. 그리고 추적하려고하는 버그가 하드웨어 디자인 결함, 느슨하거나 끊어진 와이어, 느슨하거나 나쁜 TTL 칩, 어셈블러 버그, 링커 버그, 컴파일러 버그, C 런타임 라이브러리 버그 또는 마침내 포함될 수 있습니다. 문제가되는 프로그램의 버그는 재미있는 기회가 많습니다. 아, 그리고 다른 사람들에게 벌레를 비난하는 사치품도 없습니다.

    나는 지독한 일이 전혀 실행되지 않는다는 사실에 계속해서 놀라움을 금치 못합니다.

    -1

    "any"C++ 코드를 실행할 수 없습니다. 예를 들어 fork(), system() 등은 인터럽트에 의존하는 모든 것을 말합니다. 거기까지 갈 길이 멀다. 이제 C++로 작성/작성하거나 일반적으로 C/C++와 관련된 라이브러리가 아닌 언어로만 제한하는 프로그램을 의미합니까? 언어 자체는 훨씬 쉽게 사는 규칙입니다.

    더 쉬운 질문/답변이라고 생각해보십시오. 지금까지 뭐 해봤 어? x86은 8 비트 기계이고, 정렬 및 많은 8 비트 명령어는 고려하지 않을 수도 있습니다. msp430은 llvm으로 이식되어 얼마나 쉽고 빠르게 수행되는지 보여주었습니다. 16 비트 플랫폼을 사용하면 더 나은 지원이있는 플랫폼 (내 강점이없는 곳이 아닌 곳)을보고 싶습니다. 아니 mmu. 스택이 있고 인터럽트가 있는지, 사용하지 않아도되며 라이브러리 규칙을 제거하면 인터럽트가 필요한 것입니다.

    나는 llvm을 살펴볼 것이지만, 문서 작성이 얼마나 쉽고, 날짜가 잘못되었고, 잘못된 것이고, 기본적으로 컴파일러 소스에서 직접 알아 내야 만한다는 것을 알 수 있습니다. LLC에는 최적화되지 않은 저서가 있습니다.근원은 근대 컴퓨터에 잘 컴파일되지 않으며 항상 그것을 사용하기 위해 거슬러 올라 가기 위해 노력해야합니다. 저녁을 지나면 그걸 만들려고 할 때마다 나는 그것을 포기합니다. vbcc, 간단하고, 깨끗하고, 문서화되었으며, 작은 프로세서에는 비우호적이지 않습니다. C++이냐고 기억하지 못합니다. 컴파일러를 설치하고 실행하는 것이 가장 쉬운 방법입니다. 그들 모두의 LLVM은 가장 매력적이고 가장 유용 할 때 모든 말하고 행해진 것입니다. gcc 근처에 가지 마라. 심지어는 그것을 생각해라. 덕트 테이프와 묶어 두는 철사.

    아직 지침을 발명 했습니까? 아직 시뮬레이터와 어셈블러가 있습니까? 내 명령을 찾으려면 github에서 lsasim을 찾으십시오. 내 llvm 백엔드를 연습 할 수있다. 웃어라. (내 vbcc 백엔드는 끔찍하다. 다시 시작할 필요가있다.) ...

    높은 수준 구현 될 것이지만 실제로는 명령어 세트와 명령어 세트 시뮬레이터 및 어떤 종류의 어셈블러로 시작해야합니다. 그런 다음 손을 C/C++ 코드를 어셈블리로 어셈블리를 시작하여 명령어 세트로 가져 오면 꽤 빨리 "스택없이이 작업을 수행 할 수 있습니까?"등의 작업을 수행해야합니다.이 프로세스에서 호출 규칙을 정의하고 직접 C/C++ 코드를 구현하십시오 귀하의 전화 규칙을 사용하십시오. 그런 다음 컴파일러를 파고 백 엔드를 만듭니다. 나는 당신이 디딤돌로 vbcc를 고려해야한다고 생각합니다. 그렇다면 LLVM을 향해 머리를 맞 춥니 다 (isa).

    관련 문제