Time unit for VPI call back on signal value change - system-verilog

In my VPI call back function, I am getting real value for time, but units for this time value depends on timescale for the module where signal resides.
How I can find what units for the provided time?
Here is my monitor VPI function:
my_monitor(p_cb_data cb_data_p)
{
unsigned int value, bit, i;
for(bit=1,value=0,i=strlen(cb_data_p->value->value.str) ; i ;i--){
// Convert string to hex value
value += cb_data_p->value->value.str[i-1]=='1' ? bit : 0; // TODO: Check for other values?
bit *= 2;
}
// Save to trace file
fprintf(pv_file_trace,"%15f(?s): %s = %s 0x%X\n",
cb_data_p->time->real,
cb_data_p->user_data,
cb_data_p->value->value.str, value);
}

Assuming the signal is declared in a module, you can do
ts = vpi_get(vpiTimeUnit, vpi_handle(vpiModule, cb_data_p->obj));
I could not find I documented, but ts is in the scale of 10-ts in seconds

Related

Detect timescale in System Verilog

How do I detect the timescale precision used in a simulation from the source code ?.
Consider I have a configuration parameter(cfg_delay_i) of some delay value given by user in timeunits as fs .If the user gives 1000 , my code has to wait 1000fs or 1ps before executing further.
#(cfg_delay_i * 1fs );//will wait only if timescale is 1ps/1fs
do_something();
If the timescale precision is 1fs ,there won’t be any problem but if the precision is higher than that it won’t wait and it will work as 0 delay .
So I want to write a code which will determine the timescale used by the user and give the delay accordingly.My expected pseudo-code will be like below,
if(timeprecision == 1fs )#(cfg_delay_i * 1fs ) ;
else if(timeprecision == 1ps )#(cfg_delay_i/1000 * 1ps ) ;
Please help me with the logic to determine the timescale unit and precision internally.
You can write if (int'(1fs)!=0) // the time precision is 1fs and so on. But there's no need to do this.
#(cfg_delay_i/1000.0 * 1ps)
The above works regardless if the precision is 1ps or smaller. Note the use of the real literal 1000.0 to keep the division real. 1ps is already a real number, so the result of the entire expression will be real. You could also do
#(cfg_delay_i/1.e6 * 1ns)
If the time precision at the point where this code is located is greater than 1fs, the result gets rounded to the nearest precision unit. For example if cfg_delay is 500 and the current precision is 1ps, this would get rounded to #1ps.
Do be aware that the user setting cfg_delay has to take the same care to make sure their value is set with the correct scaling/precision.
This seems to work in Vivado
// Example where we need to check the clock frequency or the time of an event
real tscale_unit;
realtime t_edge1;
realtime t_edge2;
realtime t_event;
real clk_freq;
initial begin
t_edge1 = 0.0s;
#1; // Single unit time delay
tscale_unit = $realtime / 1ps; // Normalise the timescale into picoseconds (1*10^-12)
end
always begin
#(posedge clk);
t_edge2 = t_edge1;
t_edge1 = $realtime;
clk_freq = 1.0s/((t_edge1 - t_edge2) * tscale_unit * 1ps);
end
always begin
#(posedge event);
t_event = $realtime * tscale_unit * 1ps;
end

How to read and convert Bluetooth characteristic from byte data to proper values(Bluetooth for flutter)

I have to read and write some values to a Bike Smart trainer with BLE (Bluetooth Low Energy) used with Flutter. When I try to read the values from the GATT characteristic org.bluetooth.characteristic.supported_power_range (found on bluetooth.org site https://www.bluetooth.com/specifications/gatt/characteristics/ ) I get the return value of an Int List [0,0,200,0,1,0].
The GATT characteristic sais that there are 3 sint16 fields for Min., Max. and step size Watts (Power).
The Byte transmission order also sais that the least significant octet is transmitted first.
My guessings are, that the 3 parameters are returned in an Int array with 8bit value each. But I can't interpret the 200 for maybe the maximum Power setting. Because the smart trainer should provide max. 2300W Watts resistance (ELITE Drivo https://www.elite-it.com/de/produkte/home-trainer/rollentrainer-interaktive/drivo)
The Output results from this code snippet:
device.readCharacteristic(savedCharacteristics[Characteristics.SUPPORTED_POWER_RANGE]).then((List<int> result) {
result.forEach((i) {
print(i.toString());
});
});
// result: [0,0,200,0,1,0]
Maybe some one of u knows how to interpret the binary/hex/dec values of the flutter_blue characteristic output.
Or some hints would be great
Edit
For future readers, I got the solution. I'm a bit asheamed because I read the wrong characteristic.
The return value [0,0,200,0,1,0] was for supported resistance level. (which is 20% and the 200 shows the 20% with a resolution of 0.1 like described in the GATT spec)
I also got a return value for the supported power level which was [0,0,160,15,1,0]. Now the solution how to read the 2 Bytes of max powre level: you get the 160,15 the spec sais LSO (least significant octet first, don't confuse it with LSB least significant bit first). In fact of that you have to read it like 15,160. now do the math with the first Byte 15*256 + 160 = 4000 and thats the correct maximum supported power of the trainer like in the datasheet.
I hope I help someone with that. Thanks for the two replys they are also correct and helped me to find my mistake.
I had the same problem connecting to a Polar H10 to recover HR and RR intervals. It might not be 100% the same, but I think my case can guide you to solve yours.
I am receiving the same list as you like these two examples:
[0,60]
[16,61,524,2]
Looking at the specs of the GATT Bluetooth Heart Rate Service I figured that each element of the list retrieved matches 1 byte of the data transmitted by the characteristic you are subscripted to. For this service, the first byte, i.e., the first element of the list, has some flags to point out if there is an RR value after the HR value (16) or not (0). This is just two cases among the many different ones that can ocur depending on the flags values, but I think it shows how important this first byte can be.
After that, the HR value is coded as an unsigned integer with 8 bits (UINT8), that is, the HR values match the second element of the lists shown before. However, the RR interval is coded as an unsigned integer eith 16bits (UINT16), so it complicates the translation of those two last elements of the list #2 [16,61,524,2], because we should use 16 bits to get this value and the bytes are not in the correct order.
This is when we import the library dart:typed_data
import 'dart:typed_data';
...
_parseHr(List<int> value) {
// First sort the values in the list to interpret correctly the bytes
List<int> valueSorted = [];
valueSorted.insert(0, value[0]);
valueSorted.insert(1, value[1]);
for (var i=0; i< (value.length-3); i++) {
valueSorted.insert(i+2, value[i+3]);
valueSorted.insert(i+3, value[i+2]);
}
// Get flags directly from list
var flags = valueSorted[0];
// Get the ByteBuffer view of the data to recode it later
var buffer = new Uint8List.fromList(valueSorted).buffer; // Buffer bytes from list
if (flags == 0) {
// HR
var hrBuffer = new ByteData.view(buffer, 1, 1); // Get second byte
var hr = hrBuffer.getUint8(0); // Recode as UINT8
print(hr);
}
if (flags == 16) {
// HR
var hrBuffer = new ByteData.view(buffer, 1, 1); // Get second byte
var hr = hrBuffer.getUint8(0); // Recode as UINT8
// RR (more than one can be retrieved in the list)
var nRr = (valueSorted.length-2)/2; // Remove flags and hr from byte count; then split in two since RR is coded as UINT16
List<int> rrs = [];
for (var i = 0; i < nRr; i++) {
var rrBuffer = new ByteData.view(buffer, 2+(i*2), 2); // Get pairs of bytes counting since the 3rd byte
var rr = rrBuffer.getUint16(0); // Recode as UINT16
rrs.insert(i,rr);
}
print(rrs);
}
Hope it helps, the key is to get the buffer view of the sorted list, get the bytes that you need, and recode them as the standard points out.
I used print(new String.fromCharCodes(value)); and that worked for me.
value is your return from List<int> value = await characteristic.read();
I thank ukBaz for his answer to this question. Write data to BLE device and read its response flutter?
You can use my package byte_data_wrapper to transform this data to a decimal value which you can understand:
Get the buffer:
import 'dart:typed_data';
final buffer = Uint16List.fromList(result).buffer;
Create the byteDataCreator:
// Don't forget to add it to your pubspec.yaml
//dependencies:
// byte_data_wrapper:
// git: git://github.com/Taym95/byte_data_wrapper.git
import 'byte_data_wrapper/byte_data_wrapper.dart';
final byteDataCreator = ByteDataCreator.view(buffer);
Get your data :
// You can use getUint8() if valeu is Uint8
final min = byteDataCreator.getUint16();
final max = byteDataCreator.getUint16();
final stepSize = byteDataCreator.getUint16();
I know its too late to answer this but if there is anyone still having a trouble, just convert it manually to be an integer. Because I think you are receiving a type of ByteArray (correct me if I'm wrong).
num bytesToInteger(List<int> bytes) {
/// Given
/// 232 3 0 0
/// Endian.little representation:
/// To binary
/// 00000000 00000000 00000011 11101000
/// Combine
/// 00000000000000000000001111101000
/// Equivalent : 1000
num value = 0;
//Forcing to be Endian.little (I think most devices nowadays uses this type)
if (Endian.host == Endian.big) {
bytes = List.from(bytes.reversed);
}
for (var i = 0, length = bytes.length; i < length; i++) {
value += bytes[i] * pow(256, i);
}
return value;
}
and vice versa when you try to write over 255
Uint8List integerToBytes(int value) {
const arrayLength = 4;
return Uint8List(arrayLength)..buffer.asByteData().setInt32(0, value, Endian.little);
}
Hope this helps.
P.S. I also posted the similar problem here.

Interpreting inputBuffer's Value in a Callback

I am basing my code off of Portaudio's paex_record_file.c example. One of the parameters in the callback is inputBuffer, and I wanted to use its data to calculate other numbers with the double/float type. I changed the file from a .raw to a .txt, but notepad still cannot read it, leading me to believe its data is not actually encoded as a number. How is the data stored in inputBuffer and how can I do arithmetic with it (add, multiply, divide, etc)?
This is how I initialized inputParameters:
inputParameters.device = Pa_GetDefaultInputDevice(); /* default input device */
if (inputParameters.device == paNoDevice) {
fprintf(stderr,"Error: No default input device.\n");
goto error;
}
inputParameters.channelCount = 2; /* stereo input */
inputParameters.sampleFormat = paFloat32;
inputParameters.suggestedLatency = Pa_GetDeviceInfo( inputParameters.device )->defaultLowInputLatency;
inputParameters.hostApiSpecificStreamInfo = NULL;
This question is somewhat related to print floats from audio input callback function (unanswered).
The inputBuffer parameter to the callback is a void*. The actual type of the underlying buffer depends on the parameters and the flags that you pass to Pa_OpenStream.
If you specified paFloat32 then there will be a float* in there somewhere. However the are two possibilities:
Interleaved: inputParameters.sampleFormat = paFloat32;
Non-Interleaved: inputParameters.sampleFormat = paFloat32|paNonInterleaved;
You specified the interleaved option. In this case, inputBuffer points to a single buffer of interleaved floats. So you can write:
float *samples = (float*)inputBuffer;
In a two channel stream samples will contain interleaved left and right samples, e.g.:
samples[0]; // first left sample
samples[1]; // first right sample
samples[2]; // second left sample
samples[3]; // second right sample
// etc.
For completeness: If it had been a non-interleaved stream then inputBuffer points to an array of pointers to single-channel buffers. To extract the buffer pointers you would write something like:
float *left = ((float **) inputBuffer)[0];
float *right = ((float **) inputBuffer)[1];
Note that in all cases framesPerBuffer counts frames not samples. A frame includes one sample from each channel. For example, in a stereo stream, a frame includes both the left and right channel samples.

Creating and managing two independent random number sequences

I'm having trouble generating two independent random sequences using the rand and srand functions. The details are below, any help would be most appreciated.
I'm working on a puzzle game for the iPhone, and usually for the random number generation I use the arc4 function. However for the multiplayer mode I want both players to have the same pieces throughout the game, and the only way I can control it is to have two repeatable random sequences. If I then send the seeds to the other device, the games will be identical. However when I use rand and srand and try to switch to the other seed, the sequence starts from scratch, I somehow have to initialize two independent sequences generated with a seed.
Thank you for your responses
Cryptographically bad PRNGs like rand() operate by feeding the previous result back into a certain mathematical procedure.
In order to continue a sequence from where it left off, all you have to do is store the last-generated number and use it as the seed:
srand(time(0));
int player1_rand_num = rand();
NSLog(#"Player 1: %d, %d, %d", rand(), rand(), rand());
srand(7);
int player2_rand_num = rand();
NSLog(#"Player 2: %d, %d, %d", rand(), rand(), rand());
// Re-seed Player 1 sequence
srand(player1_rand_num);
// Displays the same "random" numbers as the first NSLog
NSLog(#"Player 1 again: %ld, %ld, %ld", rand(), rand(), rand());
// and so on...
The random() function generates better random numbers, and has a separate pair of functions, initstate() and setstate() which will give you the state of the generator. You can store the state and pass it into setstate() to resume the sequence from where you left off. I direct you to man 3 random for the details.
First off, as others have pointed out already, you should use random() instead of rand(). Secondly, while your singleton approach may work for you, you could solve your problem more easily and IMHO more elgantly by using setstate(3). See Use of setstate(3) doesn't produce expected sequence of random numbers for an example on how to switch between two random number states.
Thank you for the suggestions, this is how I implemented the whole thing. I created a singleton class with 2 instance variables - seed1 and seed2 - anytime I want to get a number from the first generator I use the method generator1, same for generator2 method. The seed1/2 is instantly set to a newly generated number every time so I can just continue where I left off. In conlusion, Josh Caswell gave me all the information I needed. Check out the code if you ever need something like this. The object inits with seeds 1 and 1 but during the game they get replaced with some other numbers that both devices share.
#implementation RandomNumberGenerator
#synthesize seed1,seed2;
static RandomNumberGenerator *sharedGenerator = nil;
+(RandomNumberGenerator *) sharedInstance
{
if(!sharedGenerator) {
sharedGenerator = [[RandomNumberGenerator alloc] initWithSeed1:1 andSeed2:1];
}
return sharedGenerator;
}
-(id) initWithSeed1:(int) seedOne andSeed2:(int) seedTwo{
self = [super init];
if (self)
{
seed1 = seedOne;
seed2 = seedTwo;
}
return self;
}
-(int) generator1{
srand(seed1);
int j = rand();
seed1 = j;
return abs(j);
}
-(int) generator2 {
srand(seed2);
int k = rand();
seed2 = k;
return abs(k);
}
-(int) giveRandom {
//return abs(arc4random());
return abs(arc4random());
}
#end
Did you seed your random number generator?
srand( myIdenticalSeedValueForBothPartners );
See this question or here [C++ reference].
In case you don't need to call rand() many thousand times:
int nthRandBasedOnSeed( int seed, int count ) {
srand( seed );
int result;
while( 0 < count-- ) {
result = rand();
}
return result;
}
Alternately, you might consider sending with the seed a "count". This count would simply indicate where in the seeded-series you are and would get incretented each time you generate a random number with that seed. This approach gives you the flexibility of using any random generator you like and keeps communication to a minimum.
int playerSeed = 12345;
int playerRndCount = 0;
int generateRandomNumber() {
playerRndCount++;
return rand();
}
void synchSeed(seed, count) {
srand(seed);
for (int i=0; i<count; i++)
generateRandumNumber();
}
Some random number generator libraries allow you to save the state of the generator. This way, you can restore it later, and continue with a sequence already in progress. One I know of is called RandomLib, and it can be found on SourceForge.
Another option is save the seed, and count how many times you've pulled a value from the generator after seeding. Later on when you want to continue, reseed with the original seed, and pull off the same quantity. This probably isn't the best method, but should work fine if not done a lot.

How to increase/decrease an Unsigned Char?

I am trying to modify pixel values (8 bits per channel RGBA) by numerically increasing/decreasing the values by a certain amount. How can I do this in Objective-C or C? The following code generates a "Error: EXC_BAD_ACCESS" everytime.
// Try to Increase RED by 50
for(int i = 0; i < myLength; i += 4) {
//NSLog prints the values FINE as integers
NSLog(#"(%i/%i/%i)", rawData[i], rawData[i+1], rawData[i+2]);
//But for some reason I cannot do this
rawData[i]+=50;
}
and even
// Try to set RED to 50
for(int i = 0; i < myLength; i += 4) {
//I cannot even do this...
unsigned char newVal = 50;
rawData[i] = 50;
}
Sidenote: rawData is a data buffer of type unsigned char
It's possible that you're overrunning the end of your allocated buffer, and that's why you're getting the access violation. That most likely means that your math is wrong in the allocation, or your rawData pointer is of the wrong type.
If you are accessing the raw data of a loaded UIImage, it might be mapped into memory read-only. You'd need to copy the data into a buffer that you allocated, most likely.
Hmm... What's rawdata? Maybe it's a const type which you can not modify?