ipxact-ruby 0.11.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (142) hide show
  1. data/.autotest +15 -0
  2. data/.gitignore +2 -0
  3. data/README.html +89 -0
  4. data/README.mdown +91 -0
  5. data/Rakefile +31 -0
  6. data/VERSION +1 -0
  7. data/autotest/discover.rb +17 -0
  8. data/lib/ipxact.rb +263 -0
  9. data/lib/ipxact/component.rb +235 -0
  10. data/lib/ipxact/parser.rb +27 -0
  11. data/lib/ipxact/parser/bus_data_parser.rb +229 -0
  12. data/lib/ipxact/parser/component_data_parser.rb +309 -0
  13. data/lib/ipxact/parser/platform_data_parser.rb +63 -0
  14. data/lib/ipxact/pathfinder/graph_pathfinder.rb +191 -0
  15. data/lib/ipxact/platform.rb +43 -0
  16. data/schemas/abstractionDefinition.xsd +332 -0
  17. data/schemas/abstractor.xsd +156 -0
  18. data/schemas/autoConfigure.xsd +226 -0
  19. data/schemas/busDefinition.xsd +99 -0
  20. data/schemas/busInterface.xsd +640 -0
  21. data/schemas/commonStructures.xsd +189 -0
  22. data/schemas/component.xsd +253 -0
  23. data/schemas/configurable.xsd +82 -0
  24. data/schemas/constraints.xsd +283 -0
  25. data/schemas/design.xsd +105 -0
  26. data/schemas/designConfig.xsd +144 -0
  27. data/schemas/file.xsd +560 -0
  28. data/schemas/fileType.xsd +86 -0
  29. data/schemas/generator.xsd +240 -0
  30. data/schemas/identifier.xsd +93 -0
  31. data/schemas/index.xsd +67 -0
  32. data/schemas/memoryMap.xsd +1007 -0
  33. data/schemas/model.xsd +291 -0
  34. data/schemas/port.xsd +441 -0
  35. data/schemas/signalDrivers.xsd +220 -0
  36. data/schemas/simpleTypes.xsd +90 -0
  37. data/schemas/subInstances.xsd +256 -0
  38. data/spec/integration/bus_data_extraction_spec.rb +105 -0
  39. data/spec/integration/data_calculation_spec.rb +133 -0
  40. data/spec/integration/data_construction_spec.rb +52 -0
  41. data/spec/integration/general_spec.rb +121 -0
  42. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_initiator_port.h +135 -0
  43. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_initiator_port.tpp +247 -0
  44. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_initiator_port_base.h +189 -0
  45. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_router.h +205 -0
  46. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_router.tpp +278 -0
  47. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_slave_base.h +115 -0
  48. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_slave_base.tpp +126 -0
  49. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_target_port.h +168 -0
  50. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_target_port_base.h +133 -0
  51. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/pv_tlm_if.h +280 -0
  52. data/spec/test_data/spiritconsortium.org/Leon2TLM/PV/user_types.h +38 -0
  53. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/Leon2Platform/Leon2Platform.xml +77 -0
  54. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/Leon2Platform/design_Leon2Platform.xml +156 -0
  55. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/Leon2Platform/tlmsrc/Leon2Platform.h +149 -0
  56. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/apbSubSystem/apbSubSystem.xml +406 -0
  57. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/apbSubSystem/design_apbSubSystem.xml +135 -0
  58. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM1/apbSubSystem/tlmsrc/apbSubSystem.h +133 -0
  59. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/Leon2Platform/Leon2Platform.xml +77 -0
  60. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/Leon2Platform/design_Leon2Platform.xml +157 -0
  61. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/Leon2Platform/tlmsrc/Leon2Platform.h +150 -0
  62. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/apbSubSystem/apbSubSystem.xml +422 -0
  63. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/apbSubSystem/designConfig_apbSubSystem.xml +79 -0
  64. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/apbSubSystem/design_apbSubSystem.xml +184 -0
  65. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM2/apbSubSystem/tlmsrc/apbSubSystem.h +164 -0
  66. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/Leon2Platform/Leon2Platform.xml +105 -0
  67. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/Leon2Platform/design_Leon2Platform.xml +157 -0
  68. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/Leon2Platform/tlmsrc/Leon2Platform.h +152 -0
  69. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/apbSubSystem/apbSubSystem.xml +429 -0
  70. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/apbSubSystem/designConfig_apbSubSystem.xml +64 -0
  71. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/apbSubSystem/design_apbSubSystem.xml +150 -0
  72. data/spec/test_data/spiritconsortium.org/Leon2TLM/SystemTLM3/apbSubSystem/tlmsrc/apbSubSystem.h +167 -0
  73. data/spec/test_data/spiritconsortium.org/Leon2TLM/ahbbus/1.4/ahbbus22.xml +236 -0
  74. data/spec/test_data/spiritconsortium.org/Leon2TLM/ahbbus/1.4/tlmsrc/ahbbus.h +52 -0
  75. data/spec/test_data/spiritconsortium.org/Leon2TLM/ahbram/1.4/ahbram.xml +184 -0
  76. data/spec/test_data/spiritconsortium.org/Leon2TLM/ahbram/1.4/tlmsrc/ahbram.cc +93 -0
  77. data/spec/test_data/spiritconsortium.org/Leon2TLM/ahbram/1.4/tlmsrc/ahbram.h +77 -0
  78. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbbus/1.4/apbbus8.xml +544 -0
  79. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbbus/1.4/tlmsrc/apbbus.h +55 -0
  80. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbmst/1.4/apbmst.xml +209 -0
  81. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbmst/1.4/tlmsrc/apbmst.h +53 -0
  82. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbram/1.0/apbram.xml +395 -0
  83. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbram/1.0/hdlsrc/apbram.cc +89 -0
  84. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbram/1.0/hdlsrc/apbram.h +69 -0
  85. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbram/1.0/hdlsrc/apbram.v +82 -0
  86. data/spec/test_data/spiritconsortium.org/Leon2TLM/apbram/1.0/hdlsrc/apbram.vhd +132 -0
  87. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.4/cgu.xml +686 -0
  88. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.4/tlmsrc/cgu.cc +121 -0
  89. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.4/tlmsrc/cgu.h +81 -0
  90. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.5/cgu.xml +707 -0
  91. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.5/tlmsrc/cgu.cc +121 -0
  92. data/spec/test_data/spiritconsortium.org/Leon2TLM/cgu/1.5/tlmsrc/cgu.h +81 -0
  93. data/spec/test_data/spiritconsortium.org/Leon2TLM/dma/1.4/dma.xml +272 -0
  94. data/spec/test_data/spiritconsortium.org/Leon2TLM/dma/1.4/tlmsrc/dma.cc +230 -0
  95. data/spec/test_data/spiritconsortium.org/Leon2TLM/dma/1.4/tlmsrc/dma.h +116 -0
  96. data/spec/test_data/spiritconsortium.org/Leon2TLM/irqctrl/1.4/irqctrl.xml +530 -0
  97. data/spec/test_data/spiritconsortium.org/Leon2TLM/irqctrl/1.4/tlmsrc/irqctrl.cc +211 -0
  98. data/spec/test_data/spiritconsortium.org/Leon2TLM/irqctrl/1.4/tlmsrc/irqctrl.h +108 -0
  99. data/spec/test_data/spiritconsortium.org/Leon2TLM/processor/1.4/processor.xml +423 -0
  100. data/spec/test_data/spiritconsortium.org/Leon2TLM/processor/1.4/tlmsrc/processor.cc +331 -0
  101. data/spec/test_data/spiritconsortium.org/Leon2TLM/processor/1.4/tlmsrc/processor.h +121 -0
  102. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2apb/1.0/pv2apb.xml +240 -0
  103. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2apb/1.0/tlmsrc/pv2apb.cc +153 -0
  104. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2apb/1.0/tlmsrc/pv2apb.h +77 -0
  105. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2tac/1.0/pv2tac.xml +154 -0
  106. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2tac/1.0/tlmsrc/pv2tac.cc +114 -0
  107. data/spec/test_data/spiritconsortium.org/Leon2TLM/pv2tac/1.0/tlmsrc/pv2tac.h +67 -0
  108. data/spec/test_data/spiritconsortium.org/Leon2TLM/rgu/1.4/rgu.xml +766 -0
  109. data/spec/test_data/spiritconsortium.org/Leon2TLM/rgu/1.4/tlmsrc/rgu.cc +126 -0
  110. data/spec/test_data/spiritconsortium.org/Leon2TLM/rgu/1.4/tlmsrc/rgu.h +105 -0
  111. data/spec/test_data/spiritconsortium.org/Leon2TLM/scmlAdaptor/1.0/scmlAdaptor.xml +154 -0
  112. data/spec/test_data/spiritconsortium.org/Leon2TLM/scmlAdaptor/1.0/tlmsrc/scmladaptor.cc +100 -0
  113. data/spec/test_data/spiritconsortium.org/Leon2TLM/scmlAdaptor/1.0/tlmsrc/scmladaptor.h +62 -0
  114. data/spec/test_data/spiritconsortium.org/Leon2TLM/serial_device/1.0/serial_device.xml +151 -0
  115. data/spec/test_data/spiritconsortium.org/Leon2TLM/serial_device/1.0/tlmsrc/serial_device.h +85 -0
  116. data/spec/test_data/spiritconsortium.org/Leon2TLM/timers/1.4/timers.xml +460 -0
  117. data/spec/test_data/spiritconsortium.org/Leon2TLM/timers/1.4/tlmsrc/timers.cc +201 -0
  118. data/spec/test_data/spiritconsortium.org/Leon2TLM/timers/1.4/tlmsrc/timers.h +102 -0
  119. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/inc/uart.h +152 -0
  120. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/inc/uart_fifo.h +113 -0
  121. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/inc/uart_memory_map.h +96 -0
  122. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/inc/uart_types.h +60 -0
  123. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/src/uart.cc +125 -0
  124. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/src/uart_interrupt_handler.cc +136 -0
  125. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/src/uart_register_bank.cc +129 -0
  126. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/tlmsrc/src/uart_serial_tx_rx.cc +145 -0
  127. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_scml/1.0/uart_scml.xml +372 -0
  128. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/include/Leon2_uart.h +216 -0
  129. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/include/def_Leon2_uart.h +34 -0
  130. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/include/tlm_field.h +72 -0
  131. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/include/tlm_register.h +129 -0
  132. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/include/tlmreg_Leon2_uart.h +133 -0
  133. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/src/Leon2_uart.cc +316 -0
  134. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/src/tlmreg_Leon2_uart.cc +197 -0
  135. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/tlmsrc/src/user_specific_Leon2_uart.cc +146 -0
  136. data/spec/test_data/spiritconsortium.org/Leon2TLM/uart_tac/1.0/uart_tac.xml +222 -0
  137. data/spec/unit/component_spec.rb +98 -0
  138. data/spec/unit/graph_pathfinder_spec.rb +128 -0
  139. data/spec/unit/interconnect_spec.rb +177 -0
  140. data/spec/unit/ipxact_spec.rb +69 -0
  141. data/spec/unit/platform_spec.rb +34 -0
  142. metadata +225 -0
@@ -0,0 +1,309 @@
1
+ # Copyright (C) 2010 TIMA Laboratory
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ #
16
+
17
+ # Module for parsing IPXACT XML data and creating component objects.
18
+ #
19
+ # @author Guillaume Godet-Bar
20
+ #
21
+ module IPXACT::Parser::ComponentData
22
+
23
+ # The list of authorized connections (between two component instances in an
24
+ # interconnection).
25
+ #
26
+ AUTHORIZED_CONNECTIONS = [
27
+ {
28
+ :from => :mirrored_slave,
29
+ :to => :slave
30
+ },
31
+ {
32
+ :from => :master,
33
+ :to => :mirrored_master
34
+ },
35
+ {
36
+ :from => :master,
37
+ :to => :slave
38
+ }
39
+ ]
40
+
41
+ # Parses the component identified by +component_id+, assigns the +variables+
42
+ # associated to +instance_name+, and produces a {IPXACT::Component} object.
43
+ #
44
+ # @param [Array<String>,String] component_id the component identifier, which
45
+ # should appear in one of the component_docs. This
46
+ # identifier can either be a String (in which
47
+ # circumstance the most recent component with the
48
+ # given name will be returned, if any) or an Array of
49
+ # 2 elements, composed as follows:
50
+ # [<component_identifier>, <component_version>]
51
+ # @param [String] instance_name the name of the component instance (if any)
52
+ # that is being parsed.
53
+ # @param [Array<Hash>] variables the variables associated with the
54
+ # +instance_name+.
55
+ # @param [Hash<String, Nokogiri::Node>] component_docs the Hash of Nokogiri
56
+ # component documents that was extracted from the
57
+ # platform's IPXACT specification.
58
+ # @param [Hash<String, Nokogiri::Node>] design_docs the Hash of Nokogiri
59
+ # design documents that was extracted from the platform's
60
+ # IPXACT specification.
61
+ # @param [Array<String>] contraints an Array of constraints imposed on
62
+ # components. A constraint is an Array of 2 elements,
63
+ # composed as follows:
64
+ # [<component_identifier>, <component_version>]
65
+ # For each component instanciated during the parsing of the
66
+ # platform, the parser will verify if any of the
67
+ # constraints may apply and then select the appropriate
68
+ # component.
69
+ #
70
+ # @return [Component] the corresponding component
71
+ #
72
+ def self.parse_component(component_id, instance_name, variables, component_docs, design_docs, constraints)
73
+ component_name, component_version = select_component(component_id, component_docs)
74
+
75
+ root_component = component_docs[[component_name, component_version]]
76
+ component_vendor = root_component.xpath("./spirit:component/spirit:vendor").text
77
+ views = root_component.xpath("//spirit:model/spirit:views/spirit:view")
78
+
79
+ instances, interconnections, hierconnections = parse_design_views(views, component_docs, design_docs, constraints)
80
+
81
+ ports = root_component.xpath(".//spirit:busInterface").collect do |a_bus_interface|
82
+ IPXACT::Parser::BusData.parse_bus(a_bus_interface, root_component, variables)
83
+ end
84
+
85
+ component = IPXACT::Component.new(instance_name, component_name, component_vendor, component_version)
86
+ component.interconnections = interconnections
87
+ component.hierconnections = hierconnections
88
+ component.subcomponents = instances
89
+ component.ports = ports
90
+ component
91
+ end
92
+
93
+ # Selects from the component_docs the component that corresponds to the
94
+ # +component_id+.
95
+ # @param [String, Array<String>] component_id the component identifier, which
96
+ # should appear in one of the +component_docs+. This
97
+ # identifier can either be a String (in which circumstance
98
+ # the most recent component with the given name will be
99
+ # returned, if any) or an Array of 2 elements, composed as
100
+ # follows:
101
+ # [<component_identifier>, <component_version>]
102
+ # @param [Hash<String, Nokogiri::Node>] component_docs the Hash of Nokogiri
103
+ # component documents that was extracted from the
104
+ # platform's IPXACT specification.
105
+ #
106
+ # @return [Component] the component identified by +component_id+.
107
+ # @raise [ArgumentError] if no component could be found.
108
+ #
109
+ def self.select_component(component_id, component_docs)
110
+ if component_id.kind_of?(Array) && component_id.size == 2
111
+ # A version must have been specified
112
+ raise ArgumentError, 'Component could not be found!' unless component_docs.has_key? component_id
113
+ component_name, component_version = component_id
114
+ else
115
+ component_name = component_id
116
+ component_version = component_docs.keys.select{|name, version| name == component_name} \
117
+ .collect{|name, version| version} \
118
+ .sort{|a, b|
119
+ 1 if IPXACT::is_most_recent_version?(a,b)
120
+ 0 if IPXACT::is_same_version?(a,b)
121
+ -1
122
+ }.last
123
+ end
124
+ [component_name, component_version]
125
+ end
126
+
127
+ # Scans the given views for a hierarchical view. If such a view is found, the
128
+ # method loads the referenced design document, and parses all component
129
+ # instances, interconnections and hierconnections that are described by the
130
+ # view.
131
+ #
132
+ # @param [Array<Nokogiri::Node>] views the views from an IPXACT XML that
133
+ # should be scanned for a hierarchical view.
134
+ # @param [Hash<String, Nokogiri::Node>] component_docs the Nokogiri component
135
+ # documents that were extracted from the platform's IPXACT
136
+ # specification.
137
+ # @param [Hash<String, Nokogiri::Node>] design_docs the design documents that
138
+ # were extracted from the platform's IPXACT specification.
139
+ # @param [Array<Array>] constraints an Array of constraints imposed on
140
+ # components. A constraint is an Array of 2 elements,
141
+ # composed as follows:
142
+ # [<component_identifier>, <component_version>]
143
+ # For each component instanciated during the parsing of the
144
+ # platform, the parser will verify if any of the constraints
145
+ # may apply and then select the appropriate component.
146
+ #
147
+ # @return [Array<Hash>] an Array containing 3 Hashes, respectively: the
148
+ # component instances Hash, the interconnections Hash and the
149
+ # hierconnections Hash. Empty hashes are returned by default.
150
+ # @raise an exception if any duplicate interconnection is found.
151
+ #
152
+ def self.parse_design_views(views, component_docs, design_docs, constraints)
153
+ design_view = views.select{|view| view.xpath("./spirit:name").text == 'spirit-design' && view.xpath("./spirit:envIdentifier").text == '::Hierarchy'}
154
+ if design_view.size == 1
155
+ design_ref = IPXACT::parse_reference(design_view.first.xpath("./spirit:hierarchyRef").first)
156
+
157
+ design_doc = design_docs[[design_ref[:name], design_ref[:version]]]
158
+
159
+ instances_map = parse_component_instances(design_doc)
160
+ instances = instances_map.inject({}) do |acc, entry|
161
+ local_instance_name = entry[0]
162
+ component_reference = entry[1][:reference]
163
+ local_variables = entry[1][:variables]
164
+
165
+ constraint = constraints.select{|constraint| constraint[0] == component_reference[:name]}.first
166
+ if constraint.nil?
167
+ acc[local_instance_name] = parse_component([component_reference[:name], component_reference[:version]], local_instance_name, local_variables, component_docs, design_docs, constraints)
168
+ else
169
+ acc[local_instance_name] = parse_component(constraint, local_instance_name, local_variables, component_docs, design_docs, constraints)
170
+ end
171
+ acc
172
+ end
173
+
174
+ interconnections = parse_interconnections(design_doc, instances)
175
+ interconnection_sources = interconnections.values.collect{|v| v[0]}
176
+ interconnection_targets = interconnections.values.collect{|v| v[1]}
177
+ raise 'Duplicate connections!' \
178
+ if interconnection_sources.size != interconnection_sources.uniq.size ||
179
+ interconnection_targets.size != interconnection_targets.uniq.size
180
+
181
+ hierconnections = parse_hierconnections(design_doc, instances)
182
+ end
183
+
184
+ [(instances || {}), (interconnections || {}), (hierconnections || {})]
185
+
186
+ end
187
+
188
+ # Parses the IPXACT's design document for constructing the corresponding
189
+ # component instance interconnection.
190
+ #
191
+ # @param [Nokogiri::Node] design_doc the IPXACT design document that should
192
+ # be parsed for extracting the interconnection's
193
+ # data.
194
+ # @param [Array<Component>] component_instances the list of Component
195
+ # instances (i.e. parsed components) that correspond to
196
+ # the +design_doc+'s root component's subcomponents.
197
+ # @return [Hash] a Hash that associates the interconnection's name with an
198
+ # ordered Array (see {ComponentData#reorder_connection}) of
199
+ # Hashes, composed as follows:
200
+ # :port_name - The subcomponent's port name.
201
+ # :port_type - The subcomponent's port type.
202
+ # :component_instance - The subcomponent instance.
203
+ #
204
+ def self.parse_interconnections(design_doc, component_instances)
205
+ design_doc.xpath("//spirit:interconnection").inject({}) do |acc, inter|
206
+ unordered_connection = inter.xpath("./spirit:activeInterface").collect do |active_interface|
207
+ component_instance = component_instances[active_interface['componentRef']]
208
+ port = component_instance.ports.select{|port| port[:name] == active_interface['busRef']}.first
209
+ {
210
+ :port_name => port[:name],
211
+ :port_type => port[:type],
212
+ :component_instance => active_interface['componentRef']
213
+ }
214
+ end
215
+
216
+ ordered_connection = reorder_connection(unordered_connection)
217
+
218
+ acc[inter.xpath("./spirit:name").first.text] = ordered_connection
219
+ acc
220
+ end
221
+ end
222
+
223
+ # Parses a design document's hierconnections. A hierconnection corresponds to
224
+ # a connection between a port from the outside interface of the component
225
+ # instanciated by the design document with one of the component's
226
+ # subcomponents' ports.
227
+ #
228
+ # @param [Nokogiri::Node] design_doc the IPXACT design document that
229
+ # should be parsed for extracting the
230
+ # hierconnections.
231
+ # @param [Array<Component>] component_instances the list of Component
232
+ # instances (i.e. parsed components) that
233
+ # correspond to the +design_doc+ design document's
234
+ # root component's subcomponents.
235
+ #
236
+ # @return [Hash] a Hash that associates the outside port's name with the
237
+ # the following Hash:
238
+ # :port_name - The corresponding subcomponent's port name.
239
+ # :port_type - The corresponding subcomponent's port type.
240
+ # :component_instance - The subcomponent's instance.
241
+ #
242
+ def self.parse_hierconnections(design_doc, component_instances)
243
+ design_doc.xpath("//spirit:hierConnection").inject({}) do |acc, hier|
244
+ interface = hier.xpath("./spirit:interface").first
245
+ port = component_instances[interface['componentRef']].ports.select{|port| port[:name] == interface['busRef']}.first
246
+ acc[hier['interfaceRef']] = {
247
+ :port_name => interface['busRef'],
248
+ :port_type => port[:type],
249
+ :component_instance => interface['componentRef']
250
+ }
251
+ acc
252
+ end
253
+ end
254
+
255
+ # Extracts relevant data from an IPXACT design document (i.e., variable
256
+ # configurations)
257
+ #
258
+ # @param [Nokogiri::Node] design_doc a valid IPXACT design document.
259
+ #
260
+ # @return [Hash] a Hash that associates the component instance names with
261
+ # variable configurations. A variable configuration is composed of:
262
+ # :variables - The list of variables (name - value associations)
263
+ # :reference - The component type of the instance to which the variables
264
+ # should be affected.
265
+ #
266
+ def self.parse_component_instances(design_doc)
267
+ design_doc.xpath("//spirit:componentInstance").inject({}) do |acc, instance|
268
+
269
+ variables = instance.xpath(".//spirit:configurableElementValue").inject({}) do |acc, value|
270
+ acc[value['referenceId']] = value.text
271
+ acc
272
+ end
273
+ acc[instance.xpath("./spirit:instanceName").text] =
274
+ {
275
+ :reference => IPXACT::parse_reference(instance.xpath("./spirit:componentRef").first),
276
+ :variables => variables
277
+ }
278
+ acc
279
+ end
280
+ end
281
+
282
+ # Reorders IPXACT connections (which are not oriented in IPXACT
283
+ # specifications), following the list of authorized connections described in
284
+ # +AUTHORIZED_CONNECTIONS+.
285
+ #
286
+ # @param [Array<Hash>] connection a connection Array, that should contain 2
287
+ # elements. Each element must be a Hash with at least one
288
+ # +:port_type+ key.
289
+ #
290
+ # @return [Array] the connection Array, reversed if necessary.
291
+ # @raise an exception if no permutation of the connection elements corresponds
292
+ # to an authorized connection.
293
+ #
294
+ def self.reorder_connection(connection)
295
+ if AUTHORIZED_CONNECTIONS.include?({
296
+ :from => connection[0][:port_type],
297
+ :to => connection[1][:port_type]
298
+ })
299
+ connection
300
+ elsif AUTHORIZED_CONNECTIONS.include?({
301
+ :from => connection[1][:port_type],
302
+ :to => connection[0][:port_type]
303
+ })
304
+ connection.reverse
305
+ else
306
+ raise 'Invalid interconnect list!'
307
+ end
308
+ end
309
+ end
@@ -0,0 +1,63 @@
1
+ # Copyright (C) 2010 TIMA Laboratory
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ #
16
+
17
+ # Module for parsing IPXACT XML data and creating a platform object. Only this
18
+ # parser module should be used for working with IPXACT data.
19
+ #
20
+ # @author Guillaume Godet-Bar
21
+ #
22
+ module IPXACT::Parser::PlatformData
23
+
24
+ # Parses the +component_docs+ and +design_docs+ for creating a new
25
+ # {Platform} instance.
26
+ #
27
+ # @param [String, Array<String>] platform_id the platform identifier, which
28
+ # should appear in one of the +design_docs+.
29
+ # This identifier can either be a String (in
30
+ # which circumstance the most recent component
31
+ # with the given name will be returned, if
32
+ # any) or an Array of 2 elements, composed as
33
+ # follows:
34
+ # [<platform_identifier>, <platform_version>]
35
+ # @param [Hash<String, Nokogiri::Node>] component_docs the Hash of Nokogiri
36
+ # component documents that was
37
+ # extracted from the platform's IPXACT
38
+ # specification.
39
+ # @param [Hash<String, Nokogiri::Node>] design_docs the Hash of Nokogiri
40
+ # design documents that was extracted
41
+ # from the platform's IPXACT
42
+ # specification.
43
+ # @param [Array<String>] constraints the constraints imposed on components. A
44
+ # constraint is an Array of 2 elements, composed as
45
+ # follows:
46
+ # [<component_identifier>, <component_version>]
47
+ # For each component instanciated during the parsing
48
+ # of the platform, the parser will verify if any of
49
+ # the constraints may apply and then select the
50
+ # appropriate component.
51
+ #
52
+ # @return [Platform] the {Platform} instance. All the design documents
53
+ # related to the platform or any platform component are used for completing
54
+ # the {Platform} object. Additionally, all the variable elements, if any, are
55
+ # applied where appropriate.
56
+ #
57
+ def self.parse_platform(platform_id, component_docs, design_docs, constraints=[])
58
+ base_component = IPXACT::Parser::ComponentData.parse_component(
59
+ platform_id, "", {}, component_docs,
60
+ design_docs, constraints)
61
+ IPXACT::Platform.new(base_component)
62
+ end
63
+ end
@@ -0,0 +1,191 @@
1
+ # Copyright (C) 2010 TIMA Laboratory
2
+ #
3
+ # This program is free software: you can redistribute it and/or modify
4
+ # it under the terms of the GNU General Public License as published by
5
+ # the Free Software Foundation, either version 3 of the License, or
6
+ # (at your option) any later version.
7
+ #
8
+ # This program is distributed in the hope that it will be useful,
9
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
10
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
+ # GNU General Public License for more details.
12
+ #
13
+ # You should have received a copy of the GNU General Public License
14
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
15
+ #
16
+
17
+ # {IPXACT::GraphPathFinder} instances are used by {IPXACT::Component} instances
18
+ # for handling Branch-And-Bound type data path searches within a given IPXACT
19
+ # architecture. The {IPXACT::Component} is responsible for translating the IPXACT
20
+ # architecture into a list of connections and transition weights, which may
21
+ # then be queried for optimal paths between two nodes from the connection
22
+ # graph. As such, even though the path finder is pretty generic, it should not
23
+ # be used directly for IPXACT-related work.
24
+ #
25
+ # @example
26
+ # @pathfinder = IPXACT::GraphPathFinder.new({
27
+ # :nodes => ['component_a', 'component_b', 'component_c']
28
+ # :connections =>
29
+ # [
30
+ # {:link => [0,1]},
31
+ # {:link => [1,2], :cost => 2},
32
+ # {:link => [2,0]}
33
+ # ]
34
+ # })
35
+ # @data_path = @pathfinder.resolve('component_a', 'component_b')
36
+ #
37
+ # @author Guillaume Godet-Bar
38
+ #
39
+ class IPXACT::GraphPathFinder
40
+
41
+ # The initializer is essentially used for passing a structured connection
42
+ # Hash.
43
+ #
44
+ # @param [Hash] hash the connection Hash, which should be structured as follows:
45
+ #
46
+ # :nodes - An Array of node names (String).
47
+ #
48
+ # :connections - An Array of connection elements, which are defined as
49
+ # :link - A 2-element Array, which describes an oriented
50
+ # connection between two nodes. The nodes are
51
+ # expressed using their index in the :nodes
52
+ # Array.
53
+ # :cost - A positive Integer expressing the cost of
54
+ # the transition (in the sense of a
55
+ # Branch-And-Bound algorithm) (optional,
56
+ # default: 1).
57
+ #
58
+ def initialize(hash)
59
+ @hash = hash
60
+ end
61
+
62
+ # Searches an optimal path between the start and _end elements, which
63
+ # should be defined in the Hash structured used for instanciating the
64
+ # {IPXACT::GraphPathFinder} instance. Optimal should be understood as "the
65
+ # cheapest path given the cost of each connection". Additionally, validates
66
+ # the latter Hash structure before executing the search algorithm.
67
+ #
68
+ # @param [String] start a String that corresponds to an element that was
69
+ # registered when the pathfinder was created. The latter will be used
70
+ # as the start node by the pathfinder algorithm.
71
+ # @param [String] _end a String that corresponds to an element that was
72
+ # registered when the pathfinder was created. The latter will be used
73
+ # as the target node by the pathfinder algorithm.
74
+ #
75
+ # @return [Array<Integer>] an Array of Integers corresponding to connection
76
+ # indices for the optimal data path between the +start+ and +_end+
77
+ # elements, or an empty Array if the +start+ and +_end+ elements are
78
+ # identical.
79
+ #
80
+ # @raise an exception if the Hash structure for the connections is empty.
81
+ # @raise an exception unless all the node names are unique.
82
+ # @raise an exception if the start or end element does not exist.
83
+ # @raise an exception if no optimal data path could be found.
84
+ #
85
+ def resolve(start, _end)
86
+ raise "Empty connection table!" if @hash.empty?
87
+ return [] if start == _end
88
+ raise "Duplicate connection node found!" if @hash[:nodes].uniq.size != @hash[:nodes].size
89
+ raise "The source or target node does not exist!" unless @hash[:nodes].include?(start) && @hash[:nodes].include?(_end)
90
+
91
+ @interconnect_table = (0..@hash[:nodes].size - 1).collect do |i|
92
+ (0..@hash[:nodes].size - 1).collect do |j|
93
+ result_hash = {
94
+ :connection =>
95
+ @hash[:connections].any?{|connection| connection[:link] == [j,i]},
96
+ :total => Float::INFINITY,
97
+ :previous => nil
98
+ }
99
+ if @hash[:connections].any?{|connection| connection[:link] == [j,i]}
100
+ result = @hash[:connections].select{|connection| connection[:link] == [j,i]}.first[:cost] || 1
101
+ result_hash.merge!({:cost => result})
102
+ end
103
+
104
+ result_hash
105
+ end
106
+ end
107
+
108
+ start_index = @hash[:nodes].index(start)
109
+ end_index = @hash[:nodes].index(_end)
110
+ @interconnect_table[start_index][start_index][:total] = 0
111
+
112
+
113
+ rec_resolve([start_index, start_index], end_index, 0)
114
+
115
+ last_writer_index = nil
116
+ @interconnect_table[end_index].each_with_index do |el, i|
117
+ last_writer_index = i if el[:total] < Float::INFINITY
118
+ end
119
+ raise "Destination could not be reached!" if last_writer_index.nil?
120
+
121
+
122
+ dump_trajectory(end_index).reverse
123
+
124
+ end
125
+
126
+ private
127
+
128
+ # Recursive function for the pathfinder search algorithm.
129
+ #
130
+ # @param [Array] current the current node that is being traversed by the
131
+ # algorithm.
132
+ # @param [Integer] _end the index of the target node.
133
+ # @param [Integer] current_total current Integer cost of the trajectory that
134
+ # is being explored by this branch of the algorithm.
135
+ #
136
+ def rec_resolve(current, _end, current_total)
137
+ current_writer_index = current[0]
138
+ (0..@interconnect_table.size - 1).each do |i|
139
+ if @interconnect_table[i][current_writer_index][:connection]
140
+ new_total = current_total + (@interconnect_table[i][current_writer_index][:cost] || 1)
141
+
142
+ if @interconnect_table[i][current_writer_index][:total] > new_total
143
+ @interconnect_table[i][current_writer_index] = {:total => new_total, :connection => true, :previous => current.reverse}
144
+
145
+ unless @interconnect_table[_end].any?{|el| el[:total] < new_total}
146
+ rec_resolve([i, current_writer_index], _end, new_total)
147
+ end
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ # Scans the interconnect table, starting with the end_index, and traces a
154
+ # trajectory back to its source, using the traceback references in each cell
155
+ # from the interconnect table. The source cell is considered as the cell for
156
+ # which there is no traceback reference.
157
+ #
158
+ # @param [Integer] end_index an Integer that corresponds to the last
159
+ # element (from the original Hash structure) for which there
160
+ # should be a trajectory calculated by the search algorithm.
161
+ #
162
+ # @return [Array<Integer>] the connection indices from the original Hash
163
+ # structure.
164
+ #
165
+ def dump_trajectory(end_index)
166
+ result = []
167
+
168
+ # Get the path with the cheapest result
169
+ min_element = @interconnect_table[end_index].min{|a,b| a[:total] <=> b[:total]}
170
+ min_index = @interconnect_table[end_index].index(min_element)
171
+
172
+ previous = [min_index, end_index]
173
+ begin
174
+ connection_index = @hash[:connections].index(@hash[:connections].detect{|el| el[:link] == previous})
175
+ result << connection_index unless connection_index.nil?
176
+ previous = @interconnect_table[previous[1]][previous[0]][:previous]
177
+ end while not previous.nil?
178
+
179
+ result
180
+ end
181
+
182
+ # Commodity method for printing the interconnect table during the execution of the search algorigthm.
183
+ #
184
+ def dump_table
185
+ @interconnect_table.inject('') do |row_acc, row|
186
+ row_acc + "\n" + row.inject('') do |col_acc, col|
187
+ col_acc + (col[:total] == Float::INFINITY ? 'I' : col[:total].to_s) + " | "
188
+ end
189
+ end
190
+ end
191
+ end