In EMTF, pattern recognition is done using a set of pre-defined patterns to detect muon trigger primitives from the 4 CSC stations that are consistent with the signatures of a muon. Initially, a set of 9 patterns were used. These patterns have different shapes which separate muons of different pT and charges. Each pattern is assigned a “straightness” code which is larger for a straighter pattern. Later (around Sept 2016), a smaller set of patterns have been adopted. This new set contains only 5 patterns and does not distinguish the muon charges. The original set of patterns is called “asymmetric”, while the new set is called “symmetric”. One can think of the symmetric patterns as the “OR” of the asymmetric patterns of the same straightness. They are illustrated below.

The second station (ME2) is referred to as the key station, which is like the center of the pattern. One unit represents a double-strip from a 10° CSC chamber (approx 0.5°).

### Asymmetric

Straightness Pattern
4
ME4
ME3
ME2
ME1
3
ME4
ME3
ME2
ME1
3+
ME4
ME3
ME2
ME1
2
ME4
ME3
ME2
ME1
2+
ME4
ME3
ME2
ME1
1
ME4
ME3
ME2
ME1
1+
ME4
ME3
ME2
ME1
0
ME4
ME3
ME2
ME1
0+
ME4
ME3
ME2
ME1

### Symmetric

Straightness Pattern
4
ME4
ME3
ME2
ME1
3
ME4
ME3
ME2
ME1
2
ME4
ME3
ME2
ME1
1
ME4
ME3
ME2
ME1
0
ME4
ME3
ME2
ME1

I’ve started working on a HLS project. Initially, I have heard a lot of good things about HLS, but now I’ve also started to realize some of its problems. This is an unfinished post, and it’s based on my personal experience as someone who is not an expert on FPGA programming.

Pros

• Provide a really good environment for co-development between firmware and software (including test bench).
• Provide the firmware emulation with bitwise accurate results. The emulation can be used outside of Vivado for a lot of studies.
• Allow non-FPGA engineers to collaborate on the algorithm development. This helps physicists to take over some work load, which is useful for projects where the num of physicsts >> num of engineers.
• Facilitate interfacing with C++ and Python. Xilinx has started providing first-class HLS libraries (e.g. Vitis Libraries) to interact with its FPGAs. This helps lowering the barrier to adopt FPGAs.

Cons

• The output Verilog code generated by the Vivado HLS tool is not human readable.
• Due to the above, it’s very hard to figure out how to optimize the algorithm. Maybe an experienced FPGA engineer could do that, but it’s really difficult for me. I have no idea how should I structure a particular for loop, or which pragma directive should I use, or whether a function should be inlined, etc in order to achieve the results that I want, since I couldn’t understand the translation process.
• The Vivado HLS tool is way too slow. It takes several hours (sometimes >3 hours) to compile my codes after a single change.
• A lot of configurations need to be passed as compile-time arguments (e.g. loop bounds), rendering the C++ codes also kind of unreadable. In C++11 (the standard supported by the Vivado HLS tool), the use of constexpr is very restrictive.

If you happen to look into the TensorFlow source codes, you might find functions that belong to gen_math_ops which is imported via:

from tensorflow.python.ops import gen_math_ops


But gen_math_ops.py does not actually exist in the TensorFlow GitHub repo. This is because gen_math_ops.py (or gen_nn_ops.py etc) is generated automatically, thus not included in the repo. But in your local installation, you may find it in <tensorflow-path>/python/ops/gen_math_ops.py, where <tensorflow-path> is the path of tensorflow.__file__. The functions in this automatically generated python code are usually wrappers of the corresponding C++ functions. So if you are interested in understanding how the functions are coded, you won’t find anything useful in here, but must go look at the corresponding C++ functions.

GitHub user lucidBrot has made a nice and concise list of useful GitHub emoji. This is a copy of that with some of my own additions.

meaning emoji text
info :information_source:
note :memo:
warning :warning:
tip :penguin:
hint :bulb:
pro :heavy_plus_sign:
con :heavy_minus_sign:
error :x:
correct :heavy_check_mark:
question :question:
resolved question :grey_question:
important :heavy_exclamation_mark:
wip :construction:
bug :bug:
careful :eyes:
heart :heart:
+1 :+1:
-1 :-1:
well done :tada:

Xilinx provides an arbitrary precision (AP) data types library for use in Vivado HLS projects:

It allows the specification of any number of bits for data types, beyond what is provided by the standard C++ data types:

• char (8-bit integer)
• short (16-bit integer)
• int (32-bit integer)
• long (32-bit integer)
• long long (64-bit integer)

The number of bits of the data types can affect the resource usage. For instance, a DSP48 multiplier is 18-bit. If the data width is more than 18 bits, multiple DSP48s are required. Examples of how to define arbitrary precision integers:

• ap_int<5> (5-bit signed integer)
• ap_uint<65> (65-bit unsigned integer)

The library also supports fixed-point data types. Examples of how to define them (the two template arguments denote the total num of bits and the num of integer bits; the difference being the num of fractional bits):

• ap_fixed<11, 6> (11-bit signed word, 6 integer bits, 5 fractional bits)
• ap_ufixed<12, 11> (12-bit unsigned word, 11 integer bits, 1 fractional bit)

The bit widths can be accessed at compile time by ap_[u]int<W>::width and by ap_[u]fixed<W,I>::width and ap_[u]fixed<W,I>::iwidth.

When assigning a value from a narrower word to a wider one, the value is sign-extended if the source variable is signed; the value is zero-extended if the source variable is unsigned. When assigning a value from a wider word to a narrower one, the bits beyond the most significant bit (MSB) of the destination variable are truncated. It doesn’t matter if the destination variable is signed or unsigned.

In addition, the library also provides useful bit manipulation methods such as:

• length() returns the number of bits.
• sign() returns true if negative; false if positive.
• operator [] (int bit) returns the specified bit. The least significant bit (LSB) has index 0, the most significant bit (MSB) has index W - 1.
• range(unsigned Hi, unsigned Lo) or operator () (unsigned Hi, unsigned Lo) returns the value represented by the specified range of bits. If Hi has a value less than Lo, the bits are returned in reverse order.
• test(unsigned i) returns true if the specified bit is 1; false otherwise.
• set(unsigned i, bool v) sets the specified bit to the boolean value.
• set(unsigned i) sets the specified bit to the value 1.
• clear(unsigned i) sets the specified bit to the value 0.
• invert(unsigned i) inverts/toggles the specified bit.

(all of the above work for ap_[u]int types but not necessarily for ap_[u]fixed types).

The full reference guide for how to use the AP data types is provided at: