Intrinsic Usage and Management
Unlike in C, integer division, modulus, and floating point operations are expensive to do in hardware. In fact, there is no way to specify “add two 32-bit floats” or “multiply two 64-bit floats”, other than implementing the algorithm yourself or using a hardware IP Core specifically designed for that purpose. These operations are significantly more complex than simple operations such as addition. Since there are several ways implement division, the synthesis tool does not blindly infer a solution.
In order to simulate or synthesize code generated with ROCCC that uses integer division, modulus, or floating point operations, it is necessary to create and include an intrinsic component into your simulation or synthesis project. It is generally necessary, if you want to use floating point, to find an IP Core for each of the operations you need. Xilinx has the CoreGen utility to provide IP Cores, or a site like http://opencores.org provides cores.
Once you have found an IP Core that implements the operations you require, you will want to utilize it in your project. Traditionally, this would be done by instantiating it in the code that requires it, with each IP Core having slightly different requirements. For example, one divide core may have a reset or enable input, while another may not. Because ROCCC has no knowledge of what IP Core you will end up using, we cannot directly instantiate the IP Core you will use; instead, we instantiate a “wrapper” component. The component must be written by you, and provides a standardized interface that ROCCC can instantiate. For a description of what ports ROCCC expects on components, take a look at our Connecting to ROCCC Generated Code tutorial.
This component does not have to implement any logic; it can simply instantiate the IP Core to implement the logic. In this way, a standardized interface is presented to ROCCC, but any IP Core can be used to implement the actual logic.
When choosing an IP Core, it is important to keep several considerations in mind. First, the core should be fully pipelined, as ROCCC assumes all subcomponents are fully pipelined. Second, the core needs to have a way to stall the component. Thirdly, the component must complete the calculation in a constant number of clock cycles. This number of clock cycles must be told to the GUI when adding the intrinsic into ROCCC.
Managing Intrinsics in ROCCC 2.0
By selecting “Manage->Intrinsics” in the ROCCC menu, the user is able to select which IP Cores to use for these intrinsic operations. A window will pop up that will hold a list of intrinsic types on the left and the available intrinsics for that type on the right.
You will be able to see various details about the intrinsics such as their names, bit sizes, latency, description, and whether they are active or not. You can see what available intrinsics you have for each type by selecting the type you would like to view on the left. These types include integer division and modulus, floating point operations, and redundancy voters.
ROCCC comes bundled with some intrinsic information already in the database. These intrinsics and their values are based off of the cores generated from Xilinx CoreGen. If you ever want to add your own intrinsics to use into the intrinsic list, select the “Add” button on the right of the window.
Upon clicking that, a new window will open asking for the details of the intrinsic you would like to add. You can select what type the intrinsic is on the left and input the data about it on the right. Remember to put the values in correctly or the code that ROCCC generates may not work properly with the intrinsic.
Once you have chosen a name and specified the bit size and latency, you will have to choose whether or not this intrinsic should be active. If this intrinsic is active then it will be used whenever ROCCC needs an intrinsic that fits the details of the one you just made. The last thing you can input in is an optional description to help you remember what your intrinsic is for. Once you have input all the data for the intrinsic, press “Finish” at the bottom.
The window will close bringing you back to the intrinsics list. The intrinsic you just added will be in the list of intrinsics for what type it is. If you wrote a description for the intrinsic, you should be able to see it on the list.
If you ever want to edit any of the details for a specific intrinsic, you can double click any of the table cells and change the values to reflect the changes you wanted. You cannot edit the “Active” column by double clicking it.
If you ever want to remove an intrinsic, select the intrinsic you would like to delete and press the “Delete” button on the right. This will remove the intrinsic from the list.
If there is no intrinsic that matches the bit sizes of the variables being operating on, ROCCC will choose the closest ceiling value to those bit sizes. For example, if we only have the integer division cores shown above and we are doing division with two 9-bit integers, ROCCC will use the int_div16 intrinsic and extend the integers to 16 bits when performing the operation.
If we tried to do integer division with two 70-bit integers, ROCCC would report an error during compilation saying there is no integer division core available to handle that operation.
Multiple Intrinsics with Matching Bit Sizes
Let’s say we want two intrinsics that have the same bit sizes. For example, I may want one 8-bit integer division intrinsic for the Convey HC-1, and I want a separate 8-bit integer division intrinsic for the Pico E-16. I already have the integer division intrinsic that works for the HC-1 so, I go ahead and add one for the E-16.
Now which one will ROCCC use when it needs an 8-bit integer division? Well only one intrinsic of a certain bit size can be active at a time. So ROCCC will use whatever intrinsic is currently active.
If you want to switch between which intrinsic of a specific bit size ROCCC will use, you can select the one you want to use and select “Activate” on the right. This will activate that intrinsic as well as deactivate all other intrinsics that have the same bit sizes of that type.
How Intrinsics are Called
By now we know about intrinsics and how to manage them inside of ROCCC. Now let’s look at how they are used in ROCCC. Let’s say we have two integer division intrinsics of size 32 in our database: int_div32 and div32. Currently our div32 intrinsic is active.
If we look at a module that uses integer division, such as the bitWidth example, we will be able to see how the intrinsics are inserted into the VHDL code.
If we compile this module and look at the VHDL that was generated, we will notice that it uses our div32 intrinsic in place of the integer division operation in the C code.
Going back to the intrinsic list, we can activate our other 32-bit integer division intrinsic int_div32. This will also deactivate our div32.
Recompiling the bitWidth example and opening the VHDL, we can see that now that ROCCC instantiated an int_div32 core instead of the div32.
|<< Control Flow||Tutorials Home||Testbench Generation >>|