如何基于sc_fixed模板参数定义字长/整数位不同的sc_fixed变量?
问题:SystemC模板模块中基于sc_fixed输入类型定义中间定点变量
我希望编写一个通用SystemC模块,对不同表示的定点数据进行算法处理,因此将其实现为以定点输入/输出类型为模板参数的模块模板。我的算法中间操作需要比输入/输出类型更多的余量,因此想要声明一些整数位更多但小数位相同的中间定点变量。请问该如何实现?是否可以查询sc_fixed模板参数的字长/整数位长度,并在模块内利用这些值定义新的sc_fixed变量?
我尝试过使用wl()和iwl()方法,但这些方法仅在运行时求值,无法用作模板参数。
以下是无法正常工作的示例:
template <typename T> SC_MODULE(proc) { sc_in<bool> clk; // Clock signal sc_in<bool> rst_n; // Reset signal sc_in<T> in_sig; // Input signal sc_out<T> out_sig; // Output signal const T tttt; typedef sc_fixed<tttt.wl()+3, tttt.iwl()+3> internal_sig_t; internal_sig_t internal_sig_0, internal_sig_1; ... }
是否存在可行的实现方式?
注:作为临时解决方案,我可以传递sc_fixed的模板参数而非预定义类型,但如果存在多个输入/输出类型且不仅字长/整数位有不同选项时,这种方式会变得非常繁琐,因此我更倾向于不采用该方案。
解决方案
可以通过**模板元编程中的类型萃取(Type Trait)**实现编译时提取sc_fixed的模板参数,进而定义符合要求的中间定点类型。核心思路是利用C++模板特化,直接获取sc_fixed的字长、整数位等编译时常量参数,而非依赖运行时的成员函数。
步骤1:编写sc_fixed的类型萃取模板
首先定义一个通用的类型萃取模板,然后对sc_fixed进行特化,提取其所有模板参数:
#include <systemc> #include <systemc-ams> // 通用类型萃取模板框架 template <typename T> struct sc_fixed_traits; // 针对sc_fixed的特化萃取,提取所有模板参数 template <int WL, int IWL, sc_q_mode Q = SC_DEFAULT_Q_MODE, sc_o_mode O = SC_DEFAULT_O_MODE, int N_BITS = SC_DEFAULT_N_BITS> struct sc_fixed_traits<sc_fixed<WL, IWL, Q, O, N_BITS>> { static constexpr int word_length = WL; // 字长 static constexpr int integer_length = IWL; // 整数位长度 static constexpr sc_q_mode q_mode = Q; // 量化模式 static constexpr sc_o_mode o_mode = O; // 溢出模式 static constexpr int n_bits = N_BITS; // 舍入位数量 };
步骤2:在模块模板中使用类型萃取
在你的模板模块里,通过类型萃取获取输入类型T的参数,以此定义中间定点类型:
template <typename T> SC_MODULE(proc) { sc_in<bool> clk; // 时钟信号 sc_in<bool> rst_n; // 复位信号(低有效) sc_in<T> in_sig; // 输入信号 sc_out<T> out_sig; // 输出信号 // 提取输入sc_fixed类型的编译时参数 using fixed_traits = sc_fixed_traits<T>; // 定义中间类型:整数位+3,小数位与输入保持一致(小数位=字长-整数位,因此字长同步+3) using internal_sig_t = sc_fixed< fixed_traits::word_length + 3, fixed_traits::integer_length + 3, fixed_traits::q_mode, fixed_traits::o_mode, fixed_traits::n_bits >; internal_sig_t internal_sig_0, internal_sig_1; // 示例处理逻辑 void process() { if (!rst_n.read()) { internal_sig_0 = 0; internal_sig_1 = 0; out_sig.write(0); } else { // 中间运算:利用更大的位宽避免溢出 internal_sig_0 = in_sig.read() * 4; internal_sig_1 = internal_sig_0 + 1.5; // 最终转换回输出类型 out_sig.write(static_cast<T>(internal_sig_1)); } } SC_CTOR(proc) { SC_METHOD(process); sensitive << clk.pos() << rst_n.neg(); } };
原理说明
sc_fixed本身是模板类,其字长、整数位等参数都是编译时常量,类型萃取通过模板特化直接获取这些值,完全满足模板参数的编译时要求。- 这种方法无需额外传递sc_fixed的模板参数,即使模块有多个不同的sc_fixed输入/输出类型,也可以复用同一个类型萃取模板,避免了繁琐的参数传递。
内容的提问来源于stack exchange,提问作者monkey_nuts
相关产品推荐
相关产品推荐

