D 프로세서의 인터럽트 처리를 시뮬레이션해본 결과다. 위에 보이는 3개의 시그널중 첫번째는 클럭을 나타내고, 두번째는 프로그램 카운터의 내용을 말한다. 마지막 세번째 시그널이 인터럽트다. 시뮬레이션에 사용된 프로그램은 0x0003번지에서 0x0000으로 무조건 분기하도록 되어있고 0x0002번지에서 인터럽트를 활성화 시킨다. ISR은 0x0000으로 설정되어있다.
두번째 인터럽트가 걸릴때 0x0001번지에서 정상적인 프로그램 흐름과 다르게 0x0000으로 점프하는것을 볼 수 있다. 인터럽트 서비스 루틴으로 점프가 확실히 되는걸 알 수 있다.
@ 특징 D-Processor는 단순한 구조를 가진 16비트 RISC로 16비트 어드래스 버스와 16비트 데이터 버스를 갖고있다. 프로그램 메모리와 데이터 메모리가 분리된 구조 즉, 하버드 아키택쳐를 사용하고 있고 주소는 워드단위(16비트)로 주어진다.
따라서 128Kb의 주소공간을 가진다 (프로그램 메모리 128Kb, 데이터 메모리 128Kb). 모든 명령어는 16비트로 고정된 길이를 가지고, 메모리 접근은 로드 LD, 스토어 ST, 하위 바이트 스토어 STB의 세가지만을 제공한다.
대부분의 연산은 내부 레지스터에 의해서 이루어 지며, D-Processor는 8개의 범용 레지스터를 제공하고 있다. 주소모드는 5가지가 제공되며 단순하지만 서브루틴의 호출과 리턴을 구현하는 명령어가 제공되고 있다. 또한 인터럽트의 처리도 가능하다. 전체 인스터럭션 사이클이 한 클럭에 실행되는 싱클 사이클 익스큐션을 구현하고 있다.
more..
@ 레지스터
D
-Processor는 R0~R7까지의 범용 레지스터 8개를 제공하고 있다. 이중 R0 레지스터는 읽기전용으로 사용되며 항상
상수값 0을 출력한다. 특수 목적 레지스터로는 프로그램 카운터를 저장하기 위한 PC(Program Counter; 16비트),
인터럽트 서비스 루틴의 주소를 저장하기 위한 ISR(Interrut Service Routine; 16비트), 예외 처리를 위해
PC를 백업하는 EPC(Effective Program Counter; 16비트), 인터럽트 인에이블 플랙을 저장하기 위한
IF(Interrupt Flag; 1비트)가 있다.
@ 주소 모드
Register Mode : 명령어에 지정된 레지스터의 값이 피연산자가 된다. Immediate Mode : 명령어에 지정된 상수값이 피연산자가 된다. PC-Relative Mode : 현제 PC + 1 + 명령어에 지정된 상수값이 유효 주소가 된다. Register-indirect Mode : 명령어에 지정된 레지스터의 값이 우효 주소가 된다. Pseude Absolute Mode : 명렁어에 지정된 상수값이 유효 주소가 된다.
4 스태이지 파이프라이닝을 구현할 계획에 있으며컨트롤 해저드는 정적 분기 예측 기법과 분기 최적화 기법을 사용해 하드웨어적으로 회피할 것이며, 데이터 해저드 역시 데이터 포워딩 기법을 사용해 하드웨어적으로 제거할 예정이다.<- 현재까지는 미구현사항.
I7-format는 2개의 피연산자중 하나가 7비트 즉치값인 경우를 위한 포멧이다. 명령어에 따라 부호 확장을 하기도 한다.
I8-Format opcode(3) | DR(3) | F2(2) | imm8(8)
I8-format는 8비트 상수 값을 즉치값으로 지정할 필요가 있을 경우에 사용하는 포멧이다. 이 8비트값을 16비트로 확장하여 사용한다.
J-Format opcode(3) | Addr(13)
무조건 분기 명령어인 JAL에 사용되는 포멧이다. JAL은 Pseude Absolute 주소모드로 EA를 계산해서 분기하는데,
명령어에서 주어진 13비트에 현제 PC값의 MSB 3비트를 덧붙여 EA를 얻는다. 이렇게 함으로 128KB의 주소공간을 8개의
세그먼트로 분할했을대각 세그먼트 내에서는 절대 주소로 분기할 수 있다.
산술 연산 명령어
ADD DR, SA, SB Reg[DR] = Reg[SA] + Reg[SB] SUB DR, SA, SB Reg[DR] = Reg[SA] - Reg[SB] ADI DR, SA, imm7 Reg[DR] = Reg[SA] + SignExtend(imm7) ADIU DR, SA, imm7 Reg[DR] = Reg[SA] + ZeroExtend(imm7) LSL DR, SA, SHT Reg[DR] = Reg[SA] << SHT LSR DR, SA, SHT Reg[DR] = 0 || (Reg[SA] >> SHT) ASR DR, SA, SHT Reg[DR] = MSB || (Reg[SA] >> SHT) LDI DR, imm8 Reg[DR] = ZeroExtend(imm8)할 LUI DR, imm8 Reg[DR] = imm8 << 8 ORI DR, imm8 Reg[DR] = Reg[DR] | ZeroExtend(imm8)
LUI와 ORI 명령어를 사용해서 16비트 즉치값을 메모리 접근없이 레지스터에 저장할 수 있다.
논리 연산 명령어 XOR DR, SA, SB Reg[DR] = Reg[SA] xor Reg[SB] AND DR, SA, SB Reg[DR] = Reg[SA] and Reg[SB] OR DR, SA, SB Reg[DR] = Reg[SA] or Reg[SB] SLT DR, SA, SB if Reg[SA] < Reg[SB] Reg[DR] = 1 else Reg[DR] = 0 SLE DR, SA, SB if Reg[SA] <= Reg[SB] Reg[DR] = 1 else Reg[DR] = 0 NOT DR, SA Reg[DR] = not Reg[SA] ORI DR, imm8 Reg[DR] = Reg[DR] | ZeroExtend(imm8) ANI DR, imm8 Reg[DR] = Reg[DR] and ZeroExtend(imm8)
R1 > R2인 경우 L2로 분기하는 프로그램은 다음과 같이 2개의 명령어로 작성할 수 있다. if(R1 > R2) goto L2; SLT R3, R2, R1 BNZ R2, L2
분기 명령어 JR DR, SA PC = Reg[SA], Reg[DR] = PC + 1 BZ DR, imm8 PC = PC + 1 + SignExtend(imm8) BNZ DR, imm8 if DR == 0 PC = PC + 1 + SignExtend(imm8) BPOS DR, imm8 if DR > 0 PC = PC + 1 + SignExtend(imm8) BNEG DR, imm8 if DR < 0 PC = PC + 1 + SignExtend(imm8) JAL ADDR PC = PC[15..13] || ADDR, Reg[7] = PC + 1
JAL
명령어를 사용해서 분기를 하게되면 PC + 1을 Reg[7]로 백업하기 된다. 이를 이용해 JAL과 JR 명령어로 프로시져 콜을
구현할 수있다. 프로시져 콜은 JAL명령어를 사용하고 원래의 프로그램 흐름으로 돌아올때 JR 명령어를 사용한다.
func() JAL addr_of_func
func() { . some operation . return JR R7 }
메모리 접근 명령어 LD DR, SA Reg[DR] = Mem[SA] ST SA, SB Mem[Reg[SA]] = Reg[SB] STB SA, SB Mem[Reg[SA]][7..0] = Reg[SB][7..0]
기타 명령어 SISR SA ISR = Reg[SA] EIF Enable Interrupt CIF Disable Interrupt RTI PC = EPC, Enable Interrupt
인터럽트가 활성화 되어 있을때 인터럽트가 걸리면 PC를 EPC로 백업하고 ISR 레지스터에 지정된 주소로 분기한다. 인터럽트
서비스가 끝나고 RTI 명령을 만나면 EPC에 백업된 주소로 복귀하면서 다시 프로그램이 수행된다. 인터럽트 루틴으로 분기하면서
인터럽트는 비활성화되고 복귀하면서 활성화 된다. D프로세서는 중첩된 인터럽트를 지원하지 않는다.
---------------------------------------------------------------------------------------------------- 현재는 모든 인스트럭션이 구현되어 있는 상태고 Altera Cyclone II 2C35 FPGA에서 50Mhz로 작동되는걸 확인해 보았다.
Pc-Relative mode : 현제 PC + 2 + 명령어에서 지정한 상수이 Effective Address
Register-indirect : 명령어에서 지정한 레지스터 값이 EA
Pseude Absolute : 명령어에서 지정한 상수 값이 EA
명령어포멧
R-Format
opcode(3) | DR(3) | SA(3) | SB/SHT(3) | f1(4)
I7-Format
opcode(3) | DR(3) | SA(3) | imm7(7)
I8-Format
opcode(3) | DR(3) | f2(2) | imm8(8)
J-Format
opcode(3) | addr(13)
R -format는 2개의 피 연산자와 목적지가 모두 레지스터인 경우와 쉬프트 명령어를 위한 포멧이다. R-format 에서 opcode와 f1 field 부분이 연산의 종류를 나타내며, SA 필드는 피연산자로서 레지스터를 나타내는 필드이다. SB/SHT는 일반 산술/논리 연산의 경우에는 피연산자로 사용될 레지스터를 가리키며, 쉬프트 명령어의 경우는 한번에 쉬프트 시킬 비트의 수를 나타낸다.
I7-format는 2개의 피연산자중 하나가 7비트 즉치값인 경우를 위한 포멧이다. 16비트 프로세서임으로 7비트의 값을 16비로 확장하여 사용한다.
I8-format는 8비트 상수 값을 즉치값으로 지정할 필요가 있을 경우에 사용하는 포멧이다. 이 8비트값을 16비트로 확장하여 사용한다. 이때 f2필드는 연산의 종류를 지정하는데 추가로 사용한다.
J-format는 분기명령어 JAL에 사용되는 포멧이다. Pseude Absolute 주소모드로 EA를 계산해서 분기하게 되는데 이때 현제 PC+2의 값은 무조건 R7에 저장된다. 점프할 주소의 계산은 addr필드의 13비트를 2배하여 얻어진 14비트에 현제 PC값의 MSB 2비트를 앞에 덧붙여서 16비트를 만든다. 이렇게 함으로 전체 64K바이트의 주소공간을 4개의 세그먼트로 분할 했을때 각 세그먼트 내에서는 절대 주소로 분기할 수 있다.
산술/논리 연산 명령어
Pseudo code
RTL 수준의 기술
format
예
ADD DR, SA, SB
Reg[DR] <- Reg[SA] + Reg[SB]
R-format
ADD R1, R2, R3
SUB DR, SA, SB
Reg[DR] <- Reg[SA] - Reg[SB]
R-format
SUB R1, R2, R3
ADI DR, SA, imm7
Reg[DR] <- Reg[SA] + se(imm7)
I7-format
ADI R1, R2, -63
ADIU DR, SA, imm7
Reg[DR] <- Reg[SA] + ze(imm7)
I7-format
ADIU R1, R2, 64
XOR DR, SA, SB
Reg[DR] <- Reg[SA] xor Reg[SB]
R-format
XOR R1, R2, R3
AND DR, SA, SB
Reg[DR] <- Reg[SA] and Reg[SB]
R-format
AND R1, R2, R3
OR DR, SA, SB
Reg[DR] <- Reg[SA] and Reg[SB]
R-format
OR R1, R2, R3
NOT DR, SA
Reg[DR] <- not Reg[SA]
R-format
NOT R1, R2
ORI DR, imm8
Reg[DR] <- Reg[DR] or ze(imm8)
I8-format
ORI R1, 255
ANI DR, imm8
Reg[DR] <- Reg[DR] and ze(imm8)
I8-format
ANI R1, 255
LSL DR, SA, SHT
Reg[DR] <- Reg[SA] << SHT
R-format
LSL R1, R2, 5
LSR DR, SA, SHT
Reg[DR] <- 0 || (Reg[SA] >> SHT)
R-format
LSR R1, R2, 5
ASR DR, SA, SHT
Reg[DR]<-MSB || (Reg[SA] >> SHT)
R-format
ASR R1, R2, 5
ze = Zero extension, se = Sign extension
분기 명령어
Pseudo code
RTL 수준의 기술
format
분기조건
JAL addr
PC <- PC[15:13] || (addr << 1);
R[7] <- PC + 2
J-format
-
JR DR, SA
PC <- Reg[SA], Reg[DR] <- PC + 2
R-format
-
BZ DR, imm8
PC <- PC + 2 + se(imm8)
I8-format
IF Reg[DR] == 0
BNZ DR, imm8
PC <- PC + 2 + se(imm8)
I8-format
IF Reg[DR] != 0
BPOS DR, imm8
PC <- PC + 2 + se(imm8)
I8-format
IF Reg[DR] > 0
BNEG DR, imm8
PC <- PC + 2 + se(imm8)
I8-format
IF Reg[DR] < 0
무조건 분기 명령어는 JR이 있다. JR은 분기할 절대 주소 16비트를 레지스터에서 읽어도록 되어있다. DR은 현제 PC + 2를 저장할 레지스터이고 SA는 점프할 주소를 담은 레지스터이다. DR을 R0으로 하면 현제 PC+2는 저장되지 않는다. JAL 명령어가 현제 PC +2를 항상 R7에 저장함으로 JAL명령어와 JR명령어의 조합으로 function이나 procedure call을 구현 할 수 있다.
JAL func
func :
적절한 연산들...
JR R0, R7
조건부 분기 명령어 BZ, BNZ, BPOS, BNEG는 두개의 레지스터의 대소를 비교하여 분기할 수 없다. 이를 보안하기 위해서 SLT(Set Less Than), SLE(Set Less then or Equal to)명령어가 제공된다.
비교 명령어
Pseudo code
RTL 수준의 기술
format
예
SLT DR, SA, SB
if(Reg[SA] < Reg[SB]) then
Reg[DR] <- 1
else
Reg[DR] <- 0
R-format
SLT R1, R2, R3
SLE DR, SA, SB
if(Reg[SA] <= Reg[SB]) then
Reg[DR] <- 1
else
Reg[DR] <- 0
R-format
SLE R1, R2, R3
이를 이용해서 R1 > R2 인 경우 L2로 분기하는 프로그램은 다음과 같이 2개의 명령어로 작성할 수 있다.
If(R1 > R2) goto L2;
SLT R3, R2, R1
BNZ R2, L2
메모리 접근 명령어
Pseudo code
RTL 수준의 기술
format
비고
LD DR, SA
Reg[DR] <= Mem[Reg[SA]]
R-format
word 데이터
ST SA, SB
Mem[Reg[SA]] <- Reg[SB]
R-format
word 데이터
STB SA, SB
Mem[Reg[Sa]] <- Reg[SB]
R-format
byte 데이터
상수값 저장 명령어
Pseudo code
RTL 수준의 기술
format
비고
LDI RD, imm8
Reg[DR] <- ze(imm8)
I8-format
16비트 하위값
LUI RD, imm8
Reg[DR] <- imm8 << 8
I8-format
16비트 상위값
ORI RD, imm8
Reg[DR] <- Reg[DR] | ze(imm8)
I8-format
LUI 함께 사용
LUI와 ORI 명령어를 사용해서 16비트 즉치값을 레지스터에 메모리 접근없이 저장할 수 있다.
인터럽트 처리
Pseudo code
RTL 수준의 기술
format
비고
EIF
Enable interrupt
R-format
CIF
Disable interrupt
R-format
SISR SA
ISR <- Reg[SA]
R-format
ISR을 세팅
RTI
PC <- EPC; enable interrupt
R-format
기존의 루틴으로 복귀
인터럽트가 활성화 되어 있다면 현제 PC+2를 EPC로 백업하고 ISR 레지스터에 지정된 주소로 분기한다. 인터럽트 서비스가 끝나고 RTI 명령어를 만나면 EPC에 백업된 주소로 복귀하면서 다시 프로그램이 수행된다. 인터럽트 루틴으로 분기하면서 인터럽트는 비활성화 되고 복귀하면서 활성화 된다. XX 프로세서는 중첩되는 인터럽트를 허용하지 않는다.
새로운 8 -bit 마이크로프로세서를 위한 Instruction Set Architecture가 주어졌다고 하자. 이 새로운 프로세서를 VHDL로 기술해서 시뮬레이션하라.
이 프로세서는 데이터를 8비트로 나타내고, 주소는 데이터와 명령어 모두 7비트로 나타내며 주소 공간은 데이터와 명령어가 공유한다.
이 마이크로프로세서의 내부 레지스터는 다음과 같은 것들로 구성된다 ALU가 계산한 결과 값을 기억하는 누산기(AC), 다음 번 실행할 명령어즤 주소를 가지고 있는 프로그램 카운터 (PC), 명령어를 저장하는 임시 레지스터(IR: Instruction Register), 접근하려는 주기억 장소의 주소를 위한 주소 레지스터(AR)과 주 기억장소로 보내거나 그로부터 읽어온 값을 임시로 기억하는 DR 레지스터 등이다.
다음과 같이 명령어 format이 주어졌다고 가정하자. 다음 명령어 format에서 addr은 2's complement 값으로 해석되는 4비트 값으로서 현재 명령어의 주소값 + 1에 대한 상대적인 값이다. addr5는 psedu direct 주소로서 데이터 주소의 하위 5비트 값을 의미한다. psedu direct 주소에서 전체 주소는 모두 7비트임으로 나머지 2비트는 현재 명령어가 저장된 주소값 + 1값의 7비트 중 상위 3비트를 그대로 사용한다. addr7은 절대주소로서 주소의 7비트의 값을 그대로 명령어로부터 바로 얻을 수 있다.
ADD 명령은 AC와 M[PC + 1 + SignExt(addr)]을 더해서 AC에 저장한다. ADDI는 AC와 SignExt(imm)을 더해서 AC에 저장한다. XOR는 AC와 M[PC + 1 + SignExt(addr)]을 xor 연산해서 AC에 저장한다. JZ 명령은 AC값이 0이면 와 M[PC + 1 + SignExt(addr)]로 분기 한다. ST 명령은 AC의 값을 addr5에 저장한다. LD 명령은 addr5 주소의 데이터 값을 읽어 와서 AC에 저장한다. JMP 명령은 무조건 주어진 절대 주소로 분기한다.
댓글을 달아 주세요