2025년 12월 7일 일요일

[실습] RTL/Apple-1(6502) 복원

[실습] RTL/Apple-1(6502)복원


목차:

1. 실습 개요
    1-1. Apple-1
    1-2. 실습 목표
    1-3. 박물관에 살아있는 Apple-1
    1-4. 예제 소스코드

2. Co-Simulation
    2-1. Verilog RTL과 SystemC 테스트벤치의 구성
    2-2. 시뮬레이션 빌드
    2-3. Apple-1 기능적 시뮬레이션
    2-4. Apple-1 소프트웨어 개발 도구

3. ETRI050 노드
    3-1. 합성 환경 준비
    3-2. 베릴로그 RTL 합성
    3-3. Apple-1 네트리스트 타이밍 시뮬레이션
    3-4. 입출력 파형 관찰


CC-BY-NC
by GoodKook, goodkook@gmail.com

-------------------------------------------------------------------------------------------------

1. 실습 개요

1-1. Apple-1

Apple-1은 1976년에 "애플"사에서 발매한 개인용 컴퓨터다. 오늘날의 애플 컴퓨터(Apple Company Inc.), 그 회사 맞다. 애플에서 처음 출시한 이 컴퓨터에 사용된 CPU는 6502로 8비트 마이크로 컨트롤러다[위키][Wiki]. 40여년 전에 시너텍(Synertek)에서 nMOS 공정으로 개발하고 판매했던 이 CPU는 단종 되었지만 WDC 사에서 CMOS 로 재설계하여 판매되고 있다. 컴퓨터 구조 교과서를 매우 충실히 따를 만큼 단순한 구조의 이 CPU는 높은 에너지 가성비로 인해 오늘날에도 여전히 연간 수백만개가 팔리고 있다고 한다[Google AI]. 오늘날 내장형 시스템 용 원칩 마이크로 컨트롤러들은 다양한 주변장치들을 내장하고 있는 장점이 있지만 정작 응용에 사용되지 않은채 낭비되고 있다. 6502는 ALU와 레지스터 그리고 컨트롤 유닛으로 만 구성되었다. 명령구조도 매우 간단하여 어드레싱 모드는 직접, 간접 그리고 상수 모드 긱 1종류 만 가지고 있다. 입출력 장치는 메모리 매핑 모드만 있다.


Visual6502, http://www.visual6502.org/

6502의 프라스틱 패키지를 까서 칩의 사진을 찍어 회로를 추출 해냈다. 4004 출시 35주년(2009년) 기념 프로젝트 였다고 한다. 그 과정을 2010년 8월 SIGRAPH 학회에서 발표했다[슬라이드(pdf)]. 

Monster 6502, https://monster6502.com/

Visual6502 프로젝트에서 칩 사진으로부터 추출한 회로도를 바탕으로 PCB위에 트랜지스터로 재현했다.

Replica-1, https://www.applefritter.com/briel

6502 또는 65c02 를 사용하여 Apple-1 을 복제했다. 발매 당시(2003년) 가격은 149달러[Wiki]

RC6502, an Apple-1 clone, http://retro.hansotten.nl/6502-sbc/apple-1/rc6502-an-apple-1-clone/

OLIMEX Neo6502, https://www.olimex.com/Products/Retro-Computers/Neo6502/open-source-hardware

Apple-1의 또다른 복제품이다. 65c02 를 사용했고 주변장치로 RP2040을 사용하여 구현 했다. 현재 30유로에 판매중. 오픈-소스로 깃-허브에 공개되었다 [ https://github.com/OLIMEX/Neo6502 ]

Ben Eater 6502 Projecthttps://eater.net/6502

빵판에 Apple-1을 꾸밀수 있도록 필요한 부품을 팔고 있다. 필요한 IC를 포함하여 키트가격은 89달러.

1-2. 실습 목표

이번 실습은 Apple-1 컴퓨터를 재현한다. CPU 6502는 공개되어 있는 베릴로그 RTL 소스코드를 수정하였다. 주변장치의 제어기로 사용된 PIA와 RAM은 하드웨어 에뮬레이션 모델(SystemC 와 Raspberry PI PICO)로 구현하였다. 이번 실습에서 재현하는 Apple-I 컴퓨터에 내장되었던 256바이트의 워즈니액 모니터(WozMon) ROM을 수행한다.  그외 AppleSoft BASIC, J-Mon 등 그 시대를 대표하는 롬 코드(원본 바이너리 이미지)를 수정 없이 실행 시킬 수 있다. 소프트웨어 개발도구로 어셈블러와 CC65, SDCC 등 C 컴파일러를 사용 할 수 있다.

베릴로그와 SystemC 모델로 시뮬레이션을 수행할 것이며 FPGA와 Raspberry PI PICO로 구성하여 에뮬레이션(패스트 프로토타이핑) 한다. CPU 6502 최종적으로 "내 칩 제작 서비스" MPW로 칩 제작 한다. 사용된 설계 도구들은 모두 오픈-소스 다.

1-3. 박물관에 살아있는 Apple-1

40년 전의 Apple-I은 작동하는 보드가 고가에 거래되고 있으며 그중 한대가 제주도 넥슨 컴퓨터 박물관에 전시되어 있다.


First Apple-1 Computer [Youtube Shorts]

1-4. 예제 소스코드

    [깃 허브 링크]

2. Co-Simulation

2-1. Verilog RTL과 SystemC 테스트벤치의 구성

               +-sc_apple_1_TB.h-----------+
               | SystemC wrapper/Testbench |
               +------------+              |
+-apple_1.v--------------+  |              |
|                        |  |              |
|   +-cpu_6502.v-----+   |  |              |
|   |                |   |  |              |
|   |  +-ALU8.v----+ |   |  | +-mem.cpp--+ |
|   |  |           | |   |  | |  Sync.   | |
|   |  |           | |   |  | |   RAM*** | |
|   |  +-----------+ |   ==AB=>    &     | |
|   +----------------+   ==DO=>   I/O    | |    +-CPU_terminal.cpp--+
|                        --WE->          | |IPC*|                   |
|     +-wozmon.v---+     <=DI== (KBD,DSP)<======> Terminal          |
|     | **         |     |  | |          | |    |                   |
|     |            |     |  | |          | |    +-------------------+
|     +------------+     |  | +----------+ |
|                        |  |              |  *IPC: SOCKET or PIPE
|                        <---- Clock       |
+------------------------+  |              |                         
               +------------+              |
               |                           |
               +---------------------------+

** Inside WozMon/WozMon Listing [pdf]

***Synchronous RAM

// Synchronous Memory Model & Memory mapped I/O

void sc_mem::mem_Thread()
{
    uint32_t Address;
  // Socket IPC -----------------------------------------------
  unsigned char KBD_Buff = '\0', DSP_Buff = '\0';
  int nRead, nWrite;
#if defined(IPC_SOCKET)
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    ......
#elif defined(IPC_PIPE)
    ......
#endif
  while (true)
  {
    wait(clk.posedge_event());  // Synchronous to Clock

    Address = AB.read(); // Read Address-Bus

    if (WE.read()) // Memory Write -----------------
    {
      mem[Address] = DI.read(); // WRITE MEMORY
      // Memory Mapped I/O (Screen & Keyboard)
      if (Address == PIA_KBD_REG) // PIA.A keyboard register
                ......
      else if (Address == PIA_KBD_CTL) // PIA.A keyboard control
                ......
      else if (Address == PIA_DSP_REG) // PIA.B display register
      {
        DSP_Buff = (unsigned char)(mem[Address] & 0x07F);
#if defined(IPC_SOCKET)
        nWrite = send(sock_fd, (char*)&DSP_Buff, 1, 0); // Blocking Write
#elif defined(IPC_PIPE)
                ......
#endif
        mem[Address] = (mem[Address] & 0x07F); // Clear B7
        DSP_Buff = '\0';
      }
      else if (Address == PIA_DSP_CTL) // PIA.B display control
                ......
      else
                ......
    }
    else // Memory Read ------------------------------
    {
      if (Address == PIA_KBD_REG)         // PIA.A keyboard input
      {
        if (KBD_Buff=='\0')
        {
          mem[Address] = 0x00;
          mem[PIA_KBD_CTL] = (mem[PIA_KBD_CTL] & 0x3F); // Keyboard empty
        }
        else if (KBD_Buff=='\n')
        {
          mem[Address] = 0x08D;    // CR | Valid input
          mem[PIA_KBD_CTL] = (mem[PIA_KBD_CTL] & 0x3F); // Keyboard empty
          KBD_Buff = '\0';
        }
        else
        {
          mem[Address] = (KBD_Buff | 0x80);  // Valid input
          mem[PIA_KBD_CTL] = (mem[PIA_KBD_CTL] & 0x3F); // Keyboard empty
          KBD_Buff = '\0';
        }
      }
      else if (Address == PIA_KBD_CTL) // PIA.A keyboard Ctl Reg.
      {
        if (KBD_Buff=='\0')
        {
#if defined(IPC_SOCKET)
          nRead = recv(sock_fd, &KBD_Buff, 1, 0); // Blocking Read
#elif defined(IPC_PIPE)
                ......
#endif
          if(nRead>0)
            mem[Address] = (mem[Address] | 0x80); // Keyboard ready
         }
       }
       else if(Address == BIN_FILE_LOAD)
       {
         char szBinFilename[64], *pBinFilename;
         fputs("\nFilename(.bin):", stdout);
         pBinFilename = fgets(szBinFilename, sizeof(szBinFilename), stdin);
         szBinFilename[strlen(szBinFilename)-1] = '\0';
         ReadBIN((char*)szBinFilename, 0x0000);    // cc65 binary
       }
       DO.write(mem[Address]); // READ MEMORY
     }
    }
  }

Memory Map


2-2. 시뮬레이션 빌드

$ cd ~/ETRI050_DesignKit/Projects/RTL/apple_1/

$ source env_settings
  #****************************************************************
  #* Environment setting for RTL, Co-Simulmatio/Emulation & ETRI050
  #****************************************************************
  Setting Environment variables as follows;
    PROJECT_DIR=/home/mychip/ETRI050_DesignKit/Projects/RTL/apple_1
    TOP_MODULE=apple_1
    HW_STYLE=no_style
    MODE=CA
    MI=PI_PICO

$ cd simulation

$ ll

  total 30392
  drwxr-xr-x 3 mychip mychip     4096 Dec  6 21:01 .
  drwxr-xr-x 7 mychip mychip     4096 Dec  6 21:01 ..
  drwxr-xr-x 2 mychip mychip     4096 Dec  6 20:23 Apple-1
  -rw-r--r-- 1 mychip mychip 31052722 Dec  6 20:23 Apple-1.tar.gz
  -rw-r--r-- 1 mychip mychip     8472 Dec  6 20:23 CPU_terminal.cpp
  -rw-r--r-- 1 mychip mychip      558 Dec  6 20:23 CPU_terminal.h
  -rw-r--r-- 1 mychip mychip     3696 Dec  6 20:25 Makefile
  -rw-r--r-- 1 mychip mychip      880 Dec  6 20:23 sc_apple_1_TB.cpp
  -rw-r--r-- 1 mychip mychip     3672 Dec  6 20:23 sc_apple_1_TB.h
  -rw-r--r-- 1 mychip mychip      438 Dec  6 20:23 sc_main.cpp
  -rw-r--r-- 1 mychip mychip    10649 Dec  6 20:23 sc_mem.cpp
  -rw-r--r-- 1 mychip mychip     1483 Dec  6 20:23 sc_mem.h

$ make

  Makefile for Co-Simulation of Verilog-RTL example, apple_1

    TOP_MODULE=apple_1 make lint
    TOP_MODULE=apple_1 VCD_TRACE=YES|[NO] IPC_TYPE=[SOCKET]|PIPE make build
    TOP_MODULE=apple_1 make run
    TOP_MODULE=apple_1 make wave
    TOP_MODULE=apple_1 make clean

  CC BY-NC, by GoodKook, goodkook@gmail.com

$ make build

  verilator --sc -Wno-WIDTHTRUNC -Wno-WIDTHEXPAND --trace --timing --pins-sc-uint \
          --top-module apple_1  --exe --build \
          -CFLAGS -g -CFLAGS -I/opt/systemc/include \
          -CFLAGS -DIPC_SOCKET \
          ../apple_1/ALU8.v ../apple_1/cpu_6502.v \
          ../apple_1/wozmon.v ../apple_1/apple_1.v \
          ./sc_main.cpp ./sc_mem.cpp ./sc_apple_1_TB.cpp

     ...

  - V e r i l a t i o n   R e p o r t: Verilator 5.043 ...
  - Verilator: Built from 0.190 MB sources in 5 modules, ...

  gcc -o CPU_terminal -pthread -DIPC_SOCKET CPU_terminal.cpp

2-3. Apple-1 기능적 시뮬레이션

$ make run

터미널 도움말


2-4. Apple-1 소프트웨어 개발 도구

- CC65, AS65 : C-Compiler 와 어셈블러

$ tar xvf Apple-1.tar.gz

  Apple-1/
  Apple-1/cc65.sh
     ......
  Apple-1/cc65-2.13.3/cc65-2.13.3/testcode/compiler/pptest1.c
  Apple-1/cc65-2.13.3/cc65-2.13.3/testcode/assembler/
  Apple-1/cc65-2.13.3/cc65-2.13.3/testcode/assembler/illegal.s
  Apple-1/cc65-2.13.3/cc65-2.13.3/testcode/grc/
  Apple-1/cc65-2.13.3/cc65-2.13.3/testcode/grc/test.grc
  Apple-1/cc65-2.13.3/cc65-2.13.3/announce.txt

- "Hello World" 예제

$ cd Apple-1/hello

$ cat hello1.c

  #include <stdio.h>

  int main (void)
  {
    printf("\nHELLO, WORLD!\n");
    return 0;
  }

$ cat Makefile

  CC65_PATH = ../cc65-2.13.3
  CC65_HOME = $(CC65_PATH)/lib/cc65
  CA65_INC  = $(CC65_PATH)/lib/cc65/asminc
  CC65_INC  = $(CC65_PATH)/lib/cc65/include
  LD65_CFG  = $(CC65_PATH)/lib/cc65/cfg
  LD65_LIB  = $(CC65_PATH)/lib/cc65/lib
  LD65_OBJ  = $(CC65_PATH)/lib/cc65/obj

  export PATH := $(PATH):$(CC65_PATH)/bin

  all: hello1.bin hello2.bin nqueens.bin sieve.bin

  hello1.bin: hello1.c
    cl65 -O -l -vm -m hello1.map -t replica1 \
         -I$(CC65_INC) -L$(LD65_LIB) -o hello1.bin hello1.c

  hello2.bin: hello2.c
    cl65 -O -l -vm -m hello2.map -t replica1 \
         -I$(CC65_INC) -L$(LD65_LIB) -o hello2.bin hello2.c

  nqueens.bin: nqueens.c
    cl65 -O -l -vm -m nqueens.map -t replica1 \
         -I$(CC65_INC) -L$(LD65_LIB) -o nqueens.bin nqueens.c

  sieve.bin: sieve.c
    cl65 -O -l -vm -m sieve.map -t replica1 \
         -I$(CC65_INC) -L$(LD65_LIB) -o sieve.bin sieve.c

  clean:
    $(RM) *.o *.lst *.map *.mon

  distclean: clean
    $(RM) *.mon

$ make

$ ll *.bin

  -rw-r--r-- 1 mychip mychip 2571 Dec  7 09:25 hello1.bin
  -rw-r--r-- 1 mychip mychip 2954 Dec  7 09:25 hello2.bin
  -rw-r--r-- 1 mychip mychip 4930 Dec  7 09:25 nqueens.bin
  -rw-r--r-- 1 mychip mychip 3205 Dec  7 09:25 sieve.bin

- D018바이너리 로드: Apple-1 메모리 주소 D018 접근

- 'R' 실행  명령: WozMon 명령은 Apple-1 작동 메뉴얼 참고(Apple-1 Operation Manual)

- CC65 컴파일러의 바이너리 파일 구조

    적재주소: 0x0280, 길이: 0x0A70 (Little-Endian)

3. ETRI050 노드

시뮬레이션으로 검증된 Apple-1 베릴로그 RTL 을 "내 칩 제작 서비스" MPW의 ETRI050 노드로 합성하고 레이아웃을 생성한다.

3-1. 합성 환경 준비

$ cd ~/ETRI050_DesignKit/Projects/RTL/apple_1

$ source env_settings

$ cd ETRI050

$ make

    Symbolic link './source' to RTL...

    Makefile for "Verilog-RTL Ex.: apple_1"
    QFlow RTL-to-Layout using ETRI 0.5um CMOS Technology

    TOP_MODULE=apple_1 make synthesize
    TOP_MODULE=apple_1 make place
    TOP_MODULE=apple_1 make sta
    TOP_MODULE=apple_1 make route
    TOP_MODULE=apple_1 make migrate
    TOP_MODULE=apple_1 make lvs
    TOP_MODULE=apple_1 make size

CC BY-NC, by GoodKook, goodkook@gmail.com

베릴로그 RTL의 디렉토리가 ./source 로 소프트 링크되었다.

$ ll

  total 48
  drwxr-xr-x 7 mychip mychip 4096 Dec  7 11:49 .
  drwxr-xr-x 7 mychip mychip 4096 Dec  6 21:01 ..
  drwxr-xr-x 2 mychip mychip 4096 Dec  6 20:23 chip_top
  drwxr-xr-x 2 mychip mychip 4096 Dec  6 20:23 layout
  drwxr-xr-x 2 mychip mychip 4096 Dec  6 20:23 log
  drwxr-xr-x 2 mychip mychip 4096 Dec  6 20:25 simulation
  lrwxrwxrwx 1 mychip mychip   10 Dec  7 11:49 source -> ../apple_1
  drwxr-xr-x 2 mychip mychip 4096 Dec  6 20:23 synthesis
  -rw-r--r-- 1 mychip mychip 5155 Dec  6 20:23 Makefile
  -rw-r--r-- 1 mychip mychip 1774 Dec  6 20:23 project_vars.sh
  -rw-r--r-- 1 mychip mychip 1684 Dec  6 20:23 qflow_exec.sh
  -rw-r--r-- 1 mychip mychip  785 Dec  6 20:23 qflow_vars.sh

3-2. 베릴로그 RTL 합성

베릴로그 RTL을 합성하여 ETRI050 디자인 킷의 표준 셀 네트리스트 생성한다. 베릴로그 합성 오픈-소스 도구는 Yosys 다.

$ make synthesize

합성의 기록은 ./log/synth.log 다. 로그를 살펴보면 사용된 표준셀의 목록을 볼 수 있다.

  === apple_1 ===
   Number of wires:               2304
   Number of wire bits:           2502
   Number of public wires:        2304
   Number of public wire bits:    2502
   Number of ports:                 10
   Number of port bits:             39
   Number of memories:               0
   Number of memory bits:            0
   Number of processes:              0
   Number of cells:               2490
     $scopeinfo                      3
     AND2X2                         74
     AOI21X1                       211
     AOI22X1                        87
     BUFX2                          25
     DFFPOSX1                       24
     DFFSR                         135
     INVX1                         285
     MUX2X1                         21
     NAND2X1                       336
     NAND3X1                       188
     NOR2X1                        306
     NOR3X1                         15
     OAI21X1                       702
     OAI22X1                        39
     OR2X2                          39

시뮬레이션과 자동 배치배선 그리고 LVS(네트리스트 검사)등 합성 이후 수행할 과정에 사용될 파일들이 저장되는 곳은 synthesis 디렉토리다.

$ ll ./synthesis

  total 1876
  drwxr-xr-x 2 mychip mychip   4096 Dec  7 11:56 .
  drwxr-xr-x 7 mychip mychip   4096 Dec  7 11:49 ..
  -rw-r--r-- 1 mychip mychip 248257 Dec  7 11:56 apple_1_mapped.v
  -rw-r--r-- 1 mychip mychip      8 Dec  7 11:56 apple_1_nofanout
  -rw-r--r-- 1 mychip mychip     34 Dec  7 11:56 apple_1_powerground
  -rw-r--r-- 1 mychip mychip 249312 Dec  7 11:56 apple_1.rtlbb.v
  -rw-r--r-- 1 mychip mychip 249262 Dec  7 11:56 apple_1.rtlnopwr.v
  -rw-r--r-- 1 mychip mychip 328975 Dec  7 11:56 apple_1.rtl.v
  -rw-r--r-- 1 mychip mychip 249438 Dec  7 11:56 apple_1_sized.v
  -rw-r--r-- 1 mychip mychip 175698 Dec  7 11:56 apple_1.spc
  -rw-r--r-- 1 mychip mychip 249262 Dec  7 11:56 apple_1.v
  -rw-r--r-- 1 mychip mychip 146041 Dec  7 11:56 apple_1.xspice

3-3. Apple-1 네트리스트 타이밍 시뮬레이션

합성으로 얻은 표준 셀의 네트리스트를 시뮬레이션을 통해 검증한다. 검증에 사용될 네트리스트 베릴로그 파일은 synthesis/apple_1_mapped.v 다. 지연 정보가 포함된 표준셀의 베릴로그 모델은 ~/ETRI050_DesignKit/digital_ETRI/khu_etri05_stdcells.v 이다.

$ cd simulation

$ pwd
  ~/ETRI050_DesignKit/Projects/RTL/apple_1/ETRI050/simulation

$ make

  Symbolic Link Testbench Re-Use...
  Symbolic Link Memory & IO Re-Use...
  Symbolic Link Firmware & SDK...

  Netlist timing simulation using iVerilog-VPI:apple_1
    TOP_MODULE=apple_1 VCD_TRACE=YES|[NO] make build
    TOP_MODULE=apple_1 make run
    TOP_MODULE=apple_1 make wave
    TOP_MODULE=apple_1 make clean

네트리스트 시뮬레이션은 베릴로그의 VPI를 통해 SystemC 테스트벤치와 연동된다. 기능 시뮬레이션에 사용했던 테스트벤치와 메모리 모델들이 재사용될 것이다. 베릴로그 시뮬레이터는 오픈-소스 도구 iVerilog 다.

$ ll

  total 40
  drwxr-xr-x 2 mychip .
  drwxr-xr-x 7 mychip ..
  lrwxrwxrwx 1 mychip Apple-1 -> ../../simulation/Apple-1
  -rw-r--r-- 1 mychip apple_1_TB.v
  -rw-r--r-- 1 mychip Makefile
  lrwxrwxrwx 1 mychip sc_apple_1_TB.cpp -> ../../simulation/sc_apple_1_TB.cpp
  -rw-r--r-- 1 mychip sc_apple_1_TB.h
  lrwxrwxrwx 1 mychip sc_mem.cpp -> ../../simulation/sc_mem.cpp
  lrwxrwxrwx 1 mychip sc_mem.h -> ../../simulation/sc_mem.h
  -rw-r--r-- 1 mychip vpi_apple_1_tb.cpp
  -rw-r--r-- 1 mychip vpi_apple_1_tb_exports.h
  -rw-r--r-- 1 mychip vpi_apple_1_tb_ports.h
  -rw-r--r-- 1 mychip vpi_stub.cpp

$ make build

  g++  -DVPI_SIM \
       -I/usr/local/include/iverilog \
       -I/opt/systemc/include \
       -I../../c_untimed -I.. -L/opt/systemc/lib \
       -Dno_style -DIPC_SOCKET -g -fPIC \
       ./vpi_stub.cpp ./vpi_apple_1_tb.cpp \
       ./sc_mem.cpp ./sc_apple_1_TB.cpp \
       -o vpi_stub.vpi \
       -shared -latomic -lsystemc

  iverilog -g2005-sv -Tmin -gspecify -o apple_1_TB \
       apple_1_TB.v \
       ~/ETRI050_DesignKit/digital_ETRI/khu_etri05_stdcells.v  \
       ../synthesis/apple_1_mapped.v

표준 셀의 지연 모델링에 베릴로그의 UDP(Verilog User-Defined Primitive)가 사용되었다. 베릴레이터는 이를 지원하지 않으므로 오픈-소스 베릴로그 시뮬레이터 iVerilog를 사용한다. iVerilog는 VPI 를 지원하므로 SystemC 테스트벤치와 연동시킬 수 있다.

$ make run

네트리스트 시뮬레이션이 Apple-1의 기능 시뮬레이터와 동일하게 이뤄지는 것을 확인 할 수 있다. 합성은 추상화 수준의 급격한 변화를 가져오는 만큼 네트리스트 시뮬레이션을 통한 검증은 반도체 설계에서 필수다.  

3-4. 입출력 파형 관찰

클럭에 동기를 맞춘 디지털 회로의 동작을 관찰하는 전통적인 방법은 입력에 대한 출력을 시간상으로 기록한 파형의 관찰이다. 다수의 2진수로 한 값을 표현하는 디지털 회로의 파형 관찰은 매우 어렵다. 게다가 동작을 수행하는 과정에서 수많은 클럭이 소요되어 이를 일일이 관찰하기는 불가능하다. 이를 극복할 방법으로 다양한 검증 기법이 발달해왔다. 앞서 수행했던 Apple-1 시뮬레이터 처럼 클럭마다 입출력을 관찰하는 대신 회로가 내놓는 수행 결과만을 살펴보는 시스템 수준 검증 기법도 매우 효과적으로 널리 사용된다.

합성 후 네트리스트 시뮬레이션은 추상화 수준이 다른 두 설계물의 기능 외에 타이밍 검증도 포함된다. 네트리스트에 사용된 표준 셀은 실제 전자회로를 묘사(레이아웃)한 것으로 회로의 지연 정보를 담고 있다. 배치와 배선하기 전이므로 경로상의 지연까지 포함하지 않지만 합성의 결과 연속된 게이트 회로의 통과 지연을 반영한 타이밍 시뮬레이션이 가능하다. 설계에 대한 동작 클럭의 요건이 있는 경우 이에 따르도록 합성 옵션(긴 게이트 경로에 대하여 구동 능력이 높은 게이트 사용 등)을 변경하거나 경우에따라 설계 변경(긴 경로 중간에 플립 플롭 삽입)이 필요할 수 있다.

VCD(Value Change Dump)는 하드웨어 언어의 입출력을 기록하는 양식이다. 시뮬레이션 중 입출력 파형을 기록하면 매우 큰 VCD 파일이 생성 되어 설계 컴퓨터에 큰 부담을 준다. 따라서 시스템 수준 시뮬레이션 중에 VCD 기록을 꺼놓았다. 입출력 타이밍 관찰을 위해 VCD 추적을 켜고 시뮬레이터를 빌드한다.

$ make clean

$ VCD_TRACE=YES make build

$ make run

시뮬레이션으로 얻은 입출력 파형을 비교해 보자. 네트리스트 타이밍 시뮬레이션으로 지연을 관찰 할 수 있다. 복잡한 경로를 가지고 있는 어드레스 버스 AB[15:0]의 출력이 간단한 ROM의 출력 DO_woz[7:0] 에 비해 상대적으로 긴 지연을 가지고 있다.

$ make wave

경로 타이밍 정보를 가지고 있지 않은 기능 시뮬레이션의 파형에는 지연이 반영되지 않는다.









댓글 없음:

댓글 쓰기