In DPI-C, How to map data type to reg or wire - system-verilog

I am writing a CRC16 function in C to use in System Verilog.
Requirement as below:
Output of CRC16 has 16 bits
Input of CRC16 has bigger than 72 bits
The difficulty is that I don't know whether DPI-C can support map data type with reg/wire in System Verilog to C or not ?
how many maximum length of reg/wire can support to use DPI-C.
Can anybody help me ?

Stay with compatible types across the language boundaries. For output use shortint For input, use an array of byte in SystemVerilog which maps to array of char in C.

Dpi support has provision for any bit width, converting packed arrays into c-arrays. The question is: what are you going to do with 72-bit data at c side?
But, svBitVecVal for two-state bits and svLogicVecVal for four-stat logics could be used at 'c' side to retrieve values. Look at H.7.6/7 of lrm for more info.
Here is an example from lrm H.10.2 for 4-state data (logic):
SystemVerilog:
typedef struct {int x; int y;} pair;
import "DPI-C" function void f1(input int i1, pair i2, output logic [63:0] o3);
C:
void f1(const int i1, const pair *i2, svLogicVecVal* o3)
{
int tab[8];
printf("%d\n", i1);
o3[0].aval = i2->x;
o3[0].bval = 0;
o3[1].aval = i2->y;
o3[1].b = 0;
...
}

Related

signed and unsigned fixed point multiplication in SystemVerilog

I have a specific question and a request for more general guidance.
My question is what is the cleanest way to multiply a signed number by an unsigned number in SystemVerilog?
Below is a little test code that illustrates the problem. 'a' is the unsigned number. 'b' is the signed number. In order to produce a correct signed result SystemVerilog seems to require that both operands of the multiplication be signed. To make that work here I had to add an extra '0' to the front of the unsigned number to make it a valid signed number. I'm thinking there must be a cleaner way.
More generally, I am just getting started doing fixed point math in SystemVerilog. In VHDL there is very concrete syntax and even a standard package to support signed and unsigned fixed point math, with rounding, etc. Is there something like that in the SystemVerilog world?
Thanks,
module testbench ();
localparam int Wa = 8;
localparam int Wb = 8;
logic [Wa-1:0] a; // unsigned
logic [Wa:0] a_signed; // signed word with extra bit to hold unsigned number.
logic [Wb-1:0] b; // signed
logic [Wa+Wb-1:0] c; // result
localparam clk_period = 10;
assign a_signed = {1'b0, a};
assign c = $signed(a_signed)*$signed(b);
initial begin
a = +5;
b = +10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +5;
b = -10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +255;
b = +10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
a = +255;
b = -10;
#(clk_period*1);
$display("Hex: a=%x,b=%x, c=%x; Dec: a=%d, b=%d, c=%d", a, b, c, a, $signed(b), $signed(c));
$stop;
end
endmodule
system verilog rules say
If any operand is unsigned, the result is unsigned, regardless of the operator
Propagate the type and size of the expression (or self-determined subexpression) back down to the context-determined operands of the expression
When propagation reaches a simple operand as defined in 11.5, then that operand shall be converted to the propagated type and size.
So, in other words, when you multily signed and unsigned numbers, the expression type will be determined as unsigned. This will be propagated back to operands and all signed will be treated as unsigned as well.
so, your result will be identical to the one of multiplying two unsigned numbers. So, the cleanest way, if you need signed result, is to convert all operands to signed number.
You will also need an extra bit in your operands to have a place for the sign bit. Otherwise 255 will be treated as -1 in 8-bit sign conversion.

Hash function for 8 / 16 bit "graphics" on 8 bit processor

For an implementation of coherent noise (similar to Perlin noise), I'm looking for a hash function suitable for graphics.
I don't need it to be in any way cryptographic, and really, I don't even need it to be a super brilliant hash.
I just want to to combine two 16 bit numbers and output an 8 bit hash. As random as possible is good, but also, fast on a AVR processor (8 bit, as used by Arduino) is good.
Currently I'm using an implementation here:
const uint32_t hash(uint32_t a)
{
a -= (a<<6);
a ^= (a>>17);
a -= (a<<9);
a ^= (a<<4);
a -= (a<<3);
a ^= (a<<10);
a ^= (a>>15);
return a;
}
But given that I'm truncating all but 8 bits, and I don't need anything spectacular, can I get away with something using fewer instructions?
… I'm inspired in this search by the lib8tion library that's packaged with FastLED. It has specific functions to, for example, multiple two uint8_t numbers to give a uint16_t number in the fewest possible clock cycles.
Check out Pearson hashing:
unsigned char hash(unsigned short a, unsigned short b) {
static const unsigned char t[256] = {...};
return t[t[t[t[a & 0xFF] ^ (b & 0xFF)] ^ (a >> 8)] ^ (b >> 8)];
}

Converting a 2D array into 3D array in systemverilog

I have an 2 D dynamic array as
logic [511:0] array[];
I wan to convert it into a 3 D dynamic array defined as
logic [32][16]M[];
eg.
array[0]= 1110110000111000...512 bits....
M[0][0]= 1110110000111000...32 bits....
M[0][1]= next 32 bits....
and so on.
Can some please suggest how to accomplish this task.Did I declare my 3D array properly.I know dynamic array can only be defined in unpacked array. Can I define array as
logic [31:0] M[16][]; ?
Any suggestion or correction would be helpful.
Based on the example you gave it seems as if you want a dynamic array of an unpacked array of 16 32-bit packed words. That would be:
logic [31:0] M[16][];
You can use a bit-stream cast to assign one type shape to another type shape as long as the number of bits in the source can be fit into an exact match number of bits into the target. You need a typedef identifier for the target type (and it's a good practice to use typedefs in general when declaring variables).
typedef [31:0] my_3d_t[16][];
my_3d_t M;
M = my_3d_t'(array);
That does the assignment as
M[0][0][31:0] = array[0][511:480];
M[0][1][31:0] = array[0][479:448];
...
M[0][15][31:0] = array[0][31:0];
M[1][0][31:0] = array[1][511:480];
...

D language unsigned hash of string

I am a complete beginner with the D language.
How to get, as an uint unsigned 32 bits integer in the D language, some hash of a string...
I need a quick and dirty hash code (I don't care much about the "randomness" or the "lack of collision", I care slightly more about performance).
import std.digest.crc;
uint string_hash(string s) {
return crc320f(s);
}
is not good...
(using gdc-5 on Linux/x86-64 with phobos-2)
While Adams answer does exactly what you're looking for, you can also use a union to do the casting.
This is a pretty useful trick so may as well put it here:
/**
* Returns a crc32Of hash of a string
* Uses a union to store the ubyte[]
* And then simply reads that memory as a uint
*/
uint string_hash(string s){
import std.digest.crc;
union hashUnion{
ubyte[4] hashArray;
uint hashNumber;
}
hashUnion x;
x.hashArray = crc32Of(s); // stores the result of crc32Of into the array.
return x.hashNumber; // reads the exact same memory as the hashArray
// but reads it as a uint.
}
A really quick thing could just be this:
uint string_hash(string s) {
import std.digest.crc;
auto r = crc32Of(s);
return *(cast(uint*) r.ptr);
}
Since crc32Of returns a ubyte[4] instead of the uint you want, a conversion is necessary, but since ubyte[4] and uint are the same thing to the machine, we can just do a reinterpret cast with the pointer trick seen there to convert types for free at runtime.

concatenation of arrays in system verilog

I wrote a code for concatenation as below:
module p2;
int n[1:2][1:3] = {2{{3{1}}}};
initial
begin
$display("val:%d",n[2][1]);
end
endmodule
It is showing errors.
Please explain?
Unpacked arrays require a '{} format. See IEEE Std 1800-2012 § 5.11 (or search for '{ in the LRM for many examples).
Therefore update your assignment to:
int n[1:2][1:3] = '{2{'{3{1}}}};
int n[1:2][1:3] = {2{{3{1}}}};
Just looking at {3{1}} this is a 96 bit number 3 integers concatenated together.
It is likely that {3{1'b1}} was intended.
The main issue looks to be the the left hand side is an unpacked array, and the left hand side is a packed array.
{ 2 { {3{1'b1}} } } => 6'b111_111
What is required is [[3'b111],[3'b111]],
From IEEE std 1800-2009 the array assignments section will be of interest here
10.9.1 Array assignment patterns
Concatenation braces are used to construct and deconstruct simple bit vectors.
A similar syntax is used to support the construction and deconstruction of arrays. The expressions shall match element for element, and the braces shall match the array dimensions. Each expression item shall be evaluated in the context of an
assignment to the type of the corresponding element in the array. In other words, the following examples are not required to cause size warnings:
bit unpackedbits [1:0] = '{1,1}; // no size warning required as
// bit can be set to 1
int unpackedints [1:0] = '{1'b1, 1'b1}; // no size warning required as
// int can be set to 1’b1
A syntax resembling replications (see 11.4.12.1) can be used in array assignment patterns as well. Each replication shall represent an entire single dimension.
unpackedbits = '{2 {y}} ; // same as '{y, y}
int n[1:2][1:3] = '{2{'{3{y}}}}; // same as '{'{y,y,y},'{y,y,y}}