I came across an interesting feature recently for Simulink® libraries that could be helpful when working with buses and other types associated with them.
Let's say we have a library with multiple blocks that use a specific bus on their interfaces, for example, myBus. When generating code for our models I recommend using non-virtual bus definitions so we can have strict control over how these buses appear in the code. This bus has 3 elements, a boolean, sel, and two uint32 values, a1 and a2. As a specific example, one of the blocks from our library uses this bus for a selection operation.
When we want to use these library blocks in one of our models, we'll need to have myBus defined somewhere in the scope of this model. This means that each model that uses blocks from this library must have a setup script or be associated with a Simulink data dictionary. Conceptually, our setup would look like this diagram:
In the above figure, the yellow arrows indicate library block usage and the blue arrows show data dictionary links.
The Desired Situation
This setup works, but it would be better if we could have the definition of myBus come along with the library instead. This would save our library users time and streamline their workflows. Conceptually, we want to follow the guiding principle that the interface for a reusable component is stored with that component. With this in mind, our diagram should look like this:
Here the dictionary containing myBus will automatically be included in any model that uses blocks from the library. We'll show how to do this in the following section.
Associating a Dictionary with a Library
Let's start by creating the required bus definition in a data dictionary. From the Model Explorer, we choose File->New Data Dictionary and provide a file name. We'll call it myLibDict.sldd. Next, we'll select the Design Data section of the dictionary and choose Add->Simulink Bus, and rename the bus to myBus.
We'll add the elements to this bus using the new Type Editor
In this interface, we can set up the element names, data type, etc. for our bus elements. Once we're done, we can see the bus definition in the dictionary in the Model Explorer:
Now that we have this definition, we associate myLibDict.sldd with myLib.slx. Start by selecting myLib in the left panel of Model Explorer and choosing the External Data tab in the right panel. In the Data Dictionary Field, enter myLibDict.sldd and press apply. Here I've cropped and zoomed in on the relevant panels.
Once we've done this, we can see this association in the External Data field in the Model Explorer:
Any model that uses the library will now automatically have access the bus definition. Specifically, myModel.slx, which uses the library block, can use the bus definition. In this case, the input is defined to be of type myBus. This is clear when we update the diagram for myModel.
Housekeeping for Library Dictionaries
Example 1: Reorganizing our Files
Now let's say we want to reorganize our project and move our library to a directory called "Libraries". Initially the files are all in the root folder of the project:
We create the directory "Libraries" and move myLib.slx and myLibDict.sldd to this directory and add it to our path:
After this move, we get an error when we try to simulate our model:
This will update the cached dictionary dependency analysis and allow us to simulate myModel.
Example 2: Sharing an Archive
As a final example, let's say we want to share our project with a colleague via an archive, let's call it myProject.mlproj. We can prevent the above error when our colleague opens this project and attempts to simulate myModel by adding the following line to a project startup script. Here we can see the script myStartupScript.m in our project and the code in the editor. Note that the Run At Startup icon is set in the Status column (circled in red). We get this by right-clicking on myStartupScript.m in the project window and selecting Run At Startup from the menu.
This will allow our colleague to simulate and generate code from the model.
Now It's Your Turn
How do you store your buses and interfaces? Do you find this feature useful? Please let us know in the comments below.