среда, 12 октября 2011 г.

Install eclipse and systemverilog sveditor without root

SVeditor is a free opensource systemverilog editor plugin for eclipse.

I prefer to install eclipse manually, i.e without package managers.
The key reason is eclipse is being released more often than my operating system, Fedora, and fedora guys cease providing fresh packages for distribution in a year after release. Moreover, some servers and pc in our company use aged centos. So updating eclipse and its components from time to time without root password is crucial.
  1. Download tar-gz eclipse release for appropriate arch(i686 or x86_64) at http://www.eclipse.org/downloads). I prefer  'Eclipse IDE for C/C++ Developers' package.
  2. untar it. by itself eclipse is already available to be started (java-1.6.0-openjdk package must be installed).
  3. download sveditor plugin named something like sveditor-0.6.1.ea08.jar.
    All downloads are available at http://sourceforge.net/projects/sveditor/files/sveditor/

    I found it useful to subscribe for fresh releases with RSS feed. Just follow this url to receive notification about new releases http://sourceforge.net/api/file/index/project-id/230781/mtime/desc/limit/20/rss

    By the way, sveditor's author is quite responsive to bug reports. It's possible to fire a bug anonymously at http://sourceforge.net/tracker/?group_id=230781&atid=1081015
  4. if you can't set up eclipse to use proxy the actual plugin installation is a bit tricky. So go eclipse->help->install_new_software.
    Hit Add... button, in 'Location' field point full path to download 'sveditor...jar' file. 'Name' field may be left empty.
    After hitting Ok following dialog appears:
    check the needed boxes, next, next, accept sveditor license, next, restart.

    PS. After installing this and other plugins it's possible to set read-only access and share eclipse via NFS so colleagues could skip the installation part and just use it.

Using eclipse for functional verification projects

I use eclipse for following features:
  1. highligthning, autocomplition, open declaration for
    • make
    • asm, c/c++,(systemc, systemc_verification sources)
    • systemverilog (and ovm,uvm,vmm) (with sveditor plugin)
    • python(with plugin)
  2. integration cvs & svn
  3. my hotkeys:
    • Ctrl+shift+R - open resource(read file) while typing its name. When project becomes huge (it usually does), it becomes unbearable to remember filesystem paths of all files. navigate->'open resource' is where eclipse beats simple editors like KDE kate.
    • F3 - open declaration
    • Ctrl+space - autocompletion 
    • Ctrl+D - delete line (yes, no more home,shift+end,delete)
    • Alt+up/down  - move line up/down ( yes, no more home, shift+end,ctrl+x,up,up,up,ctrl+v)
    • Alt+Shift+up/down - duplicate line
    • Ctrl+pageup/down - move to next tab 
    • Alt+left/right - jump to last edited place

вторник, 13 сентября 2011 г.

Configurable pull-up, pull-down wires inside interface

During phy interface verification it mighty be handy to change pull-up (pull-down) resistors dynamically, i.e without recompiling verilog source codes and restarting simulation.

To implement this we need to assign second driver with weak strength to target wire. Depending on local variable this second driver will set logical 0 or 1.

Here is a workable systemverilog example of interface with configurable pull-ups and simple testbench with it.

// importing OVM here just for log messages
import ovm_pkg::*;

interface conf_pull_iface(
              inout wire clk,
              inout wire data);


    // using enumerations allows to view
    // enumeration names in waveform viewers instead of
    // integer values
    typedef enum {
        PULL_NONE=0,
        PULL_UP=1,
        PULL_DOWN=2
    } pull_mode_t;

    pull_mode_t pull_clk = PULL_NONE;
    pull_mode_t pull_data = PULL_NONE;

    logic clk_out;
    bit   clk_out_enable;

    logic data_out;
    bit   data_out_enable;

    assign clk = clk_out_enable ? clk_out: 'z;
    assign (pull1,pull0) clk = (pull_clk == PULL_UP) ?  1'b1:
                                ((pull_clk == PULL_DOWN) ? 1'b0: 'z);

    assign data = data_out_enable ? data_out : 'z;
    assign (pull1,pull0) data = (pull_data == PULL_UP) ?  1'b1:
                                 ((pull_data == PULL_DOWN) ? 1'b0: 'z);

    function void set_pull(int unsigned pull_clk_,
                           int unsigned pull_data_);

        assert(pull_clk_ <= PULL_DOWN);
        assert(pull_data_ <= PULL_DOWN);
        pull_clk = pull_mode_t'(pull_clk_);
        pull_data = pull_mode_t'(pull_data_);
        ovm_report_info("", $sformatf("%m: changed: pull_clk=%s, pull_data=%s",
                pull_clk.name(),
                pull_data.name()));
    endfunction

    function void set_enable(bit clk_enable,
                             bit data_enable);
        clk_out_enable = clk_enable;
        data_out_enable = data_enable;
        ovm_report_info("", $sformatf("%m: set enable: clk_enable=%s, data_enable=%s",
                clk_out_enable,
                data_out_enable));
    endfunction

endinterface


module tb;
    wire clk;
    wire data;

    conf_pull_iface iface(.*);

    initial begin
        #1ns iface.set_pull(1,2);
        #1ns iface.set_pull(2,1);
        #1ns iface.set_pull(0,0);
    end

endmodule
  

Using OVM-aware simulator we can run example:
$ mysimulator -ovm  configur_pull_ups.sv

Which would result in following log:
OVM_INFO @ 1: reporter [] tb.iface.set_pull: changed: pull_clk=PULL_UP, pull_data=PULL_DOWN
OVM_INFO @ 2: reporter [] tb.iface.set_pull: changed: pull_clk=PULL_DOWN, pull_data=PULL_UP
OVM_INFO @ 3: reporter [] tb.iface.set_pull: changed: pull_clk=PULL_NONE, pull_data=PULL_NONE


A couple of notes to mention:
1) we use enumerations to facilitate debugging, variables pull_clk and pull_data of enumeration type pull_mode_t will be shown in waveform viewer with appropriate string values (not plain int values). Moreover, we use pull_clk.name() function to print neat log messages.

2) we can't use enumerations in set_pull function, as this type can't be accessed outside of interface. So we add assertions to ensure passed int values are in enumeration range.

четверг, 8 сентября 2011 г.

Пример переопределения сервера ovm (uvm)

Переопределение/расширение сервера ошибок ovm может потребоваться в следующих случаях:
  1. перенаправление сообщений из ovm в собственную систему сбора сообщений.
  2. вызов callback при каком-либо условии: например, создать поток транзакций ошибок и все ошибки (фактически вызовы ovm_report_error ) выводить как на консоль так и в поток транзакций.
  3. переформатирование сообщений: например, изменение формата времени моделирования или, более полезное, печать сообщений ovm_report_error в консоль красным цветом
  4. переформатирование финального хвоста, т.е summary. Обычно по специально заточенной строке в summary инструменты регрессионного тестирования определяют успешность завершения теста (test passed, test failed).

Как известно, сервер сообщений в ovm реализован как синглтон (singleton) (синглтон на википедии). Использование синглтона необходимо для хранения единой базы о всех вызовах функций сообщений (т.е счётчиков сообщений и ошибок, словарь [id-сообщения]:счётчик и т.д).

Реализация единственного объекта ovm_report_server выполнена в классе ovm_report_global_server (исходник ovm_report_server.svh).
Обратим внимание на параметр переменной static и конструктор if (global_report_server == null) global_report_server = new;

Рассмотрим на примере как переопределить сервер сообщений в ovm: "разукрасим" все ошибки и фатальные_ошибки красным:
  1. Для этого создадим класс coloured_report_server наследующий от класса ovm_report_server и переопределим виртуальную функцию compose_message - для изменения форматирования сообщения (так же для переопределения доступны: summarize - при печати финального сообщения и process_report)
  2. создадим объект класса coloured_report_server и заменим ссылку на созданный объект в ovm_report_global_server.



import ovm_pkg::*;

`define BLACK(str)   {`"\033[30m`",str,`"\033[0m`"}
`define RED(str)     {`"\033[31m`",str,`"\033[0m`"}
`define GREEN(str)   {`"\033[32m`",str,`"\033[0m`"}
`define YELLOW(str)  {`"\033[33m`",str,`"\033[0m`"}
`define BLUE(str)    {`"\033[34m`",str,`"\033[0m`"}
`define MAGENTA(str) {`"\033[35m`",str,`"\033[0m`"}
`define CYAN(str)    {`"\033[36m`",str,`"\033[0m`"}
`define WHITE(str)   {`"\033[37m`",str,`"\033[0m`"}

`define BOLD(str)    {`"\033[1m`",str,`"\033[0m`"}

class coloured_report_server extends ovm_report_server;

    function string compose_message(
            ovm_severity severity,
            string name,
            string id,
            string message,
            string filename,
            int    line
      );
        string result;
        if ((severity==OVM_ERROR) || (severity==OVM_FATAL))
            result=super.compose_message(severity, `RED(name), `RED(id), `RED(message), filename, line);
        else
            result=super.compose_message(severity, name, id, message, filename, line);
        return result;
    endfunction
//you can overload virtual function void summarize(OVM_FILE file=0);
endclass

module coloured_server_test;
   initial begin
     coloured_report_server new_server;
     ovm_report_global_server glob;
     glob=new();
     new_server=new();
     glob.set_server(new_server);
   end

   initial begin:printing_block
     #1; //delay is needed for the first initial to finish
     ovm_report_info("info",$sformatf("info from: '%m'"));
     ovm_report_error("error-id", "printing in red"); 
     //ovm_run_test();
   end
endmodule


Для запуска примера необходимо скомпилировать пакет ovm и скормить моделировщику приведённый выше пример. Большинство современных систем моделирования имеют встроенную поддержку библиотеки ovm, поэтому подключение ovm может быть выполнено указанием ключа "использовать ovm":

 $mysimulator -useovm coloured_report_server.sv 

Результат моделирования выглядит следующим образом:

 OVM_INFO @ 1: reporter [info] info from: 'coloured_server_test.printing_block'
OVM_ERROR @ 1: reporter [error-id] printing in red



PS. несколько слов про форматирование цветом. Надо понимать, что разукраска есть вставление управляющих символов в поток сообщений. Это может влиять на результат грепанья лога моделирования. В данном случае при поиске строки
$ grep 'reporter \[info\]' simulation.log будет находиться первая строка, однако при поиске
$ grep 'reporter \[error-id\]' simulation.log 2-ая строка найдена не будет, т.к строка превратилась в [31mreporter [0m [ [31merror-id [0m] [31m