목록SystemVerilog검증/4. 객체지향 OOP 기초 (19)
지노랩 /JinoLab
객체 지향 프로그래밍(Object-Oriented Programming, OOP)을 사용하는 것은 특히 처음 프로그래밍 언어로 Verilog를 사용했던 사람들에게는 큰 도전이 될 수 있다. 그러나 OOP를 활용하면 테스트벤치가 더 모듈화되어 개발, 디버깅, 그리고 재사용이 훨씬 용이해진다.처음 OOP 기반의 테스트벤치를 작성할 때는 기존 Verilog 코드에 몇 개의 클래스만 추가한 형태처럼 보일 수 있다. 하지만 OOP 개념에 익숙해질수록 트랜잭션(transaction)과 이를 조작하는 트랜잭터(transactor)를 보다 효과적으로 설계하고 관리할 수 있게 된다.Chapter 8에서는 더욱 발전된 OOP 기법을 학습하게 된다. 이를 통해 기존 코드의 변경 없이도 테스트벤치의 동작을 유연하게 조정할 수..

SystemVerilog에서 테스트벤치는 검증 환경을 구성하는 중요한 요소이다. 테스트벤치는 계층적으로 구성되며, 각 블록이 클래스 형태로 표현된다. 아래의 다이어그램은 계층적 테스트벤치 구조를 보여준다. 계층적 테스트벤치 구조테스트벤치는 환경(Environment) 내에서 다양한 요소를 포함한다. 주요 요소는 다음과 같다.Test: 테스트 시퀀스를 정의하는 최상위 계층Generator: 트랜잭션을 생성하는 블록Agent: 드라이버와의 인터페이스 역할을 수행Driver: 트랜잭션을 DUT(Design Under Test)로 전달Monitor: DUT에서 나오는 신호를 감시Checker: 예상 결과와 비교하여 테스트 성공 여부 확인Scoreboard: 트랜잭션의 통계를 기록 및 관리Assertions: 설..
객체지향 프로그래밍(OOP)을 처음 접하는 사람들은 종종 클래스로 데이터를 구조화하는 과정이 번거롭다고 느껴 변수를 개별적으로 선언하고 사용하는 유혹을 받는다. 그러나 이러한 접근 방식은 피해야 한다.잘못된 데이터 관리 방식DUT(Device Under Test, 테스트 대상 장치)를 모니터링하는 기본적인 역할을 하는 DUT 모니터는 인터페이스에서 여러 개의 값을 샘플링한다.이때 샘플링된 데이터를 단순히 정수형 변수에 저장하고 이를 다음 단계로 전달하는 방식은 문제를 유발할 수 있다.처음에는 변수를 단순히 저장하는 방식이 시간이 절약되는 것처럼 보일 수 있지만, 궁극적으로는 이러한 값들을 하나의 완전한 트랜잭션으로 묶어야 한다.이러한 트랜잭션이 다시 그룹화되어 더 **고차원의 트랜잭션(예: DMA 전송)..
객체지향 프로그래밍(OOP)의 핵심 개념 중 하나는 데이터와 관련된 루틴을 클래스 내부로 캡슐화(encapsulation)하는 것이다. 일반적으로 데이터는 기본적으로 비공개(private)로 유지되며, 이를 통해 한 클래스가 다른 클래스의 내부 데이터에 직접 접근하는 것을 방지할 수 있다. 대신, 클래스는 데이터에 접근하고 수정할 수 있는 접근자(accessor) 루틴을 제공하여 데이터를 제어할 수 있도록 한다.이 방식은 클래스의 내부 구현을 변경하더라도 사용자에게 영향을 주지 않게 하는 장점이 있다. 예를 들어, 그래픽 패키지에서 좌표계를 데카르트(Cartesian) 좌표에서 극(polar) 좌표로 변경한다고 해도, 사용자가 동일한 인터페이스를 통해 접근할 수 있도록 하면 프로그램의 기능적인 변화 없이..

SystemVerilog에서 객체를 복사해야 하는 경우가 있다. 예를 들어, 원본 데이터를 변경하지 않고 루틴에서 사용하거나, 생성기(generator)에서 객체의 제약을 유지해야 하는 경우다. 객체를 복사하는 방법은 크게 두 가지가 있다.new 키워드를 사용하여 기본적인 복사를 수행하는 방법직접 사용자 정의 복사 메서드를 작성하여 더 정교한 복사를 수행하는 방법Section 8.3에서는 왜 복사 메서드를 만들어야 하는지에 대한 설명이 포함되어 있다.4.15.1 new를 사용한 객체 복사(Copying an object with new)new 키워드를 사용하면 쉽게 객체 복사가 가능하다. 새로운 객체가 생성되며, 기존 객체의 모든 변수가 복사된다.예제 4-27: 간단한 클래스를 new를 사용하여 복사하기..
SystemVerilog에서 동적 객체를 이해하는 것은 매우 중요하다. 기존 Verilog와 달리, 객체지향 프로그래밍(OOP)에서는 객체와 핸들이 분리되어 있어, 하나의 핸들이 여러 객체를 참조할 수 있다.Verilog에서는 모든 데이터가 고정된 변수와 연결되지만, OOP에서는 객체의 수와 핸들의 수가 다를 수 있다. 예를 들어, 테스트벤치에서 수천 개의 트랜잭션 객체를 생성하더라도, 조작하는 핸들은 몇 개만 사용할 수도 있다.이 개념은 기존 Verilog 사용자에게 익숙하지 않을 수 있으며, 객체를 다루는 새로운 방식에 적응하는 과정이 필요하다.SystemVerilog에서는 객체를 조작하기 위해 핸들을 사용한다. 핸들은 객체를 가리키는 포인터와 유사하며, 객체는 배열, 큐, 링크드 리스트 등의 자료구..
SystemVerilog에서 하나의 클래스 내부에 또 다른 클래스를 포함하는 방법에 대해 설명한다. 이는 Verilog에서 모듈 내부에 다른 모듈을 포함하는 개념과 유사하다. 이렇게 하면 재사용성이 증가하고 코드의 복잡도를 효과적으로 관리할 수 있다.클래스 내부에서 다른 클래스를 사용하는 이유재사용성 향상: 특정 기능을 여러 클래스에서 공통적으로 사용할 경우 별도의 클래스로 분리하여 코드 중복을 줄일 수 있다.복잡도 관리: 트랜잭션(Transaction)마다 개별적인 통계 정보를 기록하고 관리하려면, 별도의 Statistics 클래스를 만들어 트랜잭션의 시작과 종료 시간을 기록하고 전체 통계를 관리할 수 있다.예제 4-18: Statistics 클래스 선언class Statistics; time s..
SystemVerilog에서 테스트벤치를 작성할 때, 많은 변수를 생성하고 참조해야 한다. SystemVerilog는 Verilog와 동일한 기본 스코핑 규칙을 따르지만 몇 가지 중요한 개선 사항이 추가되었다.스코프(범위)란?스코프(Scope)는 코드 블록을 의미하며, 모듈(module), 프로그램(program), 태스크(task), 함수(function), 클래스(class) 또는 begin-end 블록이 이에 해당한다. for 및 foreach 루프는 자동으로 블록을 생성하므로, 루프 내부에서 선언된 인덱스 변수가 해당 루프의 범위에만 존재하도록 처리할 수 있다.SystemVerilog에서는 새로운 기능으로 begin-end 블록 내에서 변수를 선언할 수 있으며, 이는 for 루프에서 인덱스 변수를..
SystemVerilog에서 클래스를 정의할 때, 클래스 내부에 모든 루틴을 작성하면 코드가 길어지고 가독성이 떨어질 수 있다.이를 해결하기 위해 루틴(메서드)을 클래스 외부에 정의할 수 있는 기능을 제공한다.extern 키워드를 사용하여 클래스 내부에 루틴의 프로토타입(Prototype)만 선언하고,실제 루틴의 구현을 클래스 바깥에 위치시키면 코드 가독성이 향상된다.1. 클래스 외부 루틴 정의 방법예제 4-12: 클래스 외부에서 루틴 정의하기class BusTran; bit [31:0] addr, crc, data[8]; extern function void display(); // 함수의 프로토타입 선언endclass// 클래스 외부에서 함수 정의function void BusTran::d..
4.10 클래스 루틴(Class Routines) 개요SystemVerilog에서 **루틴(Routine)은 클래스 내부에서 정의된 task 또는 function으로, 객체의 동작을 수행하는 메서드(Method)**이다.예제에서는 두 개의 클래스 BusTran과 PCI_Tran에서 각각 display() 함수를 정의하며,SystemVerilog는 핸들(Handle) 타입에 따라 자동으로 적절한 display() 함수를 호출한다.1. SystemVerilog에서 루틴 사용 예제아래 예제에서는 BusTran과 PCI_Tran 클래스를 정의하고,각 클래스에 display() 함수를 구현하여 객체 데이터를 출력하는 기능을 제공한다.예제 4-11: 클래스 내부 루틴 정의 및 호출class BusTran; b..
SystemVerilog에서는 객체마다 독립적인 로컬 변수를 가지며, 다른 객체와 공유되지 않는다.예를 들어, 두 개의 BusTran 객체가 존재할 경우,각 객체는 자신만의 addr, crc, data 변수를 가지므로 서로 영향을 주지 않는다.하지만 때때로 모든 객체에서 공유해야 하는 변수가 필요할 수도 있다.예를 들어, 생성된 트랜잭션의 개수를 추적하려면 모든 BusTran 객체가 공통으로 사용하는 카운트 변수가 필요하다.이러한 경우, 전역 변수(Global Variable)를 사용하지 않고, 정적 변수(Static Variable)를 활용하면 더욱 효과적이다.4.9.1 정적 변수(Static Variable) 사용법SystemVerilog에서는 클래스 내부에 정적 변수(Static Variable)를..
SystemVerilog에서 객체를 생성한 후에는 이를 활용하는 방법을 알아야 한다.Verilog 모듈에서 변수 및 루틴을 접근하는 방식과 유사하게,SystemVerilog에서는 객체의 멤버 변수 및 메서드(함수, 태스크)를 접근할 때 .(닷) 연산자를 사용한다.1. SystemVerilog에서 객체 변수와 메서드 접근 방법아래 예제는 객체를 생성한 후 변수 값을 설정하고, 메서드를 호출하는 기본적인 사용법을 보여준다.예제 4-8: 객체의 변수 및 루틴 사용BusTran b; // BusTran 객체를 위한 핸들 선언b = new; // BusTran 객체 생성b.addr = 32'h42; // 객체 변수 addr 값을 설정b.display(); // 객체의 display()..
4.7 객체 할당 해제(Object Deallocation)SystemVerilog에서 객체를 생성하는 방법은 앞서 살펴보았지만, 생성된 객체를 어떻게 삭제해야 할까?예를 들어, 테스트벤치에서 수천 개의 트랜잭션을 생성하여 DUT(Device Under Test)로 전송한다고 가정해보자.트랜잭션이 완료되고 통계 데이터를 수집한 후, 더 이상 필요하지 않은 객체를 메모리에서 해제하는 것이 중요하다.메모리를 적절히 해제하지 않으면, 시뮬레이션 실행 시간이 증가하거나 시스템이 메모리 부족(Out of Memory) 상태에 빠질 수 있다.이를 방지하기 위해 SystemVerilog에서는 자동 가비지 컬렉션(Garbage Collection) 기능을 제공한다.1. SystemVerilog의 가비지 컬렉션(Garb..
4.6 객체 생성 (Creating New Objects)Verilog와 객체 지향 프로그래밍(OOP) 모두 인스턴스화(Instantiation) 개념을 사용하지만,그 세부적인 구현 방식에는 차이가 있다.Verilog에서는 **모듈(Module)**을 인스턴스화할 때, 정적으로(Statically) 선언되며,네트리스트(Netlist)가 컴파일될 때 인스턴스가 생성된다.반면, SystemVerilog 클래스(Class)는 런타임(Runtime)에서 필요할 때 동적으로(Dynamically) 생성된다.즉, 테스트벤치가 실행될 때 클래스 인스턴스를 생성하고 필요에 따라 제거할 수 있다.Verilog와 SystemVerilog 클래스 인스턴스 차이점Verilog 인스턴스는 정적(Static), SystemVer..
4.5 OOP Terminology (객체 지향 프로그래밍 용어 정리)SystemVerilog에서 객체 지향 프로그래밍(Object-Oriented Programming, OOP)은효율적인 테스트벤치(Testbench) 설계를 가능하게 하는 중요한 개념이다.초보자와 전문가의 차이는 OOP 개념과 용어를 얼마나 잘 이해하고 활용하는지에서 비롯된다.이 글에서는 Verilog 및 SystemVerilog에서 사용하는 주요 OOP 개념과 그에 대한 설명을 제공한다.1. SystemVerilog에서 사용되는 주요 OOP 개념① 클래스(Class)클래스는 객체를 생성하는 기본적인 설계 단위이다.내부에 변수(데이터)와 함수(루틴)를 포함한다.Verilog에서 모듈(Module)과 유사한 개념이다.② 객체(Object..
4.4 클래스 정의 위치 (Where to Define a Class)SystemVerilog에서 클래스(Class)는 다양한 컨텍스트에서 정의할 수 있다.주로 다음과 같은 위치에서 정의할 수 있다.프로그램(program)모듈(module)패키지(package)독립적인 파일 (Standalone Class File)각각의 방식은 특정한 용도에 맞게 사용되며, 테스트벤치 설계에서 중요한 역할을 한다.1. 프로그램 블록(Program Block)에서 클래스 정의이 책에서는 프로그램 블록(program block) 내에서 클래스를 정의하는 방식을 다룬다.프로그램 블록은 테스트 코드(Test Code)를 포함하는 모듈(Module)과 유사한 개념으로,다음과 같은 역할을 수행한다.단일 테스트(Test)를 실행하는..
SystemVerilog의 객체 지향 프로그래밍(OOP) 기능을 활용하면 데이터와 이를 조작하는 루틴을 하나의 클래스로 캡슐화할 수 있다.이로 인해 코드의 가독성과 유지보수성이 향상되며, 테스트벤치를 더욱 효율적으로 구성할 수 있다.클래스 개념과 활용예제 4-1에서는 패킷(Packet) 데이터를 표현하는 BusTran 클래스를 정의한다.이 클래스에는 **소스 및 목적지 주소(Source and Destination Addresses)와 데이터 배열(Data Array)**이 포함된다.또한, 클래스 내에는 두 개의 함수(Function)가 존재한다.display 함수패킷의 내용을 출력하는 역할을 한다.calc_crc 함수데이터의 순환 중복 검사(Cyclic Redundancy Check, CRC) 를 계산..
데이터와 코드의 결합이 중요한 이유테스트벤치를 효과적으로 개발하고 유지보수하려면 데이터와 코드가 함께 구성되어야 한다.그렇다면 어떻게 데이터와 코드를 결합할 수 있을까?가장 좋은 접근 방식은 테스트벤치가 수행해야 할 작업을 고려하는 것이다.테스트벤치(Testbench)의 목표는설계(Design)에 자극(Stimulus)을 적용하고그 결과가 올바른지 확인하는 것이다.설계로 들어오고 나가는 데이터는 트랜잭션(Transaction) 단위로 그룹화된다.따라서, 테스트벤치를 구성하는 가장 쉬운 방법은 트랜잭션 중심으로 조직하는 것이다.객체 지향 프로그래밍(OOP)에서는 트랜잭션이 핵심 객체(Object) 가 된다.자동차를 활용한 비유자동차 운전을 예로 들어보자.운전할 때 우리는 스타트 버튼을 누르고, 전진(For..
일반적인 절차형 프로그래밍 언어(Procedural Programming Language)인 Verilog와 C에서는 데이터 구조(Data Structure)와 이를 다루는 코드(Code)가 분리되어 있다.즉, 데이터 선언과 알고리즘이 서로 다른 파일에 존재하는 경우가 많아, 프로그램의 기능을 이해하는 것이 어렵다.Verilog에서의 데이터 관리 문제Verilog는 C보다 더 큰 한계를 가지고 있다.Verilog는 구조체(Structure)를 지원하지 않으며, 비트 벡터(Bit Vector)와 배열(Array)만을 제공한다.예를 들어, 버스 트랜잭션(Bus Transaction) 정보를 저장하려면 여러 개의 배열을 사용해야 한다.주소 정보 배열 (Address Array)데이터 배열 (Data Array..