ruby: added random seed option to config scripts
[gem5.git] / src / mem / ruby / config / cfg.rb
1 #!/usr/bin/ruby
2
3 class AssertionFailure < RuntimeError
4 end
5
6 class Boolean
7 def self.is_a?(obj)
8 return self.name == "Boolean"
9 end
10 end
11
12 def assert(condition,message)
13 unless condition
14 raise AssertionFailure, "\n\nAssertion failed: \n\n #{message}\n\n"
15 end
16 end
17
18 class LibRubyObject
19 @@all_objs = Array.new
20 attr_reader :obj_name
21 @@default_params = Hash.new
22
23 def initialize(obj_name)
24 assert obj_name.is_a?(String), "Obj_Name must be a string"
25 @obj_name = obj_name
26 @@all_objs << self
27 @params = Hash.new
28 end
29
30 def cppClassName()
31 raise NotImplementedException
32 end
33
34 def self.param(param_name, type)
35 idx = self.name.to_sym
36 @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
37 @@default_params[idx][param_name] = nil
38 send :define_method, param_name do
39 @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name)
40 @params[param_name]
41 end
42 method_name = (param_name.to_s + "=").to_sym
43 send :define_method, method_name do |val|
44 if val.is_a?(FalseClass) || val.is_a?(TrueClass)
45 assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
46 else
47 assert val.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
48 end
49 # assert val.is_a?(type), "#{param_name} must be of type #{type}"
50 @params[param_name] = val
51 end
52 end
53
54 def self.default_param(param_name, type, default)
55 idx = self.name.to_sym
56 @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
57 if default.is_a?(FalseClass) || default.is_a?(TrueClass)
58 assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
59 else
60 assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
61 end
62 @@default_params[idx][param_name] = default
63 send :define_method, param_name do
64 @params[param_name] = @@default_params[idx][param_name] if ! @params.key?(param_name)
65 @params[param_name]
66 end
67 method_name = (param_name.to_s + "=").to_sym
68 send :define_method, method_name do |val|
69 assert val.is_a?(type), "#{param_name} must be of type #{type}"
70 @params[param_name] = val
71 end
72 end
73
74 def applyDefaults()
75 idx = self.class.name.to_sym
76 @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
77 @@default_params[idx].each { |key, val|
78 @params[key] = val if ! @params.key?(key)
79 }
80 end
81
82 def argv()
83 str = ""
84
85 applyDefaults
86
87 @params.each { |key, val|
88 str += key.id2name + " "
89 if val.is_a?(LibRubyObject)
90 str += val.obj_name + " "
91 else
92 if val.is_a?(String) and val == ""
93 str += "null "
94 else
95 str += val.to_s + " "
96 end
97 end
98 }
99 return str
100 end
101
102 def self.printConstructors()
103 str = ""
104 @@all_objs.each { |obj|
105 str += obj.cppClassName + " " + obj.obj_name + " " + obj.argv + "\n"
106 }
107 return str
108 end
109 def self.all()
110 @@all_objs
111 end
112 end
113
114 class IfacePort < LibRubyObject
115 def initialize(obj_name)
116 super(obj_name)
117 end
118
119 def bochsConnType
120 raise NotImplementedException
121 end
122 end
123
124 class NetPort < LibRubyObject
125 attr :mach_type
126 attr_reader :version
127
128 @@type_cnt = Hash.new
129 @type_id
130 def initialize(obj_name, mach_type)
131 super(obj_name)
132 @mach_type = mach_type
133 @@type_cnt[mach_type] ||= 0
134 @type_id = @@type_cnt[mach_type]
135 @@type_cnt[mach_type] += 1
136
137 idx = "NetPort".to_sym
138 @@default_params[idx] = Hash.new if ! @@default_params.key?(idx)
139 @@default_params[idx].each { |key, val|
140 @params[key] = val if ! @params.key?(key)
141 }
142 end
143
144 def port_name
145 mach_type
146 end
147 def port_num
148 @type_id
149 end
150 def cppClassName
151 "NetPort"
152 end
153 def self.totalOfType(mach_type)
154 return @@type_cnt[mach_type]
155 end
156 end
157
158 class MemoryVector < LibRubyObject
159 def initialize(obj_name)
160 super(obj_name)
161 end
162
163 def cppClassName
164 "MemoryController"
165 end
166 end
167
168 class Debug < LibRubyObject
169 def initialize *args
170 case args.size
171 when 1
172 super(args[0])
173 when 6
174 init_params *args[1]
175 else
176 raise Exception
177 end
178 end
179
180 def init_params (protocol_trace, filter_string, verbosity_string, start_time, output_filename)
181 @params[:protocol_trace] = protocol_trace
182 @params[:filter_string] = filter_string
183 @params[:verbosity_string] = verbosity_string
184 @params[:start_time] = start_time
185 @params[:output_filename] = output_filename
186 end
187
188 def cppClassName
189 "Debug"
190 end
191 end
192
193 class RubySystem
194
195 @@params = Hash.new
196 @@defaults = Hash.new
197 @@network = nil
198
199 def self.init(iface_ports, network)
200 @@iface_ports = iface_ports
201 @@network = network
202 end
203
204 def self.reset()
205 @@iface_ports = nil
206 @@network = nil
207 @@params.each { |param_name, param|
208 param = @@defaults[param_name]
209 }
210 end
211
212 def self.default_param(param_name, type, default)
213 if default.is_a?(FalseClass) || default.is_a?(TrueClass)
214 assert type.is_a?(Boolean), "default value of param \"#{param_name}\" must be either true or false"
215 else
216 assert default.is_a?(type), "default value of param \"#{param_name}\" does not match type #{type}"
217 end
218 @@params[param_name] = default
219 @@defaults[param_name] = default
220 method_name = (param_name.to_s).to_sym
221 instance_eval <<-EOS
222 def #{method_name.to_s}
223 @@params[:#{param_name.to_s}]
224 end
225 EOS
226 instance_eval <<-EOS
227 def #{method_name.to_s}=(val)
228 @@params[:#{param_name.to_s}] = val
229 end
230 EOS
231 end
232
233 def self.getConfig()
234 # get current time for random seed if set to "rand"
235 if @@params[:random_seed] == "rand"
236 t = Time.now
237 @@params[:random_seed] = t.usec.to_i
238 end
239 if ! @@params[:random_seed].is_a?(Integer)
240 raise TypeException
241 end
242 str = "System sys0 "+argv+"\n"
243 LibRubyObject.all.each { |obj|
244 if obj.is_a?(SetAssociativeCache)
245 obj.calculateLatency
246 end
247 }
248 str += LibRubyObject.printConstructors
249 #puts str.gsub('%',' ').gsub('#','\n')
250 return str
251 end
252
253 def self.generateConfig()
254 puts getConfig
255 end
256
257 def self.printIfacePorts()
258 @@iface_ports.each { |port|
259 print port.obj_name, " "
260 }
261 puts
262 end
263
264 def self.getBochsConnections()
265 ports = Hash.new
266 @@iface_ports.each { |port|
267 ports[port.obj_name] = port.bochsConnType
268 }
269 return ports
270 end
271
272 def self.getMemorySizeMB()
273 DirectoryMemory.memorySizeMB
274 end
275
276 # override the default accessors (generated by default_param) for random_seed
277 def self.random_seed=(seed)
278 assert (val.is_a?(Integer) or val == "rand"), "RubySystem.random_seed takes either an integer value or the string \"rand\""
279 @@params[:random_seed] = seed
280 end
281
282 private
283
284 def self.argv()
285 str = ""
286 @@params.each { |key, val|
287 str += key.id2name + " "
288 str += val.to_s + " "
289 }
290 return str
291 end
292
293 def self.writeConfig()
294 @@network.printTopology
295 end
296
297 end
298
299 #require "defaults.rb"
300
301
302
303 class CacheController < NetPort
304 @@total_cache_controllers = Hash.new
305
306 def initialize(obj_name, mach_type, caches)
307 super(obj_name, mach_type)
308 caches.each { |cache|
309 cache.controller = self
310 }
311
312 if !@@total_cache_controllers.key?(mach_type)
313 @@total_cache_controllers[mach_type] = 0
314 end
315 @version = @@total_cache_controllers[mach_type]
316 @@total_cache_controllers[mach_type] += 1
317
318 # call inhereted parameters
319 transitions_per_cycle
320 buffer_size
321 number_of_TBEs
322 recycle_latency
323 end
324
325 def argv()
326 vec = "version "+@version.to_s
327 vec += " transitions_per_cycle "+@params[:transitions_per_cycle].to_s
328 vec += " buffer_size "+@params[:buffer_size].to_s
329 vec += " number_of_TBEs "+@params[:number_of_TBEs].to_s
330 vec += " recycle_latency "+@params[:recycle_latency].to_s
331 end
332
333 def cppClassName()
334 "generated:"+@mach_type
335 end
336 end
337
338 class L1CacheController < CacheController
339 attr :sequencer
340
341 def initialize(obj_name, mach_type, caches, sequencer)
342 super(obj_name, mach_type, caches)
343
344 @sequencer = sequencer
345 @sequencer.controller = self
346 @sequencer.version = @version
347 end
348
349 def argv()
350 vec = super()
351 vec += " sequencer "+@sequencer.obj_name
352 end
353 end
354
355 class DirectoryController < NetPort
356 @@total_directory_controllers = 0
357 attr :directory
358 attr :memory_control
359
360 def initialize(obj_name, mach_type, directory, memory_control)
361 super(obj_name, mach_type)
362
363 @directory = directory
364 directory.controller = self
365
366 @memory_control = memory_control
367
368 @version = @@total_directory_controllers
369 @@total_directory_controllers += 1
370 buffer_size()
371 end
372
373 def argv()
374 "version "+@version.to_s+" directory_name "+@directory.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + " memory_controller_name "+@memory_control.obj_name + " recycle_latency "+@params[:recycle_latency].to_s
375 end
376
377 def cppClassName()
378 "generated:"+@mach_type
379 end
380
381 end
382
383 class DMAController < NetPort
384 @@total_dma_controllers = 0
385 attr :dma_sequencer
386 def initialize(obj_name, mach_type, dma_sequencer)
387 super(obj_name, mach_type)
388 @dma_sequencer = dma_sequencer
389 @version = @@total_dma_controllers
390 @@total_dma_controllers += 1
391 dma_sequencer.controller = self
392 buffer_size
393 end
394
395 def argv()
396 "version "+@version.to_s+" dma_sequencer "+@dma_sequencer.obj_name+" transitions_per_cycle "+@params[:transitions_per_cycle].to_s + " buffer_size "+@params[:buffer_size].to_s + " number_of_TBEs "+@params[:number_of_TBEs].to_s + " recycle_latency "+@params[:recycle_latency].to_s
397 end
398
399 def cppClassName()
400 "generated:"+@mach_type
401 end
402 end
403
404 class Cache < LibRubyObject
405 attr :size_kb, :latency
406 attr_writer :controller
407 def initialize(obj_name, size_kb, latency)
408 super(obj_name)
409 assert size_kb.is_a?(Integer), "Cache size must be an integer"
410 @size_kb = size_kb
411 @latency = latency
412 end
413
414 def args
415 "controller "+@controller.obj_name+" size_kb "+@size_kb.to_s+" latency "+@latency.to_s
416 end
417 end
418
419 class SetAssociativeCache < Cache
420 attr :assoc, :replacement_policy
421
422 # latency can be either an integer, a float, or the string "auto"
423 # when an integer, it represents the number of cycles for a hit
424 # when a float, it represents the cache access time in ns
425 # when set to "auto", libruby will attempt to find a realistic latency by running CACTI
426 def initialize(obj_name, size_kb, latency, assoc, replacement_policy)
427 super(obj_name, size_kb, latency)
428 @assoc = assoc
429 @replacement_policy = replacement_policy
430 end
431
432 def calculateLatency()
433 if @latency == "auto"
434 cacti_args = Array.new()
435 cacti_args << (@size_kb*1024) << RubySystem.block_size_bytes << @assoc
436 cacti_args << 1 << 0 << 0 << 0 << 1
437 cacti_args << RubySystem.tech_nm << RubySystem.block_size_bytes*8
438 cacti_args << 0 << 0 << 0 << 1 << 0 << 0 << 0 << 0 << 1
439 cacti_args << 360 << 0 << 0 << 0 << 0 << 1 << 1 << 1 << 1 << 0 << 0
440 cacti_args << 50 << 10 << 10 << 0 << 1 << 1
441
442 cacti_cmd = File.dirname(__FILE__) + "/cacti/cacti " + cacti_args.join(" ")
443
444 IO.popen(cacti_cmd) { |pipe|
445 str1 = pipe.readline
446 str2 = pipe.readline
447 results = str2.split(", ")
448 if results.size != 61
449 print "CACTI ERROR: CACTI produced unexpected output.\n"
450 print "Are you using the version shipped with libruby?\n"
451 raise Exception
452 end
453 latency_ns = results[5].to_f
454 if (latency_ns == "1e+39")
455 print "CACTI ERROR: CACTI was unable to realistically model the cache ",@obj_name,"\n"
456 print "Either change the cache parameters or manually set the latency values\n"
457 raise Exception
458 end
459 clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
460 latency_cycles = (latency_ns / clk_period_ns).ceil
461 @latency = latency_cycles
462 }
463 elsif @latency.is_a?(Float)
464 clk_period_ns = 1e9 * (1.0 / (RubySystem.freq_mhz * 1e6))
465 latency_cycles = (@latency / clk_period_ns).ceil
466 @latency = latency_cycles
467 elsif ! @latency.is_a?(Integer)
468 raise Exception
469 end
470 end
471
472 def argv()
473 args+" assoc "+@assoc.to_s+" replacement_policy "+@replacement_policy
474 end
475
476 def cppClassName()
477 "SetAssociativeCache"
478 end
479 end
480
481 class DirectoryMemory < LibRubyObject
482 attr :size_mb
483 attr_writer :controller
484 @@total_size_mb = 0
485
486 def initialize(obj_name, size_mb)
487 super(obj_name)
488 @size_mb = size_mb
489 @@total_size_mb += size_mb
490 end
491
492 def argv()
493 "version "+@controller.version.to_s+" size_mb "+@size_mb.to_s+" controller "+@controller.obj_name
494 end
495
496 def cppClassName()
497 "DirectoryMemory"
498 end
499
500 def self.memorySizeMB()
501 @@total_size_mb
502 end
503 end
504
505 #added by SS
506 class MemoryControl < LibRubyObject
507 attr :name
508 def initialize(obj_name)
509 super(obj_name)
510 @name = obj_name
511 end
512
513 def argv()
514 vec = super()
515 vec += " mem_bus_cycle_multiplier "+mem_bus_cycle_multiplier.to_s
516 vec += " banks_per_rank "+banks_per_rank.to_s
517 vec += " ranks_per_dimm "+ranks_per_dimm.to_s
518 vec += " dimms_per_channel "+dimms_per_channel.to_s
519 vec += " bank_bit_0 "+bank_bit_0.to_s
520 vec += " rank_bit_0 "+rank_bit_0.to_s
521 vec += " dimm_bit_0 "+dimm_bit_0.to_s
522 vec += " bank_queue_size "+bank_queue_size.to_s
523 vec += " bank_busy_time "+bank_busy_time.to_s
524 vec += " rank_rank_delay "+rank_rank_delay.to_s
525 vec += " read_write_delay "+read_write_delay.to_s
526 vec += " basic_bus_busy_time "+basic_bus_busy_time.to_s
527 vec += " mem_ctl_latency "+mem_ctl_latency.to_s
528 vec += " refresh_period "+refresh_period.to_s
529 vec += " tFaw "+tFaw.to_s
530 vec += " mem_random_arbitrate "+mem_random_arbitrate.to_s
531 vec += " mem_fixed_delay "+mem_fixed_delay.to_s
532 vec += " memory_controller_name "+@name
533
534 end
535
536
537 def cppClassName()
538 "MemoryControl"
539 end
540 end
541
542
543
544 class Sequencer < IfacePort
545
546 def cppClassName()
547 "Sequencer"
548 end
549
550 param :controller, NetPort # must be set after initialization
551 param :icache, Cache
552 param :dcache, Cache
553 param :version, Integer
554
555 def initialize(obj_name, icache, dcache)
556 super(obj_name)
557 self.icache=icache
558 self.dcache=dcache
559 end
560
561 def bochsConnType()
562 return "cpu"+version.to_s
563 end
564
565 end
566
567
568
569 class DMASequencer < IfacePort
570 def initialize(obj_name)
571 super(obj_name)
572 @params = {
573 :controller => nil,
574 :version => nil
575 }
576 end
577
578 def controller=(controller)
579 @params[:controller] = controller.obj_name
580 @params[:version] = controller.version
581 end
582
583 def cppClassName()
584 "DMASequencer"
585 end
586
587 def bochsConnType()
588 return "dma"+@params[:version].to_s
589 end
590 end
591
592 class IntNode
593 @@num = 0
594 def initialize()
595
596 end
597 end
598
599 class Network < LibRubyObject
600 end
601
602 class Topology < LibRubyObject
603 attr :net_ports
604 param :network, Network
605 def initialize(name, net_ports)
606 super(name)
607 @net_ports = net_ports
608 end
609
610 def cppClassName
611 "Topology"
612 end
613 end
614
615 class Network < LibRubyObject
616 param :topology, Topology
617 def initialize(name, topo)
618 super(name)
619 @params[:topology] = topo
620 topo.network= self
621 end
622
623 def argv()
624 vec = super()
625
626 vec += " endpoint_bandwidth "+endpoint_bandwidth.to_s
627 vec += " adaptive_routing "+adaptive_routing.to_s
628 vec += " number_of_virtual_networks "+number_of_virtual_networks.to_s
629 vec += " fan_out_degree "+fan_out_degree.to_s
630
631 vec += " buffer_size "+buffer_size.to_s
632 vec += " link_latency "+adaptive_routing.to_s
633 vec += " on_chip_latency "+on_chip_latency.to_s
634 vec += " control_msg_size "+control_msg_size.to_s
635 end
636
637 def printTopology()
638 topology().printFile
639 end
640 def cppClassName()
641 "SimpleNetwork"
642 end
643
644 end
645
646 class PtToPtTopology < Topology
647
648 param :connections,String
649
650 def initialize(name, net_ports)
651 super(name, net_ports)
652 @params[:connections] = ""
653 @net_ports.each_index { |idx|
654 @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
655 @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
656 @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
657 }
658 @net_ports.each_index { |outer_idx|
659 @net_ports.each_index { |inner_idx|
660 if (outer_idx != inner_idx)
661 @params[:connections] << ("int_node:"+ outer_idx.to_s+ "%int_node:"+ inner_idx.to_s)
662 @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
663 @params[:connections] << ("%link_weight:"+1.to_s+"#")
664 end
665 }
666 }
667 # call the accessors of the parent class to initialize them
668 # need to find a better method!!
669 print_config
670 end
671
672 end
673
674 class CrossbarTopology < Topology
675 param :connections,String
676
677 def initialize(name, net_ports)
678 super(name, net_ports)
679 @params[:connections] = ""
680 crossbar_node = @net_ports.size
681 @net_ports.each_index { |idx|
682 @params[:connections] << ("ext_node:"+@net_ports[idx].port_name+":"+@net_ports[idx].port_num.to_s)
683 @params[:connections] << ("%int_node:"+ idx.to_s+ "%link_latency:"+ link_latency.to_s)
684 @params[:connections] << ("%bw_multiplier:"+external_bw.to_s+"#")
685 }
686 @net_ports.each_index { |idx|
687 @params[:connections] << ("int_node:"+idx.to_s+"%int_node:"+crossbar_node.to_s)
688 @params[:connections] << ("%link_latency:"+link_latency.to_s+"%bw_multiplier:"+internal_bw.to_s)
689 @params[:connections] << ("%link_weight:"+1.to_s+"#")
690 }
691 print_config
692 end
693 end
694
695 #added by SS
696 class Tracer < LibRubyObject
697 def initialize(obj_name)
698 super(obj_name)
699 end
700
701 def cppClassName()
702 "Tracer"
703 end
704
705 end
706
707 class Profiler < LibRubyObject
708 def initialize(obj_name)
709 super(obj_name)
710 end
711
712 def cppClassName()
713 "Profiler"
714 end
715
716 end
717
718 #added by SS
719 class GarnetNetwork < Network
720 def initialize(name, topo)
721 super(name, topo)
722 end
723 def argv()
724 vec = super()
725 vec += " flit_size "+flit_size.to_s
726 vec += " number_of_pipe_stages "+number_of_pipe_stages.to_s
727 vec += " vcs_per_class "+vcs_per_class.to_s
728 vec += " buffer_size "+buffer_size.to_s
729 vec += " using_network_testing "+using_network_testing.to_s
730 end
731
732 end
733
734 class GarnetFixedPipeline < GarnetNetwork
735 def initialize(name, net_ports)
736 super(name, net_ports)
737 end
738
739 def argv()
740 super()
741 end
742
743 def cppClassName()
744 "GarnetNetwork_d"
745 end
746 end
747
748 class GarnetFlexiblePipeline < GarnetNetwork
749 def initialize(name, net_ports)
750 super(name, net_ports)
751 end
752
753 def argv()
754 super()
755 end
756
757 def cppClassName()
758 "GarnetNetwork"
759 end
760 end
761
762 require "defaults.rb"