ASIC SoC2012. 2. 6. 19:20

Ruby-vpi를 테스트 하는 과정을 정리하였다.
여기서 사용하는 예제는 아래 링크에서 참조 하였다.

http://snk.tuxfamily.org/lib/ruby-vpi/#usage.tutorial.declare-design

디자인은 counter.v 이다.

일단 Top module부터 만든다.

module counter #(parameter Size = 5) (
  input                   clock,
  input                   reset,
  output reg [Size-1 : 0] count
);
endmodule


일단 폴더를 만들고

mkdir xUnit

디자인을 옮겨 둔다.
cp counter.v ./xUnit

그리고 해당 폴더로 가서 xUnit용 파일을 만든다.


GUNDAM-NT:xUnit kevinim$ ruby-vpi generate counter.v --xUnit

  module  counter
  create  counter_runner.rake
  create  counter_design.rb
  create  counter_proto.rb
  create  counter_spec.rb
  create  counter_loader.rb
  create  Rakefile 


위와 같이 커맨드를 넣으면 그에 맞게 파일이 만들어진다.
각각 앞에서 설명하였던 *.rake *_design.rb _proto.rb *_spec.rb *_loader.rb Rakefile 등이다.

(2) Spec 생성

카운터라는 것의 특성상 기본적인 내용은 아래와 같이 정의할 수 있겠다.
- 초기 값은 0이어야 한다.
- 상승 클럭에서 카운트 값이 1씩 증가한다.
- 최대 값에 도달하면 overflow가 발생하지만 하여튼 0부터 시작한다.

이것을 스펙으로 정의하면 아래와 같다.

require 'test/unit'

# lowest upper bound of counter's value
LIMIT = 2 ** DUT.Size.intVal

# maximum allowed value for a counter
MAX = LIMIT - 1


class A_counter_when_reset < Test::Unit::TestCase
  def setup
    DUT.reset! # reset the counter
  end

  def test_should_be_zero
    assert_equal( 0, DUT.count.intVal )
  end

  def test_should_increment_upon_each_subsequent_posedge
    LIMIT.times do |i|
      assert_equal( i, DUT.count.intVal )
      DUT.cycle! # increment the counter
    end
  end
end

class A_counter_with_the_maximum_value < Test::Unit::TestCase
  def setup
    DUT.reset! # reset the counter

    # increment the counter to maximum value
    MAX.times { DUT.cycle! }
    assert_equal( MAX, DUT.count.intVal )
  end

  def test_should_overflow_upon_increment
    DUT.cycle! # increment the counter
    assert_equal( 0, DUT.count.intVal )
  end
end

 크게 2개의 클래스를 만들었는데
하나가  A_counter_after_being_reset 이고
나머지 하나가 A_conter_with_the_maximum_value 이다.

각각 다음과 같은 동작을 수행한다.
 
 
A_counter_after_being_reset 
-  setup :: Reset을 건다. 
- test_should_be_zero :: 0인지 확인한다. 
- test_should_increment_upon_each_subsequent_posedge :: 계속 증가하면서 하나씩 커지는 것을 확인한다. 

A_counter_with_the_maximum_value
- setup :: 리셋을 건다.
- test_should_overflow_upon_increment :: overflow가 되면 0이 된다.

이다.

(3) Prototype을 만든다.

counter_proto.rb 파일에서 만든다.

if RubyVPI::USE_PROTOTYPE
  always do
    wait until DUT.clock.posedge?

    if DUT.reset.t ?
      DUT.count.intVal = 0 
    else
      DUT.count.intVal  += 1
   end
  end
end
      
 
카운터의 값의 프로토 타입을 의미한다.


(4) Prototype을 검증하기

검증은 다음과 같이 한다.

GUNDAM-NT:xUnit kevinim$ rake ivl PROTOTYPE=1 
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
rake aborted!
no such file to load -- ruby-vpi/runner_proxy

옵션으로 ivl은 icarus verilog simulator를 의미한다.

위와 같은 오류가 발생한다.
 
ruby-vpi/runner_proxy 

를 찾을 수 없다는 오류이다.

이 파일은 라이브러리에 있으므로 환경 변수를 설정한다.

export RUBYLIB=/Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ 

이후에 다시 실행한다.

GUNDAM-NT:xUnit kevinim$ rake ivl PROTOTYPE=1 
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
rake -f counter_runner.rake ivl PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
cp /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/obj/ivl.so ruby-vpi.vpi
["iverilog", "-mruby-vpi", "counter.v", {:verbose=>:default, :noop=>false}]
iverilog -mruby-vpi counter.v
["vvp -M. a.out", {:verbose=>:default, :noop=>false}]
vvp -M. a.out
ruby-vpi: prototype is enabled
SyntaxError: compile error
counter_proto.rb:6: syntax error, unexpected '\n'
counter_proto.rb:12: syntax error, unexpected kEND, expecting $end
        from counter_proto.rb:12:in `load_test'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi.rb:68:in `each'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi.rb:68:in `load_test'
        from ./counter_loader.rb:1
        from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
        from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/rubygems/custom_require.rb:31:in `require'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/boot/loader.rb:146
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:121:in `call'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:121:in `initialize'
        from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/generator.rb:83:in `call'
        from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/generator.rb:83:in `initialize'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:119:in `new'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:119:in `initialize'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:53:in `new'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/scheduler.rb:53:in `run'
        from /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/boot/loader.rb:144


몇개의 오류가 보인다.
이것을 먼저 수정하고 진행한다.

GUNDAM-NT:xUnit kevinim$ vi counter_proto.rb 
GUNDAM-NT:xUnit kevinim$ rake ivl PROTOTYPE=1 
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
rake -f counter_runner.rake ivl PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
cp /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/obj/ivl.so ruby-vpi.vpi
["iverilog", "-mruby-vpi", "counter.v", {:verbose=>:default, :noop=>false}]
iverilog -mruby-vpi counter.v
["vvp -M. a.out", {:verbose=>:default, :noop=>false}]
vvp -M. a.out
ruby-vpi: prototype is enabled
Loaded suite ruby-vpi
Started
EEE
Finished in 0.00128 seconds.

  1) Error:
test_should_be_zero(#<Module:0x10252d340>::A_counter_when_reset):
ArgumentError: "VpiHigh" is not a valid VPI property
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:364:in `initialize'
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:288:in `new'
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:288
....
  2) Error:
test_should_increment_upon_each_subsequent_posedge(#<Module:0x10252d340>::A_counter_when_reset):
ArgumentError: "VpiHigh" is not a valid VPI property
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:364:in `initialize'
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:288:in `new'
 ....

  3) Error:
test_should_overflow_upon_increment(#<Module:0x10252d340>::A_counter_with_the_maximum_value):
ArgumentError: "VpiHigh" is not a valid VPI property
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:364:in `initialize'
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:288:in `new'
    /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/lib/ruby-vpi/core/handle.rb:288
...

3 tests, 0 assertions, 0 failures, 3 errors
     
위의 에러는 뜻밖인데,
Ruby-VPI에서 버그가 있는것이다.
Test Code용으로 만들어낸 디자인에서 code가 틀리게 되어 있다.

counter_design.rb 를 아래와 같이 수정한다.


# Simulates the design under test for one clock cycle.
def DUT.cycle!
  clock.t!
  advance_time

  clock.f!
  advance_time
end

# Brings the design under test into a blank state.
def DUT.reset!
  reset.t!
  cycle!
  reset.f!
end
 
그리고 시뮬레이션을 수행하면 다음과 같은 오류가 발생한다.

GUNDAM-NT:xUnit kevinim$ rake ivl PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
rake -f counter_runner.rake ivl PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/ruby-vpi-test/xUnit)
cp /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/obj/ivl.so ruby-vpi.vpi
["iverilog", "-mruby-vpi", "counter.v", {:verbose=>:default, :noop=>false}]
iverilog -mruby-vpi counter.v
["vvp -M. a.out", {:verbose=>:default, :noop=>false}]
vvp -M. a.out
ruby-vpi: prototype is enabled
 MAX   is 31
 SIZE  is 5
 Limit is 32
Loaded suite ruby-vpi
Started
.FF
Finished in 0.059358 seconds.

  1) Failure:
test_should_increment_upon_each_subsequent_posedge(#<Module:0x10232d3d8>::A_counter_when_reset)
    [counter_spec.rb:27:in `test_should_increment_upon_each_subsequent_posedge'
     counter_spec.rb:26:in `times'
     counter_spec.rb:26:in `test_should_increment_upon_each_subsequent_posedge']:
<1> expected but was
<0>.

  2) Failure:
test_should_overflow_upon_increment(#<Module:0x10232d3d8>::A_counter_with_the_maximum_value) [counter_spec.rb:39]:
<31> expected but was
<0>.

3 tests, 4 assertions, 2 failures, 0 errors
 
이번의 오류는 RUBY와 icaurs가 연결이 되지 않는다는 의미이다.

그래서 이번에는 CVER로 바꾸어서 컴파일을 해본다.
GPLCver에 대한 설치는 이 페이지를 참조하고 여기서는 그냥 진행한다

GUNDAM-NT:xUnit kevinim$ rake cver PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/examples/counter/xUnit)
rake -f counter_runner.rake cver PROTOTYPE=1
(in /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/examples/counter/xUnit)
["cver", "+loadvpi=/Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/obj/cver.so:vlog_startup_routines_bootstrap", "+incdir+..", "../counter.v", {:verbose=>:default, :noop=>false}]
cver +loadvpi=/Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0/obj/cver.so:vlog_startup_routines_bootstrap +incdir+.. ../counter.v
GPLCVER_2.12a of 05/16/07 (Mac OSX).
Copyright (c) 1991-2007 Pragmatic C Software Corp.
  All Rights reserved.  Licensed under the GNU General Public License (GPL).
  See the 'COPYING' file for details.  NO WARRANTY provided.
Today is Wed Nov  2 19:37:38 2011.
Compiling source file "../counter.v"
Highest level modules:
counter

ruby-vpi: prototype is enabled
Loaded suite ruby-vpi
Started
...
Finished in 0.103285 seconds.

3 tests, 35 assertions, 0 failures, 0 errors
0 simulation events and 0 declarative immediate assigns processed.
1 behavioral statements executed (1 procedural suspends).
  Times (in sec.):  Translate 0.0, load/optimize 0.1, simulation 0.3.
  There were 3 error(s), 136 warning(s), and 4 inform(s).
End of GPLCVER_2.12a at Wed Nov  2 19:37:38 2011 (elapsed 0.3 seconds).

결과는 이상없이 잘 진행된다.
아마도 icarus와 ruby-vpi가 잘 안맞는 문제인듯..
Osx에서만 안맞는것인지 linux에서도 그런지는 확인을 하지 못하였다.
 
 
이 방법은 불안정 해서  더이상 진행하지 않습니다.
나중에 Linux + ModelSim이나 VCS로 테스트 해보고 되면 진행 예정입니다.


 
Posted by GUNDAM_IM
ASIC SoC2012. 2. 6. 19:19
(1) 개요

이 글은 아래 페이지를 참조하였다.

http://snk.tuxfamily.org/lib/ruby-vpi/

기본적으로  Ruby-VPI는 PLI 를 이용해서 Ruby까지 연결된 Interface를 제공한다.
따라서 Ruby를 이용해서  Testbench를 만들어 낼 수 있다는 점이 장점이다.
 
Ruby의 장점을 그대로 계승하기 때문에 Test bench나 검증 작성에 많은 도움이 된다.
검증 작성에서는 RUBY의 Test unit을 그대로 사용할 수 있기 때문에 TDD를 적용해 볼 수 있다.

Ruby-VPI의 최신 버전은 2008년 버전이며 21.1.0 버전이다.
다운로드는 아래 페이지에서 할 수 있다.

http://rubyforge.org/frs/?group_id=1339



(2) 설치

설치는 아래와 같이 한다.
설치에 대한 참조는 아래 링크를 참조 http://snk.tuxfamily.org/lib/ruby-vpi/#setup.inst

rake build
ruby bin/ruby-vpi -v


설치가 잘 되어 있으면 아래와 같은 메시지를 볼 수 있다.

ruby-vpi 21.1.0 (2008-08-02) http://ruby-vpi.rubyforge.org /Users/kevinim/Documents/Verilog_toos/Ruby-VPI/ruby-vpi-21.1.0


인스톨이 안되면 아래와 같이 직접 gem을 통해서 인스톨한다.

gem install ruby-vpi
WARNING:  Installing to ~/.gem since /Library/Ruby/Gems/1.8 and
          /usr/bin aren't both writable.
WARNING:  You don't have /Users/kevinim/.gem/ruby/1.8/bin in your PATH,
          gem executables will not run.
ERROR:  Error installing ruby-vpi:
        rspec requires rspec-expectations (~> 2.7.0, runtime)
 
rspec-ecpectations을 설치해야 하는데 아래와 같이 명령어를 넣어서 설치한다.
 
gem install rspec-expectations

설치되고 검사는 위와 같은 방식으로 실행한다.

ruby-vpi  -v

2008년 이후에 Update가 안되었으니까 굳이 Update할 필요가 없지만,

혹시 몰라서 업데이트 커맨드는 아래와 같다.

gem update ruby-vpi


  (3) RUBY-VPI가 지원하는 시뮬레이터

SimulatorNotes
GPL Cver(recommended) Version 2.11a or newer is acceptable.
Synopsys VCS Any version that supports the -load option is acceptable.
Mentor Modelsim Any version that supports the -pli option is acceptable. SeeSection 6.3. Mentor Modelsim if you are using Modelsim version 6.2g.
Cadence NC-Sim Any version that supports the +loadvpi option is acceptable for Ruby-VPI versions 20.0.0 or older. See Section 6.2. Cadence NC-Sim for details.
Icarus Verilog Version 0.8 is mostly acceptable because you will not be able to access child handles through method calls. See Section 6.1.1. Give full paths to Verilog objects for details.
 
 일단 OSX에서는 ICARUS를 활용해서 한다.
 

(4)  RUBY-VPI의 기본적인 개념

 

ruby-vpi는 두개의 component로 연결되어 있다.
- ruby-vpi와 verilog vpi 이다.

Ruby를 이용해서 테스트 벤치를 가동시키고 test case를 구동시킬 수 있다. 이는  Ruby interpereter는 스크립트를 구동하는데 이는 Ruby-VPI를 통해서 Verilog VPI를 거쳐서 Simulator 를 구동하게 된다.
- 귀찮은 C를 이용한 PLI 가 없으므로 테스트 케이스 개발이 쉬워진다는 장점을 얻을 수 있다.

위의 그림을 단순하게 보면 아래와 같다.



Ruby-VPI를 사용하게 되면 몇개의 파일이 생성되거나 만들어지게 된다.

각각의 파일은 아래와 같다.

- runner.rake
      verilog simulator를 구동한다.
   
- design.rb
      DUT의 method를 정의한다.
     테스팅을 데이터 구조 등도 포함될 수 있다.

- proto.rb
     DUT 모델의 Ruby version

- spec.rb
    테스트를 위한 함수 / 클래스 등을 포함시킨다.

- loader.rb
   test를 로딩하는 user defined test code 이다.



     
 
Posted by GUNDAM_IM