@Test
  public void shouldProcessFirstStep()
      throws UnreachableLabelException, InvalidInstructionException {
    Instruction first = new InstructionIType("li $s0, 15");
    Instruction second = new InstructionIType("li $s1, 25");
    Instruction third = new InstructionRType("add $s2, $s1, $s0");
    Instruction fourth = new InstructionIType("addi $s3, $s2, 15");

    Datapath datapath =
        new Datapath(Arrays.asList(first, second, third, fourth), new HashMap<String, Integer>());

    datapath.moveForward();

    assertEquals("li", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    datapath.moveForward();

    assertEquals("li", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    datapath.moveForward();

    assertEquals("add", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(15, datapath.getExMem().getALUOut());

    datapath.moveForward();

    assertEquals("addi", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("add", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(25, datapath.getExMem().getALUOut());

    datapath.moveForward();

    assertEquals("NOP", datapath.getIfId().getInstructionFetched().getOperation());
    /*assertEquals("addi", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("add", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("li", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(25, datapath.getExMem().getALUOut());
    assertEquals(15, rBank.getValue("s0")); //J� carregou o valor de 15 para o banco de registradores no quinto ciclo
    assertEquals(0, rBank.getValue("s1")); //Mas, ainda n�o carregou o valor do s1...
    */
    // datapath.moveForward();
  }
  @Test
  public void shouldExecuteAddiOperation()
      throws UnreachableLabelException, InvalidInstructionException {
    Instruction first = new InstructionIType("addi $s0, $zero, 23");

    Datapath datapath = new Datapath(Arrays.asList(first), new HashMap<String, Integer>());

    datapath.moveForward();

    assertEquals("addi", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    datapath.moveForward();

    assertEquals("NOP", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("addi", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    datapath.moveForward();

    assertEquals("NOP", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("addi", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(23, datapath.getExMem().getALUOut());

    datapath.moveForward();

    assertEquals("NOP", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("addi", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(0, rBank.getValue("s0"));

    datapath.moveForward();

    assertEquals("NOP", datapath.getIfId().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getIdEx().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getExMem().getInstructionFetched().getOperation());
    assertEquals("NOP", datapath.getMemWb().getInstructionFetched().getOperation());

    assertEquals(
        23,
        rBank.getValue("s0")); // S� modificou o valor no banco de registradores no quinto est�gio
  }
  @Test
  public void shouldSimulateJump() throws InvalidInstructionException, UnreachableLabelException {
    Instruction first = new InstructionJType("j LABEL");
    Instruction second = new InstructionIType("addi $s1, $zero, 15");
    Instruction third = new InstructionRType("add $s2, $zero, $s3");

    Map<String, Integer> labels = new HashMap();
    labels.put("LABEL", 3);

    Datapath datapath = new Datapath(Arrays.asList(first, second, third), labels);

    // First Cycle
    // Stage 1 : Jump
    // Stage 2: NOP
    datapath.moveForward();
    System.out.println(datapath.getIfId().getInstructionFetched().getOperation());

    // Second Cycle
    // Stage 1 : NOP
    // Stage 2: Jump
    datapath.moveForward();
    System.out.println(datapath.getIfId().getInstructionFetched().getOperation());

    // Third Stage
    // Stage 1 : addi $s2
    // Stage 2 : NOP
    // Stage 3 : Jump
    datapath.moveForward();
    System.out.println(datapath.getIfId().getInstructionFetched().getOperation());

    // Fourth Stage
    datapath.moveForward();
    System.out.println(datapath.getIfId().getInstructionFetched().getOperation());

    // addi $s2, $zero, 20
  }