/******************************************************************************* * openDLX - A DLX/MIPS processor simulator. * Copyright (C) 2013 The openDLX project, University of Augsburg, Germany * Project URL: <https://sourceforge.net/projects/opendlx> * Development branch: <https://github.com/smetzlaff/openDLX> * * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program, see <LICENSE>. If not, see * <http://www.gnu.org/licenses/>. ******************************************************************************/ package openDLX.memory; import openDLX.PipelineConstants; import openDLX.datatypes.uint32; import openDLX.datatypes.uint8; import openDLX.exception.CacheException; public class CacheLine { private uint32 tag; private byte line[]; private int bytes_per_line; private boolean dirty; private boolean valid; public CacheLine(int line_size, int tag_size) throws CacheException { if(line_size % PipelineConstants.WORD_SIZE != 0) { throw new CacheException("The cache line size has to be a multiple of the word size (" + PipelineConstants.WORD_SIZE + "), but it is set to " + line_size); } bytes_per_line = line_size; tag = new uint32(0); line = new byte[line_size]; for(int i = 0; i < line_size; i++) { line[i] = 0; } dirty = false; valid = false; } public boolean compareTag(uint32 tag) { return (this.tag.getValue() == tag.getValue()); } public uint32 getWord(int block_offset) throws CacheException { if(!valid) { throw new CacheException("Cannot read from cache line, it is not valid. tag: " + tag.getValueAsHexString()); } if(block_offset % PipelineConstants.WORD_SIZE != 0) { throw new CacheException("Block offset of readWord() has to be a multiple of the word size (" + PipelineConstants.WORD_SIZE + "), but it is set to " + block_offset); } if(block_offset >= bytes_per_line) { throw new CacheException("Block offset out of range: " + block_offset + "/" + bytes_per_line); } return new uint32((line[block_offset] & 0xFF) | ((line[block_offset+1] & 0xFF) << 8) | ((line[block_offset+2] & 0xFF) << 16) | ((line[block_offset+3] & 0xFF) << 24)); } public void setWord(int block_offset, uint32 value) throws CacheException { if(!valid) { throw new CacheException("Cannot write to cache line, it is not valid. tag: " + tag.getValueAsHexString()); } if(block_offset % PipelineConstants.WORD_SIZE != 0) { throw new CacheException("Block offset of setWord() has to be a multiple of the word size (" + PipelineConstants.WORD_SIZE + "), but it is set to " + block_offset); } if(block_offset >= bytes_per_line) { throw new CacheException("Block offset out of range: " + block_offset + "/" + bytes_per_line); } line[block_offset] = (byte) (value.getValue() & 0xFF); line[block_offset + 1] = (byte) ((value.getValue() >> 8) & 0xFF); line[block_offset + 2] = (byte) ((value.getValue() >> 16) & 0xFF); line[block_offset + 3] = (byte) ((value.getValue() >> 24) & 0xFF); } public uint8 getByte(int block_offset) throws CacheException { if(!valid) { throw new CacheException("Cannot read from cache line, it is not valid. tag: " + tag.getValueAsHexString()); } if(block_offset >= bytes_per_line) { throw new CacheException("Block offset out of range: " + block_offset + "/" + bytes_per_line); } return new uint8(line[block_offset]); } public void setByte(int block_offset, uint8 value) throws CacheException { if(!valid) { throw new CacheException("Cannot write to cache line, it is not valid. tag: " + tag.getValueAsHexString()); } if(block_offset >= bytes_per_line) { throw new CacheException("Block offset out of range: " + block_offset + "/" + bytes_per_line); } line[block_offset]= value.getValue(); } public void setLine(uint32 tag, byte line[]) { this.tag.setValue(tag); for(int i = 0; i < bytes_per_line; i++) { this.line[i] = line[i]; } valid = true; } public void setDirty(boolean dirty) { this.dirty = dirty; } public boolean isDirty() { return dirty; } public String dumpLine() { String s; s = tag.getValueAsHexString() + " "; for(int i = 0; i < bytes_per_line; i++) { s += "0x" + Integer.toHexString(line[i]) + " "; } s += "valid: " + valid + " dirty: " + dirty; return s; } }