Fourth week of internship.
As Dr Shawn advised me to modify the repository, I had to study the code carefully so that I could be able to generate a correct top level verilog file for synthesis. To do so, it was crucial to understand std::map, as most of the important information was stored in a map.
Std::map was an associative container to store elements, i.e. key-value pairs. A simple example would be std::map<int, int> map, where the map stored key-value pairs with type int. Some common basic functions included begin(), end(), size(), erase() and clear(). To access the values of the key-value pairs, a std::map<int, int>::iterator was instantiated and it would increment from the first key-value pair, map.begin(), to the last, map.end(). In addition, itr->first and itr->second were used to access the key and the value respectively. However, it became tricky when a more complicated map was instantiated, such as std::map<std::string, std::vector<std::string>> map. A double for loop could be created to access all the elements stored inside this map.
for (itr = map.begin(); itr != map.end(); itr++) {
for (int i = 0; i < itr->second.size(), i++) {
cout << itr->first << ‘\t’ << itr->second[i] << ‘\n’;
}
}
Furthermore, I did some experiments with cereal, a C++11 library for serialization. It could take many data types and produce different outputs, such as XML, JSON and binary encodings. It was fast and easy to implement and it worked in tandem with std::ofstream. An example was shown below.
std::ofstream file_xml(“simple.xml”);
std::ofstream file_json(“simple.json”);
cereal::XMLOutputArchive archive_xml(file_xml);
cereal::XMLOutputArchive archive_json(file_json);
…
archive_xml(CEREAL_NVP(map));
archive_json(CEREAL_NVP(map));
Moreover, I put in some effort to read up on std::stringstream, regular expressions library and Block RAMs.
Stringstream was a powerful tool that allowed a string object to be considered as a stream, and hence it could extract values from strings. This was particularly useful to convert between strings and integers. A stringstream was demonstrated below.
stringstream ss;
ss << 1 << ” “<< “Hello”;
ss >> num >> str;
Regular expressions library (regex) defined a search pattern and was mainly used to find a pattern within strings. Target sequence, pattern, matched array and replacement strings were often used as parameters by regex. In addition, common functions used in regex included regex_match(), regex_search() and regex replace(). An example of regex object was ([A-Za-z0-9-]+), which would search for letters, numbers and hyphens.
A Block RAM (BRAM) was a discrete part of FPGA, and it had width and depth. Most of the BRAMs could be initialized to a non-zero value. There were also different configurations for BRAMs, such as single port, dual port and FIFO. In AESTE, a dual port BRAM was used. BRAMs were very capable of storing a large amount of data, such as Look-Up Tables and Read-Only Data.
According to Lattice iCE40 Memory Usage Guide, a BRAM could be instantiated as below.
SB_RAM256x16 ram256x16_inst (
.RDATA(RDATA_c[15:0]),
.RADDR(RADDR_c[7:0]),
.RCLK(RCLK_c),
.RCLKE(RCLKE_c),
.RE(RE_c),
.WADDR(WADDR_c[7:0]),
.WCLK(WCLK_c),
.WCLKE(WCLKE_c),
.WDATA(WDATA_c[15:0]),
.WE(WE_c),
.MASK(MASK_c[15:0])
);
All in all, it was a productive week and I managed to generate a top level verilog file with CPU32 being automatically instantiated.
0 Comments