// DESCRIPTION: Verilog::Preproc: Example source code
// This file ONLY is placed into the Public Domain, for any use,
// without warranty, 2000-2012 by Wilson Snyder.
   text.

//===========================================================================
// Includes

//===========================================================================
// Defines

`define DEF_A3
`define DEF_A1
// DEF_A0 set by command line
   wire [3:0] q = {
		   `ifdef DEF_A3 1'b1 `else 1'b0 `endif ,
		   `ifdef DEF_A2 1'b1 `else 1'b0 `endif ,
		   `ifdef DEF_A1 1'b1 `else 1'b0 `endif ,
		   `ifdef DEF_A0 1'b1 `else 1'b0 `endif
		   };

text.

`define FOOBAR  foo /*this */ bar   /* this too */
`define FOOBAR2  foobar2 // but not
`FOOBAR
`FOOBAR2

`define MULTILINE first part \
  		second part \
  		third part

`define MOREMULTILINE {\
		       a,\
		       b,\
		       c}

/*******COMMENT*****/
`MULTILINE
`MOREMULTILINE
Line_Preproc_Check `__LINE__

//===========================================================================

`define syn_negedge_reset_l or negedge reset_l

`define DEEP deep
`define DEEPER `DEEP `DEEP
`DEEPER

`define nosubst NOT_SUBSTITUTED
`define WITHTICK "`nosubst"
"Inside: `nosubst"
`WITHTICK

`define withparam(a, b) a b LLZZ a b
`withparam(x,y)
`withparam(`withparam(p,q),`withparam ( r , s ))

`withparam(firstline
	,
	comma","line)

`define withquote(a, bar) a bar LLZZ "a" bar
`withquote( x , y)  // Simulators disagree here; some substitute "a" others do not

`define noparam (a,b)
`noparam(a,b)

`define msg(x,y) `"x: `\`"y`\`"`"
$display(`msg(left side, right side))

`define foo(f) f``_suffix
`foo(bar)  more

`define zap(which)   \
	$c("Zap(\"",which,"\");");
`zap(bug1);
`zap("bug2");

/* Define inside comment: `DEEPER and `WITHTICK */
// More commentary: `zap(bug1); `zap("bug2");

//======================================================================
// display passthru

`define ls left_side
`define rs right_side
`define noarg  na
`define thru(x) x
`define thruthru `ls `rs	// Doesn't expand
`define msg(x,y) `"x: `\`"y`\`"`"
   initial begin
      //$display(`msg( \`, \`));  // Illegal
      $display(`msg(pre `thru(thrupre `thru(thrumid) thrupost) post,right side));
      $display(`msg(left side,right side));
      $display(`msg( left side , right side ));
      $display(`msg( `ls , `rs ));
      $display(`msg( `noarg , `rs ));
      $display(`msg( prep ( midp1 `ls midp2 ( outp ) ) , `rs ));
      $display(`msg(`noarg,`noarg`noarg));
      $display(`msg( `thruthru , `thruthru ));   // Results vary between simulators
      $display(`msg(`thru(),));  // Empty
      $display(`msg(`thru(left side),`thru(right side)));
      $display(`msg( `thru( left side ) , `thru( right side ) ));
      $display(`"standalone`");

      // Unspecified when the stringification has multiple lines
`define twoline first \
      second
      $display(`msg(twoline, `twoline));
      //$display(`msg(left side, \ right side \ ));  // Not sure \{space} is legal.
      $write("*-* All Finished *-*\n");
      $finish;
   end
endmodule

//======================================================================
// rt.cpan.org bug34429

`define ADD_UP(a,c)          \
wire  tmp_``a = a; \
wire  tmp_``c = tmp_``a + 1; \
assign c = tmp_``c ;

module add1 ( input wire d1, output wire o1);
 `ADD_UP(d1,o1)   // expansion is OK
endmodule
module add2 ( input wire d2, output wire o2);
 `ADD_UP( d2 , o2 )  // expansion is bad
endmodule

 `define check(mod, width, flopname, gate, path) \
   generate for (i=0; i<(width); i=i+1) begin \
      psl cover {  path.d[i] & ~path.q[i] & !path.cond & (gate)} report `"fondNoRise: mod.flopname`"; \
      psl cover { ~path.d[i] &  path.q[i] & !path.cond & (gate)} report `"fondNoFall: mod.flopname`"; \
   end endgenerate

// parameterized macro with arguments that are macros
 `define MK		m5k.f
 `define MF		`MK .ctl
 `define CK_fr	(`MF.alive & `MF.alive_m1)

   `check(m5kc_fcl, 3, _ctl_mvldx_m1, `CK_fr,	`MF._ctl_mvldx_m1)	// ignorecmt

//======================================================================
// Quotes are legal in protected blocks.  Grr.
module prot();
`protected
    I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl)
    #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk]
`endprotected
endmodule

module prot2();
`pragma protect begin_protected
`pragma protect encrypt_agent = "Whatever agent"
`pragma protect encrypt_agent_info = "1.2.3"
`pragma protect data_method = "aes128-cbc"
`pragma protect key_keyowner = "Someone"
`pragma protect key_keyname = "somekey", key_method = "rsa"
`pragma protect key_block encoding = (enctype = "base64")
   wefjosdfjklajklasjkl
`pragma protect data_block encoding = (enctype = "base64", bytes = 1059)
    I!#r#e6<_Q{{E2+]I3<[3s)1@D|'E''i!O?]jD>Jo_![Cl)
    #nj1]p,3^1~,="E@QZB\T)eU\pC#C|7=\$J$##A[@-@{Qk]
`pragma protect end_protected
`pragma reset protect
endmodule

module prot3();
//pragma protect begin_protected
//pragma protect key_keyowner=Cadence Design Systems.
//pragma protect key_keyname=CDS_KEY
//pragma protect key_method=RC5
//pragma protect key_block
zzZzZ/4ZzzZZZzzz4zZzZzZZZZzZzZ/Zz+33zZ2zz/zzzzzzzzZZZzZ4z+ZZZZz1
Z1ZzzzZZzZZzz9ZZZZ37zzZzZzZzzz9ZZzzZzZz9Zz64+z8Z7ZzZZZzzzzZZZzZz
zzZzZZZzZ0463zzzzzZzZ6z00z4zZzzZZzzZzzzZZ8zzz09ZzZZZZZ==
//pragma protect end_key_block
//pragma protect digest_block
ZzZZzzZ9ZZZZz2ZzzzZz/Zzzz8Z=
//pragma protect end_digest_block
//pragma protect data_block
ZZZ8zZzz6ZZ/zZZ5zZZzzz3ZzzzZzZZZ6ZzZzZZZZZz1zzZZZZ7ZZZZz3Zzz+9zz
4zzz+8zZzzzzZzZZzzzZzz1Z7ZzZz+zZz8ZZZZzZ6ZzzZzZZzzZZzzZzzZzZzZzZ
ZzzzzZ0zZz1ZzzZzzZzZzz==
//pragma protect end_data_block
//pragma protect digest_block
Z4Z6zZzZ3Z7ZZ6zzZZZZzzzzZZZ=
//pragma protect end_digest_block
//pragma protect end_protected
endmodule

//======================================================================
// macro call with define that has comma
`define REG_H   6
`define REG_L   7
`define _H      regs[`REG_H]
`define _L      regs[`REG_L]
`define _HL     {`_H, `_L}
`define EX_WRITE(ad, da)      begin addr <= (ad); wdata <= (da); wr <= 1; end
`define EX_READ(ad)           begin addr <= (ad); rd <= 1; end

`EX_READ((`_HL + 1)) and `EX_WRITE((`_HL), rdata)
`EX_READ(`_HL + 1)
`EX_WRITE(`_HL, rdata)  more

//======================================================================
// include of parameterized file
`define INCNAME "t_preproc_inc4.vh"
`include `INCNAME
`ifndef T_PREPROC_INC4
 `error "No Inc4"
`endif
`undef T_PREPROC_INC4

`ifdef NOT_DEFINED_INC
 `include NOT_DEFINED_INC
`endif

//======================================================================
// macro call with , in {}

`define xxerror(logfile, msg) $blah(logfile,msg)
`xxerror("ab,cd","e,f");
`xxerror(this.logfile, vec);
`xxerror(this.logfile, vec[1,2,3]);
`xxerror(this.logfile, {blah.name(), " is not foo"});

//======================================================================
// pragma/default net type

`pragma foo = 1
`default_nettype none
`default_nettype uwire

//======================================================================
// Ifdef

`define EMPTY_TRUE
`ifndef EMPTY_TRUE
  `error "Empty is still true"
`endif
Line_Preproc_Check `__LINE__

//======================================================================
// bug84

`define ARGPAR(a,  // Hello, comments MIGHT not be legal
  /*more,,)cmts*/ b  // But newlines ARE legal... who speced THAT?
  ) (a,b)
`ARGPAR(p,q)
`ARGPAR( //Here
	      x,
  y   //Too
  )
Line_Preproc_Check `__LINE__

//======================================================================
// defines split arguments

`define BEGIN begin
`define END end
`define BEGINEND `BEGIN`END
`define quoteit(x) `"x`"
`BEGIN`END   // 2001 spec doesn't require two tokens, so "beginend" ok
`BEGINEND    // 2001 spec doesn't require two tokens, so "beginend" ok
`quoteit(`BEGIN`END)  // No space "beginend"

//======================================================================
// bug106
`define \esc`def got_escaped
`ifdef \esc`def
  `\esc`def
`endif
Not a \`define

//======================================================================
// misparsed comma in submacro
`define sb bee
`define appease_emacs_paren_matcher (
`define sa(l) x,y)
`define sfoo(q,r) q--r
`sfoo(`sa(el),`sb)  submacro has comma paren

//======================================================================
// bug191
`define bug191(bits) $display("bits %d %d", $bits(foo), bits);
`bug191(10)

//======================================================================
// 1800-2009
`define UDALL
`ifndef PREDEF_COMMAND_LINE `error "Test setup error, PREDEF_COMMAND_LINE pre-missing" `endif
`undefineall
`ifdef UDALL `error "undefineall failed" `endif
`ifndef PREDEF_COMMAND_LINE `error "Deleted too much, no PREDEF_COMMAND_LINE" `endif

//======================================================================
// bug202
`define FC_INV3(out, in)					\
  `ifdef DC							\
     cell \inv_``out <$typeof(out)> (.a(<in>), .o(<out>));	\
      /* multi-line comment					\
	 multi-line comment */					\
  `else								\
    `ifdef MACRO_ATTRIBUTE					\
      (* macro_attribute = `"INV (out``,in``)`" *)		\
    `endif							\
     assign out = ~in ;						\
  `endif

`FC_INV3(a3,b3)

`define /* multi	\
	 line1*/	\
 bug202( i /*multi	\
	   line2*/	\
     )			\
   /* multi		\
      line 3*/		\
   def i		\

`bug202(foo)

//======================================================================

`define CMT1 // verilator NOT IN DEFINE
`define CMT2 /* verilator PART OF DEFINE */
`define CMT3 /* verilator NOT PART
	        OF DEFINE */
`define CMT4 /* verilator PART \
	        OF DEFINE */
`define CMT5 // CMT NOT \
  also in  // BUT TEXT IS \
  also3  // CMT NOT

1 `CMT1 (nodef)
2 `CMT2 (hasdef)
3 `CMT3 (nodef)
4 `CMT4 (nodef)
5 `CMT5 (nodef)
`define NL HAS a NEW \
LINE
`NL

//======================================================================

`define msg_fatal(log, msg)  \
   do \
      /* synopsys translate_off */ \
`ifdef NEVER \
  `error "WTF" \
`else \
      if (start(`__FILE__, `__LINE__)) begin \
`endif \
	 message(msg); \
      end \
      /* synopsys translate_on */ \
   while(0)

`define msg_scen_(cl)   cl``_scen
`define MSG_MACRO_TO_STRING(x) `"x`"

EXP: clxx_scen
`msg_scen_(clxx)
EXP: clxx_scen
`MSG_MACRO_TO_STRING(`msg_scen_(clxx))
`define mf(clx) `msg_fatal(this.log, {"Blah-", `MSG_MACRO_TO_STRING(`msg_scen_(clx)), " end"});
EXP: do if (start("verilog/inc1.v", 25)) begin  message({"Blah-", "clx_scen", " end"}); end  while(0);
`mf(clx)

//======================================================================

`define makedefine(name) \
   `define def_``name   This is name \
   `define def_``name``_2 This is name``_2 \

`makedefine(fooed)
`ifndef def_fooed  `error "No def_fooed" `endif
//`ifndef def_fooed_2  `error "No def_fooed_2" `endif
EXP: This is fooed
`def_fooed
EXP: This is fooed_2
`def_fooed_2

//======================================================================
`define NOPARAM() np
`NOPARAM()
`NOPARAM( )
//======================================================================
// It's unclear if the spec allows this; is text_macro_idenitfier before or after substitution?
`define NODS_DEFINED
`define NODS_INDIRECT(x) x
`ifndef `NODS_INDIRECT(NODS_DEFINED)
   `error "Indirect failed"
`endif
`ifdef `NODS_INDIRECT(NODS_UNDEFINED)
   `error "Indirect2 failed"
`endif
//======================================================================
// Metaprogramming
`define REPEAT_0(d)
`define REPEAT_1(d) d
`define REPEAT_2(d) `REPEAT_1(d)d
`define REPEAT_3(d) `REPEAT_2(d)d
`define REPEAT_4(d) `REPEAT_3(d)d

`define CONCAT(a, b) a``b
`define REPEATC(n, d) `CONCAT(`REPEAT_, n)(d)
`define REPEATT(n, d) `REPEAT_``n(d)

`REPEATC(3, hello3 )
`REPEATT(4, hello4 )
//======================================================================
// Include from stringification
`undef T_PREPROC_INC4
`define NODS_CONC_VH(m) `"m.vh`"
`include `NODS_CONC_VH(t_preproc_inc4)
`ifndef T_PREPROC_INC4 `error_here `endif
//======================================================================
// Defines doing defines
// Note the newline on the end - required to form the end of a define
`define DEFINEIT(d) d \

`define _DEFIF_Z_0 1
`define DEFIF_NZ(d,n) `undef d `ifndef _DEFIF_Z_``n `DEFINEIT(`define d 1) `endif
`DEFIF_NZ(TEMP,1)
`ifndef TEMP  `error "bad1" `endif
`DEFIF_NZ(TEMP,0)
`ifdef TEMP  `error "bad0" `endif
Line_Preproc_Check `__LINE__
//======================================================================
// Quoted multiline - track line numbers, and insure \\n gets propagated
`define MULQUOTE "FOO \
  BAR "
`define MULQUOTE2(mq) `MULQUOTE mq `MULQUOTE
Line_Preproc_Check `__LINE__
`MULQUOTE2("arg_line1 \
  arg_line2")
Line_Preproc_Check `__LINE__
//======================================================================
// bug283

`define A a
`define B b
`define C c
// EXP: abc
`define C5 `A``b```C
`C5
`undef A
`undef B
`undef C

`define XTYPE sonet
`define XJOIN(__arg1, __arg2) __arg1``__arg2
`define XACTION `XJOIN(`XTYPE, _frame)
EXP: sonet_frame
`XACTION
//
`define XFRAME frame
`define XACTION2 `XJOIN(sonet_, `XFRAME)
EXP: sonet_frame
`XACTION2
// This result varies between simulators
`define sonet_frame other_frame
`define XACTION3 `XTYPE``_frame
EXP: sonet_frame
`XACTION3

// The existance of non-existance of a base define can make a difference
`define QA_b zzz
`define Q1 `QA``_b
EXP: module zzz ; endmodule
module `Q1 ; endmodule
module `Q1 ; endmodule

`define QA a
EXP: module a_b ; endmodule
module `Q1 ; endmodule
module `Q1 ; endmodule

//======================================================================
// bug311
integer/*NEED_SPACE*/foo;
//======================================================================
synth_test:
// synopsys translate_off
synthesis_turned_off
// synthesis translate_on
EXP: on
//======================================================================
// bug441
module t;
   //-----
   // case provided
   // note this does NOT escape as suggested in the mail
`define LEX_CAT(lexem1, lexem2) lexem1``lexem2
`define LEX_ESC(name) \name  \

   initial begin : `LEX_ESC( `LEX_CAT(a[0],_assignment) )   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`LEX_CAT(a[0],_assignment) ");   end
   //-----
   // SHOULD(simulator-dependant): Backslash doesn't prevent arguments from
   // substituting and the \ staying in the expansion
   // Note space after name is important so when substitute it has ending whitespace
`define ESC_CAT(name,name2) \name``_assignment_``name2 \

   initial begin : `ESC_CAT( a[0],a[1] )   $write("GOT%%m='%m' EXP='%s'\n", "t.\\a[0]_assignment_a[1] ");   end
`undef ESC_CAT
   //-----
`define CAT(a,b) a``b
`define ESC(name) \`CAT(name,suffix)
   // RULE: Ignoring backslash does NOT allow an additional expansion level
   // (Because ESC gets expanded then the \ has it's normal escape meaning)
   initial begin : `ESC(pp)   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(pp,suffix) ");   end
`undef CAT `undef ESC
   //-----
`define CAT(a,b) a``b
`define ESC(name) \name \

   // Similar to above; \ does not allow expansion after substitution
   initial begin : `ESC( `CAT(ff,bb) )   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`CAT(ff,bb) ");   end
`undef CAT `undef ESC
   //-----
`define ESC(name) \name \

   // MUST: Unknown macro with backslash escape stays as escaped symbol name
   initial begin : `ESC( `zzz )   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`zzz ");   end
`undef ESC
   //-----
`define FOO bar
`define ESC(name) \name \

   // SHOULD(simulator-dependant): Known macro with backslash escape expands
   initial begin : `ESC( `FOO )    $write("GOT%%m='%m' OTHER_EXP='%s'\n OUR_EXP='%s'", "t.bar ","t.\\`FOO ");  end
   // SHOULD(simulator-dependant): Prefix breaks the above
   initial begin : `ESC( xx`FOO )   $write("GOT%%m='%m' EXP='%s'\n", "t.\\xx`FOO ");  end
`undef FOO `undef ESC
   //-----
   // MUST: Unknown macro not under call with backslash escape doesn't expand
`undef UNKNOWN
   initial begin : \`UNKNOWN   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`UNKNOWN ");   end
   //-----
   // MUST: Unknown macro not under call doesn't expand
`define DEF_NO_EXPAND  error_dont_expand
   initial begin : \`DEF_NO_EXPAND   $write("GOT%%m='%m' EXP='%s'\n", "t.\\`DEF_NO_EXPAND ");   end
`undef DEF_NO_EXPAND
   //-----
   // bug441 derivative
   // SHOULD(simulator-dependant): Quotes doesn't prevent arguments from expanding (like backslashes above)
`define STR(name) "foo name baz"
   initial $write("GOT='%s' EXP='%s'\n", `STR(bar), "foo bar baz");
`undef STR
   //-----
   // RULE: Because there are quotes after substituting STR, the `A does NOT expand
`define STR(name) "foo name baz"
`define A(name) boo name hiss
   initial $write("GOT='%s' EXP='%s'\n", `STR(`A(bar)), "foo `A(bar) baz");
`undef A  `undef STR
   //----
   // bug845
`define SLASHED "1//2.3"
   initial $write("Slashed=`%s'\n", `SLASHED);
   //----
   // bug915
`define BUG915(a,b,c) \
       $display("%s%s",a,`"b``c``\n`")
   initial `BUG915("a1",b2,c3);
endmodule

//======================================================================
//bug1225

`define X_ITEM(SUB,UNIT) `X_STRING(SUB``UNIT)
`define X_STRING(A) `"A`"
$display(`X_ITEM(RAM,0));
$display(`X_ITEM(CPU,));

`define EMPTY
`define EMPTYP(foo)
`define SOME some
`define SOMEP(foo) foo

`define XXE_FAMILY XXE_```EMPTY
XXE_FAMILY = `XXE_FAMILY
`define XXE_```EMPTY
`ifdef XXE_
     $display("XXE_ is defined");
`endif

`define XYE_FAMILY XYE_```EMPTYP(foo)
XYE_FAMILY = `XYE_FAMILY
`define XYE_```EMPTYP(foo)
`ifdef XYE_
     $display("XYE_ is defined");
`endif

`define XXS_FAMILY XXS_```SOME
XXS_FAMILY = `XXS_FAMILY
`define XXS_```SOME
`ifdef XXS_some
     $display("XXS_some is defined");
`endif

`define XYS_FAMILY XYS_```SOMEP(foo)
XYS_FAMILY = `XYS_FAMILY
`define XYS_```SOMEP(foo)
`ifdef XYS_foo
     $display("XYS_foo is defined");
`endif

//====

`ifdef NEVER
 `define NXE_FAMILY NXE_```EMPTY
NXE_FAMILY = `NXE_FAMILY
 `define NXE_```EMPTY
 `ifdef NXE_
     $display("NXE_ is defined");
 `endif

 `define NYE_FAMILY NYE_```EMPTYP(foo)
NYE_FAMILY = `NYE_FAMILY
 `define NYE_```EMPTYP(foo)
 `ifdef NYE_
     $display("NYE_ is defined");
 `endif

 `define NXS_FAMILY NXS_```SOME
NXS_FAMILY = `NXS_FAMILY
 `define NXS_```SOME
 `ifdef NXS_some
     $display("NXS_some is defined");
 `endif

 `define NYS_FAMILY NYS_```SOMEP(foo)
NYS_FAMILY = `NYS_FAMILY
 `define NYS_```SOMEP(foo)
 `ifdef NYS_foo
     $display("NYS_foo is defined");
 `endif

 `include `EMPTY

`endif // NEVER

//bug1227
`define INSTANCE(NAME) (.mySig (myInterface.``NAME),
`INSTANCE(pa5)

//======================================================================
// Stringify bug

`define hack(GRP) `dbg_hdl(UVM_LOW, (`"Functional coverage enabled: GRP`"));
`hack(paramgrp)

`define dbg_hdl(LVL, MSG)      $display ("DEBUG : %s [%m]", $sformatf MSG)
`define svfcov_new(GRP) \
   initial do begin `dbg_hdl(UVM_LOW, (`"Functional coverage enabled: GRP`")); end while(0)
`define simple_svfcov_clk(LBL, CLK, RST, ARG) \
  covergroup LBL @(posedge CLK); \
    c: coverpoint ARG iff ((RST) === 1'b1); endgroup \
      LBL u_``LBL; `svfcov_new(u_``LBL)

module pcc2_cfg;
  generate
   `simple_svfcov_clk(a, b, c, d);
  endgenerate
endmodule

//======================================================================
// Verilog-Perl bug1668
`define stringify(text) `"text`"
`stringify(`NOT_DEFINED_STR)

//======================================================================
// IEEE mandated predefines
`undefineall  // undefineall should have no effect on these
predef `SV_COV_START 0
predef `SV_COV_STOP 1
predef `SV_COV_RESET 2
predef `SV_COV_CHECK 3
predef `SV_COV_MODULE 10
predef `SV_COV_HIER 11
predef `SV_COV_ASSERTION 20
predef `SV_COV_FSM_STATE 21
predef `SV_COV_STATEMENT 22
predef `SV_COV_TOGGLE 23
predef `SV_COV_OVERFLOW -2
predef `SV_COV_ERROR -1
predef `SV_COV_NOCOV 0
predef `SV_COV_OK 1
predef `SV_COV_PARTIAL 2
