Computer Architecture I @ ShanghaiTech University
In this homework, you are required to implement parsing of a modified floating-point format ca25
and conversion from the format to IEEE 754 single-precision floating-point number (fp32
). In this homework, you will
Before you start, you have to join the GitHub Classroom and accept the assignment via this link. A repository containing the starter code will be generated to you. You can then start on the assignment by cloning it to your Ubuntu system. To submit the assignment, you should push your local clone to GitHub and turn in your work on Gradescope by connecting to your GitHub repo.
Academic integrity is strictly enforced in this course and any plagiarism behavior will cause serious consequence. You have been warned.
The ca25
numbers to be converted are stored in text files line by line and passed to your program by Makefile
. Your program should directly read from stdin
and print to stdout
. Then the printed content is automatically saved into another text file by the test script. All input and output are ASCII text.
The C program should keep performing the following tasks until EOF
is met:
ca25
floating-point number which is expressed in 16-digit hex.ca25
number to single-precision fp32
.To examine the correctness of your work, for each ca25
number, the program is required to produce three lines of output:
ca25
.fp32
.fp32
.ca25
The modified number format is analogous to IEEE 754, but with different field lengths and organization. It has one sign bit, a 32-bit exponent field and a 31-bit mantissa field.
MSB LSB
+----+---------------+--------------+
| 63 | 62 ... 31 | 30 ... 0 |
+----+---------------+--------------+
Sign Exponent Mantissa
2^31-1
represents the actual exponent zero.Exponent | Mantissa = 0 | Mantissa ≠ 0 |
---|---|---|
0x00000000 | ±zero | subnormal |
0xFFFFFFFF | ±infinity | NaN |
otherwise | normal | normal |
This example is provided to aid you in better understanding the input and output specification. For the following input
40000038da100000
3fffffb39cde0b01
the program must print the following text output
ca25 S=0 E=80000071 M=1.b4200000 normal
fp32 S=0 E=f1 M=1.b42000 normal
78da1000
ca25 S=0 E=7fffff67 M=1.39bc1602 normal
fp32 S=0 E=00 M=0.000002 subnormal
00000001
Each line of the input consists of one ca25
floating-point number in 16-digit lower-case hex. The number of lines is unspecified: the program keeps processing input until it reads EOF
.
ca25
The format is specified as follows with some examples.
ca25 S=<sign> E=<exponent> M=<implicit>.<fraction> <type>
<sign> = sign bit
<exponent> = biased exponent in 8-digit hex
<implicit> = implicit leading bit, 0 for zero or subnormal and 1 for others
<fraction> = fraction in left-adjusted 8-digit hex
(so the LSB should always be zero)
<type> = "normal" | "subnormal" | "zero" | "nan" | "inf"
ca25 S=0 E=7fffffff M=1.80000000 normal # 3fffffffc0000000 = 1.5
ca25 S=1 E=00000000 M=0.40000000 subnormal # 8000000020000000 = -2^(2^-34)
ca25 S=1 E=00000000 M=0.00000000 zero # 8000000000000000 = -0
ca25 S=0 E=ffffffff M=1.fffffffe nan # 7fffffffffffffff = nan
ca25 S=0 E=ffffffff M=1.00000000 inf # 7fffffff80000000 = +inf
Recall that one hex digit can represent four binary bits. As ca25
has 31 explicit bits of significand, when expressed in hex digits, there is one bit redundant, namely the least significant. That bit should always be treated as zero. As a result, the LSB of <fraction>
should always be zero.
The intermediate values during a floating-point arithmetic operation are generally of higher precision than the destination, hence the result has to be rounded before storing into the destination to fit into its precision. When converting a floating-point number from a higher-precision format into a lower-precision format, the rounding mode determines how the value should be adjusted.
The rounding mode in this homework is rounding away from zero. An informal but intuitive example is that, when converting real numbers to integers with this mode, -4.5
would be rounded to -5
and 4.5
would be rounded to 5
. Formally, this mode rounds a number to the nearest representable value whose magnitude (absolute value) is no lesser than the original number.
Hint: For each type of ca25
number, consider whether this rounding mode will affect its type and how.
fp32
Recall that a fp32
has one bit for sign, 8-bit for 127-biased exponent and 23-bit explicit significand bits. The conversion has several rules:
fp32
could represent, it becomes infinity.As fp32
's exponent and mantissa fields are both shorter than the ca25
format, careful you should be for subtle things when doing the rounding, including, but not limited to the following points:
ca25
may become subnormal fp32
, resulting in more bits to be considered in rounding.fp32
The format is specified as follows with some examples.
fp32 S=<sign> E=<exponent> M=<implicit>.<fraction> <type>
<sign> = sign bit
<exponent> = biased exponent in 2-digit hex
<implicit> = implicit leading bit, 0 for zero or subnormal and 1 for others
<fraction> = fraction in left-adjusted 6-digit hex
(so the LSB should always be zero)
<type> = "normal" | "subnormal" | "zero" | "nan" | "inf"
fp32 S=1 E=01 M=1.54e44a normal # 80aa7225
fp32 S=0 E=00 M=0.000002 subnormal # 00000001
fp32 S=1 E=00 M=0.000000 zero # 80000000
fp32 S=0 E=ff M=1.20219a nan # 7f9010cd
fp32 S=1 E=ff M=1.000000 inf # ff800000
Recall that one hex digit can represent four binary bits. As fp32
has 23 explicit bits of significand, when expressed in hex digits, there is one bit redundant, namely the least significant. That bit should always be treated as zero. As a result, the LSB of <fraction>
should always be zero.
fp32
in hexNo matter what type the converted result fp32
is, output the 8-digit lower-case hex representation.
EOF
handling, you might like to run man scanf
in your terminal. For output formatting, man printf
offers useful knowledge. For those who prefer reading on a modern interface or on a Windows system, google should lead you to similar online docs.Makefile, testcases and tester script are provided in the starter code, with which you can compile and test your code.
In your assignment directory, run the following command.
make convert
This will effectively compile your code using the following command.
gcc -std=c11 -Wall -Wextra -Wpedantic -Werror -O2 -ggdb convert.c -o convert
The command enables C11 standard and many warning options. Most importantly, all warnings are treated as error and will cause the compilation to fail. This decision is made to help you avoid some tricky bugs, such as unintentionally comparing signed and unsigned integers.
In your assignment directory, run the following command.
make test
The command will run your program with the testcases and compare your output against the correct solution. It will output the number of lines which matches the expected output. In addition, it will also create testcases/total-output.mark
to indicate which output lines are incorrect. An example is as follows.
[ ] ca25 S=0 E=7ffffffc M=1.da21a280 normal
[x] fp32 S=0 E=7c M=1.da21a6 normal
[x] 3e6d10d3
[ ] ca25 S=0 E=7ffffffc M=1.9dc84602 normal
[x] fp32 S=0 E=7c M=1.9dc84c normal
[x] 3e4ee426
The mark [x]
means that line is incorrect.
To make a submission, you will take the following steps:
git add convert.c
in the assignment directory to stage your changes.git commit
and write appropriate commit message to commit your changes.git push
to push commits in your local clone to GitHub.Only the last active submission will be accounted for your homework grade. Make sure it is your best version.
The following TA(s) are responsible for this homework:
Yizhou Wang <wangyzh2024 AT shanghaitech.edu.cn>