Use $ivl_unsigned to implement VHDL to_unsigned function.

The VHDL to_unsigned function with to arguments is best handled
in the ivl elaborator, so have it generate an $ivlh_to_unsigned
function call in the vhdlpp code, and implement it in the ivl
core.

Also, implement the 'length attribute as a $bits() call for
similar reasons.
This commit is contained in:
Stephen Williams 2013-05-26 18:16:59 -07:00
parent 1b178d56b7
commit bc77a19059
2 changed files with 70 additions and 14 deletions

View File

@ -933,6 +933,35 @@ unsigned PECallFunction::test_width_sfunc_(Design*des, NetScope*scope,
{
perm_string name = peek_tail_name(path_);
if (name=="$ivlh_to_unsigned") {
ivl_assert(*this, parms_.size() == 2);
// The Icarus Verilog specific $ivl_unsigned() system
// task takes a second argument which is the output
// size. This can be an arbitrary constant function.
PExpr*pexpr = parms_[1];
if (pexpr == 0) {
cerr << get_fileline() << ": error: "
<< "Missing $ivlh_to_unsigned width." << endl;
return 0;
}
NetExpr*nexpr = elab_and_eval(des, scope, pexpr, -1, true);
if (nexpr == 0) {
cerr << get_fileline() << ": error: "
<< "Unable to evaluate " << name
<< " width argument: " << *pexpr << endl;
return 0;
}
long value = 0;
bool rc = eval_as_long(value, nexpr);
ivl_assert(*this, rc && value>=0);
expr_width_ = value;
signed_flag_= false;
return expr_width_;
}
if (name=="$signed" || name=="$unsigned") {
PExpr*expr = parms_[0];
if (expr == 0)
@ -1228,6 +1257,19 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope,
{
perm_string name = peek_tail_name(path_);
/* Catch the special case that the system function is the
$ivl_unsigned function. In this case the second argument is
the size of the expression, but should already be accounted
for so treat this very much like the $unsigned() function. */
if (name=="$ivlh_to_unsigned") {
ivl_assert(*this, parms_.size()==2);
PExpr*expr = parms_[0];
ivl_assert(*this, expr);
NetExpr*sub = expr->elaborate_expr(des, scope, expr_width_, flags);
return cast_to_width_(sub, expr_wid);
}
/* Catch the special case that the system function is the $signed
function. Its argument will be evaluated as a self-determined
expression. */

View File

@ -1,5 +1,6 @@
/*
* Copyright (c) 2011-2012 Stephen Williams (steve@icarus.com)
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2012-2013 / Stephen Williams (steve@icarus.com)
*
* This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU
@ -24,6 +25,7 @@
# include <typeinfo>
# include <iostream>
# include <cstdlib>
# include <cstring>
# include "ivl_assert.h"
# include <cassert>
@ -278,16 +280,14 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */
if (name_ == "length") {
int64_t val;
bool rc = evaluate(ent, arc, val);
out << val;
if (rc)
return errors;
else
return errors + 1;
if (name_=="length") {
out << "$bits(";
errors += base_->emit(out, ent, arc);
out << ")";
return errors;
}
out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc);
out << ", \"" << name_ << "\")";
@ -539,13 +539,12 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
out << ")";
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
int64_t use_size;
bool rc = argv_[1]->evaluate(ent, arc, use_size);
ivl_assert(*this, rc);
out << "$unsigned(" << use_size << "'(";
out << "$ivlh_to_unsigned(";
errors += argv_[0]->emit(out, ent, arc);
out << "))";
out << ", ";
errors += argv_[1]->emit(out, ent, arc);
out << ")";
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
int64_t use_size;
@ -727,6 +726,18 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
const VTypePrimitive*etype = dynamic_cast<const VTypePrimitive*> (arr->element_type());
assert(etype);
// Detect the special case that this is an array of
// CHARACTER. In this case, emit at a Verilog string.
if (etype->type()==VTypePrimitive::CHARACTER) {
vector<char> tmp (value_.size() + 3);
tmp[0] = '"';
memcpy(&tmp[1], &value_[0], value_.size());
tmp[value_.size()+1] = '"';
tmp[value_.size()+2] = 0;
out << &tmp[0];
return errors;
}
assert(etype->type() != VTypePrimitive::INTEGER);
out << value_.size() << "'b";
for (size_t idx = 0 ; idx < value_.size() ; idx += 1) {
@ -742,6 +753,9 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
out << "z";
break;
default:
cerr << get_fileline() << ": internal error: "
<< "Don't know how to handle bit " << value_[idx]
<< " with etype==" << etype->type() << endl;
assert(etype->type() == VTypePrimitive::STDLOGIC);
out << "x";
break;