801895be2b903d3f50579d2831c5093047b38306
[Mograsim.git] / plugins / net.mograsim.machine / src / net / mograsim / machine / standard / memory / CoreWordAddressableMemory.java
1 package net.mograsim.machine.standard.memory;
2
3 import java.util.List;
4
5 import net.mograsim.logic.core.components.BasicCoreComponent;
6 import net.mograsim.logic.core.timeline.Timeline;
7 import net.mograsim.logic.core.timeline.TimelineEventHandler;
8 import net.mograsim.logic.core.types.Bit;
9 import net.mograsim.logic.core.types.BitVector;
10 import net.mograsim.logic.core.wires.CoreWire.ReadEnd;
11 import net.mograsim.logic.core.wires.CoreWire.ReadWriteEnd;
12 import net.mograsim.machine.MainMemory;
13 import net.mograsim.machine.MainMemoryDefinition;
14 import net.mograsim.machine.Memory.MemoryCellModifiedListener;
15
16 /**
17  * A memory component that only allows access to words of a specific width
18  */
19 public class CoreWordAddressableMemory extends BasicCoreComponent
20 {
21         private final static Bit read = Bit.ONE;
22
23         private ReadWriteEnd data;
24         private ReadEnd rWBit, address;
25         private final MemoryCellModifiedListener memObs;
26         private final MainMemoryDefinition definition;
27         private MainMemory memory;
28
29         /**
30          * @param data    The bits of this ReadEnd are the value that is written to/read from memory; The bit width of this wire is the width of
31          *                a memory word
32          * @param rWBit   The value of the 0th bit dictates the mode: 0: Write, 1: Read
33          * @param address The bits of this ReadEnd address the memory cell to read/write
34          */
35         public CoreWordAddressableMemory(Timeline timeline, int processTime, MainMemoryDefinition definition, ReadWriteEnd data, ReadEnd rWBit,
36                         ReadEnd address)
37         {
38                 super(timeline, processTime);
39                 if (data.width() != definition.getCellWidth())
40                         throw new IllegalArgumentException(
41                                         String.format("Bit width of data wire does not match main memory definition. Expected: %d Actual: %d",
42                                                         definition.getCellWidth(), data.width()));
43                 if (rWBit.width() != 1)
44                         throw new IllegalArgumentException(
45                                         String.format("Bit width of read/write mode select wire is unexpected. Expected: 1 Actual: %d", rWBit.width()));
46                 if (address.width() != definition.getMemoryAddressBits())
47                         throw new IllegalArgumentException(
48                                         String.format("Bit width of address wire does not match main memory definition. Expected: %d Actual: %d",
49                                                         definition.getMemoryAddressBits(), address.width()));
50                 this.data = data;
51                 this.rWBit = rWBit;
52                 this.address = address;
53                 this.definition = definition;
54                 this.memObs = a -> update();
55                 data.registerObserver(this);
56                 rWBit.registerObserver(this);
57                 address.registerObserver(this);
58         }
59
60         public void setMemory(MainMemory memory)
61         {
62                 if (memory != null && !memory.getDefinition().equals(definition))
63                         throw new IllegalArgumentException("Memory of incorrect memory definition given");
64                 if (this.memory != null)
65                         this.memory.registerCellModifiedListener(memObs);
66                 this.memory = memory;
67                 if (memory != null)
68                         memory.registerCellModifiedListener(memObs);
69                 update();
70         }
71
72         public MainMemory getMemory()
73         {
74                 return memory;
75         }
76
77         @Override
78         protected TimelineEventHandler compute()
79         {
80                 if (memory == null)
81                         return e -> data.feedSignals(Bit.U.toVector(data.width()));
82                 if (!address.getValues().isBinary())
83                 {
84                         if (read.equals(rWBit.getValue()))
85                                 return e -> data.feedSignals(Bit.U.toVector(data.width()));// TODO don't always feed U, but decide to feed X or U.
86                         return e -> data.clearSignals();
87                 }
88                 long addressed = address.getValues().getUnsignedValueLong();
89                 if (read.equals(rWBit.getValue()))
90                 {
91                         BitVector storedData = memory.getCell(addressed);
92                         return e -> data.feedSignals(storedData);
93                 }
94                 BitVector transData = data.getValues();
95                 boolean isNewData = !transData.equals(memory.getCell(addressed));
96                 return e ->
97                 {
98                         data.clearSignals();
99                         if (isNewData)
100                                 memory.setCell(addressed, transData);
101                 };
102         }
103
104         @Override
105         public List<ReadEnd> getAllInputs()
106         {
107                 return List.of(data, rWBit, address);
108         }
109
110         @Override
111         public List<ReadWriteEnd> getAllOutputs()
112         {
113                 return List.of(data);
114         }
115 }