Home
Prox / RFID
Verichips
Ladder Logic
[interfacing] †
Tube Joints
Key Code From Photo
SolveSpace (3d CAD)
SketchFlat (2d CAD)
Photographs
Miscellany
Resume / Consulting
Contact Me

LDmicro Forum - Byte Code Generation

(you are viewing a thread; or go back to list of threads)

Byte Code Generation (by Nic Pablo)
Hi Jonathan,
Your compiler is a very good one. Congratulations and thanks as the generated Byte Codes truly has shortened my development time for an embedded PLC system. I just have a couple of discussion items.
1. I understand that bit variables with addresses 1 & 0 are reserved for the system, in one of my tests ( pls see attached photo) i found out that another "stray(?)" bit variable 3 was automatically generated at the *.int file. How is the variable allocation done? Will there be any other variable x that will be generated as the ladder gets complicated?

2. There is also an automatically generated integer variable with address 1. Is it the same case as above?
Thu Sep 2 2010, 02:52:53, download attachment Byte Code Voyeur.JPG
(no subject) (by Jonathan Westhues)
Yes, the compiler will reserve certain bit and integer variables for its own internal use. These are used for stuff like the intermediate state of rungs in series or parallel. The exact number and location of reserved variables is not documented, and should not be relied upon.

When it's necessary to identify a particular variable within the bytecode interpreter (for example, for input or output), the variable should be identified by its name, not its address. The names and addresses of all user-specified variables appear in the .int file, in the $$bits and $$int16s sections.
Sun Sep 5 2010, 03:49:23
Byte Code Generation (by Nic Pablo)
Thanks Jonathan! It is important for me to track all variables because my application will have to remap all of them in the embeddedPLC environment. I am in fact thinking now on how to implement ADC & UART which are equally not supported by LDMicro in ByteCode generation mode. I found a way though but it may somehow deviate from ladder standards.
Cheers everyone!
Mon Sep 6 2010, 12:13:25
(no subject) (by Jonathan Westhues)
It's intended that special input and output devices (for example, your ADC or UART) be implemented using special variables. For example, you could define the integer variable Ain0 as corresponding to the first A/D input. Your virtual machine would then write the result of that A/D conversion into the variable Ain0 (identifying it by name, and then mapping that to an address using the information in the $$int16s section) every cycle.

See the sample interpreter for an example of this. The bit variable Xosc is supplied as an input to the program, and the integer variable a is obtained as an output from the program, and printed.
Mon Sep 6 2010, 12:28:18
Byte Code Generation (by nic pablo)
Splendid inputs from the software author himself! I'm almost done with the *.int parser & intetpreter but stumbled on this issue. Thanks Jonathan. I'm planning to port the ladder drawing part to full windows GUI after this project ( unless you are working it out already)
Tue Sep 7 2010, 04:29:24
RE: Byte Code Generation (by Peter Elliot)
Is it possible to import a list of registers into LDmicro, with preset addresses, to ensure registers for I/O, Ethernet communication, etc are always located at the same place? At present the addresses seem to be assigned on a first come first served basis.

Secondly, is there any way for a bit register to be able to be set to a specific bit of a numeric register. If for example the digital inputs (x16) were assigned to InputWord, would it be possible to assign Xi0 to InputWord bit 0? This would be similar to a PIC I/O Port...

Finally (for now ;-) I looked at the output and if I have a rung with multiple parallel outputs - in my case setting up a series of registers and toggling a bit - the output code from LDmicro seems to place a comparison before each MOV with a single element jump rather than jump to the end of the parallel task at the top and then simply assigning the outputs without further checks.

I'm looking to embed a LDmicro interpreter into a piece of Industrial I/O communicating via Ethernet.
Thu Oct 7 2010, 11:54:27
(no subject) (by Jonathan Westhues)
There is no way to specify which name goes at which address. As you observe, the assignment is arbitrary. So if you would like to place certain names at certain addresses, then your interpreter can rewrite the addresses according to your preference, using the information in the $$bits and $$int16s sections.

Your interpreter could also map certain bit variables and certain integer variables onto the same physical memory, for example to access the same I/O port either as individual bit variables or as a 16-bit integer.

In general, a bytecode interpreter can implement almost any desired feature using special memory-mapped bit or integer variables.

I don't completely understand your final question. But I would note that the code that LDmicro generates is not optimized for size. Since I am the only developer (even though LDmicro has been GPL'd free software for about three years now, no one else has written even a single line of code), my first priority is correctness and simplicity of implementation, not size or speed.
Thu Oct 7 2010, 22:37:12
(no subject) (by Peter Elliot)
Hi Jonathan,

Thank you for your prompt reply. I will look into the $$bits and $$int16s section of the .int file to look at substituting the fixed addresses with those generated by the compiler.

I think for the last question I may have been looking at the output using LDinterpret...

A simple parallel output rung which loads three registers on the rising edge of an input became:

000: bits[000] := 1
001: bits[001] := bits[000]
002: unless (bits[002] clear) jump 003+1
003: bits[001] := 0
004: bits[003] := bits[001]
005: unless (bits[004] set) jump 006+1
006: bits[001] := 0
007: bits[004] := bits[003]
008: bits[005] := 0
009: bits[006] := bits[001]
00a: unless (bits[006] set) jump 00b+1
00b: int16s[000] := 10 (0x000a)
00c: unless (bits[006] set) jump 00d+1
00d: bits[005] := 1
00e: bits[006] := bits[001]
00f: unless (bits[006] set) jump 010+1
010: int16s[001] := 10 (0x000a)
011: unless (bits[006] set) jump 012+1
012: bits[005] := 1
013: bits[006] := bits[001]
014: unless (bits[006] set) jump 015+1
015: int16s[002] := 200 (0x00c8)
016: unless (bits[006] set) jump 017+1
017: bits[005] := 1
018: bits[001] := bits[005]
019: <end of program>

whereas lines 00a on could have been:

00a: unless (bits[006] set) jump 00d+1
00b: int16s[000] := 10 (0x000a)
00c: int16s[001] := 10 (0x000a)
00d: int16s[002] := 200 (0x00c8)
00e: unless (bits[006] set) jump 010+1
010: bits[005] := 1
011: bits[001] := bits[005]
012: <end of program>

With the likely performance of the cpu in the I/O block these extra tests would probably not be significant. Adding too much optimization can also lead to code reliability issues - code reliability has to be the first priority.

I'm currently getting the tools together to be able to compile the LDmicro source, and if the project goes ahead I may be able to spend some time on the byte code generation - possibly adding the ability to preset variable registers.

I'm very impressed with what you've done, and would love to be able to use it in my application - your hard work will definitely save me many (many) hours of coding.

Regards,

PJE
Fri Oct 8 2010, 07:53:09
(no subject) (by Jonathan Westhues)
As far as variables at fixed addresses: I actually prefer the current behavior. Now, the generated bytecode is the same for the same input program (.ld file), no matter what interpreter will ultimately run that bytecode. If it were possible to pre-specify the addresses for certain variables, then this wouldn't be true.

The generated code could indeed be improved significantly. In the particular example that you show, the output state of the rung is calculated, even though that's not needed, since these are the rightmost elements in the rung. The types of programs that people usually write in ladder tend to be simple enough that I didn't expect that to be a big issue; though I've been surprised by the size of programs I've seen people posting here.

Let me know if you have any other questions about the bytecode target.
Sun Oct 10 2010, 18:55:06
(no subject) (by Peter Elliot)
Jonathan,

With regard to fixed addresses, I was really meaning fixed variable offset. This a integer register 'IP1' could be assigned an address of 1000 and 'IP2' would be 1001. In that way these preset variable offsets could be mapped more easily to specific memory locations within the target without needing to parse the byte code changing the addresses.

Basically I would like to be able to assign a pin number to each variable, and also able to import a table of preset variables before I start programming which set up the target variables.

PJE
Thu Oct 14 2010, 08:00:14
(no subject) (by Jonathan Westhues)
I understand what you're saying. But if I did that, then LDmicro would have to read an address mapping file when it generated the bytecode, and a different address mapping file would result in different byte code. I don't like this.

You need some tool to load the .int file into your VM (and maybe translate it into a slightly different format; the default LDmicro format is intended to be simple, not efficient) anyways. That tool can already remap the addresses however you want, according to the information in the $$bits and $$int16s sections. So you already can do everything you're asking for, without the risk e.g. of someone generating code with the wrong address mapping file and then wondering why it didn't work.
Thu Oct 14 2010, 23:42:28
(no subject) (by BoumPower (Switzerland))
Hi
You can take a surf on http://sourceforge.net/projects/ldcompiler

I'm writing a command-line compiler to produce both C code and Virtual Machine code.

The C code is working (I use with Microchip C18 and PIC18F4550)

The VM code is not working yet, but I have started to revisit for more performance and features (I added lot of VM Code and chanded some of them to be better adapted to microchip hardware)

I will use VM code in two way :
- a (slow, but with big ladder) PLC with VM code in external memory.
- a similar output than LDmicro, but with an external assembler (CALM macro assembler) that can target other processor.

I will also add new primitive in LDMicro.

Think it could be a nice idea to make our efforts together

Best regards
Tue Oct 19 2010, 05:30:46
Post a reply to this comment:
Your Name:
Your Email:
Subject:
(no HTML tags; use plain text, and hit Enter for a line break)
Attached file (if you want, 5 MB max):