How to pass function argument by reference in Circom? - circuit

How to pass function argument by reference in the circom circuit language?
I'm trying to do the following:
pragma circom 2.0.0;
function increment(foo) {
foo++;
}
template MyTemplate() {
signal input a;
signal output b;
var foo;
foo = 0;
increment(foo);
log(foo);
// ...
}
component main = MyTemplate();
I expect log(pos) to output 1, but I'm getting 0. Is there a certain way I need to pass pos into increment so that it can modify the variable by reference?

I decided to use the C preprocessor to generate circom code, so now I have:
main.circom:
cpp -P maintpl.circom > main.circom
in my Makefile
and
#define increment(foo) foo++
in my circom code.

Related

How do I generate parameters dependent onf previous parameters in systemverilog

I recently switched from VHDL to SystemVerilog and I am converting some of my codes. I want to generate an array of local parameters based on 3 parameters SZ,L,max.
module test #(
parameter int SZ = 1024,
parameter int L = 35,
parameter int MAX = 4
)()
//...
localparam int n[MAX:0] = ;//...
for(genvar i = 0; i < max; i++) begin: gg
//n[i] and n[i+1] will be used here
//There is a second generate loop here that uses n[i+1] and therefore n[i+1] has to be parameter.
end
I tried using a function to generate localparams but I get an error that element assignment in function is not constant. I never had this issue in VHDL.
The only other option I can think of is to create the params inside the for generate but how would I reference the initial value? Is there any other solution?
The simulator I am using is Verilator but I also want the design to work in Xilinx Vivado.
Edit: I do not want to generate the parameters from an external script because I lose the ability to use Vivado's ability to run multiple synthesis/implementation in the same project with different parameters. That was what I used to do in VHDL.
You can use a function to initialize a parameter, you just have to have the output of the entire array as the result of the function. To do that, you need a typedef
typedef int array_type[MAX:0];
function array_type f();
f[0]=SZ;
for(int i=0;i<MAX;i++)
f[i+1]=f[i]-((2*i)+1)*L)/2;
endfunction
localparam array_type n = f();
I got it working by using packed array of 32-bits. Verilator doesn't support unpacked int with constants. Packed int is also not supported so I had to change the type to pack of 32-bits.
typedef [MAX:0][31:0] array_type;
function array_type f();
f[0]=SZ;
for(int i=0;i<MAX;i++)
f[i+1]=f[i]-((2*i)+1)*L)/2;
endfunction
localparam array_type n = f();

Generating XPtr from Rcpp function

I am writing an R package in which one of the functions takes Rcpp::XPtr as an input (as a SEXP). However, the creation of XPtr from Rcpp::Function is something I want to do inside the package (i.e., the user should be able to input Function).
e.g, my package takes input generated as follows, which requires the user to write an additional function (here putFunPtrInXPtr()) and run the function in R to generate the XPtr (here my_ptr).
#include <Rcpp.h>
using namespace Rcpp;
typedef NumericVector (*funcPtr) (NumericVector y);
// [[Rcpp::export]]
NumericVector timesTwo(NumericVector x) {
return x * 2;
}
// [[Rcpp::export]]
XPtr<funcPtr> putFunPtrInXPtr() {
XPtr<funcPtr> testptr(new funcPtr(&timesTwo), false);
return testptr;
}
/*** R
my_xptr <- putFunPtrInXPtr()
*/
How can I write something in which the user provides Function user_fun and I create the XPtr?
I tried
XPtr<funcPtr> package_fun(Function user_fun_input){
XPtr<funcPtr> testptr(new funcPtr(&user_fun_input), false);
}
user_fun_input is the parameter name inside the package function, but I am getting the following error
cannot initialize a new value of type 'funcPtr' (aka 'Vector<14> (*) (Vector<14>') with an rvalue of type 'Rcpp::Function *' (aka 'Function_Impl<PreserveStorage> *')
Also, there is an R step involved in creating the pointer, I am not sure how to implement that in the package (my .cpp file).
I think the creation of XPtr from Function could be confusing to the user, so better to just take Function as input and create the pointer to it, inside the package. I do use the XPtr in my package to gain speed.
Suggestions are most appreciated!

the whole codding is correct but getting garbage value

The compiler is displaying garbage value when coded as follows:
#include<iostream>
using namespace std;
void summation(int value1,int value2, int sum)
{
sum = value1+value2;
}
int main()
{
int a,b,sum;
cout<<"enter first no.\n";
cin>>a ;
cout<<"enter the second no.";
cin>>b ;
summation(a,b,sum);
cout<<"the addition of two no. is :" <<sum ;
return 0;
}
Obtaining correct input on writing &sum instead of sum. Why is it so?
You are passing sum to the summation() method by value and you want to pass it by reference. Try defining your method like this:
void summation(int value1,int value2, int& sum)
{
sum = value1+value2;
}
When you pass a parameter by its value (like you did), the method creates a copy of the value of the parameter and works with the copy. In the result, the passed parameter (sum) outside of the method stays unchanged. When you pass a parameter by its reference ( int& sum ), the sum variable inside your method will be the same as the sum variable in your main method and you can make changes to it.

Can the indivdual variables of a SystemVerilog struct be incremented with ++?

I have defined a structure with three integers, then created a dynamic array of the structure. Later in the code, I want to increment some of the integer values in the structure:
typedef struct {
integer tc;
integer pass;
integer fail;
} score_t;
score_t scorecard[];
integer tc_count;
initial
....
scorecard = new[`MAX_TC];
....
scorecard[tc_count].fail = 0;
....
scorecard[tc_count].fail++;
However, when I compile in Aldec Active-HDL I get the following error:
Error: VCP2615 ../../../m3_test_load_tb.sv : (283, 33):
scorecard[tc_count].fail is not l-value.
Is this a limitation of the language? I can assign to a temporary variable to do the increment operation and then put the value back in the struct, but that seems clumsy.
The code compiles with modelsim 10.1d. I have tested it on EDA Playground.
Seems the Aldec tool does not like the line:
scorecard[tc_count].fail++;
As a workaround you can replace the line with:
scorecard[tc_count].fail += 1;
Now it compiles with Aldec tool as well. http://www.edaplayground.com/x/VpV

Get system time in VCS

Is there way to get system time in VCS/UVM ? I am looking for something similar to Perl's localtime(time). Is there way to print system time for every uvm_info printed ?
One way is to use $system() to run any system command, including system' date command.
initial
begin
$system("date");
end
From IEEE 1800 LRM:
$system makes a call to the C function system(). The C function
executes the argument passed to it as if the argument was executed
from the terminal. $system can be called as either a task or a
function. When called as a function, it returns the return value of
the call to system() with data type int. If $system is called with no
string argument, the C function system() will be called with the NULL
string.
Also, see here.
Depends on the version of VCS you are using. The latest version should support $system as defined in IEEE Std 1800-2012 § 20.18.1. Assuming you are running in a UNIX based environment you can do:
function string get_localtime();
int fd;
string localtime;
void'($system("data > localtime")); // temp file
fd = $fopen("localtime", "r");
void'($fscanf(fd,"%s",localtime));
$fclose(fd);
void'($system("rm localtime")); // delete file
return localtime;
endfunction
If your version VCS doesn't support $system or if your more conformable with C/C++, then use DPI (see IEEE Std 1800-2012 § 35). Create a function in C and compile it in VCS with your SystemVerilog files. In the SystemVerilog, add the import to allow access to your C function. Assuming your method name is my_localtime and and return time is a string, the import should look like:
import "DPI" function string my_localtime();
In c file wallclock.c :
#include <time.h>
wallclock() {
time_t t;
t = time(NULL);
return (ctime(&t));
//return time(NULL);
}
In SV file :
import "DPI-C" function string wallclock();
module try;
//int unsigned t;
string t;
initial begin
t = wallclock();
$write("time=%0s\n", t);
end
endmodule

Resources