MASC/Elastic System
Contents
Elastic System Tutorial
This tutorial is to demonstrate how to create an Elastic System design using the default MASC synthesis flow. The first you need, if you're not yet, is to familiarize with the concept of Elastic System, the following papers should give a good introduction to the topic SELF, LI_BDN and LIDs.
There is one important difference between the approaches in these papers and the approach we use in the lab. The previous approaches have an automated flow that convert regular synchronous RTL code into elastic systems. This leads to some limitations in the types of transformations that are possible in the circuits. In the approach adopted at MASC, we require the designer to explicit write RTL using the elastic syntax. For that, we provide a custom implementation of the elastic buffer, that must be declared in the RTL code. Also, the handshake signals have to be generated by the designer.
Once you know enough about the concept of Elastic Systems, you need to get access to the RTL repo of the MASC lab (mascrtl), check instructions GIT_Repository. In the remainder of this tutorial, <mascrtl> will indicate directory to which the repository was checked-out. Thus, <mascrtl>/code indicates the directory code inside the mascrtl repository, and so forth.
Glossary
A couple of remarks that may be useful for mapping the contents of the papers into the vocabulary used here.
- Elastic Systems, Latency Insensitive and Synchronous with Handshakes: different names used in the literature, indicate the same thing (or almost the same thing).
- Valid and Stop signals are the handshakes signals used in the papers. LI-BDNs uses queue operations intead (enqueue, dequeue, empty and full. Although our papers also use valid/stop, in our verilog the names used are valid and retry.
- Elastic buffers are called stages in our verilog, but are essentially the same thing.
Methodology
The tutorial starts by presenting a simple circuit, to get the reader familiarized with the flow and the behavior and testing of elastic. We will call this circuit "Hello, Elastic". It consists of a simple buffer that returns '0' if the input is odd, and returns the input divided by two if it is even. A testbench will also be generated to verify the functionality. Then, we are going to create an elastic multiplier, with the relevant testbench. The topology used for the multiplier is the so-called shift-adder, which takes an arbitrary number of cycles to complete.
There are some useful pages about how different parts of the MASC RTL flow works. The page Synthesis Setup explain at the high level how to synthesize the circuit and what the options are. For information about the XML file that defines the project, refer to ATC.
Hello Elastic
Creating an RTL project template
We will start by creating a project template. To do that, go to <mascrtl>/code and type:
rake
This will dump some options on the screen. We want to create a project named 'hello, so type:
rake new name=hello elastic=1 gen_test=1
This will create the following file structure under <mascrtl>/code/hello/
--rtl/ --hello.v --tests/ --hello_tb.cpp --hello.xml
Those files contain the basic structure that you need to get started with your project. Now, you need to create the remaining of the test infrastructure:
cd hello/ rake test:all grid=1
The command will fail, but some files were added to the tests directory. From now on, we refer to the directory <mascrtl>/code/hello as <projectDir>.
Coding
Now, let's start coding our first elastic RTL module. This will be a simple module that checks the parity of the input, and return 0 if the input is odd, and the input divided by two if it is even.
First, let's write the code for our elastic module. Edit the file <projectDir>/rtl/hello.v. Change the types of dataIn, dataOut and dataOut_next to SampleDataType (which is a 32-bit type). Your file will look something like:
,input SampleDataType dataIn // ... ,output SampleDataType dataOut
// ...
SampleDataType dataOut_next; //note that wire needs to get removed
Also, change the stage size to 32 towards the end of the file. Now let's add some logic to the module, instead of:
assign dataOut_next = dataIn;
We want to assign 0 if dataIn is odd, or dataIn shifted to the right if dataIn is even.
TestBench
Now that we have changed the verilog file, we need to regenerate the top of our testbench so it reflects the new types of the IO. In <projDir>, run:
rake test:all grid=1
Then, edit the file <projectDir>/tests/hello_tb.cpp. Look for the gold_implementation function, you need to provide a golden implementation, ie. an implementation you know it is right. It should look like:
uint32_t gold_implementation(uint32_t input) { if(input%2 == 0) { return input/2; } else { return 0; } }
Now go to the function hello_tb_set(), that sets inputs to the design. Around line 143, you will see:
uint32 data = rand()%2; sent_packs[num_ops] = data; //... dut->dataIn = data;
The first line is getting a random number to be used. It is then saved on sent_packs and sent to the design through dut->dataIn. Change the first line so numbers up to 1000 can be sent. The function hello_tb_check() will read the outputs and compare them to the golden implementation, you don't need to change anything there.
You are now ready to run the test. In the directory <projDir>/test you will find a .sh file. Just run it and you should see the simulation results shortly.
Multiplier
(Explain arithmetically how the multiplier works).