// DESCRIPTION: Verilator: Verilog Test module
//
// This file ONLY is placed under the Creative Commons Public Domain.
// SPDX-FileCopyrightText: 2020 Wilson Snyder
// SPDX-License-Identifier: CC0-1.0

`define printtype(mytype, expec) $write({"\"", $typename(mytype), "\" ==? \"", expec, "\"\n"});

// Copied from IEEE 1800-2023 20.6.1 Type name function
// source code // $typename would return
typedef bit node;  // "bit"
node [2:0] X;  // "bit [2:0]"
int signed Y;  // "int"

package A;
  enum {
    A,
    B,
    C = 99
  } X;  // "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::e$1"
  typedef bit [9:1'b1] word_t;  // "A::bit[9:1]"
  localparam type WORD_T = word_t;
endpackage : A

import A::*;

// moved into t
// module top;
//    typedef struct {node A,B;} AB_t;
//    AB_t AB[10]; // "struct{bit A;bit B;}top.AB_t$[0:9]"
// endmodule

module t;

  real r;
  logic l;
  typedef bit mybit_t;
  localparam type MYBIT_T = mybit_t;
  mybit_t [2:0] bitp20;
  mybit_t bitu32[3:2];
  mybit_t bitu31[3:1][4:5];
  string assoc[longint];
  int q[$];
  int q3[$:3];
  bit dyn[] = '{0, 0};

  class Cls;
    int m_c;
  endclass

  typedef union {node A, B;} UAB_t;

  // From LRM
  typedef struct {node A, B;} AB_t;
  AB_t AB[10];  // "struct{bit A;bit B;}top.AB_t$[0:9]"

  initial begin
    // $write({$typename(real), "\n"});
    `printtype(real, "real");
    `printtype(bit, "bit");
    `printtype(int, "int");
    `printtype(logic, "logic");
    `printtype(string, "string");
    `printtype(r, "real");
    `printtype(l, "logic");
    `printtype(mybit_t, "bit");
    `printtype(bitp20, "bit[2:0]");
    `printtype(bitu32, "bit$[3:2]");
    `printtype(bitu31, "bit$[3:1][4:5]");

    $write("\n");
    // from LRM
    `printtype(node, "bit");
    `printtype(X, "bit[2:0]");
    `printtype(Y, "int");

    `printtype(A::word_t, "bit[9:1]");
    `printtype(A::WORD_T, "bit[9:1]");
    `printtype(assoc, "string$[longint]");
    `printtype(q, "int$[$]");
    `printtype(q3, "int$[$:3]");  // Some omit :3 - need it so != unbounded
    `printtype(dyn, "bit$[]");

    $display;

    `printtype(
        A::X,
        "enum{A=32'sd0,B=32'sd1,C=32'sd99}A::<unspecified>");  // Some have just "enum <typename>"

    `printtype(AB_t, "struct{bit A;bit B;}<some_have_typename>");

    `printtype(AB, "struct{bit A;bit B;}top.AB_t$[0:9]");
    `printtype(UAB_t, "union{bit A;bit B;}");

    `printtype(Cls, "class{}t.Cls <or class t.Cls>");

    $display;
    $write("*-* All Finished *-*\n");
    $finish;
  end

endmodule
