Can't use a typedef enum to store state information - xc16

hi - I'm using the XC16 C compiler with a Microchip dsPIC33F CPU. I'm trying to use an enum to store the state of a device. I have accessors to get and set the device state. The state is (or should be) captured in a variable called "currentNodeState" which is declared with the following:
`
typedef enum NodeState currentNodeState;
I then use it in the set accessor with:
void SetNodeState(NodeState state)
{
currentNodeState = state;
}
which results in the following compiler error:Node_IO.c:168:22: error: expected identifier or '(' before '=' token
any suggestions as to why the error message
Jim

You need to define what values are legal for the enum.
Cplusplus has a good write up on enums (near the bottom of the page): http://www.cplusplus.com/doc/tutorial/other_data_types/
Here's a modified example from my code:
typedef enum
{
ADJUST_NONE,
ADJUST_FINE,
ADJUST_COARSE,
ADJUST_INVALID
} adjustment_state_t;
adjustment_state_t ADJUSTER_StateUpdate(adjustment_state_t currentState,
uint8_t thresholdViolation);
Valid inputs to the function are any of the values in the enum. ADJUST_NONE = 0, and each subsequent value is 1 higher than the last. That makes ADJUST_INVALID = 3.

Related

How do you return multiple instances of a struct in Solidity? [duplicate]

This question already has answers here:
How can I return an array of struct in solidity?
(3 answers)
Closed 1 year ago.
I'm learning about the struct data type and I want to know if:
it's possible to return multiple instances of a struct object at the same time.
an instance declared locally (inside a function) can return its value.
I want to get the details of all the instances (book1, book2, and book3) returned to me at the SAME TIME. I ran the code and could only get the details for ONE INSTANCE at A GIVEN TIME. So, the two instances I declared at state-level (book1 and book2) returned values WHEN CALLED SEPARATELY. However, book3, which was declared locally, didn't return its value when called. What I got was a declaration error (DeclarationError: Undeclared Identifier).
How do I return all the values together?
Why is book3 not returning its value? Can't a struct have a local instance?
pragma solidity >=0.4.0 <0.9.0;
// Creating a struct contract
contract MyStruct {
// Declaring a struct
struct Book {
string name;
string writer;
uint id;
bool available;
}
// Declaring a structure object, book1 (state variable of type struct; no values)
Book book1;
// Assigning values to fields for another struct instance, book2
Book book2 = Book ("Building Ethereum DApps", "Roberto Infante", 2, false);
// Defining a function to set values for the fields for structures
function setBookDetails() public {
// Assigning values to book 1 (state struct above)
book1 = Book("Introducing Ethereum and Solidity", "Chris Dannen", 1, true);
// Defining a new book instance locally, book3 (local struct)
Book memory book3 = Book ("Solidity Programming Essentials", "Ritesh Modi", 3, true);
}
// Defining function to print book1 details
function getBookDetails() public view returns (string memory, string memory, uint, bool) {
return (book1.name, book1.writer, book1.id, book1.available);
//return (book2.name, book2.writer, book2.id, book2.available);
//return (book3.name, book3.writer, book3.id, book3.available);
}
}
You can return ALL book objects with return statement if you would use array. ALSO Solidity creates getter functions automatically for public variables. As your array could be public, a public getter function would be generated for it automatically. The getter function is used to access the array variables directly and not for retrieving the array itself.
There is a difference between Storage and Memory variables. The Solidity Smart Contract can use any amount of memory during the execution but once the execution stops, the Memory is completely wiped off for the next execution. Whereas Storage on the other hand is persistent, each execution of the Smart contract has access to the data previously stored on the storage area.
I just wanted to add to #Peteris' answer by saying that it is also possible to return multiple instances of a struct without creating an array. A function can have multiple return values but you still use a single return in that case:
function getBookDetails()
public
view
returns (Book memory, Book memory, Book memory)
{
return (book1, book2, book3);
}
Of course, since book3 is only visible in setBookDetails, it will only work if you make it available to the function, e.g. by making it a storage variable, moving the declaration to the function or passing it in via a parameter.

How to vary a struct going through a port in system verilog - generate doesnt work

module testy
#(
parameter W = 10,
parameter C = 2
)
(
aa
);
generate
if (W == 8)
begin:W8
if(C == 1)
begin:W8C1
typedef struct {
logic [8:0] so;
}my_struct;
end
if(C == 2)
begin:W8C2
typedef struct {
logic [10:0] so;
}my_struct;
end
end
endgenerate
input my_struct aa;
endmodule
I get this error:
irun(64): 14.20-p001: (c) Copyright 1995-2015 Cadence Design Systems, Inc.
file: testy.v
input my_struct aa;
|
ncvlog: *E,SVNOTY (testy.v,30|14): Syntactically this identifier appears to begin a datatype but it does not refer to a visible datatype in the current scope.
module worklib.testy:v
errors: 1, warnings: 0
ncvlog: *F,NOTOPL: no top-level unit found, must have recursive instances.
irun: *E,VLGERR: An error occurred during parsing. Review the log file for errors with the code *E and fix those identified problems to proceed. Exiting with code (status 2).
I thought generates were statically determined but I have problems compiling it - since parameters cant be overridden in packages and couldn't think of a way to do this in design which needs to be synthesized and didn't want to add interfaces or classes. Is there a bettwe way to do this. My struct has over 100 entries if I include all the combinations and use only what I want but I thought using generates I could trim it to what I want based on a set of parameters.
Thanks
Your problem is the scope of the typedef is local to the blocks inside your generate statements. If all you need to do is change the size of a data type, you can use a constant function call, with is statically determined. But then you run into another problem with your unpacked struct declaration - it is still local to the module and you will not be able to connect another struct to it with a matching data type. An interface would be a better solution and is synthesizable.
Another possibility is passing down a type parameter.

How to assign value to union in VC++

There is an union in C and embedded into C++ as below:
typedef union MyUnion MyUnion_;
union MyUnion{
ULONG mLong;
char mChar;
...
};
When I trying to init it like:
MyUnion_ test;
test = (MyUnion_)NULL;
this is can compile by Mingw32, but gives
error: C2440: 'type cast': cannot convert from 'void *' to 'MyUnion_'
in VC++ (VS2015). So how to do cast & initialize of union in VC++ compiler?
Now I am doing like this:
MyUnion_ test;
test.mLong = NULL;
but this makes the program look bad when passing union as a parameter.
void test(MyUnion_ u)
ULONG i = 0;
// mingw32
test((MyUnion_)i);
// vc++
MyUnion_ temp;
temp.mLong = i;
test(temp);
Using a compiler that supports the C++11 uniform initialization syntax you can use a braced initializer with a single value which will be used to initialize the first non-static field of the union …
MyUnion test{ 0 };
You could use NULL instead of zero in the code above but it seems confusing to initialise mLong (which is a ULONG) with NULL.
You can also use braced initialization in an assignment statement if you have to set the variable after it was declared …
MyUnion test{ 0 };
// ...
test = { 3 };
Note that the braced initializer syntax may also be available in older compilers that offer experimental support for what used to be called C++0x
Visual Studio 2015 C++ supports braced initializers unless you are compiling a file with a .c extension or are using the /TC switch to compile as C code (rather than C++ code).
Older C++ (and C) compilers
When using compilers that don't support braced initialization the older assignment initialization syntax can be used in declarations ...
MyUnion_ test = { 0 };
… but not in assignment statements.
Casting to union type
According to this IBM Knowledge Center article casting to a union type is an extension to C99 "... implemented to facilitate porting programs developed with GNU C" - which suggests it's not standard C.
This Microsoft documentation indicates there are no legal casts in C for a union, struct or array.
In C++ a cast to a union type is possible if a suitable constructor exists...
union MyUnion {
unsigned long mLong;
char mChar;
MyUnion(unsigned long val) { mLong = val; };
};
// valid cast
test = (MyUnion)3ul;
// invalid cast - no suitable constructor exists
void * ptr = 0;
test = (MyUnion)ptr;
Default constructor?
typedef union MyUnion MyUnion_;
union MyUnion {
ULONG mLong;
char mChar;
MyUnion(): mLong(0) {}
};
int main()
{
MyUnion_ temp;
return 0;
}

OpenCL: Struct within struct sending to internal function on device side

Got a question about struct handling in OpenCL that I didn't find on here. I've gathered the all of the data I use in a struct, which itself consists of several structs. I want to do the following:
typedef struct tag_OwnStruct
{
float a;
float b;
float c;
int d;
float e;
int f;
}OwnStruct;
typedef struct tag_DataStruct
{
OwnStruct g;
//+ Alot of other structs... not written for simplicity
}DataStruct;
void PrintOwnStruct(OwnStruct* g)
{
printf("Current lane id : %f\n",g->a);
}
__kernel void Test(__global DataStruct *data)
{
PrintOwnStruct(&data->g);
}
So I want, from the given data I get sent in from the host side to the device, to send the reference to a struct inside of it. That doesn't work somehow, and I don't know why. I've tried the same thing in plain C code and it worked..
If I change PrintOwnStruct to :
void PrintOwnStruct(OwnStruct g)
{
printf("Current lane id : %f\n",g.a);
}
and call the function as : PrintOwnStruct(data->g) the code will run on the device side. Is there any other way to do this? Since I'm not sending the reference to the function, is it being passed by value? And shouldn't that be slower than passing function parameters by reference?
So the problem appears (from comments) to be the confusion between __private and __global address spaces, and possibly that the compiler/runtime is not very helpful in informing about the mix of pointers.
void PrintOwnStruct(OwnStruct* g)
{
printf("Current lane id : %f\n",g->a);
}
__kernel void Test(__global DataStruct *data)
{
PrintOwnStruct(&data->g);
}
The __global DataStruct *data is a pointer to something in __global address space [in other words having the same address for all CL threads], the argument to void PrintOwnStruct OwnStruct* g) declares an argument that is pointing to OwnStruct in the default __private address space [in other words on the stack of this thread].
The correct thing to do is to maintain the address space for both pointers to __global by declaring the function PrintOwnStruct(__global OwnStruct* g).
I'm pretty sure SOME OpenCL compilers will give an error for this, but apparently not this one. I expect that true syntax errors, such as adding %-&6 to the code will in fact give you a kernel that doesn't run at all, so when you call clCreateKernel or clBuildProgram, you'll get an error - which can be displayed by clGetProgramBuildInfo. But if the compiler isn't detecting different address spaces, then it's a bug/feature of the compiler.
[In fact, if your compiler is based on Clang, you may want to have a look at this bug:
https://llvm.org/bugs/show_bug.cgi?id=19957 - half an hour of googling gives a result of some sort! :) ]
In the newer CL2.0 the default address-space is generic, which allows "any" address space to be used.

Boost Phoenix: Binding to reference members of structures?

I would like to use Boost Phoenix to generate a lambda function for use in a std::find_if operation on a structure that contains reference-type members. A contrived example is as follows:
struct MyStruct
{
MyStruct() : x(0) {}
int& x;
};
std::vector<MyStruct> AllStructs;
// Search the array for an element for which x == 5
const std::vector<MyStruct>::const_iterator& it =
find_if(
AllStructs.begin(),
AllStructs.end(),
bind(&MyStruct::x, arg1) == 5
);
If MyStruct::x is of type int instead of int&, it compiles fine. But with the reference member I get a "pointer to reference member is illegal" error.
From poking around on the net, it seems like I need to use Phoenix's 'ref' functionality, but I can't seem to figure out the required syntax.
Does anyone know how to get this to work for type 'int&' ?
Sorry that this is far too late, but for future reference, you can use a member pointer:
std::vector<MyStruct>::const_iterator it =
find_if(AllStructs.begin(), AllStructs.end(),
(&boost::phoenix::arg_names::arg1)->*&MyStruct::x == 5
);
You cannot create a pointer to a reference member, just as you cannot create a pointer to a reference. The answer from Daniel James could work only if x was a plain int, rather than int&. See phoenix.modules.operator.member_pointer_operator also.

Resources