Complex DataType in system verilog(hash of queues) - system-verilog

Suppose I declared a queue: axi4_req_txn_t wr_req_queue[$];
Now I want to have a hash of queue, key is the address and data is the pointer to the queue; Is it possible in systemverilog ?
when I write code like this: typedef wr_req_queue waw_hash[*]; the compiler reports that wr_req_queue is not a valid type.

A rule of thumb is to express any complicated struct as a typedef if you want to use in another typedef. So, here is a simple example of array of queues:
package pkg;
typedef int mytype_t; // whatever the type of queue elements
typedef mytype_t queue_type_t[$]; // queue of mytype_t
typedef queue_type_t array_type_t[int]; // associative array of queues
endpackage // pkg
// test the above
module tb;
import pkg::*;
array_type_t arr;
initial begin
arr[0] = {0};
arr[1] = {1};
arr[3] = {arr[0], arr[1]};
$display(arr);
end
endmodule // tb
Or vice versa, queue of arrays:
package pkg;
typedef int/*your type*/ mytype_t;
typedef mytype_t array_type_t[int];
typedef array_type_t queue_type_t[$];
endpackage // pkg
module tb;
import pkg::*;
array_type_t arr;
initial begin
array_type_t arr1, arr2;
queue_type_t que;
arr1[0] = 0;
arr2[0] = 1;
arr2[1] = 2;
que = {arr1};
que = {que,arr2};
$display(que);
end
endmodule // tb

Related

Pass String array as input into external C function

I would like to pass a String vector into an external C function.
In a minimal example I just want to pass the String vectors (or 1D array) through the C function.
My Modelica function looks like:
function testreadstri
input String instri[2];
output String outstri[2];
external "C" test_stri(instri,, size(instri, 1), outstri);
annotation (Include="#include <ebcmysql.cpp>", Library="libmysql");
end testreadstri;
My C fucntion looks like:
void test_stri(const char* thestring, size_t nLines, const char **testresult)
{
//bout = 12.3;
size_t iLines;
//size_t nLines;
iLines = 0;
//nLines = 1;
while ( iLines <= nLines ) {
<LINE_OF_INTEREST>
iLines++;
}
}
I tried for <LINE_OF_INTEREST> the following lines:
testresult[iLines] = thestring[iLines];
strcpy(testresult[iLines], thestring[iLines]);
What works, but of course does not pass the input through as an output, is:
testresult[iLines] = "aTestString";
Is there any possibility to handle Modelica input String vectors in the external C function?
Thanks in advance!
Here's a short, self-contained and compilable example demonstrating both input string and output string handling of a pure external function in Modelica
model Model
function testreadstri
input String instri[2];
output String outstri[2];
external "C" test_stri(instri, size(instri, 1), outstri, size(outstri, 1));
annotation(Include="
#include \"ModelicaUtilities.h\"
#include <stdlib.h>
#include <string.h>
void test_stri(const char** thestring, size_t nLinesIn, const char** testresult, size_t nLinesOut)
{
size_t iLines;
// example for input string handling
for (iLines = 0; iLines < nLinesIn; iLines++) {
ModelicaFormatMessage(\"%s\\n\", thestring[iLines]);
}
// example for output string handling
for (iLines = 0; iLines < nLinesOut; iLines++) {
char* line = ModelicaAllocateStringWithErrorReturn(6);
if (line != NULL) {
strcpy(line, \"result\");
testresult[iLines] = line;
}
}
}");
end testreadstri;
String s[:] = testreadstri({"first", "second"});
end Model;
Yes, this is supported by the Modelica specification, see https://specification.modelica.org/v3.4/Ch12.html#argument-type-mapping.

[AccelStepper][PlatformIO][mbed] Request for member '' in '', which is of non-class type

so I have been trying to create 3 'accelstepper' objects.
This is a screenshot of my code in case the code section doesn't appear. Also, this is a screenshot of the file "stepper_directory.h"
#include <mbed.h>
#include "stepper_directory.h"
//Include accelstepper library
#include <AccelStepper.h>
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
//Create accelstepper object for the theta axis actuator
AccelStepper taxis(uint8_t interface = AccelStepper::DRIVER, uint8_t tstep = TSTEP, uint8_t tdir = TDIR);
//Create accelstepper object for the magnet actuator
AccelStepper maxis(uint8_t interface = AccelStepper::DRIVER, uint8_t mstep = MSTEP, uint8_t mdir = MDIR);
This is the header file i've used "stepper_directory.h"
#ifndef _STEPPER_DIRECTORY
#define _STEPPER_DIRECTORY
#include "PinNames.h"
//Pin Definitions
#define ZSTEP PA_7
#define ZDIR PA_0
#define TSTEP PA_8
#define TDIR PA_1
#define MSTEP PA_9
#define MDIR PA_2
I've tried to setup one stepper in my main code in main.cpp as follows:
int main() {
// put your setup code here, to run once:
zaxis.setMaxSpeed(188000);
while(1) {
// put your main code here, to run repeatedly:
}
}
But the platformIO compiler is throwing out this lines:
src\main.cpp: In function 'int main()':
src\main.cpp:17:7: error: request for member 'setMaxSpeed' in 'zaxis', which is of non-class type 'AccelStepper(uint8_t, uint8_t, uint8_t)
{aka AccelStepper(unsigned char, unsigned char, unsigned char)}'
zaxis.setMaxSpeed(188000);
^~~~~~~~~~~
*** [.pio\build\nucleo_f410rb\src\main.o] Error 1
I have been attempting to search for what is wrong with my object instantiations to no avail. I would really appreciate if there someone could explain what is wrong with this. This is a screenshot of the error in question
The problem is here.
//Create accelstepper object for the Z-Axis actuator
AccelStepper zaxis(uint8_t interface = AccelStepper::DRIVER, uint8_t zstep = ZSTEP, uint8_t zdir = ZDIR);
This is a function declaration. It takes three arguments and returns AccelStepper. You cannot initialize an instance of AccelStepper with this line of code.
I assume AccelStepper's constructor is something like this:
AccelStepper AccelStepper(uint8_t interface, uint8_t zstep, uint8_t zdir);
You can initialize your instance this way:
AccelStepper zaxis(AccelStepper::DRIVER, ZSTEP, ZDIR);

how to use assertoff from test to disable assertion in side uvm object

I am looking for way to disable assert in side uvm component for certain test.
Below simple code represent my env, with comment for requirement.
I thought I can use $assertoff.
I can modify uvm component if required additional instrumentation to achieve this.
import uvm_pkg::*;
`include "uvm_macros.svh"
class tb_env extends uvm_component;
`uvm_component_utils(tb_env)
int exp_val = 0;
int act_val = 0;
function new(string name = "tb_env", uvm_component parent = null);
super.new(name, parent);
endfunction
virtual task run_phase (uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
#10us;
ASRT: assert ( exp_val == act_val) else
`uvm_error(get_name(), "Error");
#10us;
`uvm_info(get_name(), "Done env", UVM_LOW);
phase.drop_objection(this);
endtask : run_phase
endclass
program tb_run;
initial
begin
tb_env env = new("env");
// Requirement: Disable assertion env.ASRT with system call $assertoff(...)
fork
run_test();
begin
#5us;
env.exp_val = 1;
end
join
end
endprogram
I would like to make things simple to understand. So, prefer to use some glue logic for suppressing the assertion.
For some simulators, $assertoff works only on modules and not on classes, you can use some guarding flag indicating the enable/disable of assertion. The assertion will be checked only when the flag is set. You can declare this flag anywhere in the base classes and use the same flag in enabling/disabling assertions from different extended classes.
One can also develop a generalized macro for this guarding flag. The following code disables the assertions by the use of a guard. If the guard is a static variable, then it can be accessed via scope resolution (::) also.
import uvm_pkg::*;
`include "uvm_macros.svh"
`define ASSERT(VAL,ERR) \
assert(!assert_guard || (VAL)) else begin // If assert_guard=0, then assertion passes without checking other condition \
`uvm_error(get_name(),ERR); \
end \
class tb_env extends uvm_component;
`uvm_component_utils(tb_env)
bit assert_guard;
int exp_val = 0;
int act_val = 0;
function new(string name = "tb_env", uvm_component parent = null);
super.new(name, parent);
assert_guard = 1; // by default assertions are on
endfunction
virtual task run_phase (uvm_phase phase);
super.run_phase(phase);
phase.raise_objection(this);
#10us;
ASRT: `ASSERT( exp_val == act_val, "Error");
#10us;
`uvm_info(get_name(), "Done env", UVM_LOW);
phase.drop_objection(this);
endtask : run_phase
endclass
module tb_run;
initial begin
tb_env env = new("env");
env.assert_guard = 0;
//tb_env::assert_guard = ; // If assert_guard was static
//$assertoff(0,env.run_phase.ASRT); // Works only for VCS
fork
run_test();
begin
#5us;
env.exp_val = 1;
end
join
end
endmodule
// Output:
UVM_INFO # 0: reporter [RNTST] Running test ...
UVM_INFO testbench.sv(31) # 20000: env [env] Done env
As an alternative approach, one can also make use of disable statement of disabling deffered assertion. But in this case, one needs to know exact time when the assertion is to be fired. Refer to IEEE 1800-2012 Section 16.4.4 for more information about this approach.
Yes you can use $assertoff for your purpose.
Here is your code without $assertoff.
class tb_env;
int exp_val = 0;
int act_val = 0;
virtual task run_phase ();
#10;
ASRT: assert ( exp_val == act_val) else
$error("Error");
endtask : run_phase
endclass
program tb_run;
tb_env env = new();
initial
begin
// $assertoff(0, env.run_phase.ASRT);
fork
env.run_phase();
begin
#5;
env.exp_val = 1;
$display("#%0t : exp_val - %0b, act_val - %0b", $time(), env.exp_val, env.act_val);
end
join
end
endprogram
// Output -
#5 : exp_val - 1, act_val - 0
"a.sv", 7: $unit::\tb_env::run_phase .ASRT: started at 10s failed at 10s
Offending '(this.exp_val == this.act_val)'
Error: "a.sv", 7: $unit.tb_env::run_phase.ASRT: at time 10
Error
$finish at simulation time 10
And here is your code with $assertoff.
class tb_env;
int exp_val = 0;
int act_val = 0;
virtual task run_phase ();
#10;
ASRT: assert ( exp_val == act_val) else
$error("Error");
endtask : run_phase
endclass
program tb_run;
tb_env env = new();
initial
begin
$assertoff(0, env.run_phase.ASRT);
fork
env.run_phase();
begin
#5;
env.exp_val = 1;
$display("#%0t : exp_val - %0b, act_val - %0b", $time(), env.exp_val, env.act_val);
end
join
end
endprogram
// Output -
Stopping new assertion attempts at time 0s: level = 0 arg = $unit::\tb_env::run_phase .ASRT (from inst tb_run (a.sv:17))
#5 : exp_val - 1, act_val - 0
$finish at simulation time 10
The $assertoff system task can turn assertions off in specific modules, but not specific classes or objects. So, you'll have to do it manually by modifying your tb_env class.

How to add a built-in module to a C-Python API after Py_Initialize?

I have a module defined in my C code like so:
static struct PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
"the_module_name", /* m_name */
module_documentation, /* m_doc */
//....
};
and a function to initialize it:
PyMODINIT_FUNC init_the_module(void)
{
PyObject *mod, *submodule;
PyObject *sys_modules = PyThreadState_GET()->interp->modules;
mod = PyModule_Create(&module_def);
PyModule_AddObject(mod, "some_submodule", (submodule = init_the_submodule()));
PyDict_SetItemString(sys_modules, PyModule_GetName(submodule), submodule);
Py_INCREF(submodule);
// more submodules..
return mod;
}
The application that I am embedding python into is quite big and I can not change the workflow much. At this point Py_Initialize has already been called, so I can not call PyImport_ExtendInittabor PyImport_AppendInittab .
How can I create and add the module to the system modules?
Maybe I can manipulate the modules dictionary directly? Like so:
PyObject *modules, *the_module;
modules = PyImport_GetModuleDict();
PyDict_SetItemString(modules, "the_module_name", init_the_module());
the_module = PyDict_GetItemString(modules, "the_module_name"); //this is getting something back
std::cout << PyDict_Size(the_module) << std::endl; // this prints -1
The easiest way to handle this is to statically initialize your statically-linked modules by directly calling initspam() after the call to Py_Initialize() or PyMac_Initialize():
int main(int argc, char **argv)
{
/* Pass argv[0] to the Python interpreter */
Py_SetProgramName(argv[0]);
/* Initialize the Python interpreter. Required. */
Py_Initialize();
/* Add a static module */
initspam();
An example may be found in the file Demo/embed/demo.c in the Python source distribution.

getting libstruct to work in matlab for dll pointer argument

I'm trying to call a dll function in matlab. I have a C++ struct as shown in sixense.h:
typedef struct _sixenseControllerData {
float pos[3];
float rot_mat[3][3];
float joystick_x;
float joystick_y;
float trigger;
...
} sixenseControllerData;
and functions I could call:
SIXENSE_EXPORT int sixenseInit( void );
SIXENSE_EXPORT int sixenseGetAllNewestData( sixenseAllControllerData * );
I can easily get this to work with calllib('sixense','sixenseInit') since there is no input, but for the function sixenseGetAllNewestData I need to have a struct pointer. I realize that libstruct is what I need to use. However, I don't seem to be doing it right.
So I tried libstruct like so:
libstruct('sixenseControllerData')
and I get the error:
??? Error using ==> feval
Undefined function or variable 'lib.sixenseControllerData'.
Error in ==> libstruct at 15
ptr=feval(['lib.' structtype]);
EDIT: here is my current unedited proto file:
http://pastebin.com/PemmmMqF
the full header file is available here:
https://github.com/rll/sixense/blob/master/include/sixense.h
For C structures, loadlibrary generates types named: s_{NAME} where {NAME} is the name of the structure. In your case we create a pointer as:
s = libstruct('s_sixenseControllerData');
We can see this fact by instructing MATLAB to generate a prototype file:
>> loadlibrary('sixense', 'sixense.h', 'proto','sixense_proto')
A prototype file is a file of MATLAB commands which we can modify and use in place of a header file. In this case, the file will contain something like:
sixense_proto.m
...
structs.s_sixenseControllerData.members = struct('pos', 'single#3', 'rot_mat', 'single#9', 'joystick_x', 'single', 'joystick_y', 'single', 'trigger', 'single', 'buttons', 'uint32', 'sequence_number', 'uint8', 'rot_quat', 'single#4', 'firmware_revision', 'uint16', 'hardware_revision', 'uint16', 'packet_type', 'uint16', 'magnetic_frequency', 'uint16', 'enabled', 'int32', 'controller_index', 'int32', 'is_docked', 'uint8', 'which_hand', 'uint8', 'hemi_tracking_enabled', 'uint8');
structs.s_sixenseAllControllerData.members = struct('controllers', 's_sixenseControllerData#4');
....
Unfortunately, a limitation of loadlibrary is that it does not support nested structure very well, especially if a structure contains a pointer to another structure (or an array in this case):
Nested structures or structures containing a pointer to a structure are
not supported. However, MATLAB can access an array of
structures created in an external library.
So you will not be able to directly create the sixenseAllControllerData structure on the MATLAB side, which is defined in the C header file as:
typedef struct _sixenseAllControllerData {
sixenseControllerData controllers[4];
} sixenseAllControllerData;
According to the following discussion, one workaround is to "unroll"/"flatten" the array into separate variables. You can either do this in a copy of the header file, or making the changes in the generated prototype file (which I think is the preferred way). You can do this without having to recompile the shared library.
In your case, change the nested structure in the generated sixense_proto.m file into:
structs.s_sixenseAllControllerData.members = struct(...
'controllers1', 's_sixenseControllerData', ...
'controllers2', 's_sixenseControllerData', ...
'controllers3', 's_sixenseControllerData', ...
'controllers4', 's_sixenseControllerData');
Now we can create a pointer to this structure, and call the C method:
s = libstruct('s_sixenseAllControllerData');
s.controllers1 = libstruct('s_sixenseControllerData');
s.controllers2 = libstruct('s_sixenseControllerData');
s.controllers3 = libstruct('s_sixenseControllerData');
s.controllers4 = libstruct('s_sixenseControllerData');
out = calllib('sixense', 'sixenseGetAllNewestData', s);
get(s)
A completely different solution is to write a MEX-function to interface with the library. It is just like any other C/C++ code, only using mxArray and the MX-API to interface with MATLAB...
Example:
To test the above, I created a simple DLL with similar structures, and implemented the above solution. Here is the code if someone wants to test it:
helper.h
#ifndef HELPER_H
#define HELPER_H
#ifdef _WIN32
#ifdef EXPORT_FCNS
#define EXPORTED_FUNCTION __declspec(dllexport)
#else
#define EXPORTED_FUNCTION __declspec(dllimport)
#endif
#else
#define EXPORTED_FUNCTION
#endif
#endif
mylib.h
#ifndef MYLIB_H
#define MYLIB_H
#include "helper.h"
typedef struct _mystruct {
int pos[3];
double value;
} mystruct;
typedef struct _mystruct2 {
mystruct arr[2];
int num;
} mystruct2;
EXPORTED_FUNCTION void myfunc(mystruct *);
EXPORTED_FUNCTION void myfunc2(mystruct2 *);
#endif
mylib.c
#define EXPORT_FCNS
#include "helper.h"
#include "mylib.h"
void myfunc(mystruct *s)
{
s->pos[0] = 10;
s->pos[1] = 20;
s->pos[2] = 30;
s->value = 4.0;
}
void myfunc2(mystruct2 *s)
{
int i;
for(i=0; i<2; i++) {
myfunc(&(s->arr[i]));
}
s->num = 99;
}
After compiling the above into a DLL, we generate the initial prototype file:
loadlibrary('./mylib.dll', './mylib.h', 'mfilename','mylib_proto')
unloadlibrary mylib
I edit the prototype file as described before:
function [methodinfo,structs,enuminfo,ThunkLibName] = mylib_proto()
MfilePath = fileparts(mfilename('fullpath'));
ThunkLibName = fullfile(MfilePath,'mylib_thunk_pcwin64');
enuminfo = [];
structs = [];
structs.s_mystruct.members = struct('pos','int32#3', 'value','double');
structs.s_mystruct2.members = struct('arr1','s_mystruct', ...
'arr2','s_mystruct', 'num','int32');
ival = {cell(1,0)};
methodinfo = struct('name',ival, 'calltype',ival, 'LHS',ival, ...
'RHS',ival, 'alias',ival, 'thunkname',ival);
methodinfo.thunkname{1} = 'voidvoidPtrThunk';
methodinfo.name{1} = 'myfunc';
methodinfo.calltype{1} = 'Thunk';
methodinfo.LHS{1} = [];
methodinfo.RHS{1} = {'s_mystructPtr'};
methodinfo.thunkname{2} = 'voidvoidPtrThunk';
methodinfo.name{2} = 'myfunc2';
methodinfo.calltype{2} = 'Thunk';
methodinfo.LHS{2} = [];
methodinfo.RHS{2} = {'s_mystruct2Ptr'};
end
Now we can finally invoke functions exposed by the DLL:
%// load library using proto file
loadlibrary('./mylib.dll', #mylib_proto)
%// call first function with pointer to struct
s = struct('pos',[0,0,0], 'value',0);
ss = libstruct('s_mystruct',s);
calllib('mylib', 'myfunc', ss)
get(ss)
%// call second function with pointer to struct containing array of struct
xx = libstruct('s_mystruct2');
xx.arr1 = libstruct('s_mystruct');
xx.arr2 = libstruct('s_mystruct');
calllib('mylib', 'myfunc2', xx)
get(xx)
%// clear references and unload library
clear ss xx
unloadlibrary mylib