加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

systemcTLM建模

(2012-02-24 17:22:39)
分类: IC设计
Book: transaction level modeling with systemc

1. 术语
   TLM: transaction level modeling
   ISS:  Instruction set simulator
   BFM:  Bus Function Model
   SystemC: SystemC
   OSCI:  Open SystemC Initiative
   BCA:   bus cycle accuracy



2.历史
  在早期的流程中,基于RTL层次的开发已经显示了一些缺陷包括仿真速度和开发周期等,因此很多公司开始
  考虑更加抽象的建模层次。
  2.1 cycle accuracy modeling
      在早期有很多公司开发了一些建模的语言,除了完全重新设计外,有一些是基于现有的建模语言进行扩展
      子集比如基于C++的扩展specC,cowareC,VCC,systemC。基于HDL的扩展如systemVerilog等。
      使用这些扩展的语法来建模cycle级精度的模型(在早期的cpu建模中比较常用这种,使用C语言来建立
      模拟cycle级的模型),这种模型比HDL要快10倍左右。但是也存在问题:
         仿真速度仍然不够快(仿真速度取决于仿真器和模型的抽象层次)
         建模代价比较高,开发速度不够快
        
   2.2 systemC-based TLM建模
       1999年开始,Systemc0.9 开始出现。  2001年 systemc2.0 released.
       TLM建模的一个核心就是建模时计算和通信分离:
         separating communication from computation within a system
  
       transaction:data transfer  (i.e. communication) or  synchronization between two modules at
                    an instant (i.e. SoC event)
                    通信包括数据传输和同步(通过event)
            
       TLM在流程中的位置:
                http://s8/middle/80ce3a55gb9b2faf4ca67&690

  在软硬件划分后,开始进入TLM建模,TLM平台作为硬件和软件team和测试team的共同平台,在同一个平台上
  进行进一步的细化。

  systemC2.0的simulation kernel实现的是非抢占式的调度scheduler,因此软件的多线程和多任务不能用
  systemC的thread来模拟。有2个解决方法:
   1. 使用ISS来进行软件多任务的模拟和仿真,硬件部分使用systemC来模拟,在ISS和systemc 模拟器之间建
      立通信
      One could however use a processor ISS linked to the SystemC simulation to run multi-tasking
      embedded software
   2. 用本地CPU来运行软件的多任务(host机器),利用socket来建立本地执行和systemC模拟器之间的通信
      the socket connection between the SystemC simulator and tasks of the embedded software
      running natively compiled for the workstation and  executing without ISS.

  TLM 的历史:
     RTL:使用硬件描述语言verilog/VHDL进行RTL设计仍然是目前的主流流程。
     RTL+ISS: 在软硬件协同验证时,由于RTL模拟的速度比较慢,因此可以考虑使用更快的CPU模型比如ISS
               这种指令集精度的模型来加速软件的运行。其余模块仍然是RTL
     cycle-accuracy modeling: 不使用Verilog/VHDL,而是使用C语言这种高级语言来实现cycle-accuracy
                              model(早期CPU的建模就是通过基于C语言的cycle-accuracy建模);但是仿真
                              的速度比RTL快1个数量级而已。
     TLM:是在模拟速度和精度上的一个折衷。
     下图是几种建模的速度的比较:
     http://s3/middle/80ce3a55gb9e92c2eef12&690


    


   模型的抽象层次:
     不同的组织定义了不同的抽象层次,但是所有的抽象定义都是针对计算和通信两部分的精度包括timing的精
     度是否精确到cycle级别和通信的单位是否精确到bit级别来区分:
        1. Granularity of communication data:数据的粒度分为application packet,bus packet,
                                             bus size,bit。

        2. timing accuracy :时序精度分为untimed level, approximately timed level, cycle accuracy

    从上面的标准来看,只是关心通信的精度和timing的精度,不关心实现是否是基于register的,是否是可综
    合的,这是RTL比较关心的。
    
         http://s3/middle/80ce3a55gb9edf5916cc2&690
   模块计算的delay称为"functional delay"
                 http://s3/middle/80ce3a55gb9eec4d257b2&690



 

 下面是各个标准组织定义了模型抽象层次的详细说明:
    
      1. OSCI定义的层次:
         http://s16/middle/80ce3a55gb9ed63a8313f&690

          算法级:主要是函数调用,以算法功能为主,不涉及到系统的结构。常使用Matlab/UML
          PV:programmer's view 程序员视图, 以功能实现为主,不涉及到硬件架构。
          PVT:PV  + Timing, 在PV的基础上增加了timing信息,可以用来分析系统的吞吐量。这里的timing
               信息并不是精确的(不是cycle级别的).
         Cycle callable: 这个级别上可以精确到cycle级,模型内部的计算可以精确到cycle级别也可以只是
                         粗略的timing反标,但是通信必须精确到cycle级别。和RTL的差别在于使用的是
                         port(没有精确到bit级)而不是RTL级别的pin。
         RTL: 在CC级别的基础上,通信精确到了bit级(pin),基于寄存器的实现。

    OCP-IP定义了另外的一种模型抽象层次:
         http://s4/middle/80ce3a55gb9ed8da81c03&690
  在OCP-IP的定义中分成了4个抽象层次:
        Message Layer:事件驱动,没有硬件架构信息,类似于Algorithm level
        Transaction layer: 在这个级别上引入了timing信息,但是timing信息是不精确的;在计算建模上
                           可以是抽象的,和硬件结构无关;在通信上可以和实际的通信协议无关,更多
                           的是关心完成某次传输需要的时间是多少(timing 反标),模块完成某个计算
                           耗费多少时间。通信使用的是函数调用如:
                               burst_read(addr,len)
        Transfer Layer:  通信精确到了cycle级,但是数据不细化到bit(OSCI的CC层)
                         同RTL的差别在于可以是不可综合的代码。
        RTL:

 
 由于上面的两种抽象层次都不太好理解,因此OSCI在master-slaver communication library中提出了另外
 一种抽象层次:
        http://s15/middle/80ce3a55gb9edaccca71e&690

    UTF:将系统划分成多个功能模块,模块之间的通信使用点到点的通信,这个层次精确描述
          模块之间的执行顺序和通信顺序,但是没有timing概念(只是关心顺序是否正确),是纯功能的。
          等同于PV级。
    TF:  为UTF的模块引入了时间概念,UTF中定义了这些模块和通信的执行顺序,在TF中为每一个module
          执行某个功能反标上一个执行时间t,为每一个通信反标上一个时间,可以用于性能评估。
    BCA:在TF的基础上将通信细化到cycle级。
    CA:  timing精确到了cycle级别包括计算和通信,但是实现不是基于register的,可以是不可综合的
    RTL:寄存器传输级,可综合的实现。
           http://s12/middle/80ce3a55gb9ede5f38d0b&690

 
  Timed TLM模型的开发方法:
    在Timed TLM模型中需要加入timing信息,目前有2种方法来加入timing:
    1. annotated model 反标timing信息到model中
       在UTF模型中插入timing信息,由于某一段代码或者电路中包含有多个path,因此这个timing信息不会
       是一个固定的值,而是[best,typical,worst]的形式,这种方法适合于UTF中的micro-architecture和
       未来的实际的micro-architecture一致的情况。
       可以在UTF中通过宏来控制这些反标的数据:
                  #ifdef Annotated_Model

   2.standalone Timed model :独立的timing模型
     当UTF中的micro-architecure和最终的micro-architecture差别很大时,使用反标的方式不太合适,
     可以使用下图中的方式,使用一个独立的timing模型和UTF进行交互。比如一个ALU中实现了多个操作
     如ADDER/MUL,每一种操作的delay都是不同的,而且当前配置ALU成哪种操作取决于实际执行,因此
     一种方法就是使用方法1来[best,typical,worst],另外一种方法UTF通过通信port将当前执行的操作
     传输给timing model,timing model根据操作类型选择一个正确的delay作为当前UTF执行的delay。
     http://s6/middle/80ce3a55gb9eee375e875&690

   由于function部分是由UTF模型完成的,UTF中没有timing的概念,function的执行不消耗时间,因此在执行
   完该function后应该将执行权转移到TF的timing model中,这里面会推动仿真时间向前,delay为该function
   在某种实现下需要耗费的delay。

  第3章: TLM modeling technique
      这里提出了一种分层建模的方法来将模块的计算和通信进行分离。分层建模的方法如下所示:
           http://s16/middle/80ce3a55gba2b553b7d8f&690

    分成了3层:
      core TLM layer:The core TLM interface layer is the foundation of TLM methodology. It
                      defines a transactional level interface, and declares the related
                      transactional level ports accordingly。
      protocol layer: Various communication protocols can be defined on top of the core TLM
                       interface layer。利用core TLM interface上的API实现了某种通信协议,来进行虚
                       拟的点到点(point topoint)通信:
  
           http://s9/middle/80ce3a55gba2b6f4aef48&690
    initiator port:由协议开发者开发,将用户的read/write请求转换成core TLM interface call.
    translating  user-level operations (e.g. read or write) into the appropriate core TLM
    interface calls.
    target port:正好相反
     可以认为protocol port是一个协议转换器。   

     IP layer:构建在protocol layer上,利用protocol layer的API进行通信。 











第二部分: systemc function spec 2.0
       第一章 systemc 的版本
              systemc1.0类似于hdl语法,提供了module/port/signal等可以来模拟硬件行为,
              HDL中的并行always block在systemc1.0中使用SC_METHOD/THREAD来模拟。
              因此,可以认为systemc1.0是在C++的语法上扩展了描述硬件的能力。
             
              systemC2.0中开始面向system level modeling的特性,要构建高于RTL的抽象层次的模型,
              由于system level建模语言需要能够指出包括computation/design abstraction/mthodology
              等,systemc将最为通用的建模特性提炼成了一个“core language”作为系统建模的基础。

              其余的都是基于这个"core language"来构建的。systemc2.0 语言架构如下:
              http://s2/middle/80ce3a55gba3c59160451&690


               通信方面:
                   systemc1.0使用port,signal这些硬件思想的方法进行通信,但是这些通信方式都太
                   底层,不适合进行systemc level建模。
                   systemc2.0中提出了channel/interface/ports/events来进行通信和同步:
                      inteface: 是C++的抽象类,只声明一些需要实现的函数
                      channel:  是C++中的继承类,继承了多个抽象的接口类,并且进行了实现。
                                在一个channel中可以实现多个接口函数。
                      port:     port中绑定支持的interface方法,module通过port上绑定的interface去
                                channel中调用在channel中实现的函数。
                                       

                      IMC(interface method call,接口方法调用)机制。



                    分层的方法:
                        http://s7/middle/80ce3a55gba3c7eca61e6&690

                     最底层的是systemc的仿真内核。
                   
     第2章: systemc process
             process是systemc中的基本执行单元。systemc中支持3种类型的process:
               Method:
                     使用SC_METHOD()来声明一个method process,并通过sensitive建立电平敏感列表。
                     当敏感列表中的信号发生变化,该method进程执行。(可以支持对多个信号敏感)
                     METHOD类似于HDL中的组合逻辑。
                     method进程一旦开始执行,就从simulator得到了执行的控制权,直到该process返回,
                     控制权才返回给simulator,如果在method中写了一个无限循环,那么simulator有可能
                     永远也得到到控制权。因此在method中不要出现无限循环。每一次敏感列表被激活,
                     Method进程被重新调用并从开始处执行。
                     因为METHOD()在systemc的中并不会启动一个Thread来执行(而是函数调用而已),
                     因此在METHOD()中不允许调用wait()等函数(这些是线程同步才使用的,method并不
                     会生成一个线程thread,因此也不存在wait同步的问题)。

                    http://s8/middle/80ce3a55gba3c960178d7&690
               thread:
                  SC_THREAD()中可以加入wait(),也就是可以暂时中止执行等待某个事件发生后再进行刚才
                  位置继续执行。
Thread Process can be suspended and reactivated. The Thread Process can contain wait() functions that suspend process execution until an event occurs on one of the signals the process is sensitive to. An event will reactivate the thread process from the statement the process was last suspended. The process will continue to execute until the next wait().
                thread可以对电平敏感,也可以对信号edge敏感。
                http://s4/middle/80ce3a55g79061260aba3&690
                http://s3/middle/80ce3a55g7906131f5502&690

             如果THREAD中不加入无限循环loop 和wait(),那么每一次thread被重新激活都会从头开始执行,
             同METHOD功能相同;
             但是THREAD比METHOD更强的是,在THREAD中可以插入wait()来暂时中止该process的执行,等待
             event或者条件成熟,继续从上次执行的地方继续执行;由于thread中插入了wait(),在wait处
             thread会将执行的控制权返回给simulator,因此可以在thread中使用无限循环loop。
              http://s13/middle/80ce3a55gba3cf45d394c&690                  
        clock thread:
             SC_CTHREAD():是一个特殊的thread,具有thread()的所有功能,但是限制了敏感列表只能是
             clock的沿(可以是上升沿或者下降沿)。(HDL中的时序逻辑),因此在CTHREAD中必须定义一个
             clock信号。
             http://s15/middle/80ce3a55gba3d0182f9be&690

  下面是关于这些process的一个对比:
          http://s4/middle/80ce3a55gba3d150cd653&690
http://s3/middle/80ce3a55gba3d28bfcc02&690


在上面的描述中,一个最大的差异在于:
        Method并不会启动一个线程thread来执行,而只是作为一个函数来调用,因为不启动线程,因此就
        不能插入wait()这种用于线程同步的代码;
        THREAD/CTHREAD在实际执行时会启动一个线程thread来执行,因此可以插入wait()这类的线程同步
 

event事件和wait同步:
   wait的几种用法:
         http://s9/middle/80ce3a55gba3d42559468&690
需要说明的是,如果wait(e)有明确的事件等待列表,那么thread的敏感列表被暂时的屏蔽,也就是即使这时候
敏感列表信号发生了变化也不能执行,必须是事件e到来才能继续执行。
the wait() method can be called anywhere in the thread of execution of a thread process.
When it is called, the specified events will temporarily overrule the sensitivity list, and the calling  thread process will suspend. When one (or all) of the specified events is notified, the waiting thread process is resumed. The calling process is again sensitive to the sensitivity list.

               
wait_until():
   这个语法只能使用在CTHREAD中(THREAD中不能使用),
         wait_until(roadsensor.delayed() == true);
   http://s4/middle/80ce3a55gba3d57a43553&690
  wait_until()中的信号只能是bool信号,并且一定要加.delayed(),否则编译错误。

 
 next_trigger():
     只能使用在SC_METHOD()中,可以带的参数和wait()完全一致。但是它的作用并不是和wait()一样来做
     同步的,而是用来修改SC_METHOD()中的敏感列表的,也就是说下一次METHOD()的敏感列表由
     next_trigger()中提供。因此METHOD()也可以支持动态敏感(由next_triggle()来设置动态敏感列
     表,event驱动)
     http://s4/middle/80ce3a55gba3d673f4e03&690

  
 notify:事件通知
     sc_event my_event;

     //使用event的notify成员函数
     my_event.notify(); // notify immediately
     my_event.notify( SC_ZERO_TIME ); // notify next delta cycle
     my_event.notify( 10, SC_NS ); // notify in 10 ns
     sc_time t( 10, SC_NS );
     my_event.notify( t ); // same

     使用notify()函数:
     notify( my_event ); // notify immediately 在当前的delta cycle时间内就生效
     notify( SC_ZERO_TIME, my_event ); // notify next delta cycle 在下一个delta cycle时间内生效
     notify( 10, SC_NS, my_event ); // notify in 10 ns
     sc_time t( 10, SC_NS );
     notify( t, my_event ); // same

     取消事件通知
     my_event.cancel(); // cancel a delayed notification

   
 
 SYSTEMC的仿真调度机制:
   由于systemc中存在delta cycle的概念(和HDL仿真一样),因此必须事件和进程的执行要调度机制来进行调
   度。
          http://s6/middle/80ce3a55gba3d89cdf255&690
  在某个delta cycle内有很多进程需要执行。只有当该delta cycle内需要执行的全部执行完成以后才能推动
  仿真时间t前进。

  详细的调度机制为:
     http://s12/middle/80ce3a55gba3ef412450b&690

         http://s8/middle/80ce3a55gba3ef71ea777&690

  在初始化阶段所有的process(除了cthread以外)都要执行一次;如果你不需要这些process在初始化的时候执行,那么需要在process声明时加入dont_initialized()函数:
       http://s3/middle/80ce3a55gba3eff9f4d72&690

  对于立即生效的notify(),会在delta cycle内激活该event相关的process,这些process也需要在当前的
  delta cycle内执行。


 第2章  Channel/Interface/Port
  2.1 interface 接口
      从C++的角度来看实际上就是抽象类,只是定义了要实现的方法(纯虚函数),自己并不去实现,
      而是由CHANNEL继承该抽象类并进行实现。
      基类:sc_interface
      http://s10/middle/80ce3a55gba7bcd6966d9&690

register_port()函数是做静态规则检查,当绑定一个port到channel时被调用
This class defines a method register_port(), which can be used by channels to do static design
 rule checking when binding ports to channels (see Section 8.2 and Section 9.3). The arguments to this method are (i) a reference to the port, and (ii) the type name of the interface that the port expects.
The default behavior of this method is to do nothing.
void sc_interface::register_port( sc_port_base&, const char* )
{}

   http://s13/middle/80ce3a55gba7bd1588f1c&690
     在接口中的函数必须是纯虚函数
  

   2.2 Port 端口
       module通过port(port上绑定一个interface)去访问channel中实现的该interface的方法。
       http://s6/middle/80ce3a55gba7bec925205&690


      

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有