16506번 CPU
문제
디지털하드웨어설계 과목의 최종 프로젝트는 16-bit CPU를 설계하고 Verilog 언어로 구현하는 것이다. 본인이 구현한 CPU가 제대로 동작하는지 테스트하기 위해서는 기계어 코드를 입력으로 주어야 한다. 하지만 대부분의 사람은 0과 1로만 이루어진 기계어 코드를 이해하기 힘들어서 C++, Java와 같은 프로그래밍 언어로 코드를 작성하고 컴파일러를 통해 기계어 코드로 번역하는 과정을 거친다.
여러 가지 프로그래밍 언어 중에서 어셈블리어는 사람이 이해하기 쉬우면서 기계어와 가장 유사한 언어이다. 어셈블리어 코드는 어셈블러를 통해 기계어 코드로 번역된다. 그리고 어셈블리어는 기계어와 일대일로 대응하는 특징이 있다. 예를 들면, 두 수의 합을 구하는 연산의 어셈블리어 코드가 ADD
이고, 기계어 코드가 00000
이면 어셈블러는 ADD
를 읽어서 그대로 00000
로 바꾸어주는 것이다.
아래의 그림은 민호가 설계한 CPU가 처리할 수 있는 16-bit 단위 명령어들의 구조를 모아놓은 표이다.
입력과 출력은 항상 명령어 단위이며, 어셈블리어 코드는 "opcode rD rA rB" 또는 "opcode rD rA #C"의 형태이다. 기본적으로 레지스터 rA와 rB에 있는 두 수 또는 레지스터 rA에 있는 수와 상수 #C를 opcode에 해당하는 연산을 수행하고, 그 결괏값을 레지스터 rD에 저장하는 명령어이다. rA는 opcode에 따라 사용하지 않을 수도 있다. 어셈블러는 opcode, rD, rA, rB, #C를 각 bit의 자리에 맞게 2진수 0과 1로 이루어진 16-bit 기계어 코드로 변역한다. bit마다 자리의 의미는 아래와 같다.
- 0~4 : CPU가 수행해야 할 연산을 나타내는 opcode이다. 만약 4번 bit가
0
일 경우 레지스터 rB를,1
일 경우 상수 #C를 사용한다. - 5 : 사용하지 않는 bit이며, 항상
0
이다. - 6~8 : 결괏값을 저장하는 레지스터 rD의 번호이다.
- 9~11 : 연산에 사용되는 레지스터 rA의 번호이다. 사용하지 않을 경우에는
000
이다. - 12~15 : 만약 4번 bit가
0
일 경우 12~14번 bit는 연산에 사용되는 레지스터 rB의 번호이며, 15번 bit는 항상0
이다. 만약 4번 bit가1
일 경우 12~15번 bit는 상수 #C이다.
디지털하드웨어설계 과목을 듣는 민호는 Verilog로 16-bit CPU 구현을 일찍 끝내 놓은 상태이다. 이 16-bit CPU를 테스트하기 위해서는 기계어를 매번 입력으로 줘야 하는데, 너무나 귀찮은 민호는 이에 맞는 어셈블러를 구현하려고 한다. 민호가 직접 설계한 16-bit CPU의 명령어 구조 표를 보고, 어셈블리어 코드가 주어졌을 때 이를 기계어 코드로 번역하는 어셈블러를 만들어보자.
입력
첫 번째 줄에는 명령어의 개수를 의미하는 정수 N (1 ≤ N ≤ 500)이 주어진다.
다음 N개의 각 줄에는 명령어가 어셈블리어 코드로 "opcode rD rA rB" 또는 "opcode rD rA #C"의 형태로 주어진다. 문자열 opcode는 항상 대문자이다. 정수 rD, rA, rB (0 ≤ rD, rA, rB ≤ 7)는 레지스터 번호를 의미한다. 사용하는 레지스터 번호는 1부터 7까지이며, 사용하지 않을 경우에만 0이 주어진다. 정수 #C (0 ≤ #C ≤ 15)는 상수를 의미한다.
기계어 코드로 번역될 때 어긋나는 입력은 주어지지 않는다.
출력
N개의 각 줄에 어셈블리어 코드를 기계어 코드로 번역하여 출력한다.
예제 입력
4
MOVC 1 0 5
MOVC 2 0 10
ADD 3 1 2
SUB 4 1 2
8
LSFTL 4 2 4
MULTC 3 7 12
NOT 2 0 4
SUB 4 4 3
ASFTR 6 4 1
MULT 7 7 5
RLC 6 4 14
RR 1 5 4
예제 출력
0010100010000101
0010100100001010
0000000110010100
0001001000010100
0111001000101000
0110100111111100
0101000100001000
0001001001000110
1001001101000010
0110001111111010
1010101101001110
1011000011011000
해결방법
조건대로 구현하는 시뮬레이션 문제이다
⭐️ 솔루션 ⭐️
10진수를 2진수로 변환하기 위해
bitset
을 사용했다그 외에는 단순 구현이므로 어렵지 않게 문제를 해결했다
Bitset 사용법
구조
bitset<출력 자리수>(변수)
예제 코드
#include <bitset> int main(){ int dem = 10; cout << bitset<3>(dem) << "\n"; }
소스코드
문제 해결 시간 : 40m
메모리 : 1992 KB
시간 : 0 ms
#include <iostream>
#include <bitset>
#include <algorithm>
using namespace std;
int n,bit4;
int rD,rA,rB;
string opcode;
string getOPcode(){
string code;
if(opcode == "ADD" || opcode == "ADDC"){
code = "0000";
}else if(opcode == "SUB" || opcode == "SUBC"){
code = "0001";
}else if(opcode == "MOV" || opcode == "MOVC"){
code = "0010";
}else if(opcode == "AND" || opcode == "ANDC"){
code = "0011";
}else if(opcode == "OR" || opcode == "ORC"){
code = "0100";
}else if(opcode == "NOT"){
code = "0101";
}else if(opcode == "MULT" || opcode == "MULTC"){
code = "0110";
}else if(opcode == "LSFTL" || opcode == "LSFTLC"){
code = "0111";
}else if(opcode == "LSFTR" || opcode == "LSFTRC"){
code = "1000";
}else if(opcode == "ASFTR" || opcode == "ASFTRC"){
code = "1001";
}else if(opcode == "RL" || opcode == "RLC"){
code = "1010";
}else if(opcode == "RR" || opcode == "RRC"){
code = "1011";
}
return code;
}
void printCode(){
// 0 ~ 4
string code = getOPcode();
// 4번째 비트 확인
if(opcode[opcode.size()-1] == 'C')
bit4 = 1;
else
bit4 = 0;
cout << code << bit4;
// 5
cout << 0;
// 6 ~ 8
cout << bitset<3>(rD);
// 9 ~ 11
cout << bitset<3>(rA);
// 12 ~ 15
if(bit4 == 0){
cout << bitset<3>(rB) << 0;
}else{
cout << bitset<4>(rB);
}
cout << "\n";
}
int main(int argc, const char * argv[]) {
// cin,cout 속도향상
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
cin >> n;
for(int i=0; i<n; i++){
cin >> opcode;
cin >> rD >> rA >> rB;
printCode();
}
return 0;
}
'Algorithm > BOJ 문제풀이' 카테고리의 다른 글
[Greedy] 1449번 수리공 항승 (0) | 2019.02.10 |
---|---|
[Greedy] 4796번 캠핑 (0) | 2019.02.10 |
[SIM] 16113번 시그널 (0) | 2019.02.07 |
[SIM] 8911번 거북이 (0) | 2019.02.07 |
[DP] 1958번 LCS3 (0) | 2019.02.07 |