Convert if else to trernary
I have translated the following code using ternary. However, I knew there was something wrong with this. Can anyone point me in the right direction?
ForwardA = 0;
ForwardB = 0;
//EX Hazard
if (EXMEMRegWrite == 1) begin
if (EXMEMrd != 0)
if (EXMEMrd == IDEXrs)
ForwardA = 2'b10;
if (EXMEMrd == IDEXrt && IDEXTest == 0)
ForwardB = 2'b10;
end
//MEM Hazard
if (MEMWBRegWrite == 1) begin
if (MEMWBrd != 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
if (MEMWBrd == IDEXrs)
ForwardA = 2'b01;
if (IDEXTest == 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
if (MEMWBrd == IDEXrt)
ForwardB = 2'b01;
end
end
end
ForwardA = (MEMWBRegWrite && MEMWBrd != 0 && (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs))) && (MEMWBrd == IDEXrs)) ?
2'b01 : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrs) ? 2'b10 : 0);
ForwardB = (IDEXTest == 0 && MEMWBRegWrite && MEMWBrd != 0 && (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt))) && (MEMWBrd == IDEXrs)) ?
2'b01 : ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrt && IDEXTest == 0) ? 2'b10 : 0);
a source to share
Surprisingly, I'm going to risk downvotes and tell you that the right direction is to leave your code in its relatively readable state.
I suspect the only thing you could do would be worse if it would be done as a regex or convert it to inline assembly :-)
The fact that it is not easily convertible should tell you something about the wisdom in what you are trying to do.
Based on your comment elsewhere:
It is verilog and so I need to do it in ternary form and cannot have an if if else, otherwise I will always need the block before and I don’t want that ... I want the remaining ones to be 0 if none of the conditions in the if if above fails
Okay, if you have to, against my advice (and I'm not the only one here offering this advice), here is the method you should use (I have no idea what "always block" is, I have no right to argue with you ).
Since your current code sets the values ForwardA
and ForwardB
and then changes them only under certain conditions, you can convert them to ternary by changing the order. This is because in your version, if
later code takes precedence, but earlier code takes precedence in ternary.
Find out under what circumstances ForwardA
and ForwardB
are reversed and restore those conditions.
Here is your original code, bit compressed. I've also changed your stuff 2'b10
to 2'b10'
, so we're still getting good formatting in SO's render engine - don't forget to change them.
ForwardA = 0;
ForwardB = 0;
if (EXMEMRegWrite == 1) begin
if (EXMEMrd != 0)
if (EXMEMrd == IDEXrs)
ForwardA = 2'b10';
if (EXMEMrd == IDEXrt && IDEXTest == 0)
ForwardB = 2'b10';
end
if (MEMWBRegWrite == 1) begin
if (MEMWBrd != 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs)))
if (MEMWBrd == IDEXrs)
ForwardA = 2'b01';
if (IDEXTest == 0) begin
if (!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt)))
if (MEMWBrd == IDEXrt)
ForwardB = 2'b01';
end
end
end
You can see that B is given in three places. It is installed at 2'b01
the bottom if
, 2'b10
at the top and 0
at the beginning. Conversion of conditions:
ForwardB = ((MEMWBRegWrite == 1) &&
(MEMWBrd != 0) &&
(IDEXTest == 0) &&
(!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrt))) &&
(MEMWBrd == IDEXrt))
? 2'b01'
: ((EXMEMRegWrite == 1) &&
(EXMEMrd != 0) &&
(EXMEMrd == IDEXrt && IDEXTest == 0))
? 2'b10'
: 0;
Similarly for A:
ForwardA = ((MEMWBRegWrite == 1) &&
(MEMWBrd != 0) &&
(!(EXMEMRegWrite == 1 && EXMEMrd != 0 && (EXMEMrd == IDEXrs))) &&
(MEMWBrd == IDEXrs))
? 2'b01'
: ((EXMEMRegWrite == 1) &&
(EXMEMrd != 0) &&
(EXMEMrd == IDEXrs))
? 2'b10'
: 0;
Now the theory behind is good, but I wouldn't be at all surprised if I made a mistake in the transcription, or if Verilog just threw away his hands in disgust, took his ball and ran home :-)
May I at least suggest, if you should follow this path, both of you:
- try to keep ternary expressions at least a little readable, with all that nice white space and a few lines; and
- keep the source code in a comment so that at least you can come back to it if you have problems or want to change the logic?
a source to share
Okay, assuming you insist on keeping it in 3D for whatever reason, your readability has improved significantly if you just formatted it correctly.
const bool cond1 = MEMWBRegWrite && MEMWBrd != 0 &&
!(EXMEMRegWrite == 1 && EXMEMrd != 0 && EXMEMrd == IDEXrs) &&
MEMWBrd == IDEXrs;
ForwardA = cond1
? 2'b01
: ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrs) ? 2'b10 : 0);
const bool cond2 = IDEXTest == 0 &&
MEMWBRegWrite && MEMWBrd != 0 &&
!(EXMEMRegWrite == 1 && EXMEMrd != 0 && EXMEMrd == IDEXrt) &&
MEMWBrd == IDEXrs;
ForwardB = cond2
? 2'b01
: ((EXMEMRegWrite && EXMEMrd != 0 && EXMEMrd == IDEXrt && IDEXTest == 0) ? 2'b10 : 0);
This code is now formatted as if it were C ++ and not what you actually use, but it's much easier to understand what's going on.
However, I would like to point out that your if statements cannot match your ternary expressions. Your if statements do not have an else clause, and there are always other clauses in ternary expressions. However, since your question doesn't even make it clear whether you are trying to convert if-statements to ternary expressions or ternary expressions in if-statements, it is a little difficult for you to give you exactly what you want.
EDIT . Ternary expressions always have both an if and an else condition. You cannot directly convert an if statement without an else clause to ternary, because you will not have the other part of the ternary. Now you can think of some tricks in some cases if you need to, for example, set a variable for yourself. For instance,
ForwardA = cond1 ? newValue : FordwardA;
Basically, you say that you are not changing the value in the else clause, but you believe that you are assigning the result to a variable. The more complex the expression, the harder it is to pull this trick, and the more confusing the code will be when you do it. Not to mention, depending on what optimizers the compiler does or does not do, it may assign a variable to itself, which is not very efficient.
Generally speaking, translating if-statements without any additional clauses into ternary expressions is a bad idea. This can only be done by pulling out tricks, not directly saying what you mean, and it just complicates things. And this code is quite complex as it is.
I would advise against using the trinity here unless you really need to. And if you do, at least add up the expression. Even if your ternary expression was correct, it is much more difficult to read than if statements.
EDIT 2 . If you really need it to be a 3D expression, I would suggest you sit down and figure out the exact conditions under which ForwardA should be that set of values, and create a 3D expression based on that, instead of trying to directly transform if-statements that you have (and same for ForwardB). Your if-statments not only determine which value is assigned to each variable, but which variable assigns that value, and this complicates things considerably.
In other languages (I don't know about verilog), you can use a 3D expression to select which variable to assign a value to in addition to what you do on the right side of the expression, but getting is really tricky. Your best bet would be to create a temporary value that contains the value to be assigned and a separate ternary to determine which variable to assign to it.
Without knowing verilog, I really don't know what you can and cannot do with if-statements and ternary expression, but I would think it would work better for this than using ternary. Probably not, but what you are trying to do is very difficult and error prone.
a source to share