#ifndef __BS_PRIM_MOD_COUNTER_H__ #define __BS_PRIM_MOD_COUNTER_H__ #include "bluesim_kernel_api.h" #include "bs_module.h" #include "bs_reset.h" #include "bs_vcd.h" // This is the definition of the Probe primitive. template class MOD_Counter : public Module { public: MOD_Counter(tSimStateHdl simHdl, const char* name, Module* parent, unsigned int width, const T& init) : Module(simHdl, name, parent), saved_at(~bk_now(sim_hdl)), a_at(~bk_now(sim_hdl)), b_at(~bk_now(sim_hdl)), c_at(~bk_now(sim_hdl)), f_at(~bk_now(sim_hdl)), bits(width), reset_val(init) { init_val(val, bits); write_undet(&val, bits); init_val(a, bits); init_val(b, bits); init_val(c, bits); init_val(f, bits); init_val(saved_val, bits); in_reset = false; suppress_write = false; } public: const T& METH_value() const { if (bk_is_same_time(sim_hdl, saved_at)) return saved_val; else return val; } void METH_setC(const T& x) { if (!suppress_write) { if (saved_at != bk_now(sim_hdl)) { saved_at = bk_now(sim_hdl); saved_val = val; } c_at = bk_now(sim_hdl); c = x; val = x; if (a_at == bk_now(sim_hdl)) val += a; if (b_at == bk_now(sim_hdl)) val += b; mask_high_bits(&val,bits); } } void METH_addA(const T& x) { if (!suppress_write) { if (saved_at != bk_now(sim_hdl)) { saved_at = bk_now(sim_hdl); saved_val = val; } a_at = bk_now(sim_hdl); a = x; val += x; mask_high_bits(&val,bits); } } void METH_addB(const T& x) { if (!suppress_write) { if (saved_at != bk_now(sim_hdl)) { saved_at = bk_now(sim_hdl); saved_val = val; } b_at = bk_now(sim_hdl); b = x; val += x; mask_high_bits(&val,bits); } } // Note: addA, addB, setC < setF void METH_setF(const T& x) { if (!suppress_write) { if (saved_at != bk_now(sim_hdl)) { saved_at = bk_now(sim_hdl); saved_val = val; } f_at = bk_now(sim_hdl); f = x; val = x; } } const T& METH__read() const { return METH_value(); } void METH_incrA (const T& x) { METH_addA(x); } void METH_incrB (const T& x) { METH_addB(x); } void METH_update (const T& x) { METH_setC(x); } void METH__write (const T& x) { METH_setF(x); } public: // Setting the clock void set_clk_0(const char* s) { __clk_handle_0 = bk_get_or_define_clock(sim_hdl, s); } // Handle reset void reset_RST(tUInt8 rst_in) { in_reset = (rst_in == 0); if (in_reset) { start_reset_ticks(sim_hdl); /* request rst_tick() on the next clock edge */ } else { suppress_write = false; stop_reset_ticks(sim_hdl); /* stop rst_tick() when reset is not asserted */ } } void rst_tick__clk__1(tUInt8 clock_gate) { if (in_reset && (clock_gate != 0)) { val = reset_val; suppress_write = true; } } void rst_tick__clk__(tUInt8 clock_gate) { rst_tick__clk__1(clock_gate); } public: void dump_state(unsigned int indent) { printf("%*s%s = ", indent, "", inst_name); dump_val(val, bits); putchar('\n'); } unsigned int dump_VCD_defs(unsigned int /* num */) { vcd_num = vcd_reserve_ids(sim_hdl, 9); unsigned int n = vcd_num; vcd_write_def(sim_hdl, n++, inst_name, bits); vcd_write_scope_start(sim_hdl, inst_name); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "ADDA", 1); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "DATA_A", bits); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "ADDB", 1); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "DATA_B", bits); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "SETC", 1); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "DATA_C", bits); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "SETF", 1); vcd_set_clock(sim_hdl, n, __clk_handle_0); vcd_write_def(sim_hdl, n++, "DATA_F", bits); vcd_write_def(sim_hdl, vcd_num, "q_state", bits); // alias vcd_write_def(sim_hdl, vcd_num, "Q_OUT", bits); // alias vcd_write_scope_end(sim_hdl); return (vcd_num + 9); } void dump_VCD(tVCDDumpType dt, MOD_Counter& backing) { unsigned int num = vcd_num; if (dt == VCD_DUMP_XS) { vcd_write_x(sim_hdl, num++, bits); // inst, q_state, Q_OUT vcd_write_x(sim_hdl, num++, 1); // ADDA vcd_write_x(sim_hdl, num++, bits); // DATA_A vcd_write_x(sim_hdl, num++, 1); // ADDB vcd_write_x(sim_hdl, num++, bits); // DATA_B vcd_write_x(sim_hdl, num++, 1); // SETC vcd_write_x(sim_hdl, num++, bits); // DATA_C vcd_write_x(sim_hdl, num++, 1); // SETF vcd_write_x(sim_hdl, num++, bits); // DATA_F } else if (dt == VCD_DUMP_CHANGES) { if (backing.val != val) vcd_write_val(sim_hdl, num++, val, bits); else ++num; bool at_posedge = bk_clock_val(sim_hdl, __clk_handle_0) == CLK_HIGH && bk_clock_last_edge(sim_hdl, __clk_handle_0) == bk_now(sim_hdl); if (at_posedge) { did_adda = bk_is_same_time(sim_hdl, a_at); if (backing.did_adda != did_adda) { vcd_write_val(sim_hdl, num++, did_adda, 1); backing.did_adda = did_adda; } else ++num; if (backing.a != a) vcd_write_val(sim_hdl, num++, a, bits); else ++num; did_addb = bk_is_same_time(sim_hdl, b_at); if (backing.did_addb != did_addb) { vcd_write_val(sim_hdl, num++, did_addb, 1); backing.did_addb = did_addb; } else ++num; if (backing.b != b) vcd_write_val(sim_hdl, num++, b, bits); else ++num; did_setc = bk_is_same_time(sim_hdl, c_at); if (backing.did_setc != did_setc) { vcd_write_val(sim_hdl, num++, did_setc, 1); backing.did_setc = did_setc; } else ++num; if (backing.c != c) vcd_write_val(sim_hdl, num++, c, bits); else ++num; did_setf = bk_is_same_time(sim_hdl, f_at); if (backing.did_setf != did_setf) { vcd_write_val(sim_hdl, num++, did_setf, 1); backing.did_setf = did_setf; } else ++num; if (backing.f != f) vcd_write_val(sim_hdl, num++, f, bits); else ++num; } } else { vcd_write_val(sim_hdl, num++, val, bits); did_adda = bk_is_same_time(sim_hdl, a_at); vcd_write_val(sim_hdl, num++, did_adda, 1); vcd_write_val(sim_hdl, num++, a, bits); did_addb = bk_is_same_time(sim_hdl, b_at); vcd_write_val(sim_hdl, num++, did_addb, 1); vcd_write_val(sim_hdl, num++, b, bits); did_setc = bk_is_same_time(sim_hdl, c_at); vcd_write_val(sim_hdl, num++, did_setc, 1); vcd_write_val(sim_hdl, num++, c, bits); did_setf = bk_is_same_time(sim_hdl, f_at); vcd_write_val(sim_hdl, num++, did_setf, 1); vcd_write_val(sim_hdl, num++, f, bits); backing.did_adda = did_adda; backing.did_addb = did_addb; backing.did_setc = did_setc; backing.did_setf = did_setf; } if (backing.val != val) backing.val = val; if (backing.a != a) backing.a = a; if (backing.b != b) backing.b = b; if (backing.c != c) backing.c = c; if (backing.f != f) backing.f = f; } private: T val; T saved_val; T a; T b; T c; T f; tTime saved_at; tTime a_at; tTime b_at; tTime c_at; tTime f_at; const unsigned int bits; T reset_val; bool suppress_write; bool in_reset; // used for VCD dumping tClock __clk_handle_0; bool did_adda; bool did_addb; bool did_setc; bool did_setf; }; #endif /* __BS_PRIM_MOD_COUNTER_H__ */