Lab 2: Hiyerarşik Transaction

Gün 2: Nesne Yönelimli Programlama (OOP) | Transaction modeli, kalıtım ve hata enjeksiyonu

Kaynak Kod

// =============================================================================
// GUN 2 - Lab 2: Hiyerarsik Transaction Modeli ve Hata Enjeksiyonu
// =============================================================================
// Bu lab'da:
// - Temel Transaction sinifi olusturulacak
// - Kalitim ile ReadTxn, WriteTxn alt siniflari turetilecek
// - Hata enjeksiyonu yapan ErrorTxn sinifi eklenecek
// - Polimorfizm ile heterojen kuyruk islenecek
// =============================================================================

// --- Temel Islem Sinifi ---
class Transaction;
  static int global_id = 0;
  
  int          id;
  logic [31:0] address;
  logic [31:0] data;
  bit          valid;
  int          timestamp;

  function new(logic [31:0] addr = 0, logic [31:0] data = 0);
    this.id      = global_id++;
    this.address = addr;
    this.data    = data;
    this.valid   = 1;
    this.timestamp = $time;
  endfunction

  virtual function string get_type();
    return "BASE";
  endfunction

  virtual function void display();
    $display("  [%5s] ID=%0d | Addr=0x%08h | Data=0x%08h | V=%0b | T=%0t",
             get_type(), id, address, data, valid, timestamp);
  endfunction

  virtual function Transaction copy();
    Transaction t = new(this.address, this.data);
    t.id = this.id;
    t.valid = this.valid;
    return t;
  endfunction

  virtual function bit compare(Transaction other);
    return (this.address == other.address && this.data == other.data);
  endfunction
endclass

// --- Okuma Islemi ---
class ReadTransaction extends Transaction;
  int burst_size;
  logic [31:0] read_data [$];

  function new(logic [31:0] addr, int burst = 1);
    super.new(addr, 0);
    this.burst_size = burst;
  endfunction

  virtual function string get_type();
    return "READ";
  endfunction

  task execute();
    $display("  >>> READ baslatildi: Addr=0x%08h, Burst=%0d", address, burst_size);
    for (int i = 0; i < burst_size; i++) begin
      #5;
      read_data.push_back($urandom);
    end
    $display("  <<< READ tamamlandi: %0d veri okundu", read_data.size());
  endtask

  virtual function void display();
    super.display();
    $display("         Burst=%0d, Okunan=%0d adet", burst_size, read_data.size());
  endfunction
endclass

// --- Yazma Islemi ---
class WriteTransaction extends Transaction;
  logic [3:0]  byte_enable;
  logic [31:0] write_data [$];

  function new(logic [31:0] addr, logic [31:0] data, logic [3:0] be = 4'hF);
    super.new(addr, data);
    this.byte_enable = be;
    write_data.push_back(data);
  endfunction

  virtual function string get_type();
    return "WRITE";
  endfunction

  function void add_data(logic [31:0] d);
    write_data.push_back(d);
  endfunction

  virtual function void display();
    super.display();
    $display("         BE=0x%01h, WData=%p", byte_enable, write_data);
  endfunction
endclass

// --- Hata Enjeksiyonu Sinifi ---
class ErrorTransaction extends WriteTransaction;
  typedef enum {NO_ERROR, ADDR_CORRUPT, DATA_CORRUPT, BOTH_CORRUPT} error_type_e;
  error_type_e error_mode;

  function new(logic [31:0] addr, logic [31:0] data, error_type_e err = NO_ERROR);
    super.new(addr, data);
    this.error_mode = err;
  endfunction

  virtual function string get_type();
    return "ERROR";
  endfunction

  function void inject_error();
    case (error_mode)
      ADDR_CORRUPT: begin
        address ^= 32'hFFFF_0000;
        $display("  [!] HATA ENJEKSIYONU: Adres bozuldu -> 0x%08h", address);
      end
      DATA_CORRUPT: begin
        data ^= 32'h0000_FFFF;
        $display("  [!] HATA ENJEKSIYONU: Veri bozuldu -> 0x%08h", data);
      end
      BOTH_CORRUPT: begin
        address ^= 32'hFFFF_0000;
        data    ^= 32'h0000_FFFF;
        $display("  [!] HATA ENJEKSIYONU: Her ikisi de bozuldu");
      end
      default: $display("  [OK] Hata yok");
    endcase
    valid = (error_mode == NO_ERROR);
  endfunction

  virtual function void display();
    super.display();
    $display("         Hata Modu: %s", error_mode.name());
  endfunction
endclass

// =============================================================================
module lab2_hiyerarsik_transaction;
  initial begin
    Transaction txn_queue [$];  // Polimorfik kuyruk

    $display("============================================================");
    $display("  LAB 2: Hiyerarsik Transaction Modeli");
    $display("============================================================\n");

    // --- 1. Cesitli islemler olustur ---
    $display("--- 1. Islem Olusturma ---");
    begin
      ReadTransaction  r1, r2;
      WriteTransaction w1, w2;
      ErrorTransaction e1, e2, e3;

      r1 = new(32'hA000_0000, 4);
      r2 = new(32'hA000_0100, 1);
      w1 = new(32'hB000_0000, 32'hDEAD_BEEF);
      w2 = new(32'hB000_0004, 32'hCAFE_BABE, 4'h3);
      e1 = new(32'hC000_0000, 32'h1234_5678, ErrorTransaction::ADDR_CORRUPT);
      e2 = new(32'hC000_0004, 32'hABCD_EF01, ErrorTransaction::DATA_CORRUPT);
      e3 = new(32'hC000_0008, 32'h9999_9999, ErrorTransaction::BOTH_CORRUPT);

      // Polimorfik kuyruga ekle
      txn_queue = {r1, r2, w1, w2, e1, e2, e3};
    end

    // --- 2. Tum islemleri goster ---
    $display("\n--- 2. Tum Islemler (Polimorfik display) ---");
    foreach (txn_queue[i]) begin
      txn_queue[i].display();
      $display();
    end

    // --- 3. Hata enjeksiyonu ---
    $display("--- 3. Hata Enjeksiyonu ---");
    foreach (txn_queue[i]) begin
      ErrorTransaction et;
      if ($cast(et, txn_queue[i])) begin
        et.inject_error();
        et.display();
        $display();
      end
    end

    // --- 4. Istatistikler ---
    $display("--- 4. Istatistikler ---");
    begin
      int read_count = 0, write_count = 0, error_count = 0, valid_count = 0;
      foreach (txn_queue[i]) begin
        ReadTransaction rt;
        WriteTransaction wt;
        ErrorTransaction et;
        if ($cast(et, txn_queue[i])) error_count++;
        else if ($cast(rt, txn_queue[i])) read_count++;
        else if ($cast(wt, txn_queue[i])) write_count++;
        if (txn_queue[i].valid) valid_count++;
      end
      $display("  Toplam     = %0d", txn_queue.size());
      $display("  READ       = %0d", read_count);
      $display("  WRITE      = %0d", write_count);
      $display("  ERROR      = %0d", error_count);
      $display("  Gecerli    = %0d", valid_count);
      $display("  Gecersiz   = %0d", txn_queue.size() - valid_count);
    end

    $display("\n============================================================");
    $display("  LAB 2 TAMAMLANDI");
    $display("============================================================");
    $finish;
  end
endmodule