#include <systemc>

using namespace sc_core;
using namespace sc_dt;
using namespace std;

SC_MODULE(Adder) {
    sc_out<sc_logic> S, Cout;
    sc_in<sc_logic> A, B, Cin;
    SC_CTOR(Adder) {
        SC_METHOD(add);
        sensitive << A << B << Cin;
    }
private:
    void add() { 
        S = A ^ B ^ Cin;
        Cout = A & B | Cin & (A ^ B);
    }
};

SC_MODULE(Testbench) {
    sc_out<sc_logic> TA, TB, TCin;
    SC_CTOR(Testbench) {
        SC_THREAD(testprocess);
    }
private:
    void testprocess() {
        TA = SC_LOGIC_0;
        TB = SC_LOGIC_0;
        TCin = SC_LOGIC_0;
        wait(10, SC_NS);
        TA = SC_LOGIC_1;
        wait(10, SC_NS);
        TB = SC_LOGIC_1;
        wait(10, SC_NS);
        TCin = SC_LOGIC_1;
        wait(10, SC_NS);
        TA = SC_LOGIC_0;
        TB = SC_LOGIC_0;
        TCin = SC_LOGIC_0;
    }
};

int sc_main(int argc, char *argv[]) {
    sc_signal<sc_logic> A, B, Cin;
    sc_signal<sc_logic> S, Cout;
    Adder adder("adder"); 
    adder.A(A);
    adder.B(B);
    adder.Cin(Cin);
    adder.S(S);
    adder.Cout(Cout);
    Testbench tb("tb");
    tb.TA(A);
    tb.TB(B);
    tb.TCin(Cin);
    
    // Record (trace) signals for verification
    auto tf = sc_create_vcd_trace_file("trace");
    tf->set_time_unit(1, SC_NS);
    sc_trace(tf, A, "A");
    sc_trace(tf, B, "B");
    sc_trace(tf, Cin, "Cin");
    sc_trace(tf, S, "S");
    sc_trace(tf, Cout, "Cout");

    // Start the simulation for 200ns 
    sc_start(200, SC_NS);

    sc_close_vcd_trace_file(tf);
    return 0;
}
