当前位置: 首页 > news >正文

[SystemC]SystemC Hierarchical Channels

SystemC Hierarchical Channels

       摘要:分层通道构成了 SystemC 系统级建模能力的基础。它们基于通道可能包含相当复杂的行为的想法——例如,它可能是一个完整的片上总线。

       另一方面,原始通道不能包含内部结构,因此通常更简单(例如,您可以认为 sc_signal 的行为有点像一根电线)。

       为了构建复杂的系统级模型,SystemC 使用将通道定义为实现接口的事物的想法。接口是访问给定通道的可用方法的声明。例如,在 sc_signal 的情况下,接口由两个类 sc_signal_in_if 和 sc_signal_out_if 声明,它们声明访问方法(例如 read() 和 write())。

通过将接口的声明与其方法的实现区分开来,SystemC 促进了一种将通信与行为分离的编码风格,这是促进从一个抽象级别到另一个抽象级别的改进的关键特征。

       SystemC 的一项附加功能是,如果您希望模块通过通道进行通信,则必须使用模块上的端口来访问这些通道。端口充当代理,代表调用模块将方法调用转发到通道。

       分层通道在 SystemC 中作为模块实现,实际上它们是从 sc_module 派生的。原始通道有自己的基类 sc_prim_channel。总结一下:

  • 将沟通与行为分开,便于细化
  • 接口声明了一组访问通道的方法
  • 分层通道是实现接口方法的模块
  • 端口允许模块调用接口中声明的方法

       编写分层通道是一个很大的话题,所以本章将只展示一个基本示例,一个堆栈模型。

一、定义接口

       堆栈将提供一个读取方法和一个写入方法。 这些方法是非阻塞的(它们会立即返回而无需等待)。 为了使它可用,每个方法都返回一个布尔值,说明它是否成功。 例如,如果读取时堆栈为空,则 nb_read()(读取方法)返回 false。

       这些方法在两个单独的接口中声明,一个写接口 stack_write_if 和一个读接口 stack_read_if。 这是包含声明的文件 stack_if.h。

       代码到这里但不起作用?

       这些接口派生自所有接口的基类 sc_interface。 它们应该使用关键字 virtual 派生,如上所示。

       方法 nb_write、nb_read 和 reset 被声明为纯虚拟 - 这意味着它们必须在任何派生类中实现。

二、Stack Channel

       栈通道覆盖栈接口中声明的纯虚方法。 这是代码:

#include "systemc.h"
#include "stack_if.h"

// this class implements the virtual functions
// in the interfaces
class stack
: public sc_module,
  public stack_write_if, public stack_read_if
{
private:
  char data[20];
  int top;                 // pointer to top of stack

public:
  // constructor
  stack(sc_module_name nm) : sc_module(nm), top(0)
  {
  }

  bool stack::nb_write(char c)
  {
    if (top < 20)
    {
      data[top++] = c;
      return true;
    }
    return false;
  }

  void stack::reset()
  {
    top = 0;
  }

  bool stack::nb_read(char& c)
  {
    if (top > 0)
    {
      c = data[--top];
      return true;
    }
    return false;
  }

  void stack::register_port(sc_port_base& port_,
                            const char* if_typename_)
  {
    cout << "binding    " << port_.name() << " to "
         << "interface: " << if_typename_ << endl;
  }
};

       有一些本地(私有)数据来存储堆栈,还有一个整数表示堆栈数组中的当前位置。nb_write 和 nb_read 函数在这里定义。 还有一个 reset() 函数,它简单地将堆栈指针设置为 0。

       最后,您会注意到一个名为 register_port 的函数——它是从哪里来的?它在 sc_interface 本身中定义,并且可以在通道中被覆盖。 通常,它用于检查端口和接口何时绑定在一起。 例如,原始通道 sc_fifo 使用 register_port 检查最多 1 个接口可以连接到 FIFO 读取或写入端口。 这个例子只是在绑定过程中打印出一些信息。

三、Create PORT

       要使用堆栈,它必须被实例化。 在这个例子中,有两个模块,一个生产者和一个消费者。 这是生产者模块:

#include "systemc.h"
#include "stack_if.h"

class producer : public sc_module
{
public:

  sc_port<stack_write_if> out;
  sc_in<bool> Clock;

  void do_writes()
  {
    int i = 0;
    char* TestString = "Hallo,     This Will Be Reversed";
    while (true)
    {
      wait();             // for clock edge
      if (out->nb_write(TestString[i]))
        cout << "W " << TestString[i] << " at "
             << sc_time_stamp() << endl;
      i = (i+1) % 32;
    }
  }

  SC_CTOR(producer)
  {
    SC_THREAD(do_writes);
      sensitive << Clock.pos();
  }
};

       生产者模块声明了一个与堆栈接口的端口。 这是通过以下行完成的:

sc_port<stack_write_if> out;
  • 它声明了一个可以绑定到 stack_write_if 的端口,并且有一个名字 out。
  • 您可以将多个接口副本绑定到一个端口,并且您可以指定可以绑定的最大接口数。 例如,如果我们想允许绑定 10 个接口,我们可以将端口声明为
sc_port<stack_write_if,10> out;
  • 如果省略数字,则默认值为 1。
  • 要实际写入堆栈,请通过端口调用方法 nb_write:
out->nb_write('A');
  • 这通过 stack_write_if 调用 nb_write('A')。 执行此操作时必须使用指针符号 ->。
  • 从堆栈读取的消费者模块看起来非常相似,除了它声明了一个读取端口
sc_port<stack_read_if> in;
  • and calls nb_read, e.g.
in->nb_read(c);
  •  其中 c 是 char 类型。
  • 请注意,如果成功,nb_read 和 nb_write 都会返回值 true。

       也许最有趣的是函数 nb_write 和 nb_read 在调用者的上下文中执行。 换句话说,它们作为在生产者和消费者模块中声明的 SC_THREAD 的一部分执行。

四、Binding Ports and Interfaces

       Here is the code for sc_main, the top level of the design 

#include "systemc.h"
#include "producer.h"
#include "consumer.h"
#include "stack.h"

int sc_main(int argc, char* argv[])
{
  sc_clock ClkFast("ClkFast", 100, SC_NS);
  sc_clock ClkSlow("ClkSlow", 50, SC_NS);

  stack Stack1("S1");

  producer P1("P1");
  P1.out(Stack1);
  P1.Clock(ClkFast);

  consumer C1("C1");
  C1.in(Stack1);
  C1.Clock(ClkSlow);

  sc_start(5000, SC_NS);

  return 0;
};
  • 注意栈的写接口是如何隐式绑定在线网中的
P1.out(Stack1);

       这个例子有点奇怪(但完全合法!)因为堆栈本身没有端口。 它只是导致第一个 stack_write_if 被绑定在这一行中。 如果有多个stack_write_if,它们将被依次绑定。

       这是运行代码的结果:

binding    C1.port_0 to interface: 13stack_read_if
binding    P1.port_0 to interface: 14stack_write_if
W H at 0 s
R H at 0 s
W a at 100 ns
R a at 150 ns
W l at 200 ns
// and so on for 5000 ns
  • 关于绑定的消息来自 stack.h 中的 register_port 函数。 端口的名称 (C1.port_0...) 由 SystemC 内核制造,接口名称 (13stack_read_if...) 也是如此。

五、结论

       上面显示的示例非常简单,但有很多东西需要学习和理解。 它让您快速浏览定义和编写自己的分层通道的过程。 要记住的关键点是:

  1. 分层通道允许复杂的总线模型
  2. 使用接口将通信和行为分开
  3. 可以使用端口从模块外部访问接口
  4. 当你通过接口调用通道中的方法时,你不必知道它是如何实现的——你只需要知道接口调用的声明
  5. 当通道中定义的方法被执行时,它们会在调用者的上下文中执行

相关文章:

  • 2022年0903在IDEA工具中常见的一些Maven操作<第五课>
  • 【2022】计算机视觉算法岗面试题目和复习知识点汇总
  • 《算法导论》11.3 除法散列法、乘法散列法 11.4 开放寻址法
  • 【java_wxid项目】【第八章】【Apache ShardingSphere集成】
  • CTF-PUT上传漏洞【超详细】
  • 程序人生 | 编程的上帝视角应该怎么去找
  • KingbaseES V8R3集群运维案例之---主库系统down failover切换过程分析
  • 夏日水果茶饮店如何引流?这四款饮品必学
  • ESP32_esp-idf_lvgl_V8环境搭建移植
  • 人工智能第2版学习——产生式系统2
  • Cortex-A核的异常的处理过程
  • 基于IDEA 工程项目的git实操
  • SAP 多个smartforms同时打印页码问题
  • 离线数仓搭建_03_Hadoop的配置与优化测试
  • 【设计模式】Java设计模式 - 命令模式
  • -------------------- 第二讲-------- 第一节------在此给出链表的基本操作
  • 【407天】跃迁之路——程序员高效学习方法论探索系列(实验阶段164-2018.03.19)...
  • CSS盒模型深入
  • flask接收请求并推入栈
  • Java多线程(4):使用线程池执行定时任务
  • java概述
  • java正则表式的使用
  • Js实现点击查看全文(类似今日头条、知乎日报效果)
  • JS实现简单的MVC模式开发小游戏
  • js作用域和this的理解
  • Kibana配置logstash,报表一体化
  • ng6--错误信息小结(持续更新)
  • NLPIR语义挖掘平台推动行业大数据应用服务
  • Otto开发初探——微服务依赖管理新利器
  • SAP云平台里Global Account和Sub Account的关系
  • SpiderData 2019年2月23日 DApp数据排行榜
  • Spring Cloud Alibaba迁移指南(一):一行代码从 Hystrix 迁移到 Sentinel
  • spring cloud gateway 源码解析(4)跨域问题处理
  • 湖南卫视:中国白领因网络偷菜成当代最寂寞的人?
  • 基于Android乐音识别(2)
  • 记录:CentOS7.2配置LNMP环境记录
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 微信支付JSAPI,实测!终极方案
  • python最赚钱的4个方向,你最心动的是哪个?
  • 摩拜创始人胡玮炜也彻底离开了,共享单车行业还有未来吗? ...
  • 资深实践篇 | 基于Kubernetes 1.61的Kubernetes Scheduler 调度详解 ...
  • ​ubuntu下安装kvm虚拟机
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #pragam once 和 #ifndef 预编译头
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $var=htmlencode(“‘);alert(‘2“); 的个人理解
  • (04)Hive的相关概念——order by 、sort by、distribute by 、cluster by
  • (06)Hive——正则表达式
  • (175)FPGA门控时钟技术
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (八)光盘的挂载与解挂、挂载CentOS镜像、rpm安装软件详细学习笔记
  • (二十一)devops持续集成开发——使用jenkins的Docker Pipeline插件完成docker项目的pipeline流水线发布
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (十七)Flask之大型项目目录结构示例【二扣蓝图】