제어/전자HW설계

[전자HW설계] 2-2

KAU 2020. 9. 10. 22:35

 

32비트 CPU를 사용하고 있고 

한 워드 단위로 데이터를 취급하고 있기 때문에 

4바이트 단위 32비트 단위로 데이터를 읽어온다. 

 

32-bit address는 어드레스 공간이 0번지부터 2^31승 까지 있다는 것

 

4바이트 단위로 읽거나 쓰거나 한다. 

 

어드레싱은 메모리에서 데이터를 읽어서 레지스터에 가져오는데 

Ld, St (reg->mem)

 

immediate mode 

16비트 오퍼 랜드가 instruction이 정확하게 정해져 있다.

오퍼랜드는 오퍼레이션의 타깃이 되는 것 

절댓값이 적혀있는 게 immediate mode

==>그냥 숫자?

 

register mode 

데이터가 레지스터에 들어가 있고 

ri에서 i는 숫자를 의미하는 것 

==> 실제 데이터

r1, r2, r3.. 

 

register indirect mode

괄호 안에 레지스터 넘버가 들어가 있는 것 

(r3) ==> 이 값이 들어가 있는 숫자가 있을 텐데 

register indirect는 포인터이다. 

 

Displacement mode

register indirect 모드에 결합한 것 

X는 숫자인데 값을 읽고 100만큼 더한 값을 읽어오는 것

C로 따지면 Array와 같은 것 

 

Absolute mode 

숫자를 주는데 이 숫자가 

어드레스 값을 절대 값으로 주는 것 

바깥에 있는 숫자가 어드레스가 되는 것 

 

Instruction

fixed size로 32비트로 정확하게 정해져 있어서 편하다.

<=> CISC는 처리할 때 몇 비트를 읽어야 하는지 조차도 정해져 있지 않은 경우가 많다.

 

psudo-instruction

하드웨어는 곧이곧대로 받아들일 수 없다.

==>여러 개로 맵핑이 된다 <=> 컴파일러가 해준다. 

원래는 1대 1로 기계어로 맵핑이 됩니다.

Instruction format은 

I 타입 R 타입 J 타입 

 

1대1로 맵핑이 되어있고 약속이 되어있다 

==> 형식이 정해져 있다.

 

R타입의 경우

앞에 ABC는 레지스터 넘버이다.

5개 비트 5개 비트 5개 비트 

레지스터 넘버에 해당합니다. 

ra+rb->rc에 저장되는 오퍼레이션이 된다.

32비트를 읽어보면 기계가 어떤 명령어를 의미 하는지 알 수 있고

그것을 따라서 로직을 설계 

OPX는 사용할 수도 있고 사용 안 할 수도 있다

 

I타입의 경우 

로드같은류에서 I타입을 명령어

 

J타입 

점프나 브랜치같은류의 명령어

 

본격적으로 기계어들에 대해서 알아봅시다. 

Instruction function이름이 잘 정해져 있어요.

인스트럭션으로 코드를 짤 텐데 어떤 식으로 짜느냐?

메모리에 데이터가 저장이 되어있는데

 

레지스터로 데이터를 가져와서(Ld)

지지고 볶아서 메모리로 다시 저장(St)

ldldld..... StStSt

 

로드와 스토어만 외부 메모리에 Aceess 할 수 있는 Instruction이다.

나머지 Instruction은 모두 레지스터만을 가지고 처리한다.

메모리와 general-purpose 레지스터 간에 데이터를 처리

Load word 

ldw r3,80(r4)

r4에 있는 값이 어드레스인데 여기에 80을 더한다. 

그 위치에 가서 데이터를 읽어서 r3에 저장한다.

만약 80(r0)였다면 80번지로 바로 갔겠죠?

로드 명령어를 가지고 어드레스 명령어 중에서 레지스터 인다이렉스 앱솔로트 모두 사용할 수 있다.

 

ldb, ldh(하이퍼 워드), ldbu(unsined), ldhu(하이퍼 언사인드)

Store word

스토어는 방향만 반대이다.

stw r3, 80(r4)

r3에 있는 데이터를 반대로 저장하겠죠?

로드와 스토어는 메모리 공간을 액세스할 때 사용하는데

I/O 디바이스도 메모리 공간에는 특정 주소 값을 가지고 IO를 할 수 있다

IO인지 메모리인지 문법이 똑같아서 

명령어에 io를 적어주면 확실하게 I/O 디바이스로 가는구나' 알 수 있어요

IO디바이스는 캐싱이 가능합니다.

캐시가 있으면 캐시에만 쓰이고 끝날 수도 있어요.

메모리까지 안 가고 캐시에 있는 데이터만 읽어온다던가 

이런 문제가 있을 수 있다. ==> IO는 캐시를 사용하면 안돼요 

Bypass the cache 

io 안 붙여도 잘 동작은 하지만 운이 좋았을 뿐 제대로 코딩한 것이 아닙니다.

 

사칙연산하는 거예요 

add가 있고 addi가 있다.

add는 레지스터가 세 개가 붙어요

R타입입니다. 

 

add rC, rA, rB

rA랑 rB를 더한 값이 rC에 저장된다. 

addi rB, rA, IMMED16를 더해서 rB에 저장하는 식

sub, div, mul~ 모두 똑같다.

div는 몫이 저장이 됩니다.

 

Carry와 오버플로우가 발생할 수 있다. 

==> C 같은 것 쓰면 알아서 연산해주는데 

어셈블리어는 연산을 안 해줘서 여러분들이 스스로 판단을 해야 한다.

 

오퍼레이션이 제너를 펄포에서 액세스해서

and rC, rA, rB 

bit wise and인데 

한 비트씩 and 한다는 것 

or, nor, xor이 가능 ==> not은 없다.

ori, nori, xori.. 

 

카피하는 것, 대입하는것 one register에 있는 값을 다른곳으로 카피하는것

==> 슈도 instruction이다

mov rC, rA 

rA에 있는 값이 rC에 저장이 된다.==> 하드웨어는 add rC, rA, r0로 인식을 해서 수행을 합니다.

movi rB, IMMED16 ==>상수값이 rB에 저장된다. 

movui rB,IMMED16 ==> 언사인 값이 rB에 저장이 된다.

movia 어드레스를 저장

LABEL이 포인터 같은 역할을 하게 되는 것 

라벨 위치로 가서 거기에 해당하는 데이터를 rB에 저장한다.

 

비교한 결괏값을 True False로 알려주는 것

타깃이 되는 두 가지 레지스터를 주고 

큰지 작은지 같은지를 물어본다. result 레지스터에 들어가게 된다. 

 

cmplt rC rA rB

rB rB를 비교해서 트루나 false를 저장 (1or0)

lt:less than 

eq:equal

ne:not equal

ge:greater than equaul to 

gt:greater

le:less or equal

u가 붙는 것==> 언사인으로 비교하는 것
cmplti: 숫자와 비교하는 것

 

srl:

s:shift

r은 right 

l:logical

rA에 있는 값이 rB에 들어있는 숫자만큼 로지컬 하게 이동해서 rC에 저장되는 것

logical 하게 움직여서 움직인 만큼 비어있겠죠?

뒤에 빈 것은 문제가 없어요 

하지만 상위 바이트가 오른쪽으로 밀리는 경우 

로지컬과 어리스매틱 shift 하는 게 다르다 

아리스 매틱은 음수면 1로 채우고 양수였으면 0으로 채운다.

Rotate는 밀어버리는 것은 똑같은데 쉬프트 해서 나가리된값을 앞이나 뒤로 돌리는 거예요.

 

점프 

점프를 하는데 jmp rA

레지스터 파일 rA에 주소 값이 있을 것이고 rA에

저장되어있는 주소 값으로 메모리에 가는 것 

indirect 하게 가는 형태

 

브랜치

br 같은 경우 라벨로 점프하게 되는 것인데

direct 하게 가는 것입니다.

 

Conditional branch 

if나 else 같은 것을 구현할 수 있는 것

두 개의 레지스터 값을 비교해서 조건이 맞으면 브랜치로 가는 것 

 

blt 

rA와 rB값을 비교해서 rA가 작으면 

LABEL로 가는것 

beq==> equal 

조건은 여러 가지 붙을 수 있다.

조건문은 항상 사용하므로 위의 명령어는 많이 사용합니다.

 

function이다.

call  fun1 

 

call LABEL

function이 끝나면 돌아온다. 

 

끝났다는 것을 알려주기 위해 ret을 붙인다.

자체적으로 하드웨어가 어떻게 처리하느냐 

리턴 주소 값을 r31에 저장을 하고 call을 하는 것

 

callr rA 리턴 어드레스를 세이브하고 

register A로 간다~~ 근데 이거 잘 안 씁니다. 

위에 것만 씁니다.

 

rdctl, wrctl

rdctl rC, ctlN 

ctlN에 있는 값을 rC에 저장한다든가 그런 것

general purpose register랑 왔다 갔다 한다.

 

Exception

trap & erect 

call과 ret과 똑같은 것 

 

Breaks

서브루틴 비슷하게 하는 것 

디버그 하는 소프트웨어가 합니다.

우리가 사용하는 경우는 많이 없다.

 

Cache management

가끔 캐시를 건드려야 할 일이 생기는데

데이터를 비울 때 사용하게 된다.

캐시에 있는 데이터를 변경을 했을 때 업데이트된 것 

새로운 것 이런 것을 캐시가 컨시스턴트 하지 않다

==> dirty data가 생긴다'라고 하는데 

싱크를 맞춰주기 위해서 

flushd==> data 캐시 라인 혹은 인스트럭션 캐시라인을 비울 수 있다.

initd  ==> 깨끗하게 비워버리는 것 데이터가 있건 말걸==> 초기화시키는 것

init은 잘 안 씁니다.

 

캐리는 

큰 데이터를 더하고 나면 캐리가 발생하죠

rA랑 rB를 더했는데 이게 유효한 값이냐?

데이터 범위를 넘어가면 저장을 못하잖아요 

cmpltu rC와 rA를 비교해서 

rB가 양수라고 가정을 하면 

rA가 더 큰 경우는 없을 테니

rA가 더 크면 캐리가 발생했다고 가정을 하고 

rD에 비트를 셋 하는 것입니다.

 

캐리가 발생했을 때 LABEL로 가서 어떤 식으로 처리해라~

 

오버플로우는 양+양=음 

혹은 음+음=양일 때 오버플로우죠?

(양 음을 더하면 오버플로우가 발생하지 않습니다.)

 

A와 B를 더해서 C에 저장하고 

A와 B를 C와 비교해보는 거죠

그 값을 AND를 해보면 

rD가 1이 되면 

브랜치를 해서 LABEL로 보내서 조치를 취한다.

'제어 > 전자HW설계' 카테고리의 다른 글

[전자HW설계] LAB3  (0) 2020.09.30
[전자HW설계] LAB2  (0) 2020.09.22
[전자HW설계] 3-1 [Nios II 이론 마무리]  (0) 2020.09.14
Introduction to Nios II  (0) 2020.09.07
[전자HW설계] [1-1]  (0) 2020.09.01