/**
* ****************************************************************************
* Copyright (c) 2010-2016 by Min Cai (min.cai.china@gmail.com).
* <p>
* This file is part of the Archimulator multicore architectural simulator.
* <p>
* Archimulator 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
* (at your option) any later version.
* <p>
* Archimulator 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.
* <p>
* You should have received a copy of the GNU General Public License
* along with Archimulator. If not, see <http://www.gnu.org/licenses/>.
* ****************************************************************************
*/
package archimulator.isa;
import archimulator.util.Pair;
import java.util.Arrays;
/**
* Architectural register file.
*
* @author Min Cai
*/
public final class ArchitecturalRegisterFile implements Cloneable {
/**
* Floating point registers.
*/
public static class FloatingPointRegisters implements Cloneable {
private int[] data = new int[32];
private boolean littleEndian;
/**
* Create a set of floating point registers.
*
* @param littleEndian a value indicating whether the set of floating point registers is little endian or not.
*/
public FloatingPointRegisters(boolean littleEndian) {
this.littleEndian = littleEndian;
}
/**
* Create a set of floating point registers.
*
* @param littleEndian a value indicating whether the set of floating point registers is little endian or not.
* @param data the data array
*/
public FloatingPointRegisters(boolean littleEndian, int[] data) {
this.littleEndian = littleEndian;
this.data = data;
}
@Override
protected Object clone() throws CloneNotSupportedException {
return new FloatingPointRegisters(this.littleEndian, this.data.clone());
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FloatingPointRegisters fpr = (FloatingPointRegisters) o;
if (littleEndian != fpr.littleEndian) return false;
if (!Arrays.equals(data, fpr.data)) return false;
return true;
}
@Override
public int hashCode() {
int result = Arrays.hashCode(data);
result = 31 * result + (littleEndian ? 1 : 0);
return result;
}
/**
* Get the value of a floating point register as an integer.
*
* @param index the index
* @return the value of a floating point register as an integer
*/
public int getInt(int index) {
return this.data[index];
}
/**
* Set the value of a floating point register as an integer.
*
* @param index the index
* @param i the value of a floating point register as an integer
*/
public void setInt(int index, int i) {
this.data[index] = i;
}
/**
* Get the value of a floating point register as a long integer.
*
* @param index the index
* @return the value of a floating point register as a long integer
*/
public long getLong(int index) {
int i = (index / 2) * 2;
int lo = this.getInt(i);
int hi = this.getInt(i + 1);
return ((long) (hi) << 32) + (lo & 0xFFFFFFFFL);
}
/**
* Set the value of a floating point register as a long integer.
*
* @param index the index
* @param d the value of a floating point register as a long integer
*/
public void setLong(int index, long d) {
int hi = ((int) (d >> 32));
int lo = ((int) ((d << 32) >> 32));
int i = (index / 2) * 2;
this.setInt(i, lo);
this.setInt(i + 1, hi);
}
/**
* Get the value of a floating point register as a float.
*
* @param index the index
* @return the value of a floating point register as a float
*/
public float getFloat(int index) {
return Float.intBitsToFloat(this.getInt(index));
}
/**
* Set the value of a floating point register as a float.
*
* @param index the index
* @param f the value of a floating point register as a float
*/
public void setFloat(int index, float f) {
this.setInt(index, Float.floatToRawIntBits(f));
}
/**
* Get the value of a floating point register as a double.
*
* @param index the index
* @return the value of a floating point register as a double
*/
public double getDouble(int index) {
return Double.longBitsToDouble(this.getLong(index));
}
/**
* Set the value of a floating point register as a double.
*
* @param index the index
* @param d the value of a floating point register as a double
*/
public void setDouble(int index, double d) {
this.setLong(index, Double.doubleToRawLongBits(d));
}
/**
* Get a value indicating whether the set of floating point registers is little endian or not.
*
* @return a value indicating whether the set of floating point registers is little endian or not
*/
public boolean isLittleEndian() {
return littleEndian;
}
}
private boolean littleEndian;
private int pc;
private int npc;
private int nnpc;
private int[] gprs = new int[32];
private FloatingPointRegisters fprs;
private int hi;
private int lo;
private int fcsr;
/**
* Create an architectural register file.
*
* @param littleEndian a value indicating whether the architectural register file is little endian or not
*/
public ArchitecturalRegisterFile(boolean littleEndian) {
this.littleEndian = littleEndian;
setPc(0);
setNpc(0);
setNnpc(0);
setFprs(new FloatingPointRegisters(this.littleEndian));
setHi(0);
setLo(0);
setFcsr(0);
}
@Override
public Object clone() throws CloneNotSupportedException {
ArchitecturalRegisterFile obj = new ArchitecturalRegisterFile(this.littleEndian);
obj.setPc(getPc());
obj.setNpc(this.getNpc());
obj.setNnpc(this.getNnpc());
obj.gprs = this.gprs.clone();
obj.setFprs((FloatingPointRegisters) this.getFprs().clone());
obj.setHi(this.getHi());
obj.setLo(this.getLo());
obj.setFcsr(this.getFcsr());
return obj;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ArchitecturalRegisterFile that = (ArchitecturalRegisterFile) o;
if (fcsr != that.fcsr) return false;
if (hi != that.hi) return false;
if (littleEndian != that.littleEndian) return false;
if (lo != that.lo) return false;
if (nnpc != that.nnpc) return false;
if (npc != that.npc) return false;
if (pc != that.pc) return false;
if (!fprs.equals(that.fprs)) return false;
if (!Arrays.equals(gprs, that.gprs)) return false;
return true;
}
@Override
public int hashCode() {
int result = (littleEndian ? 1 : 0);
result = 31 * result + pc;
result = 31 * result + npc;
result = 31 * result + nnpc;
result = 31 * result + Arrays.hashCode(gprs);
result = 31 * result + fprs.hashCode();
result = 31 * result + hi;
result = 31 * result + lo;
result = 31 * result + fcsr;
return result;
}
/**
* Copy the value of a register from the other architectural register file.
*
* @param theOtherRegisterFile the other architectural register file
* @param dep the dependency index
*/
public void copyRegisterFrom(ArchitecturalRegisterFile theOtherRegisterFile, int dep) {
Pair<RegisterDependencyType, Integer> depTypeNumPair = RegisterDependencyType.parse(dep);
RegisterDependencyType depType = depTypeNumPair.getFirst();
int num = depTypeNumPair.getSecond();
switch (depType) {
case INTEGER:
this.setGpr(num, theOtherRegisterFile.getGpr(num));
break;
case FLOAT:
this.fprs.setFloat(num, theOtherRegisterFile.fprs.getFloat(num));
break;
case MISC:
if (num == REGISTER_MISC_LO) {
this.lo = theOtherRegisterFile.lo;
} else if (num == REGISTER_MISC_HI) {
this.hi = theOtherRegisterFile.hi;
} else if (num == REGISTER_MISC_FCSR) {
this.fcsr = theOtherRegisterFile.fcsr;
}
break;
}
}
/**
* Get the value of a general purpose register (GPR).
*
* @param index the index
* @return the value of a general purpose register (GPR)
*/
public int getGpr(int index) {
return this.gprs[index];
}
/**
* Set the value of a general purpose register (GPR).
*
* @param index the index
* @param value the value of a general purpose register (GPR)
*/
public void setGpr(int index, int value) {
this.gprs[index] = value;
}
/**
* Dump the architectural register file.
*
* @return the text representation of the architectural register file
*/
public String dump() {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 32; i++) {
sb.append(String.format("%s = 0x%08x, \n", GPR_NAMES[i], this.gprs[i]));
}
sb.append(String.format("pc = 0x%08x, npc = 0x%08x, nnpc = 0x%08x", this.pc, this.npc, this.nnpc));
return sb.toString();
}
/**
* Get a value indicating whether the architectural register file is little endian or not.
*
* @return a value indicating whether the architectural register file is little endian or not
*/
public boolean isLittleEndian() {
return littleEndian;
}
/**
* Get the value of the program counter (PC).
*
* @return the value of the program counter (PC)
*/
public int getPc() {
return pc;
}
/**
* Set the value of the program counter (PC).
*
* @param pc the value of the program counter (PC)
*/
public void setPc(int pc) {
this.pc = pc;
}
/**
* Get the value of the next program counter (NPC).
*
* @return the value of the next program counter (NPC)
*/
public int getNpc() {
return npc;
}
/**
* Set the value of the next program counter (NPC).
*
* @param npc the value of the next program counter (NPC)
*/
public void setNpc(int npc) {
this.npc = npc;
}
/**
* Get the value of the next next program counter (NNPC).
*
* @return the value of the next next program counter (NNPC)
*/
public int getNnpc() {
return nnpc;
}
/**
* Set the value of the next next program counter (NNPC).
*
* @param nnpc the value of the next next program counter (NNPC)
*/
public void setNnpc(int nnpc) {
this.nnpc = nnpc;
}
/**
* Get the value of the HI register.
*
* @return the value of the HI register
*/
public int getHi() {
return hi;
}
/**
* Set the value of the HI register.
*
* @param hi the value of the HI register
*/
public void setHi(int hi) {
this.hi = hi;
}
/**
* Get the value of the LO register.
*
* @return the value of the LO register
*/
public int getLo() {
return lo;
}
/**
* Set the value of the LO register.
*
* @param lo the value of the LO register
*/
public void setLo(int lo) {
this.lo = lo;
}
/**
* Get the value of the FCSR register.
*
* @return the value of the FCSR register
*/
public int getFcsr() {
return fcsr;
}
/**
* Set the value of the FCSR register.
*
* @param fcsr the value of the FCSR register
*/
public void setFcsr(int fcsr) {
this.fcsr = fcsr;
}
/**
* Get the set of the floating point registers.
*
* @return the set of the floating point registers
*/
public FloatingPointRegisters getFprs() {
return fprs;
}
/**
* Set the set of the floating point registers.
*
* @param fprs the set of the floating point registers
*/
public void setFprs(FloatingPointRegisters fprs) {
this.fprs = fprs;
}
/**
* (General purpose register) GPR names.
*/
public static final String[] GPR_NAMES = new String[]{
"zero", "at", "v0", "v1", "a0", "a1", "a2", "a3",
"t0", "t1", "t2", "t3", "t4", "t5", "t6", "t6",
"s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7",
"t8", "t9", "k0", "k1", "gp", "sp", "fp", "ra"
};
/**
* Number of integer registers.
*/
public static final int NUM_INT_REGISTERS = 32;
/**
* Number of floating point registers.
*/
public static final int NUM_FLOAT_REGISTERS = 32;
/**
* Number of miscellaneous registers.
*/
public static final int NUM_MISC_REGISTERS = 3;
/**
* ZERO.
*/
public static final int REGISTER_ZERO = 0;
/**
* AT.
*/
public static final int REGISTER_AT = 1;
/**
* V0.
*/
public static final int REGISTER_V0 = 2;
/**
* V1.
*/
public static final int REGISTER_V1 = 3;
/**
* A0.
*/
public static final int REGISTER_A0 = 4;
/**
* A1.
*/
public static final int REGISTER_A1 = 5;
/**
* A2.
*/
public static final int REGISTER_A2 = 6;
/**
* A3.
*/
public static final int REGISTER_A3 = 7;
/**
* T0.
*/
public static final int REGISTER_T0 = 8;
/**
* T1.
*/
public static final int REGISTER_T1 = 9;
/**
* T2.
*/
public static final int REGISTER_T2 = 10;
/**
* T3.
*/
public static final int REGISTER_T3 = 11;
/**
* T4.
*/
public static final int REGISTER_T4 = 12;
/**
* T5.
*/
public static final int REGISTER_T5 = 13;
/**
* T6.
*/
public static final int REGISTER_T6 = 14;
/**
* T7.
*/
public static final int REGISTER_T7 = 15;
/**
* S0.
*/
public static final int REGISTER_S0 = 16;
/**
* S1.
*/
public static final int REGISTER_S1 = 17;
/**
* S2.
*/
public static final int REGISTER_S2 = 18;
/**
* S3.
*/
public static final int REGISTER_S3 = 19;
/**
* S4.
*/
public static final int REGISTER_S4 = 20;
/**
* S5.
*/
public static final int REGISTER_S5 = 21;
/**
* S6.
*/
public static final int REGISTER_S6 = 22;
/**
* S7.
*/
public static final int REGISTER_S7 = 23;
/**
* T8.
*/
public static final int REGISTER_T8 = 24;
/**
* T9.
*/
public static final int REGISTER_T9 = 25;
/**
* K0.
*/
public static final int REGISTER_K0 = 26;
/**
* K1.
*/
public static final int REGISTER_K1 = 27;
/**
* (Global pointer) GP.
*/
public static final int REGISTER_GP = 28;
/**
* (Stack pointer) SP.
*/
public static final int REGISTER_SP = 29;
/**
* (Frame pointer) FP.
*/
public static final int REGISTER_FP = 30;
/**
* (Return address) RA.
*/
public static final int REGISTER_RA = 31;
/**
* LO.
*/
public static final int REGISTER_MISC_LO = 0;
/**
* HI.
*/
public static final int REGISTER_MISC_HI = 1;
/**
* FCSR.
*/
public static final int REGISTER_MISC_FCSR = 2;
}