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

学习目标为:

  • 如何使用高级综合生成流水线
  • 如何使用Stratus进行层次化设计

1.生成流水线

Stratus允许指定一个主循环(while(1))中的内容为流水线方式实现,即每个时钟周期均可以进入数据执行,需要在主循环开始时添加如下语句指定使用流水线实现:

HLS_PIPELINE_LOOP(<STALL_TYPE>, <cycle>, <name>);

上述指定该loop为流水线实现,具有三个参数,分别如下所示:

  • STALL_TYPE:实现类型,包括HARD_STALLSOFT_STALL两种
  • cycle:数据进入间隔,即“每隔多少个时钟周期可进入一个数据”,当cycle=1时表示每个周期均可进入数据
  • name:流水线配置名称,每个循环流水线名称不同即可

对于STALL_TYPE中的两种,具有以下的区别:

  • HARD_STALL:当流水线的某一级阻塞时,整条流水线停止运行
  • SOFT_STALL:当流水线的某一级阻塞时,仅阻塞级之前的流水线停止运行,阻塞级之后的流水线继续运行

对于要生成流水线的代码片(循环体),Stratus有以下的要求:

  • 循环展开(Nested Loops):循环体中仅可以嵌套次数指定的循环,且被指定生成流水线的循环要么为无限循环,要么为指定次数循环
  • 数据依赖(Data Dependencies):需要保证每一级需要的数据在运行这一级之前已经生成,即数据流向固定向前,不存在反向数据流(产生数据冲突),若发生这种情况Stratus会报错:Unable to satisfy HLS_HLS_PIPELINE_LOOP directive "main_pipeline",possibly because of a statement in this line.
  • 端口访问(Port Access Conflicts):对于端口的访问需要谨慎,需要避免连续两个周期访问一个端口的写法,因为会产生对端口的访问冲突(前一次进入loop和后一次loop在同一周期需要访问同一个接口),这种情况会报出Warning:Pipelining forces multiple assignments to output data_out
  • 非平衡流水线(Unbalanced Protocol Blocks):避免在展开为流水线的循环中使用消耗时钟周期不同的条件判断。即若在循环中使用if-else语句,两个代码块消耗的时钟周期必须一致。
  • 循环跳出(Conditional Exits in Pipelined Loops):允许使用break语句跳出循环,但用于判断是否跳出循环的逻辑消耗的时间必须少于数据进入间隔时钟周期

学习过程使用上一次使用的+1功能电路,将其执行线程改为以下按流水线展开:

void dut_template::t() {
    {
        HLS_DEFINE_PROTOCOL("reset");
        x_in.reset();
        y_out.reset();
        wait();
    }
    while(1) {
        // HLS_PIPELINE_LOOP(HARD_STALL, 1, "main_loop");
        HLS_PIPELINE_LOOP(SOFT_STALL, 1, "main_loop");
        DT x_val = x_in.get();
        DT out_val = x_val + 1;
        y_out.put(out_val);
    }
}

这里使用了输入间隔为1个周期(每个周期均可输入)的SOFT_STALL形式的流水线。

2.层次化设计

为了观察流水线功能,这次将两个+1功能模块dut_template连在一起进行仿真,顶层为pipeline_test,代码如下所所示:

#ifndef _DUT_PIPE
#define _DUT_PIPE

#include "cynw_p2p.h"
#include "cynw_fifo.h"
#include "defines.h"
#include "dut_template_wrap.h"

SC_MODULE(pipeline_test) {
public:
    cynw_p2p<DT, ioConfig>::base_in x_in;
    cynw_p2p<DT, ioConfig>::base_out y_out;
    cynw_p2p<DT, ioConfig> tmp;
    sc_in_clk clk;
    sc_in<bool> rst;

    dut_template_wrapper *ut0;
    dut_template_wrapper *ut1;

    SC_CTOR(pipeline_test):
        x_in("x_in"),y_out("y_out"),tmp("tmp"),
        clk("clk"),rst("rst") {

        ut0 = new dut_template_wrapper("ut0");
        ut0->clk(clk);
        ut0->rst(rst);
        ut0->x_in(x_in);
        ut0->y_out(tmp);

        ut1 = new dut_template_wrapper("ut1");
        ut1->clk(clk);
        ut1->rst(rst);
        ut1->x_in(tmp);
        ut1->y_out(y_out);
    }   

    // void t();  不可调用函数进行连线!!!

};

#endif

首先关注使用的p2p接口如下所示:

    cynw_p2p<DT, ioConfig>::base_in x_in;
    cynw_p2p<DT, ioConfig>::base_out y_out;

需要注意的是本次使用了base_inbase_out而不是inout(参考笔记1),因为这两个端口的目的仅仅为连接使用,相当于连线,因此不需要使用inout,也不需要指定时钟与复位信号。随后关注调用部分:

    dut_template_wrapper *ut0;
    dut_template_wrapper *ut1;

这里的调用方式为调用dut_template_wrapper而不是dut_template,这是Stratus的区别,若要在高级综合中保留层次结构,则需要在这里调用wrapper而不是本身,对应的,也需要在tcl中指定子模块dut_template为待综合模块。最后一点需要注意的是,SC_CTOR中连线部分需要在本函数中编写,不可像system中一样调用函数进行连线,否则会在仿真过程中产生问题。该设计对应的project.tcl如下所示:

...
use_tech_lib    "$LIB_PATH/$LIB_LEAF"


set_attr clock_period           10.0
set_attr message_detail         3
set_attr default_input_delay    0.1

set_attr cc_options             "  -g --std=c++0x"
enable_waveform_logging -vcd
set_attr end_of_sim_command "make saySimPassed"

define_system_module basic_ut/main.cpp
define_system_module basic_ut/system.cpp
define_system_module basic_ut/tb.cpp

define_hls_module pipeline_test dut_module/pipeline_test.cpp 
define_hls_module dut_template dut_module/dut_template.cpp # 子模块也需要指定为待综合模块

define_io_config * TLM
define_io_config * PIN

define_hls_config pipeline_test BASIC
define_hls_config dut_template BASIC # 子模块也需要指定综合等级

define_sim_config T -io_config TLM
define_sim_config B -io_config PIN

define_sim_config H {pipeline_test RTL_V BASIC}

3.仿真结果

仿真结束后使用verdi查看波形,未添加流水线的波形如下所示:

可以发现这种情况下每两个周期才能输入一个数据,添加了流水线的波形如下所示:

添加了流水线展开后,可以发现每个时钟周期均可输入新的数据。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容