Undo renaming of BitVector's length to width
[Mograsim.git] / net.mograsim.machine / src / net / mograsim / machine / standard / memory / WordAddressableMemory.java
1 package net.mograsim.machine.standard.memory;
2
3 import java.math.BigInteger;
4 import java.util.Arrays;
5 import java.util.HashMap;
6
7 import net.mograsim.logic.core.types.Bit;
8 import net.mograsim.logic.core.types.BitVector;
9 import net.mograsim.machine.MainMemory;
10 import net.mograsim.machine.MainMemoryDefinition;
11
12 public class WordAddressableMemory implements MainMemory
13 {
14         private final int cellWidth;
15         private final long minimalAddress, maximalAddress;
16         private final MainMemoryDefinition definition;
17         private final int pageSize = 64;
18
19         private HashMap<Long, Page> pages;
20
21         public WordAddressableMemory(MainMemoryDefinition definition)
22         {
23                 super();
24                 this.cellWidth = definition.getCellWidth();
25                 this.minimalAddress = definition.getMinimalAddress();
26                 this.maximalAddress = definition.getMaximalAddress();
27                 this.definition = definition;
28                 this.pages = new HashMap<>();
29         }
30         
31         private void inBoundsCheck(long address)
32         {
33                 if (address < minimalAddress || address > maximalAddress)
34                         throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d",
35                                         minimalAddress, maximalAddress, address));
36         }
37
38         private long page(long address)
39         {
40                 return address / pageSize;
41         }
42         
43         private int offset(long address)
44         {
45                 return (int) (address % pageSize);
46         }
47         
48         @Override
49         public void setCell(long address, BitVector b)
50         {
51                 inBoundsCheck(address);
52                 long page = page(address);
53                 int offset = offset(address);
54                 Page p = pages.get(Long.valueOf(page));
55                 if (p == null)
56                         pages.put(page, p = new Page());
57                 p.setCell(offset, b);
58         }
59
60         @Override
61         public BitVector getCell(long address)
62         {
63                 inBoundsCheck(address);
64                 long page = page(address);
65                 int offset = offset(address);
66                 Page p = pages.get(Long.valueOf(page));
67                 if (p == null)
68                         return BitVector.of(Bit.ZERO, cellWidth);
69                 return p.getCell(offset);
70         }
71         
72         @Override
73         public BigInteger getCellAsBigInteger(long address)
74         {
75                 inBoundsCheck(address);
76                 long page = page(address);
77                 int offset = offset(address);
78                 Page p = pages.get(Long.valueOf(page));
79                 if (p == null)
80                         return BigInteger.valueOf(0L);
81                 return p.getCellAsBigInteger(offset);
82         }
83
84         @Override
85         public void setCellAsBigInteger(long address, BigInteger word)
86         {
87                 inBoundsCheck(address);
88                 long page = page(address);
89                 int offset = offset(address);
90                 Page p = pages.get(Long.valueOf(page));
91                 if (p == null)
92                         pages.put(page, p = new Page());
93                 p.setCellAsBigInteger(offset, word);
94         }
95
96         private class Page
97         {
98                 private BitVector[] memory;
99
100                 public Page()
101                 {
102                         memory = new BitVector[pageSize];
103                 }
104
105                 public BitVector getCell(int index)
106                 {
107                         BitVector b = memory[index];
108                         if (b == null)
109                                 return BitVector.of(Bit.ZERO, cellWidth);
110                         return memory[index];
111                 }
112
113                 public void setCell(int index, BitVector bits)
114                 {
115                         if (bits.length() != cellWidth)
116                                 throw new IllegalArgumentException(String.format(
117                                                 "BitVector to be saved in memory cell has unexpected width. Expected: %d Actual: %d", cellWidth, bits.length()));
118                         memory[index] = bits;
119                 }
120
121                 public void setCellAsBigInteger(int index, BigInteger bits)
122                 {
123                         setCell(index, BitVector.from(bits, cellWidth));
124                 }
125                 
126                 public BigInteger getCellAsBigInteger(int index)
127                 {
128                         try {
129                                 return getCell(index).getUnsignedValue();
130                         }
131                         catch(NumberFormatException e)
132                         {
133                                 throw new MemoryException(e);
134                         }
135                 }
136
137                 @Override
138                 public String toString()
139                 {
140                         return Arrays.deepToString(memory);
141                 }
142         }
143
144         @Override
145         public MainMemoryDefinition getDefinition()
146         {
147                 return definition;
148         }
149 }