Запускаем UVM 1.2 в QuestaSim под Windows

Запускаем UVM 1.2 в QuestaSim под Windows

Знакомство с библиотекой UVM логично начать с примеров, которые включены в дистрибутив библиотеки. Запуск этих примеров в QuestaSim под Windows не может не вызвать затруднений, т.к. в предлагаемых Makefile’ах для запуска примеров есть ошибки. В этой статье я покажу, как с минимальной модификацией исходных Makefile’ов запустить примеры <UVM_HOME>/examples/simple/hello_world и <UVM_HOME>/examples/integrated/ubus. И в качестве бонуса более привычные для QuestaSim tcl-скрипты на замену Makefile’ам.

Описанные в статье процедуры выполнялись со следующим программным обеспечением:

  • QuestaSim 10.4a
  • UVM 1.2
  • GNU Make 3.82.90
  • gcc-4.5.0-mingw64

Если у Вас более ранняя версия QuestaSim, то рекомендую использовать UVM 1.1d.

Многие ошибочно полагают, что запуск Makefile’ов в QuestaSim под Windows вообще невозожен, т.к. первая попытка заканчивается сообщением:

#invalid command name "make"

Команда “make” не входит в состав QuestaSim, поэтому придется устанавливать ее отдельно. Процесс установки make мы опустим. Отмечу лишь, что для успешного продолжения при наборе команды:

QuestaSim> make -v

в командной строке QuestaSim или в командной строке Windows, вы должны увидеть что-то типа:

# GNU Make 3.82.90
# Built for i686-pc-mingw32
# Copyright (C) 1988-2012 Free Software Foundation, Inc.
# License GPLv3+: GNU GPL version 3 or later 
# This is free software: you are free to change and redistribute it.
# There is NO WARRANTY, to the extent permitted by law.

После установки make не забудьте добавить путь к make.exe в переменную среды PATH.

Запускаем UVM 1.2 “Hello World”

Открываем QuestaSim и перемещаемся в в папку <UVM_HOME>/examples/simple/hello_world.

QuestaSim> cd E:/libs/uvm-1.2/examples/simple/hello_world

Тут нас интересует Makefile.questa:

  1. UVM_HOME = ../../..
  2.  
  3. include ../../Makefile.questa
  4.  
  5. all: run
  6.  
  7. comp: vlib
  8. $(VLOG) +incdir+. \
  9. hello_world.sv
  10.  
  11. run: comp
  12. $(VSIM)
  13. $(CHECK)

В этом Makefile’е вызывается еще один Makefile.questa, который расположен на 2 уровня выше в папке <UVM_HOME>/examples.

По умолчанию в этих Makefile’ах происходит компиляция библиотеки DPI, после которой вы должны получить uvm_dpi.dll. Тут и начинаются настоящие проблемы. Чтобы самостоятельно скомпилировать эту uvm_dpi.dll придется немало полазить по предложенным Makefile’ам и форумам, где Вам расскажут, как исправить сделанные в этих Makefile’ах ошибки. НО даже после успешно скомпилированной uvm_dpi.dll, пример не запускается.

Разработчики из MentorGraphics включили в QuestaSim свою прекомпилированную версию библиотеки uvm_dpi.dll. Для того, чтобы использовать ее потребуется пара “костылей” в существующих Makefile’ах.

1. Создадим копию <UVM_HOME>/examples/simple/hello_world/Makefile.questa с новым названием, например, RunHelloWorld.questa:

  1. QUESTA_HOME = "C:/questasim64_10.4a"
  2. UVM_DPI_HOME = $(QUESTA_HOME)/uvm-1.2/win64
  3. USES_PRECOMPILED_UVM_DPI = 1
  4.  
  5. UVM_HOME = ../../..
  6.  
  7. include ../../CustomMakefile.questa
  8.  
  9. all: run
  10.  
  11. comp: vlib
  12. $(VLOG) +incdir+. \
  13. hello_world.sv
  14.  
  15. run: comp
  16. $(VSIM)
  17. $(CHECK)

Как видите, здесь добавлено 3 новых строки и изменено имя вложенного Makefile’а:

  1. 1) Путь к QuestaSim
  2. 2) Путь к прекомпилированной библиотеке uvm_dpi.dll.
  3. 3) И новая переменная USES_PRECOMPILED_UVM_DPI, которая будет использоваться в <UVM_HOME>/examples/CustomMakefile.questa

2. Теперь создадим копию <UVM_HOME>/examples/Makefile.questa с новым названием CustomMakefile.questa. Не буду приводить полный исходный код этого Makefile’а. Найдем следующий фрагмент кода:

  1. ifeq ($(USES_DPI),1)
  2. DPILIB_VLOG_OPT =
  3. DPILIB_VSIM_OPT = -sv_lib $(LIBDIR)/uvm_dpi
  4. DPILIB_TARGET = dpi_lib$(BITS)
  5. else
  6. DPILIB_VLOG_OPT = +define+UVM_NO_DPI
  7. DPILIB_VSIM_OPT =
  8. DPILIB_TARGET =
  9. endif

Тут задается опция для симуляции DPILIB_VSIM_OPT, которая говорит, где искать библиотеку uvm_dpi, и цель DPILIB_TARGET для компиляции этой библиотеки. Мы не хотим самостоятельно компилировать эту библиотеку, поэтому изменим приведенный выше код:

  1. ifeq ($(USES_PRECOMPILED_UVM_DPI),1)
  2. DPILIB_VLOG_OPT =
  3. DPILIB_VSIM_OPT = -sv_lib $(UVM_DPI_HOME)/uvm_dpi
  4. DPILIB_TARGET =
  5. else ifeq ($(USES_DPI),1)
  6. DPILIB_VLOG_OPT =
  7. DPILIB_VSIM_OPT = -sv_lib $(LIBDIR)/uvm_dpi
  8. DPILIB_TARGET = dpi_lib$(BITS)
  9. else
  10. DPILIB_VLOG_OPT = +define+UVM_NO_DPI
  11. DPILIB_VSIM_OPT =
  12. DPILIB_TARGET =
  13. endif

Как видите, тут в конструкцию if-else добавлена еще одна ветка с переменными из RunHelloWorld.questa, которая задает новый путь к прекомпилированной uvm_dpi.

Вот, где должны быть расположены новые файлы:

Запускаемся из папки <UVM_HOME>/examples/simple/hello_world:

  1. QuestaSim> make -f RunHelloWorld.questa all

Вот часть сообщений, которые должны появиться в консоли QuestaSim, если пример запустился успешно:

  1. ...
  2. # UVM_INFO @ 0 ns: reporter [RNTST] Running test ...
  3. # UVM_INFO ../../../src/base/uvm_root.svh(579) @ 0 ns: reporter [UVMTOP] UVM testbench topology:
  4. # ------------------------------------------------------------
  5. # Name Type Size Value
  6. # ------------------------------------------------------------
  7. # top top - -
  8. # consumer consumer #(T) - -
  9. # in uvm_blocking_put_imp - -
  10. # recording_detail uvm_verbosity 32 UVM_LOW
  11. # out uvm_get_port - -
  12. # recording_detail uvm_verbosity 32 UVM_LOW
  13. # count integral 32 'd0
  14. # recording_detail uvm_verbosity 32 UVM_LOW
  15. # fifo uvm_tlm_fifo #(T) - -
  16. # get_ap uvm_analysis_port - -
  17. # recording_detail uvm_verbosity 32 UVM_LOW
  18. # get_peek_export uvm_get_peek_imp - -
  19. # recording_detail uvm_verbosity 32 UVM_LOW
  20. # put_ap uvm_analysis_port - -
  21. # recording_detail uvm_verbosity 32 UVM_LOW
  22. # put_export uvm_put_imp - -
  23. # recording_detail uvm_verbosity 32 UVM_LOW
  24. # recording_detail uvm_verbosity 32 UVM_LOW
  25. # producer1 producer #(T) - -
  26. # out uvm_blocking_put_port - -
  27. # recording_detail uvm_verbosity 32 UVM_LOW
  28. # proto packet - -
  29. # num_packets integral 32 'd2
  30. # count integral 32 'd0
  31. # recording_detail uvm_verbosity 32 UVM_LOW
  32. # producer2 producer #(T) - -
  33. # out uvm_blocking_put_port - -
  34. # recording_detail uvm_verbosity 32 UVM_LOW
  35. # proto packet - -
  36. # num_packets integral 32 'd4
  37. # count integral 32 'd0
  38. # recording_detail uvm_verbosity 32 UVM_LOW
  39. # recording_detail uvm_verbosity 32 UVM_LOW
  40. # ------------------------------------------------------------
  41. #
  42. # UVM_INFO producer.sv(46) @ 0 ns: top.producer2 [producer] Starting.
  43. # UVM_INFO producer.sv(62) @ 0 ns: top.producer2 [producer] Sending producer2-0
  44. # UVM_INFO producer.sv(46) @ 0 ns: top.producer1 [producer] Starting.
  45. # UVM_INFO producer.sv(62) @ 0 ns: top.producer1 [producer] Sending producer1-0
  46. # UVM_INFO producer.sv(62) @ 10 ns: top.producer2 [producer] Sending producer2-1
  47. # UVM_INFO producer.sv(62) @ 20 ns: top.producer2 [producer] Sending producer2-2
  48. # UVM_INFO consumer.sv(57) @ 40 ns: top.consumer [consumer] Received producer1-0 local_count=1
  49. # UVM_INFO producer.sv(62) @ 50 ns: top.producer1 [producer] Sending producer1-1
  50. # UVM_INFO consumer.sv(57) @ 80 ns: top.consumer [consumer] Received producer2-0 local_count=2
  51. # UVM_INFO producer.sv(62) @ 90 ns: top.producer2 [producer] Sending producer2-3
  52. # UVM_INFO consumer.sv(57) @ 120 ns: top.consumer [consumer] Received producer1-1 local_count=3
  53. # UVM_INFO producer.sv(73) @ 130 ns: top.producer1 [producer] Exiting.
  54. # UVM_INFO consumer.sv(57) @ 160 ns: top.consumer [consumer] Received producer2-1 local_count=4
  55. # UVM_INFO producer.sv(73) @ 170 ns: top.producer2 [producer] Exiting.
  56. # UVM_INFO consumer.sv(57) @ 200 ns: top.consumer [consumer] Received producer2-2 local_count=5
  57. # UVM_INFO consumer.sv(57) @ 240 ns: top.consumer [consumer] Received producer2-3 local_count=6
  58. # UVM_INFO ../../../src/base/uvm_objection.svh(1271) @ 1000 ns: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
  59. # UVM_INFO ../../../src/base/uvm_report_server.svh(847) @ 1000 ns: reporter [UVM/REPORT/SERVER]
  60. # --- UVM Report Summary ---
  61. #
  62. # ** Report counts by severity
  63. # UVM_INFO : 20
  64. # UVM_WARNING : 0
  65. # UVM_ERROR : 0
  66. # UVM_FATAL : 0
  67. # ** Report counts by id
  68. # [RNTST] 1
  69. # [TEST_DONE] 1
  70. # [UVM/RELNOTES] 1
  71. # [UVMTOP] 1
  72. # [consumer] 6
  73. # [producer] 10
  74. #
  75. # ** Note: $finish : ../../../src/base/uvm_root.svh(517)
  76. # Time: 1 us Iteration: 68 Instance: /hello_world
  77. # End time: 08:36:23 on Aug 02,2016, Elapsed time: 0:00:07
  78. # Errors: 0, Warnings: 0
  79. # RunHelloWorld.questa:37: recipe for target 'run' failed
  80. # process_begin: CreateProcess(NULL, . ( `grep -c "UVM_ERROR : 0" questa.log` -eq 1 ) -a ( `grep -c "UVM_FATAL : 0" questa.log` -eq 1 ), ...) failed.
  81. # make (e=5): Îòêàçàíî â äîñòóïå.
  82. #
  83. # make.EXE: *** [run] Error 5

Несмотря на странные сообщения в конце, пример выполнился. А эти строки:

  1. # RunHelloWorld.questa:37: recipe for target 'run' failed
  2. # process_begin: CreateProcess(NULL, . ( `grep -c "UVM_ERROR : 0" questa.log` -eq 1 ) -a ( `grep -c "UVM_FATAL : 0" questa.log` -eq 1 ), ...) failed.
  3. # make (e=5): Îòêàçàíî â äîñòóïå.
  4. #
  5. # make.EXE: *** [run] Error 5

результат неправильного парсинга лог-файла на наличие ошибок. Дело в том, что этот парсер использует линуксовую команду grep. Я сделал пару попыток адаптировать этот парсер под Windows, но…не сложилось. Пока просто уберем этот парсинг из <UVM_HOME>/examples/simple/RunHelloWorld.questa:

  1. ...
  2. run: comp
  3. $(VSIM)
  4. # $(CHECK)

Запускаем UVM 1.2 “UBUS”

Для запуска примера <UVM_HOME>/examples/integrated/ubus/examples будет использоваться описанный выше <UVM_HOME>/examples/CustomMakefile.questa.

Создадим копию <UVM_HOME>/examples/integrated/ubus/examples/Makefile.questa с новым названием RunUbus.questa:

  1. QUESTA_HOME = "C:/questasim64_10.4a"
  2. UVM_DPI_HOME = $(QUESTA_HOME)/uvm-1.2/win64
  3. USES_PRECOMPILED_UVM_DPI = 1
  4.  
  5. UVM_HOME = ../../../..
  6. USES_DPI = 1
  7. UVM_TESTNAME ?=test_2m_4s
  8.  
  9. include ../../../CustomMakefile.questa
  10.  
  11. all: run
  12.  
  13. comp: vlib
  14. $(VLOG) +incdir+../sv \
  15. ubus_tb_top.sv
  16.  
  17. run: comp
  18. $(VSIM) +UVM_TESTNAME=$(UVM_TESTNAME)
  19. # $(CHECK)

Новые файлы:

Запускаем:

  1. QuestaSim> cd E:/libs/uvm-1.2/examples/integrated/ubus/examples
  2. QuestaSim> make -f RunUbus.questa all

Tcl-скрипты для запуска UVM 1.2 “UBUS”

Старался по максимуму перенести все содержимое Makefile’ов. Для описания целей используются tcl-процедуры proc.

Общий для примеров скрипт questa_base.tcl:

  1. set USES_DPI 1
  2. if [info exists UVM_NO_DPI] {
  3. set USES_DPI 0
  4. }
  5.  
  6. #---------------------------------------------------------------
  7. # Define Variables
  8. #---------------------------------------------------------------
  9. if ![info exists UVM_HOME] {
  10. set UVM_HOME ".."
  11. }
  12.  
  13. if ![info exists UVM_DPI_HOME] {
  14. set UVM_DPI_HOME ".."
  15. }
  16. if ![info exists MTI_HOME] {
  17. set MTI_HOME ${QUESTA_HOME}
  18. }
  19.  
  20. set LIBDIR ${UVM_HOME}/lib
  21. #set GCC ${MTI_HOME}/gcc-4.1.2-linux/bin/g++
  22. set GCC gcc
  23. set TEST /usr/bin/test
  24.  
  25. if ![info exists BITS] {
  26. set BITS 32
  27. }
  28.  
  29. set LIBNAME uvm_dpi
  30. set DPI_SRC ${UVM_HOME}/src/dpi/uvm_dpi.cc
  31.  
  32. set GCCCMD "exec ${GCC} \
  33. -m${BITS} \
  34. -fPIC \
  35. -DQUESTA \
  36. -g \
  37. -W \
  38. -shared \
  39. -x c \
  40. -I${MTI_HOME}/include \
  41. ${DPI_SRC} \
  42. -o ${LIBDIR}/${LIBNAME}.so"
  43. set WIN_GCC ${MTI_HOME}/gcc-4.5.0-mingw64/bin/g++.exe
  44. set GCC_WINCMD \
  45. "exec ${WIN_GCC} \
  46. -g \
  47. -DQUESTA \
  48. -W \
  49. -shared \
  50. -Bsymbolic \
  51. -I${MTI_HOME}/include \
  52. -I${UVM_HOME}/src \
  53. -I${UVM_HOME}/src/dpi/uvm_dpi.cc \
  54. -o ${UVM_HOME}/lib/uvm_dpi.dll \
  55. ${MTI_HOME}/win64/mtipli.dll \
  56. -I${MTI_HOME}/gcc-4.5.0-mingw64/include -lregex"
  57.  
  58. set VLIB "exec vlib work"
  59.  
  60. #---------------------------------------------------------------
  61. # If USES_DPI is set, enables compilation and loading of DPI
  62. # libraries. Enabling DPI adds +acc on command line, which
  63. # may adversely affect simulator performance.
  64. #---------------------------------------------------------------
  65. if {${USES_PRECOMPILED_UVM_DPI} == 1} {
  66. set DPILIB_VLOG_OPT ""
  67. set DPILIB_VSIM_OPT "-sv_lib ${UVM_DPI_HOME}/uvm_dpi"
  68. set DPILIB_TARGET ""
  69. } elseif {${USES_DPI} == 1} {
  70. set DPILIB_VLOG_OPT ""
  71. set DPILIB_VSIM_OPT "-sv_lib ${LIBDIR}/uvm_dpi"
  72. set DPILIB_TARGET dpi_lib${BITS}
  73. } else {
  74. set DPILIB_VLOG_OPT "+define+UVM_NO_DPI"
  75. set DPILIB_VSIM_OPT ""
  76. set DPILIB_TARGET ""
  77. }
  78.  
  79. if ![info exists VLOG_OPT] {
  80. set VLOG_OPT ""
  81. }
  82. if ![info exists VSIM_OPT] {
  83. set VSIM_OPT ""
  84. }
  85. if ![info exists OPT_C] {
  86. set OPT_C ""
  87. }
  88. if ![info exists OPT_R] {
  89. set OPT_R ""
  90. }
  91.  
  92. set VLOG "exec vlog \
  93. -timescale \"1ns/1ns\" \
  94. ${DPILIB_VLOG_OPT} \
  95. ${VLOG_OPT} \
  96. ${OPT_C} \
  97. -mfcu \
  98. -suppress 2181 \
  99. +acc=rmb \
  100. -writetoplevels questa.tops \
  101. +incdir+${UVM_HOME}/src \
  102. ${UVM_HOME}/src/uvm.sv"
  103.  
  104. set VSIM "exec vsim \
  105. ${DPILIB_VSIM_OPT} \
  106. ${VSIM_OPT} \
  107. ${OPT_R} \
  108. -c \
  109. -do \"run -all; q\" \
  110. -l questa.log \
  111. -f questa.tops"
  112. set N_ERRS 0
  113. set N_FATALS 0
  114.  
  115. #CHECK = \
  116. # @$(TEST) \( `grep -c 'UVM_ERROR : $(N_ERRS)' questa.log` -eq 1 \) -a \
  117. # \( `grep -c 'UVM_FATAL : $(N_FATALS)' questa.log` -eq 1 \)
  118.  
  119. #---------------------------------------------------------------
  120. # Define Targets
  121. #
  122. # vlog and vsim targets defined in individual examples
  123. #---------------------------------------------------------------
  124.  
  125.  
  126. proc help {} {
  127. puts "Usage: do questa_base.tcl"
  128. puts ""
  129. puts "Typical:"
  130. puts " do questa_base.tcl"
  131. puts ""
  132. puts "where target is any of"
  133. puts ""
  134. puts " dpi_lib - compile DPI lib (use BITS=XX, def=32)"
  135. puts " dpi_lib32 - compile DPI lib for 32-bit Linux (BITS=32)"
  136. puts " dpi_lib64 - compile DPI lib for 64-bit Linux (BITS=64)"
  137. puts " dpi_libWin - compile DPI lib for Windows"
  138. puts ""
  139. puts " clean - removes all derived files"
  140. puts " vlib - creates work library"
  141. puts " prepare - invokes clean, vlib, and dpi_lib targets"
  142. puts ""
  143. puts "When this tcl-script is included by a tcl-script from an example"
  144. puts "sub-directory, additional targets should be available:"
  145. puts ""
  146. puts " all - invokes targets prepare, vlog, and vsim"
  147. puts " vlog - invokes the vlog compiler"
  148. puts " vsim - invokes the vsim simulator"
  149. puts ""
  150. puts "Variables: specify any of the following on the make command line"
  151. puts ""
  152. puts " UVM_HOME - root directory of the UVM library (default:..)"
  153. puts " UVM_VERBOSITY - verbosity level for vsim (default:UVM_MEDIUM)"
  154. puts " BITS - the bus architecture: 32 or 64 (default:32)"
  155. puts " LIBNAME - the root name of the dpi library (default:uvm_dpi)"
  156. puts " LIBDIR - the location to put the dpi lib (default:UVM_HOME/lib)"
  157. puts ""
  158. }
  159.  
  160. proc vlib_target {} {
  161. global DPILIB_TARGET
  162. global GCCCMD
  163. if { [string length $DPILIB_TARGET] > 0 } {
  164. [$DPILIB_TARGET]
  165. }
  166. eval exec vlib work
  167. }
  168. proc prepare {} {
  169. global DPILIB_TARGET
  170. clean
  171. vlib_target
  172. if { [string length $DPILIB_TARGET] > 0 } {
  173. [$DPILIB_TARGET]
  174. }
  175. }
  176. proc dpi_lib {} {
  177. global LIBDIR
  178. global GCCCMD
  179. file mkdir ${LIBDIR}
  180. eval ${GCCCMD}
  181. }
  182. proc dpi_libWin {} {
  183. global LIBDIR
  184. global GCC_WINCMD
  185. file mkdir ${LIBDIR}
  186. eval ${GCC_WINCMD}
  187. }
  188.  
  189. proc dpi_lib32 {} {
  190. set BITS 32
  191. dpi_lib
  192. }
  193. proc dpi_lib64 {} {
  194. set BITS 64
  195. dpi_lib
  196. }
  197. proc clean {} {
  198. file delete -force -- *~ work vsim.wlf* *.log questa.tops transcript *.vstf
  199. }

Tcl-скрипт для примера UBUS run_ubus.tcl:

  1. #!/usr/bin/tclsh
  2. set QUESTA_HOME "C:/questasim64_10.4a"
  3. set UVM_DPI_HOME ${QUESTA_HOME}/uvm-1.2/win64
  4. set USES_PRECOMPILED_UVM_DPI 1
  5.  
  6. set UVM_HOME "../../../.."
  7. set USES_DPI 1
  8. set UVM_TESTNAME test_2m_4s
  9.  
  10. source ../../../questa_base.tcl
  11.  
  12. proc comp {} {
  13. global VLOG
  14. vlib_target
  15. eval ${VLOG} +incdir+../sv \
  16. ubus_tb_top.sv
  17. }
  18.  
  19. proc run {} {
  20. global VSIM
  21. global UVM_TESTNAME
  22. comp
  23. eval ${VSIM} +UVM_TESTNAME=${UVM_TESTNAME}
  24. }
  25.  
  26. proc all {} {
  27. run
  28. }
  29.  
  30. proc alt {} {
  31. global UVM_HOME
  32. set QVERILOG "exec qverilog \
  33. -timescale \"1ns/1ns\" \
  34. +acc=rmb \
  35. +incdir+${UVM_HOME}/src+../sv \
  36. ${UVM_HOME}/src/uvm.sv \
  37. ubus_tb_top.sv \
  38. ${UVM_HOME}/src/dpi/uvm_dpi.cc \
  39. -R \
  40. +UVM_TESTNAME=test_2m_4s \
  41. -c \
  42. -do \"run -all; q\" \
  43. -l questa.log"
  44. eval ${QVERILOG}
  45. }
  46.  
  47. if { [string length $1] > 0 } {
  48. [$1]
  49. }

Расположение новых файлов:

Запуск:

  1. QuestaSim> cd E:/libs/uvm-1.2/examples/integrated/ubus/examples
  2. QuestaSim> do run_ubus.tcl all

Всю жизнь запускал tcl-скрипты командой source, но при подготовке материала выяснилось, что QuestaSim в этом случае не воспринимает передаваемые в строке параметры (в приведенной выше команде это название цели all).

Share this post