SystemC- sensitivity list - c++

I have recently started learning SystemC and I have got an error with sensitivity list in "SC_METHOD". I am trying to implement a fifo and the error corresponds to following part of the code:
SC_MODULE(fifo){
...
int rd_addr, wr_addr;
...
void buffer_full();
...
SC_CTOR(fifo){
SC_METHOD(buffer_full);
sensitive << rd_addr << wr_addr;
}
};
I get error when compiling the code and it complains about sensitivity list. The error is
fifo_simple.h:32:22: error: invalid user-defined conversion from 'int' to 'const sc_core::sc_event&' [-fpermissive]
I would appreciate if someone could let me know what is wrong with the sensitivity list. how should I make "buffer_full" process sensitive to the changes in rd_addr and wr_addr.
I also tried following syntax to see if it works with single bit sensitivity but still no success
sensitive << rd_addr[0]
Many thanks

You cannot be sensitive to plain integers, only to (events of) ports or plain events.
As suggested by #jakub_d in the comments above, try changing the int variables to signal ports (although I'd suggest using inputs rather than output ports):
SC_MODULE(fifo)
{
...
// use ports instead of plain integers
sc_in<int> rd_addr, wr_addr;
...
void buffer_full();
...
SC_CTOR(fifo)
: rd_addr("rd_addr") // name your ports
, wr_addr("wr_addr")
{
SC_METHOD(buffer_full);
sensitive << rd_addr << wr_addr; // sensitivity works now
}
};
When using your FIFO, you then need to bind matching sc_signal<int> instances to these address ports:
int sc_main(int, char*[]) {
sc_signal<int> rd_addr_s("rd_addr_s"), wr_addr_s("wr_addr_s");
fifo fifo_i("fifo_i");
// bind signals to ports
fifo_i.rd_addr(rd_addr_s);
fifo_i.wr_addr(wr_addr_s);
// ...
return 0;
}

Related

BLE gattServer.write() overloaded function

I'm having an issue trying to update the value of a characteristic within a custom BLE service that's running on an MCU running mbedOS v5.8.6. I am attempting to update the value of this characteristic with the value from a sensor. Please see the function below:
void onDataReadCallback(const GattReadCallbackParams *eventDataP) {
if (eventDataP->handle == dhtServicePtr->dataStream.getValueHandle()) {
const uint8_t data = sensorData;
BLE::Instance().gattServer().write(eventDataP->handle, &data, sizeof(data), false);
}
}
I have tried explicitly stating the correct variable type (according to the BLE gattServer reference docs) to no avail.
The exact error I receive is:
Error: No instance of overloaded function "GattServer::write" matches the argument list in "main.cpp", Line: 135, Col: 39
I believe I am doing this correctly according to the afforementioned documentation. So, my question is, where exactly am I going wrong? It's entirely possible that I've just made a stupid mistake!
Thanks,
Adam
You are trying send pointer to constant, Although the function signature requires normal pointer. In the below example when value const then compiler will through error.
#include <iostream>
void test(int *ptr)
{
printf("%d",*ptr);
}
int main ()
{
//const int a = 10; //Gives error
int a = 10; //This works fine.
test(&a);
return 0;
}

Error: "sync variables cannot currently be written"

One of my students is having a severe problem with their project (assignment is: http://turing.plymouth.edu/~kgb1013/?course=4310&project=0). They (and I) are getting a weird error when compiling with my test file, testSemaphore.chpl, available at: http://turing.plymouth.edu/~kgb1013/4310/semaphoreProject/testSemaphore.chpl . The error is this:
$CHPL_HOME/modules/standard/IO.chpl:3038: error: sync variables cannot currently be written - apply readFE/readFF() to those variables first
I've had them remove the body of all of their methods, but they're still getting the error. Here is the body of their code:
use Time;
class Semaphore {
var gate1$ : sync int;
//Constructor
proc Semaphore(){
}
//secondary Constructor
proc Semaphore(givenTokens : int){
}
//returns the number of tokens available
proc getNumTokens() : int {
return 1;
}
//gives out a token
proc p() {
}
//returns a token
proc v() {
}
}
Why are they getting this error?
Sorry you're having trouble! It turns out that some of this would be better as a GitHub issue on the Chapel project, but let me first explain what's happening.
The class Semaphore includes a sync variable field. Meanwhile, the default implementation for writing a class is to write each field. So the error message in IO.chpl is trying to say that it doesn't have a reasonable way of outputting a sync variable. E.g.
var x: sync int;
writeln(x);
gives the same error. I think it would be reasonable to open up a GitHub issue on the Chapel project about how inscrutable this error is (and how it doesn't report a line number that is useful to you). Note that I personally used chpl testSemaphore.chpl --print-callstack-on-error to better understand the error - it often helps to add --print-callstack-on-error when you get an error referring to an internal/standard module.
Now, as for the assignment, there are two ways to resolve it:
Adjust testSemaphore.chpl to not print out the semaphore representation in 'writeln' calls. I commented out both writelns starting with "Testing that" and got it to compile.
Adjust the class Semaphore to include a writeThis to replace the compiler-generated write-each-field default, as below:
Here is an example of such a writeThis (see also The readThis, writeThis, and readWriteThis methods )
class Semaphore {
var gate1$ : sync int;
// Other methods as before
proc writeThis(f) {
f <~> "sync semaphore";
}
}

How can I get more details about errors generated during protobuf parsing? (C++)

I am new to protobuf (C++) and my code fails during parse of my messages. How can I get more details about the errors that occurred?
Example
The following snippet illustrates the problem:
const bool ok=my_message.ParseFromCodedStream(&stream);
if(ok){
std::cout<< "message parsed. evidence:\n"<< my_message.DebugString();
}
else{
std::cerr<< "error parsing protobuf\n";
//HOW CAN I GET A REASON FOR THE FAILURE HERE?
}
If you look inside protobuf code, you will find it's using its own logging system - based on macros. By default all these messages goes to stderr, but you can capture them in your program with SetLogHandler():
typedef void LogHandler(LogLevel level, const char* filename, int line,
const std::string& message);
The possible solution is to make your own errno-like mechanism (sorry for C++11-ishness):
typedef LogMessage std::tuple<LogLevel, std::string, int, std::string>; // C++11
typedef LogStack std::list<LogMessage>;
namespace {
LogStack stack;
bool my_errno;
} // namespace
void MyLogHandler(LogLevel level, const char* filename, int line,
const std::string& message) {
stack.push_back({level, filename, line, message}); // C++11.
my_errno = true;
}
protobuf::SetLogHandler(MyLogHandler);
bool GetError(LogStack* my_stack) {
if (my_errno && my_stack) {
// Dump collected logs.
my_stack->assign(stack.begin(), stack.end());
}
stack.clear();
bool old_errno = my_errno;
my_errno = false;
return old_errno;
}
And use it in your code:
...
else {
std::cerr<< "error parsing protobuf" << std::endl;
LogStack my_stack;
if (GetError(&my_stack) {
// Handle your errors here.
}
}
The main drawback of my sample code - it doesn't work well with multiple threads. But that can be fixed on your own.
Sometimes error information will be printed to the console, but that's it. There's no way to get extra error info through the API.
That said, there are only two kinds of errors anyway:
A required field was missing. (Information should be printed to the console in this case.)
The data is corrupt. It was not generated by a valid protobuf implementation at all -- it's not even a different type of protobuf, it's simply not a protobuf.
If you are seeing the latter case, you need to compare your data on the sending and receiving side and figure out why it's different. Remember that the data you feed to the protobuf parser not only must be the same bytes, but it must end at the same place -- the protobuf parser does not know where the message ends except by receiving EOF. This means that if you are writing multiple messages to a stream, you need to write the size before the data, and make sure to read only that many bytes on the receiving end before passing on to the protobuf parser.

C++ Scope of Static Variable In a Static Member Function

I have a simple object which does some parsing. Inside, there is a parse function, containing a static variable that is used to limit number of error messages to print to the user:
struct CMYParsePrimitive {
static bool Parse(const std::string &s_line)
{
// do the parsing
static bool b_warned = false;
if(!b_warned) {
b_warned = true;
std::cerr << "error: token XYZ is deprecated" << std::endl;
}
// print a warning about using this token (only once)
return true;
}
};
Now these parse primitives are passed in a typelist to a parser specialization. There is some other interface which tells parser which token types should be parsed using which parse primitives.
My issue is that the warning should be displayed up to once per application run. But in my case, it is sometimes displayed multiple times, seems to be per parser instance rather than application instance.
I'm using Visual Studio 2008, I imagine this might be some bug or a deviation from the standard? Does anyone have any idea as to why this happens?
I failed to notice that the function is also a template. My bad. It is instantiated twice in the code with different parameters - hence the warning is sometimes printed twice. The real code looks more like this:
struct CMYParsePrimitive {
template <class CSink>
static bool Parse(const std::string &s_line, CSink &sink)
{
// do the parsing, results passed down to "sink"
static bool b_warned = false;
if(!b_warned) {
b_warned = true;
std::cerr << "error: token XYZ is deprecated" << std::endl;
}
// print a warning about using this token (only once)
return true;
}
};
So then there are e.g. CMYParsePrimitive::Parse<PreviewParser>::b_warned, which can print the warning once when used by PreviewParser, and then also CMYParsePrimitive::Parse<Parser>::b_warned which can print the warning when used by Parser.

Is it possible to use WinRT objects in STL-like containers?

I'm trying to create a simple gesture recognizer for a D3D application. The gesture recognizer works by storing each point received into a boost::circular_buffer of capacity 3 and then counting the number of similar FrameID's in the buffer, like so:
UINT Trackball::CalculateGestureSize(Windows::UI::Input::PointerPoint ^ pPoint)
{
// shift the circular buffer queue one if it's full (common case)
if (m_pointQueue.full())
{
m_pointQueue.pop_back();
}
// then store our point
m_pointQueue.push_front(*pPoint);
// now we need to see how many of the points in the
// circular buffer match the frame Id
UINT gestureLength = 0;
for (UINT i = 0; i < MAX_GESTURE_SIZE; i += 1)
{
if (m_pointQueue[i].FrameId == pPoint->FrameId)
{
gestureLength += 1;
}
}
assert(gestureLength != 0);
return gestureLength;
}
However, the compiler is unable to figure out how to instantiate this type:
// a queue of size 3 that helps determine what kind of gesture we're working with
boost::circular_buffer<Windows::UI::Input::PointerPoint> m_pointQueue;
because & and * cannot be used on WinRT objects:
boost/concept_check.hpp(195): error C3699: '&' : cannot use this indirection on type 'const Windows::UI::Input::PointerPoint' compiler replacing '&' with '^' to continue parsing
The compiler's error list then grows long very quickly due to the cascading effects of that error.
Right now, my solution is copy the necessary information for a PointerPoint into a struct and use that as the boost::circular_buffer's typename, like so:
// So WinRT objects (like Windows::UI::Input::PointerPoint) can't
// be used in STL-like containers (like boost::circular_buffer)
// because * and & operators cannot be used on them, so I'm copying
// the necessary info into this struct and using that instead
typedef struct
{
UINT FrameId;
Windows::Foundation::Point Position;
} LocalPoint;
// a queue of size 3 that helps determine what kind of gesture we're working with
boost::circular_buffer<LocalPoint> m_pointQueue;
This definitely works, but I was wondering if there's a better solution out there.
Thanks for reading and for trying to help.
If you want to put a reference type in an STL collection, you need to use the ^ form. So you'd use: boost::circular_buffer<PointerPoint^> instead of boost::circular_buffer<PointerPoint>. A Windows::Foundation::Point is a value type so it can be used in a collection directly.
I think I accidentally found a working solution by using that Windows::Foundation::Point object in my LocalPoint struct. Just wrap the WinRT object with a struct and then the operators will work just fine, but it'll add a bit of syntactic noise.
However I'm still listening for a better solution, but I'll leave this here till then.