美文网首页
高级综合工具StratusHLS学习笔记(3)

高级综合工具StratusHLS学习笔记(3)

作者: 月见樽 | 来源:发表于2020-03-27 15:18 被阅读0次

    学习目标:

    • 学习如何使用Stratus IDE生成存储器模型
    • 学习如何在代码中使用存储器模型

    1.存储器生成

    存储器生成使用Stratus IDE内置的存储器模型生成器,首先使用Stratus IDE打开工程,在左侧边栏中打开project选项卡,打开libraries,右键Memories,选择New Memory Library新建存储器库,新建后可以在工程下发现同名文件夹

    随后,右击新建的库memlib选择新建存储器,可以打开如下的界面进行配置:

    • Memory name:存储器名称,使用存储器时使用该名称进行调用
    • Word size:数据位宽,即每个地址存储多少个bit
    • Number of words:地址数量,即有多少个word,存储容量为Word size \times Number of wordsbit
    • Latency:从地址输入到数据输出消耗的时钟周期数量
    • Setup time:通常意义的建立时间加保持时间,即控制信号需要在时钟沿附近保持的长度,不要写0。
    • Output delay:输出延迟,即从时钟沿或数据输入到数据输出的延迟时间,不要写0。
    • Area:面积,HLS将在综合报告中使用该面积(如果填写)

    中间的Option部分可以选择时序的方式,时序有以下几种:

    • Allow chaining:使用左侧的Setup time和Output delay计入延迟估算,在必要时插入寄存器
    • Disallow chaining:不计入延迟估算,等效于Setup time和Output delay都填写0
    • Registers at memories:强制插入寄存器

    在这个页面填写常规信息后,点击上方的Port端口添加或编辑端口信息,该界面如下所示。可以通过编辑端口数量、选择端口类型和编辑端口名称,这些端口名称将在波形中体现。

    随后点击OK即可生成存储器模型,生成的存储器模型文件结构如下所示:

    在调用存储器模型的文件中,需要引用头文件memlib.h

    2.存储器使用

    在高级综合中使用存储器通过wrapper和port构成:

    • wrapper:存储器模块,通过调用该模块生成存储器
    • port:访问接口,在一个模块中声明一个存储器的port并将该port和wrapper指针连接即可进行存储器访问

    对于wrapper,其声明方式为<memory name>::wrapper<ioConfig> * point,例如声明一个名称为RAM的wrapper,命名为m_mem如下所示:

    RAM::wrapper<ioConfig> * m_mem;
    

    定义后需要在构造函数(SC_CTOR)中对其进行实例化和绑定clk和rst端口,如下所示:

    m_mem = new RAM::wrapper<ioConfig>("ram_wrapper");
    m_mem->clk_rst(clk,rst);
    

    对于port,声明方式为<memory name>::port<ioConfig> port,例如声明一个名称为RAM的port,命名为ram_port如下所示:

    RAM::port<ioConfig> ram_port;
    

    同样的,需要在构造函数中绑定clk和rst端口:

    ram_port.clk_rst(clk, rst);
    

    并且需要在顶层将wrapper绑定到端口上,如下所示(m_dut为ram_port所属的模块):

    m_dut->ram_port(*m_mem);
    

    随后可以使用类似数组的方式对存储进行访问,访问方式如下所示:

    read_data = ram_port[i] // 从i地址读取数据
    ram_port[i] = write_data // 将数据写入i地址
    

    最后,需要在project.tcl中添加存储器库,使用use_hls_lib指令,写法如下所示:

    use_hls_lib "./memlib"
    

    另外,对于一个存储器模型,具有以下的参数可以方便代码的编写:

    名称 说明
    <memory name>::SIZE 存储器word数量(Number of words)
    <memory name>::address_width 存储器地址位宽
    <memory name>::data_width 存储器数据位宽

    3.实际工程

    这里实现了一个将memory集成的加法器功能,功能为输入一个数据i,从存储器的地址i获取数据并与i相加,加法部分模块如下所示:

    #ifndef __DUT_TEMPLATE__H
    #define __DUT_TEMPLATE__H
    #include "cynw_p2p.h"
    #include "cynw_fifo.h"
    #include "defines.h"
    #include "memlib.h"
    SC_MODULE(dut_template) {
    public:
    
        cynw_p2p<DT, ioConfig>::in x_in;
        cynw_p2p<DT, ioConfig>::out y_out;
        RAM::port<ioConfig> ram_port;  // 存储器访问接口
        
        sc_in_clk clk;
        sc_in<bool> rst;
    
        SC_CTOR(dut_template):
            x_in("x_in"),
            y_out("y_out"), 
            clk("clk"), rst("rst")
        {
            SC_CTHREAD(t, clk.pos());
            reset_signal_is(rst, 0);
            x_in.clk_rst(clk, rst);
            y_out.clk_rst(clk, rst);
            ram_port.clk_rst(clk, rst);
        }
        void t();
    };
    
    #endif
    
    #include "dut_template.h"
    
    void dut_template::t() {
        {
            HLS_DEFINE_PROTOCOL("reset");
            x_in.reset();
            y_out.reset();
            ram_port.reset();
            wait();
        }
        for (int i = 0; i < RAM::SIZE; ++i) // 存储器初始化过程
        {
            ram_port[i] = i; // 写入存储器
        }
        while(1) {
            HLS_PIPELINE_LOOP(SOFT_STALL, 1, "main_loop"); // 使用流水线
            DT x_val = x_in.get();
            sc_uint<RAM::address_width> addr = x_val;  
            sc_uint<RAM::data_width> ram_data = ram_port[addr];  // 从存储器中读取数据
            DT out_val = x_val + ram_data;
            y_out.put(out_val);
        }
    }
    

    顶层模块如下所示:

    #ifndef _DUI_MEM
    #define _DUI_MEM
    #include "cynw_p2p.h"
    #include "cynw_fifo.h"
    #include "defines.h"
    #include "memlib.h"
    #include "dut_template_wrap.h"
    
    SC_MODULE(memory_acc_test) {
    public:
    
        cynw_p2p<DT, ioConfig>::base_in x_in;
        cynw_p2p<DT, ioConfig>::base_out y_out;
        
        RAM::wrapper<ioConfig> * m_mem;  // 定义RAM的wrapper
        dut_template_wrapper *m_dut;
        
        sc_in_clk clk;
        sc_in<bool> rst;
    
        SC_CTOR(memory_acc_test):
            x_in("x_in"),
            y_out("y_out"), 
            clk("clk"), rst("rst")
        {
            m_mem = new RAM::wrapper<ioConfig>("ram_wrapper"); // 实例化
            m_mem->clk_rst(clk,rst); // 绑定端口
    
            m_dut = new dut_template_wrapper("m_dut");
            m_dut->clk(clk);
            m_dut->rst(rst);
            m_dut->x_in(x_in);
            m_dut->y_out(y_out);
            m_dut->ram_port(*m_mem); // 将wrapper绑定到port上
        }
    };
    
    #endif
    

    对于以上工程,project.tcl中的库部分如下所示:

    set LIB_PATH "[get_install_path]/share/stratus/techlibs/GPDK045/gsclib045_svt_v4.4/gsclib045/timing"
    set LIB_LEAF "slow_vdd1v2_basicCells.lib"
    
    use_tech_lib    "$LIB_PATH/$LIB_LEAF"
    use_hls_lib "./memlib"
    

    除此之外,基本与之前的工程相同,进行仿真,不带流水线的结果如下所示:

    带流水线的结果如下所示:

    可以发现流水线有三级,分别是输入地址、获取输出和计算和。

    相关文章

      网友评论

          本文标题:高级综合工具StratusHLS学习笔记(3)

          本文链接:https://www.haomeiwen.com/subject/mwiluhtx.html