mirror of
https://github.com/YosysHQ/yosys
synced 2025-04-13 04:28:18 +00:00
Merge pull request #1551 from whitequark/manual-cell-operands
Clarify semantics of comb cells, in particular shifts
This commit is contained in:
commit
7dece7955e
|
@ -2242,7 +2242,7 @@ gen_stmt:
|
||||||
ast_stack.back()->children.push_back(node);
|
ast_stack.back()->children.push_back(node);
|
||||||
ast_stack.push_back(node);
|
ast_stack.push_back(node);
|
||||||
} opt_arg_list ';'{
|
} opt_arg_list ';'{
|
||||||
ast_stack.pop_back();
|
ast_stack.pop_back();
|
||||||
};
|
};
|
||||||
|
|
||||||
gen_stmt_block:
|
gen_stmt_block:
|
||||||
|
@ -2413,19 +2413,19 @@ basic_expr:
|
||||||
append_attr($$, $2);
|
append_attr($$, $2);
|
||||||
} |
|
} |
|
||||||
basic_expr OP_SHL attr basic_expr {
|
basic_expr OP_SHL attr basic_expr {
|
||||||
$$ = new AstNode(AST_SHIFT_LEFT, $1, $4);
|
$$ = new AstNode(AST_SHIFT_LEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
|
||||||
append_attr($$, $3);
|
append_attr($$, $3);
|
||||||
} |
|
} |
|
||||||
basic_expr OP_SHR attr basic_expr {
|
basic_expr OP_SHR attr basic_expr {
|
||||||
$$ = new AstNode(AST_SHIFT_RIGHT, $1, $4);
|
$$ = new AstNode(AST_SHIFT_RIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
|
||||||
append_attr($$, $3);
|
append_attr($$, $3);
|
||||||
} |
|
} |
|
||||||
basic_expr OP_SSHL attr basic_expr {
|
basic_expr OP_SSHL attr basic_expr {
|
||||||
$$ = new AstNode(AST_SHIFT_SLEFT, $1, $4);
|
$$ = new AstNode(AST_SHIFT_SLEFT, $1, new AstNode(AST_TO_UNSIGNED, $4));
|
||||||
append_attr($$, $3);
|
append_attr($$, $3);
|
||||||
} |
|
} |
|
||||||
basic_expr OP_SSHR attr basic_expr {
|
basic_expr OP_SSHR attr basic_expr {
|
||||||
$$ = new AstNode(AST_SHIFT_SRIGHT, $1, $4);
|
$$ = new AstNode(AST_SHIFT_SRIGHT, $1, new AstNode(AST_TO_UNSIGNED, $4));
|
||||||
append_attr($$, $3);
|
append_attr($$, $3);
|
||||||
} |
|
} |
|
||||||
basic_expr '<' attr basic_expr {
|
basic_expr '<' attr basic_expr {
|
||||||
|
|
|
@ -783,6 +783,14 @@ namespace {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int param_bool(RTLIL::IdString name, bool expected)
|
||||||
|
{
|
||||||
|
int v = param_bool(name);
|
||||||
|
if (v != expected)
|
||||||
|
error(__LINE__);
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
void param_bits(RTLIL::IdString name, int width)
|
void param_bits(RTLIL::IdString name, int width)
|
||||||
{
|
{
|
||||||
param(name);
|
param(name);
|
||||||
|
@ -869,13 +877,23 @@ namespace {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx))) {
|
if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr))) {
|
||||||
|
param_bool(ID(A_SIGNED));
|
||||||
|
param_bool(ID(B_SIGNED), /*expected=*/false);
|
||||||
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
|
check_expected(/*check_matched_sign=*/false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cell->type.in(ID($shift), ID($shiftx))) {
|
||||||
param_bool(ID(A_SIGNED));
|
param_bool(ID(A_SIGNED));
|
||||||
param_bool(ID(B_SIGNED));
|
param_bool(ID(B_SIGNED));
|
||||||
port(ID::A, param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID::B, param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID::Y, param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected(false);
|
check_expected(/*check_matched_sign=*/false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -957,7 +975,7 @@ namespace {
|
||||||
port(ID::A, param(ID(A_WIDTH)));
|
port(ID::A, param(ID(A_WIDTH)));
|
||||||
port(ID::B, param(ID(B_WIDTH)));
|
port(ID::B, param(ID(B_WIDTH)));
|
||||||
port(ID::Y, param(ID(Y_WIDTH)));
|
port(ID::Y, param(ID(Y_WIDTH)));
|
||||||
check_expected(false);
|
check_expected(/*check_matched_sign=*/false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,11 @@ Verilog & Cell Type \\
|
||||||
\label{tab:CellLib_unary}
|
\label{tab:CellLib_unary}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
|
For the unary cells that output a logical value ({\tt \$reduce\_and}, {\tt \$reduce\_or},
|
||||||
|
{\tt \$reduce\_xor}, {\tt \$reduce\_xnor}, {\tt \$reduce\_bool}, {\tt \$logic\_not}),
|
||||||
|
when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended,
|
||||||
|
and only the least significant bit varies.
|
||||||
|
|
||||||
Note that {\tt \$reduce\_or} and {\tt \$reduce\_bool} actually represent the same
|
Note that {\tt \$reduce\_or} and {\tt \$reduce\_bool} actually represent the same
|
||||||
logic function. But the HDL frontends generate them in different situations. A
|
logic function. But the HDL frontends generate them in different situations. A
|
||||||
{\tt \$reduce\_or} cell is generated when the prefix {\tt |} operator is being used. A
|
{\tt \$reduce\_or} cell is generated when the prefix {\tt |} operator is being used. A
|
||||||
|
@ -97,41 +102,6 @@ The width of the output port \B{Y}.
|
||||||
|
|
||||||
Table~\ref{tab:CellLib_binary} lists all cells for binary RTL operators.
|
Table~\ref{tab:CellLib_binary} lists all cells for binary RTL operators.
|
||||||
|
|
||||||
\subsection{Multiplexers}
|
|
||||||
|
|
||||||
Multiplexers are generated by the Verilog HDL frontend for {\tt
|
|
||||||
?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees
|
|
||||||
from RTLIL::Process objects to logic.
|
|
||||||
|
|
||||||
The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter
|
|
||||||
and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also
|
|
||||||
has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to
|
|
||||||
the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux}
|
|
||||||
cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;.
|
|
||||||
|
|
||||||
The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells
|
|
||||||
of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and
|
|
||||||
an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both
|
|
||||||
\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of
|
|
||||||
\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is
|
|
||||||
set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more
|
|
||||||
than one bit from \B{S} is set the output is undefined. Cells of this type are used to model
|
|
||||||
``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by
|
|
||||||
an optimization).
|
|
||||||
|
|
||||||
The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH}
|
|
||||||
parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are
|
|
||||||
\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y}
|
|
||||||
is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore,
|
|
||||||
the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;.
|
|
||||||
|
|
||||||
Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements
|
|
||||||
usually results in trees of multiplexer cells. Many passes (from various
|
|
||||||
optimizations to FSM extraction) heavily depend on these multiplexer trees to
|
|
||||||
understand dependencies between signals. Therefore optimizations should not
|
|
||||||
break these multiplexer trees (e.g.~by replacing a multiplexer between a
|
|
||||||
calculated signal and a constant zero with an {\tt \$and} gate).
|
|
||||||
|
|
||||||
\begin{table}[t!]
|
\begin{table}[t!]
|
||||||
\hfil
|
\hfil
|
||||||
\begin{tabular}[t]{ll}
|
\begin{tabular}[t]{ll}
|
||||||
|
@ -175,6 +145,57 @@ Verilog & Cell Type \\
|
||||||
\label{tab:CellLib_binary}
|
\label{tab:CellLib_binary}
|
||||||
\end{table}
|
\end{table}
|
||||||
|
|
||||||
|
The {\tt \$shl} and {\tt \$shr} cells implement logical shifts, whereas the {\tt \$sshl} and
|
||||||
|
{\tt \$sshr} cells implement arithmetic shifts. The {\tt \$shl} and {\tt \$sshl} cells implement
|
||||||
|
the same operation. All four of these cells interpret the second operand as unsigned, and require
|
||||||
|
\B{B\_SIGNED} to be zero.
|
||||||
|
|
||||||
|
Two additional shift operator cells are available that do not directly correspond to any operator
|
||||||
|
in Verilog, {\tt \$shift} and {\tt \$shiftx}. The {\tt \$shift} cell performs a right logical shift
|
||||||
|
if the second operand is positive (or unsigned), and a left logical shift if it is negative.
|
||||||
|
The {\tt \$shiftx} cell performs the same operation as the {\tt \$shift} cell, but the vacated bit
|
||||||
|
positions are filled with undef (x) bits, and corresponds to the Verilog indexed part-select expression.
|
||||||
|
|
||||||
|
For the binary cells that output a logical value ({\tt \$logic\_and}, {\tt \$logic\_or},
|
||||||
|
{\tt \$eqx}, {\tt \$nex}, {\tt \$lt}, {\tt \$le}, {\tt \$eq}, {\tt \$ne}, {\tt \$ge},
|
||||||
|
{\tt \$gt}), when the \B{Y\_WIDTH} parameter is greater than 1, the output is zero-extended,
|
||||||
|
and only the least significant bit varies.
|
||||||
|
|
||||||
|
\subsection{Multiplexers}
|
||||||
|
|
||||||
|
Multiplexers are generated by the Verilog HDL frontend for {\tt
|
||||||
|
?:}-expressions. Multiplexers are also generated by the {\tt proc} pass to map the decision trees
|
||||||
|
from RTLIL::Process objects to logic.
|
||||||
|
|
||||||
|
The simplest multiplexer cell type is {\tt \$mux}. Cells of this type have a \B{WIDTH} parameter
|
||||||
|
and data inputs \B{A} and \B{B} and a data output \B{Y}, all of the specified width. This cell also
|
||||||
|
has a single bit control input \B{S}. If \B{S} is 0 the value from the \B{A} input is sent to
|
||||||
|
the output, if it is 1 the value from the \B{B} input is sent to the output. So the {\tt \$mux}
|
||||||
|
cell implements the function \lstinline[language=Verilog]; Y = S ? B : A;.
|
||||||
|
|
||||||
|
The {\tt \$pmux} cell is used to multiplex between many inputs using a one-hot select signal. Cells
|
||||||
|
of this type have a \B{WIDTH} and a \B{S\_WIDTH} parameter and inputs \B{A}, \B{B}, and \B{S} and
|
||||||
|
an output \B{Y}. The \B{S} input is \B{S\_WIDTH} bits wide. The \B{A} input and the output are both
|
||||||
|
\B{WIDTH} bits wide and the \B{B} input is \B{WIDTH}*\B{S\_WIDTH} bits wide. When all bits of
|
||||||
|
\B{S} are zero, the value from \B{A} input is sent to the output. If the $n$'th bit from \B{S} is
|
||||||
|
set, the value $n$'th \B{WIDTH} bits wide slice of the \B{B} input is sent to the output. When more
|
||||||
|
than one bit from \B{S} is set the output is undefined. Cells of this type are used to model
|
||||||
|
``parallel cases'' (defined by using the {\tt parallel\_case} attribute or detected by
|
||||||
|
an optimization).
|
||||||
|
|
||||||
|
The {\tt \$tribuf} cell is used to implement tristate logic. Cells of this type have a \B{WIDTH}
|
||||||
|
parameter and inputs \B{A} and \B{EN} and an output \B{Y}. The \B{A} input and \B{Y} output are
|
||||||
|
\B{WIDTH} bits wide, and the \B{EN} input is one bit wide. When \B{EN} is 0, the output \B{Y}
|
||||||
|
is not driven. When \B{EN} is 1, the value from \B{A} input is sent to the \B{Y} output. Therefore,
|
||||||
|
the {\tt \$tribuf} cell implements the function \lstinline[language=Verilog]; Y = EN ? A : 'bz;.
|
||||||
|
|
||||||
|
Behavioural code with cascaded {\tt if-then-else}- and {\tt case}-statements
|
||||||
|
usually results in trees of multiplexer cells. Many passes (from various
|
||||||
|
optimizations to FSM extraction) heavily depend on these multiplexer trees to
|
||||||
|
understand dependencies between signals. Therefore optimizations should not
|
||||||
|
break these multiplexer trees (e.g.~by replacing a multiplexer between a
|
||||||
|
calculated signal and a constant zero with an {\tt \$and} gate).
|
||||||
|
|
||||||
\subsection{Registers}
|
\subsection{Registers}
|
||||||
|
|
||||||
D-Type Flip-Flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK},
|
D-Type Flip-Flops are represented by {\tt \$dff} cells. These cells have a clock port \B{CLK},
|
||||||
|
|
Loading…
Reference in a new issue