<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=Windows-1252">
<meta name="Generator" content="Microsoft Word 15 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
        {margin:0cm;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
a:link, span.MsoHyperlink
        {mso-style-priority:99;
        color:blue;
        text-decoration:underline;}
pre
        {mso-style-priority:99;
        mso-style-link:"HTML Vorformatiert Zchn";
        margin:0cm;
        margin-bottom:.0001pt;
        font-size:10.0pt;
        font-family:"Courier New";}
p.MsoListParagraph, li.MsoListParagraph, div.MsoListParagraph
        {mso-style-priority:34;
        margin-top:0cm;
        margin-right:0cm;
        margin-bottom:0cm;
        margin-left:36.0pt;
        font-size:10.0pt;
        font-family:"Calibri",sans-serif;}
span.HTMLVorformatiertZchn
        {mso-style-name:"HTML Vorformatiert Zchn";
        mso-style-priority:99;
        mso-style-link:"HTML Vorformatiert";
        font-family:"Courier New";}
span.E-MailFormatvorlage22
        {mso-style-type:personal-reply;
        font-family:"Calibri",sans-serif;
        color:windowtext;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-size:10.0pt;
        mso-ligatures:none;}
@page WordSection1
        {size:612.0pt 792.0pt;
        margin:70.85pt 70.85pt 2.0cm 70.85pt;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:613099571;
        mso-list-type:hybrid;
        mso-list-template-ids:-1730660458 67567639 67567641 67567643 67567631 67567641 67567643 67567631 67567641 67567643;}
@list l0:level1
        {mso-level-number-format:alpha-lower;
        mso-level-text:"%1\)";
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level3
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level4
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level6
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l0:level7
        {mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l0:level9
        {mso-level-number-format:roman-lower;
        mso-level-tab-stop:none;
        mso-level-number-position:right;
        text-indent:-9.0pt;}
@list l1
        {mso-list-id:1312323889;
        mso-list-template-ids:1285561180;}
@list l1:level1
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:36.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:72.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:108.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:144.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:180.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:216.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:252.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:288.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l1:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:324.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2
        {mso-list-id:1350135908;
        mso-list-template-ids:-306839172;}
@list l2:level1
        {mso-level-start-at:2;
        mso-level-number-format:alpha-lower;
        mso-level-tab-stop:36.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level2
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:72.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level3
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:108.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level4
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:144.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level5
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:180.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level6
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:216.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level7
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:252.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level8
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:288.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
@list l2:level9
        {mso-level-number-format:alpha-lower;
        mso-level-tab-stop:324.0pt;
        mso-level-number-position:left;
        text-indent:-18.0pt;}
ol
        {margin-bottom:0cm;}
ul
        {margin-bottom:0cm;}
--></style>
</head>
<body lang="DE-CH" link="blue" vlink="purple" style="word-wrap:break-word">
<div class="WordSection1">
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Hi<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Here the corrected version. I splitted “round and normalize” into two steps.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Introduced a new variable z1 for the rounding phase.<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">PROCEDURE FML*(x, y: REAL; VAR z: REAL); (* floating multiply *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                VAR<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               S: INTEGER; (* state *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               P0, P24: INTEGER; (* 48 bit product: 0..23 and 24..47 *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               sign: BOOLEAN;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               xe, ye: INTEGER; (* 8 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">e0, e1: INTEGER; (* 9 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                               z0: INTEGER; (* 23 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                               w0: INTEGER; (* 24 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                               w1: INTEGER; (* 25 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">z1: INTEGER; (* 26 bits *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                BEGIN<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               sign := Bit(ORD(x), 31, 31) # Bit(ORD(y), 31, 31);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               xe := Bit(ORD(x), 30, 23);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ye := Bit(ORD(y), 30, 23);
<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               Out.printf("xe = %d, ye = %d\n", xe, ye, "");<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               e0 := xe + ye;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               P24 := 0; P0 := 800000H + Bit(ORD(x), 22, 0);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               FOR S := 0 TO 23 DO (* look at all bits in p0 aka x *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               IF ODD(P0) THEN w0 := 800000H + Bit(ORD(y), 22, 0) ELSE w0 := 0 END;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               w1 := P24 + w0; (* 25 bit result *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               (* P <= {w1, P[23:1]} *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               P0 := Bit(P0, 23, 1); (* this is P0 := P0 DIV 2 *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               IF ODD(w1) THEN P0 := P0 + 800000H END;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               P24 := w1 DIV 2<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               END;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               Out.printf("product P =%x%x\n", P24, P0, "");<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               z1 := P24*4 + Bit(P0, 23, 22) + 1 + Bit(P24, 23, 23); (* round *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               IF Bit(z1, 25, 25) = 1 THEN (* normalize *)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                              
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">z0 := Bit(z1, 24, 2)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSE<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                                               z0 := Bit(z1, 23, 1)<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">END;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               e1 := e0 - 127 + Bit(z1, 25, 25); (* P[47],  should be z1[25]*)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">Out.printf("z0 = %x, e1 = %d\n", z0, e1, "");<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">IF (xe = 0) OR (ye = 0) THEN z := 0R<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSIF Bit(e1, 8, 8) = 0 THEN z := SYSTEM.VAL(REAL, Bit(e1, 7, 0)* 800000H + z0)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSIF Bit(e1, 7, 7) = 0 THEN z := SYSTEM.VAL(REAL, 7F800000H+ z0)<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSE z := 0R<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               END;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               IF sign THEN z := -z END<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">               
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">END FML;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">This is in Verlog:<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">`timescale 1ns / 1ps  // NW 15.9.2015  8.8.2016 jr/16.10.2023<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">module FPMultiplier(<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">  input clk, run,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">  input [31:0] x, y,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">  output stall,<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">  output [31:0] z);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">reg [4:0] S;  // state<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">reg [47:0] P; // product<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">wire sign;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [7:0] xe, ye;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [8:0] e0, e1;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [22:0] z0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [23:0] w0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [24:0] w1;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">wire [25:0] z1;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign sign = x[31] ^ y[31];<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign xe = x[30:23];<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign ye = y[30:23];<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign e0 = xe + ye;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign e1 = e0 - 127 + z1[25];<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New""><o:p> </o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign stall = run & ~(S == 25);<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign w0 = P[0] ? {1'b1, y[22:0]} : 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign w1 = {1'b0, P[47:24]} + {1'b0, w0};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign z1 = P[47:22]+1+P[47];  // round<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign z0 = z1[25] ? z1[24:2] : z1[23:1];  // normalize<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">assign z = (xe == 0) | (ye == 0) ? 0 :<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">   (~e1[8]) ? {sign, e1[7:0], z0} :<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">   (~e1[7]) ? {sign, 8'b11111111, z0} : 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">always @ (posedge(clk)) begin<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    P <= (S == 0) ? {24'b0, 1'b1, x[22:0]} : {w1, P[23:1]};<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US" style="font-family:"Courier New"">    S <= run ?
</span><span style="font-family:"Courier New"">S+1 : 0;<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">end<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-family:"Courier New"">endmodule<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">Jörg<o:p></o:p></span></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"><o:p> </o:p></span></p>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">Von:
</span></b><span style="font-size:12.0pt;color:black">Oberon <oberon-bounces@lists.inf.ethz.ch> im Auftrag von joerg.straube@iaeth.ch <joerg.straube@iaeth.ch><br>
<b>Datum: </b>Montag, 16. Oktober 2023 um 00:21<br>
<b>An: </b>ETH Oberon and related systems <oberon@lists.inf.ethz.ch><br>
<b>Betreff: </b>Re: [Oberon] Wrong results of selected REAL multiplications<o:p></o:p></span></p>
</div>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Hi</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">I ported the Verilog code of the floating multiplication to Oberon-07.</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Some of the Oberon code could be written more elegantly in Oberon, but for the sake of comparing 1:1, I let the code as it is in Verlog.</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">PROCEDURE Bit(x: INTEGER; hi, lo: INTEGER): INTEGER;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                RETURN ROR(x, lo) MOD LSL(2, hi-lo)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                END Bit;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">PROCEDURE FML*(x, y: REAL; VAR z: REAL); (* floating multiply *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                VAR</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               S: INTEGER; (* state *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               P0, P24: INTEGER; (* 48 bit product: 0..23 and 24..47 *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               sign: BOOLEAN;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               xe, ye: INTEGER; (* 8 bits *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">e0, e1: INTEGER; (* 9 bits *)</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                               w0: INTEGER; (* 24 bits *)</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">w1, z0: INTEGER; (* 25 bits *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                BEGIN</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               sign := Bit(ORD(x), 31, 31) # Bit(ORD(y), 31, 31);</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               xe := Bit(ORD(x), 30, 23);</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ye := Bit(ORD(y), 30, 23);
</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               Out.printf("xe = %d, ye = %d\n", xe, ye, "");</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               e0 := xe + ye;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               P24 := 0; P0 := 800000H + Bit(ORD(x), 22, 0);</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               FOR S := 0 TO 23 DO (* look at all bits in p0 aka x *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               IF ODD(P0) THEN w0 := 800000H + Bit(ORD(y), 22, 0) ELSE w0 := 0 END;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               w1 := P24 + w0; (* 25 bit result *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               (* P <= {w1, P[23:1]} *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               P0 := Bit(P0, 23, 1); (* this is P0 := P0 DIV 2 *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               IF ODD(w1) THEN P0 := P0 + 800000H END;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               P24 := w1 DIV 2</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               END;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               Out.printf("product P =%x%x\n", P24, P0, "");</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               IF Bit(P24, 23, 23) = 1 THEN</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               z0 := P24*2 + Bit(P0, 23, 23) + 1</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSE</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                                               z0 := P24*4 + Bit(P0, 23, 22) + 1 (* e1 is not adjusted if rounding sets the highest bit!! *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               END;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               e1 := e0 - 127 + Bit(P24, 23, 23); (* P[47] *)</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">Out.printf("z0 = %x, e1 = %d\n", z0, e1, "");</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US">                              
</span><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">IF (xe = 0) OR (ye = 0) THEN z := 0R</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSIF Bit(e1, 8, 8) = 0 THEN z := SYSTEM.VAL(REAL, Bit(e1, 7, 0)* 800000H + Bit(z0, 23, 1))</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSIF Bit(e1, 7, 7) = 0 THEN z := SYSTEM.VAL(REAL, 7F800000H+ Bit(z0, 23, 1))</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               ELSE z := 0R</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               END;</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">                               IF sign THEN z := -z END</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">               
</span><span style="font-size:11.0pt;mso-fareast-language:EN-US">END FML;</span><o:p></o:p></p>
<p class="MsoNormal"><span style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">If the highest bit of the 48 bit product is set, we have to adjust the final exponent e1 by one.</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">There are TWO possibilities how the highest bit of the product P is set</span><o:p></o:p></p>
<ol style="margin-top:0cm" start="1" type="a">
<li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo3"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Either the values of x and y are big enough, so their products sets the highest bit.</span><o:p></o:p></li></ol>
<p class="MsoListParagraph"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">This case is taken care of by
</span><span lang="EN-US">assign e1 = e0 - 127 + P[47];</span><o:p></o:p></p>
<p class="MsoListParagraph">Or in Oberon<span style="font-size:11.0pt;mso-fareast-language:EN-US"> e1 := e0 - 127 + Bit(P24, 23, 23);</span><o:p></o:p></p>
<p class="MsoListParagraph"><span style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<ol style="margin-top:0cm" start="2" type="a">
<li class="MsoListParagraph" style="margin-left:0cm;mso-list:l0 level1 lfo3"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">During the final rounding step from P to z0 a carry might flow over to the highest bit<br>
If this is the case e1 is not adjusted. So basically this step is wrong</span><o:p></o:p></li></ol>
<pre><span lang="EN-US">        assign z0 = P[47] ? P[47:23]+1 : P[46:22]+1;  // round and normalize</span><o:p></o:p></pre>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">So far the analysis. I’ll try to come up with a solution.</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">br</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US">Jörg
</span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<p class="MsoNormal"><span lang="EN-US" style="font-size:11.0pt;mso-fareast-language:EN-US"> </span><o:p></o:p></p>
<div id="mail-editor-reference-message-container">
<div>
<div style="border:none;border-top:solid #B5C4DF 1.0pt;padding:3.0pt 0cm 0cm 0cm">
<p class="MsoNormal" style="margin-bottom:12.0pt"><b><span style="font-size:12.0pt;color:black">Von:
</span></b><span style="font-size:12.0pt;color:black">Oberon <oberon-bounces@lists.inf.ethz.ch> im Auftrag von Michael Schierl <schierlm@gmx.de><br>
<b>Datum: </b>Freitag, 13. Oktober 2023 um 23:55<br>
<b>An: </b>oberon@lists.inf.ethz.ch <oberon@lists.inf.ethz.ch><br>
<b>Betreff: </b>Re: [Oberon] Wrong results of selected REAL multiplications</span><o:p></o:p></p>
</div>
<div>
<p class="MsoNormal"><span style="font-size:11.0pt">Hello,<br>
<br>
<br>
Am 13.10.2023 um 18:39 schrieb Hans Klaver:<br>
<br>
>> The problem does not occur on a April 2016 verison of Peter's<br>
>> emulator. This leads me to suspect that the problem may have been<br>
>> introduced during the changes to the Floating Point-related Verilog<br>
>> files that were made between 8 Aug 2016 and 3 Oct 2016 as<br>
>> summarised here:<br>
>><br>
>> <a href="https://people.inf.ethz.ch/wirth/news.txt">https://people.inf.ethz.ch/wirth/news.txt</a><br>
<br>
For the record, the changes talked about are in this diff:<br>
<<a href="https://github.com/Spirit-of-Oberon/wirth-personal/commit/359240b9d1c63d23aff6c90aa90fdd46917c743b">https://github.com/Spirit-of-Oberon/wirth-personal/commit/359240b9d1c63d23aff6c90aa90fdd46917c743b</a>>.<br>
<br>
> Thanks for checking this.<br>
><br>
> As I don't know much about Verilog programming I am afraid that I<br>
> can't be of much help to pinpoint this bug and propose a solution.<br>
<br>
I don't think having experience about Verilog programming really helps<br>
me much in understanding this very dense code of parallel bit-twiddling<br>
(and a significant part of the twiddling and its state machine is for<br>
doing the "integer" multiplication of the mantissae).<br>
<br>
> Hoping others in the community are able and willing to look into<br>
> this.<br>
<br>
Just starting from the facts you stated (sometimes, when multiplying a<br>
value with mantissa # 1.0 with a value with mantissa # 1.0 and the<br>
result has a mantissa = 1.0, the exponent is off by one), and when<br>
looking at the changes to FPMultiplier in the commit above, I have a<br>
suspicion ...<br>
<br>
Just picking a few lines of the assignments from the new version (I<br>
slightly reordered them for the argument, but that does not matter as<br>
all those assignments happen in parallel anyway):<br>
<br>
<br>
reg [47:0] P; // product<br>
wire [24:0] z0;<br>
<br>
assign e1 = e0 - 127 + P[47];<br>
<br>
assign z0 = P[47] ? P[47:23]+1 : P[46:22]+1;  // round and normalize<br>
<br>
assign z = (xe == 0) | (ye == 0) ? 0 :<br>
    (~e1[8]) ? {sign, e1[7:0], z0[23:1]} :<br>
    (~e1[7]) ? {sign, 8'b11111111, z0[23:1]} : 0;<br>
<br>
<br>
Or condensed to the part I'd like to point out<br>
<br>
<br>
assign e1 = <something> + P[47];<br>
<br>
assign z0 = P[47] ? P[47:23]+1 : P[46:22]+1;  // round and normalize<br>
<br>
assign z = <some corner cases omitted, but the main case is><br>
            {sign, e1[7:0], z0[23:1]};<br>
<br>
<br>
z is our final output, and in the final step of the state machine it<br>
gets set by using e1 as exponent and the "middle" of z0 as mantissa<br>
(while z0 is a 25-bit value, we omit the first and last bit of it. First<br>
bit has to be 1 and is omitted in IEEE float representation, and last<br>
bit was there for better rounding).<br>
<br>
Both exponent and mantissa have special logic for handing the most<br>
significant bit of the intermediate product, P[47], to be 1. In that<br>
case we increase the exponent by 1, while at the same time shifting the<br>
mantissa one more bit. That way, even if P[47] is not 1, P[46] is 1, so<br>
we end up with a normalized mantissa.<br>
<br>
Or at least, that is what you might think at first point.<br>
<br>
Now consider the case, where (the relevant part of) P has the value of<br>
<br>
0111111111111111111111111<br>
<br>
<br>
The most significant bit is 0. Yet for the actual computation of the<br>
mantissa, we add 1 after shifting (this bit is cut off afterwards and as<br>
the comment suggests, this is to improve rounding of results), resulting<br>
in a mantissa of all zeros (as the top bit is cut off as well), instead<br>
of a mantissa of 1000000000000000000000000. The leading bit does not<br>
matter, though, as we will discard it anyway, assuming it to be a 1.<br>
<br>
But what does matter: For the computation of the exponent we don't take<br>
care of the overflow of the addition and do not add an extra 1.<br>
<br>
An easy fix would be to remove the rounding (the two +1), but then your<br>
result would be 437FFFFFH instead of 43800000H (still a lot better than<br>
43000000H, though). But a correct fix that keeps the rounding does not<br>
seem to be trivial.<br>
<br>
In the emulator source, I could easily fix this by adding an additional<br>
if statement and just do the addition again before comparing the most<br>
significant bit for incrementing the exponent, but I don't feel able to<br>
do this in Verilog (while still keeping the whole circuit being fast),<br>
especially since I don't have a way to test it on real hardware. Maybe<br>
somebody else wants to give it a stab?<br>
<br>
So either, change the computation of P in the previous states to add 1<br>
there (while for the best rounding you would have to add 2 in case the<br>
value is shifted one bit later). Or account for the extra 1 exponent in<br>
case of overflow.<br>
<br>
As a compromise, one could also just omit the rounding in case the value<br>
before rounding but after normalization (or at least a significant part<br>
of its digits) happens to be all ones; in that case, the rounding would<br>
still happen in most cases but not in the one that currently triggers<br>
the bug.<br>
<br>
<br>
Or did I miss anything obvious? :)<br>
<br>
<br>
Regards,<br>
<br>
<br>
Michael<br>
--<br>
Oberon@lists.inf.ethz.ch mailing list for ETH Oberon and related systems<br>
<a href="https://lists.inf.ethz.ch/mailman/listinfo/oberon">https://lists.inf.ethz.ch/mailman/listinfo/oberon</a></span><o:p></o:p></p>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>