Added handle priorities
[Mograsim.git] / net.mograsim.logic.core / src / net / mograsim / logic / core / components / gates / WordAddressableMemoryComponent.java
1 package net.mograsim.logic.core.components.gates;
2
3 import java.util.Arrays;
4 import java.util.HashMap;
5 import java.util.List;
6
7 import net.mograsim.logic.core.components.BasicComponent;
8 import net.mograsim.logic.core.timeline.Timeline;
9 import net.mograsim.logic.core.types.Bit;
10 import net.mograsim.logic.core.types.BitVector;
11 import net.mograsim.logic.core.wires.Wire.ReadEnd;
12 import net.mograsim.logic.core.wires.Wire.ReadWriteEnd;
13
14 public class WordAddressableMemoryComponent extends BasicComponent
15 {
16         private final WordAddressableMemory memory;
17         private final static Bit read = Bit.ONE;
18
19         private ReadWriteEnd data;
20         private ReadEnd rWBit, address;
21
22         /**
23          * 
24          * @param timeline
25          * @param processTime
26          * @param minimalAddress
27          * @param maximalAddress
28          * @param data
29          * @param rWBit          0: Write 1: Read
30          * @param address
31          */
32         public WordAddressableMemoryComponent(Timeline timeline, int processTime, long minimalAddress, long maximalAddress, ReadWriteEnd data,
33                         ReadEnd rWBit, ReadEnd address)
34         {
35                 super(timeline, processTime);
36                 this.data = data;
37                 this.rWBit = rWBit;
38                 this.address = address;
39                 data.registerObserver(this);
40                 rWBit.registerObserver(this);
41                 address.registerObserver(this);
42
43                 memory = new WordAddressableMemory(data.length(), minimalAddress, maximalAddress);
44         }
45
46         @Override
47         protected void compute()
48         {
49                 if (!address.hasNumericValue())
50                 {
51                         if (read.equals(rWBit.getValue()))
52                                 data.feedSignals(BitVector.of(Bit.U, data.length()));
53                         else
54                                 data.clearSignals();
55                         return;
56                 }
57                 long addressed = address.getUnsignedValue();
58                 if (read.equals(rWBit.getValue()))
59                         data.feedSignals(memory.getCell(addressed));
60                 else
61                 {
62                         data.clearSignals();
63                         System.out.println(memory);
64                         memory.setCell(addressed, data.getValues());
65                 }
66         }
67
68         @Override
69         public List<ReadEnd> getAllInputs()
70         {
71                 return List.of(data, rWBit, address);
72         }
73
74         @Override
75         public List<ReadWriteEnd> getAllOutputs()
76         {
77                 return List.of(data);
78         }
79
80         private class WordAddressableMemory
81         {
82                 private final int cellWidth;
83                 private final long minimalAddress, maximalAddress;
84                 private final int pageSize;
85
86                 private HashMap<Long, Page> pages;
87
88                 public WordAddressableMemory(int cellWidth, long minimalAddress, long maximalAddress)
89                 {
90                         super();
91                         this.cellWidth = cellWidth;
92                         this.minimalAddress = minimalAddress;
93                         this.maximalAddress = maximalAddress;
94                         this.pages = new HashMap<>();
95                         this.pageSize = 64;
96                 }
97
98                 public void setCell(long address, BitVector b)
99                 {
100                         if (address < minimalAddress || address > maximalAddress)
101                                 throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maimum: %d Actual: %d",
102                                                 minimalAddress, maximalAddress, address));
103                         long page = address / pageSize;
104                         int offset = (int) (address % pageSize);
105                         Page p = pages.get(Long.valueOf(page));
106                         if (p == null)
107                                 pages.put(page, p = new Page());
108                         p.setCell(offset, b);
109                 }
110
111                 public BitVector getCell(long address)
112                 {
113                         long page = address / pageSize;
114                         int offset = (int) (address % pageSize);
115                         Page p = pages.get(Long.valueOf(page));
116                         if (p == null)
117                                 return BitVector.of(Bit.U, cellWidth);
118                         return p.getCell(offset);
119                 }
120
121                 private class Page
122                 {
123                         private BitVector[] memory;
124
125                         public Page()
126                         {
127                                 memory = new BitVector[pageSize];
128                         }
129
130                         public BitVector getCell(int index)
131                         {
132                                 BitVector b = memory[index];
133                                 if (b == null)
134                                         return BitVector.of(Bit.U, cellWidth);
135                                 return memory[index];
136                         }
137
138                         public void setCell(int index, BitVector bits)
139                         {
140                                 if (bits.length() != cellWidth)
141                                         throw new IllegalArgumentException(
142                                                         String.format("BitVector to be saved in memory cell has unexpected length. Expected: %d Actual: %d", cellWidth,
143                                                                         bits.length()));
144                                 memory[index] = bits;
145                         }
146
147                         @Override
148                         public String toString()
149                         {
150                                 return Arrays.deepToString(memory);
151                         }
152                 }
153         }
154 }
155 //import java.math.BigInteger;
156 //
157 //import net.mograsim.logic.core.types.Bit;
158 //import net.mograsim.logic.core.types.BitVector;
159 //
160 //private byte[] encode(BitVector v)
161 //{
162 //      BigInteger d = BigInteger.ZERO;
163 //      Bit[] bits = v.getBits();
164 //      for (int i = v.length() - 1; i >= 0; i--)
165 //      {
166 //              d = d.add(BigInteger.valueOf(bits[i].ordinal()));
167 //              d = d.multiply(BigInteger.valueOf(Bit.values().length));
168 //      }
169 //      return d.toByteArray();
170 //}
171 //
172 ///**
173 // * 
174 // * @param bytes
175 // * @param numBits length of the resulting BitVector
176 // * @return
177 // */
178 //private BitVector decode(byte[] bytes, int numBits)
179 //{
180 //      BigInteger d = new BigInteger(bytes);
181 //      Bit[] bits = new Bit[numBits];
182 //      return BitVector.of(bits);
183 //}
184 //
185 //private static class CellArray
186 //{
187 //      private byte[] bytes;
188 //      private final static byte mask = -1;
189 //      public CellArray(int numCells, int cellSize)
190 //      {
191 //              bytes = new byte[numCells * cellSize / 8];
192 //      }
193 //      
194 //      public byte[] getCell(int i)
195 //      {
196 //              
197 //      }
198 //}