Rust로 작성해 보는 컴퓨터 구조 (9) - 반가산기

나빌레라의 이미지

이 장에서는 반가산기(Half Adder)를 만들것이다. 왜 반가산기라고 하는지는 만들고 나면 알게된다. 아래 게이트 회로가 반가산기의 구조다.

반가산기 구조

XOR 게이트와 AND 게이트 각 한 개씩으로 구성한 반가산기 회로다. A와 B가 입력이고 S와 C가 출력이다. 이 회로의 진리표를 보자.

입력 A 입력 B 출력 C 출력 S
0 0 0 0
0 1 0 1
1 0 0 1
1 1 1 0

진리표를 보면 입력에 대한 결과가 덧셈임을 알 수 있다. 보기 쉬운 덧셈 기호로 다시 표현해 보면 아래와 같다.

0 + 0 = 00
0 + 1 = 01
1 + 0 = 01
1 + 1 = 10

회로의 동작이 덧셈을 만족하기 때문에 위 회로를 가산기라고 한다. 출력 S에 덧셈 결과가 나오고 출력 C에 자리올림(carry) 결과가 나온다. 그런데 이름에 한 글자가 더 붙어 반가산기라고 한다. 반만 동작하는 가산기라는 뜻이다. 왜 반만 동작하는 것일까? 기능이 반만 있기 때문이다. 나머지 없는 기능 반은 무엇일까? 바로 올림수를 받는 기능이다. 반가산기는 올림수를 출력하긴 하지만 올림수를 받지 않기 때문에 반가산기라고 하는 것이다.

위 게이트 회로를 기반으로 반가산기를 모델링한다. 새로운 파일 adder.rs를 src 폴더에 만들고 아래 코드를 작성한다.

{caption="adder.rs | 가산기 모델 껍데기"}
use crate::gates;
 
use gates::GateInterfaces;
 
pub struct HalfAdder {
    pub conn_a: bool,
    pub conn_b: bool,
    pub conn_out_s: bool,
    pub conn_out_c: bool,
 
    xorgate: gates::XorGate,
    andgate: gates::AndGate,
}
 
impl HalfAdder {
    pub fn new() -> HalfAdder {
        HalfAdder {
            conn_a: false,
            conn_b: false,
            conn_out_s: false,
            conn_out_c: false,
 
            xorgate: gates::XorGate::new(),
            andgate: gates::AndGate::new(),
        }
    }
}
 
pub trait AdderInterfaces {
    fn proc(&mut self, input_a: bool, input_b: bool);
}
 
impl AdderInterfaces for HalfAdder {
    fn proc(&mut self, input_a: bool, input_b: bool) {
 
    }
}

반가산기 모델 본체인 proc() 함수는 아직 만들지 않았다. 일단 껍데기만 미리 만들어 놓고 유닛 테스트를 만들기 위함이다. 그래서 위 코드는 반가산기 모델의 틀만 잡아 놓은 코드다. 5번째 줄에서 13번째 줄이 반가산기에 대한 구조체인 HalfAdder 구조체 선언이다. 입력 A, B 두 개와 출력 S, C 두 개를 선언하고 XOR 게이트와 AND 게이트 모델 변수를 선언했다. 15번째 줄에서 27번째 줄이 HalfAdder 객체의 생성자다. 신호선은 모두 false로 초기화하고 XOR 게이트와 AND 게이트 객체를 할당했다. 29번째 줄부터 31번째 줄이 트래잇 선언이다. 가산기의 proc() 인터페이스는 리턴값이 없다. 출력 신호가 두 개기 때문이다. 그래서 proc() 함수의 리턴은 없고 결과를 보려면 proc() 함수를 호출한 후에 conn_out_s와 conn_out_c의 값을 읽어야 한다. 35번째 줄 위치에 반가산기 모델 코드가 들어가야 한다. 일단 지금은 비워두고 유닛 테스트를 먼저 만든다.

유닛 테스트는 tests 폴더에 만든다. tests 폴더에 adder_test.rs 파일을 만들고 아래 코드를 작성한다.

{caption="adder_test.rs | 반가산기 유닛 테스트"}
extern crate programming_coms;
 
use programming_coms::adder;
 
use adder::AdderInterfaces;
 
#[test]
fn test_halfadder() {
    let mut half_adder = adder::HalfAdder::new();
 
    half_adder.proc(false, false);
    assert_eq!(false, half_adder.conn_out_c);
    assert_eq!(false, half_adder.conn_out_s);
 
    half_adder.proc(false, true);
    assert_eq!(false, half_adder.conn_out_c);
    assert_eq!(true, half_adder.conn_out_s);
 
    half_adder.proc(true, false);
    assert_eq!(false, half_adder.conn_out_c);
    assert_eq!(true, half_adder.conn_out_s);
 
    half_adder.proc(true, true);
    assert_eq!(true, half_adder.conn_out_c);
    assert_eq!(false, half_adder.conn_out_s);
}

위 코드는 반가산기의 진리표를 HalfAdder 객체가 만족하는지 확인하는 유닛 테스트다. 11번째 줄에 half_adder.proc() 메소드를 호출했다. 그러면 반가산기 모델이 동작한다. 동작 결과는 12, 13번째 줄에 나온대로 half_adder.conn_out_c와 half_adder.conn_out_s를 읽어서 확인한다. 같은 패턴으로 11번째 줄에서 25번째 줄까지 코드에 반가산기 진리표를 확인하는 테스트를 작성한다.

현 상태에서 유닛 테스트를 실행하면 당연히 실패한다. 먼저 테스트를 만들어서 실패하는 것을 보고 코드를 수정해서 테스트를 성공시키는 순서로 작업한다.

$ cargo test
... 생략 ...
running 1 test
test test_halfadder ... FAILED
failures:
---- test_halfadder stdout ----
thread 'test_halfadder' panicked at 'assertion failed: (left == right)
left: true,
right: false', tests/adder_test.rs:17:5

테스트가 실패했다고 나온다. 이제 다시 adder.rs에서 작업한다.

{caption="adder.rs | 반가산기 모델 본체"}
// ... 생략 ...
 
impl AdderInterfaces for HalfAdder {
    fn proc(&mut self, input_a: bool, input_b: bool) {
        self.conn_a = input_a;
        self.conn_b = input_b;
 
        self.conn_out_s = self.xorgate.proc(input_a, input_b);
        self.conn_out_c = self.andgate.proc(input_a, input_b);
    }
}

반가산기 게이트 회로를 보면 입력 A, B가 각각 XOR 게이트와 AND 게이트에 독립적으로 들어간다. XOR 게이트 출력이 그대로 출력 S고 AND 게이트 출력이 그대로 출력 C다. 그 구성 그대로 모델링한 코드가 위 코드다.

이렇게 작업하고 유닛 테스트를 실행한다. 유닛 테스트가 통과한다면 반가산기 모델을 제대로 만든 것이다.

$ cargo test
... 생략 ...
running 1 test
test test_halfadder ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
running 7 tests
test test_and_gate ... ok
test test_inverter ... ok
test test_nand_gate ... ok
test test_nor_gate ... ok
test test_or_gate ... ok
test test_transistor ... ok
test test_xor_gate ... ok
test result: ok. 7 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

앞 장에서 만든 게이트 유닛 테스트와 방금 만든 반가산기 유닛 테스트가 모두 통과했다. 따라서 반가산기 모델이 잘 동작함을 확인했다.

File attachments: 
첨부파일 크기
Image icon adder-gate-construction.png15.95 KB

댓글

나빌레라의 이미지

그림에서 XOR 게이트는 식별 가능할테고 아래에 있는 게이트는 조금 이상하게 생기긴 해도 AND 게이트입니다.

----------------------
얇은 사 하이얀 고깔은 고이 접어서 나빌레라

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.