hneemann / Digital

A digital logic designer and circuit simulator.
GNU General Public License v3.0
4.37k stars 440 forks source link

Complex circuits performance #278

Closed hinell closed 5 years ago

hinell commented 5 years ago

Hi.

I got used to Digital for a while and currently experimenting with simulation a couple of sophisticated memory circuits but I came across an issue of freezing Digital when I hit the RUN or STEP-RUN buttons.

The Circuit

Screenshot_1

As you can see I'm trying to emulate simple memory cell (it isn't that obvious but on the left there are addresses and on the right are the outputs).

The circuit I have created uses 3-levels of nested (embedded) sub circuits. You may notice that it also uses a lot of tunnels (don't ask me how I've created them). The tunnels are also used in the sub circuits.

The every slightly pinkish circuit contains about a 2 ^ 8 (total = 256) addressable cell each of which contains 32 bit-wide D-Flip-Flop. Everything is addressed by MUX.

The Issue

The issue arises when I hit the run button. The program simply renders unresponsive. It neither does shows signs of high CPU usage nor of excessive memory consumption. When I switch (open and run emulation) to a single circuit (pink in color) below it works at this level but it still takes noticeable time to respond.

Footnotes

So far I wasn't able to identify the weak part of the circuits. I came to a conclusion that Digital still doesn't handle well such complex cases. I'm still looking for solution or at least advice on how to organize custom-built RAM in order to get it to work.

Any thoughts?

I also noticed that there is no debuglog or something like that enabling users to report their problems supplying basic info about digital's state. It would be really nice feature I believe.

Related issues

The circuit above doesn't relate to a concept called unaligned memory access that was mentioned in the #233 issue.

Configuration

I've tried two versions of Digital.

hneemann commented 5 years ago

Please attach the zipped circuit to this issue or send it to digital-simulator@web.de.

But of course there are limits to the maximum size of a circuit. The "Conways Game of Life" example consists of about 2400 components and the creation of the simulation model at the start of the simulation takes about one second on my computer. I expect a linear behavior, so that with several 100000 components the creation of the simulation model can take minutes.

There's no advice on what to do. If a 128kByte RAM is running, someone will want to build a RAM twice as big. You can only do what is done on a FPGA: Use the RAM components provided for this purpose.

hinell commented 5 years ago

@hneemann Thanks for a speedy answer. How are these limitations stipulated/conditioned? I mean do they arise from Java VM?

hneemann commented 5 years ago

@hinell I don't think the JVM is causing the problem. But without the circuit, it's hard to tell what the problem is.

hneemann commented 5 years ago

@hinell I built a 256kx32 RAM which consists of 256K 32 Bit registers (in total there are 337k components), and the simulation start takes about 24sec. That's better than I expected. When the 4kx32 circuit is started, which corresponds to your circuit, only 5266 components are needed and there is no noticeable delay.

ram256Kx32.zip

This is a funny circuit to play around with, but has nothing to do with real memory.

hinell commented 5 years ago

@hneemann Very weird. I got my digital freezing even after those 24 secs when I run 256k circuit in .exe app version. When I did the same by using .jar executable it showed me the following error (this time it didn't freeze though):

Error creating the circuit.
Could not create a component of type Demultiplexer!
caused by: Java heap space

Any ideas?

hinell commented 5 years ago

Wait, looks like I have found what's the problem. I run my circuit by using Digital.sh script and got the following error:

WARNING: Could not open/create prefs root node Software\JavaSoft\Prefs at root 0x80000002. Windows RegCreateKeyEx(...) returned error code 5.
java.lang.OutOfMemoryError: Java heap space
        at java.util.HashSet.<init>(Unknown Source)
        at de.neemann.digital.draw.model.Net.<init>(Net.java:59)
        at de.neemann.digital.draw.model.NetList.add(NetList.java:121)
        at de.neemann.digital.draw.model.NetList.<init>(NetList.java:32)
        at de.neemann.digital.draw.library.CustomElement.getModelCreator(CustomElement.java:56)
        at de.neemann.digital.draw.model.ModelCreator.<init>(ModelCreator.java:150)
        at de.neemann.digital.draw.library.CustomElement.getModelCreator(CustomElement.java:61)
        at de.neemann.digital.draw.model.ModelCreator.<init>(ModelCreator.java:150)
        at de.neemann.digital.draw.library.CustomElement.getModelCreator(CustomElement.java:61)
        at de.neemann.digital.draw.model.ModelCreator.<init>(ModelCreator.java:150)
        at de.neemann.digital.draw.model.ModelCreator.<init>(ModelCreator.java:66)
        at de.neemann.digital.draw.model.ModelCreator.<init>(ModelCreator.java:52)
        at de.neemann.digital.gui.Main.createAndStartModel(Main.java:1265)
        at de.neemann.digital.gui.Main.access$4000(Main.java:89)
        at de.neemann.digital.gui.Main$RunModelState.enter(Main.java:1683)
        at de.neemann.digital.gui.Main$RunModelState.enter(Main.java:1675)
        at de.neemann.digital.gui.state.State$1.actionPerformed(State.java:82)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
hneemann commented 5 years ago

@hinell Because of the large number of components, a large amount of ram is required to simulate the circuit. The shell script you mentioned does use the default settings for ram usage. On my machine this is 2GBytes which is enough to start the simulation.

Please try to start Digital like this:

java -jar -Xmx2048M Digital.jar

When the JVM runs out of memory, its behavior is more or less undefined. But before that, the JVM spends a lot of time in the garbage collector, which feels like the program is frozen.

hinell commented 5 years ago

@hneemann Oh thanks, it works now. I downloaded x64 version of the java run time and now it works. Though it is still too slow. The 256k circuit you have sent me took approximately 17 seconds to run. I wonder what will happen over 1mb of memory... it must be hell. I'm gonna give it a little bit of testing and will report soon if anything wrong happen. Don't close issue right now please.

hneemann commented 5 years ago

@hinell Keep in mind that it makes little sense to build memory this way. It is much more efficient to use the components provided for this purpose. Even from a didactic point of view, it makes little sense, since real memory is not built that way. The only real situation that might come close to this circuit is the synthesis of a large memory block as distributed RAM on an FPGA. And also this is an application that should be avoided, because a lot of resources are consumed on the FPGA doing so.

hinell commented 5 years ago

@hneemann What do you mean that it is not build that way? I'm only trying to create a proof-of-concept prototype and only need a little bit more addressable memory than 2^16x32. I know I could use RAM* but I'm trying to create multi-accessible variant (like that with dual port).

hneemann commented 5 years ago

@hinell If you need dual ported ram, why not using the dual ported ram component provided by Digital?

hinell commented 5 years ago

@hneemann Well cause it wasn't enough and I needed 3-way (or even more) RAM.

hneemann commented 5 years ago

@hinell If there is only one writer and multiple readers, you can write to multiple Dual Ported RAMs simultaneously, and then read the same data from all of them. Sounds like waste at first, but is much more efficient than the discrete construction of the memory.

hinell commented 5 years ago

@hneemann But there is no such component except dual-ported RAM. Yeah, I too though at first that it would be most optimized solution but then I figured it wasn't enough. If you could make some ram configurable of how much write/reads ports it can have it would be really nice. I understand that my approach may be inefficient but seems like I have no other choice except to resort to a discrete solution.

hneemann commented 5 years ago

@hinell Another possibility would be the Register File. It offers one write port and two read ports.

hneemann commented 5 years ago

Since this was a lack of memory that could be fixed with a JVM start parameter, I close the issue. If there are any problems again, just reopen it.

hneemann commented 5 years ago

@hinell The java plugin example now contains a multi port RAM which allows to configure the number of input and output ports.