// File: /workspace/github_cpp_makefile_star2_O2/Sooryakiran[P]dotV/src/verilog.cpp
// Function: Chip::auto_gen(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>)
string Chip::auto_gen(string head){
    /*------------------------------------------------------------------------------------------
    Automatically generates the chip module header definition

    Param : head (string), a module name.
    Returns : head_def

    Example if head = "module MY_CHIP"
    ------------------------------------------------------------------------------------------*/

    string head_def = head + " (";

    /*------------------------------------------------------------------------------------------
    head_def will be "module MY_CHIP("

    The next stage checks for any input declarations and head def will be appended
    ------------------------------------------------------------------------------------------*/

    for(vector<string>::iterator i = this->input_names.begin(); i != this->input_names.end(); i++){
        if(i!=this->input_names.begin()){
            head_def += ", ";
        }
        string input = *i;
        head_def += wire_name(input);
    }

    /*------------------------------------------------------------------------------------------
    The next stage checks for any output declarations and head def will be appended
    ------------------------------------------------------------------------------------------*/
    for(vector<string>::iterator i = this->output_names.begin(); i != this->output_names.end(); i++){
        string input = *i;
        head_def += ", " + wire_name(input);
    }
    head_def += ");";

    /*------------------------------------------------------------------------------------------
    At this stage head_def will be "module MY_CHIP(my_input_1, my_input_2, my_output);"
    ------------------------------------------------------------------------------------------*/

    // string pre = "";
    // if(this->n_bits > 1){
    //     pre = "[" + to_string(this->n_bits -1) + ": 0] ";
    // } 
    
    head_def += "\n\t// Transistor count : " + to_string(this->num_transistors()) + "\n";
    /*------------------------------------------------------------------------------------------
    In the next stage we again write these inputs and outputs inside the module. We also checked
    for the bit width to make appropriate declarations.
    ------------------------------------------------------------------------------------------*/
    head_def += "\n\t// Inputs\n\n";

    for(int i=0; i < this->input_names.size(); i++){
        if(this->is_input_reg.at(i))
            head_def += "\tinput reg "  + this->input_names.at(i) + ";\n";
        else
            head_def += "\tinput "  + this->input_names.at(i) + ";\n";
    }

    head_def += "\n\t// Outputs\n\n";
    for(int i=0; i < this->output_names.size(); i++){
        if(this->is_output_reg.at(i))
            head_def += "\toutput reg "  + this->output_names.at(i) + ";\n";
        else
            head_def += "\toutput "  + this->output_names.at(i) + ";\n";
    }

    /*------------------------------------------------------------------------------------------
    At this stage head_def will be assuming 8 bit width
    """
    module MY_CHIP(my_input_1, my_input_2, my_output);
        // Inputs
        input [7:0] my_input_1;
        input [7:0] my_input_2;
        // Outputs
        output [7:0] my_output;
    """
    ------------------------------------------------------------------------------------------*/

    /*------------------------------------------------------------------------------------------
    Now we add any wires and reg declared.
    ------------------------------------------------------------------------------------------*/
    head_def += "\n\t// Wires\n\n";
    for(vector<string>::iterator i = this->wires.begin(); i != this->wires.end(); i++){
        head_def += "\twire " + *i + ";\n";
    }

    head_def += "\n\t// Regs\n\n";
    for(vector<string>::iterator i = this->regs.begin(); i != this->regs.end(); i++){
        head_def += "\treg " + *i + ";\n";
    }

    /*------------------------------------------------------------------------------------------
    Embed any verilog codes.
    ------------------------------------------------------------------------------------------*/
    head_def += "\n\t// Extras\n\n";
    for(vector<string>::iterator i = this->extras.begin(); i != this->extras.end(); i++){
        head_def += "\t"+ *i + "\n";
    }

    /*------------------------------------------------------------------------------------------
    At this stage head_def will be something like
    """
    module MY_CHIP(my_input_1, my_input_2, my_output);
        // Inputs
        input [7:0] my_input_1;
        input [7:0] my_input_2;

        // Outputs
        output [7:0] my_output;

        // Wires
        wire my_wire_1;
        wire my_wire_2;
        wire [7:0] my_wide_wire;

        // Extras
        assign my_wire_1 = 0;

    """
    ------------------------------------------------------------------------------------------*/

    /*------------------------------------------------------------------------------------------
    Now add submodule instances.
    ------------------------------------------------------------------------------------------*/

    head_def += "\n\t// Sub Modules\n\n";
    for(vector<Chip>::iterator i = this->submodules.begin(); i != this->submodules.end(); i++){
        head_def += "\t" + i->generate + "\n";
    }

    /*------------------------------------------------------------------------------------------
    Now we add the behaviours specified
    ------------------------------------------------------------------------------------------*/

    head_def += "\n\t// Behaviours\n\n";
    for(vector<BehaviourModel>::iterator i = this->behaviours.begin(); i != this->behaviours.end(); i++){
        string code = i->code();
        size_t index = 0;
        while(string::npos != (index = code.find('\n', index))){
            code.replace(index, 1, "\n\t");
            index +=2;
        }
        

        head_def += "\t" + code + "\n";
    }

    head_def += "\nendmodule\n";

    /*------------------------------------------------------------------------------------------
    At this stage head_def will be something like
    """
    module MY_CHIP(my_input_1, my_input_2, my_output);
        // Inputs
        input [7:0] my_input_1;
        input [7:0] my_input_2;

        // Outputs
        output [7:0] my_output;

        // Wires
        wire my_wire_1;
        wire my_wire_2;
        wire [7:0] my_wide_wire;

        // Regs
        reg a;

        // Extras
        assign my_wire_1 = 0;

        // Submodules
        AND_GATE my_and_1(my_input_1[0], my_input_2[0], my_wire_1);
        ...

        // Behaviours
        
        always @(posedge my_input_1);
        begin;
            a <= ~my_input_2;
        end;

        ...

    endmodule
    """
    ------------------------------------------------------------------------------------------*/
    return head_def;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0xc8, %rsp
movq %rsi, %rbx
leaq 0x138bf(%rip), %rax     # 0x1f06d
movq %rdi, -0x30(%rbp)
movq %rdx, %rsi
movq %rax, %rdx
callq 0xa960
leaq 0xe0(%rbx), %rax
movq %rax, -0x40(%rbp)
movq %rbx, -0x38(%rbp)
movq 0xe0(%rbx), %rbx
leaq -0x80(%rbp), %r14
leaq -0xe8(%rbp), %r15
leaq -0x60(%rbp), %r12
leaq 0x13887(%rip), %r13     # 0x1f070
movq -0x38(%rbp), %rax
cmpq 0xe8(%rax), %rbx
je 0xb856
movq -0x40(%rbp), %rax
cmpq (%rax), %rbx
je 0xb80b
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xae40
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa40
movq %r15, %rdi
movq %r14, %rsi
callq 0xaa40
movq %r12, %rdi
movq %r15, %rsi
callq 0xa5f0
movq -0x30(%rbp), %rdi
movq %r12, %rsi
callq 0xaeb0
movq %r12, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
movq %r14, %rdi
callq 0xa370
addq $0x20, %rbx
jmp 0xb7e9
movq -0x38(%rbp), %rax
leaq 0x120(%rax), %rcx
movq %rcx, -0x88(%rbp)
movq 0x120(%rax), %rbx
leaq -0x80(%rbp), %r14
leaq -0xc8(%rbp), %r15
leaq -0xa8(%rbp), %r12
leaq -0x60(%rbp), %r13
movq -0x38(%rbp), %rax
cmpq 0x128(%rax), %rbx
je 0xb8f7
movq %r14, %rdi
movq %rbx, %rsi
callq 0xaa40
movq %r15, %rdi
movq %r14, %rsi
callq 0xaa40
movq %r12, %rdi
movq %r15, %rsi
callq 0xa5f0
movq %r13, %rdi
leaq 0x137b3(%rip), %rsi     # 0x1f070
movq %r12, %rdx
callq 0xac40
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r12, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
movq %r14, %rdi
callq 0xa370
addq $0x20, %rbx
jmp 0xb885
leaq 0x13e13(%rip), %rsi     # 0x1f711
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rdi
callq 0xa7c0
leaq -0xa8(%rbp), %rdi
movl %eax, %esi
callq 0xa9a0
leaq 0x1374e(%rip), %rsi     # 0x1f073
leaq -0x60(%rbp), %rdi
leaq -0xa8(%rbp), %rdx
callq 0xac40
leaq 0x137cc(%rip), %rdx     # 0x1f108
leaq -0x80(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0xa150
leaq -0x80(%rbp), %rsi
movq -0x30(%rbp), %rbx
movq %rbx, %rdi
callq 0xaeb0
leaq -0x80(%rbp), %rdi
callq 0xa370
leaq -0x60(%rbp), %rdi
callq 0xa370
leaq -0xa8(%rbp), %rdi
callq 0xa370
leaq 0x1370e(%rip), %rsi     # 0x1f08c
movq %rbx, %rdi
callq 0xae40
movq -0x38(%rbp), %rax
leaq 0xf8(%rax), %rbx
xorl %r15d, %r15d
leaq 0x1370e(%rip), %r14     # 0x1f0a9
leaq -0x60(%rbp), %r12
leaq -0x80(%rbp), %r13
movq -0x38(%rbp), %rcx
movq 0xe8(%rcx), %rax
subq 0xe0(%rcx), %rax
sarq $0x5, %rax
cmpq %r15, %rax
jbe 0xba60
movq %rbx, %rdi
movq %r15, %rsi
callq 0xae80
testq %rdx, (%rax)
je 0xba10
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0xa200
movq %r12, %rdi
leaq 0x136b2(%rip), %rsi     # 0x1f09a
movq %rax, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r12, %rsi
leaq 0x136a9(%rip), %rdx     # 0x1f0a6
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
jmp 0xba48
movq -0x40(%rbp), %rdi
movq %r15, %rsi
callq 0xa200
movq %r12, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r12, %rsi
leaq 0x1366f(%rip), %rdx     # 0x1f0a6
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r12, %rdi
callq 0xa370
incq %r15
jmp 0xb9a3
leaq 0x1364a(%rip), %rsi     # 0x1f0b1
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
leaq 0x138(%rax), %rbx
xorl %r13d, %r13d
leaq 0x13648(%rip), %r14     # 0x1f0cd
leaq -0x60(%rbp), %r15
leaq -0x80(%rbp), %r12
movq -0x38(%rbp), %rcx
movq 0x128(%rcx), %rax
subq 0x120(%rcx), %rax
sarq $0x5, %rax
cmpq %r13, %rax
jbe 0xbb50
movq %rbx, %rdi
movq %r13, %rsi
callq 0xae80
testq %rdx, (%rax)
je 0xbafd
movq -0x88(%rbp), %rdi
movq %r13, %rsi
callq 0xa200
movq %r15, %rdi
leaq 0x135eb(%rip), %rsi     # 0x1f0c0
movq %rax, %rdx
callq 0xa6c0
movq %r12, %rdi
movq %r15, %rsi
leaq 0x135bc(%rip), %rdx     # 0x1f0a6
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r12, %rsi
callq 0xaeb0
jmp 0xbb38
movq -0x88(%rbp), %rdi
movq %r13, %rsi
callq 0xa200
movq %r15, %rdi
movq %r14, %rsi
movq %rax, %rdx
callq 0xa6c0
movq %r12, %rdi
movq %r15, %rsi
leaq 0x1357f(%rip), %rdx     # 0x1f0a6
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r12, %rsi
callq 0xaeb0
movq %r12, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
incq %r13
jmp 0xba8d
leaq 0x1357f(%rip), %rsi     # 0x1f0d6
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
movq 0xb0(%rax), %rbx
leaq 0x13571(%rip), %r14     # 0x1f0e3
leaq -0x60(%rbp), %r15
leaq 0x13529(%rip), %r12     # 0x1f0a6
leaq -0x80(%rbp), %r13
movq -0x38(%rbp), %rax
cmpq 0xb8(%rax), %rbx
je 0xbbcc
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
addq $0x20, %rbx
jmp 0xbb81
leaq 0x13517(%rip), %rsi     # 0x1f0ea
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
movq 0x160(%rax), %rbx
leaq 0x13508(%rip), %r14     # 0x1f0f6
leaq -0x60(%rbp), %r15
leaq 0x134ad(%rip), %r12     # 0x1f0a6
leaq -0x80(%rbp), %r13
movq -0x38(%rbp), %rax
cmpq 0x168(%rax), %rbx
je 0xbc48
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
addq $0x20, %rbx
jmp 0xbbfd
leaq 0x134ad(%rip), %rsi     # 0x1f0fc
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
movq 0xc8(%rax), %rbx
leaq 0x134c6(%rip), %r14     # 0x1f130
leaq -0x60(%rbp), %r15
leaq 0x13493(%rip), %r12     # 0x1f108
leaq -0x80(%rbp), %r13
movq -0x38(%rbp), %rax
cmpq 0xd0(%rax), %rbx
je 0xbcc4
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
addq $0x20, %rbx
jmp 0xbc79
leaq 0x1343f(%rip), %rsi     # 0x1f10a
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
movq 0x68(%rax), %rbx
leaq 0x1344d(%rip), %r14     # 0x1f130
leaq -0x60(%rbp), %r15
leaq 0x1341a(%rip), %r12     # 0x1f108
leaq -0x80(%rbp), %r13
movq -0x38(%rbp), %rax
cmpq 0x70(%rax), %rbx
je 0xbd41
addq $0x40, %rbx
movq %r15, %rdi
movq %r14, %rsi
movq %rbx, %rdx
callq 0xa6c0
movq %r13, %rdi
movq %r15, %rsi
movq %r12, %rdx
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r13, %rsi
callq 0xaeb0
movq %r13, %rdi
callq 0xa370
movq %r15, %rdi
callq 0xa370
addq $0x158, %rbx            # imm = 0x158
jmp 0xbcf2
leaq 0x133d5(%rip), %rsi     # 0x1f11d
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x38(%rbp), %rax
movq 0x178(%rax), %rsi
leaq -0x80(%rbp), %r12
pushq $0xa
popq %r13
leaq 0x133c4(%rip), %r14     # 0x1f12f
pushq $0x1
popq %rbx
movq -0x38(%rbp), %rax
cmpq 0x180(%rax), %rsi
je 0xbe21
movq %r12, %rdi
movq %rsi, -0x40(%rbp)
callq 0xa4d0
xorl %r15d, %r15d
movq %r12, %rdi
movl %r13d, %esi
movq %r15, %rdx
callq 0xa990
cmpq $-0x1, %rax
je 0xbdbc
movq %rax, %r15
movq %r12, %rdi
movq %rax, %rsi
movq %rbx, %rdx
movq %r14, %rcx
callq 0xa490
addq $0x2, %r15
jmp 0xbd8e
leaq -0xa8(%rbp), %rdi
leaq 0x13366(%rip), %rsi     # 0x1f130
movq %r12, %rdx
callq 0xa6c0
leaq -0x60(%rbp), %r15
movq %r15, %rdi
leaq -0xa8(%rbp), %rsi
leaq 0x13321(%rip), %rdx     # 0x1f108
callq 0xa150
movq -0x30(%rbp), %rdi
movq %r15, %rsi
callq 0xaeb0
movq %r15, %rdi
callq 0xa370
leaq -0xa8(%rbp), %rdi
callq 0xa370
movq %r12, %rdi
callq 0xa370
movq -0x40(%rbp), %rsi
addq $0x38, %rsi
jmp 0xbd6e
leaq 0x1330a(%rip), %rsi     # 0x1f132
movq -0x30(%rbp), %rdi
callq 0xae40
movq -0x30(%rbp), %rax
addq $0xc8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq %rax, %r14
leaq -0x80(%rbp), %rdi
callq 0xa370
jmp 0xbe58
movq %rax, %r14
leaq -0x60(%rbp), %rdi
callq 0xa370
jmp 0xbe66
movq %rax, %r14
leaq -0xa8(%rbp), %rdi
jmp 0xbf54
jmp 0xbf48
jmp 0xbf48
jmp 0xbede
jmp 0xbed9
jmp 0xbede
jmp 0xbed9
jmp 0xbed9
jmp 0xbede
jmp 0xbed9
jmp 0xbede
jmp 0xbf48
jmp 0xbf48
jmp 0xbf48
jmp 0xbf4d
movq %rax, %r14
jmp 0xbeb1
movq %rax, %r14
leaq -0x60(%rbp), %rdi
callq 0xa370
leaq -0xa8(%rbp), %rdi
jmp 0xbf3f
jmp 0xbf48
jmp 0xbf48
jmp 0xbed9
jmp 0xbede
jmp 0xbf48
jmp 0xbed9
jmp 0xbede
jmp 0xbf48
jmp 0xbed9
jmp 0xbede
jmp 0xbf48
movq %rax, %r14
jmp 0xbeea
movq %rax, %r14
leaq -0x80(%rbp), %rdi
callq 0xa370
leaq -0x60(%rbp), %rdi
jmp 0xbf54
jmp 0xbf48
jmp 0xbf48
jmp 0xbf4d
movq %rax, %r14
jmp 0xbf18
movq %rax, %r14
jmp 0xbf0c
movq %rax, %r14
leaq -0x60(%rbp), %rdi
callq 0xa370
leaq -0xa8(%rbp), %rdi
callq 0xa370
leaq -0xc8(%rbp), %rdi
jmp 0xbf3f
jmp 0xbf48
jmp 0xbf48
jmp 0xbf4d
movq %rax, %r14
jmp 0xbf38
movq %rax, %r14
leaq -0x60(%rbp), %rdi
callq 0xa370
leaq -0xe8(%rbp), %rdi
callq 0xa370
jmp 0xbf50
jmp 0xbf48
movq %rax, %r14
jmp 0xbf59
movq %rax, %r14
leaq -0x80(%rbp), %rdi
callq 0xa370
movq -0x30(%rbp), %rdi
callq 0xa370
movq %r14, %rdi
callq 0xad00