/*
 * Copyright (c) 2018 Ivan Deras.
 * Use of this source code is governed by the GPL v3 license
 * that can be found in the LICENSE file.
 */
package de.neemann.digital.hdl.verilog2;

import de.neemann.digital.hdl.printer.CodePrinterStr;
import de.neemann.digital.integration.ToBreakRunner;
import junit.framework.TestCase;

public class VerilogGeneratorTest extends TestCase {

    public void testComb() throws Exception {
        ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/comb.dig");
        CodePrinterStr out = new CodePrinterStr();
        VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out).export(br.getCircuit());

        assertEquals("/*\n"
                + " * Generated by Digital. Don't modify this file!\n"
                + " * Any changes will be lost if this file is regenerated.\n"
                + " */\n"
                + "module DIG_D_FF_1bit\n"
                + "#(\n"
                    + "    parameter Default = 0\n"
                    + ")\n"
                    + "(\n"
                    + "   input D,\n"
                    + "   input C,\n"
                    + "   output Q,\n"
                    + "   output \\~Q\n"
                    + ");\n"
                    + "    reg state;\n"
                    + "\n"
                    + "    assign Q = state;\n"
                    + "    assign \\~Q = ~state;\n"
                    + "\n"
                    + "    always @ (posedge C) begin\n"
                    + "        state <= D;\n"
                    + "    end\n"
                    + "\n"
                    + "    initial begin\n"
                    + "        state = Default;\n"
                    + "    end\n"
                    + "endmodule\n"
                    + "\n"
                    + "\n"
                    + "module comb (\n"
                    + "  input A,\n"
                    + "  input B,\n"
                    + "  input C,\n"
                    + "  output X,\n"
                    + "  output Y,\n"
                    + "  output Z,\n"
                    + "  output Aident\n"
                    + ");\n"
                    + "  wire Y_temp;\n"
                    + "  wire s0;\n"
                    + "  wire Z_temp;\n"
                    + "  assign Y_temp = (B | ~ C);\n"
                    + "  assign Z_temp = ~ A;\n"
                    + "  assign s0 = ((A | C) & (Z_temp | C) & 1'b1 & ~ (B | C) & Y_temp);\n"
                    + "  DIG_D_FF_1bit #(\n"
                    + "    .Default(0)\n"
                    + "  )\n"
                    + "  DIG_D_FF_1bit_i0 (\n"
                    + "    .D( s0 ),\n"
                    + "    .C( 1'b1 ),\n"
                    + "    .Q( X )\n"
                    + "  );\n"
                    + "  assign Y = Y_temp;\n"
                    + "  assign Z = Z_temp;\n"
                    + "  assign Aident = A;\n"
                    + "endmodule\n", out.toString());
    }

    public void testSplitter3() throws Exception {
        ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/splitter3.dig");
        CodePrinterStr out = new CodePrinterStr();
        VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out).export(br.getCircuit());

        assertEquals("/*\n"
                + " * Generated by Digital. Don't modify this file!\n"
                + " * Any changes will be lost if this file is regenerated.\n"
                + " */\n"
                + "\n"
                + "module splitter3 (\n"
                    + "  input [3:0] A,\n"
                    + "  input [3:0] B,\n"
                    + "  output [3:0] S\n"
                    + ");\n"
                    + "  assign S[1:0] = (A[1:0] & B[1:0]);\n"
                    + "  assign S[3:2] = (A[3:2] | B[3:2]);\n"
                    + "endmodule\n", out.toString());
    }

    public void testSplitter2() throws Exception {
        ToBreakRunner br = new ToBreakRunner("dig/hdl/model2/splitter2.dig");
        CodePrinterStr out = new CodePrinterStr();
        VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out).export(br.getCircuit());

        assertEquals("/*\n"
                + " * Generated by Digital. Don't modify this file!\n"
                + " * Any changes will be lost if this file is regenerated.\n"
                + " */\n"
                + "\n"
                + "module splitter2 (\n"
                    + "  input [1:0] A,\n"
                    + "  input [1:0] B,\n"
                    + "  output X,\n"
                    + "  output [2:0] Y\n"
                    + ");\n"
                    + "  wire [3:0] s0;\n"
                    + "  assign s0[1:0] = A;\n"
                    + "  assign s0[3:2] = B;\n"
                    + "  assign X = s0[0];\n"
                    + "  assign Y = s0[3:1];\n"
                    + "endmodule\n", out.toString());
    }

    public void testSplitter2I() throws Exception {
        ToBreakRunner br = new ToBreakRunner("dig/hdl/splitter2.dig");
        CodePrinterStr out = new CodePrinterStr();
        VerilogGenerator gen = new VerilogGenerator(br.getLibrary(), out).export(br.getCircuit());

        assertEquals("/*\n"
                + " * Generated by Digital. Don't modify this file!\n"
                + " * Any changes will be lost if this file is regenerated.\n"
                + " */\n"
                + "\n"
                + "module splitter2 (\n"
                    + "  input [15:0] inst,\n"
                    + "  output [15:0] \\9SD \n"
                    + ");\n"
                    + "  wire s0;\n"
                    + "  assign s0 = inst[8];\n"
                    + "  assign \\9SD [7:0] = inst[7:0];\n"
                    + "  assign \\9SD [8] = s0;\n"
                    + "  assign \\9SD [9] = s0;\n"
                    + "  assign \\9SD [10] = s0;\n"
                    + "  assign \\9SD [11] = s0;\n"
                    + "  assign \\9SD [12] = s0;\n"
                    + "  assign \\9SD [13] = s0;\n"
                    + "  assign \\9SD [14] = s0;\n"
                    + "  assign \\9SD [15] = s0;\n"
                    + "endmodule\n", out.toString());
    }


}