forked from PIFO-TM/ns3-bmv2
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcreate-module.py
executable file
·417 lines (282 loc) · 10 KB
/
create-module.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
#! /usr/bin/env python
from __future__ import print_function
import sys
from optparse import OptionParser
import os
WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
# def options(opt):
# pass
# def configure(conf):
# conf.check_nonfatal(header_name='stdint.h', define_name='HAVE_STDINT_H')
def build(bld):
module = bld.create_ns3_module(%(MODULE)r, ['core'])
module.source = [
'model/%(MODULE)s.cc',
'helper/%(MODULE)s-helper.cc',
]
module_test = bld.create_ns3_module_test_library('%(MODULE)s')
module_test.source = [
'test/%(MODULE)s-test-suite.cc',
]
headers = bld(features='ns3header')
headers.module = %(MODULE)r
headers.source = [
'model/%(MODULE)s.h',
'helper/%(MODULE)s-helper.h',
]
if bld.env.ENABLE_EXAMPLES:
bld.recurse('examples')
# bld.ns3_python_bindings()
'''
MODEL_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "%(MODULE)s.h"
namespace ns3 {
/* ... */
}
'''
MODEL_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef %(INCLUDE_GUARD)s
#define %(INCLUDE_GUARD)s
namespace ns3 {
/* ... */
}
#endif /* %(INCLUDE_GUARD)s */
'''
HELPER_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "%(MODULE)s-helper.h"
namespace ns3 {
/* ... */
}
'''
HELPER_H_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#ifndef %(INCLUDE_GUARD)s
#define %(INCLUDE_GUARD)s
#include "ns3/%(MODULE)s.h"
namespace ns3 {
/* ... */
}
#endif /* %(INCLUDE_GUARD)s */
'''
EXAMPLES_WSCRIPT_TEMPLATE = '''# -*- Mode: python; py-indent-offset: 4; indent-tabs-mode: nil; coding: utf-8; -*-
def build(bld):
obj = bld.create_ns3_program('%(MODULE)s-example', [%(MODULE)r])
obj.source = '%(MODULE)s-example.cc'
'''
EXAMPLE_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
#include "ns3/core-module.h"
#include "ns3/%(MODULE)s-helper.h"
using namespace ns3;
int
main (int argc, char *argv[])
{
bool verbose = true;
CommandLine cmd;
cmd.AddValue ("verbose", "Tell application to log if true", verbose);
cmd.Parse (argc,argv);
/* ... */
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
'''
TEST_CC_TEMPLATE = '''/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
// Include a header file from your module to test.
#include "ns3/%(MODULE)s.h"
// An essential include is test.h
#include "ns3/test.h"
// Do not put your test classes in namespace ns3. You may find it useful
// to use the using directive to access the ns3 namespace directly
using namespace ns3;
// This is an example TestCase.
class %(CAPITALIZED)sTestCase1 : public TestCase
{
public:
%(CAPITALIZED)sTestCase1 ();
virtual ~%(CAPITALIZED)sTestCase1 ();
private:
virtual void DoRun (void);
};
// Add some help text to this case to describe what it is intended to test
%(CAPITALIZED)sTestCase1::%(CAPITALIZED)sTestCase1 ()
: TestCase ("%(CAPITALIZED)s test case (does nothing)")
{
}
// This destructor does nothing but we include it as a reminder that
// the test case should clean up after itself
%(CAPITALIZED)sTestCase1::~%(CAPITALIZED)sTestCase1 ()
{
}
//
// This method is the pure virtual method from class TestCase that every
// TestCase must implement
//
void
%(CAPITALIZED)sTestCase1::DoRun (void)
{
// A wide variety of test macros are available in src/core/test.h
NS_TEST_ASSERT_MSG_EQ (true, true, "true doesn't equal true for some reason");
// Use this one for floating point comparisons
NS_TEST_ASSERT_MSG_EQ_TOL (0.01, 0.01, 0.001, "Numbers are not equal within tolerance");
}
// The TestSuite class names the TestSuite, identifies what type of TestSuite,
// and enables the TestCases to be run. Typically, only the constructor for
// this class must be defined
//
class %(CAPITALIZED)sTestSuite : public TestSuite
{
public:
%(CAPITALIZED)sTestSuite ();
};
%(CAPITALIZED)sTestSuite::%(CAPITALIZED)sTestSuite ()
: TestSuite ("%(MODULE)s", UNIT)
{
// TestDuration for TestCase can be QUICK, EXTENSIVE or TAKES_FOREVER
AddTestCase (new %(CAPITALIZED)sTestCase1, TestCase::QUICK);
}
// Do not forget to allocate an instance of this TestSuite
static %(CAPITALIZED)sTestSuite %(COMPOUND)sTestSuite;
'''
DOC_RST_TEMPLATE = '''Example Module Documentation
----------------------------
.. include:: replace.txt
.. highlight:: cpp
.. heading hierarchy:
------------- Chapter
************* Section (#.#)
============= Subsection (#.#.#)
############# Paragraph (no number)
This is a suggested outline for adding new module documentation to |ns3|.
See ``src/click/doc/click.rst`` for an example.
The introductory paragraph is for describing what this code is trying to
model.
For consistency (italicized formatting), please use |ns3| to refer to
ns-3 in the documentation (and likewise, |ns2| for ns-2). These macros
are defined in the file ``replace.txt``.
Model Description
*****************
The source code for the new module lives in the directory ``src/%(MODULE)s``.
Add here a basic description of what is being modeled.
Design
======
Briefly describe the software design of the model and how it fits into
the existing ns-3 architecture.
Scope and Limitations
=====================
What can the model do? What can it not do? Please use this section to
describe the scope and limitations of the model.
References
==========
Add academic citations here, such as if you published a paper on this
model, or if readers should read a particular specification or other work.
Usage
*****
This section is principally concerned with the usage of your model, using
the public API. Focus first on most common usage patterns, then go
into more advanced topics.
Building New Module
===================
Include this subsection only if there are special build instructions or
platform limitations.
Helpers
=======
What helper API will users typically use? Describe it here.
Attributes
==========
What classes hold attributes, and what are the key ones worth mentioning?
Output
======
What kind of data does the model generate? What are the key trace
sources? What kind of logging output can be enabled?
Advanced Usage
==============
Go into further details (such as using the API outside of the helpers)
in additional sections, as needed.
Examples
========
What examples using this new code are available? Describe them here.
Troubleshooting
===============
Add any tips for avoiding pitfalls, etc.
Validation
**********
Describe how the model has been tested/validated. What tests run in the
test suite? How much API and code is covered by the tests? Again,
references to outside published work may help here.
'''
def main(argv):
parser = OptionParser(usage=("Usage: %prog [options] modulename\n"
"Utility script to create a basic template for a new ns-3 module"))
(options, args) = parser.parse_args()
if len(args) != 1:
parser.print_help()
return 1
modname = args[0].lower()
if False in [word.isalnum() for word in modname.split("-")]:
print("Module name should only contain alphanumeric characters and dashes", file=sys.stderr)
return 2
assert os.path.sep not in modname
moduledir = os.path.join(os.path.dirname(__file__), modname)
if os.path.exists(moduledir):
print("Module %r already exists" % (modname,), file=sys.stderr)
return 2
print("Creating module %r, "
"run './waf configure' to include it in the build" % (modname,))
os.mkdir(moduledir)
wscript = open(os.path.join(moduledir, "wscript"), "wt")
wscript.write(WSCRIPT_TEMPLATE % dict(MODULE=modname))
wscript.close()
#
# model
#
modeldir = os.path.join(moduledir, "model")
os.mkdir(modeldir)
model_cc = open(os.path.join(moduledir, "model", "%s.cc" % modname), "wt")
model_cc.write(MODEL_CC_TEMPLATE % dict(MODULE=modname))
model_cc.close()
model_h = open(os.path.join(moduledir, "model", "%s.h" % modname), "wt")
model_h.write(MODEL_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_H" % (modname.replace("-", "_").upper()),))
model_h.close()
#
# test
#
testdir = os.path.join(moduledir, "test")
os.mkdir(testdir)
test_cc = open(os.path.join(moduledir, "test", "%s-test-suite.cc" % modname), "wt")
test_cc.write(TEST_CC_TEMPLATE % dict(MODULE=modname,
CAPITALIZED=''.join([word.capitalize() for word in modname.split('-')]),
COMPOUND=''.join([modname.split('-')[0]] + [word.capitalize() for word in modname.split('-')[1:]]),
))
test_cc.close()
#
# helper
#
helperdir = os.path.join(moduledir, "helper")
os.mkdir(helperdir)
helper_cc = open(os.path.join(moduledir, "helper", "%s-helper.cc" % modname), "wt")
helper_cc.write(HELPER_CC_TEMPLATE % dict(MODULE=modname))
helper_cc.close()
helper_h = open(os.path.join(moduledir, "helper", "%s-helper.h" % modname), "wt")
helper_h.write(HELPER_H_TEMPLATE % dict(MODULE=modname, INCLUDE_GUARD="%s_HELPER_H" % (modname.replace("-", "_").upper()),))
helper_h.close()
#
# examples
#
examplesdir = os.path.join(moduledir, "examples")
os.mkdir(examplesdir)
examples_wscript = open(os.path.join(examplesdir, "wscript"), "wt")
examples_wscript.write(EXAMPLES_WSCRIPT_TEMPLATE % dict(MODULE=modname))
examples_wscript.close()
example_cc = open(os.path.join(moduledir, "examples", "%s-example.cc" % modname), "wt")
example_cc.write(EXAMPLE_CC_TEMPLATE % dict(MODULE=modname))
example_cc.close()
#
# doc
#
docdir = os.path.join(moduledir, "doc")
os.mkdir(docdir)
doc_rst = open(os.path.join(moduledir, "doc", "%s.rst" % modname), "wt")
doc_rst.write(DOC_RST_TEMPLATE % dict(MODULE=modname))
doc_rst.close()
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))