OMNeT++ 代码迁移从 3x 到 40.docx

上传人:b****4 文档编号:5003254 上传时间:2022-12-12 格式:DOCX 页数:11 大小:25.23KB
下载 相关 举报
OMNeT++ 代码迁移从 3x 到 40.docx_第1页
第1页 / 共11页
OMNeT++ 代码迁移从 3x 到 40.docx_第2页
第2页 / 共11页
OMNeT++ 代码迁移从 3x 到 40.docx_第3页
第3页 / 共11页
OMNeT++ 代码迁移从 3x 到 40.docx_第4页
第4页 / 共11页
OMNeT++ 代码迁移从 3x 到 40.docx_第5页
第5页 / 共11页
点击查看更多>>
下载资源
资源描述

OMNeT++ 代码迁移从 3x 到 40.docx

《OMNeT++ 代码迁移从 3x 到 40.docx》由会员分享,可在线阅读,更多相关《OMNeT++ 代码迁移从 3x 到 40.docx(11页珍藏版)》请在冰豆网上搜索。

OMNeT++ 代码迁移从 3x 到 40.docx

OMNeT++代码迁移从3x到40

OMNeT++ 代码迁移指南:

从 3.x 到 4.0

 

第一章:

 3.x 版本后的改变

 

概述

因为 C++API 、 NED 、 ini 和 msg 文件的改变,为 OMNeT++3.x 版本写的仿真模型是不能直接在 OMNeT++4.0 及其以后的版本中使用的。

本文档描述了如何将一个 3.x 的模型转化为可以在 OMNeT++4.0 下运行的模型。

在进行代码迁移之前,你应该已经熟悉 OMNeT++3.x 和 4.0 版本。

我们建议在继续之前看看 4.0 中的示例仿真文件。

 

 

NED 文件

NED 语言被大幅度的修改,并增加了大量的语法。

还包括有扩展的一系列新概念:

继承,模块和信道接口,内部类型,双向连接, package 结构,元信息(属性)等等。

下面列表显示了从 3.x 版本以来的重大改变。

∙大括号的引入,用于下列地方:

模块和信道的定义(去掉了endsimple,endmodule,endnetwork,endchannel等关键字)中;子模块中;连接中的链路参数中。

∙gate 定义以及参数的语法从 Pascal 风格变成了 C 风格。

∙在参数中,numeric参数类型已经被取消,根据上下文需要将其转化为 int 或者 double 。

∙const 关键字被移除,而引入了一个 volatile 新的关键字;在 3.x 中不限制的参数值是不确定的,而在 4.0 中则为常数0 。

∙display 字符串变成了属性,采用@display(...)的语法。

∙input 关键字被移除,而对于参数的提示可以采用属性来做:

@prompt(...)。

∙引入了一个新的参数属性@unit(...),用来表示物理单位。

对于有单位的参数,在 ini 和 NED 文件中的值必须要给出相同或者可以转换的单位,否则将会报告一个错误。

∙取消了 ref 关键字,因为现在参数总是通过引用来传递的。

∙取消了ancestor关键字。

∙复合模块中的gatesizes节重命名为 gates 。

∙Conditional参数以及gatesize节已经不再被支持。

大多数情况下,它们可以被 ?

:

 操作符所替代。

∙connectionsnocheck改为了connectionsallowunconnected。

∙connection的 for 循环语法也得到了改变。

∙现在已没有布尔类型和 long/double 类型之间的隐式转换。

∙import 声明已经改为一个完整的 package 定义

∙现在可以在网络中直接使用子模块,而不需要像在 3.x 中必须创建一个复合模块并单独声明成网络。

 

报文消息文件( msg )

field 属性的语法改成了和 NED 文件一致。

 

初始值设置文件( ini )

∙[Cmdenv],[Tkenv],[Parameters],[Partitioning] 和 [OutVectors]节已经不存在了,其内容需要拷贝到[General]节下。

∙[Cmdenv]和[Tkenv]中的配置选项需要分别加上cmdenv-和tkenv-前缀。

∙[Run1],[Run2],...节已经不能使用,而应该被转换为命名配置如[ConfigFirst],[ConfigSecond]等。

注意,现在运行个数已经不再依赖于配置文件,而是参考迭代次数。

∙cmdenv-express-mode选项([Cmdenv]下的express-mode选项)将默认值从 false 改为了 true 。

∙[Tkenv] 节中的大部分选项已经被移除,除了下面几个:

tkenv-default-run,tkenv-image-path,tkenv-plugin-path。

∙tkenv-default-run选项([Tkenv]中为default-run)已经和迭代次数联系了起来,所以现在只有和新的tkenv-default-section一起才有意义。

∙现在有一个新的cmdenv-interactive选项,默认为 false ,这使得 Cmdenv 将不会读取标准输入,在缺少参数值的时候中止。

在 3.x 版本中,默认的行为是从标准输入中读取值。

∙preload-ned-files选项已经被移除,因为在 4.0 中, NED 文件是通过从 NED 路径中的文件夹中加载得到的( NED 路径是一个包含了文件夹列表的字符串,可以从 NEDPATH 环境变量、命令行选项或者是 ini 文件中的 ned-path 选项来获得。

对于只有一个目录的仿真模型,默认值 "." 应该已经足够了)。

∙在 3.0 版本中, network 选项被指代为一个从preload-ned-files选项中的文件获取的 NED 类型。

在 4.0 版本中,则指代一个在 ned-path 选项中的可用的目录。

在许多情况下, network 选项并不需要修改。

∙**.somepar.use-default=true语法应该改为**.somepar=default。

**=default没有必要写出来,因为这是默认的行为。

∙还有一些配置选项被重命名或者改变。

更多细节的问题,请参看src/envir/ChangeLog和其他ChangeLog文件。

 

项目配置文件( Makefile )

makefile 的生产和 make 过程已经被重写过。

现在,一个 opp_makemake--deep 可以替代非常复杂的 makefile 系统,这可以用于多目录的仿真模型,如 INET 框架。

使用 opp_makemake-h 来获取更多的信息。

makefile 生成器可以生成三种类型的 makefile :

∙本地的(默认):

只有当前目录下的源文件会被包含,而忽略子目录。

在单目录的工程中推荐这种方法。

∙递归的( --recurse ):

包含当前目录中的源文件,并且在所有子目录中被调用。

这将在所有的子目录下生成 Makefile文件。

∙更深的( --deep ):

这在多目录项目中是适用的。

所有目录下的源文件将被递归收集出来。

只会在根目录下生成一个Makefile 文件。

项目的包含路径也会被自动查找。

可以通过 -X 选项排除某些目录。

 

C++ 代码( cc/h )

下面是从 3.x 版本以来 API 的主要变化。

请参看include/ChangeLog来获取更详细的信息。

∙omnetpp/include 中的几个头文件被重命名。

(这不会影响到仿真模型,因为在仿真模型中只需要包含

∙cObject重命名为cOwnedObject,cPolymorphic重命名为cObject,引入了cNamedObject。

不同类中的几个方法已经改变。

检查 ChangeLog 文件来获取详细信息。

∙为几乎所有的 getter 方法增加了 get 动词。

 提供了 C99 的整数类型和 limit 宏,即使是系统中不存在  。

∙simtime_t现在不是 double 而是 SimTime 类型( 64 位)。

∙增加了 simtime 的兼容模式:

如果需要的话,仿真内核可以编译成 simtime_t=double 。

为了达到这点,可以加入USE_DOUBLE_SIMTIME定义(在 CFLAGS 中增加-DUSE_DOUBLE_SIMTIME标志)。

∙增加了 inout 门。

对于这种类型的门,gate("gatename")是不会工作的,使用gate("gatename$i")或者gate("gatename$o")。

∙Channel 变为了“一等公民”:

和 cModule 一样有着同样的基类 cComponet ,参与了initialize()/finish()协议,等等。

∙引入了cComponent作为cModule和cChannel的基类。

有些新方法需要在这里提及:

isModule(),getNedTypeName()。

∙cBasicChannel重命名为cDatarateChannel,增加了cIdealChannel使得信息可以在传递的时候不经过任何延时和修改。

∙异常处理机制的变化:

现在所有的异常都是继承于std:

:

exception(如cException是std:

:

exception的子类)。

同时,现在异常是通过值抛出而不是指针。

∙cOutVector:

从cOutVector及其下层中去除了用处不大的tuple=2支持,并且为元信息增加了一些方法:

setEnum(),setUnit(),setType(),setInterpolationMode(),setMin(),setMax()等。

∙和cDisplayString相关的许多改动。

参加include/ChangeLo g 。

∙cQueue :

去掉了head()/tail(),增加back()/front()(在最后插入,在前面删除)。

因为head()/tail()的变化,insertBefore()/insertAfter()的迭代指示符也变化了。

另外,指示递增递减顺序的布尔变量也被删除了。

∙cMessage变化:

cMessage中的长度,比特错误标志和封装信息被从cMessage移到了 cPacket 类中(从cMessage 继承)。

所有的网络分包(帧、数据报等)现在都是从 cPacket 继承,而不是直接从 cMessage 中继承。

∙一个新的cPacketQueue被引入用来保存 cPacket 及其子类。

∙全局的findXXX(constchar*name)函数被改为staticcXXX:

:

find(constchar*name);方法。

(受影响的:

findLink(),findFunction,findEnum,findChannelType,findNetworkType(),findModuleType())

∙cEnvir.cSimulation:

:

runNumber()中的 Runnumberhandling 已经移除。

同样从cEnvir回调函数的参数列表中移除。

 

环境变量

OMNETPP_BITMAP_PATH环境变量被更名成OMNETPP_IMAGE_PATH。

 OMNeT++ 将会在运行时进行检查,如果发现老的环境变量将会打印出警告信息。

 

命令行选项

∙当指定 ini 文件的时候 -f 是可选的。

∙-r 现在用来指代运行次数,而不是在 ini 文件中的命名配置。

一般的, -r 只有和 -c (选择运行配置)选项一起的时候才有意义。

∙使用 -h 来获取仿真执行使的帮助信息(或者是 opp_run-h 获取 OMNeT++ 的信息)。

∙需要更多的信息可以使用opp_run-h或者可执行仿真文件的 -h 选项。

 

第二章:

迁移工具

代码迁移的过程有些步骤可以自动化执行。

 OMNeT++4 提供了几个实用的命令行工具来帮助代码迁移。

这些工具可以在OMNeT++4 的 migrate 目录下找到。

 

migratened

这个工具递归的对当前目录下的 .ned 文件进行迁移。

此工具将完成下面的过程:

∙将所有的simple,module,network,channel类型定义改成新的大括号样式。

∙将参数定义改变成新样式。

∙删除 const 修饰词,并为非 const 参数定义增加 volatile 修饰词。

∙为了安全原因,此工具将numeric参数变为 double 。

以后必须手工检查,如果 int 已经足够的话。

∙将所有的submodule声明变为新的大括号语法。

 

migratemsg

这个工具递归的对当前目录下的 .msg 文件进行迁移。

此工具将完成下面的过程:

∙将所有的属性改为新格式。

 

migrateini

这个工具递归的对当前目录下的 .ini 文件进行迁移。

此工具将完成下面的过程:

∙将[Parameters],[Cmdenv],[Tkenv],[OutVectors]和[Partitioning]移动到了[General]中。

∙将多个出现的[General]节合并成一个。

∙[Cmdenv]和[Tkenv]中的没有加上前缀的条目加上cmdenv-和tkenv-。

∙将[Run1],[Run2]等重命名为[Configconfig1],[Configconfig2]等。

∙重命名已经更改的配置选项。

∙将**.use-default更改为**=default。

 

migratecpp

这个工具递归的对当前目录下的 .cc 和 .h 文件进行迁移。

此工具将完成下面的过程:

∙将代码中明确标志的已经更改的类重命名。

∙删除废弃的宏(如Define_Module_Members())。

∙在所有可能需要进一步修改和检查的地方打印警告语句。

 

opp_makemake

这个工具并不是一个迁移工具,但是可以使用其来生成新的 Makefile 文件。

旧的 Makefile 文件不能够使用。

 

第三章:

如何迁移代码

 

我们推荐你按照几个步骤来迁移你的仿真模型:

尽快的工作在 4.0 版本下:

使用自动迁移脚本

对自己的模型进行手工迁移,并使用尽可能少的新特性

检查你的模型是否能够工作,并看是否可以产生和旧模型一样的结果(精确的或者是统计上的)

使用 OMNeT++4 版本的新特性对其进行改进。

 

使仿真模型可以工作

前提条件:

已经安装好了 OMNeT++4.0 并可以工作,同时熟悉 IDE 的操作。

为你的仿真模型做个备份。

因为可能在迁移成功之前需要做多次尝试。

切换到你的仿真模型目录,并运行在 /migrate 中的所有脚本文件。

$cdMyModel

$../omnetpp-4.0/migrate/migratened

$../omnetpp-4.0/migrate/migrateini

$../omnetpp-4.0/migrate/migratemsg

$../omnetpp-4.0/migrate/migratecpp|teemigratecpp.out

这些脚本文件将转换 NED 、 ini 、 msg 和 C++ 文件到 4.0 的格式。

结果可能还需要进一步处理,因为不是所有的东西都可以自动转换的。

脚本将在你可能需要手工修改的地方打印警告信息,所以请注意这些打印信息。

特别的,migratecpp脚本将打印一系列的注意、警告和提示,认真的读读它们。

如果你的仿真模型是基于 INET 框架的,则首先要安装新的 INET ,然后执行在 INET 下的子目录 migrate/ 中的脚本。

这将会根据 INET 框架的变化而对源代码进行修改。

$cdMyModel

$../INET/migrate/migratened

$../INET/migrate/migrateini

$../INET/migrate/migratemsg

$../INET/migrate/migratecpp|teemigratecpp.out

接下里的工作你可以在命令行中完成,也可以在 OMNeT++IDE 中完成。

我们推荐使用后者。

为了使用 IDE ,需要为仿真模型创建一个工程。

在菜单中选择 File|New|OMNeT  +  +Project... ,将会出现一个向导。

在第一页中,取消“ Usedefaultlocation ”的复选并选择你的仿真模型目录,然后继续其他向导页,并在最后点击 Finish ,你应该可以看到在左边的“ ProjectExplorer ”有了一个新工程,其中包含了你的工程中的文件。

如果发生了错误,选择工程并点击 DEL 。

 IDE 将会询问是否将文件也从磁盘中删除,选择“ No ”。

然后可以重新开始工程的创建。

如果你的工程是依赖于 INET 或者其他工程,你可以设置一个依赖于 INET 的工程。

为了做到这点, INET 工程必须已经导入和打开,然后在你的工程中打开Properties对话框(选择工程,右键点击,从上下文菜单中选择Properties),然后在ProjectReferences页中检查 INET 。

这将使得 INET 中的 NED 类型可以用你的工程,同时将 INET 的目录加入到了 C++的头文件路径。

确保 INET 框架编译成了库(静态或者动态),这样你的工程才可以链接到 INET 。

可以通过检查 INET 工程的ProjectProperties对话框中的C/C++Build/Makemake页面。

 OMNeT++4.0 版本中的 NED 有着和 Java 类似的包系统。

如果你的模型在不同的子目录中包含有 NED 文件,这些子目录意味着包, NED 文件需要包声明同时增加了 import 。

这在 IDE 中可以自动完成。

创建或者打开你的工程,从菜单中选择Navigate|CleanupNEDfiles...。

选择你的工程并点击 OK 。

 IDE 将修复所有的包声明并导入你的 NED 文件。

你可能需要一个 package.ned 文件来定义你的根包——这将在后面一节进行讨论。

对 NED 文件进行修订。

包括:

修订 volatile 型的参数,看看它们是否必须要使用 volatile

在原来模型中如果没有指定为 const 的参数, volatile 的限定符可能会出现的比较多。

如果一个参数在仿真过程中是不变的,则可以将 volatile 限定符安全的删除。

所以作为一个规则,只有在仿真期间被读取的变量才有可能需要设置为 volatile,而不是在初始化阶段。

如果只是在initialize()函数中使用了的参数,则可以将 volatile 限定符去掉。

检查为 double 的参数是否可以为 int 。

3.x 版本中的 numeric 参数类型将会被自动转换为 double 类型,但是你可以根据需要将其改为 int 。

确保你同步修改了相应的 C++ 源代码。

somepar=input;将变成somepar;——你可能需要删除它们。

提示:

NED 文件中已经不支持使用 input 关键字,但是你可以在 ini 文件中设置**.somepar=ask来达到同样的效果。

移除多余的网络定义

3.x 风格的网络定义实际上是一个网路的复合模块。

在 4.0 版本中,一个复合模块可以直接被定义成为一个网络,而不需要多余的步骤。

举个例子, 3.x 版本中的网络定义:

networkcqn:

CQN

endmodule

将会被自动迁移脚本转换为继承的形式:

 

networkcqnextendsCQN{

}

实际上,你可以完全删除这个定义。

可以使用 network 关键字来改变 CQN 的模块定义(如networkCQN{...}),同时在ini 文件中将network=cqn替换为network= CQN 。

 "like" 模块类型应该被改为接口,而且真实的类型声明应该相像。

例如,你有一个子模块:

app:

likeApp;

App 应该变为一个模块接口(一般习惯上在前面加上一个“ I ”):

moduleinterfaceIApp{

    gates:

        inputin;

        outputout;

}

而具体的类型则应该根据 IApp 来修改:

simpleBurstyApplikeIApp{...}

simpleAnotherApplikeIApp{...}

编译你的仿真模型(右键点击你的工程,从上下文菜单中选择“ Build ”,或者是关闭所有的其他工程然后按下 Ctrl+B)。

常见的编译错误以及解决方法:

不能将SimTime转换为 double ("CannotconvertSimTimetodouble")

simtime_t现在是一个基于int64的SimTime类,而不是 double 。

无论在什么地方一个simtime_t被赋值成 double 类型,考虑将其修改为simtime_t。

新的 SimTime 没有提供和 double 之间的隐式转换,因为这可能会造成 C++ 的歧义性错误。

检查迁移工具的输出,其中给出了应该修改变量的一些提示。

提示:

如果需要的话,使用SIMTIME_DBL(t)来将一个simtime_t类型转换为double类型。

在 printf 函数中,使用"%s"和SIMTIME_STR(t)。

使用这些宏而不是SimTime方法的好处是可以编译成-DUSE_DOUBLE_SIMTIME的兼容模式。

提示:

如果你使用了很多 double 类型的时间变量,同时西王佐一个快速的移植,有一个比较不是很干净的方法,那就是在CFLAGS 中指定 -DUSE_DOUBLE_SIMTIME ,从而使得其保持原来的行为。

需要注意的是,如果这样做的话,需要使用此标志重编译所有的 OMNeT++ 库。

我们建议如果可能的话尽量使用新的 SimTime 类型。

"NosuchmethodsetBitLength/getBitLength/encapsulate/decapsulate"

长度和封装属性已经移到了cPacket中,这是cMessage的一个子类。

你可能需要将 .msg 文件中的 message 关键字改为packet 关键字,从而使得生成的类使用 cPacket 作为基类。

messageABCPacket{...}==>packetABCPacket{...}

在handleMessage()和其他函数中,将cMessage*指针指向cPacket*:

cPacket*pkt=check_and_cast(msg);

"Cannotopenfilecsimul.h"(oranyotherheader)

只有是公共的 API 。

其他的 OMNeT++ 头文件不应该被直接引用,因为有可能在以后的版本中改名或者删除。

"sendDirect()doesnottake3(or4)arguments"

sendDirect()函数已经更改。

过去此函数经常接受延时作为第二个参数。

现在此函数有两个变种,一个没有时延参数(所以,如果你的仿真模型中是 0.0 ,则可以直接删除),而另外一个则接受传播时延和传输持续时间。

如果你准备使用第二种的话,你可能需要在目标模块中接收门的initialize()方法中调用setDeliverOnReceptionStart(true)。

运行你的仿真模型。

常见的错误和解决方法:

"Cannotconvertunit'none'to'seconds'"

物理类型必须写在表达式中,所以需要将 5 改为 5s ,而将exponential

(1)改为exponential(1 s

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 广告传媒

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1