systemVeilog - pass array of unknown size - function

I have the following function:
function void foo_arr_bit (int seed, ref bit [*] mem, string mem_name);
for (int i=0; i< mem.size(); i++)
mem[i] = my_randomize_int(seed, mem[i], mem_name);
endfunction: foo_arr_bit
I call the function by:
foo_arr_bit(seed, data_bit, "data_bit");
Where data_bit can be:
bit [1:0]/ bit [2:0]/ bit [3:0]/ bit [4:0]/ bit [5:0] etc...
When I try to compile I got the following error:
near "[": syntax error, unexpected [ , expecting IDENTIFIER or TYPE_IDENTIFIER or NETTYPE_IDENTIFIER.

[*] is not the correct syntax for a dynamic array, use [].
Your array can only be dynamic in the unpacked dimension. So you cannot have bit [] mem_array, but must have bit mem_array[].
Finally a function using pass by reference cannot have a static lifetime. That is, it must be declared as automatic.
function automatic void foo_arr_bit (int seed, ref bit mem[], string mem_name);
for (int i=0; i< mem.size(); i++)
mem[i] = my_randomize_int(seed, mem[i], mem_name);
endfunction: foo_arr_bit
Edit: But even with these changes you face a bigger issue. Passing by reference demands very strict typing. There is no casting allowed so I expect there to be issues with type conversion.
Furthermore, passing by reference is not really necessary in your case. Use inout instead.
function automatic void foo_arr_bit (input int seed, string mem_name, inout bit mem[]);
for (int i=0; i< mem.size(); i++)
mem[i] = my_randomize_int(seed, mem[i], mem_name);
endfunction: foo_arr_bit

Related

Converting uint32_t to binary in C

The main problem I'm having is to read out values in binary in C. Python and C# had some really quick/easy functions to do this, I found topic about how to do it in C++, I found topic about how to convert int to binary in C, but not how to convert uint32_t to binary in C.
What I am trying to do is to read bit by bit the 32 bits of the DR_REG_RNG_BASE address of an ESP32 (this is the address where the random values of the Random Hardware Generator of the ESP are stored).
So for the moment I was doing that:
#define DR_REG_RNG_BASE 0x3ff75144
void printBitByBit( ){
// READ_PERI_REG is the ESP32 function to read DR_REG_RNG_BASE
uint32_t rndval = READ_PERI_REG(DR_REG_RNG_BASE);
int i;
for (i = 1; i <= 32; i++){
int mask = 1 << i;
int masked_n = rndval & mask;
int thebit = masked_n >> i;
Serial.printf("%i", thebit);
}
Serial.println("\n");
}
At first I thought it was working well. But in fact it takes me out of binary representations that are totally false. Any ideas?
Your shown code has a number of errors/issues.
First, bit positions for a uint32_t (32-bit unsigned integer) are zero-based – so, they run from 0 thru 31, not from 1 thru 32, as your code assumes. Thus, in your code, you are (effectively) ignoring the lowest bit (bit #0); further, when you do the 1 << i on the last loop (when i == 32), your mask will (most likely) have a value of zero (although that shift is, technically, undefined behaviour for a signed integer, as your code uses), so you'll also drop the highest bit.
Second, your code prints (from left-to-right) the lowest bit first, but you want (presumably) to print the highest bit first, as is normal. So, you should run the loop with the i index starting at 31 and decrement it to zero.
Also, your code mixes and mingles unsigned and signed integer types. This sort of thing is best avoided – so it's better to use uint32_t for the intermediate values used in the loop.
Lastly (as mentioned by Eric in the comments), there is a far simpler way to extract "bit n" from an unsigned integer: just use value >> n & 1.
I don't have access to an Arduino platform but, to demonstrate the points made in the above discussion, here is a standard, console-mode C++ program that compares the output of your code to versions with the aforementioned corrections applied:
#include <iostream>
#include <cstdint>
#include <inttypes.h>
int main()
{
uint32_t test = 0x84FF0048uL;
int i;
// Your code ...
for (i = 1; i <= 32; i++) {
int mask = 1 << i;
int masked_n = test & mask;
int thebit = masked_n >> i;
printf("%i", thebit);
}
printf("\n");
// Corrected limits/order/types ...
for (i = 31; i >= 0; --i) {
uint32_t mask = (uint32_t)(1) << i;
uint32_t masked_n = test & mask;
uint32_t thebit = masked_n >> i;
printf("%"PRIu32, thebit);
}
printf("\n");
// Better ...
for (i = 31; i >= 0; --i) {
printf("%"PRIu32, test >> i & 1);
}
printf("\n");
return 0;
}
The three lines of output (first one wrong, as you know; last two correct) are:
001001000000000111111110010000-10
10000100111111110000000001001000
10000100111111110000000001001000
Notes:
(1) On the use of the funny-looking "%"PRu32 format specifier for printing the uint32_t types, see: printf format specifiers for uint32_t and size_t.
(2) The cast on the (uint32_t)(1) constant will ensure that the bit-shift is safe, even when int and unsigned are 16-bit types; without that, you would get undefined behaviour in such a case.
When you printing out a binary string representation of a number, you print the Most Signification Bit (MSB) first, whether the number is a uint32_t or uint16_t, so you will need to have a mask for detecting whether the MSB is a 1 or 0, so you need a mask of 0x80000000, and shift-down on each iteration.
#define DR_REG_RNG_BASE 0x3ff75144
void printBitByBit( ){
// READ_PERI_REG is the ESP32 function to read DR_REG_RNG_BASE
uint32_t rndval = READ_PERI_REG(DR_REG_RNG_BASE);
Serial.println(rndval, HEX); //print out the value in hex for verification purpose
uint32_t mask = 0x80000000;
for (int i=1; i<32; i++) {
Serial.println((rndval & mask) ? "1" : "0");
mask = (uint32_t) mask >> 1;
}
Serial.println("\n");
}
For Arduino, there are actually a couple of built-in functions that can print out the binary string representation of a number. Serial.print(x, BIN) allows you to specify the number base on the 2nd function argument.
Another function that can achieve the same result is itoa(x, str, base) which is not part of standard ANSI C or C++, but available in Arduino to allow you to convert the number x to a str with number base specified.
char str[33];
itoa(rndval, str, 2);
Serial.println(str);
However, both functions does not pad with leading zero, see the result here:
36E68B6D // rndval in HEX
00110110111001101000101101101101 // print by our function
110110111001101000101101101101 // print by Serial.print(rndval, BIN)
110110111001101000101101101101 // print by itoa(rndval, str, 2)
BTW, Arduino is c++, so don't use c tag for your post. I changed it for you.

Using I2C_master library AVR

I am using I2C_master library for AVR, Communication works fine, but I have little problem, how can I get data.
I am using this function
uint16_t i2c_2byte_readReg(uint8_t devaddr, uint16_t regaddr, uint8_t* data, uint16_t length){
devaddr += 1;
if (i2c_start(devaddr<<1|0)) return 1;
i2c_write(regaddr >> 8);
i2c_write(regaddr & 0xFF);
if (i2c_start(devaddr<<1| 1)) return 1;
for (uint16_t i = 0; i < (length-1); i++)
{
data[i] = i2c_read_ack();
}
data[(length-1)] = i2c_read_nack();
i2c_stop();
return 0;}
And now I need to use received data, and send it by UART to PC
uint8_t* DevId;
i2c_2byte_readReg(address,REVISION_CODE_DEVID,DevId,2);
deviceH=*DevId++;
deviceL=*DevId;
UART_send(deviceH);
UART_send(deviceL);
I think that I am lost with pointers. Could you help me, how can I get received data for future use? (UART works fine for me in this case, but it sends only 0x00 with this code)
The function i2c_2byte_readReg takes as a third argument a pointer to the buffer where the data will be written. Note that it must have size bigger than the forth argument called length. Your DevId pointer doesn't point to any buffer so when calling the function you've got an access violation.
To get the data you should define an array before calling the function:
const size_t size = 8;
uint8_t data[size];
Then you can call the function passing the address of the buffer as an argument (the name of the array is converted into its address):
const uin16_t length = 2;
i2c_2byte_readReg(address, REVISION_CODE_DEVID, data, length);
Assuming that the function works well those two bytes will be saved into data buffer. Remember that size must be bigger or equal to length argument.
Then you can send the data over UART:
UART_send(data[0]);
UART_send(data[1]);

CUDA: Copy 1D array from GPU to 2D array on host

int main() {
char** hMat,* dArr;
hMat = new char*[10];
for (int i=0;i<10;i++) {
hMat[i] = new char[10];
}
cudaMalloc((void**)&dArr,100);
// Copy from dArr to hMat here:
}
I have an array, dArr on the GPU, and I want to copy it into a 2D array hMat on the host, where the first 10 fields in the GPU array are copied to the first row in the host matrix, and the next 10 fields are copied to the second row, and so on.
There are some functions in the documentation, namely CudaMemcpy2D and CudaMemcpy2DFromArray, but I'm not quite sure how they should be used.
Your allocation scheme (an array of pointers, separately allocated) has the potential to create a discontiguous allocation on the host. There are no cudaMemcpy operations of any type (including the ones you mention) that can target an arbitrarily discontiguous area, which your allocation scheme has the potential to create.
In a nutshell, then, your approach is troublesome. It can be made to work, but will require a loop to perform the copying -- essentially one cudaMemcpy operation per "row" of your "2D array". If you choose to do that, presumably you don't need help. It's quite straightforward.
What I will suggest is that you instead modify your host allocation to create an underlying contiguous allocation. Such a region can be handled by a single, ordinary cudaMemcpy call, but you can still treat it as a "2D array" in host code.
The basic idea is to create a single allocation of the correct overall size, then to create a set of pointers to specific places within the single allocation, where each "row" should start. You then reference into this pointer array using your initial double-pointer.
Something like this:
#include <stdio.h>
typedef char mytype;
int main(){
const int rows = 10;
const int cols = 10;
mytype **hMat = new mytype*[rows];
hMat[0] = new mytype[rows*cols];
for (int i = 1; i < rows; i++) hMat[i] = hMat[i-1]+cols;
//initialize "2D array"
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
hMat[i][j] = 0;
mytype *dArr;
cudaMalloc(&dArr, rows*cols*sizeof(mytype));
//copy to device
cudaMemcpy(dArr, hMat[0], rows*cols*sizeof(mytype), cudaMemcpyHostToDevice);
//kernel call
//copy from device
cudaMemcpy(hMat[0], dArr, rows*cols*sizeof(mytype), cudaMemcpyDeviceToHost);
return 0;
}

Allocating using malloc inside a function passing the address of the pointer and using vector syntax?

What's wrong on the code below? I need to send the address of the pointer *A to the function, read some numbers with scanf inside it, return to main and print the numbers read at that function.
void create_number_vector(int **number)
{
(*number) = (int*)malloc(5*sizeof(int));
int i;
for(i=0; i<5; i++){
scanf("%d",number[i]);
}
}
int main(void){
int i, *A;
create_number_vector(&A);
for(i=0; i<5; i++){
printf("%d",A[i]);
}
return 0;
}
Except one line(concept), everything is pretty much OK.
Problamatic line is:
scanf("%d",number[i]);
And should be replace with:
scanf("%d", *number+i);
Because our allocated variable is a pointer, we should use him like that, we should go to the 'i' address inside of the allocated variable and scan into him.
Ofcourse you can keep on using the "array" style usage, with this syntax:
scanf("%d", &(*number)[i]);
P.S
Don't forget to free the allocated resources at the end of the usage, altough this kind of small program that exits at the end of the echoing, it's still a good practice to always free your resources at the end of its usage.

Problem with constructor - initialization list (c++)

it's a weird problem that I have
I have a very simple constructor that's creates a matrix with no values:
RegMatrix::RegMatrix(const int numRow, const int numCol):
_numRow(numRow),_numCol(numCol),_matrix()
{
}
_matrix is a vector that holds 'Comlex', an object I've created
and VAL(i,j) is #define VAL(i,j) ((i * _numCol) + j)
Now, I call this constructor in function transpose:
RegMatrix RegMatrix::transpose()
{
RegMatrix newMatrix(_numCol,_numRow);
cout << "DIMENSIONS " << newMatrix._numRow << " " << newMatrix._numCol << endl;
for(int j=0; j<_numCol; j++)
{
for(int i=0; i<_numRow; i++)
{
newMatrix._matrix[VAL(i,j)] = _matrix[VAL(j,i)]; //<--SEGMENTATION FAULT
}
}
return newMatrix;
}
And here's my problem: I get a segmentation fault the very first time I enter the second loop. When I use the eclipse debugger I see that _nunRow and _numCol values of newMatrix seem to be garbage (one is '0' the other is -10000000 or something like that). What's even more weird is that I added the output line just to be sure and it gave me the right numbers!
So, any ideas as to what can be my problem?
Thanks!
You are indexing into an empty vector, which is doomed to fail. Use at instead of the subscript operator and you will get an exception.
My guess (based on what you show) is that there may be some problems with how you implement the copy constructor.