2

三項を使用して次のコードを翻訳しました。しかし、私はそれには何か問題があることを知っていました。誰かが私を正しい方向に向けることができますか?

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);
4

4 に答える 4

10

驚いたことに、反対票を投じる危険を冒して、正しい方向はコードを比較的読みやすい状態にしておくことだと言います。

あなたができる唯一のことは、正規表現として行うか、インラインアセンブリに変換することだと思います:-)

簡単に変換できないという事実は、あなたが試みていることの知恵について何かを教えてくれるはずです.


他の場所でのコメントに基づいて:

これは Verilog であるため、3 進数で実行する必要があり、if を使用できません。そうしないと、前に常にブロックが必要になり、それは望ましくありません... if else の条件が満たされる

もしそうしなければならないのなら、私のアドバイスに反して(このアドバイスを提供しているのは私だけではありません)、使用すべき方法は次のとおりです(「常にブロック」が何であるかさえわからないので、資格がありません.あなたと要点を議論する)。

現在のコードは値を設定ForwardAForwardBてから特定の条件下でのみ変更するため、順序を逆にすることでそれを三項に変換できます。これは、あなたのifバージョンでは後のコードが優先されますが、三項では以前のコードが優先されるためです。

どのような状況ForwardAで とForwardBが逆の順序で設定されているかを調べ、それらの状況を再構築します。

これが元のコードで、少し圧縮されています。また、SO レンダリング エンジンで適切な書式設定が得られるように、あなたの2'b10ものも変更2'b10'しました。元に戻すことを忘れないでください。

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

B が 3 か所に設定されていることがわかります。2'b01一番下if、一番2'b10上、そして最初に設定されてい0ます。条件の変換:

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;

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;

その背後にある理論は優れていますが、転写に誤りがあったとしても、またはVerilogが嫌悪感を持って手を上げ、ボールを拾い上げて家に帰ったとしても、少しも驚かないでしょう:- )

少なくとも、この道をたどる必要がある場合は、お二人とも:

  • 三項式を少なくとも少しは読みやすいままにしておいてください。適切な空白と複数の行をすべて使用してください。と
  • 問題がある場合やロジックを変更したい場合に、少なくとも元のコードに戻ることができるように、元のコードをコメントに残しておきますか?

真剣に、あなたがこれをもう一度見て、地球上で何を考えていたのかを理解しようとしているときに、6か月後に私に感謝します:-)

于 2010-05-05T16:27:35.360 に答える
3

これを行う必要はありません。コードを「always @*」ブロックに挿入し、割り当て先を「reg」として宣言します。

reg [1:0] ForwardA;
reg [1:0] ForwardB;

always @(*) begin
   // Your combo logic here..
end
于 2010-05-07T10:48:56.140 に答える
1

なんらかの理由で三部形式に保つことを主張すると仮定すると、正しくフォーマットするだけで読みやすさが大幅に向上します。

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);

これで、そのコードは実際に使用しているものではなくC ++であるかのようにフォーマットされますが、何が起こっているのかを理解するのがはるかに簡単になります。

ただし、ifステートメントが3項式と一致しない可能性があることを指摘しておきます。ifステートメントにはelse句がなく、3項式には常にelse句があります。ただし、質問では、ifステートメントを3項式に変換しようとしているのか、3項式をifステートメントに変換しようとしているのかが完全には明確になっていないため、必要なものを正確に提供するのは少し難しいです。

編集:3項式には、常にif句とelse句の両方があります。三項のelse部分がないため、else節のないifステートメントを直接三項に変換することはできませんこれで、変数をそれ自体に設定するなど、必要に応じていくつかのトリックを引き出すことができます。例えば、

ForwardA = cond1 ? newValue : FordwardA;

基本的に、else句の値を変更しないと言っていますが、これは、結果を変数に割り当てることを前提としています。式が複雑になるほど、そのようなトリックを引き出すのは難しくなり、コードを複雑にすることになります。言うまでもなく、コンパイラーが実行する最適化と実行しない最適化によっては、変数をそれ自体に割り当てる可能性がありますが、これはそれほど効率的ではありません。

一般的に言えば、else節のないifステートメントを3項式に変換することは悪い考えです。それは、あなたが何を意味するのかを直接言うのではなく、トリックを引くことによってのみ行うことができ、それは物事を複雑にするだけです。そして、このコードはそれなりに複雑です。

本当に必要な場合を除いて、ここではターナリを使用しないことをお勧めします。もしそうなら、少なくとも表現を分解してください。三項式が正しかったとしても、if文よりも読みにくいです。

編集2:これが本当に三項式である必要がある場合は、座って、ForwardAが値のセットになる正確な条件を理解し、それを試してみるのではなく、それに基づいて三項式を作成することをお勧めします持っているifステートメントを直接変換します(ForwardBでも同じです)。ifステートメントは、各変数に割り当てる値を決定するだけでなく、その値を割り当てる変数を決定するため、事態はかなり複雑になります。

他の言語(Verilogについてはわかりません)では、式の右側で行っていることに加えて、値を割り当てる変数を選択するために3項式を使用できますが、これは非常に複雑になります。割り当てられる値を保持する一時的なものと、それを割り当てる変数を決定するための別の3進数を作成するのが最善の場合があります。

Verilogがわからないので、if文と3項式で何ができるのか、何ができないのかはわかりませんが、3項を使用するよりも、これを処理するためのより良い方法が必要だと思います。そうではないかもしれませんが、あなたがやろうとしていることは非常に難しく、エラーが発生しやすいものです。

于 2010-05-05T16:37:05.197 に答える
1

まずやらない!そうしても意味がありません。修正しようとして気付いたように、より良いコードにコンパイルされず、読みにくくなります。式として必要な場合は、インライン関数としてコーディングすることをお勧めします。

于 2010-05-05T17:04:40.963 に答える