fCPU


Factorio Customizable Processing Unit. Allow to write any logic on low level machine code. The fCPU acts like a programmable microcontroller with a vector coprocessor that supports many useful instructions.

Content
3 months ago
0.18 - 1.1
8.51K
Logistic network Circuit network

b Lua Error + Mem issues

3 years ago

Just added this into an existing game. Weird stuff ensued.

Error displayed in fCPU GUI:
Line 3: _fcpu__/src/cpu/io.lua:288: attempt to concatenate field "index" (a nil value)

fCPU code:

mov r1 1[item=iron-ore]
mov mem1[1] r1
idx r2 mem[1] r1

I'm also having troubles with memory. I can store signals fine, and they show up in the memory viewer where they ought to. However, I can't retrieve them reliably. I set the first five cells to different ore types I was interested in, then tried to get their indices using idx. For some reason, idx was always returning 0 (or maybe just doing nothing?), even though the types/signals were present. Also, trying to move the signals back out of mem into registers didn't work as expected. I get a signal from a seemingly random cell or nothing at all.

This mod is super cool! Keep up the good work!

3 years ago
(updated 3 years ago)

Here's a bit more info. A bit of test code I was working with:

clr
mov mem1[1] 1[item=iron-ore]
mov mem1[2] 1[item=copper-ore]
mov mem1[3] 1[item=coal]
mov mem1[4] 1[item=stone]
mov mem1[5] 1[item=uranium-ore]

idx r1 mem1 [item=copper-ore]
mov r2 mem1[1]
mov r3 mem1[2]
mov r4 mem1[3]
mov r5 mem1[4]
mov r6 mem1[5]

So obviously you have mem1 with some ore signals stored in it in indices 1 to 5. Great. That seems to work fine.

Then, I try to look up where I put the copper ore. First time I tried to do something like this, it just did nothing. Then I tested it again and it put signal 4[item=copper-ore] into register 1... which is... totally wrong. Copper ore is in index 2...

I then read all mem1 values from 1 to 5 and stick them in registers r2 to r6.

The values in the memory read: iron, copper, coal, stone, uranium.
The values in the registers read: coal, stone, iron, copper, uranium.

So... something isn't right here. The GUI is presenting the items in mem as I asked them to be arranged, but they are being stored in or retrieved from the actual array differently...

3 years ago

So I changed the order of the signals I was storing to see what would happen. Just rotated them by one index and moved 5 to 1. More weird. Also I figured out how to make a loop work.

clr
mov mem1[2] 1[item=iron-ore]
mov mem1[3] 1[item=copper-ore]
mov mem1[4] 1[item=coal]
mov mem1[5] 1[item=stone]
mov mem1[1] 1[item=uranium-ore]

idx r8 mem1 [item=coal]

clr r7
:loop
add r7 1
mov r@7 mem1@7
tlt r7 5
jmp :loop

The ordering of the retrieved values is preserved... sort of. Coal disappears. It's in the memory viewer, but it isn't where I tried to put it and idx can't find it... so... fix plz?

3 years ago

Hello, rhdabe!
Thank you for detailed report. Unfortunately it is not a bug and a bit complicated for now (until I implement v0.5.0 on roadmap https://www.buymeacoffee.com/konstg/todo-list-fcpu).

I'll try to explain how the mod works with memory and why it's done this way.

Each Factorio wire can contain a huge number of signals simultaneously (hundreds). These signals are not sorted in any way and in fact have a random indices. To make everything look more beautiful, GUI panels sort signals in descending order (power poles and β“˜ tooltips).

To process a large number of signals in the game, vanilla combinators optimized inside game engine itself in C++. If you try to process a similar number of signals in the LUA mod, there will be significant overhead and performance degradation. This applies to any Factorio mod.

To get around this, fCPU uses a trick - it partially compiles the written program (SIMD mnemonics x*) into invisible circuits with vanilla combinators and coordinates their execution line-by-line. This part of fCPU called coprocessor. It provides better performance than similar calculations on the LUA.

Unlike registers, which are implemented as ordinary variables and always retain their indices, the memory for SIMD commands is also implemented using vanilla combinators.

Here comes the most important thing:
To modify the memory, you need to subtract one signal and add another (it is shown on the video https://youtu.be/xOADSQPs4Z4).
Like any other vanilla combinator operation, this breaks the signal indices.
That is why, if you change the state of memory, then the indexes will also change.

Besides this there are some discussions of memory on the discord server, join us!

3 years ago

Hm. It seems I must do more research to use fCPU properly! Thanks for the detailed response and explanation.

New response