Modelica Boolean variable in continuous time - time

The following Modelica model checks and simulates.
model boolCheck_OK1
Real a = sin(time);
Real b = cos(time);
Real c;
//protected
// Boolean isInReg = inRegionCheck(a, b);
equation
c = if inRegionCheck(a, b) then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;
The function inRegionCheck() returns a Boolean, here is a simplified version:
function inRegionCheck
input Real a;
input Real b;
output Boolean c;
algorithm
c := a>b;
end inRegionCheck;
In the actual code, the function has more inputs and a longer name and is several lines long and the same check is used several times, so for readability I would like to introduce an intermediate variable as shown in the commented protected section, but that results in an error "Non-real equation in continuous time are not legal".
Any suggestions for an elegant workaround?

Works in SimulationX (with protected Boolean variable isInReg) if the function inRegionCheck is annotated by annotation(GenerateEvents=true);. In Dymola, you need to set annotation(Inline=true,GenerateEvents=true); to make it working.

The function call introduces a noEvent in your equation for isInReg.
This is what Dymola 2019 FD01 reports if the boolean is used:
Non-real equation in continuous time are not legal:
isInReg = noEvent(a > b);
Hence, your equation reduces to
isInReg = noEvent(a > b)
which is not allowed, as boolean values can only change on events.
You have to get rid of the function call and thus the noEvent.
Maybe there is a better solution, but you could try to define the check in a block instead of a function. At least for your minimal example it works perfectly fine.
Then your code could look like this:
model boolCheck_OK1
Real a = sin(time);
Real b = cos(time);
Real c;
protected
InRegionCheck check(a=a, b=b);
Boolean isInReg=check.c;
equation
c = if isInReg then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;
block InRegionCheck
input Real a;
input Real b;
output Boolean c;
equation
c = a>b;
end InRegionCheck;

Based on the fact that there is no function to convert to boolean but only a block, i would suggest marco's answer is the way to go.
With a workaround you can still do it inside a function, but not with the type Boolean. Instead use Real and compare in the if-clause if it's greater zero. For showing the switching behaviour of the boolean this works fine. If you rely on the function and don't use the boolean too often, this could be an option.
model boolCheck_OK1
Real a = sin(time);
Real b = cos(time);
Real c;
function inRegionCheck
input Real a;
input Real b;
output Real c;
algorithm
c := if a>b then 1 else 0;
end inRegionCheck;
protected
Real isInReg = inRegionCheck(a, b);
equation
c = if inRegionCheck(a, b)>Modelica.Constants.eps then 1.3*a^b else 0.7*b^a;
end boolCheck_OK1;

Related

DMux.hdl failure when in=1, sel=0

I'm writing the hdl code for a DMux based on the Nand2Tetris course.
CHIP DMux {
IN in, sel;
OUT a, b;
PARTS:
And(a = sel, b = in, out = b);
Not(in = sel, out = selNot);
And(a = in, b = selNot, out = a);
}
For some reason, this code fails on the test script values of in = 1 and sel = 0. It evaluates a and b both to 0 in this case.
I have written out the gates multiple times, and I can't figure out why the result is not a = 1 and b = 0
Can someone explain to me what is happening?
I have a feeling your Not implementation may have a problem.
Try replacing the Not with a Nand:
Nand(a=sel,b=sel,out=notSel); // notSel = ! sel
If this works, then your Not.hdl is incorrect.
Also, on a style point, it's clearer if you define your intermediates before your final outputs (ie: put the Nand first), and be consistent in your input ordering (ie: a=in, b=sel or notSel, out = a or b). Helps reduce the chance you will misread something.
Not sure that anything is wrong with your code. It looks to be the same as mine, which works. Have you tested your other And and Not gates?
My code:
Not(in=sel, out=notsel);
And(a=notsel, b=in, out=a);
And(a=in, b=sel, out=b);

Pass parameters between method name

I was wondering if you know of any programming language in which we can pass parameters inside method name. I'm guessing this could improve the code readability. I.e.
Lets say I want to multiply to integers in a method. Normally my method declaration would be something like:
function multiply(int a, int b){
return a*b;
}
However, it may be nice to be able to define it this way also:
function multiply (int a) times (int b){
return a*b;
}
This way, we could make a more explicit call in the code by calling:
var c = multiply(4)times(2);
This could have a greater impact on more complicated code and programming syntax.
Do you know if something like this exists?
Of course, there is Smalltalk which is really expressive with its keyword messages...
n := collection size // 2.
head := collection copyFrom: 1 to: n.
Other than that, you will find that in ADA or Python, and probably some others you can prefix each argument with a key (which should match the function parameter names)...

Concise notation for assigning `unique_ptr`?

I have a pointer to a parent class and I want to assign a new child object to that pointer conditionally. Right now, the syntax I have is rather lengthly:
std::unique_ptr<ParentClass> parentPtr;
if (...) {
parentPtr = std::unique_ptr<ParentClass>(new ChildClass1());
} else {
parentPtr = std::unique_ptr<ParentClass>(new ChildClass2());
}
Is there a good way of making this more readable / less lengthly?
Two possibilities would be:
std::unique_ptr<ParentClass> parentPtr(condition ?
(ParentClass*)new ChildClass1() :
(ParentClass*)new ChildClass2());
If condition is complicated, just assign a boolean to it and then write the construction. This solution only works for a binary condition though.
Another is to embrace C++14, and use
parentPtr = std::make_unique<ChildClass>();
First off, the "obvious" solution C ? new X : new Y does not work, since even if X and Y have a common base class A, the types X * and Y * have no common type. This is actually not so surprising after all if you consider that a class can have many bases (direct or indirect) and a given type may appear as a base multiple times.
You could make the conditional operator work by inserting a cast:
A * = C ? static_cast<A *>(new X) : static_cast<A *>(new Y);
But this would quickly get long and tedious to read when you try to apply this to your real situation.
However, as for std::unique_ptr, it offers the reset function which can be used to good effect here:
std::unique_ptr<A> p;
if (C)
{
p.reset(new X);
}
else
{
p.reset(new Y);
}
Now even if the actual new expressions are long, this is still nicely readable.

SystemVerilog: How come the enum next() method cannot be used in a constant function?

I have a package containing a number of packed-struct typedefs and I am trying to write a CONSTANT function to tell me the maximum bit width of these structs. Each struct has an explicit message_type which is enumerated. I believe the below function I have written should be interpreted by the compiler as constant, but I am getting the error "(vlog-2118) The function 'get_max_message_length' is not a valid constant function" (this is in ModelSim).
Can anyone tell me why this function is not constant? After debugging I have determined that it is the enum method 'next()' that is causing it to be interpreted wrong. Any possible alternate solutions? Thank you in advance!
typedef enum logic [7:0]
{
MESSAGE_TYPE_0=0,
MESSAGE_TYPE_1=1,
MESSAGE_TYPE_2=2
} _MSGTYPE;
function integer get_message_length (_MSGTYPE message_type);
case (message_type)
MESSAGE_TYPE_0: return ($bits(message_0));
MESSAGE_TYPE_1: return ($bits(message_1));
MESSAGE_TYPE_2: return ($bits(message_2));
default: return 0;
endcase
endfunction
function integer get_max_message_length ();
automatic _MSGTYPE largest = largest.first();
automatic _MSGTYPE next = next.first();
next = next.next();
while (next != next.first()) begin
largest = get_message_length(largest) > get_message_length(next) ? largest : next;
next = next.next();
end
return get_message_length(largest);
endfunction
A constant function has certain restrictions - it must be a pure function (i.e. have no side effects and return the same value if called with the same arguments).
This restriction propagates, so your constant function can only call other functions that are also pure functions. The problem you have is that next.next() is not a pure function - it does not return the same value every time you call it.
Sadly the SystemVerilog LRM doesn't appear to define any pure mechanism for accessing enumerated values - for example this would work if it were possible: for (int i=0; i<enum.num(); i++) size=get_message_length(enum.item(i));
Off the top of my head I can't think of a neat way to do this. You could create a localparam which was an array of enum values and iterate over that but you'd have to write out the enum values again.

How can I write pseudocode for the following diagram?

I failed to use the do-while or while loop for the following diagram:
Here, A, B, and C are functions.
How can I write pseudocode for the diagram above?
EDIT: This is from my programming practice of C++. Without the "B loop" (or the "A loop"), I am able to write it as the following:
Start
Input x;
while(x!=2)
{
A(); Input x;
}
C();
End
However, when the "B loop" comes in, I have no idea how to include it.
Start;
Input x;
while(x!=2){
if (x!=1){
A();
} else{
B()
}
Input x;
}
C();
End
But beware of the langage you are using I advise you to add a sleep mode between data aquisitions (Just before Input x)
#BaptisteGousset 's answer is good, but there is an alternative way that could be better under certain circumstances. It is possible to use a do...while loop instead of a while to simplify the code to remove the doubled Input operation, but this makes the comparative logic a little more complex.
Start;
Do
{
Input x;
if (x equals 1)
{
B();
}
elseif(x not equal to 2)
{
A();
}
} While (x not equal to 2);
C();
End;
You can also implement this using a goto statement, but goto is often considered harmful.
Generally, there is not a single canonical "pseudocode" answer for any flowchart - it depends on what structures you are willing to use and how elegantly those structures fit with your actual task.
What does the program do? Explain it in English, then write it down. You then have your pseudocode.
If any input
if input is not 1 and not 2
return a and do more input (? dont get the diagram here ;p)
if input is 1
return b and more input (??)
else if not above
return c and end program

Resources