Further renaming of length to width
[Mograsim.git] / net.mograsim.machine / src / net / mograsim / machine / standard / memory / WordAddressableMemory.java
index 719c993..2e209f1 100644 (file)
@@ -1,50 +1,97 @@
 package net.mograsim.machine.standard.memory;
 
+import java.math.BigInteger;
 import java.util.Arrays;
 import java.util.HashMap;
 
 import net.mograsim.logic.core.types.Bit;
 import net.mograsim.logic.core.types.BitVector;
+import net.mograsim.machine.MainMemory;
+import net.mograsim.machine.MainMemoryDefinition;
 
-public class WordAddressableMemory
+public class WordAddressableMemory implements MainMemory
 {
        private final int cellWidth;
        private final long minimalAddress, maximalAddress;
+       private final MainMemoryDefinition definition;
        private final int pageSize = 64;
 
        private HashMap<Long, Page> pages;
 
-       public WordAddressableMemory(int cellWidth, long minimalAddress, long maximalAddress)
+       public WordAddressableMemory(MainMemoryDefinition definition)
        {
                super();
-               this.cellWidth = cellWidth;
-               this.minimalAddress = minimalAddress;
-               this.maximalAddress = maximalAddress;
+               this.cellWidth = definition.getCellWidth();
+               this.minimalAddress = definition.getMinimalAddress();
+               this.maximalAddress = definition.getMaximalAddress();
+               this.definition = definition;
                this.pages = new HashMap<>();
        }
-
-       public void setCell(long address, BitVector b)
+       
+       private void inBoundsCheck(long address)
        {
                if (address < minimalAddress || address > maximalAddress)
                        throw new IndexOutOfBoundsException(String.format("Memory address out of bounds! Minimum: %d Maximum: %d Actual: %d",
                                        minimalAddress, maximalAddress, address));
-               long page = address / pageSize;
-               int offset = (int) (address % pageSize);
+       }
+
+       private long page(long address)
+       {
+               return address / pageSize;
+       }
+       
+       private int offset(long address)
+       {
+               return (int) (address % pageSize);
+       }
+       
+       @Override
+       public void setCell(long address, BitVector b)
+       {
+               inBoundsCheck(address);
+               long page = page(address);
+               int offset = offset(address);
                Page p = pages.get(Long.valueOf(page));
                if (p == null)
                        pages.put(page, p = new Page());
                p.setCell(offset, b);
        }
 
+       @Override
        public BitVector getCell(long address)
        {
-               long page = address / pageSize;
-               int offset = (int) (address % pageSize);
+               inBoundsCheck(address);
+               long page = page(address);
+               int offset = offset(address);
                Page p = pages.get(Long.valueOf(page));
                if (p == null)
-                       return BitVector.of(Bit.U, cellWidth);
+                       return BitVector.of(Bit.ZERO, cellWidth);
                return p.getCell(offset);
        }
+       
+       @Override
+       public BigInteger getCellAsBigInteger(long address)
+       {
+               inBoundsCheck(address);
+               long page = page(address);
+               int offset = offset(address);
+               Page p = pages.get(Long.valueOf(page));
+               if (p == null)
+                       return BigInteger.valueOf(0L);
+               return p.getCellAsBigInteger(offset);
+       }
+
+       @Override
+       public void setCellAsBigInteger(long address, BigInteger word)
+       {
+               inBoundsCheck(address);
+               long page = page(address);
+               int offset = offset(address);
+               Page p = pages.get(Long.valueOf(page));
+               if (p == null)
+                       pages.put(page, p = new Page());
+               p.setCellAsBigInteger(offset, word);
+       }
 
        private class Page
        {
@@ -59,22 +106,44 @@ public class WordAddressableMemory
                {
                        BitVector b = memory[index];
                        if (b == null)
-                               return BitVector.of(Bit.U, cellWidth);
+                               return BitVector.of(Bit.ZERO, cellWidth);
                        return memory[index];
                }
 
                public void setCell(int index, BitVector bits)
                {
-                       if (bits.length() != cellWidth)
+                       if (bits.width() != cellWidth)
                                throw new IllegalArgumentException(String.format(
-                                               "BitVector to be saved in memory cell has unexpected length. Expected: %d Actual: %d", cellWidth, bits.length()));
+                                               "BitVector to be saved in memory cell has unexpected width. Expected: %d Actual: %d", cellWidth, bits.width()));
                        memory[index] = bits;
                }
 
+               public void setCellAsBigInteger(int index, BigInteger bits)
+               {
+                       setCell(index, BitVector.from(bits, cellWidth));
+               }
+               
+               public BigInteger getCellAsBigInteger(int index)
+               {
+                       try {
+                               return getCell(index).getUnsignedValue();
+                       }
+                       catch(NumberFormatException e)
+                       {
+                               throw new MemoryException(e);
+                       }
+               }
+
                @Override
                public String toString()
                {
                        return Arrays.deepToString(memory);
                }
        }
+
+       @Override
+       public MainMemoryDefinition getDefinition()
+       {
+               return definition;
+       }
 }