{"action":"created","issue":{"url":"https://api.github.com/repos/ucb-bar/chisel/issues/358","labels_url":"https://api.github.com/repos/ucb-bar/chisel/issues/358/labels{/name}","comments_url":"https://api.github.com/repos/ucb-bar/chisel/issues/358/comments","events_url":"https://api.github.com/repos/ucb-bar/chisel/issues/358/events","html_url":"https://github.com/ucb-bar/chisel/issues/358","id":55979521,"number":358,"title":"Unintuitive width inference/Mux/SInt behavior: sign-extension fails in presence of a UInt","user":{"login":"ccelio","id":788854,"avatar_url":"https://avatars.githubusercontent.com/u/788854?v=3","gravatar_id":"","url":"https://api.github.com/users/ccelio","html_url":"https://github.com/ccelio","followers_url":"https://api.github.com/users/ccelio/followers","following_url":"https://api.github.com/users/ccelio/following{/other_user}","gists_url":"https://api.github.com/users/ccelio/gists{/gist_id}","starred_url":"https://api.github.com/users/ccelio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ccelio/subscriptions","organizations_url":"https://api.github.com/users/ccelio/orgs","repos_url":"https://api.github.com/users/ccelio/repos","events_url":"https://api.github.com/users/ccelio/events{/privacy}","received_events_url":"https://api.github.com/users/ccelio/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-01-30T00:41:38Z","updated_at":"2015-01-30T23:23:20Z","closed_at":null,"body":"````scala\r\n    val out = UInt(width=8)\r\n    val b = UInt(3, width=2)\r\n    out := Mux(condition, UInt(0), b.SInt())\r\n````\r\n\r\nIf condition is false, `out == 3`, not `0xFF`.  Intuitively, I am expecting b.SInt() to sign-extend to the full width of the LHS variable `out`. \r\n\r\n````Verilog\r\n    // Verilog\r\n    wire[7:0] T2;\r\n    wire[1:0] T1; \r\n    wire[1:0] b;\r\n    … \r\n    assign T2 = {6'h0, T1};\r\n    assign T1 = condition ? 2'h0 : b;       \r\n````                              \r\n\r\nInstead, the Mux() becomes a Node of the length of the maximum child member (2-bits in this case). Sign-extension is only performed up to the width of the Mux().  Then, the Mux is zero-extended to the length of the LHS of the assignment ( `out = Mux()` ). \r\n\r\nThe above code can be fixed by using a SInt(0), which apparently tells the Mux() \"No really, I want you to be a sign-extending Node\".  By default, Mux's are otherwise unsigned. \r\n\r\n\r\nLooking through Rocket code, I find the following example (simplified) from csr.scala:\r\n\r\n````scala\r\n   val io_evec = UInt(width = VaddrBits+1)\r\n   val reg_evec = Reg(Bits(width = VaddrBits))\r\n   val reg_epc = Reg(Bits(width = VaddrBits+1))\r\n   io_evec := Mux(exception, reg_evec.toSInt, reg_epc).toUInt\r\n````\r\nThis works currently because the final width of the `Mux()` and the LHS variable `io_evec` are the same (VaddrBits+1).  The `reg_evec` variable is properly sign-extended to the width of the Mux, and there is no final zero-padded extension to perform that would raise an error. \r\n\r\n\r\n**Solutions?**\r\n\r\nOne solution is to throw an error if a user mixes signed and unsigned types in their Muxes (at least, if the Mux width and the LHS width are mismatched and extension is required). I don't think that this adds much in the way of superfluous casting of nodes and will save users from the occasional edge-case of unintuitive width inference behavior. \r\n\r\n"},"comment":{"url":"https://api.github.com/repos/ucb-bar/chisel/issues/comments/72288327","html_url":"https://github.com/ucb-bar/chisel/issues/358#issuecomment-72288327","issue_url":"https://api.github.com/repos/ucb-bar/chisel/issues/358","id":72288327,"user":{"login":"ccelio","id":788854,"avatar_url":"https://avatars.githubusercontent.com/u/788854?v=3","gravatar_id":"","url":"https://api.github.com/users/ccelio","html_url":"https://github.com/ccelio","followers_url":"https://api.github.com/users/ccelio/followers","following_url":"https://api.github.com/users/ccelio/following{/other_user}","gists_url":"https://api.github.com/users/ccelio/gists{/gist_id}","starred_url":"https://api.github.com/users/ccelio/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ccelio/subscriptions","organizations_url":"https://api.github.com/users/ccelio/orgs","repos_url":"https://api.github.com/users/ccelio/repos","events_url":"https://api.github.com/users/ccelio/events{/privacy}","received_events_url":"https://api.github.com/users/ccelio/received_events","type":"User","site_admin":false},"created_at":"2015-01-30T23:23:20Z","updated_at":"2015-01-30T23:23:20Z","body":"Another solution is to make muxes SInt and not UInt in the presence of SInts, as SInt is the more general type.\r\n\r\nIn general, we should probably do whatever C does when it comes to mixing widths and signed-ness."}}