/* * To change this license header, choose License Headers in Project Properties. * To change this template file, choose Tools | Templates * and open the template in the editor. */ package tools.mips; import API.Utils; import java.util.TreeMap; /** * * @author EUGENIO CARVALHO */ public class Memory { public Integer WORD_BYTES_COUNT = 4; protected String EMPTY_BYTE = "00000000"; protected boolean writable; protected String file; protected Long size = 0L, localAddress = 0L; protected TreeMap data = new TreeMap<>(); protected MemoryImportExportInterface io; public Memory ReadOnly() { this.writable = false; return this; } public int WordBitSize() { return WORD_BYTES_COUNT * 8; } public Memory Writable() { this.writable = true; return this; } public void Reset() { data.entrySet().forEach((entry) -> { entry.setValue(EMPTY_BYTE); }); } public Memory(long size) { this.size = size; } public Memory(String filename, long size) throws Exception { if (filename.equals("")) { throw new Exception("Empty file not allowed."); } this.file = filename; this.size = size; } public TreeMap Data() { return data; } @Override public String toString() { try { return Dump(); } catch (Exception ex) { return ex.getMessage(); } } protected void CheckIOSet() throws Exception { if (io == null) { throw new Exception("Interface de IO da memória não definida."); } } public String Dump() throws Exception { CheckIOSet(); return io.DumpFile(this); } protected void ReadFile() throws Exception { CheckIOSet(); io.FromFile(this); } public Long ReadLong(long address, int rsize) throws Exception { // System.out.println("R(address, rsize):" + Utils.padPreserveSignal(64, R(address, rsize))); return Long.parseUnsignedLong(Utils.padPreserveSignal(64, R(address, rsize)), 2); } public String R(long address, int rsize) throws Exception { valid(address); String buffer = ""; for (int i = 0; i < rsize; i++) { buffer += RB(address + i); } return buffer; // return Utils.Pad(buffer, "0", Utils.PAD_LEFT, 32); // System.out.println("R:" + buffer); // return Utils.padPreserveSignal(32, buffer); } public String RB(long address) throws Exception { valid(address); address = (address + size) % size; if (!data.containsKey(address)) { data.put(address, EMPTY_BYTE); } return data.get(address); } protected void valid(long address) throws Exception { if (Math.abs(address) > size) { throw new Exception("Address '" + address + "' out of range limit " + size + "!"); } } public void WB(String sbyte) throws Exception { WB(localAddress++, sbyte); } public void WB(Long address, String sbyte) throws Exception { valid(address); int len = sbyte.length(); if (len > 8) { sbyte = sbyte.substring(sbyte.length() - 8); } else if (len < 8) { sbyte = Utils.Pad(sbyte, "0", Utils.PAD_LEFT, 8); } data.put((address + size) % size, sbyte); } public void W(long address, long value, int wsize) throws Exception { W(address, Long.toBinaryString(value), wsize); } public void W(long address, String bin, int wsize) throws Exception { valid(address); int bpos = 4 - wsize; bin = Utils.Pad(bin, "0", Utils.PAD_LEFT, 32); String[] bytes = Utils.SplitEach(bin, 8); //Fix to 16 bytes of negative value binary // System.out.println("W(" + address + ")" + Arrays.asList(bytes)); if (bytes.length > 4) { bpos += 4; } for (int i = 0; i < wsize; i++) { WB(address + i, bytes[bpos + i]); } } public Memory Save() throws Exception { return Save(file); } public Memory Save(String filename) throws Exception { // Grava o conteudo no arquivo Utils.WriteFile(filename, Dump()); return this; } public void SetIO(MemoryImportExportInterface memoryInitializationFile) { io = memoryInitializationFile; } public String File() { return file; } public long Size() { return size; } }