Are wild MUL results a known bug, or is ML Emulate simply not to be trusted?

drbitboy

Lifetime Supporting Member
Join Date
Dec 2019
Location
Rochester, NY
Posts
7,873
Windows 10, x86_64,
RSLogix Micro Starter Lite
RSLogix Emulate 500 6.00.00.07 (CPR9)
RSLinx Classic 2.57.00.14 CPR 9 SR 3

See the attached ZIP: the result of a MUL instruction on 16-bit Sources 20077 and -20423 is 26176; it should be 26181; the should never be even.

Thanks.
 
If I do the roughly equivalent in a Do-more simulator, I get your "desired" result if i use 16 bit signed integers for the math. If I use reals for the sources or include a 1.0* in the equation, I get your "incorrect" integer result.

I suspect this means Emulate is doing floating point math even when only integers are used.
 
Doing the math on an ordinary calculator (Android tablet default) I get -410032571. I imagine it all depends on the final conversion of the intermediate result back to 16 bit integer. Since neither is correct it seems like the difference doesn't matter.
 
If I do the roughly equivalent in a Do-more simulator, I get your "desired" result if i use 16 bit signed integers for the math. If I use reals for the sources or include a 1.0* in the equation, I get your "incorrect" integer result.

I suspect this means Emulate is doing floating point math even when only integers are used.

I'll bet you're right.

I suspect the real, non-emulated MicroLogix hardware doesn't do this.

Thanks.
 
It matters very much

Doing the math on an ordinary calculator (Android tablet default) I get -410032571. I imagine it all depends on the final conversion of the intermediate result back to 16 bit integer. Since neither is correct it seems like the difference doesn't matter.

If we do a [Bitwise-inclusive AND] with -410032571 and 32767 (i.e. FFFFH) to get the lower 16 bits of the answer, we get the correct 16-bit result i.e. 26181, which is what I expect a non-emulated MicroLogix would yield from this program.

For example, a Linear Congruential Generator depends on correct behavior here; I had to re-implement the LCG in LONGs to make it work, even though the effective modulus was 32768.
 
Test case

I emulated Mike Nash's suggestion, that the bits are being lost in a floating-point multiply, here.;)

The results are consistent with what I see when [RSLogix Emulate500] is running, so it looks like that is the issue.

The test cases suggest that no more than five bits will be lost, plus the sign bit of course.

Thanks, Mike!
 
Yet another situation arises that "emulate" doesn't, if you get my meaning....

I personally would not trust any A-B emulator to test anything important, nor give it any credibility to reproduce what a physical controller will do.
 
This may sound strange but try it using all real numbers
I remember reading someplace a while back that you should never mix int and real numbers math functions in a plc
It has to do with the they are handled in a plc it is different then in a computer or calculator
 
Since I'm old enough to have learned Physics on a slide rule, and programming was strictly done with Integers a decade later... Then the 'Pentium Math Bug' hit the news to show that Floating Point / Real Number math had a basic flaw, I learned not to trust any Floating Point math without a 'Sanity Check'...

I still use Integers for 99% of my programming, and imply the decimal places with Tag Names like PSI_X100 :)
 
This may sound strange but try it using all real numbers
I remember reading someplace a while back that you should never mix int and real numbers math functions in a plc
It has to do with the they are handled in a plc it is different then in a computer or calculator

The original calculation used only integers, no mixing, but the result was off: the MUL of two ODD 16-bit INTEGERs was an EVEN INTEGER product.

The problem appears to be that it is not the program, but it is the EMULATOR that is MOVing INTEGERs into REALs, doing the multiply in REALs, and MOVing the REAL product back the an INTEGER result, which MOVe drops any LSBits after the first 24 MSBits, when in fact the most important part of the result is the 15 LSBITs.

The odd thing is that I cannot imagine that the emulator, whether written in C, Fortran, assembler or anything else, would have any trouble whatsoever multiplying two 16-bit integers and getting the correct result, so this is a design decision, perhaps to keep the freely-available emulator from being of any commercial use.

Hah, it would be funny, and not incredibly difficult, to go in and modify the binary emulator .EXE file to do it correctly.
 
Last edited:
Since I'm old enough to have learned Physics on a slide rule, and programming was strictly done with Integers a decade later... Then the 'Pentium Math Bug' hit the news to show that Floating Point / Real Number math had a basic flaw, I learned not to trust any Floating Point math without a 'Sanity Check'...

I still use Integers for 99% of my programming, and imply the decimal places with Tag Names like PSI_X100 :)

Yes, well, my slide rule that my Dad gave me is over 22" long*, so if we are going to start unzipping and measuring ... ;)

The point of the original post is that the program WAS using INTEGERs in the multiplication, but the emulator apparently overrides that for 16-bit INTEGERSs; with 32-LONGs the results are correct.

* and good to three sig figs, could I but find the dang cursor - "for want of a cursor the Least SigFig was lost ..."
 
Last edited:
I am mystified with the argumentation that multiplying 20077 and -20423 should result in 26181. Even if you argue that it is what the 16 LSB of the resulting long INT, that is never what should be the result of trying to squeze -410032571 into a 16-bit INT.
Your Micrologix should trigger a math overflow. It is the only "correct" result in this situation.
I bet that the emulator is only tested to provide correct results when the result falls within -32768 and 32767.

As I see it, your task requires you to multiply INTs (16 bit), which will produce a long INT (32 bit). So why bother with 16-bit INTs in the first place ?
 
Last edited:
Stale phart thread

Mike Nash solved this issue in the first response, yet this thread hangs around like a stale phart; I apologize for bringing it up.

JesperMP: Go back to the original post of this thread: no matter what you mistakenly believe the 16-bit INTEGER product of two odd 16-bit INTEGERS might be, the correct answer should never be even.

I am mystified with the argumentation that multiplying 20077 and -20423 should result in 26181. Even if you argue that it is what the 16 LSB of the resulting long INT, that is never what should be the result of trying to squeze into a 16-bit INT.

I don't understand why there is any mystery, because 26181 is obviously the correct result, and it is exactly what should be the result of squeezing -410032571 into a 16-bit INTEGER; in fact, that is precisely what the emulator does, when MOVing that value, as a 32-bit LONG, into a 16-bit INTEGER, with proper overflow handling; see the attached files.

Also, to look at it mathematically, although in decimal instead of hexadecimal or binary:

Code:
 20077 x -20423 = -410032571
-410032571 AND 65535 = 26181
Taking an alternate, but equivalent, approach yields the same correct result:
Code:
-410032571 / 65536 = -6256.6xxx
65536 x -6257 = -410058752
-410032571 - -410058752 = 26181

So, by using three separate (though equivalent) methods, including the emulator itself, it should be plain that 26181 is indeed the correct answer. The question is why the MUL operation in the emulator uses REALs instead of LONGs, as originally suggested by Mike Nash and verified (as much as possible) by me.

Your Micrologix should trigger a math overflow. It is the only "correct" result in this situation.

That there is a math overflow in this situation is about the only thing you got correct; how I choose to control and use the overflow and the result is my own affair.

I bet that the emulator is only tested to provide correct results when the result falls within -32768 and 32767.

You would lose that bet, because if you multiply 16-bit INTEGERs of 16384 and 3 in the emulator you get the correct low-16-bit answer of -16384; that assumes you handle the overflow correctly. Also if that is the level of testing, then that's a very very poor emulator, and someone was either naive or disingenuous in its design. Not that I am complaining or expecting it to be fixed: you get what you pay for and said emulator is free; the only reason I am using the emulator is that my test case is very simple and does not have physical I/O requirements, and I did not have an 1100 at hand. My only purpose in opening this thread was curiosity i.e. to understand the emulator's unexpected behavior and to bring it to others' attention; I knew all along that 32-bit integers were a workaround, but it was only later that I stumbled onto how to add a LONG data file to an 1100 program.

As I see it, your task requires you to multiply INTs (16 bit), which will produce a long INT (32 bit). So why bother with 16-bit INTs in the first place ?

Because I am only interested in the low 16 bits (15, actually).

In the end I had to go to 32-bit LONGs to get the correct 16-bit result from the emulator, obviously, but the point of this thread is why the 16-bit INTEGER MULtiply instruction gives the wrong answer in the emulator, while the MOVe instruction gives the correct answer.

I have another case where I MULtiply a 32-bit LONG by 1.1G in another LONG, and in that case I am still interested in the lower 31 bits regardless of any overflow condition. Should I have to go to 64-bit LONGLONGs? Are those even available on a MicroLogix controller? Why does a LONG MULtiply with overflow work correctly when the equivalent INTEGER multiply does not?

Since I only want the low 15 bits i.e. I want the result of

Code:
[[20077 x -20423] MOD 32768]

which will be identical, in the low 15 bits, to

Code:
[[20077 x (32768 - 20423)] MOD 32768]

but I don't have access to 32768 in signed, twos-complement 16-bit INTEGERs, however, what I want is available, in the low 15-bits, in this formula

Code:
[20077 x -20423] OR -32768

I do not care about overflow; I can turn on the [Math Overflow Selected] bit (S:2/14), and clear the [Overflow Trap] bit (S:5/0) when overflow occurs.
And every other CPU, that does 16-bit operations, will give me the correct result.

I'm still trying to get my hands on an actual 1100 to try this out; I suspect this is an emulator-only issue, but if not, then what the heck is going on?
 
Last edited:

Similar Topics

Replies
14
Views
3,344
HI All, I am trying to do some repeat logic on and existing code SLC504. The code is the same just the addresses are different, I have created...
Replies
11
Views
3,327
I am using a ML1400 to count the RPM of several items. They all use the same math to determine the RPM after 10 counts of the counter. The one...
Replies
8
Views
3,256
Hi there every one, I'm working in a PL7 program, (TSX 573623) the existing timer (FTON or %Tm) are working good. The problem is : when I add a...
Replies
2
Views
1,730
http://arstechnica.com/security/news/2010/09/stuxnet-worm-attacks-industrial-targets-could-be-aimed-at-iran.ars Great, all I need is to start...
Replies
2
Views
3,046
Back
Top Bottom