Topologies.jl 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191
  1. @enum Structure LI HI HO HOmod
  2. translate = (msg::A2A) -> (A2A(msg.activate))
  3. # Port Config
  4. function setup_ports!(top_model::CoupledDEVS, type::Structure)
  5. has_out_port = type in (HI, HO, HOmod)
  6. add_in_port!(top_model, :i_in)
  7. if has_out_port
  8. add_out_port!(top_model, :o_out)
  9. end
  10. if type in (HO, HOmod)
  11. add_in_port!(top_model, :i_in2)
  12. end
  13. if type == HO
  14. add_out_port!(top_model, :o_out2)
  15. end
  16. return has_out_port
  17. end
  18. function build_leaf_node(name::String, type::Structure, int_delay::Float64, ext_delay::Float64, stats::Bool)
  19. top_model = CoupledDEVS(name)
  20. has_out_port = setup_ports!(top_model, type)
  21. p_time = round(rand() + 1.0, digits=3)
  22. atom = add_submodel!(top_model, "A0", DelayedAtomic;
  23. inbox=(; i_in=A2A[]),
  24. out_ports=has_out_port ? (; o_out=A2A) : (;),
  25. int_delay=int_delay, ext_delay=ext_delay, prep_time=p_time,
  26. has_out_port=has_out_port, stats=stats)
  27. connect!(top_model, self.i_in, atom.i_in; Z=translate)
  28. if has_out_port
  29. connect!(top_model, atom.o_out, self.o_out; Z=translate)
  30. end
  31. return top_model
  32. end
  33. # Create Atomics (LI, HI, HO)
  34. function build_atomics!(top_model::CoupledDEVS, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, has_out_port::Bool, stats::Bool)
  35. width_models = ModelRef[]
  36. for idx in 0:(width - 2)
  37. p_time = 1.0 - round(rand() * (0.5 / width) + (idx / width), digits=3)
  38. atomic_name = "A$(idx)"
  39. atom = add_submodel!(top_model, atomic_name, DelayedAtomic;
  40. inbox=(; i_in=A2A[]),
  41. out_ports=has_out_port ? (; o_out=A2A) : (;),
  42. int_delay=int_delay, ext_delay=ext_delay, prep_time=p_time,
  43. has_out_port=has_out_port, stats=stats)
  44. push!(width_models, atom)
  45. end
  46. return width_models
  47. end
  48. # Routing
  49. function route_LI!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
  50. for atom in width_models
  51. connect!(top_model, self.i_in, atom.i_in; Z=translate)
  52. end
  53. end
  54. function route_HI!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
  55. for atom in width_models
  56. connect!(top_model, self.i_in, atom.i_in; Z=translate)
  57. end
  58. for i in 1:(length(width_models) - 1)
  59. connect!(top_model, width_models[i].o_out, width_models[i + 1].i_in; Z=translate)
  60. end
  61. end
  62. function route_HO!(top_model::CoupledDEVS, width_models::Vector{ModelRef})
  63. for i in 1:(length(width_models) - 1)
  64. curr_atom = width_models[i]
  65. next_atom = width_models[i + 1]
  66. connect!(top_model, curr_atom.o_out, next_atom.i_in; Z=translate)
  67. connect!(top_model, self.i_in2, curr_atom.i_in; Z=translate)
  68. connect!(top_model, curr_atom.o_out, self.o_out2; Z=translate)
  69. end
  70. if !isempty(width_models)
  71. last_atom = width_models[end]
  72. connect!(top_model, self.i_in2, last_atom.i_in; Z=translate)
  73. connect!(top_model, last_atom.o_out, self.o_out2; Z=translate)
  74. end
  75. end
  76. # Create HOmod Structure---
  77. function build_HOmod!(top_model::CoupledDEVS, child::ModelRef, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, stats::Bool)
  78. if width < 2
  79. return
  80. end
  81. atomics = Dict{Int, Vector{ModelRef}}()
  82. # create grid
  83. for i in 0:(width - 1)
  84. atomics[i] = ModelRef[]
  85. min_row_idx = i < 2 ? 0 : i - 1
  86. for j in min_row_idx:(width - 2)
  87. atomic_name = "A$(i)_$(j)"
  88. atom = add_submodel!(top_model, atomic_name, DelayedAtomic;
  89. inbox=(; i_in=A2A[]),
  90. out_ports=(; o_out=A2A),
  91. int_delay=int_delay, ext_delay=ext_delay, prep_time=1.0,
  92. has_out_port=true, stats=stats)
  93. push!(atomics[i], atom)
  94. end
  95. end
  96. for atom in atomics[0]
  97. connect!(top_model, self.i_in2, atom.i_in; Z=translate)
  98. end
  99. for i in 1:(width - 1)
  100. if !isempty(atomics[i])
  101. connect!(top_model, self.i_in2, atomics[i][1].i_in; Z=translate)
  102. end
  103. end
  104. for atom in atomics[0]
  105. connect!(top_model, atom.o_out, child.i_in2; Z=translate)
  106. end
  107. if haskey(atomics, 1) && haskey(atomics, 0)
  108. for atom1 in atomics[1]
  109. for atom0 in atomics[0]
  110. connect!(top_model, atom1.o_out, atom0.i_in; Z=translate)
  111. end
  112. end
  113. end
  114. for i in 2:(width - 1)
  115. for j in 1:length(atomics[i])
  116. connect!(top_model, atomics[i][j].o_out, atomics[i-1][j+1].i_in; Z=translate)
  117. end
  118. end
  119. end
  120. function build_devstone(type::Structure, name::String, depth::Int, width::Int, int_delay::Float64, ext_delay::Float64, stats::Bool=false)
  121. if depth < 1 || width < 1
  122. error("Invalid depth or width")
  123. end
  124. # Base Case
  125. if depth == 1
  126. return build_leaf_node(name, type, int_delay, ext_delay, stats)
  127. end
  128. # Recursive
  129. top_model = CoupledDEVS(name)
  130. has_out_port = setup_ports!(top_model, type)
  131. coupled_name = "C$(depth - 1)"
  132. child_coupled = build_devstone(type, coupled_name, depth - 1, width, int_delay, ext_delay, stats)
  133. child = add_submodel!(top_model, coupled_name, child_coupled)
  134. # Connect Parent to Child
  135. connect!(top_model, self.i_in, child.i_in; Z=translate)
  136. if type == HO
  137. connect!(top_model, self.i_in, child.i_in2; Z=translate)
  138. end
  139. if has_out_port
  140. connect!(top_model, child.o_out, self.o_out; Z=translate)
  141. end
  142. # Sub-topology Generation & Routing
  143. if type == HOmod
  144. build_HOmod!(top_model, child, depth, width, int_delay, ext_delay, stats)
  145. else
  146. width_models = build_atomics!(top_model, depth, width, int_delay, ext_delay, has_out_port, stats)
  147. if type == LI
  148. route_LI!(top_model, width_models)
  149. elseif type == HI
  150. route_HI!(top_model, width_models)
  151. elseif type == HO
  152. route_HO!(top_model, width_models)
  153. end
  154. end
  155. return top_model
  156. end