Randomization of a parameterized class inside a class not working - system-verilog

I am trying to use a parameterized class inside another class which I have to randomize.
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class parameterized_class #( type enum_type);
static int initial_allocation;
static enum_type list[$];
rand int unsigned ptr;
constraint ptr_c {
ptr < list.size();
}
function new();
enum_type my_enum;
if(initial_allocation == 0) begin
initial_allocation = 1;
for(int unsigned i = 0; i < my_enum.num(); i++)
repeat($urandom_range(1,10)) list.push_back(my_enum);
end
endfunction
endclass
class random_class;
rand parameterized_class#(leg_e) leg_select;
rand parameterized_class#(animal_e) animal_select;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
leg_select.list[leg_select.ptr] == TWO_LEGS -> animal_select.list[animal_select.ptr] inside {HUMAN};
leg_select.list[leg_select.ptr] == FOUR_LEGS -> animal_select.list[animal_select.ptr] inside {DOGS, CAT, ELEPHANT};
leg_select.list[leg_select.ptr] == SIX_LEGS -> animal_select.list[animal_select.ptr] inside {FLY, COCKROACH};
leg_select.list[leg_select.ptr] == EIGHT_LEGS -> animal_select.list[animal_select.ptr] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}
}
function new();
leg_select = new;
animal_select = new;
endfunction
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
I am getting an error:
The solver will not solve for array 'animal_select.list' indexed by random
variable 'animal_select.ptr'.
Please try to use a state variable, constant, or loop variable for array
index.
What modification I havee to make to get a result like:
{DOGS, CAT, HUMAN, ELEPHANT}
{FOUR_LEGS, FOUR_LEGS, TWO_LEGS, FOUR_LEGS, }

I think you might be over-thinking your problem. I think this code produces the result you are hoping for:
typedef enum logic [1:0] {
TWO_LEGS,
FOUR_LEGS,
SIX_LEGS,
EIGHT_LEGS
} leg_e;
typedef enum logic [2:0] {
HUMAN,
DOGS,
CAT,
ELEPHANT,
FLY,
COCKROACH,
SPIDER
} animal_e;
class random_class;
rand leg_e leg_q[$];
rand animal_e animal_q[$];
constraint leg_animal_c {
foreach (leg_q[i]) leg_q[i] == TWO_LEGS -> animal_q[i] inside {HUMAN};
foreach (leg_q[i]) leg_q[i] == FOUR_LEGS -> animal_q[i] inside {DOGS, CAT, ELEPHANT};
foreach (leg_q[i]) leg_q[i] == SIX_LEGS -> animal_q[i] inside {FLY, COCKROACH};
foreach (leg_q[i]) leg_q[i] == EIGHT_LEGS -> animal_q[i] inside {SPIDER};
}
constraint q_c {
leg_q.size() dist {[0:5] := 50, [6:10] := 50};
animal_q.size() == leg_q.size();
}
endclass
module tb;
initial begin
random_class rnd = new;
repeat (10) begin
rnd.randomize();
$display("Animals in queue = %p", rnd.animal_q);
$display("Legs in queue = %p", rnd.leg_q);
end
end
endmodule
https://www.edaplayground.com/x/3rh8

I put a $diplay() debug in your code
foreach (list[i]) $display(list[i].name());
and see that your initialization is wrong. You always push the first enum into the list.
I changed your code to
for(int unsigned i = 0; i < my_enum.num(); i++) begin
/*repeat($urandom_range(1,10))*/ list.push_back(my_enum);
my_enum = my_enum.next();
end
and it does work. EDA code here.
And why do all the queues have identical elements, it is because of your constraints
foreach(leg_q[i]) {
leg_q[i] == leg_select.list[leg_select.ptr];
animal_q[i] == animal_select.list[animal_select.ptr];
}

Related

Create aggregate in postgres using C language

I want to create user-defined aggregate in postgres by C language. Here are my code.
sql code:
CREATE FUNCTION res_tras_crimes_c(state_c, int64)
RETURNS state_c
AS 'MODULE_PATHNAME', 'res_tras_crimes'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE FUNCTION finalize_trans_crimes_c(state_c)
RETURNS ArrayType
AS 'MODULE_PATHNAME'
LANGUAGE C
IMMUTABLE
PARALLEL SAFE;
CREATE AGGREGATE reservoir_sampling_c(int64)
(
sfunc = res_tras_crimes,
stype = state_c,
FINALFUNC = finalize_trans_crimes,
);
For C code:
typedef struct state_c
{
int64 *reservoir;
int32 poscnt;
int32 reservoir_size;
} state_c;
PG_FUNCTION_INFO_V1(res_tras);
Datum
res_tras(PG_FUNCTION_ARGS)
{
//state_c *d1 = malloc(sizeof(state_c));
//struct state_c st;
// st = (state_c *)PG_GETARG_DATUM(0);
struct state_c *st = (state_c *)PG_GETARG_POINTER(0);
int64 newsample = PG_GETARG_INT64(1);
if(st == NULL) {
int64 r[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
int64 *a = r;
st->poscnt = 1;
st->reservoir_size = 100;
st->reservoir = a;
}
if(st->poscnt <= st->reservoir_size){
int32 p = st->poscnt;
*(st->reservoir+p-1) = newsample;
st->poscnt ++;
}else{
int32 pos = rand() % st->poscnt ; //0 - postcnt -1
if(pos < st->reservoir_size){
*(st->reservoir+pos) = newsample;
}
st->poscnt ++;
}
PG_RETURN_POINTER(st);
}
PG_FUNCTION_INFO_V1(finalize_trans);
Datum
finalize_trans_(PG_FUNCTION_ARGS)
{
struct state_c *st = (state_c *) PG_GETARG_POINTER(0);
PG_RETURN_ARRAYTYPE_P(st->reservoir);
}
Can i pass my struct pointer in transition function? and I want to return ARRAYTYPE in final function. I don't konw how to deal with it. Colud you help me? Thanks!
I want to know how to deal the arraytype and struct in c language in postgres
I didn't run your code, but that should work in principle. You would use internal as STYPE in CREATE AGGREGATE and as first argument to the state transition function.
You can look at the PostgreSQL source for an example: array_agg uses internal as STYPE, and you can look at the definition of the state transition function array_agg_array_transfn in src/backend/utils/adt/array_userfuncs.c.

How to make an array with all the enum values in system verilog?

I have an enum :
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
I want to make an array that has all the values of the enum:
enum_t enum_array[ enum_t.num() ] = { enum_A, enum_B, enum_C };
The problem is how to initialize the array without litrally writing the enum values?
I tried foreach & simple for - nothing works...
enum_t enum_array[ enum_t.num() ] = enum_array_alues();
function enum_t [enum_t.num() -1:0] enum_array_alues();
automatic enum_t enum_val = enum_t.first();
foreach ( enum_array_alues[val] ) begin
enum_array_alues[val] = enum_val;
enum_val = enum_val.next(); << .next() on a non-contiguous enum type not supported
end
endfunction;
Is there a solution to this problem?
System Verilog could be ugly :-). This is one of these cases. You cannot use enum methods on typedefs, you need an enum variable to do so. Also, function return type cannot be directly defined as an array, you need a typedef for it.
Also, different compilers have their own minds as well. The following works with vcs, mentor and aldera. However, it failed with cadence.
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10, hello } enum_t;
enum_t enum_var;
typedef enum_t enum_a[enum_var.num()];
enum_a enum_array;
initial begin
enum_array = enum_array_values();
end
function automatic enum_a enum_array_values();
enum_t enum_val = enum_val.first;
foreach(enum_array_values[i]) begin
enum_array_values[i] = enum_val;
enum_val = enum_val.next();
end
endfunction
So, my suggestion is to use dynamic arrays. It seems that this method below works with all compilers in eda playground. It is less ugly but requires a bit more code.
module top;
// Code your design here
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
typedef enum_t enum_array_t[];
enum_t enum_array[];
initial begin
enum_array = enum_array_values();
foreach (enum_array[i])
$display(enum_array[i].name);
end
function automatic enum_array_t enum_array_values();
int i = 0;
enum_t enum_val;
enum_val = enum_val.first();
forever begin
enum_array_values = new [i+1] (enum_array_values);
enum_array_values[i] = enum_val;
if (enum_val == enum_val.last)
break;
i++;
enum_val = enum_val.next();
end
endfunction
endmodule
A do-while loop works well for iterating over enums
module top;
typedef enum { enum_A = 1, enum_B = -5, enum_C = 10 } enum_t;
typedef enum_t enum_list_t[$];
enum_list_t enum_array = enum_array_values();
function automatic enum_list_t enum_array_values;
enum_t tmp = tmp.first;
do begin
enum_array_values.push_back(tmp);
tmp = tmp.next;
end
while (tmp != tmp.first);
endfunction
initial $display("%p", enum_array);
endmodule

Using implication operator for different address ranges

I am wondering how implication operator can be used if I want to choose between different address ranges. I am using if/else condition, but it seems constraint solver is not accepting any solution for this.
constraint ctCopy { mode == C_CMD -> if (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
else if (addr_range == "DST_AXI") {dstAddr inside {['h30000:'h3FFFF]}; }
else if (addr_range == "DST_AHB") {dstAddr inside {[20000:'h2FFFF]}; }
else {dstAddr inside {[0:'hFFFF]}; }
mode == C_CMD -> if (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
else if (addr_range == "SRC_AXI") {srcAddr inside {[0:'h30000]}; }
else {srcAddr inside {[0:'hFFFF]}; }
mode == C_CMD -> cSize inside {[2:10]} ;
}
I am trying to use with constraint, but solver does not accept. Here is the snippet:
Trn0.randomize() with { mode == C_CMD; addr_range == "DST_AHB";};
small example to reproduce is as below
class top;
rand logic [3:0] mode;
rand logic [16:0] dstAddr;
rand logic [16:0] srcAddr;
string addr_range;
rand logic [4:0] copySize;
constraint ctCopy { mode == 1 -> if (addr_range == "DST_SRAM") {dstAddr inside {[0:'hFFFF]}; }
else if (addr_range == "DST_AXI") {dstAddr inside {['h30000:'h3FFFF]}; }
else if (addr_range == "DST_AHB") {dstAddr inside {[20000:'h2FFFF]}; }
else {dstAddr inside {[0:'hFFFF]}; }
mode == 1 -> if (addr_range == "SRC_SRAM") {srcAddr inside {[0:'hFFFF]}; }
else if (addr_range == "SRC_AXI") {srcAddr inside {[0:'h30000]}; }
else {srcAddr inside {[0:'hFFFF]}; }
mode == 1 -> copySize inside {[2:10]} ;
}
endclass
module tb;
initial begin
top tb = new;
tb.randomize() with { mode == 1; addr_range == "DST_AHB";};
$display("dstAddr=%0d,srcAddr=%0d",tb.dstAddr,tb.srcAddr);
end
endmodule
Self contained example at:
https://www.edaplayground.com/x/rjZy
addr_range is of type string, which means it can not be a rand variable. One way to fix your problem is to set addr_range before you call randomize:
module tb;
initial begin
top tb = new;
tb.addr_range = "DST_AHB";
tb.randomize() with { mode == 1; };
$display("dstAddr=%0d,srcAddr=%0d",tb.dstAddr,tb.srcAddr);
end
endmodule
Another way is to use enums instead of strings if you want addr_range to be random.
When you run with Cadence on edaplayground, it generates warning messages about some of the values in your constraint being out of range. For example, you declared dstAddr as a 17-bit value, but 'h3FFFF requires at least 18 bits. You should fix your values.

swift 3 variable used before begin initialized

I have an issue with my n variable. I cannot use n in for loop. Why? n was initialized before for loop. Please, help.
import Foundation
var n: Int
var t: Int
while(true){
var tt = readLine()
t = Int(tt!)!
if (t==0){
break
}
else if ( t < 0){
n = t*(-1)
}
else if(t > 0){
n = t
}
var arr : [[String]] = []
for i in 0..<n*2{
for y in 0..<n*2{
arr[i][y] = "."
}
}
}
A variable may be declared and not immediately initialized, as long as initialization is guaranteed before first use
The error is more subtle than at first glance. You may actually declare a property without initializing it, as long as all program flows leading to its first use ascertain initialization of it.
The issue is with the if, else if and else if block:
var n: Int // declaration
// ...
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
else if (t > 0){
n = t
}
// first use
for i in 0..<n*2 { /* ... */ }
Swift cannot not infer that this block is in fact exhaustive, and believes that there is a possibility that none of the above if statements holds, which, in the eyes of the compiler, would lead to the following program state:
program flow has not been broken (break)
and n has not been instantiated
As humans, however, we know that the if - else if - else if block above is indeed exhaustive, and can help the compiler out by simply changing the last if else statement to a simple else statement.
if (t == 0) {
break
}
else if (t < 0) {
n = t*(-1)
}
// if none of the above, t > 0
else {
n = t
}
On another note, the nested array access of non-existing array elements, arr[i][y] = "." will lead to a runtime exception, but this is another issue. In its current form, it looks as if the intent with the nested loops could be replaced with a nested array instantiation:
var arr = [[String]](repeating: [String](repeating: ".", count: 2*n), count: 2*n)
or,
var arr = (0..<2*n).map { _ in [String](repeating: ".", count: 2*n) }
The variable n is only declared, not initialized.
To initialize the variables:
var n: Int = 0
var t: Int = 0

Variadic opIndex Override

Following my previous question, I'm now having trouble overriding opIndex with variadic parameters. I've tried multiple methods (even hack-ish ones) but to no avail.
The code I'm using to generate the identifier string
static string array_decl(D...)(string identifier, D dimensions)
{
static if(dimensions.length == 0)
{
return identifier;
}
else
{
return array_decl(identifier ~ "[" ~ to!(string)(dimensions[0]) ~ "]", dimensions[1..$]);
}
}
What my opIndex override looks like:
T opIndex(D...)(D indices)
{
mixin("return " ~ array_decl("Data", indices) ~ ";");
}
Fails with:
./inheritance.d(81): Error: tuple D is used as a type
./inheritance.d(89): Error: template instance inheritance.array_ident!(int, int, int).array_ident.array_ident!(_param_2, _param_3) error instantiating
./inheritance.d(112): instantiated from here: array_ident!(int, int, int)
./inheritance.d(174): instantiated from here: opIndex!(int, int, int)
./inheritance.d(112): Error: CTFE failed because of previous errors in array_ident
./inheritance.d(112): Error: argument to mixin must be a string, not ("return " ~ array_ident("Data", _param_0, _param_1, _param_2) ~ ";") of type string
The question is how (or is it possible) to implement the opIndex operator for this situation.
I think mixins are the way to go since I only have to generate a string with the format of:
type[index0][index1]...[indexN] Data
for the opIndex overload.
Apparently this is not possible as the tuple passed to opIndex is inaccessible at compile-time. A few solutions I came up with (by Adam D. Ruppe's suggestions):
1. Hard-coding Array Access
Using compile-time conditions to index the array, a bit ugly and the amount of dimensions that can be accessed depends on the amount of conditions implemented.
T opIndex(D...)(D indices)
{
static if(indices.length == 1)
{
return Data[indices[0]];
}
static if(indices.length == 2)
{
return Data[indices[0]][indices[1]];
}
static if(indices.length == 3)
{
return Data[indices[0]][indices[1]][indices[2]];
}
static if(indices.length == 4)
{
return Data[indices[0]][indices[1]][indices[2]][indices[3]];
}
}
2. Pointer(s)
The only other method was to cast the array to a pointer then use offsets. The offset is computed and is then used to index the pointer.
To be able to access the template parameters at run-time:
struct Vector_MultiDim(T, D...)
{
enum dimensions = [D];
static const size_t DimCount = D.length;
... Other members here
}
Function to compute offset (the size of each dimension must be known at run-time):
size_t GetIndex(size_t[] indices)
{
size_t index;
for(size_t i = 0; i < DimCount; i++)
{
size_t factor = 1;
for(size_t j = i + 1; j < DimCount; j++)
{
factor *= dimensions[j];
}
index += indices[i] * factor;
}
return index;
}
opIndex Override:
T opIndex(D...)(D indices)
{
T* arr = cast(T*)Data;
return arr[GetIndex([indices])];
}