Use the output of a module inside a class (including task (generator)

In reply to chr_sue:

Hi dave, chr_sue

i think there is a misundrstood, ModelSIM does not found sin, cos, log, or any mathematical function i had used in my code, the uvm-1.1b\win32\uvm_dpi.dll exist and not empty but the math function i’m using is not integrated in the DLL.

i had used the following command to import “sin” generation function into my code:

import “DPI-C” pure function real sin(input real rTheta);

i had downloaded uvm_1.2,

i think i need to compile the $UVM_HOME/src/dpi/uvm_dpi.cc, i will try this(try to adapt this to ModelSim10.1c) and hope this work:

For Windows (win32):

cd $UVM_HOME/examples
setenv MTI_HOME /u/release/10.0a/questasim/
make -f Makefile.questa dpi_libWin

mkdir -p …/lib
c:/QuestaSim_10.0a/gcc-4.2.1-mingw32vc9/bin/g++.exe
-g -DQUESTA -W -shared
-Bsymbolic -Ic:/QuestaSim_10.0a/include
…/src/dpi/uvm_dpi.cc -o
…/lib/uvm_dpi.dll
c:/QuestaSim_10.0a/win32/mtipli.dll -lregex

i may need gcc, but i do not know the exact command to do this

Regards,

In reply to saketa:

The DPI does not provide any mathematical function. DPI stands for ‘Direct Programming Interface’.
It helps you that you can call C/C++ subroutines in your SV code. You have to integraate the corresponding C-libraries containing these functions into your SV-code.

In reply to chr_sue:

i’m OK with you, sin cos log are a standard libraries, where to find them? (i think they are implemented within Visual studio?!) what are the subroutines you are talking about?

In reply to saketa:

All DPI routines you import must be linked into a shared object (Windows: *.dll, Linux: *.so). The message about not finding it in the uvm_dpi.dll isbecause that was the only shared object provided. Math library functions like sin,cos, log need to be compiled into another shared object and loaded into the simulator. See this link for an example. The actual commands needed to compile this are tool/platform specific, and you will need to read the user manual of your tool, or contact your tool vendor directly for support.

In reply to dave_59:

Dave: Here it is the whole code:

import uvm_pkg::*;
import math_pkg::*;
`include "uvm_macros.svh"
//----------------
// environment env
//----------------



class env extends uvm_env;

  virtual SDM_if m_if;
  virtual sine_if si_if;
  
  function new(string name, uvm_component parent = null);
    super.new(name, parent);
  endfunction
  
  function void connect_phase(uvm_phase phase);
    `uvm_info("LABEL", "Started connect phase.", UVM_HIGH);
    // Get the interface from the resource database.
    assert(uvm_resource_db#(virtual SDM_if)::read_by_name(
      get_full_name(), "SDM_if", m_if));
   `uvm_info("LABEL", "Finished connect phase.", UVM_HIGH);
  
   // assert(uvm_config_db #(virtual SDM_if)::set(this, "*", "m_if", m_if));
   //`uvm_info("LABEL", "Finished connect phase.", UVM_HIGH);
   
   assert(uvm_resource_db#(virtual sine_if)::read_by_name(
    get_full_name(), "sine_if", si_if));
   
    //assert(uvm_config_db #(virtual sine_if)::set(this, "*", "si_if", si_if));
    `uvm_info("LABEL", "Finished connect phase.", UVM_HIGH);
  endfunction: connect_phase

  task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    `uvm_info("LABEL", "Started run phase.", UVM_HIGH);
    
    begin
    
      int reset_n = 0;
      @(m_if.cb);
      m_if.cb.Ain <= si_if.sine_out;
//      m_if.cb.reset_n <= reset_n;
      repeat(2) @(m_if.cb);
      
    end
    `uvm_info("LABEL", "Finished run phase.", UVM_HIGH);
    phase.drop_objection(this);
  endtask: run_phase
   
  
endclass

//-----------
// module top
//-----------
module top;

  bit clk_1mhz;
  real sine_out;
  SDM_if SDM_if1();
  sine_if sine_if1();
  
  env environment;
  
  sdm_rnm dut(SDM_if1);
  sv_ams_sin_voltage_gen sin_voltage_gen(sine_if1);

  initial begin
    environment = new("env");
    // Put the interface into the resource database.
    uvm_resource_db#(virtual SDM_if)::set("env",
    "SDM_if", dut.SDM_if1);
    uvm_resource_db#(virtual sine_if)::set("env",
     "sine_if", sin_voltage_gen.sine_if1);
      
    clk_1mhz = 0;
    run_test();
  end
  
  initial begin
    forever begin
      #(50) clk_1mhz = ~clk_1mhz;
    end
  end
  
  initial begin
    // Dump waves
    $dumpvars(0, top);
  end
  
endmodule
// SDM2 module
module sdm_rnm (SDM_if SDM_if2 );

parameter real clk_vth=0.9;
parameter alpha = 0.5;
parameter beta  = 0.5;


real int1_out;   /// variable-- not connection with the outside world
real int2_out;
real dac_out;
real mix1_out;
real mix2_out;
real t_int1_out;
real t_int2_out;
real sdm_out;


initial begin


   int1_out = 0.0 ;
   int2_out = 0.0 ;
   dac_out  = 0.0 ;
   mix1_out = 0.0 ;
   mix2_out = 0.0 ;
   sdm_out  = 0 ;
   t_int2_out  = 0 ;
   t_int1_out  = 0 ;
 end

 always @(negedge(SDM_if2.clk_1mhz))
 begin
  mix2_out   = int1_out - dac_out ;
  int2_out = t_int2_out + beta*mix2_out ;
  t_int2_out = int2_out ;
  mix1_out   = SDM_if2.Ain    - dac_out ;
  int1_out = t_int1_out + alpha*mix1_out ;
  t_int1_out = int1_out ;

    if (int2_out >= 0.0) begin 
     sdm_out = 1.8 ;   // ADC-- comparator
   end
    else if (int2_out <= 0.0)  
    begin  sdm_out = 0 ;
    end 

  if (sdm_out == 0) begin     dac_out = 0.5 ;
  end
  else                 dac_out =  1.3 ;
 SDM_if2.Dout = sdm_out ;
end
endmodule


//---------------------------------------
// Interface for the DUT
//---------------------------------------
interface SDM_if(input bit clk_1mhz, input real Ain, output bit Dout);

  clocking cb @(negedge clk_1mhz);
    output    Ain;
    input     Dout;
  endclocking // cb

endinterface: SDM_if

//---------------
// Interface bind
//---------------
//bind sdm_rnm SDM_if SDM_if_if0(
//  .clk_1mhz(clk_1mhz),
 // .Ain(Ain),
 // .Dout(Dout),
 // .reset_n(reset_n)
//);

//bind sv_ams_sin_voltage_gen sine_if sine_if_if0(
 // .clk_1mhz(clk_1mhz),
//  .sine_out(sine_out)
//);

module sv_ams_sin_voltage_gen(sine_if sine_if2);
parameter sampling_time = 5;
const real pi = 3.1416;
real time_us, time_s ;
bit sampling_clock;
real freq = 20;
real offset = 2.5;
real ampl = 2.5;
always sampling_clock = #(sampling_time) ~sampling_clock;
always @(sampling_clock) begin
time_us = $time/1000;
time_s = time_us/1000000;
end
assign sine_if2.sine_out = offset + (ampl * sin(2*pi*freq*time_s));
endmodule

interface sine_if(input bit clk_1mhz, output real sine_out);

  clocking cb @(posedge clk_1mhz);
    
    input sine_out;
    

endclocking
endinterface: sine_if

This code does not elaborate (when lanching simulation): Error: (vopt-7052) D:/sigma_delta_SV/FirstSDM.sv(75): Failed to find ‘SDM_if1’ in hierarchical name ‘/dut/SDM_if1’

** Error: (vopt-7052) D:/sigma_delta_SV/FirstSDM.sv(77): Failed to find ‘sine_if1’ in hierarchical name ‘/sin_voltage_gen/sine_if1’.

but when delating

environment = new("env");
    // Put the interface into the resource database.
    uvm_resource_db#(virtual SDM_if)::set("env",
    "SDM_if", dut.SDM_if1);
    uvm_resource_db#(virtual sine_if)::set("env",
     "sine_if", sin_voltage_gen.sine_if1);

it elaborate and begin simulation, and there where the sin library is not found

Any help from your side will be appreciated

In reply to saketa:

Please look to the initial block of the module top:
initial begin
environment = new(“env”);
// Put the interface into the resource database.
uvm_resource_db#(virtual SDM_if)::set(“env”, “SDM_if”, dut.SDM_if1);
uvm_resource_db#(virtual sine_if)::set(“env”, “sine_if”, sin_voltage_gen.sine_if1);

clk_1mhz = 0;
run_test();

end
The values of the interfaces are wrong. They should be
SDM_if1 instead of dut.SDM_if1
sine_if1 instead of sin_voltage_gen.sine_if1

In reply to chr_sue:

thank you chr_sue now it work, and i had replaced the C sin function by a SV sin approximation function

but a fatal error has occured:

** Fatal: vl_unpack_regbit: Cannot handle type.
# Time: 1 ns Iteration: 0 Process: /top/sine_if1/cb File: D:/sigma_delta_SV/FirstSDM.sv
# Fatal error at an unknown location

In reply to saketa:

The type vl_unpack_regbit is not a SV standard type. It looks like type which is a reference C type.

In reply to chr_sue:

Hi all again,

I’m trying to use DPI-C to import sin function, but it doesn’t work, as a workround i had used a sin approximative function which finally give a static value of 2.5 (the offset value) i think that the instanciation of the sin in the code does not work, and i did not know why, any help would be appreciable:

package math_pkg;
  //import dpi task      C Name = SV function name
 //import "DPI-C" pure function real sin (input real rTheta);
 `define PI 3.14159265
 
  function real sin;
 
     input x;
 
     real x;
 
     real x1,y,y2,y3,y5,y7,sum,sign;
 
     begin
 
         sign = 1.0;
 
         x1 = x;
 
         if (x1<0)
 
           begin
 
               x1 = -x1;
 
               sign = -1.0;
 
           end
 
         while (x1 > `PI/2.0)        
 
           begin
 
               x1 = x1 - `PI;
 
               sign = -1.0*sign;
 
           end  
 
         y = x1*2/`PI;
 
         y2 = y*y;
 
         y3 = y*y2;
 
         y5 = y3*y2;
 
         y7 = y5*y2;
 
         sum = 1.570794*y - 0.645962*y3 +
 
               0.079692*y5 - 0.004681712*y7;
 
         sin = sign*sum;
 
     end
 
  endfunction // sin
 
 
endpackage : math_pkg
 
module sv_ams_sin_voltage_gen(output real sine_out);
import math_pkg::*;
parameter sampling_time = 5;
const real pi = 3.1416;
real time_us, time_s ;
bit sampling_clock;
real freq = 20;
real offset = 2.5;
real ampl = 2.5;
always sampling_clock = #(sampling_time) ~sampling_clock;
always @(sampling_clock) begin
time_us = $time/1000;
time_s = time_us/1000000;
end
assign sine_out = offset + (ampl * sin(2*pi*freq));
endmodule

In reply to saketa:

I did not calculate all the details, but I got
sine_out = 2.500735
with your code and the same value with using the C-library subroutine sin form the math-package.
This value is definitely not only the offset.

BTW this is the code I using the sin c-lib:
module sv_ams_sin_voltage_gen(output real sine_out);
parameter sampling_time = 5;
const real pi = 3.1416;
real time_us, time_s ;
bit sampling_clock;
real freq = 20;
real offset = 2.5;
real ampl = 2.5;

import “DPI-C” pure function real sin(real);

always sampling_clock = #(sampling_time) ~sampling_clock;

always @(sampling_clock) begin
time_us = $time/1000;
time_s = time_us/1000000;
end

assign sine_out = offset + (ampl * sin(2pifreq));
initial
$display(“sine_out = %0f”, offset + (ampl * sin(2pifreq)));

endmodule

In reply to chr_sue:

Hi sue, have you any solution, because i’m stuck

In reply to saketa:

Above you have the solution (for Linux). But this requires yyou have the ‘math’ C-lib installed.
You can check this looking for ‘math.h’ in /usr/include or /usr/local/include.

I include here the same code which calculates a few values using your formula. Copy and paste the code to a file and you can run it directly.

module sv_ams_sin_voltage_gen(output real sine_out);
  parameter sampling_time = 5;
  const real pi = 3.1416;
  real time_us, time_s ;
  bit sampling_clock;
  real freq = 20;
  real offset = 2.5;
  real ampl = 2.5;
  real sin_int;
  int count = 0;

  import "DPI-C" pure function real sin(real);

  always sampling_clock = #(sampling_time) ~sampling_clock;

  always @(sampling_clock) begin
    time_us = $time/1000;
    time_s = time_us/1000000;
   end

  assign sine_out = sin_int;

  always @(posedge sampling_clock) begin
    while (count < 5) begin
      freq = freq/2;
      sin_int = offset + (ampl * sin(2*pi*freq));
      $display("freq = %0f, sine_out = %0f", freq, sin_int);
      count++;
    end  
    $stop;
  end

endmodule

In reply to chr_sue:

Many thanks sue,

it woks only on linux ? what for windows?

In reply to saketa:

It works also for Windows, but I’m not so familiar with C in Windows. I cannot guide you where to look for if the math-lib is available there.

In reply to chr_sue:

it does not work for windows, Chr_sue: what simulator and C compiler are you using? ?

In reply to saketa:

I guess this is not a question of the compiler, because I’m compiling the stuff with the vlog command from Questa
You could try to download and install cygwin. This could help you to have the math package available.

In reply to chr_sue:

i had downloaded cygwin but it does not work

In reply to saketa:

What is the error message you are getting. If you are working on Windows there is no standard place for C code to look for. You have to advice the Questa-Compiler where to look for.

In reply to saketa:

OK, I vahe a solution for compiling under Windows/cygwin. If you are putting a wrapper around the C-lib function it works. The C-wrapper code is here:

  1. dpi_sin.c:
    # include “math.h”
    double dpi_sin(double val) {
    return sin(val);
    }

Your SV should look like this. Consider import “DPI-C” …
2. sine.sv:

module sv_ams_sin_voltage_gen(output real sine_out);
import “DPI-C” dpi_sin = function real sin(input real x);

parameter sampling_time = 5;
const real pi = 3.1416;
real time_us, time_s ;
bit sampling_clock;
real freq = 20;
real offset = 2.5;
real ampl = 2.5;
real sin_int;
int count = 0;

always sampling_clock = #(sampling_time) ~sampling_clock;

always @(sampling_clock) begin
time_us = $time/1000;
time_s = time_us/1000000;
end

assign sine_out = sin_int;

always @(posedge sampling_clock) begin
while (count < 5) begin
freq = freq/2;
sin_int = offset + (ampl * sin(2pifreq));
$display(“freq = %0f, sine_out = %0f”, freq, sin_int);
count++;
end
$stop;
end

endmodule

  1. compile from the cygwin command line
    vlog sine1.sv sin.c -dpiheader sin.h

4 Start the Questa from the cygwin command line:
vsim -c sv_ams_sin_voltage_gen

Note Questa in Gui mode might not run, thus use "vsim -c … "

In reply to chr_sue:

Many thanks Chr_su

i’m little bite confused, can you explaine where a re sine1.sv sin.c