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:
parent
1b178d56b7
commit
bc77a19059
42
elab_expr.cc
42
elab_expr.cc
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
Loading…
Reference in New Issue