PLCS.net - Interactive Q & A

PLCS.net - Interactive Q & A (http://www.plctalk.net/qanda/index.php)
-   LIVE PLC Questions And Answers (http://www.plctalk.net/qanda/forumdisplay.php?f=2)
-   -   Are wild MUL results a known bug, or is ML Emulate simply not to be trusted? (http://www.plctalk.net/qanda/showthread.php?t=123215)

drbitboy January 1st, 2020 12:30 AM

Are wild MUL results a known bug, or is ML Emulate simply not to be trusted?
 
1 Attachment(s)
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.

Mike Nash January 1st, 2020 11:15 AM

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.

bernie_carlton January 1st, 2020 01:23 PM

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.

drbitboy January 1st, 2020 02:07 PM

Quote:

Originally Posted by Mike Nash (Post 835815)
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.

drbitboy January 1st, 2020 02:14 PM

It matters very much
 
Quote:

Originally Posted by bernie_carlton (Post 835819)
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.

drbitboy January 2nd, 2020 05:45 PM

Test case
 
I emulated Mike Nash's suggestion, that the bits are being lost in a floating-point multiply, here.:bonkhead:

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!

daba January 3rd, 2020 08:35 PM

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.

GaryS January 3rd, 2020 09:05 PM

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

Gene Bond January 5th, 2020 08:20 AM

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 :)

drbitboy January 5th, 2020 04:11 PM

Quote:

Originally Posted by GaryS (Post 836040)
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.

drbitboy January 5th, 2020 04:20 PM

Quote:

Originally Posted by Gene Bond (Post 836092)
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 ..."

GaryS January 5th, 2020 08:17 PM

Here are a few places to check out
https://www.dummies.com/programming/...-point-values/

http://www.differencebetween.net/sci...-and-integers/

drbitboy January 5th, 2020 09:37 PM

Quote:

Originally Posted by GaryS (Post 836123)

Thank you, but that does not help because the problem is a bug in the emulator. I have already implemented the workaround: use LONGs instead of INTEGERs.

JesperMP January 6th, 2020 06:48 AM

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 ?

drbitboy January 6th, 2020 10:11 AM

Stale phart thread
 
1 Attachment(s)
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.

Quote:

Originally Posted by JesperMP (Post 836147)
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.

Quote:

Originally Posted by JesperMP (Post 836147)
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.

Quote:

Originally Posted by JesperMP (Post 836147)
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.

Quote:

Originally Posted by JesperMP (Post 836147)
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?


All times are GMT -5. The time now is 05:16 AM.

.