{'fraction_non_alphanumeric': 0.03694482370893904, 'fraction_numerical': 0.022106658099751025, 'mean_word_length': 4.5561133422579205, 'pattern_counts': {'":': 0, '<': 0, '<?xml version=': 0, '>': 0, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
The Accuracy and Efficiency of Posit Arithmetic

Motivated by the increasing interest in the posit numeric format, in this paper we evaluate the accuracy and efficiency of posit arithmetic in contrast to the traditional IEEE 754 32-bit floating-point (FP32) arithmetic. We first design and implement a Posit Arithmetic Unit (PAU), called POSAR, with flexible bit-sized arithmetic suitable for applications that can trade accuracy for savings in chip area. Next, we analyze the accuracy and efficiency of POSAR with a series of benchmarks including mathematical computations, ML kernels, NAS Parallel Benchmarks (NPB), and Cifar-10 CNN. This analysis is done on our implementation of POSAR integrated into a RISC-V Rocket Chip core in comparison with the IEEE 754-based Floting Point Unit (FPU) of Rocket Chip. Our analysis shows that POSAR can outperform the FPU, but the results are not spectacular. For NPB, 32-bit posit achieves better accuracy than FP32 and improves the execution by up to 2%. However, POSAR with 32-bit posit needs 30% more FPGA resources compared to the FPU. For classic ML algorithms, we find that 8-bit posits are not suitable to replace FP32 because they exhibit low accuracy leading to wrong results. Instead, 16-bit posit offers the best option in terms of accuracy and efficiency. For example, 16-bit posit achieves the same Top-1 accuracy as FP32 on a Cifar-10 CNN with a speedup of 18%.


I. INTRODUCTION
With the tremendous interest in Machine Learning (ML) which sparked new use cases and business opportunities, companies are deploying Artificial Intelligence (AI) models in users' devices, at the edge of the Internet. Typical architectures used by these edge devices include ARM CPU cores integrated with a Digital Signal Processor (DSP) and a Graphics Processing Unit (GPU) to increase the performance of AI applications. In general, GPUs are more timeenergy efficient compared to CPUs when running ML applications, both during the training and inference phases [9]. But a recent study by Facebook [43], shows that only 20% of the smartphone SoCs have accelerators that are significantly more efficient than the CPU. In addition, it is more tedious to program accelerators compared to CPUs, due to different architecture, programming model and, sometimes, due to the immaturity of the Software Development Kit (SDK). Hence, it is important to optimize CPU inference performance on mobile edge devices.
ML computations take place in two different stages, namely (i) at model training when an ML model is built using huge datasets, and (ii) at inference when a new sample or small dataset is processed by a trained model. Traditionally, ML training is done on powerful accelerators, such as GPUs or Tensor Flow Units (TPUs) [27]. To achieve high accuracy, ML models increasingly use large numbers of parameters and, at runtime, they induce a huge number of arithmetical operations. For example, VGG-16 [37] from 2015 has approximately 138 million parameters and 15,300 million multiply-add operations [21], [37], while some current submissions for ImageNet classification have one billion parameters. This level of complexity is inappropriate for real-time applications, especially when the inference is running on edge devices.
To address the complexity of ML inference, researchers have explored both model pruning and lower bit representations for the parameters. Recent studies [26], [7] show that new floating-point representations are more energy-efficient compared to the IEEE 754 floating-point standard implemented by all modern hardware processing units, including CPUs and GPUs. IEEE 754 hardware implementations use significant chip area and power because they need to handle many corner cases and exceptions described by the standard. Some studies show that that this standard is error-prone [18] and its different implementations may produce different results [42].
Among the alternatives to IEEE 754, unum [18] and its third version, named posit [19], [35], were introduced by Gustafson to solve some of the issues of IEEE 754 floating-point representation. Compared to IEEE 754, posit has variable length fields to represent the exponent and the fraction of a real number. Hence, posits can represent small numbers more accurately by reserving more bits for the fraction and fewer bits for the exponent. Moreover, posits have only two special representations, namely for 0 and not-a-real (N aR), whereas IEEE 754 reserves many binary representations for not-a-number (N aN ). This feature, together with the non-existence of subnormal make posit implementations simpler. In this paper, we address the following research questions, (i) are posits more efficient than IEEE 754 for ML inferencing at the edge? (ii) what is a good trade-off between accuracy and time-energy efficiency when employing lower bit size posits?
To answer these questions, we propose an alternative hardwaresoftware approach for efficient ML inference at the edge by (i) designing and implementing an Elastic Posit Arithmetic Unit (POSAR) in a Rocket Chip-based [2] RISC-V core replacing its IEEE 754 floatingpoint unit (FPU), and (ii) modifying existing software to run on this system. RISC-V [40] is an open-source architecture with limited available hardware implementations. However, it is very promising due to its energy efficiency and modular ISA, thus, it is timely to explore this new CPU architecture for ML inference at the edge. Without modifying the ISA, we use the F extension of the RISC-V specification [41] but change the internal processor representation of floating-point numbers to posit. To address the challenge of executing the same application software on the modified hardware, we make minor high-level code changes and convert IEEE 754 constants to posit.
To evaluate the POSAR, we use three application levels and compare their accuracy, execution time, and power consumed on an FPGA implementation. In addition, we compare the resource utilization of POSAR on the FPGA. Among the three application levels, the first consists of computing the values of well-known mathematical constants, such as π and e for testing accuracy over a large number of operations. The second level represents kernels frequently used in ML applications, such as matrix multiplication, k-means, and linear regression, among others. The third level is a Convolutional Neural Network (CNN) running on Cifar-10 dataset.
Among the existing posit hardware implementations [8], [22], [23], [34], [24], most are accelerators, co-processors or stand-alone units. The closest work to ours is PERI [39], which designs a PAU for the RISC-V core SHAKTI implemented in Bluespec System Verilog for 32-bit posits. However, PERI is evaluated only on 32bit posits with two exponent sizes while running image processing, FFT, trigonometric functions, and K-means. In contrast, our proposed approach is elastic as it can be adapted to different posit sizes. In this paper we have evaluated POSAR on three posit sizes of 8, 16, and 32 bits. To the best of our knowledge, we are the first to (i) implement an POSAR in the Chisel language (a dialect of Scala) and integrate it into a Rocket Chip core, and (ii) evaluate a posit-enabled Rocket Chip system on an FPGA. In addition, we release the code associated with our project and the documentation as open-source to aid future research in this area 1 .
In summary, we make the following contributions: • We implement an Elastic Posit Arithmetic Unit (POSAR) in the Chisel language to replace the traditional Floating Point Unit (FPU) in a Rocket Chip RISC-V core. In addition, we implement a Scala library for posit arithmetic to test our POSAR.
• Our POSAR supports any posit size and exponent size, but in this paper we instantiate it for three sizes: 8, 16, and 32 bits, respectively. We test these instantiations in both simulation mode and on an Arty A7-100T FPGA.
• Our evaluation shows that POSAR with 32-bit posit achieves the same accuracy as the original FPU of Rocket Chip with 32bit IEEE 754 floating-point. POSAR is logging fewer cycles, but uses more FPGA resources and consumes more power. However, our energy measurements on the FPGA running a loop of two million iterations that computes π show that 32-bit posit uses only 6% more energy while being 30% faster compared to 32-bit IEEE 754 float.
• We show that 8-bit posit is not suitable to replace 32-bit IEEE 754 float in scientific and classic ML applications due to low accuracy. On the other hand, 16-bit posit offers the best option in terms of accuracy and efficiency. For example, 16-bit posit achieves the same Top-1 accuracy as 32-bit IEEE 754 singleprecision format on a Cifar-10 CNN with a speedup of 18%. Moreover, a hybrid approach where 8-bit posit is used to store parameters in memory and a 16-bit posit POSAR is used for computations leads to no loss of accuracy on the Cifar-10 CNN. In the next section, we provide details on ML complexity, posit and RISC-V. In Section III we summarize related works. In Section IV we present the design of our POSAR and discuss the challenges of enabling existing applications to run on it. In Section V we evaluate our approach before concluding in Section VI.

A. Machine Learning Complexity
As previously stated, ML applications are becoming increasingly complex from the point of view of parameters and runtime operations. One way to address this issue is pruning which aims to reduce the depth and complexity of a neural network. Howard et al. [21] propose the usage of depth-wise and point-wise convolutions instead of full convolution to reduce the number of parameters by 32 times and the number of operation by 27 times in comparison with the original VGG-16 while achieving nearly the same accuracy. Another approach is knowledge distillation [32] where a smaller network is trained with a larger network in a teacher-student style. This method achieves better accuracy than the case where the small network is trained alone. A third approach is quantization [30] which replaces floating-point arithmetic with other numeric representations, such as fixed-point, to reduce the number of bits and the cost of operations in terms of latency.
The quantization approach uses different types of numerical representations, such as binary, ternary, integer, fixed-point, small-size floating-point, and posit [19]. Depending on its usage, quantization can be classified into storage or computing. The storage quantization tackles the problem of memory usage by adopting a lower bit representation in memory for integers, fixed-point [36], floating-point and posit numbers [29]. But before performing the operations, these lower bit representations are converted to full-size floating-point. This method degrades accuracy and increases latency. To address this issue, Langroudi et al. [29] proposed using different bit sizes per ML network layer. This method decreases memory utilization by as much as 94% while degrading the accuracy by only 1%. This is a good solution for saving storage but it may increase design complexity.
Carmichael et al. [7] analyze fixed-point, floating-point and posit representations on DNN showing that posit offers the best accuracy while exhibiting a smaller latency compared to floats. In this paper, we aim to explore deeper the suitability of using posit for ML inference. Specifically, we evaluate three different posit sizes to determine which one offers the best accuracy-efficiency trade-off.

B. Posit
Posit [35] is a real number representation that aims to improve the widely-used IEEE 754 floating-point standard implemented by the majority of modern processors. A 32-bit, single-precision floatingpoint in IEEE 754 comprises three fields, as shown in Figure 1 (top), namely (i) a sign field of 1 bit, (ii) an exponent field of 8 bits and (iii) a fraction or mantissa field of 23 bits. In contrast to IEEE 754 which reserves many binary representations for the special number N aN , posit format has only two special numbers, 0 and N aR (nota-real). If the binary representation of the posit has all the bits equal to zero, except the first bit from the left which represents the sign, then it is a special number. If the sign bit is 0 then the special posit has the value 0, otherwise it represents the posit N aR, as shown in Table I for 8-bit posit. Compared to IEEE 754, posit representation comprises an additional field named regime which determines the final exponent value together with the exponent field, as shown in Figure 1 (bottom). In posit, the regime and fraction fields are variable, while the exponent field is customizable. In fact, a posit format can be described only by its total size, ps, and its exponent size, es.
In a posit, the regime field follows the 1-bit sign and continues as long as the bits have the same value ri, followed by a bit of opposed value. The number of regime bits of the same value, rn, is used to determine the value k as shown in Equation 1. k is a factor that multiplies the maximum value of the exponent field, 2 es , to which the actual value of the exponent field, e, is added to determine the final exponent (k · 2 es + e). This feature of elastic exponent field allows a larger fraction field, hence, a higher representation accuracy compared to the fixed 23-bit mantissa of the IEEE 754 format. However, this higher accuracy occurs only in a range called the "golden zone" [12] which can be useful in scientific applications.
To improve the rounding error and to abide by mathematical properties such as associativity and distributivity, the posit standard  introduces a quire [35] which is a long accumulator [12]. However, the implementation of a quire uses 10 times more area and increases the latency by 8 times compared to posit without quire [12]. For example, an implementation of an unum type co-processor in SMURF [4] for a RISC-V Rocket-Chip uses 9 times more area and consumes 12 times more energy than the 64-bit FPU of the Rocket-Chip. Thus, in this paper, we decided not to implement a quire in our POSAR.

C. RISC-V and Elastic ISA
RISC-V is a Reduced Instruction Set Computer (RISC) instruction set architecture (ISA) that is open-source and designed in a modular way that permits adding new extensions [40]. A RISC-V processor design must start with a base ISA module, such as 32-or 64-bit integer operations to which other modules can be added. For example, single-and double-precision floating-point extensions, denoted by letters F and D, respectively, can be added to a processor to support floating-point arithmetic. There is a multitude of open-source implementations of RISC-V architecture, some of which are documented on the GitHub page maintained by the RISC-V community [17].
Recently, even commercial architecture companies, like ARM, have opened up their architectures for customized extensions by partners and have added custom instructions to their ISA [1]. These developments in the industry are in line with the research moving towards "elastic ISA". Such an elastic ISA provides the core set of instructions for a domain-specific application such that the processor's hardware units are efficiently utilized in order to achieve minimal energy usage for a given execution time performance target. This is directly applicable in the field of ML due to the fast pace of development of algorithms versus the pace of available hardware catering to the throughput and power demands of inference at the edge [44]. The POSAR proposed in this work helps bridge this gap between algorithms and hardware as the elasticity in its compute engine lends itself easily to advances in ML algorithms in the area of changing arithmetic representations.

III. RELATED WORKS
Posit Implementations in Hardware. The closest work to ours is PERI, a posit-enabled RISC-V core presented in a preprint [39]. Similar to our work, PERI implements a posit unit capable of executing RISC-V F extension instructions, presents a similar way to run existing floating-point programs on the posit-enabled processor, and evaluates the processor on an Arty A7-100T FPGA. However, we implement our project in the Chisel language to integrate it with the Rocket Chip core, while PERI uses Bluespec System Verilog and integrates the unit into the SHAKTI core [15]. PERI uses two posit formats at the same time. Both are 32-bit in size, with one having es = 2 and the other es = 3. To switch between these two formats, PERI introduces a new instruction, F CV T.ES. In contrast, our POSAR supports multiple bit-sized posits but uses only one size at a time to keep full compatibility with existing software. We evaluate 8-and 16-bit posits in addition to 32-bit posits in this paper. In terms of benchmarking, both PERI and we use k-means, along with the computation of sin(x) and e. We evaluate pi computation, matrix multiplication, k nearest neighbors, naive Bayes, and support vector machine, while PERI is evaluated on JPEG image processing and fast Fourier transform.
Posit in Machine Learning. Some works analyze the suitability of using posits in ML applications [6], [7], [14], [26]. [7] and [6] present Deep Positron, an Deep Neural Network (DNN) accelerator that can run on FPGAs, and claim that 8-bit posits can achieve better inference accuracy than 8-bit floats and integers, while being close to the accuracy of 32-bit IEEE 754 floats. In contrast, we find that 8-bit posits almost always produce inaccurate results when compared to both 32-bit posits and IEEE 754 floats. However, we acknowledge that we use Cifar-10 dataset for the ML application, whereas Deep Positron uses medical low-dimensionality datasets. Johnson [26] evaluates multiple numeric formats, including posit, to replace IEEE 754 floats in DNNs. Among others, the author shows that 8-bit posits with 1-bit exponents can achieve similar Top-1 accuracy on a Resnet50 model compared to classic 32-bit floats. In [14], posits are used to store ML parameters in memory, being converted to classic IEEE 754 floats when computations are performed. The authors claim that posits of smaller size can represent the parameters compared to bigger sized IEEE 754 floats, and hence, save up to 36% of memory space while less than 1% accuracy loss is exhibited. In contrast, we show that frequent conversions between posit and IEEE 754 formats can lead to significant accuracy degradation and discuss this in detail in Section IV-B.
Posit in Scientific Computing. In [10], the authors evaluate the impact of posit on NPB benchmarks using software emulation. As expected, the emulation leads to a much higher execution time of the program using posit compared to the IEEE 754 format running natively on the hardware. However, the accuracy of 32-bit posit is higher compared to FP32. In [19], the authors show using highlevel emulation that 32-bit posit can achieve better accuracy and (potentially) faster execution compared to the IEEE 754 format on the LINPACK benchmark. In contrast, we use a hardware-based approach to better understand the impact of posit on cycle-efficiency, not only on accuracy.

IV. POSAR: DESIGN AND IMPLEMENTATION
In this section, we describe the implementation of POSAR and the high-level design choices we made to run existing software on the system that integrates POSAR.

A. POSAR
In this section, we describe the implementation of POSAR, our Posit Arithmetic Unit. We wrote the high-level design code in the Chisel language and integrated it into a Rocket Chip tiny core to replace the original Floating Point Unit (FPU) than implements the IEEE 754 standard. Our POSAR is activated during the execution phase of the pipeline, as shown in Figure 2. In addition to supporting all the instructions of the F extension of RISC-V [41], our POSAR is elastic to cater to parameterized sizes for posit and exponent. Using this elastic feature, we evaluate POSAR on 8-, 16-, and 32bit posits (ps) with 1-, 2-, and 3-bit exponents (es), respectively. To verify our implementation, we wrote a posit arithmetic library in Scala and tested the POSAR Chisel code using unit testing. In this section, we discuss our internal posit representation, the instructions implemented, and the challenges of running programs on a positenabled processor.
Supported Instructions. POSAR supports all the instructions of the F extension of RISC-V [41]. For bitwise addition, subtraction, multiplication, and division we used the Chisel build-in operators. We acknowledge that this choice leaves some room for further optimizations. For testing the hardware implementation, we wrote a small library in Scala representing posit numbers and we used it inside unit tests. We hope this library will help others in trying different hardware implementations of posit operations.
Posit Representation. We use an internal posit representation comprising the sign s, the regime k and its size rs, the exponent e and its actual size in the binary representation, ers, the fraction f and its size f s, and one bit sn for the special numbers 0 and N aR. We decode a binary posit representation before performing an operation in the POSAR using Algorithm 1. We encode our internal representation into a binary representation at the end of the operation, using Algorithm 2. The notations used by the algorithms presented in this section are summarized in Table II.
In addition to making it easy to implement the arithmetic operations, this internal posit representation allows us to keep the additional bit resulted after applying different operations on the posit. In turn, this bit helps us perform better rounding when encoding the binary posit representation.
Decoder and Encoder. The posit decoder takes as input a binary representation, BP , the posit and exponent sizes, ps and es, respectively, and computes s, sn, k, rs, e, ers, f, f s, as shown in Algorithm 1. The algorithm verifies if BP represents one of the special numbers, 0 or N aR. In this case, we set sn and s. If BP is not a special number and s is set, it represents a negative number and we take its two's complement. Based on the first bit of the regime, ri, we compute rn and k. If ri is 0, all bits of the BP are negated, then reversed, and the result goes to a leading ones detector which computes rn. k is then computed based on Equation 1. If ri is 1, the same steps are applied, except that BP is not negated.
The posit encoder takes as input ps, es, s, sn, k, e, f, f s, bm and computes BP , as shown in Algorithm 2. Here, bm is a bit which is set when bits of value one are present in the extended fraction, after the first f s bit. This bit affects the final value of BP , as we  shall see below. If sn is set, BP is one of the special numbers 0 or N aR, depending on s. Otherwise, Algorithm 2 checks if the regime is greater or equal than the regime of the maximum possible value of a posit (2 ps−2 ) or smaller than the regime of the minimum value (2 2−ps ). In these cases, BP is rounded to the maximum or minimum possible value, respectively. Otherwise, the values of rn, rs, and nrs, which is the number of bits that do not represent regime bits, are computed and the regime bits are set. Using a buffer of size 3 · ps, the fraction is shifted left with 2 · ps − f s, then concatenated with the exponent and shifted with ps − es such that the most significant bit of the exponent is at index 3 · ps. We take the regime bits and this concatenation of exponent and fraction shifted with nrs and store them in BP . Next, Algorithm 2 rounds the posit to the nearest value using the tie to even rule. The first bit which could not be represented in the binary representation is stored in bn+1. All the bits after it are or-ed, and the value is stored in bm if there is a bit with value 1 after bn+1. Adder, Subtractor, Multiplier and Divider. The Posit Adder/-Subtractor presented in Algorithm 4 takes two posit numbers, P1 and P2, the operation op where 0 and 1 respectively represent add and subtract, and computes the result, P3. Before performing the actual operation, an auxiliary selector, PositAddSubSelector(), is used to set the actual operation, the order of the operands and the sign of the result. In particular, we ensure that the first operand is the one with the highest absolute value. The Adder/Subtractor checks for special cases first. If the operands are not special posits, it computes the result and sets the extra bit, P3.bm.
The Posit Multiplier and Divider, presented respectively in Algorithm 5 and Algorithm 6, take two posit numbers P1 and P2, and compute the result P3. Both algorithms check for special posits first, before continuing to the normal case.
The square root extraction (SQRT) is usually done in hardware using restoring, non-restoring [38], look-up table (LUT), or approximation [20]. We adapt a non-restoring algorithm from [33] because it has a lower delay compared to other approaches. We present our implementation in Algorithm 8 and the wrapper SQRT instruction in Algorithm 7. The wrapper function checks for special cases, such as values 0, N aR, and negative values. For the SQRT of a negative value, our implementation returns a N aR. Next, if the input is positive, the exponent and fraction size of the result are half those of the input. Hence, we use right-shift operations for halving and we check if the exponent and fraction sizes are odd. If they are odd (i.e., P1.e&1 is 1 and P1.f s&1 is 1), we multiply and divide, respectively, them by 2 and we reverse the operations on the fraction. That is, we divide the fraction by 1, 2, or 4, depending on the parity of the exponent and fraction size. Lastly, we use the non-restoring algorithm to extract the square root of the updated fraction value, which is a positive integer.
Algorithm 8 computes the square root Q and reminder R of an integer value D, such that D = Q 2 + R. The key idea is to advance at each iteration with two digits from D plus the reminder of the previous iteration and to compute the coresponding digit in Q. If the reminder is positive, the corresponding digit of Q is 1, otherwise it is 0. At the end, if the reminder is negative, we restore it to its previous positive value by adding (Q ≪ 2)|1.
Elasticity. We define elasticity as the capability of a hardware- software system to adapt its resources to the workload. In our case, elasticity means that POSAR uses the most suitable posit size for a given workload. Furthermore, elasticity could manifest offline, when the system is configured or implemented, or online, during workload execution. We leave online elasticity for future work and focus on offline elasticity in this paper. From the hardware's perspective, offline elasticity requires that our execution unit supports flexible posit size. Indeed, our POSAR supports any posit and exponent size. From the software's perspective, offline elasticity requires that we identify the minimum posit size that achieves the targeted accuracy or leads to correct results. Intuitively, identifying the range of the real numbers used during the execution of a given workload should be a necessary step in determining the most suitable posit size. However, we shall see in Section V-D that this is not always the case.

B. Software Support
On the software side, there is very limited support for the posit format. For example, the widely-used gcc compiler and the GNU C library do not support posits. Given this limitation, we devise two alternatives to execute programs with floating-point numbers on the POSAR without compiler support. The first alternative is to add a hardware conversion unit activated each time a floatingpoint value is loaded from and stored to the memory. In such an implementation, highlighted in Figure 2 under the Memory pipeline stage, the program, memory, and caches are working with IEEE 754 representations, while the core is working with posits. This is a flexible solution but it has two disadvantages due to frequent conversions, namely (i) low efficiency and (ii) low accuracy. We shall see below that the loss of accuracy is significant. The second alternative is to replace the IEEE 754 float representation with posit representation directly in the high-level code or in the binary. This alternative is less flexible but exhibits better efficiency. We use this second approach in our evaluation since it yields better results.
Next, we present an example to illustrate our second approach. This approach consists of loading different binary values in the floatingpoint constants, as shown in Listing 1 for Euler's number computation using numerical series. In this listing, all arithmetic operations are done with variables because immediate operands are generated in FP32 format by the compiler, in this case by riscv64-unknown-elf- Fig. 3: Loss of accuracy in Euler's number computation with frequent conversion between FP32 and Posit (32,3) gcc. Hence, any immediate operand in FP32 format breaks our posit implementation. Instead, we load the variables, which are memory locations, with FP32 or posit, in this case 32-bit posits with 3-bit exponents. This representation solves the challenge of not having compiler support for posits and allows us to use RISC-V extension F ISA. Moreover, the programming approach shown in Listing 1 results in generating near-identical assembly code for FP32 and posit, except for the values of the constants. These identical assembly footprints ensure a fair cycle-level comparison between FP32 and posit.
Impact of Runtime Conversion. Lastly, we present empirical evidence that the first alternative of converting between FP32 and posit at runtime, in the hardware, leads to loss of accuracy. Taking Euler's number computation as an example, shown in Listing 1, we emulate runtime conversion by encoding 32-bit IEEE 754 singleprecision floating-points (FP32) to 32-bit posits with 3-bit exponents (Posit(32,3)) before each iteration, and decoding Posit (32,3) to FP32 after each iteration. This represents the runtime behavior of having FP32 values in the memory, including cache, and Posit (32,3) values in the CPU's core registers. As shown in Figure 3, the loss of accuracy is drastic. With runtime conversions, only one digit of the fraction is accurate, i.e. e = 2.7, while directly loading into the memory and operating with Posit (32,3) leads to six accurate fraction digits, which is the same as the accuracy achieved by FP32. In the remainder of this paper, we are using the approach highlighted in Listing 1 since it leads to higher accuracy.

V. EVALUATION
In this section we evaluate and analyze our approach based on accuracy, efficiency, estimated area and power.

A. Setup
We compare the original 32-bit FPU of Rocket Chip which claims to implement the IEEE 754 standard (FP32) with our POSAR operating with posits of three bit widths, namely 8-bit with 1-bit exponent denoted by Posit(8,1) or P8, 16-bit with 2-bit exponent denoted by Posit (16,2) or P16, and 32-bit with 3-bit exponent denoted by Posit (32,3) or P32. We wrote the high-level code for POSAR in Chisel, integrated it with Rocket Chip [2], and used SiFive's Freedom E310 2 development platform to implement and synthesize our code to run on an Arty A7-100T FPGA. The original Rocket Chip with FPU and Rocket Chip with POSAR run at the same frequency.
Even if the Arty A7-100T FPGA represents the high-end of its family, it still exhibits a serious limitation in terms of available data memory which hinders the execution of full-fledged ML models. The 4,860 Kb (kilobits) block RAM of Arty A7-100T limits the data memory size of our Rocket Chip core to 512 kB (kilobytes). However, typical ML models have thousands or millions of weights which take several MB of memory. Even for the classic matrix multiplication, we can only run it on square matrices of size up to 182. In our future work, we plan to address this limitation by linking Rocket Chip to the 256 MB of RAM available on the Arty A7-100T. However, in this paper, we can only use a maximum of 512 kB of main memory.

B. Benchmarks
To evaluate our approach, we select benchmarks that use floatingpoint operations. We organize these benchmarks into three levels as follows. Level one benchmarks are used to evaluate both the accuracy and efficiency, in terms of cycles, of our POSAR versus the original IEEE 754 FPU of Rocket Chip. These benchmarks represent the computation of well-known mathematical constants using series and sequences. In particular, we compute the constants π and e (Euler's number), using numerical series, as shown in Table III. For π, we use Leibniz and Nilakantha series [11]. Since Leibniz series converges slowly, we run it for two million iterations. In contrast, Nilakantha series converges faster, thus, we run it for 200 iterations. For e, we use Euler's series which is fast-converging, thus, we run it for 20 iterations. In addition to π and e, we also compute sin(1) with 10 iterations.
Level two consists of kernels that are typically used in ML applications [31], as summarized in Table V. For these kernels, we evaluate the efficiency of our POSAR versus the FPU in terms of cycles. The correctness of the results is checked against reference outputs. Next, we briefly describe each kernel. Matrix Multiplication (MM) implements the multiplication of two square matrices which is often used in ML and HPC workloads. In our testbed, we can accommodate matrices of size up to n = 182. k-means (KM) groups a set of multi-dimensional points into k groups, or clusters, based on their Euclidean distance. KM is often used in ML and data analytics applications. k-nearest neighbors (KNN) classifies a multi-dimensional point based on the Euclidean distance to its k nearest neighbors. Linear Regression (LR) is a kernel used in ML and data analytics. We implement Multivariate Linear Regression which consists of matrix and vector operations. Naive Bayes (NB) implements a simple Bayesian model. The Classification (or Decision) Tree (CT) kernel is used in ML and data analytics to represent a target variable based on some input attributes. We implement both the creation (training) and usage (inference) of CT. We use Iris dataset 3 as input for level two benchmarks, except MM. This dataset consists of n = 150 data points with m = 4 dimensions representing flowers. These points belong to k = 3 classes.
Level three is represented by one NAS Parallel Benchmark (NPB) [3] scientific application and one Convolutional Neural Network (CNN) ML inference application. Specifically, we selected Block Tri-diagonal (BT) solver from NPB and we converted all floating-point variables to 32-bit float. We use the verification threshold error, epsilon (ǫ), as a measure of accuracy. That is, a smaller ǫ corresponds to a higher accuracy. Next, we use a Convolutional Neural Network (CNN) implemented in Caffe [25] and trained on Cifar-10 4 dataset, as depicted in Figure 4. This CNN has 14 layers and the parameters file has a size of 351 kB. However, we cannot accommodate this model on our testbed with limited memory size. Hence, we take only the last four layers of this CNN, starting from relu3 as shown in Figure 4, and generate standard C code with static memory allocations in order to run it on the bare-metal SiFive's Freedom E310. By instrumenting the Caffe framework, we collect all the parameters and the input of relu3 layer as binary files with FP32 values. We then convert these binaries to all three posit sizes, namely P8, P16, and P32, transform them into objects and link them with the generated C code to get the final RISC-V executable, as shown in Figure 4. We then run the validation on all 10,000 images of Cifar-10 test dataset by running the executables on the Arty A7-100T FPGA. The prediction results are compared against the reference execution on an x86/64 host.

C. Accuracy and Efficiency
Level One. We evaluate the accuracy and efficiency of posit in comparison with 32-bit, single-precision IEEE 754 floating-point (FP32), using level one benchmarks summarized in Table III and  Table IV. The accuracy is measured in terms of exact fraction digits compared to the reference value of the mathematical constant. The efficiency represents the number of cycles taken by Rocket Chip running on the FPGA to execute the meaningful section of the program. For posits, we compute the speedup with respect to the FP32 execution. We note that we use 64-bit, double-precision IEEE 754 floating-point in our evaluation scripts. This is because any posit can be accurately represented by an IEEE 754 float of bigger size [12].
The results presented in Table III show that Posit(32,3) achieves similar or better accuracy compared to FP32. Moreover, Posit (32,3) achieves a speedup of 1.3 compared to FP32 FPU, when π with Leibniz series is computed, as shown in Table IV. The accuracy of small posit representations, such as Posit (8,1), is low when estimating Fig. 5: Accuracy and efficiency of Euler's number computation using FP32 and Posit (32,3) numerical series. This is expected if we consider the internals of posit representation. Taking e = 2.7182 . . . as example, we first observe that the closest Posit (8,1) numbers are 2.625 (0x55) and 2.75 (0x56). That is, one cannot get better accuracy for e than these two values. Second, Euler series leads to an issue regarding the storage in Posit (8,1) of the factorial which grows very fast. The maximum value that a Posit (8,1) can represent is 192, which is less than 6!. Hence, the accuracy of Euler's series becomes worst when the number of iterations grows. For example, when N = 4, we get e = 2.75, but when N = 6 we get e = 3.
Posit operations take fewer cycles to complete, thus, applications with higher numbers of iterations exhibit better efficiency. For example, Posit (32,3) is 30%, 9%, and 3% faster than FP32 for π Leibniz with two million iterations, π Nilakantha with 200 iterations, and e with 20 iterations, respectively. Our analysis revealed that this speedup is the result of faster multiplication and division operations on posits. This, in turn, is the result of simpler exception and corner case handling in posits. Intuitively, the gap in efficiency grows with the number of iterations. Figure 5 shows that Posit (32,3) achieves the same accuracy as FP32 with fewer cycles as the number of iterations increases.
Level Two. We observe that Posit (32,3) and Posit (16,2) lead to the same final results as FP32 when running level two benchmarks while saving up to 6% of the cycles, as shown in Table V. However, LR with Posit (8,1) and Posit (16,2) exhibits wrong results. In turn, the final results are affected by the wrong value of one of the determinants computed by the program. In fact, all the programs operating with Posit(8,1) produce wrong results, except CT. This shows that small size posits are not suitable for some classic ML kernels that need high numerical accuracy. This observation is in contrast to some of the related works [26], [6], [7]. However, we note that our evaluation is done on a different dataset, namely the Iris dataset. We shall see below that Posit (8,1) performs better on a partial CNN. On the other hand, Posit (16,2) offers a good alternative to 32-bit floating-point representations.
Level Three. For the NPB application, Posit (32,3) achieves one level of magnitude higher accuracy than FP32. For example, setting ǫ = 10 −4 in BT leads to successful validation when Posit (32,3) is used. On the other hand, FP32 needs ǫ = 10 −3 in BT to pass the validation. Moreover, Posit(32,3) exhibits a marginal speedup compared to FP32. These results are in correlation to those of level one benchmarks. Since there are more and diverse floating-point operations in BT compared to level one benchmarks, the accuracy gain of Posit (32,3) is more visible. On the other hand, the speedup gain is not spectacular because the fraction of operations where posit is faster than IEEE 754 is smaller. For the same reason of very large number of operations in BT, Posit (8,1) and Posit (16,2) do not exhibit good accuracy. In fact, Posit (8,1) cannot even represent accurately all the validation reference values due to its limitted range. For example, the validation reference value 7.38e − 5 of BT cannot be represented by Posit (8,1) because its range stops at 2.44e − 4 (0x1).
When compared to the reference execution on an x86/64 host, the Cifar-10 CNN in Figure 4 with FP32, Posit (32,3) and Posit (16,2) running on our FPGA with a Rocket Chip core exhibit the same Top-1 accuracy as the reference model, namely 68.15%. Even Posit(8,1) achieves a reasonable accuracy of 62.68%. In terms of speed, all three posit representations are around 18% faster compared to the execution with FP32. The results with Posit (16,2) and Posit (8,1) are very promising and open-up a series of future optimizations. For example, these formats save respectively half and three-quarters of the memory for representing inputs and parameters compared to 32bit FP32 or Posit (32,3). Next, by packing two Posit (16,2) and four Posit (8,1) operands per instruction, we can reduce the execution time by two and four times, respectively.
We observe that one reason why Posit(8,1) exhibits accuracy loss is due to the out-of-range representation of some parameters or input image pixels. There is at least one out-of-range representation for each of the 10,000 input images of the Cifar-10 test dataset. This is in contrast to Posit (32,3) and Posit (16,2) which can represent these parameters without loss of accuracy. For example, the minimum positive value of the weights of ip1 layer is 0.000001119 which cannot be represented by Posit (8,1). The closest posit size that can represent this value relatively accurate is Posit (15,2) with 0.0000011176 (0x10b). We note that scaling cannot be applied for Posit (8,1) because of the wide parameter distribution interval, that is, the minimum positive value is 0.000001119 and the maximum one is 87.84.
Another source of accuracy loss is due to underflow or overflow at runtime. For example, prob layer includes exponentiation, among other operations. On Posit (8,1), exponentiation can easily result in underflow or overflow. To test this hypothesis, we keep the parameters in 8-bit posit format in memory but we employ the POSAR with Posit (16,2) and convert between these two formats at runtime. The result is better than expected because the Top-1 accuracy of this approach is 68.47%, a bit higher than the accuracy of the reference execution on FP32. This result confirms our hypothesis that the main source of inaccuracy of Posit (8,1) is at runtime and shows that using a hybrid approach with posits of different size can save memory without losing accuracy.

D. Dynamic Range and Elasticity
To help developers analyze the floating-point values used during the execution of a program, we implemented an instrumentation tool based on DynamoRIO [5]. This tool takes a binary and inspects the registers and memory locations involved in FP32 instructions. This instrumentation does not require high-level code changes and can be done on an x86/64 host. At the moment, we cannot perform this analysis directly on the RISC-V ISA since DynamoRIO does not support it yet.
Using this tool, we determine the absolute minimum value in the interval (0, 1] and the absolute maximum value in the interval [1, ∞). These values determine the minimum posit size needed to represent the real numbers involved in the binary's execution. The results for all our benchmarks running on the inputs stated in Table IV and Table V are summarized in Table VI. We note that the minimum values higher than zero that can be represented by Posit (8,1), Posit (16,2), and    Posit (32,3) are 2 −10 , 2 −48 , and 2 −216 , respectively. The maximum values that can be represented by the same posit sizes are 2 9 , 2 47 , and 2 215 , respectively. Interestingly, we do not observe a strong correlation between the dynamic range and wrong results. For example, Posit (16,2) covers the dynamic range of almost all benchmarks, except e, sin(1), KM, and CNN. But it produces correct results for KM and CNN, while for e and sin(1) it leads to the same number of accurate digits as for π. On the other hand, the dynamic values of LR are in the range of Posit (16,2), but the final result is wrong. Hence, it is not sufficient to perform this analysis in order to determine the most suitable posit size for an application. For the offline elasticity of POSAR, developers must simulate or run the application with different posit sizes and select the most suitable size for the application in the hardware.

E. Resource Utilization
As a proxy to the chip area taken by our implementation, we evaluate the FPGA resource utilization of our POSAR compared to the original FPU of Rocket Chip. We evaluate the FPGA resource utilization of the entire system, namely SiFive Freedom E310 with a Rocket Chip core that has an FPU/POSAR, running on the Arty A7-100T FPGA. While the results here denote savings in terms of resources from an FPGA perspective, similar or even higher savings in terms of the area will be obtained when the design is implemented on an ASIC [13], [28]. Savings in area directly relate to savings in both static and dynamic power and thus are important for low-power constrained applications such as IoT-based edge devices. Table VII shows the utilization of the different FPGA resources with respect to both posit and FP32 implementations.
We observe that all the implementations use the same amount of memory resources (Shift-register Look up table -SRL, LUTRAM, and BRAM) which indicates that the comparison involves only the modified FPU with the rest of the system being the same across all implementations. For significant savings in area and power without much loss in accuracy Posit (16,2) seems to be a viable option that saves almost 50% of the DSPs which translate to the multiplyaccumulate (MAC) units in an ASIC flow. These savings in area should translate to a 50% drop in dynamic power as the MACs account for a higher power compared to flops or other logic [16]. In contrast, Posit (32,3) uses 30% more LUTs and 27% more DSPs compared to FP32. These results are worse than those reported in [8], which needs only 4% more LUTs compared to the FPU, but similar to the ones reported in [23]. On the other hand, we note that the original FPU of Rocket Chip is a work-in-progress. That is, it may not implement all the corner cases of IEEE 754 standard. Nonetheless, the higher resource utilization of Posit(32,3) may be counterbalanced by its speedup which can lead to higher time and energy efficiency compared to FP32.

F. Power and Energy
We measure the average power of the FPGA as a proxy to the energy efficiency of our POSAR versus the original FPU of Rocket Chip. For these measurements, we connect a Yokogawa power meter to the 12 V DC input of the FPGA. This power meter allows reading the power once per second. We run only π computation using Leibniz series with two million iterations and MM with input size 182 since they exhibit sufficiently high execution time to allow us to measure the power. The average power of the FPGA with the original IEEE 754 FPU when running π and MM is 1.39 W and 1.48 W, respectively. The higher power of MM is due to the extended data memory size since MM with input size 182 cannot run on the default 16 kB memory. When running π on POSAR with posit size 8, 16, and 32 bits, the average power is 1.38 W, 1.4 W, and 1.48 W, respectively. When running MM, the respective average power is 1.47 W, 1.51 W, and 1.52 W. The results are encouraging. POSAR with Posit(32,3) uses 6% more power than the FPU, but is 30% faster when computing π. Hence, the energy efficiency of POSAR is superior. On the other hand, POSAR with Posit(32,3) uses only 2% more power when running MM, while POSAR with Posit(8,1) uses 1% less power compared to the FPU. While the power savings of posit on the FPGA are not spectacular, an ASIC implementation should yield even higher power savings [13], [28].

VI. CONCLUSIONS
In this paper, we explore the opportunity of replacing the traditional IEEE 754 floating-point standard with the newly-proposed posit format [19] in the context of machine learning at the edge. We present our implementation of an POSAR to replace the original FPU in a RISC-V core. We are the first to do a thorough evaluation of posit versus FP32 to determine (i) whether hardware or software conversion between posit and FP32 is better, (ii) the time-energy performance for both mathematical and ML kernels, and (iii) insights on choosing the bit-width of posits for different types of applications. We evaluate our implementation on an FPGA using the SiFive Freedom E310 platform. We compare the accuracy, efficiency in terms of cycles, FPGA resource utilization and power of three posit sizes compared to 32-bit, single-precision IEEE 754 floats.
We find that 8-bit posits are not producing the required accuracy to replace FP32 in classic ML applications. On the other hand, 32bit posit are not exhibiting spectacular improvements in terms of efficiency over FP32. While they achieve the same or higher accuracy and can speedup the execution when the program has multiplications and divisions, they need around 30% more FPGA resources and use 6% more power compared to FP32. However, 16-bit posits exhibit the best results. Even if they exhibit lower accuracy in scientific computations, they produce correct results for most of ML kernels and applications, while requiring less area and power compared to FP32. For example, Posit (16,2) achieves the same Top-1 accuracy as FP32 on a Cifar-10 CNN while exhibiting 18% speedup.