#!/usr/bin/env python3
#
# Copyright 2017 Jeff Bush
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

"""Making a stub unit test from a verilog module.

This is a quick and dirty helper for creating new unit tests.
It creates declarations for inputs and outputs, a reset block that zeroes
all inputs, and a stub test execution loop.
"""

import os
import sys

def main():
    source_file = sys.argv[1]
    modulename = os.path.splitext(os.path.basename(source_file))[0]
    output_file = 'test_' + modulename + '.sv'

    with open(output_file, 'w') as out:
        out.write('''

    `include "defines.svh"

    import defines::*;

    ''')

        out.write('module test_' + modulename + '(input clk, input reset);\n')

        input_names = []
        with open(sys.argv[1]) as f:
            for line in f:
                if 'input' in line or 'output' in line:
                    fields = line.split()
                    name = fields[-1]
                    if name.endswith(','):
                        name = name.rstrip(',')
                    elif name.endswith(');'):
                        name = name.rstrip(');')

                    if name == 'clk':
                        continue
                    elif name == 'reset':
                        continue

                    if fields[0] == 'input':
                        input_names += [name]

                    if len(fields) == 2:
                        out.write('    logic ' + name + ';\n')
                    elif fields[1].startswith('['):
                        out.write('    logic' +
                                ' '.join(fields[1:-1]) + ' ' + name + ';\n')
                    else:
                        out.write(
                            '    ' + ' '.join(fields[1:-1]) + ' ' + name + ';\n')

        out.write('    int cycle;\n')
        out.write('\n    ' + modulename + ' ' + modulename + '(.*);\n')
        out.write('''
        always_ff @(posedge clk, posedge reset)
        begin
            if (reset)
            begin
                cycle <= 0;
    ''')

        for net in input_names:
            if '[' in net:
                lbracket = net.find('[')
                rbracket = net.find(']')
                size = net[lbracket + 1:rbracket]
                signalname = net[:lbracket]
                out.write('            for (int i = 0; i < ' + size + '; i++)\n')
                out.write('                ' + signalname + '[i] <= \'0;\n')
                out.write('\n')
            else:
                out.write('            ' + net + ' <= \'0;\n')

        out.write('''        end
            else
            begin
                cycle <= cycle + 1;
                unique case (cycle)

                    // test cases...

                    0:
                    begin
                        $display("PASS");
                        $finish;
                    end
                endcase
            end
        end
    endmodule
    ''')

if __name__ == '__main__':
    main()
