[MOD 0.12.x][0.0.2] Programmable Controllers

Topics and discussion about specific mods
lukeplechaty
Burner Inserter
Burner Inserter
Posts: 5
Joined: Sun Feb 23, 2014 10:30 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by lukeplechaty »

y.petremann are you still working on this as i wood like to have an update please if your not i wood like to update if for you :)
+ i did found some bugs but i fix them
++ your texturs for 4E and 4F is wrong just to let you know

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

lukeplechaty wrote:y.petremann are you still working on this as i wood like to have an update please if your not i wood like to update if for you :)
+ i did found some bugs but i fix them
++ your texturs for 4E and 4F is wrong just to let you know
Just for information, the mod is not dead, You can submit your own ideas to this git, for now I've mainly made performances optimizations through memory caching and added preview graphics for new instructions. but anything that complete or optimize the mod is welcome.

Here is my actual todo list by order of importance :
- Finishing instructions
- Fixing CPU execution order (so first cpu of a group would always run his code before the next one)
- Paralelism (would permit to have sub tick communication between programs)
- High speed circuit communication (Any high speed circuit component could read and write in the circuit network at very hight speed )
- Adding a 8 channel sound module (It would add 8 programmable sound emitters directly accessible, volume would be accessed through the 2n cell, type and pitch through 2n+1 cell)

lukeplechaty
Burner Inserter
Burner Inserter
Posts: 5
Joined: Sun Feb 23, 2014 10:30 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by lukeplechaty »

i must ask, this is built to ack like assembly language right, if so what chip set is it base on, as i dont know it, it good to know, i rewrote the instructions to ack more like pic chip set for me, ie value can only be edit in the register and memory can only be move in and out of register by the instructions.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

lukeplechaty wrote:i must ask, this is built to ack like assembly language right, if so what chip set is it base on, as i dont know it, it good to know, i rewrote the instructions to ack more like pic chip set for me, ie value can only be edit in the register and memory can only be move in and out of register by the instructions.
The fact is that I took inspiration on 4 different assembly instructions set, one of them is arm itself. There is some facts about this language, some more about lore, and ingame technical stuff, and other about game performance and capability :
  • At the first time, the processor was designed to be a everything on memory and everything is rewritable, so including instructions themselves and module parameters (this including control pointer, enable state and more), but modifying signals are not easy, and addition/removal of mods could corrupt the processor. So I decided memory cells would be based on classic signals, and since everything is memory, instructions would be represented by signals.
  • Next is the fact that the easiest way to get integrated with game mechanics is to use them, so constant combinator is the best way to handle memory. And with natural connection to the circuit network, it's possible to read and write to it with little interaction (reading circuit network is only necessary when reading a specific memory cell and writing is only needed when writing a slot in the constant combinator).
  • The programmable controller need real time access to the circuit network, it should have the possibility to execute his program each tick to read everything it needs and write it back, the base CPU run at about 128 instructions per tick, so almost 7.7kHz and each module have 16 memory cells, a decent grid would have 32 modules which result in 512 memory cells (instructions and variables mixed), the cycle and memory availability makes it hard to create really complex programs like we could have on Arduino, Pics and other micro-controllers, so the instructions set needed to let shorter operations.
  • The processors and memory limits have been chosen based on gameplay and performance, the processor basicaly run 128 ticks to allow a easy way to do electricity based graph, which use availlable graph height, and alos permit to easily display percentage, memory is based on hexadecimal number representation which could be simplified to MMMC where MMM is module sector and C the module cell address, an upgrade to 32 cell could be envisaged.
  • The game is basically set in a distant future, our engineer almost know everything from aeronautics, nuclear, mechanical, logistics and electronics. The instructions are basically a reflection of this, our engineer made the circuitry of this computer, so why would he make a circuit that limit his possibilities.
  • One fun fact is as everything is in memory cell, can be get and set, it's possible to make the program to self-modify and so make really cool stuff.)
  • Some instructions on other assembly languages used some registers for secondary arguments and function return, to avoid that, I needed to design instructions to only use the instruction parameter and the register.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

lukeplechaty wrote:i must ask, this is built to ack like assembly language right, if so what chip set is it base on, as i dont know it, it good to know, i rewrote the instructions to ack more like pic chip set for me, ie value can only be edit in the register and memory can only be move in and out of register by the instructions.
If you have an alternative instruction set, please feel free to share.

lukeplechaty
Burner Inserter
Burner Inserter
Posts: 5
Joined: Sun Feb 23, 2014 10:30 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by lukeplechaty »

y.petremann wrote:If you have an alternative instruction set, please feel free to share.
Ill share them when i have got them all workinhg right and updated to you code (your code more beter then mine :D )

Nightinggale
Fast Inserter
Fast Inserter
Posts: 120
Joined: Sun May 14, 2017 12:01 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Nightinggale »

This mod sounds really awesome. There is not really any end to what I want to do with it and I suspect it's not that hard to use once you get started and get to know the system. Unfortunately it seems that the learning curve is quite steep.

Figuring that it would be best to start simple, I decided on a really simple task. I made a loop of belts and put an item there. I then made a circuit network, which provides a pulse each time the item pass. I then set up a combinator, which counts the amount of pulses and outputs the result to a nixie display. That works as intended and expected.

My next step is to make a program, which does the very same thing. I have come as far as setting up input/output for circuit network, a memory and a CPU. The plan is:
  • read input signal
  • add together with int from memory
  • write result to the same address in memory
  • write result to output
  • loop (presumably jump and wait a tick to ensure it runs just once each tick)
The problem here is that I don't really know where to start. If everything is memory, then the input has a memory address and it's a question of reading that one. However how to I figure out the address? What if I add another container. How will that affect addresses? Can addresses change if I add/remove "containers"?

I think it's a good example. It's really simple and should be easy to understand, but at the same time, it handles I/O, memory and programming of the CPU, meaning it covers all the basics. Once you figure out this much, you should have figured out the engine and moving on is a matter of asm programming knowledge/skills.

I would really like a blueprint string of a working setup of this example. A screenshot is nice, but getting the setup ingame to examine is even better and might be just what this mod needs to get people started.


Some thoughts on this mod:

What if each container has an extra slot, which is hardcoded to always contain an address signal? That way the address is easily accessible and it can be changed by the player if that makes sense. For instance it could make sense to to have I/O ports starting at say 4096 to leave room for expansion of the program in the low address space to have a sequential program. Back in the 8 bit days it wasn't unusual to have expansions and similar on specific addresses, meaning if you had 16 kB memory and you added a 4 kB ROM, the address was rarely at the end of the memory. Instead it could be at the address of say 40k, meaning the ROM would contain hardcoded addresses, which worked in both 16 and 32 kB systems. Leaving gaps in your address space can be surprisingly beneficial on systems without virtual memory support.

It seems that all items have a contents of 16, which makes me wonder. Why use ROM if you can add a second CPU next to the existing one and get more CPU power while gaining the same amount of storage. It might be worth considering if CPUs should have just one slot, which is the address of where in the ROM to start running the program.

I will likely have more feedback once I can actually manage to get a program running.
y.petremann wrote:
  • One fun fact is as everything is in memory cell, can be get and set, it's possible to make the program to self-modify and so make really cool stuff.)
So basically we can blame you for creating the foundation for Skynet :lol:

Nightinggale
Fast Inserter
Fast Inserter
Posts: 120
Joined: Sun May 14, 2017 12:01 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Nightinggale »

mod page wrote:The icons should be self explanatory, but their is 4 main things :
- #V is the value in the instruction
- @A is an address to a memory cell
- &P is an address to a pointer to a memory cell
- %R is the cpu register
- §C represent the CPU control status and pointer
There are @A, %A and #A when you look ingame. &P is not used, nor is §C or #V.

It's also not clear where the result is placed. For instance "20: add %R to #A" could write the result to either #A or %R. Maybe there is some ASM convention that the result is always put in %R, but then it would be nice to tell this explicitly in the mod documentation. It's not like we are all ASM experts :?

Similarly I had to research the skip instructions. Turns out that they skip the next instruction if condition is true. That would be useful to add to mod documentation.
mod page wrote:modules get their address from their position sorted top-bottom left-right.
Wouldn't that cause havoc if you expand after writing a program? It did however answer my question about figuring out addresses, though it's not as simple, or stable as I would like.

Some icons have a mismatch between icon and text. For instance 21 says SUB in the icon, but ADD in the text. Also the text keys are missing starting from 50. Normally I would view something like this as a minor GUI glitch, but it does make it harder to experiment with the mod.

EDIT: how do I init the program? It seems that whenever I start the CPU, it sets a jump instruction at address 2 and then it keeps on increasing that one. This makes me suspect that the contents of the CPU is actually registers and not memory, but I'm not certain.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

Nightinggale wrote: My next step is to make a program, which does the very same thing. I have come as far as setting up input/output for circuit network, a memory and a CPU. The plan is:
  • read input signal
  • add together with int from memory
  • write result to the same address in memory
  • write result to output
  • loop (presumably jump and wait a tick to ensure it runs just once each tick)
The problem here is that I don't really know where to start. If everything is memory, then the input has a memory address and it's a question of reading that one. However how to I figure out the address? What if I add another container. How will that affect addresses? Can addresses change if I add/remove "containers"?

I think it's a good example. It's really simple and should be easy to understand, but at the same time, it handles I/O, memory and programming of the CPU, meaning it covers all the basics. Once you figure out this much, you should have figured out the engine and moving on is a matter of asm programming knowledge/skills.
Each device have exactly 16 memory slots, memory slot get addresses from device and device get his adress from it's order in the device list, the device list is sorted each time any device is added, and his ordering goes from left to right and top to bottom, so is you add/remove devices below or right of them, they keep their adresses, If at another place, then their adress is modified, I would suggest to design your CPU like a square and with empty memory, so if you need to medify to CPU or connector, everything is still fine.
Nightinggale wrote: I would really like a blueprint string of a working setup of this example. A screenshot is nice, but getting the setup ingame to examine is even better and might be just what this mod needs to get people started.
Sure that would be great, for now I'm making the next release that is not easy, basicaly I'm trying to make the programmable controller mod separate to instructions sets mods and to devices mods, so I could either way update the engine, update/add modules or work on instructions sets with different themes.
If I get to the point where I can add instructions from another mod, then anybody could write their own instructions sets, also I could really work at making a lot of demos with blueprints.
Nightinggale wrote: Some thoughts on this mod:

What if each container has an extra slot, which is hardcoded to always contain an address signal? That way the address is easily accessible and it can be changed by the player if that makes sense. For instance it could make sense to to have I/O ports starting at say 4096 to leave room for expansion of the program in the low address space to have a sequential program. Back in the 8 bit days it wasn't unusual to have expansions and similar on specific addresses, meaning if you had 16 kB memory and you added a 4 kB ROM, the address was rarely at the end of the memory. Instead it could be at the address of say 40k, meaning the ROM would contain hardcoded addresses, which worked in both 16 and 32 kB systems. Leaving gaps in your address space can be surprisingly beneficial on systems without virtual memory support.
I think that if I add an extra slot, it would simply to indicate the actual address of the device, keep in mind that outputung connector will use a signal that will always be outputed. I would not allow modification of address, also the way you setup your controller grid define the adresses. also I think I will move from base16 to base10
so it would be easier to calulate the addresses.
Nightinggale wrote: It seems that all items have a contents of 16, which makes me wonder. Why use ROM if you can add a second CPU next to the existing one and get more CPU power while gaining the same amount of storage. It might be worth considering if CPUs should have just one slot, which is the address of where in the ROM to start running the program.
Basicaly every device must have the same adress space lenght, Basicaly I want to move to a CPU architechture that enable stacks and calls, so every cell in the cpu could be managed manually or by the corresponding instructions but ROM is garanted to not be modified unless an instruction specifically use the coresponding adress while CPUS can modify any cell inside themselve for any instruction, you can still pout your entire program inside the CPU, but beware of instruction that would modify what you want to keep !
Nightinggale wrote:
mod page wrote:The icons should be self explanatory, but their is 4 main things :
- #V is the value in the instruction
- @A is an address to a memory cell
- &P is an address to a pointer to a memory cell
- %R is the cpu register
- §C represent the CPU control status and pointer
There are @A, %A and #A when you look ingame. &P is not used, nor is §C or #V.
Basicaly it's a mistake that I'm resolving for the next release. Letters will be used the right way.for now consider that &P=&A, #V=#A, §C=§A.
Nightinggale wrote: It's also not clear where the result is placed. For instance "20: add %R to #A" could write the result to either #A or %R. Maybe there is some ASM convention that the result is always put in %R, but then it would be nice to tell this explicitly in the mod documentation. It's not like we are all ASM experts :?

Similarly I had to research the skip instructions. Turns out that they skip the next instruction if condition is true. That would be useful to add to mod documentation.
Here is another issue I tend to resolve with next release, For now their is not official documentation, but I will make tooltips more explicit so it will get easier to know what an instruction does.
Nightinggale wrote:
mod page wrote:modules get their address from their position sorted top-bottom left-right.
Wouldn't that cause havoc if you expand after writing a program? It did however answer my question about figuring out addresses, though it's not as simple, or stable as I would like.
It's the way it should works, the original mod was not predicable and adresses were depending to their positions, so moving a device would break the adress space, here it works on relative space, so things are predicable and keep working if the device is moved ...
Nightinggale wrote: Some icons have a mismatch between icon and text. For instance 21 says SUB in the icon, but ADD in the text. Also the text keys are missing starting from 50. Normally I would view something like this as a minor GUI glitch, but it does make it harder to experiment with the mod.
For now it's worse, there is a mismatch between icon, text and function ... because creating an hundred of instructions is not fun and I can be messy at the end ...
Nightinggale wrote: EDIT: how do I init the program? It seems that whenever I start the CPU, it sets a jump instruction at address 2 and then it keeps on increasing that one. This makes me suspect that the contents of the CPU is actually registers and not memory, but I'm not certain.
[/quote]
In fact for now there is 3 registers, 0xX0 for Control Status, 0xX1 for Control Pointer, 0xX2 for Main Register. The fact is that memory and register can be handled the same way, you could do a jump by setting the control pointer directly, but the JMP instruction use directly the control pointerso you don't have to handle Control Pointer Address and thus not making a 4 instruction program where one one can be used just for a jump.

Nightinggale
Fast Inserter
Fast Inserter
Posts: 120
Joined: Sun May 14, 2017 12:01 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Nightinggale »

I think I will wait for the next version. I figured out how to create a loop, but that's about it. I suspect it could be due to having a mismatch between icon, text and functionality, which really hurts the ability to do anything useful.
y.petremann wrote:Each device have exactly 16 memory slots, memory slot get addresses from device and device get his adress from it's order in the device list, the device list is sorted each time any device is added, and his ordering goes from left to right and top to bottom, so is you add/remove devices below or right of them, they keep their adresses, If at another place, then their adress is modified, I would suggest to design your CPU like a square and with empty memory, so if you need to medify to CPU or connector, everything is still fine.
Sounds ok, but I still wonder if it could be better. I got a new idea: a new module. It contains one number and that's the address the next module starts with. This will allow gaps in the address space, which means it's possible to expand even if you did not spend the resources to make it big enough from the start. The only issue is: what happens if you make two places with the same address. I say make one of them inaccessible, possibly with a flashing red icon or something. It's undefined behavior.
y.petremann wrote:Sure that would be great, for now I'm making the next release that is not easy, basicaly I'm trying to make the programmable controller mod separate to instructions sets mods and to devices mods, so I could either way update the engine, update/add modules or work on instructions sets with different themes.
If I get to the point where I can add instructions from another mod, then anybody could write their own instructions sets, also I could really work at making a lot of demos with blueprints.
So you are saying you plan to release the engine itself with an "API", which allows people to write their own instructions. Now that could be interesting.

One feature I imagine could be added like that would be to make a set of instructions to manage a list. First block would be length and then the contents would follow. Instructions for this could then be append to the end, get the first and make the rest move one block to the left. Other functions like sort and detecting if a certain value is present could also be useful. The only issue I have with this is that it really is a CISC instruction in a RISC system. This means to make it balanced, the API should support setting how many CPU cycles the instruction use (default 1 as it is right now), meaning using such a complex instruction should reduce the number of instructions done each tick, which in turn should counter lag.
y.petremann wrote:Basicaly every device must have the same adress space lenght, Basicaly I want to move to a CPU architechture that enable stacks and calls, so every cell in the cpu could be managed manually or by the corresponding instructions but ROM is garanted to not be modified unless an instruction specifically use the coresponding adress while CPUS can modify any cell inside themselve for any instruction, you can still pout your entire program inside the CPU, but beware of instruction that would modify what you want to keep !
This made me wonder. A stack shouldn't be that hard to implement. Say we set address 4 to stack size +4 and then the stack is added after it. It then requires a few new instructions.
  • jump, which increases the stack counter by one and then copy contents of address 2 to the block pointed to by address 4. Then the normal jump is performed.
  • a return instruction, which reads address 4, reads the contents of the address it points to and copies that one to address 2. Then decreases address 4 by 1.
Sure it's a simple stack, but I think it might do the job just fine. It might not be the best place to store it in memory though as it could be beneficial to add more registers.

Another interesting approach could be to change how the CPU is viewed as memory. Instead of a global memory, a CPU should view itself as the first memory. The rest of the memory then have an offset to ensure it won't overlap with the CPU.

Example of why this could be really useful.
Say we have one CPU, a ROM (big and complex) and then an input and an output module. This is hooked up to a vehicle scanner and controller. The CPU then reads conditions about the vehicle and sends outputs to control it to behave in a somewhat sane way. Say we control a hauler to fetch ore from miners and drop it off at the base using your own pathfinding, which is based on zones (there are zones looking like arrows). This can avoid collisions in tight locations etc. I know this works well because I have it working in my current game using combinators.... a whole lot of them.

Next you figure you need one more hauler. You then add a CPU and input and output. If the ROM uses data in the CPU as well as pointers in the CPU to access I/O, then the very same ROM can be used by both CPUs if the data inside the CPUs are private. This system can be expanded as much as you want and you can have 10 CPUs controlling 10 haulers, but still only one ROM.

Sure you can loop the haulers, but if you control them based on the zone they are driving in and they need to turn, then there is a limited amount of ticks from they enter a new zone until they need to start turning. Being able to run in parallel without creating a new complex program for each sounds really attractive.


One neat solution to this setup would be to add a register to the CPU and then add get and set instructions, which accesses the address (register value + #V). This will allow making a chunk of I/O and RAM for each CPU, meaning only one memory block will be needed in the CPU to allow the setup I just explained. I'm sure people can quickly find other uses for it as well.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

Nightinggale wrote:I think I will wait for the next version. I figured out how to create a loop, but that's about it. I suspect it could be due to having a mismatch between icon, text and functionality, which really hurts the ability to do anything useful.
y.petremann wrote:Each device have exactly 16 memory slots, memory slot get addresses from device and device get his adress from it's order in the device list, the device list is sorted each time any device is added, and his ordering goes from left to right and top to bottom, so is you add/remove devices below or right of them, they keep their adresses, If at another place, then their adress is modified, I would suggest to design your CPU like a square and with empty memory, so if you need to medify to CPU or connector, everything is still fine.
Sounds ok, but I still wonder if it could be better. I got a new idea: a new module. It contains one number and that's the address the next module starts with. This will allow gaps in the address space, which means it's possible to expand even if you did not spend the resources to make it big enough from the start. The only issue is: what happens if you make two places with the same address. I say make one of them inaccessible, possibly with a flashing red icon or something. It's undefined behavior.
Well, I don't really like to add a module just for one adress, instead I would prefer something a bit more complex but still interesting, an adress module would have 16 slot and would be capable of moving 4 address range (always blocks of 16 because of the way memory and cache is managed inside the mod and because it would be more easier and meaningful), first would be the Mode of adress range moving, the three others would be the parameters for the move which would be Original position, New position and Lenght. The modes would works like this :

Code: Select all

0:(push blocks of L from O to N, keep blank) 
0 4 8 4
CCCCRRRR--NNNN
CCCC----RRRR--NNNN

Code: Select all

1:(move blocks of from O to N, remove blank) 
1 4 8 4
CCCCRRRR--NNNN
CCCC----RRRRNNNN

Code: Select all

2:(swap blocks of L size at O and N) 
2 4 10 4
CCCCRRRR--NNNN
CCCCNNNN--RRRR

Code: Select all

3:(set a local space of L size from O to N, everything inside that local space can access using N+x address instead of O+x, local spaces can overlap)
3  0 0 4
3  4 0 4
3  8 0 4
3 12 0 4
CRN-CRN-CRN-CRN-
LLLLCRN-CRN-CRN-CRN-
Also with this method an address space never get over another, you could put so many address modules but any modification would result in a resort then processing of the device list since address modification would only apply on the original space.

Nightinggale wrote:
y.petremann wrote:Sure that would be great, for now I'm making the next release that is not easy, basicaly I'm trying to make the programmable controller mod separate to instructions sets mods and to devices mods, so I could either way update the engine, update/add modules or work on instructions sets with different themes.
If I get to the point where I can add instructions from another mod, then anybody could write their own instructions sets, also I could really work at making a lot of demos with blueprints.
So you are saying you plan to release the engine itself with an "API", which allows people to write their own instructions. Now that could be interesting.

One feature I imagine could be added like that would be to make a set of instructions to manage a list. First block would be length and then the contents would follow. Instructions for this could then be append to the end, get the first and make the rest move one block to the left. Other functions like sort and detecting if a certain value is present could also be useful. The only issue I have with this is that it really is a CISC instruction in a RISC system. This means to make it balanced, the API should support setting how many CPU cycles the instruction use (default 1 as it is right now), meaning using such a complex instruction should reduce the number of instructions done each tick, which in turn should counter lag.
This is why I want to separate the instructions set from the core, because there is so many potential for instructions sets, I don't want to make the most difficult ASM, since the device has pretty hard limits, I want to add instructions that makes programmer life easier, basicaly the instructions set to manage lists/stacks is pretty cool, and I alos got the idea to be able to manage strings, which are simply list of numbers used as characters, also a math instruction set to allow trigonometry or advanced math functions would be interesting. But all those should be put in additionnal instructions sets mods.

For stacks and lists, I would add an instruction which would be an hard size limit for them, so if the list don't go over this limit and then don't write over any other memory.
Nightinggale wrote:
y.petremann wrote:Basicaly every device must have the same adress space lenght, Basicaly I want to move to a CPU architechture that enable stacks and calls, so every cell in the cpu could be managed manually or by the corresponding instructions but ROM is garanted to not be modified unless an instruction specifically use the coresponding adress while CPUS can modify any cell inside themselve for any instruction, you can still pout your entire program inside the CPU, but beware of instruction that would modify what you want to keep !
This made me wonder. A stack shouldn't be that hard to implement. Say we set address 4 to stack size +4 and then the stack is added after it. It then requires a few new instructions.
  • jump, which increases the stack counter by one and then copy contents of address 2 to the block pointed to by address 4. Then the normal jump is performed.
  • a return instruction, which reads address 4, reads the contents of the address it points to and copies that one to address 2. Then decreases address 4 by 1.
Sure it's a simple stack, but I think it might do the job just fine. It might not be the best place to store it in memory though as it could be beneficial to add more registers.
Basicaly you can do it with the actual instruction set but as of the preceding example, you would spend too much instructions to simply do a call and a return. I want the call instruction to be separated to jump, because jump simply jump without taking care of old position, call keep the address in the stack and then return get it.
Nightinggale wrote: Another interesting approach could be to change how the CPU is viewed as memory. Instead of a global memory, a CPU should view itself as the first memory. The rest of the memory then have an offset to ensure it won't overlap with the CPU.
Basicaly ... no ! it add more confusion because with this architechture, it would be frequent to use CPU that need to access things, instead I think that the local space mode for the address module would be more insteresting because to would let to bundle a complete address space inside it, local space could be used in two ways: CPU space would let to have a local space bound to the current CPU and RAM local space would let to have a local space bound to the current instruction module.
Nightinggale wrote: Example of why this could be really useful.
Say we have one CPU, a ROM (big and complex) and then an input and an output module. This is hooked up to a vehicle scanner and controller. The CPU then reads conditions about the vehicle and sends outputs to control it to behave in a somewhat sane way. Say we control a hauler to fetch ore from miners and drop it off at the base using your own pathfinding, which is based on zones (there are zones looking like arrows). This can avoid collisions in tight locations etc. I know this works well because I have it working in my current game using combinators.... a whole lot of them.

Next you figure you need one more hauler. You then add a CPU and input and output. If the ROM uses data in the CPU as well as pointers in the CPU to access I/O, then the very same ROM can be used by both CPUs if the data inside the CPUs are private. This system can be expanded as much as you want and you can have 10 CPUs controlling 10 haulers, but still only one ROM.

Sure you can loop the haulers, but if you control them based on the zone they are driving in and they need to turn, then there is a limited amount of ticks from they enter a new zone until they need to start turning. Being able to run in parallel without creating a new complex program for each sounds really attractive.

One neat solution to this setup would be to add a register to the CPU and then add get and set instructions, which accesses the address (register value + #V). This will allow making a chunk of I/O and RAM for each CPU, meaning only one memory block will be needed in the CPU to allow the setup I just explained. I'm sure people can quickly find other uses for it as well.
There are some instructions that are in beta which unlock so much potential :
- get CPU id : simply let get the actual CPU
- get power level : simply get the actual power level
- get memory count : simply get the total number of memory cells available
- move register : this one is pretty handy in a lot of situation, it let the processor move his main register to any address you want (the original register contain the address of this memory cell)
- move control : this one can be handy when you want two processor to act as one because you need more instructions to be executed, you can simply move the status and control register to any address you want, even on another cpu status and control registers. For now CPU don't have true paralelism, but I don't think it's really needed, because CPU are executed in their adress order, so you can have a ABA architechture where A and B are CPU, but A share their registers, here a fixed B program could be executed inbetween the A program.

Nightinggale
Fast Inserter
Fast Inserter
Posts: 120
Joined: Sun May 14, 2017 12:01 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Nightinggale »

I will write how I understand the plan, because I'm not sure I get it right. If I don't, then I will write this as suggestions because it sounds really useful and really cool.

Each CPU is handled individually. They are executed one at a time (Factorio is single threaded), but each has unique registers, meaning they each run independent from each other, though with shared memory. A CPU can specify where in the memory the registers should be stored and if multiple CPUs share the same location for registers, the second CPU will continue where the first finished, meaning they will act as one CPU with twice the number of cycles each tick.

The location of registers is a memory slot in itself, meaning it can be overwritten. Say there is a setup with 7 CPUs. The first one checks if aliens are on radar (attacking) and if that's the case, assign the remaining CPUs to all share the same location for registers. The rest will then be a powerful CPU to deal with defenses (like moving tanks into position). If no aliens are on radar, the other CPUs are switched back to do their normal tasks. In other words being attacked triggers an interrupt.

CPU execution order isn't mentioned, but it would be nice to have them execute in the same order as address space. I can think of cases where it could be useful information, even though it often likely won't matter at all.

Sleep X ticks would really need to be that, not just halt until the next CPU if multiple CPUs share the same registers.
y.petremann wrote:Basicaly ... no ! it add more confusion because with this architechture, it would be frequent to use CPU that need to access things, instead I think that the local space mode for the address module would be more insteresting because to would let to bundle a complete address space inside it, local space could be used in two ways: CPU space would let to have a local space bound to the current CPU and RAM local space would let to have a local space bound to the current instruction module.
So you are saying that a CPU has a register, which is a pointer to an address module. An address module can then make a local address space out of the global by combining up to 4 rows of local memory. If you add modules and change the memory layout, updating the address module will fix everything because instructions will be set relative to the setup in the address module.

Sounds interesting, but not without issues. What if the player makes one chunk of ROM, which is coded to be in one address module and then later add another one, which is in another address module. This involves two problems: how to call the function in the other module and wouldn't that result in ever changing the active address module? And what if there is one address module for the ROM with the code and another one for the RAM with input and output?

It could be interesting to add a label instruction (which is essentially just a no operation if executed). #V would then be the label ID. This would allow a instruction to jump to label ID #V. That would be really useful if combined with relative jumps since this will make function calls ignore the issue of which address they reside in. This would remove the need to make an address space for instructions, though it would be nice to get some sort of assistance in figuring out where a relative jump ends up. Not sure how to make that.

Next a CPU can get a local address space where data is stored from 33-160 (or whatever else you would want). This range will then be the only space where absolute addresses will be needed. Instructions then comes in the high range, but we don't really care about the addresses for those, because they will be all relative and label based.

General considerations
Power usage:
ROM should use way less power than RAM, if ROM use any at all. People should be encouraged to consider if they need ROM or RAM.

CPUs could be power hungry, though power usage should depend on how many cycles are used each tick, meaning making a CPU sleep or halt should result in a low power standby. People should be encourage to figure out how to use as few CPUs as possible for other reasons than just lag while at the same time not be so restrictive that you can't add a hundred CPUs and make something brilliant if the computer can handle it.

It would be useful with multiple general purpose registers, say R1-R4. This will allow more complex instructions, which can take multiple arguments. Since each instruction has only one #V, it would be a matter of filling up the registers and then call the instruction, which reads them as input. It could also allow making instructions with multiple outputs. This seems quite important when considering that you want to encourage other people to release addon mods with additional instructions.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

Nightinggale wrote:I will write how I understand the plan, because I'm not sure I get it right. If I don't, then I will write this as suggestions because it sounds really useful and really cool.

Each CPU is handled individually. They are executed one at a time (Factorio is single threaded), but each has unique registers, meaning they each run independent from each other, though with shared memory. A CPU can specify where in the memory the registers should be stored and if multiple CPUs share the same location for registers, the second CPU will continue where the first finished, meaning they will act as one CPU with twice the number of cycles each tick.

The location of registers is a memory slot in itself, meaning it can be overwritten. Say there is a setup with 7 CPUs. The first one checks if aliens are on radar (attacking) and if that's the case, assign the remaining CPUs to all share the same location for registers. The rest will then be a powerful CPU to deal with defenses (like moving tanks into position). If no aliens are on radar, the other CPUs are switched back to do their normal tasks. In other words being attacked triggers an interrupt.
That exactly the plan, and more, the CPU status relly itself on a register so if the register say that the given CPU is halted, then it is, if it remove the halt status, then the CPU woke, also as you said, a CPU could be reasigned to another task by moving his registers, it simply need to have theirs registers moved first because by default, the CPU use his own registers and then use them to say their are moved, so the default register could point to different registers depending of the needed use. Also it's not just move the registers, there is in fact 4 commands, move all registers, move status register, move control register, move main register, so you can for example have seven CPU that shared their control pointers but not their status and main register, which can be powerful in some cases
Nightinggale wrote: CPU execution order isn't mentioned, but it would be nice to have them execute in the same order as address space. I can think of cases where it could be useful information, even though it often likely won't matter at all.
CPU execution is in the address space order.
Nightinggale wrote: Sleep X ticks would really need to be that, not just halt until the next CPU if multiple CPUs share the same registers.
In fact yield (sleep X ticks) is about making a CPU sleep X ticks, if CPUs share their status registers, they all wait for the next tick as soon as one instruction said so.
Nightinggale wrote:
y.petremann wrote:Basicaly ... no ! it add more confusion because with this architechture, it would be frequent to use CPU that need to access things, instead I think that the local space mode for the address module would be more insteresting because to would let to bundle a complete address space inside it, local space could be used in two ways: CPU space would let to have a local space bound to the current CPU and RAM local space would let to have a local space bound to the current instruction module.
So you are saying that a CPU has a register, which is a pointer to an address module. An address module can then make a local address space out of the global by combining up to 4 rows of local memory. If you add modules and change the memory layout, updating the address module will fix everything because instructions will be set relative to the setup in the address module.
Not really, The address module would rebound all address, but is a CPU has his register (original or pointed) to a local space defined by an address module, then it can use that local space, but yeah the address modules would help fix everything, local space or not. Local space would simply help with some cases where about 8 CPUs use the same program but don't process the same data.
Nightinggale wrote: Sounds interesting, but not without issues. What if the player makes one chunk of ROM, which is coded to be in one address module and then later add another one, which is in another address module. This involves two problems: how to call the function in the other module and wouldn't that result in ever changing the active address module? And what if there is one address module for the ROM with the code and another one for the RAM with input and output?
The fact is that Address Modules would not be used as ROM or RAM because they would modify the structure of the grid everytime, They need to be used to move other modules address space, they can even move their own address space.
In fact letting the process modifying the address module is the point, but their is a functionnality not yet documented : ROM, Connector and Address Module are read only by program if disabled, Connectors are Writen by circuit network depending of signal the user want.
And finally, there is two type of rebound of address space, global and local, global rebound would rebound completely for the complete grid, local would simply add a sort of proxy of what you need to specific address, so wherever you placed your CPU, you can rebound them to be considered at 0, so each CPU with local space could use 0 to 16 to access their registers, but also their real address, simply think that defining a local address space would push addresses and reserve that space for local space, defining another local space at the same address but bigger, would simply expand that local space so that each space could fit inside.
Nightinggale wrote: It could be interesting to add a label instruction (which is essentially just a no operation if executed). #V would then be the label ID. This would allow a instruction to jump to label ID #V. That would be really useful if combined with relative jumps since this will make function calls ignore the issue of which address they reside in. This would remove the need to make an address space for instructions, though it would be nice to get some sort of assistance in figuring out where a relative jump ends up. Not sure how to make that.

Next a CPU can get a local address space where data is stored from 33-160 (or whatever else you would want). This range will then be the only space where absolute addresses will be needed. Instructions then comes in the high range, but we don't really care about the addresses for those, because they will be all relative and label based.
That quite hard to do that way because it would need a full memory search done in the mod and not by program which result in bad performances, instead the solution would be to do some sort of call map in the ram, so you could call not by direct address but by a pointer which could be interesting because you could add a blueprinted CPU that would scan entire memory for a specific pattern like wood item signal and then report their address in a specific memory space containing pointers.

Also in real asm, labels don't exists ... everything is ... data, program is data, and when a program call another, it simply jump (call) to the address. Labels would definitely be a thing, like any other cool feature, but not inside the controllers, more inside a higher level language that peoples would compile to get the blueprint and then use.
Nightinggale wrote: General considerations
Power usage:
ROM should use way less power than RAM, if ROM use any at all. People should be encouraged to consider if they need ROM or RAM.
Yeah, in fact to report this, I made so that to write a value, you need to read it before. A read only module would refuse to write and thus consume write power. using CPU memory consume less power.
Nightinggale wrote: CPUs could be power hungry, though power usage should depend on how many cycles are used each tick, meaning making a CPU sleep or halt should result in a low power standby. People should be encourage to figure out how to use as few CPUs as possible for other reasons than just lag while at the same time not be so restrictive that you can't add a hundred CPUs and make something brilliant if the computer can handle it.
Yeah definitively a a point too, I've just not balanced this yet, and for now the mod is quite power hungry, I've got pretty bad results, for now about performance, and I think it can be definitively better but there is a lot of optimisations to do.
Nightinggale wrote: It would be useful with multiple general purpose registers, say R1-R4. This will allow more complex instructions, which can take multiple arguments. Since each instruction has only one #V, it would be a matter of filling up the registers and then call the instruction, which reads them as input. It could also allow making instructions with multiple outputs. This seems quite important when considering that you want to encourage other people to release addon mods with additional instructions.
Will definitivelly add general purpose registers, I think for a total of 8 documented registers, in fact they are already there since memory and registers are not so different, it's just that no instruction use these memory slots as registers.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

Also, I think I will make a temporary release once all current instructions are functionnal before the split between core and instruction sets mods.

Nightinggale
Fast Inserter
Fast Inserter
Posts: 120
Joined: Sun May 14, 2017 12:01 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Nightinggale »

y.petremann wrote:That quite hard to do that way because it would need a full memory search done in the mod and not by program which result in bad performances, instead the solution would be to do some sort of call map in the ram, so you could call not by direct address but by a pointer which could be interesting because you could add a blueprinted CPU that would scan entire memory for a specific pattern like wood item signal and then report their address in a specific memory space containing pointers.

Also in real asm, labels don't exists ... everything is ... data, program is data, and when a program call another, it simply jump (call) to the address. Labels would definitely be a thing, like any other cool feature, but not inside the controllers, more inside a higher level language that peoples would compile to get the blueprint and then use.
Sure labels is something, which is used prior to compiling something. However I was thinking of caching them in an array. However having pointers in address 1,2,3... and then add an instruction to read #V and then jump to the read data, then we would have labels or label like behavior. Alternatively it can be a jump to the low address, which then contains a jump. It would make jumping use two cycles instead of one, which is isn't ideal.

Even with that setup, having a virtual signal to remind you where it jumps to would be nice. Basically just a no operation instruction with a different icon.
y.petremann wrote:Will definitivelly add general purpose registers, I think for a total of 8 documented registers, in fact they are already there since memory and registers are not so different, it's just that no instruction use these memory slots as registers.
Even if there currently memory usable for registers, changing %R into a list of registers would be beneficial, both for moving registers (CPU sharing) and to ensure nothing else will start to take up that space. Imagine somebody writing an instruction, which assumes the registers to be at a certain location and then you add the call stack at that location. Even if the memory is there, having it officially declared which slots have special meaning and which meaning they have will help prevent such conflicts. However it will not really be a problem until you release an instruction API.
y.petremann wrote:Also, I think I will make a temporary release once all current instructions are functional before the split between core and instruction sets mods.
Great. I'm really looking forward to trying this out.

I had a new idea for instructions. Skip instructions, which instead of comparing one value, they check if any value is different from 0 in a specific input module and there should be both == 0 and != 0. I suspect the game caches that info for displaying icons on chests and similar, meaning it might be possible to make the check as simple/fast as checking if a list is empty. It would still be nice to have even without shortcuts, but it would lose a bit of the idea.

User avatar
y.petremann
Filter Inserter
Filter Inserter
Posts: 407
Joined: Mon Mar 17, 2014 4:24 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by y.petremann »

Nightinggale wrote:
y.petremann wrote:That quite hard to do that way because it would need a full memory search done in the mod and not by program which result in bad performances, instead the solution would be to do some sort of call map in the ram, so you could call not by direct address but by a pointer which could be interesting because you could add a blueprinted CPU that would scan entire memory for a specific pattern like wood item signal and then report their address in a specific memory space containing pointers.

Also in real asm, labels don't exists ... everything is ... data, program is data, and when a program call another, it simply jump (call) to the address. Labels would definitely be a thing, like any other cool feature, but not inside the controllers, more inside a higher level language that peoples would compile to get the blueprint and then use.
Sure labels is something, which is used prior to compiling something. However I was thinking of caching them in an array. However having pointers in address 1,2,3... and then add an instruction to read #V and then jump to the read data, then we would have labels or label like behavior. Alternatively it can be a jump to the low address, which then contains a jump. It would make jumping use two cycles instead of one, which is isn't ideal.

Even with that setup, having a virtual signal to remind you where it jumps to would be nice. Basically just a no operation instruction with a different icon.
Firstly you already have two version of jump, one for #Value and one for value at @Address
Secondly, you can put all signal you want inside the program, if they're not instruction they are simply ignored because they are considered data and we don't execute data.
Nightinggale wrote:
y.petremann wrote:Will definitivelly add general purpose registers, I think for a total of 8 documented registers, in fact they are already there since memory and registers are not so different, it's just that no instruction use these memory slots as registers.
Even if there currently memory usable for registers, changing %R into a list of registers would be beneficial, both for moving registers (CPU sharing) and to ensure nothing else will start to take up that space. Imagine somebody writing an instruction, which assumes the registers to be at a certain location and then you add the call stack at that location. Even if the memory is there, having it officially declared which slots have special meaning and which meaning they have will help prevent such conflicts. However it will not really be a problem until you release an instruction API.
I think that in a more general way, peoples should take care of what they put inside CPU, I think that I will move the initial control pointer to point next memory module.
Nightinggale wrote: I had a new idea for instructions. Skip instructions, which instead of comparing one value, they check if any value is different from 0 in a specific input module and there should be both == 0 and != 0. I suspect the game caches that info for displaying icons on chests and similar, meaning it might be possible to make the check as simple/fast as checking if a list is empty. It would still be nice to have even without shortcuts, but it would lose a bit of the idea.
You mean that they compare to 0 instead of %R ? I can still add the instruction (later).
But I could still try to hook a instruction to detect memory changes on a module.

Just as a remainder, the core of the mod has nothing to do with factorio, once memory is cached, I no longer use entities and all calulation is inside the mod. just as an example interactions between the core and the entities occur only in certains situations :
  • Read/Write each tick if entity is opened.
  • Read/Write each tick if entity is a connector.
  • Read if entity settings got pasted.
  • Read if memory is not cached.
Most of the time I only work on cached memory.

Steven_McWayne
Burner Inserter
Burner Inserter
Posts: 10
Joined: Mon Apr 18, 2016 1:18 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Steven_McWayne »

This needs a tutorial and a testmap, maybe some basic stuff like and/or/rs latches to give us some experience with assembler?
Also how to get signals from the network into the cpu and how to find out adresses of the ram/rom to work with them.

Hyratel
Inserter
Inserter
Posts: 34
Joined: Sun May 15, 2016 10:35 pm
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Hyratel »

-pokes dead thread- is OP still maintaining this? latest GIT activity is over a year ago

Krypt
Burner Inserter
Burner Inserter
Posts: 15
Joined: Sat Oct 05, 2019 7:39 am
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Krypt »

Just installed this mod in existing world and there is no way to craft it.
Apparently the reason is Advanced Automation being already researched.

Workaround was to "unresearch" tech using console and research it again

Command:

Code: Select all

/c game.player.force.technologies["advanced-electronics"].researched = false

Krypt
Burner Inserter
Burner Inserter
Posts: 15
Joined: Sat Oct 05, 2019 7:39 am
Contact:

Re: [MOD 0.12.x][0.0.2] Programmable Controllers

Post by Krypt »

No buttons works in code window :(

Post Reply

Return to “Mods”