| 1 | [[PageOutline]] |
| 2 | |
| 3 | = Metadata = |
| 4 | |
| 5 | For SoCLib components, metadata is in `.sd` files, parsed by `soclib-cc`. |
| 6 | |
| 7 | In these files, there is an optional `extensions = ` statement. This statement is a list of string formatted as |
| 8 | `"namespace:keyword=value"`. An example for the dsx namespace is: |
| 9 | {{{ |
| 10 | extensions = [ |
| 11 | 'dsx:cpu=wrapper:iss_t', |
| 12 | 'dsx:addressable=target_index', |
| 13 | ], |
| 14 | }}} |
| 15 | |
| 16 | Here we'll make a list of these extensions and their effects |
| 17 | |
| 18 | = Pure C++ module constraints = |
| 19 | |
| 20 | == Module without a name as first parameter == |
| 21 | |
| 22 | Some pure-C++ (i.e. not SystemC) modules do not need a name as first parameter. There |
| 23 | is an extension telling the netlister to generate a correct constructor invocation |
| 24 | for the module: |
| 25 | {{{ |
| 26 | "dsx:noname", |
| 27 | }}} |
| 28 | |
| 29 | = Memory mapping & organization = |
| 30 | |
| 31 | == VCI srcid / tgtid, ports and mapping tables == |
| 32 | |
| 33 | VCI uses `(``r)srcid` to route response packets back to the originating initiator. As it is |
| 34 | decoded, the srcid field attributed to an initiator is directly equivalent to the port it is |
| 35 | connected to on peer interconnect. A module then has to be able to retrieve: |
| 36 | * srcid field value (or initiator index as an `IntTab` parameter) |
| 37 | * mapping table associated to the interconnect |
| 38 | * correspondance between ports and indexes |
| 39 | |
| 40 | Likewise for targets. |
| 41 | |
| 42 | == Target components == |
| 43 | |
| 44 | For a simple target component, we'll probably have: |
| 45 | * a `VciTarget` port |
| 46 | * a mapping table as parameter |
| 47 | * a target index as parameter |
| 48 | |
| 49 | {{{ |
| 50 | ports = [ |
| 51 | Port('caba:vci_target', 'p_vci_port_name'), |
| 52 | … |
| 53 | ], |
| 54 | instance_parameters = [ |
| 55 | … |
| 56 | parameter.IntTab('target_index_parameter_name'), |
| 57 | parameter.Module('mapping_table_parameter_name', typename = 'common:mapping_table'), |
| 58 | … |
| 59 | ], |
| 60 | }}} |
| 61 | |
| 62 | Needed metadata are: |
| 63 | |
| 64 | {{{ |
| 65 | "dsx:get_ident=target_index_parameter_name:p_vci_port_name:mapping_table_port_name", |
| 66 | "dsx:addressable=target_index_parameter_name", |
| 67 | }}} |
| 68 | |
| 69 | `dsx:get_ident` associates a given index to a port and a mapping table. Actual index |
| 70 | value and mapping table to use will be implicitly retrieved through the module connected |
| 71 | to the port. |
| 72 | |
| 73 | `dsx:addressable` tells the target is accessible through this target index. |
| 74 | |
| 75 | == Maximum target segments == |
| 76 | |
| 77 | Sometimes targets can only have a limited number of addressable segments. You can enforce |
| 78 | this limit telling DSX to do so. |
| 79 | |
| 80 | For instance, a simple controller may only need one segment: |
| 81 | |
| 82 | {{{ |
| 83 | extensions = [ |
| 84 | 'dsx:max_segments=1', |
| 85 | ], |
| 86 | }}} |
| 87 | |
| 88 | == Addressable segments associated to a srcid == |
| 89 | |
| 90 | For coherent platforms, we sometimes need to associate a source id to a segment. |
| 91 | Thus when creating the segment, we have to add an id. This is done through |
| 92 | `"dsx:on_segment=` extension. Example in the `vci_cc_xcache_wrapper_v1`: |
| 93 | |
| 94 | Syntax: `target_segment_mapping_table:add_index:initiator_index_name` |
| 95 | |
| 96 | {{{ |
| 97 | instance_parameters = [ |
| 98 | parameter.Int('proc_id'), |
| 99 | parameter.Module('mtp', 'common:mapping_table'), |
| 100 | parameter.Module('mtc', 'common:mapping_table'), |
| 101 | parameter.IntTab('initiator_rw_index'), |
| 102 | parameter.IntTab('initiator_c_index'), |
| 103 | parameter.IntTab('target_index'), |
| 104 | … |
| 105 | ], |
| 106 | extensions = [ |
| 107 | 'dsx:get_ident=' |
| 108 | 'initiator_rw_index:p_vci_ini_rw:mt,' |
| 109 | 'initiator_c_index:p_vci_ini_c:mc,' |
| 110 | 'target_index:p_vci_tgt:mc', |
| 111 | 'dsx:on_segment=mc:add_index:initiator_rw_index', |
| 112 | 'dsx:addressable=target_index', |
| 113 | … |
| 114 | ], |
| 115 | }}} |
| 116 | |
| 117 | == Initiator == |
| 118 | |
| 119 | For a simple initiator component, we'll probably have: |
| 120 | * a `VciInitiator` port |
| 121 | * a mapping table as parameter |
| 122 | * a source index as parameter |
| 123 | |
| 124 | {{{ |
| 125 | ports = [ |
| 126 | Port('caba:vci_initiator', 'p_vci'), |
| 127 | … |
| 128 | ], |
| 129 | instance_parameters = [ |
| 130 | … |
| 131 | parameter.Module('mt', 'common:mapping_table'), |
| 132 | parameter.IntTab('index'), |
| 133 | … |
| 134 | ], |
| 135 | }}} |
| 136 | |
| 137 | This works the same way as for targets. Let's have an example with real names: |
| 138 | |
| 139 | {{{ |
| 140 | extensions = [ |
| 141 | 'dsx:get_ident=index:p_vci:mt', |
| 142 | ], |
| 143 | }}} |
| 144 | |
| 145 | `dsx:get_ident` associates a given index to a port and a mapping table. Actual index |
| 146 | value and mapping table to use will be implicitly retrieved through the module connected |
| 147 | to the port. |
| 148 | |
| 149 | == Interconnects == |
| 150 | |
| 151 | In order to get the two preceding points working, interconnects need to provide a way to |
| 152 | get a source / target identifier. When DSX reaches an interconnect, it looks for the following extension: |
| 153 | |
| 154 | {{{ |
| 155 | extensions = [ |
| 156 | 'dsx:interconnect=root', |
| 157 | 'dsx:obtain_ident_method=port', |
| 158 | ], |
| 159 | }}} |
| 160 | |
| 161 | `dsx:interconnect` may either have no value, or "root". "root" means the interconnect is |
| 162 | the root of the routing tree, for instance a VGMN. Local interconnects (like the `vci_local_crossbar`) |
| 163 | only need `"dsx:interconnect"`. |
| 164 | |
| 165 | `dsx:obtain_ident_method` may value either `port` or `param`. |
| 166 | |
| 167 | `port`:: |
| 168 | The identifier is directly related to the port number in a port array, this is the usual value |
| 169 | for all port-array based interconnects like VGMN or crossbars. |
| 170 | |
| 171 | `param=some_parameter_name`:: |
| 172 | Use a given instance parameter as identifier for associated component. This is the usual value |
| 173 | for one-wrapper-per-component interconnects like ring or dspin. |
| 174 | |
| 175 | = CPUs / ISS wrappers = |
| 176 | |
| 177 | == Processor type == |
| 178 | |
| 179 | For DSX software deployment system, we need to highlight CPUs and their types. This is the |
| 180 | `"dsx:cpu="` extension. |
| 181 | |
| 182 | As ISS are wrapped in caches, and wrapping may be nested (GDB, memchecker, …) |
| 183 | a recursive way, a recursive lookup is achieved. |
| 184 | |
| 185 | `"dsx:cpu="` may be: |
| 186 | |
| 187 | `wrapper:some_template_parameter_type`:: |
| 188 | used in caches and iss wrappers, to tell the iss is unknown, but given as a parameter |
| 189 | |
| 190 | `some_arch`:: |
| 191 | used for actual CPU implementations, tells what the cpu architure is. |
| 192 | Current known architectures are `mips32el`, `mips32eb`, `powerpc405`, `arm`. |
| 193 | |
| 194 | == Processor identifier == |
| 195 | |
| 196 | CPU are associated to an unique identifier for the platform, usually a sequential name. |
| 197 | DSX needs to know what parameter corresponds to this identifier. This is done with the |
| 198 | `"dsx:mapping_type=processor:parameter_name"`: |
| 199 | |
| 200 | {{{ |
| 201 | instance_parameters = [ |
| 202 | parameter.Int('ident'), # processor identifier |
| 203 | parameter.Module('mt', 'common:mapping_table'), |
| 204 | parameter.IntTab('index'), |
| 205 | … |
| 206 | ], |
| 207 | extensions = [ |
| 208 | 'dsx:mapping_type=processor:ident', |
| 209 | ], |
| 210 | }}} |
| 211 | |
| 212 | == Devices == |
| 213 | |
| 214 | Devices may be declared, in order to be able to map specific options to them. For |
| 215 | now, only ttys are supported. |
| 216 | |
| 217 | {{{ |
| 218 | extensions = [ |
| 219 | 'dsx:device=tty', |
| 220 | ], |
| 221 | }}} |
| 222 | |
| 223 | == C++ hacks == |
| 224 | |
| 225 | Sometimes, you have to call a C++ static function once |
| 226 | per class, or a method once per object instance. |
| 227 | These two things will help, even if this obscure feature |
| 228 | is mostly undocumented. Use source code for reference. |
| 229 | |
| 230 | === Static configuration lines === |
| 231 | |
| 232 | `'dsx:static_config_lines=%(class)s::init(%(env:mapping_table)s,%(env:loader)s,"%(meta:all_peripherals)s")'` |
| 233 | |
| 234 | This is an excerpt from `iss_memchecker` metadata, telling |
| 235 | the netlister must generate a line with a given |
| 236 | template once for each IssMemchecker<…> type, taking references |
| 237 | from envorinment and all peripherals. |
| 238 | |
| 239 | === Instance configuration lines === |
| 240 | |
| 241 | Likewise, there is |
| 242 | |
| 243 | `'dsx:config_lines=…'`, emitted once for each object. See dsx soclib's component handling code for usage. |
| 244 | |
| 245 | == MutekH configuration == |
| 246 | |
| 247 | Some modules may want to influence MutekH's own configuration. This is only available |
| 248 | when using DSX software-generation feature. Using a given module may then change some |
| 249 | configuration tokens in MutekH's build system. |
| 250 | |
| 251 | For instance, when putting an `iss_memchecker` in the netlist, we want MutekH to be built with |
| 252 | memchecker support code activated, thus we can add in iss_memchecker's metadata the following |
| 253 | extension: |
| 254 | |
| 255 | {{{ |
| 256 | extensions = [ |
| 257 | 'dsx:set_config=CONFIG_SOCLIB_MEMCHECK', |
| 258 | ], |
| 259 | }}} |
| 260 | |
| 261 | = Examples = |
| 262 | |
| 263 | == DMA == |
| 264 | |
| 265 | Let's describe a DMA. It has |
| 266 | * one initiator port |
| 267 | * one target port |
| 268 | * an initiator index |
| 269 | * a target index |
| 270 | * a mapping table associated to this all |
| 271 | |
| 272 | It only supports one addressable segment |
| 273 | |
| 274 | {{{ |
| 275 | ports = [ |
| 276 | Port('caba:vci_target', 'p_vci_target'), |
| 277 | Port('caba:vci_initiator', 'p_vci_initiator'), |
| 278 | … |
| 279 | ], |
| 280 | instance_parameters = [ |
| 281 | parameter.Module('mt', typename = 'common:mapping_table'), |
| 282 | parameter.IntTab('srcid'), |
| 283 | parameter.IntTab('tgtid'), |
| 284 | parameter.Int('burst_size'), |
| 285 | ], |
| 286 | extensions = [ |
| 287 | 'dsx:addressable=tgtid', |
| 288 | 'dsx:max_segments=1', |
| 289 | 'dsx:get_ident=srcid:p_vci_target:mt,tgtid:p_vci_initiator:mt', |
| 290 | ], |
| 291 | }}} |