преобразование if else в троичное выражение - PullRequest
2 голосов
/ 05 мая 2010

Я перевел следующий код, используя троичный.Однако я знал, что с этим что-то не так.Может кто-нибудь указать мне правильное направление?

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 ]

10 голосов
/ 05 мая 2010

Удивительно, но я собираюсь рискнуть понизить голос и сказать вам, что правильное направление - это оставить ваш код в относительно читабельном состоянии.

Я подозреваю, что единственное, что вы могли бы сделать, было бы хуже, сделать это как регулярное выражение или преобразовать его во встроенную сборку: -)

Тот факт, что не легко конвертируется, должен рассказать вам о мудрости в том, что вы пытаетесь.


На основании вашего комментария в другом месте:

Это verilog, и поэтому мне нужно сделать это в троичной форме, и у меня не может быть if if else, в противном случае мне понадобится блок всегда, и я этого не хочу ... Я хочу, чтобы оставшееся было 0, если не выполняется ни одно из условий, указанных выше,

Что ж, если вы должны сделать это, вопреки моему совету (и я здесь не один, чтобы предлагать этот совет), вот метод, который вы должны использовать (я понятия не имею, что такое "всегда блокировать" "Даже если я не могу спорить с тобой).

Поскольку ваш текущий код устанавливает значения ForwardA и ForwardB, а затем изменяет их только при определенных условиях, вы можете преобразовать это в троичное, изменив порядок в обратном порядке. Это связано с тем, что в вашей версии if более поздний код имеет приоритет, но более ранний код имеет приоритет в троичной форме.

Узнайте, при каких обстоятельствах ForwardA и ForwardB установлены в обратном порядке, и восстановите эти условия.

Вот ваш оригинальный код, немного сжатый. Я также изменил ваши 2'b10 вещи на 2'b10', поэтому мы по-прежнему получаем хорошее форматирование в движке SO рендеринга - не забудьте вернуть их обратно.

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 установлен в трех местах. Для него установлено значение 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 просто с отвращением поднял руки, поднял мяч и побежал прочь home: -)

Могу ли я по крайней мере предложить, если вы должны следовать по этому пути, вы оба:

  • старайтесь оставить троичные выражения, по крайней мере, немного читабельными, со всем этим красивым пробелом и несколькими строками; и
  • сохранить исходный код в комментарии, чтобы, по крайней мере, вы могли вернуться к нему, если у вас есть проблемы или вы хотите изменить логику?

Серьезно, вы будете благодарить меня через шесть месяцев, когда снова посмотрите на это, пытаясь выяснить, о чем вы думали: -)

3 голосов
/ 07 мая 2010

Вам не нужно это делать. Вставьте код в блок 'Always @ *' и объявите все, что вы назначаете, как 'reg'.

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

always @(*) begin
   // Your combo logic here..
end
1 голос
/ 05 мая 2010

Первый не делай этого! нет никакого смысла в этом. Он не компилируется в лучший код и менее читабелен, как вы заметили, пытаясь исправить его. Если вам нужно это как выражение, было бы лучше закодировать его как встроенную функцию.

1 голос
/ 05 мая 2010

Что ж, если вы настаиваете на том, чтобы по какой-то причине вы сохраняли его в троичной форме, ваша читаемость значительно повысилась бы, если бы вы просто правильно отформатировали его.

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 не могут соответствовать вашим троичным выражениям. Ваши операторы if не имеют предложения else, а троичные выражения всегда имеют предложения else. Однако, поскольку ваш вопрос даже не дает полной ясности, пытаетесь ли вы преобразовать операторы if в троичные выражения или троичные выражения в операторы if, немного сложно дать вам именно то, что вы хотите.

EDIT : Тернарные выражения всегда содержат предложения if и else. Вы не можете напрямую превратить оператор if без предложения else в троичный, потому что у вас не будет остальной части троичного. Теперь вы можете использовать некоторые приемы в некоторых случаях, если вам нужно, например, установить переменную для себя. Например,

ForwardA = cond1 ? newValue : FordwardA;

Вы в основном говорите не изменять значение в предложении else - но это предполагает, что вы присваиваете результат переменной. Чем сложнее выражение, тем сложнее его реализовать, и тем более запутанным становится код, когда вы это делаете. Не говоря уже о том, что в зависимости от того, какие оптимизации выполняет или не делает компилятор, он может назначать переменную себе, что не очень эффективно.

Вообще говоря, перевод операторов if без предложений else в троичные выражения является плохой идеей. Это может быть сделано только путем использования трюков, вместо того, чтобы прямо сказать, что вы имеете в виду, и это только усложняет ситуацию. И этот код достаточно сложен, как есть.

Я бы посоветовал не использовать здесь троицу, если вам это действительно не нужно. И если вы делаете, по крайней мере, сломать выражение. Даже если ваше троичное выражение было правильным, его намного сложнее читать, чем операторы if.

РЕДАКТИРОВАТЬ 2 : Если вам действительно нужно, чтобы это было троичное выражение, то я бы посоветовал вам сесть и выяснить точные условия, при которых ForwardA должен быть тем или иным набором значений, и создать троичное выражение, основанное на этом, вместо того, чтобы пытаться напрямую преобразовать операторы if, которые у вас есть (и то же самое для ForwardB). Ваши if-statments не только решают, какое значение назначить каждой переменной, но и какую переменную назначить этому значению, и это значительно усложняет ситуацию.

В других языках (я не знаю о verilog) вы можете использовать троичное выражение для выбора, какой переменной присваивать значение в дополнение к тому, что вы делаете в правой части выражения, но это действительно сложно. Лучше всего создать временный объект, содержащий значение, которое должно быть назначено, и отдельный троичный объект, чтобы определить, какой переменной присвоить его.

Не зная verilog, я действительно не знаю, что вы можете и не можете сделать с помощью операторов if и троичного выражения, но я думаю, что должен быть лучший способ справиться с этим, чем использование троичного. Может и нет, но то, что вы пытаетесь сделать, очень сложно и подвержено ошибкам.

...