Unary AND and XOR

This commit is contained in:
Nick Gasson 2008-07-20 16:41:57 +01:00
parent d8351ec1b2
commit 3ca85491ee
4 changed files with 61 additions and 21 deletions

View File

@ -103,6 +103,23 @@ static vhdl_expr *translate_ulong(ivl_expr_t e)
return new vhdl_const_int(ivl_expr_uvalue(e)); return new vhdl_const_int(ivl_expr_uvalue(e));
} }
static vhdl_expr *translate_reduction(support_function_t f, bool neg,
vhdl_expr *operand)
{
require_support_function(f);
vhdl_fcall *fcall =
new vhdl_fcall(support_function::function_name(f),
vhdl_type::std_logic());
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
fcall->add_expr(operand->cast(&std_logic_vector));
if (neg)
return new vhdl_unaryop_expr(VHDL_UNARYOP_NOT, fcall,
vhdl_type::std_logic());
else
return fcall;
}
static vhdl_expr *translate_unary(ivl_expr_t e) static vhdl_expr *translate_unary(ivl_expr_t e)
{ {
vhdl_expr *operand = translate_expr(ivl_expr_oper1(e)); vhdl_expr *operand = translate_expr(ivl_expr_oper1(e));
@ -111,13 +128,15 @@ static vhdl_expr *translate_unary(ivl_expr_t e)
bool should_be_signed = ivl_expr_signed(e) != 0; bool should_be_signed = ivl_expr_signed(e) != 0;
if (operand->get_type()->get_name() == VHDL_TYPE_UNSIGNED && should_be_signed) { if (operand->get_type()->get_name() == VHDL_TYPE_UNSIGNED
&& should_be_signed) {
//operand->print(); //operand->print();
//std::cout << "^ should be signed but is not" << std::endl; //std::cout << "^ should be signed but is not" << std::endl;
operand = change_signedness(operand, true); operand = change_signedness(operand, true);
} }
else if (operand->get_type()->get_name() == VHDL_TYPE_SIGNED && !should_be_signed) { else if (operand->get_type()->get_name() == VHDL_TYPE_SIGNED
&& !should_be_signed) {
//operand->print(); //operand->print();
//std::cout << "^ should be unsigned but is not" << std::endl; //std::cout << "^ should be unsigned but is not" << std::endl;
@ -131,20 +150,13 @@ static vhdl_expr *translate_unary(ivl_expr_t e)
return new vhdl_unaryop_expr return new vhdl_unaryop_expr
(VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type())); (VHDL_UNARYOP_NOT, operand, new vhdl_type(*operand->get_type()));
case 'N': // NOR case 'N': // NOR
return translate_reduction(SF_REDUCE_OR, true, operand);
case '|': case '|':
{ return translate_reduction(SF_REDUCE_OR, false, operand);
require_support_function(SF_REDUCE_OR); case 'A': // NAND
vhdl_fcall *f = return translate_reduction(SF_REDUCE_AND, true, operand);
new vhdl_fcall(support_function::function_name(SF_REDUCE_OR), case '&':
vhdl_type::std_logic()); return translate_reduction(SF_REDUCE_AND, false, operand);
vhdl_type std_logic_vector(VHDL_TYPE_STD_LOGIC_VECTOR);
f->add_expr(operand->cast(&std_logic_vector));
if ('N' == opcode)
return new vhdl_unaryop_expr(VHDL_UNARYOP_NOT, f, vhdl_type::std_logic());
else
return f;
}
default: default:
error("No translation for unary opcode '%c'\n", error("No translation for unary opcode '%c'\n",
ivl_expr_opcode(e)); ivl_expr_opcode(e));

View File

@ -261,18 +261,18 @@ static vhdl_expr *lpm_to_expr(vhdl_scope *scope, ivl_lpm_t lpm)
return part_select_pv_lpm_to_expr(scope, lpm); return part_select_pv_lpm_to_expr(scope, lpm);
case IVL_LPM_UFUNC: case IVL_LPM_UFUNC:
return ufunc_lpm_to_expr(scope, lpm); return ufunc_lpm_to_expr(scope, lpm);
/*case IVL_LPM_RE_AND: case IVL_LPM_RE_AND:
return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", false); return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_AND, false);
case IVL_LPM_RE_NAND: case IVL_LPM_RE_NAND:
return reduction_lpm_to_expr(scope, lpm, "Reduce_AND", true);*/ return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_AND, true);
case IVL_LPM_RE_NOR: case IVL_LPM_RE_NOR:
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_OR, true); return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_OR, true);
case IVL_LPM_RE_OR: case IVL_LPM_RE_OR:
return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_OR, false); return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_OR, false);
/*case IVL_LPM_RE_XOR: case IVL_LPM_RE_XOR:
return reduction_lpm_to_expr(scope, lpm, "Reduce_XOR", false); return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false);
case IVL_LPM_RE_XNOR: case IVL_LPM_RE_XNOR:
return reduction_lpm_to_expr(scope, lpm, "Reduce_XNOR", false);*/ return reduction_lpm_to_expr(scope, lpm, SF_REDUCE_XOR, false);
case IVL_LPM_SIGN_EXT: case IVL_LPM_SIGN_EXT:
return sign_extend_lpm_to_expr(scope, lpm); return sign_extend_lpm_to_expr(scope, lpm);
case IVL_LPM_ARRAY: case IVL_LPM_ARRAY:

View File

@ -42,6 +42,10 @@ const char *support_function::function_name(support_function_t type)
return "Boolean_To_Logic"; return "Boolean_To_Logic";
case SF_REDUCE_OR: case SF_REDUCE_OR:
return "Reduce_OR"; return "Reduce_OR";
case SF_REDUCE_AND:
return "Reduce_AND";
case SF_REDUCE_XOR:
return "Reduce_XOR";
default: default:
assert(false); assert(false);
} }
@ -55,6 +59,8 @@ vhdl_type *support_function::function_type(support_function_t type)
return vhdl_type::boolean(); return vhdl_type::boolean();
case SF_BOOLEAN_TO_LOGIC: case SF_BOOLEAN_TO_LOGIC:
case SF_REDUCE_OR: case SF_REDUCE_OR:
case SF_REDUCE_AND:
case SF_REDUCE_XOR:
return vhdl_type::std_logic(); return vhdl_type::std_logic();
default: default:
assert(false); assert(false);
@ -95,6 +101,26 @@ void support_function::emit(std::ostream &of, int level) const
<< "end loop;" << nl_string(indent(level)) << "end loop;" << nl_string(indent(level))
<< "return '0';" << nl_string(level); << "return '0';" << nl_string(level);
break; break;
case SF_REDUCE_AND:
of << "(X : std_logic_vector) return std_logic is" << nl_string(level)
<< "begin" << nl_string(indent(level))
<< "for I in X'Range loop" << nl_string(indent(indent(level)))
<< "if X(I) = '0' then" << nl_string(indent(indent(indent(level))))
<< "return '0';" << nl_string(indent(indent(level)))
<< "end if;" << nl_string(indent(level))
<< "end loop;" << nl_string(indent(level))
<< "return '1';" << nl_string(level);
break;
case SF_REDUCE_XOR:
of << "(X : std_logic_vector) return std_logic is"
<< nl_string(indent(level))
<< "variable R : std_logic := '0';" << nl_string(level)
<< "begin" << nl_string(indent(level))
<< "for I in X'Range loop" << nl_string(indent(indent(level)))
<< "R := X(I) xor R;" << nl_string(indent(level))
<< "end loop;" << nl_string(indent(level))
<< "return R;" << nl_string(level);
break;
default: default:
assert(false); assert(false);
} }

View File

@ -28,6 +28,8 @@ enum support_function_t {
SF_SIGNED_TO_BOOLEAN, SF_SIGNED_TO_BOOLEAN,
SF_BOOLEAN_TO_LOGIC, SF_BOOLEAN_TO_LOGIC,
SF_REDUCE_OR, SF_REDUCE_OR,
SF_REDUCE_AND,
SF_REDUCE_XOR,
}; };
class support_function : public vhdl_function { class support_function : public vhdl_function {