1 package net.mograsim.machine.standard.memory;
3 import java.math.BigInteger;
4 import java.util.Arrays;
5 import java.util.HashMap;
6 import java.util.HashSet;
9 import net.mograsim.logic.core.types.Bit;
10 import net.mograsim.logic.core.types.BitVector;
11 import net.mograsim.machine.MainMemory;
12 import net.mograsim.machine.MainMemoryDefinition;
13 import net.mograsim.machine.MemoryObserver;
15 public class WordAddressableMemory implements MainMemory
17 private final int cellWidth;
18 private final long minimalAddress, maximalAddress;
19 private final MainMemoryDefinition definition;
20 private final int pageSize = 64;
21 private Set<MemoryObserver> observers = new HashSet<>();
23 private HashMap<Long, Page> pages;
25 public WordAddressableMemory(MainMemoryDefinition definition)
28 this.cellWidth = definition.getCellWidth();
29 this.minimalAddress = definition.getMinimalAddress();
30 this.maximalAddress = definition.getMaximalAddress();
31 this.definition = definition;
32 this.pages = new HashMap<>();
35 private void inBoundsCheck(long address)
37 if (address < minimalAddress || address > maximalAddress)
38 throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d",
39 minimalAddress, maximalAddress, address));
42 private long page(long address)
44 return address / pageSize;
47 private int offset(long address)
49 return (int) (address % pageSize);
53 public void setCell(long address, BitVector b)
55 inBoundsCheck(address);
56 long page = page(address);
57 int offset = offset(address);
58 Page p = pages.get(Long.valueOf(page));
60 pages.put(page, p = new Page());
62 notifyObservers(address);
66 public BitVector getCell(long address)
68 inBoundsCheck(address);
69 long page = page(address);
70 int offset = offset(address);
71 Page p = pages.get(Long.valueOf(page));
73 return BitVector.of(Bit.ZERO, cellWidth);
74 return p.getCell(offset);
78 public BigInteger getCellAsBigInteger(long address)
80 inBoundsCheck(address);
81 long page = page(address);
82 int offset = offset(address);
83 Page p = pages.get(Long.valueOf(page));
85 return BigInteger.valueOf(0L);
86 return p.getCellAsBigInteger(offset);
90 public void setCellAsBigInteger(long address, BigInteger word)
92 inBoundsCheck(address);
93 long page = page(address);
94 int offset = offset(address);
95 Page p = pages.get(Long.valueOf(page));
97 pages.put(page, p = new Page());
98 p.setCellAsBigInteger(offset, word);
99 notifyObservers(address);
104 private BitVector[] memory;
108 memory = new BitVector[pageSize];
111 public BitVector getCell(int index)
113 BitVector b = memory[index];
115 return BitVector.of(Bit.ZERO, cellWidth);
116 return memory[index];
119 public void setCell(int index, BitVector bits)
121 if (bits.length() != cellWidth)
122 throw new IllegalArgumentException(String.format(
123 "BitVector to be saved in memory cell has unexpected width. Expected: %d Actual: %d", cellWidth, bits.length()));
124 memory[index] = bits;
127 public void setCellAsBigInteger(int index, BigInteger bits)
129 setCell(index, BitVector.from(bits, cellWidth));
132 public BigInteger getCellAsBigInteger(int index)
135 return getCell(index).getUnsignedValue();
137 catch(NumberFormatException e)
139 throw new MemoryException(e);
144 public String toString()
146 return Arrays.deepToString(memory);
151 public MainMemoryDefinition getDefinition()
157 public void registerObserver(MemoryObserver ob)
163 public void deregisterObserver(MemoryObserver ob)
165 observers.remove(ob);
169 public void notifyObservers(long address)
171 observers.forEach(ob -> ob.update(address));