//  *********************************************************************************************
//  Project Version  : v1.0
//  Project          : [BCDC] Microtec Academy Course: Building a RISC-V CPU with SystemVerilog
//  -----
//  Copyright (c)    : 2025 Fraunhofer IIS, Department IDS
//  Created          : 15.Oct.2025  by Bomin Kim
//  Last Modified    : 23.Oct.2025  by Bomin Kim       [commit 2f8f03d]
//  -----
//  HISTORY          : Date         By         Comments
//                     -----------  ---------  -------------------------------------------------
//  *********************************************************************************************



`timescale 1ns/1ns

module alu_tb();

  // Local Signals
  logic[2:0]   aluOp;
  logic        aluNegAr;
  logic        aluBypass;
  logic[31:0]  op1;
  logic[31:0]  op2;
  logic[31:0]  result;
  logic        eqFlag;

  // Toplevel instance (DUT)
  alu u_alu (
    .aluOp(aluOp),
    .aluNegAr(aluNegAr),
    .aluBypass(aluBypass),
    .op1(op1),
    .op2(op2),
    .result(result),
    .eqFlag(eqFlag)
  );

  // list of aluOp
  localparam logic[2:0] f3add    = 3'b000;
  localparam logic[2:0] f3sl     = 3'b001;
  localparam logic[2:0] f3slt    = 3'b010;
  localparam logic[2:0] f3sltU   = 3'b011;
  localparam logic[2:0] f3xor    = 3'b100;
  localparam logic[2:0] f3sr     = 3'b101;
  localparam logic[2:0] f3or     = 3'b110;
  localparam logic[2:0] f3and    = 3'b111;

  // Initialize and run simulation
  initial begin
    dumpWave("wave.vcd");

    // Initialize inputs
    aluOp = 0;
    aluNegAr = 0;
    aluBypass = 0;
    op1 = 0;
    op2 = 0;
    #10

    // Set op1 and op2
    op1 = 32'hDEAD_BEEF; op2 = 32'h0000_0001; #70
    $display("\nTime =  %0dns \t  : op1 = %h, op2 = %h", $time, op1, op2);

    $display("\nTime =  %0dns \t  : Is op1 and op2 equal?; eqFlag = %d", $time, eqFlag);

    aluBypass = 1; #70
    $display("\nTime =  %0dns \t  : AluBypass is set; result = %h", $time, result);

    aluBypass = 0; aluOp = f3add; #70
    $display("\nTime =  %0dns \t  : Alu operates addition; result = %h", $time, result);

    aluNegAr = 1; #70
    $display("\nTime =  %0dns \t  : Alu operates subtraction; result = %h", $time, result);

    aluNegAr = 0; aluOp = f3sl; #70
    $display("\nTime =  %0dns \t  : Alu operates shift left; result = %h", $time, result);

    aluOp = f3slt; #70
    $display("\nTime =  %0dns \t  : Alu operates set less than; result = %h", $time, result);

    aluOp = f3sltU; #70
    $display("\nTime =  %0dns \t  : Alu operates set less than (unsigned); result = %h", $time, result);

    aluOp = f3xor; #70
    $display("\nTime =  %0dns \t  : Alu operates bit-wise XOR; result = %h", $time, result);

    aluOp = f3sr; aluNegAr = 1; #70
    $display("\nTime =  %0dns \t  : Alu operates arithmetic right shift; result = %h", $time, result);

    aluNegAr = 0; #70
    $display("\nTime =  %0dns \t  : Alu operates logical right shift; result = %h", $time, result);

    aluOp = f3or; #70
    $display("\nTime =  %0dns \t  : Alu operates bit-wise OR; result = %h", $time, result);

    aluOp = f3and; #70
    $display("\nTime =  %0dns \t  : Alu operates bit-wise AND; result = %h", $time, result);
    $finish;

  end

  // Wave Dump Helper Task
  task dumpWave(string fileName);
    // Open wave file and dump all signals (2D arrays not included)
    $display("\nTime =  %0dns \t  : Opening wave file '%s'", $time, fileName);
    $dumpfile(fileName);
    $display("Time =  %0dns \t  : Dumping all %s signals in wave file (2D arrays not included)", $time, "alu_tb");
    $dumpvars(0, alu_tb);
  endtask: dumpWave

endmodule
