The following Modelica code resets variable 'bb' to 0 after it sets to 123. Can anyone explain why? I am using OpenModelica v1.13.2.
model test2
import Modelica.Utilities.Streams.print;
Real b(start=0, fixed=true);
Real bb(start=0, fixed=true);
Integer c(start=0,fixed=true);
algorithm
when sample(0,0.1) then
c := pre(c) + 1;
if c == 1 then
b := 12.3;
elseif c == 2 then
bb := 123;
end if;
print(String(time)+", "+String(b)+", "+String(bb));
end when;
end test2;
Simulation prints:
0, 12.3, 0
0, 12.3, 123
0, 12.3, 0
...(repeats)
Also screenshot of the plot:
The result is incorrect according to the Modelica 3.4 specification, and bb should not be set to zero:
At the start of the algorithm bb should be set to pre(bb) which is 123; according to "11.1.2 Execution of an algorithm in a model" https://specification.modelica.org/master/Ch11.html#execution-of-an-algorithm-in-a-model
Note that the semantics for when in equations give similar results but in a different way, in that case the specific when-clause is instead implicitly mapped to an if-then-else where the else-branch would set bb=pre(bb) according to section "8.3.5.1" - https://specification.modelica.org/master/Ch8.html#defining-when-equations-by-if-expressions-in-equality-equations
Related
This question already has answers here:
Verilog - what is the difference in use between vertical bar (|) and "or"
(2 answers)
Closed 6 months ago.
I am trying to wait for a change in 2 signals in following 2 ways.
Option 1: #(a or b)
Option 2: #(a || b)
If any change observed for any signal then I am trying to display the value as shown below.
module wait_test;
int a, b;
initial
begin
#10 a += 10;
#10 b += 10;
#10 a += 10;
#10 b += 10;
end
initial
forever
begin
#(a or b)
$display($time,"\ta = %0d,b = %0d", a, b);
end
endmodule
Result:
10 a = 10,b = 0
20 a = 10,b = 10
30 a = 20,b = 10
40 a = 20,b = 20
When I replace #(a or b) with #(a || b), I only observe 1st display with no errors. Please help me with the reason.
Result:
10 a = 10,b = 0
The or operator in this context is described in IEEE Std 1800-2017, section 9.4.2.1 Event OR operator. Whenever there is a change in either a or b, the $display statement will be executed, as you have seen.
The || operator is a simple logical OR. It will first evaluate the expression (a || b), then the event control # syntax will wait for a change in the expression, not the individual signals. At time 0, both signals are 0, which means the expression is 0. At time 10, a changes to 10, which means the expression changes to 1. Although the signals continue to change every 10 time units, the expression remains 1, so there are no further changes in the expression.
#(a || b) is not a typical construct. #(a or b) is a typical construct.
Also, your initial forever block is much more commonly coded as:
always #* begin
$display($time,"\ta = %0d,b = %0d", a, b);
end
How "inside" sub-expressions bit lengths are supposed to be computed in System Verilog?
It appears that the type of an expression depends on whether an operand is a numeric literal or a variable.
The following System Verilog program:
`define M( x ) $display( `"x -- %b`", x )
module top ();
bit [3:0] a, b;
initial begin
// (a+b) could be evaluated either to 0 or 16, depending on the bit length of the expression.
a = 15;
b = 1;
`M(4'd1 inside { [(a+b):17] } ); // 0
`M(4'd1);
`M( b inside { [(a+b):17] } ); // 1
`M( b);
end
endmodule
outputs:
Chronologic VCS simulator copyright 1991-2019
Contains Synopsys proprietary information.
Compiler version P-2019.06-SP1-1_Full64; Runtime version P-2019.06-SP1-1_Full64; May 8 20:27 2020
4'd1 inside { [(a+b):17] } -- 0
4'd1 -- 0001
b inside { [(a+b):17] } -- 1
b -- 0001
V C S S i m u l a t i o n R e p o r t
Time: 0
CPU Time: 0.250 seconds; Data structure size: 0.0Mb
Fri May 8 20:27:08 2020
PS: Verific interprets the standard differently from Synopsys.
It's definitely a tool bug that it produces different results for two different operands of the same value and width.
However, the correct answer is slightly ambiguous because the inside operator was left out of Table 11-21—Bit lengths resulting from self-determined expressions in the IEEE 1800-2017 LRM. This is a reported issue for the LRM, and the consensus is that is should behave the same as the case inside statement in that all operands get sized to the largest size operand before doing any comparisons. In this example, the literal 17 is 32-bits wide and has the largest width. So the result of the inside operator should be 1'b0.
I am wondering how I can make a unit test to automatically stop, once an error in the system under test (sut) occurs?
Let's assume, the unit test runs some 1,000 different input combinations, and is supposed to verify that the results are equal to the expectations. Now, let's further assume there is a simple syntax error in sut, which causes an error. In this case I would like the unit test to automatically stop and invoke the tear down method.
Is that possible?
Edit:
I am borrowing a MATLAB example from their help site (https://de.mathworks.com/help/matlab/matlab_prog/create-basic-parameterized-test.html) in order to show more clearly what I mean:
Here you can see the test class:
classdef TestCarpet < matlab.unittest.TestCase
properties (TestParameter)
type = {'single','double','uint16'};
level = struct('small', 2,'medium', 4, 'large', 6);
side = struct('small', 9, 'medium', 81,'large', 729);
end
methods (Test)
function testRemainPixels(testCase, level)
% expected number pixels equal to 1
expPixelCount = 8^level;
% actual number pixels equal to 1
actPixels = find(sierpinski(level));
testCase.verifyNumElements(actPixels,expPixelCount)
end
function testClass(testCase, type, level)
testCase.verifyClass(...
sierpinski(level,type), type)
end
function testDefaultL1Output(testCase)
exp = single([1 1 1; 1 0 1; 1 1 1]);
testCase.verifyEqual(sierpinski(1), exp)
end
end
methods (Test, ParameterCombination='sequential')
function testNumel(testCase, level, side)
import matlab.unittest.constraints.HasElementCount
testCase.verifyThat(sierpinski(level),...
HasElementCount(side^2))
end
end
end
Here's the system under test:
function carpet = sierpinski(nLevels,classname)
if nargin == 1
classname = 'single';
end
% original line: mSize = 3^nLevels;
mSize = "That's clearly wrong here";
carpet = ones(mSize,classname);
cutCarpet(1,1,mSize,nLevels) % begin recursion
function cutCarpet(x,y,s,cL)
if cL
ss = s/3; % define subsize
for lx = 0:2
for ly = 0:2
if lx == 1 && ly == 1
% remove center square
carpet(x+ss:x+2*ss-1,y+ss:y+2*ss-1) = 0;
else
% recurse
cutCarpet(x + lx*ss, y + ly*ss, ss, cL-1)
end
end
end
end
end
end
I changed the definition of mSize to a string to produce an error. Now, if I run the tests, all tests will result in an error. I am wondering if it is possible to stop the tests as soon as possible, i.e. after the occurence of the first error?
The problem that I see is that the test code won't even reach the last line of testRemainPixels (testCase.verifyNumElements(actPixels,expPixelCount)). A fatalAssert does not help at this point, right?
Assuming you are using the test framework built into MATLAB, take a look at the types of qualifications, in particular the bulleted list at the top of this page:
https://www.mathworks.com/help/matlab/matlab_prog/types-of-qualifications.html
If you want to stop the entire testing session you can use fatal assertions. If you want other tests to continue you can use assertions. If you want to skip all the test methods (and parameterizations) in a single file you can use an assertion in TestClassSetup or just add a basic "smoke" level exercise step of the code in TestClassSetup and if it errors it will behave like an assertion.
Hope that helps.
The following code
model FunctionCall
Boolean result;
function F
input Real p1;
output Boolean result;
algorithm
result :=p1 < 0.5;
end F;
algorithm
result :=F(time);
end FunctionCall;
(also described in http://www.modelica-forum.com/forums/index.php?showtopic=2) still throws an error in Dymola 2018FD01, while in OpenModelica it is accepted.
Is this wrong Modelica code or a Dymola bug?
Thanks in advance.
The model is incorrect.
3.8 "For an assignment v:=expr or binding equation v=expr, v must be declared to be at least as variable as expr"
Boolean variables are discrete-time expressions according to 3.8.3 "Discrete-time variables, i.e., Integer, Boolean, String variables and enumeration variables, as well as Real variables assigned in when-clauses"
F(time) is not a discrete-time expression, since 3.8.3 only includes "Function calls where all input arguments of the function are discrete-time expressions"
All according to Modelica 3.4.
The reason is that Boolean variables in models should only change at events, and the result of a function such as F(time) can neither guarantee that nor reliably generate events.
Hans answer is the correct one for your question.
Your unasked question may be how one can get the same behavior within the language specifications. Below I have provided one possible solution.
model FunctionCall
Boolean result;
function F
input Real p1;
output Integer result;
algorithm
result := if p1 < 0.5 then 1 else 0;
end F;
algorithm
result := if F(time) < 0.5 then false else true;
end FunctionCall;
I would like to use the pseudo_encrypt function mentioned a few times on StackOverflow to make my IDs look more random: https://wiki.postgresql.org/wiki/Pseudo_encrypt
How can I customize this to output unique "random" numbers for just me. I read somewhere that you can just change the 1366.0 constant, but I don't want to take any risks with my IDs as any potential ID duplicates would cause major issues.
I really have no idea what each constant actually does, so I don't want to mess around with it unless I get some direction. Does anyone know which constants I can safely change?
Here it is:
CREATE OR REPLACE FUNCTION "pseudo_encrypt"("VALUE" int) RETURNS int IMMUTABLE STRICT AS $function_pseudo_encrypt$
DECLARE
l1 int;
l2 int;
r1 int;
r2 int;
i int:=0;
BEGIN
l1:= ("VALUE" >> 16) & 65535;
r1:= "VALUE" & 65535;
WHILE i < 3 LOOP
l2 := r1;
r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
r1 := l2;
l1 := r2;
i := i + 1;
END LOOP;
RETURN ((l1::int << 16) + r1);
END;
$function_pseudo_encrypt$ LANGUAGE plpgsql;
for bigint's
CREATE OR REPLACE FUNCTION "pseudo_encrypt"("VALUE" bigint) RETURNS bigint IMMUTABLE STRICT AS $function_pseudo_encrypt$
DECLARE
l1 bigint;
l2 bigint;
r1 bigint;
r2 bigint;
i int:=0;
BEGIN
l1:= ("VALUE" >> 32) & 4294967295::bigint;
r1:= "VALUE" & 4294967295;
WHILE i < 3 LOOP
l2 := r1;
r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767*32767)::bigint;
r1 := l2;
l1 := r2;
i := i + 1;
END LOOP;
RETURN ((l1::bigint << 32) + r1);
END;
$function_pseudo_encrypt$ LANGUAGE plpgsql;
Alternative solution: use different ciphers
Other cipher functions are now available on postgres wiki. They're going to be significantly slower, but aside from that, they're better candidates for generating customized random-looking series of unique numbers.
For 32 bit outputs, Skip32 in plpgsql will encrypt its input with a 10 bytes wide key, so you just have to choose your own secret key to have your own specific permutation (the particular order in which the 2^32 unique values will come out).
For 64 bit outputs, XTEA in plpgsql will do similarly, but using a 16 bytes wide key.
Otherwise, to just customize pseudo_encrypt, see below:
Explanations about pseudo_encrypt's implementation:
This function has 3 properties
global unicity of the output values
reversability
pseudo-random effect
The first and second property come from the Feistel Network, and as already explained in #CodesInChaos's answer, they don't depend on the choice of these constants: 1366 and also 150889 and 714025.
Make sure when changing f(r1) that it stays a function in the mathematical sense, that is x=y implies f(x)=f(y), or in other words the same input must always produce the same output. Breaking this would break the unicity.
The purpose of these constants and this formula for f(r1) is to produce a reasonably good pseudo-random effect. Using postgres built-in random() or similar method is not possible because it's not a mathematical function as described above.
Why these arbitrary constants? In this part of the function:
r2 := l1 # ((((1366.0 * r1 + 150889) % 714025) / 714025.0) * 32767)::int;
The formula and the values 1366, 150889 and 714025 come from Numerical recipes in C (1992, by William H.Press, 2nd ed.), chapter 7: random numbers, specifically p.284 and 285.
The book is not directly indexable on the web but readable through an interface here: http://apps.nrbook.com/c/index.html .It's also cited as a reference in various source code implementing PRNGs.
Among the algorithms discussed in this chapter, the one used above is very simple and relatively effective. The formula to get a new random number from a previous one (jran) is:
jran = (jran * ia + ic) % im;
ran = (float) jran / (float) im; /* normalize into the 0..1 range */
where jran is the current random integer.
This generator will necessarily loop over itself after a certain number of values (the "period"), so the constants ia, ic and im have to be chosen carefully for that period to be as large as possible. The book provides a table p.285 where constants are suggested for various lengths of the period.
ia=1366, ic=150889 and im=714025 is one of the entries for a period of
229 bits, which is way more than needed.
Finally the multiplication by 32767 or 215-1 is not part of the PRNG but meant to produce a positive half-integer from the 0..1 pseudo-random float value. Don't change that part, unless to widen the blocksize of the algorithm.
This function looks like a blockcipher based on a Feistel network - but it's lacking a key.
The Feistel construction is bijective, i.e. it guarantees that there are no collisions. The interesting part is: r2 := l1 # f(r1). As long as f(r1) only depends on r1 the pseudo_encrypt will be bijective, no matter what the function does.
The lack of key means that anybody who knows the source code can recover the sequential ID. So you're relying on security-though-obscurity.
The alternative is using a block cipher which takes a key. For 32 bit blocks there are relatively few choices, I know of Skip32 and ipcrypt. For 64 bit blocks there are many ciphers to choose from, including 3DES, Blowfish and XTEA.