// ============================================================== // Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC v2019.2.1 (64-bit) // Copyright 1986-2019 Xilinx, Inc. All Rights Reserved. // ============================================================== #ifndef AESL_COMP_H #define AESL_COMP_H #include //#include "systemc.h" #define DEBUG(x) ///CFU: combinational FU, no clock, reset and ce //template template class AESLFUComp; template SC_MODULE( AESLCFUComp ) { public: sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; SC_CTOR( AESLCFUComp ); AESLFUComp *super; virtual void sanity_check() {} virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (super) return super->compute(in0, in1); else return sc_lv(); } void thread_compute() { DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] input: %llx %llx\n", din0.read().to_uint64(), din1.read().to_uint64()); else printf("[ACMP_ADD] input: %x %x\n", din0.read().to_uint(), din1.read().to_uint()); }); sc_lv result = compute(din0.read(), din1.read()); dout.write(result); DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] comb output: %llx\n", result.to_uint64()); else printf("[ACMP_ADD] comb output: %x\n", result.to_uint()); }); } }; template AESLCFUComp:: AESLCFUComp(const sc_module_name name): sc_module( name ), super(0) { //sanity_check(); SC_METHOD( thread_compute ); sensitive << din0; sensitive << din1; } ///FU: sequential FU, with clock, reset and ce template SC_MODULE(AESLFUComp) { AESLCFUComp core; public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; /// Dont use stage_regvec[0]. sc_signal< sc_lv > stage_regvec[NUM_STAGE]; SC_CTOR( AESLFUComp ); virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return sc_lv(); } void thread_stage() { if (ce.read() == SC_LOGIC_0) return; dout.write(stage_regvec[NUM_STAGE-1]); for (unsigned i = NUM_STAGE-1; i > 1; --i) { stage_regvec[i].write(stage_regvec[i-1].read()); } DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] reg output %llx\n", stage_regvec[NUM_STAGE-1].read().to_uint64()); else printf("[ACMP_ADD] reg output %x\n", stage_regvec[NUM_STAGE-1].read().to_uint()); }); } }; template AESLFUComp:: AESLFUComp(const sc_module_name name): sc_module( name ), core("CFU_U") { //sanity_check(); core.din0(din0); core.din1(din1); core.dout(stage_regvec[1]); core.super = this; if (NUM_STAGE > 1) { SC_METHOD( thread_stage ); sensitive << clk.pos(); } } //Need refine here////////////////////////////////////////////////////////////// ///CFU: combinational FU, no clock, reset and ce //template template class AESLFUComp_seq; template SC_MODULE( AESLCFUComp_seq ) { public: sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; SC_CTOR( AESLCFUComp_seq ); AESLFUComp_seq *super; virtual void sanity_check() {} virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (super) return super->compute(in0, in1); else return sc_lv(); } void thread_compute() { DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] input: %llx %llx\n", din0.read().to_uint64(), din1.read().to_uint64()); else printf("[ACMP_ADD] input: %x %x\n", din0.read().to_uint(), din1.read().to_uint()); }); sc_lv result = compute(din0.read(), din1.read()); dout.write(result); DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] comb output: %llx\n", result.to_uint64()); else printf("[ACMP_ADD] comb output: %x\n", result.to_uint()); }); } }; template AESLCFUComp_seq:: AESLCFUComp_seq(const sc_module_name name): sc_module( name ), super(0) { //sanity_check(); SC_METHOD( thread_compute ); sensitive << din0; sensitive << din1; } ///FU: sequential FU, with clock, reset, ce and start template SC_MODULE(AESLFUComp_seq) { AESLCFUComp_seq core; public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_logic > start; sc_in< sc_logic > done; sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; /// Dont use stage_regvec[0]. sc_signal< sc_lv > stage_regvec[NUM_STAGE]; SC_CTOR( AESLFUComp_seq ); virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return sc_lv(); } void thread_stage() { if (ce.read() == SC_LOGIC_0) return; dout.write(stage_regvec[NUM_STAGE-1]); for (unsigned i = NUM_STAGE-1; i > 1; --i) { stage_regvec[i].write(stage_regvec[i-1].read()); } DEBUG( { if (DIN0_WIDTH == 64) printf("[ACMP_ADD] reg output %llx\n", stage_regvec[NUM_STAGE-1].read().to_uint64()); else printf("[ACMP_ADD] reg output %x\n", stage_regvec[NUM_STAGE-1].read().to_uint()); }); } }; template AESLFUComp_seq:: AESLFUComp_seq(const sc_module_name name): sc_module( name ), core("CFU_U") { //sanity_check(); core.din0(din0); core.din1(din1); core.dout(stage_regvec[1]); core.super = this; if (NUM_STAGE > 1) { SC_METHOD( thread_stage ); sensitive << clk.pos(); } } //end/////////////////////////////////////////////////////////////////////////// template struct FUComputeCore { virtual sc_lv compute(const sc_lv& opcode, const sc_lv& in)=0; }; //////////////////////////////////////////////////////////////// // Abstract Multi-op combinational Functional Units. //////////////////////////////////////////////////////////////// template SC_MODULE( AESLCFUMOComp ) { public: sc_in< sc_lv > opcode; sc_in< sc_lv > din; sc_out< sc_lv > dout; public: SC_CTOR( AESLCFUMOComp ) { assert(OPC_WIDTH > 0 && DIN_WIDTH > 0 && DOUT_WIDTH > 0 && NUM_STAGE == 1); SC_METHOD( thread_compute ); sensitive << opcode << din; } //virtual sc_lv //compute(const sc_lv& opcode, const sc_lv& in) { FUComputeCore* mCore; void setComputeCore(FUComputeCore* core) { mCore = core; } FUComputeCore* getComputeCore() { return mCore; } public: void thread_compute() { DEBUG( cerr << "[ACMP] " << name() << " Input: " << din.read() << endl; ); assert(mCore); sc_lv result; if (din.read().is_01()) { result = mCore->compute(opcode.read(), din.read()); } else { result = sc_lv(); } dout.write(result); DEBUG( cerr << "[ACMP] " << name() << " C-out: " << result << endl;); } }; //////////////////////////////////////////////////////////////// // Abstract Pipelined Functional Units. //////////////////////////////////////////////////////////////// template SC_MODULE( AESLFUMultiCycle ) { public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > opcode; sc_in< sc_lv > din; sc_out< sc_lv > dout; public: SC_CTOR( AESLFUMultiCycle ) { assert(OPC_WIDTH > 0 && DIN_WIDTH > 0 && DOUT_WIDTH > 0 && NUM_STAGE > 0); SC_METHOD( thread_compute ); sensitive << opcode << din; sensitive << clk; if (NUM_STAGE > 1) { SC_METHOD( thread_stage ); sensitive << (clk.pos()); } } //virtual sc_lv //compute(const sc_lv& opcode, const sc_lv& in) { FUComputeCore* mCore; void setComputeCore(FUComputeCore* core) { mCore = core; } FUComputeCore* getComputeCore() { return mCore; } public: sc_signal< sc_lv > stage_regvec[NUM_STAGE]; void thread_compute() { DEBUG( cerr << "[ACMP] " << name() << " Input: " << din.read() << endl; ); assert(mCore); sc_lv result; if (din.read().is_01() && opcode.read().is_01()) { result = mCore->compute(opcode.read(), din.read()); } else { result = sc_lv(); } if (NUM_STAGE > 1) stage_regvec[1].write(result); else dout.write(result); DEBUG( cerr << "[ACMP] " << name() << " C-out: " << result << endl;); } void thread_stage() { if (ce.read() == SC_LOGIC_0) return; dout.write(stage_regvec[NUM_STAGE-1]); for (unsigned i = NUM_STAGE-1; i > 1; --i) { stage_regvec[i].write(stage_regvec[i-1].read()); } DEBUG( cerr << "[ACMP] " << name() << " R-out: " << stage_regvec[NUM_STAGE-1].read() << endl;); } }; //////////////////////////////////////////////////////////////// /// Unary operator //////////////////////////////////////////////////////////////// template< int NUM_STAGE, int DIN0_WIDTH, int DOUT_WIDTH=DIN0_WIDTH> SC_MODULE( CFUUnaryOp ) { public: sc_in< sc_lv > din0; sc_out< sc_lv > dout; SC_CTOR(CFUUnaryOp) { mMCModule = new AESLFUMultiCycle ("u_U"); mMCModule->opcode(sigone); mMCModule->din(din0); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); SC_METHOD(IOConnection); } AESLFUMultiCycle* mMCModule; void setComputeCore(FUComputeCore<1, DIN0_WIDTH, DOUT_WIDTH>* core) { mMCModule->setComputeCore(core); } private: sc_signal< sc_lv<1> > sigone; sc_signal< bool > clk; sc_signal< sc_logic > reset; sc_signal< sc_logic > ce; void IOConnection() { sigone.write(sc_lv<1>("1")); } }; template< int NUM_STAGE, int DIN0_WIDTH, int DOUT_WIDTH=DIN0_WIDTH> SC_MODULE( FUUnaryOp ) { public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > din0; sc_out< sc_lv > dout; SC_CTOR(FUUnaryOp) { mMCModule = new AESLFUMultiCycle ("u_U"); mMCModule->opcode(sigone); mMCModule->din(din0); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); SC_METHOD(IOConnection); sensitive << clk; } AESLFUMultiCycle* mMCModule; void setComputeCore(FUComputeCore<1, DIN0_WIDTH, DOUT_WIDTH>* core) { mMCModule->setComputeCore(core); } private: sc_signal< sc_lv<1> > sigone; void IOConnection() { sigone.write(sc_lv<1>("1")); } }; template< int NUM_STAGE, int OPC_WIDTH, int DIN0_WIDTH, int DOUT_WIDTH> SC_MODULE( FUMOUnaryOp ) { public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > opcode; sc_in< sc_lv > din0; sc_out< sc_lv > dout; SC_CTOR(FUMOUnaryOp) { mMCModule = new AESLFUMultiCycle ("mu_U"); mMCModule->opcode(opcode); mMCModule->din(din0); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); } AESLFUMultiCycle* mMCModule; void setComputeCore(FUComputeCore* core) { mMCModule->setComputeCore(core); } }; template< int NUM_STAGE, int DIN0_WIDTH, int DIN1_WIDTH, int DOUT_WIDTH> SC_MODULE (CFUBinaryOp) { public: sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; AESLFUMultiCycle* mMCModule; SC_CTOR( CFUBinaryOp ) { mMCModule = new AESLFUMultiCycle ("b_u"); //sigone.write(sc_lv<1>("1")); mMCModule->opcode(sigone); mMCModule->din(din_sig); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); SC_METHOD(IOConnection); sensitive << din0 << din1; } void setComputeCore(FUComputeCore<1, DIN0_WIDTH+DIN1_WIDTH, DOUT_WIDTH>* core) { mMCModule->setComputeCore(core); } sc_signal< sc_lv > din_sig; sc_signal< sc_lv<1> > sigone; sc_signal< bool > clk; sc_signal< sc_logic > reset; sc_signal< sc_logic > ce; void IOConnection() { sigone.write(sc_lv<1>("1")); sc_lv din_tmp; din_tmp.range(0, DIN0_WIDTH-1) = din0.read().range(0, DIN0_WIDTH-1); din_tmp.range(DIN0_WIDTH, DIN0_WIDTH+DIN1_WIDTH-1) = din1.read().range(0, DIN1_WIDTH-1); din_sig.write(din_tmp); } }; template< int NUM_STAGE, int DIN0_WIDTH, int DIN1_WIDTH, int DOUT_WIDTH> SC_MODULE (FUBinaryOp) { public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; AESLFUMultiCycle* mMCModule; SC_CTOR( FUBinaryOp ) { mMCModule = new AESLFUMultiCycle ("b_u"); //sigone.write(sc_lv<1>("1")); mMCModule->opcode(sigone); mMCModule->din(din_sig); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); SC_METHOD(IOConnection); sensitive << din0 << din1 << clk; } void setComputeCore(FUComputeCore<1, DIN0_WIDTH+DIN1_WIDTH, DOUT_WIDTH>* core) { mMCModule->setComputeCore(core); } sc_signal< sc_lv > din_sig; sc_signal< sc_lv<1> > sigone; void IOConnection() { sigone.write(sc_lv<1>("1")); sc_lv din_tmp; din_tmp.range(0, DIN0_WIDTH-1) = din0.read().range(0, DIN0_WIDTH-1); din_tmp.range(DIN0_WIDTH, DIN0_WIDTH+DIN1_WIDTH-1) = din1.read().range(0, DIN1_WIDTH-1); din_sig.write(din_tmp); } }; template< int NUM_STAGE, int OPC_WIDTH, int DIN0_WIDTH, int DIN1_WIDTH=DIN0_WIDTH, int DOUT_WIDTH=DIN0_WIDTH> SC_MODULE (CFUMOBinaryOp) { public: sc_in< sc_lv > opcode; sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; AESLCFUMOComp* mMCModule; SC_CTOR( CFUMOBinaryOp ) { mMCModule = new AESLCFUMOComp ("mb_U"); mMCModule->opcode(opcode); mMCModule->din(din_sig); mMCModule->dout(dout); SC_METHOD(IOConnection); sensitive << din0 << din1 << opcode ; } void setComputeCore(FUComputeCore* core) { mMCModule->setComputeCore(core); } sc_signal< sc_lv > din_sig; void IOConnection() { sc_lv din_tmp; din_tmp.range(0, DIN0_WIDTH-1) = din0.read().range(0, DIN0_WIDTH-1); din_tmp.range(DIN0_WIDTH, DIN0_WIDTH+DIN1_WIDTH-1) = din1.read().range(0, DIN1_WIDTH-1); din_sig.write(din_tmp); } }; template< int NUM_STAGE, int OPC_WIDTH, int DIN0_WIDTH, int DIN1_WIDTH=DIN0_WIDTH, int DOUT_WIDTH=DIN0_WIDTH> SC_MODULE (FUMOBinaryOp) { public: sc_in< bool > clk; sc_in< sc_logic > reset; sc_in< sc_logic > ce; sc_in< sc_lv > opcode; sc_in< sc_lv > din0; sc_in< sc_lv > din1; sc_out< sc_lv > dout; AESLFUMultiCycle* mMCModule; SC_CTOR( FUMOBinaryOp ) { mMCModule = new AESLFUMultiCycle ("mb_U"); mMCModule->opcode(opcode); mMCModule->din(din_sig); mMCModule->dout(dout); mMCModule->clk(clk); mMCModule->reset(reset); mMCModule->ce(ce); SC_METHOD(IOConnection); sensitive << din0 << din1 << opcode << clk; } void setComputeCore(FUComputeCore* core) { mMCModule->setComputeCore(core); } sc_signal< sc_lv > din_sig; void IOConnection() { sc_lv din_tmp; din_tmp.range(0, DIN0_WIDTH-1) = din0.read().range(0, DIN0_WIDTH-1); din_tmp.range(DIN0_WIDTH, DIN0_WIDTH+DIN1_WIDTH-1) = din1.read().range(0, DIN1_WIDTH-1); din_sig.write(din_tmp); } }; template< bool SIGNED, int DIN0_W, int DIN1_W=DIN0_W, int DOUT_W=DIN0_W> struct IntArithCoreDivRem : public FUComputeCore<2, DIN0_W+DIN1_W, DOUT_W> { virtual sc_lv compute(const sc_lv<2>& opcode, const sc_lv& in) { sc_lv in0; sc_lv in1; (in1, in0) = in; sc_lv undef; if (!opcode.is_01() || !in.is_01()) return undef; bool opc = opcode[0].to_bool(); if (!SIGNED) { unsigned long long val0 = in0.to_uint64(); unsigned long long val1 = in1.to_uint64(); if (val1 == 0) return undef; sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = opc ? (bval0 % bval1) : (bval0 / bval1); return sc_lv(boutv); } else { long long val0 = in0.to_int64(); long long val1 = in1.to_int64(); if (val1 == 0) return undef; sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = opc ? (bval0 % bval1) : (bval0 / bval1); return sc_lv(boutv); } } }; //////////////////////////////////////////////////////////////// // Integer UDIV/UREM component. //////////////////////////////////////////////////////////////// template struct ACMP_udivurem_comb : public CFUMOBinaryOp { ACMP_udivurem_comb(const char* mname ) : CFUMOBinaryOp(mname) { setComputeCore( new IntArithCoreDivRem()); } }; template struct ACMP_udivurem : public FUMOBinaryOp { ACMP_udivurem(const char* mname ) : FUMOBinaryOp(mname) { setComputeCore( new IntArithCoreDivRem()); } }; //////////////////////////////////////////////////////////////// // Integer SDIV/SREM component. //////////////////////////////////////////////////////////////// template struct ACMP_sdivsrem_comb : public CFUMOBinaryOp { ACMP_sdivsrem_comb(const char* mname ) : CFUMOBinaryOp(mname) { setComputeCore( new IntArithCoreDivRem()); } }; template struct ACMP_sdivsrem : public FUMOBinaryOp { ACMP_sdivsrem(const char* mname ) : FUMOBinaryOp(mname) { setComputeCore( new IntArithCoreDivRem()); } }; //////////////////////////////////////////////////////////////// // Integer UDIV component. //////////////////////////////////////////////////////////////// template struct ACMP_udiv_comb : public AESLCFUComp { public: ACMP_udiv_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned long long ival1 = (in1).to_uint64(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 / bval1; return sc_lv(boutv); } }; template struct ACMP_udiv : public AESLFUComp { public: ACMP_udiv(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); // assert(DIN0_WIDTH == DOUT_WIDTH); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned long long ival1 = (in1).to_uint64(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 / bval1; return sc_lv(boutv); } }; template struct ACMP_udiv_seq : public AESLFUComp_seq { public: ACMP_udiv_seq(const char* mname) : AESLFUComp_seq(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); // assert(DIN0_WIDTH == DOUT_WIDTH); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned long long ival1 = (in1).to_uint64(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 / bval1; return sc_lv(boutv); } }; template struct ACMP_sdiv_comb : public AESLCFUComp { public: ACMP_sdiv_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 / bval1; return sc_lv(boutv); } }; template struct ACMP_sdiv : public AESLFUComp { public: ACMP_sdiv(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); //assert(DIN0_WIDTH == DOUT_WIDTH); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 / bval1; return sc_lv(boutv); } }; template struct ACMP_sdiv_seq : public AESLFUComp_seq { public: ACMP_sdiv_seq(const char* mname) : AESLFUComp_seq(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); //assert(DIN0_WIDTH == DOUT_WIDTH); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 / bval1; return sc_lv(boutv); } }; template sc_lv compute_mul_ss(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); sc_bigint outi = sc_bigint(in0) * sc_bigint(in1); return sc_lv(outi); } template sc_lv compute_mul_su(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); sc_bigint outi = sc_bigint(in0) * sc_biguint(in1); return sc_lv(outi); } template sc_lv compute_mul_us(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); sc_bigint outi = sc_biguint(in0) * sc_bigint(in1); return sc_lv(outi); } template sc_lv compute_mul_uu(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); sc_biguint outi = sc_biguint(in0) * sc_biguint(in1); return sc_lv(outi); } template struct ACMP_mul_ss : public AESLFUComp { public: ACMP_mul_ss(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_ss(in0, in1); } }; template struct ACMP_mul_su : public AESLFUComp { public: ACMP_mul_su(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_su(in0, in1); } }; template struct ACMP_mul_us : public AESLFUComp { public: ACMP_mul_us(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_us(in0, in1); } }; template struct ACMP_mul_uu : public AESLFUComp { public: ACMP_mul_uu(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_uu(in0, in1); } }; template struct ACMP_smul_ss : public AESLCFUComp { public: ACMP_smul_ss(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_ss(in0, in1); } }; template struct ACMP_smul_su : public AESLCFUComp { public: ACMP_smul_su(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_su(in0, in1); } }; template struct ACMP_smul_us : public AESLCFUComp { public: ACMP_smul_us(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_us(in0, in1); } }; template struct ACMP_smul_uu : public AESLCFUComp { public: ACMP_smul_uu(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { return compute_mul_uu(in0, in1); } }; template struct ACMP_add_comb : public AESLCFUComp { public: typedef sc_bigint OpDataTypeT; ACMP_add_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT ival0 = OpDataTypeT(in0); OpDataTypeT ival1 = OpDataTypeT(in1); OpDataTypeT outi = ival0 + ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_add : public AESLFUComp { public: typedef sc_bigint OpDataTypeT; ACMP_add(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT ival0 = OpDataTypeT(in0); OpDataTypeT ival1 = OpDataTypeT(in1); OpDataTypeT outi = ival0 + ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_sub_comb : public AESLCFUComp { public: typedef sc_bigint OpDataTypeT; ACMP_sub_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT ival0 = OpDataTypeT(in0); OpDataTypeT ival1 = OpDataTypeT(in1); OpDataTypeT outi = ival0 - ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_sub : public AESLFUComp { public: typedef sc_bigint OpDataTypeT; ACMP_sub(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT ival0 = OpDataTypeT(in0); OpDataTypeT ival1 = OpDataTypeT(in1); OpDataTypeT outi = ival0 - ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_urem_comb : public AESLCFUComp { public: ACMP_urem_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 32); // assert(DIN1_WIDTH == DOUT_WIDTH); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned int ival0 = (in0).to_uint(); unsigned int ival1 = (in1).to_uint(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 % bval1; return sc_lv(boutv); } }; template struct ACMP_urem : public AESLFUComp { public: ACMP_urem(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned int ival0 = (in0).to_uint(); unsigned int ival1 = (in1).to_uint(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 % bval1; return sc_lv(boutv); } }; template struct ACMP_urem_seq : public AESLFUComp_seq { public: ACMP_urem_seq(const char* mname) : AESLFUComp_seq(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); unsigned int ival0 = (in0).to_uint(); unsigned int ival1 = (in1).to_uint(); if (ival1 == 0) return sc_lv(); sc_biguint bval0 = sc_biguint(in0); sc_biguint bval1 = sc_biguint(in1); sc_biguint boutv = bval0 % bval1; return sc_lv(boutv); } }; template struct ACMP_srem_comb : public AESLCFUComp { public: ACMP_srem_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 % bval1; return sc_lv(boutv); } }; template struct ACMP_srem : public AESLFUComp { public: ACMP_srem(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 % bval1; return sc_lv(boutv); } }; template struct ACMP_srem_seq : public AESLFUComp_seq { public: ACMP_srem_seq(const char* mname) : AESLFUComp_seq(mname) { sanity_check(); } virtual void sanity_check() { //assert(DIN0_WIDTH <= 64); } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if (!in0.is_01() || !in1.is_01()) return sc_lv(); int ival1 = (in1).to_int(); if (ival1 == 0) return sc_lv(); sc_bigint bval0 = sc_bigint(in0); sc_bigint bval1 = sc_bigint(in1); sc_bigint boutv = bval0 % bval1; return sc_lv(boutv); } }; // shl template struct ACMP_shl_comb : public AESLCFUComp { public: typedef sc_biguint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_shl_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); if(ival1>DIN0_WIDTH) return sc_lv(0); OpDataTypeT1 outi = ival0 << ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_shl : public AESLFUComp { public: typedef sc_biguint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_shl(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); if(ival1>DIN0_WIDTH) return sc_lv(0); OpDataTypeT1 outi = ival0 << ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; // lshr template struct ACMP_lshr_comb : public AESLCFUComp { public: typedef sc_biguint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_lshr_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); OpDataTypeT1 outi = ival0 >> ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_lshr : public AESLFUComp { public: typedef sc_biguint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_lshr(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); OpDataTypeT1 outi = ival0 >> ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; // ashr template struct ACMP_ashr_comb : public AESLCFUComp { public: typedef sc_bigint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_ashr_comb(const char* mname) : AESLCFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); OpDataTypeT1 outi = ival0 >> ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; template struct ACMP_ashr : public AESLFUComp { public: typedef sc_bigint OpDataTypeT1; typedef sc_biguint OpDataTypeT2; ACMP_ashr(const char* mname) : AESLFUComp(mname) { sanity_check(); } virtual void sanity_check() { } virtual sc_lv compute(const sc_lv& in0, const sc_lv& in1) { if(in0.is_01() && in1.is_01()) { OpDataTypeT1 ival0 = OpDataTypeT1(in0); OpDataTypeT2 ival1 = sc_bv(in1.range(DIN1_WIDTH-1, 0)); OpDataTypeT1 outi = ival0 >> ival1; return sc_lv(outi); } else return sc_lv(SC_LOGIC_X); } }; #endif