simulators.py 9.35 KB
Newer Older
1
2
import math

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Simulator(object):
    # number of cores required for this simulator
    def resreq_cores(self):
        return 1

    # memory required for this simulator (in MB)
    def resreq_mem(self):
        return 64

    def prep_cmds(self, env):
        return []

    def run_cmd(self, env):
        pass

class HostSim(Simulator):
    node_config = None
    name = ''
    wait = False
22
    sleep = 0
23
    cpu_freq = '3GHz'
24

25
    sync_mode = 0
26
27
28
    sync_period = 500
    pci_latency = 500

29
30
31
32
    def __init__(self):
        self.nics = []

    def full_name(self):
33
        return 'host.' + self.name
34
35

    def add_nic(self, nic):
36
        nic.name = self.name + '.' + nic.name
37
38
        self.nics.append(nic)

39
40
41
    def set_config(self, nc):
        self.node_config = nc

42
43
44
45
class NICSim(Simulator):
    network = None
    name = ''

Jialin Li's avatar
Jialin Li committed
46
    sync_mode = 0
47
48
49
50
    sync_period = 500
    pci_latency = 500
    eth_latency = 500

51
52
53
54
    def set_network(self, net):
        self.network = net
        net.nics.append(self)

55
    def basic_run_cmd(self, env, name, extra=None):
Jialin Li's avatar
Jialin Li committed
56
        cmd = '%s/%s %s %s %s %d 0 %d %d %d' % \
57
            (env.repodir, name, env.nic_pci_path(self), env.nic_eth_path(self),
Jialin Li's avatar
Jialin Li committed
58
59
                    env.nic_shm_path(self), self.sync_mode, self.sync_period,
                    self.pci_latency, self.eth_latency)
60
61
62
63

        if extra is not None:
            cmd += ' ' + extra
        return cmd
64
65

    def full_name(self):
66
        return 'nic.' + self.name
67
68
69

class NetSim(Simulator):
    name = ''
70
    opt = ''
Jialin Li's avatar
Jialin Li committed
71
    sync_mode = 0
72
73
    sync_period = 500
    eth_latency = 500
74
75
76
77
78

    def __init__(self):
        self.nics = []

    def full_name(self):
79
        return 'net.' + self.name
80
81
82


class QemuHost(HostSim):
83
    sync = False
84
    def resreq_cores(self):
85
86
87
88
        if self.sync:
            return 1
        else:
            return self.node_config.cores + 1
89
90
91
92
93
94
95

    def resreq_mem(self):
        return 4096

    def prep_cmds(self, env):
        to_path = env.hdcopy_path(self)
        return [f'{env.qemu_img_path} create -f qcow2 -o '
96
            f'backing_file="{env.hd_path(self.node_config.disk_image)}" '
97
98
99
            f'{env.hdcopy_path(self)}']

    def run_cmd(self, env):
100
101
        cmd = (f'{env.qemu_path} -machine q35 -serial mon:stdio '
            '-display none -nic none '
102
103
104
105
106
107
            f'-kernel {env.qemu_kernel_path} '
            f'-drive file={env.hdcopy_path(self)},if=ide,index=0,media=disk '
            f'-drive file={env.cfgtar_path(self)},if=ide,index=1,media=disk,'
                'driver=raw '
            '-append "earlyprintk=ttyS0 console=ttyS0 root=/dev/sda1 '
                'init=/home/ubuntu/guestinit.sh rw" '
108
            f'-m {self.node_config.memory} -smp {self.node_config.cores} ')
109
110

        if self.sync:
111
112
113
114
115
116
117
118
119
120
121
            unit = self.cpu_freq[-3:]
            if unit.lower() == 'ghz':
                base = 0
            elif unit.lower() == 'mhz':
                base = 3
            else:
                raise Exception('cpu frequency specified in unsupported unit')
            num = float(self.cpu_freq[:-3])
            shift = base - int(math.ceil(math.log(num, 2)))

            cmd += f' -cpu Skylake-Server -icount shift={shift},sleep=off '
122
123
124
        else:
            cmd += ' -cpu host -enable-kvm '

125
126
127
128
        if len(self.nics) > 0:
            assert len(self.nics) == 1
            cmd += f'-chardev socket,path={env.nic_pci_path(self.nics[0])},'
            cmd += 'id=cosimcd '
129
130
131
            cmd += f'-device cosim-pci,chardev=cosimcd'
            if self.sync:
                cmd += ',sync=on'
132
                cmd += f',sync-mode={self.sync_mode}'
133
134
135
136
137
138
                cmd += f',pci-latency={self.pci_latency}'
                cmd += f',sync-period={self.sync_period}'
            else:
                cmd += ',sync=off'
            cmd += ' '

139
140
141
142
143
        return cmd

class Gem5Host(HostSim):
    cpu_type_cp = 'X86KvmCPU'
    cpu_type = 'TimingSimpleCPU'
Hejing Li's avatar
Hejing Li committed
144
    sys_clock  = '1GHz'
145

146

147
148
149
150
    def set_config(self, nc):
        nc.sim = 'gem5'
        super().set_config(nc)

151
152
153
154
155
156
    def resreq_cores(self):
        return 1

    def resreq_mem(self):
        return 4096

157
158
    def prep_cmds(self, env):
        return [f'mkdir -p {env.gem5_cpdir(self)}']
159
160
161
162
163
164
165
166
167

    def run_cmd(self, env):
        cpu_type = self.cpu_type
        if env.create_cp:
            cpu_type = self.cpu_type_cp

        cmd = (f'{env.gem5_path} --outdir={env.gem5_outdir(self)} '
            f'{env.gem5_py_path} --caches --l2cache --l3cache '
            '--l1d_size=32kB --l1i_size=32kB --l2_size=2MB --l3_size=32MB '
Hejing Li's avatar
Hejing Li committed
168
            f'--cacheline_size=64 --cpu-clock={self.cpu_freq} --sys-clock={self.sys_clock} '
169
170
            f'--checkpoint-dir={env.gem5_cpdir(self)} '
            f'--kernel={env.gem5_kernel_path} '
171
            f'--disk-image={env.hd_raw_path(self.node_config.disk_image)} '
172
            f'--disk-image={env.cfgtar_path(self)} '
173
            f'--cpu-type={cpu_type} --mem-size={self.node_config.memory}MB '
174
            f'--num-cpus={self.node_config.cores} '
175
176
177
178
179
180
181
182
183
184
185
186
            '--ddio-enabled --ddio-way-part=8 --mem-type=DDR4_2400_16x4 ')

        if env.restore_cp:
            cmd += '-r 0 '

        if len(self.nics) > 0:
            assert len(self.nics) == 1
            nic = self.nics[0]
            cmd += f'--cosim-pci={env.nic_pci_path(nic)} '
            cmd += f'--cosim-shm={env.nic_shm_path(nic)} '
            if cpu_type == 'TimingSimpleCPU':
                cmd += '--cosim-sync '
187
                cmd += f'--cosim-sync_mode={self.sync_mode} '
188
189
                cmd += f'--cosim-pci-lat={self.pci_latency} '
                cmd += f'--cosim-sync-int={self.sync_period} '
190
191
192
193
194
195
196
            if isinstance(nic, I40eNIC):
                cmd += '--cosim-type=i40e '
        return cmd



class CorundumVerilatorNIC(NICSim):
197
198
    clock_freq = 250 # MHz

199
200
201
202
203
    def resreq_mem(self):
        # this is a guess
        return 512

    def run_cmd(self, env):
204
205
        return self.basic_run_cmd(env, 'corundum/corundum_verilator',
            str(self.clock_freq))
206
207
208
209
210
211
212
213
214
215
216
217
218
219

class CorundumBMNIC(NICSim):
    def run_cmd(self, env):
        return self.basic_run_cmd(env, 'corundum_bm/corundum_bm')

class I40eNIC(NICSim):
    def run_cmd(self, env):
        return self.basic_run_cmd(env, 'i40e_bm/i40e_bm')



class WireNet(NetSim):
    def run_cmd(self, env):
        assert len(self.nics) == 2
Jialin Li's avatar
Jialin Li committed
220
        return '%s/net_wire/net_wire %s %s %d %d %d' % \
221
                (env.repodir, env.nic_eth_path(self.nics[0]),
222
                        env.nic_eth_path(self.nics[1]),
Jialin Li's avatar
Jialin Li committed
223
                        self.sync_mode, self.sync_period, self.eth_latency)
224
225
226
227

class SwitchNet(NetSim):
    def run_cmd(self, env):
        cmd = env.repodir + '/net_switch/net_switch'
Jialin Li's avatar
Jialin Li committed
228
        cmd += f' -m {self.sync_mode} -S {self.sync_period} -E {self.eth_latency}'
229
230
231
        for n in self.nics:
            cmd += ' -s ' + env.nic_eth_path(n)
        return cmd
232
233


234
235
236
237
238
239
240
241
242
243
244
245
246
247
class NS3DumbbellNet(NetSim):
    def run_cmd(self, env):
        ports = ''
        for n in self.nics:
            if 'server' in n.name:
                ports += '--CosimPortLeft=' + env.nic_eth_path(n) + ' '
            else:
                ports += '--CosimPortRight=' + env.nic_eth_path(n) + ' '

        cmd = env.repodir + '/ns-3' + '/cosim-run.sh cosim cosim-dumbbell-example ' + ports + ' ' + self.opt
        print(cmd)

        return cmd

248
249
250
251
252
253
254
255
256
257
class NS3BridgeNet(NetSim):
    def run_cmd(self, env):
        ports = ''
        for n in self.nics:
            ports += '--CosimPort=' + env.nic_eth_path(n) + ' '

        cmd = env.repodir + '/ns-3' + '/cosim-run.sh cosim cosim-bridge-example ' + ports + ' ' + self.opt
        print(cmd)

        return cmd
258

259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
class NS3SequencerNet(NetSim):
    def run_cmd(self, env):
        ports = ''
        for n in self.nics:
            if 'client' in n.name:
                ports += '--ClientPort=' + env.nic_eth_path(n) + ' '
            elif 'replica' in n.name:
                ports += '--ServerPort=' + env.nic_eth_path(n) + ' '
            elif 'sequencer' in n.name:
                ports += '--EndhostSequencerPort=' + env.nic_eth_path(n) + ' '
            else:
                raise Exception('Wrong NIC type')
        cmd = env.repodir + '/ns-3' + '/cosim-run.sh sequencer sequencer-single-switch-example ' + ports + ' ' + self.opt
        return cmd


275
276
277
278
279
def create_basic_hosts(e, num, name_prefix, net, nic_class, host_class,
        nc_class, app_class, ip_start=1):
    hosts = []
    for i in range(0, num):
        nic = nic_class()
280
        #nic.name = '%s.%d' % (name_prefix, i)
281
282
283
284
        nic.set_network(net)

        host = host_class()
        host.name = '%s.%d' % (name_prefix, i)
285
286
287
288
289
290

        node_config = nc_class()
        node_config.ip = '10.0.0.%d' % (ip_start + i)
        node_config.app = app_class()
        host.set_config(node_config)

291
292
293
294
295
296
297
        host.add_nic(nic)
        e.add_nic(nic)
        e.add_host(host)

        hosts.append(host)

    return hosts
298
299
300
301
302
303
304
305
306
307
308
309


def create_dctcp_hosts(e, num, name_prefix, net, nic_class, host_class,
        nc_class, app_class, cpu_freq, mtu, ip_start=1):
    hosts = []
    for i in range(0, num):
        nic = nic_class()
        #nic.name = '%s.%d' % (name_prefix, i)
        nic.set_network(net)

        host = host_class()
        host.name = '%s.%d' % (name_prefix, i)
Hejing Li's avatar
Hejing Li committed
310
        host.cpu_freq = cpu_freq
311
312
313
314
315
316
317
318
319
320
321
322
323

        node_config = nc_class()
        node_config.mtu = mtu
        node_config.ip = '192.168.64.%d' % (ip_start + i)
        node_config.app = app_class()
        host.set_config(node_config)

        host.add_nic(nic)
        e.add_nic(nic)
        e.add_host(host)

        hosts.append(host)

Jialin Li's avatar
Jialin Li committed
324
    return hosts